@effect-uai/google 0.17.0 → 0.19.0-dev-20261109183959

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 (70) hide show
  1. package/README.md +4 -4
  2. package/dist/Gemini.d.mts +1 -1
  3. package/dist/Gemini.mjs +1 -1
  4. package/dist/Gemini.mjs.map +1 -1
  5. package/dist/GeminiEmbedding.d.mts +1 -1
  6. package/dist/GeminiEmbedding.d.mts.map +1 -1
  7. package/dist/GeminiEmbedding.mjs +4 -3
  8. package/dist/GeminiEmbedding.mjs.map +1 -1
  9. package/dist/GeminiImageGenerator.d.mts +1 -1
  10. package/dist/GeminiImageGenerator.d.mts.map +1 -1
  11. package/dist/GeminiImageGenerator.mjs +4 -3
  12. package/dist/GeminiImageGenerator.mjs.map +1 -1
  13. package/dist/GeminiLiveSession.d.mts +1 -1
  14. package/dist/GeminiSynthesizer.d.mts +1 -1
  15. package/dist/GeminiSynthesizer.mjs +1 -1
  16. package/dist/GeminiSynthesizer.mjs.map +1 -1
  17. package/dist/GeminiSynthesizer.test.mjs +1 -1
  18. package/dist/GoogleDeepResearch.d.mts +1 -1
  19. package/dist/GoogleDeepResearch.mjs +1 -1
  20. package/dist/GoogleDeepResearch.mjs.map +1 -1
  21. package/dist/GoogleDeepResearch.test.mjs +1 -1
  22. package/dist/LyriaGenerator.d.mts +1 -1
  23. package/dist/LyriaGenerator.d.mts.map +1 -1
  24. package/dist/LyriaGenerator.mjs +4 -3
  25. package/dist/LyriaGenerator.mjs.map +1 -1
  26. package/dist/LyriaGenerator.test.mjs +4 -142
  27. package/dist/LyriaGenerator.test.mjs.map +1 -1
  28. package/dist/codec.d.mts +28 -7
  29. package/dist/codec.d.mts.map +1 -1
  30. package/dist/codec.mjs +55 -12
  31. package/dist/codec.mjs.map +1 -1
  32. package/dist/codec.test.d.mts +1 -0
  33. package/dist/codec.test.mjs +61 -0
  34. package/dist/codec.test.mjs.map +1 -0
  35. package/dist/dist-DHer1cql.mjs +1533 -0
  36. package/dist/dist-DHer1cql.mjs.map +1 -0
  37. package/dist/geminiSpeechCodec.d.mts.map +1 -1
  38. package/dist/geminiSpeechCodec.mjs +4 -3
  39. package/dist/geminiSpeechCodec.mjs.map +1 -1
  40. package/dist/geminiSpeechCodec.test.mjs +5 -4
  41. package/dist/geminiSpeechCodec.test.mjs.map +1 -1
  42. package/dist/geminiTools.test.mjs +2 -1
  43. package/dist/geminiTools.test.mjs.map +1 -1
  44. package/dist/{test.DNmyFkvJ-BPz3G1HS.mjs → index.C4tKZ0yW-DjxCdpW_.mjs} +9115 -5993
  45. package/dist/index.C4tKZ0yW-DjxCdpW_.mjs.map +1 -0
  46. package/dist/{realtimeSession-7HSIjWh4.d.mts → realtimeSession-BlBgLDdp.d.mts} +2 -2
  47. package/dist/{realtimeSession-7HSIjWh4.d.mts.map → realtimeSession-BlBgLDdp.d.mts.map} +1 -1
  48. package/dist/realtimeSession.d.mts +1 -1
  49. package/dist/realtimeSession.mjs +8 -7
  50. package/dist/realtimeSession.mjs.map +1 -1
  51. package/dist/realtimeSession.test.mjs +120 -98
  52. package/dist/realtimeSession.test.mjs.map +1 -1
  53. package/package.json +5 -5
  54. package/src/Gemini.ts +1 -1
  55. package/src/GeminiEmbedding.ts +4 -3
  56. package/src/GeminiImageGenerator.ts +4 -3
  57. package/src/GeminiSynthesizer.ts +1 -1
  58. package/src/GoogleDeepResearch.ts +1 -1
  59. package/src/LyriaGenerator.test.ts +1 -1
  60. package/src/LyriaGenerator.ts +4 -14
  61. package/src/codec.test.ts +54 -0
  62. package/src/codec.ts +93 -23
  63. package/src/geminiSpeechCodec.test.ts +4 -3
  64. package/src/geminiSpeechCodec.ts +4 -3
  65. package/src/geminiTools.test.ts +1 -0
  66. package/src/realtimeSession.test.ts +9 -8
  67. package/src/realtimeSession.ts +7 -7
  68. package/dist/magic-string.es-CUAnjKYC.mjs +0 -1014
  69. package/dist/magic-string.es-CUAnjKYC.mjs.map +0 -1
  70. package/dist/test.DNmyFkvJ-BPz3G1HS.mjs.map +0 -1
@@ -1,41 +1,64 @@
1
1
  import { openSession } from "./realtimeSession.mjs";
2
- import { a as beforeEach, i as beforeAll, n as globalExpect, o as describe, r as afterAll, s as it$1, t as TestRunner } from "./test.DNmyFkvJ-BPz3G1HS.mjs";
3
- import { Duration, Effect, Encoding, Fiber, Logger, Redacted, Ref, Stream } from "effect";
2
+ import { a as beforeAll, c as it$2, i as afterAll, n as globalExpect, o as beforeEach, s as describe, t as TestRunner } from "./index.C4tKZ0yW-DjxCdpW_.mjs";
3
+ import { Duration, Effect, Fiber, Logger, Redacted, Ref, Stream } from "effect";
4
+ import { Base64 } from "effect/encoding";
4
5
  import { RealtimeInput } from "@effect-uai/core/Realtime";
6
+ import * as Arbitrary from "effect/Arbitrary";
5
7
  import * as Cause$1 from "effect/Cause";
6
8
  import * as Duration$1 from "effect/Duration";
7
9
  import * as Effect$1 from "effect/Effect";
8
10
  import * as Exit from "effect/Exit";
9
- import { flow, pipe as pipe$1 } from "effect/Function";
11
+ import "effect/Fiber";
12
+ import { constVoid, flow, pipe as pipe$1 } from "effect/Function";
10
13
  import * as Layer$1 from "effect/Layer";
11
- import { isObject } from "effect/Predicate";
12
- import * as Rec from "effect/Record";
13
14
  import * as Schedule from "effect/Schedule";
14
- import * as Schema$1 from "effect/Schema";
15
15
  import * as Scope$1 from "effect/Scope";
16
- import * as fc from "effect/testing/FastCheck";
17
16
  import * as TestClock from "effect/testing/TestClock";
18
17
  import * as TestConsole from "effect/testing/TestConsole";
19
18
  import * as FakeWebSocket from "@effect-uai/core/testing/FakeWebSocket";
20
- //#region ../../../node_modules/.pnpm/@effect+vitest@4.0.0-rc.111_effect@4.0.0-rc.111_vitest@4.1.11_@types+node@26.2.0_vite@7_0a4161190c2476edad4e3173ad651095/node_modules/@effect/vitest/dist/internal/internal.js
19
+ //#region ../../../node_modules/.pnpm/@effect+vitest@4.1.2_effect@4.1.2_vitest@5.0.3_@types+node@26.2.0_vite@7.3.2_@types+nod_a2fffe0deec250ef9d6207b86a9a1ab8/node_modules/@effect/vitest/dist/internal/internal.js
21
20
  /**
22
21
  * @since 4.0.0
23
22
  */
24
23
  const getCurrentSuite = TestRunner.getCurrentSuite;
25
- const runPromise = /*#__PURE__*/ Effect$1.fnUntraced(function* (effect, _ctx) {
26
- const exit = yield* Effect$1.exit(effect);
24
+ const runPromise = (effect, ctx) => Effect$1.runPromise(Effect$1.uninterruptibleMask((restore) => Effect$1.gen(function* () {
25
+ const exit = yield* Effect$1.exit(restore(effect));
27
26
  if (Exit.isFailure(exit)) {
28
27
  const errors = Cause$1.prettyErrors(exit.cause);
29
28
  for (let i = 0; i < errors.length; i++) yield* Effect$1.logError(errors[i]);
30
29
  }
31
30
  return yield* exit;
32
- }, (effect, _, ctx) => Effect$1.runPromise(effect, { signal: ctx?.signal }));
31
+ })), { signal: ctx?.signal });
32
+ const settleOnAbort = (ctx, promise) => {
33
+ const onAbort = () => ctx.onTestFinished(() => promise.then(constVoid, constVoid));
34
+ ctx.signal.addEventListener("abort", onAbort, { once: true });
35
+ const cleanup = () => ctx.signal.removeEventListener("abort", onAbort);
36
+ promise.then(cleanup, cleanup);
37
+ if (ctx.signal.aborted) onAbort();
38
+ return promise;
39
+ };
33
40
  /** @internal */
34
- const runTest = (ctx) => (effect) => runPromise(effect, ctx);
41
+ const runTest = (ctx) => (effect) => {
42
+ const promise = runPromise(effect, ctx);
43
+ return ctx ? settleOnAbort(ctx, promise) : promise;
44
+ };
35
45
  const TestEnv = /*#__PURE__*/ Layer$1.mergeAll(TestConsole.layer, /*#__PURE__*/ TestClock.layer());
36
46
  /** @internal */
37
47
  const testOptions = (timeout) => typeof timeout === "number" ? { timeout } : timeout ?? {};
38
48
  const hookTimeout = (timeout) => timeout === void 0 ? void 0 : Duration$1.toMillis(Duration$1.fromInputUnsafe(timeout));
