@oneinbox/web-sdk-react 0.1.0-beta.1 → 0.1.0-beta.3
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/dist/index.cjs +58 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +26 -7
- package/dist/index.js.map +1 -1
- package/package.json +13 -5
package/dist/index.cjs
CHANGED
|
@@ -1,25 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
6
19
|
|
|
7
20
|
// src/index.tsx
|
|
8
|
-
var
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
OneInboxProvider: () => OneInboxProvider,
|
|
24
|
+
useOneInbox: () => useOneInbox,
|
|
25
|
+
useOneInboxClient: () => useOneInboxClient
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
var import_web_sdk = require("@oneinbox/web-sdk");
|
|
29
|
+
var import_react = require("react");
|
|
30
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
31
|
+
var OneInboxContext = (0, import_react.createContext)(null);
|
|
9
32
|
function OneInboxProvider({
|
|
10
33
|
publishableKey,
|
|
11
34
|
children,
|
|
12
35
|
...config
|
|
13
36
|
}) {
|
|
14
37
|
const baseUrl = config.baseUrl;
|
|
15
|
-
const client =
|
|
16
|
-
() => new
|
|
38
|
+
const client = (0, import_react.useMemo)(
|
|
39
|
+
() => new import_web_sdk.OneInbox(publishableKey, { baseUrl }),
|
|
17
40
|
[publishableKey, baseUrl]
|
|
18
41
|
);
|
|
19
|
-
|
|
42
|
+
(0, import_react.useEffect)(() => {
|
|
43
|
+
return () => {
|
|
44
|
+
void client.stop();
|
|
45
|
+
};
|
|
46
|
+
}, [client]);
|
|
47
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OneInboxContext.Provider, { value: client, children });
|
|
20
48
|
}
|
|
21
49
|
function useOneInboxClient() {
|
|
22
|
-
const client =
|
|
50
|
+
const client = (0, import_react.useContext)(OneInboxContext);
|
|
23
51
|
if (!client) {
|
|
24
52
|
throw new Error("useOneInbox must be used within an <OneInboxProvider>.");
|
|
25
53
|
}
|
|
@@ -27,15 +55,15 @@ function useOneInboxClient() {
|
|
|
27
55
|
}
|
|
28
56
|
function useOneInbox() {
|
|
29
57
|
const client = useOneInboxClient();
|
|
30
|
-
const [status, setStatus] =
|
|
31
|
-
const [isMuted, setIsMuted] =
|
|
32
|
-
const [isAgentSpeaking, setIsAgentSpeaking] =
|
|
33
|
-
const [volume, setVolume] =
|
|
34
|
-
const [transcripts, setTranscripts] =
|
|
35
|
-
const [error, setError] =
|
|
36
|
-
const clientRef =
|
|
58
|
+
const [status, setStatus] = (0, import_react.useState)(client.status);
|
|
59
|
+
const [isMuted, setIsMuted] = (0, import_react.useState)(client.isMuted());
|
|
60
|
+
const [isAgentSpeaking, setIsAgentSpeaking] = (0, import_react.useState)(false);
|
|
61
|
+
const [volume, setVolume] = (0, import_react.useState)(0);
|
|
62
|
+
const [transcripts, setTranscripts] = (0, import_react.useState)([]);
|
|
63
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
64
|
+
const clientRef = (0, import_react.useRef)(client);
|
|
37
65
|
clientRef.current = client;
|
|
38
|
-
|
|
66
|
+
(0, import_react.useEffect)(() => {
|
|
39
67
|
const offs = [
|
|
40
68
|
client.on("status", setStatus),
|
|
41
69
|
client.on("volume-level", setVolume),
|
|
@@ -55,23 +83,26 @@ function useOneInbox() {
|
|
|
55
83
|
client.on("call-end", () => {
|
|
56
84
|
setIsAgentSpeaking(false);
|
|
57
85
|
setVolume(0);
|
|
86
|
+
setIsMuted(false);
|
|
58
87
|
})
|
|
59
88
|
];
|
|
60
89
|
return () => offs.forEach((off) => off());
|
|
61
90
|
}, [client]);
|
|
62
|
-
const start =
|
|
91
|
+
const start = (0, import_react.useCallback)(
|
|
63
92
|
(agentId, opts) => clientRef.current.start(agentId, opts),
|
|
64
93
|
[]
|
|
65
94
|
);
|
|
66
|
-
const stop =
|
|
67
|
-
const setMuted =
|
|
95
|
+
const stop = (0, import_react.useCallback)(() => clientRef.current.stop(), []);
|
|
96
|
+
const setMuted = (0, import_react.useCallback)((muted) => {
|
|
68
97
|
clientRef.current.setMuted(muted);
|
|
69
98
|
setIsMuted(muted);
|
|
70
99
|
}, []);
|
|
100
|
+
const resumeAudio = (0, import_react.useCallback)(() => clientRef.current.resumeAudio(), []);
|
|
71
101
|
return {
|
|
72
102
|
start,
|
|
73
103
|
stop,
|
|
74
104
|
setMuted,
|
|
105
|
+
resumeAudio,
|
|
75
106
|
status,
|
|
76
107
|
isMuted,
|
|
77
108
|
isAgentSpeaking,
|
|
@@ -81,9 +112,10 @@ function useOneInbox() {
|
|
|
81
112
|
client
|
|
82
113
|
};
|
|
83
114
|
}
|
|
84
|
-
|
|
85
|
-
exports
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
115
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
116
|
+
0 && (module.exports = {
|
|
117
|
+
OneInboxProvider,
|
|
118
|
+
useOneInbox,
|
|
119
|
+
useOneInboxClient
|
|
120
|
+
});
|
|
89
121
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import {\n type CallStatus,\n OneInbox,\n type OneInboxConfig,\n type OneInboxError,\n type StartOptions,\n type TranscriptEvent,\n} from \"@oneinbox/web-sdk\";\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport type { CallStatus, OneInboxError, StartOptions, TranscriptEvent };\n\nconst OneInboxContext = createContext<OneInbox | null>(null);\n\nexport interface OneInboxProviderProps extends OneInboxConfig {\n /** Publishable key (`oi_pk_…`). */\n publishableKey: string;\n children: ReactNode;\n}\n\n/**\n * Provides a single `OneInbox` instance to the tree. Place near the root.\n *\n * ```tsx\n * <OneInboxProvider publishableKey=\"oi_pk_…\">\n * <App />\n * </OneInboxProvider>\n * ```\n */\nexport function OneInboxProvider({\n publishableKey,\n children,\n ...config\n}: OneInboxProviderProps) {\n // baseUrl is the only config field today; spread keeps it forward-compatible.\n const baseUrl = config.baseUrl;\n const client = useMemo(\n () => new OneInbox(publishableKey, { baseUrl }),\n [publishableKey, baseUrl],\n );\n // Bug-fix: when publishableKey/baseUrl change, useMemo builds a fresh client.\n // Tear the previous one down (and on unmount) so its live WebRTC call doesn't\n // leak with no handle to close it.\n useEffect(() => {\n return () => {\n void client.stop();\n };\n }, [client]);\n return <OneInboxContext.Provider value={client}>{children}</OneInboxContext.Provider>;\n}\n\n/** Access the raw `OneInbox` client from context. Throws outside a provider. */\nexport function useOneInboxClient(): OneInbox {\n const client = useContext(OneInboxContext);\n if (!client) {\n throw new Error(\"useOneInbox must be used within an <OneInboxProvider>.\");\n }\n return client;\n}\n\nexport interface UseOneInbox {\n /** Start a call by agent id (publishable-key path). */\n start: (agentId: string, opts?: StartOptions) => Promise<void>;\n /** End the active call. */\n stop: () => Promise<void>;\n /** Mute/unmute the local microphone. */\n setMuted: (muted: boolean) => void;\n /** Resume audio if the browser blocked autoplay (call from a click handler). */\n resumeAudio: () => Promise<void>;\n status: CallStatus;\n isMuted: boolean;\n /** Whether the agent is currently speaking (best-effort). */\n isAgentSpeaking: boolean;\n /** Local mic level 0..1 (sampled while active). */\n volume: number;\n /** Accumulated transcript chunks (interim + final), in arrival order. */\n transcripts: TranscriptEvent[];\n /** Last error, if any. */\n error: OneInboxError | null;\n /** Escape hatch to the underlying client. */\n client: OneInbox;\n}\n\n/**\n * Subscribes to the client's events and exposes them as React state.\n *\n * ```tsx\n * const { start, stop, status, transcripts, isAgentSpeaking } = useOneInbox();\n * ```\n */\nexport function useOneInbox(): UseOneInbox {\n const client = useOneInboxClient();\n\n const [status, setStatus] = useState<CallStatus>(client.status);\n const [isMuted, setIsMuted] = useState<boolean>(client.isMuted());\n const [isAgentSpeaking, setIsAgentSpeaking] = useState(false);\n const [volume, setVolume] = useState(0);\n const [transcripts, setTranscripts] = useState<TranscriptEvent[]>([]);\n const [error, setError] = useState<OneInboxError | null>(null);\n // Keep a ref so the imperative callbacks below don't re-create per render.\n const clientRef = useRef(client);\n clientRef.current = client;\n\n useEffect(() => {\n const offs = [\n client.on(\"status\", setStatus),\n client.on(\"volume-level\", setVolume),\n client.on(\"error\", setError),\n client.on(\"transcript\", (t) => setTranscripts((prev) => [...prev, t])),\n client.on(\"speech-start\", (who) => {\n if (who === \"agent\") setIsAgentSpeaking(true);\n }),\n client.on(\"speech-end\", (who) => {\n if (who === \"agent\") setIsAgentSpeaking(false);\n }),\n client.on(\"call-start\", () => {\n setTranscripts([]);\n setError(null);\n setIsMuted(client.isMuted());\n }),\n client.on(\"call-end\", () => {\n setIsAgentSpeaking(false);\n setVolume(0);\n // Bug-fix: reset mute state too, else a call ended while muted leaves\n // isMuted stuck true on the next render.\n setIsMuted(false);\n }),\n ];\n return () => offs.forEach((off) => off());\n }, [client]);\n\n const start = useCallback(\n (agentId: string, opts?: StartOptions) => clientRef.current.start(agentId, opts),\n [],\n );\n const stop = useCallback(() => clientRef.current.stop(), []);\n const setMuted = useCallback((muted: boolean) => {\n clientRef.current.setMuted(muted);\n setIsMuted(muted);\n }, []);\n const resumeAudio = useCallback(() => clientRef.current.resumeAudio(), []);\n\n return {\n start,\n stop,\n setMuted,\n resumeAudio,\n status,\n isMuted,\n isAgentSpeaking,\n volume,\n transcripts,\n error,\n client,\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -27,6 +27,8 @@ interface UseOneInbox {
|
|
|
27
27
|
stop: () => Promise<void>;
|
|
28
28
|
/** Mute/unmute the local microphone. */
|
|
29
29
|
setMuted: (muted: boolean) => void;
|
|
30
|
+
/** Resume audio if the browser blocked autoplay (call from a click handler). */
|
|
31
|
+
resumeAudio: () => Promise<void>;
|
|
30
32
|
status: CallStatus;
|
|
31
33
|
isMuted: boolean;
|
|
32
34
|
/** Whether the agent is currently speaking (best-effort). */
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ interface UseOneInbox {
|
|
|
27
27
|
stop: () => Promise<void>;
|
|
28
28
|
/** Mute/unmute the local microphone. */
|
|
29
29
|
setMuted: (muted: boolean) => void;
|
|
30
|
+
/** Resume audio if the browser blocked autoplay (call from a click handler). */
|
|
31
|
+
resumeAudio: () => Promise<void>;
|
|
30
32
|
status: CallStatus;
|
|
31
33
|
isMuted: boolean;
|
|
32
34
|
/** Whether the agent is currently speaking (best-effort). */
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import { OneInbox } from '@oneinbox/web-sdk';
|
|
2
|
-
import { createContext, useMemo, useContext, useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
-
import { jsx } from 'react/jsx-runtime';
|
|
4
|
-
|
|
5
1
|
// src/index.tsx
|
|
2
|
+
import {
|
|
3
|
+
OneInbox
|
|
4
|
+
} from "@oneinbox/web-sdk";
|
|
5
|
+
import {
|
|
6
|
+
createContext,
|
|
7
|
+
useCallback,
|
|
8
|
+
useContext,
|
|
9
|
+
useEffect,
|
|
10
|
+
useMemo,
|
|
11
|
+
useRef,
|
|
12
|
+
useState
|
|
13
|
+
} from "react";
|
|
14
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
15
|
var OneInboxContext = createContext(null);
|
|
7
16
|
function OneInboxProvider({
|
|
8
17
|
publishableKey,
|
|
@@ -14,6 +23,11 @@ function OneInboxProvider({
|
|
|
14
23
|
() => new OneInbox(publishableKey, { baseUrl }),
|
|
15
24
|
[publishableKey, baseUrl]
|
|
16
25
|
);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
return () => {
|
|
28
|
+
void client.stop();
|
|
29
|
+
};
|
|
30
|
+
}, [client]);
|
|
17
31
|
return /* @__PURE__ */ jsx(OneInboxContext.Provider, { value: client, children });
|
|
18
32
|
}
|
|
19
33
|
function useOneInboxClient() {
|
|
@@ -53,6 +67,7 @@ function useOneInbox() {
|
|
|
53
67
|
client.on("call-end", () => {
|
|
54
68
|
setIsAgentSpeaking(false);
|
|
55
69
|
setVolume(0);
|
|
70
|
+
setIsMuted(false);
|
|
56
71
|
})
|
|
57
72
|
];
|
|
58
73
|
return () => offs.forEach((off) => off());
|
|
@@ -66,10 +81,12 @@ function useOneInbox() {
|
|
|
66
81
|
clientRef.current.setMuted(muted);
|
|
67
82
|
setIsMuted(muted);
|
|
68
83
|
}, []);
|
|
84
|
+
const resumeAudio = useCallback(() => clientRef.current.resumeAudio(), []);
|
|
69
85
|
return {
|
|
70
86
|
start,
|
|
71
87
|
stop,
|
|
72
88
|
setMuted,
|
|
89
|
+
resumeAudio,
|
|
73
90
|
status,
|
|
74
91
|
isMuted,
|
|
75
92
|
isAgentSpeaking,
|
|
@@ -79,7 +96,9 @@ function useOneInbox() {
|
|
|
79
96
|
client
|
|
80
97
|
};
|
|
81
98
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
99
|
+
export {
|
|
100
|
+
OneInboxProvider,
|
|
101
|
+
useOneInbox,
|
|
102
|
+
useOneInboxClient
|
|
103
|
+
};
|
|
85
104
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import {\n type CallStatus,\n OneInbox,\n type OneInboxConfig,\n type OneInboxError,\n type StartOptions,\n type TranscriptEvent,\n} from \"@oneinbox/web-sdk\";\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport type { CallStatus, OneInboxError, StartOptions, TranscriptEvent };\n\nconst OneInboxContext = createContext<OneInbox | null>(null);\n\nexport interface OneInboxProviderProps extends OneInboxConfig {\n /** Publishable key (`oi_pk_…`). */\n publishableKey: string;\n children: ReactNode;\n}\n\n/**\n * Provides a single `OneInbox` instance to the tree. Place near the root.\n *\n * ```tsx\n * <OneInboxProvider publishableKey=\"oi_pk_…\">\n * <App />\n * </OneInboxProvider>\n * ```\n */\nexport function OneInboxProvider({\n publishableKey,\n children,\n ...config\n}: OneInboxProviderProps) {\n // baseUrl is the only config field today; spread keeps it forward-compatible.\n const baseUrl = config.baseUrl;\n const client = useMemo(\n () => new OneInbox(publishableKey, { baseUrl }),\n [publishableKey, baseUrl],\n );\n // Bug-fix: when publishableKey/baseUrl change, useMemo builds a fresh client.\n // Tear the previous one down (and on unmount) so its live WebRTC call doesn't\n // leak with no handle to close it.\n useEffect(() => {\n return () => {\n void client.stop();\n };\n }, [client]);\n return <OneInboxContext.Provider value={client}>{children}</OneInboxContext.Provider>;\n}\n\n/** Access the raw `OneInbox` client from context. Throws outside a provider. */\nexport function useOneInboxClient(): OneInbox {\n const client = useContext(OneInboxContext);\n if (!client) {\n throw new Error(\"useOneInbox must be used within an <OneInboxProvider>.\");\n }\n return client;\n}\n\nexport interface UseOneInbox {\n /** Start a call by agent id (publishable-key path). */\n start: (agentId: string, opts?: StartOptions) => Promise<void>;\n /** End the active call. */\n stop: () => Promise<void>;\n /** Mute/unmute the local microphone. */\n setMuted: (muted: boolean) => void;\n /** Resume audio if the browser blocked autoplay (call from a click handler). */\n resumeAudio: () => Promise<void>;\n status: CallStatus;\n isMuted: boolean;\n /** Whether the agent is currently speaking (best-effort). */\n isAgentSpeaking: boolean;\n /** Local mic level 0..1 (sampled while active). */\n volume: number;\n /** Accumulated transcript chunks (interim + final), in arrival order. */\n transcripts: TranscriptEvent[];\n /** Last error, if any. */\n error: OneInboxError | null;\n /** Escape hatch to the underlying client. */\n client: OneInbox;\n}\n\n/**\n * Subscribes to the client's events and exposes them as React state.\n *\n * ```tsx\n * const { start, stop, status, transcripts, isAgentSpeaking } = useOneInbox();\n * ```\n */\nexport function useOneInbox(): UseOneInbox {\n const client = useOneInboxClient();\n\n const [status, setStatus] = useState<CallStatus>(client.status);\n const [isMuted, setIsMuted] = useState<boolean>(client.isMuted());\n const [isAgentSpeaking, setIsAgentSpeaking] = useState(false);\n const [volume, setVolume] = useState(0);\n const [transcripts, setTranscripts] = useState<TranscriptEvent[]>([]);\n const [error, setError] = useState<OneInboxError | null>(null);\n // Keep a ref so the imperative callbacks below don't re-create per render.\n const clientRef = useRef(client);\n clientRef.current = client;\n\n useEffect(() => {\n const offs = [\n client.on(\"status\", setStatus),\n client.on(\"volume-level\", setVolume),\n client.on(\"error\", setError),\n client.on(\"transcript\", (t) => setTranscripts((prev) => [...prev, t])),\n client.on(\"speech-start\", (who) => {\n if (who === \"agent\") setIsAgentSpeaking(true);\n }),\n client.on(\"speech-end\", (who) => {\n if (who === \"agent\") setIsAgentSpeaking(false);\n }),\n client.on(\"call-start\", () => {\n setTranscripts([]);\n setError(null);\n setIsMuted(client.isMuted());\n }),\n client.on(\"call-end\", () => {\n setIsAgentSpeaking(false);\n setVolume(0);\n // Bug-fix: reset mute state too, else a call ended while muted leaves\n // isMuted stuck true on the next render.\n setIsMuted(false);\n }),\n ];\n return () => offs.forEach((off) => off());\n }, [client]);\n\n const start = useCallback(\n (agentId: string, opts?: StartOptions) => clientRef.current.start(agentId, opts),\n [],\n );\n const stop = useCallback(() => clientRef.current.stop(), []);\n const setMuted = useCallback((muted: boolean) => {\n clientRef.current.setMuted(muted);\n setIsMuted(muted);\n }, []);\n const resumeAudio = useCallback(() => clientRef.current.resumeAudio(), []);\n\n return {\n start,\n stop,\n setMuted,\n resumeAudio,\n status,\n isMuted,\n isAgentSpeaking,\n volume,\n transcripts,\n error,\n client,\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oneinbox/web-sdk-react",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
4
|
-
"description": "React bindings for @oneinbox/web-sdk
|
|
3
|
+
"version": "0.1.0-beta.3",
|
|
4
|
+
"description": "React bindings for @oneinbox/web-sdk \u2014 <OneInboxProvider> + useOneInbox().",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -29,19 +29,27 @@
|
|
|
29
29
|
"prepublishOnly": "tsup"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@oneinbox/web-sdk": "^0.1.0-beta.
|
|
32
|
+
"@oneinbox/web-sdk": "^0.1.0-beta.3",
|
|
33
33
|
"livekit-client": "^2.0.0",
|
|
34
34
|
"react": "^18.0.0 || ^19.0.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@oneinbox/web-sdk": "^0.1.0-beta.
|
|
37
|
+
"@oneinbox/web-sdk": "^0.1.0-beta.3",
|
|
38
38
|
"@types/react": "^19.0.0",
|
|
39
39
|
"livekit-client": "^2.5.0",
|
|
40
40
|
"react": "^19.0.0",
|
|
41
41
|
"tsup": "^8.0.0",
|
|
42
42
|
"typescript": "^5.4.0"
|
|
43
43
|
},
|
|
44
|
-
"keywords": [
|
|
44
|
+
"keywords": [
|
|
45
|
+
"voice",
|
|
46
|
+
"ai",
|
|
47
|
+
"agents",
|
|
48
|
+
"webrtc",
|
|
49
|
+
"livekit",
|
|
50
|
+
"react",
|
|
51
|
+
"hooks"
|
|
52
|
+
],
|
|
45
53
|
"author": "OneInbox",
|
|
46
54
|
"homepage": "https://www.npmjs.com/package/@oneinbox/web-sdk-react",
|
|
47
55
|
"license": "MIT",
|