@absolutejs/absolute 0.19.0-beta.248 → 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.
Files changed (38) hide show
  1. package/.absolutejs/eslint-cache +1 -1
  2. package/.absolutejs/prettier.cache.json +17 -13
  3. package/.absolutejs/vue-tsc.tsbuildinfo +1 -1
  4. package/.claude/settings.local.json +2 -1
  5. package/dist/ai/index.js +636 -1
  6. package/dist/ai/index.js.map +10 -8
  7. package/dist/ai/providers/anthropic.js.map +2 -2
  8. package/dist/ai/providers/gemini.js +331 -0
  9. package/dist/ai/providers/gemini.js.map +10 -0
  10. package/dist/ai/providers/ollama.js.map +2 -2
  11. package/dist/ai/providers/openai.js.map +2 -2
  12. package/dist/ai/providers/openaiCompatible.js.map +3 -3
  13. package/dist/ai/providers/openaiResponses.js +432 -0
  14. package/dist/ai/providers/openaiResponses.js.map +10 -0
  15. package/dist/ai-client/angular/ai/index.js +61 -1
  16. package/dist/ai-client/react/ai/index.js +61 -1
  17. package/dist/ai-client/vue/ai/index.js +61 -1
  18. package/dist/angular/ai/index.js +62 -2
  19. package/dist/angular/ai/index.js.map +5 -5
  20. package/dist/build.js +3 -1
  21. package/dist/build.js.map +3 -3
  22. package/dist/index.js +3 -1
  23. package/dist/index.js.map +3 -3
  24. package/dist/react/ai/index.js +62 -2
  25. package/dist/react/ai/index.js.map +6 -6
  26. package/dist/src/ai/client/actions.d.ts +43 -0
  27. package/dist/src/ai/index.d.ts +2 -0
  28. package/dist/src/ai/providers/gemini.d.ts +7 -0
  29. package/dist/src/ai/providers/openaiResponses.d.ts +10 -0
  30. package/dist/svelte/ai/index.js +62 -2
  31. package/dist/svelte/ai/index.js.map +5 -5
  32. package/dist/types/ai.d.ts +38 -2
  33. package/dist/vue/ai/index.js +62 -2
  34. package/dist/vue/ai/index.js.map +5 -5
  35. package/package.json +9 -1
  36. package/scripts/build.ts +2 -0
  37. package/types/ai.ts +73 -6
  38. package/types/typeGuards.ts +11 -0
@@ -263,7 +263,8 @@
263
263
  "WebFetch(domain:platform.openai.com)",
264
264
  "Bash(bunx absolute:*)",
265
265
  "mcp__playwright__browser_file_upload",
266
- "WebFetch(domain:docs.anthropic.com)"
266
+ "WebFetch(domain:docs.anthropic.com)",
267
+ "WebFetch(domain:ai.google.dev)"
267
268
  ]
268
269
  }
269
270
  }
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":
@@ -481,6 +483,607 @@ var moonshot = (config) => openaiCompatible({
481
483
  baseUrl: "https://api.moonshot.ai"
482
484
  });
483
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
+
484
1087
  // src/plugins/aiChat.ts
485
1088
  import { Elysia } from "elysia";
486
1089
 
@@ -651,6 +1254,16 @@ var extractTextContent = (chunk, onChunk) => {
651
1254
  }
652
1255
  return chunk.content;
653
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
+ });
654
1267
  var sendToolRunning = async (socket, toolName, toolInput, messageId, conversationId) => sendMessage(socket, {
655
1268
  conversationId,
656
1269
  input: toolInput,
@@ -715,6 +1328,16 @@ var processToolChunk = (chunk, state, options, socket, messageId, conversationId
715
1328
  case "text":
716
1329
  handleToolChunkText(chunk, state, options, socket, messageId, conversationId);
717
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;
718
1341
  case "tool_use":
719
1342
  handleToolChunkToolUse(chunk, state);
720
1343
  hitAnotherTool = true;
@@ -865,6 +1488,16 @@ var consumeStreamChunk = async (chunk, options, socket, messages, messageId, con
865
1488
  return "";
866
1489
  case "text":
867
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 "";
868
1501
  case "tool_use":
869
1502
  await processStreamToolUseChunk(chunk, socket, options, messages, messageId, conversationId, signal, fullResponse, startTime);
870
1503
  return { earlyReturn: true, fullResponse, usage: undefined };
@@ -1059,17 +1692,19 @@ export {
1059
1692
  streamAI,
1060
1693
  serializeAIMessage,
1061
1694
  parseAIMessage,
1695
+ openaiResponses,
1062
1696
  openaiCompatible,
1063
1697
  moonshot,
1064
1698
  mistralai,
1065
1699
  meta,
1066
1700
  google,
1067
1701
  generateId,
1702
+ gemini,
1068
1703
  deepseek,
1069
1704
  createConversationManager,
1070
1705
  alibaba,
1071
1706
  aiChat
1072
1707
  };
1073
1708
 
1074
- //# debugId=C554CBF32C5F355864756E2164756E21
1709
+ //# debugId=214AE01443FBB99E64756E2164756E21
1075
1710
  //# sourceMappingURL=index.js.map