@effect-uai/core 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -16
- package/dist/{AiError-eLV9t1lU.d.mts → AiError-DvhLIbmd.d.mts} +15 -4
- package/dist/{AiError-eLV9t1lU.d.mts.map → AiError-DvhLIbmd.d.mts.map} +1 -1
- package/dist/{Loop-B54AB1ME.d.mts → Loop-ChpaO-ya.d.mts} +2 -2
- package/dist/{Loop-B54AB1ME.d.mts.map → Loop-ChpaO-ya.d.mts.map} +1 -1
- package/dist/{Toolkit-DAjJ9Tvl.d.mts → Toolkit-tlL0F2YR.d.mts} +2 -2
- package/dist/{Toolkit-DAjJ9Tvl.d.mts.map → Toolkit-tlL0F2YR.d.mts.map} +1 -1
- package/dist/chunker/Chunker.d.mts +1 -1
- package/dist/decision-model/Decision.d.mts +155 -0
- package/dist/decision-model/Decision.d.mts.map +1 -0
- package/dist/decision-model/Decision.mjs +118 -0
- package/dist/decision-model/Decision.mjs.map +1 -0
- package/dist/decision-model/Decision.test.mjs +164 -0
- package/dist/decision-model/Decision.test.mjs.map +1 -0
- package/dist/decision-model/DecisionModel.d.mts +45 -0
- package/dist/decision-model/DecisionModel.d.mts.map +1 -0
- package/dist/decision-model/DecisionModel.mjs +25 -0
- package/dist/decision-model/DecisionModel.mjs.map +1 -0
- package/dist/domain/AiError.d.mts +2 -2
- package/dist/domain/AiError.mjs +9 -2
- package/dist/domain/AiError.mjs.map +1 -1
- package/dist/domain/Realtime.d.mts +616 -0
- package/dist/domain/Realtime.d.mts.map +1 -0
- package/dist/domain/Realtime.mjs +21 -0
- package/dist/domain/Realtime.mjs.map +1 -0
- package/dist/domain/Transcript.d.mts +17 -3
- package/dist/domain/Transcript.d.mts.map +1 -1
- package/dist/domain/Transcript.mjs +30 -1
- package/dist/domain/Transcript.mjs.map +1 -1
- package/dist/domain/Transcript.test.d.mts +1 -0
- package/dist/domain/Transcript.test.mjs +110 -0
- package/dist/domain/Transcript.test.mjs.map +1 -0
- package/dist/embedding-model/EmbeddingModel.d.mts +1 -1
- package/dist/image-generator/ImageGenerator.d.mts +1 -1
- package/dist/index.d.mts +11 -5
- package/dist/index.mjs +9 -3
- package/dist/job/Job.d.mts +1 -1
- package/dist/language-model/LanguageModel.d.mts +2 -2
- package/dist/loop/Loop.d.mts +1 -1
- package/dist/math/Probability.d.mts +21 -0
- package/dist/math/Probability.d.mts.map +1 -0
- package/dist/math/Probability.mjs +31 -0
- package/dist/math/Probability.mjs.map +1 -0
- package/dist/math/Probability.test.d.mts +1 -0
- package/dist/math/Probability.test.mjs +95 -0
- package/dist/math/Probability.test.mjs.map +1 -0
- package/dist/music-generator/MusicGenerator.d.mts +1 -1
- package/dist/realtime/RealtimeSession.d.mts +50 -0
- package/dist/realtime/RealtimeSession.d.mts.map +1 -0
- package/dist/realtime/RealtimeSession.mjs +45 -0
- package/dist/realtime/RealtimeSession.mjs.map +1 -0
- package/dist/realtime/RealtimeSession.test.d.mts +1 -0
- package/dist/realtime/RealtimeSession.test.mjs +95 -0
- package/dist/realtime/RealtimeSession.test.mjs.map +1 -0
- package/dist/reranker/Reranker.d.mts +1 -1
- package/dist/research/DeepResearch.d.mts +1 -1
- package/dist/retry/Retry.d.mts +1 -1
- package/dist/speech-synthesizer/SpeechSynthesizer.d.mts +1 -1
- package/dist/streaming/Settle.d.mts +45 -0
- package/dist/streaming/Settle.d.mts.map +1 -0
- package/dist/streaming/Settle.mjs +95 -0
- package/dist/streaming/Settle.mjs.map +1 -0
- package/dist/streaming/Settle.test.d.mts +1 -0
- package/dist/streaming/Settle.test.mjs +252 -0
- package/dist/streaming/Settle.test.mjs.map +1 -0
- package/dist/streaming/WebSocketSession.d.mts +36 -0
- package/dist/streaming/WebSocketSession.d.mts.map +1 -0
- package/dist/streaming/WebSocketSession.mjs +89 -0
- package/dist/streaming/WebSocketSession.mjs.map +1 -0
- package/dist/streaming/WebSocketSession.test.d.mts +1 -0
- package/dist/streaming/WebSocketSession.test.mjs +51 -0
- package/dist/streaming/WebSocketSession.test.mjs.map +1 -0
- package/dist/testing/FakeWebSocket.d.mts +25 -0
- package/dist/testing/FakeWebSocket.d.mts.map +1 -0
- package/dist/testing/FakeWebSocket.mjs +79 -0
- package/dist/testing/FakeWebSocket.mjs.map +1 -0
- package/dist/testing/MockRealtimeSession.d.mts +30 -0
- package/dist/testing/MockRealtimeSession.d.mts.map +1 -0
- package/dist/testing/MockRealtimeSession.mjs +52 -0
- package/dist/testing/MockRealtimeSession.mjs.map +1 -0
- package/dist/tool/Toolkit.d.mts +1 -1
- package/dist/transcriber/Transcriber.d.mts +1 -1
- package/dist/web-read/WebRead.d.mts +1 -1
- package/dist/web-read/WebReadTool.d.mts +1 -1
- package/dist/web-search/WebSearch.d.mts +1 -1
- package/dist/web-search/WebSearchTool.d.mts +1 -1
- package/package.json +36 -4
- package/src/decision-model/Decision.test.ts +146 -0
- package/src/decision-model/Decision.ts +273 -0
- package/src/decision-model/DecisionModel.ts +53 -0
- package/src/domain/AiError.ts +11 -0
- package/src/domain/Realtime.ts +101 -0
- package/src/domain/Transcript.test.ts +98 -0
- package/src/domain/Transcript.ts +53 -1
- package/src/index.ts +7 -1
- package/src/math/Probability.test.ts +61 -0
- package/src/math/Probability.ts +44 -0
- package/src/realtime/RealtimeSession.test.ts +100 -0
- package/src/realtime/RealtimeSession.ts +77 -0
- package/src/streaming/Settle.test.ts +344 -0
- package/src/streaming/Settle.ts +196 -0
- package/src/streaming/WebSocketSession.test.ts +52 -0
- package/src/streaming/WebSocketSession.ts +132 -0
- package/src/testing/FakeWebSocket.ts +120 -0
- package/src/testing/MockRealtimeSession.ts +92 -0
- package/dist/inbox/Inbox.d.mts +0 -16
- package/dist/inbox/Inbox.d.mts.map +0 -1
- package/dist/inbox/Inbox.mjs +0 -28
- package/dist/inbox/Inbox.mjs.map +0 -1
- package/dist/inbox/Inbox.test.mjs +0 -42
- package/dist/inbox/Inbox.test.mjs.map +0 -1
- package/src/inbox/Inbox.test.ts +0 -52
- package/src/inbox/Inbox.ts +0 -33
- /package/dist/{inbox/Inbox.test.d.mts → decision-model/Decision.test.d.mts} +0 -0
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { n as __exportAll } from "../rolldown-runtime-EAsCxrDo.mjs";
|
|
2
|
+
import { onQuiet } from "../streaming/Settle.mjs";
|
|
3
|
+
import { Effect, Match, Option, Ref, Stream } from "effect";
|
|
2
4
|
//#region src/domain/Transcript.ts
|
|
3
5
|
var Transcript_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
accumulatePartials: () => accumulatePartials,
|
|
4
7
|
isAudioEvent: () => isAudioEvent,
|
|
5
8
|
isError: () => isError,
|
|
6
9
|
isFinal: () => isFinal,
|
|
@@ -16,7 +19,33 @@ const isUtteranceEnded = (e) => e._tag === "utterance-ended";
|
|
|
16
19
|
const isAudioEvent = (e) => e._tag === "audio-event";
|
|
17
20
|
const isMetadata = (e) => e._tag === "metadata";
|
|
18
21
|
const isError = (e) => e._tag === "error";
|
|
22
|
+
const DEFAULT_SILENCE = "700 millis";
|
|
23
|
+
const finalOf = (text) => text.trim().length === 0 ? Option.none() : Option.some({
|
|
24
|
+
_tag: "final",
|
|
25
|
+
text: text.trim()
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Join fragment `partial`s into the running hypothesis and commit it as a
|
|
29
|
+
* `final` after `silence`. For providers that stream token-sized deltas
|
|
30
|
+
* (OpenAI Realtime) or never segment; piping one that already accumulates
|
|
31
|
+
* repeats its text.
|
|
32
|
+
*
|
|
33
|
+
* Partials are forwarded as they arrive; only the synthetic `final` waits.
|
|
34
|
+
* A real `final` resets the accumulator, and the stream end flushes it.
|
|
35
|
+
*/
|
|
36
|
+
const accumulatePartials = (options) => (self) => Stream.unwrap(Effect.gen(function* () {
|
|
37
|
+
const acc = yield* Ref.make("");
|
|
38
|
+
const flush = Effect.map(Ref.getAndSet(acc, ""), finalOf);
|
|
39
|
+
const rewrite = (event) => Match.value(event).pipe(Match.when({ _tag: "partial" }, (e) => Effect.map(Ref.updateAndGet(acc, (text) => text + e.text), (text) => ({
|
|
40
|
+
...e,
|
|
41
|
+
text: text.trim()
|
|
42
|
+
}))), Match.when({ _tag: "final" }, (e) => Effect.as(Ref.set(acc, ""), e)), Match.orElse((e) => Effect.succeed(e)));
|
|
43
|
+
return self.pipe(Stream.mapEffect(rewrite), onQuiet(options?.silence ?? DEFAULT_SILENCE, flush), Stream.concat(Stream.unwrap(Effect.map(flush, Option.match({
|
|
44
|
+
onNone: () => Stream.empty,
|
|
45
|
+
onSome: Stream.make
|
|
46
|
+
})))));
|
|
47
|
+
}));
|
|
19
48
|
//#endregion
|
|
20
|
-
export { isAudioEvent, isError, isFinal, isMetadata, isPartial, isSpeechStarted, isUtteranceEnded, Transcript_exports as t };
|
|
49
|
+
export { accumulatePartials, isAudioEvent, isError, isFinal, isMetadata, isPartial, isSpeechStarted, isUtteranceEnded, Transcript_exports as t };
|
|
21
50
|
|
|
22
51
|
//# sourceMappingURL=Transcript.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Transcript.mjs","names":[],"sources":["../../src/domain/Transcript.ts"],"sourcesContent":["import type
|
|
1
|
+
{"version":3,"file":"Transcript.mjs","names":["Settle.onQuiet"],"sources":["../../src/domain/Transcript.ts"],"sourcesContent":["import { type Duration, Effect, Match, Option, Ref, Stream } from \"effect\"\nimport * as Settle from \"../streaming/Settle.js\"\n\n/**\n * Per-word timing + metadata. `confidence` and `speakerId` are optional\n * because providers vary widely in what they emit and when (some only on\n * final, some only with diarization enabled, some not at all).\n *\n * `startSeconds` / `endSeconds` stay raw `number` offsets (not `Duration`)\n * — they're positions in the audio, not durations.\n */\nexport type WordTimestamp = {\n readonly text: string\n readonly startSeconds: number\n readonly endSeconds: number\n readonly confidence?: number\n readonly speakerId?: string\n readonly languageCode?: string\n}\n\n/**\n * Sync STT result. `raw` preserves the provider-specific response for\n * consumers that need fields the common shape doesn't expose\n * (alternatives, segments, NBest, audio events, etc.).\n */\nexport type TranscriptResult = {\n readonly text: string\n readonly languageCode?: string\n /** Total audio duration. (Word offsets stay raw seconds on `WordTimestamp`.) */\n readonly duration?: Duration.Duration\n readonly words?: ReadonlyArray<WordTimestamp>\n readonly raw?: unknown\n}\n\n/**\n * Streaming STT event union. Collapses every provider's vocabulary into\n * a small set; provider-specific shapes survive on `metadata.raw`.\n *\n * - `partial`: interim hypothesis. `stability` is Google-only.\n * - `final`: committed transcript for the current utterance / segment.\n * - `speech-started` / `utterance-ended`: VAD-derived boundaries. Not\n * all providers emit them (OpenAI Realtime, Google with\n * `voice_activity_events`, Deepgram with `vad_events`, AssemblyAI).\n * - `audio-event`: non-speech label (`(laughter)`, `(music)`) — ElevenLabs only.\n * - `metadata`: opaque server-side bookkeeping (request_id, model info).\n * - `error`: non-fatal provider error mid-stream. Fatal errors surface\n * on the `Stream`'s error channel as `AiError.AiError`.\n */\nexport type TranscriptEvent =\n | {\n readonly _tag: \"partial\"\n readonly text: string\n readonly words?: ReadonlyArray<WordTimestamp>\n readonly stability?: number\n }\n | {\n readonly _tag: \"final\"\n readonly text: string\n readonly words?: ReadonlyArray<WordTimestamp>\n readonly languageCode?: string\n }\n | { readonly _tag: \"speech-started\"; readonly atSeconds: number }\n | { readonly _tag: \"utterance-ended\"; readonly atSeconds: number }\n | {\n readonly _tag: \"audio-event\"\n readonly label: string\n readonly startSeconds: number\n readonly endSeconds: number\n }\n | { readonly _tag: \"metadata\"; readonly raw: unknown }\n | { readonly _tag: \"error\"; readonly code?: string; readonly message: string }\n\nexport const isPartial = (e: TranscriptEvent): e is Extract<TranscriptEvent, { _tag: \"partial\" }> =>\n e._tag === \"partial\"\nexport const isFinal = (e: TranscriptEvent): e is Extract<TranscriptEvent, { _tag: \"final\" }> =>\n e._tag === \"final\"\nexport const isSpeechStarted = (\n e: TranscriptEvent,\n): e is Extract<TranscriptEvent, { _tag: \"speech-started\" }> => e._tag === \"speech-started\"\nexport const isUtteranceEnded = (\n e: TranscriptEvent,\n): e is Extract<TranscriptEvent, { _tag: \"utterance-ended\" }> => e._tag === \"utterance-ended\"\nexport const isAudioEvent = (\n e: TranscriptEvent,\n): e is Extract<TranscriptEvent, { _tag: \"audio-event\" }> => e._tag === \"audio-event\"\nexport const isMetadata = (\n e: TranscriptEvent,\n): e is Extract<TranscriptEvent, { _tag: \"metadata\" }> => e._tag === \"metadata\"\nexport const isError = (e: TranscriptEvent): e is Extract<TranscriptEvent, { _tag: \"error\" }> =>\n e._tag === \"error\"\n\nexport type AccumulatePartialsOptions = {\n /** Silence after the last `partial` before the text so far is committed. */\n readonly silence?: Duration.Input\n}\n\nconst DEFAULT_SILENCE = \"700 millis\"\n\nconst finalOf = (text: string): Option.Option<TranscriptEvent> =>\n text.trim().length === 0 ? Option.none() : Option.some({ _tag: \"final\", text: text.trim() })\n\n/**\n * Join fragment `partial`s into the running hypothesis and commit it as a\n * `final` after `silence`. For providers that stream token-sized deltas\n * (OpenAI Realtime) or never segment; piping one that already accumulates\n * repeats its text.\n *\n * Partials are forwarded as they arrive; only the synthetic `final` waits.\n * A real `final` resets the accumulator, and the stream end flushes it.\n */\nexport const accumulatePartials =\n (options?: AccumulatePartialsOptions) =>\n <E, R>(self: Stream.Stream<TranscriptEvent, E, R>): Stream.Stream<TranscriptEvent, E, R> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const acc = yield* Ref.make(\"\")\n const flush = Effect.map(Ref.getAndSet(acc, \"\"), finalOf)\n\n const rewrite = (event: TranscriptEvent): Effect.Effect<TranscriptEvent> =>\n Match.value(event).pipe(\n Match.when({ _tag: \"partial\" }, (e) =>\n Effect.map(\n Ref.updateAndGet(acc, (text) => text + e.text),\n (text): TranscriptEvent => ({ ...e, text: text.trim() }),\n ),\n ),\n Match.when({ _tag: \"final\" }, (e) => Effect.as(Ref.set(acc, \"\"), e as TranscriptEvent)),\n Match.orElse((e) => Effect.succeed(e as TranscriptEvent)),\n )\n\n return self.pipe(\n Stream.mapEffect(rewrite),\n Settle.onQuiet(options?.silence ?? DEFAULT_SILENCE, flush),\n Stream.concat(\n Stream.unwrap(\n Effect.map(flush, Option.match({ onNone: () => Stream.empty, onSome: Stream.make })),\n ),\n ),\n )\n }),\n )\n"],"mappings":";;;;;;;;;;;;;;AAwEA,MAAa,aAAa,MACxB,EAAE,SAAS;AACb,MAAa,WAAW,MACtB,EAAE,SAAS;AACb,MAAa,mBACX,MAC8D,EAAE,SAAS;AAC3E,MAAa,oBACX,MAC+D,EAAE,SAAS;AAC5E,MAAa,gBACX,MAC2D,EAAE,SAAS;AACxE,MAAa,cACX,MACwD,EAAE,SAAS;AACrE,MAAa,WAAW,MACtB,EAAE,SAAS;AAOb,MAAM,kBAAkB;AAExB,MAAM,WAAW,SACf,KAAK,KAAK,CAAC,CAAC,WAAW,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK;CAAE,MAAM;CAAS,MAAM,KAAK,KAAK;AAAE,CAAC;;;;;;;;;;AAW7F,MAAa,sBACV,aACM,SACL,OAAO,OACL,OAAO,IAAI,aAAa;CACtB,MAAM,MAAM,OAAO,IAAI,KAAK,EAAE;CAC9B,MAAM,QAAQ,OAAO,IAAI,IAAI,UAAU,KAAK,EAAE,GAAG,OAAO;CAExD,MAAM,WAAW,UACf,MAAM,MAAM,KAAK,CAAC,CAAC,KACjB,MAAM,KAAK,EAAE,MAAM,UAAU,IAAI,MAC/B,OAAO,IACL,IAAI,aAAa,MAAM,SAAS,OAAO,EAAE,IAAI,IAC5C,UAA2B;EAAE,GAAG;EAAG,MAAM,KAAK,KAAK;CAAE,EACxD,CACF,GACA,MAAM,KAAK,EAAE,MAAM,QAAQ,IAAI,MAAM,OAAO,GAAG,IAAI,IAAI,KAAK,EAAE,GAAG,CAAoB,CAAC,GACtF,MAAM,QAAQ,MAAM,OAAO,QAAQ,CAAoB,CAAC,CAC1D;CAEF,OAAO,KAAK,KACV,OAAO,UAAU,OAAO,GACxBA,QAAe,SAAS,WAAW,iBAAiB,KAAK,GACzD,OAAO,OACL,OAAO,OACL,OAAO,IAAI,OAAO,OAAO,MAAM;EAAE,cAAc,OAAO;EAAO,QAAQ,OAAO;CAAK,CAAC,CAAC,CACrF,CACF,CACF;AACF,CAAC,CACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { accumulatePartials } from "./Transcript.mjs";
|
|
2
|
+
import { o as describe } from "../utils-CiH_DjFW.mjs";
|
|
3
|
+
import { n as globalExpect } from "../test.DNmyFkvJ-YPzDR0Co.mjs";
|
|
4
|
+
import { t as it } from "../dist-nohcnkD6.mjs";
|
|
5
|
+
import { Effect, Queue, Ref, Stream } from "effect";
|
|
6
|
+
import { TestClock } from "effect/testing";
|
|
7
|
+
//#region src/domain/Transcript.test.ts
|
|
8
|
+
const collecting = (stream) => Effect.gen(function* () {
|
|
9
|
+
const seen = yield* Ref.make([]);
|
|
10
|
+
yield* Effect.forkChild(Stream.runForEach(stream, (e) => Ref.update(seen, (xs) => [...xs, e])));
|
|
11
|
+
return seen;
|
|
12
|
+
});
|
|
13
|
+
/** Deltas arriving faster than any settle window. */
|
|
14
|
+
const speak = (queue, tokens) => Effect.forEach(tokens, (text) => Effect.andThen(Queue.offer(queue, {
|
|
15
|
+
_tag: "partial",
|
|
16
|
+
text
|
|
17
|
+
}), TestClock.adjust("100 millis")), { discard: true });
|
|
18
|
+
const opened = Effect.gen(function* () {
|
|
19
|
+
const queue = yield* Queue.unbounded();
|
|
20
|
+
return {
|
|
21
|
+
queue,
|
|
22
|
+
seen: yield* collecting(Stream.fromQueue(queue).pipe(accumulatePartials({ silence: "1 second" })))
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
describe("accumulatePartials", () => {
|
|
26
|
+
it.effect("joins deltas into the running hypothesis, forwarding each as it arrives", () => Effect.gen(function* () {
|
|
27
|
+
const { queue, seen } = yield* opened;
|
|
28
|
+
yield* speak(queue, [
|
|
29
|
+
" Hi",
|
|
30
|
+
",",
|
|
31
|
+
" how"
|
|
32
|
+
]);
|
|
33
|
+
globalExpect(yield* Ref.get(seen)).toEqual([
|
|
34
|
+
{
|
|
35
|
+
_tag: "partial",
|
|
36
|
+
text: "Hi"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
_tag: "partial",
|
|
40
|
+
text: "Hi,"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
_tag: "partial",
|
|
44
|
+
text: "Hi, how"
|
|
45
|
+
}
|
|
46
|
+
]);
|
|
47
|
+
}));
|
|
48
|
+
it.effect("commits on silence and starts the next utterance from empty", () => Effect.gen(function* () {
|
|
49
|
+
const { queue, seen } = yield* opened;
|
|
50
|
+
yield* speak(queue, [" Hi", " there"]);
|
|
51
|
+
yield* TestClock.adjust("3 seconds");
|
|
52
|
+
yield* speak(queue, [" Bye"]);
|
|
53
|
+
yield* TestClock.adjust("3 seconds");
|
|
54
|
+
globalExpect(yield* Ref.get(seen)).toEqual([
|
|
55
|
+
{
|
|
56
|
+
_tag: "partial",
|
|
57
|
+
text: "Hi"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
_tag: "partial",
|
|
61
|
+
text: "Hi there"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
_tag: "final",
|
|
65
|
+
text: "Hi there"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
_tag: "partial",
|
|
69
|
+
text: "Bye"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
_tag: "final",
|
|
73
|
+
text: "Bye"
|
|
74
|
+
}
|
|
75
|
+
]);
|
|
76
|
+
}));
|
|
77
|
+
it.effect("a provider's own final resets the accumulator, so silence adds no duplicate", () => Effect.gen(function* () {
|
|
78
|
+
const { queue, seen } = yield* opened;
|
|
79
|
+
yield* speak(queue, [" Hi"]);
|
|
80
|
+
yield* Queue.offer(queue, {
|
|
81
|
+
_tag: "final",
|
|
82
|
+
text: "Hi."
|
|
83
|
+
});
|
|
84
|
+
yield* TestClock.adjust("3 seconds");
|
|
85
|
+
globalExpect(yield* Ref.get(seen)).toEqual([{
|
|
86
|
+
_tag: "partial",
|
|
87
|
+
text: "Hi"
|
|
88
|
+
}, {
|
|
89
|
+
_tag: "final",
|
|
90
|
+
text: "Hi."
|
|
91
|
+
}]);
|
|
92
|
+
}));
|
|
93
|
+
it.effect("commits the pending text when the stream ends mid-utterance", () => Effect.gen(function* () {
|
|
94
|
+
const { queue, seen } = yield* opened;
|
|
95
|
+
yield* speak(queue, [" Half a sen"]);
|
|
96
|
+
yield* Queue.end(queue);
|
|
97
|
+
yield* TestClock.adjust("10 millis");
|
|
98
|
+
globalExpect(yield* Ref.get(seen)).toEqual([{
|
|
99
|
+
_tag: "partial",
|
|
100
|
+
text: "Half a sen"
|
|
101
|
+
}, {
|
|
102
|
+
_tag: "final",
|
|
103
|
+
text: "Half a sen"
|
|
104
|
+
}]);
|
|
105
|
+
}));
|
|
106
|
+
});
|
|
107
|
+
//#endregion
|
|
108
|
+
export {};
|
|
109
|
+
|
|
110
|
+
//# sourceMappingURL=Transcript.test.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Transcript.test.mjs","names":[],"sources":["../../src/domain/Transcript.test.ts"],"sourcesContent":["import { describe, it } from \"@effect/vitest\"\nimport { Cause, Effect, Queue, Ref, Stream } from \"effect\"\nimport { TestClock } from \"effect/testing\"\nimport { expect } from \"vitest\"\nimport { accumulatePartials, type TranscriptEvent } from \"./Transcript.js\"\n\nconst collecting = (stream: Stream.Stream<TranscriptEvent, never>) =>\n Effect.gen(function* () {\n const seen = yield* Ref.make<ReadonlyArray<TranscriptEvent>>([])\n yield* Effect.forkChild(Stream.runForEach(stream, (e) => Ref.update(seen, (xs) => [...xs, e])))\n return seen\n })\n\n/** Deltas arriving faster than any settle window. */\nconst speak = (\n queue: Queue.Queue<TranscriptEvent, Cause.Done>,\n tokens: ReadonlyArray<string>,\n): Effect.Effect<void> =>\n Effect.forEach(\n tokens,\n (text) =>\n Effect.andThen(Queue.offer(queue, { _tag: \"partial\", text }), TestClock.adjust(\"100 millis\")),\n { discard: true },\n )\n\nconst opened = Effect.gen(function* () {\n const queue = yield* Queue.unbounded<TranscriptEvent, Cause.Done>()\n const seen = yield* collecting(\n Stream.fromQueue(queue).pipe(accumulatePartials({ silence: \"1 second\" })),\n )\n return { queue, seen }\n})\n\ndescribe(\"accumulatePartials\", () => {\n it.effect(\"joins deltas into the running hypothesis, forwarding each as it arrives\", () =>\n Effect.gen(function* () {\n const { queue, seen } = yield* opened\n\n yield* speak(queue, [\" Hi\", \",\", \" how\"])\n\n // Three in, three out, each the whole sentence so far, none delayed.\n expect(yield* Ref.get(seen)).toEqual([\n { _tag: \"partial\", text: \"Hi\" },\n { _tag: \"partial\", text: \"Hi,\" },\n { _tag: \"partial\", text: \"Hi, how\" },\n ])\n }),\n )\n\n it.effect(\"commits on silence and starts the next utterance from empty\", () =>\n Effect.gen(function* () {\n const { queue, seen } = yield* opened\n\n yield* speak(queue, [\" Hi\", \" there\"])\n yield* TestClock.adjust(\"3 seconds\")\n yield* speak(queue, [\" Bye\"])\n yield* TestClock.adjust(\"3 seconds\")\n\n expect(yield* Ref.get(seen)).toEqual([\n { _tag: \"partial\", text: \"Hi\" },\n { _tag: \"partial\", text: \"Hi there\" },\n { _tag: \"final\", text: \"Hi there\" },\n { _tag: \"partial\", text: \"Bye\" },\n { _tag: \"final\", text: \"Bye\" },\n ])\n }),\n )\n\n it.effect(\"a provider's own final resets the accumulator, so silence adds no duplicate\", () =>\n Effect.gen(function* () {\n const { queue, seen } = yield* opened\n\n yield* speak(queue, [\" Hi\"])\n yield* Queue.offer(queue, { _tag: \"final\", text: \"Hi.\" })\n yield* TestClock.adjust(\"3 seconds\")\n\n expect(yield* Ref.get(seen)).toEqual([\n { _tag: \"partial\", text: \"Hi\" },\n { _tag: \"final\", text: \"Hi.\" },\n ])\n }),\n )\n\n it.effect(\"commits the pending text when the stream ends mid-utterance\", () =>\n Effect.gen(function* () {\n const { queue, seen } = yield* opened\n\n yield* speak(queue, [\" Half a sen\"])\n yield* Queue.end(queue)\n yield* TestClock.adjust(\"10 millis\")\n\n expect(yield* Ref.get(seen)).toEqual([\n { _tag: \"partial\", text: \"Half a sen\" },\n { _tag: \"final\", text: \"Half a sen\" },\n ])\n }),\n )\n})\n"],"mappings":";;;;;;;AAMA,MAAM,cAAc,WAClB,OAAO,IAAI,aAAa;CACtB,MAAM,OAAO,OAAO,IAAI,KAAqC,CAAC,CAAC;CAC/D,OAAO,OAAO,UAAU,OAAO,WAAW,SAAS,MAAM,IAAI,OAAO,OAAO,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;CAC9F,OAAO;AACT,CAAC;;AAGH,MAAM,SACJ,OACA,WAEA,OAAO,QACL,SACC,SACC,OAAO,QAAQ,MAAM,MAAM,OAAO;CAAE,MAAM;CAAW;AAAK,CAAC,GAAG,UAAU,OAAO,YAAY,CAAC,GAC9F,EAAE,SAAS,KAAK,CAClB;AAEF,MAAM,SAAS,OAAO,IAAI,aAAa;CACrC,MAAM,QAAQ,OAAO,MAAM,UAAuC;CAIlE,OAAO;EAAE;EAAO,MAAA,OAHI,WAClB,OAAO,UAAU,KAAK,CAAC,CAAC,KAAK,mBAAmB,EAAE,SAAS,WAAW,CAAC,CAAC,CAC1E;CACqB;AACvB,CAAC;AAED,SAAS,4BAA4B;CACnC,GAAG,OAAO,iFACR,OAAO,IAAI,aAAa;EACtB,MAAM,EAAE,OAAO,SAAS,OAAO;EAE/B,OAAO,MAAM,OAAO;GAAC;GAAO;GAAK;EAAM,CAAC;EAGxC,aAAO,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ;GACnC;IAAE,MAAM;IAAW,MAAM;GAAK;GAC9B;IAAE,MAAM;IAAW,MAAM;GAAM;GAC/B;IAAE,MAAM;IAAW,MAAM;GAAU;EACrC,CAAC;CACH,CAAC,CACH;CAEA,GAAG,OAAO,qEACR,OAAO,IAAI,aAAa;EACtB,MAAM,EAAE,OAAO,SAAS,OAAO;EAE/B,OAAO,MAAM,OAAO,CAAC,OAAO,QAAQ,CAAC;EACrC,OAAO,UAAU,OAAO,WAAW;EACnC,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC;EAC5B,OAAO,UAAU,OAAO,WAAW;EAEnC,aAAO,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ;GACnC;IAAE,MAAM;IAAW,MAAM;GAAK;GAC9B;IAAE,MAAM;IAAW,MAAM;GAAW;GACpC;IAAE,MAAM;IAAS,MAAM;GAAW;GAClC;IAAE,MAAM;IAAW,MAAM;GAAM;GAC/B;IAAE,MAAM;IAAS,MAAM;GAAM;EAC/B,CAAC;CACH,CAAC,CACH;CAEA,GAAG,OAAO,qFACR,OAAO,IAAI,aAAa;EACtB,MAAM,EAAE,OAAO,SAAS,OAAO;EAE/B,OAAO,MAAM,OAAO,CAAC,KAAK,CAAC;EAC3B,OAAO,MAAM,MAAM,OAAO;GAAE,MAAM;GAAS,MAAM;EAAM,CAAC;EACxD,OAAO,UAAU,OAAO,WAAW;EAEnC,aAAO,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CACnC;GAAE,MAAM;GAAW,MAAM;EAAK,GAC9B;GAAE,MAAM;GAAS,MAAM;EAAM,CAC/B,CAAC;CACH,CAAC,CACH;CAEA,GAAG,OAAO,qEACR,OAAO,IAAI,aAAa;EACtB,MAAM,EAAE,OAAO,SAAS,OAAO;EAE/B,OAAO,MAAM,OAAO,CAAC,aAAa,CAAC;EACnC,OAAO,MAAM,IAAI,KAAK;EACtB,OAAO,UAAU,OAAO,WAAW;EAEnC,aAAO,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CACnC;GAAE,MAAM;GAAW,MAAM;EAAa,GACtC;GAAE,MAAM;GAAS,MAAM;EAAa,CACtC,CAAC;CACH,CAAC,CACH;AACF,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as AiError } from "../AiError-
|
|
1
|
+
import { t as AiError } from "../AiError-DvhLIbmd.mjs";
|
|
2
2
|
import { EmbedInput, EmbeddingFor, ResponseEncoding, Usage } from "./Embedding.mjs";
|
|
3
3
|
import { Context, Effect } from "effect";
|
|
4
4
|
declare namespace EmbeddingModel_d_exports {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as AspectRatio } from "../Media-BbX7BAaO.mjs";
|
|
2
2
|
import { a as ImageResolution, l as ProviderData, o as ImageSource, t as GeneratedImage } from "../Image-Cv6iBLTy.mjs";
|
|
3
|
-
import { t as AiError } from "../AiError-
|
|
3
|
+
import { t as AiError } from "../AiError-DvhLIbmd.mjs";
|
|
4
4
|
import { Context, Data, Effect, Stream } from "effect";
|
|
5
5
|
declare namespace ImageGenerator_d_exports {
|
|
6
6
|
export { AspectRatio, CommonImageEditRequest, CommonImageGenerateRequest, CommonStreamImageEditRequest, CommonStreamImageRequest, GeneratedImage, ImageGenerator, ImageGeneratorService, ImageResolution, ImageResponse, ImageStreamEvent, ImageStreaming, ImageUsage, ProviderData, edit, generate, isComplete, isPartialImage, streamEdit, streamGeneration };
|
package/dist/index.d.mts
CHANGED
|
@@ -6,11 +6,14 @@ import { u as Items_d_exports } from "./Items-C7MyrYPX.mjs";
|
|
|
6
6
|
import { _ as Tool_d_exports } from "./Tool-BF78QWtn.mjs";
|
|
7
7
|
import { t as BrowserTool_d_exports } from "./browser/BrowserTool.mjs";
|
|
8
8
|
import { t as Capabilities_d_exports } from "./capabilities/Capabilities.mjs";
|
|
9
|
-
import { n as AiError_d_exports } from "./AiError-
|
|
9
|
+
import { n as AiError_d_exports } from "./AiError-DvhLIbmd.mjs";
|
|
10
10
|
import { t as Chunker_d_exports } from "./chunker/Chunker.mjs";
|
|
11
|
+
import { t as Decision_d_exports } from "./decision-model/Decision.mjs";
|
|
12
|
+
import { t as DecisionModel_d_exports } from "./decision-model/DecisionModel.mjs";
|
|
11
13
|
import { o as Audio_d_exports } from "./Audio-_nGR4V0X.mjs";
|
|
12
14
|
import { t as Citation_d_exports } from "./domain/Citation.mjs";
|
|
13
15
|
import { t as Music_d_exports } from "./domain/Music.mjs";
|
|
16
|
+
import { t as Realtime_d_exports } from "./domain/Realtime.mjs";
|
|
14
17
|
import { t as Job_d_exports } from "./job/Job.mjs";
|
|
15
18
|
import { a as StructuredFormat_d_exports } from "./StructuredFormat-BlZhyOsi.mjs";
|
|
16
19
|
import { t as Turn_d_exports } from "./domain/Turn.mjs";
|
|
@@ -19,12 +22,12 @@ import { t as Transcript_d_exports } from "./domain/Transcript.mjs";
|
|
|
19
22
|
import { t as Embedding_d_exports } from "./embedding-model/Embedding.mjs";
|
|
20
23
|
import { t as EmbeddingModel_d_exports } from "./embedding-model/EmbeddingModel.mjs";
|
|
21
24
|
import { t as ImageGenerator_d_exports } from "./image-generator/ImageGenerator.mjs";
|
|
22
|
-
import { t as Inbox_d_exports } from "./inbox/Inbox.mjs";
|
|
23
25
|
import { t as DeepResearch_d_exports } from "./research/DeepResearch.mjs";
|
|
24
|
-
import { t as
|
|
26
|
+
import { t as RealtimeSession_d_exports } from "./realtime/RealtimeSession.mjs";
|
|
27
|
+
import { t as Loop_d_exports } from "./Loop-ChpaO-ya.mjs";
|
|
25
28
|
import { n as ToolResult_d_exports } from "./ToolResult-BsYQRjmW.mjs";
|
|
26
29
|
import { n as ToolEvent_d_exports } from "./ToolEvent-Di4a723B.mjs";
|
|
27
|
-
import { l as Toolkit_d_exports } from "./Toolkit-
|
|
30
|
+
import { l as Toolkit_d_exports } from "./Toolkit-tlL0F2YR.mjs";
|
|
28
31
|
import { t as LanguageModel_d_exports } from "./language-model/LanguageModel.mjs";
|
|
29
32
|
import { r as MessengerError_d_exports } from "./MessengerError-CeK6VAcu.mjs";
|
|
30
33
|
import { t as Messenger_d_exports } from "./messenger/Messenger.mjs";
|
|
@@ -42,8 +45,11 @@ import { t as WebRead_d_exports } from "./web-read/WebRead.mjs";
|
|
|
42
45
|
import { t as WebReadTool_d_exports } from "./web-read/WebReadTool.mjs";
|
|
43
46
|
import { t as WebSearch_d_exports } from "./web-search/WebSearch.mjs";
|
|
44
47
|
import { t as WebSearchTool_d_exports } from "./web-search/WebSearchTool.mjs";
|
|
48
|
+
import { t as Probability_d_exports } from "./math/Probability.mjs";
|
|
45
49
|
import { t as Vector_d_exports } from "./math/Vector.mjs";
|
|
46
50
|
import { t as Tokenizer_d_exports } from "./tokenizer/Tokenizer.mjs";
|
|
51
|
+
import { t as Settle_d_exports } from "./streaming/Settle.mjs";
|
|
52
|
+
import { t as WebSocketSession_d_exports } from "./streaming/WebSocketSession.mjs";
|
|
47
53
|
import { t as Retry_d_exports } from "./retry/Retry.mjs";
|
|
48
54
|
import { t as Approval_d_exports } from "./tool/Approval.mjs";
|
|
49
55
|
import { t as HistoryCheck_d_exports } from "./tool/HistoryCheck.mjs";
|
|
@@ -53,4 +59,4 @@ import { t as Multipart_d_exports } from "./streaming/Multipart.mjs";
|
|
|
53
59
|
import { t as SSE_d_exports } from "./streaming/SSE.mjs";
|
|
54
60
|
import { t as Metrics_d_exports } from "./observability/Metrics.mjs";
|
|
55
61
|
import { t as Telemetry_d_exports } from "./observability/Telemetry.mjs";
|
|
56
|
-
export { AiError_d_exports as AiError, Approval_d_exports as Approval, Audio_d_exports as Audio, Browser_d_exports as Browser, BrowserError_d_exports as BrowserError, BrowserTool_d_exports as BrowserTool, Capabilities_d_exports as Capabilities, Chunker_d_exports as Chunker, Citation_d_exports as Citation, DeepResearch_d_exports as DeepResearch, Embedding_d_exports as Embedding, EmbeddingModel_d_exports as EmbeddingModel, HistoryCheck_d_exports as HistoryCheck, Image_d_exports as Image, ImageGenerator_d_exports as ImageGenerator,
|
|
62
|
+
export { AiError_d_exports as AiError, Approval_d_exports as Approval, Audio_d_exports as Audio, Browser_d_exports as Browser, BrowserError_d_exports as BrowserError, BrowserTool_d_exports as BrowserTool, Capabilities_d_exports as Capabilities, Chunker_d_exports as Chunker, Citation_d_exports as Citation, Decision_d_exports as Decision, DecisionModel_d_exports as DecisionModel, DeepResearch_d_exports as DeepResearch, Embedding_d_exports as Embedding, EmbeddingModel_d_exports as EmbeddingModel, HistoryCheck_d_exports as HistoryCheck, Image_d_exports as Image, ImageGenerator_d_exports as ImageGenerator, Items_d_exports as Items, JSONL_d_exports as JSONL, Job_d_exports as Job, LanguageModel_d_exports as LanguageModel, Lines_d_exports as Lines, Loop_d_exports as Loop, Media_d_exports as Media, Memory_d_exports as Memory, Messenger_d_exports as Messenger, MessengerAdapter_d_exports as MessengerAdapter, MessengerError_d_exports as MessengerError, Metrics_d_exports as Metrics, Multipart_d_exports as Multipart, Music_d_exports as Music, MusicGenerator_d_exports as MusicGenerator, Probability_d_exports as Probability, Realtime_d_exports as Realtime, RealtimeSession_d_exports as RealtimeSession, Reranker_d_exports as Reranker, Research_d_exports as Research, Retry_d_exports as Retry, SSE_d_exports as SSE, Sandbox_d_exports as Sandbox, SandboxError_d_exports as SandboxError, SandboxImage_d_exports as SandboxImage, SandboxNetwork_d_exports as SandboxNetwork, Settle_d_exports as Settle, SpeechSynthesizer_d_exports as SpeechSynthesizer, StructuredFormat_d_exports as StructuredFormat, Telemetry_d_exports as Telemetry, Tokenizer_d_exports as Tokenizer, Tool_d_exports as Tool, ToolEvent_d_exports as ToolEvent, ToolResult_d_exports as ToolResult, Toolkit_d_exports as Toolkit, Transcriber_d_exports as Transcriber, Transcript_d_exports as Transcript, Turn_d_exports as Turn, Vector_d_exports as Vector, WebRead_d_exports as WebRead, WebReadTool_d_exports as WebReadTool, WebSearch_d_exports as WebSearch, WebSearchTool_d_exports as WebSearchTool, WebSocketSession_d_exports as WebSocketSession };
|
package/dist/index.mjs
CHANGED
|
@@ -16,10 +16,16 @@ import { t as BrowserTool_exports } from "./browser/BrowserTool.mjs";
|
|
|
16
16
|
import { t as Capabilities_exports } from "./capabilities/Capabilities.mjs";
|
|
17
17
|
import { t as Chunker_exports } from "./chunker/Chunker.mjs";
|
|
18
18
|
import { t as Citation_exports } from "./domain/Citation.mjs";
|
|
19
|
+
import { t as Probability_exports } from "./math/Probability.mjs";
|
|
20
|
+
import { t as Decision_exports } from "./decision-model/Decision.mjs";
|
|
21
|
+
import { t as DecisionModel_exports } from "./decision-model/DecisionModel.mjs";
|
|
19
22
|
import { t as Job_exports } from "./job/Job.mjs";
|
|
20
23
|
import { t as DeepResearch_exports } from "./research/DeepResearch.mjs";
|
|
21
24
|
import { t as Music_exports } from "./domain/Music.mjs";
|
|
22
25
|
import { t as Research_exports } from "./domain/Research.mjs";
|
|
26
|
+
import { t as Realtime_exports } from "./domain/Realtime.mjs";
|
|
27
|
+
import { t as RealtimeSession_exports } from "./realtime/RealtimeSession.mjs";
|
|
28
|
+
import { t as Settle_exports } from "./streaming/Settle.mjs";
|
|
23
29
|
import { t as Transcript_exports } from "./domain/Transcript.mjs";
|
|
24
30
|
import { t as Embedding_exports } from "./embedding-model/Embedding.mjs";
|
|
25
31
|
import { t as EmbeddingModel_exports } from "./embedding-model/EmbeddingModel.mjs";
|
|
@@ -43,14 +49,14 @@ import { t as WebSearch_exports } from "./web-search/WebSearch.mjs";
|
|
|
43
49
|
import { t as WebSearchTool_exports } from "./web-search/WebSearchTool.mjs";
|
|
44
50
|
import { t as Vector_exports } from "./math/Vector.mjs";
|
|
45
51
|
import { t as Tokenizer_exports } from "./tokenizer/Tokenizer.mjs";
|
|
46
|
-
import { t as
|
|
52
|
+
import { t as JSONL_exports } from "./streaming/JSONL.mjs";
|
|
53
|
+
import { t as WebSocketSession_exports } from "./streaming/WebSocketSession.mjs";
|
|
47
54
|
import { t as Retry_exports } from "./retry/Retry.mjs";
|
|
48
55
|
import { t as Approval_exports } from "./tool/Approval.mjs";
|
|
49
56
|
import { t as HistoryCheck_exports } from "./tool/HistoryCheck.mjs";
|
|
50
|
-
import { t as JSONL_exports } from "./streaming/JSONL.mjs";
|
|
51
57
|
import { t as Lines_exports } from "./streaming/Lines.mjs";
|
|
52
58
|
import { t as Multipart_exports } from "./streaming/Multipart.mjs";
|
|
53
59
|
import { t as SSE_exports } from "./streaming/SSE.mjs";
|
|
54
60
|
import { t as Metrics_exports } from "./observability/Metrics.mjs";
|
|
55
61
|
import { t as Telemetry_exports } from "./observability/Telemetry.mjs";
|
|
56
|
-
export { AiError_exports as AiError, Approval_exports as Approval, Audio_exports as Audio, Browser_exports as Browser, BrowserError_exports as BrowserError, BrowserTool_exports as BrowserTool, Capabilities_exports as Capabilities, Chunker_exports as Chunker, Citation_exports as Citation, DeepResearch_exports as DeepResearch, Embedding_exports as Embedding, EmbeddingModel_exports as EmbeddingModel, HistoryCheck_exports as HistoryCheck, Image_exports as Image, ImageGenerator_exports as ImageGenerator,
|
|
62
|
+
export { AiError_exports as AiError, Approval_exports as Approval, Audio_exports as Audio, Browser_exports as Browser, BrowserError_exports as BrowserError, BrowserTool_exports as BrowserTool, Capabilities_exports as Capabilities, Chunker_exports as Chunker, Citation_exports as Citation, Decision_exports as Decision, DecisionModel_exports as DecisionModel, DeepResearch_exports as DeepResearch, Embedding_exports as Embedding, EmbeddingModel_exports as EmbeddingModel, HistoryCheck_exports as HistoryCheck, Image_exports as Image, ImageGenerator_exports as ImageGenerator, Items_exports as Items, JSONL_exports as JSONL, Job_exports as Job, LanguageModel_exports as LanguageModel, Lines_exports as Lines, Loop_exports as Loop, Media_exports as Media, Memory_exports as Memory, Messenger_exports as Messenger, MessengerAdapter_exports as MessengerAdapter, MessengerError_exports as MessengerError, Metrics_exports as Metrics, Multipart_exports as Multipart, Music_exports as Music, MusicGenerator_exports as MusicGenerator, Probability_exports as Probability, Realtime_exports as Realtime, RealtimeSession_exports as RealtimeSession, Reranker_exports as Reranker, Research_exports as Research, Retry_exports as Retry, SSE_exports as SSE, Sandbox_exports as Sandbox, SandboxError_exports as SandboxError, SandboxImage_exports as SandboxImage, SandboxNetwork_exports as SandboxNetwork, Settle_exports as Settle, SpeechSynthesizer_exports as SpeechSynthesizer, StructuredFormat_exports as StructuredFormat, Telemetry_exports as Telemetry, Tokenizer_exports as Tokenizer, Tool_exports as Tool, ToolEvent_exports as ToolEvent, ToolResult_exports as ToolResult, Toolkit_exports as Toolkit, Transcriber_exports as Transcriber, Transcript_exports as Transcript, Turn_exports as Turn, Vector_exports as Vector, WebRead_exports as WebRead, WebReadTool_exports as WebReadTool, WebSearch_exports as WebSearch, WebSearchTool_exports as WebSearchTool, WebSocketSession_exports as WebSocketSession };
|
package/dist/job/Job.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as AiError } from "../AiError-
|
|
1
|
+
import { t as AiError } from "../AiError-DvhLIbmd.mjs";
|
|
2
2
|
import { Duration, Effect } from "effect";
|
|
3
3
|
declare namespace Job_d_exports {
|
|
4
4
|
export { JobConfig, JobOps, JobRef, JobState, collect, isSettled, jobRef, run };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { o as HistoryItem } from "../Items-C7MyrYPX.mjs";
|
|
2
|
-
import { t as AiError } from "../AiError-
|
|
2
|
+
import { t as AiError } from "../AiError-DvhLIbmd.mjs";
|
|
3
3
|
import { i as StructuredFormat } from "../StructuredFormat-BlZhyOsi.mjs";
|
|
4
4
|
import { Turn, TurnEvent } from "../domain/Turn.mjs";
|
|
5
|
-
import { o as Toolkit } from "../Toolkit-
|
|
5
|
+
import { o as Toolkit } from "../Toolkit-tlL0F2YR.mjs";
|
|
6
6
|
import { Context, Effect, Stream } from "effect";
|
|
7
7
|
declare namespace LanguageModel_d_exports {
|
|
8
8
|
export { CommonRequest, LanguageModel, LanguageModelService, streamTurn, turn, turnFromStream };
|
package/dist/loop/Loop.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as StopWith, c as loopOver, d as onTurnComplete, f as stop, i as Stop, l as loopWithState, n as Next, o as Value, p as value, r as Step, s as loop, u as next } from "../Loop-
|
|
1
|
+
import { a as StopWith, c as loopOver, d as onTurnComplete, f as stop, i as Stop, l as loopWithState, n as Next, o as Value, p as value, r as Step, s as loop, u as next } from "../Loop-ChpaO-ya.mjs";
|
|
2
2
|
export { Next, Step, Stop, StopWith, Value, loop, loopOver, loopWithState, next, onTurnComplete, stop, value };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare namespace Probability_d_exports {
|
|
2
|
+
export { confidence, margin };
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* 1 minus normalized Shannon entropy: 1 when all mass sits on one outcome, 0
|
|
6
|
+
* when spread evenly. Fewer than two outcomes yields 1.
|
|
7
|
+
*
|
|
8
|
+
* Conservative on two outcomes, where `[0.94, 0.06]` scores ~0.67, so a
|
|
9
|
+
* threshold tuned on a long vector does not transfer. {@link margin} is the
|
|
10
|
+
* more stable gate across vectors of different length.
|
|
11
|
+
*/
|
|
12
|
+
declare const confidence: (probabilities: ReadonlyArray<number>) => number;
|
|
13
|
+
/**
|
|
14
|
+
* Top mass minus runner-up mass, which unlike {@link confidence} separates a
|
|
15
|
+
* close second from a flat spread. A single outcome yields its own
|
|
16
|
+
* probability; empty yields 0.
|
|
17
|
+
*/
|
|
18
|
+
declare const margin: (probabilities: ReadonlyArray<number>) => number;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { confidence, margin, Probability_d_exports as t };
|
|
21
|
+
//# sourceMappingURL=Probability.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Probability.d.mts","names":[],"sources":["../../src/math/Probability.ts"],"mappings":";;;;;;;;;;;cAaa,aAAU,eAAmB;;;;;;cAiB7B,SAAM,eAAmB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { n as __exportAll } from "../rolldown-runtime-EAsCxrDo.mjs";
|
|
2
|
+
import { Array, Number, Option, Order, pipe } from "effect";
|
|
3
|
+
//#region src/math/Probability.ts
|
|
4
|
+
/** Certainty measures over a probability vector. */
|
|
5
|
+
var Probability_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
confidence: () => confidence,
|
|
7
|
+
margin: () => margin
|
|
8
|
+
});
|
|
9
|
+
const descending = Order.flip(Order.Number);
|
|
10
|
+
/**
|
|
11
|
+
* 1 minus normalized Shannon entropy: 1 when all mass sits on one outcome, 0
|
|
12
|
+
* when spread evenly. Fewer than two outcomes yields 1.
|
|
13
|
+
*
|
|
14
|
+
* Conservative on two outcomes, where `[0.94, 0.06]` scores ~0.67, so a
|
|
15
|
+
* threshold tuned on a long vector does not transfer. {@link margin} is the
|
|
16
|
+
* more stable gate across vectors of different length.
|
|
17
|
+
*/
|
|
18
|
+
const confidence = (probabilities) => probabilities.length < 2 ? 1 : 1 - pipe(probabilities, Array.filter((p) => p > 0), Array.map((p) => -p * Math.log(p)), Number.sumAll) / Math.log(probabilities.length);
|
|
19
|
+
/**
|
|
20
|
+
* Top mass minus runner-up mass, which unlike {@link confidence} separates a
|
|
21
|
+
* close second from a flat spread. A single outcome yields its own
|
|
22
|
+
* probability; empty yields 0.
|
|
23
|
+
*/
|
|
24
|
+
const margin = (probabilities) => {
|
|
25
|
+
const top = pipe(probabilities, Array.sort(descending), Array.take(2));
|
|
26
|
+
return pipe(Array.get(top, 0), Option.map((first) => pipe(Array.get(top, 1), Option.getOrElse(() => 0), (second) => first - second)), Option.getOrElse(() => 0));
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { confidence, margin, Probability_exports as t };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=Probability.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Probability.mjs","names":["A","N"],"sources":["../../src/math/Probability.ts"],"sourcesContent":["/** Certainty measures over a probability vector. */\nimport { Array as A, Number as N, Option, Order, pipe } from \"effect\"\n\nconst descending = Order.flip(Order.Number)\n\n/**\n * 1 minus normalized Shannon entropy: 1 when all mass sits on one outcome, 0\n * when spread evenly. Fewer than two outcomes yields 1.\n *\n * Conservative on two outcomes, where `[0.94, 0.06]` scores ~0.67, so a\n * threshold tuned on a long vector does not transfer. {@link margin} is the\n * more stable gate across vectors of different length.\n */\nexport const confidence = (probabilities: ReadonlyArray<number>): number =>\n probabilities.length < 2\n ? 1\n : 1 -\n pipe(\n probabilities,\n A.filter((p) => p > 0),\n A.map((p) => -p * Math.log(p)),\n N.sumAll,\n ) /\n Math.log(probabilities.length)\n\n/**\n * Top mass minus runner-up mass, which unlike {@link confidence} separates a\n * close second from a flat spread. A single outcome yields its own\n * probability; empty yields 0.\n */\nexport const margin = (probabilities: ReadonlyArray<number>): number => {\n const top = pipe(probabilities, A.sort(descending), A.take(2))\n return pipe(\n A.get(top, 0),\n Option.map((first) =>\n pipe(\n A.get(top, 1),\n Option.getOrElse(() => 0),\n (second) => first - second,\n ),\n ),\n Option.getOrElse(() => 0),\n )\n}\n"],"mappings":";;;;;;;;AAGA,MAAM,aAAa,MAAM,KAAK,MAAM,MAAM;;;;;;;;;AAU1C,MAAa,cAAc,kBACzB,cAAc,SAAS,IACnB,IACA,IACA,KACE,eACAA,MAAE,QAAQ,MAAM,IAAI,CAAC,GACrBA,MAAE,KAAK,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,GAC7BC,OAAE,MACJ,IACE,KAAK,IAAI,cAAc,MAAM;;;;;;AAOrC,MAAa,UAAU,kBAAiD;CACtE,MAAM,MAAM,KAAK,eAAeD,MAAE,KAAK,UAAU,GAAGA,MAAE,KAAK,CAAC,CAAC;CAC7D,OAAO,KACLA,MAAE,IAAI,KAAK,CAAC,GACZ,OAAO,KAAK,UACV,KACEA,MAAE,IAAI,KAAK,CAAC,GACZ,OAAO,gBAAgB,CAAC,IACvB,WAAW,QAAQ,MACtB,CACF,GACA,OAAO,gBAAgB,CAAC,CAC1B;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { confidence, margin } from "./Probability.mjs";
|
|
2
|
+
import { m as it, o as describe } from "../utils-CiH_DjFW.mjs";
|
|
3
|
+
import { n as globalExpect } from "../test.DNmyFkvJ-YPzDR0Co.mjs";
|
|
4
|
+
//#region src/math/Probability.test.ts
|
|
5
|
+
describe("confidence", () => {
|
|
6
|
+
it("is 1 when all mass sits on one outcome", () => {
|
|
7
|
+
globalExpect(confidence([
|
|
8
|
+
1,
|
|
9
|
+
0,
|
|
10
|
+
0
|
|
11
|
+
])).toBeCloseTo(1, 10);
|
|
12
|
+
});
|
|
13
|
+
it("is 0 when mass is spread evenly, at any length", () => {
|
|
14
|
+
globalExpect(confidence([.5, .5])).toBeCloseTo(0, 10);
|
|
15
|
+
globalExpect(confidence([
|
|
16
|
+
.25,
|
|
17
|
+
.25,
|
|
18
|
+
.25,
|
|
19
|
+
.25
|
|
20
|
+
])).toBeCloseTo(0, 10);
|
|
21
|
+
});
|
|
22
|
+
it("is 1 for fewer than two outcomes, which have nothing to be uncertain between", () => {
|
|
23
|
+
globalExpect(confidence([])).toBe(1);
|
|
24
|
+
globalExpect(confidence([1])).toBe(1);
|
|
25
|
+
});
|
|
26
|
+
it("rises as mass concentrates", () => {
|
|
27
|
+
const spread = confidence([
|
|
28
|
+
.4,
|
|
29
|
+
.35,
|
|
30
|
+
.25
|
|
31
|
+
]);
|
|
32
|
+
const leaning = confidence([
|
|
33
|
+
.6,
|
|
34
|
+
.25,
|
|
35
|
+
.15
|
|
36
|
+
]);
|
|
37
|
+
const decided = confidence([
|
|
38
|
+
.9,
|
|
39
|
+
.07,
|
|
40
|
+
.03
|
|
41
|
+
]);
|
|
42
|
+
globalExpect(spread).toBeLessThan(leaning);
|
|
43
|
+
globalExpect(leaning).toBeLessThan(decided);
|
|
44
|
+
});
|
|
45
|
+
it("is conservative on two outcomes, so a threshold does not transfer across lengths", () => {
|
|
46
|
+
globalExpect(confidence([.94, .06])).toBeCloseTo(.67, 2);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe("margin", () => {
|
|
50
|
+
it("is the gap between the top two, whatever order they arrive in", () => {
|
|
51
|
+
globalExpect(margin([
|
|
52
|
+
.6,
|
|
53
|
+
.3,
|
|
54
|
+
.1
|
|
55
|
+
])).toBeCloseTo(.3, 10);
|
|
56
|
+
globalExpect(margin([
|
|
57
|
+
.1,
|
|
58
|
+
.6,
|
|
59
|
+
.3
|
|
60
|
+
])).toBeCloseTo(.3, 10);
|
|
61
|
+
});
|
|
62
|
+
it("is 0 on a tie and 0 when empty", () => {
|
|
63
|
+
globalExpect(margin([.5, .5])).toBeCloseTo(0, 10);
|
|
64
|
+
globalExpect(margin([])).toBe(0);
|
|
65
|
+
});
|
|
66
|
+
it("yields the lone probability for a single outcome", () => {
|
|
67
|
+
globalExpect(margin([.7])).toBeCloseTo(.7, 10);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
describe("confidence and margin disagree, which is why both exist", () => {
|
|
71
|
+
const closeSecond = [
|
|
72
|
+
.45,
|
|
73
|
+
.42,
|
|
74
|
+
.13
|
|
75
|
+
];
|
|
76
|
+
const flatSpread = [
|
|
77
|
+
.45,
|
|
78
|
+
.11,
|
|
79
|
+
.11,
|
|
80
|
+
.11,
|
|
81
|
+
.11,
|
|
82
|
+
.11
|
|
83
|
+
];
|
|
84
|
+
it("confidence cannot separate them", () => {
|
|
85
|
+
globalExpect(Math.abs(confidence(closeSecond) - confidence(flatSpread))).toBeLessThan(.05);
|
|
86
|
+
});
|
|
87
|
+
it("margin separates them sharply", () => {
|
|
88
|
+
globalExpect(margin(closeSecond)).toBeCloseTo(.03, 10);
|
|
89
|
+
globalExpect(margin(flatSpread)).toBeCloseTo(.34, 10);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
//#endregion
|
|
93
|
+
export {};
|
|
94
|
+
|
|
95
|
+
//# sourceMappingURL=Probability.test.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Probability.test.mjs","names":[],"sources":["../../src/math/Probability.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\"\nimport { confidence, margin } from \"./Probability.js\"\n\ndescribe(\"confidence\", () => {\n it(\"is 1 when all mass sits on one outcome\", () => {\n expect(confidence([1, 0, 0])).toBeCloseTo(1, 10)\n })\n\n it(\"is 0 when mass is spread evenly, at any length\", () => {\n expect(confidence([0.5, 0.5])).toBeCloseTo(0, 10)\n expect(confidence([0.25, 0.25, 0.25, 0.25])).toBeCloseTo(0, 10)\n })\n\n it(\"is 1 for fewer than two outcomes, which have nothing to be uncertain between\", () => {\n expect(confidence([])).toBe(1)\n expect(confidence([1])).toBe(1)\n })\n\n it(\"rises as mass concentrates\", () => {\n const spread = confidence([0.4, 0.35, 0.25])\n const leaning = confidence([0.6, 0.25, 0.15])\n const decided = confidence([0.9, 0.07, 0.03])\n expect(spread).toBeLessThan(leaning)\n expect(leaning).toBeLessThan(decided)\n })\n\n it(\"is conservative on two outcomes, so a threshold does not transfer across lengths\", () => {\n expect(confidence([0.94, 0.06])).toBeCloseTo(0.67, 2)\n })\n})\n\ndescribe(\"margin\", () => {\n it(\"is the gap between the top two, whatever order they arrive in\", () => {\n expect(margin([0.6, 0.3, 0.1])).toBeCloseTo(0.3, 10)\n expect(margin([0.1, 0.6, 0.3])).toBeCloseTo(0.3, 10)\n })\n\n it(\"is 0 on a tie and 0 when empty\", () => {\n expect(margin([0.5, 0.5])).toBeCloseTo(0, 10)\n expect(margin([])).toBe(0)\n })\n\n it(\"yields the lone probability for a single outcome\", () => {\n expect(margin([0.7])).toBeCloseTo(0.7, 10)\n })\n})\n\ndescribe(\"confidence and margin disagree, which is why both exist\", () => {\n // Two plausible answers versus no idea. Same winner, same top mass.\n const closeSecond = [0.45, 0.42, 0.13]\n const flatSpread = [0.45, 0.11, 0.11, 0.11, 0.11, 0.11]\n\n it(\"confidence cannot separate them\", () => {\n expect(Math.abs(confidence(closeSecond) - confidence(flatSpread))).toBeLessThan(0.05)\n })\n\n it(\"margin separates them sharply\", () => {\n expect(margin(closeSecond)).toBeCloseTo(0.03, 10)\n expect(margin(flatSpread)).toBeCloseTo(0.34, 10)\n })\n})\n"],"mappings":";;;;AAGA,SAAS,oBAAoB;CAC3B,GAAG,gDAAgD;EACjD,aAAO,WAAW;GAAC;GAAG;GAAG;EAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,EAAE;CACjD,CAAC;CAED,GAAG,wDAAwD;EACzD,aAAO,WAAW,CAAC,IAAK,EAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,EAAE;EAChD,aAAO,WAAW;GAAC;GAAM;GAAM;GAAM;EAAI,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,EAAE;CAChE,CAAC;CAED,GAAG,sFAAsF;EACvF,aAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;EAC7B,aAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;CAChC,CAAC;CAED,GAAG,oCAAoC;EACrC,MAAM,SAAS,WAAW;GAAC;GAAK;GAAM;EAAI,CAAC;EAC3C,MAAM,UAAU,WAAW;GAAC;GAAK;GAAM;EAAI,CAAC;EAC5C,MAAM,UAAU,WAAW;GAAC;GAAK;GAAM;EAAI,CAAC;EAC5C,aAAO,MAAM,CAAC,CAAC,aAAa,OAAO;EACnC,aAAO,OAAO,CAAC,CAAC,aAAa,OAAO;CACtC,CAAC;CAED,GAAG,0FAA0F;EAC3F,aAAO,WAAW,CAAC,KAAM,GAAI,CAAC,CAAC,CAAC,CAAC,YAAY,KAAM,CAAC;CACtD,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB;CACvB,GAAG,uEAAuE;EACxE,aAAO,OAAO;GAAC;GAAK;GAAK;EAAG,CAAC,CAAC,CAAC,CAAC,YAAY,IAAK,EAAE;EACnD,aAAO,OAAO;GAAC;GAAK;GAAK;EAAG,CAAC,CAAC,CAAC,CAAC,YAAY,IAAK,EAAE;CACrD,CAAC;CAED,GAAG,wCAAwC;EACzC,aAAO,OAAO,CAAC,IAAK,EAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,EAAE;EAC5C,aAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;CAC3B,CAAC;CAED,GAAG,0DAA0D;EAC3D,aAAO,OAAO,CAAC,EAAG,CAAC,CAAC,CAAC,CAAC,YAAY,IAAK,EAAE;CAC3C,CAAC;AACH,CAAC;AAED,SAAS,iEAAiE;CAExE,MAAM,cAAc;EAAC;EAAM;EAAM;CAAI;CACrC,MAAM,aAAa;EAAC;EAAM;EAAM;EAAM;EAAM;EAAM;CAAI;CAEtD,GAAG,yCAAyC;EAC1C,aAAO,KAAK,IAAI,WAAW,WAAW,IAAI,WAAW,UAAU,CAAC,CAAC,CAAC,CAAC,aAAa,GAAI;CACtF,CAAC;CAED,GAAG,uCAAuC;EACxC,aAAO,OAAO,WAAW,CAAC,CAAC,CAAC,YAAY,KAAM,EAAE;EAChD,aAAO,OAAO,UAAU,CAAC,CAAC,CAAC,YAAY,KAAM,EAAE;CACjD,CAAC;AACH,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as Watermark } from "../Media-BbX7BAaO.mjs";
|
|
2
|
-
import { t as AiError } from "../AiError-
|
|
2
|
+
import { t as AiError } from "../AiError-DvhLIbmd.mjs";
|
|
3
3
|
import { n as AudioChunk } from "../Audio-_nGR4V0X.mjs";
|
|
4
4
|
import { CommonGenerateMusicRequest, CommonStreamGenerateMusicRequest, GenerateResult, MusicResult, MusicSection, MusicSessionControl, MusicSessionInput, MusicStreamEvent, WeightedPrompt } from "../domain/Music.mjs";
|
|
5
5
|
import { Context, Effect, Stream } from "effect";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { o as ImageSource } from "../Image-Cv6iBLTy.mjs";
|
|
2
|
+
import { t as AiError } from "../AiError-DvhLIbmd.mjs";
|
|
3
|
+
import { CommonSessionRequest, RealtimeEvent, RealtimeInput } from "../domain/Realtime.mjs";
|
|
4
|
+
import { Context, Effect, Scope, Stream } from "effect";
|
|
5
|
+
declare namespace RealtimeSession_d_exports {
|
|
6
|
+
export { RealtimeSession, RealtimeSessionHandle, RealtimeSessionService, RealtimeVideoInput, audioDeltas, open, sendVideoFrame, toolCalls };
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The live connection. `events` ends when the socket closes cleanly; a close
|
|
10
|
+
* during a response ends it with `AiError.IncompleteTurn` instead, and never
|
|
11
|
+
* synthesizes a `ResponseDone`. `send` after close fails `Unavailable`.
|
|
12
|
+
*/
|
|
13
|
+
type RealtimeSessionHandle = {
|
|
14
|
+
readonly send: (input: RealtimeInput) => Effect.Effect<void, AiError>;
|
|
15
|
+
readonly events: Stream.Stream<RealtimeEvent, AiError>;
|
|
16
|
+
};
|
|
17
|
+
type RealtimeSessionService = {
|
|
18
|
+
/**
|
|
19
|
+
* Connect and complete the provider handshake before succeeding. Closing the
|
|
20
|
+
* `Scope` closes the socket.
|
|
21
|
+
*/
|
|
22
|
+
readonly open: (request: CommonSessionRequest) => Effect.Effect<RealtimeSessionHandle, AiError, Scope.Scope>;
|
|
23
|
+
};
|
|
24
|
+
declare const RealtimeSession_base: Context.ServiceClass<RealtimeSession, "@betalyra/effect-uai/RealtimeSession", RealtimeSessionService>;
|
|
25
|
+
declare class RealtimeSession extends RealtimeSession_base {}
|
|
26
|
+
declare const RealtimeVideoInput_base: Context.ServiceClass<RealtimeVideoInput, "@betalyra/effect-uai/capability/RealtimeVideoInput", void>;
|
|
27
|
+
/**
|
|
28
|
+
* Capability marker for sessions that accept video frames. Phantom: providers
|
|
29
|
+
* register with `Layer.succeed(RealtimeVideoInput, undefined)`. Only Gemini
|
|
30
|
+
* ships it, so `sendVideoFrame` against an OpenAI-only Layer is a type error.
|
|
31
|
+
*/
|
|
32
|
+
declare class RealtimeVideoInput extends RealtimeVideoInput_base {}
|
|
33
|
+
/** Open a session for the lifetime of the surrounding `Scope`. */
|
|
34
|
+
declare const open: (request: CommonSessionRequest) => Effect.Effect<RealtimeSessionHandle, AiError, RealtimeSession | Scope.Scope>;
|
|
35
|
+
/**
|
|
36
|
+
* Push one video frame. Requires `RealtimeVideoInput`, so a provider without
|
|
37
|
+
* video fails at `Effect.provide` rather than at runtime.
|
|
38
|
+
*/
|
|
39
|
+
declare const sendVideoFrame: (handle: RealtimeSessionHandle, frame: ImageSource) => Effect.Effect<void, AiError, RealtimeVideoInput>;
|
|
40
|
+
/** Just the audio, for wiring straight to playback. */
|
|
41
|
+
declare const audioDeltas: <E, R>(events: Stream.Stream<RealtimeEvent, E, R>) => Stream.Stream<Extract<RealtimeEvent, {
|
|
42
|
+
readonly _tag: "AudioDelta";
|
|
43
|
+
}>, E, R>;
|
|
44
|
+
/** Just the tool calls. Answer each with a `ToolResult`; the adapter resumes. */
|
|
45
|
+
declare const toolCalls: <E, R>(events: Stream.Stream<RealtimeEvent, E, R>) => Stream.Stream<Extract<RealtimeEvent, {
|
|
46
|
+
readonly _tag: "ToolCall";
|
|
47
|
+
}>, E, R>;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { RealtimeSession, RealtimeSessionHandle, RealtimeSessionService, RealtimeVideoInput, audioDeltas, open, sendVideoFrame, RealtimeSession_d_exports as t, toolCalls };
|
|
50
|
+
//# sourceMappingURL=RealtimeSession.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RealtimeSession.d.mts","names":[],"sources":["../../src/realtime/RealtimeSession.ts"],"mappings":";;;;;;;;;;;;KAmBY;WACD,OAAO,OAAO,kBAAkB,OAAO,aAAa;WACpD,QAAQ,OAAO,OAAO,eAAe;;KAGpC;;;;;WAKD,OACP,SAAS,yBACN,OAAO,OAAO,uBAAuB,SAAiB,MAAM;;;cAGtD,wBAAwB;;;;;;;cASxB,2BAA2B;;cAK3B,OAAI,SACN,yBACR,OAAO,OAAO,uBAAuB,SAAiB,kBAAkB,MAAM;;;;;cAOpE,iBAAc,QACjB,uBAAqB,OACtB,gBACN,OAAO,aAAa,SAAiB;;cAO3B,cAAe,GAAG,GAAC,QACtB,OAAO,OAAO,eAAe,GAAG,OACvC,OAAO,OAAO,QAAQ;WAA0B;IAAuB,GAAG;;cAIhE,YAAa,GAAG,GAAC,QACpB,OAAO,OAAO,eAAe,GAAG,OACvC,OAAO,OAAO,QAAQ;WAA0B;IAAqB,GAAG"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { n as __exportAll } from "../rolldown-runtime-EAsCxrDo.mjs";
|
|
2
|
+
import { RealtimeEvent, RealtimeInput } from "../domain/Realtime.mjs";
|
|
3
|
+
import { Context, Effect, Stream } from "effect";
|
|
4
|
+
//#region src/realtime/RealtimeSession.ts
|
|
5
|
+
/**
|
|
6
|
+
* A duplex speech-to-speech session. The server drives turn-taking, so this is
|
|
7
|
+
* its own primitive rather than a variant of `Loop`.
|
|
8
|
+
*
|
|
9
|
+
* The session is deliberately low level: tool execution, playback, barge-in
|
|
10
|
+
* bookkeeping and reconnection are the caller's, built from `send` and
|
|
11
|
+
* `events`. There is no agent wrapper, no hidden queue and no automatic
|
|
12
|
+
* reconnect here.
|
|
13
|
+
*/
|
|
14
|
+
var RealtimeSession_exports = /* @__PURE__ */ __exportAll({
|
|
15
|
+
RealtimeSession: () => RealtimeSession,
|
|
16
|
+
RealtimeVideoInput: () => RealtimeVideoInput,
|
|
17
|
+
audioDeltas: () => audioDeltas,
|
|
18
|
+
open: () => open,
|
|
19
|
+
sendVideoFrame: () => sendVideoFrame,
|
|
20
|
+
toolCalls: () => toolCalls
|
|
21
|
+
});
|
|
22
|
+
var RealtimeSession = class extends Context.Service()("@betalyra/effect-uai/RealtimeSession") {};
|
|
23
|
+
/**
|
|
24
|
+
* Capability marker for sessions that accept video frames. Phantom: providers
|
|
25
|
+
* register with `Layer.succeed(RealtimeVideoInput, undefined)`. Only Gemini
|
|
26
|
+
* ships it, so `sendVideoFrame` against an OpenAI-only Layer is a type error.
|
|
27
|
+
*/
|
|
28
|
+
var RealtimeVideoInput = class extends Context.Service()("@betalyra/effect-uai/capability/RealtimeVideoInput") {};
|
|
29
|
+
/** Open a session for the lifetime of the surrounding `Scope`. */
|
|
30
|
+
const open = (request) => Effect.flatMap(RealtimeSession, (s) => s.open(request));
|
|
31
|
+
/**
|
|
32
|
+
* Push one video frame. Requires `RealtimeVideoInput`, so a provider without
|
|
33
|
+
* video fails at `Effect.provide` rather than at runtime.
|
|
34
|
+
*/
|
|
35
|
+
const sendVideoFrame = (handle, frame) => Effect.flatMap(RealtimeVideoInput, () => handle.send(RealtimeInput.VideoFrame({ frame })));
|
|
36
|
+
const isAudioDelta = RealtimeEvent.$is("AudioDelta");
|
|
37
|
+
const isToolCall = RealtimeEvent.$is("ToolCall");
|
|
38
|
+
/** Just the audio, for wiring straight to playback. */
|
|
39
|
+
const audioDeltas = (events) => Stream.filter(events, isAudioDelta);
|
|
40
|
+
/** Just the tool calls. Answer each with a `ToolResult`; the adapter resumes. */
|
|
41
|
+
const toolCalls = (events) => Stream.filter(events, isToolCall);
|
|
42
|
+
//#endregion
|
|
43
|
+
export { RealtimeSession, RealtimeVideoInput, audioDeltas, open, sendVideoFrame, RealtimeSession_exports as t, toolCalls };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=RealtimeSession.mjs.map
|