botversion-sdk 1.0.4 → 1.0.6
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/bin/init.js +186 -140
- package/cli/detector.js +360 -173
- package/cli/generator.js +21 -479
- package/cli/prompts.js +40 -42
- package/cli/writer.js +119 -43
- package/client.js +33 -69
- package/index.js +54 -515
- package/interceptor.js +57 -132
- package/package.json +3 -1
- package/scanner.js +733 -28
package/index.js
CHANGED
|
@@ -10,15 +10,6 @@ var BotVersion = {
|
|
|
10
10
|
_initialized: false,
|
|
11
11
|
|
|
12
12
|
init: function (appOrOptions, optionsArg) {
|
|
13
|
-
console.log("=== INIT CALLED ===");
|
|
14
|
-
console.log("appOrOptions type:", typeof appOrOptions);
|
|
15
|
-
console.log(
|
|
16
|
-
"appOrOptions is express app:",
|
|
17
|
-
appOrOptions && typeof appOrOptions.use === "function",
|
|
18
|
-
);
|
|
19
|
-
console.log("optionsArg type:", typeof optionsArg);
|
|
20
|
-
console.log("optionsArg value:", JSON.stringify(optionsArg));
|
|
21
|
-
console.log("===================");
|
|
22
13
|
var app = null;
|
|
23
14
|
var options = {};
|
|
24
15
|
|
|
@@ -35,23 +26,17 @@ var BotVersion = {
|
|
|
35
26
|
app = null;
|
|
36
27
|
}
|
|
37
28
|
|
|
38
|
-
console.log("options received:", JSON.stringify(options));
|
|
39
|
-
if (!options.apiKey) {
|
|
40
|
-
console.error("[BotVersion SDK] ❌ apiKey is required.");
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
29
|
// Restore from global if module was re-imported after hot reload
|
|
45
30
|
if (global._botVersionClient) {
|
|
46
31
|
this._client = global._botVersionClient;
|
|
47
32
|
this._options = global._botVersionOptions;
|
|
48
33
|
this._initialized = true;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
34
|
+
// Re-attach interceptor after hot reload
|
|
35
|
+
interceptor.attachNextJsInterceptor(this._client, {
|
|
36
|
+
exclude: (global._botVersionOptions || {}).exclude || [],
|
|
37
|
+
apiPrefix: (global._botVersionOptions || {}).apiPrefix || "/api",
|
|
38
|
+
debug: (global._botVersionOptions || {}).debug || false,
|
|
39
|
+
});
|
|
55
40
|
return;
|
|
56
41
|
}
|
|
57
42
|
|
|
@@ -61,7 +46,7 @@ var BotVersion = {
|
|
|
61
46
|
|
|
62
47
|
this._client = new BotVersionClient({
|
|
63
48
|
apiKey: options.apiKey,
|
|
64
|
-
platformUrl: options.platformUrl || "https://
|
|
49
|
+
platformUrl: options.platformUrl || "https://botversion.com",
|
|
65
50
|
debug: options.debug || false,
|
|
66
51
|
timeout: options.timeout || 30000,
|
|
67
52
|
});
|
|
@@ -72,56 +57,21 @@ var BotVersion = {
|
|
|
72
57
|
var self = this;
|
|
73
58
|
var debug = options.debug || false;
|
|
74
59
|
|
|
75
|
-
|
|
76
|
-
console.log("[BotVersion SDK] Initializing...");
|
|
77
|
-
if (app) {
|
|
78
|
-
console.log("[BotVersion SDK] Mode: Express");
|
|
79
|
-
} else {
|
|
80
|
-
console.log("[BotVersion SDK] Mode: Next.js (file-based routing)");
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// ── Framework detection ──────────────────────────────────────────────────
|
|
85
|
-
if (app) {
|
|
86
|
-
var frameworkCheck = detectFramework(app);
|
|
87
|
-
if (!frameworkCheck.supported) {
|
|
88
|
-
console.error(
|
|
89
|
-
"[BotVersion SDK] ❌ Unsupported framework:",
|
|
90
|
-
frameworkCheck.name,
|
|
91
|
-
);
|
|
92
|
-
console.error(
|
|
93
|
-
"[BotVersion SDK] ❌ Currently supports Express and Next.js only.",
|
|
94
|
-
);
|
|
95
|
-
console.error(
|
|
96
|
-
"[BotVersion SDK] ❌ Visit https://docs.botversion.com for supported frameworks.",
|
|
97
|
-
);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
if (debug) {
|
|
101
|
-
console.log(
|
|
102
|
-
"[BotVersion SDK] ✅ Framework detected:",
|
|
103
|
-
frameworkCheck.name,
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// ── Runtime interceptor — Express only ───────────────────────────────────
|
|
60
|
+
// ── Runtime interceptor — Express or Next.js ─────────────────────────────
|
|
109
61
|
if (app && app.use) {
|
|
62
|
+
// Express
|
|
110
63
|
interceptor.attachInterceptor(app, self._client, {
|
|
111
64
|
exclude: options.exclude || [],
|
|
112
65
|
apiPrefix: options.apiPrefix || null,
|
|
113
66
|
debug: debug,
|
|
114
|
-
getUserContext: options.getUserContext || null,
|
|
115
67
|
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
);
|
|
124
|
-
}
|
|
68
|
+
} else {
|
|
69
|
+
// Next.js — patch the global fetch/http server to intercept API calls
|
|
70
|
+
interceptor.attachNextJsInterceptor(self._client, {
|
|
71
|
+
exclude: options.exclude || [],
|
|
72
|
+
apiPrefix: options.apiPrefix || "/api",
|
|
73
|
+
debug: debug,
|
|
74
|
+
});
|
|
125
75
|
}
|
|
126
76
|
|
|
127
77
|
// ── Static scan ──────────────────────────────────────────────────────────
|
|
@@ -130,95 +80,54 @@ var BotVersion = {
|
|
|
130
80
|
|
|
131
81
|
// Express scan
|
|
132
82
|
if (app) {
|
|
133
|
-
|
|
134
|
-
endpoints = scanner.scanExpressRoutes(app);
|
|
135
|
-
console.log(
|
|
136
|
-
"[BotVersion SDK] Found",
|
|
137
|
-
endpoints.length,
|
|
138
|
-
"Express routes",
|
|
139
|
-
);
|
|
140
|
-
console.log(
|
|
141
|
-
"[BotVersion SDK] Endpoints:",
|
|
142
|
-
JSON.stringify(endpoints, null, 2),
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
if (endpoints.length === 0) {
|
|
146
|
-
console.warn("[BotVersion SDK] ⚠ No endpoints found.");
|
|
147
|
-
console.warn(
|
|
148
|
-
"[BotVersion SDK] ⚠ Make sure routes are defined BEFORE BotVersion.init()",
|
|
149
|
-
);
|
|
150
|
-
console.warn(
|
|
151
|
-
"[BotVersion SDK] ⚠ and BotVersion.init() is called BEFORE app.listen().",
|
|
152
|
-
);
|
|
153
|
-
}
|
|
83
|
+
var cwd = options.cwd || process.cwd();
|
|
84
|
+
endpoints = scanner.scanExpressRoutes(app, cwd);
|
|
154
85
|
}
|
|
155
86
|
|
|
156
|
-
// Next.js scan
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
);
|
|
162
|
-
var nextRoutes = scanner.scanNextJsRoutes(options.pagesDir);
|
|
163
|
-
endpoints = endpoints.concat(nextRoutes);
|
|
164
|
-
console.log(
|
|
165
|
-
"[BotVersion SDK] Found",
|
|
166
|
-
nextRoutes.length,
|
|
167
|
-
"Next.js routes",
|
|
168
|
-
);
|
|
169
|
-
console.log(
|
|
170
|
-
"[BotVersion SDK] Next.js routes:",
|
|
171
|
-
JSON.stringify(nextRoutes, null, 2),
|
|
172
|
-
);
|
|
87
|
+
// Next.js scan
|
|
88
|
+
if (!app) {
|
|
89
|
+
const fs = require("fs");
|
|
90
|
+
const path = require("path");
|
|
91
|
+
const cwd = process.cwd();
|
|
173
92
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
)
|
|
93
|
+
const possibleAppDirs = [
|
|
94
|
+
path.join(cwd, "app"),
|
|
95
|
+
path.join(cwd, "src", "app"),
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
const possiblePagesDirs = [
|
|
99
|
+
path.join(cwd, "pages"),
|
|
100
|
+
path.join(cwd, "src", "pages"),
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
for (const dir of possibleAppDirs) {
|
|
104
|
+
if (fs.existsSync(dir)) {
|
|
105
|
+
const routes = scanner.scanNextJsAppRoutes(dir);
|
|
106
|
+
endpoints = endpoints.concat(routes);
|
|
107
|
+
}
|
|
182
108
|
}
|
|
183
|
-
}
|
|
184
109
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
console.error(
|
|
192
|
-
"[BotVersion SDK] ❌ For Next.js: pass pagesDir — BotVersion.init({ apiKey, pagesDir: path.join(process.cwd(), 'pages') })",
|
|
193
|
-
);
|
|
194
|
-
return;
|
|
110
|
+
for (const dir of possiblePagesDirs) {
|
|
111
|
+
if (fs.existsSync(dir)) {
|
|
112
|
+
const routes = scanner.scanNextJsRoutes(dir);
|
|
113
|
+
endpoints = endpoints.concat(routes);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
195
116
|
}
|
|
196
117
|
|
|
197
118
|
// Send to platform
|
|
198
119
|
if (endpoints.length > 0) {
|
|
199
|
-
|
|
200
|
-
"[BotVersion SDK] Sending",
|
|
201
|
-
endpoints.length,
|
|
202
|
-
"endpoints to platform...",
|
|
203
|
-
);
|
|
204
|
-
self._client
|
|
205
|
-
.registerEndpoints(endpoints)
|
|
206
|
-
.then(function () {
|
|
207
|
-
console.log(
|
|
208
|
-
"[BotVersion SDK] ✅ Endpoints queued —",
|
|
209
|
-
endpoints.length,
|
|
210
|
-
"endpoints will be sent shortly",
|
|
211
|
-
);
|
|
212
|
-
})
|
|
213
|
-
.catch(function (err) {
|
|
214
|
-
console.error(
|
|
215
|
-
"[BotVersion SDK] ❌ Failed to register endpoints:",
|
|
216
|
-
err.message,
|
|
217
|
-
);
|
|
218
|
-
});
|
|
120
|
+
self._client.registerEndpoints(endpoints);
|
|
219
121
|
}
|
|
220
122
|
|
|
221
|
-
|
|
123
|
+
var routePatterns = scanner.scanFrontendRoutes(
|
|
124
|
+
options.cwd || process.cwd(),
|
|
125
|
+
);
|
|
126
|
+
if (routePatterns.length > 0) {
|
|
127
|
+
self._client
|
|
128
|
+
.registerRoutePatterns(routePatterns)
|
|
129
|
+
.catch(function (err) {});
|
|
130
|
+
}
|
|
222
131
|
}, 500);
|
|
223
132
|
},
|
|
224
133
|
|
|
@@ -239,385 +148,15 @@ var BotVersion = {
|
|
|
239
148
|
}
|
|
240
149
|
return this._client.registerEndpoints([endpoint]);
|
|
241
150
|
},
|
|
242
|
-
|
|
243
|
-
chat: function (req, res) {
|
|
244
|
-
if (!this._client) {
|
|
245
|
-
return res.status(500).json({ error: "BotVersion SDK not initialized." });
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
var getUserContext = this._options && this._options.getUserContext;
|
|
249
|
-
var userContext = getUserContext
|
|
250
|
-
? getUserContext(req)
|
|
251
|
-
: extractDefaultContext(req);
|
|
252
|
-
|
|
253
|
-
this._client
|
|
254
|
-
.agentChat({
|
|
255
|
-
message: req.body.message,
|
|
256
|
-
conversationHistory: req.body.conversationHistory || [],
|
|
257
|
-
pageContext: req.body.pageContext || {},
|
|
258
|
-
userContext: userContext,
|
|
259
|
-
workspaceKey: this._options.apiKey,
|
|
260
|
-
chatbotId: req.body.chatbotId,
|
|
261
|
-
})
|
|
262
|
-
.then(function (response) {
|
|
263
|
-
return res.status(200).json(response);
|
|
264
|
-
})
|
|
265
|
-
.catch(function (err) {
|
|
266
|
-
console.error("[BotVersion SDK] chat error:", err);
|
|
267
|
-
return res.status(500).json({ error: "Agent error" });
|
|
268
|
-
});
|
|
269
|
-
},
|
|
270
151
|
};
|
|
271
152
|
|
|
272
|
-
|
|
273
|
-
var user = req.user || (req.session && req.session.user) || {};
|
|
274
|
-
var sensitiveKeys = [
|
|
275
|
-
"password",
|
|
276
|
-
"passwd",
|
|
277
|
-
"pwd",
|
|
278
|
-
"token",
|
|
279
|
-
"accesstoken",
|
|
280
|
-
"refreshtoken",
|
|
281
|
-
"bearertoken",
|
|
282
|
-
"secret",
|
|
283
|
-
"privatesecret",
|
|
284
|
-
"apikey",
|
|
285
|
-
"api_key",
|
|
286
|
-
"privatekey",
|
|
287
|
-
"private_key",
|
|
288
|
-
"signingkey",
|
|
289
|
-
"hash",
|
|
290
|
-
"passwordhash",
|
|
291
|
-
"salt",
|
|
292
|
-
"cvv",
|
|
293
|
-
"ssn",
|
|
294
|
-
"pin",
|
|
295
|
-
"creditcard",
|
|
296
|
-
"credit_card",
|
|
297
|
-
"cardnumber",
|
|
298
|
-
"card_number",
|
|
299
|
-
"otp",
|
|
300
|
-
"mfa",
|
|
301
|
-
"totp",
|
|
302
|
-
"image",
|
|
303
|
-
"avatar",
|
|
304
|
-
"photo",
|
|
305
|
-
];
|
|
306
|
-
|
|
307
|
-
// Step 1: Flatten nested objects
|
|
308
|
-
function flattenObject(obj, prefix) {
|
|
309
|
-
prefix = prefix || "";
|
|
310
|
-
var result = {};
|
|
311
|
-
Object.keys(obj).forEach(function (key) {
|
|
312
|
-
var value = obj[key];
|
|
313
|
-
var fullKey = prefix ? prefix + "_" + key : key;
|
|
314
|
-
if (value === null || value === undefined) return;
|
|
315
|
-
if (typeof value === "object" && !Array.isArray(value)) {
|
|
316
|
-
var nested = flattenObject(value, fullKey);
|
|
317
|
-
Object.keys(nested).forEach(function (k) {
|
|
318
|
-
result[k] = nested[k];
|
|
319
|
-
});
|
|
320
|
-
} else if (typeof value !== "object") {
|
|
321
|
-
result[fullKey] = value;
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
return result;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
var flatUser = flattenObject(user);
|
|
328
|
-
|
|
329
|
-
// Step 2: Strip sensitive keys
|
|
330
|
-
var context = {};
|
|
331
|
-
Object.keys(flatUser).forEach(function (key) {
|
|
332
|
-
var isSensitive = sensitiveKeys.some(function (sk) {
|
|
333
|
-
return key.toLowerCase().includes(sk);
|
|
334
|
-
});
|
|
335
|
-
if (!isSensitive) {
|
|
336
|
-
context[key] = flatUser[key];
|
|
337
|
-
}
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
// Step 3: Smart aliasing
|
|
341
|
-
var idSuffixes = ["id", "key", "code", "ref", "slug", "uuid", "num", "no"];
|
|
342
|
-
var cleanPrefixes = [
|
|
343
|
-
"active",
|
|
344
|
-
"current",
|
|
345
|
-
"selected",
|
|
346
|
-
"default",
|
|
347
|
-
"my",
|
|
348
|
-
"the",
|
|
349
|
-
"this",
|
|
350
|
-
];
|
|
351
|
-
|
|
352
|
-
Object.keys(context).forEach(function (key) {
|
|
353
|
-
var lowerKey = key.toLowerCase();
|
|
354
|
-
var isIdField = idSuffixes.some(function (suffix) {
|
|
355
|
-
return lowerKey.endsWith(suffix);
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
if (isIdField && context[key]) {
|
|
359
|
-
var cleanKey = key;
|
|
360
|
-
cleanPrefixes.forEach(function (prefix) {
|
|
361
|
-
var regex = new RegExp("^" + prefix, "i");
|
|
362
|
-
if (regex.test(cleanKey)) {
|
|
363
|
-
cleanKey = cleanKey.replace(regex, "");
|
|
364
|
-
cleanKey = cleanKey.charAt(0).toLowerCase() + cleanKey.slice(1);
|
|
365
|
-
}
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
if (cleanKey !== key && !context[cleanKey]) {
|
|
369
|
-
context[cleanKey] = context[key];
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
return context;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Named exports for both CJS and ESM
|
|
153
|
+
// Named exports
|
|
378
154
|
BotVersion.init = BotVersion.init.bind(BotVersion);
|
|
379
155
|
BotVersion.getEndpoints = BotVersion.getEndpoints.bind(BotVersion);
|
|
380
156
|
BotVersion.registerEndpoint = BotVersion.registerEndpoint.bind(BotVersion);
|
|
381
|
-
BotVersion.chat = BotVersion.chat.bind(BotVersion);
|
|
382
|
-
|
|
383
|
-
BotVersion.nextHandler = function (options) {
|
|
384
|
-
options = options || {};
|
|
385
|
-
var self = this;
|
|
386
|
-
var hasScanned = false;
|
|
387
|
-
|
|
388
|
-
return async function handler(req, res) {
|
|
389
|
-
// ── Initialize on first request if not already done ──
|
|
390
|
-
if (!self._initialized || !self._client) {
|
|
391
|
-
var apiKey = options.apiKey;
|
|
392
|
-
if (!apiKey) {
|
|
393
|
-
console.error(
|
|
394
|
-
"[BotVersion SDK] ❌ apiKey is required in nextHandler options.",
|
|
395
|
-
);
|
|
396
|
-
return res
|
|
397
|
-
.status(500)
|
|
398
|
-
.json({ error: "BotVersion SDK not configured." });
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
self._client = new BotVersionClient({
|
|
402
|
-
apiKey: apiKey,
|
|
403
|
-
platformUrl:
|
|
404
|
-
options.platformUrl || "https://chatbusiness-two.vercel.app",
|
|
405
|
-
debug: options.debug || false,
|
|
406
|
-
timeout: options.timeout || 30000,
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
global._botVersionClient = self._client;
|
|
410
|
-
global._botVersionOptions = options;
|
|
411
|
-
self._initialized = true;
|
|
412
|
-
self._options = options;
|
|
413
|
-
|
|
414
|
-
console.log("[BotVersion SDK] ✅ Initialized from nextHandler");
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// Restore from global if hot reload lost the instance
|
|
418
|
-
if (!self._client && global._botVersionClient) {
|
|
419
|
-
self._client = global._botVersionClient;
|
|
420
|
-
self._options = global._botVersionOptions;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// ── Handle the chat request ───────────────────────────────────────────
|
|
424
|
-
var session = null;
|
|
425
|
-
if (options.getSession) {
|
|
426
|
-
session = await options.getSession(req, res);
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
req.user = (session && session.user) || {};
|
|
430
|
-
|
|
431
|
-
var getUserContext =
|
|
432
|
-
(self._options && self._options.getUserContext) ||
|
|
433
|
-
function (req) {
|
|
434
|
-
var user = req.user || {};
|
|
435
|
-
var sensitiveKeys = [
|
|
436
|
-
"password",
|
|
437
|
-
"passwd",
|
|
438
|
-
"pwd",
|
|
439
|
-
"token",
|
|
440
|
-
"accesstoken",
|
|
441
|
-
"refreshtoken",
|
|
442
|
-
"bearertoken",
|
|
443
|
-
"secret",
|
|
444
|
-
"privatesecret",
|
|
445
|
-
"apikey",
|
|
446
|
-
"api_key",
|
|
447
|
-
"privatekey",
|
|
448
|
-
"private_key",
|
|
449
|
-
"signingkey",
|
|
450
|
-
"hash",
|
|
451
|
-
"passwordhash",
|
|
452
|
-
"salt",
|
|
453
|
-
"cvv",
|
|
454
|
-
"ssn",
|
|
455
|
-
"pin",
|
|
456
|
-
"creditcard",
|
|
457
|
-
"credit_card",
|
|
458
|
-
"cardnumber",
|
|
459
|
-
"card_number",
|
|
460
|
-
"otp",
|
|
461
|
-
"mfa",
|
|
462
|
-
"totp",
|
|
463
|
-
"image",
|
|
464
|
-
"avatar",
|
|
465
|
-
"photo",
|
|
466
|
-
];
|
|
467
|
-
|
|
468
|
-
// Step 1: Flatten nested objects
|
|
469
|
-
function flattenObject(obj, prefix) {
|
|
470
|
-
prefix = prefix || "";
|
|
471
|
-
var result = {};
|
|
472
|
-
Object.keys(obj).forEach(function (key) {
|
|
473
|
-
var value = obj[key];
|
|
474
|
-
var fullKey = prefix ? prefix + "_" + key : key;
|
|
475
|
-
if (value === null || value === undefined) return;
|
|
476
|
-
if (typeof value === "object" && !Array.isArray(value)) {
|
|
477
|
-
var nested = flattenObject(value, fullKey);
|
|
478
|
-
Object.keys(nested).forEach(function (k) {
|
|
479
|
-
result[k] = nested[k];
|
|
480
|
-
});
|
|
481
|
-
} else if (typeof value !== "object") {
|
|
482
|
-
result[fullKey] = value;
|
|
483
|
-
}
|
|
484
|
-
});
|
|
485
|
-
return result;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
var flatUser = flattenObject(user);
|
|
489
|
-
|
|
490
|
-
// Step 2: Strip sensitive keys
|
|
491
|
-
var context = {};
|
|
492
|
-
Object.keys(flatUser).forEach(function (key) {
|
|
493
|
-
var isSensitive = sensitiveKeys.some(function (sk) {
|
|
494
|
-
return key.toLowerCase().includes(sk);
|
|
495
|
-
});
|
|
496
|
-
if (!isSensitive) {
|
|
497
|
-
context[key] = flatUser[key];
|
|
498
|
-
}
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
// Step 3: Smart aliasing
|
|
502
|
-
var idSuffixes = [
|
|
503
|
-
"id",
|
|
504
|
-
"key",
|
|
505
|
-
"code",
|
|
506
|
-
"ref",
|
|
507
|
-
"slug",
|
|
508
|
-
"uuid",
|
|
509
|
-
"num",
|
|
510
|
-
"no",
|
|
511
|
-
];
|
|
512
|
-
var cleanPrefixes = [
|
|
513
|
-
"active",
|
|
514
|
-
"current",
|
|
515
|
-
"selected",
|
|
516
|
-
"default",
|
|
517
|
-
"my",
|
|
518
|
-
"the",
|
|
519
|
-
"this",
|
|
520
|
-
];
|
|
521
|
-
|
|
522
|
-
Object.keys(context).forEach(function (key) {
|
|
523
|
-
var lowerKey = key.toLowerCase();
|
|
524
|
-
var isIdField = idSuffixes.some(function (suffix) {
|
|
525
|
-
return lowerKey.endsWith(suffix);
|
|
526
|
-
});
|
|
527
|
-
|
|
528
|
-
if (isIdField && context[key]) {
|
|
529
|
-
var cleanKey = key;
|
|
530
|
-
cleanPrefixes.forEach(function (prefix) {
|
|
531
|
-
var regex = new RegExp("^" + prefix, "i");
|
|
532
|
-
if (regex.test(cleanKey)) {
|
|
533
|
-
cleanKey = cleanKey.replace(regex, "");
|
|
534
|
-
cleanKey = cleanKey.charAt(0).toLowerCase() + cleanKey.slice(1);
|
|
535
|
-
}
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
if (cleanKey !== key && !context[cleanKey]) {
|
|
539
|
-
context[cleanKey] = context[key];
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
console.log("[BotVersion] userContext being sent:", context);
|
|
545
|
-
return context;
|
|
546
|
-
};
|
|
547
|
-
|
|
548
|
-
return new Promise(function (resolve) {
|
|
549
|
-
console.log("[BotVersion] req.body:", JSON.stringify(req.body));
|
|
550
|
-
console.log("[BotVersion] chatbotId from body:", req.body.chatbotId);
|
|
551
|
-
self._client
|
|
552
|
-
.agentChat({
|
|
553
|
-
message: req.body.message,
|
|
554
|
-
conversationHistory: req.body.conversationHistory || [],
|
|
555
|
-
pageContext: req.body.pageContext || {},
|
|
556
|
-
userContext: getUserContext(req),
|
|
557
|
-
chatbotId: req.body.chatbotId,
|
|
558
|
-
publicKey: req.body.publicKey,
|
|
559
|
-
})
|
|
560
|
-
.then(function (response) {
|
|
561
|
-
res.status(200).json(response);
|
|
562
|
-
resolve();
|
|
563
|
-
})
|
|
564
|
-
.catch(function (err) {
|
|
565
|
-
console.error("[BotVersion SDK] chat error:", err);
|
|
566
|
-
res.status(500).json({ error: "Agent error" });
|
|
567
|
-
resolve();
|
|
568
|
-
});
|
|
569
|
-
});
|
|
570
|
-
};
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
BotVersion.nextHandler = BotVersion.nextHandler.bind(BotVersion);
|
|
574
|
-
|
|
575
|
-
BotVersion.appRouterHandler = function () {
|
|
576
|
-
throw new Error(
|
|
577
|
-
"[BotVersion SDK] appRouterHandler is not supported. " +
|
|
578
|
-
"Please run: npx botversion-sdk init --key YOUR_KEY --force " +
|
|
579
|
-
"to regenerate the correct route file.",
|
|
580
|
-
);
|
|
581
|
-
};
|
|
582
157
|
|
|
583
158
|
module.exports = BotVersion;
|
|
584
159
|
module.exports.default = BotVersion;
|
|
585
160
|
module.exports.init = BotVersion.init;
|
|
586
161
|
module.exports.getEndpoints = BotVersion.getEndpoints;
|
|
587
162
|
module.exports.registerEndpoint = BotVersion.registerEndpoint;
|
|
588
|
-
module.exports.chat = BotVersion.chat;
|
|
589
|
-
module.exports.nextHandler = BotVersion.nextHandler;
|
|
590
|
-
module.exports.appRouterHandler = BotVersion.appRouterHandler;
|
|
591
|
-
|
|
592
|
-
// ── Framework detection ──────────────────────────────────────────────────────
|
|
593
|
-
function detectFramework(app) {
|
|
594
|
-
if (!app) return { supported: false, name: "unknown (no app passed)" };
|
|
595
|
-
|
|
596
|
-
var isExpress =
|
|
597
|
-
typeof app.use === "function" &&
|
|
598
|
-
typeof app.get === "function" &&
|
|
599
|
-
typeof app.post === "function" &&
|
|
600
|
-
(app._router !== undefined ||
|
|
601
|
-
app.stack !== undefined ||
|
|
602
|
-
app.lazyrouter !== undefined);
|
|
603
|
-
|
|
604
|
-
if (isExpress) return { supported: true, name: "Express" };
|
|
605
|
-
|
|
606
|
-
if (typeof app.addHook === "function" && typeof app.route === "function") {
|
|
607
|
-
return { supported: false, name: "Fastify" };
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
if (
|
|
611
|
-
typeof app.use === "function" &&
|
|
612
|
-
app.context !== undefined &&
|
|
613
|
-
typeof app.get !== "function"
|
|
614
|
-
) {
|
|
615
|
-
return { supported: false, name: "Koa" };
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
if (typeof app.route === "function" && typeof app.start === "function") {
|
|
619
|
-
return { supported: false, name: "Hapi" };
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
return { supported: false, name: "unknown" };
|
|
623
|
-
}
|