blun-king-cli 9.1.594 → 9.1.595
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/blun.mjs +680 -29
- package/package.json +1 -1
- package/worker-host.mjs +672 -33
package/blun.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:bb2a99b699d299ac283bd9b157d0c18555ae0ab62c58c7b3c10d8311dfa87a0d
|
|
3
3
|
import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
|
|
4
4
|
import { dirname as __cjsShimDirname } from 'node:path';
|
|
5
5
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
@@ -234565,10 +234565,11 @@ var init_context$2 = __esmMin((() => {
|
|
|
234565
234565
|
const openStepIndex = openStep === void 0 ? -1 : this._history.indexOf(openStep);
|
|
234566
234566
|
const coveredCount = openStepIndex === -1 ? this._history.length : openStepIndex + 1;
|
|
234567
234567
|
const totalUsage = event.usage.inputCacheRead + event.usage.inputCacheCreation + event.usage.inputOther + event.usage.output;
|
|
234568
|
-
if (totalUsage > 0) this._tokenCount = totalUsage;
|
|
234568
|
+
if (totalUsage > 0 && event.contextCoverage !== "partial") this._tokenCount = totalUsage;
|
|
234569
234569
|
else {
|
|
234570
234570
|
const previousCoveredCount = this.tokenCountCoveredMessageCount;
|
|
234571
234571
|
this._tokenCount += estimateTokensForMessages(this._history.slice(previousCoveredCount, coveredCount));
|
|
234572
|
+
this._tokenCount = Math.max(this._tokenCount, totalUsage);
|
|
234572
234573
|
}
|
|
234573
234574
|
this.tokenCountCoveredMessageCount = coveredCount;
|
|
234574
234575
|
}
|
|
@@ -238580,9 +238581,524 @@ var init_auto_mode_ask_user_question_deny = __esmMin((() => {
|
|
|
238580
238581
|
};
|
|
238581
238582
|
}));
|
|
238582
238583
|
//#endregion
|
|
238584
|
+
//#region ../../packages/agent-core/src/agent/turn/turn-tool-performance-policy.cjs
|
|
238585
|
+
var require_turn_tool_performance_policy = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
238586
|
+
const TOOL_SCHEMA_BUDGET_RATIO = .25;
|
|
238587
|
+
const TOOL_SCHEMA_MAX_TOKENS = 64e3;
|
|
238588
|
+
const DEFERRED_TOOL_LOADER_NAME = "ToolSearch";
|
|
238589
|
+
const MAX_PERSISTENT_DEFERRED_TOOLS = 12;
|
|
238590
|
+
const MAX_TOOL_SEARCH_QUERY_CHARS = 1e3;
|
|
238591
|
+
const MAX_AUTO_RANKED_TOOLS = 6;
|
|
238592
|
+
const deferredToolLoaders = /* @__PURE__ */ new WeakSet();
|
|
238593
|
+
const TOOL_RANK_EMBEDDED_CONTENT_RE = /<(attached_documents?|attachment_content|document_content|file_content)\b[^>]*>[\s\S]*?<\/\1>/giu;
|
|
238594
|
+
const TOOL_RANK_STOP_WORDS = new Set([
|
|
238595
|
+
"aber",
|
|
238596
|
+
"also",
|
|
238597
|
+
"and",
|
|
238598
|
+
"aus",
|
|
238599
|
+
"bitte",
|
|
238600
|
+
"can",
|
|
238601
|
+
"das",
|
|
238602
|
+
"den",
|
|
238603
|
+
"der",
|
|
238604
|
+
"des",
|
|
238605
|
+
"die",
|
|
238606
|
+
"dies",
|
|
238607
|
+
"diese",
|
|
238608
|
+
"du",
|
|
238609
|
+
"ein",
|
|
238610
|
+
"eine",
|
|
238611
|
+
"einer",
|
|
238612
|
+
"eines",
|
|
238613
|
+
"for",
|
|
238614
|
+
"fuer",
|
|
238615
|
+
"für",
|
|
238616
|
+
"haben",
|
|
238617
|
+
"ich",
|
|
238618
|
+
"ist",
|
|
238619
|
+
"kann",
|
|
238620
|
+
"kannst",
|
|
238621
|
+
"mal",
|
|
238622
|
+
"me",
|
|
238623
|
+
"mein",
|
|
238624
|
+
"meine",
|
|
238625
|
+
"mir",
|
|
238626
|
+
"mit",
|
|
238627
|
+
"of",
|
|
238628
|
+
"please",
|
|
238629
|
+
"soll",
|
|
238630
|
+
"the",
|
|
238631
|
+
"und",
|
|
238632
|
+
"uns",
|
|
238633
|
+
"von",
|
|
238634
|
+
"was",
|
|
238635
|
+
"wir",
|
|
238636
|
+
"with",
|
|
238637
|
+
"you",
|
|
238638
|
+
"zeige",
|
|
238639
|
+
"zeig",
|
|
238640
|
+
"pruefe",
|
|
238641
|
+
"prüfe",
|
|
238642
|
+
"lies",
|
|
238643
|
+
"read",
|
|
238644
|
+
"show",
|
|
238645
|
+
"get"
|
|
238646
|
+
]);
|
|
238647
|
+
const TOOL_SEARCH_INTENT_WORDS = new Set([
|
|
238648
|
+
"find",
|
|
238649
|
+
"fetch",
|
|
238650
|
+
"get",
|
|
238651
|
+
"holen",
|
|
238652
|
+
"list",
|
|
238653
|
+
"read",
|
|
238654
|
+
"search",
|
|
238655
|
+
"show",
|
|
238656
|
+
"anzeigen",
|
|
238657
|
+
"lesen",
|
|
238658
|
+
"suchen"
|
|
238659
|
+
]);
|
|
238660
|
+
const TOOL_SEARCH_RELATED_TERM_GROUPS = Object.freeze([
|
|
238661
|
+
Object.freeze([
|
|
238662
|
+
"checklist",
|
|
238663
|
+
"list",
|
|
238664
|
+
"liste",
|
|
238665
|
+
"listen"
|
|
238666
|
+
]),
|
|
238667
|
+
Object.freeze([
|
|
238668
|
+
"aufgabe",
|
|
238669
|
+
"aufgaben",
|
|
238670
|
+
"aufgabenliste",
|
|
238671
|
+
"todo",
|
|
238672
|
+
"todos"
|
|
238673
|
+
]),
|
|
238674
|
+
Object.freeze([
|
|
238675
|
+
"current",
|
|
238676
|
+
"inbox",
|
|
238677
|
+
"latest",
|
|
238678
|
+
"message",
|
|
238679
|
+
"messages",
|
|
238680
|
+
"nachricht",
|
|
238681
|
+
"nachrichten",
|
|
238682
|
+
"queue",
|
|
238683
|
+
"queued",
|
|
238684
|
+
"recent",
|
|
238685
|
+
"letzte",
|
|
238686
|
+
"letzten",
|
|
238687
|
+
"letzter",
|
|
238688
|
+
"vergangen",
|
|
238689
|
+
"update",
|
|
238690
|
+
"updates"
|
|
238691
|
+
]),
|
|
238692
|
+
Object.freeze([
|
|
238693
|
+
"chat",
|
|
238694
|
+
"conversation",
|
|
238695
|
+
"history",
|
|
238696
|
+
"log",
|
|
238697
|
+
"logs",
|
|
238698
|
+
"processed",
|
|
238699
|
+
"protokoll",
|
|
238700
|
+
"transcript",
|
|
238701
|
+
"verlauf"
|
|
238702
|
+
]),
|
|
238703
|
+
Object.freeze([
|
|
238704
|
+
"fact",
|
|
238705
|
+
"facts",
|
|
238706
|
+
"fakt",
|
|
238707
|
+
"fakten",
|
|
238708
|
+
"memory",
|
|
238709
|
+
"memories",
|
|
238710
|
+
"merk",
|
|
238711
|
+
"merken",
|
|
238712
|
+
"note",
|
|
238713
|
+
"notes",
|
|
238714
|
+
"persist",
|
|
238715
|
+
"persistent",
|
|
238716
|
+
"profile",
|
|
238717
|
+
"remember",
|
|
238718
|
+
"save",
|
|
238719
|
+
"speichern",
|
|
238720
|
+
"store"
|
|
238721
|
+
])
|
|
238722
|
+
]);
|
|
238723
|
+
const TOOL_SEARCH_SINGLE_TERM_RELATED_FALLBACKS = new Set([
|
|
238724
|
+
"fact",
|
|
238725
|
+
"facts",
|
|
238726
|
+
"fakt",
|
|
238727
|
+
"fakten",
|
|
238728
|
+
"memory",
|
|
238729
|
+
"memories",
|
|
238730
|
+
"merk",
|
|
238731
|
+
"merken",
|
|
238732
|
+
"note",
|
|
238733
|
+
"notes",
|
|
238734
|
+
"persist",
|
|
238735
|
+
"persistent",
|
|
238736
|
+
"profile",
|
|
238737
|
+
"remember",
|
|
238738
|
+
"save",
|
|
238739
|
+
"speichern",
|
|
238740
|
+
"store",
|
|
238741
|
+
"transcript"
|
|
238742
|
+
]);
|
|
238743
|
+
const CORE_TOOL_NAMES = Object.freeze([
|
|
238744
|
+
"Bash",
|
|
238745
|
+
"Read",
|
|
238746
|
+
"ReadBatch",
|
|
238747
|
+
"Edit",
|
|
238748
|
+
"Grep",
|
|
238749
|
+
"Write",
|
|
238750
|
+
"Glob",
|
|
238751
|
+
"TodoList",
|
|
238752
|
+
"mcp__plugin-telegram_telegram__reply"
|
|
238753
|
+
]);
|
|
238754
|
+
const IMAGE_MEDIA_TERM_RE = /(?:^|[^\p{L}])(?:bild(?:er)?|foto(?:s)?|grafik(?:en)?|illustration(?:en)?|logo(?:s)?|image|images|photo|photos|picture|pictures|illustration|illustrations|visual|visuals)(?=$|[^\p{L}])/u;
|
|
238755
|
+
const VIDEO_MEDIA_TERM_RE = /(?:^|[^\p{L}])(?:video(?:s)?|clip(?:s)?|film(?:e)?|animation(?:en)?|movie|movies)(?=$|[^\p{L}])/u;
|
|
238756
|
+
const ANIMATE_ACTION_RE = /(?:^|[^\p{L}])(?:animier(?:e|en|t)?|animate|animated|animating)(?=$|[^\p{L}])/u;
|
|
238757
|
+
const CREATE_ACTION_RE = /(?:^|[^\p{L}])(?:erstell(?:e|en|t)?|generier(?:e|en|t)?|erzeug(?:e|en|t)?|produzier(?:e|en|t)?|zeichn(?:e|en|et)?|mal(?:e|en|t)?|render(?:e|n|t)?|mach(?:e|en|t)?|create|creates|creating|generate|generates|generating|make|makes|making|draw|draws|drawing|paint|paints|painting|render|renders|rendering|produce|produces|producing)(?=$|[^\p{L}])/u;
|
|
238758
|
+
const REQUEST_PREFIX_RE = /^(?:bitte\s+|please\s+)?(?:erstell|generier|erzeug|produzier|zeichn|mal|render|mach|animier|create|generate|make|draw|paint|render|produce|animate)/u;
|
|
238759
|
+
const REQUEST_PHRASE_RE = /(?:^|[^\p{L}])(?:bitte|kannst du|könntest du|ich möchte|ich will|ich brauche|please|can you|could you|i want|i need)(?=$|[^\p{L}])/u;
|
|
238760
|
+
function mediaGenerationToolNamesForText(value) {
|
|
238761
|
+
const text = String(value || "").normalize("NFKC").trim().toLowerCase();
|
|
238762
|
+
const selected = /* @__PURE__ */ new Set();
|
|
238763
|
+
if (!text) return selected;
|
|
238764
|
+
if (/(?:^|[^a-z])generateimage(?=$|[^a-z])/u.test(text)) selected.add("GenerateImage");
|
|
238765
|
+
if (/(?:^|[^a-z])generatevideo(?=$|[^a-z])/u.test(text)) selected.add("GenerateVideo");
|
|
238766
|
+
if (selected.size > 0) return selected;
|
|
238767
|
+
const animate = ANIMATE_ACTION_RE.test(text);
|
|
238768
|
+
const create = CREATE_ACTION_RE.test(text);
|
|
238769
|
+
if (!(REQUEST_PREFIX_RE.test(text) || REQUEST_PHRASE_RE.test(text)) || !create && !animate) return selected;
|
|
238770
|
+
if (animate && (IMAGE_MEDIA_TERM_RE.test(text) || VIDEO_MEDIA_TERM_RE.test(text))) {
|
|
238771
|
+
selected.add("GenerateVideo");
|
|
238772
|
+
return selected;
|
|
238773
|
+
}
|
|
238774
|
+
if (IMAGE_MEDIA_TERM_RE.test(text)) selected.add("GenerateImage");
|
|
238775
|
+
if (VIDEO_MEDIA_TERM_RE.test(text)) selected.add("GenerateVideo");
|
|
238776
|
+
return selected;
|
|
238777
|
+
}
|
|
238778
|
+
function mediaToolNamesForTurnText(value) {
|
|
238779
|
+
const text = String(value || "");
|
|
238780
|
+
const selected = /* @__PURE__ */ new Set();
|
|
238781
|
+
const channelBodies = [...text.matchAll(/(?:^|\r?\n)<channel\b[^>]*>\r?\n([\s\S]*?)\r?\n<\/channel>(?=\r?\n|$)/giu)].map((match) => match[1]);
|
|
238782
|
+
const intentTexts = channelBodies.length > 0 ? channelBodies : [text];
|
|
238783
|
+
for (const intentText of intentTexts) for (const name of mediaGenerationToolNamesForText(intentText)) selected.add(name);
|
|
238784
|
+
if (/\bimage_path\s*=\s*["'][^"']+["']/iu.test(text)) {
|
|
238785
|
+
selected.add("ReadMediaFile");
|
|
238786
|
+
selected.add("UnderstandImage");
|
|
238787
|
+
}
|
|
238788
|
+
if (/\battachment_file_id\s*=\s*["'][^"']+["']/iu.test(text)) {
|
|
238789
|
+
selected.add("mcp__plugin-telegram_telegram__download_attachment");
|
|
238790
|
+
selected.add("UnderstandImage");
|
|
238791
|
+
}
|
|
238792
|
+
return selected;
|
|
238793
|
+
}
|
|
238794
|
+
function toolSchemaBudgetTokens(maxContextTokens) {
|
|
238795
|
+
const context = Number(maxContextTokens);
|
|
238796
|
+
if (!Number.isFinite(context) || context <= 0) return TOOL_SCHEMA_MAX_TOKENS;
|
|
238797
|
+
return Math.min(TOOL_SCHEMA_MAX_TOKENS, Math.floor(context * TOOL_SCHEMA_BUDGET_RATIO));
|
|
238798
|
+
}
|
|
238799
|
+
function deferredToolNames(tools) {
|
|
238800
|
+
return [...new Set((Array.isArray(tools) ? tools : []).map((tool) => String(tool?.name || "").trim()).filter(Boolean))].sort((left, right) => left.localeCompare(right));
|
|
238801
|
+
}
|
|
238802
|
+
function deferredToolCatalog(tools) {
|
|
238803
|
+
const names = deferredToolNames(tools);
|
|
238804
|
+
const leaves = names.map((name) => name.split(/__|:/).at(-1) || name);
|
|
238805
|
+
const leafCounts = /* @__PURE__ */ new Map();
|
|
238806
|
+
for (const leaf of leaves) leafCounts.set(leaf, (leafCounts.get(leaf) || 0) + 1);
|
|
238807
|
+
return names.map((name, index) => leafCounts.get(leaves[index]) === 1 ? leaves[index] : name).sort((left, right) => left.localeCompare(right));
|
|
238808
|
+
}
|
|
238809
|
+
function normalizeDeferredToolQuery(value) {
|
|
238810
|
+
const query = String(value ?? "").trim();
|
|
238811
|
+
if (query.length <= MAX_TOOL_SEARCH_QUERY_CHARS) return query;
|
|
238812
|
+
const bounded = query.slice(0, MAX_TOOL_SEARCH_QUERY_CHARS);
|
|
238813
|
+
const wordBoundary = bounded.lastIndexOf(" ");
|
|
238814
|
+
return (wordBoundary >= MAX_TOOL_SEARCH_QUERY_CHARS * .8 ? bounded.slice(0, wordBoundary) : bounded).trimEnd();
|
|
238815
|
+
}
|
|
238816
|
+
function searchDeferredTools(tools, query) {
|
|
238817
|
+
const normalized = normalizeDeferredToolQuery(query).toLowerCase();
|
|
238818
|
+
if (!normalized) return [];
|
|
238819
|
+
if (normalized.startsWith("select:")) {
|
|
238820
|
+
const selector = normalized.slice(7).trim();
|
|
238821
|
+
if (!selector) return [];
|
|
238822
|
+
const exact = tools.find((tool) => String(tool?.name || "").toLowerCase() === selector);
|
|
238823
|
+
if (exact) return [exact];
|
|
238824
|
+
return tools.filter((tool) => {
|
|
238825
|
+
return String(tool?.name || "").toLowerCase().split(/__|:/).at(-1) === selector;
|
|
238826
|
+
});
|
|
238827
|
+
}
|
|
238828
|
+
const tokens = normalized.split(/\s+/).filter(Boolean);
|
|
238829
|
+
const requiredNameTokens = tokens.filter((token) => token.startsWith("+")).map((token) => token.slice(1)).filter(Boolean);
|
|
238830
|
+
const searchTokens = tokens.filter((token) => !token.startsWith("+"));
|
|
238831
|
+
const eligibleTools = tools.filter((tool) => {
|
|
238832
|
+
const name = String(tool?.name || "").toLowerCase();
|
|
238833
|
+
return requiredNameTokens.every((token) => name.includes(token));
|
|
238834
|
+
});
|
|
238835
|
+
const firstSelector = searchTokens[0];
|
|
238836
|
+
if (firstSelector) {
|
|
238837
|
+
const exactNameMatches = eligibleTools.filter((tool) => String(tool?.name || "").toLowerCase() === firstSelector);
|
|
238838
|
+
if (exactNameMatches.length === 1) return exactNameMatches;
|
|
238839
|
+
const exactLeafMatches = eligibleTools.filter((tool) => {
|
|
238840
|
+
return String(tool?.name || "").toLowerCase().split(/__|:/).at(-1) === firstSelector;
|
|
238841
|
+
});
|
|
238842
|
+
if (exactLeafMatches.length === 1) return exactLeafMatches;
|
|
238843
|
+
}
|
|
238844
|
+
return tools.map((tool) => {
|
|
238845
|
+
const name = String(tool?.name || "").toLowerCase();
|
|
238846
|
+
const description = String(tool?.description || "").toLowerCase();
|
|
238847
|
+
if (!requiredNameTokens.every((token) => name.includes(token))) return null;
|
|
238848
|
+
if (!searchTokens.every((token) => name.includes(token) || description.includes(token))) return null;
|
|
238849
|
+
return {
|
|
238850
|
+
tool,
|
|
238851
|
+
score: searchTokens.reduce((total, token) => total + (name.includes(token) ? 5 : 1), 0) + requiredNameTokens.length * 5
|
|
238852
|
+
};
|
|
238853
|
+
}).filter(Boolean).sort((left, right) => right.score - left.score || String(left.tool.name).localeCompare(String(right.tool.name))).slice(0, 5).map((entry) => entry.tool);
|
|
238854
|
+
}
|
|
238855
|
+
function relatedSearchTerms(token) {
|
|
238856
|
+
return TOOL_SEARCH_RELATED_TERM_GROUPS.find((terms) => terms.includes(token)) || [token];
|
|
238857
|
+
}
|
|
238858
|
+
function rankingIntentTexts(value) {
|
|
238859
|
+
const text = String(value || "");
|
|
238860
|
+
const channelBodies = [...text.matchAll(/(?:^|\r?\n)<channel\b[^>]*>\r?\n([\s\S]*?)\r?\n<\/channel>(?=\r?\n|$)/giu)].map((match) => match[1]);
|
|
238861
|
+
return (channelBodies.length > 0 ? channelBodies : [text]).map((intentText) => normalizeDeferredToolQuery(intentText.replace(TOOL_RANK_EMBEDDED_CONTENT_RE, " ")));
|
|
238862
|
+
}
|
|
238863
|
+
function rankingTokens(value) {
|
|
238864
|
+
return [...new Set(String(value || "").normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}]{3,}/gu) || [])].filter((token) => !TOOL_RANK_STOP_WORDS.has(token));
|
|
238865
|
+
}
|
|
238866
|
+
function toolRankingDocument(tool) {
|
|
238867
|
+
const name = String(tool?.name || "");
|
|
238868
|
+
const leaf = name.split(/__|:/).at(-1) || name;
|
|
238869
|
+
const splitToolName = (value) => String(value || "").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replaceAll("_", " ");
|
|
238870
|
+
const nameTokens = rankingTokens(`${splitToolName(name)} ${splitToolName(leaf)}`);
|
|
238871
|
+
const descriptionTokens = rankingTokens(tool?.description);
|
|
238872
|
+
const parameterText = [];
|
|
238873
|
+
const properties = tool?.parameters?.properties;
|
|
238874
|
+
if (properties && typeof properties === "object") for (const [parameterName, definition] of Object.entries(properties)) parameterText.push(parameterName, definition?.description || "");
|
|
238875
|
+
const exampleText = Array.isArray(tool?.examples) ? tool.examples.map((example) => example?.prompt || "").join(" ") : "";
|
|
238876
|
+
return {
|
|
238877
|
+
name,
|
|
238878
|
+
nameTokens: new Set(nameTokens),
|
|
238879
|
+
descriptionTokens: new Set(descriptionTokens),
|
|
238880
|
+
detailTokens: new Set(rankingTokens(`${parameterText.join(" ")} ${exampleText}`))
|
|
238881
|
+
};
|
|
238882
|
+
}
|
|
238883
|
+
function tokenMatchScore(document, token) {
|
|
238884
|
+
if (document.nameTokens.has(token)) return 10;
|
|
238885
|
+
if (document.descriptionTokens.has(token)) return 5;
|
|
238886
|
+
if (document.detailTokens.has(token)) return 4;
|
|
238887
|
+
const related = relatedSearchTerms(token).filter((term) => term !== token);
|
|
238888
|
+
if (related.some((term) => document.nameTokens.has(term))) return 5;
|
|
238889
|
+
if (related.some((term) => document.descriptionTokens.has(term))) return 3;
|
|
238890
|
+
if (related.some((term) => document.detailTokens.has(term))) return 2;
|
|
238891
|
+
return 0;
|
|
238892
|
+
}
|
|
238893
|
+
/**
|
|
238894
|
+
* Select a tiny, high-confidence subset of deferred schemas for the current
|
|
238895
|
+
* request. This mirrors AnythingLLM's tool-reranker boundary without adding an
|
|
238896
|
+
* embedding runtime: King reuses the descriptions it already owns and keeps
|
|
238897
|
+
* ToolSearch available whenever the lexical evidence is weak or ambiguous.
|
|
238898
|
+
*/
|
|
238899
|
+
function rankedToolNamesForTurnText(tools, value, options = {}) {
|
|
238900
|
+
const maxTools = Math.max(0, Math.min(MAX_AUTO_RANKED_TOOLS, Number.isInteger(options.maxTools) ? options.maxTools : MAX_AUTO_RANKED_TOOLS));
|
|
238901
|
+
if (maxTools === 0) return /* @__PURE__ */ new Set();
|
|
238902
|
+
const queryTokens = [...new Set(rankingIntentTexts(value).flatMap(rankingTokens))];
|
|
238903
|
+
if (queryTokens.length === 0) return /* @__PURE__ */ new Set();
|
|
238904
|
+
const ranked = (Array.isArray(tools) ? tools : []).map((tool) => {
|
|
238905
|
+
const document = toolRankingDocument(tool);
|
|
238906
|
+
if (!document.name) return null;
|
|
238907
|
+
let score = 0;
|
|
238908
|
+
let matchedTokens = 0;
|
|
238909
|
+
let exactNameMatches = 0;
|
|
238910
|
+
let relatedNameMatches = 0;
|
|
238911
|
+
for (const token of queryTokens) {
|
|
238912
|
+
const tokenScore = tokenMatchScore(document, token);
|
|
238913
|
+
if (tokenScore === 0) continue;
|
|
238914
|
+
score += tokenScore;
|
|
238915
|
+
matchedTokens += 1;
|
|
238916
|
+
if (document.nameTokens.has(token)) exactNameMatches += 1;
|
|
238917
|
+
else if (relatedSearchTerms(token).some((term) => document.nameTokens.has(term))) relatedNameMatches += 1;
|
|
238918
|
+
}
|
|
238919
|
+
return matchedTokens >= 2 || exactNameMatches >= 1 && score >= 10 || relatedNameMatches >= 1 && score >= 5 ? {
|
|
238920
|
+
name: document.name,
|
|
238921
|
+
score,
|
|
238922
|
+
matchedTokens,
|
|
238923
|
+
exactNameMatches
|
|
238924
|
+
} : null;
|
|
238925
|
+
}).filter(Boolean).sort((left, right) => right.matchedTokens - left.matchedTokens || right.score - left.score || right.exactNameMatches - left.exactNameMatches || left.name.localeCompare(right.name));
|
|
238926
|
+
return new Set(ranked.slice(0, maxTools).map((entry) => entry.name));
|
|
238927
|
+
}
|
|
238928
|
+
function rankedSupportToolNamesForGoal(tools, goal, origin) {
|
|
238929
|
+
if (origin?.kind !== "system_trigger" || origin?.name !== "goal_continuation") return /* @__PURE__ */ new Set();
|
|
238930
|
+
if (goal?.status !== "active") return /* @__PURE__ */ new Set();
|
|
238931
|
+
const checkpoint = goal.actionCheckpoint;
|
|
238932
|
+
if (checkpoint?.phase === "wait" || checkpoint?.nextTrigger?.kind !== "immediate") return /* @__PURE__ */ new Set();
|
|
238933
|
+
const supportChoice = String(checkpoint?.problemFrame?.supportChoice ?? "").trim();
|
|
238934
|
+
if (!supportChoice.match(/^(?:tool|skill)\s*:\s*(.+)$/iu)?.[1]) return /* @__PURE__ */ new Set();
|
|
238935
|
+
return rankedToolNamesForTurnText(tools, supportChoice, { maxTools: 1 });
|
|
238936
|
+
}
|
|
238937
|
+
function searchRelatedDeferredTools(tools, query, options = {}) {
|
|
238938
|
+
const normalized = normalizeDeferredToolQuery(query).toLowerCase();
|
|
238939
|
+
if (!normalized || normalized.startsWith("select:")) return [];
|
|
238940
|
+
const tokens = normalized.split(/\s+/).filter(Boolean);
|
|
238941
|
+
const requestedNameTokens = tokens.filter((token) => token.startsWith("+")).map((token) => token.slice(1)).filter(Boolean);
|
|
238942
|
+
const relaxRequiredNameTokens = options.relaxRequiredNameTokens === true && requestedNameTokens.length > 0;
|
|
238943
|
+
const requiredNameTokens = relaxRequiredNameTokens ? [] : requestedNameTokens;
|
|
238944
|
+
const searchTokens = [...tokens.filter((token) => !token.startsWith("+")), ...relaxRequiredNameTokens ? requestedNameTokens : []].filter((token) => !TOOL_SEARCH_INTENT_WORDS.has(token));
|
|
238945
|
+
if (searchTokens.length < 2 && !TOOL_SEARCH_SINGLE_TERM_RELATED_FALLBACKS.has(searchTokens[0])) return [];
|
|
238946
|
+
const minimumMatchedTokens = searchTokens.length === 1 ? 1 : Math.max(2, Math.ceil(searchTokens.length * .75));
|
|
238947
|
+
const ranked = tools.map((tool) => {
|
|
238948
|
+
const name = String(tool?.name || "").toLowerCase();
|
|
238949
|
+
const description = String(tool?.description || "").toLowerCase();
|
|
238950
|
+
if (!requiredNameTokens.every((token) => name.includes(token))) return null;
|
|
238951
|
+
let matchedTokens = 0;
|
|
238952
|
+
let score = requiredNameTokens.length * 8;
|
|
238953
|
+
for (const token of searchTokens) {
|
|
238954
|
+
if (name.includes(token)) {
|
|
238955
|
+
matchedTokens += 1;
|
|
238956
|
+
score += 8;
|
|
238957
|
+
continue;
|
|
238958
|
+
}
|
|
238959
|
+
if (description.includes(token)) {
|
|
238960
|
+
matchedTokens += 1;
|
|
238961
|
+
score += 4;
|
|
238962
|
+
continue;
|
|
238963
|
+
}
|
|
238964
|
+
const related = relatedSearchTerms(token).filter((term) => term !== token);
|
|
238965
|
+
if (related.some((term) => name.includes(term))) {
|
|
238966
|
+
matchedTokens += 1;
|
|
238967
|
+
score += 3;
|
|
238968
|
+
} else if (related.some((term) => description.includes(term))) {
|
|
238969
|
+
matchedTokens += 1;
|
|
238970
|
+
score += 2;
|
|
238971
|
+
}
|
|
238972
|
+
}
|
|
238973
|
+
return matchedTokens >= minimumMatchedTokens ? {
|
|
238974
|
+
tool,
|
|
238975
|
+
score,
|
|
238976
|
+
matchedTokens
|
|
238977
|
+
} : null;
|
|
238978
|
+
}).filter(Boolean).sort((left, right) => right.matchedTokens - left.matchedTokens || right.score - left.score || String(left.tool.name).localeCompare(String(right.tool.name)));
|
|
238979
|
+
if (relaxRequiredNameTokens && ranked.length > 0) {
|
|
238980
|
+
const best = ranked[0];
|
|
238981
|
+
return ranked.filter((entry) => entry.matchedTokens === best.matchedTokens && entry.score === best.score).slice(0, 5).map((entry) => entry.tool);
|
|
238982
|
+
}
|
|
238983
|
+
return ranked.slice(0, 5).map((entry) => entry.tool);
|
|
238984
|
+
}
|
|
238985
|
+
function rememberLoadedTool(loadedToolNames, name) {
|
|
238986
|
+
loadedToolNames.delete(name);
|
|
238987
|
+
loadedToolNames.add(name);
|
|
238988
|
+
while (loadedToolNames.size > MAX_PERSISTENT_DEFERRED_TOOLS) loadedToolNames.delete(loadedToolNames.values().next().value);
|
|
238989
|
+
}
|
|
238990
|
+
function rememberDeferredToolAfterNotFound(loadedToolNames, toolName, result) {
|
|
238991
|
+
if (!(loadedToolNames instanceof Set) || result?.isError !== true) return false;
|
|
238992
|
+
const name = String(toolName || "").trim();
|
|
238993
|
+
if (!name || String(result?.output || "").trim() !== `Tool "${name}" not found`) return false;
|
|
238994
|
+
rememberLoadedTool(loadedToolNames, name);
|
|
238995
|
+
return true;
|
|
238996
|
+
}
|
|
238997
|
+
function createDeferredToolLoader(selectedTools, deferredTools, loadedToolNames = /* @__PURE__ */ new Set()) {
|
|
238998
|
+
if (!Array.isArray(selectedTools)) throw new TypeError("selectedTools must be an array");
|
|
238999
|
+
if (!(loadedToolNames instanceof Set)) throw new TypeError("loadedToolNames must be a Set");
|
|
239000
|
+
const available = /* @__PURE__ */ new Map();
|
|
239001
|
+
for (const tool of Array.isArray(deferredTools) ? deferredTools : []) {
|
|
239002
|
+
const name = String(tool?.name || "").trim();
|
|
239003
|
+
if (name && !available.has(name)) available.set(name, tool);
|
|
239004
|
+
}
|
|
239005
|
+
const deferredCount = available.size;
|
|
239006
|
+
const loader = {
|
|
239007
|
+
name: DEFERRED_TOOL_LOADER_NAME,
|
|
239008
|
+
description: [
|
|
239009
|
+
`Search ${deferredCount} deferred ${deferredCount === 1 ? "tool schema" : "tool schemas"} without loading all definitions.`,
|
|
239010
|
+
"Use select:leaf_name for one known tool, plain keywords to search, or +word to require that word in the tool name.",
|
|
239011
|
+
`Loaded tools are available in the next step; the ${MAX_PERSISTENT_DEFERRED_TOOLS} most recently selected schemas remain loaded.`
|
|
239012
|
+
].join("\n"),
|
|
239013
|
+
parameters: {
|
|
239014
|
+
type: "object",
|
|
239015
|
+
properties: { query: {
|
|
239016
|
+
type: "string",
|
|
239017
|
+
maxLength: MAX_TOOL_SEARCH_QUERY_CHARS,
|
|
239018
|
+
description: "Exact selection or keyword query, for example select:download_attachment or +slack send."
|
|
239019
|
+
} },
|
|
239020
|
+
required: ["query"],
|
|
239021
|
+
additionalProperties: false
|
|
239022
|
+
},
|
|
239023
|
+
resolveExecution(args) {
|
|
239024
|
+
const query = normalizeDeferredToolQuery(args?.query);
|
|
239025
|
+
return {
|
|
239026
|
+
description: query ? `Searching tool schemas for ${query}` : "Searching tool schemas",
|
|
239027
|
+
approvalRule: DEFERRED_TOOL_LOADER_NAME,
|
|
239028
|
+
execute: async () => {
|
|
239029
|
+
let matches = searchDeferredTools([...available.values()], query);
|
|
239030
|
+
let relatedFallback = false;
|
|
239031
|
+
if (matches.length === 0) {
|
|
239032
|
+
matches = searchRelatedDeferredTools([...available.values()], query);
|
|
239033
|
+
relatedFallback = matches.length > 0;
|
|
239034
|
+
}
|
|
239035
|
+
if (matches.length === 0) {
|
|
239036
|
+
matches = searchRelatedDeferredTools([...available.values()], query, { relaxRequiredNameTokens: true });
|
|
239037
|
+
relatedFallback = matches.length > 0;
|
|
239038
|
+
}
|
|
239039
|
+
if (matches.length === 0) {
|
|
239040
|
+
const alreadyLoaded = query.toLowerCase().startsWith("select:") ? searchDeferredTools(selectedTools.filter((tool) => tool?.name !== DEFERRED_TOOL_LOADER_NAME), query) : [];
|
|
239041
|
+
if (alreadyLoaded.length === 1) return {
|
|
239042
|
+
isError: false,
|
|
239043
|
+
output: `Tool schema already loaded: ${alreadyLoaded[0].name}. Invoke it now.`
|
|
239044
|
+
};
|
|
239045
|
+
return {
|
|
239046
|
+
isError: false,
|
|
239047
|
+
output: [
|
|
239048
|
+
`No eligible deferred tool is available for: ${query || "[empty query]"}.`,
|
|
239049
|
+
"Use a loaded alternative or report this integration as unavailable.",
|
|
239050
|
+
"ToolSearch remains available for a different tool needed later."
|
|
239051
|
+
].join(" ")
|
|
239052
|
+
};
|
|
239053
|
+
}
|
|
239054
|
+
if (query.toLowerCase().startsWith("select:") && matches.length !== 1) return {
|
|
239055
|
+
isError: true,
|
|
239056
|
+
output: `Tool selection is ambiguous: ${matches.map((tool) => tool.name).join(", ")}`
|
|
239057
|
+
};
|
|
239058
|
+
const loaded = [];
|
|
239059
|
+
for (const tool of matches) {
|
|
239060
|
+
const name = String(tool.name);
|
|
239061
|
+
if (!selectedTools.some((candidate) => candidate?.name === name)) selectedTools.push(tool);
|
|
239062
|
+
rememberLoadedTool(loadedToolNames, name);
|
|
239063
|
+
loaded.push(name);
|
|
239064
|
+
}
|
|
239065
|
+
return {
|
|
239066
|
+
isError: false,
|
|
239067
|
+
output: `${relatedFallback ? "Loaded related tool schemas" : "Loaded tool schemas"}: ${loaded.join(", ")}. Invoke them in the next step.`
|
|
239068
|
+
};
|
|
239069
|
+
}
|
|
239070
|
+
};
|
|
239071
|
+
}
|
|
239072
|
+
};
|
|
239073
|
+
deferredToolLoaders.add(loader);
|
|
239074
|
+
return loader;
|
|
239075
|
+
}
|
|
239076
|
+
module.exports = {
|
|
239077
|
+
isDeferredToolLoader: (tool) => deferredToolLoaders.has(tool),
|
|
239078
|
+
CORE_TOOL_NAMES,
|
|
239079
|
+
DEFERRED_TOOL_LOADER_NAME,
|
|
239080
|
+
MAX_PERSISTENT_DEFERRED_TOOLS,
|
|
239081
|
+
MAX_AUTO_RANKED_TOOLS,
|
|
239082
|
+
MAX_TOOL_SEARCH_QUERY_CHARS,
|
|
239083
|
+
TOOL_SCHEMA_BUDGET_RATIO,
|
|
239084
|
+
TOOL_SCHEMA_MAX_TOKENS,
|
|
239085
|
+
createDeferredToolLoader,
|
|
239086
|
+
deferredToolCatalog,
|
|
239087
|
+
deferredToolNames,
|
|
239088
|
+
mediaGenerationToolNamesForText,
|
|
239089
|
+
mediaToolNamesForTurnText,
|
|
239090
|
+
normalizeDeferredToolQuery,
|
|
239091
|
+
rankedSupportToolNamesForGoal,
|
|
239092
|
+
rankedToolNamesForTurnText,
|
|
239093
|
+
rememberDeferredToolAfterNotFound,
|
|
239094
|
+
toolSchemaBudgetTokens
|
|
239095
|
+
};
|
|
239096
|
+
}));
|
|
239097
|
+
//#endregion
|
|
238583
239098
|
//#region ../../packages/agent-core/src/agent/permission/policies/default-tool-approve.ts
|
|
238584
|
-
var DEFAULT_APPROVE_TOOLS, DefaultToolApprovePermissionPolicy;
|
|
239099
|
+
var import_turn_tool_performance_policy$1, DEFAULT_APPROVE_TOOLS, DefaultToolApprovePermissionPolicy;
|
|
238585
239100
|
var init_default_tool_approve = __esmMin((() => {
|
|
239101
|
+
import_turn_tool_performance_policy$1 = require_turn_tool_performance_policy();
|
|
238586
239102
|
DEFAULT_APPROVE_TOOLS = new Set([
|
|
238587
239103
|
"Read",
|
|
238588
239104
|
"Grep",
|
|
@@ -238605,7 +239121,7 @@ var init_default_tool_approve = __esmMin((() => {
|
|
|
238605
239121
|
DefaultToolApprovePermissionPolicy = class {
|
|
238606
239122
|
name = "default-tool-approve";
|
|
238607
239123
|
evaluate(context) {
|
|
238608
|
-
if (!DEFAULT_APPROVE_TOOLS.has(context.toolCall.name)) return;
|
|
239124
|
+
if (!DEFAULT_APPROVE_TOOLS.has(context.toolCall.name) && !(0, import_turn_tool_performance_policy$1.isDeferredToolLoader)(context.tool)) return;
|
|
238609
239125
|
return { kind: "approve" };
|
|
238610
239126
|
}
|
|
238611
239127
|
};
|
|
@@ -240440,6 +240956,43 @@ var init_scanner = __esmMin((() => {
|
|
|
240440
240956
|
}));
|
|
240441
240957
|
//#endregion
|
|
240442
240958
|
//#region ../../packages/agent-core/src/skill/registry.ts
|
|
240959
|
+
function compactLegacyModelSkillListing(prompt, registry) {
|
|
240960
|
+
const header = "DISREGARD any earlier skill listings. Current available skills:";
|
|
240961
|
+
if (!prompt.includes(header)) return prompt;
|
|
240962
|
+
const listing = renderGroupedSkills(registry.listInvocableSkills().filter((skill) => skill.metadata.isSubSkill !== true), formatModelSkill);
|
|
240963
|
+
if (listing.length <= MODEL_SKILL_LISTING_MAX_CHARS) return prompt;
|
|
240964
|
+
const legacy = `${header}\n${listing}`;
|
|
240965
|
+
const start = prompt.indexOf(legacy);
|
|
240966
|
+
if (start < 0) return prompt;
|
|
240967
|
+
const end = start + legacy.length;
|
|
240968
|
+
if (end < prompt.length && !prompt.startsWith("\n\n", end)) return prompt;
|
|
240969
|
+
return prompt.slice(0, start) + registry.getModelSkillListing() + prompt.slice(end);
|
|
240970
|
+
}
|
|
240971
|
+
function searchModelSkills(skills, query, offset = 0) {
|
|
240972
|
+
const normalize = (value) => value.normalize("NFKC").toLowerCase();
|
|
240973
|
+
const words = normalize(query.slice(0, 1e3)).match(/[\p{L}\p{N}_-]+/gu) ?? [];
|
|
240974
|
+
const matches = skills.filter((skill) => skill.metadata.disableModelInvocation !== true && skill.metadata.isSubSkill !== true && isInlineSkillType(skill.metadata.type)).map((skill) => {
|
|
240975
|
+
const name = normalize(skill.name);
|
|
240976
|
+
const metadata = normalize(`${skill.name} ${skill.description} ${skill.metadata.whenToUse ?? ""}`);
|
|
240977
|
+
return {
|
|
240978
|
+
skill,
|
|
240979
|
+
matches: words.every((word) => metadata.includes(word)),
|
|
240980
|
+
score: words.filter((word) => name.includes(word)).length
|
|
240981
|
+
};
|
|
240982
|
+
}).filter((item) => item.matches).sort((a, b) => b.score - a.score || a.skill.name.localeCompare(b.skill.name));
|
|
240983
|
+
const start = Number.isSafeInteger(offset) && offset >= 0 ? offset : 0;
|
|
240984
|
+
const page = matches.slice(start, start + 10);
|
|
240985
|
+
return JSON.stringify({
|
|
240986
|
+
total: matches.length,
|
|
240987
|
+
offset: start,
|
|
240988
|
+
nextOffset: start + page.length < matches.length ? start + page.length : null,
|
|
240989
|
+
matches: page.map(({ skill }) => ({
|
|
240990
|
+
name: skill.name,
|
|
240991
|
+
description: truncate$2(skill.description, LISTING_DESC_MAX),
|
|
240992
|
+
path: skill.path
|
|
240993
|
+
}))
|
|
240994
|
+
});
|
|
240995
|
+
}
|
|
240443
240996
|
function pluginSkillKey(pluginId, skillName) {
|
|
240444
240997
|
return `${pluginId}\0${normalizeSkillName(skillName)}`;
|
|
240445
240998
|
}
|
|
@@ -240477,13 +241030,14 @@ function truncate$2(value, max) {
|
|
|
240477
241030
|
}
|
|
240478
241031
|
return `${result}…`;
|
|
240479
241032
|
}
|
|
240480
|
-
var LISTING_DESC_MAX, SessionSkillRegistry, SOURCE_GROUPS, graphemeSegmenter$2;
|
|
241033
|
+
var LISTING_DESC_MAX, MODEL_SKILL_LISTING_MAX_CHARS, SessionSkillRegistry, SOURCE_GROUPS, graphemeSegmenter$2;
|
|
240481
241034
|
var init_registry = __esmMin((() => {
|
|
240482
241035
|
init_parser$1();
|
|
240483
241036
|
init_scanner();
|
|
240484
241037
|
init_types$15();
|
|
240485
241038
|
init_xml_escape();
|
|
240486
241039
|
LISTING_DESC_MAX = 250;
|
|
241040
|
+
MODEL_SKILL_LISTING_MAX_CHARS = 8e3;
|
|
240487
241041
|
SessionSkillRegistry = class {
|
|
240488
241042
|
byName = /* @__PURE__ */ new Map();
|
|
240489
241043
|
byPluginAndName = /* @__PURE__ */ new Map();
|
|
@@ -240563,6 +241117,17 @@ var init_registry = __esmMin((() => {
|
|
|
240563
241117
|
getModelSkillListing() {
|
|
240564
241118
|
const lines = ["DISREGARD any earlier skill listings. Current available skills:"];
|
|
240565
241119
|
const listing = renderGroupedSkills(this.listInvocableSkills().filter((skill) => skill.metadata.isSubSkill !== true), formatModelSkill);
|
|
241120
|
+
if (listing.length > MODEL_SKILL_LISTING_MAX_CHARS) {
|
|
241121
|
+
const count = this.listInvocableSkills().filter((skill) => skill.metadata.isSubSkill !== true).length;
|
|
241122
|
+
return [
|
|
241123
|
+
lines[0],
|
|
241124
|
+
`${count} skills are available on demand.`,
|
|
241125
|
+
"Before specialized work, search descriptions with Skill({skill: \"task keywords\", search: true}).",
|
|
241126
|
+
"Search returns names and metadata only. Invoke Skill({skill: \"exact-name\", args: \"...\"}) to load instructions.",
|
|
241127
|
+
"Use an empty search string to browse; follow nextOffset with offset to see more results.",
|
|
241128
|
+
"A search miss is not proof that no skill exists; try its exact name or browse the catalog."
|
|
241129
|
+
].join("\n");
|
|
241130
|
+
}
|
|
240566
241131
|
if (listing.length > 0) lines.push(listing);
|
|
240567
241132
|
return lines.length === 1 ? "" : lines.join("\n");
|
|
240568
241133
|
}
|
|
@@ -256945,7 +257510,7 @@ human_shell_hint: The pending question is also visible in /tasks.`,
|
|
|
256945
257510
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/skill-tool.md?raw
|
|
256946
257511
|
var skill_tool_default;
|
|
256947
257512
|
var init_skill_tool$1 = __esmMin((() => {
|
|
256948
|
-
skill_tool_default = "Invoke a registered skill from the current skill listing. BLOCKING REQUIREMENT: when a skill from the listing matches the user's request, you MUST call this tool (not free-form text). Do not re-invoke a skill to repeat work already done: if a `<blun-skill-loaded>` block for it with the same `args` is already present in the conversation, follow those instructions directly instead of calling the tool again. Do call the tool again when you need the skill with different arguments — the loaded block was expanded with the earlier `args` and will not reflect new inputs.\n\nAUTO-SKILL-ROUTING — you MUST proactively use skills WITHOUT being asked:\n- Before responding to any user request, check if an available skill matches the task. If it does, call this tool FIRST — do not attempt the task without the skill.\n- Images/screenshots → use the image/vision skill (e.g. \"screenshot-lesen\") to read and understand the image content before responding.\n- Design/UI tasks → use the appropriate design skill (e.g. \"design-taste-frontend\", \"high-end-visual-design\", \"apple-design\", \"huashu-design\", \"emil-design-eng\", \"motion-design-taste\", \"stitch-design-taste\", \"minimalist-ui\", \"industrial-brutalist-ui\", \"redesign-existing-projects\").\n- FOR ANY UI/frontend/visual output you MUST first load a design skill — never produce raw/default-styled UI. Gradients-everywhere, random emoji-icons, generic AI-looking layouts = FORBIDDEN slop. Always use a design skill before writing UI code.\n- Video/media tasks → use \"ffmpeg\" or the relevant media skill.\n- Web scraping/reading → use \"web-lesen\".\n- PDF/document tasks → use the PDF or document skill.\n- When in doubt whether a skill applies, call it — using a skill when not needed is harmless; NOT using a skill when it would help is a failure.\n- Never tell the user \"I don't have the right tool\" if a matching skill exists in the listing — use it.\n- This is automatic: do not ask the user \"should I use a skill?\" — just use it.\n";
|
|
257513
|
+
skill_tool_default = "Invoke a registered skill from the current skill listing. BLOCKING REQUIREMENT: when a skill from the listing matches the user's request, you MUST call this tool (not free-form text). Do not re-invoke a skill to repeat work already done: if a `<blun-skill-loaded>` block for it with the same `args` is already present in the conversation, follow those instructions directly instead of calling the tool again. Do call the tool again when you need the skill with different arguments — the loaded block was expanded with the earlier `args` and will not reflect new inputs.\n\nFor a deferred catalog, call `Skill({skill: \"task keywords\", search: true})` first. Search returns at most 10 eligible names and descriptions without loading skill instructions. An empty search browses the catalog; pass `nextOffset` as `offset` for the next page. Then invoke the chosen exact name with `search` omitted.\n\nAUTO-SKILL-ROUTING — you MUST proactively use skills WITHOUT being asked:\n- Before responding to any user request, check if an available skill matches the task. If it does, call this tool FIRST — do not attempt the task without the skill.\n- Images/screenshots → use the image/vision skill (e.g. \"screenshot-lesen\") to read and understand the image content before responding.\n- Design/UI tasks → use the appropriate design skill (e.g. \"design-taste-frontend\", \"high-end-visual-design\", \"apple-design\", \"huashu-design\", \"emil-design-eng\", \"motion-design-taste\", \"stitch-design-taste\", \"minimalist-ui\", \"industrial-brutalist-ui\", \"redesign-existing-projects\").\n- FOR ANY UI/frontend/visual output you MUST first load a design skill — never produce raw/default-styled UI. Gradients-everywhere, random emoji-icons, generic AI-looking layouts = FORBIDDEN slop. Always use a design skill before writing UI code.\n- Video/media tasks → use \"ffmpeg\" or the relevant media skill.\n- Web scraping/reading → use \"web-lesen\".\n- PDF/document tasks → use the PDF or document skill.\n- When in doubt whether a skill applies, call it — using a skill when not needed is harmless; NOT using a skill when it would help is a failure.\n- Never tell the user \"I don't have the right tool\" if a matching skill exists in the listing — use it.\n- This is automatic: do not ask the user \"should I use a skill?\" — just use it.\n";
|
|
256949
257514
|
}));
|
|
256950
257515
|
//#endregion
|
|
256951
257516
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/skill-tool.ts
|
|
@@ -257001,7 +257566,9 @@ var init_skill_tool = __esmMin((() => {
|
|
|
257001
257566
|
};
|
|
257002
257567
|
SkillToolInputSchema = object$1({
|
|
257003
257568
|
skill: string().describe("The exact name of the skill to invoke, spelled as it appears in the current skill listing (e.g. \"commit\", \"pdf\")."),
|
|
257004
|
-
args: string().optional().describe("Optional argument string for the skill, written like a command line (e.g. `-m \"fix bug\"`, `123`, a file path). It is split on whitespace (quotes group a token) and expanded into the skill's placeholders ($NAME, $1, $ARGUMENTS); if the skill body has no placeholders, the whole string is still appended as a trailing `ARGUMENTS:` line. Omit it only when there is nothing to pass.")
|
|
257569
|
+
args: string().optional().describe("Optional argument string for the skill, written like a command line (e.g. `-m \"fix bug\"`, `123`, a file path). It is split on whitespace (quotes group a token) and expanded into the skill's placeholders ($NAME, $1, $ARGUMENTS); if the skill body has no placeholders, the whole string is still appended as a trailing `ARGUMENTS:` line. Omit it only when there is nothing to pass."),
|
|
257570
|
+
search: boolean$1().optional().describe("Search eligible skill metadata using skill as keywords, without activating a skill."),
|
|
257571
|
+
offset: number$1().int().min(0).optional().describe("For search only: nextOffset from a previous page. Each page has at most 10 skills.")
|
|
257005
257572
|
});
|
|
257006
257573
|
SkillTool = class SkillTool {
|
|
257007
257574
|
agent;
|
|
@@ -257014,6 +257581,12 @@ var init_skill_tool = __esmMin((() => {
|
|
|
257014
257581
|
this.options = options;
|
|
257015
257582
|
}
|
|
257016
257583
|
resolveExecution(args) {
|
|
257584
|
+
if (args.search === true) return {
|
|
257585
|
+
description: `Search skill metadata: ${args.skill}`,
|
|
257586
|
+
approvalRule: this.name,
|
|
257587
|
+
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.skill),
|
|
257588
|
+
execute: async () => ({ output: searchModelSkills(this.agent.skills?.registry.listInvocableSkills() ?? [], args.skill, args.offset) })
|
|
257589
|
+
};
|
|
257017
257590
|
return {
|
|
257018
257591
|
description: `Invoke skill ${args.skill}`,
|
|
257019
257592
|
display: {
|
|
@@ -264616,22 +265189,45 @@ function blunThinkingIntentInput(input) {
|
|
|
264616
265189
|
text: channelText
|
|
264617
265190
|
}];
|
|
264618
265191
|
}
|
|
265192
|
+
function blunTurnHasAttachment(input) {
|
|
265193
|
+
return input.some((part) => part.type !== "text") || /\b(?:image_path|attachment_file_id)\s*=/i.test(blunExtractText(input));
|
|
265194
|
+
}
|
|
265195
|
+
function greetingHistory(history, anchor) {
|
|
265196
|
+
const start = anchor === void 0 ? -1 : history.indexOf(anchor);
|
|
265197
|
+
if (start < 0) return history;
|
|
265198
|
+
const recent = [];
|
|
265199
|
+
let chars = 0;
|
|
265200
|
+
for (let i = start - 1; i >= 0 && recent.length < 6; i -= 1) {
|
|
265201
|
+
const message = history[i];
|
|
265202
|
+
if (message.role === "tool" || message.toolCalls.length > 0) break;
|
|
265203
|
+
if (message.role !== "assistant" && message.origin?.kind !== "user") continue;
|
|
265204
|
+
const size = blunExtractText(message.content).length;
|
|
265205
|
+
if (chars + size > 12e3 || message.content.some((part) => part.type !== "text")) break;
|
|
265206
|
+
recent.unshift(message);
|
|
265207
|
+
chars += size;
|
|
265208
|
+
}
|
|
265209
|
+
while (recent.length > 0 && recent[0].role !== "user") recent.shift();
|
|
265210
|
+
return [...recent, ...history.slice(start)];
|
|
265211
|
+
}
|
|
264619
265212
|
function blunToolsForOrigin(tools, origin) {
|
|
264620
265213
|
if (origin.kind !== "system_trigger" && origin.kind !== "injection") return tools;
|
|
264621
265214
|
return tools.filter((tool) => !BLUN_TELEGRAM_OUTBOUND_TOOL_RE.test(tool.name));
|
|
264622
265215
|
}
|
|
264623
265216
|
/**
|
|
264624
|
-
*
|
|
264625
|
-
*
|
|
264626
|
-
*
|
|
264627
|
-
* tools were requested: a profile with no lean-set matches keeps the full set
|
|
264628
|
-
* rather than sending a tool-less task turn.
|
|
265217
|
+
* Restore bounded schema disclosure even on large-context models. Only tools
|
|
265218
|
+
* already eligible for this turn enter the loader; execution still follows
|
|
265219
|
+
* the ordinary permission pipeline.
|
|
264629
265220
|
*/
|
|
264630
|
-
function blunSelectTurnTools(tools, maxContextTokens) {
|
|
264631
|
-
if (
|
|
264632
|
-
|
|
264633
|
-
|
|
264634
|
-
|
|
265221
|
+
function blunSelectTurnTools(tools, maxContextTokens, loadedToolNames = /* @__PURE__ */ new Set(), requiredToolNames = /* @__PURE__ */ new Set(), selected = []) {
|
|
265222
|
+
if (estimateTokensForTools(tools) <= (0, import_turn_tool_performance_policy.toolSchemaBudgetTokens)(maxContextTokens) || tools.some((tool) => tool.name === "ToolSearch")) {
|
|
265223
|
+
selected.splice(0, selected.length, ...tools);
|
|
265224
|
+
return selected;
|
|
265225
|
+
}
|
|
265226
|
+
selected.splice(0, selected.length, ...tools.filter((tool) => BLUN_LEAN_TOOL_NAMES.has(tool.name) || BLUN_LEAN_KEEP_RE.test(tool.name) || BLUN_LANGUAGE_REVIEW_TOOL_NAMES.has(tool.name) || loadedToolNames.has(tool.name) || requiredToolNames.has(tool.name)));
|
|
265227
|
+
const names = new Set(selected.map((tool) => tool.name));
|
|
265228
|
+
const deferred = tools.filter((tool) => !names.has(tool.name));
|
|
265229
|
+
if (deferred.length > 0) selected.push((0, import_turn_tool_performance_policy.createDeferredToolLoader)(selected, deferred, loadedToolNames));
|
|
265230
|
+
return selected;
|
|
264635
265231
|
}
|
|
264636
265232
|
function goalContinuationOrigin(origin) {
|
|
264637
265233
|
const cronRunId = origin.kind === "cron_job" ? origin.runId : origin.kind === "system_trigger" && origin.name === "goal_continuation" ? origin.cronRunId : void 0;
|
|
@@ -264874,7 +265470,7 @@ function toolResultText(result) {
|
|
|
264874
265470
|
function abandonedToolResultOutput(ended) {
|
|
264875
265471
|
return `Tool call did not complete: ${ended.reason === "cancelled" ? "the turn was cancelled" : ended.reason === "failed" ? `the turn failed${ended.error !== void 0 ? ` (${ended.error.message})` : ""}` : "the turn ended"} before its result was recorded. Do not assume the tool completed successfully.`;
|
|
264876
265472
|
}
|
|
264877
|
-
var BLUN_LEAN_TOOL_NAMES, BLUN_LANGUAGE_REVIEW_TOOL_NAMES, BLUN_LEAN_KEEP_RE, BLUN_TELEGRAM_OUTBOUND_TOOL_RE,
|
|
265473
|
+
var import_turn_tool_performance_policy, BLUN_LEAN_TOOL_NAMES, BLUN_LANGUAGE_REVIEW_TOOL_NAMES, BLUN_LEAN_KEEP_RE, BLUN_TELEGRAM_OUTBOUND_TOOL_RE, LLM_NOT_SET_MESSAGE, GOAL_CONTINUATION_ORIGIN, GOAL_COMPLETION_REMINDER_NAME, GOAL_BLOCKED_REMINDER_NAME, GOAL_RATE_LIMIT_PAUSE_REASON, GOAL_PROVIDER_CONNECTION_PAUSE_PREFIX, GOAL_PROVIDER_AUTH_PAUSE_PREFIX, GOAL_PROVIDER_API_PAUSE_PREFIX, GOAL_MODEL_CONFIG_PAUSE_PREFIX, GOAL_RUNTIME_PAUSE_PREFIX, GOAL_PROVIDER_FILTERED_PAUSE_REASON, GOAL_CONTINUATION_PROMPT, TurnFlow;
|
|
264878
265474
|
var init_turn = __esmMin((() => {
|
|
264879
265475
|
init_dist$4();
|
|
264880
265476
|
init_src$4();
|
|
@@ -264892,14 +265488,17 @@ var init_turn = __esmMin((() => {
|
|
|
264892
265488
|
init_tool_dedup();
|
|
264893
265489
|
init_tool_result_budget();
|
|
264894
265490
|
init_response_review();
|
|
265491
|
+
import_turn_tool_performance_policy = require_turn_tool_performance_policy();
|
|
264895
265492
|
BLUN_LEAN_TOOL_NAMES = new Set([
|
|
264896
265493
|
"Read",
|
|
265494
|
+
"ReadBatch",
|
|
264897
265495
|
"Write",
|
|
264898
265496
|
"Edit",
|
|
264899
265497
|
"Grep",
|
|
264900
265498
|
"Glob",
|
|
264901
265499
|
"Bash",
|
|
264902
265500
|
"TodoList",
|
|
265501
|
+
"Skill",
|
|
264903
265502
|
"CompactConversation",
|
|
264904
265503
|
"MistakeRecord"
|
|
264905
265504
|
]);
|
|
@@ -264911,7 +265510,6 @@ var init_turn = __esmMin((() => {
|
|
|
264911
265510
|
].map((name) => qualifyMcpToolName("blun-language-guard", name)));
|
|
264912
265511
|
BLUN_LEAN_KEEP_RE = /(^|__|:)(reply|react|edit_message|download_attachment|memory_(?:status|settings_update|remember|list|threads_list|recall))$/i;
|
|
264913
265512
|
BLUN_TELEGRAM_OUTBOUND_TOOL_RE = /^mcp__[^\s]*telegram[^\s]*__(?:reply|react|edit_message)$/i;
|
|
264914
|
-
BLUN_TOOL_BUDGET_RATIO = .25;
|
|
264915
265513
|
LLM_NOT_SET_MESSAGE = "LLM not set, send \"/login\" to login";
|
|
264916
265514
|
GOAL_CONTINUATION_ORIGIN = {
|
|
264917
265515
|
kind: "system_trigger",
|
|
@@ -264954,6 +265552,8 @@ var init_turn = __esmMin((() => {
|
|
|
264954
265552
|
TurnFlow = class {
|
|
264955
265553
|
agent;
|
|
264956
265554
|
admissionClosed = false;
|
|
265555
|
+
loadedToolNames = /* @__PURE__ */ new Set();
|
|
265556
|
+
refreshSelectedTools;
|
|
264957
265557
|
executions = new ExecutionLedger();
|
|
264958
265558
|
executingControllers = /* @__PURE__ */ new Set();
|
|
264959
265559
|
steerBuffer = [];
|
|
@@ -265190,6 +265790,9 @@ var init_turn = __esmMin((() => {
|
|
|
265190
265790
|
if (snapshot.throughSequence < 0) return false;
|
|
265191
265791
|
return this.flushSteerBuffer(turnId, snapshot.throughSequence);
|
|
265192
265792
|
}
|
|
265793
|
+
refreshRequestTools(snapshot) {
|
|
265794
|
+
return this.refreshSelectedTools?.(snapshot);
|
|
265795
|
+
}
|
|
265193
265796
|
bufferSteer(input, origin, targetTurnId) {
|
|
265194
265797
|
this.steerBuffer.push({
|
|
265195
265798
|
sequence: this.nextSteerSequence,
|
|
@@ -265573,17 +266176,41 @@ var init_turn = __esmMin((() => {
|
|
|
265573
266176
|
const personalMemoryRecall = await this.agent.injection.injectPersonalMemoryForTurn(turnId, input, origin, signal);
|
|
265574
266177
|
await this.agent.injection.injectGoal();
|
|
265575
266178
|
this.setActiveSteerAcceptance(turnId, true);
|
|
265576
|
-
const turnNeedsTools = blunTurnNeedsTools(input, origin);
|
|
265577
266179
|
const turnNeedsThinking = blunTurnNeedsTools(blunThinkingIntentInput(input), origin);
|
|
266180
|
+
let toolInput = input;
|
|
266181
|
+
let taskToolsNeeded = turnNeedsThinking || blunTurnHasAttachment(input);
|
|
266182
|
+
const greetingAnchor = this.agent.context.history.findLast((message) => message.role === "user" && message.origin?.kind === "user");
|
|
266183
|
+
let partialContext = false;
|
|
266184
|
+
const turnHistory = () => {
|
|
266185
|
+
const history = personalMemoryRecall === void 0 ? this.agent.context.history : [...this.agent.context.history, personalMemoryRecall];
|
|
266186
|
+
const selected = taskToolsNeeded ? history : greetingHistory(history, greetingAnchor);
|
|
266187
|
+
partialContext = selected.length < history.length;
|
|
266188
|
+
return selected;
|
|
266189
|
+
};
|
|
265578
266190
|
const turnLLM = this.agent.llmForTurn(turnNeedsThinking ? void 0 : "off");
|
|
266191
|
+
const turnTools = this.agent.tools.captureTurnTools();
|
|
265579
266192
|
while (true) {
|
|
265580
266193
|
signal.throwIfAborted();
|
|
265581
266194
|
const model = this.agent.config.model;
|
|
265582
266195
|
const loopControl = this.agent.blunConfig?.loopControl;
|
|
265583
266196
|
let stopForGoalBudget = false;
|
|
265584
266197
|
try {
|
|
265585
|
-
const
|
|
265586
|
-
|
|
266198
|
+
const selectedTools = [];
|
|
266199
|
+
this.refreshSelectedTools = (snapshot) => {
|
|
266200
|
+
if (snapshot.messages.length > 0) toolInput = snapshot.messages.flatMap((message) => message.content);
|
|
266201
|
+
const eligibleTools = blunToolsForOrigin(this.agent.injection.filterPersonalMemoryToolsForTurn(turnId, input, origin, turnTools()), origin);
|
|
266202
|
+
const intent = blunThinkingIntentInput(toolInput);
|
|
266203
|
+
taskToolsNeeded ||= blunTurnNeedsTools(intent, origin) || blunTurnHasAttachment(toolInput);
|
|
266204
|
+
const required = (0, import_turn_tool_performance_policy.mediaToolNamesForTurnText)(blunExtractText(toolInput));
|
|
266205
|
+
if (taskToolsNeeded) {
|
|
266206
|
+
blunSelectTurnTools(eligibleTools, this.agent.config.modelCapabilities?.max_context_tokens, this.loadedToolNames, required, selectedTools);
|
|
266207
|
+
for (const name of (0, import_turn_tool_performance_policy.rankedToolNamesForTurnText)(eligibleTools, blunExtractText(intent))) {
|
|
266208
|
+
const tool = eligibleTools.find((candidate) => candidate.name === name);
|
|
266209
|
+
if (tool !== void 0 && !selectedTools.some((candidate) => candidate.name === name) && estimateTokensForTools([...selectedTools, tool]) <= (0, import_turn_tool_performance_policy.toolSchemaBudgetTokens)(this.agent.config.modelCapabilities?.max_context_tokens)) selectedTools.push(tool);
|
|
266210
|
+
}
|
|
266211
|
+
} else selectedTools.splice(0, selectedTools.length, ...eligibleTools.filter((tool) => BLUN_LANGUAGE_REVIEW_TOOL_NAMES.has(tool.name) || BLUN_TELEGRAM_OUTBOUND_TOOL_RE.test(tool.name)));
|
|
266212
|
+
return selectedTools;
|
|
266213
|
+
};
|
|
265587
266214
|
return (await runTurn({
|
|
265588
266215
|
turnId: String(turnId),
|
|
265589
266216
|
signal,
|
|
@@ -265594,15 +266221,15 @@ var init_turn = __esmMin((() => {
|
|
|
265594
266221
|
}, completion);
|
|
265595
266222
|
},
|
|
265596
266223
|
llm: turnLLM,
|
|
265597
|
-
buildMessages: () => this.agent.context.project(
|
|
265598
|
-
buildMessagesStrict: () => this.agent.context.project(
|
|
266224
|
+
buildMessages: () => this.agent.context.project(turnHistory(), { dropOrphanResults: true }),
|
|
266225
|
+
buildMessagesStrict: () => this.agent.context.project(turnHistory(), {
|
|
265599
266226
|
synthesizeMissing: true,
|
|
265600
266227
|
dropOrphanResults: true,
|
|
265601
266228
|
dedupeDuplicateToolCalls: true,
|
|
265602
266229
|
dropLeadingNonUser: true,
|
|
265603
266230
|
mergeConsecutiveAssistants: true
|
|
265604
266231
|
}),
|
|
265605
|
-
dispatchEvent: this.buildDispatchEvent(turnId, signal, onFinalResponse),
|
|
266232
|
+
dispatchEvent: this.buildDispatchEvent(turnId, signal, onFinalResponse, () => partialContext),
|
|
265606
266233
|
tools: selectedTools,
|
|
265607
266234
|
log: this.agent.log,
|
|
265608
266235
|
maxSteps: loopControl?.maxStepsPerTurn,
|
|
@@ -265719,6 +266346,8 @@ var init_turn = __esmMin((() => {
|
|
|
265719
266346
|
error
|
|
265720
266347
|
});
|
|
265721
266348
|
throw error;
|
|
266349
|
+
} finally {
|
|
266350
|
+
this.refreshSelectedTools = void 0;
|
|
265722
266351
|
}
|
|
265723
266352
|
}
|
|
265724
266353
|
}
|
|
@@ -265739,13 +266368,16 @@ var init_turn = __esmMin((() => {
|
|
|
265739
266368
|
this.agent.log.warn("failed to close abandoned tool exchange", { error });
|
|
265740
266369
|
}
|
|
265741
266370
|
}
|
|
265742
|
-
buildDispatchEvent(turnId, signal, onFinalResponse) {
|
|
266371
|
+
buildDispatchEvent(turnId, signal, onFinalResponse, usesPartialContext) {
|
|
265743
266372
|
let responseStepUuid;
|
|
265744
266373
|
let responseParts = [];
|
|
265745
266374
|
let responseHasToolCall = false;
|
|
265746
266375
|
const dispatch = createLoopEventDispatcher({
|
|
265747
266376
|
appendTranscriptRecord: async (event) => {
|
|
265748
|
-
this.agent.context.appendLoopEvent(event)
|
|
266377
|
+
this.agent.context.appendLoopEvent(event.type === "step.end" && usesPartialContext?.() ? {
|
|
266378
|
+
...event,
|
|
266379
|
+
contextCoverage: "partial"
|
|
266380
|
+
} : event);
|
|
265749
266381
|
},
|
|
265750
266382
|
emitLiveEvent: (event) => {
|
|
265751
266383
|
this.agent.cron?.observeLoopEvent(turnId, event);
|
|
@@ -268617,6 +269249,17 @@ var init_tool$1 = __esmMin((() => {
|
|
|
268617
269249
|
const names = uniq([...this.enabledTools, ...mcpNames]).toSorted((a, b) => a.localeCompare(b)).filter((name) => !(hideGoalMutationTools && (name === "SetGoalBudget" || name === "UpdateGoal")));
|
|
268618
269250
|
return (allowedTools !== void 0 && allowedTools.length > 0 ? names.filter((name) => allowedTools.includes(name)) : names).map((name) => this.userTools.get(name) ?? this.mcpTools.get(name)?.tool ?? this.builtinTools.get(name)).filter((tool) => !!tool);
|
|
268619
269251
|
}
|
|
269252
|
+
captureTurnTools() {
|
|
269253
|
+
if (this.loopToolsOverride !== void 0) {
|
|
269254
|
+
const tools = this.loopToolsOverride;
|
|
269255
|
+
return () => tools;
|
|
269256
|
+
}
|
|
269257
|
+
const fixed = this.loopTools.filter((tool) => this.mcpTools.get(tool.name)?.tool !== tool);
|
|
269258
|
+
const fixedNames = new Set(fixed.map((tool) => tool.name));
|
|
269259
|
+
const patterns = [...this.mcpAccessPatterns];
|
|
269260
|
+
const allowed = this.allowedTools === void 0 ? void 0 : new Set(this.allowedTools);
|
|
269261
|
+
return () => [...fixed, ...[...this.mcpTools.entries()].filter(([name]) => !fixedNames.has(name) && patterns.some((pattern) => import_picomatch.default.isMatch(name, pattern)) && (allowed === void 0 || allowed.has(name))).map(([, entry]) => entry.tool)].toSorted((a, b) => a.name.localeCompare(b.name));
|
|
269262
|
+
}
|
|
268620
269263
|
};
|
|
268621
269264
|
}));
|
|
268622
269265
|
//#endregion
|
|
@@ -269276,6 +269919,7 @@ var init_agent = __esmMin((() => {
|
|
|
269276
269919
|
init_records();
|
|
269277
269920
|
init_replay();
|
|
269278
269921
|
init_skill$3();
|
|
269922
|
+
init_registry();
|
|
269279
269923
|
init_swarm();
|
|
269280
269924
|
init_tool$1();
|
|
269281
269925
|
init_turn();
|
|
@@ -269476,6 +270120,12 @@ var init_agent = __esmMin((() => {
|
|
|
269476
270120
|
this.setActiveResponderModel(alias);
|
|
269477
270121
|
}, async (_candidate, params, rebuildMessages) => {
|
|
269478
270122
|
const steers = this.turn.snapshotPendingSteers();
|
|
270123
|
+
const requestTools = this.turn.refreshRequestTools(steers) ?? params.tools;
|
|
270124
|
+
params = {
|
|
270125
|
+
...params,
|
|
270126
|
+
tools: requestTools,
|
|
270127
|
+
messages: await rebuildMessages()
|
|
270128
|
+
};
|
|
269479
270129
|
let systemPrompt = this.effectiveSystemPrompt;
|
|
269480
270130
|
const compacted = await this.fullCompaction.beforeStep(params.signal, {
|
|
269481
270131
|
messages: params.messages,
|
|
@@ -269515,7 +270165,7 @@ var init_agent = __esmMin((() => {
|
|
|
269515
270165
|
capability: runtimeModel.modelCapabilities,
|
|
269516
270166
|
generate: this.generateForModel(modelAlias),
|
|
269517
270167
|
completionBudgetConfig,
|
|
269518
|
-
reportedContextTokens: () => this.context.
|
|
270168
|
+
reportedContextTokens: () => this.context.tokenCountWithPending,
|
|
269519
270169
|
idleTimeoutMs: this.blunConfig?.timeout ? this.blunConfig.timeout * 1e3 : void 0,
|
|
269520
270170
|
onMediaDropped: this.onMediaDropped,
|
|
269521
270171
|
visionReader: this.visionReader,
|
|
@@ -269536,7 +270186,8 @@ var init_agent = __esmMin((() => {
|
|
|
269536
270186
|
this.emitStatusUpdated();
|
|
269537
270187
|
}
|
|
269538
270188
|
get effectiveSystemPrompt() {
|
|
269539
|
-
const
|
|
270189
|
+
const registry = this.skills?.registry;
|
|
270190
|
+
const base = registry === void 0 ? this.config.systemPrompt : compactLegacyModelSkillListing(this.config.systemPrompt, registry);
|
|
269540
270191
|
if (this.runtimeSystemPromptAppend.length === 0) return base;
|
|
269541
270192
|
return base.length === 0 ? this.runtimeSystemPromptAppend : `${base}\n\n${this.runtimeSystemPromptAppend}`;
|
|
269542
270193
|
}
|