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