@ai-ecoverse/pi-audio 1.18.0 → 1.19.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 +3 -1
- package/dist/fish/catalog.js +78 -0
- package/dist/fish/catalog.js.map +7 -0
- package/dist/fish/index.js +5 -0
- package/dist/fish/index.js.map +7 -0
- package/dist/fish/speak.js +269 -0
- package/dist/fish/speak.js.map +7 -0
- package/dist/fish/transcribe.js +158 -0
- package/dist/fish/transcribe.js.map +7 -0
- package/dist/fish/wire.js +386 -0
- package/dist/fish/wire.js.map +7 -0
- package/dist/gemini-live/session.js +32 -15
- package/dist/gemini-live/session.js.map +2 -2
- package/dist/openai-realtime/session.js +35 -9
- package/dist/openai-realtime/session.js.map +2 -2
- package/dist/openai-realtime/socket.js +12 -0
- package/dist/openai-realtime/socket.js.map +2 -2
- package/dist/talker.js +71 -27
- package/dist/talker.js.map +3 -3
- package/dist/types/fish/catalog.d.ts +1 -0
- package/dist/types/fish/index.d.ts +1 -0
- package/dist/types/fish/speak.d.ts +4 -0
- package/dist/types/fish/transcribe.d.ts +4 -0
- package/dist/types/fish/wire.d.ts +27 -0
- package/dist/types/openai-realtime/socket.d.ts +1 -0
- package/dist/types/talker.d.ts +1 -1
- package/package.json +5 -1
package/dist/talker.js
CHANGED
|
@@ -88,6 +88,16 @@ function capResult(result, maxChars) {
|
|
|
88
88
|
});
|
|
89
89
|
return { ...result, content };
|
|
90
90
|
}
|
|
91
|
+
function requestContext(call) {
|
|
92
|
+
const value = call.arguments.context;
|
|
93
|
+
return typeof value === "string" ? value : void 0;
|
|
94
|
+
}
|
|
95
|
+
function track(pending, promise) {
|
|
96
|
+
pending.add(promise);
|
|
97
|
+
void promise.finally(() => {
|
|
98
|
+
pending.delete(promise);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
91
101
|
function bindThinker(session, thinker, direct, options) {
|
|
92
102
|
const captions = new PushStream();
|
|
93
103
|
const phases = new PushStream();
|
|
@@ -102,42 +112,31 @@ function bindThinker(session, thinker, direct, options) {
|
|
|
102
112
|
async function run(session, thinker, direct, options, captions, phases) {
|
|
103
113
|
const heard = [];
|
|
104
114
|
const running = /* @__PURE__ */ new Map();
|
|
115
|
+
const pending = /* @__PURE__ */ new Set();
|
|
105
116
|
for await (const event of session) {
|
|
106
117
|
if (event.type === "input_transcript" && event.final) heard.push(`user: ${event.text}`);
|
|
107
118
|
if (event.type === "output_transcript" && event.final) heard.push(`talker: ${event.text}`);
|
|
108
119
|
if (event.type === "tool_call_cancelled") {
|
|
109
|
-
|
|
110
|
-
if (!job2) continue;
|
|
111
|
-
job2.abort.abort();
|
|
112
|
-
if (!job2.answered) {
|
|
113
|
-
job2.answered = true;
|
|
114
|
-
send(() => session.respond(event.callId, errorResult(job2.call, new Error("cancelled"))));
|
|
115
|
-
}
|
|
120
|
+
cancelJob(session, running, event.callId);
|
|
116
121
|
continue;
|
|
117
122
|
}
|
|
118
123
|
if (event.type !== "tool_call") continue;
|
|
119
124
|
const call = event.call;
|
|
120
125
|
if (call.name !== askAgent.name) {
|
|
121
|
-
phases
|
|
122
|
-
phase: "tool",
|
|
123
|
-
toolName: call.name,
|
|
124
|
-
toolCallId: call.id,
|
|
125
|
-
args: call.arguments
|
|
126
|
-
});
|
|
127
|
-
void direct(call, AbortSignal.timeout(options.directTimeoutMs)).then((result) => {
|
|
128
|
-
send(() => session.respond(call.id, capResult(result, options.directMaxChars)));
|
|
129
|
-
phases.push({ phase: "idle" });
|
|
130
|
-
}).catch((error) => {
|
|
131
|
-
send(() => session.respond(call.id, errorResult(call, error)));
|
|
132
|
-
phases.push({ phase: "idle" });
|
|
133
|
-
});
|
|
126
|
+
track(pending, runDirect(session, direct, options, phases, running, call));
|
|
134
127
|
continue;
|
|
135
128
|
}
|
|
136
|
-
const job = {
|
|
129
|
+
const job = {
|
|
130
|
+
abort: new AbortController(),
|
|
131
|
+
answered: false,
|
|
132
|
+
dropped: false,
|
|
133
|
+
call,
|
|
134
|
+
kind: "ask"
|
|
135
|
+
};
|
|
137
136
|
running.set(call.id, job);
|
|
138
137
|
phases.push({ phase: "thinking" });
|
|
139
138
|
if (event.blocking) send(() => session.respond(call.id, acknowledged(call, options.ack)));
|
|
140
|
-
|
|
139
|
+
const ask = followAsk(
|
|
141
140
|
session,
|
|
142
141
|
thinker,
|
|
143
142
|
options,
|
|
@@ -149,14 +148,52 @@ async function run(session, thinker, direct, options, captions, phases) {
|
|
|
149
148
|
event.blocking,
|
|
150
149
|
job
|
|
151
150
|
);
|
|
151
|
+
track(pending, ask);
|
|
152
152
|
}
|
|
153
|
+
for (const job of running.values()) {
|
|
154
|
+
job.dropped = true;
|
|
155
|
+
job.abort.abort();
|
|
156
|
+
}
|
|
157
|
+
await Promise.allSettled([...pending]);
|
|
158
|
+
}
|
|
159
|
+
function cancelJob(session, running, callId) {
|
|
160
|
+
const job = running.get(callId);
|
|
161
|
+
if (!job) return;
|
|
162
|
+
job.abort.abort();
|
|
163
|
+
job.dropped = true;
|
|
164
|
+
if (job.kind !== "ask" || job.answered) return;
|
|
165
|
+
job.answered = true;
|
|
166
|
+
send(() => session.respond(callId, errorResult(job.call, new Error("cancelled"))));
|
|
167
|
+
}
|
|
168
|
+
function runDirect(session, direct, options, phases, running, call) {
|
|
169
|
+
const abort = new AbortController();
|
|
170
|
+
const signal = AbortSignal.any([abort.signal, AbortSignal.timeout(options.directTimeoutMs)]);
|
|
171
|
+
const job = { abort, answered: false, dropped: false, call, kind: "direct" };
|
|
172
|
+
running.set(call.id, job);
|
|
173
|
+
phases.push({
|
|
174
|
+
phase: "tool",
|
|
175
|
+
toolName: call.name,
|
|
176
|
+
toolCallId: call.id,
|
|
177
|
+
args: call.arguments
|
|
178
|
+
});
|
|
179
|
+
return direct(call, signal).then((result) => {
|
|
180
|
+
if (job.dropped) return;
|
|
181
|
+
send(() => session.respond(call.id, capResult(result, options.directMaxChars)));
|
|
182
|
+
}).catch((error) => {
|
|
183
|
+
if (job.dropped) return;
|
|
184
|
+
send(() => session.respond(call.id, errorResult(call, error)));
|
|
185
|
+
}).finally(() => {
|
|
186
|
+
running.delete(call.id);
|
|
187
|
+
phases.push({ phase: "idle" });
|
|
188
|
+
});
|
|
153
189
|
}
|
|
154
190
|
async function followAsk(session, thinker, options, captions, phases, running, heard, call, blocking, job) {
|
|
155
191
|
try {
|
|
156
192
|
for await (const update of thinker.ask(
|
|
157
193
|
String(call.arguments.request),
|
|
158
194
|
heard.slice(-heardLimit),
|
|
159
|
-
job.abort.signal
|
|
195
|
+
job.abort.signal,
|
|
196
|
+
requestContext(call)
|
|
160
197
|
)) {
|
|
161
198
|
if (job.abort.signal.aborted) break;
|
|
162
199
|
if (update.type === "progress") {
|
|
@@ -175,10 +212,17 @@ async function followAsk(session, thinker, options, captions, phases, running, h
|
|
|
175
212
|
else send(() => session.respond(call.id, update.message, options.result));
|
|
176
213
|
}
|
|
177
214
|
} catch (error) {
|
|
178
|
-
if (
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
215
|
+
if (job.abort.signal.aborted || job.answered) return;
|
|
216
|
+
job.answered = true;
|
|
217
|
+
const message = errorResult(call, error);
|
|
218
|
+
captions.push({
|
|
219
|
+
type: "thinker_result",
|
|
220
|
+
callId: call.id,
|
|
221
|
+
summary: textOf(message),
|
|
222
|
+
isError: true
|
|
223
|
+
});
|
|
224
|
+
if (blocking) send(() => session.inject(textOf(message), options.result));
|
|
225
|
+
else send(() => session.respond(call.id, message));
|
|
182
226
|
} finally {
|
|
183
227
|
running.delete(call.id);
|
|
184
228
|
phases.push({ phase: "idle" });
|
package/dist/talker.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/talker.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type JsonObject,\n type Tool,\n type ToolCall,\n type ToolResultMessage,\n Type,\n} from '@earendil-works/pi-ai';\nimport { VoiceRequestError } from './errors.ts';\nimport type { Delivery } from './models.ts';\nimport type { RealtimeSession } from './realtime.ts';\n\nconst heardLimit = 20;\n\nexport const talkerTools = ['ask_agent', 'read'] as const;\n\nexport const askAgent: Tool = {\n name: 'ask_agent',\n description:\n 'Hand a request to the coding agent. Use for anything that needs files, the browser, tools or more than a few seconds of thought.',\n parameters: Type.Object({\n request: Type.String(),\n context: Type.Optional(Type.String()),\n }),\n};\n\nexport type ThinkerUpdate =\n | { type: 'progress'; text: string }\n | { type: 'result'; message: ToolResultMessage };\n\nexport interface Thinker {\n ask(request: string
|
|
5
|
-
"mappings": "AAAA;AAAA,EAKE;AAAA,OACK;AACP,SAAS,yBAAyB;AAIlC,MAAM,aAAa;AAEZ,MAAM,cAAc,CAAC,aAAa,MAAM;AAExC,MAAM,WAAiB;AAAA,EAC5B,MAAM;AAAA,EACN,aACE;AAAA,EACF,YAAY,KAAK,OAAO;AAAA,IACtB,SAAS,KAAK,OAAO;AAAA,IACrB,SAAS,KAAK,SAAS,KAAK,OAAO,CAAC;AAAA,EACtC,CAAC;AACH;
|
|
6
|
-
"names": [
|
|
4
|
+
"sourcesContent": ["import {\n type JsonObject,\n type Tool,\n type ToolCall,\n type ToolResultMessage,\n Type,\n} from '@earendil-works/pi-ai';\nimport { VoiceRequestError } from './errors.ts';\nimport type { Delivery } from './models.ts';\nimport type { RealtimeSession } from './realtime.ts';\n\nconst heardLimit = 20;\n\nexport const talkerTools = ['ask_agent', 'read'] as const;\n\nexport const askAgent: Tool = {\n name: 'ask_agent',\n description:\n 'Hand a request to the coding agent. Use for anything that needs files, the browser, tools or more than a few seconds of thought.',\n parameters: Type.Object({\n request: Type.String(),\n context: Type.Optional(Type.String()),\n }),\n};\n\nexport type ThinkerUpdate =\n | { type: 'progress'; text: string }\n | { type: 'result'; message: ToolResultMessage };\n\nexport interface Thinker {\n ask(\n request: string,\n heard: string[],\n signal: AbortSignal,\n context?: string\n ): AsyncIterable<ThinkerUpdate>;\n}\n\nexport interface BindThinkerOptions {\n progress: Delivery;\n result: Delivery;\n ack: string;\n directTimeoutMs: number;\n directMaxChars: number;\n}\n\nexport type ThinkerCaption =\n | { type: 'thinker_progress'; callId: string; text: string }\n | { type: 'thinker_result'; callId: string; summary: string; isError: boolean };\n\nexport type ThinkerPhase =\n | { phase: 'thinking' }\n | { phase: 'tool'; toolName: string; toolCallId: string; args: JsonObject }\n | { phase: 'idle' };\n\nexport interface BoundThinker {\n captions: AsyncIterable<ThinkerCaption>;\n phases: AsyncIterable<ThinkerPhase>;\n done: Promise<void>;\n}\n\nclass PushStream<T> implements AsyncIterable<T> {\n readonly #queue: T[] = [];\n readonly #waiters: Array<(result: { value?: T; done: boolean }) => void> = [];\n #closed = false;\n\n push(value: T): void {\n if (this.#closed) return;\n const waiter = this.#waiters.shift();\n if (waiter) waiter({ value, done: false });\n else this.#queue.push(value);\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n while (this.#waiters.length > 0) this.#waiters.shift()?.({ done: true });\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n while (true) {\n const queued = this.#queue.shift();\n if (queued !== undefined) {\n yield queued;\n continue;\n }\n if (this.#closed) return;\n const next = await new Promise<{ value?: T; done: boolean }>((resolve) =>\n this.#waiters.push(resolve)\n );\n if (next.done || next.value === undefined) return;\n yield next.value;\n }\n }\n}\n\nfunction send(action: () => void): void {\n try {\n action();\n } catch (error) {\n if (!(error instanceof VoiceRequestError)) throw error;\n }\n}\n\nfunction textOf(message: ToolResultMessage): string {\n return message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text)\n .join('\\n');\n}\n\nfunction acknowledged(call: ToolCall, ack: string): ToolResultMessage {\n return {\n role: 'toolResult',\n toolCallId: call.id,\n toolName: call.name,\n content: [{ type: 'text', text: ack }],\n isError: false,\n timestamp: Date.now(),\n };\n}\n\nfunction errorResult(call: ToolCall, error: unknown): ToolResultMessage {\n return {\n role: 'toolResult',\n toolCallId: call.id,\n toolName: call.name,\n content: [{ type: 'text', text: error instanceof Error ? error.message : String(error) }],\n isError: true,\n timestamp: Date.now(),\n };\n}\n\nfunction capResult(result: ToolResultMessage, maxChars: number): ToolResultMessage {\n let left = maxChars;\n const content = result.content.map((part) => {\n if (part.type !== 'text') return part;\n if (left <= 0) return { ...part, text: '' };\n if (part.text.length <= left) {\n left -= part.text.length;\n return part;\n }\n const text = part.text.slice(0, left);\n left = 0;\n return { ...part, text };\n });\n return { ...result, content };\n}\n\ninterface AskJob {\n abort: AbortController;\n answered: boolean;\n dropped: boolean;\n call: ToolCall;\n kind: 'ask' | 'direct';\n}\n\nfunction requestContext(call: ToolCall): string | undefined {\n const value = call.arguments.context;\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction track(pending: Set<Promise<void>>, promise: Promise<void>): void {\n pending.add(promise);\n void promise.finally(() => {\n pending.delete(promise);\n });\n}\n\nexport function bindThinker(\n session: RealtimeSession,\n thinker: Thinker,\n direct: (call: ToolCall, signal: AbortSignal) => Promise<ToolResultMessage>,\n options: BindThinkerOptions\n): BoundThinker {\n const captions = new PushStream<ThinkerCaption>();\n const phases = new PushStream<ThinkerPhase>();\n const done = run(session, thinker, direct, options, captions, phases).finally(() => {\n captions.close();\n phases.close();\n captions.close();\n phases.close();\n });\n return { captions, phases, done };\n}\n\nasync function run(\n session: RealtimeSession,\n thinker: Thinker,\n direct: (call: ToolCall, signal: AbortSignal) => Promise<ToolResultMessage>,\n options: BindThinkerOptions,\n captions: PushStream<ThinkerCaption>,\n phases: PushStream<ThinkerPhase>\n): Promise<void> {\n const heard: string[] = [];\n const running = new Map<string, AskJob>();\n const pending = new Set<Promise<void>>();\n for await (const event of session) {\n if (event.type === 'input_transcript' && event.final) heard.push(`user: ${event.text}`);\n if (event.type === 'output_transcript' && event.final) heard.push(`talker: ${event.text}`);\n if (event.type === 'tool_call_cancelled') {\n cancelJob(session, running, event.callId);\n continue;\n }\n if (event.type !== 'tool_call') continue;\n const call = event.call;\n if (call.name !== askAgent.name) {\n track(pending, runDirect(session, direct, options, phases, running, call));\n continue;\n }\n const job: AskJob = {\n abort: new AbortController(),\n answered: false,\n dropped: false,\n call,\n kind: 'ask',\n };\n running.set(call.id, job);\n phases.push({ phase: 'thinking' });\n if (event.blocking) send(() => session.respond(call.id, acknowledged(call, options.ack)));\n const ask = followAsk(\n session,\n thinker,\n options,\n captions,\n phases,\n running,\n heard,\n call,\n event.blocking,\n job\n );\n track(pending, ask);\n }\n for (const job of running.values()) {\n job.dropped = true;\n job.abort.abort();\n }\n await Promise.allSettled([...pending]);\n}\n\nfunction cancelJob(session: RealtimeSession, running: Map<string, AskJob>, callId: string): void {\n const job = running.get(callId);\n if (!job) return;\n job.abort.abort();\n job.dropped = true;\n if (job.kind !== 'ask' || job.answered) return;\n job.answered = true;\n send(() => session.respond(callId, errorResult(job.call, new Error('cancelled'))));\n}\n\nfunction runDirect(\n session: RealtimeSession,\n direct: (call: ToolCall, signal: AbortSignal) => Promise<ToolResultMessage>,\n options: BindThinkerOptions,\n phases: PushStream<ThinkerPhase>,\n running: Map<string, AskJob>,\n call: ToolCall\n): Promise<void> {\n const abort = new AbortController();\n const signal = AbortSignal.any([abort.signal, AbortSignal.timeout(options.directTimeoutMs)]);\n const job: AskJob = { abort, answered: false, dropped: false, call, kind: 'direct' };\n running.set(call.id, job);\n phases.push({\n phase: 'tool',\n toolName: call.name,\n toolCallId: call.id,\n args: call.arguments,\n });\n return direct(call, signal)\n .then((result) => {\n if (job.dropped) return;\n send(() => session.respond(call.id, capResult(result, options.directMaxChars)));\n })\n .catch((error: unknown) => {\n if (job.dropped) return;\n send(() => session.respond(call.id, errorResult(call, error)));\n })\n .finally(() => {\n running.delete(call.id);\n phases.push({ phase: 'idle' });\n });\n}\n\nasync function followAsk(\n session: RealtimeSession,\n thinker: Thinker,\n options: BindThinkerOptions,\n captions: PushStream<ThinkerCaption>,\n phases: PushStream<ThinkerPhase>,\n running: Map<string, AskJob>,\n heard: string[],\n call: ToolCall,\n blocking: boolean,\n job: AskJob\n): Promise<void> {\n try {\n for await (const update of thinker.ask(\n String(call.arguments.request),\n heard.slice(-heardLimit),\n job.abort.signal,\n requestContext(call)\n )) {\n if (job.abort.signal.aborted) break;\n if (update.type === 'progress') {\n captions.push({ type: 'thinker_progress', callId: call.id, text: update.text });\n send(() => session.inject(update.text, options.progress));\n continue;\n }\n job.answered = true;\n captions.push({\n type: 'thinker_result',\n callId: call.id,\n summary: textOf(update.message),\n isError: update.message.isError,\n });\n if (blocking) send(() => session.inject(textOf(update.message), options.result));\n else send(() => session.respond(call.id, update.message, options.result));\n }\n } catch (error) {\n if (job.abort.signal.aborted || job.answered) return;\n job.answered = true;\n const message = errorResult(call, error);\n captions.push({\n type: 'thinker_result',\n callId: call.id,\n summary: textOf(message),\n isError: true,\n });\n if (blocking) send(() => session.inject(textOf(message), options.result));\n else send(() => session.respond(call.id, message));\n } finally {\n running.delete(call.id);\n phases.push({ phase: 'idle' });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerFish(): () => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { registerFish } from './catalog.ts';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ProviderRequestOptions } from '@earendil-works/pi-ai';
|
|
2
|
+
import type { SpeechModel } from '../models.ts';
|
|
3
|
+
import { SpeechEventStream, type SpeechInput } from '../speech.ts';
|
|
4
|
+
export declare function speakFish(model: SpeechModel<string>, input: SpeechInput, options?: ProviderRequestOptions): SpeechEventStream;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ProviderRequestOptions } from '@earendil-works/pi-ai';
|
|
2
|
+
import type { TranscriptionModel } from '../models.ts';
|
|
3
|
+
import type { AudioInput, Transcript } from '../transcription.ts';
|
|
4
|
+
export declare function transcribeFish(model: TranscriptionModel<string>, input: AudioInput, options?: ProviderRequestOptions): Promise<Transcript>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ProviderRequestOptions } from '@earendil-works/pi-ai';
|
|
2
|
+
import type { AudioFormat } from '../audio.ts';
|
|
3
|
+
export type PackValue = null | boolean | number | string | Uint8Array | PackValue[] | {
|
|
4
|
+
[key: string]: PackValue;
|
|
5
|
+
};
|
|
6
|
+
export interface FishFile {
|
|
7
|
+
data: Uint8Array;
|
|
8
|
+
mimeType: string;
|
|
9
|
+
filename: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function pack(value: PackValue): Uint8Array;
|
|
12
|
+
export declare function unpack(data: Uint8Array): PackValue;
|
|
13
|
+
export declare function mediaType(mimeType: string): string;
|
|
14
|
+
export declare function audioFilename(mimeType: string): string;
|
|
15
|
+
export declare function encodeForm(file: FishFile, fields: Record<string, string>): ArrayBuffer;
|
|
16
|
+
export declare function formType(): string;
|
|
17
|
+
export declare function fishHeaders(model: {
|
|
18
|
+
id: string;
|
|
19
|
+
provider: string;
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
}, options: ProviderRequestOptions | undefined): Record<string, string>;
|
|
22
|
+
export declare function socketUrl(baseUrl: string, path: string): URL;
|
|
23
|
+
export declare function speechFormatName(format: AudioFormat): string;
|
|
24
|
+
export declare function connectSocket(url: string, headers: Record<string, string>): WebSocket;
|
|
25
|
+
export declare function awaitOpen(socket: WebSocket, label: string, fail: (message: string) => void): Promise<void>;
|
|
26
|
+
export declare function messageBytes(data: unknown): Promise<Uint8Array>;
|
|
27
|
+
export declare function sameFormat(left: AudioFormat, right: AudioFormat): boolean;
|
|
@@ -11,6 +11,7 @@ export interface VoiceWire {
|
|
|
11
11
|
export interface VoiceSocket {
|
|
12
12
|
send(data: string): void;
|
|
13
13
|
close(): void;
|
|
14
|
+
addEventListener(type: 'open', listener: () => void): void;
|
|
14
15
|
addEventListener(type: 'message', listener: (event: {
|
|
15
16
|
data: unknown;
|
|
16
17
|
}) => void): void;
|
package/dist/types/talker.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export type ThinkerUpdate = {
|
|
|
11
11
|
message: ToolResultMessage;
|
|
12
12
|
};
|
|
13
13
|
export interface Thinker {
|
|
14
|
-
ask(request: string, heard: string[], signal: AbortSignal): AsyncIterable<ThinkerUpdate>;
|
|
14
|
+
ask(request: string, heard: string[], signal: AbortSignal, context?: string): AsyncIterable<ThinkerUpdate>;
|
|
15
15
|
}
|
|
16
16
|
export interface BindThinkerOptions {
|
|
17
17
|
progress: Delivery;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/pi-audio",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "Voice bindings for pi: speech-to-text, text-to-speech and realtime speech for pi-coding-agent plugins and slicc-agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -54,6 +54,10 @@
|
|
|
54
54
|
"types": "./dist/types/mistral/index.d.ts",
|
|
55
55
|
"default": "./dist/mistral/index.js"
|
|
56
56
|
},
|
|
57
|
+
"./fish": {
|
|
58
|
+
"types": "./dist/types/fish/index.d.ts",
|
|
59
|
+
"default": "./dist/fish/index.js"
|
|
60
|
+
},
|
|
57
61
|
"./durable": {
|
|
58
62
|
"types": "./dist/types/durable/index.d.ts",
|
|
59
63
|
"default": "./dist/durable/index.js"
|