@x12i/openrouter-runtime 1.0.1 → 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.js
CHANGED
|
@@ -161,7 +161,7 @@ function isRecord(value) {
|
|
|
161
161
|
function resultToChatToolMessage(result) {
|
|
162
162
|
return {
|
|
163
163
|
role: "tool",
|
|
164
|
-
|
|
164
|
+
tool_call_id: result.callId,
|
|
165
165
|
name: result.name,
|
|
166
166
|
content: stringifyToolResult(result.status === "completed" ? result.result : { error: result.error })
|
|
167
167
|
};
|
|
@@ -177,6 +177,9 @@ function resultToResponsesInput(result) {
|
|
|
177
177
|
// src/normalize/citations.ts
|
|
178
178
|
function extractCitations(value) {
|
|
179
179
|
const citations = [];
|
|
180
|
+
if (typeof value === "string") {
|
|
181
|
+
return extractCitationsFromText(value);
|
|
182
|
+
}
|
|
180
183
|
visit(value, (item) => {
|
|
181
184
|
const url = pickString(item, ["url", "uri"]);
|
|
182
185
|
if (!url) return;
|
|
@@ -191,7 +194,37 @@ function extractCitations(value) {
|
|
|
191
194
|
...optional("endIndex", pickNumber(item, ["end_index", "endIndex"]))
|
|
192
195
|
});
|
|
193
196
|
});
|
|
194
|
-
return
|
|
197
|
+
return dedupeCitations(citations);
|
|
198
|
+
}
|
|
199
|
+
function extractCitationsFromText(text) {
|
|
200
|
+
const citations = [];
|
|
201
|
+
const markdownLinkPattern = /\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g;
|
|
202
|
+
for (const match of text.matchAll(markdownLinkPattern)) {
|
|
203
|
+
const title = match[1];
|
|
204
|
+
const url = cleanUrl(match[2]);
|
|
205
|
+
const startIndex = match.index;
|
|
206
|
+
citations.push({
|
|
207
|
+
type: "url",
|
|
208
|
+
url,
|
|
209
|
+
sourceProvider: "openrouter",
|
|
210
|
+
raw: match[0],
|
|
211
|
+
...title ? { title } : {},
|
|
212
|
+
...startIndex !== void 0 ? { startIndex, endIndex: startIndex + match[0].length } : {}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const urlPattern = /https?:\/\/[^\s)]+/g;
|
|
216
|
+
for (const match of text.matchAll(urlPattern)) {
|
|
217
|
+
const url = cleanUrl(match[0]);
|
|
218
|
+
const startIndex = match.index;
|
|
219
|
+
citations.push({
|
|
220
|
+
type: "url",
|
|
221
|
+
url,
|
|
222
|
+
sourceProvider: "openrouter",
|
|
223
|
+
raw: match[0],
|
|
224
|
+
...startIndex !== void 0 ? { startIndex, endIndex: startIndex + match[0].length } : {}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
return dedupeCitations(citations);
|
|
195
228
|
}
|
|
196
229
|
function optional(key, value) {
|
|
197
230
|
return value === void 0 ? {} : { [key]: value };
|
|
@@ -213,15 +246,18 @@ function pickNumber(record, keys) {
|
|
|
213
246
|
for (const key of keys) if (typeof record[key] === "number") return record[key];
|
|
214
247
|
return void 0;
|
|
215
248
|
}
|
|
216
|
-
function
|
|
249
|
+
function dedupeCitations(citations) {
|
|
217
250
|
const seen = /* @__PURE__ */ new Set();
|
|
218
251
|
return citations.filter((citation) => {
|
|
219
|
-
const key =
|
|
252
|
+
const key = citation.url;
|
|
220
253
|
if (seen.has(key)) return false;
|
|
221
254
|
seen.add(key);
|
|
222
255
|
return true;
|
|
223
256
|
});
|
|
224
257
|
}
|
|
258
|
+
function cleanUrl(url) {
|
|
259
|
+
return (url ?? "").replace(/[.,;:!?]+$/, "");
|
|
260
|
+
}
|
|
225
261
|
|
|
226
262
|
// src/normalize/images.ts
|
|
227
263
|
function extractImages(value) {
|
|
@@ -403,7 +439,10 @@ function normalizeChatResponse(params) {
|
|
|
403
439
|
apiMode: params.apiMode,
|
|
404
440
|
model: typeof responseRecord.model === "string" ? responseRecord.model : params.model,
|
|
405
441
|
text,
|
|
406
|
-
citations:
|
|
442
|
+
citations: dedupeCitations([
|
|
443
|
+
...extractCitations([message.annotations, responseRecord.citations, params.response]),
|
|
444
|
+
...extractCitations(text)
|
|
445
|
+
]),
|
|
407
446
|
images: extractImages(params.response),
|
|
408
447
|
patches: extractPatches(params.response),
|
|
409
448
|
toolUsage: createToolUsage(params.serverTools, params.response, params.functionToolUsage),
|
|
@@ -436,6 +475,10 @@ function optional3(key, value) {
|
|
|
436
475
|
async function validatePostResponse(response, defaults) {
|
|
437
476
|
const errors = [...response.errors];
|
|
438
477
|
const warnings = [...response.warnings];
|
|
478
|
+
if (response.toolUsage.serverTools.webSearch.requested && response.citations.length > 0 && !response.toolUsage.serverTools.webSearch.used) {
|
|
479
|
+
response.toolUsage.serverTools.webSearch.used = true;
|
|
480
|
+
response.toolUsage.serverTools.webSearch.callCount = Math.max(response.toolUsage.serverTools.webSearch.callCount ?? 0, 1);
|
|
481
|
+
}
|
|
439
482
|
for (const [key, usage] of Object.entries(response.toolUsage.serverTools)) {
|
|
440
483
|
if (usage.required && !usage.used) {
|
|
441
484
|
const code = `${toScreamingSnake(key)}_REQUIRED_BUT_NOT_USED`;
|
|
@@ -832,7 +875,7 @@ function compileMessages(request) {
|
|
|
832
875
|
if (request.system) messages.push({ role: "system", content: request.system });
|
|
833
876
|
if (request.messages) messages.push(...request.messages);
|
|
834
877
|
if (request.prompt) messages.push({ role: "user", content: request.prompt });
|
|
835
|
-
return messages;
|
|
878
|
+
return messages.map(compileMessage);
|
|
836
879
|
}
|
|
837
880
|
function compilePromptInput(request) {
|
|
838
881
|
if (request.prompt) return request.prompt;
|
|
@@ -841,6 +884,32 @@ function compilePromptInput(request) {
|
|
|
841
884
|
content: message.content
|
|
842
885
|
}));
|
|
843
886
|
}
|
|
887
|
+
function compileMessage(message) {
|
|
888
|
+
return clean({
|
|
889
|
+
role: message.role,
|
|
890
|
+
content: compileContent(message.content),
|
|
891
|
+
name: message.name,
|
|
892
|
+
tool_call_id: message.toolCallId
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
function compileContent(content) {
|
|
896
|
+
if (typeof content === "string") return content;
|
|
897
|
+
return content.map((part) => {
|
|
898
|
+
if (part.type === "image_url") {
|
|
899
|
+
return { type: "image_url", image_url: { url: part.imageUrl } };
|
|
900
|
+
}
|
|
901
|
+
if (part.type === "file") {
|
|
902
|
+
return clean({
|
|
903
|
+
type: "file",
|
|
904
|
+
file_name: part.fileName,
|
|
905
|
+
mime_type: part.mimeType,
|
|
906
|
+
data: part.data,
|
|
907
|
+
url: part.url
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
return part;
|
|
911
|
+
});
|
|
912
|
+
}
|
|
844
913
|
function compileToolChoice(choice, serverTools) {
|
|
845
914
|
if (!choice || choice === "auto") return void 0;
|
|
846
915
|
if (choice === "none" || choice === "required") return choice;
|
|
@@ -968,7 +1037,7 @@ async function executeFunctionCalls(params) {
|
|
|
968
1037
|
name: result.name,
|
|
969
1038
|
callId: result.callId,
|
|
970
1039
|
status: result.status,
|
|
971
|
-
args: call.args,
|
|
1040
|
+
args: parseToolArgs(call.args),
|
|
972
1041
|
...result.result !== void 0 ? { result: result.result } : {},
|
|
973
1042
|
...result.error !== void 0 ? { error: result.error } : {},
|
|
974
1043
|
...result.durationMs !== void 0 ? { durationMs: result.durationMs } : {}
|
|
@@ -1004,8 +1073,10 @@ async function runChat(request, compiled, context) {
|
|
|
1004
1073
|
functionUsage.push(...results);
|
|
1005
1074
|
const body = activeCompiled.body;
|
|
1006
1075
|
const messages = Array.isArray(body.messages) ? [...body.messages] : [];
|
|
1076
|
+
const assistantMessage = extractAssistantMessage(response);
|
|
1077
|
+
if (assistantMessage) messages.push(assistantMessage);
|
|
1007
1078
|
messages.push(...results.map(resultToChatToolMessage));
|
|
1008
|
-
activeCompiled = { ...activeCompiled, body: { ...body, messages } };
|
|
1079
|
+
activeCompiled = { ...activeCompiled, body: { ...body, messages, tool_choice: "auto" } };
|
|
1009
1080
|
}
|
|
1010
1081
|
const model = typeof compiled.body.model === "string" ? compiled.body.model : "";
|
|
1011
1082
|
const normalized = normalizeChatResponse({
|
|
@@ -1023,17 +1094,25 @@ async function runChat(request, compiled, context) {
|
|
|
1023
1094
|
function optional4(key, value) {
|
|
1024
1095
|
return value === void 0 ? {} : { [key]: value };
|
|
1025
1096
|
}
|
|
1097
|
+
function extractAssistantMessage(response) {
|
|
1098
|
+
const record = isRecord(response) ? response : {};
|
|
1099
|
+
const choice = Array.isArray(record.choices) && isRecord(record.choices[0]) ? record.choices[0] : {};
|
|
1100
|
+
const message = isRecord(choice.message) ? choice.message : void 0;
|
|
1101
|
+
if (!message) return void 0;
|
|
1102
|
+
return message;
|
|
1103
|
+
}
|
|
1026
1104
|
|
|
1027
1105
|
// src/normalize/normalize-responses-response.ts
|
|
1028
1106
|
function normalizeResponsesResponse(params) {
|
|
1029
1107
|
const record = isRecord(params.response) ? params.response : {};
|
|
1108
|
+
const text = extractOutputText(record);
|
|
1030
1109
|
return {
|
|
1031
1110
|
id: typeof record.id === "string" ? record.id : createRuntimeId("orresp"),
|
|
1032
1111
|
status: record.status === "requires_action" ? "requires_action" : "completed",
|
|
1033
1112
|
apiMode: "responses",
|
|
1034
1113
|
model: typeof record.model === "string" ? record.model : params.model,
|
|
1035
|
-
text
|
|
1036
|
-
citations: extractCitations(params.response),
|
|
1114
|
+
text,
|
|
1115
|
+
citations: dedupeCitations([...extractCitations(params.response), ...extractCitations(text)]),
|
|
1037
1116
|
images: extractImages(params.response),
|
|
1038
1117
|
patches: extractPatches(params.response),
|
|
1039
1118
|
toolUsage: createToolUsage(params.serverTools, params.response, params.functionToolUsage),
|
|
@@ -1095,6 +1174,7 @@ async function runResponses(request, compiled, context) {
|
|
|
1095
1174
|
...activeCompiled,
|
|
1096
1175
|
body: {
|
|
1097
1176
|
...activeCompiled.body,
|
|
1177
|
+
tool_choice: "auto",
|
|
1098
1178
|
previous_response_id: isRecord(response) && typeof response.id === "string" ? response.id : void 0,
|
|
1099
1179
|
input: results.map(resultToResponsesInput)
|
|
1100
1180
|
}
|