49
+ const propertyTestOptions = (timeout) => typeof timeout === "number" ? void 0 : timeout;
50
+ const checkOptions = (timeout) => propertyTestOptions(timeout)?.arbitrary;
51
+ const compileArbitraryInput = (input) => Arbitrary.isArbitrary(input) ? input : Arbitrary.schema(input);
52
+ const makeArbitrary = (arbitraries) => Arbitrary.all(Array.isArray(arbitraries) ? arbitraries.map(compileArbitraryInput) : Object.fromEntries(Object.entries(arbitraries).map(([key, input]) => [key, compileArbitraryInput(input)])));
53
+ const normalizeProperty = (property, value) => Effect$1.catchCause(Effect$1.suspend(() => {
54
+ const output = property(value);
55
+ return Effect$1.isEffect(output) ? output : Effect$1.succeed(output);
56
+ }), (cause) => Cause$1.hasInterrupts(cause) ? Effect$1.failCause(cause) : Effect$1.fail(cause));
57
+ const runCheck = (ctx, arbitrary, property, options) => runTest(ctx)(Effect$1.flatMapEager(Arbitrary.checkEffect(arbitrary, (value) => normalizeProperty(property, value), options), (result) => {
58
+ const failure = Arbitrary.formatCheckFailure(result);
59
+ return failure === void 0 ? Effect$1.void : Effect$1.die(new Error(failure));
60
+ }));
61
+ const withFixturesOf = (source, f) => Object.defineProperty(f, "toString", { value: () => source.toString() });
39
62
  const makeItProxy = (it, overrides) => new Proxy(it, {
40
63
  apply(target, thisArg, argArray) {
41
64
  return Reflect.apply(target, thisArg, argArray);
@@ -53,109 +76,93 @@ const collectTasks = (tasks, acc = []) => {
53
76
  }
54
77
  return acc;
55
78
  };
56
- /** @internal */
57
- const makeTester = (mapEffect, it = it$1) => {
79
+ const runsMoreThanOnce = (task) => {
80
+ return ((typeof task.retry === "number" ? task.retry : task.retry?.count) ?? 0) > 0 || (task.repeats ?? 0) > 0;
81
+ };
82
+ const registerProp = (it, name, arbitraries, property, timeout) => {
83
+ const arbitrary = makeArbitrary(arbitraries);
84
+ it(name, testOptions(timeout), withFixturesOf(() => {}, (ctx) => runCheck(ctx, arbitrary, (values) => property(values, ctx), checkOptions(timeout))));
85
+ };
86
+ const makeTester = (mapEffect, it) => {
58
87
  const run = (ctx, args, self) => pipe$1(Effect$1.suspend(() => self(...args)), mapEffect, runTest(ctx));
59
- const f = (name, self, timeout) => it(name, testOptions(timeout), (ctx) => run(ctx, [ctx], self));
60
- const skip = (name, self, timeout) => it.skip(name, testOptions(timeout), (ctx) => run(ctx, [ctx], self));
61
- const skipIf = (condition) => (name, self, timeout) => it.skipIf(condition)(name, testOptions(timeout), (ctx) => run(ctx, [ctx], self));
62
- const runIf = (condition) => (name, self, timeout) => it.runIf(condition)(name, testOptions(timeout), (ctx) => run(ctx, [ctx], self));
63
- const only = (name, self, timeout) => it.only(name, testOptions(timeout), (ctx) => run(ctx, [ctx], self));
64
- const each = (cases) => (name, self, timeout) => it.for(cases)(name, testOptions(timeout), (args, ctx) => run(ctx, [args], self));
65
- const fails = (name, self, timeout) => it$1.fails(name, testOptions(timeout), (ctx) => run(ctx, [ctx], self));
66
- const prop = (name, arbitraries, self, timeout) => {
67
- if (Array.isArray(arbitraries)) {
68
- const arbs = arbitraries.map((arbitrary) => {
69
- if (Schema$1.isSchema(arbitrary)) return Schema$1.toArbitrary(arbitrary)(fc);
70
- return arbitrary;
71
- });
72
- return it(name, testOptions(timeout), (ctx) => fc.assert(fc.asyncProperty(...arbs, (...as) => run(ctx, [as, ctx], self)), isObject(timeout) ? timeout?.fastCheck : {}));
73
- }
74
- const arbs = fc.record(Object.keys(arbitraries).reduce(function(result, key) {
75
- const arb = arbitraries[key];
76
- Rec.assignProperty(result, key, Schema$1.isSchema(arb) ? Schema$1.toArbitrary(arb)(fc) : arb);
77
- return result;
78
- }, {}));
79
- return it(name, testOptions(timeout), (ctx) => fc.assert(fc.asyncProperty(arbs, (...as) => run(ctx, [as[0], ctx], self)), isObject(timeout) ? timeout?.fastCheck : {}));
80
- };
81
- return Object.assign(f, {
82
- skip,
83
- skipIf,
84
- runIf,
85
- only,
88
+ const register = (test) => (name, self, timeout) => test(name, testOptions(timeout), withFixturesOf(self, (ctx) => run(ctx, [ctx], self)));
89
+ const each = (cases) => (name, self, timeout) => it.for(cases)(name, testOptions(timeout), withFixturesOf(self, (args, ctx) => run(ctx, [args, ctx], self).then(constVoid)));
90
+ const prop = (name, arbitraries, self, timeout) => registerProp(it, name, arbitraries, (values, ctx) => Effect$1.mapEager(mapEffect(Effect$1.suspend(() => self(values, ctx))), (value) => value !== false), timeout);
91
+ return Object.assign(register(it), {
92
+ skip: register(it.skip),
93
+ skipIf: (condition) => register(it.skipIf(condition)),
94
+ runIf: (condition) => register(it.runIf(condition)),
95
+ only: register(it.only),
86
96
  each,
87
- fails,
97
+ fails: register(it.fails),
88
98
  prop
89
99
  });
90
100
  };
91
- /** @internal */
92
- const prop = (name, arbitraries, self, timeout) => {
93
- if (Array.isArray(arbitraries)) {
94
- const arbs = arbitraries.map((arbitrary) => {
95
- if (Schema$1.isSchema(arbitrary)) throw new Error("Schemas are not supported yet");
96
- return arbitrary;
97
- });
98
- return it$1(name, testOptions(timeout), (ctx) => fc.assert(fc.property(...arbs, (...as) => self(as, ctx)), isObject(timeout) ? timeout?.fastCheck : {}));
99
- }
100
- const arbs = fc.record(Object.keys(arbitraries).reduce(function(result, key) {
101
- const arb = arbitraries[key];
102
- if (Schema$1.isSchema(arb)) throw new Error("Schemas are not supported yet");
103
- Rec.assignProperty(result, key, arb);
104
- return result;
105
- }, {}));
106
- return it$1(name, testOptions(timeout), (ctx) => fc.assert(fc.property(arbs, (as) => self(as, ctx)), isObject(timeout) ? timeout?.fastCheck : {}));
107
- };
108
- /** @internal */
109
- const layer = (layer_, options) => (...args) => {
101
+ const makeProp = (it) => (name, arbitraries, self, timeout) => registerProp(it, name, arbitraries, (values, ctx) => {
102
+ const result = self(values, ctx);
103
+ if (result !== void 0 && typeof result !== "boolean") throw new TypeError("it.prop callbacks must return boolean or void. Use it.effect.prop for Effect callbacks.");
104
+ return result !== false;
105
+ }, timeout);
106
+ const makeLayer = (it) => (layer_, options) => (...args) => {
110
107
  const excludeTestServices = options?.excludeTestServices ?? false;
111
108
  const withTestEnv = excludeTestServices ? layer_ : Layer$1.provideMerge(layer_, TestEnv);
112
109
  const memoMap = options?.memoMap ?? Effect$1.runSync(Layer$1.makeMemoMap);
110
+ const buildPerTest = options?.buildPerTest ?? false;
111
+ const suiteOptions = options?.concurrent === void 0 ? {} : { concurrent: options.concurrent };
112
+ const makeBlockMethods = (provide) => makeItProxy(it, {
113
+ effect: makeTester((effect) => provide(Effect$1.scoped(effect)), it),
114
+ prop: makeProp(it),
115
+ flakyTest,
116
+ layer(nestedLayer, nestedOptions) {
117
+ return makeLayer(it)(Layer$1.provideMerge(nestedLayer, withTestEnv), {
118
+ ...nestedOptions,
119
+ memoMap: Layer$1.forkMemoMapUnsafe(memoMap),
120
+ excludeTestServices,
121
+ buildPerTest: buildPerTest || nestedOptions?.buildPerTest === true
122
+ });
123
+ }
124
+ });
125
+ if (buildPerTest) {
126
+ const methods = makeBlockMethods((effect) => Effect$1.scopedWith((scope) => Layer$1.buildWithMemoMap(withTestEnv, Layer$1.forkMemoMapUnsafe(memoMap), scope).pipe(Effect$1.orDie, Effect$1.flatMap((context) => Effect$1.provide(effect, context)))));
127
+ if (args.length === 1) return args[0](methods);
128
+ return describe(args[0], suiteOptions, () => args[1](methods));
129
+ }
113
130
  const scope = Effect$1.runSync(Scope$1.make());
114
131
  const contextEffect = Layer$1.buildWithMemoMap(withTestEnv, memoMap, scope).pipe(Effect$1.orDie, Effect$1.cached, Effect$1.runSync);
115
132
  let closed = false;
116
- const closeScope = (ctx) => {
133
+ const closeScope = () => {
117
134
  if (closed) return Promise.resolve();
118
135
  closed = true;
119
- return runPromise(Scope$1.close(scope, Exit.void), ctx);
136
+ return runPromise(Scope$1.close(scope, Exit.void));
120
137
  };
121
- const makeIt = (it) => makeItProxy(it, {
122
- effect: makeTester((effect) => Effect$1.flatMap(contextEffect, (context) => effect.pipe(Effect$1.scoped, Effect$1.provide(context))), it),
123
- prop,
124
- flakyTest,
125
- layer(nestedLayer, options) {
126
- return layer(Layer$1.provideMerge(nestedLayer, withTestEnv), {
127
- ...options,
128
- memoMap: Layer$1.forkMemoMapUnsafe(memoMap),
129
- excludeTestServices
130
- });
131
- }
132
- });
138
+ const methods = makeBlockMethods((effect) => Effect$1.flatMap(contextEffect, (context) => Effect$1.provide(effect, context)));
133
139
  if (args.length === 1) {
134
140
  const currentSuite = getCurrentSuite();
135
141
  const previousTasks = new Set(currentSuite.tasks);
136
- args[0](makeIt(it$1));
142
+ args[0](methods);
137
143
  const blockTasks = collectTasks(currentSuite.tasks.filter((task) => !previousTasks.has(task)));
138
144
  if (blockTasks.length === 0) {
139
145
  afterAll(() => closeScope(), hookTimeout(options?.timeout));
140
146
  return;
141
147
  }
142
148
  const blockTaskSet = new Set(blockTasks);
149
+ const releaseAfterLastTest = !blockTasks.some(runsMoreThanOnce);
143
150
  let remaining = blockTasks.length;
144
- beforeEach((ctx) => {
145
- if (!blockTaskSet.has(ctx.task)) return;
146
- ctx.onTestFinished(() => {
151
+ beforeEach(({ onTestFinished, signal, task }) => {
152
+ if (!blockTaskSet.has(task)) return;
153
+ if (releaseAfterLastTest) onTestFinished(() => {
147
154
  remaining--;
148
- if (remaining === 0) return closeScope(ctx);
155
+ if (remaining === 0) return closeScope();
149
156
  });
150
- return runPromise(Effect$1.asVoid(contextEffect), ctx);
157
+ return runPromise(Effect$1.asVoid(contextEffect), { signal });
151
158
  }, hookTimeout(options?.timeout));
152
159
  afterAll(() => closeScope(), hookTimeout(options?.timeout));
153
160
  return;
154
161
  }
155
- return describe(args[0], () => {
162
+ return describe(args[0], suiteOptions, () => {
156
163
  beforeAll(() => runPromise(Effect$1.asVoid(contextEffect)), hookTimeout(options?.timeout));
157
164
  afterAll(() => closeScope(), hookTimeout(options?.timeout));
158
- return args[1](makeIt(it$1));
165
+ return args[1](methods);
159
166
  });
160
167
  };
161
168
  /** @internal */
@@ -165,20 +172,23 @@ const makeMethods = (it) => makeItProxy(it, {
165
172
  effect: makeTester(flow(Effect$1.scoped, Effect$1.provide(TestEnv)), it),
166
173
  live: makeTester(Effect$1.scoped, it),
167
174
  flakyTest,
168
- layer,
169
- prop
175
+ layer: makeLayer(it),
176
+ prop: makeProp(it)
170
177
  });
171
178
  /** @internal */
172
- const { effect, live } = /*#__PURE__*/ makeMethods(it$1);
179
+ const it$1 = /*#__PURE__*/ makeMethods(it$2);
180
+ /** @internal */
181
+ const { effect, layer, live, prop } = it$1;
173
182
  //#endregion
174
- //#region ../../../node_modules/.pnpm/@effect+vitest@4.0.0-rc.111_effect@4.0.0-rc.111_vitest@4.1.11_@types+node@26.2.0_vite@7_0a4161190c2476edad4e3173ad651095/node_modules/@effect/vitest/dist/index.js
175
- /**
176
- * @since 4.0.0
177
- */
183
+ //#region ../../../node_modules/.pnpm/@effect+vitest@4.1.2_effect@4.1.2_vitest@5.0.3_@types+node@26.2.0_vite@7.3.2_@types+nod_a2fffe0deec250ef9d6207b86a9a1ab8/node_modules/@effect/vitest/dist/index.js
178
184
  /**
185
+ * Vitest test API extended with Effect test helpers.
186
+ *
187
+ * @stability unstable
188
+ * @category testing
179
189
  * @since 4.0.0
180
190
  */
181
- const it = /*#__PURE__*/ makeMethods(it$1);
191
+ const it = it$1;
182
192
  //#endregion
183
193
  //#region src/realtimeSession.test.ts
184
194
  const request = {
@@ -225,7 +235,7 @@ const transcript = (server, script, options) => Effect.gen(function* () {
225
235
  const tags = (events) => events.map((e) => e._tag);
226
236
  const audioPart = (bytes) => ({ inlineData: {
227
237
  mimeType: "audio/pcm;rate=24000",
228
- data: Encoding.encodeBase64(new Uint8Array(bytes))
238
+ data: Base64.encode(new Uint8Array(bytes))
229
239
  } });
230
240
  describe("Gemini live session turns", () => {
231
241
  it.live("mints one turn id for a whole answer, and reports its usage at the end", () => Effect.gen(function* () {
@@ -335,7 +345,10 @@ describe("Gemini live session tools", () => {
335
345
  yield* handle.send(RealtimeInput.ToolResult({ output: {
336
346
  type: "function_call_output",
337
347
  call_id: "fc_1",
338
- output: "{\"celsius\":32}",
348
+ output: [{
349
+ type: "input_json",
350
+ value: { celsius: 32 }
351
+ }],
339
352
  providerData: void 0
340
353
  } }));
341
354
  yield* server.push({ serverContent: { turnComplete: true } });
@@ -347,7 +360,7 @@ describe("Gemini live session tools", () => {
347
360
  globalExpect(response.toolResponse.functionResponses).toEqual([{
348
361
  id: "fc_1",
349
362
  name: "get_weather",
350
- response: { celsius: 32 },
363
+ response: { output: { celsius: 32 } },
351
364
  scheduling: "WHEN_IDLE"
352
365
  }]);
353
366
  }).pipe(Effect.scoped));
@@ -363,7 +376,10 @@ describe("Gemini live session tools", () => {
363
376
  yield* handle.send(RealtimeInput.ToolResult({ output: {
364
377
  type: "function_call_output",
365
378
  call_id: "fc_1",
366
- output: "{}",
379
+ output: [{
380
+ type: "input_json",
381
+ value: {}
382
+ }],
367
383
  providerData: void 0
368
384
  } }));
369
385
  }), { request: {
@@ -382,7 +398,10 @@ describe("Gemini live session tools", () => {
382
398
  const failure = yield* Effect.exit(handle.send(RealtimeInput.ToolResult({ output: {
383
399
  type: "function_call_output",
384
400
  call_id: "fc_unknown",
385
- output: "{}",
401
+ output: [{
402
+ type: "input_json",
403
+ value: {}
404
+ }],
386
405
  providerData: void 0
387
406
  } })));
388
407
  globalExpect(failure._tag).toBe("Failure");
@@ -462,7 +481,10 @@ describe("Gemini live session history", () => {
462
481
  {
463
482
  type: "function_call_output",
464
483
  call_id: "fc_1",
465
- output: "{\"now\":\"12:00\"}",
484
+ output: [{
485
+ type: "input_json",
486
+ value: { now: "12:00" }
487
+ }],
466
488
  providerData: void 0
467
489
  }
468
490
  ]
@@ -494,7 +516,7 @@ describe("Gemini live session video", () => {
494
516
  }));
495
517
  const sent = yield* server.sent;
496
518
  globalExpect(sent.filter((f) => f.realtimeInput?.video !== void 0)).toEqual([{ realtimeInput: { video: {
497
- data: Encoding.encodeBase64(new Uint8Array([1, 2])),
519
+ data: Base64.encode(new Uint8Array([1, 2])),
498
520
  mimeType: "image/jpeg"
499
521
  } } }]);
500
522
  }).pipe(Effect.scoped));
@@ -1 +1 @@
1
- {"version":3,"file":"realtimeSession.test.mjs","names":["Effect","Cause","Duration","V.it","pipe","Schema","Layer","Scope","V.describe","V.it"],"sources":["../../../../node_modules/.pnpm/@effect+vitest@4.0.0-rc.111_effect@4.0.0-rc.111_vitest@4.1.11_@types+node@26.2.0_vite@7_0a4161190c2476edad4e3173ad651095/node_modules/@effect/vitest/dist/internal/internal.js","../../../../node_modules/.pnpm/@effect+vitest@4.0.0-rc.111_effect@4.0.0-rc.111_vitest@4.1.11_@types+node@26.2.0_vite@7_0a4161190c2476edad4e3173ad651095/node_modules/@effect/vitest/dist/index.js","../src/realtimeSession.test.ts"],"sourcesContent":["/**\n * @since 4.0.0\n */\nimport * as Cause from \"effect/Cause\";\nimport * as Duration from \"effect/Duration\";\nimport * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\nimport { flow, pipe } from \"effect/Function\";\nimport * as Layer from \"effect/Layer\";\nimport { isObject } from \"effect/Predicate\";\nimport * as Rec from \"effect/Record\";\nimport * as Schedule from \"effect/Schedule\";\nimport * as Schema from \"effect/Schema\";\nimport * as Scope from \"effect/Scope\";\nimport * as fc from \"effect/testing/FastCheck\";\nimport * as TestClock from \"effect/testing/TestClock\";\nimport * as TestConsole from \"effect/testing/TestConsole\";\nimport * as V from \"vitest\";\nconst getCurrentSuite = V.TestRunner.getCurrentSuite;\nconst runPromise = /*#__PURE__*/Effect.fnUntraced(function* (effect, _ctx) {\n const exit = yield* Effect.exit(effect);\n if (Exit.isFailure(exit)) {\n const errors = Cause.prettyErrors(exit.cause);\n for (let i = 0; i < errors.length; i++) {\n yield* Effect.logError(errors[i]);\n }\n }\n return yield* exit;\n}, (effect, _, ctx) => Effect.runPromise(effect, {\n signal: ctx?.signal\n}));\n/** @internal */\nconst runTest = ctx => effect => runPromise(effect, ctx);\nconst TestEnv = /*#__PURE__*/Layer.mergeAll(TestConsole.layer, /*#__PURE__*/TestClock.layer());\n/** @internal */\nexport const addEqualityTesters = () => {\n V.expect.addEqualityTesters([]);\n};\n/** @internal */\nconst testOptions = timeout => typeof timeout === \"number\" ? {\n timeout\n} : timeout ?? {};\nconst hookTimeout = timeout => timeout === undefined ? undefined : Duration.toMillis(Duration.fromInputUnsafe(timeout));\nconst makeItProxy = (it, overrides) => new Proxy(it, {\n apply(target, thisArg, argArray) {\n return Reflect.apply(target, thisArg, argArray);\n },\n get(target, property, receiver) {\n if (Object.hasOwn(overrides, property)) {\n return Reflect.get(overrides, property);\n }\n // do not bind: binding would strip vitest's static helpers (e.g. `describe.each`)\n return Reflect.get(target, property, receiver);\n }\n});\nconst collectTasks = (tasks, acc = []) => {\n for (let i = 0; i < tasks.length; i++) {\n const task = tasks[i];\n if (task.type === \"test\" && task.mode !== \"skip\" && task.mode !== \"todo\") {\n acc.push(task);\n } else if (task.tasks !== undefined) {\n collectTasks(task.tasks, acc);\n }\n }\n return acc;\n};\n/** @internal */\nconst makeTester = (mapEffect, it = V.it) => {\n const run = (ctx, args, self) => pipe(Effect.suspend(() => self(...args)), mapEffect, runTest(ctx));\n const f = (name, self, timeout) => it(name, testOptions(timeout), ctx => run(ctx, [ctx], self));\n const skip = (name, self, timeout) => it.skip(name, testOptions(timeout), ctx => run(ctx, [ctx], self));\n const skipIf = condition => (name, self, timeout) => it.skipIf(condition)(name, testOptions(timeout), ctx => run(ctx, [ctx], self));\n const runIf = condition => (name, self, timeout) => it.runIf(condition)(name, testOptions(timeout), ctx => run(ctx, [ctx], self));\n const only = (name, self, timeout) => it.only(name, testOptions(timeout), ctx => run(ctx, [ctx], self));\n const each = cases => (name, self, timeout) => it.for(cases)(name, testOptions(timeout), (args, ctx) => run(ctx, [args], self));\n const fails = (name, self, timeout) => V.it.fails(name, testOptions(timeout), ctx => run(ctx, [ctx], self));\n const prop = (name, arbitraries, self, timeout) => {\n if (Array.isArray(arbitraries)) {\n const arbs = arbitraries.map(arbitrary => {\n if (Schema.isSchema(arbitrary)) {\n return Schema.toArbitrary(arbitrary)(fc);\n }\n return arbitrary;\n });\n return it(name, testOptions(timeout), ctx =>\n // @ts-ignore\n fc.assert(\n // @ts-ignore\n fc.asyncProperty(...arbs, (...as) => run(ctx, [as, ctx], self)),\n // @ts-ignore\n isObject(timeout) ? timeout?.fastCheck : {}));\n }\n const arbs = fc.record(Object.keys(arbitraries).reduce(function (result, key) {\n const arb = arbitraries[key];\n Rec.assignProperty(result, key, Schema.isSchema(arb) ? Schema.toArbitrary(arb)(fc) : arb);\n return result;\n }, {}));\n return it(name, testOptions(timeout), ctx =>\n // @ts-ignore\n fc.assert(fc.asyncProperty(arbs, (...as) =>\n // @ts-ignore\n run(ctx, [as[0], ctx], self)),\n // @ts-ignore\n isObject(timeout) ? timeout?.fastCheck : {}));\n };\n return Object.assign(f, {\n skip,\n skipIf,\n runIf,\n only,\n each,\n fails,\n prop\n });\n};\n/** @internal */\nexport const prop = (name, arbitraries, self, timeout) => {\n if (Array.isArray(arbitraries)) {\n const arbs = arbitraries.map(arbitrary => {\n if (Schema.isSchema(arbitrary)) {\n throw new Error(\"Schemas are not supported yet\");\n }\n return arbitrary;\n });\n return V.it(name, testOptions(timeout),\n // @ts-ignore\n ctx => fc.assert(fc.property(...arbs, (...as) => self(as, ctx)), isObject(timeout) ? timeout?.fastCheck : {}));\n }\n const arbs = fc.record(Object.keys(arbitraries).reduce(function (result, key) {\n const arb = arbitraries[key];\n if (Schema.isSchema(arb)) {\n throw new Error(\"Schemas are not supported yet\");\n }\n Rec.assignProperty(result, key, arb);\n return result;\n }, {}));\n return V.it(name, testOptions(timeout),\n // @ts-ignore\n ctx => fc.assert(fc.property(arbs, as => self(as, ctx)), isObject(timeout) ? timeout?.fastCheck : {}));\n};\n/** @internal */\nexport const layer = (layer_, options) => (...args) => {\n const excludeTestServices = options?.excludeTestServices ?? false;\n const withTestEnv = excludeTestServices ? layer_ : Layer.provideMerge(layer_, TestEnv);\n const memoMap = options?.memoMap ?? Effect.runSync(Layer.makeMemoMap);\n const scope = Effect.runSync(Scope.make());\n const contextEffect = Layer.buildWithMemoMap(withTestEnv, memoMap, scope).pipe(Effect.orDie, Effect.cached, Effect.runSync);\n let closed = false;\n const closeScope = ctx => {\n if (closed) {\n return Promise.resolve();\n }\n closed = true;\n return runPromise(Scope.close(scope, Exit.void), ctx);\n };\n const makeIt = it => makeItProxy(it, {\n effect: makeTester(effect => Effect.flatMap(contextEffect, context => effect.pipe(Effect.scoped, Effect.provide(context))), it),\n prop,\n flakyTest,\n layer(nestedLayer, options) {\n return layer(Layer.provideMerge(nestedLayer, withTestEnv), {\n ...options,\n memoMap: Layer.forkMemoMapUnsafe(memoMap),\n excludeTestServices\n });\n }\n });\n if (args.length === 1) {\n const currentSuite = getCurrentSuite();\n const previousTasks = new Set(currentSuite.tasks);\n args[0](makeIt(V.it));\n const blockTasks = collectTasks(currentSuite.tasks.filter(task => !previousTasks.has(task)));\n if (blockTasks.length === 0) {\n V.afterAll(() => closeScope(), hookTimeout(options?.timeout));\n return;\n }\n const blockTaskSet = new Set(blockTasks);\n let remaining = blockTasks.length;\n V.beforeEach(ctx => {\n if (!blockTaskSet.has(ctx.task)) {\n return;\n }\n ctx.onTestFinished(() => {\n remaining--;\n if (remaining === 0) {\n return closeScope(ctx);\n }\n });\n return runPromise(Effect.asVoid(contextEffect), ctx);\n }, hookTimeout(options?.timeout));\n V.afterAll(() => closeScope(), hookTimeout(options?.timeout));\n return;\n }\n return V.describe(args[0], () => {\n V.beforeAll(() => runPromise(Effect.asVoid(contextEffect)), hookTimeout(options?.timeout));\n V.afterAll(() => closeScope(), hookTimeout(options?.timeout));\n return args[1](makeIt(V.it));\n });\n};\n/** @internal */\nexport const flakyTest = (self, timeout = Duration.seconds(30)) => pipe(self, Effect.scoped, Effect.sandbox, Effect.retry(pipe(Schedule.recurs(10), Schedule.while(_ => Effect.succeed(Duration.isLessThanOrEqualTo(Duration.fromInputUnsafe(_.elapsed), Duration.fromInputUnsafe(timeout)))))), Effect.orDie);\n/** @internal */\nexport const makeMethods = it => makeItProxy(it, {\n effect: makeTester(flow(Effect.scoped, Effect.provide(TestEnv)), it),\n live: makeTester(Effect.scoped, it),\n flakyTest,\n layer,\n prop\n});\n/** @internal */\nexport const {\n /** @internal */\n effect,\n /** @internal */\n live\n} = /*#__PURE__*/makeMethods(V.it);\n/** @internal */\nexport const describeWrapped = (name, f) => V.describe(name, it => f(makeMethods(it)));\n//# sourceMappingURL=internal.js.map","import * as V from \"vitest\";\nimport * as internal from \"./internal/internal.js\";\n/**\n * @since 4.0.0\n */\nexport * from \"vitest\";\n/**\n * @since 4.0.0\n */\nexport const addEqualityTesters = internal.addEqualityTesters;\n/**\n * @since 4.0.0\n */\nexport const effect = internal.effect;\n/**\n * @since 4.0.0\n */\nexport const live = internal.live;\n/**\n * Share a `Layer` between multiple tests, optionally wrapping\n * the tests in a `describe` block if a name is provided.\n *\n * @since 4.0.0\n *\n * ```ts\n * import { assert, layer } from \"@effect/vitest\"\n * import { Effect, Layer, Context } from \"effect\"\n *\n * class Foo extends Context.Service<Foo, \"foo\">()(\"Foo\") {\n * static layer = Layer.succeed(Foo, \"foo\")\n * }\n *\n * class Bar extends Context.Service<Bar, \"bar\">()(\"Bar\") {\n * static layer = Layer.effect(\n * Bar,\n * Effect.map(Foo, () => \"bar\" as const)\n * )\n * }\n *\n * layer(Foo.layer)(\"layer\", (it) => {\n * it.effect(\"adds context\", () =>\n * Effect.gen(function*() {\n * const foo = yield* Foo\n * assert.strictEqual(foo, \"foo\")\n * }))\n *\n * it.layer(Bar.layer)(\"nested\", (it) => {\n * it.effect(\"adds context\", () =>\n * Effect.gen(function*() {\n * const foo = yield* Foo\n * const bar = yield* Bar\n * assert.strictEqual(foo, \"foo\")\n * assert.strictEqual(bar, \"bar\")\n * }))\n * })\n * })\n * ```\n */\nexport const layer = internal.layer;\n/**\n * @since 4.0.0\n */\nexport const flakyTest = internal.flakyTest;\n/**\n * @since 4.0.0\n */\nexport const prop = internal.prop;\n/**\n * @since 4.0.0\n */\n/**\n * @since 4.0.0\n */\nexport const it = /*#__PURE__*/internal.makeMethods(V.it);\n/**\n * @since 4.0.0\n */\nexport const makeMethods = internal.makeMethods;\n/**\n * @since 4.0.0\n */\nexport const describeWrapped = internal.describeWrapped;\n//# sourceMappingURL=index.js.map","import { describe, it } from \"@effect/vitest\"\nimport { Duration, Effect, Encoding, Fiber, Logger, Redacted, Ref, Stream } from \"effect\"\nimport { expect } from \"vitest\"\nimport type { RealtimeEvent } from \"@effect-uai/core/Realtime\"\nimport { RealtimeInput } from \"@effect-uai/core/Realtime\"\nimport type { RealtimeSessionHandle } from \"@effect-uai/core/RealtimeSession\"\nimport * as FakeWebSocket from \"@effect-uai/core/testing/FakeWebSocket\"\nimport { type GeminiLiveRequest, openSession } from \"./realtimeSession.js\"\n\nconst request: GeminiLiveRequest = {\n model: \"gemini-3.1-flash-live-preview\",\n instructions: \"be terse\",\n voiceId: \"Kore\",\n inputFormat: { container: \"raw\", encoding: \"pcm_s16le\", sampleRate: 16000, channels: 1 },\n outputFormat: { container: \"raw\", encoding: \"pcm_s16le\", sampleRate: 24000, channels: 1 },\n}\n\nconst cfg = { apiKey: Redacted.make(\"test-key\") }\n\n/** The client speaks first here, so the handshake answers `setup`. */\nconst gemini = FakeWebSocket.make({\n reply: (frame) =>\n Effect.succeed(Object.hasOwn(frame as object, \"setup\") ? [{ setupComplete: {} }] : []),\n})\n\n/** Let the socket's own turn and the adapter's fibers run. */\nconst tick = Effect.sleep(\"5 millis\")\n\n/**\n * Events are recorded as they arrive rather than collected at the end, so a\n * run that ends in a failure still says what the caller saw before it.\n */\nconst transcript = (\n server: FakeWebSocket.FakeWebSocketServer,\n script: (handle: RealtimeSessionHandle) => Effect.Effect<void, unknown>,\n options?: { readonly closeCode?: number; readonly request?: GeminiLiveRequest },\n) =>\n Effect.gen(function* () {\n const handle = yield* openSession({ ...cfg, webSocket: server.connect })(\n options?.request ?? request,\n )\n const seen = yield* Ref.make<ReadonlyArray<RealtimeEvent>>([])\n const collector = yield* Effect.forkChild(\n Effect.exit(Stream.runForEach(handle.events, (e) => Ref.update(seen, (xs) => [...xs, e]))),\n )\n yield* script(handle)\n yield* tick\n yield* server.close(options?.closeCode ?? 1000)\n const exit = yield* Fiber.join(collector)\n return { exit, events: yield* Ref.get(seen) }\n })\n\nconst tags = (events: ReadonlyArray<RealtimeEvent>) => events.map((e) => e._tag)\n\nconst audioPart = (bytes: ReadonlyArray<number>) => ({\n inlineData: {\n mimeType: \"audio/pcm;rate=24000\",\n data: Encoding.encodeBase64(new Uint8Array(bytes)),\n },\n})\n\ndescribe(\"Gemini live session turns\", () => {\n it.live(\"mints one turn id for a whole answer, and reports its usage at the end\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { events } = yield* transcript(server, () =>\n Effect.gen(function* () {\n // 3.1 packs several parts, and their transcription, into one message.\n yield* server.push({\n serverContent: {\n modelTurn: { parts: [audioPart([1, 2, 3]), { thought: true, text: \"planning\" }] },\n outputTranscription: { text: \"hi\" },\n },\n })\n yield* server.push({\n serverContent: { modelTurn: { parts: [audioPart([4, 5])] } },\n usageMetadata: { promptTokenCount: 10, responseTokenCount: 20, totalTokenCount: 30 },\n })\n yield* server.push({ serverContent: { turnComplete: true } })\n }),\n )\n\n // The thought part is the model reasoning, not something to speak.\n expect(tags(events)).toEqual([\n \"ResponseStarted\",\n \"AudioDelta\",\n \"OutputTranscriptDelta\",\n \"AudioDelta\",\n \"ResponseDone\",\n ])\n // The wire carries no response id, so every event of the turn shares one.\n expect(new Set(events.map((e) => (\"responseId\" in e ? e.responseId : \"\")))).toEqual(\n new Set([\"turn_1\"]),\n )\n const done = events[4]\n expect(done?._tag === \"ResponseDone\" && done.reason).toBe(\"complete\")\n expect(done?._tag === \"ResponseDone\" && done.usage?.total_tokens).toBe(30)\n }).pipe(Effect.scoped),\n )\n\n it.live(\"ends an interrupted turn once, and numbers the next one after it\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { events } = yield* transcript(server, () =>\n Effect.gen(function* () {\n yield* server.push({ serverContent: { modelTurn: { parts: [audioPart([1])] } } })\n yield* server.push({ serverContent: { interrupted: true } })\n // The server follows an interruption with `turnComplete`, which\n // would otherwise end the same turn a second time.\n yield* server.push({ serverContent: { turnComplete: true } })\n yield* server.push({ serverContent: { modelTurn: { parts: [audioPart([2])] } } })\n yield* server.push({ serverContent: { turnComplete: true } })\n }),\n )\n\n expect(tags(events)).toEqual([\n \"ResponseStarted\",\n \"AudioDelta\",\n \"Interrupted\",\n \"ResponseDone\",\n \"ResponseStarted\",\n \"AudioDelta\",\n \"ResponseDone\",\n ])\n const interrupted = events[3]\n expect(interrupted?._tag === \"ResponseDone\" && interrupted.reason).toBe(\"interrupted\")\n const next = events[4]\n expect(next?._tag === \"ResponseStarted\" && next.responseId).toBe(\"turn_2\")\n }).pipe(Effect.scoped),\n )\n\n it.live(\"marks the user's words interim until the utterance is transcribed\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { events } = yield* transcript(server, () =>\n Effect.gen(function* () {\n yield* server.push({ serverContent: { interimInputTranscription: { text: \"weather\" } } })\n yield* server.push({\n serverContent: { inputTranscription: { text: \"weather in Lisbon\" } },\n })\n }),\n )\n\n // A transcript belongs to no turn, so none is started for it.\n expect(events).toEqual([\n { _tag: \"InputTranscript\", text: \"weather\", final: false },\n { _tag: \"InputTranscript\", text: \"weather in Lisbon\", final: true },\n ])\n }).pipe(Effect.scoped),\n )\n\n it.live(\"ends the stream as an incomplete turn when a turn is still running\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { exit } = yield* transcript(server, () =>\n server.push({ serverContent: { modelTurn: { parts: [audioPart([1])] } } }),\n )\n\n // A close must never look like a finished turn.\n expect(exit._tag).toBe(\"Failure\")\n expect(JSON.stringify(exit)).toContain(\"IncompleteTurn\")\n }).pipe(Effect.scoped),\n )\n\n it.live(\"fails when the socket closes before the configuration is accepted\", () =>\n Effect.gen(function* () {\n const mute = yield* FakeWebSocket.make()\n const opened = yield* Effect.forkChild(\n Effect.exit(openSession({ ...cfg, webSocket: mute.connect })(request)),\n )\n yield* tick\n yield* mute.close(1000)\n\n const exit = yield* Fiber.join(opened)\n expect(exit._tag).toBe(\"Failure\")\n expect(JSON.stringify(exit)).toContain(\"Unavailable\")\n }).pipe(Effect.scoped),\n )\n})\n\ndescribe(\"Gemini live session tools\", () => {\n it.live(\"answers a call with the name the server gave it\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { events } = yield* transcript(server, (handle) =>\n Effect.gen(function* () {\n yield* server.push({\n toolCall: {\n functionCalls: [{ id: \"fc_1\", name: \"get_weather\", args: { city: \"Lisbon\" } }],\n },\n })\n yield* tick\n yield* handle.send(\n RealtimeInput.ToolResult({\n output: {\n type: \"function_call_output\",\n call_id: \"fc_1\",\n output: '{\"celsius\":32}',\n providerData: undefined,\n },\n }),\n )\n yield* server.push({ serverContent: { turnComplete: true } })\n }),\n )\n\n const call = events.find((e) => e._tag === \"ToolCall\")\n expect(call?._tag === \"ToolCall\" && call.call.arguments).toBe('{\"city\":\"Lisbon\"}')\n // A call arrives with no turn open, so it gets one of its own.\n expect(call?._tag === \"ToolCall\" && call.responseId).toBe(\"turn_1\")\n\n const sent = yield* server.sent\n const response = sent.find((f: any) => f.toolResponse !== undefined) as any\n // The name comes from the call, and the payload has to be an object.\n // `WHEN_IDLE` by default: a model that kept talking while the tool ran\n // finishes the sentence rather than cutting itself off to report.\n expect(response.toolResponse.functionResponses).toEqual([\n {\n id: \"fc_1\",\n name: \"get_weather\",\n response: { celsius: 32 },\n scheduling: \"WHEN_IDLE\",\n },\n ])\n }).pipe(Effect.scoped),\n )\n\n it.live(\"reports a result at once when the caller asks it to interrupt\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n yield* transcript(\n server,\n (handle) =>\n Effect.gen(function* () {\n yield* server.push({\n toolCall: { functionCalls: [{ id: \"fc_1\", name: \"get_weather\", args: {} }] },\n })\n yield* tick\n yield* handle.send(\n RealtimeInput.ToolResult({\n output: {\n type: \"function_call_output\",\n call_id: \"fc_1\",\n output: \"{}\",\n providerData: undefined,\n },\n }),\n )\n }),\n { request: { ...request, toolScheduling: \"interrupt\" } },\n )\n\n const sent = yield* server.sent\n const response = sent.find((f: any) => f.toolResponse !== undefined) as any\n expect(response.toolResponse.functionResponses[0].scheduling).toBe(\"INTERRUPT\")\n }).pipe(Effect.scoped),\n )\n\n it.live(\"rejects a result for a call this session never made\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const handle = yield* openSession({ ...cfg, webSocket: server.connect })(request)\n const failure = yield* Effect.exit(\n handle.send(\n RealtimeInput.ToolResult({\n output: {\n type: \"function_call_output\",\n call_id: \"fc_unknown\",\n output: \"{}\",\n providerData: undefined,\n },\n }),\n ),\n )\n\n expect(failure._tag).toBe(\"Failure\")\n expect(JSON.stringify(failure)).toContain(\"InvalidRequest\")\n expect((yield* server.sent).some((f: any) => f.toolResponse !== undefined)).toBe(false)\n }).pipe(Effect.scoped),\n )\n})\n\ndescribe(\"Gemini live session lifetime\", () => {\n it.live(\"keeps only a resumable handle, and reads the closing warning as a duration\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { events, exit } = yield* transcript(server, () =>\n Effect.gen(function* () {\n // Sent while a tool runs: no handle, and the stored one must stand.\n yield* server.push({ sessionResumptionUpdate: { newHandle: \"\", resumable: false } })\n yield* server.push({ sessionResumptionUpdate: { newHandle: \"h1\", resumable: true } })\n yield* server.push({ goAway: { timeLeft: \"60s\" } })\n }),\n )\n\n expect(tags(events)).toEqual([\"ResumptionHandle\", \"SessionEnding\"])\n const handle = events[0]\n expect(handle?._tag === \"ResumptionHandle\" && handle.handle).toBe(\"h1\")\n const ending = events[1]\n // A proto duration string, not a number.\n expect(ending?._tag === \"SessionEnding\" && ending.timeLeft).toEqual(Duration.seconds(60))\n // The close `goAway` announced is the lifetime cap, not a clean end, so\n // a caller can tell \"reconnect\" from \"we are done here\".\n expect(JSON.stringify(exit)).toContain(\"SessionExpired\")\n }).pipe(Effect.scoped),\n )\n\n it.live(\"ends cleanly when the close was not announced\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { exit } = yield* transcript(server, () =>\n server.push({ serverContent: { turnComplete: true } }),\n )\n\n expect(exit._tag).toBe(\"Success\")\n }).pipe(Effect.scoped),\n )\n})\n\n/** The `CapabilityWarning` payloads a run produced, in order. */\nconst warningCollector = () => {\n const seen: Array<{ readonly field: string; readonly value?: unknown }> = []\n const logger = Logger.make((options) => {\n const [label, warning] = options.message as ReadonlyArray<any>\n if (label === \"Capability dropped\") seen.push(warning)\n })\n return { seen, layer: Logger.layer([logger]) }\n}\n\nconst userText = (text: string) =>\n ({\n type: \"message\",\n role: \"user\",\n content: [{ type: \"input_text\", text, providerData: undefined }],\n providerData: undefined,\n }) as const\n\nconst call = (id: string) =>\n ({\n type: \"function_call\",\n call_id: id,\n name: \"get_time\",\n arguments: \"{}\",\n providerData: undefined,\n }) as const\n\ndescribe(\"Gemini live session history\", () => {\n it.live(\"names each kind of item the text-only seed cannot carry, once\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const warnings = warningCollector()\n\n yield* openSession({ ...cfg, webSocket: server.connect })({\n ...request,\n history: [\n userText(\"what time is it\"),\n call(\"fc_1\"),\n call(\"fc_2\"),\n {\n type: \"function_call_output\",\n call_id: \"fc_1\",\n output: '{\"now\":\"12:00\"}',\n providerData: undefined,\n },\n ],\n }).pipe(Effect.provide(warnings.layer))\n yield* tick\n\n // Two calls, one kind: a long tool history is not a wall of warnings.\n expect(warnings.seen.map((w) => w.value)).toEqual([\"function_call\", \"function_call_output\"])\n expect(warnings.seen.every((w) => w.field === \"history\")).toBe(true)\n\n const sent = yield* server.sent\n const seed = sent.find((f: any) => f.clientContent !== undefined) as any\n expect(seed.clientContent.turns).toEqual([\n { role: \"user\", parts: [{ text: \"what time is it\" }] },\n ])\n }).pipe(Effect.scoped),\n )\n})\n\ndescribe(\"Gemini live session video\", () => {\n it.live(\"sends frame bytes inline, and refuses a frame it would have to fetch\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n yield* transcript(server, (handle) =>\n Effect.gen(function* () {\n yield* handle.send(\n RealtimeInput.VideoFrame({\n frame: { _tag: \"bytes\", bytes: new Uint8Array([1, 2]), mimeType: \"image/jpeg\" },\n }),\n )\n // A URL would need an upload through the Files API first.\n const exit = yield* Effect.exit(\n handle.send(\n RealtimeInput.VideoFrame({\n frame: { _tag: \"url\", url: \"https://example.com/frame.jpg\" },\n }),\n ),\n )\n expect(JSON.stringify(exit)).toContain(\"Unsupported\")\n }),\n )\n\n const sent = yield* server.sent\n expect(sent.filter((f: any) => f.realtimeInput?.video !== undefined)).toEqual([\n {\n realtimeInput: {\n video: { data: Encoding.encodeBase64(new Uint8Array([1, 2])), mimeType: \"image/jpeg\" },\n },\n },\n ])\n }).pipe(Effect.scoped),\n )\n})\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
1
+ {"version":3,"file":"realtimeSession.test.mjs","names":["Effect","Cause","Duration","pipe","Layer","V.describe","Scope","it","V.it","internal.it"],"sources":["../../../../node_modules/.pnpm/@effect+vitest@4.1.2_effect@4.1.2_vitest@5.0.3_@types+node@26.2.0_vite@7.3.2_@types+nod_a2fffe0deec250ef9d6207b86a9a1ab8/node_modules/@effect/vitest/dist/internal/internal.js","../../../../node_modules/.pnpm/@effect+vitest@4.1.2_effect@4.1.2_vitest@5.0.3_@types+node@26.2.0_vite@7.3.2_@types+nod_a2fffe0deec250ef9d6207b86a9a1ab8/node_modules/@effect/vitest/dist/index.js","../src/realtimeSession.test.ts"],"sourcesContent":["/**\n * @since 4.0.0\n */\nimport * as Arbitrary from \"effect/Arbitrary\";\nimport * as Cause from \"effect/Cause\";\nimport * as Duration from \"effect/Duration\";\nimport * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\nimport * as Fiber from \"effect/Fiber\";\nimport { constVoid, flow, pipe } from \"effect/Function\";\nimport * as Layer from \"effect/Layer\";\nimport * as Schedule from \"effect/Schedule\";\nimport * as Scope from \"effect/Scope\";\nimport * as TestClock from \"effect/testing/TestClock\";\nimport * as TestConsole from \"effect/testing/TestConsole\";\nimport * as V from \"vitest\";\nconst getCurrentSuite = V.TestRunner.getCurrentSuite;\nconst runPromise = (effect, ctx) => Effect.runPromise(\n// Only the test is interruptible: once the signal aborts, the fiber stops\n// at its next interruptible step, which would skip reporting the defects\n// raised by finalizers.\nEffect.uninterruptibleMask(restore => Effect.gen(function* () {\n const exit = yield* Effect.exit(restore(effect));\n if (Exit.isFailure(exit)) {\n const errors = Cause.prettyErrors(exit.cause);\n for (let i = 0; i < errors.length; i++) {\n yield* Effect.logError(errors[i]);\n }\n }\n return yield* exit;\n})), {\n signal: ctx?.signal\n});\nconst settleOnAbort = (ctx, promise) => {\n // Vitest stops awaiting the promise once the signal aborts (timeout or\n // cancellation), so only then add a hook that waits for the finalizers.\n // Registering it unconditionally would change the teardown of every test.\n const onAbort = () => ctx.onTestFinished(() => promise.then(constVoid, constVoid));\n ctx.signal.addEventListener(\"abort\", onAbort, {\n once: true\n });\n const cleanup = () => ctx.signal.removeEventListener(\"abort\", onAbort);\n promise.then(cleanup, cleanup);\n // A retry after a timed-out attempt reuses the aborted signal, so no event fires.\n if (ctx.signal.aborted) onAbort();\n return promise;\n};\n/** @internal */\nconst runTest = ctx => effect => {\n const promise = runPromise(effect, ctx);\n return ctx ? settleOnAbort(ctx, promise) : promise;\n};\nconst TestEnv = /*#__PURE__*/Layer.mergeAll(TestConsole.layer, /*#__PURE__*/TestClock.layer());\n/** @internal */\nexport const addEqualityTesters = () => {\n V.expect.addEqualityTesters([]);\n};\n/** @internal */\nconst testOptions = timeout => typeof timeout === \"number\" ? {\n timeout\n} : timeout ?? {};\nconst hookTimeout = timeout => timeout === undefined ? undefined : Duration.toMillis(Duration.fromInputUnsafe(timeout));\nconst propertyTestOptions = timeout => typeof timeout === \"number\" ? undefined : timeout;\nconst checkOptions = timeout => propertyTestOptions(timeout)?.arbitrary;\nconst compileArbitraryInput = input => Arbitrary.isArbitrary(input) ? input : Arbitrary.schema(input);\nconst makeArbitrary = arbitraries => Arbitrary.all(Array.isArray(arbitraries) ? arbitraries.map(compileArbitraryInput) : Object.fromEntries(Object.entries(arbitraries).map(([key, input]) => [key, compileArbitraryInput(input)])));\nconst normalizeProperty = (property, value) => Effect.catchCause(Effect.suspend(() => {\n const output = property(value);\n return Effect.isEffect(output) ? output : Effect.succeed(output);\n}), cause => Cause.hasInterrupts(cause) ? Effect.failCause(cause) : Effect.fail(cause));\nconst runCheck = (ctx, arbitrary, property, options) => runTest(ctx)(Effect.flatMapEager(Arbitrary.checkEffect(arbitrary, value => normalizeProperty(property, value), options), result => {\n const failure = Arbitrary.formatCheckFailure(result);\n return failure === undefined ? Effect.void : Effect.die(new Error(failure));\n}));\n// Vitest decides which fixtures to set up by parsing the source of a test\n// function's context parameter, and there is no public API to supply the names\n// for a wrapper, so wrappers expose the source of the function they call.\nconst withFixturesOf = (source, f) => Object.defineProperty(f, \"toString\", {\n value: () => source.toString()\n});\nconst runHook = (fn, run) => withFixturesOf(fn, (...args) => {\n const result = fn(...args);\n if (!Effect.isEffect(result)) {\n return result;\n }\n const scope = Scope.makeUnsafe();\n // Everything the hook leaves behind lives in the scope: the resources it\n // acquired and, ahead of them, a cleanup function it returned. On failure\n // the scope closes inside the fiber, so interrupting it awaits the release.\n const effect = Scope.provide(result, scope).pipe(Effect.flatMap(cleanup => typeof cleanup === \"function\" ? Scope.addFinalizer(scope, Effect.promise(async () => await cleanup())) : Effect.void), Effect.onError(cause => Scope.close(scope, Exit.failCause(cause))));\n return run(args, effect, scope);\n});\n// Closing must outlive an already-aborted signal, so it runs without one.\nconst closeHookScope = scope => runPromise(Scope.close(scope, Exit.void));\n/** @internal */\nexport const beforeAll = (fn, timeout) => {\n let dispose = () => Promise.resolve();\n // Vitest drops the cleanup of a setup that outlives its timeout, so the\n // scope is disposed by the cleanup of a hook registered just before this\n // one. It runs in the same cleanup phase, in the slot next to this hook's,\n // with this hook's timeout.\n V.beforeAll(() => () => dispose(), timeout);\n V.beforeAll(runHook(fn, (_, effect, scope) => {\n const fiber = Effect.runFork(effect);\n // Interrupting a setup that Vitest stopped waiting for awaits its release.\n dispose = () => runPromise(Effect.andThen(Fiber.interrupt(fiber), Scope.close(scope, Exit.void)));\n return runPromise(Fiber.join(fiber));\n }), timeout);\n};\n/** @internal */\nexport const beforeEach = (fn, timeout) => V.beforeEach(runHook(fn, ([ctx], effect, scope) =>\n// The scope closes when Vitest runs the hook's cleanup after the test,\n// and the next test waits for it even if that cleanup times out.\nrunTest(ctx)(effect).then(() => () => settleOnAbort(ctx, closeHookScope(scope)))), timeout);\nconst makeItProxy = (it, overrides) => new Proxy(it, {\n apply(target, thisArg, argArray) {\n return Reflect.apply(target, thisArg, argArray);\n },\n get(target, property, receiver) {\n if (Object.hasOwn(overrides, property)) {\n return Reflect.get(overrides, property);\n }\n // do not bind: binding would strip vitest's static helpers (e.g. `describe.each`)\n return Reflect.get(target, property, receiver);\n }\n});\nconst collectTasks = (tasks, acc = []) => {\n for (let i = 0; i < tasks.length; i++) {\n const task = tasks[i];\n if (task.type === \"test\" && task.mode !== \"skip\" && task.mode !== \"todo\") {\n acc.push(task);\n } else if (task.tasks !== undefined) {\n collectTasks(task.tasks, acc);\n }\n }\n return acc;\n};\nconst runsMoreThanOnce = task => {\n const retry = typeof task.retry === \"number\" ? task.retry : task.retry?.count;\n return (retry ?? 0) > 0 || (task.repeats ?? 0) > 0;\n};\nconst registerProp = (it, name, arbitraries, property, timeout) => {\n const arbitrary = makeArbitrary(arbitraries);\n // Property callbacks receive only the base context; the empty source requests no fixtures.\n it(name, testOptions(timeout), withFixturesOf(() => {}, ctx => runCheck(ctx, arbitrary, values => property(values, ctx), checkOptions(timeout))));\n};\nconst makeTester = (mapEffect, it) => {\n const run = (ctx, args, self) => pipe(Effect.suspend(() => self(...args)), mapEffect, runTest(ctx));\n const register = test => (name, self, timeout) => test(name, testOptions(timeout), withFixturesOf(self, ctx => run(ctx, [ctx], self)));\n const each = cases => (name, self, timeout) => it.for(cases)(name, testOptions(timeout), withFixturesOf(self, (args, ctx) => run(ctx, [args, ctx], self).then(constVoid)));\n const prop = (name, arbitraries, self, timeout) => registerProp(it, name, arbitraries, (values, ctx) => Effect.mapEager(mapEffect(Effect.suspend(() => self(values, ctx))), value => value !== false), timeout);\n return Object.assign(register(it), {\n skip: register(it.skip),\n skipIf: condition => register(it.skipIf(condition)),\n runIf: condition => register(it.runIf(condition)),\n only: register(it.only),\n each,\n fails: register(it.fails),\n prop\n });\n};\nconst makeProp = it => (name, arbitraries, self, timeout) => registerProp(it, name, arbitraries, (values, ctx) => {\n const result = self(values, ctx);\n if (result !== undefined && typeof result !== \"boolean\") {\n throw new TypeError(\"it.prop callbacks must return boolean or void. Use it.effect.prop for Effect callbacks.\");\n }\n return result !== false;\n}, timeout);\nconst makeLayer = it => (layer_, options) => (...args) => {\n const excludeTestServices = options?.excludeTestServices ?? false;\n const withTestEnv = excludeTestServices ? layer_ : Layer.provideMerge(layer_, TestEnv);\n const memoMap = options?.memoMap ?? Effect.runSync(Layer.makeMemoMap);\n const buildPerTest = options?.buildPerTest ?? false;\n const suiteOptions = options?.concurrent === undefined ? {} : {\n concurrent: options.concurrent\n };\n const makeBlockMethods = provide => makeItProxy(it, {\n effect: makeTester(effect => provide(Effect.scoped(effect)), it),\n prop: makeProp(it),\n flakyTest,\n layer(nestedLayer, nestedOptions) {\n return makeLayer(it)(Layer.provideMerge(nestedLayer, withTestEnv), {\n ...nestedOptions,\n memoMap: Layer.forkMemoMapUnsafe(memoMap),\n excludeTestServices,\n // The services of a per-test block only exist during a test, so\n // blocks nested in it are built per test as well.\n buildPerTest: buildPerTest || nestedOptions?.buildPerTest === true\n });\n }\n });\n if (buildPerTest) {\n // Each test builds into its own fork of the memo map, so it reuses the\n // services of enclosing blocks and releases the rest when it finishes.\n const methods = makeBlockMethods(effect => Effect.scopedWith(scope => Layer.buildWithMemoMap(withTestEnv, Layer.forkMemoMapUnsafe(memoMap), scope).pipe(Effect.orDie, Effect.flatMap(context => Effect.provide(effect, context)))));\n if (args.length === 1) {\n return args[0](methods);\n }\n return V.describe(args[0], suiteOptions, () => args[1](methods));\n }\n const scope = Effect.runSync(Scope.make());\n const contextEffect = Layer.buildWithMemoMap(withTestEnv, memoMap, scope).pipe(Effect.orDie, Effect.cached, Effect.runSync);\n let closed = false;\n const closeScope = () => {\n if (closed) {\n return Promise.resolve();\n }\n closed = true;\n // Layer cleanup must outlive the last test's already-aborted signal.\n return runPromise(Scope.close(scope, Exit.void));\n };\n const methods = makeBlockMethods(effect => Effect.flatMap(contextEffect, context => Effect.provide(effect, context)));\n if (args.length === 1) {\n const currentSuite = getCurrentSuite();\n const previousTasks = new Set(currentSuite.tasks);\n args[0](methods);\n const blockTasks = collectTasks(currentSuite.tasks.filter(task => !previousTasks.has(task)));\n if (blockTasks.length === 0) {\n V.afterAll(() => closeScope(), hookTimeout(options?.timeout));\n return;\n }\n const blockTaskSet = new Set(blockTasks);\n // Vitest runs hooks once per retry and repeat attempt, so a test's last\n // attempt cannot be counted. Blocks with such tests are released by `afterAll`.\n const releaseAfterLastTest = !blockTasks.some(runsMoreThanOnce);\n let remaining = blockTasks.length;\n V.beforeEach(\n // Destructured so Vitest can parse the hook once the suite defines fixtures.\n ({\n onTestFinished,\n signal,\n task\n }) => {\n if (!blockTaskSet.has(task)) {\n return;\n }\n if (releaseAfterLastTest) {\n onTestFinished(() => {\n remaining--;\n if (remaining === 0) {\n return closeScope();\n }\n });\n }\n return runPromise(Effect.asVoid(contextEffect), {\n signal\n });\n }, hookTimeout(options?.timeout));\n V.afterAll(() => closeScope(), hookTimeout(options?.timeout));\n return;\n }\n return V.describe(args[0], suiteOptions, () => {\n V.beforeAll(() => runPromise(Effect.asVoid(contextEffect)), hookTimeout(options?.timeout));\n V.afterAll(() => closeScope(), hookTimeout(options?.timeout));\n return args[1](methods);\n });\n};\n/** @internal */\nexport const flakyTest = (self, timeout = Duration.seconds(30)) => pipe(self, Effect.scoped, Effect.sandbox, Effect.retry(pipe(Schedule.recurs(10), Schedule.while(_ => Effect.succeed(Duration.isLessThanOrEqualTo(Duration.fromInputUnsafe(_.elapsed), Duration.fromInputUnsafe(timeout)))))), Effect.orDie);\n/** @internal */\nexport const makeMethods = it => makeItProxy(it, {\n effect: makeTester(flow(Effect.scoped, Effect.provide(TestEnv)), it),\n live: makeTester(Effect.scoped, it),\n flakyTest,\n layer: makeLayer(it),\n prop: makeProp(it)\n});\n/** @internal */\nexport const it = /*#__PURE__*/makeMethods(V.it);\n/** @internal */\nexport const {\n /** @internal */\n effect,\n /** @internal */\n layer,\n /** @internal */\n live,\n /** @internal */\n prop\n} = it;\n/** @internal */\nexport const describeWrapped = (name, f) => V.describe(name, () => f(it));\n//# sourceMappingURL=internal.js.map","import * as internal from \"./internal/internal.js\";\n/**\n * Re-exports the `vitest` API unchanged.\n *\n * @stability unstable\n * @since 4.0.0\n */\nexport * from \"vitest\";\n/**\n * Invokes the Effect Vitest equality-tester registration hook.\n *\n * @stability unstable\n * @category utils\n * @since 4.0.0\n */\nexport const addEqualityTesters = internal.addEqualityTesters;\n/**\n * Registers a callback to run once before all tests in the current suite. If\n * the callback returns an `Effect`, it is run and awaited with a `Scope` that\n * closes in a cleanup after the suite's `afterAll` hooks, within the hook's\n * timeout. The `Effect` must not require any other services.\n *\n * **Details**\n *\n * If Vitest stops waiting for the setup, the setup is interrupted before the\n * `Scope` closes. As with any `beforeAll` cleanup, Vitest reports a closing\n * that exceeds the hook's timeout and does not wait for it.\n *\n * @stability unstable\n * @category hooks\n * @since 4.0.0\n */\nexport const beforeAll = internal.beforeAll;\n/**\n * Registers a callback to run before each test in the current suite. If the\n * callback returns an `Effect`, it is run and awaited with a `Scope` that\n * closes when the test finishes, and interrupted if the hook times out. The\n * `Effect` must not require any other services.\n *\n * @stability unstable\n * @category hooks\n * @since 4.0.0\n */\nexport const beforeEach = internal.beforeEach;\n/**\n * Runs a scoped Effect test with test clock and console services.\n *\n * @stability unstable\n * @category testing\n * @since 4.0.0\n */\nexport const effect = internal.effect;\n/**\n * Runs a scoped Effect test with live services.\n *\n * @stability unstable\n * @category testing\n * @since 4.0.0\n */\nexport const live = internal.live;\n/**\n * Share a `Layer` between multiple tests, optionally wrapping\n * the tests in a `describe` block if a name is provided.\n *\n * **Details**\n *\n * Named layers accept `concurrent` to override inherited suite concurrency.\n * Anonymous layers always inherit the enclosing suite's concurrency.\n * Use `ctx.expect` in concurrent tests for test-local snapshots and assertion counts.\n *\n * Pass `buildPerTest: true` to build the layer once per test instead of once\n * per block. Each test gets new services, released when the test finishes,\n * while services from an enclosing `layer` block stay shared. A build failure\n * fails only that test. Blocks nested inside a per-test block are built per\n * test as well. `timeout` has no effect on a per-test block, since the test's\n * own timeout covers the build.\n *\n * **Example** (Sharing layers between tests)\n *\n * ```ts\n * import { assert, layer } from \"@effect/vitest\"\n * import { Effect, Layer, Context } from \"effect\"\n *\n * class Foo extends Context.Service<Foo, \"foo\">()(\"Foo\") {\n * static layer = Layer.succeed(Foo, \"foo\")\n * }\n *\n * class Bar extends Context.Service<Bar, \"bar\">()(\"Bar\") {\n * static layer = Layer.effect(\n * Bar,\n * Effect.map(Foo, () => \"bar\" as const)\n * )\n * }\n *\n * layer(Foo.layer)(\"layer\", (it) => {\n * it.effect(\"adds context\", () =>\n * Effect.gen(function*() {\n * const foo = yield* Foo\n * assert.strictEqual(foo, \"foo\")\n * }))\n *\n * it.layer(Bar.layer)(\"nested\", (it) => {\n * it.effect(\"adds context\", () =>\n * Effect.gen(function*() {\n * const foo = yield* Foo\n * const bar = yield* Bar\n * assert.strictEqual(foo, \"foo\")\n * assert.strictEqual(bar, \"bar\")\n * }))\n * })\n * })\n * ```\n *\n * **Example** (Building a layer for each test)\n *\n * ```ts\n * import { assert, layer } from \"@effect/vitest\"\n * import { Effect, Layer, Context, Ref } from \"effect\"\n *\n * class Database extends Context.Service<Database, \"database\">()(\"Database\") {\n * static layer = Layer.succeed(Database, \"database\")\n * }\n *\n * class Cache extends Context.Service<Cache, Ref.Ref<Array<string>>>()(\"Cache\") {\n * static layer = Layer.effect(\n * Cache,\n * Effect.andThen(Database, Ref.make<Array<string>>([]))\n * )\n * }\n *\n * layer(Database.layer)(\"repository\", (it) => {\n * // Database is shared, Cache is built for each test\n * it.layer(Cache.layer, { buildPerTest: true })((it) => {\n * it.effect(\"writes to the cache\", () =>\n * Effect.gen(function*() {\n * const cache = yield* Cache\n * yield* Ref.update(cache, (keys) => [...keys, \"a\"])\n * assert.deepStrictEqual(yield* Ref.get(cache), [\"a\"])\n * }))\n *\n * it.effect(\"starts with an empty cache\", () =>\n * Effect.gen(function*() {\n * const cache = yield* Cache\n * assert.deepStrictEqual(yield* Ref.get(cache), [])\n * }))\n * })\n * })\n * ```\n *\n * @stability unstable\n * @category testing\n * @since 4.0.0\n */\nexport const layer = internal.layer;\n/**\n * Retries a scoped Effect to tolerate intermittent test failures, dying on exhausted retries.\n *\n * @stability unstable\n * @category testing\n * @since 4.0.0\n */\nexport const flakyTest = internal.flakyTest;\n/**\n * Runs a synchronous property test using schemas or arbitraries.\n *\n * @stability unstable\n * @category testing\n * @since 4.0.0\n */\nexport const prop = internal.prop;\n/**\n * Vitest test API extended with Effect test helpers.\n *\n * @stability unstable\n * @category testing\n * @since 4.0.0\n */\nexport const it = internal.it;\n/**\n * Creates the Effect test helpers for a Vitest test API, such as one extended with fixtures.\n *\n * **Details**\n *\n * Tests receive the fixtures they destructure from their context. Vitest sets them up before the test and tears\n * them down after the test's scope closes, as it does for its own tests. `it.effect.each` passes the context\n * after the test case, and named and anonymous `it.layer` blocks keep the fixtures.\n *\n * **Gotchas**\n *\n * Vitest reads the destructured names to decide which fixtures to set up. Once any fixture is defined, a test that\n * takes the whole context as a plain parameter, such as `(ctx) =>`, fails with a `FixtureParseError`. Property\n * tests receive only the base test context and cannot request fixtures; auto fixtures still run.\n *\n * **Example** (Using a Vitest fixture in an Effect test)\n *\n * ```ts\n * import { assert, makeMethods, test } from \"@effect/vitest\"\n * import { Effect } from \"effect\"\n *\n * const it = makeMethods(\n * test.extend(\"config\", { scope: \"file\" }, () => ({ port: 3000 }))\n * )\n *\n * it.effect(\"reads the config fixture\", ({ config }) =>\n * Effect.sync(() => {\n * assert.strictEqual(config.port, 3000)\n * }))\n * ```\n *\n * @stability unstable\n * @category constructors\n * @since 4.0.0\n */\nexport const makeMethods = internal.makeMethods;\n/**\n * Creates a named Vitest suite whose callback receives Effect test helpers.\n *\n * @stability unstable\n * @category testing\n * @since 4.0.0\n */\nexport const describeWrapped = internal.describeWrapped;\n//# sourceMappingURL=index.js.map","import { describe, it } from \"@effect/vitest\"\nimport { Duration, Effect, Fiber, Logger, Redacted, Ref, Stream } from \"effect\"\nimport { Base64 } from \"effect/encoding\"\nimport { expect } from \"vitest\"\nimport type { RealtimeEvent } from \"@effect-uai/core/Realtime\"\nimport { RealtimeInput } from \"@effect-uai/core/Realtime\"\nimport type { RealtimeSessionHandle } from \"@effect-uai/core/RealtimeSession\"\nimport * as FakeWebSocket from \"@effect-uai/core/testing/FakeWebSocket\"\nimport { type GeminiLiveRequest, openSession } from \"./realtimeSession.js\"\n\nconst request: GeminiLiveRequest = {\n model: \"gemini-3.1-flash-live-preview\",\n instructions: \"be terse\",\n voiceId: \"Kore\",\n inputFormat: { container: \"raw\", encoding: \"pcm_s16le\", sampleRate: 16000, channels: 1 },\n outputFormat: { container: \"raw\", encoding: \"pcm_s16le\", sampleRate: 24000, channels: 1 },\n}\n\nconst cfg = { apiKey: Redacted.make(\"test-key\") }\n\n/** The client speaks first here, so the handshake answers `setup`. */\nconst gemini = FakeWebSocket.make({\n reply: (frame) =>\n Effect.succeed(Object.hasOwn(frame as object, \"setup\") ? [{ setupComplete: {} }] : []),\n})\n\n/** Let the socket's own turn and the adapter's fibers run. */\nconst tick = Effect.sleep(\"5 millis\")\n\n/**\n * Events are recorded as they arrive rather than collected at the end, so a\n * run that ends in a failure still says what the caller saw before it.\n */\nconst transcript = (\n server: FakeWebSocket.FakeWebSocketServer,\n script: (handle: RealtimeSessionHandle) => Effect.Effect<void, unknown>,\n options?: { readonly closeCode?: number; readonly request?: GeminiLiveRequest },\n) =>\n Effect.gen(function* () {\n const handle = yield* openSession({ ...cfg, webSocket: server.connect })(\n options?.request ?? request,\n )\n const seen = yield* Ref.make<ReadonlyArray<RealtimeEvent>>([])\n const collector = yield* Effect.forkChild(\n Effect.exit(Stream.runForEach(handle.events, (e) => Ref.update(seen, (xs) => [...xs, e]))),\n )\n yield* script(handle)\n yield* tick\n yield* server.close(options?.closeCode ?? 1000)\n const exit = yield* Fiber.join(collector)\n return { exit, events: yield* Ref.get(seen) }\n })\n\nconst tags = (events: ReadonlyArray<RealtimeEvent>) => events.map((e) => e._tag)\n\nconst audioPart = (bytes: ReadonlyArray<number>) => ({\n inlineData: {\n mimeType: \"audio/pcm;rate=24000\",\n data: Base64.encode(new Uint8Array(bytes)),\n },\n})\n\ndescribe(\"Gemini live session turns\", () => {\n it.live(\"mints one turn id for a whole answer, and reports its usage at the end\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { events } = yield* transcript(server, () =>\n Effect.gen(function* () {\n // 3.1 packs several parts, and their transcription, into one message.\n yield* server.push({\n serverContent: {\n modelTurn: { parts: [audioPart([1, 2, 3]), { thought: true, text: \"planning\" }] },\n outputTranscription: { text: \"hi\" },\n },\n })\n yield* server.push({\n serverContent: { modelTurn: { parts: [audioPart([4, 5])] } },\n usageMetadata: { promptTokenCount: 10, responseTokenCount: 20, totalTokenCount: 30 },\n })\n yield* server.push({ serverContent: { turnComplete: true } })\n }),\n )\n\n // The thought part is the model reasoning, not something to speak.\n expect(tags(events)).toEqual([\n \"ResponseStarted\",\n \"AudioDelta\",\n \"OutputTranscriptDelta\",\n \"AudioDelta\",\n \"ResponseDone\",\n ])\n // The wire carries no response id, so every event of the turn shares one.\n expect(new Set(events.map((e) => (\"responseId\" in e ? e.responseId : \"\")))).toEqual(\n new Set([\"turn_1\"]),\n )\n const done = events[4]\n expect(done?._tag === \"ResponseDone\" && done.reason).toBe(\"complete\")\n expect(done?._tag === \"ResponseDone\" && done.usage?.total_tokens).toBe(30)\n }).pipe(Effect.scoped),\n )\n\n it.live(\"ends an interrupted turn once, and numbers the next one after it\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { events } = yield* transcript(server, () =>\n Effect.gen(function* () {\n yield* server.push({ serverContent: { modelTurn: { parts: [audioPart([1])] } } })\n yield* server.push({ serverContent: { interrupted: true } })\n // The server follows an interruption with `turnComplete`, which\n // would otherwise end the same turn a second time.\n yield* server.push({ serverContent: { turnComplete: true } })\n yield* server.push({ serverContent: { modelTurn: { parts: [audioPart([2])] } } })\n yield* server.push({ serverContent: { turnComplete: true } })\n }),\n )\n\n expect(tags(events)).toEqual([\n \"ResponseStarted\",\n \"AudioDelta\",\n \"Interrupted\",\n \"ResponseDone\",\n \"ResponseStarted\",\n \"AudioDelta\",\n \"ResponseDone\",\n ])\n const interrupted = events[3]\n expect(interrupted?._tag === \"ResponseDone\" && interrupted.reason).toBe(\"interrupted\")\n const next = events[4]\n expect(next?._tag === \"ResponseStarted\" && next.responseId).toBe(\"turn_2\")\n }).pipe(Effect.scoped),\n )\n\n it.live(\"marks the user's words interim until the utterance is transcribed\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { events } = yield* transcript(server, () =>\n Effect.gen(function* () {\n yield* server.push({ serverContent: { interimInputTranscription: { text: \"weather\" } } })\n yield* server.push({\n serverContent: { inputTranscription: { text: \"weather in Lisbon\" } },\n })\n }),\n )\n\n // A transcript belongs to no turn, so none is started for it.\n expect(events).toEqual([\n { _tag: \"InputTranscript\", text: \"weather\", final: false },\n { _tag: \"InputTranscript\", text: \"weather in Lisbon\", final: true },\n ])\n }).pipe(Effect.scoped),\n )\n\n it.live(\"ends the stream as an incomplete turn when a turn is still running\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { exit } = yield* transcript(server, () =>\n server.push({ serverContent: { modelTurn: { parts: [audioPart([1])] } } }),\n )\n\n // A close must never look like a finished turn.\n expect(exit._tag).toBe(\"Failure\")\n expect(JSON.stringify(exit)).toContain(\"IncompleteTurn\")\n }).pipe(Effect.scoped),\n )\n\n it.live(\"fails when the socket closes before the configuration is accepted\", () =>\n Effect.gen(function* () {\n const mute = yield* FakeWebSocket.make()\n const opened = yield* Effect.forkChild(\n Effect.exit(openSession({ ...cfg, webSocket: mute.connect })(request)),\n )\n yield* tick\n yield* mute.close(1000)\n\n const exit = yield* Fiber.join(opened)\n expect(exit._tag).toBe(\"Failure\")\n expect(JSON.stringify(exit)).toContain(\"Unavailable\")\n }).pipe(Effect.scoped),\n )\n})\n\ndescribe(\"Gemini live session tools\", () => {\n it.live(\"answers a call with the name the server gave it\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { events } = yield* transcript(server, (handle) =>\n Effect.gen(function* () {\n yield* server.push({\n toolCall: {\n functionCalls: [{ id: \"fc_1\", name: \"get_weather\", args: { city: \"Lisbon\" } }],\n },\n })\n yield* tick\n yield* handle.send(\n RealtimeInput.ToolResult({\n output: {\n type: \"function_call_output\",\n call_id: \"fc_1\",\n output: [{ type: \"input_json\", value: { celsius: 32 } }],\n providerData: undefined,\n },\n }),\n )\n yield* server.push({ serverContent: { turnComplete: true } })\n }),\n )\n\n const call = events.find((e) => e._tag === \"ToolCall\")\n expect(call?._tag === \"ToolCall\" && call.call.arguments).toBe('{\"city\":\"Lisbon\"}')\n // A call arrives with no turn open, so it gets one of its own.\n expect(call?._tag === \"ToolCall\" && call.responseId).toBe(\"turn_1\")\n\n const sent = yield* server.sent\n const response = sent.find((f: any) => f.toolResponse !== undefined) as any\n // The name comes from the call, and the payload has to be an object.\n // `WHEN_IDLE` by default: a model that kept talking while the tool ran\n // finishes the sentence rather than cutting itself off to report.\n expect(response.toolResponse.functionResponses).toEqual([\n {\n id: \"fc_1\",\n name: \"get_weather\",\n response: { output: { celsius: 32 } },\n scheduling: \"WHEN_IDLE\",\n },\n ])\n }).pipe(Effect.scoped),\n )\n\n it.live(\"reports a result at once when the caller asks it to interrupt\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n yield* transcript(\n server,\n (handle) =>\n Effect.gen(function* () {\n yield* server.push({\n toolCall: { functionCalls: [{ id: \"fc_1\", name: \"get_weather\", args: {} }] },\n })\n yield* tick\n yield* handle.send(\n RealtimeInput.ToolResult({\n output: {\n type: \"function_call_output\",\n call_id: \"fc_1\",\n output: [{ type: \"input_json\", value: {} }],\n providerData: undefined,\n },\n }),\n )\n }),\n { request: { ...request, toolScheduling: \"interrupt\" } },\n )\n\n const sent = yield* server.sent\n const response = sent.find((f: any) => f.toolResponse !== undefined) as any\n expect(response.toolResponse.functionResponses[0].scheduling).toBe(\"INTERRUPT\")\n }).pipe(Effect.scoped),\n )\n\n it.live(\"rejects a result for a call this session never made\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const handle = yield* openSession({ ...cfg, webSocket: server.connect })(request)\n const failure = yield* Effect.exit(\n handle.send(\n RealtimeInput.ToolResult({\n output: {\n type: \"function_call_output\",\n call_id: \"fc_unknown\",\n output: [{ type: \"input_json\", value: {} }],\n providerData: undefined,\n },\n }),\n ),\n )\n\n expect(failure._tag).toBe(\"Failure\")\n expect(JSON.stringify(failure)).toContain(\"InvalidRequest\")\n expect((yield* server.sent).some((f: any) => f.toolResponse !== undefined)).toBe(false)\n }).pipe(Effect.scoped),\n )\n})\n\ndescribe(\"Gemini live session lifetime\", () => {\n it.live(\"keeps only a resumable handle, and reads the closing warning as a duration\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { events, exit } = yield* transcript(server, () =>\n Effect.gen(function* () {\n // Sent while a tool runs: no handle, and the stored one must stand.\n yield* server.push({ sessionResumptionUpdate: { newHandle: \"\", resumable: false } })\n yield* server.push({ sessionResumptionUpdate: { newHandle: \"h1\", resumable: true } })\n yield* server.push({ goAway: { timeLeft: \"60s\" } })\n }),\n )\n\n expect(tags(events)).toEqual([\"ResumptionHandle\", \"SessionEnding\"])\n const handle = events[0]\n expect(handle?._tag === \"ResumptionHandle\" && handle.handle).toBe(\"h1\")\n const ending = events[1]\n // A proto duration string, not a number.\n expect(ending?._tag === \"SessionEnding\" && ending.timeLeft).toEqual(Duration.seconds(60))\n // The close `goAway` announced is the lifetime cap, not a clean end, so\n // a caller can tell \"reconnect\" from \"we are done here\".\n expect(JSON.stringify(exit)).toContain(\"SessionExpired\")\n }).pipe(Effect.scoped),\n )\n\n it.live(\"ends cleanly when the close was not announced\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const { exit } = yield* transcript(server, () =>\n server.push({ serverContent: { turnComplete: true } }),\n )\n\n expect(exit._tag).toBe(\"Success\")\n }).pipe(Effect.scoped),\n )\n})\n\n/** The `CapabilityWarning` payloads a run produced, in order. */\nconst warningCollector = () => {\n const seen: Array<{ readonly field: string; readonly value?: unknown }> = []\n const logger = Logger.make((options) => {\n const [label, warning] = options.message as ReadonlyArray<any>\n if (label === \"Capability dropped\") seen.push(warning)\n })\n return { seen, layer: Logger.layer([logger]) }\n}\n\nconst userText = (text: string) =>\n ({\n type: \"message\",\n role: \"user\",\n content: [{ type: \"input_text\", text, providerData: undefined }],\n providerData: undefined,\n }) as const\n\nconst call = (id: string) =>\n ({\n type: \"function_call\",\n call_id: id,\n name: \"get_time\",\n arguments: \"{}\",\n providerData: undefined,\n }) as const\n\ndescribe(\"Gemini live session history\", () => {\n it.live(\"names each kind of item the text-only seed cannot carry, once\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n const warnings = warningCollector()\n\n yield* openSession({ ...cfg, webSocket: server.connect })({\n ...request,\n history: [\n userText(\"what time is it\"),\n call(\"fc_1\"),\n call(\"fc_2\"),\n {\n type: \"function_call_output\",\n call_id: \"fc_1\",\n output: [{ type: \"input_json\", value: { now: \"12:00\" } }],\n providerData: undefined,\n },\n ],\n }).pipe(Effect.provide(warnings.layer))\n yield* tick\n\n // Two calls, one kind: a long tool history is not a wall of warnings.\n expect(warnings.seen.map((w) => w.value)).toEqual([\"function_call\", \"function_call_output\"])\n expect(warnings.seen.every((w) => w.field === \"history\")).toBe(true)\n\n const sent = yield* server.sent\n const seed = sent.find((f: any) => f.clientContent !== undefined) as any\n expect(seed.clientContent.turns).toEqual([\n { role: \"user\", parts: [{ text: \"what time is it\" }] },\n ])\n }).pipe(Effect.scoped),\n )\n})\n\ndescribe(\"Gemini live session video\", () => {\n it.live(\"sends frame bytes inline, and refuses a frame it would have to fetch\", () =>\n Effect.gen(function* () {\n const server = yield* gemini\n yield* transcript(server, (handle) =>\n Effect.gen(function* () {\n yield* handle.send(\n RealtimeInput.VideoFrame({\n frame: { _tag: \"bytes\", bytes: new Uint8Array([1, 2]), mimeType: \"image/jpeg\" },\n }),\n )\n // A URL would need an upload through the Files API first.\n const exit = yield* Effect.exit(\n handle.send(\n RealtimeInput.VideoFrame({\n frame: { _tag: \"url\", url: \"https://example.com/frame.jpg\" },\n }),\n ),\n )\n expect(JSON.stringify(exit)).toContain(\"Unsupported\")\n }),\n )\n\n const sent = yield* server.sent\n expect(sent.filter((f: any) => f.realtimeInput?.video !== undefined)).toEqual([\n {\n realtimeInput: {\n video: { data: Base64.encode(new Uint8Array([1, 2])), mimeType: \"image/jpeg\" },\n },\n },\n ])\n }).pipe(Effect.scoped),\n )\n})\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-uai/google",
3
- "version": "0.17.0",
3
+ "version": "0.19.0-dev-20261109183959",
4
4
  "description": "Google Gemini provider for @effect-uai/core.",
5
5
  "keywords": [
6
6
  "ai",
@@ -67,13 +67,13 @@
67
67
  "access": "public"
68
68
  },
69
69
  "devDependencies": {
70
- "effect": "4.0.0-rc.111",
70
+ "effect": "4.1.2",
71
71
  "typescript": "^7.0.2",
72
- "@effect-uai/core": "0.17.0"
72
+ "@effect-uai/core": "0.19.0-dev-20261109183959"
73
73
  },
74
74
  "peerDependencies": {
75
- "@effect-uai/core": ">=0.2.0 <1",
76
- "effect": ">=4.0.0-rc.111 <5.0.0"
75
+ "@effect-uai/core": "0.19.0-dev-20261109183959",
76
+ "effect": ">=4.0.1 <5.0.0"
77
77
  },
78
78
  "scripts": {
79
79
  "build": "tsdown",
package/src/Gemini.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Context, Effect, Layer, Option, Redacted, Result, Schema, Stream } from "effect"
2
- import { HttpClient, HttpClientRequest } from "effect/unstable/http"
2
+ import { HttpClient, HttpClientRequest } from "effect/http"
3
3
  import * as AiError from "@effect-uai/core/AiError"
4
4
  import {
5
5
  type CommonRequest,