@bike4mind/cli 0.10.0 → 0.10.2
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/{ConfigStore-DPWN3-0c.mjs → ConfigStore-BX6XcTa1.mjs} +76 -54
- package/dist/commands/apiCommand.mjs +1 -1
- package/dist/commands/doctorCommand.mjs +1 -1
- package/dist/commands/headlessCommand.mjs +2 -2
- package/dist/commands/mcpCommand.mjs +1 -1
- package/dist/commands/updateCommand.mjs +1 -1
- package/dist/index.mjs +243 -24
- package/dist/{tools-_X4rUM4L.mjs → tools-t-9dtjjl.mjs} +408 -8979
- package/dist/{updateChecker-C3DYG0Gn.mjs → updateChecker-DdgysXM8.mjs} +1 -1
- package/package.json +10 -7
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as SessionStore, A as formatStep, B as DEFAULT_RETRY_CONFIG, C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, G as getPlanModeFilePath, H as clearFeatureModuleTools, I as generateCliTools, J as isReadOnlyTool, K as buildSystemPrompt, L as ALWAYS_DENIED_FOR_AGENTS, M as loadContextFiles, N as getApiUrl, O as McpManager, P as getEnvironmentName, Q as CommandHistoryStore, R as DEFAULT_AGENT_MODEL, S as ApiClient, T as FallbackLlmBackend, U as registerFeatureModuleTools, V as DEFAULT_THOROUGHNESS, W as setWebSocketToolExecutor, X as CustomCommandStore, Y as ReActAgent, Z as CheckpointStore, _ as createAgentDelegateTool, a as createBlockerTools, at as formatFileSize, b as createSkillTool, c as createDecisionStore, d as createFindDefinitionTool, et as OAuthClient, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, i as createBlockerStore, it as mergeCommands, j as extractCompactInstructions, k as substituteArguments, l as formatDecisionsOutput, m as createCoordinateTaskTool, n as createReviewGateTool, nt as processFileReferences, o as formatBlockersOutput, ot as searchFiles, p as createWriteTodosTool, q as buildSkillsPromptSection, r as formatReviewGatesOutput, rt as searchCommands, s as createDecisionLogTool, st as warmFileCache, t as createReviewGateStore, tt as hasFileReferences, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, x as parseAgentConfig, y as SubagentOrchestrator, z as DEFAULT_MAX_ITERATIONS } from "./tools-t-9dtjjl.mjs";
|
|
3
3
|
import { n as useCliStore, t as selectActiveBackgroundAgents } from "./store-DV5s-qni.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { a as version, t as checkForUpdate } from "./updateChecker-
|
|
4
|
+
import { Ht as validateNotebookPath$1, Vt as validateJupyterKernelName, g as ChatModels, m as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore } from "./ConfigStore-BX6XcTa1.mjs";
|
|
5
|
+
import { a as version, t as checkForUpdate } from "./updateChecker-DdgysXM8.mjs";
|
|
6
6
|
import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
7
7
|
import { Box, Static, Text, render, useApp, useInput, usePaste, useStdout } from "ink";
|
|
8
8
|
import { execSync } from "child_process";
|
|
@@ -22,6 +22,7 @@ import SelectInput from "ink-select-input";
|
|
|
22
22
|
import jwt from "jsonwebtoken";
|
|
23
23
|
import open from "open";
|
|
24
24
|
import axios, { isAxiosError } from "axios";
|
|
25
|
+
import { OllamaBackend } from "@bike4mind/llm-adapters";
|
|
25
26
|
import { get_encoding } from "tiktoken";
|
|
26
27
|
import WsWebSocket from "ws";
|
|
27
28
|
//#region src/components/StatusBar.tsx
|
|
@@ -3761,6 +3762,196 @@ Unlike agent_delegate (which uses pre-defined agents), this tool lets you compos
|
|
|
3761
3762
|
};
|
|
3762
3763
|
}
|
|
3763
3764
|
//#endregion
|
|
3765
|
+
//#region src/tools/deferredToolRegistry.ts
|
|
3766
|
+
/**
|
|
3767
|
+
* Registry of tool schemas that are NOT loaded into the model's initial tool
|
|
3768
|
+
* list. The model sees only the names (via the system prompt directory) and
|
|
3769
|
+
* must call the `tool_search` meta-tool to load schemas on demand.
|
|
3770
|
+
*
|
|
3771
|
+
* This mirrors Claude Code's deferred-tool pattern. The win is large for
|
|
3772
|
+
* heavy MCP integrations (e.g. 41 GitHub MCP tools at ~250-350 tokens of
|
|
3773
|
+
* JSONSchema each = ~10-15k tokens per turn that's now ~1-1.5k of names).
|
|
3774
|
+
*/
|
|
3775
|
+
var DeferredToolRegistry = class {
|
|
3776
|
+
constructor() {
|
|
3777
|
+
this.byName = /* @__PURE__ */ new Map();
|
|
3778
|
+
}
|
|
3779
|
+
/** Replace registry contents with the supplied tools. Idempotent. */
|
|
3780
|
+
register(tools) {
|
|
3781
|
+
this.byName.clear();
|
|
3782
|
+
for (const tool of tools) this.byName.set(tool.toolSchema.name, tool);
|
|
3783
|
+
logger.debug(`[DeferredToolRegistry] Registered ${tools.length} deferred tool(s)`);
|
|
3784
|
+
}
|
|
3785
|
+
clear() {
|
|
3786
|
+
this.byName.clear();
|
|
3787
|
+
}
|
|
3788
|
+
size() {
|
|
3789
|
+
return this.byName.size;
|
|
3790
|
+
}
|
|
3791
|
+
has(name) {
|
|
3792
|
+
return this.byName.has(name);
|
|
3793
|
+
}
|
|
3794
|
+
get(name) {
|
|
3795
|
+
return this.byName.get(name);
|
|
3796
|
+
}
|
|
3797
|
+
getAll() {
|
|
3798
|
+
return Array.from(this.byName.values());
|
|
3799
|
+
}
|
|
3800
|
+
/** Return tools whose names appear in the supplied list, in input order. */
|
|
3801
|
+
getByNames(names) {
|
|
3802
|
+
const found = [];
|
|
3803
|
+
for (const name of names) {
|
|
3804
|
+
const tool = this.byName.get(name);
|
|
3805
|
+
if (tool) found.push(tool);
|
|
3806
|
+
}
|
|
3807
|
+
return found;
|
|
3808
|
+
}
|
|
3809
|
+
/**
|
|
3810
|
+
* Rank-search deferred tools by query terms. Name matches outrank
|
|
3811
|
+
* description matches; exact substring on name wins ties.
|
|
3812
|
+
*/
|
|
3813
|
+
searchByKeywords(query, maxResults) {
|
|
3814
|
+
const terms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 0);
|
|
3815
|
+
if (terms.length === 0) return [];
|
|
3816
|
+
const scored = [];
|
|
3817
|
+
for (const tool of this.byName.values()) {
|
|
3818
|
+
const name = tool.toolSchema.name.toLowerCase();
|
|
3819
|
+
const desc = (tool.toolSchema.description || "").toLowerCase();
|
|
3820
|
+
let score = 0;
|
|
3821
|
+
for (const term of terms) {
|
|
3822
|
+
if (name.includes(term)) score += 10;
|
|
3823
|
+
if (desc.includes(term)) score += 1;
|
|
3824
|
+
}
|
|
3825
|
+
if (score > 0) scored.push({
|
|
3826
|
+
tool,
|
|
3827
|
+
score
|
|
3828
|
+
});
|
|
3829
|
+
}
|
|
3830
|
+
scored.sort((a, b) => b.score - a.score);
|
|
3831
|
+
return scored.slice(0, maxResults).map((s) => s.tool);
|
|
3832
|
+
}
|
|
3833
|
+
/** Return the directory entries used to render the system-prompt reminder. */
|
|
3834
|
+
getDirectoryNames() {
|
|
3835
|
+
return Array.from(this.byName.keys()).sort();
|
|
3836
|
+
}
|
|
3837
|
+
};
|
|
3838
|
+
const deferredToolRegistry = new DeferredToolRegistry();
|
|
3839
|
+
//#endregion
|
|
3840
|
+
//#region src/tools/toolSearchTool.ts
|
|
3841
|
+
/**
|
|
3842
|
+
* Default number of tools returned for a keyword search. Matches Claude
|
|
3843
|
+
* Code's ToolSearch convention. 5 keeps the response payload small while
|
|
3844
|
+
* surfacing enough alternatives for the model to refine its query.
|
|
3845
|
+
*/
|
|
3846
|
+
const DEFAULT_MAX_RESULTS = 5;
|
|
3847
|
+
/**
|
|
3848
|
+
* Runtime validation for tool_search params. The LLM produces these
|
|
3849
|
+
* values, so we validate at this boundary rather than trusting the
|
|
3850
|
+
* shape. Coerces `max_results` from string→number for models that emit
|
|
3851
|
+
* numeric-looking strings.
|
|
3852
|
+
*/
|
|
3853
|
+
const ToolSearchParamsSchema = z.object({
|
|
3854
|
+
query: z.string().min(1, "query must be a non-empty string"),
|
|
3855
|
+
max_results: z.coerce.number().int().min(1).max(20).optional()
|
|
3856
|
+
});
|
|
3857
|
+
/**
|
|
3858
|
+
* Parse the query string. Two forms:
|
|
3859
|
+
* - `select:name1,name2,...` — exact-name selection
|
|
3860
|
+
* - free text — keyword search across name + description
|
|
3861
|
+
*/
|
|
3862
|
+
function parseQuery(query) {
|
|
3863
|
+
const trimmed = query.trim();
|
|
3864
|
+
const selectMatch = trimmed.match(/^select:(.+)$/i);
|
|
3865
|
+
if (selectMatch) return {
|
|
3866
|
+
mode: "select",
|
|
3867
|
+
names: selectMatch[1].split(",").map((n) => n.trim()).filter((n) => n.length > 0)
|
|
3868
|
+
};
|
|
3869
|
+
return {
|
|
3870
|
+
mode: "search",
|
|
3871
|
+
text: trimmed
|
|
3872
|
+
};
|
|
3873
|
+
}
|
|
3874
|
+
/**
|
|
3875
|
+
* Format the loaded-tools response. Mirrors Claude Code's convention:
|
|
3876
|
+
* one <function>{...}</function> line per matched tool. The model has
|
|
3877
|
+
* already seen this format in its tool-registration system messages, so
|
|
3878
|
+
* it parses without additional explanation.
|
|
3879
|
+
*
|
|
3880
|
+
* Note: the schemas are *also* injected into context.tools by the caller,
|
|
3881
|
+
* so on the next iteration the model gets them as native tool definitions.
|
|
3882
|
+
* The text response here is for in-turn awareness and audit trail.
|
|
3883
|
+
*/
|
|
3884
|
+
function renderToolsBlock(tools) {
|
|
3885
|
+
if (tools.length === 0) return "";
|
|
3886
|
+
return `<functions>\n${tools.map((tool) => {
|
|
3887
|
+
const schema = {
|
|
3888
|
+
description: tool.toolSchema.description,
|
|
3889
|
+
name: tool.toolSchema.name,
|
|
3890
|
+
parameters: tool.toolSchema.parameters
|
|
3891
|
+
};
|
|
3892
|
+
return `<function>${JSON.stringify(schema)}</function>`;
|
|
3893
|
+
}).join("\n")}\n</functions>`;
|
|
3894
|
+
}
|
|
3895
|
+
/**
|
|
3896
|
+
* Build the tool_search meta-tool. The returned tool has a closure over
|
|
3897
|
+
* the supplied `toolListAccessor`, which it uses to push newly-resolved
|
|
3898
|
+
* tool schemas into the live agent context.
|
|
3899
|
+
*
|
|
3900
|
+
* Idempotent: re-loading a tool that's already in the context is a no-op.
|
|
3901
|
+
*/
|
|
3902
|
+
function createToolSearchTool(toolListAccessor) {
|
|
3903
|
+
return {
|
|
3904
|
+
toolSchema: {
|
|
3905
|
+
name: "tool_search",
|
|
3906
|
+
description: "Fetches full schema definitions for deferred tools so they can be called. Deferred tools appear by name only in a system reminder; their parameter schemas are NOT loaded by default. Use this tool to load schemas on demand. Query forms: 'select:name1,name2' for exact selection, or free-text keywords to search by name and description. Once a tool's schema is returned, it becomes callable in subsequent turns.",
|
|
3907
|
+
parameters: {
|
|
3908
|
+
type: "object",
|
|
3909
|
+
properties: {
|
|
3910
|
+
query: {
|
|
3911
|
+
type: "string",
|
|
3912
|
+
description: "Either 'select:<comma-separated names>' to fetch specific tools, or free-text keywords (e.g. 'github pull request') to rank-search deferred tools."
|
|
3913
|
+
},
|
|
3914
|
+
max_results: {
|
|
3915
|
+
type: "number",
|
|
3916
|
+
description: `Maximum number of tools to return for keyword search. Defaults to ${DEFAULT_MAX_RESULTS}. Ignored for 'select:' queries.`
|
|
3917
|
+
}
|
|
3918
|
+
},
|
|
3919
|
+
required: ["query"]
|
|
3920
|
+
}
|
|
3921
|
+
},
|
|
3922
|
+
toolFn: async (params) => {
|
|
3923
|
+
const parsedParams = ToolSearchParamsSchema.safeParse(params ?? {});
|
|
3924
|
+
if (!parsedParams.success) {
|
|
3925
|
+
const issue = parsedParams.error.issues[0];
|
|
3926
|
+
return `tool_search: invalid parameters — ${issue.path.join(".") || "params"}: ${issue.message}`;
|
|
3927
|
+
}
|
|
3928
|
+
const { query, max_results } = parsedParams.data;
|
|
3929
|
+
const parsed = parseQuery(query);
|
|
3930
|
+
let matched;
|
|
3931
|
+
let unmatched = [];
|
|
3932
|
+
if (parsed.mode === "select") {
|
|
3933
|
+
matched = deferredToolRegistry.getByNames(parsed.names);
|
|
3934
|
+
const foundNames = new Set(matched.map((t) => t.toolSchema.name));
|
|
3935
|
+
unmatched = parsed.names.filter((n) => !foundNames.has(n));
|
|
3936
|
+
} else {
|
|
3937
|
+
const max = max_results ?? DEFAULT_MAX_RESULTS;
|
|
3938
|
+
matched = deferredToolRegistry.searchByKeywords(parsed.text, max);
|
|
3939
|
+
}
|
|
3940
|
+
if (matched.length === 0) return parsed.mode === "select" ? `tool_search: no deferred tools matched ${parsed.names.join(", ")}. Use a free-text query to search.` : `tool_search: no deferred tools matched query "${parsed.text}".`;
|
|
3941
|
+
const liveTools = toolListAccessor();
|
|
3942
|
+
const liveNames = new Set(liveTools.map((t) => t.toolSchema.name));
|
|
3943
|
+
let added = 0;
|
|
3944
|
+
for (const tool of matched) if (!liveNames.has(tool.toolSchema.name)) {
|
|
3945
|
+
liveTools.push(tool);
|
|
3946
|
+
added++;
|
|
3947
|
+
}
|
|
3948
|
+
logger.debug(`[tool_search] query="${query}" matched=${matched.length} added=${added} alreadyLoaded=${matched.length - added}`);
|
|
3949
|
+
const block = renderToolsBlock(matched);
|
|
3950
|
+
return `${`Loaded ${added} new tool schema(s)${added < matched.length ? ` (${matched.length - added} already loaded)` : ""}. These are now callable in your next message.${unmatched.length > 0 ? `\n\nNot found: ${unmatched.join(", ")}` : ""}`}\n\n${block}`;
|
|
3951
|
+
}
|
|
3952
|
+
};
|
|
3953
|
+
}
|
|
3954
|
+
//#endregion
|
|
3764
3955
|
//#region src/features/FeatureModuleRegistry.ts
|
|
3765
3956
|
/**
|
|
3766
3957
|
* Manages the lifecycle of opt-in CLI feature modules.
|
|
@@ -5976,10 +6167,23 @@ function CliApp() {
|
|
|
5976
6167
|
loadContextFiles(agentProjectDir)
|
|
5977
6168
|
]);
|
|
5978
6169
|
const mcpTools = mcpManager.getTools();
|
|
6170
|
+
const deferredB4mToolNames = new Set([
|
|
6171
|
+
"math_evaluate",
|
|
6172
|
+
"dice_roll",
|
|
6173
|
+
"current_datetime",
|
|
6174
|
+
"recent_changes",
|
|
6175
|
+
"prompt_enhancement"
|
|
6176
|
+
]);
|
|
6177
|
+
const deferredB4mTools = b4mTools.filter((t) => deferredB4mToolNames.has(t.toolSchema.name));
|
|
6178
|
+
const loadedB4mTools = b4mTools.filter((t) => !deferredB4mToolNames.has(t.toolSchema.name));
|
|
6179
|
+
deferredToolRegistry.register([...mcpTools, ...deferredB4mTools]);
|
|
5979
6180
|
if (mcpTools.length > 0) {
|
|
5980
6181
|
const serverSummaries = mcpManager.getToolCount().map((s) => `${s.serverName} (${s.count})`).join(", ");
|
|
5981
|
-
startupLog.push(`🛠️ Loaded ${
|
|
5982
|
-
} else
|
|
6182
|
+
startupLog.push(`🛠️ Loaded ${loadedB4mTools.length} B4M + ${mcpTools.length} MCP tool(s, ${deferredB4mTools.length + mcpTools.length} deferred): ${serverSummaries}`);
|
|
6183
|
+
} else {
|
|
6184
|
+
const suffix = deferredB4mTools.length > 0 ? ` (${deferredB4mTools.length} deferred)` : "";
|
|
6185
|
+
startupLog.push(`🛠️ Loaded ${loadedB4mTools.length} B4M tool(s)${suffix}, no MCP tools`);
|
|
6186
|
+
}
|
|
5983
6187
|
const agentSummary = agentStore.getSummary();
|
|
5984
6188
|
startupLog.push(`🤖 Loaded ${agentSummary.total} agent(s): ${agentSummary.builtin} built-in, ${agentSummary.global} global, ${agentSummary.project} project`);
|
|
5985
6189
|
const orchestrator = new SubagentOrchestrator({
|
|
@@ -6053,9 +6257,14 @@ function CliApp() {
|
|
|
6053
6257
|
cliTools.push(coordinateTaskTool);
|
|
6054
6258
|
}
|
|
6055
6259
|
const featureTools = featureRegistry.getAllTools();
|
|
6260
|
+
const agentToolsRef = { current: null };
|
|
6261
|
+
const toolSearchTool = deferredToolRegistry.size() > 0 ? createToolSearchTool(() => {
|
|
6262
|
+
if (!agentToolsRef.current) throw new Error("tool_search invoked before agent context was wired");
|
|
6263
|
+
return agentToolsRef.current;
|
|
6264
|
+
}) : null;
|
|
6056
6265
|
const allTools = [
|
|
6057
|
-
...
|
|
6058
|
-
...
|
|
6266
|
+
...loadedB4mTools,
|
|
6267
|
+
...toolSearchTool ? [toolSearchTool] : [],
|
|
6059
6268
|
...cliTools,
|
|
6060
6269
|
...featureTools
|
|
6061
6270
|
];
|
|
@@ -6070,7 +6279,7 @@ function CliApp() {
|
|
|
6070
6279
|
const moduleNames = featureRegistry.getModuleNames().join(", ");
|
|
6071
6280
|
startupLog.push(`🏰 Feature modules: ${moduleNames} (${featureTools.length} tools)`);
|
|
6072
6281
|
}
|
|
6073
|
-
logger.debug(`Total tools available to agent: ${allTools.length} (${
|
|
6282
|
+
logger.debug(`Total tools available to agent: ${allTools.length} (${loadedB4mTools.length} B4M loaded + ${cliTools.length} CLI + ${featureTools.length} feature + ${toolSearchTool ? 1 : 0} tool_search, ${deferredB4mTools.length} B4M + ${mcpTools.length} MCP deferred)`);
|
|
6074
6283
|
if (contextResult.globalContext) startupLog.push(`📄 Global context: ${contextResult.globalContext.filename}`);
|
|
6075
6284
|
if (contextResult.projectContext) startupLog.push(`📄 Project context: ${contextResult.projectContext.filename}`);
|
|
6076
6285
|
for (const error of contextResult.errors) startupLog.push(`⚠️ Context file error: ${error}`);
|
|
@@ -6084,7 +6293,8 @@ function CliApp() {
|
|
|
6084
6293
|
enableDynamicAgentCreation: config.preferences.enableDynamicAgentCreation === true,
|
|
6085
6294
|
additionalDirectories,
|
|
6086
6295
|
featureModulePrompts: featureModulePrompts || void 0,
|
|
6087
|
-
planModeFilePath: mode === "plan" ? getPlanModeFilePath(newSession.id) : void 0
|
|
6296
|
+
planModeFilePath: mode === "plan" ? getPlanModeFilePath(newSession.id) : void 0,
|
|
6297
|
+
deferredToolNames: deferredToolRegistry.getDirectoryNames()
|
|
6088
6298
|
});
|
|
6089
6299
|
const cliSystemPrompt = buildPromptForMode(useCliStore.getState().interactionMode);
|
|
6090
6300
|
const maxIterations = config.preferences.maxIterations === null ? 999999 : config.preferences.maxIterations;
|
|
@@ -6097,16 +6307,17 @@ function CliApp() {
|
|
|
6097
6307
|
maxIterations,
|
|
6098
6308
|
maxTokens: config.preferences.maxTokens,
|
|
6099
6309
|
temperature: config.preferences.temperature,
|
|
6100
|
-
systemPrompt: cliSystemPrompt
|
|
6310
|
+
systemPrompt: cliSystemPrompt,
|
|
6311
|
+
unknownToolResolver: async (toolName) => deferredToolRegistry.get(toolName) ?? null
|
|
6101
6312
|
});
|
|
6313
|
+
agentToolsRef.current = agent.getTools();
|
|
6102
6314
|
agentContext.currentAgent = agent;
|
|
6103
|
-
const agentInternalContext = agent.context;
|
|
6104
6315
|
let lastInteractionMode = useCliStore.getState().interactionMode;
|
|
6105
6316
|
useCliStore.subscribe((s) => {
|
|
6106
6317
|
if (s.interactionMode === lastInteractionMode) return;
|
|
6107
6318
|
lastInteractionMode = s.interactionMode;
|
|
6108
6319
|
if (agentContext.currentAgent !== agent) return;
|
|
6109
|
-
|
|
6320
|
+
agent.setSystemPrompt(buildPromptForMode(s.interactionMode));
|
|
6110
6321
|
});
|
|
6111
6322
|
agent.observationQueue = agentContext.observationQueue;
|
|
6112
6323
|
const stepHandler = (step) => {
|
|
@@ -6562,7 +6773,8 @@ function CliApp() {
|
|
|
6562
6773
|
customCommands: state.customCommandStore.getAllCommands(),
|
|
6563
6774
|
enableSkillTool: config?.preferences.enableSkillTool !== false,
|
|
6564
6775
|
additionalDirectories: state.additionalDirectories,
|
|
6565
|
-
featureModulePrompts: state.featureRegistry?.getSystemPromptSections() || void 0
|
|
6776
|
+
featureModulePrompts: state.featureRegistry?.getSystemPromptSections() || void 0,
|
|
6777
|
+
deferredToolNames: deferredToolRegistry.getDirectoryNames()
|
|
6566
6778
|
});
|
|
6567
6779
|
if (tokenCounter.countSessionTokens(activeSession, systemPrompt).totalTokens >= threshold) {
|
|
6568
6780
|
console.log("\n⚠️ Context window 80% full. Auto-compacting...\n");
|
|
@@ -7753,7 +7965,7 @@ Multi-line Input:
|
|
|
7753
7965
|
const skillsTokens = skillsSection ? tokenCounter.countTokens(skillsSection) : 0;
|
|
7754
7966
|
const agentDirectoryTokens = state.agentStore ? tokenCounter.countTokens(state.agentStore.getDirectoryContext()) : 0;
|
|
7755
7967
|
const mcpTools = state.mcpManager?.getTools() || [];
|
|
7756
|
-
const
|
|
7968
|
+
const deferredNames = deferredToolRegistry.getDirectoryNames();
|
|
7757
7969
|
const mcpToolCount = state.mcpManager?.getToolCount() || [];
|
|
7758
7970
|
const systemPrompt = buildSystemPrompt(variantForCount, {
|
|
7759
7971
|
contextContent: state.contextContent,
|
|
@@ -7761,10 +7973,13 @@ Multi-line Input:
|
|
|
7761
7973
|
customCommands: commands,
|
|
7762
7974
|
enableSkillTool: state.config?.preferences.enableSkillTool !== false,
|
|
7763
7975
|
additionalDirectories: state.additionalDirectories,
|
|
7764
|
-
featureModulePrompts: state.featureRegistry?.getSystemPromptSections() || void 0
|
|
7976
|
+
featureModulePrompts: state.featureRegistry?.getSystemPromptSections() || void 0,
|
|
7977
|
+
deferredToolNames: deferredNames
|
|
7765
7978
|
});
|
|
7766
7979
|
const usage = tokenCounter.countSessionTokens(state.session, systemPrompt);
|
|
7767
|
-
const
|
|
7980
|
+
const agentTools = state.agent?.getTools() ?? [];
|
|
7981
|
+
const agentToolsTokens = tokenCounter.countToolSchemaTokens(agentTools);
|
|
7982
|
+
const totalWithTools = usage.totalTokens + agentToolsTokens;
|
|
7768
7983
|
const usagePercent = totalWithTools / contextWindow * 100;
|
|
7769
7984
|
const BAR_WIDTH = 40;
|
|
7770
7985
|
const filledWidth = Math.min(Math.round(usagePercent / 100 * BAR_WIDTH), BAR_WIDTH);
|
|
@@ -7781,10 +7996,14 @@ Multi-line Input:
|
|
|
7781
7996
|
console.log(` Agent Directory: ${agentDirectoryTokens.toLocaleString()} tokens (${agentCount} agents)`);
|
|
7782
7997
|
}
|
|
7783
7998
|
if (mcpTools.length > 0) {
|
|
7784
|
-
console.log("\nMCP Tools:");
|
|
7785
|
-
console.log(`
|
|
7999
|
+
console.log("\nMCP Tools (deferred):");
|
|
8000
|
+
console.log(` Schemas: load on demand via tool_search (${mcpTools.length} tools available)`);
|
|
7786
8001
|
for (const { serverName, count } of mcpToolCount) console.log(` ${serverName}: ${count} tools`);
|
|
7787
8002
|
}
|
|
8003
|
+
if (agentTools.length > 0) {
|
|
8004
|
+
console.log("\nLoaded Tool Schemas:");
|
|
8005
|
+
console.log(` Schemas: ${agentToolsTokens.toLocaleString()} tokens (${agentTools.length} tools active)`);
|
|
8006
|
+
}
|
|
7788
8007
|
console.log("\nConversation:");
|
|
7789
8008
|
console.log(` Messages: ${usage.messageTokens.toLocaleString()} tokens (${state.session.messages.length} messages)`);
|
|
7790
8009
|
if (usagePercent >= 80) {
|
|
@@ -8320,14 +8539,13 @@ Multi-line Input:
|
|
|
8320
8539
|
const newToolNames = newFeatureRegistry.getAllToolNames();
|
|
8321
8540
|
if (newToolNames.length > 0) registerFeatureModuleTools(newToolNames);
|
|
8322
8541
|
if (state.wsManager && newFeatureRegistry.hasModules) newFeatureRegistry.registerAllWsHandlers(state.wsManager);
|
|
8323
|
-
const agentContext = state.agent.context;
|
|
8324
8542
|
const oldFeatureToolNames = new Set(state.featureRegistry?.getAllToolNames() ?? []);
|
|
8325
|
-
const baseTools =
|
|
8543
|
+
const baseTools = state.agent.getTools().filter((t) => !oldFeatureToolNames.has(t.toolSchema.name));
|
|
8326
8544
|
const newFeatureTools = newFeatureRegistry.getAllTools();
|
|
8327
|
-
|
|
8545
|
+
state.agent.setTools([...baseTools, ...newFeatureTools]);
|
|
8328
8546
|
const newFeaturePrompts = newFeatureRegistry.getSystemPromptSections();
|
|
8329
8547
|
const planFilePathForRebuild = useCliStore.getState().interactionMode === "plan" && state.session ? getPlanModeFilePath(state.session.id) : void 0;
|
|
8330
|
-
|
|
8548
|
+
state.agent.setSystemPrompt(buildSystemPrompt(updatedConfig.preferences.promptVariant ?? "current", {
|
|
8331
8549
|
contextContent: state.contextContent,
|
|
8332
8550
|
agentStore: state.agentStore || void 0,
|
|
8333
8551
|
customCommands: state.customCommandStore.getAllCommands(),
|
|
@@ -8335,8 +8553,9 @@ Multi-line Input:
|
|
|
8335
8553
|
enableDynamicAgentCreation: updatedConfig.preferences.enableDynamicAgentCreation === true,
|
|
8336
8554
|
additionalDirectories: state.additionalDirectories,
|
|
8337
8555
|
featureModulePrompts: newFeaturePrompts || void 0,
|
|
8338
|
-
planModeFilePath: planFilePathForRebuild
|
|
8339
|
-
|
|
8556
|
+
planModeFilePath: planFilePathForRebuild,
|
|
8557
|
+
deferredToolNames: deferredToolRegistry.getDirectoryNames()
|
|
8558
|
+
}));
|
|
8340
8559
|
const moduleNames = newFeatureRegistry.getModuleNames();
|
|
8341
8560
|
if (moduleNames.length > 0) console.error(`\n\x1b[36m🏰 Feature modules hot-reloaded: ${moduleNames.join(", ")}\x1b[0m`);
|
|
8342
8561
|
else console.error(`\n\x1b[36m🏰 Feature modules disabled\x1b[0m`);
|