@burtson-labs/bandit-engine 2.0.55 → 2.0.58
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 +76 -76
- package/dist/{chat-IDE6Z4Q4.mjs → chat-MXC6O7M5.mjs} +3 -3
- package/dist/chat-provider.js +20 -67
- package/dist/chat-provider.js.map +1 -1
- package/dist/chat-provider.mjs +2 -2
- package/dist/{chunk-TLY6A6XL.mjs → chunk-N7GCS2BH.mjs} +156 -113
- package/dist/chunk-N7GCS2BH.mjs.map +1 -0
- package/dist/{chunk-AVV7HDGR.mjs → chunk-POTQI33D.mjs} +2 -2
- package/dist/{chunk-EHNWQ4T3.mjs → chunk-QPBG6JQE.mjs} +21 -68
- package/dist/chunk-QPBG6JQE.mjs.map +1 -0
- package/dist/{chunk-NP2OHTTX.mjs → chunk-VU5N57QZ.mjs} +3 -3
- package/dist/index.js +176 -180
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/management/management.js +176 -180
- package/dist/management/management.js.map +1 -1
- package/dist/management/management.mjs +2 -2
- package/package.json +2 -2
- package/dist/chunk-EHNWQ4T3.mjs.map +0 -1
- package/dist/chunk-TLY6A6XL.mjs.map +0 -1
- /package/dist/{chat-IDE6Z4Q4.mjs.map → chat-MXC6O7M5.mjs.map} +0 -0
- /package/dist/{chunk-AVV7HDGR.mjs.map → chunk-POTQI33D.mjs.map} +0 -0
- /package/dist/{chunk-NP2OHTTX.mjs.map → chunk-VU5N57QZ.mjs.map} +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
chat_default
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-N7GCS2BH.mjs";
|
|
4
4
|
import {
|
|
5
5
|
chat_provider_default
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-POTQI33D.mjs";
|
|
7
7
|
import "./chunk-ONQMRE2G.mjs";
|
|
8
8
|
import {
|
|
9
9
|
management_default,
|
|
10
10
|
useGatewayHealth,
|
|
11
11
|
useGatewayMemory,
|
|
12
12
|
useGatewayModels
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-VU5N57QZ.mjs";
|
|
14
14
|
import "./chunk-KM7FUWCM.mjs";
|
|
15
15
|
import "./chunk-UFSEYVRS.mjs";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-QPBG6JQE.mjs";
|
|
17
17
|
import {
|
|
18
18
|
defineCustomElement
|
|
19
19
|
} from "./chunk-IXIM7BNO.mjs";
|
|
@@ -19760,7 +19760,7 @@ ${listMarkdown}`;
|
|
|
19760
19760
|
});
|
|
19761
19761
|
|
|
19762
19762
|
// src/store/mcpToolsStore.ts
|
|
19763
|
-
var import_zustand13, healthCheckTool,
|
|
19763
|
+
var import_zustand13, healthCheckTool, webSearchTool, webFetchTool, imageGenerationTool, defaultTools, useMCPToolsStore;
|
|
19764
19764
|
var init_mcpToolsStore = __esm({
|
|
19765
19765
|
"src/store/mcpToolsStore.ts"() {
|
|
19766
19766
|
"use strict";
|
|
@@ -19786,94 +19786,47 @@ var init_mcpToolsStore = __esm({
|
|
|
19786
19786
|
method: "GET",
|
|
19787
19787
|
isBuiltIn: true
|
|
19788
19788
|
};
|
|
19789
|
-
|
|
19790
|
-
id: "
|
|
19791
|
-
name: "
|
|
19792
|
-
description: "
|
|
19789
|
+
webSearchTool = {
|
|
19790
|
+
id: "web-search",
|
|
19791
|
+
name: "web_search",
|
|
19792
|
+
description: "Search the web for current information, documentation, and facts",
|
|
19793
19793
|
enabled: true,
|
|
19794
19794
|
type: "function",
|
|
19795
19795
|
function: {
|
|
19796
|
-
name: "
|
|
19797
|
-
description: "
|
|
19796
|
+
name: "web_search",
|
|
19797
|
+
description: "Search the web and return ranked results with snippets (and an optional summarized answer). Use for current events, documentation, libraries, error messages, and factual lookups.",
|
|
19798
19798
|
parameters: {
|
|
19799
19799
|
type: "object",
|
|
19800
19800
|
properties: {
|
|
19801
|
-
|
|
19802
|
-
count: { type: "number", description: "Number of
|
|
19803
|
-
|
|
19804
|
-
},
|
|
19805
|
-
required: []
|
|
19806
|
-
}
|
|
19807
|
-
},
|
|
19808
|
-
endpoint: "/mcp/news",
|
|
19809
|
-
method: "GET",
|
|
19810
|
-
isBuiltIn: true
|
|
19811
|
-
};
|
|
19812
|
-
weatherTool = {
|
|
19813
|
-
id: "weather",
|
|
19814
|
-
name: "weather",
|
|
19815
|
-
description: "Get current weather conditions and forecasts by location",
|
|
19816
|
-
enabled: true,
|
|
19817
|
-
type: "function",
|
|
19818
|
-
function: {
|
|
19819
|
-
name: "weather",
|
|
19820
|
-
description: "Get weather information by location",
|
|
19821
|
-
parameters: {
|
|
19822
|
-
type: "object",
|
|
19823
|
-
properties: {
|
|
19824
|
-
zip: { type: "string", description: "US zip code" },
|
|
19825
|
-
latitude: { type: "number", description: "Latitude" },
|
|
19826
|
-
longitude: { type: "number", description: "Longitude" }
|
|
19827
|
-
},
|
|
19828
|
-
required: []
|
|
19829
|
-
}
|
|
19830
|
-
},
|
|
19831
|
-
endpoint: "/mcp/weather",
|
|
19832
|
-
method: "GET",
|
|
19833
|
-
isBuiltIn: true
|
|
19834
|
-
};
|
|
19835
|
-
docsTool = {
|
|
19836
|
-
id: "docs",
|
|
19837
|
-
name: "docs",
|
|
19838
|
-
description: "Search framework documentation",
|
|
19839
|
-
enabled: true,
|
|
19840
|
-
type: "function",
|
|
19841
|
-
function: {
|
|
19842
|
-
name: "docs",
|
|
19843
|
-
description: "Search framework documentation",
|
|
19844
|
-
parameters: {
|
|
19845
|
-
type: "object",
|
|
19846
|
-
properties: {
|
|
19847
|
-
query: { type: "string", description: "Search query" },
|
|
19848
|
-
framework: { type: "string", description: "Specific framework to search" },
|
|
19849
|
-
count: { type: "number", description: "Number of results (1-50)" }
|
|
19801
|
+
query: { type: "string", description: "The search query \u2014 natural language or keywords" },
|
|
19802
|
+
count: { type: "number", description: "Number of results to return (1-10, default 5)" },
|
|
19803
|
+
include_answer: { type: "boolean", description: "Include a short summarized answer when available" }
|
|
19850
19804
|
},
|
|
19851
19805
|
required: ["query"]
|
|
19852
19806
|
}
|
|
19853
19807
|
},
|
|
19854
|
-
endpoint: "/mcp/
|
|
19808
|
+
endpoint: "/mcp/web-search",
|
|
19855
19809
|
method: "GET",
|
|
19856
19810
|
isBuiltIn: true
|
|
19857
19811
|
};
|
|
19858
|
-
|
|
19859
|
-
id: "
|
|
19860
|
-
name: "
|
|
19861
|
-
description: "
|
|
19812
|
+
webFetchTool = {
|
|
19813
|
+
id: "web-fetch",
|
|
19814
|
+
name: "web_fetch",
|
|
19815
|
+
description: "Fetch the text content of a specific URL",
|
|
19862
19816
|
enabled: true,
|
|
19863
19817
|
type: "function",
|
|
19864
19818
|
function: {
|
|
19865
|
-
name: "
|
|
19866
|
-
description: "
|
|
19819
|
+
name: "web_fetch",
|
|
19820
|
+
description: "Fetch a single public URL and return its trimmed text content. Use when you already have a specific link you need to read.",
|
|
19867
19821
|
parameters: {
|
|
19868
19822
|
type: "object",
|
|
19869
19823
|
properties: {
|
|
19870
|
-
|
|
19871
|
-
date: { type: "string", description: "Date in YYYY-MM-DD format" }
|
|
19824
|
+
url: { type: "string", description: "Absolute http(s) URL to fetch" }
|
|
19872
19825
|
},
|
|
19873
|
-
required: []
|
|
19826
|
+
required: ["url"]
|
|
19874
19827
|
}
|
|
19875
19828
|
},
|
|
19876
|
-
endpoint: "/mcp/
|
|
19829
|
+
endpoint: "/mcp/web-fetch",
|
|
19877
19830
|
method: "GET",
|
|
19878
19831
|
isBuiltIn: true
|
|
19879
19832
|
};
|
|
@@ -19901,7 +19854,7 @@ var init_mcpToolsStore = __esm({
|
|
|
19901
19854
|
method: "POST",
|
|
19902
19855
|
isBuiltIn: true
|
|
19903
19856
|
};
|
|
19904
|
-
defaultTools = [healthCheckTool,
|
|
19857
|
+
defaultTools = [healthCheckTool, webSearchTool, webFetchTool, imageGenerationTool];
|
|
19905
19858
|
useMCPToolsStore = (0, import_zustand13.create)((set, get) => ({
|
|
19906
19859
|
tools: defaultTools,
|
|
19907
19860
|
isLoaded: false,
|
|
@@ -20460,7 +20413,7 @@ var init_stt_client = __esm({
|
|
|
20460
20413
|
normalizedBlob = new Blob([blob], { type: "audio/webm" });
|
|
20461
20414
|
}
|
|
20462
20415
|
const body = new FormData();
|
|
20463
|
-
const filename = normalizedBlob.type.includes("ogg") ? "audio.ogg" : normalizedBlob.type.includes("wav") ? "audio.wav" : normalizedBlob.type.includes("mp3") ? "audio.mp3" : "audio.webm";
|
|
20416
|
+
const filename = normalizedBlob.type.includes("ogg") ? "audio.ogg" : normalizedBlob.type.includes("wav") ? "audio.wav" : normalizedBlob.type.includes("mp4") || normalizedBlob.type.includes("m4a") || normalizedBlob.type.includes("aac") ? "audio.mp4" : normalizedBlob.type.includes("mp3") ? "audio.mp3" : "audio.webm";
|
|
20464
20417
|
body.append("audio", normalizedBlob, filename);
|
|
20465
20418
|
body.append("file", normalizedBlob, filename);
|
|
20466
20419
|
body.append("audioFile", normalizedBlob, filename);
|
|
@@ -22797,6 +22750,7 @@ USE THE ABOVE CONTENT to answer the user's question. Reference specific informat
|
|
|
22797
22750
|
- Only use tools for live data (news, weather, sports scores) when specifically requested
|
|
22798
22751
|
- Trust and utilize the provided context without hesitation`;
|
|
22799
22752
|
enhancedSystemPrompt += ragGuidance;
|
|
22753
|
+
const systemPromptForSummary = enhancedSystemPrompt;
|
|
22800
22754
|
const mcpToolsAvailable = isMCPAvailable();
|
|
22801
22755
|
if (mcpToolsAvailable) {
|
|
22802
22756
|
const enabledTools = getEnabledMCPToolsForAI();
|
|
@@ -22812,10 +22766,10 @@ USE THE ABOVE CONTENT to answer the user's question. Reference specific informat
|
|
|
22812
22766
|
TOOL USAGE PROTOCOL (conservative approach)
|
|
22813
22767
|
- PRIORITIZE your built-in knowledge and the provided context ABOVE to answer questions first.
|
|
22814
22768
|
- Use your training data and general knowledge confidently for common topics, concepts, and questions.
|
|
22815
|
-
- Only call tools for SPECIFIC, CURRENT information that requires real-time data:
|
|
22816
|
-
*
|
|
22817
|
-
*
|
|
22818
|
-
*
|
|
22769
|
+
- Only call tools for SPECIFIC, CURRENT information that requires real-time data or a source you don't already have:
|
|
22770
|
+
* 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
|
|
22771
|
+
* web_fetch() - ONLY when you already have a specific URL whose contents you need to read
|
|
22772
|
+
* image_generation() - ONLY when explicitly asked to create or generate an image
|
|
22819
22773
|
- For general questions about concepts, definitions, explanations, or how-to topics, use your built-in knowledge WITHOUT calling tools.
|
|
22820
22774
|
- Examples of what NOT to use tools for: "who are you?", "what is React?", "explain machine learning", "how does X work?", general programming questions.
|
|
22821
22775
|
- When a tool is truly needed, call exactly ONE tool that best matches the request.
|
|
@@ -22827,11 +22781,11 @@ functionName({"param": "value"})
|
|
|
22827
22781
|
Examples of appropriate tool usage:
|
|
22828
22782
|
|
|
22829
22783
|
\`\`\`tool_code
|
|
22830
|
-
|
|
22784
|
+
web_search({"query": "latest AI developments 2026", "count": 5})
|
|
22831
22785
|
\`\`\`
|
|
22832
22786
|
|
|
22833
22787
|
\`\`\`tool_code
|
|
22834
|
-
|
|
22788
|
+
web_fetch({"url": "https://example.com/changelog"})
|
|
22835
22789
|
\`\`\`
|
|
22836
22790
|
`;
|
|
22837
22791
|
enhancedSystemPrompt += `
|
|
@@ -22874,6 +22828,7 @@ ${protocol}`;
|
|
|
22874
22828
|
if (openIdx !== -1) result = result.slice(0, openIdx);
|
|
22875
22829
|
return result.trimStart();
|
|
22876
22830
|
};
|
|
22831
|
+
const stripToolBlocks = (text) => text.replace(/```(?:tool_code|TOOL_CODE)\s*\n[\s\S]*?\n```/gi, "").trim();
|
|
22877
22832
|
const flushNow = () => {
|
|
22878
22833
|
clearFlushTimer();
|
|
22879
22834
|
if (!sawToolBlock) {
|
|
@@ -22947,6 +22902,8 @@ ${protocol}`;
|
|
|
22947
22902
|
}
|
|
22948
22903
|
const toolCallMatches = fullMessage.match(/```(?:tool_code|TOOL_CODE)\s*\n([^`]+)\n```/gi);
|
|
22949
22904
|
let enhancedMessage = fullMessage;
|
|
22905
|
+
const summarizableResults = [];
|
|
22906
|
+
const inlineImageBlocks = [];
|
|
22950
22907
|
if (toolCallMatches && toolCallMatches.length > 0 && mcpToolsAvailable) {
|
|
22951
22908
|
debugLogger.info("Detected tool calls in AI response", {
|
|
22952
22909
|
toolCallCount: toolCallMatches.length,
|
|
@@ -22987,47 +22944,43 @@ ${protocol}`;
|
|
|
22987
22944
|
});
|
|
22988
22945
|
let resultText = "";
|
|
22989
22946
|
if (result.success) {
|
|
22990
|
-
if (functionName === "
|
|
22991
|
-
const
|
|
22992
|
-
const
|
|
22993
|
-
const
|
|
22994
|
-
|
|
22995
|
-
|
|
22996
|
-
|
|
22997
|
-
|
|
22998
|
-
|
|
22999
|
-
|
|
23000
|
-
|
|
23001
|
-
|
|
23002
|
-
|
|
23003
|
-
|
|
23004
|
-
|
|
23005
|
-
|
|
23006
|
-
|
|
23007
|
-
|
|
23008
|
-
|
|
23009
|
-
|
|
23010
|
-
|
|
23011
|
-
|
|
23012
|
-
|
|
23013
|
-
const awayTokens = tokens(game.awayTeam);
|
|
23014
|
-
const hits = [...homeTokens, ...awayTokens].reduce(
|
|
23015
|
-
(acc, token) => acc + (q.includes(token) ? 1 : 0),
|
|
23016
|
-
0
|
|
22947
|
+
if (functionName === "web_search" || functionName === "web-search") {
|
|
22948
|
+
const search = result.data ?? {};
|
|
22949
|
+
const items = Array.isArray(search.results) ? search.results : [];
|
|
22950
|
+
const blocks = [];
|
|
22951
|
+
if (typeof search.answer === "string" && search.answer.trim().length > 0) {
|
|
22952
|
+
blocks.push(search.answer.trim());
|
|
22953
|
+
}
|
|
22954
|
+
if (items.length > 0) {
|
|
22955
|
+
blocks.push(
|
|
22956
|
+
items.slice(0, 6).map((item, index) => {
|
|
22957
|
+
const title = item.title?.trim() || "Untitled";
|
|
22958
|
+
const url = item.url?.trim();
|
|
22959
|
+
const snippet = item.content?.trim();
|
|
22960
|
+
let line = `${index + 1}. **${title}**`;
|
|
22961
|
+
if (url) line += `
|
|
22962
|
+
${url}`;
|
|
22963
|
+
if (snippet) {
|
|
22964
|
+
const truncated = snippet.length > 300 ? `${snippet.slice(0, 300)}\u2026` : snippet;
|
|
22965
|
+
line += `
|
|
22966
|
+
${truncated}`;
|
|
22967
|
+
}
|
|
22968
|
+
return line;
|
|
22969
|
+
}).join("\n\n")
|
|
23017
22970
|
);
|
|
23018
|
-
if (hits > bestScore) {
|
|
23019
|
-
bestScore = hits;
|
|
23020
|
-
best = game;
|
|
23021
|
-
}
|
|
23022
22971
|
}
|
|
23023
|
-
|
|
23024
|
-
|
|
23025
|
-
|
|
23026
|
-
|
|
23027
|
-
resultText =
|
|
23028
|
-
- ${topGames.map(scoreLine).join("\n- ")}`;
|
|
22972
|
+
resultText = blocks.length ? blocks.join("\n\n") : `No results found${search.query ? ` for "${search.query}"` : ""}.`;
|
|
22973
|
+
} else if (functionName === "web_fetch" || functionName === "web-fetch") {
|
|
22974
|
+
const fetched = result.data ?? {};
|
|
22975
|
+
if (fetched.blocked || fetched.error && !fetched.content) {
|
|
22976
|
+
resultText = fetched.error || "Unable to fetch that URL.";
|
|
23029
22977
|
} else {
|
|
23030
|
-
|
|
22978
|
+
const body = (fetched.content ?? "").trim();
|
|
22979
|
+
const preview = body.length > 2e3 ? `${body.slice(0, 2e3)}\u2026` : body;
|
|
22980
|
+
const source = fetched.url ? `**Source:** ${fetched.url}
|
|
22981
|
+
|
|
22982
|
+
` : "";
|
|
22983
|
+
resultText = preview ? `${source}${preview}` : `${source}No readable content found.`;
|
|
23031
22984
|
}
|
|
23032
22985
|
} else if (functionName === "image_generation" || functionName === "image-generation") {
|
|
23033
22986
|
const imageData = result.data ?? {};
|
|
@@ -23038,63 +22991,6 @@ ${protocol}`;
|
|
|
23038
22991
|
|
|
23039
22992
|
${revisedPrompt ? `Prompt refinement: \u201C${revisedPrompt}\u201D
|
|
23040
22993
|
` : ""}Note: the image link may expire in ~2 hours.` : "Image generated successfully.";
|
|
23041
|
-
} else if (functionName === "news" && Array.isArray(result.data)) {
|
|
23042
|
-
const items = result.data.slice(0, 3);
|
|
23043
|
-
resultText = items.length ? `## Top News Results
|
|
23044
|
-
|
|
23045
|
-
${items.map((item, index) => {
|
|
23046
|
-
const title = item.title ?? "Untitled";
|
|
23047
|
-
const source = item.source ?? "Unknown";
|
|
23048
|
-
const url = item.url ?? item.link;
|
|
23049
|
-
const description = item.description ?? item.summary;
|
|
23050
|
-
const publishedAt = item.publishedAt ?? item.published;
|
|
23051
|
-
let newsItem = `### ${index + 1}. ${title}
|
|
23052
|
-
`;
|
|
23053
|
-
if (typeof description === "string" && description.length > 0) {
|
|
23054
|
-
const truncated = description.length > 150 ? `${description.slice(0, 150)}...` : description;
|
|
23055
|
-
newsItem += `${truncated}
|
|
23056
|
-
|
|
23057
|
-
`;
|
|
23058
|
-
}
|
|
23059
|
-
newsItem += `**Source:** ${source}
|
|
23060
|
-
`;
|
|
23061
|
-
if (publishedAt) {
|
|
23062
|
-
const date = new Date(publishedAt);
|
|
23063
|
-
if (!Number.isNaN(date.getTime())) {
|
|
23064
|
-
newsItem += `**Published:** ${date.toLocaleDateString()} at ${date.toLocaleTimeString(
|
|
23065
|
-
[],
|
|
23066
|
-
{ hour: "2-digit", minute: "2-digit" }
|
|
23067
|
-
)}
|
|
23068
|
-
`;
|
|
23069
|
-
}
|
|
23070
|
-
}
|
|
23071
|
-
if (typeof url === "string" && url.length > 0) {
|
|
23072
|
-
newsItem += `
|
|
23073
|
-
**[\u{1F4F0} Read Full Article](${url})**
|
|
23074
|
-
`;
|
|
23075
|
-
}
|
|
23076
|
-
return newsItem;
|
|
23077
|
-
}).join("\n---\n\n")}` : "No news results found.";
|
|
23078
|
-
} else if (functionName === "docs" && Array.isArray(result.data)) {
|
|
23079
|
-
const items = result.data.slice(0, 3);
|
|
23080
|
-
resultText = items.length ? `Relevant docs:
|
|
23081
|
-
- ${items.map((item) => {
|
|
23082
|
-
const title = item.title ?? "Untitled doc";
|
|
23083
|
-
const url = item.url ?? item.link;
|
|
23084
|
-
return url ? `${title} \u2014 ${url}` : title;
|
|
23085
|
-
}).join("\n- ")}` : "No documentation results found.";
|
|
23086
|
-
} else if (functionName === "weather") {
|
|
23087
|
-
const weatherData = result.data ?? {};
|
|
23088
|
-
const informative = [weatherData.message, weatherData.details, weatherData.error].map((value) => typeof value === "string" ? value.trim() : void 0).filter((value) => Boolean(value) && value.toLowerCase() !== "n/a");
|
|
23089
|
-
if (informative.length > 0) {
|
|
23090
|
-
const locationLabel = typeof weatherData.location === "string" && weatherData.location.length > 0 ? ` for ${weatherData.location}` : "";
|
|
23091
|
-
resultText = `Weather service notice${locationLabel}: ${informative.join(" \u2014 ")}`;
|
|
23092
|
-
} else {
|
|
23093
|
-
const parts = [weatherData.location, weatherData.description, weatherData.temperature].map(
|
|
23094
|
-
(value) => typeof value === "number" || typeof value === "string" ? String(value).trim() : void 0
|
|
23095
|
-
).filter((value) => Boolean(value));
|
|
23096
|
-
resultText = parts.length ? parts.join(" \u2014 ") : "No weather data found.";
|
|
23097
|
-
}
|
|
23098
22994
|
} else if (typeof result.data === "string") {
|
|
23099
22995
|
resultText = result.data;
|
|
23100
22996
|
} else if (result.data) {
|
|
@@ -23105,16 +23001,16 @@ ${items.map((item, index) => {
|
|
|
23105
23001
|
} else {
|
|
23106
23002
|
const data = result.data ?? {};
|
|
23107
23003
|
const informative = [data.message, data.details, data.error, result.error].map((value) => typeof value === "string" ? value.trim() : void 0).filter((value) => Boolean(value) && value.toLowerCase() !== "n/a");
|
|
23108
|
-
|
|
23109
|
-
const locationLabel = typeof data.location === "string" && data.location.length > 0 ? ` for ${data.location}` : "";
|
|
23110
|
-
resultText = `Weather service issue${locationLabel}: ${informative.join(" \u2014 ")}`;
|
|
23111
|
-
} else if (informative.length) {
|
|
23112
|
-
resultText = informative.join(" \u2014 ");
|
|
23113
|
-
} else {
|
|
23114
|
-
resultText = `I couldn't complete that request: ${result.error || "Unknown error"}.`;
|
|
23115
|
-
}
|
|
23004
|
+
resultText = informative.length ? informative.join(" \u2014 ") : `I couldn't complete that request: ${result.error || "Unknown error"}.`;
|
|
23116
23005
|
}
|
|
23117
23006
|
enhancedMessage = enhancedMessage.replace(placeholderToken, resultText);
|
|
23007
|
+
if (result.success) {
|
|
23008
|
+
if (functionName === "image_generation" || functionName === "image-generation") {
|
|
23009
|
+
inlineImageBlocks.push(resultText);
|
|
23010
|
+
} else if (functionName !== "check_gateway_health") {
|
|
23011
|
+
summarizableResults.push({ name: functionName, output: resultText });
|
|
23012
|
+
}
|
|
23013
|
+
}
|
|
23118
23014
|
debugLogger.info("Tool execution completed", {
|
|
23119
23015
|
functionName,
|
|
23120
23016
|
success: result.success,
|
|
@@ -23137,6 +23033,65 @@ ${items.map((item, index) => {
|
|
|
23137
23033
|
}
|
|
23138
23034
|
}
|
|
23139
23035
|
}
|
|
23036
|
+
if (summarizableResults.length > 0) {
|
|
23037
|
+
try {
|
|
23038
|
+
const toolResultsText = summarizableResults.map((r) => `## ${r.name}
|
|
23039
|
+
${r.output}`).join("\n\n");
|
|
23040
|
+
const summaryMessages = [
|
|
23041
|
+
{ role: "system", content: systemPromptForSummary },
|
|
23042
|
+
...contextMessages,
|
|
23043
|
+
{ role: "user", content: question },
|
|
23044
|
+
{ role: "assistant", content: stripToolBlocks(fullMessage) || "Let me look that up." },
|
|
23045
|
+
{
|
|
23046
|
+
role: "user",
|
|
23047
|
+
content: `I ran the tool(s) you requested. Here are the raw results:
|
|
23048
|
+
|
|
23049
|
+
${toolResultsText}
|
|
23050
|
+
|
|
23051
|
+
Using these results together with your own knowledge, answer my original question concisely and in a natural, well-formatted way. Cite source URLs inline when you rely on them. Do NOT output tool_code or call any tools again.`
|
|
23052
|
+
}
|
|
23053
|
+
];
|
|
23054
|
+
const summaryRequest = {
|
|
23055
|
+
model: modelName,
|
|
23056
|
+
messages: summaryMessages,
|
|
23057
|
+
stream: true,
|
|
23058
|
+
options: { num_predict: tokenLimit + 250 }
|
|
23059
|
+
};
|
|
23060
|
+
clearFlushTimer();
|
|
23061
|
+
setStreamBuffer("");
|
|
23062
|
+
const summaryText = await new Promise((resolve) => {
|
|
23063
|
+
let acc = "";
|
|
23064
|
+
const summarySub = provider.chat(summaryRequest).subscribe({
|
|
23065
|
+
next: (data) => {
|
|
23066
|
+
if (data?.message?.content) {
|
|
23067
|
+
acc += data.message.content;
|
|
23068
|
+
const visible = stripThinking(acc);
|
|
23069
|
+
latestDisplayMessage = visible;
|
|
23070
|
+
lastPartialRef.current.text = visible;
|
|
23071
|
+
setStreamBuffer(visible);
|
|
23072
|
+
}
|
|
23073
|
+
},
|
|
23074
|
+
error: (summaryErr) => {
|
|
23075
|
+
debugLogger.error("Summarization pass failed", {
|
|
23076
|
+
error: summaryErr instanceof Error ? summaryErr.message : String(summaryErr)
|
|
23077
|
+
});
|
|
23078
|
+
resolve("");
|
|
23079
|
+
},
|
|
23080
|
+
complete: () => resolve(stripThinking(acc).trim())
|
|
23081
|
+
});
|
|
23082
|
+
currentSubRef.current = summarySub;
|
|
23083
|
+
});
|
|
23084
|
+
if (summaryText.trim()) {
|
|
23085
|
+
enhancedMessage = summaryText + (inlineImageBlocks.length ? `
|
|
23086
|
+
|
|
23087
|
+
${inlineImageBlocks.join("\n\n")}` : "");
|
|
23088
|
+
}
|
|
23089
|
+
} catch (summaryError) {
|
|
23090
|
+
debugLogger.error("Summarization pass threw", {
|
|
23091
|
+
error: summaryError instanceof Error ? summaryError.message : String(summaryError)
|
|
23092
|
+
});
|
|
23093
|
+
}
|
|
23094
|
+
}
|
|
23140
23095
|
}
|
|
23141
23096
|
overrideComponentStatus("Idle");
|
|
23142
23097
|
setIsSubmitting(false);
|
|
@@ -27855,7 +27810,7 @@ var init_ConnectionStatus = __esm({
|
|
|
27855
27810
|
});
|
|
27856
27811
|
|
|
27857
27812
|
// src/hooks/useVoiceMode.ts
|
|
27858
|
-
var import_react55, RMS_BASELINE, RMS_NORMALIZER, computeRms, useVoiceMode;
|
|
27813
|
+
var import_react55, RMS_BASELINE, RMS_NORMALIZER, computeRms, pickSupportedMimeType, useVoiceMode;
|
|
27859
27814
|
var init_useVoiceMode = __esm({
|
|
27860
27815
|
"src/hooks/useVoiceMode.ts"() {
|
|
27861
27816
|
"use strict";
|
|
@@ -27873,6 +27828,19 @@ var init_useVoiceMode = __esm({
|
|
|
27873
27828
|
}
|
|
27874
27829
|
return Math.sqrt(sumSquares / data.length);
|
|
27875
27830
|
};
|
|
27831
|
+
pickSupportedMimeType = () => {
|
|
27832
|
+
if (typeof MediaRecorder === "undefined" || typeof MediaRecorder.isTypeSupported !== "function") {
|
|
27833
|
+
return void 0;
|
|
27834
|
+
}
|
|
27835
|
+
const candidates = [
|
|
27836
|
+
"audio/webm;codecs=opus",
|
|
27837
|
+
"audio/webm",
|
|
27838
|
+
"audio/mp4;codecs=mp4a.40.2",
|
|
27839
|
+
"audio/mp4",
|
|
27840
|
+
"audio/aac"
|
|
27841
|
+
];
|
|
27842
|
+
return candidates.find((type) => MediaRecorder.isTypeSupported(type));
|
|
27843
|
+
};
|
|
27876
27844
|
useVoiceMode = (config) => {
|
|
27877
27845
|
const enabled = useVoiceModeStore((state) => state.enabled);
|
|
27878
27846
|
const setStatus = useVoiceModeStore((state) => state.setStatus);
|
|
@@ -27896,10 +27864,15 @@ var init_useVoiceMode = __esm({
|
|
|
27896
27864
|
let silenceStartAt = 0;
|
|
27897
27865
|
const isRecordingRef = { current: false };
|
|
27898
27866
|
const isProcessingRef = { current: false };
|
|
27867
|
+
let removeResumeListeners = null;
|
|
27899
27868
|
const amplitudeThreshold = configRef.current.amplitudeThreshold ?? 0.025;
|
|
27900
27869
|
const minSpeechMs = configRef.current.minSpeechMs ?? 180;
|
|
27901
27870
|
const minSilenceMs = configRef.current.minSilenceMs ?? 720;
|
|
27902
27871
|
const clearAudioSession = async () => {
|
|
27872
|
+
if (removeResumeListeners) {
|
|
27873
|
+
removeResumeListeners();
|
|
27874
|
+
removeResumeListeners = null;
|
|
27875
|
+
}
|
|
27903
27876
|
if (rafId) {
|
|
27904
27877
|
cancelAnimationFrame(rafId);
|
|
27905
27878
|
rafId = null;
|
|
@@ -27991,7 +27964,8 @@ var init_useVoiceMode = __esm({
|
|
|
27991
27964
|
const startRecording = (stream) => {
|
|
27992
27965
|
chunks = [];
|
|
27993
27966
|
try {
|
|
27994
|
-
|
|
27967
|
+
const mimeType = pickSupportedMimeType();
|
|
27968
|
+
recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);
|
|
27995
27969
|
recorder.addEventListener("dataavailable", (event) => {
|
|
27996
27970
|
if (event.data && event.data.size > 0) {
|
|
27997
27971
|
chunks.push(event.data);
|
|
@@ -28085,6 +28059,28 @@ var init_useVoiceMode = __esm({
|
|
|
28085
28059
|
dataArray
|
|
28086
28060
|
};
|
|
28087
28061
|
resetTransientState();
|
|
28062
|
+
if (audioContext.state === "suspended") {
|
|
28063
|
+
try {
|
|
28064
|
+
await audioContext.resume();
|
|
28065
|
+
} catch (resumeError) {
|
|
28066
|
+
debugLogger.warn("Voice mode audio context resume failed", { error: resumeError });
|
|
28067
|
+
}
|
|
28068
|
+
}
|
|
28069
|
+
if (!cancelled && audioContext.state === "suspended") {
|
|
28070
|
+
const resumeOnGesture = () => {
|
|
28071
|
+
audioContext.resume().catch(() => void 0);
|
|
28072
|
+
};
|
|
28073
|
+
const gestureEvents = ["touchend", "pointerdown", "click"];
|
|
28074
|
+
gestureEvents.forEach(
|
|
28075
|
+
(evt) => window.addEventListener(evt, resumeOnGesture, { once: true, passive: true })
|
|
28076
|
+
);
|
|
28077
|
+
removeResumeListeners = () => {
|
|
28078
|
+
gestureEvents.forEach((evt) => window.removeEventListener(evt, resumeOnGesture));
|
|
28079
|
+
};
|
|
28080
|
+
}
|
|
28081
|
+
if (cancelled) {
|
|
28082
|
+
return;
|
|
28083
|
+
}
|
|
28088
28084
|
monitorAudio();
|
|
28089
28085
|
} catch (error) {
|
|
28090
28086
|
debugLogger.error("Voice mode failed to initialize microphone", {
|