@revojs/ai 0.2.32 → 0.2.35
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/index.d.ts +2 -1
- package/dist/index.js +28 -4
- package/dist/module/index.d.ts +1 -0
- package/dist/module/index.js +3 -2
- package/dist/protocols/anthropic-messages.js +2 -3
- package/dist/protocols/google-models.js +26 -5
- package/dist/protocols/openai-chat-completions.js +3 -3
- package/dist/protocols/openai-responses.js +10 -10
- package/dist/providers/opencode-go.js +11 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -847,7 +847,7 @@ export declare class ModelContextProtocolClient {
|
|
|
847
847
|
export declare class ModelContextProtocolConnection {
|
|
848
848
|
readonly client: ModelContextProtocolClient;
|
|
849
849
|
constructor(client: ModelContextProtocolClient);
|
|
850
|
-
listTools(options?: ModelContextProtocolRequestOptions): Promise<Array<
|
|
850
|
+
listTools(options?: ModelContextProtocolRequestOptions): Promise<Array<ToolDescription>>;
|
|
851
851
|
executeTool(call: LanguageModelToolCall, options?: ModelContextProtocolRequestOptions): Promise<LanguageModelToolResultPart>;
|
|
852
852
|
close(): Promise<void>;
|
|
853
853
|
}
|
|
@@ -868,6 +868,7 @@ export declare function useModelsDev(id: string, resolve: (model: ModelsDevModel
|
|
|
868
868
|
}>;
|
|
869
869
|
export declare function modelsDevProtocol(model: ModelsDevModel, provider: ModelsDevProvider): ModelsDevProtocol | undefined;
|
|
870
870
|
export declare function toToolInput(value: string | undefined): string;
|
|
871
|
+
export declare function toToolParameters(schema: JsonSchema): JSONObject;
|
|
871
872
|
export declare function mergeHeaders(...headers: Array<Record<string, string | undefined> | undefined>): Record<string, string>;
|
|
872
873
|
export declare function postJson(url: string, body: unknown, options?: {
|
|
873
874
|
headers?: Record<string, string | undefined>;
|
package/dist/index.js
CHANGED
|
@@ -110,7 +110,8 @@ var ModelContextProtocolClient = class {
|
|
|
110
110
|
headers: {
|
|
111
111
|
...this.headers,
|
|
112
112
|
"mcp-session-id": sessionId
|
|
113
|
-
}
|
|
113
|
+
},
|
|
114
|
+
redirect: "manual"
|
|
114
115
|
});
|
|
115
116
|
await response.body?.cancel();
|
|
116
117
|
if (!response.ok && response.status !== 405) throw new Error(`Model Context Protocol session termination failed with HTTP ${response.status}.`);
|
|
@@ -125,8 +126,13 @@ var ModelContextProtocolClient = class {
|
|
|
125
126
|
method: "POST",
|
|
126
127
|
headers,
|
|
127
128
|
body: JSON.stringify(message),
|
|
128
|
-
signal
|
|
129
|
+
signal,
|
|
130
|
+
redirect: "manual"
|
|
129
131
|
});
|
|
132
|
+
if (response.type === "opaqueredirect" || response.status >= 300 && response.status < 400) {
|
|
133
|
+
await response.body?.cancel();
|
|
134
|
+
throw new Error("Model Context Protocol server redirected the request; configure its final endpoint.");
|
|
135
|
+
}
|
|
130
136
|
if (!response.ok) {
|
|
131
137
|
await response.body?.cancel();
|
|
132
138
|
throw new Error(`Model Context Protocol request failed with HTTP ${response.status}.`);
|
|
@@ -187,7 +193,8 @@ var ModelContextProtocolConnection = class {
|
|
|
187
193
|
type: "function",
|
|
188
194
|
name: tool.name,
|
|
189
195
|
description: tool.description,
|
|
190
|
-
inputSchema: tool.inputSchema
|
|
196
|
+
inputSchema: tool.inputSchema,
|
|
197
|
+
annotations: tool.annotations
|
|
191
198
|
});
|
|
192
199
|
cursor = result.nextCursor;
|
|
193
200
|
if (cursor !== void 0 && cursors.has(cursor)) throw new Error("Model Context Protocol server returned a repeated tools pagination cursor.");
|
|
@@ -628,6 +635,13 @@ function modelsDevProtocol(model, provider) {
|
|
|
628
635
|
function toToolInput(value) {
|
|
629
636
|
return value === void 0 || value.trim() === "" ? "{}" : value;
|
|
630
637
|
}
|
|
638
|
+
function toToolParameters(schema) {
|
|
639
|
+
const parameters = {};
|
|
640
|
+
for (const [key, value] of Object.entries(toJsonSchema(schema))) if (!TOOL_PARAMETER_ROOT_KEYWORDS.has(key)) parameters[key] = value;
|
|
641
|
+
parameters.type = "object";
|
|
642
|
+
if (parameters.properties === null || typeof parameters.properties !== "object" || Array.isArray(parameters.properties)) parameters.properties = {};
|
|
643
|
+
return parameters;
|
|
644
|
+
}
|
|
631
645
|
function mergeHeaders(...headers) {
|
|
632
646
|
const merged = {};
|
|
633
647
|
for (const record of headers) for (const [name, value] of Object.entries(record ?? {})) if (value !== void 0) merged[name] = value;
|
|
@@ -684,6 +698,16 @@ function toStream(read) {
|
|
|
684
698
|
});
|
|
685
699
|
}
|
|
686
700
|
var modelsDevCache = { loadedAt: 0 };
|
|
701
|
+
var TOOL_PARAMETER_ROOT_KEYWORDS = /* @__PURE__ */ new Set([
|
|
702
|
+
"anyOf",
|
|
703
|
+
"oneOf",
|
|
704
|
+
"allOf",
|
|
705
|
+
"not",
|
|
706
|
+
"enum",
|
|
707
|
+
"if",
|
|
708
|
+
"then",
|
|
709
|
+
"else"
|
|
710
|
+
]);
|
|
687
711
|
var MODEL_CONTEXT_PROTOCOL_VERSIONS = [
|
|
688
712
|
"2025-11-25",
|
|
689
713
|
"2025-06-18",
|
|
@@ -707,4 +731,4 @@ var JSON_SCHEMA_DRAFTS = {
|
|
|
707
731
|
"http://json-schema.org/draft-04/schema#": "4"
|
|
708
732
|
};
|
|
709
733
|
//#endregion
|
|
710
|
-
export { MODEL_CONTEXT_PROTOCOL_TIMEOUT, MODEL_CONTEXT_PROTOCOL_VERSIONS, ModelContextProtocolClient, ModelContextProtocolConnection, ModelContextProtocolError, ModelContextProtocolErrorCode, defineProvider, defineTool, handleModelContextProtocol, mergeHeaders, modelsDevProtocol, postJson, readDataFrames, toStream, toToolInput, useAi, useModelContextProtocol, useModelsDev, useTools };
|
|
734
|
+
export { MODEL_CONTEXT_PROTOCOL_TIMEOUT, MODEL_CONTEXT_PROTOCOL_VERSIONS, ModelContextProtocolClient, ModelContextProtocolConnection, ModelContextProtocolError, ModelContextProtocolErrorCode, defineProvider, defineTool, handleModelContextProtocol, mergeHeaders, modelsDevProtocol, postJson, readDataFrames, toStream, toToolInput, toToolParameters, useAi, useModelContextProtocol, useModelsDev, useTools };
|
package/dist/module/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface AiConfig {
|
|
|
8
8
|
name: string;
|
|
9
9
|
version: string;
|
|
10
10
|
instructions?: string;
|
|
11
|
+
route: boolean;
|
|
11
12
|
};
|
|
12
13
|
}
|
|
13
14
|
declare const _default: import("revojs/module").Module<"ai", AiConfig, readonly [import("revojs/module").Module<"server", Record<string, never>, []>]>;
|
package/dist/module/index.js
CHANGED
|
@@ -11,13 +11,14 @@ var module_default = defineModule({
|
|
|
11
11
|
},
|
|
12
12
|
modelContextProtocol: {
|
|
13
13
|
name: "revojs",
|
|
14
|
-
version: "1.0.0"
|
|
14
|
+
version: "1.0.0",
|
|
15
|
+
route: false
|
|
15
16
|
}
|
|
16
17
|
}),
|
|
17
18
|
modules: [server],
|
|
18
19
|
setup(config) {
|
|
19
20
|
const { fromModule } = useModule(import.meta.url);
|
|
20
|
-
addRoutes(config, fromModule("../routes"));
|
|
21
|
+
if (config.ai.modelContextProtocol.route) addRoutes(config, fromModule("../routes"));
|
|
21
22
|
return {
|
|
22
23
|
variables: { server: {
|
|
23
24
|
anthropicApiKey: {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { mergeHeaders, postJson, readDataFrames, toStream, toToolInput } from "../index.js";
|
|
2
|
-
import { toJsonSchema } from "revojs/shared";
|
|
1
|
+
import { mergeHeaders, postJson, readDataFrames, toStream, toToolInput, toToolParameters } from "../index.js";
|
|
3
2
|
//#region src/protocols/anthropic-messages.ts
|
|
4
3
|
function toUsage(inputTokens, cacheRead, cacheWrite, outputTokens) {
|
|
5
4
|
const raw = {};
|
|
@@ -156,7 +155,7 @@ function toBody(options, stream) {
|
|
|
156
155
|
else tools.push({
|
|
157
156
|
name: tool.name,
|
|
158
157
|
description: tool.description,
|
|
159
|
-
input_schema:
|
|
158
|
+
input_schema: toToolParameters(tool.inputSchema)
|
|
160
159
|
});
|
|
161
160
|
if (cache && tools.length > 0) tools[tools.length - 1].cache_control = { type: "ephemeral" };
|
|
162
161
|
if (cache && Array.isArray(lastContent)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mergeHeaders, postJson, readDataFrames, toStream } from "../index.js";
|
|
1
|
+
import { mergeHeaders, postJson, readDataFrames, toStream, toToolParameters } from "../index.js";
|
|
2
2
|
import { toJsonSchema } from "revojs/shared";
|
|
3
3
|
//#region src/protocols/google-models.ts
|
|
4
4
|
function toBase64(data) {
|
|
@@ -96,6 +96,14 @@ function toBody(options) {
|
|
|
96
96
|
} catch {
|
|
97
97
|
args = {};
|
|
98
98
|
}
|
|
99
|
+
const signature = part.providerOptions?.google?.thoughtSignature;
|
|
100
|
+
if (typeof signature === "string") return [{
|
|
101
|
+
functionCall: {
|
|
102
|
+
name: part.toolName,
|
|
103
|
+
args
|
|
104
|
+
},
|
|
105
|
+
thoughtSignature: signature
|
|
106
|
+
}];
|
|
99
107
|
return [{ functionCall: {
|
|
100
108
|
name: part.toolName,
|
|
101
109
|
args
|
|
@@ -115,6 +123,14 @@ function toBody(options) {
|
|
|
115
123
|
});
|
|
116
124
|
return [];
|
|
117
125
|
});
|
|
126
|
+
let signed = false;
|
|
127
|
+
for (const part of parts) if (part.functionCall !== void 0 && part.thoughtSignature !== void 0) signed = true;
|
|
128
|
+
if (!signed) {
|
|
129
|
+
for (const part of parts) if (part.functionCall !== void 0) {
|
|
130
|
+
part.thoughtSignature = SKIP_THOUGHT_SIGNATURE;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
118
134
|
if (parts.length > 0) contents.push({
|
|
119
135
|
role: "model",
|
|
120
136
|
parts
|
|
@@ -135,7 +151,7 @@ function toBody(options) {
|
|
|
135
151
|
return [{
|
|
136
152
|
name: tool.name,
|
|
137
153
|
description: tool.description,
|
|
138
|
-
parameters:
|
|
154
|
+
parameters: toToolParameters(tool.inputSchema)
|
|
139
155
|
}];
|
|
140
156
|
});
|
|
141
157
|
return [{
|
|
@@ -221,12 +237,14 @@ async function* readParts(response, warnings) {
|
|
|
221
237
|
}
|
|
222
238
|
if (part.functionCall !== void 0) {
|
|
223
239
|
toolCalls = true;
|
|
224
|
-
|
|
240
|
+
const call = {
|
|
225
241
|
type: "tool-call",
|
|
226
242
|
toolCallId: `gemini-tool-${toolCount++}`,
|
|
227
243
|
toolName: part.functionCall.name ?? "",
|
|
228
244
|
input: JSON.stringify(part.functionCall.args ?? {})
|
|
229
245
|
};
|
|
246
|
+
if (part.thoughtSignature !== void 0) call.providerMetadata = { google: { thoughtSignature: part.thoughtSignature } };
|
|
247
|
+
yield call;
|
|
230
248
|
continue;
|
|
231
249
|
}
|
|
232
250
|
if (typeof part.text === "string" && part.text.length > 0) {
|
|
@@ -280,12 +298,14 @@ function geminiGenerateProtocol(config) {
|
|
|
280
298
|
}
|
|
281
299
|
if (part.functionCall !== void 0) {
|
|
282
300
|
toolCalls = true;
|
|
283
|
-
|
|
301
|
+
const call = {
|
|
284
302
|
type: "tool-call",
|
|
285
303
|
toolCallId: `gemini-tool-${toolCount++}`,
|
|
286
304
|
toolName: part.functionCall.name ?? "",
|
|
287
305
|
input: JSON.stringify(part.functionCall.args ?? {})
|
|
288
|
-
}
|
|
306
|
+
};
|
|
307
|
+
if (part.thoughtSignature !== void 0) call.providerMetadata = { google: { thoughtSignature: part.thoughtSignature } };
|
|
308
|
+
content.push(call);
|
|
289
309
|
continue;
|
|
290
310
|
}
|
|
291
311
|
if (typeof part.text === "string" && part.text.length > 0) content.push({
|
|
@@ -321,5 +341,6 @@ function geminiStreamProtocol(config) {
|
|
|
321
341
|
};
|
|
322
342
|
};
|
|
323
343
|
}
|
|
344
|
+
var SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
|
|
324
345
|
//#endregion
|
|
325
346
|
export { geminiGenerateProtocol, geminiStreamProtocol };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mergeHeaders, postJson, readDataFrames, toStream, toToolInput } from "../index.js";
|
|
1
|
+
import { mergeHeaders, postJson, readDataFrames, toStream, toToolInput, toToolParameters } from "../index.js";
|
|
2
2
|
import { toJsonSchema } from "revojs/shared";
|
|
3
3
|
//#region src/protocols/openai-chat-completions.ts
|
|
4
4
|
function toMessages(prompt) {
|
|
@@ -91,7 +91,7 @@ function toBody(config, options, stream) {
|
|
|
91
91
|
function: {
|
|
92
92
|
name: tool.name,
|
|
93
93
|
description: tool.description,
|
|
94
|
-
parameters:
|
|
94
|
+
parameters: toToolParameters(tool.inputSchema),
|
|
95
95
|
strict: tool.strict
|
|
96
96
|
}
|
|
97
97
|
}) } : {},
|
|
@@ -214,7 +214,7 @@ async function* readParts(response, warnings) {
|
|
|
214
214
|
let accumulator = tools.get(index);
|
|
215
215
|
if (accumulator === void 0) {
|
|
216
216
|
accumulator = {
|
|
217
|
-
streamId: `openai-tool-${index}`,
|
|
217
|
+
streamId: partial.id ?? `openai-tool-${index}`,
|
|
218
218
|
callId: partial.id ?? "",
|
|
219
219
|
name: "",
|
|
220
220
|
arguments: ""
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mergeHeaders, postJson, readDataFrames, toStream, toToolInput } from "../index.js";
|
|
1
|
+
import { mergeHeaders, postJson, readDataFrames, toStream, toToolInput, toToolParameters } from "../index.js";
|
|
2
2
|
import { toJsonSchema } from "revojs/shared";
|
|
3
3
|
//#region src/protocols/openai-responses.ts
|
|
4
4
|
function toUsage(usage) {
|
|
@@ -142,7 +142,7 @@ function toBody(options, stream) {
|
|
|
142
142
|
type: "function",
|
|
143
143
|
name: tool.name,
|
|
144
144
|
description: tool.description,
|
|
145
|
-
parameters:
|
|
145
|
+
parameters: toToolParameters(tool.inputSchema),
|
|
146
146
|
strict: tool.strict
|
|
147
147
|
}) } : {},
|
|
148
148
|
...options.toolChoice !== void 0 ? { tool_choice: options.toolChoice.type === "tool" ? {
|
|
@@ -188,17 +188,17 @@ async function* readParts(response, warnings) {
|
|
|
188
188
|
continue;
|
|
189
189
|
}
|
|
190
190
|
if (event.type === "response.output_item.added" && event.item?.type === "function_call") {
|
|
191
|
-
const
|
|
191
|
+
const itemId = event.item.id ?? event.item.call_id ?? `responses-tool-${event.output_index ?? tools.size}`;
|
|
192
192
|
const record = {
|
|
193
|
-
streamId,
|
|
193
|
+
streamId: event.item.call_id ?? itemId,
|
|
194
194
|
callId: event.item.call_id ?? "",
|
|
195
195
|
name: event.item.name ?? "",
|
|
196
196
|
arguments: ""
|
|
197
197
|
};
|
|
198
|
-
tools.set(
|
|
198
|
+
tools.set(itemId, record);
|
|
199
199
|
yield {
|
|
200
200
|
type: "tool-input-start",
|
|
201
|
-
id: streamId,
|
|
201
|
+
id: record.streamId,
|
|
202
202
|
toolName: record.name
|
|
203
203
|
};
|
|
204
204
|
continue;
|
|
@@ -255,7 +255,7 @@ async function* readParts(response, warnings) {
|
|
|
255
255
|
record.arguments += event.delta;
|
|
256
256
|
yield {
|
|
257
257
|
type: "tool-input-delta",
|
|
258
|
-
id:
|
|
258
|
+
id: record.streamId,
|
|
259
259
|
delta: event.delta
|
|
260
260
|
};
|
|
261
261
|
}
|
|
@@ -265,7 +265,7 @@ async function* readParts(response, warnings) {
|
|
|
265
265
|
const itemId = event.item.id ?? "";
|
|
266
266
|
if (event.item.type === "function_call") {
|
|
267
267
|
const record = tools.get(itemId);
|
|
268
|
-
const streamId = record?.streamId ?? itemId;
|
|
268
|
+
const streamId = record?.streamId ?? event.item.call_id ?? itemId;
|
|
269
269
|
tools.delete(itemId);
|
|
270
270
|
hasToolCall = true;
|
|
271
271
|
yield {
|
|
@@ -308,7 +308,7 @@ async function* readParts(response, warnings) {
|
|
|
308
308
|
type: "reasoning-end",
|
|
309
309
|
id
|
|
310
310
|
};
|
|
311
|
-
for (const
|
|
311
|
+
for (const record of tools.values()) {
|
|
312
312
|
yield {
|
|
313
313
|
type: "tool-input-end",
|
|
314
314
|
id: record.streamId
|
|
@@ -316,7 +316,7 @@ async function* readParts(response, warnings) {
|
|
|
316
316
|
hasToolCall = true;
|
|
317
317
|
yield {
|
|
318
318
|
type: "tool-call",
|
|
319
|
-
toolCallId: record.callId ||
|
|
319
|
+
toolCallId: record.callId || record.streamId,
|
|
320
320
|
toolName: record.name,
|
|
321
321
|
input: toToolInput(record.arguments)
|
|
322
322
|
};
|
|
@@ -2,6 +2,7 @@ import { defineProvider, modelsDevProtocol, useModelsDev } from "../index.js";
|
|
|
2
2
|
import { messagesGenerateProtocol, messagesStreamProtocol } from "../protocols/anthropic-messages.js";
|
|
3
3
|
import { chatCompletionsGenerateProtocol, chatCompletionsStreamProtocol } from "../protocols/openai-chat-completions.js";
|
|
4
4
|
import { responsesGenerateProtocol, responsesStreamProtocol } from "../protocols/openai-responses.js";
|
|
5
|
+
import { geminiGenerateProtocol, geminiStreamProtocol } from "../protocols/google-models.js";
|
|
5
6
|
import { useVariables } from "revojs";
|
|
6
7
|
//#region src/providers/opencode-go.ts
|
|
7
8
|
var opencode_go_default = defineProvider({ setup(scope) {
|
|
@@ -47,6 +48,16 @@ var opencode_go_default = defineProvider({ setup(scope) {
|
|
|
47
48
|
};
|
|
48
49
|
return useModelsDev("opencode-go", (model, provider) => {
|
|
49
50
|
const protocol = modelsDevProtocol(model, provider);
|
|
51
|
+
if (protocol === "google-models") {
|
|
52
|
+
const google = {
|
|
53
|
+
baseURL: model.provider?.api ?? "https://opencode.ai/inference/go/google/v1beta",
|
|
54
|
+
apiKey: variables.opencodeApiKey
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
textGenerate: withSession(geminiGenerateProtocol(google)),
|
|
58
|
+
textStream: withSession(geminiStreamProtocol(google))
|
|
59
|
+
};
|
|
60
|
+
}
|
|
50
61
|
return protocol === void 0 ? void 0 : protocols[protocol];
|
|
51
62
|
});
|
|
52
63
|
} });
|