@x12i/openrouter-runtime 1.0.0 → 1.0.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/index.cjs +90 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +90 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -191,7 +191,7 @@ function isRecord(value) {
|
|
|
191
191
|
function resultToChatToolMessage(result) {
|
|
192
192
|
return {
|
|
193
193
|
role: "tool",
|
|
194
|
-
|
|
194
|
+
tool_call_id: result.callId,
|
|
195
195
|
name: result.name,
|
|
196
196
|
content: stringifyToolResult(result.status === "completed" ? result.result : { error: result.error })
|
|
197
197
|
};
|
|
@@ -207,6 +207,9 @@ function resultToResponsesInput(result) {
|
|
|
207
207
|
// src/normalize/citations.ts
|
|
208
208
|
function extractCitations(value) {
|
|
209
209
|
const citations = [];
|
|
210
|
+
if (typeof value === "string") {
|
|
211
|
+
return extractCitationsFromText(value);
|
|
212
|
+
}
|
|
210
213
|
visit(value, (item) => {
|
|
211
214
|
const url = pickString(item, ["url", "uri"]);
|
|
212
215
|
if (!url) return;
|
|
@@ -221,7 +224,37 @@ function extractCitations(value) {
|
|
|
221
224
|
...optional("endIndex", pickNumber(item, ["end_index", "endIndex"]))
|
|
222
225
|
});
|
|
223
226
|
});
|
|
224
|
-
return
|
|
227
|
+
return dedupeCitations(citations);
|
|
228
|
+
}
|
|
229
|
+
function extractCitationsFromText(text) {
|
|
230
|
+
const citations = [];
|
|
231
|
+
const markdownLinkPattern = /\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g;
|
|
232
|
+
for (const match of text.matchAll(markdownLinkPattern)) {
|
|
233
|
+
const title = match[1];
|
|
234
|
+
const url = cleanUrl(match[2]);
|
|
235
|
+
const startIndex = match.index;
|
|
236
|
+
citations.push({
|
|
237
|
+
type: "url",
|
|
238
|
+
url,
|
|
239
|
+
sourceProvider: "openrouter",
|
|
240
|
+
raw: match[0],
|
|
241
|
+
...title ? { title } : {},
|
|
242
|
+
...startIndex !== void 0 ? { startIndex, endIndex: startIndex + match[0].length } : {}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
const urlPattern = /https?:\/\/[^\s)]+/g;
|
|
246
|
+
for (const match of text.matchAll(urlPattern)) {
|
|
247
|
+
const url = cleanUrl(match[0]);
|
|
248
|
+
const startIndex = match.index;
|
|
249
|
+
citations.push({
|
|
250
|
+
type: "url",
|
|
251
|
+
url,
|
|
252
|
+
sourceProvider: "openrouter",
|
|
253
|
+
raw: match[0],
|
|
254
|
+
...startIndex !== void 0 ? { startIndex, endIndex: startIndex + match[0].length } : {}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return dedupeCitations(citations);
|
|
225
258
|
}
|
|
226
259
|
function optional(key, value) {
|
|
227
260
|
return value === void 0 ? {} : { [key]: value };
|
|
@@ -243,15 +276,18 @@ function pickNumber(record, keys) {
|
|
|
243
276
|
for (const key of keys) if (typeof record[key] === "number") return record[key];
|
|
244
277
|
return void 0;
|
|
245
278
|
}
|
|
246
|
-
function
|
|
279
|
+
function dedupeCitations(citations) {
|
|
247
280
|
const seen = /* @__PURE__ */ new Set();
|
|
248
281
|
return citations.filter((citation) => {
|
|
249
|
-
const key =
|
|
282
|
+
const key = citation.url;
|
|
250
283
|
if (seen.has(key)) return false;
|
|
251
284
|
seen.add(key);
|
|
252
285
|
return true;
|
|
253
286
|
});
|
|
254
287
|
}
|
|
288
|
+
function cleanUrl(url) {
|
|
289
|
+
return (url ?? "").replace(/[.,;:!?]+$/, "");
|
|
290
|
+
}
|
|
255
291
|
|
|
256
292
|
// src/normalize/images.ts
|
|
257
293
|
function extractImages(value) {
|
|
@@ -433,7 +469,10 @@ function normalizeChatResponse(params) {
|
|
|
433
469
|
apiMode: params.apiMode,
|
|
434
470
|
model: typeof responseRecord.model === "string" ? responseRecord.model : params.model,
|
|
435
471
|
text,
|
|
436
|
-
citations:
|
|
472
|
+
citations: dedupeCitations([
|
|
473
|
+
...extractCitations([message.annotations, responseRecord.citations, params.response]),
|
|
474
|
+
...extractCitations(text)
|
|
475
|
+
]),
|
|
437
476
|
images: extractImages(params.response),
|
|
438
477
|
patches: extractPatches(params.response),
|
|
439
478
|
toolUsage: createToolUsage(params.serverTools, params.response, params.functionToolUsage),
|
|
@@ -466,6 +505,10 @@ function optional3(key, value) {
|
|
|
466
505
|
async function validatePostResponse(response, defaults) {
|
|
467
506
|
const errors = [...response.errors];
|
|
468
507
|
const warnings = [...response.warnings];
|
|
508
|
+
if (response.toolUsage.serverTools.webSearch.requested && response.citations.length > 0 && !response.toolUsage.serverTools.webSearch.used) {
|
|
509
|
+
response.toolUsage.serverTools.webSearch.used = true;
|
|
510
|
+
response.toolUsage.serverTools.webSearch.callCount = Math.max(response.toolUsage.serverTools.webSearch.callCount ?? 0, 1);
|
|
511
|
+
}
|
|
469
512
|
for (const [key, usage] of Object.entries(response.toolUsage.serverTools)) {
|
|
470
513
|
if (usage.required && !usage.used) {
|
|
471
514
|
const code = `${toScreamingSnake(key)}_REQUIRED_BUT_NOT_USED`;
|
|
@@ -862,7 +905,7 @@ function compileMessages(request) {
|
|
|
862
905
|
if (request.system) messages.push({ role: "system", content: request.system });
|
|
863
906
|
if (request.messages) messages.push(...request.messages);
|
|
864
907
|
if (request.prompt) messages.push({ role: "user", content: request.prompt });
|
|
865
|
-
return messages;
|
|
908
|
+
return messages.map(compileMessage);
|
|
866
909
|
}
|
|
867
910
|
function compilePromptInput(request) {
|
|
868
911
|
if (request.prompt) return request.prompt;
|
|
@@ -871,6 +914,32 @@ function compilePromptInput(request) {
|
|
|
871
914
|
content: message.content
|
|
872
915
|
}));
|
|
873
916
|
}
|
|
917
|
+
function compileMessage(message) {
|
|
918
|
+
return clean({
|
|
919
|
+
role: message.role,
|
|
920
|
+
content: compileContent(message.content),
|
|
921
|
+
name: message.name,
|
|
922
|
+
tool_call_id: message.toolCallId
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
function compileContent(content) {
|
|
926
|
+
if (typeof content === "string") return content;
|
|
927
|
+
return content.map((part) => {
|
|
928
|
+
if (part.type === "image_url") {
|
|
929
|
+
return { type: "image_url", image_url: { url: part.imageUrl } };
|
|
930
|
+
}
|
|
931
|
+
if (part.type === "file") {
|
|
932
|
+
return clean({
|
|
933
|
+
type: "file",
|
|
934
|
+
file_name: part.fileName,
|
|
935
|
+
mime_type: part.mimeType,
|
|
936
|
+
data: part.data,
|
|
937
|
+
url: part.url
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
return part;
|
|
941
|
+
});
|
|
942
|
+
}
|
|
874
943
|
function compileToolChoice(choice, serverTools) {
|
|
875
944
|
if (!choice || choice === "auto") return void 0;
|
|
876
945
|
if (choice === "none" || choice === "required") return choice;
|
|
@@ -998,7 +1067,7 @@ async function executeFunctionCalls(params) {
|
|
|
998
1067
|
name: result.name,
|
|
999
1068
|
callId: result.callId,
|
|
1000
1069
|
status: result.status,
|
|
1001
|
-
args: call.args,
|
|
1070
|
+
args: parseToolArgs(call.args),
|
|
1002
1071
|
...result.result !== void 0 ? { result: result.result } : {},
|
|
1003
1072
|
...result.error !== void 0 ? { error: result.error } : {},
|
|
1004
1073
|
...result.durationMs !== void 0 ? { durationMs: result.durationMs } : {}
|
|
@@ -1034,8 +1103,10 @@ async function runChat(request, compiled, context) {
|
|
|
1034
1103
|
functionUsage.push(...results);
|
|
1035
1104
|
const body = activeCompiled.body;
|
|
1036
1105
|
const messages = Array.isArray(body.messages) ? [...body.messages] : [];
|
|
1106
|
+
const assistantMessage = extractAssistantMessage(response);
|
|
1107
|
+
if (assistantMessage) messages.push(assistantMessage);
|
|
1037
1108
|
messages.push(...results.map(resultToChatToolMessage));
|
|
1038
|
-
activeCompiled = { ...activeCompiled, body: { ...body, messages } };
|
|
1109
|
+
activeCompiled = { ...activeCompiled, body: { ...body, messages, tool_choice: "auto" } };
|
|
1039
1110
|
}
|
|
1040
1111
|
const model = typeof compiled.body.model === "string" ? compiled.body.model : "";
|
|
1041
1112
|
const normalized = normalizeChatResponse({
|
|
@@ -1053,17 +1124,25 @@ async function runChat(request, compiled, context) {
|
|
|
1053
1124
|
function optional4(key, value) {
|
|
1054
1125
|
return value === void 0 ? {} : { [key]: value };
|
|
1055
1126
|
}
|
|
1127
|
+
function extractAssistantMessage(response) {
|
|
1128
|
+
const record = isRecord(response) ? response : {};
|
|
1129
|
+
const choice = Array.isArray(record.choices) && isRecord(record.choices[0]) ? record.choices[0] : {};
|
|
1130
|
+
const message = isRecord(choice.message) ? choice.message : void 0;
|
|
1131
|
+
if (!message) return void 0;
|
|
1132
|
+
return message;
|
|
1133
|
+
}
|
|
1056
1134
|
|
|
1057
1135
|
// src/normalize/normalize-responses-response.ts
|
|
1058
1136
|
function normalizeResponsesResponse(params) {
|
|
1059
1137
|
const record = isRecord(params.response) ? params.response : {};
|
|
1138
|
+
const text = extractOutputText(record);
|
|
1060
1139
|
return {
|
|
1061
1140
|
id: typeof record.id === "string" ? record.id : createRuntimeId("orresp"),
|
|
1062
1141
|
status: record.status === "requires_action" ? "requires_action" : "completed",
|
|
1063
1142
|
apiMode: "responses",
|
|
1064
1143
|
model: typeof record.model === "string" ? record.model : params.model,
|
|
1065
|
-
text
|
|
1066
|
-
citations: extractCitations(params.response),
|
|
1144
|
+
text,
|
|
1145
|
+
citations: dedupeCitations([...extractCitations(params.response), ...extractCitations(text)]),
|
|
1067
1146
|
images: extractImages(params.response),
|
|
1068
1147
|
patches: extractPatches(params.response),
|
|
1069
1148
|
toolUsage: createToolUsage(params.serverTools, params.response, params.functionToolUsage),
|
|
@@ -1125,6 +1204,7 @@ async function runResponses(request, compiled, context) {
|
|
|
1125
1204
|
...activeCompiled,
|
|
1126
1205
|
body: {
|
|
1127
1206
|
...activeCompiled.body,
|
|
1207
|
+
tool_choice: "auto",
|
|
1128
1208
|
previous_response_id: isRecord(response) && typeof response.id === "string" ? response.id : void 0,
|
|
1129
1209
|
input: results.map(resultToResponsesInput)
|
|
1130
1210
|
}
|