@diegoaltoworks/chatter 1.0.0 → 2.1.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 +3 -1
- package/dist/channels/gates.d.ts +21 -2
- package/dist/channels/gates.d.ts.map +1 -1
- package/dist/channels/index.d.ts +5 -3
- package/dist/channels/index.d.ts.map +1 -1
- package/dist/channels/index.js +31 -13
- package/dist/channels/index.mjs +30 -13
- package/dist/channels/matrix/channel.d.ts +2 -0
- package/dist/channels/matrix/channel.d.ts.map +1 -1
- package/dist/channels/matrix/handler.d.ts +9 -0
- package/dist/channels/matrix/handler.d.ts.map +1 -1
- package/dist/channels/matrix/index.d.ts +1 -1
- package/dist/channels/matrix/index.d.ts.map +1 -1
- package/dist/channels/matrix/index.js +75 -20
- package/dist/channels/matrix/index.mjs +74 -20
- package/dist/channels/matrix/updates.d.ts +8 -2
- package/dist/channels/matrix/updates.d.ts.map +1 -1
- package/dist/channels/pipeline.d.ts +34 -4
- package/dist/channels/pipeline.d.ts.map +1 -1
- package/dist/channels/polling.d.ts +11 -0
- package/dist/channels/polling.d.ts.map +1 -1
- package/dist/channels/telegram/channel.d.ts +2 -0
- package/dist/channels/telegram/channel.d.ts.map +1 -1
- package/dist/channels/telegram/handler.d.ts +9 -0
- package/dist/channels/telegram/handler.d.ts.map +1 -1
- package/dist/channels/telegram/index.d.ts +1 -1
- package/dist/channels/telegram/index.d.ts.map +1 -1
- package/dist/channels/telegram/index.js +73 -24
- package/dist/channels/telegram/index.mjs +72 -24
- package/dist/channels/telegram/updates.d.ts +8 -2
- package/dist/channels/telegram/updates.d.ts.map +1 -1
- package/dist/channels/telegram/webhook.d.ts +10 -0
- package/dist/channels/telegram/webhook.d.ts.map +1 -1
- package/dist/channels/whatsapp/channel.d.ts +8 -0
- package/dist/channels/whatsapp/channel.d.ts.map +1 -1
- package/dist/channels/whatsapp/inbound.d.ts +2 -0
- package/dist/channels/whatsapp/inbound.d.ts.map +1 -1
- package/dist/channels/whatsapp/index.js +45 -18
- package/dist/channels/whatsapp/index.mjs +45 -18
- package/dist/core/answer.d.ts +9 -2
- package/dist/core/answer.d.ts.map +1 -1
- package/dist/core/chunking.d.ts +31 -0
- package/dist/core/chunking.d.ts.map +1 -0
- package/dist/core/guardrails.d.ts +11 -1
- package/dist/core/guardrails.d.ts.map +1 -1
- package/dist/core/llm.d.ts +3 -1
- package/dist/core/llm.d.ts.map +1 -1
- package/dist/core/retrieval.d.ts +39 -0
- package/dist/core/retrieval.d.ts.map +1 -1
- package/dist/history/index.js +12 -9
- package/dist/history/index.mjs +12 -9
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +261 -52
- package/dist/index.mjs +254 -47
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +217 -30
- package/dist/mcp-server.mjs +216 -29
- package/dist/personas/index.d.ts +1 -1
- package/dist/personas/index.d.ts.map +1 -1
- package/dist/personas/index.js +21 -7
- package/dist/personas/index.mjs +21 -7
- package/dist/personas/resolver.d.ts +35 -8
- package/dist/personas/resolver.d.ts.map +1 -1
- package/dist/personas/timeContext.d.ts.map +1 -1
- package/dist/routes/demo.d.ts.map +1 -1
- package/dist/routes/openai.d.ts.map +1 -1
- package/dist/routes/private.d.ts.map +1 -1
- package/dist/routes/public.d.ts.map +1 -1
- package/dist/scheduler/index.js +12 -9
- package/dist/scheduler/index.mjs +12 -9
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +251 -50
- package/dist/server.mjs +246 -45
- package/dist/types.d.ts +39 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +13 -13
package/dist/index.js
CHANGED
|
@@ -94,6 +94,126 @@ var init_buildLock = __esm({
|
|
|
94
94
|
}
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
+
// src/core/chunking.ts
|
|
98
|
+
function headingOf(line) {
|
|
99
|
+
const match = HEADING.exec(line);
|
|
100
|
+
if (!match) return void 0;
|
|
101
|
+
const title = (match[2] ?? "").replace(/[ \t]+#+$/, "").replace(/^#+$/, "").trim();
|
|
102
|
+
return { level: match[1].length, title };
|
|
103
|
+
}
|
|
104
|
+
function startsTable(lines, i) {
|
|
105
|
+
return lines[i].includes("|") && i + 1 < lines.length && TABLE_DELIMITER.test(lines[i + 1]);
|
|
106
|
+
}
|
|
107
|
+
function fenceEnd(lines, start) {
|
|
108
|
+
const opener = FENCE.exec(lines[start]);
|
|
109
|
+
if (!opener) return start + 1;
|
|
110
|
+
const marker = opener[1];
|
|
111
|
+
const closer = new RegExp(`^ {0,3}${marker[0] === "`" ? "`" : "~"}{${marker.length},}[ \\t]*$`);
|
|
112
|
+
for (let i = start + 1; i < lines.length; i++) if (closer.test(lines[i])) return i + 1;
|
|
113
|
+
return lines.length;
|
|
114
|
+
}
|
|
115
|
+
function listEnd(lines, start) {
|
|
116
|
+
let end = start + 1;
|
|
117
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
118
|
+
const line = lines[i];
|
|
119
|
+
if (isBlank(line)) {
|
|
120
|
+
let next = i + 1;
|
|
121
|
+
while (next < lines.length && isBlank(lines[next])) next++;
|
|
122
|
+
if (next < lines.length && (LIST_ITEM.test(lines[next]) || isIndented(lines[next]))) {
|
|
123
|
+
i = next - 1;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
if (headingOf(line) && !isIndented(line)) break;
|
|
129
|
+
if (FENCE.test(line) && !isIndented(line)) break;
|
|
130
|
+
end = i + 1;
|
|
131
|
+
}
|
|
132
|
+
return end;
|
|
133
|
+
}
|
|
134
|
+
function tableEnd(lines, start) {
|
|
135
|
+
let end = start + 2;
|
|
136
|
+
while (end < lines.length && !isBlank(lines[end]) && lines[end].includes("|")) end++;
|
|
137
|
+
return end;
|
|
138
|
+
}
|
|
139
|
+
function paragraphEnd(lines, start) {
|
|
140
|
+
let end = start + 1;
|
|
141
|
+
while (end < lines.length && !isBlank(lines[end]) && !headingOf(lines[end]) && !FENCE.test(lines[end]) && !LIST_ITEM.test(lines[end])) {
|
|
142
|
+
end++;
|
|
143
|
+
}
|
|
144
|
+
return end;
|
|
145
|
+
}
|
|
146
|
+
function scan(text) {
|
|
147
|
+
const lines = text.replace(/\r\n?/g, "\n").split("\n");
|
|
148
|
+
const sections = [{ trail: [], blocks: [] }];
|
|
149
|
+
const stack = [];
|
|
150
|
+
let i = 0;
|
|
151
|
+
while (i < lines.length) {
|
|
152
|
+
const line = lines[i];
|
|
153
|
+
if (isBlank(line)) {
|
|
154
|
+
i++;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const heading = FENCE.test(line) ? void 0 : headingOf(line);
|
|
158
|
+
if (heading) {
|
|
159
|
+
while (stack.length && stack[stack.length - 1].level >= heading.level) stack.pop();
|
|
160
|
+
stack.push(heading);
|
|
161
|
+
sections.push({ trail: stack.map((h) => h.title), heading: line, blocks: [] });
|
|
162
|
+
i++;
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
let end;
|
|
166
|
+
if (FENCE.test(line)) end = fenceEnd(lines, i);
|
|
167
|
+
else if (LIST_ITEM.test(line)) end = listEnd(lines, i);
|
|
168
|
+
else if (startsTable(lines, i)) end = tableEnd(lines, i);
|
|
169
|
+
else end = paragraphEnd(lines, i);
|
|
170
|
+
sections[sections.length - 1].blocks.push({ lines: lines.slice(i, end) });
|
|
171
|
+
i = end;
|
|
172
|
+
}
|
|
173
|
+
return sections;
|
|
174
|
+
}
|
|
175
|
+
function chunkSections(text, max = 900) {
|
|
176
|
+
const cap = Math.max(1, max);
|
|
177
|
+
const out = [];
|
|
178
|
+
const emit = (parts, section) => {
|
|
179
|
+
const body = parts.join("\n\n");
|
|
180
|
+
if (body.trim() === "") return;
|
|
181
|
+
out.push({ text: body, section: [...section], position: out.length });
|
|
182
|
+
};
|
|
183
|
+
for (const section of scan(text)) {
|
|
184
|
+
let parts = section.heading ? [section.heading.trim()] : [];
|
|
185
|
+
let size = parts.join("\n\n").length;
|
|
186
|
+
let hasBlock = false;
|
|
187
|
+
for (const block of section.blocks) {
|
|
188
|
+
const piece = block.lines.join("\n");
|
|
189
|
+
const added = piece.length + (parts.length ? 2 : 0);
|
|
190
|
+
if (hasBlock && size + added > cap) {
|
|
191
|
+
emit(parts, section.trail);
|
|
192
|
+
parts = [];
|
|
193
|
+
size = 0;
|
|
194
|
+
hasBlock = false;
|
|
195
|
+
}
|
|
196
|
+
size += piece.length + (parts.length ? 2 : 0);
|
|
197
|
+
parts.push(piece);
|
|
198
|
+
hasBlock = true;
|
|
199
|
+
}
|
|
200
|
+
emit(parts, section.trail);
|
|
201
|
+
}
|
|
202
|
+
return out;
|
|
203
|
+
}
|
|
204
|
+
var FENCE, HEADING, LIST_ITEM, TABLE_DELIMITER, isBlank, isIndented;
|
|
205
|
+
var init_chunking = __esm({
|
|
206
|
+
"src/core/chunking.ts"() {
|
|
207
|
+
"use strict";
|
|
208
|
+
FENCE = /^ {0,3}(`{3,}|~{3,})/;
|
|
209
|
+
HEADING = /^ {0,3}(#{1,6})(?:[ \t]+(.*?))?[ \t]*$/;
|
|
210
|
+
LIST_ITEM = /^[ \t]*(?:[-*+]|\d{1,9}[.)])[ \t]+\S/;
|
|
211
|
+
TABLE_DELIMITER = /^[ \t]*\|?[ \t]*:?-+:?[ \t]*(?:\|[ \t]*:?-+:?[ \t]*)*\|?[ \t]*$/;
|
|
212
|
+
isBlank = (line) => line.trim() === "";
|
|
213
|
+
isIndented = (line) => /^(?: {2,}|\t)/.test(line);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
97
217
|
// src/core/loaders.ts
|
|
98
218
|
function walk(dir) {
|
|
99
219
|
const items = [];
|
|
@@ -199,11 +319,13 @@ async function sha256(input) {
|
|
|
199
319
|
const hash = await crypto.subtle.digest("SHA-256", data);
|
|
200
320
|
return Array.from(new Uint8Array(hash)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
201
321
|
}
|
|
202
|
-
var EMB_MODEL, DEFAULT_KNOWLEDGE_DIR, DATABASE_CONFIG_REQUIRED_MESSAGE, VectorStore;
|
|
322
|
+
var import_node_path3, EMB_MODEL, DEFAULT_KNOWLEDGE_DIR, DATABASE_CONFIG_REQUIRED_MESSAGE, VectorStore;
|
|
203
323
|
var init_retrieval = __esm({
|
|
204
324
|
"src/core/retrieval.ts"() {
|
|
205
325
|
"use strict";
|
|
326
|
+
import_node_path3 = require("node:path");
|
|
206
327
|
init_buildLock();
|
|
328
|
+
init_chunking();
|
|
207
329
|
init_loaders();
|
|
208
330
|
init_logger();
|
|
209
331
|
EMB_MODEL = "text-embedding-3-large";
|
|
@@ -214,6 +336,7 @@ var init_retrieval = __esm({
|
|
|
214
336
|
this.embed = embed;
|
|
215
337
|
this.db = options.databaseClient;
|
|
216
338
|
this.knowledgeDir = options.knowledgeDir || DEFAULT_KNOWLEDGE_DIR;
|
|
339
|
+
this.chunking = options.chunking ?? "lines";
|
|
217
340
|
this.logger = options.logger ?? createConsoleLogger();
|
|
218
341
|
this.buildLock = options.buildLock ?? createTursoBuildLock(this.db);
|
|
219
342
|
this.instanceId = options.instanceId ?? crypto.randomUUID();
|
|
@@ -227,6 +350,7 @@ var init_retrieval = __esm({
|
|
|
227
350
|
*/
|
|
228
351
|
db;
|
|
229
352
|
knowledgeDir;
|
|
353
|
+
chunking;
|
|
230
354
|
logger;
|
|
231
355
|
buildLock;
|
|
232
356
|
instanceId;
|
|
@@ -287,11 +411,41 @@ var init_retrieval = __esm({
|
|
|
287
411
|
this.logger.info("No knowledge documents and no existing chunks - nothing to build");
|
|
288
412
|
return;
|
|
289
413
|
}
|
|
414
|
+
this.logger.info(`Chunking mode: ${this.chunking}`);
|
|
415
|
+
if (this.chunking === "sections") await this.ensureSectionColumns();
|
|
290
416
|
const rows = [];
|
|
291
417
|
for (const d of docs) {
|
|
292
|
-
|
|
293
|
-
const
|
|
294
|
-
|
|
418
|
+
if (this.chunking === "sections") {
|
|
419
|
+
const source = (0, import_node_path3.relative)(this.knowledgeDir, d.source).split(import_node_path3.sep).join("/");
|
|
420
|
+
for (const c of chunkSections(d.text)) {
|
|
421
|
+
const section = c.section.join(" > ");
|
|
422
|
+
const id = await sha256(`${d.bucket}|${source}|${section}|${c.text}`);
|
|
423
|
+
const context = section ? `${source} > ${section}` : source;
|
|
424
|
+
rows.push({
|
|
425
|
+
id,
|
|
426
|
+
bucket: d.bucket,
|
|
427
|
+
source,
|
|
428
|
+
text: c.text,
|
|
429
|
+
embedText: `${context}
|
|
430
|
+
|
|
431
|
+
${c.text}`,
|
|
432
|
+
section,
|
|
433
|
+
position: c.position
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
} else {
|
|
437
|
+
for (const part of chunk(d.text)) {
|
|
438
|
+
const id = await sha256(`${d.bucket}|${d.source}|${part}`);
|
|
439
|
+
rows.push({
|
|
440
|
+
id,
|
|
441
|
+
bucket: d.bucket,
|
|
442
|
+
source: d.source,
|
|
443
|
+
text: part,
|
|
444
|
+
embedText: part,
|
|
445
|
+
section: null,
|
|
446
|
+
position: null
|
|
447
|
+
});
|
|
448
|
+
}
|
|
295
449
|
}
|
|
296
450
|
}
|
|
297
451
|
this.logger.info(`Created ${rows.length} chunks from knowledge documents`);
|
|
@@ -300,11 +454,17 @@ var init_retrieval = __esm({
|
|
|
300
454
|
for (let i = 0; i < rows.length; i += UPSERT_BATCH) {
|
|
301
455
|
const batch = rows.slice(i, i + UPSERT_BATCH);
|
|
302
456
|
await this.db.batch(
|
|
303
|
-
batch.map(
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
457
|
+
batch.map(
|
|
458
|
+
(r) => this.chunking === "sections" ? {
|
|
459
|
+
sql: `INSERT INTO chunks(id,bucket,source,text,section,position) VALUES(?,?,?,?,?,?)
|
|
460
|
+
ON CONFLICT(id) DO NOTHING`,
|
|
461
|
+
args: [r.id, r.bucket, r.source, r.text, r.section, r.position]
|
|
462
|
+
} : {
|
|
463
|
+
sql: `INSERT INTO chunks(id,bucket,source,text) VALUES(?,?,?,?)
|
|
464
|
+
ON CONFLICT(id) DO NOTHING`,
|
|
465
|
+
args: [r.id, r.bucket, r.source, r.text]
|
|
466
|
+
}
|
|
467
|
+
),
|
|
308
468
|
"write"
|
|
309
469
|
);
|
|
310
470
|
}
|
|
@@ -325,7 +485,7 @@ var init_retrieval = __esm({
|
|
|
325
485
|
return;
|
|
326
486
|
}
|
|
327
487
|
this.logger.info(`Embedding ${missing.length} new/updated chunks with ${EMB_MODEL}...`);
|
|
328
|
-
const textById = new Map(rows.map((r) => [r.id, r.
|
|
488
|
+
const textById = new Map(rows.map((r) => [r.id, r.embedText]));
|
|
329
489
|
const BATCH = 96;
|
|
330
490
|
for (let i = 0; i < missing.length; i += BATCH) {
|
|
331
491
|
const batchIds = missing.slice(i, i + BATCH);
|
|
@@ -346,6 +506,18 @@ var init_retrieval = __esm({
|
|
|
346
506
|
}
|
|
347
507
|
this.logger.info(`Successfully embedded ${missing.length} new chunks`);
|
|
348
508
|
}
|
|
509
|
+
/**
|
|
510
|
+
* Adds the nullable `section`/`position` columns to a `chunks` table that
|
|
511
|
+
* every released version created without them. Checked via table_info so it
|
|
512
|
+
* is a no-op once present; only `'sections'` mode ever calls it.
|
|
513
|
+
*/
|
|
514
|
+
async ensureSectionColumns() {
|
|
515
|
+
const info = await this.db.execute("PRAGMA table_info(chunks)");
|
|
516
|
+
const have = new Set(info.rows.map((r) => String(r.name)));
|
|
517
|
+
if (!have.has("section")) await this.db.execute("ALTER TABLE chunks ADD COLUMN section TEXT");
|
|
518
|
+
if (!have.has("position"))
|
|
519
|
+
await this.db.execute("ALTER TABLE chunks ADD COLUMN position INTEGER");
|
|
520
|
+
}
|
|
349
521
|
// Remove chunks from database that no longer exist in markdown files
|
|
350
522
|
async cleanupStaleChunks(currentIds) {
|
|
351
523
|
const result = await this.db.execute("SELECT id FROM chunks");
|
|
@@ -392,25 +564,34 @@ var init_retrieval = __esm({
|
|
|
392
564
|
* interpolated. An empty list retrieves nothing, and short-circuits before
|
|
393
565
|
* the embedding call.
|
|
394
566
|
*/
|
|
395
|
-
async
|
|
567
|
+
async queryChunks(q, k = 6, allowed = ["base"]) {
|
|
396
568
|
if (allowed.length === 0) return [];
|
|
397
569
|
const [qv] = await this.embed([q]);
|
|
398
570
|
const placeholders = allowed.map(() => "?").join(",");
|
|
399
571
|
const res = await this.db.execute({
|
|
400
|
-
sql: `SELECT c
|
|
572
|
+
sql: `SELECT c.*, e.embedding
|
|
401
573
|
FROM chunks c
|
|
402
574
|
JOIN embeddings e ON e.id = c.id
|
|
403
575
|
WHERE c.bucket IN (${placeholders})`,
|
|
404
576
|
args: allowed
|
|
405
577
|
});
|
|
406
|
-
const scored =
|
|
407
|
-
for (const row of res.rows) {
|
|
578
|
+
const scored = res.rows.map((row) => {
|
|
408
579
|
const emb = JSON.parse(String(row.embedding));
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
580
|
+
const trail = row.section == null ? "" : String(row.section);
|
|
581
|
+
return {
|
|
582
|
+
text: String(row.text),
|
|
583
|
+
bucket: String(row.bucket ?? ""),
|
|
584
|
+
source: String(row.source ?? ""),
|
|
585
|
+
section: trail ? trail.split(" > ") : [],
|
|
586
|
+
score: _VectorStore.cosine(qv, emb)
|
|
587
|
+
};
|
|
588
|
+
});
|
|
589
|
+
scored.sort((a, b) => b.score - a.score);
|
|
590
|
+
return scored.slice(0, k);
|
|
591
|
+
}
|
|
592
|
+
/** Same results as {@link queryChunks}, as bare text. */
|
|
593
|
+
async query(q, k = 6, allowed = ["base"]) {
|
|
594
|
+
return (await this.queryChunks(q, k, allowed)).map((c) => c.text);
|
|
414
595
|
}
|
|
415
596
|
};
|
|
416
597
|
}
|
|
@@ -538,6 +719,7 @@ __export(index_exports, {
|
|
|
538
719
|
DEFAULT_KNOWLEDGE_DIR: () => DEFAULT_KNOWLEDGE_DIR,
|
|
539
720
|
DEFAULT_MODEL: () => DEFAULT_MODEL,
|
|
540
721
|
DEFAULT_PROMPTS_DIR: () => DEFAULT_PROMPTS_DIR,
|
|
722
|
+
DEFAULT_REFUSAL: () => DEFAULT_REFUSAL,
|
|
541
723
|
PromptLoader: () => PromptLoader,
|
|
542
724
|
VectorStore: () => VectorStore,
|
|
543
725
|
answerOnce: () => answerOnce,
|
|
@@ -545,6 +727,7 @@ __export(index_exports, {
|
|
|
545
727
|
applyTransformReply: () => applyTransformReply,
|
|
546
728
|
canAcquireBuildLock: () => canAcquireBuildLock,
|
|
547
729
|
chatBodyLimit: () => chatBodyLimit,
|
|
730
|
+
chunkSections: () => chunkSections,
|
|
548
731
|
completeOnce: () => completeOnce,
|
|
549
732
|
completeStream: () => completeStream,
|
|
550
733
|
cors: () => cors,
|
|
@@ -719,9 +902,10 @@ function detectLeakage(text) {
|
|
|
719
902
|
function scrubOutput(text) {
|
|
720
903
|
return text.replace(/sk-[A-Za-z0-9]{15,}/g, "[REDACTED]").replace(/AIza[0-9A-Za-z_-]{30,}/g, "[REDACTED]");
|
|
721
904
|
}
|
|
722
|
-
|
|
905
|
+
var DEFAULT_REFUSAL = "Sorry, I can't share internal instructions. How else can I help?";
|
|
906
|
+
function guardOutput(text, refusal) {
|
|
723
907
|
if (detectLeakage(text)) {
|
|
724
|
-
return
|
|
908
|
+
return typeof refusal === "string" && refusal.trim() ? refusal : DEFAULT_REFUSAL;
|
|
725
909
|
}
|
|
726
910
|
return scrubOutput(text);
|
|
727
911
|
}
|
|
@@ -733,7 +917,8 @@ async function completeOnce({
|
|
|
733
917
|
system,
|
|
734
918
|
messages,
|
|
735
919
|
temperature = 0.2,
|
|
736
|
-
model = DEFAULT_MODEL
|
|
920
|
+
model = DEFAULT_MODEL,
|
|
921
|
+
refusal
|
|
737
922
|
}) {
|
|
738
923
|
const res = await client.chat.completions.create({
|
|
739
924
|
model,
|
|
@@ -742,7 +927,7 @@ async function completeOnce({
|
|
|
742
927
|
});
|
|
743
928
|
const text = res.choices[0]?.message?.content ?? "";
|
|
744
929
|
return {
|
|
745
|
-
content: guardOutput(text),
|
|
930
|
+
content: guardOutput(text, refusal),
|
|
746
931
|
usage: res.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
|
|
747
932
|
};
|
|
748
933
|
}
|
|
@@ -767,12 +952,12 @@ async function* completeStream({
|
|
|
767
952
|
|
|
768
953
|
// src/core/answer.ts
|
|
769
954
|
var noUsage = () => ({ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 });
|
|
770
|
-
async function runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }) {
|
|
955
|
+
async function runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }, refusal) {
|
|
771
956
|
const result = await answerFn({ system, messages, mode, sender, conversationId });
|
|
772
957
|
const raw = typeof result === "string" ? result : result?.content;
|
|
773
958
|
const usage = typeof result === "string" ? void 0 : result?.usage;
|
|
774
959
|
return {
|
|
775
|
-
content: guardOutput(typeof raw === "string" ? raw : ""),
|
|
960
|
+
content: guardOutput(typeof raw === "string" ? raw : "", refusal),
|
|
776
961
|
usage: usage ?? noUsage()
|
|
777
962
|
};
|
|
778
963
|
}
|
|
@@ -785,12 +970,13 @@ async function answerOnce({
|
|
|
785
970
|
sender,
|
|
786
971
|
conversationId,
|
|
787
972
|
temperature,
|
|
788
|
-
model
|
|
973
|
+
model,
|
|
974
|
+
refusal
|
|
789
975
|
}) {
|
|
790
976
|
if (answerFn) {
|
|
791
|
-
return runAnswerFn(answerFn, { system, messages, mode, sender, conversationId });
|
|
977
|
+
return runAnswerFn(answerFn, { system, messages, mode, sender, conversationId }, refusal);
|
|
792
978
|
}
|
|
793
|
-
return completeOnce({ client, system, messages, temperature, model });
|
|
979
|
+
return completeOnce({ client, system, messages, temperature, model, refusal });
|
|
794
980
|
}
|
|
795
981
|
async function applyTransformReply(transformReply, input, logger) {
|
|
796
982
|
if (!transformReply) return input.text;
|
|
@@ -814,16 +1000,15 @@ async function* answerStream({
|
|
|
814
1000
|
sender,
|
|
815
1001
|
conversationId,
|
|
816
1002
|
temperature,
|
|
817
|
-
model
|
|
1003
|
+
model,
|
|
1004
|
+
refusal
|
|
818
1005
|
}) {
|
|
819
1006
|
if (answerFn) {
|
|
820
|
-
const { content } = await runAnswerFn(
|
|
821
|
-
|
|
822
|
-
messages,
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
conversationId
|
|
826
|
-
});
|
|
1007
|
+
const { content } = await runAnswerFn(
|
|
1008
|
+
answerFn,
|
|
1009
|
+
{ system, messages, mode, sender, conversationId },
|
|
1010
|
+
refusal
|
|
1011
|
+
);
|
|
827
1012
|
if (content) yield content;
|
|
828
1013
|
return;
|
|
829
1014
|
}
|
|
@@ -863,6 +1048,7 @@ async function resolveBuckets({
|
|
|
863
1048
|
|
|
864
1049
|
// src/index.ts
|
|
865
1050
|
init_buildLock();
|
|
1051
|
+
init_chunking();
|
|
866
1052
|
init_loaders();
|
|
867
1053
|
init_logger();
|
|
868
1054
|
|
|
@@ -1351,6 +1537,7 @@ async function createMCPServer(config) {
|
|
|
1351
1537
|
store = new VectorStore2(createOpenAIEmbedder2(client), {
|
|
1352
1538
|
databaseClient: db,
|
|
1353
1539
|
knowledgeDir: config.knowledgeDir || DEFAULT_KNOWLEDGE_DIR2,
|
|
1540
|
+
chunking: config.chunking,
|
|
1354
1541
|
logger: log
|
|
1355
1542
|
});
|
|
1356
1543
|
}
|
|
@@ -1422,7 +1609,8 @@ async function createMCPServer(config) {
|
|
|
1422
1609
|
messages: conversationMessages,
|
|
1423
1610
|
mode: "public",
|
|
1424
1611
|
conversationId: convId,
|
|
1425
|
-
model
|
|
1612
|
+
model,
|
|
1613
|
+
refusal: config.refusal
|
|
1426
1614
|
});
|
|
1427
1615
|
const replyText = await applyTransformReply(
|
|
1428
1616
|
config.transformReply,
|
|
@@ -1512,7 +1700,8 @@ async function createMCPServer(config) {
|
|
|
1512
1700
|
messages: conversationMessages,
|
|
1513
1701
|
mode: "private",
|
|
1514
1702
|
conversationId: convId,
|
|
1515
|
-
model
|
|
1703
|
+
model,
|
|
1704
|
+
refusal: config.refusal
|
|
1516
1705
|
});
|
|
1517
1706
|
const replyText = await applyTransformReply(
|
|
1518
1707
|
config.transformReply,
|
|
@@ -2011,7 +2200,8 @@ function demoRoutes(deps) {
|
|
|
2011
2200
|
system,
|
|
2012
2201
|
messages,
|
|
2013
2202
|
mode: "public",
|
|
2014
|
-
model
|
|
2203
|
+
model,
|
|
2204
|
+
refusal: config.refusal
|
|
2015
2205
|
})) {
|
|
2016
2206
|
await s.write(`data: ${JSON.stringify({ delta })}
|
|
2017
2207
|
|
|
@@ -2026,7 +2216,8 @@ function demoRoutes(deps) {
|
|
|
2026
2216
|
system,
|
|
2027
2217
|
messages,
|
|
2028
2218
|
mode: "public",
|
|
2029
|
-
model
|
|
2219
|
+
model,
|
|
2220
|
+
refusal: config.refusal
|
|
2030
2221
|
});
|
|
2031
2222
|
const reply = await applyTransformReply(
|
|
2032
2223
|
config.transformReply,
|
|
@@ -2167,7 +2358,8 @@ function openaiRoutes(deps) {
|
|
|
2167
2358
|
sender,
|
|
2168
2359
|
conversationId,
|
|
2169
2360
|
temperature,
|
|
2170
|
-
model: serverModel
|
|
2361
|
+
model: serverModel,
|
|
2362
|
+
refusal: config.refusal
|
|
2171
2363
|
})) {
|
|
2172
2364
|
await s.write(chunk2({ content: delta }, null));
|
|
2173
2365
|
}
|
|
@@ -2184,7 +2376,8 @@ function openaiRoutes(deps) {
|
|
|
2184
2376
|
sender,
|
|
2185
2377
|
conversationId,
|
|
2186
2378
|
temperature,
|
|
2187
|
-
model: serverModel
|
|
2379
|
+
model: serverModel,
|
|
2380
|
+
refusal: config.refusal
|
|
2188
2381
|
});
|
|
2189
2382
|
const reply = await applyTransformReply(
|
|
2190
2383
|
config.transformReply,
|
|
@@ -2275,7 +2468,8 @@ function privateRoutes(deps) {
|
|
|
2275
2468
|
messages,
|
|
2276
2469
|
mode: "private",
|
|
2277
2470
|
sender,
|
|
2278
|
-
model
|
|
2471
|
+
model,
|
|
2472
|
+
refusal: config.refusal
|
|
2279
2473
|
})) {
|
|
2280
2474
|
await s.write(`data: ${JSON.stringify({ delta })}
|
|
2281
2475
|
|
|
@@ -2291,7 +2485,8 @@ function privateRoutes(deps) {
|
|
|
2291
2485
|
messages,
|
|
2292
2486
|
mode: "private",
|
|
2293
2487
|
sender,
|
|
2294
|
-
model
|
|
2488
|
+
model,
|
|
2489
|
+
refusal: config.refusal
|
|
2295
2490
|
});
|
|
2296
2491
|
const reply = await applyTransformReply(
|
|
2297
2492
|
config.transformReply,
|
|
@@ -2360,7 +2555,8 @@ function publicRoutes(deps) {
|
|
|
2360
2555
|
system,
|
|
2361
2556
|
messages,
|
|
2362
2557
|
mode: "public",
|
|
2363
|
-
model
|
|
2558
|
+
model,
|
|
2559
|
+
refusal: config.refusal
|
|
2364
2560
|
})) {
|
|
2365
2561
|
await s.write(`data: ${JSON.stringify({ delta })}
|
|
2366
2562
|
|
|
@@ -2369,7 +2565,15 @@ function publicRoutes(deps) {
|
|
|
2369
2565
|
await s.write("event: end\ndata: {}\n\n");
|
|
2370
2566
|
});
|
|
2371
2567
|
}
|
|
2372
|
-
const out = await answerOnce({
|
|
2568
|
+
const out = await answerOnce({
|
|
2569
|
+
answerFn,
|
|
2570
|
+
client,
|
|
2571
|
+
system,
|
|
2572
|
+
messages,
|
|
2573
|
+
mode: "public",
|
|
2574
|
+
model,
|
|
2575
|
+
refusal: config.refusal
|
|
2576
|
+
});
|
|
2373
2577
|
const reply = await applyTransformReply(
|
|
2374
2578
|
config.transformReply,
|
|
2375
2579
|
{ channel: "widget-public", text: out.content },
|
|
@@ -2381,7 +2585,7 @@ function publicRoutes(deps) {
|
|
|
2381
2585
|
}
|
|
2382
2586
|
|
|
2383
2587
|
// src/server.ts
|
|
2384
|
-
var
|
|
2588
|
+
var import_node_path5 = require("node:path");
|
|
2385
2589
|
var import_hono5 = require("hono");
|
|
2386
2590
|
var import_openai2 = __toESM(require("openai"));
|
|
2387
2591
|
|
|
@@ -2485,7 +2689,7 @@ function loadServeStatic(runtime = detectRuntime()) {
|
|
|
2485
2689
|
|
|
2486
2690
|
// src/core/widgets.ts
|
|
2487
2691
|
var import_node_fs3 = require("node:fs");
|
|
2488
|
-
var
|
|
2692
|
+
var import_node_path4 = require("node:path");
|
|
2489
2693
|
var import_node_url = require("node:url");
|
|
2490
2694
|
var import_meta = {};
|
|
2491
2695
|
function resolveStatic(configStaticDir) {
|
|
@@ -2494,15 +2698,15 @@ function resolveStatic(configStaticDir) {
|
|
|
2494
2698
|
}
|
|
2495
2699
|
try {
|
|
2496
2700
|
if (import_meta.url) {
|
|
2497
|
-
const moduleDir = (0,
|
|
2498
|
-
const staticDir = (0,
|
|
2701
|
+
const moduleDir = (0, import_node_path4.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
2702
|
+
const staticDir = (0, import_node_path4.join)(moduleDir, "static");
|
|
2499
2703
|
if ((0, import_node_fs3.existsSync)(staticDir)) return { staticDir };
|
|
2500
2704
|
}
|
|
2501
2705
|
} catch {
|
|
2502
2706
|
}
|
|
2503
2707
|
try {
|
|
2504
2708
|
if (typeof __dirname !== "undefined") {
|
|
2505
|
-
const staticDir = (0,
|
|
2709
|
+
const staticDir = (0, import_node_path4.join)(__dirname, "static");
|
|
2506
2710
|
if ((0, import_node_fs3.existsSync)(staticDir)) return { staticDir };
|
|
2507
2711
|
}
|
|
2508
2712
|
} catch {
|
|
@@ -2541,6 +2745,7 @@ async function createServer(config) {
|
|
|
2541
2745
|
store = new VectorStore2(createOpenAIEmbedder2(client), {
|
|
2542
2746
|
databaseClient: db,
|
|
2543
2747
|
knowledgeDir: config.knowledgeDir || DEFAULT_KNOWLEDGE_DIR2,
|
|
2748
|
+
chunking: config.chunking,
|
|
2544
2749
|
logger
|
|
2545
2750
|
});
|
|
2546
2751
|
}
|
|
@@ -2591,7 +2796,7 @@ async function createServer(config) {
|
|
|
2591
2796
|
}
|
|
2592
2797
|
}
|
|
2593
2798
|
if (serveStatic && staticDir) {
|
|
2594
|
-
const relativePath = (0,
|
|
2799
|
+
const relativePath = (0, import_node_path5.relative)(process.cwd(), staticDir);
|
|
2595
2800
|
app.get("/chatter.js", serveStatic({ path: `${relativePath}/chatter.js` }));
|
|
2596
2801
|
app.get("/chatter.css", serveStatic({ path: `${relativePath}/chatter.css` }));
|
|
2597
2802
|
}
|
|
@@ -2638,6 +2843,7 @@ async function createServer(config) {
|
|
|
2638
2843
|
app.get("/demo/react", serveStatic({ path: `${publicDir}/react-demo.html` }));
|
|
2639
2844
|
}
|
|
2640
2845
|
const senders = createSenderRegistry(logger);
|
|
2846
|
+
const identities = /* @__PURE__ */ new Map();
|
|
2641
2847
|
const deps = {
|
|
2642
2848
|
client,
|
|
2643
2849
|
store,
|
|
@@ -2649,6 +2855,7 @@ async function createServer(config) {
|
|
|
2649
2855
|
prompts,
|
|
2650
2856
|
apiKeyManager,
|
|
2651
2857
|
senders,
|
|
2858
|
+
identities,
|
|
2652
2859
|
logger
|
|
2653
2860
|
};
|
|
2654
2861
|
if (enablePublic) {
|
|
@@ -2743,6 +2950,7 @@ function createShortener(config, fetchImpl = fetch) {
|
|
|
2743
2950
|
DEFAULT_KNOWLEDGE_DIR,
|
|
2744
2951
|
DEFAULT_MODEL,
|
|
2745
2952
|
DEFAULT_PROMPTS_DIR,
|
|
2953
|
+
DEFAULT_REFUSAL,
|
|
2746
2954
|
PromptLoader,
|
|
2747
2955
|
VectorStore,
|
|
2748
2956
|
answerOnce,
|
|
@@ -2750,6 +2958,7 @@ function createShortener(config, fetchImpl = fetch) {
|
|
|
2750
2958
|
applyTransformReply,
|
|
2751
2959
|
canAcquireBuildLock,
|
|
2752
2960
|
chatBodyLimit,
|
|
2961
|
+
chunkSections,
|
|
2753
2962
|
completeOnce,
|
|
2754
2963
|
completeStream,
|
|
2755
2964
|
cors,
|