@absolutejs/absolute 0.19.0-beta.247 → 0.19.0-beta.249
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/.absolutejs/eslint-cache +1 -1
- package/.absolutejs/prettier.cache.json +17 -13
- package/.absolutejs/vue-tsc.tsbuildinfo +1 -1
- package/.claude/settings.local.json +2 -1
- package/.playwright-mcp/page-2026-03-31T16-05-33-392Z.png +0 -0
- package/dist/ai/index.js +667 -11
- package/dist/ai/index.js.map +10 -8
- package/dist/ai/providers/anthropic.js +7 -1
- package/dist/ai/providers/anthropic.js.map +3 -3
- package/dist/ai/providers/gemini.js +331 -0
- package/dist/ai/providers/gemini.js.map +10 -0
- package/dist/ai/providers/ollama.js.map +2 -2
- package/dist/ai/providers/openai.js +11 -3
- package/dist/ai/providers/openai.js.map +3 -3
- package/dist/ai/providers/openaiCompatible.js +11 -3
- package/dist/ai/providers/openaiCompatible.js.map +4 -4
- package/dist/ai/providers/openaiResponses.js +432 -0
- package/dist/ai/providers/openaiResponses.js.map +10 -0
- package/dist/ai-client/angular/ai/index.js +61 -1
- package/dist/ai-client/react/ai/index.js +61 -1
- package/dist/ai-client/vue/ai/index.js +61 -1
- package/dist/angular/ai/index.js +62 -2
- package/dist/angular/ai/index.js.map +5 -5
- package/dist/build.js +3 -1
- package/dist/build.js.map +3 -3
- package/dist/index.js +3 -1
- package/dist/index.js.map +3 -3
- package/dist/react/ai/index.js +62 -2
- package/dist/react/ai/index.js.map +6 -6
- package/dist/src/ai/client/actions.d.ts +43 -0
- package/dist/src/ai/index.d.ts +2 -0
- package/dist/src/ai/providers/gemini.d.ts +7 -0
- package/dist/src/ai/providers/openaiResponses.d.ts +10 -0
- package/dist/svelte/ai/index.js +62 -2
- package/dist/svelte/ai/index.js.map +5 -5
- package/dist/types/ai.d.ts +48 -3
- package/dist/vue/ai/index.js +62 -2
- package/dist/vue/ai/index.js.map +5 -5
- package/package.json +9 -1
- package/scripts/build.ts +2 -0
- package/types/ai.ts +80 -6
- package/types/typeGuards.ts +11 -0
package/dist/ai/index.js
CHANGED
|
@@ -106,6 +106,8 @@ var isValidAIClientMessage = (data) => {
|
|
|
106
106
|
return "content" in data && typeof data.content === "string" && "messageId" in data && "conversationId" in data;
|
|
107
107
|
case "tool_status":
|
|
108
108
|
return "name" in data && "status" in data && "messageId" in data && "conversationId" in data;
|
|
109
|
+
case "image":
|
|
110
|
+
return "data" in data && typeof data.data === "string" && "format" in data && typeof data.format === "string" && "isPartial" in data && typeof data.isPartial === "boolean" && "messageId" in data && "conversationId" in data;
|
|
109
111
|
case "complete":
|
|
110
112
|
return "messageId" in data && "conversationId" in data;
|
|
111
113
|
case "error":
|
|
@@ -207,8 +209,8 @@ var mapOpenAIContent = (msg) => {
|
|
|
207
209
|
if (typeof msg.content === "string") {
|
|
208
210
|
return msg.content;
|
|
209
211
|
}
|
|
210
|
-
const
|
|
211
|
-
if (!
|
|
212
|
+
const hasMedia = msg.content.some((block) => block.type === "image" || block.type === "document");
|
|
213
|
+
if (!hasMedia) {
|
|
212
214
|
return null;
|
|
213
215
|
}
|
|
214
216
|
const blocks = [];
|
|
@@ -220,6 +222,14 @@ var mapOpenAIContent = (msg) => {
|
|
|
220
222
|
},
|
|
221
223
|
type: "image_url"
|
|
222
224
|
});
|
|
225
|
+
} else if (block.type === "document") {
|
|
226
|
+
blocks.push({
|
|
227
|
+
file: {
|
|
228
|
+
file_data: `data:${block.source.media_type};base64,${block.source.data}`,
|
|
229
|
+
filename: block.name ?? "document.pdf"
|
|
230
|
+
},
|
|
231
|
+
type: "file"
|
|
232
|
+
});
|
|
223
233
|
} else if (block.type === "text") {
|
|
224
234
|
blocks.push({ text: block.content, type: "text" });
|
|
225
235
|
}
|
|
@@ -473,6 +483,607 @@ var moonshot = (config) => openaiCompatible({
|
|
|
473
483
|
baseUrl: "https://api.moonshot.ai"
|
|
474
484
|
});
|
|
475
485
|
|
|
486
|
+
// src/ai/providers/openaiResponses.ts
|
|
487
|
+
var DEFAULT_BASE_URL2 = "https://api.openai.com";
|
|
488
|
+
var EVENT_PREFIX_LENGTH = 7;
|
|
489
|
+
var DATA_PREFIX_LENGTH = 6;
|
|
490
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null;
|
|
491
|
+
var isRecordArray2 = (value) => Array.isArray(value) && value.length > 0 && isRecord2(value[0]);
|
|
492
|
+
var mapContentToResponsesFormat = (content) => {
|
|
493
|
+
if (typeof content === "string") {
|
|
494
|
+
return content;
|
|
495
|
+
}
|
|
496
|
+
const parts = [];
|
|
497
|
+
for (const block of content) {
|
|
498
|
+
if (block.type === "text") {
|
|
499
|
+
parts.push({ text: block.content, type: "input_text" });
|
|
500
|
+
} else if (block.type === "image") {
|
|
501
|
+
parts.push({
|
|
502
|
+
image_url: {
|
|
503
|
+
url: `data:${block.source.media_type};base64,${block.source.data}`
|
|
504
|
+
},
|
|
505
|
+
type: "input_image"
|
|
506
|
+
});
|
|
507
|
+
} else if (block.type === "document") {
|
|
508
|
+
parts.push({
|
|
509
|
+
file: {
|
|
510
|
+
file_data: `data:${block.source.media_type};base64,${block.source.data}`,
|
|
511
|
+
filename: block.name ?? "document.pdf"
|
|
512
|
+
},
|
|
513
|
+
type: "input_file"
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return parts.length > 0 ? parts : "";
|
|
518
|
+
};
|
|
519
|
+
var hasToolBlocks = (content) => content.some((block) => block.type === "tool_use" || block.type === "tool_result");
|
|
520
|
+
var convertToolBlocks = (content) => {
|
|
521
|
+
const items = [];
|
|
522
|
+
for (const block of content) {
|
|
523
|
+
if (block.type === "tool_use") {
|
|
524
|
+
items.push({
|
|
525
|
+
arguments: typeof block.input === "string" ? block.input : JSON.stringify(block.input),
|
|
526
|
+
call_id: block.id,
|
|
527
|
+
name: block.name,
|
|
528
|
+
type: "function_call"
|
|
529
|
+
});
|
|
530
|
+
} else if (block.type === "tool_result") {
|
|
531
|
+
items.push({
|
|
532
|
+
call_id: block.tool_use_id,
|
|
533
|
+
output: typeof block.content === "string" ? block.content : "",
|
|
534
|
+
type: "function_call_output"
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return items;
|
|
539
|
+
};
|
|
540
|
+
var convertMessage = (msg) => {
|
|
541
|
+
if (typeof msg.content !== "string" && Array.isArray(msg.content)) {
|
|
542
|
+
if (hasToolBlocks(msg.content)) {
|
|
543
|
+
return convertToolBlocks(msg.content);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
const content = mapContentToResponsesFormat(msg.content);
|
|
547
|
+
return [
|
|
548
|
+
{
|
|
549
|
+
content,
|
|
550
|
+
role: msg.role === "system" ? "developer" : msg.role,
|
|
551
|
+
type: "message"
|
|
552
|
+
}
|
|
553
|
+
];
|
|
554
|
+
};
|
|
555
|
+
var buildInput = (messages) => {
|
|
556
|
+
const input = [];
|
|
557
|
+
for (const msg of messages) {
|
|
558
|
+
input.push(...convertMessage(msg));
|
|
559
|
+
}
|
|
560
|
+
return input;
|
|
561
|
+
};
|
|
562
|
+
var mapToolDefinition = (tool) => ({
|
|
563
|
+
description: tool.description,
|
|
564
|
+
name: tool.name,
|
|
565
|
+
parameters: tool.input_schema,
|
|
566
|
+
type: "function"
|
|
567
|
+
});
|
|
568
|
+
var buildTools = (tools, imageGeneration) => {
|
|
569
|
+
const result = [];
|
|
570
|
+
if (tools) {
|
|
571
|
+
for (const tool of tools) {
|
|
572
|
+
result.push(mapToolDefinition(tool));
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
if (imageGeneration) {
|
|
576
|
+
const imageGenTool = {
|
|
577
|
+
type: "image_generation"
|
|
578
|
+
};
|
|
579
|
+
if (imageGeneration.partialImages !== undefined) {
|
|
580
|
+
imageGenTool.partial_images = imageGeneration.partialImages;
|
|
581
|
+
}
|
|
582
|
+
result.push(imageGenTool);
|
|
583
|
+
}
|
|
584
|
+
return result.length > 0 ? result : undefined;
|
|
585
|
+
};
|
|
586
|
+
var buildRequestBody2 = (params, imageGeneration) => {
|
|
587
|
+
const body = {
|
|
588
|
+
input: buildInput(params.messages),
|
|
589
|
+
model: params.model,
|
|
590
|
+
stream: true
|
|
591
|
+
};
|
|
592
|
+
if (params.systemPrompt) {
|
|
593
|
+
body.instructions = params.systemPrompt;
|
|
594
|
+
}
|
|
595
|
+
const tools = buildTools(params.tools, imageGeneration);
|
|
596
|
+
if (tools) {
|
|
597
|
+
body.tools = tools;
|
|
598
|
+
}
|
|
599
|
+
return body;
|
|
600
|
+
};
|
|
601
|
+
var parseJSON = (data) => {
|
|
602
|
+
try {
|
|
603
|
+
return JSON.parse(data);
|
|
604
|
+
} catch {
|
|
605
|
+
return null;
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
var parseToolInput2 = (rawArguments) => {
|
|
609
|
+
try {
|
|
610
|
+
return JSON.parse(rawArguments);
|
|
611
|
+
} catch {
|
|
612
|
+
return rawArguments;
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
var extractUsage2 = (response) => {
|
|
616
|
+
if (!isRecord2(response.usage)) {
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
const { usage } = response;
|
|
620
|
+
return {
|
|
621
|
+
inputTokens: typeof usage.input_tokens === "number" ? usage.input_tokens : 0,
|
|
622
|
+
outputTokens: typeof usage.output_tokens === "number" ? usage.output_tokens : 0
|
|
623
|
+
};
|
|
624
|
+
};
|
|
625
|
+
var extractMimeFormat = (mimeType) => {
|
|
626
|
+
if (typeof mimeType !== "string") {
|
|
627
|
+
return "png";
|
|
628
|
+
}
|
|
629
|
+
if (mimeType.includes("jpeg"))
|
|
630
|
+
return "jpeg";
|
|
631
|
+
if (mimeType.includes("webp"))
|
|
632
|
+
return "webp";
|
|
633
|
+
return "png";
|
|
634
|
+
};
|
|
635
|
+
var processTextDelta = function* (parsed) {
|
|
636
|
+
if (typeof parsed.delta === "string") {
|
|
637
|
+
yield { content: parsed.delta, type: "text" };
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
var processPartialImage = function* (parsed) {
|
|
641
|
+
const itemId = typeof parsed.item_id === "string" ? parsed.item_id : undefined;
|
|
642
|
+
const b64 = typeof parsed.partial_image_b64 === "string" ? parsed.partial_image_b64 : undefined;
|
|
643
|
+
if (b64) {
|
|
644
|
+
yield {
|
|
645
|
+
data: b64,
|
|
646
|
+
format: "png",
|
|
647
|
+
imageId: itemId,
|
|
648
|
+
isPartial: true,
|
|
649
|
+
type: "image"
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
var processFunctionCallArgumentsDelta = (parsed, pendingCalls) => {
|
|
654
|
+
const itemId = typeof parsed.item_id === "string" ? parsed.item_id : "";
|
|
655
|
+
const callId = typeof parsed.call_id === "string" ? parsed.call_id : "";
|
|
656
|
+
const delta = typeof parsed.arguments_delta === "string" ? parsed.arguments_delta : "";
|
|
657
|
+
const existing = pendingCalls.get(itemId);
|
|
658
|
+
if (existing) {
|
|
659
|
+
existing.arguments += delta;
|
|
660
|
+
} else {
|
|
661
|
+
pendingCalls.set(itemId, {
|
|
662
|
+
arguments: delta,
|
|
663
|
+
callId,
|
|
664
|
+
name: ""
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
var processFunctionCallArgumentsDone = function* (parsed, pendingCalls) {
|
|
669
|
+
const itemId = typeof parsed.item_id === "string" ? parsed.item_id : "";
|
|
670
|
+
const callId = typeof parsed.call_id === "string" ? parsed.call_id : "";
|
|
671
|
+
const fullArgs = typeof parsed.arguments === "string" ? parsed.arguments : "";
|
|
672
|
+
const pending = pendingCalls.get(itemId);
|
|
673
|
+
const name = pending?.name ?? "";
|
|
674
|
+
const args = fullArgs || pending?.arguments || "";
|
|
675
|
+
pendingCalls.delete(itemId);
|
|
676
|
+
yield {
|
|
677
|
+
id: callId,
|
|
678
|
+
input: parseToolInput2(args),
|
|
679
|
+
name,
|
|
680
|
+
type: "tool_use"
|
|
681
|
+
};
|
|
682
|
+
};
|
|
683
|
+
var processOutputItemAdded = (parsed, pendingCalls) => {
|
|
684
|
+
if (!isRecord2(parsed.item)) {
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
const { item } = parsed;
|
|
688
|
+
const itemId = typeof item.id === "string" ? item.id : "";
|
|
689
|
+
const itemType = typeof item.type === "string" ? item.type : "";
|
|
690
|
+
if (itemType === "function_call") {
|
|
691
|
+
const callId = typeof item.call_id === "string" ? item.call_id : "";
|
|
692
|
+
const name = typeof item.name === "string" ? item.name : "";
|
|
693
|
+
pendingCalls.set(itemId, {
|
|
694
|
+
arguments: "",
|
|
695
|
+
callId,
|
|
696
|
+
name
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
var extractImageFromOutput = function* (output) {
|
|
701
|
+
for (const item of output) {
|
|
702
|
+
if (item.type !== "image_generation_call") {
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
if (item.status !== "completed") {
|
|
706
|
+
continue;
|
|
707
|
+
}
|
|
708
|
+
const data = typeof item.result === "string" ? item.result : "";
|
|
709
|
+
if (!data) {
|
|
710
|
+
continue;
|
|
711
|
+
}
|
|
712
|
+
const format = extractMimeFormat(item.output_format);
|
|
713
|
+
const revisedPrompt = typeof item.revised_prompt === "string" ? item.revised_prompt : undefined;
|
|
714
|
+
const imageId = typeof item.id === "string" ? item.id : undefined;
|
|
715
|
+
yield {
|
|
716
|
+
data,
|
|
717
|
+
format,
|
|
718
|
+
imageId,
|
|
719
|
+
isPartial: false,
|
|
720
|
+
revisedPrompt,
|
|
721
|
+
type: "image"
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
var processCompleted = function* (parsed) {
|
|
726
|
+
if (!isRecord2(parsed.response)) {
|
|
727
|
+
yield { type: "done", usage: undefined };
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
const { response } = parsed;
|
|
731
|
+
const usage = extractUsage2(response);
|
|
732
|
+
if (isRecordArray2(response.output)) {
|
|
733
|
+
yield* extractImageFromOutput(response.output);
|
|
734
|
+
}
|
|
735
|
+
yield { type: "done", usage };
|
|
736
|
+
};
|
|
737
|
+
var processSSEEvent = function* (eventType, parsed, pendingCalls) {
|
|
738
|
+
switch (eventType) {
|
|
739
|
+
case "response.output_text.delta":
|
|
740
|
+
yield* processTextDelta(parsed);
|
|
741
|
+
break;
|
|
742
|
+
case "response.image_generation_call.partial_image":
|
|
743
|
+
yield* processPartialImage(parsed);
|
|
744
|
+
break;
|
|
745
|
+
case "response.output_item.added":
|
|
746
|
+
processOutputItemAdded(parsed, pendingCalls);
|
|
747
|
+
break;
|
|
748
|
+
case "response.function_call_arguments.delta":
|
|
749
|
+
processFunctionCallArgumentsDelta(parsed, pendingCalls);
|
|
750
|
+
break;
|
|
751
|
+
case "response.function_call_arguments.done":
|
|
752
|
+
yield* processFunctionCallArgumentsDone(parsed, pendingCalls);
|
|
753
|
+
break;
|
|
754
|
+
case "response.completed":
|
|
755
|
+
yield* processCompleted(parsed);
|
|
756
|
+
break;
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
var processSSELines2 = function* (lines, state) {
|
|
760
|
+
for (const line of lines) {
|
|
761
|
+
const trimmed = line.trim();
|
|
762
|
+
if (!trimmed) {
|
|
763
|
+
if (state.currentEvent && state.buffer) {
|
|
764
|
+
const parsed = parseJSON(state.buffer);
|
|
765
|
+
if (parsed) {
|
|
766
|
+
yield* processSSEEvent(state.currentEvent, parsed, state.pendingCalls);
|
|
767
|
+
}
|
|
768
|
+
state.currentEvent = "";
|
|
769
|
+
state.buffer = "";
|
|
770
|
+
}
|
|
771
|
+
continue;
|
|
772
|
+
}
|
|
773
|
+
if (trimmed.startsWith("event: ")) {
|
|
774
|
+
state.currentEvent = trimmed.slice(EVENT_PREFIX_LENGTH);
|
|
775
|
+
} else if (trimmed.startsWith("data: ")) {
|
|
776
|
+
state.buffer = trimmed.slice(DATA_PREFIX_LENGTH);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
var drainReader2 = async function* (reader, decoder, state, signal) {
|
|
781
|
+
let textBuffer = "";
|
|
782
|
+
for (let result = await reader.read();!result.done && !signal?.aborted; result = await reader.read()) {
|
|
783
|
+
textBuffer += decoder.decode(result.value, { stream: true });
|
|
784
|
+
const lines = textBuffer.split(`
|
|
785
|
+
`);
|
|
786
|
+
textBuffer = lines.pop() ?? "";
|
|
787
|
+
yield* processSSELines2(lines, state);
|
|
788
|
+
}
|
|
789
|
+
if (textBuffer.trim()) {
|
|
790
|
+
yield* processSSELines2([textBuffer, ""], state);
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
var parseSSEStream2 = async function* (body, signal) {
|
|
794
|
+
const reader = body.getReader();
|
|
795
|
+
const decoder = new TextDecoder;
|
|
796
|
+
const state = {
|
|
797
|
+
buffer: "",
|
|
798
|
+
currentEvent: "",
|
|
799
|
+
pendingCalls: new Map,
|
|
800
|
+
usage: undefined
|
|
801
|
+
};
|
|
802
|
+
try {
|
|
803
|
+
yield* drainReader2(reader, decoder, state, signal);
|
|
804
|
+
} finally {
|
|
805
|
+
reader.releaseLock();
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
var fetchResponsesStream = async function* (baseUrl, apiKey, body, signal) {
|
|
809
|
+
const response = await fetch(`${baseUrl}/v1/responses`, {
|
|
810
|
+
body: JSON.stringify(body),
|
|
811
|
+
headers: {
|
|
812
|
+
Authorization: `Bearer ${apiKey}`,
|
|
813
|
+
"Content-Type": "application/json"
|
|
814
|
+
},
|
|
815
|
+
method: "POST",
|
|
816
|
+
signal
|
|
817
|
+
});
|
|
818
|
+
if (!response.ok) {
|
|
819
|
+
const errorText = await response.text();
|
|
820
|
+
throw new Error(`OpenAI Responses API error ${response.status}: ${errorText}`);
|
|
821
|
+
}
|
|
822
|
+
if (!response.body) {
|
|
823
|
+
throw new Error("OpenAI Responses API returned no response body");
|
|
824
|
+
}
|
|
825
|
+
yield* parseSSEStream2(response.body, signal);
|
|
826
|
+
};
|
|
827
|
+
var openaiResponses = (config) => {
|
|
828
|
+
const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL2;
|
|
829
|
+
return {
|
|
830
|
+
stream: (params) => {
|
|
831
|
+
const body = buildRequestBody2(params, config.imageGeneration);
|
|
832
|
+
return fetchResponsesStream(baseUrl, config.apiKey, body, params.signal);
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
};
|
|
836
|
+
|
|
837
|
+
// src/ai/providers/gemini.ts
|
|
838
|
+
var DEFAULT_BASE_URL3 = "https://generativelanguage.googleapis.com";
|
|
839
|
+
var SSE_DATA_PREFIX_LENGTH2 = 6;
|
|
840
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null;
|
|
841
|
+
var isRecordArray3 = (value) => Array.isArray(value) && value.length > 0 && isRecord3(value[0]);
|
|
842
|
+
var mapRole = (role) => {
|
|
843
|
+
if (role === "assistant" || role === "system")
|
|
844
|
+
return "model";
|
|
845
|
+
return "user";
|
|
846
|
+
};
|
|
847
|
+
var mapContentBlock = (block) => {
|
|
848
|
+
switch (block.type) {
|
|
849
|
+
case "text":
|
|
850
|
+
return { text: block.content };
|
|
851
|
+
case "image":
|
|
852
|
+
return {
|
|
853
|
+
inlineData: {
|
|
854
|
+
data: block.source.data,
|
|
855
|
+
mimeType: block.source.media_type
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
case "document":
|
|
859
|
+
return {
|
|
860
|
+
inlineData: {
|
|
861
|
+
data: block.source.data,
|
|
862
|
+
mimeType: block.source.media_type
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
case "tool_use":
|
|
866
|
+
return {
|
|
867
|
+
functionCall: {
|
|
868
|
+
args: typeof block.input === "string" ? JSON.parse(block.input) : block.input,
|
|
869
|
+
name: block.name
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
case "tool_result":
|
|
873
|
+
return {
|
|
874
|
+
functionResponse: {
|
|
875
|
+
name: block.tool_use_id,
|
|
876
|
+
response: { result: block.content }
|
|
877
|
+
}
|
|
878
|
+
};
|
|
879
|
+
default:
|
|
880
|
+
return null;
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
var convertMessageContent = (content) => {
|
|
884
|
+
if (typeof content === "string") {
|
|
885
|
+
return [{ text: content }];
|
|
886
|
+
}
|
|
887
|
+
const parts = [];
|
|
888
|
+
for (const block of content) {
|
|
889
|
+
const mapped = mapContentBlock(block);
|
|
890
|
+
if (mapped) {
|
|
891
|
+
parts.push(mapped);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
return parts;
|
|
895
|
+
};
|
|
896
|
+
var hasFunctionResponse = (content) => content.some((block) => block.type === "tool_result");
|
|
897
|
+
var convertMessages = (messages) => {
|
|
898
|
+
const contents = [];
|
|
899
|
+
for (const msg of messages) {
|
|
900
|
+
if (typeof msg.content !== "string" && hasFunctionResponse(msg.content)) {
|
|
901
|
+
const parts = convertMessageContent(msg.content);
|
|
902
|
+
contents.push({ parts, role: "user" });
|
|
903
|
+
continue;
|
|
904
|
+
}
|
|
905
|
+
contents.push({
|
|
906
|
+
parts: convertMessageContent(msg.content),
|
|
907
|
+
role: mapRole(msg.role)
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
return contents;
|
|
911
|
+
};
|
|
912
|
+
var mapToolDefinitions2 = (tools) => tools.map((tool) => ({
|
|
913
|
+
description: tool.description,
|
|
914
|
+
name: tool.name,
|
|
915
|
+
parameters: tool.input_schema
|
|
916
|
+
}));
|
|
917
|
+
var buildRequestBody3 = (params) => {
|
|
918
|
+
const body = {
|
|
919
|
+
contents: convertMessages(params.messages),
|
|
920
|
+
generationConfig: {
|
|
921
|
+
responseModalities: ["TEXT", "IMAGE"]
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
if (params.systemPrompt) {
|
|
925
|
+
body.systemInstruction = {
|
|
926
|
+
parts: [{ text: params.systemPrompt }]
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
if (params.tools && params.tools.length > 0) {
|
|
930
|
+
body.tools = [
|
|
931
|
+
{ functionDeclarations: mapToolDefinitions2(params.tools) }
|
|
932
|
+
];
|
|
933
|
+
}
|
|
934
|
+
return body;
|
|
935
|
+
};
|
|
936
|
+
var extractMimeFormat2 = (mimeType) => {
|
|
937
|
+
if (typeof mimeType !== "string") {
|
|
938
|
+
return "png";
|
|
939
|
+
}
|
|
940
|
+
if (mimeType.includes("jpeg") || mimeType.includes("jpg"))
|
|
941
|
+
return "jpeg";
|
|
942
|
+
if (mimeType.includes("webp"))
|
|
943
|
+
return "webp";
|
|
944
|
+
return "png";
|
|
945
|
+
};
|
|
946
|
+
var processTextPart = function* (part) {
|
|
947
|
+
if (typeof part.text === "string" && part.text) {
|
|
948
|
+
yield { content: part.text, type: "text" };
|
|
949
|
+
}
|
|
950
|
+
};
|
|
951
|
+
var processInlineDataPart = function* (inlineData) {
|
|
952
|
+
const data = typeof inlineData.data === "string" ? inlineData.data : "";
|
|
953
|
+
const mimeType = inlineData.mimeType;
|
|
954
|
+
if (!data) {
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
yield {
|
|
958
|
+
data,
|
|
959
|
+
format: extractMimeFormat2(mimeType),
|
|
960
|
+
isPartial: false,
|
|
961
|
+
type: "image"
|
|
962
|
+
};
|
|
963
|
+
};
|
|
964
|
+
var processFunctionCallPart = function* (functionCall) {
|
|
965
|
+
const name = typeof functionCall.name === "string" ? functionCall.name : "";
|
|
966
|
+
const args = functionCall.args ?? {};
|
|
967
|
+
yield {
|
|
968
|
+
id: `gemini-${name}-${Date.now()}`,
|
|
969
|
+
input: args,
|
|
970
|
+
name,
|
|
971
|
+
type: "tool_use"
|
|
972
|
+
};
|
|
973
|
+
};
|
|
974
|
+
var processPart = function* (part) {
|
|
975
|
+
if ("text" in part) {
|
|
976
|
+
yield* processTextPart(part);
|
|
977
|
+
}
|
|
978
|
+
if (isRecord3(part.inlineData)) {
|
|
979
|
+
yield* processInlineDataPart(part.inlineData);
|
|
980
|
+
}
|
|
981
|
+
if (isRecord3(part.functionCall)) {
|
|
982
|
+
yield* processFunctionCallPart(part.functionCall);
|
|
983
|
+
}
|
|
984
|
+
};
|
|
985
|
+
var extractUsage3 = (parsed) => {
|
|
986
|
+
if (!isRecord3(parsed.usageMetadata)) {
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
const { usageMetadata } = parsed;
|
|
990
|
+
return {
|
|
991
|
+
inputTokens: typeof usageMetadata.promptTokenCount === "number" ? usageMetadata.promptTokenCount : 0,
|
|
992
|
+
outputTokens: typeof usageMetadata.candidatesTokenCount === "number" ? usageMetadata.candidatesTokenCount : 0
|
|
993
|
+
};
|
|
994
|
+
};
|
|
995
|
+
var processChunk = function* (parsed, state) {
|
|
996
|
+
const usage = extractUsage3(parsed);
|
|
997
|
+
if (usage) {
|
|
998
|
+
state.usage = usage;
|
|
999
|
+
}
|
|
1000
|
+
if (!isRecordArray3(parsed.candidates)) {
|
|
1001
|
+
return;
|
|
1002
|
+
}
|
|
1003
|
+
const candidate = parsed.candidates[0];
|
|
1004
|
+
if (!candidate || !isRecord3(candidate.content)) {
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
const { content } = candidate;
|
|
1008
|
+
if (!isRecordArray3(content.parts)) {
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
for (const part of content.parts) {
|
|
1012
|
+
yield* processPart(part);
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
var processSSELine2 = function* (line, state) {
|
|
1016
|
+
const trimmed = line.trim();
|
|
1017
|
+
if (!trimmed || !trimmed.startsWith("data: ")) {
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
const data = trimmed.slice(SSE_DATA_PREFIX_LENGTH2);
|
|
1021
|
+
let parsed;
|
|
1022
|
+
try {
|
|
1023
|
+
parsed = JSON.parse(data);
|
|
1024
|
+
} catch {
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
yield* processChunk(parsed, state);
|
|
1028
|
+
};
|
|
1029
|
+
var drainReader3 = async function* (reader, decoder, state, signal) {
|
|
1030
|
+
let textBuffer = "";
|
|
1031
|
+
for (let result = await reader.read();!result.done && !signal?.aborted; result = await reader.read()) {
|
|
1032
|
+
textBuffer += decoder.decode(result.value, { stream: true });
|
|
1033
|
+
const lines = textBuffer.split(`
|
|
1034
|
+
`);
|
|
1035
|
+
textBuffer = lines.pop() ?? "";
|
|
1036
|
+
for (const line of lines) {
|
|
1037
|
+
yield* processSSELine2(line, state);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
if (textBuffer.trim()) {
|
|
1041
|
+
yield* processSSELine2(textBuffer, state);
|
|
1042
|
+
}
|
|
1043
|
+
yield { type: "done", usage: state.usage };
|
|
1044
|
+
};
|
|
1045
|
+
var parseSSEStream3 = async function* (body, signal) {
|
|
1046
|
+
const reader = body.getReader();
|
|
1047
|
+
const decoder = new TextDecoder;
|
|
1048
|
+
const state = {
|
|
1049
|
+
buffer: "",
|
|
1050
|
+
usage: undefined
|
|
1051
|
+
};
|
|
1052
|
+
try {
|
|
1053
|
+
yield* drainReader3(reader, decoder, state, signal);
|
|
1054
|
+
} finally {
|
|
1055
|
+
reader.releaseLock();
|
|
1056
|
+
}
|
|
1057
|
+
};
|
|
1058
|
+
var fetchGeminiStream = async function* (baseUrl, apiKey, model, body, signal) {
|
|
1059
|
+
const url = `${baseUrl}/v1beta/models/${model}:streamGenerateContent?alt=sse&key=${apiKey}`;
|
|
1060
|
+
const response = await fetch(url, {
|
|
1061
|
+
body: JSON.stringify(body),
|
|
1062
|
+
headers: {
|
|
1063
|
+
"Content-Type": "application/json"
|
|
1064
|
+
},
|
|
1065
|
+
method: "POST",
|
|
1066
|
+
signal
|
|
1067
|
+
});
|
|
1068
|
+
if (!response.ok) {
|
|
1069
|
+
const errorText = await response.text();
|
|
1070
|
+
throw new Error(`Gemini API error ${response.status}: ${errorText}`);
|
|
1071
|
+
}
|
|
1072
|
+
if (!response.body) {
|
|
1073
|
+
throw new Error("Gemini API returned no response body");
|
|
1074
|
+
}
|
|
1075
|
+
yield* parseSSEStream3(response.body, signal);
|
|
1076
|
+
};
|
|
1077
|
+
var gemini = (config) => {
|
|
1078
|
+
const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL3;
|
|
1079
|
+
return {
|
|
1080
|
+
stream: (params) => {
|
|
1081
|
+
const body = buildRequestBody3(params);
|
|
1082
|
+
return fetchGeminiStream(baseUrl, config.apiKey, params.model, body, params.signal);
|
|
1083
|
+
}
|
|
1084
|
+
};
|
|
1085
|
+
};
|
|
1086
|
+
|
|
476
1087
|
// src/plugins/aiChat.ts
|
|
477
1088
|
import { Elysia } from "elysia";
|
|
478
1089
|
|
|
@@ -643,6 +1254,16 @@ var extractTextContent = (chunk, onChunk) => {
|
|
|
643
1254
|
}
|
|
644
1255
|
return chunk.content;
|
|
645
1256
|
};
|
|
1257
|
+
var sendImageMessage = async (socket, chunk, messageId, conversationId) => sendMessage(socket, {
|
|
1258
|
+
conversationId,
|
|
1259
|
+
data: chunk.data,
|
|
1260
|
+
format: chunk.format,
|
|
1261
|
+
imageId: chunk.imageId,
|
|
1262
|
+
isPartial: chunk.isPartial,
|
|
1263
|
+
messageId,
|
|
1264
|
+
revisedPrompt: chunk.revisedPrompt,
|
|
1265
|
+
type: "image"
|
|
1266
|
+
});
|
|
646
1267
|
var sendToolRunning = async (socket, toolName, toolInput, messageId, conversationId) => sendMessage(socket, {
|
|
647
1268
|
conversationId,
|
|
648
1269
|
input: toolInput,
|
|
@@ -707,6 +1328,16 @@ var processToolChunk = (chunk, state, options, socket, messageId, conversationId
|
|
|
707
1328
|
case "text":
|
|
708
1329
|
handleToolChunkText(chunk, state, options, socket, messageId, conversationId);
|
|
709
1330
|
break;
|
|
1331
|
+
case "image":
|
|
1332
|
+
sendImageMessage(socket, chunk, messageId, conversationId);
|
|
1333
|
+
options.onImage?.({
|
|
1334
|
+
data: chunk.data,
|
|
1335
|
+
format: chunk.format,
|
|
1336
|
+
imageId: chunk.imageId,
|
|
1337
|
+
isPartial: chunk.isPartial,
|
|
1338
|
+
revisedPrompt: chunk.revisedPrompt
|
|
1339
|
+
});
|
|
1340
|
+
break;
|
|
710
1341
|
case "tool_use":
|
|
711
1342
|
handleToolChunkToolUse(chunk, state);
|
|
712
1343
|
hitAnotherTool = true;
|
|
@@ -857,6 +1488,16 @@ var consumeStreamChunk = async (chunk, options, socket, messages, messageId, con
|
|
|
857
1488
|
return "";
|
|
858
1489
|
case "text":
|
|
859
1490
|
return processStreamTextChunk(chunk, options, socket, messageId, conversationId);
|
|
1491
|
+
case "image":
|
|
1492
|
+
await sendImageMessage(socket, chunk, messageId, conversationId);
|
|
1493
|
+
options.onImage?.({
|
|
1494
|
+
data: chunk.data,
|
|
1495
|
+
format: chunk.format,
|
|
1496
|
+
imageId: chunk.imageId,
|
|
1497
|
+
isPartial: chunk.isPartial,
|
|
1498
|
+
revisedPrompt: chunk.revisedPrompt
|
|
1499
|
+
});
|
|
1500
|
+
return "";
|
|
860
1501
|
case "tool_use":
|
|
861
1502
|
await processStreamToolUseChunk(chunk, socket, options, messages, messageId, conversationId, signal, fullResponse, startTime);
|
|
862
1503
|
return { earlyReturn: true, fullResponse, usage: undefined };
|
|
@@ -966,14 +1607,27 @@ var aiChat = (config) => {
|
|
|
966
1607
|
const resolvedTools = typeof config.tools === "function" ? config.tools(providerName, model) : config.tools;
|
|
967
1608
|
const userMessage = attachments && attachments.length > 0 ? {
|
|
968
1609
|
content: [
|
|
969
|
-
...attachments.map((att) =>
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1610
|
+
...attachments.map((att) => {
|
|
1611
|
+
if (att.media_type === "application/pdf") {
|
|
1612
|
+
return {
|
|
1613
|
+
name: att.name,
|
|
1614
|
+
source: {
|
|
1615
|
+
data: att.data,
|
|
1616
|
+
media_type: att.media_type,
|
|
1617
|
+
type: "base64"
|
|
1618
|
+
},
|
|
1619
|
+
type: "document"
|
|
1620
|
+
};
|
|
1621
|
+
}
|
|
1622
|
+
return {
|
|
1623
|
+
source: {
|
|
1624
|
+
data: att.data,
|
|
1625
|
+
media_type: att.media_type,
|
|
1626
|
+
type: "base64"
|
|
1627
|
+
},
|
|
1628
|
+
type: "image"
|
|
1629
|
+
};
|
|
1630
|
+
}),
|
|
977
1631
|
{ content, type: "text" }
|
|
978
1632
|
],
|
|
979
1633
|
role: "user"
|
|
@@ -1038,17 +1692,19 @@ export {
|
|
|
1038
1692
|
streamAI,
|
|
1039
1693
|
serializeAIMessage,
|
|
1040
1694
|
parseAIMessage,
|
|
1695
|
+
openaiResponses,
|
|
1041
1696
|
openaiCompatible,
|
|
1042
1697
|
moonshot,
|
|
1043
1698
|
mistralai,
|
|
1044
1699
|
meta,
|
|
1045
1700
|
google,
|
|
1046
1701
|
generateId,
|
|
1702
|
+
gemini,
|
|
1047
1703
|
deepseek,
|
|
1048
1704
|
createConversationManager,
|
|
1049
1705
|
alibaba,
|
|
1050
1706
|
aiChat
|
|
1051
1707
|
};
|
|
1052
1708
|
|
|
1053
|
-
//# debugId=
|
|
1709
|
+
//# debugId=214AE01443FBB99E64756E2164756E21
|
|
1054
1710
|
//# sourceMappingURL=index.js.map
|