@ai-ecoverse/pi-audio 1.21.0 → 1.23.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/fish-agents/provision.ts"],
4
- "sourcesContent": ["import type { JsonObject, ProviderRequestOptions, Tool } from '@earendil-works/pi-ai';\nimport { VoiceRequestError } from '../errors.ts';\nimport {\n type CustomLlm,\n type HostedAgent,\n type HostedAgentSpec,\n type HostedCache,\n hashHostedSpec,\n hostedCacheKey,\n memoryHostedCache,\n} from '../hosted-agent.ts';\nimport type { RealtimeModel } from '../models.ts';\n\nexport interface ProvisionOptions extends ProviderRequestOptions {\n agentId?: string;\n now?: () => number;\n cache?: HostedCache;\n}\n\nconst defaultCache = memoryHostedCache();\nconst toolName = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction asVoice(error: unknown): VoiceRequestError {\n if (error instanceof VoiceRequestError) return error;\n if (error instanceof Error && error.name === 'AbortError') {\n return new VoiceRequestError('aborted', 'session aborted');\n }\n if (error instanceof Error) return new VoiceRequestError('error', error.message);\n return new VoiceRequestError('error', String(error));\n}\n\nexport function httpsOrigin(baseUrl: string): string {\n const url = new URL(baseUrl);\n let protocol = url.protocol;\n if (protocol === 'wss:') protocol = 'https:';\n if (protocol === 'ws:') protocol = 'http:';\n return `${protocol}//${url.host}`;\n}\n\nfunction mergedHeaders(\n options: ProvisionOptions,\n defaults: Record<string, string>\n): Record<string, string> {\n const headers = { ...defaults };\n const extra = options.headers;\n if (extra === undefined) return headers;\n for (const [key, value] of Object.entries(extra)) {\n if (value === null) delete headers[key];\n else headers[key] = value;\n }\n return headers;\n}\n\nfunction apiKey(options: ProvisionOptions): string {\n const key = options.apiKey;\n if (typeof key === 'string' && key.length > 0) return key;\n throw new VoiceRequestError('error', 'missing realtime credential');\n}\n\nfunction timeoutSeconds(timeoutMs: number | undefined): number {\n if (timeoutMs === undefined) return 30;\n return Math.min(120, Math.max(1, Math.round(timeoutMs / 1000)));\n}\n\nfunction argumentsOf(tool: Tool): JsonObject[] {\n const parameters = tool.parameters as unknown;\n if (!isRecord(parameters) || !isRecord(parameters.properties)) return [];\n const args: JsonObject[] = [];\n for (const [name, schema] of Object.entries(parameters.properties)) {\n const description =\n isRecord(schema) && typeof schema.description === 'string' ? schema.description : '';\n args.push({ name, description });\n }\n return args;\n}\n\nfunction clientTool(tool: Tool, timeoutMs: number | undefined): JsonObject {\n if (!toolName.test(tool.name)) {\n throw new VoiceRequestError('error', `invalid client tool name: ${tool.name}`);\n }\n return {\n tool_type: 'client',\n name: tool.name,\n description: tool.description,\n arguments: argumentsOf(tool),\n expects_response: true,\n timeout_seconds: timeoutSeconds(timeoutMs),\n };\n}\n\nfunction bearer(headers: CustomLlm['headers']): string | undefined {\n if (headers === undefined) return undefined;\n const value = headers.Authorization ?? headers.authorization;\n if (typeof value !== 'string' || value.length === 0) return undefined;\n if (value.startsWith('Bearer ')) return value.slice('Bearer '.length);\n return value;\n}\n\nfunction llmFields(llm: string | CustomLlm): JsonObject {\n if (typeof llm === 'string') return { model: llm };\n if (llm.api === 'openai-responses') {\n throw new VoiceRequestError('error', 'fish custom llm accepts openai-completions only');\n }\n const custom: JsonObject = { base_url: llm.baseUrl, model: llm.id };\n const key = bearer(llm.headers);\n if (key !== undefined) custom.api_key = key;\n return { custom };\n}\n\nexport function agentConfig(spec: HostedAgentSpec, toolIds: string[]): JsonObject {\n const prompt: JsonObject = { system_prompt: spec.instructions };\n if (spec.firstMessage !== undefined) prompt.first_message = spec.firstMessage;\n const config: JsonObject = {\n prompt,\n voice: { voice_id: spec.voice },\n llm: llmFields(spec.llm),\n };\n if (toolIds.length > 0) config.tools = { enabled: true, tool_ids: toolIds };\n return config;\n}\n\nasync function requestJson(\n fetchImpl: typeof fetch,\n url: string,\n init: RequestInit\n): Promise<Record<string, unknown>> {\n let response: Response;\n try {\n response = await fetchImpl(url, init);\n } catch (error) {\n throw asVoice(error);\n }\n if (!response.ok) {\n throw new VoiceRequestError('error', `agent request failed (${response.status})`);\n }\n if (response.status === 204) return {};\n let json: unknown;\n try {\n json = await response.json();\n } catch (error) {\n throw asVoice(error);\n }\n if (!isRecord(json)) throw new VoiceRequestError('error', 'agent response was not an object');\n return json;\n}\n\nfunction textId(\n json: Record<string, unknown>,\n field: string,\n fallback: string | undefined\n): string {\n const id = json[field];\n if (typeof id === 'string' && id.length > 0) return id;\n if (fallback !== undefined) return fallback;\n throw new VoiceRequestError('error', `agent response had no ${field}`);\n}\n\nasync function createTools(\n origin: string,\n spec: HostedAgentSpec,\n options: ProvisionOptions,\n fetchImpl: typeof fetch\n): Promise<string[]> {\n const ids: string[] = [];\n for (const tool of spec.tools) {\n const json = await requestJson(fetchImpl, `${origin}/v1/agent/tools`, {\n method: 'POST',\n headers: mergedHeaders(options, {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey(options)}`,\n }),\n body: JSON.stringify(clientTool(tool, spec.clientToolTimeoutMs)),\n signal: options.signal,\n });\n ids.push(textId(json, 'tool_id', undefined));\n }\n return ids;\n}\n\nexport async function provisionAgent(\n model: RealtimeModel<string>,\n spec: HostedAgentSpec,\n options: ProvisionOptions = {}\n): Promise<HostedAgent> {\n if (options.signal?.aborted === true) throw new VoiceRequestError('aborted', 'session aborted');\n const cache = options.cache ?? defaultCache;\n const now = options.now ?? Date.now;\n const key = hostedCacheKey(model.provider, spec.name);\n const hash = hashHostedSpec(spec);\n const cached = cache.get(key);\n if (cached !== undefined && cached.specHash === hash) return cached;\n const origin = httpsOrigin(model.baseUrl);\n const fetchImpl = options.fetch ?? globalThis.fetch;\n const toolIds = await createTools(origin, spec, options, fetchImpl);\n const config = agentConfig(spec, toolIds);\n const existing = cached?.agentId ?? options.agentId;\n const headers = mergedHeaders(options, {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey(options)}`,\n });\n const url =\n existing === undefined\n ? `${origin}/v1/agent/agents`\n : `${origin}/v1/agent/agents/${encodeURIComponent(existing)}/config`;\n const json = await requestJson(fetchImpl, url, {\n method: existing === undefined ? 'POST' : 'PATCH',\n headers,\n body: JSON.stringify(existing === undefined ? { name: spec.name, config } : config),\n signal: options.signal,\n });\n const agentId = textId(json, 'agent_id', existing);\n await requestJson(fetchImpl, `${origin}/v1/agent/agents/${encodeURIComponent(agentId)}/publish`, {\n method: 'POST',\n headers: mergedHeaders(options, { Authorization: `Bearer ${apiKey(options)}` }),\n signal: options.signal,\n });\n const agent: HostedAgent = { agentId, specHash: hash, publishedAt: now() };\n cache.set(key, agent);\n return agent;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { JsonObject, ProviderRequestOptions, Tool } from '@earendil-works/pi-ai';\nimport { fishCustomLlm } from '../custom-llm.ts';\nimport { VoiceRequestError } from '../errors.ts';\nimport {\n type CustomLlm,\n type HostedAgent,\n type HostedAgentSpec,\n type HostedCache,\n hashHostedSpec,\n hostedCacheKey,\n memoryHostedCache,\n} from '../hosted-agent.ts';\nimport type { RealtimeModel } from '../models.ts';\n\nexport interface ProvisionOptions extends ProviderRequestOptions {\n agentId?: string;\n now?: () => number;\n cache?: HostedCache;\n}\n\nconst defaultCache = memoryHostedCache();\nconst toolName = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction asVoice(error: unknown): VoiceRequestError {\n if (error instanceof VoiceRequestError) return error;\n if (error instanceof Error && error.name === 'AbortError') {\n return new VoiceRequestError('aborted', 'session aborted');\n }\n if (error instanceof Error) return new VoiceRequestError('error', error.message);\n return new VoiceRequestError('error', String(error));\n}\n\nexport function httpsOrigin(baseUrl: string): string {\n const url = new URL(baseUrl);\n let protocol = url.protocol;\n if (protocol === 'wss:') protocol = 'https:';\n if (protocol === 'ws:') protocol = 'http:';\n return `${protocol}//${url.host}`;\n}\n\nfunction mergedHeaders(\n options: ProvisionOptions,\n defaults: Record<string, string>\n): Record<string, string> {\n const headers = { ...defaults };\n const extra = options.headers;\n if (extra === undefined) return headers;\n for (const [key, value] of Object.entries(extra)) {\n if (value === null) delete headers[key];\n else headers[key] = value;\n }\n return headers;\n}\n\nfunction apiKey(options: ProvisionOptions): string {\n const key = options.apiKey;\n if (typeof key === 'string' && key.length > 0) return key;\n throw new VoiceRequestError('error', 'missing realtime credential');\n}\n\nfunction timeoutSeconds(timeoutMs: number | undefined): number {\n if (timeoutMs === undefined) return 30;\n return Math.min(120, Math.max(1, Math.round(timeoutMs / 1000)));\n}\n\nfunction argumentsOf(tool: Tool): JsonObject[] {\n const parameters = tool.parameters as unknown;\n if (!isRecord(parameters) || !isRecord(parameters.properties)) return [];\n const args: JsonObject[] = [];\n for (const [name, schema] of Object.entries(parameters.properties)) {\n const description =\n isRecord(schema) && typeof schema.description === 'string' ? schema.description : '';\n args.push({ name, description });\n }\n return args;\n}\n\nfunction clientTool(tool: Tool, timeoutMs: number | undefined): JsonObject {\n if (!toolName.test(tool.name)) {\n throw new VoiceRequestError('error', `invalid client tool name: ${tool.name}`);\n }\n return {\n tool_type: 'client',\n name: tool.name,\n description: tool.description,\n arguments: argumentsOf(tool),\n expects_response: true,\n timeout_seconds: timeoutSeconds(timeoutMs),\n };\n}\n\nfunction llmFields(llm: string | CustomLlm): JsonObject {\n if (typeof llm === 'string') return { model: llm };\n return fishCustomLlm(llm);\n}\n\nexport function agentConfig(spec: HostedAgentSpec, toolIds: string[]): JsonObject {\n const prompt: JsonObject = { system_prompt: spec.instructions };\n if (spec.firstMessage !== undefined) prompt.first_message = spec.firstMessage;\n const config: JsonObject = {\n prompt,\n voice: { voice_id: spec.voice },\n llm: llmFields(spec.llm),\n };\n if (toolIds.length > 0) config.tools = { enabled: true, tool_ids: toolIds };\n return config;\n}\n\nasync function requestJson(\n fetchImpl: typeof fetch,\n url: string,\n init: RequestInit\n): Promise<Record<string, unknown>> {\n let response: Response;\n try {\n response = await fetchImpl(url, init);\n } catch (error) {\n throw asVoice(error);\n }\n if (!response.ok) {\n throw new VoiceRequestError('error', `agent request failed (${response.status})`);\n }\n if (response.status === 204) return {};\n let json: unknown;\n try {\n json = await response.json();\n } catch (error) {\n throw asVoice(error);\n }\n if (!isRecord(json)) throw new VoiceRequestError('error', 'agent response was not an object');\n return json;\n}\n\nfunction textId(\n json: Record<string, unknown>,\n field: string,\n fallback: string | undefined\n): string {\n const id = json[field];\n if (typeof id === 'string' && id.length > 0) return id;\n if (fallback !== undefined) return fallback;\n throw new VoiceRequestError('error', `agent response had no ${field}`);\n}\n\nasync function createTools(\n origin: string,\n spec: HostedAgentSpec,\n options: ProvisionOptions,\n fetchImpl: typeof fetch\n): Promise<string[]> {\n const ids: string[] = [];\n for (const tool of spec.tools) {\n const json = await requestJson(fetchImpl, `${origin}/v1/agent/tools`, {\n method: 'POST',\n headers: mergedHeaders(options, {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey(options)}`,\n }),\n body: JSON.stringify(clientTool(tool, spec.clientToolTimeoutMs)),\n signal: options.signal,\n });\n ids.push(textId(json, 'tool_id', undefined));\n }\n return ids;\n}\n\nexport async function provisionAgent(\n model: RealtimeModel<string>,\n spec: HostedAgentSpec,\n options: ProvisionOptions = {}\n): Promise<HostedAgent> {\n if (options.signal?.aborted === true) throw new VoiceRequestError('aborted', 'session aborted');\n const cache = options.cache ?? defaultCache;\n const now = options.now ?? Date.now;\n const key = hostedCacheKey(model.provider, spec.name);\n const hash = hashHostedSpec(spec);\n const cached = cache.get(key);\n if (cached !== undefined && cached.specHash === hash) return cached;\n const origin = httpsOrigin(model.baseUrl);\n const fetchImpl = options.fetch ?? globalThis.fetch;\n const toolIds = await createTools(origin, spec, options, fetchImpl);\n const config = agentConfig(spec, toolIds);\n const existing = cached?.agentId ?? options.agentId;\n const headers = mergedHeaders(options, {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey(options)}`,\n });\n const url =\n existing === undefined\n ? `${origin}/v1/agent/agents`\n : `${origin}/v1/agent/agents/${encodeURIComponent(existing)}/config`;\n const json = await requestJson(fetchImpl, url, {\n method: existing === undefined ? 'POST' : 'PATCH',\n headers,\n body: JSON.stringify(existing === undefined ? { name: spec.name, config } : config),\n signal: options.signal,\n });\n const agentId = textId(json, 'agent_id', existing);\n await requestJson(fetchImpl, `${origin}/v1/agent/agents/${encodeURIComponent(agentId)}/publish`, {\n method: 'POST',\n headers: mergedHeaders(options, { Authorization: `Bearer ${apiKey(options)}` }),\n signal: options.signal,\n });\n const agent: HostedAgent = { agentId, specHash: hash, publishedAt: now() };\n cache.set(key, agent);\n return agent;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1 @@
1
+ export declare function registerCloudflare(): () => void;
@@ -0,0 +1 @@
1
+ export { registerCloudflare } from './catalog.ts';
@@ -0,0 +1,4 @@
1
+ import type { AudioSource } from '../audio.ts';
2
+ import type { TranscriptionModel } from '../models.ts';
3
+ import { type ListenOptions, TranscriptionEventStream } from '../transcription.ts';
4
+ export declare function listenCloudflare(model: TranscriptionModel<string>, audio: AudioSource, options?: ListenOptions): TranscriptionEventStream;
@@ -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 speakCloudflare(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 transcribeCloudflare(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
+ interface RouteModel {
4
+ provider: string;
5
+ baseUrl: string;
6
+ headers?: Record<string, string>;
7
+ }
8
+ export interface CloudflareRoute {
9
+ headers: Record<string, string>;
10
+ account: string;
11
+ gateway: string;
12
+ }
13
+ export declare function gatewayId(headers: Record<string, string>): string;
14
+ export declare function session(model: RouteModel, options: ProviderRequestOptions | undefined): CloudflareRoute;
15
+ export declare function runUrl(baseUrl: string, modelId: string, account: string): string;
16
+ export declare function workersAiSocket(account: string, gateway: string, modelId: string, query: string): string;
17
+ export declare function auraEncoding(format: AudioFormat): string;
18
+ export declare function listenQuery(modelId: string, format: AudioFormat): string;
19
+ export declare function sameFormat(left: AudioFormat, right: AudioFormat): boolean;
20
+ export declare function connectSocket(url: string, headers: Record<string, string>): WebSocket;
21
+ export declare function awaitOpen(socket: WebSocket, label: string, fail: (message: string) => void): Promise<void>;
22
+ export declare function audioFrame(data: Uint8Array): ArrayBuffer;
23
+ export declare function messageBytes(data: unknown): Promise<Uint8Array | undefined>;
24
+ export declare function failureMessage(body: Record<string, unknown>, fallback: string): string;
25
+ export declare function resultOf(body: unknown): unknown;
26
+ export declare function errorText(text: string, status: number): string;
27
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { JsonObject } from '@earendil-works/pi-ai';
2
+ import type { CustomLlm } from './hosted-agent.ts';
3
+ export declare function elevenLabsCustomLlm(llm: CustomLlm): JsonObject;
4
+ export declare function fishCustomLlm(llm: CustomLlm): JsonObject;
@@ -2,6 +2,7 @@ import type { RealtimeModel } from '../models.ts';
2
2
  import type { ElevenLabsOptions } from './session.ts';
3
3
  export declare const elevenLabsAgent: RealtimeModel<'elevenlabs-agents'>;
4
4
  export declare function registerElevenLabsAgents(options?: ElevenLabsOptions): () => void;
5
+ export { elevenLabsCustomLlm } from '../custom-llm.ts';
5
6
  export type { CustomLlm, HostedAgent, HostedAgentSpec, HostedCache } from '../hosted-agent.ts';
6
7
  export { hashHostedSpec, memoryHostedCache } from '../hosted-agent.ts';
7
8
  export type { ProvisionOptions } from './provision.ts';
@@ -2,6 +2,7 @@ import type { RealtimeModel } from '../models.ts';
2
2
  import type { FishOptions } from './session.ts';
3
3
  export declare const fishAgent: RealtimeModel<'fish-agents'>;
4
4
  export declare function registerFishAgents(options?: FishOptions): () => void;
5
+ export { fishCustomLlm } from '../custom-llm.ts';
5
6
  export type { CustomLlm, HostedAgent, HostedAgentSpec, HostedCache } from '../hosted-agent.ts';
6
7
  export { hashHostedSpec, memoryHostedCache } from '../hosted-agent.ts';
7
8
  export type { ProvisionOptions } from './provision.ts';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/pi-audio",
3
- "version": "1.21.0",
3
+ "version": "1.23.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",
@@ -62,6 +62,10 @@
62
62
  "types": "./dist/types/google/index.d.ts",
63
63
  "default": "./dist/google/index.js"
64
64
  },
65
+ "./cloudflare": {
66
+ "types": "./dist/types/cloudflare/index.d.ts",
67
+ "default": "./dist/cloudflare/index.js"
68
+ },
65
69
  "./durable": {
66
70
  "types": "./dist/types/durable/index.d.ts",
67
71
  "default": "./dist/durable/index.js"