@kuralle-syrinx/gemini 2.1.1 → 3.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kuralle-syrinx/gemini",
3
- "version": "2.1.1",
3
+ "version": "3.1.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -8,7 +8,7 @@
8
8
  "types": "./src/index.ts",
9
9
  "dependencies": {
10
10
  "@google/genai": "^1.0.0",
11
- "@kuralle-syrinx/core": "2.1.1"
11
+ "@kuralle-syrinx/core": "3.1.0"
12
12
  },
13
13
  "devDependencies": {
14
14
  "typescript": "^5.7.0",
package/src/index.test.ts CHANGED
@@ -73,4 +73,43 @@ describe("GeminiTTSPlugin", () => {
73
73
  bus.stop();
74
74
  await started;
75
75
  });
76
+
77
+ it("sends the raw text to Gemini by default (no hardcoded persona lead-in)", async () => {
78
+ generateContent.mockResolvedValue({
79
+ candidates: [{ content: { parts: [{ inlineData: { mimeType: "audio/pcm", data: Buffer.from(new Uint8Array([1, 2, 3, 4])).toString("base64") } }] } }],
80
+ });
81
+ const bus = new PipelineBusImpl();
82
+ const started = bus.start();
83
+ const plugin = new GeminiTTSPlugin();
84
+ await plugin.initialize(bus, { api_key: "test-gemini-key" });
85
+ bus.push(Route.Main, { kind: "tts.done", contextId: "t1", timestampMs: Date.now(), text: "Add Biology 101." });
86
+ await new Promise((resolve) => setTimeout(resolve, 50));
87
+
88
+ expect(generateContent).toHaveBeenCalledTimes(1);
89
+ const arg = generateContent.mock.calls[0]![0] as { contents: Array<{ parts: Array<{ text: string }> }> };
90
+ expect(arg.contents[0]!.parts[0]!.text).toBe("Add Biology 101.");
91
+
92
+ await plugin.close();
93
+ bus.stop();
94
+ await started;
95
+ });
96
+
97
+ it("prepends a configured instruction lead-in when provided", async () => {
98
+ generateContent.mockResolvedValue({
99
+ candidates: [{ content: { parts: [{ inlineData: { mimeType: "audio/pcm", data: Buffer.from(new Uint8Array([1, 2, 3, 4])).toString("base64") } }] } }],
100
+ });
101
+ const bus = new PipelineBusImpl();
102
+ const started = bus.start();
103
+ const plugin = new GeminiTTSPlugin();
104
+ await plugin.initialize(bus, { api_key: "test-gemini-key", instruction: "Read aloud warmly" });
105
+ bus.push(Route.Main, { kind: "tts.done", contextId: "t2", timestampMs: Date.now(), text: "Hi." });
106
+ await new Promise((resolve) => setTimeout(resolve, 50));
107
+
108
+ const arg = generateContent.mock.calls[0]![0] as { contents: Array<{ parts: Array<{ text: string }> }> };
109
+ expect(arg.contents[0]!.parts[0]!.text).toBe("Read aloud warmly: Hi.");
110
+
111
+ await plugin.close();
112
+ bus.stop();
113
+ await started;
114
+ });
76
115
  });
package/src/index.ts CHANGED
@@ -59,6 +59,7 @@ export class GeminiTTSPlugin implements VoicePlugin {
59
59
  private apiKey: string = "";
60
60
  private model: string = DEFAULT_MODEL;
61
61
  private voiceName: string = DEFAULT_VOICE;
62
+ private instruction = "";
62
63
  private timeoutMs = 45_000;
63
64
  private abortController: AbortController | null = null;
64
65
  private textByContextId = new Map<string, string>();
@@ -71,6 +72,7 @@ export class GeminiTTSPlugin implements VoicePlugin {
71
72
  this.apiKey = requireStringConfig(config, "api_key");
72
73
  this.model = optionalStringConfig(config, "model") ?? DEFAULT_MODEL;
73
74
  this.voiceName = optionalStringConfig(config, "voice_name") ?? DEFAULT_VOICE;
75
+ this.instruction = optionalStringConfig(config, "instruction") ?? "";
74
76
  this.timeoutMs = readPositiveInteger(config["timeout_ms"], 45_000);
75
77
  this.retryConfig = readRetryConfig(config);
76
78
  assertAudioFormat(this.audioFormat);
@@ -171,7 +173,7 @@ export class GeminiTTSPlugin implements VoicePlugin {
171
173
  const response = await withTimeout(
172
174
  client.models.generateContent({
173
175
  model: this.model,
174
- contents: [{ parts: [{ text: `Read this aloud in a natural student-support phone voice: ${text}` }] }],
176
+ contents: [{ parts: [{ text: this.instruction ? `${this.instruction}: ${text}` : text }] }],
175
177
  config: {
176
178
  responseModalities: ["AUDIO"],
177
179
  speechConfig: {