@shogo-ai/voice 1.10.0 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +89 -0
  2. package/dist/{chunk-S3S2RNO6.js → chunk-BI6SL35K.js} +1 -184
  3. package/dist/chunk-IOFWML5L.js +1078 -0
  4. package/dist/chunk-KMSL5PWK.js +540 -0
  5. package/dist/chunk-ME3SIZZU.js +581 -0
  6. package/dist/{chunk-T3T4EBWY.js → chunk-RALZRMFL.js} +6 -2
  7. package/dist/chunk-TQOBJMEK.js +17 -0
  8. package/dist/chunk-U5UC7ZVS.js +988 -0
  9. package/dist/chunk-UW7VQ3S6.js +148 -0
  10. package/dist/chunk-ZAW6F3YT.js +172 -0
  11. package/dist/index.cjs +748 -25
  12. package/dist/index.d.cts +396 -3
  13. package/dist/index.d.ts +396 -3
  14. package/dist/index.js +63 -3
  15. package/dist/live/client.cjs +173 -0
  16. package/dist/live/client.d.cts +132 -0
  17. package/dist/live/client.d.ts +132 -0
  18. package/dist/live/client.js +9 -0
  19. package/dist/native/index.d.cts +5 -2
  20. package/dist/native/index.d.ts +5 -2
  21. package/dist/native/index.js +15 -11
  22. package/dist/{organicParticlesShaders-DIva0vBO.d.ts → organicParticlesShaders-seZq7jYX.d.cts} +1 -421
  23. package/dist/{organicParticlesShaders-DIva0vBO.d.cts → organicParticlesShaders-seZq7jYX.d.ts} +1 -421
  24. package/dist/particlesConfig-0YbdPOdY.d.cts +223 -0
  25. package/dist/particlesConfig-0YbdPOdY.d.ts +223 -0
  26. package/dist/react/conversation.cjs +789 -0
  27. package/dist/react/conversation.d.cts +134 -0
  28. package/dist/react/conversation.d.ts +134 -0
  29. package/dist/react/conversation.js +13 -0
  30. package/dist/react/index.cjs +374 -36
  31. package/dist/react/index.d.cts +10 -141
  32. package/dist/react/index.d.ts +10 -141
  33. package/dist/react/index.js +23 -770
  34. package/dist/react/visuals.cjs +1048 -0
  35. package/dist/react/visuals.d.cts +70 -0
  36. package/dist/react/visuals.d.ts +70 -0
  37. package/dist/react/visuals.js +10 -0
  38. package/dist/route/agent.cjs +1047 -85
  39. package/dist/route/agent.js +3 -3
  40. package/dist/route/audio-tags.cjs +1047 -85
  41. package/dist/route/audio-tags.js +3 -3
  42. package/dist/route/index.cjs +1051 -85
  43. package/dist/route/index.d.cts +19 -3
  44. package/dist/route/index.d.ts +19 -3
  45. package/dist/route/index.js +3 -3
  46. package/dist/route/music.cjs +1047 -85
  47. package/dist/route/music.js +3 -3
  48. package/dist/route/op.cjs +2127 -0
  49. package/dist/route/op.d.cts +43 -0
  50. package/dist/route/op.d.ts +43 -0
  51. package/dist/route/op.js +27 -0
  52. package/dist/route/signed-url.cjs +1047 -85
  53. package/dist/route/signed-url.js +3 -3
  54. package/dist/route/tts-preview.cjs +1047 -85
  55. package/dist/route/tts-preview.d.cts +6 -4
  56. package/dist/route/tts-preview.d.ts +6 -4
  57. package/dist/route/tts-preview.js +3 -3
  58. package/dist/server.cjs +1047 -85
  59. package/dist/server.d.cts +40 -8
  60. package/dist/server.d.ts +40 -8
  61. package/dist/server.js +2 -2
  62. package/dist/types-Bfhu-aQH.d.cts +199 -0
  63. package/dist/types-Bfhu-aQH.d.ts +199 -0
  64. package/dist/{types-W9y6eMj3.d.ts → types-CadjTXNH.d.cts} +193 -12
  65. package/dist/{types-W9y6eMj3.d.cts → types-CadjTXNH.d.ts} +193 -12
  66. package/package.json +21 -1
  67. package/dist/chunk-B4JC3DK2.js +0 -529
  68. package/dist/chunk-O362EJQR.js +0 -524
