@byteoniclabs/intake 1.0.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 +187 -0
- package/dist/index.d.mts +42 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +166 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +138 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react/index.d.mts +51 -0
- package/dist/react/index.d.ts +51 -0
- package/dist/react/index.js +392 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +349 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/server.d.mts +42 -0
- package/dist/server.d.ts +42 -0
- package/dist/server.js +105 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +80 -0
- package/dist/server.mjs.map +1 -0
- package/dist/types-1XzE88JK.d.mts +13 -0
- package/dist/types-1XzE88JK.d.ts +13 -0
- package/package.json +62 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { S as SubmissionResponse, B as ByteonicConfig } from '../types-1XzE88JK.js';
|
|
2
|
+
import React$1, { ReactNode } from 'react';
|
|
3
|
+
import { ByteonicClient, ChatMessage, ChatbotConfig } from '../index.js';
|
|
4
|
+
|
|
5
|
+
interface UseByteonicIntakeOptions {
|
|
6
|
+
formSlug: string;
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
}
|
|
10
|
+
declare function useByteonicIntake<T = Record<string, any>>(options: UseByteonicIntakeOptions | string): {
|
|
11
|
+
submit: (data: T | FormData | React.FormEvent<HTMLFormElement>) => Promise<SubmissionResponse | {
|
|
12
|
+
success: boolean;
|
|
13
|
+
error: any;
|
|
14
|
+
}>;
|
|
15
|
+
isLoading: boolean;
|
|
16
|
+
isSuccess: boolean;
|
|
17
|
+
error: string | null;
|
|
18
|
+
response: SubmissionResponse | null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
interface ByteonicProviderProps extends ByteonicConfig {
|
|
22
|
+
children: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
declare function ByteonicProvider({ apiKey, baseUrl, children }: ByteonicProviderProps): React$1.JSX.Element;
|
|
25
|
+
declare function useByteonicClient(): ByteonicClient;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A hidden input field used to trick bots into filling it out.
|
|
29
|
+
* If this field is submitted, Byteonic Intake will ignore the submission, protecting you from spam.
|
|
30
|
+
*
|
|
31
|
+
* Simply place `<ByteonicHoneypot />` anywhere inside your `<form>` element.
|
|
32
|
+
*/
|
|
33
|
+
declare function ByteonicHoneypot(): React$1.JSX.Element;
|
|
34
|
+
|
|
35
|
+
interface UseByteonicChatbotOptions {
|
|
36
|
+
botId: string;
|
|
37
|
+
apiKey?: string;
|
|
38
|
+
baseUrl?: string;
|
|
39
|
+
stream?: boolean;
|
|
40
|
+
}
|
|
41
|
+
declare function useByteonicChatbot(options: UseByteonicChatbotOptions | string): {
|
|
42
|
+
messages: ChatMessage[];
|
|
43
|
+
sendMessage: (content: string) => Promise<void>;
|
|
44
|
+
isLoading: boolean;
|
|
45
|
+
isStreaming: boolean;
|
|
46
|
+
streamedMessage: string;
|
|
47
|
+
config: ChatbotConfig | null;
|
|
48
|
+
clearHistory: () => void;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { ByteonicHoneypot, ByteonicProvider, useByteonicChatbot, useByteonicClient, useByteonicIntake };
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/react/index.ts
|
|
31
|
+
var react_exports = {};
|
|
32
|
+
__export(react_exports, {
|
|
33
|
+
ByteonicHoneypot: () => ByteonicHoneypot,
|
|
34
|
+
ByteonicProvider: () => ByteonicProvider,
|
|
35
|
+
useByteonicChatbot: () => useByteonicChatbot,
|
|
36
|
+
useByteonicClient: () => useByteonicClient,
|
|
37
|
+
useByteonicIntake: () => useByteonicIntake
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(react_exports);
|
|
40
|
+
|
|
41
|
+
// src/react/useForm.ts
|
|
42
|
+
var import_react2 = require("react");
|
|
43
|
+
|
|
44
|
+
// src/react/provider.tsx
|
|
45
|
+
var import_react = __toESM(require("react"));
|
|
46
|
+
|
|
47
|
+
// src/client.ts
|
|
48
|
+
var ByteonicClient = class {
|
|
49
|
+
constructor(config) {
|
|
50
|
+
if (!config.apiKey) {
|
|
51
|
+
throw new Error("[Byteonic Intake] API Key is required");
|
|
52
|
+
}
|
|
53
|
+
this.apiKey = config.apiKey;
|
|
54
|
+
this.baseUrl = config.baseUrl || "https://intake.byteoniclabs.com/api/external";
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Submit form data to Byteonic Intake
|
|
58
|
+
* @param formSlug The slug of the form to submit to
|
|
59
|
+
* @param data The form data (Record<string, any> or FormData)
|
|
60
|
+
*/
|
|
61
|
+
async submit(formSlug, data) {
|
|
62
|
+
const url = `${this.baseUrl}/forms/${formSlug}/submit`;
|
|
63
|
+
const meta = {
|
|
64
|
+
sdk_version: "1.0.0",
|
|
65
|
+
source_url: typeof window !== "undefined" ? window.location.href : "server",
|
|
66
|
+
submission_source: "byteonic_intake_sdk"
|
|
67
|
+
};
|
|
68
|
+
let fetchOptions = {
|
|
69
|
+
method: "POST",
|
|
70
|
+
headers: {
|
|
71
|
+
"Authorization": `Bearer ${this.apiKey}`
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
if (typeof FormData !== "undefined" && data instanceof FormData) {
|
|
75
|
+
data.append("_meta", JSON.stringify(meta));
|
|
76
|
+
fetchOptions.body = data;
|
|
77
|
+
} else {
|
|
78
|
+
const payload = data;
|
|
79
|
+
payload._meta = meta;
|
|
80
|
+
fetchOptions.headers = {
|
|
81
|
+
...fetchOptions.headers,
|
|
82
|
+
"Content-Type": "application/json"
|
|
83
|
+
};
|
|
84
|
+
fetchOptions.body = JSON.stringify(payload);
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const response = await fetch(url, fetchOptions);
|
|
88
|
+
const responseData = await response.json().catch(() => ({}));
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
throw new Error(responseData.error || responseData.message || "Submission failed");
|
|
91
|
+
}
|
|
92
|
+
return responseData;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
return {
|
|
95
|
+
success: false,
|
|
96
|
+
error: error.message || "An unexpected error occurred"
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// src/react/provider.tsx
|
|
103
|
+
var ByteonicContext = (0, import_react.createContext)(void 0);
|
|
104
|
+
function ByteonicProvider({ apiKey, baseUrl, children }) {
|
|
105
|
+
const client = (0, import_react.useMemo)(() => new ByteonicClient({ apiKey, baseUrl }), [apiKey, baseUrl]);
|
|
106
|
+
return /* @__PURE__ */ import_react.default.createElement(ByteonicContext.Provider, { value: client }, children);
|
|
107
|
+
}
|
|
108
|
+
function useByteonicClient() {
|
|
109
|
+
const context = (0, import_react.useContext)(ByteonicContext);
|
|
110
|
+
if (!context) {
|
|
111
|
+
throw new Error("useByteonicClient must be used within a ByteonicProvider");
|
|
112
|
+
}
|
|
113
|
+
return context;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/react/useForm.ts
|
|
117
|
+
var import_meta = {};
|
|
118
|
+
function useByteonicIntake(options) {
|
|
119
|
+
const formSlug = typeof options === "string" ? options : options.formSlug;
|
|
120
|
+
const configApiKey = typeof options === "string" ? void 0 : options.apiKey;
|
|
121
|
+
const configBaseUrl = typeof options === "string" ? void 0 : options.baseUrl;
|
|
122
|
+
let contextClient;
|
|
123
|
+
try {
|
|
124
|
+
contextClient = useByteonicClient();
|
|
125
|
+
} catch (e) {
|
|
126
|
+
}
|
|
127
|
+
const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
|
|
128
|
+
const [isSuccess, setIsSuccess] = (0, import_react2.useState)(false);
|
|
129
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
130
|
+
const [response, setResponse] = (0, import_react2.useState)(null);
|
|
131
|
+
const submit = (0, import_react2.useCallback)(async (data) => {
|
|
132
|
+
setIsLoading(true);
|
|
133
|
+
setError(null);
|
|
134
|
+
setIsSuccess(false);
|
|
135
|
+
try {
|
|
136
|
+
let client = contextClient;
|
|
137
|
+
if (!client) {
|
|
138
|
+
if (!configApiKey) {
|
|
139
|
+
const envKey = typeof process !== "undefined" && process.env?.NEXT_PUBLIC_BYTEONIC_API_KEY || typeof globalThis.import?.meta !== "undefined" && globalThis.import?.meta?.env?.VITE_BYTEONIC_API_KEY || typeof import_meta !== "undefined" && import_meta.env?.VITE_BYTEONIC_API_KEY;
|
|
140
|
+
if (envKey) {
|
|
141
|
+
client = new ByteonicClient({ apiKey: envKey, baseUrl: configBaseUrl });
|
|
142
|
+
} else {
|
|
143
|
+
throw new Error("Byteonic Intake: apiKey is required via <ByteonicProvider>, directly in useByteonicIntake, or as an environment variable (NEXT_PUBLIC_BYTEONIC_API_KEY / VITE_BYTEONIC_API_KEY)");
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
client = new ByteonicClient({ apiKey: configApiKey, baseUrl: configBaseUrl });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
let payload = data;
|
|
150
|
+
if (data && typeof data.preventDefault === "function") {
|
|
151
|
+
data.preventDefault();
|
|
152
|
+
payload = new FormData(data.currentTarget);
|
|
153
|
+
}
|
|
154
|
+
const result = await client.submit(formSlug, payload);
|
|
155
|
+
setResponse(result);
|
|
156
|
+
if (result.success !== false) {
|
|
157
|
+
setIsSuccess(true);
|
|
158
|
+
} else {
|
|
159
|
+
setError(result.error || "Submission failed");
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
} catch (err) {
|
|
163
|
+
setError(err.message || "An unexpected error occurred");
|
|
164
|
+
return { success: false, error: err.message };
|
|
165
|
+
} finally {
|
|
166
|
+
setIsLoading(false);
|
|
167
|
+
}
|
|
168
|
+
}, [formSlug, contextClient, configApiKey, configBaseUrl]);
|
|
169
|
+
return {
|
|
170
|
+
submit,
|
|
171
|
+
isLoading,
|
|
172
|
+
isSuccess,
|
|
173
|
+
error,
|
|
174
|
+
response
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/react/honeypot.tsx
|
|
179
|
+
var import_react3 = __toESM(require("react"));
|
|
180
|
+
function ByteonicHoneypot() {
|
|
181
|
+
return /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "none", position: "absolute", left: "-9999px", opacity: 0 }, "aria-hidden": "true" }, /* @__PURE__ */ import_react3.default.createElement("label", { htmlFor: "_gotcha" }, "Please leave this field blank"), /* @__PURE__ */ import_react3.default.createElement("input", { type: "text", name: "_gotcha", id: "_gotcha", tabIndex: -1, autoComplete: "off" }));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/react/useChatbot.ts
|
|
185
|
+
var import_react4 = require("react");
|
|
186
|
+
|
|
187
|
+
// src/chat.ts
|
|
188
|
+
var ByteonicChatClient = class {
|
|
189
|
+
constructor(config) {
|
|
190
|
+
if (!config.apiKey) {
|
|
191
|
+
throw new Error("[Byteonic Intake] API Key is required");
|
|
192
|
+
}
|
|
193
|
+
this.apiKey = config.apiKey;
|
|
194
|
+
this.baseUrl = config.baseUrl || "https://backend.intake.byteoniclabs.com/api/v1/chat";
|
|
195
|
+
}
|
|
196
|
+
async getConfig(botId) {
|
|
197
|
+
const url = `${this.baseUrl}/config?id=${botId}`;
|
|
198
|
+
try {
|
|
199
|
+
const response = await fetch(url, {
|
|
200
|
+
headers: {
|
|
201
|
+
"Authorization": `Bearer ${this.apiKey}`
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
if (!response.ok) return null;
|
|
205
|
+
return await response.json();
|
|
206
|
+
} catch {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async generate(botId, sessionId, message, history = [], options) {
|
|
211
|
+
const url = `${this.baseUrl}/generate`;
|
|
212
|
+
try {
|
|
213
|
+
const response = await fetch(url, {
|
|
214
|
+
method: "POST",
|
|
215
|
+
headers: {
|
|
216
|
+
"Content-Type": "application/json",
|
|
217
|
+
"Authorization": `Bearer ${this.apiKey}`
|
|
218
|
+
},
|
|
219
|
+
body: JSON.stringify({
|
|
220
|
+
chatbot_id: botId,
|
|
221
|
+
session_id: sessionId,
|
|
222
|
+
message,
|
|
223
|
+
history
|
|
224
|
+
})
|
|
225
|
+
});
|
|
226
|
+
if (!response.ok) {
|
|
227
|
+
const errorData = await response.json().catch(() => ({}));
|
|
228
|
+
throw new Error(errorData.error || "Generation failed");
|
|
229
|
+
}
|
|
230
|
+
const reader = response.body?.getReader();
|
|
231
|
+
const decoder = new TextDecoder("utf-8");
|
|
232
|
+
let fullMessage = "";
|
|
233
|
+
if (reader) {
|
|
234
|
+
let done = false;
|
|
235
|
+
let buffer = "";
|
|
236
|
+
while (!done) {
|
|
237
|
+
const { value, done: readerDone } = await reader.read();
|
|
238
|
+
done = readerDone;
|
|
239
|
+
if (value) {
|
|
240
|
+
buffer += decoder.decode(value, { stream: true });
|
|
241
|
+
const lines = buffer.split("\n");
|
|
242
|
+
buffer = lines.pop() || "";
|
|
243
|
+
for (const line of lines) {
|
|
244
|
+
if (line.startsWith("data: ") && !line.includes("[DONE]")) {
|
|
245
|
+
try {
|
|
246
|
+
const data = JSON.parse(line.slice(6));
|
|
247
|
+
const content = data.choices?.[0]?.delta?.content;
|
|
248
|
+
if (content) {
|
|
249
|
+
fullMessage += content;
|
|
250
|
+
if (options?.onChunk) options.onChunk(fullMessage);
|
|
251
|
+
}
|
|
252
|
+
} catch (e) {
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return { success: true, message: fullMessage.trim() || "No response generated." };
|
|
260
|
+
} catch (err) {
|
|
261
|
+
return { success: false, error: err.message || "Network error" };
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
// src/react/useChatbot.ts
|
|
267
|
+
var import_meta2 = {};
|
|
268
|
+
function useByteonicChatbot(options) {
|
|
269
|
+
const botId = typeof options === "string" ? options : options.botId;
|
|
270
|
+
const configApiKey = typeof options === "string" ? void 0 : options.apiKey;
|
|
271
|
+
const configBaseUrl = typeof options === "string" ? void 0 : options.baseUrl;
|
|
272
|
+
const configStream = typeof options === "string" ? false : options.stream ?? true;
|
|
273
|
+
let contextClient;
|
|
274
|
+
try {
|
|
275
|
+
contextClient = useByteonicClient();
|
|
276
|
+
} catch (e) {
|
|
277
|
+
}
|
|
278
|
+
const [client, setClient] = (0, import_react4.useState)(null);
|
|
279
|
+
const [messages, setMessages] = (0, import_react4.useState)([]);
|
|
280
|
+
const [config, setConfig] = (0, import_react4.useState)(null);
|
|
281
|
+
const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
|
|
282
|
+
const [isStreaming, setIsStreaming] = (0, import_react4.useState)(false);
|
|
283
|
+
const [streamedMessage, setStreamedMessage] = (0, import_react4.useState)("");
|
|
284
|
+
const [sessionId, setSessionId] = (0, import_react4.useState)("");
|
|
285
|
+
const [isInitialized, setIsInitialized] = (0, import_react4.useState)(false);
|
|
286
|
+
(0, import_react4.useEffect)(() => {
|
|
287
|
+
if (typeof window !== "undefined") {
|
|
288
|
+
const saved = localStorage.getItem(`byteonic_messages_${botId}`);
|
|
289
|
+
if (saved) {
|
|
290
|
+
try {
|
|
291
|
+
const parsed = JSON.parse(saved);
|
|
292
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
293
|
+
setMessages(parsed);
|
|
294
|
+
}
|
|
295
|
+
} catch (e) {
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
setIsInitialized(true);
|
|
300
|
+
}, [botId]);
|
|
301
|
+
(0, import_react4.useEffect)(() => {
|
|
302
|
+
let sid = typeof window !== "undefined" ? localStorage.getItem(`byteonic_chat_${botId}`) : null;
|
|
303
|
+
if (!sid) {
|
|
304
|
+
sid = Math.random().toString(36).substring(2, 15);
|
|
305
|
+
if (typeof window !== "undefined") localStorage.setItem(`byteonic_chat_${botId}`, sid);
|
|
306
|
+
}
|
|
307
|
+
setSessionId(sid);
|
|
308
|
+
let resolvedClient = null;
|
|
309
|
+
const finalApiKey = configApiKey || contextClient?.apiKey || typeof process !== "undefined" && process.env?.NEXT_PUBLIC_BYTEONIC_API_KEY || typeof globalThis.import?.meta !== "undefined" && globalThis.import?.meta?.env?.VITE_BYTEONIC_API_KEY || typeof import_meta2 !== "undefined" && import_meta2.env?.VITE_BYTEONIC_API_KEY;
|
|
310
|
+
if (finalApiKey) {
|
|
311
|
+
resolvedClient = new ByteonicChatClient({ apiKey: finalApiKey, baseUrl: configBaseUrl });
|
|
312
|
+
setClient(resolvedClient);
|
|
313
|
+
} else {
|
|
314
|
+
console.warn("Byteonic Chatbot: No API Key provided. Chat will not function.");
|
|
315
|
+
}
|
|
316
|
+
if (resolvedClient && isInitialized) {
|
|
317
|
+
resolvedClient.getConfig(botId).then((cfg) => {
|
|
318
|
+
if (cfg) {
|
|
319
|
+
setConfig(cfg);
|
|
320
|
+
setMessages((prev) => {
|
|
321
|
+
if (prev.length === 0 && cfg.welcomeMessage) {
|
|
322
|
+
return [{ role: "assistant", content: cfg.welcomeMessage }];
|
|
323
|
+
}
|
|
324
|
+
return prev;
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}, [botId, configApiKey, configBaseUrl, isInitialized]);
|
|
330
|
+
(0, import_react4.useEffect)(() => {
|
|
331
|
+
if (isInitialized && typeof window !== "undefined") {
|
|
332
|
+
localStorage.setItem(`byteonic_messages_${botId}`, JSON.stringify(messages));
|
|
333
|
+
}
|
|
334
|
+
}, [messages, botId, isInitialized]);
|
|
335
|
+
const sendMessage = (0, import_react4.useCallback)(async (content) => {
|
|
336
|
+
if (!client || !content.trim()) return;
|
|
337
|
+
const userMsg = { role: "user", content };
|
|
338
|
+
const newHistory = [...messages, userMsg];
|
|
339
|
+
setMessages(newHistory);
|
|
340
|
+
setIsLoading(true);
|
|
341
|
+
if (configStream) {
|
|
342
|
+
setIsStreaming(true);
|
|
343
|
+
setStreamedMessage("");
|
|
344
|
+
}
|
|
345
|
+
try {
|
|
346
|
+
const res = await client.generate(botId, sessionId, content, messages, {
|
|
347
|
+
onChunk: configStream ? (chunk) => setStreamedMessage(chunk) : void 0
|
|
348
|
+
});
|
|
349
|
+
if (configStream) {
|
|
350
|
+
setIsStreaming(false);
|
|
351
|
+
setStreamedMessage("");
|
|
352
|
+
}
|
|
353
|
+
if (res.success && res.message) {
|
|
354
|
+
setMessages([...newHistory, { role: "assistant", content: res.message }]);
|
|
355
|
+
} else {
|
|
356
|
+
setMessages([...newHistory, { role: "assistant", content: res.error || "Sorry, I encountered an error." }]);
|
|
357
|
+
}
|
|
358
|
+
} catch (e) {
|
|
359
|
+
if (configStream) setIsStreaming(false);
|
|
360
|
+
setMessages([...newHistory, { role: "assistant", content: "Network error." }]);
|
|
361
|
+
} finally {
|
|
362
|
+
setIsLoading(false);
|
|
363
|
+
}
|
|
364
|
+
}, [client, messages, botId, sessionId, configStream]);
|
|
365
|
+
const clearHistory = (0, import_react4.useCallback)(() => {
|
|
366
|
+
setMessages(config?.welcomeMessage ? [{ role: "assistant", content: config.welcomeMessage }] : []);
|
|
367
|
+
const sid = Math.random().toString(36).substring(2, 15);
|
|
368
|
+
setSessionId(sid);
|
|
369
|
+
if (typeof window !== "undefined") {
|
|
370
|
+
localStorage.setItem(`byteonic_chat_${botId}`, sid);
|
|
371
|
+
localStorage.removeItem(`byteonic_messages_${botId}`);
|
|
372
|
+
}
|
|
373
|
+
}, [botId, config]);
|
|
374
|
+
return {
|
|
375
|
+
messages,
|
|
376
|
+
sendMessage,
|
|
377
|
+
isLoading,
|
|
378
|
+
isStreaming,
|
|
379
|
+
streamedMessage,
|
|
380
|
+
config,
|
|
381
|
+
clearHistory
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
385
|
+
0 && (module.exports = {
|
|
386
|
+
ByteonicHoneypot,
|
|
387
|
+
ByteonicProvider,
|
|
388
|
+
useByteonicChatbot,
|
|
389
|
+
useByteonicClient,
|
|
390
|
+
useByteonicIntake
|
|
391
|
+
});
|
|
392
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts","../../src/react/useForm.ts","../../src/react/provider.tsx","../../src/client.ts","../../src/react/honeypot.tsx","../../src/react/useChatbot.ts","../../src/chat.ts"],"sourcesContent":["export { useByteonicIntake } from './useForm';\nexport { ByteonicProvider, useByteonicClient } from './provider';\nexport { ByteonicHoneypot } from './honeypot';\nexport { useByteonicChatbot } from './useChatbot';\n","import { useState, useCallback } from 'react';\r\nimport { useByteonicClient } from './provider';\r\nimport { SubmissionResponse } from '../types';\r\nimport { ByteonicClient } from '../client';\r\n\r\nexport interface UseByteonicIntakeOptions {\r\n formSlug: string;\r\n apiKey?: string;\r\n baseUrl?: string;\r\n}\r\n\r\nexport function useByteonicIntake<T = Record<string, any>>(options: UseByteonicIntakeOptions | string) {\r\n const formSlug = typeof options === 'string' ? options : options.formSlug;\r\n const configApiKey = typeof options === 'string' ? undefined : options.apiKey;\r\n const configBaseUrl = typeof options === 'string' ? undefined : options.baseUrl;\r\n\r\n let contextClient: ByteonicClient | undefined;\r\n try {\r\n contextClient = useByteonicClient();\r\n } catch (e) {\r\n // Suppress error if outside provider\r\n }\r\n\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [isSuccess, setIsSuccess] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [response, setResponse] = useState<SubmissionResponse | null>(null);\r\n\r\n const submit = useCallback(async (data: T | FormData | React.FormEvent<HTMLFormElement>) => {\r\n setIsLoading(true);\r\n setError(null);\r\n setIsSuccess(false);\r\n\r\n try {\r\n let client = contextClient;\r\n \r\n if (!client) {\r\n if (!configApiKey) {\r\n const envKey = \r\n (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_BYTEONIC_API_KEY) ||\r\n (typeof (globalThis as any).import?.meta !== 'undefined' && (globalThis as any).import?.meta?.env?.VITE_BYTEONIC_API_KEY) ||\r\n (typeof import.meta !== 'undefined' && (import.meta as any).env?.VITE_BYTEONIC_API_KEY);\r\n\r\n if (envKey) {\r\n client = new ByteonicClient({ apiKey: envKey as string, baseUrl: configBaseUrl });\r\n } else {\r\n throw new Error('Byteonic Intake: apiKey is required via <ByteonicProvider>, directly in useByteonicIntake, or as an environment variable (NEXT_PUBLIC_BYTEONIC_API_KEY / VITE_BYTEONIC_API_KEY)');\r\n }\r\n } else {\r\n client = new ByteonicClient({ apiKey: configApiKey, baseUrl: configBaseUrl });\r\n }\r\n }\r\n\r\n let payload: any = data;\r\n if (data && typeof (data as any).preventDefault === 'function') {\r\n (data as any).preventDefault();\r\n payload = new FormData((data as any).currentTarget);\r\n }\r\n\r\n const result = await client.submit(formSlug, payload);\r\n \r\n setResponse(result);\r\n if (result.success !== false) {\r\n setIsSuccess(true);\r\n } else {\r\n setError(result.error || 'Submission failed');\r\n }\r\n return result;\r\n } catch (err: any) {\r\n setError(err.message || 'An unexpected error occurred');\r\n return { success: false, error: err.message };\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [formSlug, contextClient, configApiKey, configBaseUrl]);\r\n\r\n return {\r\n submit,\r\n isLoading,\r\n isSuccess,\r\n error,\r\n response\r\n };\r\n}\r\n","import React, { createContext, useContext, ReactNode, useMemo } from 'react';\r\nimport { ByteonicClient } from '../client';\r\nimport { ByteonicConfig } from '../types';\r\n\r\nconst ByteonicContext = createContext<ByteonicClient | undefined>(undefined);\r\n\r\nexport interface ByteonicProviderProps extends ByteonicConfig {\r\n children: ReactNode;\r\n}\r\n\r\nexport function ByteonicProvider({ apiKey, baseUrl, children }: ByteonicProviderProps) {\r\n const client = useMemo(() => new ByteonicClient({ apiKey, baseUrl }), [apiKey, baseUrl]);\r\n\r\n return (\r\n <ByteonicContext.Provider value={client}>\r\n {children}\r\n </ByteonicContext.Provider>\r\n );\r\n}\r\n\r\nexport function useByteonicClient(): ByteonicClient {\r\n const context = useContext(ByteonicContext);\r\n if (!context) {\r\n throw new Error('useByteonicClient must be used within a ByteonicProvider');\r\n }\r\n return context;\r\n}\r\n","import { ByteonicConfig, SubmissionResponse } from './types';\r\n\r\nexport class ByteonicClient {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n\r\n constructor(config: ByteonicConfig) {\r\n if (!config.apiKey) {\r\n throw new Error('[Byteonic Intake] API Key is required');\r\n }\r\n this.apiKey = config.apiKey;\r\n this.baseUrl = config.baseUrl || 'https://intake.byteoniclabs.com/api/external';\r\n }\r\n\r\n /**\r\n * Submit form data to Byteonic Intake\r\n * @param formSlug The slug of the form to submit to\r\n * @param data The form data (Record<string, any> or FormData)\r\n */\r\n async submit(formSlug: string, data: Record<string, any> | FormData): Promise<SubmissionResponse> {\r\n const url = `${this.baseUrl}/forms/${formSlug}/submit`;\r\n \r\n // Auto-track metadata\r\n const meta = {\r\n sdk_version: '1.0.0',\r\n source_url: typeof window !== 'undefined' ? window.location.href : 'server',\r\n submission_source: 'byteonic_intake_sdk'\r\n };\r\n\r\n let fetchOptions: RequestInit = {\r\n method: 'POST',\r\n headers: {\r\n 'Authorization': `Bearer ${this.apiKey}`\r\n }\r\n };\r\n\r\n if (typeof FormData !== 'undefined' && data instanceof FormData) {\r\n // Native File uploads require FormData to remain untouched.\r\n // Do NOT set Content-Type header, the browser sets the multi-part boundary automatically.\r\n data.append('_meta', JSON.stringify(meta));\r\n fetchOptions.body = data;\r\n } else {\r\n // Standard JSON payload\r\n const payload = data as Record<string, any>;\r\n payload._meta = meta;\r\n \r\n fetchOptions.headers = {\r\n ...fetchOptions.headers,\r\n 'Content-Type': 'application/json'\r\n };\r\n fetchOptions.body = JSON.stringify(payload);\r\n }\r\n\r\n try {\r\n const response = await fetch(url, fetchOptions);\r\n\r\n const responseData = await response.json().catch(() => ({}));\r\n \r\n if (!response.ok) {\r\n throw new Error(responseData.error || responseData.message || 'Submission failed');\r\n }\r\n \r\n return responseData;\r\n } catch (error: any) {\r\n return {\r\n success: false,\r\n error: error.message || 'An unexpected error occurred'\r\n };\r\n }\r\n }\r\n}\r\n","import React from 'react';\n\n/**\n * A hidden input field used to trick bots into filling it out.\n * If this field is submitted, Byteonic Intake will ignore the submission, protecting you from spam.\n * \n * Simply place `<ByteonicHoneypot />` anywhere inside your `<form>` element.\n */\nexport function ByteonicHoneypot() {\n return (\n <div style={{ display: 'none', position: 'absolute', left: '-9999px', opacity: 0 }} aria-hidden=\"true\">\n <label htmlFor=\"_gotcha\">Please leave this field blank</label>\n <input type=\"text\" name=\"_gotcha\" id=\"_gotcha\" tabIndex={-1} autoComplete=\"off\" />\n </div>\n );\n}\n","import { useState, useCallback, useEffect } from 'react';\nimport { useByteonicClient } from './provider';\nimport { ByteonicChatClient, ChatMessage, ChatbotConfig } from '../chat';\n\nexport interface UseByteonicChatbotOptions {\n botId: string;\n apiKey?: string;\n baseUrl?: string;\n stream?: boolean;\n}\n\nexport function useByteonicChatbot(options: UseByteonicChatbotOptions | string) {\n const botId = typeof options === 'string' ? options : options.botId;\n const configApiKey = typeof options === 'string' ? undefined : options.apiKey;\n const configBaseUrl = typeof options === 'string' ? undefined : options.baseUrl;\n const configStream = typeof options === 'string' ? false : (options.stream ?? true);\n\n let contextClient: any;\n try {\n contextClient = useByteonicClient();\n } catch (e) {\n // Suppress error if outside provider\n }\n\n const [client, setClient] = useState<ByteonicChatClient | null>(null);\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [config, setConfig] = useState<ChatbotConfig | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [streamedMessage, setStreamedMessage] = useState('');\n const [sessionId, setSessionId] = useState<string>('');\n const [isInitialized, setIsInitialized] = useState(false);\n\n // Load from local storage exclusively on the client after hydration\n useEffect(() => {\n if (typeof window !== 'undefined') {\n const saved = localStorage.getItem(`byteonic_messages_${botId}`);\n if (saved) {\n try {\n const parsed = JSON.parse(saved);\n if (Array.isArray(parsed) && parsed.length > 0) {\n setMessages(parsed);\n }\n } catch (e) {}\n }\n }\n setIsInitialized(true);\n }, [botId]);\n\n useEffect(() => {\n // Generate a random session ID if not exists (using localStorage to persist across tabs/reloads)\n let sid = typeof window !== 'undefined' ? localStorage.getItem(`byteonic_chat_${botId}`) : null;\n if (!sid) {\n sid = Math.random().toString(36).substring(2, 15);\n if (typeof window !== 'undefined') localStorage.setItem(`byteonic_chat_${botId}`, sid);\n }\n setSessionId(sid);\n\n let resolvedClient: ByteonicChatClient | null = null;\n \n // Attempt to pull apiKey from context, then config, then env\n const finalApiKey = configApiKey || (contextClient as any)?.apiKey || \n (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_BYTEONIC_API_KEY) ||\n (typeof (globalThis as any).import?.meta !== 'undefined' && (globalThis as any).import?.meta?.env?.VITE_BYTEONIC_API_KEY) ||\n (typeof import.meta !== 'undefined' && (import.meta as any).env?.VITE_BYTEONIC_API_KEY);\n\n if (finalApiKey) {\n resolvedClient = new ByteonicChatClient({ apiKey: finalApiKey as string, baseUrl: configBaseUrl });\n setClient(resolvedClient);\n } else {\n console.warn('Byteonic Chatbot: No API Key provided. Chat will not function.');\n }\n\n if (resolvedClient && isInitialized) {\n resolvedClient.getConfig(botId).then(cfg => {\n if (cfg) {\n setConfig(cfg);\n // Only set welcome message if we don't have stored messages\n setMessages(prev => {\n if (prev.length === 0 && cfg.welcomeMessage) {\n return [{ role: 'assistant', content: cfg.welcomeMessage }];\n }\n return prev;\n });\n }\n });\n }\n }, [botId, configApiKey, configBaseUrl, isInitialized]);\n\n // Persist messages to localStorage whenever they change\n useEffect(() => {\n if (isInitialized && typeof window !== 'undefined') {\n localStorage.setItem(`byteonic_messages_${botId}`, JSON.stringify(messages));\n }\n }, [messages, botId, isInitialized]);\n\n const sendMessage = useCallback(async (content: string) => {\n if (!client || !content.trim()) return;\n\n const userMsg: ChatMessage = { role: 'user', content };\n const newHistory = [...messages, userMsg];\n setMessages(newHistory);\n setIsLoading(true);\n\n if (configStream) {\n setIsStreaming(true);\n setStreamedMessage('');\n }\n\n try {\n const res = await client.generate(botId, sessionId, content, messages, {\n onChunk: configStream ? (chunk: string) => setStreamedMessage(chunk) : undefined\n });\n \n if (configStream) {\n setIsStreaming(false);\n setStreamedMessage('');\n }\n\n if (res.success && res.message) {\n setMessages([...newHistory, { role: 'assistant', content: res.message }]);\n } else {\n setMessages([...newHistory, { role: 'assistant', content: res.error || 'Sorry, I encountered an error.' }]);\n }\n } catch (e) {\n if (configStream) setIsStreaming(false);\n setMessages([...newHistory, { role: 'assistant', content: 'Network error.' }]);\n } finally {\n setIsLoading(false);\n }\n }, [client, messages, botId, sessionId, configStream]);\n\n const clearHistory = useCallback(() => {\n setMessages(config?.welcomeMessage ? [{ role: 'assistant', content: config.welcomeMessage }] : []);\n const sid = Math.random().toString(36).substring(2, 15);\n setSessionId(sid);\n if (typeof window !== 'undefined') {\n localStorage.setItem(`byteonic_chat_${botId}`, sid);\n localStorage.removeItem(`byteonic_messages_${botId}`);\n }\n }, [botId, config]);\n\n return {\n messages,\n sendMessage,\n isLoading,\n isStreaming,\n streamedMessage,\n config,\n clearHistory\n };\n}\n","import { ByteonicConfig } from './types';\n\nexport interface ChatMessage {\n role: 'user' | 'assistant' | 'system';\n content: string;\n}\n\nexport interface ChatbotConfig {\n botId: string;\n name?: string;\n theme?: string;\n welcomeMessage?: string;\n [key: string]: any;\n}\n\nexport interface GenerateResponse {\n success: boolean;\n message?: string;\n error?: string;\n}\n\nexport interface GenerateOptions {\n onChunk?: (fullMessage: string) => void;\n}\n\nexport class ByteonicChatClient {\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: ByteonicConfig) {\n if (!config.apiKey) {\n throw new Error('[Byteonic Intake] API Key is required');\n }\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || 'https://backend.intake.byteoniclabs.com/api/v1/chat';\n }\n\n async getConfig(botId: string): Promise<ChatbotConfig | null> {\n const url = `${this.baseUrl}/config?id=${botId}`;\n try {\n const response = await fetch(url, {\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`\n }\n });\n if (!response.ok) return null;\n return await response.json();\n } catch {\n return null;\n }\n }\n\n async generate(botId: string, sessionId: string, message: string, history: ChatMessage[] = [], options?: GenerateOptions): Promise<GenerateResponse> {\n const url = `${this.baseUrl}/generate`;\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`\n },\n body: JSON.stringify({ \n chatbot_id: botId, \n session_id: sessionId, \n message, \n history \n })\n });\n \n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new Error(errorData.error || 'Generation failed');\n }\n\n const reader = response.body?.getReader();\n const decoder = new TextDecoder('utf-8');\n let fullMessage = '';\n\n if (reader) {\n let done = false;\n let buffer = '';\n while (!done) {\n const { value, done: readerDone } = await reader.read();\n done = readerDone;\n if (value) {\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || ''; // Keep incomplete lines in buffer\n\n for (const line of lines) {\n if (line.startsWith('data: ') && !line.includes('[DONE]')) {\n try {\n const data = JSON.parse(line.slice(6));\n const content = data.choices?.[0]?.delta?.content;\n if (content) {\n fullMessage += content;\n if (options?.onChunk) options.onChunk(fullMessage);\n }\n } catch (e) {\n // Ignore partial chunk parse errors\n }\n }\n }\n }\n }\n }\n\n return { success: true, message: fullMessage.trim() || 'No response generated.' };\n } catch (err: any) {\n return { success: false, error: err.message || 'Network error' };\n }\n }\n}\n"],"mappings":"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","names":["import_react","React","import_react","React","import_react","import_meta"]}
|