@posthog/ai 8.14.4 → 8.15.0
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/README.md +14 -0
- package/dist/adk/index.cjs +22 -7
- package/dist/adk/index.cjs.map +1 -1
- package/dist/adk/index.mjs +22 -7
- package/dist/adk/index.mjs.map +1 -1
- package/dist/anthropic/index.cjs +12 -5
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +12 -5
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/claude-agent-sdk/index.cjs +12 -5
- package/dist/claude-agent-sdk/index.cjs.map +1 -1
- package/dist/claude-agent-sdk/index.mjs +12 -5
- package/dist/claude-agent-sdk/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +403 -19
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.d.ts +28 -0
- package/dist/gemini/index.mjs +403 -19
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +12 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +12 -5
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +12 -5
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.mjs +12 -5
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/langchain/middleware/index.cjs +12 -5
- package/dist/langchain/middleware/index.cjs.map +1 -1
- package/dist/langchain/middleware/index.mjs +12 -5
- package/dist/langchain/middleware/index.mjs.map +1 -1
- package/dist/openai/index.cjs +12 -5
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +12 -5
- package/dist/openai/index.mjs.map +1 -1
- package/dist/openai-agents/index.cjs +12 -5
- package/dist/openai-agents/index.cjs.map +1 -1
- package/dist/openai-agents/index.mjs +12 -5
- package/dist/openai-agents/index.mjs.map +1 -1
- package/dist/otel/index.cjs +11 -4
- package/dist/otel/index.cjs.map +1 -1
- package/dist/otel/index.mjs +11 -4
- package/dist/otel/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +12 -5
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +12 -5
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/gemini/index.cjs
CHANGED
|
@@ -96,6 +96,12 @@ const FILE_FAMILY_TYPES = /* @__PURE__ */ new Set([
|
|
|
96
96
|
"media",
|
|
97
97
|
"file-data"
|
|
98
98
|
]);
|
|
99
|
+
const TYPED_BINARY_DATA_TYPES = /* @__PURE__ */ new Set([
|
|
100
|
+
"image",
|
|
101
|
+
"audio",
|
|
102
|
+
"video",
|
|
103
|
+
"document"
|
|
104
|
+
]);
|
|
99
105
|
const KNOWN_AUDIO_FORMATS = /* @__PURE__ */ new Set([
|
|
100
106
|
"wav",
|
|
101
107
|
"mp3",
|
|
@@ -147,7 +153,8 @@ var MediaTypeContext = class MediaTypeContext {
|
|
|
147
153
|
if (key.includes("image")) return "image";
|
|
148
154
|
if (key.includes("file") || key.includes("document")) return "application/octet-stream";
|
|
149
155
|
}
|
|
150
|
-
|
|
156
|
+
hasDefiniteBinaryData() {
|
|
157
|
+
if (this.parent && this.key === "data" && typeof this.parent.type === "string" && TYPED_BINARY_DATA_TYPES.has(this.parent.type)) return true;
|
|
151
158
|
if (!this.explicitMediaType && (!this.parent || !this.key || !STRONG_CONTEXT_KEYS.has(this.key))) return false;
|
|
152
159
|
const mediaType = this.inferFromSiblingMime();
|
|
153
160
|
return mediaType !== void 0 && !mediaType.toLowerCase().startsWith("text/");
|
|
@@ -201,9 +208,9 @@ var BinaryContentRedactor = class {
|
|
|
201
208
|
return out;
|
|
202
209
|
}
|
|
203
210
|
redactString(value, ctx) {
|
|
204
|
-
const
|
|
205
|
-
const recognitionValue =
|
|
206
|
-
const minLength =
|
|
211
|
+
const hasDefiniteBinaryData = ctx.hasDefiniteBinaryData();
|
|
212
|
+
const recognitionValue = hasDefiniteBinaryData ? value.replace(/[\r\n]/g, "") : value;
|
|
213
|
+
const minLength = hasDefiniteBinaryData ? Math.min(recognitionValue.length, STRONG_CONTEXT_MIN_LENGTH) : ctx.signalsBinary() ? STRONG_CONTEXT_MIN_LENGTH : WEAK_CONTEXT_MIN_LENGTH;
|
|
207
214
|
const recognition = this.recognizer.recognize(recognitionValue, minLength);
|
|
208
215
|
switch (recognition.kind) {
|
|
209
216
|
case "data-url": return this.placeholderFor(recognition.mediaType);
|
|
@@ -335,7 +342,11 @@ const formatResponseGemini = (response, client) => {
|
|
|
335
342
|
if (response.candidates && Array.isArray(response.candidates)) {
|
|
336
343
|
for (const candidate of response.candidates) if (candidate.content && candidate.content.parts) {
|
|
337
344
|
const content = [];
|
|
338
|
-
for (const part of candidate.content.parts) if (part.text) content.push({
|
|
345
|
+
for (const part of candidate.content.parts) if (part.thought === true && part.text) content.push({
|
|
346
|
+
type: "reasoning",
|
|
347
|
+
text: part.text
|
|
348
|
+
});
|
|
349
|
+
else if (part.text) content.push({
|
|
339
350
|
type: "text",
|
|
340
351
|
text: part.text
|
|
341
352
|
});
|
|
@@ -452,7 +463,7 @@ function addDefaults(params) {
|
|
|
452
463
|
}
|
|
453
464
|
//#endregion
|
|
454
465
|
//#region package.json
|
|
455
|
-
var version = "8.
|
|
466
|
+
var version = "8.15.0";
|
|
456
467
|
//#endregion
|
|
457
468
|
//#region src/serializeError.ts
|
|
458
469
|
const DEFAULT_MAX_DEPTH = 3;
|
|
@@ -718,7 +729,385 @@ function mapGeminiUsage(metadata, additionalUsage = {}) {
|
|
|
718
729
|
};
|
|
719
730
|
}
|
|
720
731
|
//#endregion
|
|
732
|
+
//#region src/gemini/interactions.ts
|
|
733
|
+
function record(value) {
|
|
734
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
735
|
+
}
|
|
736
|
+
function string(value) {
|
|
737
|
+
return typeof value === "string" ? value : void 0;
|
|
738
|
+
}
|
|
739
|
+
function number(value) {
|
|
740
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
741
|
+
}
|
|
742
|
+
function isStream(value) {
|
|
743
|
+
return value !== null && typeof value === "object" && Symbol.asyncIterator in value;
|
|
744
|
+
}
|
|
745
|
+
function usageFromInteraction(value, model) {
|
|
746
|
+
const usage = record(value);
|
|
747
|
+
if (!usage) return {};
|
|
748
|
+
const cached = number(usage.total_cached_tokens);
|
|
749
|
+
const searches = Array.isArray(usage.grounding_tool_count) ? usage.grounding_tool_count.reduce((total, entry) => {
|
|
750
|
+
const grounding = record(entry);
|
|
751
|
+
return total + (grounding?.type === "google_search" ? number(grounding.count) ?? 0 : 0);
|
|
752
|
+
}, 0) : void 0;
|
|
753
|
+
const modelMajor = /^(?:models\/)?gemini-(\d+)/.exec(model ?? "")?.[1];
|
|
754
|
+
const webSearchCount = modelMajor === void 0 ? void 0 : Number(modelMajor) >= 3 ? searches : searches ? 1 : 0;
|
|
755
|
+
return {
|
|
756
|
+
inputTokens: number(usage.total_input_tokens),
|
|
757
|
+
outputTokens: number(usage.total_output_tokens),
|
|
758
|
+
reasoningTokens: number(usage.total_thought_tokens),
|
|
759
|
+
cacheReadInputTokens: cached,
|
|
760
|
+
...cached !== void 0 ? { cacheReportingExclusive: false } : {},
|
|
761
|
+
webSearchCount,
|
|
762
|
+
rawUsage: usage
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
function functionArguments(value) {
|
|
766
|
+
if (typeof value !== "string") return record(value) ?? {};
|
|
767
|
+
try {
|
|
768
|
+
return record(JSON.parse(value)) ?? value;
|
|
769
|
+
} catch {
|
|
770
|
+
return value;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
function outputFromSteps(steps, fallbackText) {
|
|
774
|
+
const content = [];
|
|
775
|
+
if (Array.isArray(steps)) for (const rawStep of steps) {
|
|
776
|
+
const step = record(rawStep);
|
|
777
|
+
if (step?.type === "model_output" && Array.isArray(step.content)) content.push(...step.content);
|
|
778
|
+
else if (step?.type === "function_call" && string(step.name)) content.push({
|
|
779
|
+
type: "function",
|
|
780
|
+
id: string(step.id),
|
|
781
|
+
function: {
|
|
782
|
+
name: step.name,
|
|
783
|
+
arguments: functionArguments(step.arguments)
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
if (content.length === 0 && fallbackText) content.push({
|
|
788
|
+
type: "text",
|
|
789
|
+
text: fallbackText
|
|
790
|
+
});
|
|
791
|
+
return content.length ? [{
|
|
792
|
+
role: "assistant",
|
|
793
|
+
content
|
|
794
|
+
}] : [];
|
|
795
|
+
}
|
|
796
|
+
function inputFromRequest(input, systemInstruction) {
|
|
797
|
+
const messages = [];
|
|
798
|
+
if (typeof systemInstruction === "string") messages.push({
|
|
799
|
+
role: "system",
|
|
800
|
+
content: systemInstruction
|
|
801
|
+
});
|
|
802
|
+
let userContent = [];
|
|
803
|
+
const flushUserContent = () => {
|
|
804
|
+
if (userContent.length) messages.push({
|
|
805
|
+
role: "user",
|
|
806
|
+
content: userContent
|
|
807
|
+
});
|
|
808
|
+
userContent = [];
|
|
809
|
+
};
|
|
810
|
+
for (const part of Array.isArray(input) ? input : [input]) {
|
|
811
|
+
const step = record(part);
|
|
812
|
+
if (step?.type === "text" || step?.type === "image" || step?.type === "audio" || step?.type === "video" || step?.type === "document") {
|
|
813
|
+
userContent.push(part);
|
|
814
|
+
continue;
|
|
815
|
+
}
|
|
816
|
+
flushUserContent();
|
|
817
|
+
if (step?.type === "function_result") messages.push({
|
|
818
|
+
role: "tool",
|
|
819
|
+
content: [{
|
|
820
|
+
type: "tool_result",
|
|
821
|
+
tool_use_id: step.call_id,
|
|
822
|
+
content: step.result
|
|
823
|
+
}]
|
|
824
|
+
});
|
|
825
|
+
else if (step?.type === "user_input") messages.push({
|
|
826
|
+
role: "user",
|
|
827
|
+
content: step.content ?? [part]
|
|
828
|
+
});
|
|
829
|
+
else if (step?.type === "model_output") messages.push({
|
|
830
|
+
role: "assistant",
|
|
831
|
+
content: step.content ?? [part]
|
|
832
|
+
});
|
|
833
|
+
else if (step?.type === "function_call") {
|
|
834
|
+
const output = outputFromSteps([part]);
|
|
835
|
+
messages.push(...output.length ? output : [{
|
|
836
|
+
role: "assistant",
|
|
837
|
+
content: [part]
|
|
838
|
+
}]);
|
|
839
|
+
} else messages.push({
|
|
840
|
+
role: "user",
|
|
841
|
+
content: part
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
flushUserContent();
|
|
845
|
+
return messages;
|
|
846
|
+
}
|
|
847
|
+
function safeTools(tools) {
|
|
848
|
+
if (!Array.isArray(tools)) return void 0;
|
|
849
|
+
return tools.map((tool) => ({
|
|
850
|
+
type: string(record(tool)?.type),
|
|
851
|
+
name: string(record(tool)?.name)
|
|
852
|
+
}));
|
|
853
|
+
}
|
|
854
|
+
function isFailure(status) {
|
|
855
|
+
return status === "failed" || status === "cancelled" || status === "incomplete" || status === "budget_exceeded";
|
|
856
|
+
}
|
|
857
|
+
var WrappedInteractions = class {
|
|
858
|
+
constructor(client, phClient) {
|
|
859
|
+
this.client = client;
|
|
860
|
+
this.phClient = phClient;
|
|
861
|
+
}
|
|
862
|
+
async create(params, options) {
|
|
863
|
+
const { providerParams, posthogParams } = extractPosthogParams(params);
|
|
864
|
+
const request = providerParams;
|
|
865
|
+
const requestData = record(request) ?? {};
|
|
866
|
+
if (requestData.background === true || typeof requestData.model !== "string" || requestData.agent !== void 0) throw new Error("Gemini Interactions tracing supports foreground model calls only");
|
|
867
|
+
const startTime = Date.now();
|
|
868
|
+
const capture = async (interaction, error, output, firstTokenTime) => {
|
|
869
|
+
try {
|
|
870
|
+
const privateCapture = withPrivacyMode(this.phClient, posthogParams.privacyMode, false) === null;
|
|
871
|
+
const model = string(interaction?.model) ?? string(requestData.model);
|
|
872
|
+
const generationConfig = record(requestData.generation_config);
|
|
873
|
+
const modelParameters = privateCapture ? {} : {
|
|
874
|
+
...number(generationConfig?.max_output_tokens) !== void 0 ? { max_tokens: generationConfig?.max_output_tokens } : {},
|
|
875
|
+
...string(generationConfig?.thinking_level) !== void 0 ? { thinking_level: generationConfig?.thinking_level } : {}
|
|
876
|
+
};
|
|
877
|
+
await captureAiGeneration(this.phClient, {
|
|
878
|
+
...posthogParams,
|
|
879
|
+
model,
|
|
880
|
+
provider: "gemini",
|
|
881
|
+
input: privateCapture ? null : inputFromRequest(sanitizeGemini(requestData.input, this.phClient), sanitizeGemini(requestData.system_instruction, this.phClient)),
|
|
882
|
+
output: privateCapture ? null : sanitizeGemini(output ?? outputFromSteps(interaction?.steps, string(interaction?.output_text)), this.phClient),
|
|
883
|
+
latency: (Date.now() - startTime) / 1e3,
|
|
884
|
+
timeToFirstToken: firstTokenTime === void 0 ? void 0 : (firstTokenTime - startTime) / 1e3,
|
|
885
|
+
baseURL: "https://generativelanguage.googleapis.com",
|
|
886
|
+
modelParameters,
|
|
887
|
+
completionId: string(interaction?.id),
|
|
888
|
+
stopReason: string(interaction?.status),
|
|
889
|
+
servedServiceTier: string(interaction?.service_tier),
|
|
890
|
+
usage: usageFromInteraction(interaction?.usage, model),
|
|
891
|
+
tools: privateCapture ? void 0 : safeTools(requestData.tools),
|
|
892
|
+
error: privateCapture && error ? /* @__PURE__ */ new Error("Gemini interaction failed") : error
|
|
893
|
+
});
|
|
894
|
+
} catch {}
|
|
895
|
+
};
|
|
896
|
+
try {
|
|
897
|
+
if (!this.client.interactions?.create) throw new Error("Gemini Interactions requires @google/genai 2.18.0 or newer");
|
|
898
|
+
const result = await (options === void 0 ? this.client.interactions.create(request) : this.client.interactions.create(request, options));
|
|
899
|
+
if (requestData.stream === true) {
|
|
900
|
+
if (!isStream(result)) throw new Error("Gemini Interactions did not return a stream");
|
|
901
|
+
return this.wrapStream(result, capture);
|
|
902
|
+
}
|
|
903
|
+
if (isStream(result)) throw new Error("Gemini Interactions returned an unexpected stream");
|
|
904
|
+
const interaction = record(result);
|
|
905
|
+
let unsupportedSchema = false;
|
|
906
|
+
try {
|
|
907
|
+
unsupportedSchema = Array.isArray(interaction?.outputs) && !Array.isArray(interaction?.steps);
|
|
908
|
+
} catch {
|
|
909
|
+
return result;
|
|
910
|
+
}
|
|
911
|
+
if (unsupportedSchema) throw new Error("Gemini Interactions GA schema requires @google/genai 2.18.0 or newer");
|
|
912
|
+
try {
|
|
913
|
+
const status = interaction?.status;
|
|
914
|
+
if (status !== "queued" && status !== "in_progress") await capture(interaction, isFailure(status) ? /* @__PURE__ */ new Error(`Gemini interaction ${status}`) : void 0);
|
|
915
|
+
} catch {}
|
|
916
|
+
return result;
|
|
917
|
+
} catch (error) {
|
|
918
|
+
await capture(void 0, error);
|
|
919
|
+
throw error;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
wrapStream(stream, capture) {
|
|
923
|
+
const reader = "getReader" in stream && typeof stream.getReader === "function" ? stream.getReader() : void 0;
|
|
924
|
+
const iterator = reader ? void 0 : stream[Symbol.asyncIterator]();
|
|
925
|
+
let readerReleased = false;
|
|
926
|
+
let errorIterator;
|
|
927
|
+
let readError;
|
|
928
|
+
const next = async () => {
|
|
929
|
+
if (!reader) return iterator.next();
|
|
930
|
+
try {
|
|
931
|
+
return await reader.read();
|
|
932
|
+
} catch (providerError) {
|
|
933
|
+
if (closed) throw providerError;
|
|
934
|
+
readError = providerError;
|
|
935
|
+
release();
|
|
936
|
+
try {
|
|
937
|
+
errorIterator = stream[Symbol.asyncIterator]();
|
|
938
|
+
} catch {
|
|
939
|
+
throw providerError;
|
|
940
|
+
}
|
|
941
|
+
try {
|
|
942
|
+
await errorIterator.next();
|
|
943
|
+
} finally {
|
|
944
|
+
try {
|
|
945
|
+
await errorIterator.return?.();
|
|
946
|
+
} catch {}
|
|
947
|
+
}
|
|
948
|
+
throw providerError;
|
|
949
|
+
}
|
|
950
|
+
};
|
|
951
|
+
const cancelSource = async (reason) => {
|
|
952
|
+
if (reader && !readerReleased) await reader.cancel(reason);
|
|
953
|
+
else if (reader) {
|
|
954
|
+
try {
|
|
955
|
+
await errorIterator?.return?.();
|
|
956
|
+
} catch {}
|
|
957
|
+
throw readError;
|
|
958
|
+
} else await iterator?.return?.();
|
|
959
|
+
};
|
|
960
|
+
const release = () => {
|
|
961
|
+
if (readerReleased) return;
|
|
962
|
+
try {
|
|
963
|
+
reader?.releaseLock();
|
|
964
|
+
readerReleased = true;
|
|
965
|
+
} catch {}
|
|
966
|
+
};
|
|
967
|
+
let interaction;
|
|
968
|
+
let latestUsage;
|
|
969
|
+
let finalUsage;
|
|
970
|
+
let error;
|
|
971
|
+
let firstTokenTime;
|
|
972
|
+
const steps = /* @__PURE__ */ new Map();
|
|
973
|
+
let completed = false;
|
|
974
|
+
let closed = false;
|
|
975
|
+
let cancelled = false;
|
|
976
|
+
let captured = false;
|
|
977
|
+
const observe = (event) => {
|
|
978
|
+
let schemaError;
|
|
979
|
+
try {
|
|
980
|
+
const item = record(event);
|
|
981
|
+
const eventType = item?.event_type;
|
|
982
|
+
if (eventType === "interaction.start" || eventType === "interaction.complete" || eventType === "interaction.delta" || typeof eventType === "string" && eventType.startsWith("content.")) schemaError = /* @__PURE__ */ new Error("Gemini Interactions GA schema requires @google/genai 2.18.0 or newer");
|
|
983
|
+
else {
|
|
984
|
+
const usage = record(record(item?.metadata)?.total_usage) ?? (eventType === "step.stop" ? record(item?.usage) : void 0);
|
|
985
|
+
if (usage) latestUsage = { ...usage };
|
|
986
|
+
if (eventType === "interaction.created") {
|
|
987
|
+
interaction = { ...record(item?.interaction) };
|
|
988
|
+
const initialUsage = record(interaction.usage);
|
|
989
|
+
if (initialUsage) latestUsage = { ...initialUsage };
|
|
990
|
+
} else if (eventType === "step.start") {
|
|
991
|
+
const index = number(item?.index);
|
|
992
|
+
const step = record(item?.step);
|
|
993
|
+
if (index !== void 0) steps.set(index, {
|
|
994
|
+
...step,
|
|
995
|
+
content: Array.isArray(step?.content) ? step.content.map((item) => ({ ...record(item) })) : []
|
|
996
|
+
});
|
|
997
|
+
} else if (eventType === "step.delta") {
|
|
998
|
+
const index = number(item?.index);
|
|
999
|
+
const delta = record(item?.delta);
|
|
1000
|
+
const step = index === void 0 ? void 0 : steps.get(index);
|
|
1001
|
+
if (step && delta?.type === "text" && typeof delta.text === "string") {
|
|
1002
|
+
const last = step.content?.at(-1);
|
|
1003
|
+
const text = record(last);
|
|
1004
|
+
if (text?.type === "text") text.text = `${text.text ?? ""}${delta.text}`;
|
|
1005
|
+
else step.content?.push({
|
|
1006
|
+
type: "text",
|
|
1007
|
+
text: delta.text
|
|
1008
|
+
});
|
|
1009
|
+
firstTokenTime ??= Date.now();
|
|
1010
|
+
} else if (step && (delta?.type === "image" || delta?.type === "audio" || delta?.type === "video" || delta?.type === "document")) {
|
|
1011
|
+
step.content?.push({ ...delta });
|
|
1012
|
+
firstTokenTime ??= Date.now();
|
|
1013
|
+
} else if (step && delta?.type === "arguments_delta" && typeof delta.arguments === "string") {
|
|
1014
|
+
step.argumentChunks = `${step.argumentChunks ?? ""}${delta.arguments}`;
|
|
1015
|
+
firstTokenTime ??= Date.now();
|
|
1016
|
+
}
|
|
1017
|
+
} else if (eventType === "interaction.completed") {
|
|
1018
|
+
const result = record(item?.interaction);
|
|
1019
|
+
interaction = {
|
|
1020
|
+
...interaction,
|
|
1021
|
+
...result
|
|
1022
|
+
};
|
|
1023
|
+
completed = interaction.status !== "queued" && interaction.status !== "in_progress";
|
|
1024
|
+
const reportedUsage = record(result?.usage);
|
|
1025
|
+
if (reportedUsage) {
|
|
1026
|
+
latestUsage = { ...reportedUsage };
|
|
1027
|
+
if (completed) finalUsage = latestUsage;
|
|
1028
|
+
}
|
|
1029
|
+
if (isFailure(interaction.status)) error = /* @__PURE__ */ new Error(`Gemini interaction ${interaction.status}`);
|
|
1030
|
+
if (!completed) error = /* @__PURE__ */ new Error("Gemini interaction stream ended without a terminal result");
|
|
1031
|
+
} else if (eventType === "error") error = /* @__PURE__ */ new Error("Gemini interaction stream failed");
|
|
1032
|
+
}
|
|
1033
|
+
} catch {}
|
|
1034
|
+
if (schemaError) throw schemaError;
|
|
1035
|
+
};
|
|
1036
|
+
const finish = async (status, providerError) => {
|
|
1037
|
+
if (captured) return;
|
|
1038
|
+
captured = true;
|
|
1039
|
+
try {
|
|
1040
|
+
const streamedSteps = [...steps.entries()].sort(([left], [right]) => left - right).map(([, step]) => ({
|
|
1041
|
+
...step,
|
|
1042
|
+
arguments: step.argumentChunks === void 0 ? step.arguments : functionArguments(step.argumentChunks)
|
|
1043
|
+
}));
|
|
1044
|
+
const output = outputFromSteps(Array.isArray(interaction?.steps) && interaction.steps.length > 0 ? interaction.steps : streamedSteps);
|
|
1045
|
+
await capture({
|
|
1046
|
+
...interaction,
|
|
1047
|
+
usage: finalUsage ?? latestUsage,
|
|
1048
|
+
...completed ? {} : { status }
|
|
1049
|
+
}, providerError ?? error ?? (!completed && status === "incomplete" ? /* @__PURE__ */ new Error("Gemini interaction stream ended without completion") : void 0), output, firstTokenTime);
|
|
1050
|
+
} catch {}
|
|
1051
|
+
};
|
|
1052
|
+
return new ReadableStream({
|
|
1053
|
+
async pull(controller) {
|
|
1054
|
+
try {
|
|
1055
|
+
const result = await next();
|
|
1056
|
+
if (closed) return;
|
|
1057
|
+
if (result.done) {
|
|
1058
|
+
closed = true;
|
|
1059
|
+
await finish("incomplete");
|
|
1060
|
+
release();
|
|
1061
|
+
if (!cancelled) controller.close();
|
|
1062
|
+
} else {
|
|
1063
|
+
observe(result.value);
|
|
1064
|
+
controller.enqueue(result.value);
|
|
1065
|
+
}
|
|
1066
|
+
} catch (providerError) {
|
|
1067
|
+
if (closed) return;
|
|
1068
|
+
closed = true;
|
|
1069
|
+
try {
|
|
1070
|
+
await cancelSource(providerError);
|
|
1071
|
+
} catch {}
|
|
1072
|
+
await finish("failed", providerError);
|
|
1073
|
+
release();
|
|
1074
|
+
if (!cancelled) controller.error(providerError);
|
|
1075
|
+
}
|
|
1076
|
+
},
|
|
1077
|
+
async cancel(reason) {
|
|
1078
|
+
cancelled = true;
|
|
1079
|
+
if (closed) return;
|
|
1080
|
+
closed = true;
|
|
1081
|
+
let cancellationError;
|
|
1082
|
+
try {
|
|
1083
|
+
await cancelSource(reason);
|
|
1084
|
+
} catch (providerError) {
|
|
1085
|
+
cancellationError = providerError;
|
|
1086
|
+
throw providerError;
|
|
1087
|
+
} finally {
|
|
1088
|
+
await finish("cancelled", cancellationError);
|
|
1089
|
+
release();
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
};
|
|
1095
|
+
//#endregion
|
|
721
1096
|
//#region src/gemini/index.ts
|
|
1097
|
+
/** Append streamed text to the last block of the same type, or start a new one. */
|
|
1098
|
+
function appendStreamedText(content, type, text) {
|
|
1099
|
+
for (let i = content.length - 1; i >= 0; i--) {
|
|
1100
|
+
const item = content[i];
|
|
1101
|
+
if (item.type === type) {
|
|
1102
|
+
item.text += text;
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
content.push({
|
|
1107
|
+
type,
|
|
1108
|
+
text
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
722
1111
|
const TOOL_RESULT_MAX_BYTES = 5e3;
|
|
723
1112
|
function geminiFunctionResponseContent(response) {
|
|
724
1113
|
return response.parts !== void 0 ? {
|
|
@@ -732,6 +1121,7 @@ var PostHogGoogleGenAI = class {
|
|
|
732
1121
|
this.phClient = posthog;
|
|
733
1122
|
this.client = new _google_genai.GoogleGenAI(geminiConfig);
|
|
734
1123
|
this.models = new WrappedModels(this.client, this.phClient);
|
|
1124
|
+
this.interactions = new WrappedInteractions(this.client, this.phClient);
|
|
735
1125
|
}
|
|
736
1126
|
};
|
|
737
1127
|
var WrappedModels = class {
|
|
@@ -797,18 +1187,8 @@ var WrappedModels = class {
|
|
|
797
1187
|
if (firstTokenTime === void 0 && chunk.text) firstTokenTime = Date.now();
|
|
798
1188
|
const chunkWebSearchCount = calculateGoogleWebSearchCount(chunk);
|
|
799
1189
|
if (chunkWebSearchCount > 0 && chunkWebSearchCount > (usage.webSearchCount ?? 0)) usage.webSearchCount = chunkWebSearchCount;
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
for (let i = accumulatedContent.length - 1; i >= 0; i--) if (accumulatedContent[i].type === "text") {
|
|
803
|
-
lastTextItem = accumulatedContent[i];
|
|
804
|
-
break;
|
|
805
|
-
}
|
|
806
|
-
if (lastTextItem && lastTextItem.type === "text") lastTextItem.text += chunk.text;
|
|
807
|
-
else accumulatedContent.push({
|
|
808
|
-
type: "text",
|
|
809
|
-
text: chunk.text
|
|
810
|
-
});
|
|
811
|
-
}
|
|
1190
|
+
for (const part of chunk.candidates?.[0]?.content?.parts ?? []) if (part.thought === true && part.text) appendStreamedText(accumulatedContent, "reasoning", part.text);
|
|
1191
|
+
if (chunk.text) appendStreamedText(accumulatedContent, "text", chunk.text);
|
|
812
1192
|
if (chunk.candidates?.[0]?.finishReason) stopReason = chunk.candidates[0].finishReason;
|
|
813
1193
|
if (chunk.candidates && Array.isArray(chunk.candidates)) {
|
|
814
1194
|
for (const candidate of chunk.candidates) if (candidate.content && candidate.content.parts) {
|
|
@@ -917,7 +1297,11 @@ var WrappedModels = class {
|
|
|
917
1297
|
}
|
|
918
1298
|
formatPartsAsContentBlocks(parts) {
|
|
919
1299
|
const blocks = [];
|
|
920
|
-
for (const part of parts) if (part && typeof part === "object" && "text" in part && part.text) blocks.push({
|
|
1300
|
+
for (const part of parts) if (part && typeof part === "object" && "thought" in part && part.thought === true && "text" in part && part.text) blocks.push({
|
|
1301
|
+
type: "reasoning",
|
|
1302
|
+
text: String(part.text)
|
|
1303
|
+
});
|
|
1304
|
+
else if (part && typeof part === "object" && "text" in part && part.text) blocks.push({
|
|
921
1305
|
type: "text",
|
|
922
1306
|
text: String(part.text)
|
|
923
1307
|
});
|