@effect-uai/google 0.2.0 → 0.3.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/dist/Gemini.d.mts +105 -0
- package/dist/Gemini.d.mts.map +1 -0
- package/dist/Gemini.mjs +170 -0
- package/dist/Gemini.mjs.map +1 -0
- package/dist/GeminiEmbedding.d.mts +64 -0
- package/dist/GeminiEmbedding.d.mts.map +1 -0
- package/dist/GeminiEmbedding.mjs +167 -0
- package/dist/GeminiEmbedding.mjs.map +1 -0
- package/dist/codec.d.mts +107 -0
- package/dist/codec.d.mts.map +1 -0
- package/dist/codec.mjs +151 -0
- package/dist/codec.mjs.map +1 -0
- package/dist/index.d.mts +5 -214
- package/dist/index.mjs +5 -289
- package/dist/models.d.mts +27 -0
- package/dist/models.d.mts.map +1 -0
- package/dist/models.mjs +1 -0
- package/package.json +20 -12
- package/src/Gemini.ts +3 -3
- package/src/GeminiEmbedding.ts +351 -0
- package/src/codec.ts +42 -35
- package/src/index.ts +3 -2
- package/src/models.ts +20 -0
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/codec.d.mts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Option, Schema } from "effect";
|
|
2
|
+
import { Turn } from "@effect-uai/core/Turn";
|
|
3
|
+
import { Item } from "@effect-uai/core/Items";
|
|
4
|
+
|
|
5
|
+
//#region src/codec.d.ts
|
|
6
|
+
declare namespace codec_d_exports {
|
|
7
|
+
export { Accumulator, ChunkPart, ChunkResult, GenerationConfig, RequestBody, ThinkingConfig, WireChunk, accumulatorToTurn, buildRequestBody, emptyAccumulator, ingestChunk };
|
|
8
|
+
}
|
|
9
|
+
declare const WireChunk: Schema.Struct<{
|
|
10
|
+
readonly candidates: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
11
|
+
readonly content: Schema.optional<Schema.Struct<{
|
|
12
|
+
readonly role: Schema.optional<Schema.String>;
|
|
13
|
+
readonly parts: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
|
|
14
|
+
readonly text: Schema.String;
|
|
15
|
+
/**
|
|
16
|
+
* Gemini's flag for chain-of-thought parts. When `true`, the part is
|
|
17
|
+
* reasoning trace, not the model's user-facing answer. Maps onto
|
|
18
|
+
* `reasoning_delta { kind: "trace" }` in the canonical view.
|
|
19
|
+
*/
|
|
20
|
+
readonly thought: Schema.optional<Schema.Boolean>;
|
|
21
|
+
}>]>>>;
|
|
22
|
+
}>>;
|
|
23
|
+
readonly finishReason: Schema.optional<Schema.String>;
|
|
24
|
+
readonly index: Schema.optional<Schema.Number>;
|
|
25
|
+
}>>>;
|
|
26
|
+
readonly usageMetadata: Schema.optional<Schema.Struct<{
|
|
27
|
+
readonly promptTokenCount: Schema.optional<Schema.Number>;
|
|
28
|
+
readonly candidatesTokenCount: Schema.optional<Schema.Number>;
|
|
29
|
+
readonly totalTokenCount: Schema.optional<Schema.Number>;
|
|
30
|
+
readonly cachedContentTokenCount: Schema.optional<Schema.Number>;
|
|
31
|
+
readonly thoughtsTokenCount: Schema.optional<Schema.Number>;
|
|
32
|
+
}>>;
|
|
33
|
+
}>;
|
|
34
|
+
type WireChunk = typeof WireChunk.Type;
|
|
35
|
+
type RequestPart = {
|
|
36
|
+
readonly text: string;
|
|
37
|
+
} | {
|
|
38
|
+
readonly inlineData: {
|
|
39
|
+
readonly mimeType: string;
|
|
40
|
+
readonly data: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
type RequestContent = {
|
|
44
|
+
readonly role: "user" | "model";
|
|
45
|
+
readonly parts: ReadonlyArray<RequestPart>;
|
|
46
|
+
};
|
|
47
|
+
type RequestSystemInstruction = {
|
|
48
|
+
readonly parts: ReadonlyArray<{
|
|
49
|
+
readonly text: string;
|
|
50
|
+
}>;
|
|
51
|
+
};
|
|
52
|
+
type ThinkingConfig = {
|
|
53
|
+
readonly thinkingBudget: number;
|
|
54
|
+
};
|
|
55
|
+
type GenerationConfig = {
|
|
56
|
+
readonly temperature?: number;
|
|
57
|
+
readonly maxOutputTokens?: number;
|
|
58
|
+
readonly topP?: number;
|
|
59
|
+
readonly thinkingConfig?: ThinkingConfig; /** Set together with `responseJsonSchema` to constrain output to JSON. */
|
|
60
|
+
readonly responseMimeType?: string; /** JSON Schema constraint on the output. */
|
|
61
|
+
readonly responseJsonSchema?: Record<string, unknown>;
|
|
62
|
+
};
|
|
63
|
+
type RequestBody = {
|
|
64
|
+
readonly contents: ReadonlyArray<RequestContent>;
|
|
65
|
+
readonly systemInstruction?: RequestSystemInstruction;
|
|
66
|
+
readonly generationConfig?: GenerationConfig;
|
|
67
|
+
};
|
|
68
|
+
declare const buildRequestBody: (history: ReadonlyArray<Item>, generationConfig: Option.Option<GenerationConfig>) => RequestBody;
|
|
69
|
+
type Accumulator = {
|
|
70
|
+
readonly text: string;
|
|
71
|
+
readonly reasoning: string;
|
|
72
|
+
readonly finishReason: Option.Option<string>;
|
|
73
|
+
readonly usage: {
|
|
74
|
+
readonly input_tokens?: number;
|
|
75
|
+
readonly output_tokens?: number;
|
|
76
|
+
readonly total_tokens?: number;
|
|
77
|
+
readonly input_tokens_details?: {
|
|
78
|
+
readonly cached_tokens?: number;
|
|
79
|
+
};
|
|
80
|
+
readonly output_tokens_details?: {
|
|
81
|
+
readonly reasoning_tokens?: number;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
declare const emptyAccumulator: Accumulator;
|
|
86
|
+
/**
|
|
87
|
+
* One part's worth of streamable text: either the model's answer
|
|
88
|
+
* (`kind: "text"`) or chain-of-thought (`kind: "reasoning"`). Emitted
|
|
89
|
+
* in wire order so consumers can interleave faithfully.
|
|
90
|
+
*/
|
|
91
|
+
type ChunkPart = {
|
|
92
|
+
readonly kind: "text";
|
|
93
|
+
readonly text: string;
|
|
94
|
+
} | {
|
|
95
|
+
readonly kind: "reasoning";
|
|
96
|
+
readonly text: string;
|
|
97
|
+
};
|
|
98
|
+
type ChunkResult = {
|
|
99
|
+
readonly accumulator: Accumulator;
|
|
100
|
+
readonly parts: ReadonlyArray<ChunkPart>;
|
|
101
|
+
readonly finished: boolean;
|
|
102
|
+
};
|
|
103
|
+
declare const ingestChunk: (acc: Accumulator, chunk: WireChunk) => ChunkResult;
|
|
104
|
+
declare const accumulatorToTurn: (acc: Accumulator) => Turn;
|
|
105
|
+
//#endregion
|
|
106
|
+
export { Accumulator, ChunkPart, ChunkResult, GenerationConfig, RequestBody, ThinkingConfig, WireChunk, accumulatorToTurn, buildRequestBody, emptyAccumulator, ingestChunk, codec_d_exports as t };
|
|
107
|
+
//# sourceMappingURL=codec.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.d.mts","names":[],"sources":["../src/codec.ts"],"mappings":";;;;;;;;cAwCa,SAAA,EAAS,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;KAIV,SAAA,UAAmB,SAAA,CAAU,IAAA;AAAA,KAMpC,WAAA;EAAA,SACU,IAAA;AAAA;EAAA,SACA,UAAA;IAAA,SAAuB,QAAA;IAAA,SAA2B,IAAA;EAAA;AAAA;AAAA,KAE5D,cAAA;EAAA,SACM,IAAA;EAAA,SACA,KAAA,EAAO,aAAA,CAAc,WAAA;AAAA;AAAA,KAG3B,wBAAA;EAAA,SACM,KAAA,EAAO,aAAA;IAAA,SAAyB,IAAA;EAAA;AAAA;AAAA,KAG/B,cAAA;EAAA,SACD,cAAA;AAAA;AAAA,KAGC,gBAAA;EAAA,SACD,WAAA;EAAA,SACA,eAAA;EAAA,SACA,IAAA;EAAA,SACA,cAAA,GAAiB,cAAA,EA/BN;EAAA,SAiCX,gBAAA,WAjCW;EAAA,SAmCX,kBAAA,GAAqB,MAAA;AAAA;AAAA,KAGpB,WAAA;EAAA,SACD,QAAA,EAAU,aAAA,CAAc,cAAA;EAAA,SACxB,iBAAA,GAAoB,wBAAA;EAAA,SACpB,gBAAA,GAAmB,gBAAA;AAAA;AAAA,cAqEjB,gBAAA,GACX,OAAA,EAAS,aAAA,CAAc,IAAA,GACvB,gBAAA,EAAkB,MAAA,CAAO,MAAA,CAAO,gBAAA,MAC/B,WAAA;AAAA,KA6BS,WAAA;EAAA,SACD,IAAA;EAAA,SACA,SAAA;EAAA,SACA,YAAA,EAAc,MAAA,CAAO,MAAA;EAAA,SACrB,KAAA;IAAA,SACE,YAAA;IAAA,SACA,aAAA;IAAA,SACA,YAAA;IAAA,SACA,oBAAA;MAAA,SAAkC,aAAA;IAAA;IAAA,SAClC,qBAAA;MAAA,SAAmC,gBAAA;IAAA;EAAA;AAAA;AAAA,cAInC,gBAAA,EAAkB,WAAA;;;;;;KAYnB,SAAA;EAAA,SACG,IAAA;EAAA,SAAuB,IAAA;AAAA;EAAA,SACvB,IAAA;EAAA,SAA4B,IAAA;AAAA;AAAA,KAE/B,WAAA;EAAA,SACD,WAAA,EAAa,WAAA;EAAA,SACb,KAAA,EAAO,aAAA,CAAc,SAAA;EAAA,SACrB,QAAA;AAAA;AAAA,cA2CE,WAAA,GAAe,GAAA,EAAK,WAAA,EAAa,KAAA,EAAO,SAAA,KAAY,WAAA;AAAA,cAepD,iBAAA,GAAqB,GAAA,EAAK,WAAA,KAAc,IAAA"}
|
package/dist/codec.mjs
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { t as __exportAll } from "./chunk-CfYAbeIz.mjs";
|
|
2
|
+
import { Array, Encoding, Match, Option, Result, Schema, pipe } from "effect";
|
|
3
|
+
//#region src/codec.ts
|
|
4
|
+
var codec_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
WireChunk: () => WireChunk,
|
|
6
|
+
accumulatorToTurn: () => accumulatorToTurn,
|
|
7
|
+
buildRequestBody: () => buildRequestBody,
|
|
8
|
+
emptyAccumulator: () => emptyAccumulator,
|
|
9
|
+
ingestChunk: () => ingestChunk
|
|
10
|
+
});
|
|
11
|
+
const TextPart = Schema.Struct({
|
|
12
|
+
text: Schema.String,
|
|
13
|
+
/**
|
|
14
|
+
* Gemini's flag for chain-of-thought parts. When `true`, the part is
|
|
15
|
+
* reasoning trace, not the model's user-facing answer. Maps onto
|
|
16
|
+
* `reasoning_delta { kind: "trace" }` in the canonical view.
|
|
17
|
+
*/
|
|
18
|
+
thought: Schema.optional(Schema.Boolean)
|
|
19
|
+
});
|
|
20
|
+
const Part = Schema.Union([TextPart]);
|
|
21
|
+
const Content = Schema.Struct({
|
|
22
|
+
role: Schema.optional(Schema.String),
|
|
23
|
+
parts: Schema.optional(Schema.Array(Part))
|
|
24
|
+
});
|
|
25
|
+
const Candidate = Schema.Struct({
|
|
26
|
+
content: Schema.optional(Content),
|
|
27
|
+
finishReason: Schema.optional(Schema.String),
|
|
28
|
+
index: Schema.optional(Schema.Number)
|
|
29
|
+
});
|
|
30
|
+
const UsageMetadata = Schema.Struct({
|
|
31
|
+
promptTokenCount: Schema.optional(Schema.Number),
|
|
32
|
+
candidatesTokenCount: Schema.optional(Schema.Number),
|
|
33
|
+
totalTokenCount: Schema.optional(Schema.Number),
|
|
34
|
+
cachedContentTokenCount: Schema.optional(Schema.Number),
|
|
35
|
+
thoughtsTokenCount: Schema.optional(Schema.Number)
|
|
36
|
+
});
|
|
37
|
+
const WireChunk = Schema.Struct({
|
|
38
|
+
candidates: Schema.optional(Schema.Array(Candidate)),
|
|
39
|
+
usageMetadata: Schema.optional(UsageMetadata)
|
|
40
|
+
});
|
|
41
|
+
const blockText = Match.type().pipe(Match.discriminatorsExhaustive("type")({
|
|
42
|
+
input_text: (b) => b.text,
|
|
43
|
+
input_image: () => "",
|
|
44
|
+
output_text: (b) => b.text,
|
|
45
|
+
refusal: (b) => b.text
|
|
46
|
+
}));
|
|
47
|
+
const messageText = (message) => message.content.map(blockText).join("");
|
|
48
|
+
/**
|
|
49
|
+
* Gemini's `inlineData` form expects a base64 payload. URL-form images
|
|
50
|
+
* would need to go through Gemini's Files API (upload then `fileData`
|
|
51
|
+
* with the returned URI); pre-uploading isn't free, so we skip those for
|
|
52
|
+
* now and document as a follow-up.
|
|
53
|
+
*/
|
|
54
|
+
const imageSourceToParts = Match.type().pipe(Match.tag("url", () => []), Match.tag("base64", (s) => [{ inlineData: {
|
|
55
|
+
mimeType: s.mimeType,
|
|
56
|
+
data: s.base64
|
|
57
|
+
} }]), Match.tag("bytes", (s) => [{ inlineData: {
|
|
58
|
+
mimeType: s.mimeType,
|
|
59
|
+
data: Encoding.encodeBase64(s.bytes)
|
|
60
|
+
} }]), Match.exhaustive);
|
|
61
|
+
const blockToParts = Match.type().pipe(Match.discriminatorsExhaustive("type")({
|
|
62
|
+
input_text: (b) => b.text.length === 0 ? [] : [{ text: b.text }],
|
|
63
|
+
input_image: (b) => imageSourceToParts(b.source),
|
|
64
|
+
output_text: (b) => b.text.length === 0 ? [] : [{ text: b.text }],
|
|
65
|
+
refusal: () => []
|
|
66
|
+
}));
|
|
67
|
+
const messageToContent = (message) => {
|
|
68
|
+
const parts = pipe(message.content, Array.flatMap(blockToParts));
|
|
69
|
+
if (parts.length === 0) return Result.failVoid;
|
|
70
|
+
return Match.value(message.role).pipe(Match.when("user", () => Result.succeed({
|
|
71
|
+
role: "user",
|
|
72
|
+
parts
|
|
73
|
+
})), Match.when("assistant", () => Result.succeed({
|
|
74
|
+
role: "model",
|
|
75
|
+
parts
|
|
76
|
+
})), Match.when("system", () => Result.failVoid), Match.exhaustive);
|
|
77
|
+
};
|
|
78
|
+
const systemMessageText = (message) => {
|
|
79
|
+
if (message.role !== "system") return Result.failVoid;
|
|
80
|
+
const text = messageText(message);
|
|
81
|
+
return text.length === 0 ? Result.failVoid : Result.succeed(text);
|
|
82
|
+
};
|
|
83
|
+
const messages = (history) => pipe(history, Array.filterMap((item) => item.type === "message" ? Result.succeed(item) : Result.failVoid));
|
|
84
|
+
const buildRequestBody = (history, generationConfig) => {
|
|
85
|
+
const msgs = messages(history);
|
|
86
|
+
const systemTexts = pipe(msgs, Array.filterMap(systemMessageText));
|
|
87
|
+
return {
|
|
88
|
+
contents: pipe(msgs, Array.filterMap(messageToContent)),
|
|
89
|
+
...systemTexts.length > 0 && { systemInstruction: { parts: [{ text: systemTexts.join("\n") }] } },
|
|
90
|
+
...Option.match(generationConfig, {
|
|
91
|
+
onNone: () => ({}),
|
|
92
|
+
onSome: (cfg) => ({ generationConfig: cfg })
|
|
93
|
+
})
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
const finishReasonToStop = (reason) => Option.match(reason, {
|
|
97
|
+
onNone: () => "stop",
|
|
98
|
+
onSome: (r) => r === "MAX_TOKENS" ? "max_tokens" : "stop"
|
|
99
|
+
});
|
|
100
|
+
const emptyAccumulator = {
|
|
101
|
+
text: "",
|
|
102
|
+
reasoning: "",
|
|
103
|
+
finishReason: Option.none(),
|
|
104
|
+
usage: {}
|
|
105
|
+
};
|
|
106
|
+
const chunkParts = (chunk) => pipe(chunk.candidates?.[0]?.content?.parts ?? [], Array.filterMap((p) => p.text.length === 0 ? Result.failVoid : Result.succeed({
|
|
107
|
+
kind: p.thought === true ? "reasoning" : "text",
|
|
108
|
+
text: p.text
|
|
109
|
+
})));
|
|
110
|
+
const sumByKind = (parts, kind) => pipe(parts, Array.filterMap((p) => p.kind === kind ? Result.succeed(p.text) : Result.failVoid)).join("");
|
|
111
|
+
const mergeUsage = (prev, next) => next === void 0 ? prev : {
|
|
112
|
+
...prev,
|
|
113
|
+
...next.promptTokenCount !== void 0 && { input_tokens: next.promptTokenCount },
|
|
114
|
+
...next.candidatesTokenCount !== void 0 && { output_tokens: next.candidatesTokenCount },
|
|
115
|
+
...next.totalTokenCount !== void 0 && { total_tokens: next.totalTokenCount },
|
|
116
|
+
...next.cachedContentTokenCount !== void 0 && { input_tokens_details: { cached_tokens: next.cachedContentTokenCount } },
|
|
117
|
+
...next.thoughtsTokenCount !== void 0 && { output_tokens_details: { reasoning_tokens: next.thoughtsTokenCount } }
|
|
118
|
+
};
|
|
119
|
+
const ingestChunk = (acc, chunk) => {
|
|
120
|
+
const parts = chunkParts(chunk);
|
|
121
|
+
const finishReason = Option.fromNullishOr(chunk.candidates?.[0]?.finishReason);
|
|
122
|
+
return {
|
|
123
|
+
parts,
|
|
124
|
+
finished: Option.isSome(finishReason),
|
|
125
|
+
accumulator: {
|
|
126
|
+
text: acc.text + sumByKind(parts, "text"),
|
|
127
|
+
reasoning: acc.reasoning + sumByKind(parts, "reasoning"),
|
|
128
|
+
finishReason: Option.orElse(finishReason, () => acc.finishReason),
|
|
129
|
+
usage: mergeUsage(acc.usage, chunk.usageMetadata)
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
const accumulatorToTurn = (acc) => ({
|
|
134
|
+
stop_reason: finishReasonToStop(acc.finishReason),
|
|
135
|
+
usage: { ...acc.usage },
|
|
136
|
+
items: [...acc.reasoning.length > 0 ? [{
|
|
137
|
+
type: "reasoning",
|
|
138
|
+
summary: acc.reasoning
|
|
139
|
+
}] : [], ...acc.text.length === 0 ? [] : [{
|
|
140
|
+
type: "message",
|
|
141
|
+
role: "assistant",
|
|
142
|
+
content: [{
|
|
143
|
+
type: "output_text",
|
|
144
|
+
text: acc.text
|
|
145
|
+
}]
|
|
146
|
+
}]]
|
|
147
|
+
});
|
|
148
|
+
//#endregion
|
|
149
|
+
export { WireChunk, accumulatorToTurn, buildRequestBody, emptyAccumulator, ingestChunk, codec_exports as t };
|
|
150
|
+
|
|
151
|
+
//# sourceMappingURL=codec.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.mjs","names":["Arr"],"sources":["../src/codec.ts"],"sourcesContent":["import { Array as Arr, Encoding, Match, Option, Result, Schema, pipe } from \"effect\"\nimport type { ContentBlock, InputImage, Item, Message } from \"@effect-uai/core/Items\"\nimport type { Turn } from \"@effect-uai/core/Turn\"\n\n// ---------------------------------------------------------------------------\n// Wire schemas - the subset of Gemini's streamGenerateContent payload we\n// consume. Reference: https://ai.google.dev/api/generate-content\n// ---------------------------------------------------------------------------\n\nconst TextPart = Schema.Struct({\n text: Schema.String,\n /**\n * Gemini's flag for chain-of-thought parts. When `true`, the part is\n * reasoning trace, not the model's user-facing answer. Maps onto\n * `reasoning_delta { kind: \"trace\" }` in the canonical view.\n */\n thought: Schema.optional(Schema.Boolean),\n})\n\nconst Part = Schema.Union([TextPart])\n\nconst Content = Schema.Struct({\n role: Schema.optional(Schema.String),\n parts: Schema.optional(Schema.Array(Part)),\n})\n\nconst Candidate = Schema.Struct({\n content: Schema.optional(Content),\n finishReason: Schema.optional(Schema.String),\n index: Schema.optional(Schema.Number),\n})\n\nconst UsageMetadata = Schema.Struct({\n promptTokenCount: Schema.optional(Schema.Number),\n candidatesTokenCount: Schema.optional(Schema.Number),\n totalTokenCount: Schema.optional(Schema.Number),\n cachedContentTokenCount: Schema.optional(Schema.Number),\n thoughtsTokenCount: Schema.optional(Schema.Number),\n})\n\nexport const WireChunk = Schema.Struct({\n candidates: Schema.optional(Schema.Array(Candidate)),\n usageMetadata: Schema.optional(UsageMetadata),\n})\nexport type WireChunk = typeof WireChunk.Type\n\n// ---------------------------------------------------------------------------\n// History → request body\n// ---------------------------------------------------------------------------\n\ntype RequestPart =\n | { readonly text: string }\n | { readonly inlineData: { readonly mimeType: string; readonly data: string } }\n\ntype RequestContent = {\n readonly role: \"user\" | \"model\"\n readonly parts: ReadonlyArray<RequestPart>\n}\n\ntype RequestSystemInstruction = {\n readonly parts: ReadonlyArray<{ readonly text: string }>\n}\n\nexport type ThinkingConfig = {\n readonly thinkingBudget: number\n}\n\nexport type GenerationConfig = {\n readonly temperature?: number\n readonly maxOutputTokens?: number\n readonly topP?: number\n readonly thinkingConfig?: ThinkingConfig\n /** Set together with `responseJsonSchema` to constrain output to JSON. */\n readonly responseMimeType?: string\n /** JSON Schema constraint on the output. */\n readonly responseJsonSchema?: Record<string, unknown>\n}\n\nexport type RequestBody = {\n readonly contents: ReadonlyArray<RequestContent>\n readonly systemInstruction?: RequestSystemInstruction\n readonly generationConfig?: GenerationConfig\n}\n\nconst blockText = Match.type<ContentBlock>().pipe(\n Match.discriminatorsExhaustive(\"type\")({\n input_text: (b) => b.text,\n input_image: () => \"\",\n output_text: (b) => b.text,\n refusal: (b) => b.text,\n }),\n)\n\nconst messageText = (message: Message): string => message.content.map(blockText).join(\"\")\n\n/**\n * Gemini's `inlineData` form expects a base64 payload. URL-form images\n * would need to go through Gemini's Files API (upload then `fileData`\n * with the returned URI); pre-uploading isn't free, so we skip those for\n * now and document as a follow-up.\n */\nconst imageSourceToParts = Match.type<InputImage[\"source\"]>().pipe(\n Match.tag(\"url\", (): ReadonlyArray<RequestPart> => []),\n Match.tag(\n \"base64\",\n (s): ReadonlyArray<RequestPart> => [{ inlineData: { mimeType: s.mimeType, data: s.base64 } }],\n ),\n Match.tag(\n \"bytes\",\n (s): ReadonlyArray<RequestPart> => [\n { inlineData: { mimeType: s.mimeType, data: Encoding.encodeBase64(s.bytes) } },\n ],\n ),\n Match.exhaustive,\n)\n\nconst blockToParts = Match.type<ContentBlock>().pipe(\n Match.discriminatorsExhaustive(\"type\")({\n input_text: (b): ReadonlyArray<RequestPart> => (b.text.length === 0 ? [] : [{ text: b.text }]),\n input_image: (b): ReadonlyArray<RequestPart> => imageSourceToParts(b.source),\n output_text: (b): ReadonlyArray<RequestPart> => (b.text.length === 0 ? [] : [{ text: b.text }]),\n // Refusals are assistant-side content; they don't round-trip into Gemini's\n // request body as parts. Skip.\n refusal: (): ReadonlyArray<RequestPart> => [],\n }),\n)\n\nconst messageToContent = (message: Message): Result.Result<RequestContent, void> => {\n const parts = pipe(message.content, Arr.flatMap(blockToParts))\n if (parts.length === 0) return Result.failVoid\n return Match.value(message.role).pipe(\n Match.when(\"user\", () => Result.succeed({ role: \"user\" as const, parts })),\n Match.when(\"assistant\", () => Result.succeed({ role: \"model\" as const, parts })),\n Match.when(\"system\", () => Result.failVoid),\n Match.exhaustive,\n )\n}\n\nconst systemMessageText = (message: Message): Result.Result<string, void> => {\n if (message.role !== \"system\") return Result.failVoid\n const text = messageText(message)\n return text.length === 0 ? Result.failVoid : Result.succeed(text)\n}\n\nconst messages = (history: ReadonlyArray<Item>): ReadonlyArray<Message> =>\n pipe(\n history,\n Arr.filterMap((item) => (item.type === \"message\" ? Result.succeed(item) : Result.failVoid)),\n )\n\nexport const buildRequestBody = (\n history: ReadonlyArray<Item>,\n generationConfig: Option.Option<GenerationConfig>,\n): RequestBody => {\n const msgs = messages(history)\n const systemTexts = pipe(msgs, Arr.filterMap(systemMessageText))\n const contents = pipe(msgs, Arr.filterMap(messageToContent))\n return {\n contents,\n ...(systemTexts.length > 0 && {\n systemInstruction: { parts: [{ text: systemTexts.join(\"\\n\") }] },\n }),\n ...Option.match(generationConfig, {\n onNone: () => ({}),\n onSome: (cfg) => ({ generationConfig: cfg }),\n }),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Stream-level state - accumulate chunk text + final usage/finish.\n//\n// `Accumulator` is immutable; `ingestChunk` returns a fresh one per chunk.\n// Drive it via `Stream.mapAccum` in the consumer.\n// ---------------------------------------------------------------------------\n\nconst finishReasonToStop = (reason: Option.Option<string>): Turn[\"stop_reason\"] =>\n Option.match(reason, {\n onNone: () => \"stop\" as const,\n onSome: (r) => (r === \"MAX_TOKENS\" ? (\"max_tokens\" as const) : (\"stop\" as const)),\n })\n\nexport type Accumulator = {\n readonly text: string\n readonly reasoning: string\n readonly finishReason: Option.Option<string>\n readonly usage: {\n readonly input_tokens?: number\n readonly output_tokens?: number\n readonly total_tokens?: number\n readonly input_tokens_details?: { readonly cached_tokens?: number }\n readonly output_tokens_details?: { readonly reasoning_tokens?: number }\n }\n}\n\nexport const emptyAccumulator: Accumulator = {\n text: \"\",\n reasoning: \"\",\n finishReason: Option.none(),\n usage: {},\n}\n\n/**\n * One part's worth of streamable text: either the model's answer\n * (`kind: \"text\"`) or chain-of-thought (`kind: \"reasoning\"`). Emitted\n * in wire order so consumers can interleave faithfully.\n */\nexport type ChunkPart =\n | { readonly kind: \"text\"; readonly text: string }\n | { readonly kind: \"reasoning\"; readonly text: string }\n\nexport type ChunkResult = {\n readonly accumulator: Accumulator\n readonly parts: ReadonlyArray<ChunkPart>\n readonly finished: boolean\n}\n\nconst chunkParts = (chunk: WireChunk): ReadonlyArray<ChunkPart> =>\n pipe(\n chunk.candidates?.[0]?.content?.parts ?? [],\n Arr.filterMap((p) =>\n p.text.length === 0\n ? Result.failVoid\n : Result.succeed({\n kind: p.thought === true ? (\"reasoning\" as const) : (\"text\" as const),\n text: p.text,\n }),\n ),\n )\n\nconst sumByKind = (parts: ReadonlyArray<ChunkPart>, kind: ChunkPart[\"kind\"]): string =>\n pipe(\n parts,\n Arr.filterMap((p) => (p.kind === kind ? Result.succeed(p.text) : Result.failVoid)),\n ).join(\"\")\n\nconst mergeUsage = (\n prev: Accumulator[\"usage\"],\n next: WireChunk[\"usageMetadata\"],\n): Accumulator[\"usage\"] =>\n next === undefined\n ? prev\n : {\n ...prev,\n ...(next.promptTokenCount !== undefined && { input_tokens: next.promptTokenCount }),\n ...(next.candidatesTokenCount !== undefined && {\n output_tokens: next.candidatesTokenCount,\n }),\n ...(next.totalTokenCount !== undefined && { total_tokens: next.totalTokenCount }),\n ...(next.cachedContentTokenCount !== undefined && {\n input_tokens_details: { cached_tokens: next.cachedContentTokenCount },\n }),\n ...(next.thoughtsTokenCount !== undefined && {\n output_tokens_details: { reasoning_tokens: next.thoughtsTokenCount },\n }),\n }\n\nexport const ingestChunk = (acc: Accumulator, chunk: WireChunk): ChunkResult => {\n const parts = chunkParts(chunk)\n const finishReason = Option.fromNullishOr(chunk.candidates?.[0]?.finishReason)\n return {\n parts,\n finished: Option.isSome(finishReason),\n accumulator: {\n text: acc.text + sumByKind(parts, \"text\"),\n reasoning: acc.reasoning + sumByKind(parts, \"reasoning\"),\n finishReason: Option.orElse(finishReason, () => acc.finishReason),\n usage: mergeUsage(acc.usage, chunk.usageMetadata),\n },\n }\n}\n\nexport const accumulatorToTurn = (acc: Accumulator): Turn => ({\n stop_reason: finishReasonToStop(acc.finishReason),\n usage: { ...acc.usage },\n items: [\n ...(acc.reasoning.length > 0 ? [{ type: \"reasoning\" as const, summary: acc.reasoning }] : []),\n ...(acc.text.length === 0\n ? []\n : [\n {\n type: \"message\" as const,\n role: \"assistant\" as const,\n content: [{ type: \"output_text\" as const, text: acc.text }],\n },\n ]),\n ],\n})\n"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,214 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import { Item } from "@effect-uai/core/Items";
|
|
7
|
-
|
|
8
|
-
//#region src/codec.d.ts
|
|
9
|
-
declare namespace codec_d_exports {
|
|
10
|
-
export { Accumulator, ChunkPart, ChunkResult, GenerationConfig, RequestBody, ThinkingConfig, WireChunk, accumulatorToTurn, buildRequestBody, emptyAccumulator, ingestChunk };
|
|
11
|
-
}
|
|
12
|
-
declare const WireChunk: Schema.Struct<{
|
|
13
|
-
readonly candidates: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
14
|
-
readonly content: Schema.optional<Schema.Struct<{
|
|
15
|
-
readonly role: Schema.optional<Schema.String>;
|
|
16
|
-
readonly parts: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
|
|
17
|
-
readonly text: Schema.String;
|
|
18
|
-
/**
|
|
19
|
-
* Gemini's flag for chain-of-thought parts. When `true`, the part is
|
|
20
|
-
* reasoning trace, not the model's user-facing answer. Maps onto
|
|
21
|
-
* `reasoning_delta { kind: "trace" }` in the canonical view.
|
|
22
|
-
*/
|
|
23
|
-
readonly thought: Schema.optional<Schema.Boolean>;
|
|
24
|
-
}>]>>>;
|
|
25
|
-
}>>;
|
|
26
|
-
readonly finishReason: Schema.optional<Schema.String>;
|
|
27
|
-
readonly index: Schema.optional<Schema.Number>;
|
|
28
|
-
}>>>;
|
|
29
|
-
readonly usageMetadata: Schema.optional<Schema.Struct<{
|
|
30
|
-
readonly promptTokenCount: Schema.optional<Schema.Number>;
|
|
31
|
-
readonly candidatesTokenCount: Schema.optional<Schema.Number>;
|
|
32
|
-
readonly totalTokenCount: Schema.optional<Schema.Number>;
|
|
33
|
-
readonly cachedContentTokenCount: Schema.optional<Schema.Number>;
|
|
34
|
-
readonly thoughtsTokenCount: Schema.optional<Schema.Number>;
|
|
35
|
-
}>>;
|
|
36
|
-
}>;
|
|
37
|
-
type WireChunk = typeof WireChunk.Type;
|
|
38
|
-
type RequestPart = {
|
|
39
|
-
readonly text: string;
|
|
40
|
-
} | {
|
|
41
|
-
readonly inlineData: {
|
|
42
|
-
readonly mimeType: string;
|
|
43
|
-
readonly data: string;
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
interface RequestContent {
|
|
47
|
-
readonly role: "user" | "model";
|
|
48
|
-
readonly parts: ReadonlyArray<RequestPart>;
|
|
49
|
-
}
|
|
50
|
-
interface RequestSystemInstruction {
|
|
51
|
-
readonly parts: ReadonlyArray<{
|
|
52
|
-
readonly text: string;
|
|
53
|
-
}>;
|
|
54
|
-
}
|
|
55
|
-
interface ThinkingConfig {
|
|
56
|
-
readonly thinkingBudget: number;
|
|
57
|
-
}
|
|
58
|
-
interface GenerationConfig {
|
|
59
|
-
readonly temperature?: number;
|
|
60
|
-
readonly maxOutputTokens?: number;
|
|
61
|
-
readonly topP?: number;
|
|
62
|
-
readonly thinkingConfig?: ThinkingConfig;
|
|
63
|
-
/** Set together with `responseJsonSchema` to constrain output to JSON. */
|
|
64
|
-
readonly responseMimeType?: string;
|
|
65
|
-
/** JSON Schema constraint on the output. */
|
|
66
|
-
readonly responseJsonSchema?: Record<string, unknown>;
|
|
67
|
-
}
|
|
68
|
-
interface RequestBody {
|
|
69
|
-
readonly contents: ReadonlyArray<RequestContent>;
|
|
70
|
-
readonly systemInstruction?: RequestSystemInstruction;
|
|
71
|
-
readonly generationConfig?: GenerationConfig;
|
|
72
|
-
}
|
|
73
|
-
declare const buildRequestBody: (history: ReadonlyArray<Item>, generationConfig: Option.Option<GenerationConfig>) => RequestBody;
|
|
74
|
-
interface Accumulator {
|
|
75
|
-
readonly text: string;
|
|
76
|
-
readonly reasoning: string;
|
|
77
|
-
readonly finishReason: Option.Option<string>;
|
|
78
|
-
readonly usage: {
|
|
79
|
-
readonly input_tokens?: number;
|
|
80
|
-
readonly output_tokens?: number;
|
|
81
|
-
readonly total_tokens?: number;
|
|
82
|
-
readonly input_tokens_details?: {
|
|
83
|
-
readonly cached_tokens?: number;
|
|
84
|
-
};
|
|
85
|
-
readonly output_tokens_details?: {
|
|
86
|
-
readonly reasoning_tokens?: number;
|
|
87
|
-
};
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
declare const emptyAccumulator: Accumulator;
|
|
91
|
-
/**
|
|
92
|
-
* One part's worth of streamable text: either the model's answer
|
|
93
|
-
* (`kind: "text"`) or chain-of-thought (`kind: "reasoning"`). Emitted
|
|
94
|
-
* in wire order so consumers can interleave faithfully.
|
|
95
|
-
*/
|
|
96
|
-
type ChunkPart = {
|
|
97
|
-
readonly kind: "text";
|
|
98
|
-
readonly text: string;
|
|
99
|
-
} | {
|
|
100
|
-
readonly kind: "reasoning";
|
|
101
|
-
readonly text: string;
|
|
102
|
-
};
|
|
103
|
-
interface ChunkResult {
|
|
104
|
-
readonly accumulator: Accumulator;
|
|
105
|
-
readonly parts: ReadonlyArray<ChunkPart>;
|
|
106
|
-
readonly finished: boolean;
|
|
107
|
-
}
|
|
108
|
-
declare const ingestChunk: (acc: Accumulator, chunk: WireChunk) => ChunkResult;
|
|
109
|
-
declare const accumulatorToTurn: (acc: Accumulator) => Turn;
|
|
110
|
-
//#endregion
|
|
111
|
-
//#region src/models.d.ts
|
|
112
|
-
/**
|
|
113
|
-
* Known Gemini model identifiers (as of April 2026). The `(string & {})`
|
|
114
|
-
* tail keeps autocomplete on the literals while still accepting any string,
|
|
115
|
-
* so newly-released models work without an SDK update.
|
|
116
|
-
*
|
|
117
|
-
* Reference: https://ai.google.dev/gemini-api/docs/models
|
|
118
|
-
*/
|
|
119
|
-
type GoogleModel = "gemini-3.1-pro-preview" | "gemini-3-flash-preview" | "gemini-3.1-flash-lite-preview" | "gemini-3.1-flash-live-preview" | "gemini-3.1-flash-tts-preview" | "gemini-2.5-pro" | "gemini-2.5-flash" | "gemini-2.5-flash-lite" | (string & {});
|
|
120
|
-
//#endregion
|
|
121
|
-
//#region src/Gemini.d.ts
|
|
122
|
-
/**
|
|
123
|
-
* Gemini's native event vocabulary. Aliased from `WireChunk` so the public
|
|
124
|
-
* surface matches `@effect-uai/responses` and `@effect-uai/anthropic`. Each
|
|
125
|
-
* `ProviderEvent` is a full `GenerateContentResponse` chunk (not a per-field
|
|
126
|
-
* delta) - that's how Gemini's SSE works.
|
|
127
|
-
*/
|
|
128
|
-
declare const ProviderEvent: Schema.Struct<{
|
|
129
|
-
readonly candidates: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
130
|
-
readonly content: Schema.optional<Schema.Struct<{
|
|
131
|
-
readonly role: Schema.optional<Schema.String>;
|
|
132
|
-
readonly parts: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
|
|
133
|
-
readonly text: Schema.String;
|
|
134
|
-
readonly thought: Schema.optional<Schema.Boolean>;
|
|
135
|
-
}>]>>>;
|
|
136
|
-
}>>;
|
|
137
|
-
readonly finishReason: Schema.optional<Schema.String>;
|
|
138
|
-
readonly index: Schema.optional<Schema.Number>;
|
|
139
|
-
}>>>;
|
|
140
|
-
readonly usageMetadata: Schema.optional<Schema.Struct<{
|
|
141
|
-
readonly promptTokenCount: Schema.optional<Schema.Number>;
|
|
142
|
-
readonly candidatesTokenCount: Schema.optional<Schema.Number>;
|
|
143
|
-
readonly totalTokenCount: Schema.optional<Schema.Number>;
|
|
144
|
-
readonly cachedContentTokenCount: Schema.optional<Schema.Number>;
|
|
145
|
-
readonly thoughtsTokenCount: Schema.optional<Schema.Number>;
|
|
146
|
-
}>>;
|
|
147
|
-
}>;
|
|
148
|
-
type ProviderEvent = WireChunk;
|
|
149
|
-
interface GeminiRequest extends Omit<CommonRequest, "model"> {
|
|
150
|
-
/**
|
|
151
|
-
* Narrows `CommonRequest.model` (`string`) to the typed `GoogleModel`
|
|
152
|
-
* literal union for autocomplete.
|
|
153
|
-
*/
|
|
154
|
-
readonly model: GoogleModel;
|
|
155
|
-
/**
|
|
156
|
-
* Gemini 2.5 thinking budget. `0` disables thinking entirely (lowest
|
|
157
|
-
* latency); higher values let the model think longer. Forwarded as
|
|
158
|
-
* `generationConfig.thinkingConfig.thinkingBudget`.
|
|
159
|
-
*/
|
|
160
|
-
readonly thinkingBudget?: number;
|
|
161
|
-
}
|
|
162
|
-
interface GeminiService {
|
|
163
|
-
/**
|
|
164
|
-
* Stream the provider's native event vocabulary (post-SSE-decode). For
|
|
165
|
-
* Gemini, each event is a full `GenerateContentResponse` chunk. Use this
|
|
166
|
-
* when you need access to fields the canonical view doesn't surface
|
|
167
|
-
* (`thoughtSignature`, granular `safetyRatings`, etc.). For
|
|
168
|
-
* provider-portable code, use `streamTurn`.
|
|
169
|
-
*/
|
|
170
|
-
readonly streamNative: (request: GeminiRequest) => Stream.Stream<ProviderEvent, AiError.AiError>;
|
|
171
|
-
/**
|
|
172
|
-
* Stream canonical `TurnEvent`s. Implemented as
|
|
173
|
-
* `streamNative |> toCanonical`.
|
|
174
|
-
*/
|
|
175
|
-
readonly streamTurn: (request: GeminiRequest) => Stream.Stream<TurnEvent, AiError.AiError>;
|
|
176
|
-
/**
|
|
177
|
-
* Project a stream of native `ProviderEvent`s into canonical `TurnEvent`s.
|
|
178
|
-
* Threads a fresh `Accumulator` so chunk-level text/usage merging happens
|
|
179
|
-
* per stream.
|
|
180
|
-
*/
|
|
181
|
-
readonly toCanonical: <E, R>(s: Stream.Stream<ProviderEvent, E, R>) => Stream.Stream<TurnEvent, E, R>;
|
|
182
|
-
}
|
|
183
|
-
declare const Gemini_base: Context.ServiceClass<Gemini, "@betalyra/effect-uai/providers/google/Gemini", GeminiService>;
|
|
184
|
-
/**
|
|
185
|
-
* Provider-typed service tag. Yield this when you want Gemini-specific
|
|
186
|
-
* options (`thinkingBudget`); yield the generic `LanguageModel` tag for
|
|
187
|
-
* provider-portable code. Both are registered by `layer`.
|
|
188
|
-
*/
|
|
189
|
-
declare class Gemini extends Gemini_base {}
|
|
190
|
-
interface Config {
|
|
191
|
-
readonly apiKey: Redacted.Redacted;
|
|
192
|
-
readonly baseUrl?: string;
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Project a stream of native `ProviderEvent`s into canonical `TurnEvent`s.
|
|
196
|
-
* Threads a fresh `Accumulator` so chunk-level text/usage merging works
|
|
197
|
-
* across the run.
|
|
198
|
-
*/
|
|
199
|
-
declare const toCanonical: <E, R>(s: Stream.Stream<ProviderEvent, E, R>) => Stream.Stream<TurnEvent, E, R>;
|
|
200
|
-
/**
|
|
201
|
-
* Build a `GeminiService` value. For Layer-based setup, prefer `layer`.
|
|
202
|
-
*/
|
|
203
|
-
declare const make: (cfg: Config) => Effect.Effect<GeminiService, never, HttpClient.HttpClient>;
|
|
204
|
-
/**
|
|
205
|
-
* Layer that registers both the provider-specific `Gemini` tag and the
|
|
206
|
-
* generic `LanguageModel` tag, sharing one underlying implementation.
|
|
207
|
-
*
|
|
208
|
-
* The generic tag accepts `CommonRequest`; the typed tag accepts the full
|
|
209
|
-
* `GeminiRequest` surface.
|
|
210
|
-
*/
|
|
211
|
-
declare const layer: (cfg: Config) => Layer.Layer<Gemini | LanguageModel, never, HttpClient.HttpClient>;
|
|
212
|
-
//#endregion
|
|
213
|
-
export { Config, Gemini, GeminiRequest, GeminiService, GoogleModel, ProviderEvent, codec_d_exports as codec, layer, make, toCanonical };
|
|
214
|
-
//# sourceMappingURL=index.d.mts.map
|
|
1
|
+
import { t as codec_d_exports } from "./codec.mjs";
|
|
2
|
+
import { GoogleEmbeddingModel, GoogleModel } from "./models.mjs";
|
|
3
|
+
import { t as Gemini_d_exports } from "./Gemini.mjs";
|
|
4
|
+
import { t as GeminiEmbedding_d_exports } from "./GeminiEmbedding.mjs";
|
|
5
|
+
export { Gemini_d_exports as Gemini, GeminiEmbedding_d_exports as GeminiEmbedding, GoogleEmbeddingModel, GoogleModel, codec_d_exports as codec };
|