@yourgpt/llm-sdk 2.0.1 → 2.0.2-beta.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/adapters/index.d.mts +27 -4
- package/dist/adapters/index.d.ts +27 -4
- package/dist/adapters/index.js +395 -25
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/index.mjs +395 -25
- package/dist/adapters/index.mjs.map +1 -1
- package/dist/index.d.mts +24 -5
- package/dist/index.d.ts +24 -5
- package/dist/index.js +20 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +20 -4
- package/dist/index.mjs.map +1 -1
- package/dist/providers/anthropic/index.d.mts +1 -2
- package/dist/providers/anthropic/index.d.ts +1 -2
- package/dist/providers/anthropic/index.js +108 -12
- package/dist/providers/anthropic/index.js.map +1 -1
- package/dist/providers/anthropic/index.mjs +108 -12
- package/dist/providers/anthropic/index.mjs.map +1 -1
- package/dist/providers/azure/index.d.mts +1 -2
- package/dist/providers/azure/index.d.ts +1 -2
- package/dist/providers/azure/index.js.map +1 -1
- package/dist/providers/azure/index.mjs.map +1 -1
- package/dist/providers/google/index.d.mts +1 -2
- package/dist/providers/google/index.d.ts +1 -2
- package/dist/providers/google/index.js +61 -2
- package/dist/providers/google/index.js.map +1 -1
- package/dist/providers/google/index.mjs +61 -2
- package/dist/providers/google/index.mjs.map +1 -1
- package/dist/providers/ollama/index.d.mts +8 -3
- package/dist/providers/ollama/index.d.ts +8 -3
- package/dist/providers/ollama/index.js +227 -17
- package/dist/providers/ollama/index.js.map +1 -1
- package/dist/providers/ollama/index.mjs +227 -17
- package/dist/providers/ollama/index.mjs.map +1 -1
- package/dist/providers/openai/index.d.mts +1 -2
- package/dist/providers/openai/index.d.ts +1 -2
- package/dist/providers/openai/index.js +57 -3
- package/dist/providers/openai/index.js.map +1 -1
- package/dist/providers/openai/index.mjs +57 -3
- package/dist/providers/openai/index.mjs.map +1 -1
- package/dist/providers/openrouter/index.d.mts +56 -3
- package/dist/providers/openrouter/index.d.ts +56 -3
- package/dist/providers/openrouter/index.js +90 -276
- package/dist/providers/openrouter/index.js.map +1 -1
- package/dist/providers/openrouter/index.mjs +89 -277
- package/dist/providers/openrouter/index.mjs.map +1 -1
- package/dist/providers/xai/index.d.mts +1 -2
- package/dist/providers/xai/index.d.ts +1 -2
- package/dist/providers/xai/index.js.map +1 -1
- package/dist/providers/xai/index.mjs.map +1 -1
- package/dist/{base-DdxolpKP.d.mts → types-C_f95PKp.d.mts} +434 -3
- package/dist/{base-DdxolpKP.d.ts → types-C_f95PKp.d.ts} +434 -3
- package/package.json +1 -1
- package/dist/types-Ck25ZYma.d.mts +0 -323
- package/dist/types-Dsz8SpdB.d.ts +0 -323
package/dist/adapters/index.js
CHANGED
|
@@ -361,29 +361,60 @@ var OpenAIAdapter = class {
|
|
|
361
361
|
request.systemPrompt
|
|
362
362
|
);
|
|
363
363
|
}
|
|
364
|
-
const tools = request.actions?.length ? formatTools(request.actions) :
|
|
364
|
+
const tools = request.actions?.length ? formatTools(request.actions) : [];
|
|
365
|
+
const webSearchConfig = request.webSearch ?? this.config.webSearch;
|
|
366
|
+
if (webSearchConfig) {
|
|
367
|
+
const webSearchTool = {
|
|
368
|
+
type: "web_search_preview"
|
|
369
|
+
};
|
|
370
|
+
const wsConfig = typeof webSearchConfig === "object" ? webSearchConfig : {};
|
|
371
|
+
if (wsConfig.userLocation) {
|
|
372
|
+
webSearchTool.search_context_size = "medium";
|
|
373
|
+
}
|
|
374
|
+
tools.push(webSearchTool);
|
|
375
|
+
}
|
|
365
376
|
const messageId = generateMessageId();
|
|
366
377
|
yield { type: "message:start", id: messageId };
|
|
367
378
|
try {
|
|
368
379
|
const stream = await client.chat.completions.create({
|
|
369
380
|
model: request.config?.model || this.model,
|
|
370
381
|
messages,
|
|
371
|
-
tools,
|
|
382
|
+
tools: tools.length > 0 ? tools : void 0,
|
|
372
383
|
temperature: request.config?.temperature ?? this.config.temperature,
|
|
373
384
|
max_tokens: request.config?.maxTokens ?? this.config.maxTokens,
|
|
374
385
|
stream: true,
|
|
375
386
|
stream_options: { include_usage: true }
|
|
376
387
|
});
|
|
377
388
|
let currentToolCall = null;
|
|
389
|
+
const collectedCitations = [];
|
|
390
|
+
let citationIndex = 0;
|
|
378
391
|
let usage;
|
|
379
392
|
for await (const chunk of stream) {
|
|
380
393
|
if (request.signal?.aborted) {
|
|
381
394
|
break;
|
|
382
395
|
}
|
|
383
396
|
const delta = chunk.choices[0]?.delta;
|
|
397
|
+
const choice = chunk.choices[0];
|
|
384
398
|
if (delta?.content) {
|
|
385
399
|
yield { type: "message:delta", content: delta.content };
|
|
386
400
|
}
|
|
401
|
+
const annotations = delta?.annotations;
|
|
402
|
+
if (annotations && annotations.length > 0) {
|
|
403
|
+
for (const annotation of annotations) {
|
|
404
|
+
if (annotation.type === "url_citation" && annotation.url_citation?.url) {
|
|
405
|
+
citationIndex++;
|
|
406
|
+
const url = annotation.url_citation.url;
|
|
407
|
+
const domain = extractDomain(url);
|
|
408
|
+
collectedCitations.push({
|
|
409
|
+
index: citationIndex,
|
|
410
|
+
url,
|
|
411
|
+
title: annotation.url_citation.title || domain,
|
|
412
|
+
domain,
|
|
413
|
+
favicon: domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=32` : void 0
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
387
418
|
if (delta?.tool_calls) {
|
|
388
419
|
for (const toolCall of delta.tool_calls) {
|
|
389
420
|
if (toolCall.id) {
|
|
@@ -416,7 +447,7 @@ var OpenAIAdapter = class {
|
|
|
416
447
|
total_tokens: chunk.usage.total_tokens
|
|
417
448
|
};
|
|
418
449
|
}
|
|
419
|
-
if (
|
|
450
|
+
if (choice?.finish_reason) {
|
|
420
451
|
if (currentToolCall) {
|
|
421
452
|
yield {
|
|
422
453
|
type: "action:args",
|
|
@@ -426,6 +457,10 @@ var OpenAIAdapter = class {
|
|
|
426
457
|
}
|
|
427
458
|
}
|
|
428
459
|
}
|
|
460
|
+
if (collectedCitations.length > 0) {
|
|
461
|
+
const uniqueCitations = deduplicateCitations(collectedCitations);
|
|
462
|
+
yield { type: "citation", citations: uniqueCitations };
|
|
463
|
+
}
|
|
429
464
|
yield { type: "message:end" };
|
|
430
465
|
yield { type: "done", usage };
|
|
431
466
|
} catch (error) {
|
|
@@ -437,6 +472,25 @@ var OpenAIAdapter = class {
|
|
|
437
472
|
}
|
|
438
473
|
}
|
|
439
474
|
};
|
|
475
|
+
function extractDomain(url) {
|
|
476
|
+
try {
|
|
477
|
+
const parsed = new URL(url);
|
|
478
|
+
return parsed.hostname;
|
|
479
|
+
} catch {
|
|
480
|
+
return "";
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
function deduplicateCitations(citations) {
|
|
484
|
+
const seen = /* @__PURE__ */ new Map();
|
|
485
|
+
let index = 0;
|
|
486
|
+
for (const citation of citations) {
|
|
487
|
+
if (!seen.has(citation.url)) {
|
|
488
|
+
index++;
|
|
489
|
+
seen.set(citation.url, { ...citation, index });
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return Array.from(seen.values());
|
|
493
|
+
}
|
|
440
494
|
function createOpenAIAdapter(config) {
|
|
441
495
|
return new OpenAIAdapter(config);
|
|
442
496
|
}
|
|
@@ -635,14 +689,45 @@ var AnthropicAdapter = class {
|
|
|
635
689
|
) : {},
|
|
636
690
|
required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : []
|
|
637
691
|
}
|
|
638
|
-
}));
|
|
692
|
+
})) || [];
|
|
693
|
+
const webSearchConfig = request.webSearch ?? this.config.webSearch;
|
|
694
|
+
let serverToolConfiguration;
|
|
695
|
+
if (webSearchConfig) {
|
|
696
|
+
tools.push({
|
|
697
|
+
type: "web_search_20260209",
|
|
698
|
+
name: "web_search",
|
|
699
|
+
allowed_callers: ["direct"]
|
|
700
|
+
});
|
|
701
|
+
const wsConfig = typeof webSearchConfig === "object" ? webSearchConfig : {};
|
|
702
|
+
const webSearchToolConfig = {};
|
|
703
|
+
if (wsConfig.maxUses !== void 0) {
|
|
704
|
+
webSearchToolConfig.max_uses = wsConfig.maxUses;
|
|
705
|
+
}
|
|
706
|
+
if (wsConfig.allowedDomains && wsConfig.allowedDomains.length > 0) {
|
|
707
|
+
webSearchToolConfig.allowed_domains = wsConfig.allowedDomains;
|
|
708
|
+
}
|
|
709
|
+
if (wsConfig.blockedDomains && wsConfig.blockedDomains.length > 0) {
|
|
710
|
+
webSearchToolConfig.blocked_domains = wsConfig.blockedDomains;
|
|
711
|
+
}
|
|
712
|
+
if (wsConfig.userLocation) {
|
|
713
|
+
webSearchToolConfig.user_location = wsConfig.userLocation;
|
|
714
|
+
}
|
|
715
|
+
if (Object.keys(webSearchToolConfig).length > 0) {
|
|
716
|
+
serverToolConfiguration = {
|
|
717
|
+
web_search: webSearchToolConfig
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
}
|
|
639
721
|
const options = {
|
|
640
722
|
model: request.config?.model || this.model,
|
|
641
723
|
max_tokens: request.config?.maxTokens || this.config.maxTokens || 4096,
|
|
642
724
|
system: systemMessage,
|
|
643
725
|
messages,
|
|
644
|
-
tools: tools
|
|
726
|
+
tools: tools.length ? tools : void 0
|
|
645
727
|
};
|
|
728
|
+
if (serverToolConfiguration) {
|
|
729
|
+
options.server_tool_configuration = serverToolConfiguration;
|
|
730
|
+
}
|
|
646
731
|
if (this.config.thinking?.type === "enabled") {
|
|
647
732
|
options.thinking = {
|
|
648
733
|
type: "enabled",
|
|
@@ -698,6 +783,8 @@ var AnthropicAdapter = class {
|
|
|
698
783
|
const stream = await client.messages.stream(options);
|
|
699
784
|
let currentToolUse = null;
|
|
700
785
|
let isInThinkingBlock = false;
|
|
786
|
+
const collectedCitations = [];
|
|
787
|
+
let citationIndex = 0;
|
|
701
788
|
let usage;
|
|
702
789
|
for await (const event of stream) {
|
|
703
790
|
if (request.signal?.aborted) {
|
|
@@ -726,11 +813,30 @@ var AnthropicAdapter = class {
|
|
|
726
813
|
name: event.content_block.name,
|
|
727
814
|
input: ""
|
|
728
815
|
};
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
816
|
+
if (currentToolUse.name !== "web_search") {
|
|
817
|
+
yield {
|
|
818
|
+
type: "action:start",
|
|
819
|
+
id: currentToolUse.id,
|
|
820
|
+
name: currentToolUse.name
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
} else if (event.content_block.type === "web_search_tool_result") {
|
|
824
|
+
const webSearchResult = event.content_block;
|
|
825
|
+
if (webSearchResult.content && Array.isArray(webSearchResult.content)) {
|
|
826
|
+
for (const result of webSearchResult.content) {
|
|
827
|
+
if (result.type === "web_search_result" && result.url) {
|
|
828
|
+
citationIndex++;
|
|
829
|
+
const domain = extractDomain2(result.url);
|
|
830
|
+
collectedCitations.push({
|
|
831
|
+
index: citationIndex,
|
|
832
|
+
url: result.url,
|
|
833
|
+
title: result.title || domain,
|
|
834
|
+
domain,
|
|
835
|
+
favicon: domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=32` : void 0
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
734
840
|
} else if (event.content_block.type === "thinking") {
|
|
735
841
|
isInThinkingBlock = true;
|
|
736
842
|
yield { type: "thinking:start" };
|
|
@@ -739,6 +845,20 @@ var AnthropicAdapter = class {
|
|
|
739
845
|
case "content_block_delta":
|
|
740
846
|
if (event.delta.type === "text_delta") {
|
|
741
847
|
yield { type: "message:delta", content: event.delta.text };
|
|
848
|
+
} else if (event.delta.type === "citations_delta") {
|
|
849
|
+
const citationsDelta = event.delta;
|
|
850
|
+
if (citationsDelta.citation?.url) {
|
|
851
|
+
citationIndex++;
|
|
852
|
+
const domain = extractDomain2(citationsDelta.citation.url);
|
|
853
|
+
collectedCitations.push({
|
|
854
|
+
index: citationIndex,
|
|
855
|
+
url: citationsDelta.citation.url,
|
|
856
|
+
title: citationsDelta.citation.title || domain,
|
|
857
|
+
citedText: citationsDelta.citation.cited_text,
|
|
858
|
+
domain,
|
|
859
|
+
favicon: domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=32` : void 0
|
|
860
|
+
});
|
|
861
|
+
}
|
|
742
862
|
} else if (event.delta.type === "thinking_delta") {
|
|
743
863
|
yield { type: "thinking:delta", content: event.delta.thinking };
|
|
744
864
|
} else if (event.delta.type === "input_json_delta" && currentToolUse) {
|
|
@@ -747,11 +867,18 @@ var AnthropicAdapter = class {
|
|
|
747
867
|
break;
|
|
748
868
|
case "content_block_stop":
|
|
749
869
|
if (currentToolUse) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
870
|
+
if (currentToolUse.name !== "web_search") {
|
|
871
|
+
yield {
|
|
872
|
+
type: "action:args",
|
|
873
|
+
id: currentToolUse.id,
|
|
874
|
+
args: currentToolUse.input
|
|
875
|
+
};
|
|
876
|
+
yield {
|
|
877
|
+
type: "action:end",
|
|
878
|
+
id: currentToolUse.id,
|
|
879
|
+
name: currentToolUse.name
|
|
880
|
+
};
|
|
881
|
+
}
|
|
755
882
|
currentToolUse = null;
|
|
756
883
|
}
|
|
757
884
|
if (isInThinkingBlock) {
|
|
@@ -763,6 +890,10 @@ var AnthropicAdapter = class {
|
|
|
763
890
|
break;
|
|
764
891
|
}
|
|
765
892
|
}
|
|
893
|
+
if (collectedCitations.length > 0) {
|
|
894
|
+
const uniqueCitations = deduplicateCitations2(collectedCitations);
|
|
895
|
+
yield { type: "citation", citations: uniqueCitations };
|
|
896
|
+
}
|
|
766
897
|
yield { type: "message:end" };
|
|
767
898
|
yield { type: "done", usage };
|
|
768
899
|
} catch (error) {
|
|
@@ -774,11 +905,136 @@ var AnthropicAdapter = class {
|
|
|
774
905
|
}
|
|
775
906
|
}
|
|
776
907
|
};
|
|
908
|
+
function extractDomain2(url) {
|
|
909
|
+
try {
|
|
910
|
+
const parsed = new URL(url);
|
|
911
|
+
return parsed.hostname;
|
|
912
|
+
} catch {
|
|
913
|
+
return "";
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
function deduplicateCitations2(citations) {
|
|
917
|
+
const seen = /* @__PURE__ */ new Map();
|
|
918
|
+
let index = 0;
|
|
919
|
+
for (const citation of citations) {
|
|
920
|
+
if (!seen.has(citation.url)) {
|
|
921
|
+
index++;
|
|
922
|
+
seen.set(citation.url, { ...citation, index });
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
return Array.from(seen.values());
|
|
926
|
+
}
|
|
777
927
|
function createAnthropicAdapter(config) {
|
|
778
928
|
return new AnthropicAdapter(config);
|
|
779
929
|
}
|
|
780
930
|
|
|
781
931
|
// src/adapters/ollama.ts
|
|
932
|
+
function extractBase64Data(data) {
|
|
933
|
+
if (data.startsWith("data:")) {
|
|
934
|
+
const commaIndex = data.indexOf(",");
|
|
935
|
+
if (commaIndex !== -1) {
|
|
936
|
+
return data.slice(commaIndex + 1);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return data;
|
|
940
|
+
}
|
|
941
|
+
async function downloadImageAsBase64(url) {
|
|
942
|
+
try {
|
|
943
|
+
const response = await fetch(url);
|
|
944
|
+
if (!response.ok) return null;
|
|
945
|
+
const buffer = await response.arrayBuffer();
|
|
946
|
+
const base64 = Buffer.from(buffer).toString("base64");
|
|
947
|
+
return base64;
|
|
948
|
+
} catch {
|
|
949
|
+
return null;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
async function extractImagesFromAttachments(attachments) {
|
|
953
|
+
if (!attachments) return [];
|
|
954
|
+
const images = [];
|
|
955
|
+
for (const attachment of attachments) {
|
|
956
|
+
if (attachment.type !== "image") continue;
|
|
957
|
+
if (attachment.data) {
|
|
958
|
+
images.push(extractBase64Data(attachment.data));
|
|
959
|
+
} else if (attachment.url) {
|
|
960
|
+
const base64 = await downloadImageAsBase64(attachment.url);
|
|
961
|
+
if (base64) {
|
|
962
|
+
images.push(base64);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
return images;
|
|
967
|
+
}
|
|
968
|
+
async function formatMessagesForOllama(messages, systemPrompt) {
|
|
969
|
+
const formatted = [];
|
|
970
|
+
if (systemPrompt) {
|
|
971
|
+
formatted.push({ role: "system", content: systemPrompt });
|
|
972
|
+
}
|
|
973
|
+
for (const msg of messages) {
|
|
974
|
+
const baseMessage = {
|
|
975
|
+
role: msg.role,
|
|
976
|
+
content: msg.content ?? ""
|
|
977
|
+
};
|
|
978
|
+
if (msg.role === "user" && msg.metadata?.attachments) {
|
|
979
|
+
const images = await extractImagesFromAttachments(
|
|
980
|
+
msg.metadata.attachments
|
|
981
|
+
);
|
|
982
|
+
if (images.length > 0) {
|
|
983
|
+
baseMessage.images = images;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
if (msg.role === "assistant" && msg.tool_calls && msg.tool_calls.length > 0) {
|
|
987
|
+
baseMessage.tool_calls = msg.tool_calls.map((tc) => ({
|
|
988
|
+
id: tc.id,
|
|
989
|
+
function: {
|
|
990
|
+
name: tc.function.name,
|
|
991
|
+
arguments: JSON.parse(tc.function.arguments)
|
|
992
|
+
}
|
|
993
|
+
}));
|
|
994
|
+
}
|
|
995
|
+
if (msg.role === "tool" && msg.tool_call_id) {
|
|
996
|
+
baseMessage.tool_call_id = msg.tool_call_id;
|
|
997
|
+
}
|
|
998
|
+
formatted.push(baseMessage);
|
|
999
|
+
}
|
|
1000
|
+
return formatted;
|
|
1001
|
+
}
|
|
1002
|
+
async function processRawMessagesForOllama(rawMessages, systemPrompt) {
|
|
1003
|
+
const processed = [];
|
|
1004
|
+
if (systemPrompt) {
|
|
1005
|
+
const hasSystem = rawMessages.some((m) => m.role === "system");
|
|
1006
|
+
if (!hasSystem) {
|
|
1007
|
+
processed.push({ role: "system", content: systemPrompt });
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
for (const msg of rawMessages) {
|
|
1011
|
+
const baseMessage = {
|
|
1012
|
+
role: msg.role,
|
|
1013
|
+
content: msg.content ?? ""
|
|
1014
|
+
};
|
|
1015
|
+
if (msg.role === "user" && msg.attachments && Array.isArray(msg.attachments)) {
|
|
1016
|
+
const attachments = msg.attachments;
|
|
1017
|
+
const images = await extractImagesFromAttachments(attachments);
|
|
1018
|
+
if (images.length > 0) {
|
|
1019
|
+
baseMessage.images = images;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
if (msg.tool_calls && Array.isArray(msg.tool_calls)) {
|
|
1023
|
+
baseMessage.tool_calls = msg.tool_calls.map((tc) => ({
|
|
1024
|
+
id: tc.id,
|
|
1025
|
+
function: {
|
|
1026
|
+
name: tc.function.name,
|
|
1027
|
+
arguments: typeof tc.function.arguments === "string" ? JSON.parse(tc.function.arguments) : tc.function.arguments
|
|
1028
|
+
}
|
|
1029
|
+
}));
|
|
1030
|
+
}
|
|
1031
|
+
if (msg.tool_call_id) {
|
|
1032
|
+
baseMessage.tool_call_id = msg.tool_call_id;
|
|
1033
|
+
}
|
|
1034
|
+
processed.push(baseMessage);
|
|
1035
|
+
}
|
|
1036
|
+
return processed;
|
|
1037
|
+
}
|
|
782
1038
|
var OllamaAdapter = class {
|
|
783
1039
|
constructor(config = {}) {
|
|
784
1040
|
this.provider = "ollama";
|
|
@@ -787,10 +1043,32 @@ var OllamaAdapter = class {
|
|
|
787
1043
|
this.baseUrl = config.baseUrl || "http://localhost:11434";
|
|
788
1044
|
}
|
|
789
1045
|
async *stream(request) {
|
|
790
|
-
|
|
1046
|
+
let messages;
|
|
1047
|
+
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
1048
|
+
messages = await processRawMessagesForOllama(
|
|
1049
|
+
request.rawMessages,
|
|
1050
|
+
request.systemPrompt
|
|
1051
|
+
);
|
|
1052
|
+
} else {
|
|
1053
|
+
messages = await formatMessagesForOllama(
|
|
1054
|
+
request.messages,
|
|
1055
|
+
request.systemPrompt
|
|
1056
|
+
);
|
|
1057
|
+
}
|
|
1058
|
+
const tools = request.actions?.length ? formatTools(request.actions) : void 0;
|
|
791
1059
|
const messageId = generateMessageId();
|
|
792
1060
|
yield { type: "message:start", id: messageId };
|
|
793
1061
|
try {
|
|
1062
|
+
const ollamaOptions = {
|
|
1063
|
+
temperature: request.config?.temperature ?? this.config.temperature
|
|
1064
|
+
};
|
|
1065
|
+
const maxTokens = request.config?.maxTokens ?? this.config.maxTokens;
|
|
1066
|
+
if (maxTokens !== void 0) {
|
|
1067
|
+
ollamaOptions.num_predict = maxTokens;
|
|
1068
|
+
}
|
|
1069
|
+
if (this.config.options) {
|
|
1070
|
+
Object.assign(ollamaOptions, this.config.options);
|
|
1071
|
+
}
|
|
794
1072
|
const response = await fetch(`${this.baseUrl}/api/chat`, {
|
|
795
1073
|
method: "POST",
|
|
796
1074
|
headers: {
|
|
@@ -799,16 +1077,15 @@ var OllamaAdapter = class {
|
|
|
799
1077
|
body: JSON.stringify({
|
|
800
1078
|
model: request.config?.model || this.model,
|
|
801
1079
|
messages,
|
|
1080
|
+
tools,
|
|
802
1081
|
stream: true,
|
|
803
|
-
options:
|
|
804
|
-
temperature: request.config?.temperature ?? this.config.temperature,
|
|
805
|
-
num_predict: request.config?.maxTokens ?? this.config.maxTokens
|
|
806
|
-
}
|
|
1082
|
+
options: ollamaOptions
|
|
807
1083
|
}),
|
|
808
1084
|
signal: request.signal
|
|
809
1085
|
});
|
|
810
1086
|
if (!response.ok) {
|
|
811
|
-
|
|
1087
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
1088
|
+
throw new Error(`Ollama API error: ${response.status} - ${errorText}`);
|
|
812
1089
|
}
|
|
813
1090
|
if (!response.body) {
|
|
814
1091
|
throw new Error("No response body");
|
|
@@ -816,6 +1093,8 @@ var OllamaAdapter = class {
|
|
|
816
1093
|
const reader = response.body.getReader();
|
|
817
1094
|
const decoder = new TextDecoder();
|
|
818
1095
|
let buffer = "";
|
|
1096
|
+
let hasEmittedToolCalls = false;
|
|
1097
|
+
const toolCallsInProgress = /* @__PURE__ */ new Map();
|
|
819
1098
|
while (true) {
|
|
820
1099
|
const { done, value } = await reader.read();
|
|
821
1100
|
if (done) break;
|
|
@@ -829,6 +1108,28 @@ var OllamaAdapter = class {
|
|
|
829
1108
|
if (chunk.message?.content) {
|
|
830
1109
|
yield { type: "message:delta", content: chunk.message.content };
|
|
831
1110
|
}
|
|
1111
|
+
if (chunk.message?.tool_calls && !hasEmittedToolCalls) {
|
|
1112
|
+
for (let i = 0; i < chunk.message.tool_calls.length; i++) {
|
|
1113
|
+
const toolCall = chunk.message.tool_calls[i];
|
|
1114
|
+
const toolCallId = toolCall.id || generateToolCallId();
|
|
1115
|
+
toolCallsInProgress.set(i, {
|
|
1116
|
+
id: toolCallId,
|
|
1117
|
+
name: toolCall.function?.name || "",
|
|
1118
|
+
arguments: toolCall.function?.arguments || {}
|
|
1119
|
+
});
|
|
1120
|
+
yield {
|
|
1121
|
+
type: "action:start",
|
|
1122
|
+
id: toolCallId,
|
|
1123
|
+
name: toolCall.function?.name || ""
|
|
1124
|
+
};
|
|
1125
|
+
yield {
|
|
1126
|
+
type: "action:args",
|
|
1127
|
+
id: toolCallId,
|
|
1128
|
+
args: JSON.stringify(toolCall.function?.arguments || {})
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
hasEmittedToolCalls = true;
|
|
1132
|
+
}
|
|
832
1133
|
if (chunk.done) {
|
|
833
1134
|
break;
|
|
834
1135
|
}
|
|
@@ -842,10 +1143,20 @@ var OllamaAdapter = class {
|
|
|
842
1143
|
if (error.name === "AbortError") {
|
|
843
1144
|
yield { type: "done" };
|
|
844
1145
|
} else {
|
|
1146
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
1147
|
+
let code = "OLLAMA_ERROR";
|
|
1148
|
+
let message = errorMessage;
|
|
1149
|
+
if (errorMessage.includes("ECONNREFUSED") || errorMessage.includes("fetch failed")) {
|
|
1150
|
+
message = `Cannot connect to Ollama at ${this.baseUrl}. Make sure Ollama is running (ollama serve).`;
|
|
1151
|
+
code = "OLLAMA_CONNECTION_ERROR";
|
|
1152
|
+
} else if (errorMessage.includes("model") && errorMessage.includes("not found")) {
|
|
1153
|
+
message = `Model "${this.model}" not found. Pull it with: ollama pull ${this.model}`;
|
|
1154
|
+
code = "OLLAMA_MODEL_NOT_FOUND";
|
|
1155
|
+
}
|
|
845
1156
|
yield {
|
|
846
1157
|
type: "error",
|
|
847
|
-
message
|
|
848
|
-
code
|
|
1158
|
+
message,
|
|
1159
|
+
code
|
|
849
1160
|
};
|
|
850
1161
|
}
|
|
851
1162
|
}
|
|
@@ -986,6 +1297,7 @@ var GoogleAdapter = class {
|
|
|
986
1297
|
async *stream(request) {
|
|
987
1298
|
const client = await this.getClient();
|
|
988
1299
|
const modelId = request.config?.model || this.model;
|
|
1300
|
+
const webSearchConfig = request.webSearch ?? this.config.webSearch;
|
|
989
1301
|
const model = client.getGenerativeModel({
|
|
990
1302
|
model: modelId,
|
|
991
1303
|
safetySettings: this.config.safetySettings
|
|
@@ -1033,7 +1345,16 @@ var GoogleAdapter = class {
|
|
|
1033
1345
|
mergedContents.push({ ...content, parts: [...content.parts] });
|
|
1034
1346
|
}
|
|
1035
1347
|
}
|
|
1036
|
-
const
|
|
1348
|
+
const functionTools = formatToolsForGemini(request.actions);
|
|
1349
|
+
const toolsArray = [];
|
|
1350
|
+
if (functionTools) {
|
|
1351
|
+
toolsArray.push(functionTools);
|
|
1352
|
+
}
|
|
1353
|
+
if (webSearchConfig) {
|
|
1354
|
+
toolsArray.push({
|
|
1355
|
+
google_search: {}
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1037
1358
|
const messageId = generateMessageId();
|
|
1038
1359
|
yield { type: "message:start", id: messageId };
|
|
1039
1360
|
try {
|
|
@@ -1041,7 +1362,7 @@ var GoogleAdapter = class {
|
|
|
1041
1362
|
history: mergedContents.slice(0, -1),
|
|
1042
1363
|
// All but the last message
|
|
1043
1364
|
systemInstruction: systemInstruction ? { parts: [{ text: systemInstruction }] } : void 0,
|
|
1044
|
-
tools:
|
|
1365
|
+
tools: toolsArray.length > 0 ? toolsArray : void 0,
|
|
1045
1366
|
generationConfig: {
|
|
1046
1367
|
temperature: request.config?.temperature ?? this.config.temperature,
|
|
1047
1368
|
maxOutputTokens: request.config?.maxTokens ?? this.config.maxTokens
|
|
@@ -1050,6 +1371,7 @@ var GoogleAdapter = class {
|
|
|
1050
1371
|
const lastMessage = mergedContents[mergedContents.length - 1];
|
|
1051
1372
|
const result = await chat.sendMessageStream(lastMessage.parts);
|
|
1052
1373
|
let currentToolCall = null;
|
|
1374
|
+
const collectedCitations = [];
|
|
1053
1375
|
for await (const chunk of result.stream) {
|
|
1054
1376
|
if (request.signal?.aborted) {
|
|
1055
1377
|
break;
|
|
@@ -1091,6 +1413,24 @@ var GoogleAdapter = class {
|
|
|
1091
1413
|
};
|
|
1092
1414
|
}
|
|
1093
1415
|
}
|
|
1416
|
+
const groundingMetadata = candidate?.groundingMetadata;
|
|
1417
|
+
if (groundingMetadata?.groundingChunks) {
|
|
1418
|
+
for (const chunk2 of groundingMetadata.groundingChunks) {
|
|
1419
|
+
if (chunk2.web?.uri) {
|
|
1420
|
+
const url = chunk2.web.uri;
|
|
1421
|
+
const domain = extractDomain3(url);
|
|
1422
|
+
if (!collectedCitations.some((c) => c.url === url)) {
|
|
1423
|
+
collectedCitations.push({
|
|
1424
|
+
index: collectedCitations.length + 1,
|
|
1425
|
+
url,
|
|
1426
|
+
title: chunk2.web.title || domain,
|
|
1427
|
+
domain,
|
|
1428
|
+
favicon: domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=32` : void 0
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1094
1434
|
}
|
|
1095
1435
|
let usage;
|
|
1096
1436
|
try {
|
|
@@ -1102,8 +1442,30 @@ var GoogleAdapter = class {
|
|
|
1102
1442
|
total_tokens: response.usageMetadata.totalTokenCount || 0
|
|
1103
1443
|
};
|
|
1104
1444
|
}
|
|
1445
|
+
const finalCandidate = response.candidates?.[0];
|
|
1446
|
+
const finalGrounding = finalCandidate?.groundingMetadata;
|
|
1447
|
+
if (finalGrounding?.groundingChunks) {
|
|
1448
|
+
for (const chunk of finalGrounding.groundingChunks) {
|
|
1449
|
+
if (chunk.web?.uri) {
|
|
1450
|
+
const url = chunk.web.uri;
|
|
1451
|
+
const domain = extractDomain3(url);
|
|
1452
|
+
if (!collectedCitations.some((c) => c.url === url)) {
|
|
1453
|
+
collectedCitations.push({
|
|
1454
|
+
index: collectedCitations.length + 1,
|
|
1455
|
+
url,
|
|
1456
|
+
title: chunk.web.title || domain,
|
|
1457
|
+
domain,
|
|
1458
|
+
favicon: domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=32` : void 0
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1105
1464
|
} catch {
|
|
1106
1465
|
}
|
|
1466
|
+
if (collectedCitations.length > 0) {
|
|
1467
|
+
yield { type: "citation", citations: collectedCitations };
|
|
1468
|
+
}
|
|
1107
1469
|
yield { type: "message:end" };
|
|
1108
1470
|
yield { type: "done", usage };
|
|
1109
1471
|
} catch (error) {
|
|
@@ -1191,6 +1553,14 @@ var GoogleAdapter = class {
|
|
|
1191
1553
|
function createGoogleAdapter(config) {
|
|
1192
1554
|
return new GoogleAdapter(config);
|
|
1193
1555
|
}
|
|
1556
|
+
function extractDomain3(url) {
|
|
1557
|
+
try {
|
|
1558
|
+
const parsed = new URL(url);
|
|
1559
|
+
return parsed.hostname;
|
|
1560
|
+
} catch {
|
|
1561
|
+
return "";
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1194
1564
|
|
|
1195
1565
|
// src/adapters/xai.ts
|
|
1196
1566
|
var XAI_BASE_URL = "https://api.x.ai/v1";
|