@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.js
CHANGED
|
@@ -15388,7 +15388,7 @@ ${sourcesMarkdownList.join("\n")}`;
|
|
|
15388
15388
|
});
|
|
15389
15389
|
|
|
15390
15390
|
// src/chat/source-chips.tsx
|
|
15391
|
-
var import_react18, import_material11, import_jsx_runtime14, parseWebSources, stripSourcesForDisplay, domainOf, SourceChip, SourceChips, source_chips_default;
|
|
15391
|
+
var import_react18, import_material11, import_jsx_runtime14, parseWebSources, stripSourcesForDisplay, linkifyCitations, domainOf, SourceChip, SourceChips, source_chips_default;
|
|
15392
15392
|
var init_source_chips = __esm({
|
|
15393
15393
|
"src/chat/source-chips.tsx"() {
|
|
15394
15394
|
"use strict";
|
|
@@ -15423,6 +15423,14 @@ var init_source_chips = __esm({
|
|
|
15423
15423
|
);
|
|
15424
15424
|
return c.replace(/\s+$/u, "");
|
|
15425
15425
|
};
|
|
15426
|
+
linkifyCitations = (content, sources) => {
|
|
15427
|
+
if (!content || sources.length === 0) return content;
|
|
15428
|
+
const link = (text) => text.replace(/\[(\d{1,2})\]/g, (full, num) => {
|
|
15429
|
+
const src = sources[parseInt(num, 10) - 1];
|
|
15430
|
+
return src ? `[\\[${num}\\]](${src.url})` : full;
|
|
15431
|
+
});
|
|
15432
|
+
return content.split(/(```[\s\S]*?```)/g).map((seg, i) => i % 2 === 0 ? link(seg) : seg).join("");
|
|
15433
|
+
};
|
|
15426
15434
|
domainOf = (url) => {
|
|
15427
15435
|
try {
|
|
15428
15436
|
return new URL(url).hostname.replace(/^www\./, "");
|
|
@@ -15631,7 +15639,7 @@ var init_chat_messages = __esm({
|
|
|
15631
15639
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
15632
15640
|
StreamingMarkdown_default,
|
|
15633
15641
|
{
|
|
15634
|
-
content: stripSourcesForDisplay(content),
|
|
15642
|
+
content: linkifyCitations(stripSourcesForDisplay(content), parseWebSources(content)),
|
|
15635
15643
|
isStreaming: isStreaming && isLast,
|
|
15636
15644
|
sources: sourceSummaries
|
|
15637
15645
|
}
|
|
@@ -21524,7 +21532,7 @@ TOOL USAGE PROTOCOL (conservative approach)
|
|
|
21524
21532
|
* 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
|
|
21525
21533
|
* 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)
|
|
21526
21534
|
* image_generation() - ONLY when explicitly asked to create or generate an image
|
|
21527
|
-
* 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.
|
|
21535
|
+
* 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.
|
|
21528
21536
|
* 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.
|
|
21529
21537
|
- For general questions about concepts, definitions, explanations, or how-to topics, use your built-in knowledge WITHOUT calling tools.
|
|
21530
21538
|
- Examples of what NOT to use tools for: "who are you?", "what is React?", "explain machine learning", "how does X work?", general programming questions.
|
|
@@ -21710,16 +21718,50 @@ ${fn}(${argStr})
|
|
|
21710
21718
|
\`\`\``;
|
|
21711
21719
|
}
|
|
21712
21720
|
}
|
|
21713
|
-
|
|
21714
|
-
const
|
|
21715
|
-
const
|
|
21716
|
-
|
|
21717
|
-
|
|
21718
|
-
|
|
21719
|
-
|
|
21721
|
+
const extractToolCalls = (message) => {
|
|
21722
|
+
const KNOWN = ["web_search", "web_fetch", "image_generation", "create_file", "ask_user", "ask-user"];
|
|
21723
|
+
const out = [];
|
|
21724
|
+
const nameRe = new RegExp(`\\b(${KNOWN.join("|")})\\s*\\(`, "g");
|
|
21725
|
+
let m;
|
|
21726
|
+
while ((m = nameRe.exec(message)) !== null) {
|
|
21727
|
+
const functionName = m[1];
|
|
21728
|
+
const openIdx = m.index + m[0].length - 1;
|
|
21729
|
+
let depth = 0;
|
|
21730
|
+
let i = openIdx;
|
|
21731
|
+
let inStr = false;
|
|
21732
|
+
let esc = false;
|
|
21733
|
+
for (; i < message.length; i++) {
|
|
21734
|
+
const ch = message[i];
|
|
21735
|
+
if (inStr) {
|
|
21736
|
+
if (esc) esc = false;
|
|
21737
|
+
else if (ch === "\\") esc = true;
|
|
21738
|
+
else if (ch === '"') inStr = false;
|
|
21739
|
+
} else if (ch === '"') inStr = true;
|
|
21740
|
+
else if (ch === "(") depth++;
|
|
21741
|
+
else if (ch === ")") {
|
|
21742
|
+
depth--;
|
|
21743
|
+
if (depth === 0) {
|
|
21744
|
+
i++;
|
|
21745
|
+
break;
|
|
21746
|
+
}
|
|
21747
|
+
}
|
|
21748
|
+
}
|
|
21749
|
+
if (depth !== 0) continue;
|
|
21750
|
+
const params = message.slice(openIdx + 1, i - 1).trim();
|
|
21751
|
+
let start = m.index;
|
|
21752
|
+
let end = i;
|
|
21753
|
+
const fenceOpen = message.slice(0, m.index).match(/```[a-zA-Z0-9_-]*[ \t]*\n[ \t]*$/);
|
|
21754
|
+
if (fenceOpen) {
|
|
21755
|
+
start = m.index - fenceOpen[0].length;
|
|
21756
|
+
const fenceClose = message.slice(i).match(/^[ \t]*\n```/);
|
|
21757
|
+
if (fenceClose) end = i + fenceClose[0].length;
|
|
21758
|
+
}
|
|
21759
|
+
out.push({ raw: message.slice(start, end), functionName, params });
|
|
21760
|
+
nameRe.lastIndex = i;
|
|
21720
21761
|
}
|
|
21721
|
-
|
|
21722
|
-
|
|
21762
|
+
return out;
|
|
21763
|
+
};
|
|
21764
|
+
const toolCallMatches = extractToolCalls(fullMessage);
|
|
21723
21765
|
let enhancedMessage = fullMessage;
|
|
21724
21766
|
const summarizableResults = [];
|
|
21725
21767
|
const inlineImageBlocks = [];
|
|
@@ -21727,13 +21769,10 @@ ${fm[1].trim()}
|
|
|
21727
21769
|
if (toolCallMatches && toolCallMatches.length > 0 && mcpToolsAvailable) {
|
|
21728
21770
|
debugLogger.info("Detected tool calls in AI response", {
|
|
21729
21771
|
toolCallCount: toolCallMatches.length,
|
|
21730
|
-
toolCalls: toolCallMatches
|
|
21772
|
+
toolCalls: toolCallMatches.map((t) => t.functionName)
|
|
21731
21773
|
});
|
|
21732
|
-
for (const
|
|
21733
|
-
const
|
|
21734
|
-
const functionCallMatch = toolCallCode.match(/^(\w+)\(\s*(.*?)\s*\)$/);
|
|
21735
|
-
if (!functionCallMatch) continue;
|
|
21736
|
-
const [, functionName, params] = functionCallMatch;
|
|
21774
|
+
for (const call of toolCallMatches) {
|
|
21775
|
+
const { raw: match, functionName, params } = call;
|
|
21737
21776
|
try {
|
|
21738
21777
|
let parsedParams = {};
|
|
21739
21778
|
const raw = params.trim();
|
|
@@ -21897,6 +21936,29 @@ _This link is temporary and expires in about ${mins} minutes._`;
|
|
|
21897
21936
|
try {
|
|
21898
21937
|
const toolResultsText = summarizableResults.map((r) => `## ${r.name}
|
|
21899
21938
|
${r.output}`).join("\n\n");
|
|
21939
|
+
const dedupeSources = (arr) => {
|
|
21940
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21941
|
+
return arr.filter((s) => seen.has(s.url) ? false : (seen.add(s.url), true));
|
|
21942
|
+
};
|
|
21943
|
+
const citeDomain = (u) => {
|
|
21944
|
+
try {
|
|
21945
|
+
return new URL(u).hostname.replace(/^www\./, "");
|
|
21946
|
+
} catch {
|
|
21947
|
+
return u;
|
|
21948
|
+
}
|
|
21949
|
+
};
|
|
21950
|
+
const buildCitationGuide = () => {
|
|
21951
|
+
const cite = dedupeSources(collectedSources).slice(0, 6);
|
|
21952
|
+
if (!cite.length)
|
|
21953
|
+
return `
|
|
21954
|
+
|
|
21955
|
+
Do NOT add citations, footnotes, superscript reference numbers, or a Sources list \u2014 sources are attached automatically.`;
|
|
21956
|
+
const list = cite.map((s, i) => `[${i + 1}] ${s.title || citeDomain(s.url)}`).join("\n");
|
|
21957
|
+
return `
|
|
21958
|
+
|
|
21959
|
+
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):
|
|
21960
|
+
${list}`;
|
|
21961
|
+
};
|
|
21900
21962
|
const MAX_CHAIN_ROUNDS = 4;
|
|
21901
21963
|
const enabledToolsForChain = getEnabledMCPToolsForAI();
|
|
21902
21964
|
const convo = [
|
|
@@ -21912,7 +21974,7 @@ ${r.output}`).join("\n\n");
|
|
|
21912
21974
|
${toolResultsText}
|
|
21913
21975
|
===END TOOL RESULTS===
|
|
21914
21976
|
|
|
21915
|
-
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
|
|
21977
|
+
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()}`
|
|
21916
21978
|
}
|
|
21917
21979
|
];
|
|
21918
21980
|
const streamTurn = (req) => new Promise((resolve) => {
|
|
@@ -22058,7 +22120,7 @@ That step failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
|
22058
22120
|
${roundOut.join("\n\n")}
|
|
22059
22121
|
===END TOOL RESULTS===
|
|
22060
22122
|
|
|
22061
|
-
Now give your final answer to my original request, or call another tool if you still genuinely need to
|
|
22123
|
+
Now give your final answer to my original request, or call another tool if you still genuinely need to.${buildCitationGuide()}`
|
|
22062
22124
|
});
|
|
22063
22125
|
}
|
|
22064
22126
|
setIsThinking?.(false);
|
|
@@ -22071,7 +22133,7 @@ Now give your final answer to my original request, or call another tool if you s
|
|
|
22071
22133
|
const sourcesMd = collectedSources.length ? `
|
|
22072
22134
|
|
|
22073
22135
|
**Sources**
|
|
22074
|
-
${collectedSources.slice(0, 6).map((s) => {
|
|
22136
|
+
${dedupeSources(collectedSources).slice(0, 6).map((s) => {
|
|
22075
22137
|
let domain = s.url;
|
|
22076
22138
|
try {
|
|
22077
22139
|
domain = new URL(s.url).hostname.replace(/^www\./, "");
|