@burtson-labs/bandit-engine 2.0.102 → 2.0.104
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/{chat-PMO3WTM4.mjs → chat-TIX4XHMD.mjs} +2 -2
- package/dist/{chunk-7NXSMMCU.mjs → chunk-BJOPAWGI.mjs} +2 -2
- package/dist/{chunk-R3HBSHLE.mjs → chunk-EGIUL7QB.mjs} +83 -21
- package/dist/chunk-EGIUL7QB.mjs.map +1 -0
- package/dist/index.js +83 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/management/management.js +83 -21
- package/dist/management/management.js.map +1 -1
- package/dist/management/management.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-R3HBSHLE.mjs.map +0 -1
- /package/dist/{chat-PMO3WTM4.mjs.map → chat-TIX4XHMD.mjs.map} +0 -0
- /package/dist/{chunk-7NXSMMCU.mjs.map → chunk-BJOPAWGI.mjs.map} +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
chat_default
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EGIUL7QB.mjs";
|
|
4
4
|
import {
|
|
5
5
|
chat_provider_default
|
|
6
6
|
} from "./chunk-VTKRZNLI.mjs";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
useGatewayHealth,
|
|
11
11
|
useGatewayMemory,
|
|
12
12
|
useGatewayModels
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-BJOPAWGI.mjs";
|
|
14
14
|
import "./chunk-KYC7CC6C.mjs";
|
|
15
15
|
import "./chunk-HAUDGBUS.mjs";
|
|
16
16
|
import "./chunk-BN3D45E2.mjs";
|
|
@@ -20365,7 +20365,7 @@ var init_bandit_chat_logo = __esm({
|
|
|
20365
20365
|
});
|
|
20366
20366
|
|
|
20367
20367
|
// src/chat/source-chips.tsx
|
|
20368
|
-
var import_react43, import_material35, import_jsx_runtime35, parseWebSources, stripSourcesForDisplay, domainOf, SourceChip, SourceChips, source_chips_default;
|
|
20368
|
+
var import_react43, import_material35, import_jsx_runtime35, parseWebSources, stripSourcesForDisplay, linkifyCitations, domainOf, SourceChip, SourceChips, source_chips_default;
|
|
20369
20369
|
var init_source_chips = __esm({
|
|
20370
20370
|
"src/chat/source-chips.tsx"() {
|
|
20371
20371
|
"use strict";
|
|
@@ -20400,6 +20400,14 @@ var init_source_chips = __esm({
|
|
|
20400
20400
|
);
|
|
20401
20401
|
return c.replace(/\s+$/u, "");
|
|
20402
20402
|
};
|
|
20403
|
+
linkifyCitations = (content, sources) => {
|
|
20404
|
+
if (!content || sources.length === 0) return content;
|
|
20405
|
+
const link = (text) => text.replace(/\[(\d{1,2})\]/g, (full, num) => {
|
|
20406
|
+
const src = sources[parseInt(num, 10) - 1];
|
|
20407
|
+
return src ? `[\\[${num}\\]](${src.url})` : full;
|
|
20408
|
+
});
|
|
20409
|
+
return content.split(/(```[\s\S]*?```)/g).map((seg, i) => i % 2 === 0 ? link(seg) : seg).join("");
|
|
20410
|
+
};
|
|
20403
20411
|
domainOf = (url) => {
|
|
20404
20412
|
try {
|
|
20405
20413
|
return new URL(url).hostname.replace(/^www\./, "");
|
|
@@ -20608,7 +20616,7 @@ var init_chat_messages = __esm({
|
|
|
20608
20616
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
20609
20617
|
StreamingMarkdown_default,
|
|
20610
20618
|
{
|
|
20611
|
-
content: stripSourcesForDisplay(content),
|
|
20619
|
+
content: linkifyCitations(stripSourcesForDisplay(content), parseWebSources(content)),
|
|
20612
20620
|
isStreaming: isStreaming && isLast,
|
|
20613
20621
|
sources: sourceSummaries
|
|
20614
20622
|
}
|
|
@@ -23763,7 +23771,7 @@ TOOL USAGE PROTOCOL (conservative approach)
|
|
|
23763
23771
|
* web_search() - when asked about recent/current events, breaking news, live information (weather, prices, sports scores), or when you need to look up documentation, libraries, APIs, error messages, or verify a specific fact
|
|
23764
23772
|
* web_fetch() - to read the FULL contents of a specific URL you already have. Reach for this when the user wants to "tell me more", "go deeper", "read/open that article", or asks for details about a specific source, link, or article from an EARLIER answer: take that item's URL from the previous Sources list in this conversation and fetch it, then answer from the page's actual content (not just the prior summary)
|
|
23765
23773
|
* image_generation() - ONLY when explicitly asked to create or generate an image
|
|
23766
|
-
* create_file({"content": "...", "filename": "report.docx", "format": "docx"}) - when the user asks for a downloadable FILE (a document, spreadsheet, slides, markdown, code, etc.) or to "export"/"download"/"save" something. Formats: md, txt, csv, json, html, xml, yaml, docx, pptx. For docx/pptx write well-structured Markdown (use "## " headings to start each slide for pptx). It returns a temporary download link \u2014 ALWAYS tell the user the file expires (~1 hour). If it is unclear whether they want it shown inline vs. as a downloadable file, use ask_user first.
|
|
23774
|
+
* create_file({"content": "...", "filename": "report.docx", "format": "docx"}) - when the user asks for a downloadable FILE (a document, spreadsheet, slides, markdown, code, etc.) or to "export"/"download"/"save" something. Formats: md, txt, csv, json, html, xml, yaml, docx, pptx. PDF is NOT a supported format \u2014 if the user asks for a PDF, create a docx instead. For docx/pptx write well-structured Markdown (use "## " headings to start each slide for pptx). It returns a temporary download link \u2014 ALWAYS tell the user the file expires (~1 hour). If it is unclear whether they want it shown inline vs. as a downloadable file, use ask_user first.
|
|
23767
23775
|
* ask_user({"questions": [{"question": "...", "header": "Format", "options": [{"label": "Inline (Recommended)"}, {"label": "Download a file"}]}]}) - when you are genuinely BLOCKED on a decision that is the USER's to make and cannot resolve from the request, context, or sensible defaults (e.g. show content inline vs. let them download it, which format/option they want). Renders clickable options the user answers in one step \u2014 better than asking in prose and ending your turn. Give 1-4 questions, each with 2-4 options; if one is clearly best, list it first and append " (Recommended)". The user may also type their own answer; act on it directly.
|
|
23768
23776
|
- For general questions about concepts, definitions, explanations, or how-to topics, use your built-in knowledge WITHOUT calling tools.
|
|
23769
23777
|
- Examples of what NOT to use tools for: "who are you?", "what is React?", "explain machine learning", "how does X work?", general programming questions.
|
|
@@ -23949,16 +23957,50 @@ ${fn}(${argStr})
|
|
|
23949
23957
|
\`\`\``;
|
|
23950
23958
|
}
|
|
23951
23959
|
}
|
|
23952
|
-
|
|
23953
|
-
const
|
|
23954
|
-
const
|
|
23955
|
-
|
|
23956
|
-
|
|
23957
|
-
|
|
23958
|
-
|
|
23960
|
+
const extractToolCalls = (message) => {
|
|
23961
|
+
const KNOWN = ["web_search", "web_fetch", "image_generation", "create_file", "ask_user", "ask-user"];
|
|
23962
|
+
const out = [];
|
|
23963
|
+
const nameRe = new RegExp(`\\b(${KNOWN.join("|")})\\s*\\(`, "g");
|
|
23964
|
+
let m;
|
|
23965
|
+
while ((m = nameRe.exec(message)) !== null) {
|
|
23966
|
+
const functionName = m[1];
|
|
23967
|
+
const openIdx = m.index + m[0].length - 1;
|
|
23968
|
+
let depth = 0;
|
|
23969
|
+
let i = openIdx;
|
|
23970
|
+
let inStr = false;
|
|
23971
|
+
let esc = false;
|
|
23972
|
+
for (; i < message.length; i++) {
|
|
23973
|
+
const ch = message[i];
|
|
23974
|
+
if (inStr) {
|
|
23975
|
+
if (esc) esc = false;
|
|
23976
|
+
else if (ch === "\\") esc = true;
|
|
23977
|
+
else if (ch === '"') inStr = false;
|
|
23978
|
+
} else if (ch === '"') inStr = true;
|
|
23979
|
+
else if (ch === "(") depth++;
|
|
23980
|
+
else if (ch === ")") {
|
|
23981
|
+
depth--;
|
|
23982
|
+
if (depth === 0) {
|
|
23983
|
+
i++;
|
|
23984
|
+
break;
|
|
23985
|
+
}
|
|
23986
|
+
}
|
|
23987
|
+
}
|
|
23988
|
+
if (depth !== 0) continue;
|
|
23989
|
+
const params = message.slice(openIdx + 1, i - 1).trim();
|
|
23990
|
+
let start = m.index;
|
|
23991
|
+
let end = i;
|
|
23992
|
+
const fenceOpen = message.slice(0, m.index).match(/```[a-zA-Z0-9_-]*[ \t]*\n[ \t]*$/);
|
|
23993
|
+
if (fenceOpen) {
|
|
23994
|
+
start = m.index - fenceOpen[0].length;
|
|
23995
|
+
const fenceClose = message.slice(i).match(/^[ \t]*\n```/);
|
|
23996
|
+
if (fenceClose) end = i + fenceClose[0].length;
|
|
23997
|
+
}
|
|
23998
|
+
out.push({ raw: message.slice(start, end), functionName, params });
|
|
23999
|
+
nameRe.lastIndex = i;
|
|
23959
24000
|
}
|
|
23960
|
-
|
|
23961
|
-
|
|
24001
|
+
return out;
|
|
24002
|
+
};
|
|
24003
|
+
const toolCallMatches = extractToolCalls(fullMessage);
|
|
23962
24004
|
let enhancedMessage = fullMessage;
|
|
23963
24005
|
const summarizableResults = [];
|
|
23964
24006
|
const inlineImageBlocks = [];
|
|
@@ -23966,13 +24008,10 @@ ${fm[1].trim()}
|
|
|
23966
24008
|
if (toolCallMatches && toolCallMatches.length > 0 && mcpToolsAvailable) {
|
|
23967
24009
|
debugLogger.info("Detected tool calls in AI response", {
|
|
23968
24010
|
toolCallCount: toolCallMatches.length,
|
|
23969
|
-
toolCalls: toolCallMatches
|
|
24011
|
+
toolCalls: toolCallMatches.map((t) => t.functionName)
|
|
23970
24012
|
});
|
|
23971
|
-
for (const
|
|
23972
|
-
const
|
|
23973
|
-
const functionCallMatch = toolCallCode.match(/^(\w+)\(\s*(.*?)\s*\)$/);
|
|
23974
|
-
if (!functionCallMatch) continue;
|
|
23975
|
-
const [, functionName, params] = functionCallMatch;
|
|
24013
|
+
for (const call of toolCallMatches) {
|
|
24014
|
+
const { raw: match, functionName, params } = call;
|
|
23976
24015
|
try {
|
|
23977
24016
|
let parsedParams = {};
|
|
23978
24017
|
const raw = params.trim();
|
|
@@ -24136,6 +24175,29 @@ _This link is temporary and expires in about ${mins} minutes._`;
|
|
|
24136
24175
|
try {
|
|
24137
24176
|
const toolResultsText = summarizableResults.map((r) => `## ${r.name}
|
|
24138
24177
|
${r.output}`).join("\n\n");
|
|
24178
|
+
const dedupeSources = (arr) => {
|
|
24179
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24180
|
+
return arr.filter((s) => seen.has(s.url) ? false : (seen.add(s.url), true));
|
|
24181
|
+
};
|
|
24182
|
+
const citeDomain = (u) => {
|
|
24183
|
+
try {
|
|
24184
|
+
return new URL(u).hostname.replace(/^www\./, "");
|
|
24185
|
+
} catch {
|
|
24186
|
+
return u;
|
|
24187
|
+
}
|
|
24188
|
+
};
|
|
24189
|
+
const buildCitationGuide = () => {
|
|
24190
|
+
const cite = dedupeSources(collectedSources).slice(0, 6);
|
|
24191
|
+
if (!cite.length)
|
|
24192
|
+
return `
|
|
24193
|
+
|
|
24194
|
+
Do NOT add citations, footnotes, superscript reference numbers, or a Sources list \u2014 sources are attached automatically.`;
|
|
24195
|
+
const list = cite.map((s, i) => `[${i + 1}] ${s.title || citeDomain(s.url)}`).join("\n");
|
|
24196
|
+
return `
|
|
24197
|
+
|
|
24198
|
+
When a statement is supported by one of the sources below, add an inline citation right after it using that source's number in square brackets \u2014 e.g. [1] or [2]. Use ONLY these numbers, never invent one, never use superscripts, and do NOT write your own Sources/References list (the numbered list is attached automatically below your answer):
|
|
24199
|
+
${list}`;
|
|
24200
|
+
};
|
|
24139
24201
|
const MAX_CHAIN_ROUNDS = 4;
|
|
24140
24202
|
const enabledToolsForChain = getEnabledMCPToolsForAI();
|
|
24141
24203
|
const convo = [
|
|
@@ -24151,7 +24213,7 @@ ${r.output}`).join("\n\n");
|
|
|
24151
24213
|
${toolResultsText}
|
|
24152
24214
|
===END TOOL RESULTS===
|
|
24153
24215
|
|
|
24154
|
-
Use them to fully complete my original request. If you still need to take an action I asked for (for example, actually create a file I want to download), call the appropriate tool now with a \`\`\`tool_code\`\`\` block. Otherwise give your final answer
|
|
24216
|
+
Use them to fully complete my original request. If you still need to take an action I asked for (for example, actually create a file I want to download), call the appropriate tool now with a \`\`\`tool_code\`\`\` block. Otherwise give your final answer.${buildCitationGuide()}`
|
|
24155
24217
|
}
|
|
24156
24218
|
];
|
|
24157
24219
|
const streamTurn = (req) => new Promise((resolve) => {
|
|
@@ -24297,7 +24359,7 @@ That step failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
|
24297
24359
|
${roundOut.join("\n\n")}
|
|
24298
24360
|
===END TOOL RESULTS===
|
|
24299
24361
|
|
|
24300
|
-
Now give your final answer to my original request, or call another tool if you still genuinely need to
|
|
24362
|
+
Now give your final answer to my original request, or call another tool if you still genuinely need to.${buildCitationGuide()}`
|
|
24301
24363
|
});
|
|
24302
24364
|
}
|
|
24303
24365
|
setIsThinking?.(false);
|
|
@@ -24310,7 +24372,7 @@ Now give your final answer to my original request, or call another tool if you s
|
|
|
24310
24372
|
const sourcesMd = collectedSources.length ? `
|
|
24311
24373
|
|
|
24312
24374
|
**Sources**
|
|
24313
|
-
${collectedSources.slice(0, 6).map((s) => {
|
|
24375
|
+
${dedupeSources(collectedSources).slice(0, 6).map((s) => {
|
|
24314
24376
|
let domain = s.url;
|
|
24315
24377
|
try {
|
|
24316
24378
|
domain = new URL(s.url).hostname.replace(/^www\./, "");
|