@@ -0,0 +1,148 @@
1
+ // src/live/client.ts
2
+ function encodeAudio(audio) {
3
+ if (typeof btoa === "function") {
4
+ let binary = "";
5
+ for (let i = 0; i < audio.length; i += 32768) {
6
+ binary += String.fromCharCode(...audio.subarray(i, i + 32768));
7
+ }
8
+ return btoa(binary);
9
+ }
10
+ const BufferImpl = globalThis.Buffer;
11
+ if (BufferImpl) return BufferImpl.from(audio).toString("base64");
12
+ throw new Error("Base64 encoding is unavailable in this runtime");
13
+ }
14
+ function normalizeBaseUrl(value) {
15
+ return value.replace(/\/+$/, "");
16
+ }
17
+ var LiveSession = class {
18
+ constructor(socket, initialSession) {
19
+ this.socket = socket;
20
+ this.initialSession = initialSession;
21
+ this.handlers = /* @__PURE__ */ new Map();
22
+ this.closed = false;
23
+ this.latestUsageSeconds = 0;
24
+ this.startedPromise = new Promise((resolve, reject) => {
25
+ this.resolveStarted = resolve;
26
+ this.rejectStarted = reject;
27
+ });
28
+ this.started = this.startedPromise;
29
+ this.closedPromise = new Promise((resolve) => {
30
+ this.resolveClosed = resolve;
31
+ });
32
+ socket.addEventListener("message", (message) => {
33
+ const raw = typeof message.data === "string" ? message.data : "";
34
+ if (!raw) return;
35
+ let event;
36
+ try {
37
+ event = JSON.parse(raw);
38
+ } catch {
39
+ return;
40
+ }
41
+ if (event.type === "session.started") this.resolveStarted(event);
42
+ if (event.type === "session.usage.updated") {
43
+ const seconds = event.usage?.seconds;
44
+ if (typeof seconds === "number") this.latestUsageSeconds = seconds;
45
+ }
46
+ if (event.type === "session.closed") {
47
+ this.closed = true;
48
+ this.resolveClosed(event);
49
+ }
50
+ if (event.type === "error" && !this.closed) {
51
+ const messageText = String(event.error?.message || "Live session error");
52
+ this.rejectStarted(new Error(messageText));
53
+ }
54
+ for (const handler of this.handlers.get(String(event.type)) ?? []) handler(event);
55
+ for (const handler of this.handlers.get("*") ?? []) handler(event);
56
+ });
57
+ socket.addEventListener("close", () => {
58
+ if (!this.closed) this.resolveClosed();
59
+ });
60
+ socket.addEventListener("error", () => {
61
+ if (!this.closed) this.rejectStarted(new Error("Live session WebSocket error"));
62
+ });
63
+ socket.addEventListener("open", () => {
64
+ if (initialSession) this.send({ type: "session.start", session: initialSession });
65
+ });
66
+ }
67
+ on(eventType, handler) {
68
+ const handlers = this.handlers.get(eventType) ?? /* @__PURE__ */ new Set();
69
+ handlers.add(handler);
70
+ this.handlers.set(eventType, handlers);
71
+ return () => handlers.delete(handler);
72
+ }
73
+ send(event) {
74
+ if (this.closed) throw new Error("Live session is closed");
75
+ this.socket.send(JSON.stringify(event));
76
+ }
77
+ appendAudio(audio) {
78
+ this.send({
79
+ type: "session.input_audio.append",
80
+ audio: typeof audio === "string" ? audio : encodeAudio(audio)
81
+ });
82
+ }
83
+ async close(timeoutMs = 15e3) {
84
+ if (this.closed) return;
85
+ if (this.socket.readyState === 1) this.send({ type: "session.close" });
86
+ const timeout = new Promise((resolve) => setTimeout(resolve, timeoutMs));
87
+ const result = await Promise.race([this.closedPromise, timeout]);
88
+ if (!this.closed) this.socket.close();
89
+ return result;
90
+ }
91
+ };
92
+ var ShogoLiveClient = class {
93
+ constructor(options) {
94
+ if (!!options.apiKey === !!options.runtimeToken) {
95
+ throw new Error("ShogoLiveClient requires exactly one of apiKey or runtimeToken.");
96
+ }
97
+ this.apiUrl = normalizeBaseUrl(options.apiUrl);
98
+ this.token = options.apiKey ?? options.runtimeToken;
99
+ this.fetchImpl = options.fetch ?? globalThis.fetch;
100
+ this.WebSocketImpl = options.WebSocket ?? globalThis.WebSocket;
101
+ if (typeof this.fetchImpl !== "function") throw new Error("fetch is unavailable");
102
+ if (typeof this.WebSocketImpl !== "function") throw new Error("WebSocket is unavailable");
103
+ }
104
+ httpUrl(path) {
105
+ return `${this.apiUrl}${path}`;
106
+ }
107
+ wsUrl(path) {
108
+ return this.httpUrl(path).replace(/^http/, "ws");
109
+ }
110
+ protocols() {
111
+ return ["shogo-live", `shogo-insecure-api-key.${this.token}`];
112
+ }
113
+ connect(session) {
114
+ const socket = new this.WebSocketImpl(this.wsUrl("/api/ai/v1/live/sessions"), this.protocols());
115
+ return new LiveSession(socket, session);
116
+ }
117
+ attach(sessionId) {
118
+ const socket = new this.WebSocketImpl(
119
+ this.wsUrl(`/api/ai/v1/live/sessions/${encodeURIComponent(sessionId)}/attach`),
120
+ this.protocols()
121
+ );
122
+ return new LiveSession(socket);
123
+ }
124
+ async createWebRtcSession(input) {
125
+ const response = await this.fetchImpl(this.httpUrl("/api/ai/v1/live/sessions"), {
126
+ method: "POST",
127
+ headers: {
128
+ Authorization: `Bearer ${this.token}`,
129
+ "Content-Type": "application/json"
130
+ },
131
+ body: JSON.stringify({
132
+ session: input.session,
133
+ transport: { type: "webrtc", sdp: input.sdp }
134
+ })
135
+ });
136
+ const body = await response.json();
137
+ if (!response.ok) {
138
+ throw new Error(body?.error?.message || `Live session creation failed (${response.status})`);
139
+ }
140
+ return body;
141
+ }
142
+ };
143
+
144
+ export {
145
+ LiveSession,
146
+ ShogoLiveClient
147
+ };
148
+ //# sourceMappingURL=chunk-UW7VQ3S6.js.map
@@ -0,0 +1,172 @@
1
+ import {
2
+ stripAudioTags
3
+ } from "./chunk-Q3TJAJ54.js";
4
+
5
+ // src/shared/postJson.ts
6
+ function createPostJson({
7
+ authHeaders,
8
+ fetchCredentials
9
+ }) {
10
+ return async function postJson(path, body) {
11
+ return fetch(path, {
12
+ method: "POST",
13
+ headers: { "content-type": "application/json", ...authHeaders() },
14
+ credentials: fetchCredentials,
15
+ body: JSON.stringify(body)
16
+ });
17
+ };
18
+ }
19
+
20
+ // src/shared/memory.ts
21
+ function createMemoryAddTool({
22
+ postJson,
23
+ memoryAddPath
24
+ }) {
25
+ return async (params) => {
26
+ const fact = typeof params.fact === "string" ? params.fact : "";
27
+ if (!fact.trim()) return "Memory save failed: empty fact.";
28
+ try {
29
+ const res = await postJson(memoryAddPath, { fact });
30
+ if (!res.ok) return "Failed to save memory.";
31
+ return "Memory saved.";
32
+ } catch {
33
+ return "Memory save failed.";
34
+ }
35
+ };
36
+ }
37
+ function createMemoryContextInjector({
38
+ postJson,
39
+ memoryRetrievePath,
40
+ conversationRef,
41
+ enabled,
42
+ lastInjectedRef
43
+ }) {
44
+ return async function inject(userText) {
45
+ if (!enabled) return;
46
+ try {
47
+ const res = await postJson(memoryRetrievePath, { query: userText, limit: 4 });
48
+ if (!res.ok) return;
49
+ const data = await res.json();
50
+ const results = data.results ?? [];
51
+ if (!results.length) return;
52
+ const lines = results.map((r) => `- ${r.chunk.trim().replace(/\s+/g, " ").slice(0, 200)}`).join("\n");
53
+ if (lines === lastInjectedRef.current) return;
54
+ lastInjectedRef.current = lines;
55
+ const payload = `Relevant memory about this user:
56
+ ${lines}`;
57
+ conversationRef.current?.sendContextualUpdate(payload);
58
+ } catch {
59
+ }
60
+ };
61
+ }
62
+
63
+ // src/shared/transcript.ts
64
+ function createTranscriptDisconnectHandler({
65
+ isRestartingRef,
66
+ weStartedSessionRef,
67
+ transcriptRef,
68
+ onTranscript,
69
+ transcriptIngestPath,
70
+ postJson
71
+ }) {
72
+ return function handleTranscriptOnDisconnect() {
73
+ if (isRestartingRef.current) {
74
+ return;
75
+ }
76
+ if (!weStartedSessionRef.current) {
77
+ transcriptRef.current = [];
78
+ return;
79
+ }
80
+ weStartedSessionRef.current = false;
81
+ const transcript = transcriptRef.current.join("\n");
82
+ transcriptRef.current = [];
83
+ if (onTranscript) {
84
+ void onTranscript(transcript);
85
+ return;
86
+ }
87
+ const trimmed = transcript.trim();
88
+ if (trimmed.length < 20) return;
89
+ void postJson(transcriptIngestPath, { transcript: trimmed }).catch(() => {
90
+ });
91
+ };
92
+ }
93
+ function appendTranscriptLine(msg, { transcriptRef, weStartedSessionRef }) {
94
+ if (!msg?.message || !msg?.source) return;
95
+ if (!weStartedSessionRef.current) return;
96
+ const speaker = msg.source === "user" ? "User" : "Agent";
97
+ const cleaned = msg.source === "user" ? msg.message : stripAudioTags(msg.message);
98
+ if (!cleaned) return;
99
+ transcriptRef.current.push(`${speaker}: ${cleaned}`);
100
+ }
101
+
102
+ // src/shared/sessionPayload.ts
103
+ function sanitizeDynamicVariables(raw) {
104
+ if (raw == null) return {};
105
+ const out = {};
106
+ for (const [k, v] of Object.entries(raw)) {
107
+ if (v == null) continue;
108
+ out[k] = typeof v === "string" ? v : String(v);
109
+ }
110
+ return out;
111
+ }
112
+ function buildSessionPayload(opts) {
113
+ const dynamicVariables = {
114
+ ...sanitizeDynamicVariables(opts.dynamicVariables),
115
+ character_name: opts.characterName,
116
+ user_context: opts.userContext
117
+ };
118
+ if (typeof opts.conversationId === "string" && opts.conversationId.length > 0) {
119
+ dynamicVariables.conversation_id = opts.conversationId;
120
+ }
121
+ const payload = {
122
+ signedUrl: opts.signedUrl,
123
+ dynamicVariables
124
+ };
125
+ const agentOverrides = {};
126
+ if (opts.suppressFirstMessage) {
127
+ agentOverrides.firstMessage = "";
128
+ }
129
+ if (typeof opts.agentPromptOverride === "string" && opts.agentPromptOverride.length > 0) {
130
+ agentOverrides.prompt = { prompt: opts.agentPromptOverride };
131
+ }
132
+ if (Object.keys(agentOverrides).length > 0) {
133
+ payload.overrides = { agent: agentOverrides };
134
+ }
135
+ return payload;
136
+ }
137
+ async function fetchSignedUrl({
138
+ path,
139
+ fetchCredentials,
140
+ authHeaders
141
+ }) {
142
+ const res = await fetch(path, {
143
+ credentials: fetchCredentials,
144
+ headers: authHeaders()
145
+ });
146
+ if (!res.ok) throw new Error(`Signed URL request failed: ${res.status}`);
147
+ return await res.json();
148
+ }
149
+ function withProjectQuery(signedUrlPath, params) {
150
+ const tail = [];
151
+ if (typeof params.projectId === "string" && params.projectId.length > 0) {
152
+ tail.push(`projectId=${encodeURIComponent(params.projectId)}`);
153
+ }
154
+ if (typeof params.agentName === "string" && params.agentName.length > 0) {
155
+ tail.push(`agentName=${encodeURIComponent(params.agentName)}`);
156
+ }
157
+ if (tail.length === 0) return signedUrlPath;
158
+ const sep = signedUrlPath.includes("?") ? "&" : "?";
159
+ return `${signedUrlPath}${sep}${tail.join("&")}`;
160
+ }
161
+
162
+ export {
163
+ createPostJson,
164
+ createMemoryAddTool,
165
+ createMemoryContextInjector,
166
+ createTranscriptDisconnectHandler,
167
+ appendTranscriptLine,
168
+ buildSessionPayload,
169
+ fetchSignedUrl,
170
+ withProjectQuery
171
+ };
172
+ //# sourceMappingURL=chunk-ZAW6F3YT.js.map