@bike4mind/cli 0.10.0 → 0.10.1
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-aeJGqjKm.mjs} +56 -7
- 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 +242 -24
- package/dist/{tools-_X4rUM4L.mjs → tools-RdGu37Lw.mjs} +98 -9
- package/dist/{updateChecker-C3DYG0Gn.mjs → updateChecker-CP_jeER9.mjs} +1 -1
- package/package.json +6 -6
|
@@ -1002,6 +1002,8 @@ let ApiKeyScope = /* @__PURE__ */ function(ApiKeyScope) {
|
|
|
1002
1002
|
* radius of a sprite-spawning credential, not a billable AI key. */
|
|
1003
1003
|
ApiKeyScope["CC_BRIDGE"] = "cc-bridge:connect";
|
|
1004
1004
|
ApiKeyScope["ADMIN"] = "admin:*";
|
|
1005
|
+
ApiKeyScope["MARKETING_REPORTS_READ"] = "marketing-reports:read";
|
|
1006
|
+
ApiKeyScope["MARKETING_REPORTS_WRITE"] = "marketing-reports:write";
|
|
1005
1007
|
return ApiKeyScope;
|
|
1006
1008
|
}({});
|
|
1007
1009
|
/** Valid document types that can be favorited */
|
|
@@ -3667,6 +3669,8 @@ z.enum([
|
|
|
3667
3669
|
"EnableRapidReplyDefault",
|
|
3668
3670
|
"EnableLattice",
|
|
3669
3671
|
"EnableLatticeDefault",
|
|
3672
|
+
"EnableDataLakes",
|
|
3673
|
+
"EnableDataLakesDefault",
|
|
3670
3674
|
"RapidReplySettings",
|
|
3671
3675
|
"EnableResearchEngine",
|
|
3672
3676
|
"EnableResearchEngineDefault",
|
|
@@ -5039,6 +5043,25 @@ const settingsMap = {
|
|
|
5039
5043
|
group: API_SERVICE_GROUPS.NOTEBOOK.id,
|
|
5040
5044
|
order: 1
|
|
5041
5045
|
}),
|
|
5046
|
+
EnableDataLakes: makeBooleanSetting({
|
|
5047
|
+
key: "EnableDataLakes",
|
|
5048
|
+
name: "Enable Data Lakes",
|
|
5049
|
+
defaultValue: false,
|
|
5050
|
+
description: "Server-side gate for the Data Lake capability (bulk folder ingestion). Off by default — turn on to expose the data-lake APIs and wizard.",
|
|
5051
|
+
category: "Experimental",
|
|
5052
|
+
group: API_SERVICE_GROUPS.EXPERIMENTAL.id,
|
|
5053
|
+
order: 88
|
|
5054
|
+
}),
|
|
5055
|
+
EnableDataLakesDefault: makeBooleanSetting({
|
|
5056
|
+
key: "EnableDataLakesDefault",
|
|
5057
|
+
name: "Data Lakes: On by default for users",
|
|
5058
|
+
defaultValue: false,
|
|
5059
|
+
description: "When enabled, Data Lakes is active for users who have never explicitly toggled it.",
|
|
5060
|
+
category: "Experimental",
|
|
5061
|
+
group: API_SERVICE_GROUPS.EXPERIMENTAL.id,
|
|
5062
|
+
order: 89,
|
|
5063
|
+
dependsOn: "EnableDataLakes"
|
|
5064
|
+
}),
|
|
5042
5065
|
EnableQuestMaster: makeBooleanSetting({
|
|
5043
5066
|
key: "EnableQuestMaster",
|
|
5044
5067
|
name: "Enable Quest Master",
|
|
@@ -7661,18 +7684,36 @@ z$1.object({
|
|
|
7661
7684
|
slug: z$1.string().min(2).max(60).regex(slugRegex, "Slug must be lowercase alphanumeric with hyphens (e.g. \"my-data-lake\")"),
|
|
7662
7685
|
description: z$1.string().max(2e3).optional(),
|
|
7663
7686
|
fileTagPrefix: z$1.string().min(2).max(30).refine((s) => s.endsWith(":"), "Tag prefix must end with \":\" (e.g. \"acme:\")"),
|
|
7664
|
-
requiredUserTag: z$1.string().min(1).max(100).optional()
|
|
7665
|
-
organizationId: z$1.string().optional()
|
|
7687
|
+
requiredUserTag: z$1.string().min(1).max(100).optional()
|
|
7666
7688
|
});
|
|
7667
7689
|
z$1.object({
|
|
7668
7690
|
name: z$1.string().min(1).max(200).optional(),
|
|
7669
7691
|
description: z$1.string().max(2e3).optional(),
|
|
7670
|
-
requiredUserTag: z$1.string().min(1).max(100).optional()
|
|
7671
|
-
status: z$1.enum(["active", "archived"]).optional()
|
|
7692
|
+
requiredUserTag: z$1.string().min(1).max(100).optional()
|
|
7672
7693
|
});
|
|
7673
7694
|
z$1.object({
|
|
7674
7695
|
organizationId: z$1.string().optional(),
|
|
7675
|
-
status: z$1.enum([
|
|
7696
|
+
status: z$1.enum([
|
|
7697
|
+
"draft",
|
|
7698
|
+
"active",
|
|
7699
|
+
"archived",
|
|
7700
|
+
"deleted"
|
|
7701
|
+
]).optional()
|
|
7702
|
+
});
|
|
7703
|
+
const ConflictResolutionSchema = z$1.enum([
|
|
7704
|
+
"skip",
|
|
7705
|
+
"update",
|
|
7706
|
+
"duplicate"
|
|
7707
|
+
]);
|
|
7708
|
+
z$1.object({
|
|
7709
|
+
dataLakeId: z$1.string(),
|
|
7710
|
+
totalFiles: z$1.number().positive(),
|
|
7711
|
+
totalSizeBytes: z$1.number().nonnegative(),
|
|
7712
|
+
conflictResolution: ConflictResolutionSchema.optional(),
|
|
7713
|
+
appliedTags: z$1.array(z$1.object({
|
|
7714
|
+
name: z$1.string(),
|
|
7715
|
+
strength: z$1.number()
|
|
7716
|
+
})).optional()
|
|
7676
7717
|
});
|
|
7677
7718
|
const BatchPresignedUrlFileItem = z$1.object({
|
|
7678
7719
|
fileName: z$1.string().min(1),
|
|
@@ -7687,7 +7728,13 @@ const BatchPresignedUrlFileItem = z$1.object({
|
|
|
7687
7728
|
});
|
|
7688
7729
|
z$1.object({
|
|
7689
7730
|
files: z$1.array(BatchPresignedUrlFileItem).min(1).max(100),
|
|
7690
|
-
dataLakeSlug: z$1.string().optional()
|
|
7731
|
+
dataLakeSlug: z$1.string().optional(),
|
|
7732
|
+
/**
|
|
7733
|
+
* When uploading into a data lake batch, the batch id so each created FabFile is
|
|
7734
|
+
* correlated to the batch (stamped with batchId) AND appended to the batch
|
|
7735
|
+
* manifest. Without it the pipeline can't track batch progress.
|
|
7736
|
+
*/
|
|
7737
|
+
batchId: z$1.string().optional()
|
|
7691
7738
|
});
|
|
7692
7739
|
const InferTaxonomyFolderEntry = z$1.object({
|
|
7693
7740
|
relativePath: z$1.string(),
|
|
@@ -7713,7 +7760,9 @@ const SyncDeltaFileEntry = z$1.object({
|
|
|
7713
7760
|
});
|
|
7714
7761
|
z$1.object({
|
|
7715
7762
|
dataLakeSlug: z$1.string(),
|
|
7716
|
-
currentFiles: z$1.array(SyncDeltaFileEntry).min(1).max(1e4)
|
|
7763
|
+
currentFiles: z$1.array(SyncDeltaFileEntry).min(1).max(1e4),
|
|
7764
|
+
/** Per-request dedup policy for files whose content hash already exists. Defaults to 'skip'. */
|
|
7765
|
+
conflictResolution: ConflictResolutionSchema.optional()
|
|
7717
7766
|
});
|
|
7718
7767
|
z$1.object({
|
|
7719
7768
|
dataLakeSlug: z$1.string(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as version, n as compareSemver, r as fetchLatestVersion } from "../updateChecker-
|
|
2
|
+
import { a as version, n as compareSemver, r as fetchLatestVersion } from "../updateChecker-CP_jeER9.mjs";
|
|
3
3
|
import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
|
|
4
4
|
import { execSync } from "child_process";
|
|
5
5
|
import { constants, existsSync, promises } from "fs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, I as generateCliTools, M as loadContextFiles, N as getApiUrl, O as McpManager, Q as CheckpointStore, S as ApiClient, T as FallbackLlmBackend, W as setWebSocketToolExecutor, X as ReActAgent, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createAgentDelegateTool, b as createSkillTool, d as createFindDefinitionTool, et as SessionStore, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, m as createCoordinateTaskTool, p as createWriteTodosTool, q as buildSystemPrompt, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, y as SubagentOrchestrator } from "../tools-
|
|
3
|
-
import { n as logger, t as ConfigStore } from "../ConfigStore-
|
|
2
|
+
import { C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, I as generateCliTools, M as loadContextFiles, N as getApiUrl, O as McpManager, Q as CheckpointStore, S as ApiClient, T as FallbackLlmBackend, W as setWebSocketToolExecutor, X as ReActAgent, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createAgentDelegateTool, b as createSkillTool, d as createFindDefinitionTool, et as SessionStore, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, m as createCoordinateTaskTool, p as createWriteTodosTool, q as buildSystemPrompt, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, y as SubagentOrchestrator } from "../tools-RdGu37Lw.mjs";
|
|
3
|
+
import { n as logger, t as ConfigStore } from "../ConfigStore-aeJGqjKm.mjs";
|
|
4
4
|
import { t as DEFAULT_SANDBOX_CONFIG } from "../types-LyRNHOiS.mjs";
|
|
5
5
|
import { t as createSandboxRuntime } from "../SandboxRuntimeAdapter-ChGlxSGQ.mjs";
|
|
6
6
|
import { t as SandboxOrchestrator } from "../SandboxOrchestrator-BoINxbX4.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as version, i as forceCheckForUpdate } from "../updateChecker-
|
|
2
|
+
import { a as version, i as forceCheckForUpdate } from "../updateChecker-CP_jeER9.mjs";
|
|
3
3
|
import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
|
|
4
4
|
import { execSync } from "child_process";
|
|
5
5
|
//#region src/commands/updateCommand.ts
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as CommandHistoryStore, A as formatStep, B as DEFAULT_RETRY_CONFIG, C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, G as OllamaBackend, H as clearFeatureModuleTools, I as generateCliTools, J as buildSkillsPromptSection, K as getPlanModeFilePath, L as ALWAYS_DENIED_FOR_AGENTS, M as loadContextFiles, N as getApiUrl, O as McpManager, P as getEnvironmentName, Q as CheckpointStore, R as DEFAULT_AGENT_MODEL, S as ApiClient, T as FallbackLlmBackend, U as registerFeatureModuleTools, V as DEFAULT_THOROUGHNESS, W as setWebSocketToolExecutor, X as ReActAgent, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createAgentDelegateTool, a as createBlockerTools, at as mergeCommands, b as createSkillTool, c as createDecisionStore, ct as warmFileCache, d as createFindDefinitionTool, et as SessionStore, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, i as createBlockerStore, it as searchCommands, j as extractCompactInstructions, k as substituteArguments, l as formatDecisionsOutput, m as createCoordinateTaskTool, n as createReviewGateTool, nt as hasFileReferences, o as formatBlockersOutput, ot as formatFileSize, p as createWriteTodosTool, q as buildSystemPrompt, r as formatReviewGatesOutput, rt as processFileReferences, s as createDecisionLogTool, st as searchFiles, t as createReviewGateStore, tt as OAuthClient, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, x as parseAgentConfig, y as SubagentOrchestrator, z as DEFAULT_MAX_ITERATIONS } from "./tools-
|
|
2
|
+
import { $ as CommandHistoryStore, A as formatStep, B as DEFAULT_RETRY_CONFIG, C as WebSocketToolExecutor, D as ServerLlmBackend, E as WebSocketLlmBackend, F as PermissionManager, G as OllamaBackend, H as clearFeatureModuleTools, I as generateCliTools, J as buildSkillsPromptSection, K as getPlanModeFilePath, L as ALWAYS_DENIED_FOR_AGENTS, M as loadContextFiles, N as getApiUrl, O as McpManager, P as getEnvironmentName, Q as CheckpointStore, R as DEFAULT_AGENT_MODEL, S as ApiClient, T as FallbackLlmBackend, U as registerFeatureModuleTools, V as DEFAULT_THOROUGHNESS, W as setWebSocketToolExecutor, X as ReActAgent, Y as isReadOnlyTool, Z as CustomCommandStore, _ as createAgentDelegateTool, a as createBlockerTools, at as mergeCommands, b as createSkillTool, c as createDecisionStore, ct as warmFileCache, d as createFindDefinitionTool, et as SessionStore, f as createTodoStore, g as BackgroundAgentManager, h as createBackgroundAgentTools, i as createBlockerStore, it as searchCommands, j as extractCompactInstructions, k as substituteArguments, l as formatDecisionsOutput, m as createCoordinateTaskTool, n as createReviewGateTool, nt as hasFileReferences, o as formatBlockersOutput, ot as formatFileSize, p as createWriteTodosTool, q as buildSystemPrompt, r as formatReviewGatesOutput, rt as processFileReferences, s as createDecisionLogTool, st as searchFiles, t as createReviewGateStore, tt as OAuthClient, u as createGetFileStructureTool, v as AgentStore, w as WebSocketConnectionManager, x as parseAgentConfig, y as SubagentOrchestrator, z as DEFAULT_MAX_ITERATIONS } from "./tools-RdGu37Lw.mjs";
|
|
3
3
|
import { n as useCliStore, t as selectActiveBackgroundAgents } from "./store-DV5s-qni.mjs";
|
|
4
|
-
import { Xt as validateNotebookPath$1, Yt as validateJupyterKernelName, g as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore, v as ChatModels } from "./ConfigStore-
|
|
5
|
-
import { a as version, t as checkForUpdate } from "./updateChecker-
|
|
4
|
+
import { Xt as validateNotebookPath$1, Yt as validateJupyterKernelName, g as CREDIT_DEDUCT_TRANSACTION_TYPES, n as logger, t as ConfigStore, v as ChatModels } from "./ConfigStore-aeJGqjKm.mjs";
|
|
5
|
+
import { a as version, t as checkForUpdate } from "./updateChecker-CP_jeER9.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";
|
|
@@ -3761,6 +3761,196 @@ Unlike agent_delegate (which uses pre-defined agents), this tool lets you compos
|
|
|
3761
3761
|
};
|
|
3762
3762
|
}
|
|
3763
3763
|
//#endregion
|
|
3764
|
+
//#region src/tools/deferredToolRegistry.ts
|
|
3765
|
+
/**
|
|
3766
|
+
* Registry of tool schemas that are NOT loaded into the model's initial tool
|
|
3767
|
+
* list. The model sees only the names (via the system prompt directory) and
|
|
3768
|
+
* must call the `tool_search` meta-tool to load schemas on demand.
|
|
3769
|
+
*
|
|
3770
|
+
* This mirrors Claude Code's deferred-tool pattern. The win is large for
|
|
3771
|
+
* heavy MCP integrations (e.g. 41 GitHub MCP tools at ~250-350 tokens of
|
|
3772
|
+
* JSONSchema each = ~10-15k tokens per turn that's now ~1-1.5k of names).
|
|
3773
|
+
*/
|
|
3774
|
+
var DeferredToolRegistry = class {
|
|
3775
|
+
constructor() {
|
|
3776
|
+
this.byName = /* @__PURE__ */ new Map();
|
|
3777
|
+
}
|
|
3778
|
+
/** Replace registry contents with the supplied tools. Idempotent. */
|
|
3779
|
+
register(tools) {
|
|
3780
|
+
this.byName.clear();
|
|
3781
|
+
for (const tool of tools) this.byName.set(tool.toolSchema.name, tool);
|
|
3782
|
+
logger.debug(`[DeferredToolRegistry] Registered ${tools.length} deferred tool(s)`);
|
|
3783
|
+
}
|
|
3784
|
+
clear() {
|
|
3785
|
+
this.byName.clear();
|
|
3786
|
+
}
|
|
3787
|
+
size() {
|
|
3788
|
+
return this.byName.size;
|
|
3789
|
+
}
|
|
3790
|
+
has(name) {
|
|
3791
|
+
return this.byName.has(name);
|
|
3792
|
+
}
|
|
3793
|
+
get(name) {
|
|
3794
|
+
return this.byName.get(name);
|
|
3795
|
+
}
|
|
3796
|
+
getAll() {
|
|
3797
|
+
return Array.from(this.byName.values());
|
|
3798
|
+
}
|
|
3799
|
+
/** Return tools whose names appear in the supplied list, in input order. */
|
|
3800
|
+
getByNames(names) {
|
|
3801
|
+
const found = [];
|
|
3802
|
+
for (const name of names) {
|
|
3803
|
+
const tool = this.byName.get(name);
|
|
3804
|
+
if (tool) found.push(tool);
|
|
3805
|
+
}
|
|
3806
|
+
return found;
|
|
3807
|
+
}
|
|
3808
|
+
/**
|
|
3809
|
+
* Rank-search deferred tools by query terms. Name matches outrank
|
|
3810
|
+
* description matches; exact substring on name wins ties.
|
|
3811
|
+
*/
|
|
3812
|
+
searchByKeywords(query, maxResults) {
|
|
3813
|
+
const terms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 0);
|
|
3814
|
+
if (terms.length === 0) return [];
|
|
3815
|
+
const scored = [];
|
|
3816
|
+
for (const tool of this.byName.values()) {
|
|
3817
|
+
const name = tool.toolSchema.name.toLowerCase();
|
|
3818
|
+
const desc = (tool.toolSchema.description || "").toLowerCase();
|
|
3819
|
+
let score = 0;
|
|
3820
|
+
for (const term of terms) {
|
|
3821
|
+
if (name.includes(term)) score += 10;
|
|
3822
|
+
if (desc.includes(term)) score += 1;
|
|
3823
|
+
}
|
|
3824
|
+
if (score > 0) scored.push({
|
|
3825
|
+
tool,
|
|
3826
|
+
score
|
|
3827
|
+
});
|
|
3828
|
+
}
|
|
3829
|
+
scored.sort((a, b) => b.score - a.score);
|
|
3830
|
+
return scored.slice(0, maxResults).map((s) => s.tool);
|
|
3831
|
+
}
|
|
3832
|
+
/** Return the directory entries used to render the system-prompt reminder. */
|
|
3833
|
+
getDirectoryNames() {
|
|
3834
|
+
return Array.from(this.byName.keys()).sort();
|
|
3835
|
+
}
|
|
3836
|
+
};
|
|
3837
|
+
const deferredToolRegistry = new DeferredToolRegistry();
|
|
3838
|
+
//#endregion
|
|
3839
|
+
//#region src/tools/toolSearchTool.ts
|
|
3840
|
+
/**
|
|
3841
|
+
* Default number of tools returned for a keyword search. Matches Claude
|
|
3842
|
+
* Code's ToolSearch convention. 5 keeps the response payload small while
|
|
3843
|
+
* surfacing enough alternatives for the model to refine its query.
|
|
3844
|
+
*/
|
|
3845
|
+
const DEFAULT_MAX_RESULTS = 5;
|
|
3846
|
+
/**
|
|
3847
|
+
* Runtime validation for tool_search params. The LLM produces these
|
|
3848
|
+
* values, so we validate at this boundary rather than trusting the
|
|
3849
|
+
* shape. Coerces `max_results` from string→number for models that emit
|
|
3850
|
+
* numeric-looking strings.
|
|
3851
|
+
*/
|
|
3852
|
+
const ToolSearchParamsSchema = z.object({
|
|
3853
|
+
query: z.string().min(1, "query must be a non-empty string"),
|
|
3854
|
+
max_results: z.coerce.number().int().min(1).max(20).optional()
|
|
3855
|
+
});
|
|
3856
|
+
/**
|
|
3857
|
+
* Parse the query string. Two forms:
|
|
3858
|
+
* - `select:name1,name2,...` — exact-name selection
|
|
3859
|
+
* - free text — keyword search across name + description
|
|
3860
|
+
*/
|
|
3861
|
+
function parseQuery(query) {
|
|
3862
|
+
const trimmed = query.trim();
|
|
3863
|
+
const selectMatch = trimmed.match(/^select:(.+)$/i);
|
|
3864
|
+
if (selectMatch) return {
|
|
3865
|
+
mode: "select",
|
|
3866
|
+
names: selectMatch[1].split(",").map((n) => n.trim()).filter((n) => n.length > 0)
|
|
3867
|
+
};
|
|
3868
|
+
return {
|
|
3869
|
+
mode: "search",
|
|
3870
|
+
text: trimmed
|
|
3871
|
+
};
|
|
3872
|
+
}
|
|
3873
|
+
/**
|
|
3874
|
+
* Format the loaded-tools response. Mirrors Claude Code's convention:
|
|
3875
|
+
* one <function>{...}</function> line per matched tool. The model has
|
|
3876
|
+
* already seen this format in its tool-registration system messages, so
|
|
3877
|
+
* it parses without additional explanation.
|
|
3878
|
+
*
|
|
3879
|
+
* Note: the schemas are *also* injected into context.tools by the caller,
|
|
3880
|
+
* so on the next iteration the model gets them as native tool definitions.
|
|
3881
|
+
* The text response here is for in-turn awareness and audit trail.
|
|
3882
|
+
*/
|
|
3883
|
+
function renderToolsBlock(tools) {
|
|
3884
|
+
if (tools.length === 0) return "";
|
|
3885
|
+
return `<functions>\n${tools.map((tool) => {
|
|
3886
|
+
const schema = {
|
|
3887
|
+
description: tool.toolSchema.description,
|
|
3888
|
+
name: tool.toolSchema.name,
|
|
3889
|
+
parameters: tool.toolSchema.parameters
|
|
3890
|
+
};
|
|
3891
|
+
return `<function>${JSON.stringify(schema)}</function>`;
|
|
3892
|
+
}).join("\n")}\n</functions>`;
|
|
3893
|
+
}
|
|
3894
|
+
/**
|
|
3895
|
+
* Build the tool_search meta-tool. The returned tool has a closure over
|
|
3896
|
+
* the supplied `toolListAccessor`, which it uses to push newly-resolved
|
|
3897
|
+
* tool schemas into the live agent context.
|
|
3898
|
+
*
|
|
3899
|
+
* Idempotent: re-loading a tool that's already in the context is a no-op.
|
|
3900
|
+
*/
|
|
3901
|
+
function createToolSearchTool(toolListAccessor) {
|
|
3902
|
+
return {
|
|
3903
|
+
toolSchema: {
|
|
3904
|
+
name: "tool_search",
|
|
3905
|
+
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.",
|
|
3906
|
+
parameters: {
|
|
3907
|
+
type: "object",
|
|
3908
|
+
properties: {
|
|
3909
|
+
query: {
|
|
3910
|
+
type: "string",
|
|
3911
|
+
description: "Either 'select:<comma-separated names>' to fetch specific tools, or free-text keywords (e.g. 'github pull request') to rank-search deferred tools."
|
|
3912
|
+
},
|
|
3913
|
+
max_results: {
|
|
3914
|
+
type: "number",
|
|
3915
|
+
description: `Maximum number of tools to return for keyword search. Defaults to ${DEFAULT_MAX_RESULTS}. Ignored for 'select:' queries.`
|
|
3916
|
+
}
|
|
3917
|
+
},
|
|
3918
|
+
required: ["query"]
|
|
3919
|
+
}
|
|
3920
|
+
},
|
|
3921
|
+
toolFn: async (params) => {
|
|
3922
|
+
const parsedParams = ToolSearchParamsSchema.safeParse(params ?? {});
|
|
3923
|
+
if (!parsedParams.success) {
|
|
3924
|
+
const issue = parsedParams.error.issues[0];
|
|
3925
|
+
return `tool_search: invalid parameters — ${issue.path.join(".") || "params"}: ${issue.message}`;
|
|
3926
|
+
}
|
|
3927
|
+
const { query, max_results } = parsedParams.data;
|
|
3928
|
+
const parsed = parseQuery(query);
|
|
3929
|
+
let matched;
|
|
3930
|
+
let unmatched = [];
|
|
3931
|
+
if (parsed.mode === "select") {
|
|
3932
|
+
matched = deferredToolRegistry.getByNames(parsed.names);
|
|
3933
|
+
const foundNames = new Set(matched.map((t) => t.toolSchema.name));
|
|
3934
|
+
unmatched = parsed.names.filter((n) => !foundNames.has(n));
|
|
3935
|
+
} else {
|
|
3936
|
+
const max = max_results ?? DEFAULT_MAX_RESULTS;
|
|
3937
|
+
matched = deferredToolRegistry.searchByKeywords(parsed.text, max);
|
|
3938
|
+
}
|
|
3939
|
+
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}".`;
|
|
3940
|
+
const liveTools = toolListAccessor();
|
|
3941
|
+
const liveNames = new Set(liveTools.map((t) => t.toolSchema.name));
|
|
3942
|
+
let added = 0;
|
|
3943
|
+
for (const tool of matched) if (!liveNames.has(tool.toolSchema.name)) {
|
|
3944
|
+
liveTools.push(tool);
|
|
3945
|
+
added++;
|
|
3946
|
+
}
|
|
3947
|
+
logger.debug(`[tool_search] query="${query}" matched=${matched.length} added=${added} alreadyLoaded=${matched.length - added}`);
|
|
3948
|
+
const block = renderToolsBlock(matched);
|
|
3949
|
+
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}`;
|
|
3950
|
+
}
|
|
3951
|
+
};
|
|
3952
|
+
}
|
|
3953
|
+
//#endregion
|
|
3764
3954
|
//#region src/features/FeatureModuleRegistry.ts
|
|
3765
3955
|
/**
|
|
3766
3956
|
* Manages the lifecycle of opt-in CLI feature modules.
|
|
@@ -5976,10 +6166,23 @@ function CliApp() {
|
|
|
5976
6166
|
loadContextFiles(agentProjectDir)
|
|
5977
6167
|
]);
|
|
5978
6168
|
const mcpTools = mcpManager.getTools();
|
|
6169
|
+
const deferredB4mToolNames = new Set([
|
|
6170
|
+
"math_evaluate",
|
|
6171
|
+
"dice_roll",
|
|
6172
|
+
"current_datetime",
|
|
6173
|
+
"recent_changes",
|
|
6174
|
+
"prompt_enhancement"
|
|
6175
|
+
]);
|
|
6176
|
+
const deferredB4mTools = b4mTools.filter((t) => deferredB4mToolNames.has(t.toolSchema.name));
|
|
6177
|
+
const loadedB4mTools = b4mTools.filter((t) => !deferredB4mToolNames.has(t.toolSchema.name));
|
|
6178
|
+
deferredToolRegistry.register([...mcpTools, ...deferredB4mTools]);
|
|
5979
6179
|
if (mcpTools.length > 0) {
|
|
5980
6180
|
const serverSummaries = mcpManager.getToolCount().map((s) => `${s.serverName} (${s.count})`).join(", ");
|
|
5981
|
-
startupLog.push(`🛠️ Loaded ${
|
|
5982
|
-
} else
|
|
6181
|
+
startupLog.push(`🛠️ Loaded ${loadedB4mTools.length} B4M + ${mcpTools.length} MCP tool(s, ${deferredB4mTools.length + mcpTools.length} deferred): ${serverSummaries}`);
|
|
6182
|
+
} else {
|
|
6183
|
+
const suffix = deferredB4mTools.length > 0 ? ` (${deferredB4mTools.length} deferred)` : "";
|
|
6184
|
+
startupLog.push(`🛠️ Loaded ${loadedB4mTools.length} B4M tool(s)${suffix}, no MCP tools`);
|
|
6185
|
+
}
|
|
5983
6186
|
const agentSummary = agentStore.getSummary();
|
|
5984
6187
|
startupLog.push(`🤖 Loaded ${agentSummary.total} agent(s): ${agentSummary.builtin} built-in, ${agentSummary.global} global, ${agentSummary.project} project`);
|
|
5985
6188
|
const orchestrator = new SubagentOrchestrator({
|
|
@@ -6053,9 +6256,14 @@ function CliApp() {
|
|
|
6053
6256
|
cliTools.push(coordinateTaskTool);
|
|
6054
6257
|
}
|
|
6055
6258
|
const featureTools = featureRegistry.getAllTools();
|
|
6259
|
+
const agentToolsRef = { current: null };
|
|
6260
|
+
const toolSearchTool = deferredToolRegistry.size() > 0 ? createToolSearchTool(() => {
|
|
6261
|
+
if (!agentToolsRef.current) throw new Error("tool_search invoked before agent context was wired");
|
|
6262
|
+
return agentToolsRef.current;
|
|
6263
|
+
}) : null;
|
|
6056
6264
|
const allTools = [
|
|
6057
|
-
...
|
|
6058
|
-
...
|
|
6265
|
+
...loadedB4mTools,
|
|
6266
|
+
...toolSearchTool ? [toolSearchTool] : [],
|
|
6059
6267
|
...cliTools,
|
|
6060
6268
|
...featureTools
|
|
6061
6269
|
];
|
|
@@ -6070,7 +6278,7 @@ function CliApp() {
|
|
|
6070
6278
|
const moduleNames = featureRegistry.getModuleNames().join(", ");
|
|
6071
6279
|
startupLog.push(`🏰 Feature modules: ${moduleNames} (${featureTools.length} tools)`);
|
|
6072
6280
|
}
|
|
6073
|
-
logger.debug(`Total tools available to agent: ${allTools.length} (${
|
|
6281
|
+
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
6282
|
if (contextResult.globalContext) startupLog.push(`📄 Global context: ${contextResult.globalContext.filename}`);
|
|
6075
6283
|
if (contextResult.projectContext) startupLog.push(`📄 Project context: ${contextResult.projectContext.filename}`);
|
|
6076
6284
|
for (const error of contextResult.errors) startupLog.push(`⚠️ Context file error: ${error}`);
|
|
@@ -6084,7 +6292,8 @@ function CliApp() {
|
|
|
6084
6292
|
enableDynamicAgentCreation: config.preferences.enableDynamicAgentCreation === true,
|
|
6085
6293
|
additionalDirectories,
|
|
6086
6294
|
featureModulePrompts: featureModulePrompts || void 0,
|
|
6087
|
-
planModeFilePath: mode === "plan" ? getPlanModeFilePath(newSession.id) : void 0
|
|
6295
|
+
planModeFilePath: mode === "plan" ? getPlanModeFilePath(newSession.id) : void 0,
|
|
6296
|
+
deferredToolNames: deferredToolRegistry.getDirectoryNames()
|
|
6088
6297
|
});
|
|
6089
6298
|
const cliSystemPrompt = buildPromptForMode(useCliStore.getState().interactionMode);
|
|
6090
6299
|
const maxIterations = config.preferences.maxIterations === null ? 999999 : config.preferences.maxIterations;
|
|
@@ -6097,16 +6306,17 @@ function CliApp() {
|
|
|
6097
6306
|
maxIterations,
|
|
6098
6307
|
maxTokens: config.preferences.maxTokens,
|
|
6099
6308
|
temperature: config.preferences.temperature,
|
|
6100
|
-
systemPrompt: cliSystemPrompt
|
|
6309
|
+
systemPrompt: cliSystemPrompt,
|
|
6310
|
+
unknownToolResolver: async (toolName) => deferredToolRegistry.get(toolName) ?? null
|
|
6101
6311
|
});
|
|
6312
|
+
agentToolsRef.current = agent.getTools();
|
|
6102
6313
|
agentContext.currentAgent = agent;
|
|
6103
|
-
const agentInternalContext = agent.context;
|
|
6104
6314
|
let lastInteractionMode = useCliStore.getState().interactionMode;
|
|
6105
6315
|
useCliStore.subscribe((s) => {
|
|
6106
6316
|
if (s.interactionMode === lastInteractionMode) return;
|
|
6107
6317
|
lastInteractionMode = s.interactionMode;
|
|
6108
6318
|
if (agentContext.currentAgent !== agent) return;
|
|
6109
|
-
|
|
6319
|
+
agent.setSystemPrompt(buildPromptForMode(s.interactionMode));
|
|
6110
6320
|
});
|
|
6111
6321
|
agent.observationQueue = agentContext.observationQueue;
|
|
6112
6322
|
const stepHandler = (step) => {
|
|
@@ -6562,7 +6772,8 @@ function CliApp() {
|
|
|
6562
6772
|
customCommands: state.customCommandStore.getAllCommands(),
|
|
6563
6773
|
enableSkillTool: config?.preferences.enableSkillTool !== false,
|
|
6564
6774
|
additionalDirectories: state.additionalDirectories,
|
|
6565
|
-
featureModulePrompts: state.featureRegistry?.getSystemPromptSections() || void 0
|
|
6775
|
+
featureModulePrompts: state.featureRegistry?.getSystemPromptSections() || void 0,
|
|
6776
|
+
deferredToolNames: deferredToolRegistry.getDirectoryNames()
|
|
6566
6777
|
});
|
|
6567
6778
|
if (tokenCounter.countSessionTokens(activeSession, systemPrompt).totalTokens >= threshold) {
|
|
6568
6779
|
console.log("\n⚠️ Context window 80% full. Auto-compacting...\n");
|
|
@@ -7753,7 +7964,7 @@ Multi-line Input:
|
|
|
7753
7964
|
const skillsTokens = skillsSection ? tokenCounter.countTokens(skillsSection) : 0;
|
|
7754
7965
|
const agentDirectoryTokens = state.agentStore ? tokenCounter.countTokens(state.agentStore.getDirectoryContext()) : 0;
|
|
7755
7966
|
const mcpTools = state.mcpManager?.getTools() || [];
|
|
7756
|
-
const
|
|
7967
|
+
const deferredNames = deferredToolRegistry.getDirectoryNames();
|
|
7757
7968
|
const mcpToolCount = state.mcpManager?.getToolCount() || [];
|
|
7758
7969
|
const systemPrompt = buildSystemPrompt(variantForCount, {
|
|
7759
7970
|
contextContent: state.contextContent,
|
|
@@ -7761,10 +7972,13 @@ Multi-line Input:
|
|
|
7761
7972
|
customCommands: commands,
|
|
7762
7973
|
enableSkillTool: state.config?.preferences.enableSkillTool !== false,
|
|
7763
7974
|
additionalDirectories: state.additionalDirectories,
|
|
7764
|
-
featureModulePrompts: state.featureRegistry?.getSystemPromptSections() || void 0
|
|
7975
|
+
featureModulePrompts: state.featureRegistry?.getSystemPromptSections() || void 0,
|
|
7976
|
+
deferredToolNames: deferredNames
|
|
7765
7977
|
});
|
|
7766
7978
|
const usage = tokenCounter.countSessionTokens(state.session, systemPrompt);
|
|
7767
|
-
const
|
|
7979
|
+
const agentTools = state.agent?.getTools() ?? [];
|
|
7980
|
+
const agentToolsTokens = tokenCounter.countToolSchemaTokens(agentTools);
|
|
7981
|
+
const totalWithTools = usage.totalTokens + agentToolsTokens;
|
|
7768
7982
|
const usagePercent = totalWithTools / contextWindow * 100;
|
|
7769
7983
|
const BAR_WIDTH = 40;
|
|
7770
7984
|
const filledWidth = Math.min(Math.round(usagePercent / 100 * BAR_WIDTH), BAR_WIDTH);
|
|
@@ -7781,10 +7995,14 @@ Multi-line Input:
|
|
|
7781
7995
|
console.log(` Agent Directory: ${agentDirectoryTokens.toLocaleString()} tokens (${agentCount} agents)`);
|
|
7782
7996
|
}
|
|
7783
7997
|
if (mcpTools.length > 0) {
|
|
7784
|
-
console.log("\nMCP Tools:");
|
|
7785
|
-
console.log(`
|
|
7998
|
+
console.log("\nMCP Tools (deferred):");
|
|
7999
|
+
console.log(` Schemas: load on demand via tool_search (${mcpTools.length} tools available)`);
|
|
7786
8000
|
for (const { serverName, count } of mcpToolCount) console.log(` ${serverName}: ${count} tools`);
|
|
7787
8001
|
}
|
|
8002
|
+
if (agentTools.length > 0) {
|
|
8003
|
+
console.log("\nLoaded Tool Schemas:");
|
|
8004
|
+
console.log(` Schemas: ${agentToolsTokens.toLocaleString()} tokens (${agentTools.length} tools active)`);
|
|
8005
|
+
}
|
|
7788
8006
|
console.log("\nConversation:");
|
|
7789
8007
|
console.log(` Messages: ${usage.messageTokens.toLocaleString()} tokens (${state.session.messages.length} messages)`);
|
|
7790
8008
|
if (usagePercent >= 80) {
|
|
@@ -8320,14 +8538,13 @@ Multi-line Input:
|
|
|
8320
8538
|
const newToolNames = newFeatureRegistry.getAllToolNames();
|
|
8321
8539
|
if (newToolNames.length > 0) registerFeatureModuleTools(newToolNames);
|
|
8322
8540
|
if (state.wsManager && newFeatureRegistry.hasModules) newFeatureRegistry.registerAllWsHandlers(state.wsManager);
|
|
8323
|
-
const agentContext = state.agent.context;
|
|
8324
8541
|
const oldFeatureToolNames = new Set(state.featureRegistry?.getAllToolNames() ?? []);
|
|
8325
|
-
const baseTools =
|
|
8542
|
+
const baseTools = state.agent.getTools().filter((t) => !oldFeatureToolNames.has(t.toolSchema.name));
|
|
8326
8543
|
const newFeatureTools = newFeatureRegistry.getAllTools();
|
|
8327
|
-
|
|
8544
|
+
state.agent.setTools([...baseTools, ...newFeatureTools]);
|
|
8328
8545
|
const newFeaturePrompts = newFeatureRegistry.getSystemPromptSections();
|
|
8329
8546
|
const planFilePathForRebuild = useCliStore.getState().interactionMode === "plan" && state.session ? getPlanModeFilePath(state.session.id) : void 0;
|
|
8330
|
-
|
|
8547
|
+
state.agent.setSystemPrompt(buildSystemPrompt(updatedConfig.preferences.promptVariant ?? "current", {
|
|
8331
8548
|
contextContent: state.contextContent,
|
|
8332
8549
|
agentStore: state.agentStore || void 0,
|
|
8333
8550
|
customCommands: state.customCommandStore.getAllCommands(),
|
|
@@ -8335,8 +8552,9 @@ Multi-line Input:
|
|
|
8335
8552
|
enableDynamicAgentCreation: updatedConfig.preferences.enableDynamicAgentCreation === true,
|
|
8336
8553
|
additionalDirectories: state.additionalDirectories,
|
|
8337
8554
|
featureModulePrompts: newFeaturePrompts || void 0,
|
|
8338
|
-
planModeFilePath: planFilePathForRebuild
|
|
8339
|
-
|
|
8555
|
+
planModeFilePath: planFilePathForRebuild,
|
|
8556
|
+
deferredToolNames: deferredToolRegistry.getDirectoryNames()
|
|
8557
|
+
}));
|
|
8340
8558
|
const moduleNames = newFeatureRegistry.getModuleNames();
|
|
8341
8559
|
if (moduleNames.length > 0) console.error(`\n\x1b[36m🏰 Feature modules hot-reloaded: ${moduleNames.join(", ")}\x1b[0m`);
|
|
8342
8560
|
else console.error(`\n\x1b[36m🏰 Feature modules disabled\x1b[0m`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as PermissionDeniedError, $t as isNearLimit, A as GEMINI_IMAGE_MODELS, At as VideoGenerationUsageTransaction, B as InternalServerError, Bt as isGPTImage2Model, C as ElabsEvents, Ct as TooManyRequestsError, D as FileEvents, Dt as UnauthorizedError, E as FeedbackEvents, Et as UiNavigationEvents, F as HttpStatus, Ft as dayjsConfig_default, G as MiscEvents, Gt as resolveNavigationIntents, H as InviteType, Ht as isModelDeprecated, I as ImageEditUsageTransaction, It as getAccessibleDataLakes, J as NO_TEMPERATURE_MODELS, Jt as settingsMap, K as ModalEvents, Kt as sanitizeTelemetryError, L as ImageGenerationUsageTransaction, Lt as getDataLakeTags, M as GenericCreditAddTransaction, Mt as VoyageAIEmbeddingModel, N as GenericCreditDeductTransaction, Nt as XAI_IMAGE_MODELS, O as ForbiddenError, Ot as UnprocessableEntityError, P as HTTPError, Pt as b4mLLMTools, Q as Permission, Qt as extractSnippetMeta, R as ImageModels, Rt as getMcpProviderMetadata, S as DashboardParamsSchema, St as TextGenerationUsageTransaction, T as FavoriteDocumentType, Tt as TransferCreditTransaction, U as KnowledgeType, Ut as isZodError, V as InviteEvents, Vt as isGPTImageModel, W as LLMEvents, Wt as obfuscateApiKey, X as OpenAIEmbeddingModel, Y as NotFoundError, Z as OpenAIImageGenerationInput, Zt as buildRateLimitLogEntry, _ as ChatCompletionCreateInputSchema, _t as SpeechToTextUsageTransaction, a as ApiKeyEvents, at as QuestMasterParamsSchema, b as CompletionApiUsageTransaction, bt as TagType, c as AppFileEvents, ct as ReceivedCreditTransaction, d as BEDROCK_NO_PROMPT_CACHING_MODELS, dt as ResearchModeParamsSchema, en as parseRateLimitHeaders, et as ProfileEvents, f as BFL_IMAGE_MODELS, ft as ResearchTaskExecutionType, gt as SpeechToTextModels, h as BedrockEmbeddingModel, ht as SessionEvents, i as AiEvents, it as PurchaseTransaction, j as GenerateImageToolCallSchema, jt as VideoModels, k as FriendshipEvents, kt as VIDEO_SIZE_CONSTRAINTS, l as ArtifactTypeSchema, lt as RechartsChartTypeList, m as BadRequestError, mt as ResearchTaskType, n as logger, nt as PromptIntentSchema, o as ApiKeyScope, ot as REASONING_SUPPORTED_MODELS, p as BFL_SAFETY_TOLERANCE, pt as ResearchTaskPeriodicFrequencyType, q as ModelBackend, qt as secureParameters, r as ALERT_THRESHOLDS, rt as PromptMetaZodSchema, s as ApiKeyType, st as RealtimeVoiceUsageTransaction, t as ConfigStore, tn as CollectionType, tt as ProjectEvents, u as AuthEvents, ut as RegInviteEvents, v as ChatModels, vt as SubscriptionCreditTransaction, w as FIXED_TEMPERATURE_MODELS, wt as ToolUsageTransaction, x as CorruptedFileError, xt as TaskScheduleHandler, y as ClaudeArtifactMimeTypes, yt as SupportedFabFileMimeTypes, z as InboxEvents, zt as getViewById } from "./ConfigStore-
|
|
2
|
+
import { $ as PermissionDeniedError, $t as isNearLimit, A as GEMINI_IMAGE_MODELS, At as VideoGenerationUsageTransaction, B as InternalServerError, Bt as isGPTImage2Model, C as ElabsEvents, Ct as TooManyRequestsError, D as FileEvents, Dt as UnauthorizedError, E as FeedbackEvents, Et as UiNavigationEvents, F as HttpStatus, Ft as dayjsConfig_default, G as MiscEvents, Gt as resolveNavigationIntents, H as InviteType, Ht as isModelDeprecated, I as ImageEditUsageTransaction, It as getAccessibleDataLakes, J as NO_TEMPERATURE_MODELS, Jt as settingsMap, K as ModalEvents, Kt as sanitizeTelemetryError, L as ImageGenerationUsageTransaction, Lt as getDataLakeTags, M as GenericCreditAddTransaction, Mt as VoyageAIEmbeddingModel, N as GenericCreditDeductTransaction, Nt as XAI_IMAGE_MODELS, O as ForbiddenError, Ot as UnprocessableEntityError, P as HTTPError, Pt as b4mLLMTools, Q as Permission, Qt as extractSnippetMeta, R as ImageModels, Rt as getMcpProviderMetadata, S as DashboardParamsSchema, St as TextGenerationUsageTransaction, T as FavoriteDocumentType, Tt as TransferCreditTransaction, U as KnowledgeType, Ut as isZodError, V as InviteEvents, Vt as isGPTImageModel, W as LLMEvents, Wt as obfuscateApiKey, X as OpenAIEmbeddingModel, Y as NotFoundError, Z as OpenAIImageGenerationInput, Zt as buildRateLimitLogEntry, _ as ChatCompletionCreateInputSchema, _t as SpeechToTextUsageTransaction, a as ApiKeyEvents, at as QuestMasterParamsSchema, b as CompletionApiUsageTransaction, bt as TagType, c as AppFileEvents, ct as ReceivedCreditTransaction, d as BEDROCK_NO_PROMPT_CACHING_MODELS, dt as ResearchModeParamsSchema, en as parseRateLimitHeaders, et as ProfileEvents, f as BFL_IMAGE_MODELS, ft as ResearchTaskExecutionType, gt as SpeechToTextModels, h as BedrockEmbeddingModel, ht as SessionEvents, i as AiEvents, it as PurchaseTransaction, j as GenerateImageToolCallSchema, jt as VideoModels, k as FriendshipEvents, kt as VIDEO_SIZE_CONSTRAINTS, l as ArtifactTypeSchema, lt as RechartsChartTypeList, m as BadRequestError, mt as ResearchTaskType, n as logger, nt as PromptIntentSchema, o as ApiKeyScope, ot as REASONING_SUPPORTED_MODELS, p as BFL_SAFETY_TOLERANCE, pt as ResearchTaskPeriodicFrequencyType, q as ModelBackend, qt as secureParameters, r as ALERT_THRESHOLDS, rt as PromptMetaZodSchema, s as ApiKeyType, st as RealtimeVoiceUsageTransaction, t as ConfigStore, tn as CollectionType, tt as ProjectEvents, u as AuthEvents, ut as RegInviteEvents, v as ChatModels, vt as SubscriptionCreditTransaction, w as FIXED_TEMPERATURE_MODELS, wt as ToolUsageTransaction, x as CorruptedFileError, xt as TaskScheduleHandler, y as ClaudeArtifactMimeTypes, yt as SupportedFabFileMimeTypes, z as InboxEvents, zt as getViewById } from "./ConfigStore-aeJGqjKm.mjs";
|
|
3
3
|
import { a as isUserLockedOut, c as userCanDisableMFA, d as userRequiresMFA, f as verifyBackupCode, i as getLockoutTimeRemaining, l as userEligibleForMFA, n as generateBackupCodes, o as recordFailedAttempt, p as verifyTOTPToken, r as generateTOTPSetup, s as shouldResetFailedAttempts, t as clearFailedAttempts, u as userHasMFAConfigured } from "./utils-PpNti-tY.mjs";
|
|
4
4
|
import { n as isPathAllowed, t as assertPathAllowed } from "./pathValidation-D8tjkQXE-1HwvsuYT.mjs";
|
|
5
5
|
import { execFile, execFileSync, spawn } from "child_process";
|
|
@@ -1945,6 +1945,35 @@ var ReActAgent = class extends EventEmitter {
|
|
|
1945
1945
|
};
|
|
1946
1946
|
}
|
|
1947
1947
|
/**
|
|
1948
|
+
* Return the live tools array used by this agent. Mutations (push/splice)
|
|
1949
|
+
* are reflected in subsequent ReAct iterations because the array is read
|
|
1950
|
+
* each turn at the top of the loop. Intended for hosts that load tool
|
|
1951
|
+
* schemas lazily (see `unknownToolResolver` and the CLI's tool_search
|
|
1952
|
+
* meta-tool). Prefer this over reaching into `agent.context.tools` via a
|
|
1953
|
+
* type cast.
|
|
1954
|
+
*/
|
|
1955
|
+
getTools() {
|
|
1956
|
+
return this.context.tools;
|
|
1957
|
+
}
|
|
1958
|
+
/**
|
|
1959
|
+
* Replace the live tools array. Used by hosts that need to swap the
|
|
1960
|
+
* tool set wholesale (e.g. hot-reload of feature module tools). Prefer
|
|
1961
|
+
* `getTools()` + array mutation for incremental additions — replacing
|
|
1962
|
+
* the reference invalidates any closures that captured the previous
|
|
1963
|
+
* array (e.g. `createToolSearchTool`'s `toolListAccessor`).
|
|
1964
|
+
*/
|
|
1965
|
+
setTools(tools) {
|
|
1966
|
+
this.context.tools = tools;
|
|
1967
|
+
}
|
|
1968
|
+
/**
|
|
1969
|
+
* Update the system prompt. Used to hot-swap prompts when the user
|
|
1970
|
+
* cycles interaction modes (e.g. into plan mode) or when feature
|
|
1971
|
+
* modules reload.
|
|
1972
|
+
*/
|
|
1973
|
+
setSystemPrompt(systemPrompt) {
|
|
1974
|
+
this.context.systemPrompt = systemPrompt;
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1948
1977
|
* Run the agent to completion
|
|
1949
1978
|
*
|
|
1950
1979
|
* @param query - The user's question or task (can be text or multimodal content with images)
|
|
@@ -2826,7 +2855,20 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
|
|
|
2826
2855
|
return typeof result === "string" ? result : JSON.stringify(result);
|
|
2827
2856
|
}
|
|
2828
2857
|
const tool = this.context.tools.find((t) => t.toolSchema.name === toolUse.name);
|
|
2829
|
-
if (!tool)
|
|
2858
|
+
if (!tool) {
|
|
2859
|
+
if (this.context.unknownToolResolver) {
|
|
2860
|
+
const resolved = await this.context.unknownToolResolver(toolUse.name);
|
|
2861
|
+
if (resolved) {
|
|
2862
|
+
this.context.tools.push(resolved);
|
|
2863
|
+
return `Tool '${toolUse.name}' was deferred and its schema is now loaded. The previous call was made without the schema visible — please re-issue the call with valid parameters per the schema below.\n\n<function>${JSON.stringify({
|
|
2864
|
+
description: resolved.toolSchema.description,
|
|
2865
|
+
name: resolved.toolSchema.name,
|
|
2866
|
+
parameters: resolved.toolSchema.parameters
|
|
2867
|
+
})}</function>`;
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
return `Error: Tool ${toolUse.name} not found in agent context`;
|
|
2871
|
+
}
|
|
2830
2872
|
try {
|
|
2831
2873
|
const params = this.parseToolArguments(toolUse.arguments);
|
|
2832
2874
|
const result = await tool.toolFn(params);
|
|
@@ -3253,6 +3295,28 @@ const TOOL_WRITE_TODOS = "write_todos";
|
|
|
3253
3295
|
const TOOL_CREATE_DYNAMIC_AGENT = "create_dynamic_agent";
|
|
3254
3296
|
const EXPLORE_SUBAGENT_TYPE = "explore";
|
|
3255
3297
|
/**
|
|
3298
|
+
* Render the deferred-tool directory: names only, no descriptions.
|
|
3299
|
+
* Following Claude Code's pattern, MCP tools have self-describing names
|
|
3300
|
+
* (e.g. mcp__github__create_pull_request) that the model parses without
|
|
3301
|
+
* needing extra text. The model can also call `tool_search` with free-text
|
|
3302
|
+
* keywords for non-obvious names.
|
|
3303
|
+
*/
|
|
3304
|
+
function buildDeferredToolDirectory(names) {
|
|
3305
|
+
if (names.length === 0) return "";
|
|
3306
|
+
const sorted = [...names].sort();
|
|
3307
|
+
return `
|
|
3308
|
+
|
|
3309
|
+
## Deferred tool schemas
|
|
3310
|
+
|
|
3311
|
+
The following ${sorted.length} tool(s) are available but their parameter schemas are NOT loaded by default to save context. Calling them directly will fail with "Tool not found". Use the \`tool_search\` tool to load schemas on demand:
|
|
3312
|
+
- Exact selection: \`tool_search(query="select:<name>[,<name>...]")\`
|
|
3313
|
+
- Keyword search: \`tool_search(query="<free text>")\`
|
|
3314
|
+
|
|
3315
|
+
Once a tool's schema is loaded, it becomes callable in subsequent turns. Deferred tool names:
|
|
3316
|
+
|
|
3317
|
+
${sorted.join("\n")}`;
|
|
3318
|
+
}
|
|
3319
|
+
/**
|
|
3256
3320
|
* Plan-mode section: tells the model that write tools are blocked and where to put the plan.
|
|
3257
3321
|
* Appended dynamically when the user cycles into plan mode via Shift+Tab.
|
|
3258
3322
|
*
|
|
@@ -3343,6 +3407,7 @@ function buildCoreSystemPrompt(contextSection, config) {
|
|
|
3343
3407
|
let directoriesSection = "";
|
|
3344
3408
|
let featureModulesSection = "";
|
|
3345
3409
|
let planModeSection = "";
|
|
3410
|
+
let deferredToolSection = "";
|
|
3346
3411
|
if (typeof contextSection === "string") {
|
|
3347
3412
|
projectContextSection = contextSection;
|
|
3348
3413
|
if (config) {
|
|
@@ -3351,6 +3416,7 @@ function buildCoreSystemPrompt(contextSection, config) {
|
|
|
3351
3416
|
if (config.enableDynamicAgentCreation) dynamicAgentSection = buildDynamicAgentPromptSection();
|
|
3352
3417
|
if (config.featureModulePrompts) featureModulesSection = config.featureModulePrompts;
|
|
3353
3418
|
if (config.planModeFilePath) planModeSection = buildPlanModePromptSection(config.planModeFilePath);
|
|
3419
|
+
if (config.deferredToolNames && config.deferredToolNames.length > 0) deferredToolSection = buildDeferredToolDirectory(config.deferredToolNames);
|
|
3354
3420
|
}
|
|
3355
3421
|
} else if (contextSection && typeof contextSection === "object") {
|
|
3356
3422
|
config = contextSection;
|
|
@@ -3361,6 +3427,7 @@ function buildCoreSystemPrompt(contextSection, config) {
|
|
|
3361
3427
|
if (config.additionalDirectories && config.additionalDirectories.length > 0) directoriesSection = `\n\n## Additional Allowed Directories\n\nIn addition to the working directory (${process.cwd()}), you have read/write access to these directories:\n${config.additionalDirectories.map((d) => `- ${d}`).join("\n")}\n\nTo access files in additional directories, pass the full path to the 'dir_path' parameter of file tools:\n- ${TOOL_GREP_SEARCH}(pattern="...", dir_path="/path/to/additional/dir")\n- ${TOOL_GLOB_FILES}(pattern="**/*.ts", dir_path="/path/to/additional/dir")\n- ${TOOL_FILE_READ}(path="/path/to/additional/dir/file.ts")\n\nWhen the user asks about content in an additional directory, search there first using the dir_path parameter.`;
|
|
3362
3428
|
if (config.featureModulePrompts) featureModulesSection = config.featureModulePrompts;
|
|
3363
3429
|
if (config.planModeFilePath) planModeSection = buildPlanModePromptSection(config.planModeFilePath);
|
|
3430
|
+
if (config.deferredToolNames && config.deferredToolNames.length > 0) deferredToolSection = buildDeferredToolDirectory(config.deferredToolNames);
|
|
3364
3431
|
}
|
|
3365
3432
|
return `You are an autonomous AI assistant with access to tools. Your job is to help users by taking action and solving problems proactively.
|
|
3366
3433
|
|
|
@@ -3478,7 +3545,7 @@ These tools are lightweight — use them naturally as part of your work, not as
|
|
|
3478
3545
|
|
|
3479
3546
|
## Working Directory
|
|
3480
3547
|
|
|
3481
|
-
The current working directory is \`${process.cwd()}\`. All relative paths in tool calls resolve from here. When using \`${TOOL_GLOB_FILES}\` or \`${TOOL_GREP_SEARCH}\` without an explicit \`dir_path\`, they search from this directory.${directoriesSection}${projectContextSection}${skillsSection}${featureModulesSection}${planModeSection}`;
|
|
3548
|
+
The current working directory is \`${process.cwd()}\`. All relative paths in tool calls resolve from here. When using \`${TOOL_GLOB_FILES}\` or \`${TOOL_GREP_SEARCH}\` without an explicit \`dir_path\`, they search from this directory.${directoriesSection}${projectContextSection}${skillsSection}${featureModulesSection}${planModeSection}${deferredToolSection}`;
|
|
3482
3549
|
}
|
|
3483
3550
|
/**
|
|
3484
3551
|
* Build the minimal-variant system prompt. Reuses the project context,
|
|
@@ -3492,11 +3559,13 @@ function buildMinimalSystemPrompt(config = {}) {
|
|
|
3492
3559
|
let directoriesSection = "";
|
|
3493
3560
|
let featureModulesSection = "";
|
|
3494
3561
|
let planModeSection = "";
|
|
3562
|
+
let deferredToolSection = "";
|
|
3495
3563
|
if (config.contextContent) projectContextSection = `\n\n## Project Context\n\nFollow these project-specific instructions:\n\n${config.contextContent}`;
|
|
3496
3564
|
if (config.enableSkillTool !== false && config.customCommands && config.customCommands.length > 0) skillsSection = buildSkillsPromptSection(config.customCommands);
|
|
3497
3565
|
if (config.additionalDirectories && config.additionalDirectories.length > 0) directoriesSection = `\n\n## Additional Allowed Directories\n\nIn addition to the working directory (${process.cwd()}), you have read/write access to these directories:\n${config.additionalDirectories.map((d) => `- ${d}`).join("\n")}\n\nPass full paths to file tools' \`dir_path\` parameter to access these directories.`;
|
|
3498
3566
|
if (config.featureModulePrompts) featureModulesSection = config.featureModulePrompts;
|
|
3499
3567
|
if (config.planModeFilePath) planModeSection = buildPlanModePromptSection(config.planModeFilePath);
|
|
3568
|
+
if (config.deferredToolNames && config.deferredToolNames.length > 0) deferredToolSection = buildDeferredToolDirectory(config.deferredToolNames);
|
|
3500
3569
|
return `You are an expert coding assistant. You help users by reading files, executing commands, editing code, and writing new files using the tools available to you.
|
|
3501
3570
|
|
|
3502
3571
|
Guidelines:
|
|
@@ -3506,7 +3575,7 @@ Guidelines:
|
|
|
3506
3575
|
|
|
3507
3576
|
## Working Directory
|
|
3508
3577
|
|
|
3509
|
-
The current working directory is \`${process.cwd()}\`. All relative paths in tool calls resolve from here. When using \`${TOOL_GLOB_FILES}\` or \`${TOOL_GREP_SEARCH}\` without an explicit \`dir_path\`, they search from this directory.${directoriesSection}${projectContextSection}${skillsSection}${featureModulesSection}${planModeSection}`;
|
|
3578
|
+
The current working directory is \`${process.cwd()}\`. All relative paths in tool calls resolve from here. When using \`${TOOL_GLOB_FILES}\` or \`${TOOL_GREP_SEARCH}\` without an explicit \`dir_path\`, they search from this directory.${directoriesSection}${projectContextSection}${skillsSection}${featureModulesSection}${planModeSection}${deferredToolSection}`;
|
|
3510
3579
|
}
|
|
3511
3580
|
/**
|
|
3512
3581
|
* Pick a system prompt by variant. The dispatch point for the
|
|
@@ -16332,13 +16401,12 @@ var BFLImageService = class extends AIImageService {
|
|
|
16332
16401
|
throw pollError;
|
|
16333
16402
|
}
|
|
16334
16403
|
const elapsedSeconds = Math.round((Date.now() - startTime) / 1e3);
|
|
16335
|
-
const timeoutError = `Image generation is taking longer than expected (timed out after ${elapsedSeconds}s). The image may still be processing on BFL's servers. Request ID: ${requestId}`;
|
|
16336
16404
|
console.error(`[DEBUG] ❌ Polling timeout:`, {
|
|
16337
16405
|
requestId,
|
|
16338
16406
|
maxAttempts,
|
|
16339
16407
|
totalTime: `${elapsedSeconds}s`
|
|
16340
16408
|
});
|
|
16341
|
-
throw new Error(
|
|
16409
|
+
throw new Error("Image generation is taking longer than usual and your request could not be completed. Please try again in a few minutes.");
|
|
16342
16410
|
}
|
|
16343
16411
|
};
|
|
16344
16412
|
var XAIImageService = class extends AIImageService {
|
|
@@ -18449,7 +18517,10 @@ const webFetchTool = {
|
|
|
18449
18517
|
if (error instanceof FirecrawlError && [
|
|
18450
18518
|
400,
|
|
18451
18519
|
403,
|
|
18452
|
-
408
|
|
18520
|
+
408,
|
|
18521
|
+
502,
|
|
18522
|
+
503,
|
|
18523
|
+
504
|
|
18453
18524
|
].includes(error.statusCode)) {
|
|
18454
18525
|
const { userMessage, statusLabel } = {
|
|
18455
18526
|
400: {
|
|
@@ -18463,6 +18534,18 @@ const webFetchTool = {
|
|
|
18463
18534
|
408: {
|
|
18464
18535
|
userMessage: `The page timed out before loading completely — the site may be slow or require heavy JavaScript rendering. Try using web_search to find the information instead.`,
|
|
18465
18536
|
statusLabel: "scrape timed out"
|
|
18537
|
+
},
|
|
18538
|
+
502: {
|
|
18539
|
+
userMessage: `The website returned a Bad Gateway error — it may be temporarily unavailable. Try again later or use web_search to find the information instead.`,
|
|
18540
|
+
statusLabel: "bad gateway"
|
|
18541
|
+
},
|
|
18542
|
+
503: {
|
|
18543
|
+
userMessage: `The website is temporarily unavailable (Service Unavailable). Try again later or use web_search to find the information instead.`,
|
|
18544
|
+
statusLabel: "service unavailable"
|
|
18545
|
+
},
|
|
18546
|
+
504: {
|
|
18547
|
+
userMessage: `The website took too long to respond (Gateway Timeout). Try again later or use web_search to find the information instead.`,
|
|
18548
|
+
statusLabel: "gateway timeout"
|
|
18466
18549
|
}
|
|
18467
18550
|
}[error.statusCode];
|
|
18468
18551
|
context.logger.warn("WebFetch expected Firecrawl failure", {
|
|
@@ -20651,7 +20734,7 @@ No markdown, no explanation, no code blocks — just the raw JSON object.`;
|
|
|
20651
20734
|
"Minimize: sum(error^2)"
|
|
20652
20735
|
].join("\n");
|
|
20653
20736
|
//#endregion
|
|
20654
|
-
//#region ../../b4m-core/services/dist/tools-
|
|
20737
|
+
//#region ../../b4m-core/services/dist/tools-DtGzruvF.mjs
|
|
20655
20738
|
async function performDeepResearch(context, params, config) {
|
|
20656
20739
|
const maxDepth = config.maxDepth || 7;
|
|
20657
20740
|
const duration = config.duration || 4.5;
|
|
@@ -21463,6 +21546,11 @@ async function evaluateMath(params) {
|
|
|
21463
21546
|
} catch (error) {
|
|
21464
21547
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
21465
21548
|
console.error(`❌ Math Tool: Evaluation error for expression "${params.expression}":`, errorMessage);
|
|
21549
|
+
const undefinedSymbol = errorMessage.match(/Undefined symbol (\w+)/);
|
|
21550
|
+
if (undefinedSymbol) {
|
|
21551
|
+
const symbol = undefinedSymbol[1];
|
|
21552
|
+
return `Error: Failed to evaluate math expression "${params.expression}". Reason: the symbol "${symbol}" is used but never assigned a value. Assign it first with a semicolon-separated statement (e.g. "${symbol} = <value>; ...") before referencing it, then try again.`;
|
|
21553
|
+
}
|
|
21466
21554
|
return `Error: Failed to evaluate math expression "${params.expression}". Reason: ${errorMessage}. Please provide a valid mathematical expression using numbers and operators only (no natural language).`;
|
|
21467
21555
|
}
|
|
21468
21556
|
}
|
|
@@ -24269,7 +24357,7 @@ const knowledgeBaseRetrieveTool = {
|
|
|
24269
24357
|
if (ownedFile) files = [ownedFile];
|
|
24270
24358
|
else {
|
|
24271
24359
|
const sharedFile = await context.db.fabfiles.findById(file_id);
|
|
24272
|
-
if (sharedFile && !sharedFile.deletedAt) {
|
|
24360
|
+
if (sharedFile && !sharedFile.deletedAt && !sharedFile.archivedAt) {
|
|
24273
24361
|
const { dataLakeTags, dataLakeTagPrefixes } = await getDynamicDataLakeAccess(context);
|
|
24274
24362
|
const fileTags = sharedFile.tags?.map((t) => t.name) || [];
|
|
24275
24363
|
const hasMetaTagAccess = dataLakeTags.some((dlt) => fileTags.includes(dlt));
|
|
@@ -27975,6 +28063,7 @@ z.object({
|
|
|
27975
28063
|
embargoDetected: z.boolean().prefault(false),
|
|
27976
28064
|
suggestedTags: z.array(z.string()).prefault([])
|
|
27977
28065
|
});
|
|
28066
|
+
ImageModels.GPT_IMAGE_1, ImageModels.GPT_IMAGE_1_5, ImageModels.GPT_IMAGE_1_MINI, ImageModels.GPT_IMAGE_2;
|
|
27978
28067
|
/**
|
|
27979
28068
|
* Regex patterns for extracting GitHub entities from text
|
|
27980
28069
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -121,11 +121,11 @@
|
|
|
121
121
|
"tsx": "^4.22.3",
|
|
122
122
|
"typescript": "^5.9.3",
|
|
123
123
|
"vitest": "^4.1.7",
|
|
124
|
-
"@bike4mind/agents": "0.11.
|
|
125
|
-
"@bike4mind/common": "2.
|
|
126
|
-
"@bike4mind/mcp": "1.37.
|
|
127
|
-
"@bike4mind/services": "2.90.
|
|
128
|
-
"@bike4mind/utils": "2.23.
|
|
124
|
+
"@bike4mind/agents": "0.11.3",
|
|
125
|
+
"@bike4mind/common": "2.103.0",
|
|
126
|
+
"@bike4mind/mcp": "1.37.17",
|
|
127
|
+
"@bike4mind/services": "2.90.3",
|
|
128
|
+
"@bike4mind/utils": "2.23.5"
|
|
129
129
|
},
|
|
130
130
|
"optionalDependencies": {
|
|
131
131
|
"@vscode/ripgrep": "^1.18.0"
|