@bike4mind/cli 1.2.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/{AgentHistoryStore-B2NEOvSW.mjs → AgentHistoryStore-DIMzvf-y.mjs} +460 -274
- package/dist/{ApiClient-D0fQ2FT6.mjs → ApiClient-BTI0-m0g.mjs} +44 -5
- package/dist/{ConfigStore-qV7NrCgZ.mjs → ConfigStore-DIs-K9oD.mjs} +3205 -1078
- package/dist/{buildAgent-C-C-VGff.mjs → buildAgent-DOvEp92a.mjs} +115 -10
- package/dist/commands/acpCommand.mjs +5 -4
- package/dist/commands/apiCommand.mjs +1 -1
- package/dist/commands/doctorCommand.mjs +1 -1
- package/dist/commands/envCommand.mjs +1 -1
- package/dist/commands/headlessCommand.mjs +4 -3
- package/dist/commands/mcpCommand.mjs +3 -3
- package/dist/commands/pluginCommand.mjs +1 -1
- package/dist/commands/updateCommand.mjs +1 -1
- package/dist/index.mjs +522 -34
- package/dist/{package-CGZIoxcs.mjs → package-Dl_F2Fah.mjs} +1 -1
- package/dist/{serve-CPXqcEZr.mjs → serve-Y2zMbfGs.mjs} +237 -73
- package/package.json +11 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { I as generateCliTools, J as setWebSocketToolExecutor, L as wrapTools, N as ReActAgent, X as buildSystemPrompt, Y as getPlanModeFilePath, a as loadProjectContext, c as createSseBackend, i as buildProjectAgentStore, it as Logger, l as ServerLlmBackend, n as BackgroundAgentManager, o as McpManager, r as SubagentOrchestrator, t as AgentHistoryStore } from "./AgentHistoryStore-
|
|
3
|
-
import {
|
|
2
|
+
import { I as generateCliTools, J as setWebSocketToolExecutor, L as wrapTools, N as ReActAgent, X as buildSystemPrompt, Y as getPlanModeFilePath, a as loadProjectContext, c as createSseBackend, i as buildProjectAgentStore, it as Logger, l as ServerLlmBackend, n as BackgroundAgentManager, o as McpManager, r as SubagentOrchestrator, t as AgentHistoryStore } from "./AgentHistoryStore-DIMzvf-y.mjs";
|
|
3
|
+
import { $ as hasDeliverablePinnedArtifact, C as ARTIFACT_REMOVED_PLACEHOLDER, E as CONTEXT_WINDOW_SAFETY_BUFFER_TOKENS, J as filterToolArtifactMarkup, K as createThinkMarkerEscaper, M as MODEL_INFO_FIELD_GROUP_OF, O as ChatModels, P as ModelBackend, S as ARTIFACT_DELIVERED_PLACEHOLDER, Z as getQuestErrorCode, ct as stripDeliveredArtifactBlocks, lt as stripToolArtifactMarkup, n as logger, q as escapeThinkMarkers, rt as isUserInitiatedAbort, z as PermissionDeniedError } from "./ConfigStore-DIs-K9oD.mjs";
|
|
4
4
|
import "crypto";
|
|
5
5
|
import { v4 } from "uuid";
|
|
6
6
|
import { z as z$1 } from "zod";
|
|
@@ -135,6 +135,96 @@ function attachFullToolResult(entry, observation) {
|
|
|
135
135
|
writable: true
|
|
136
136
|
});
|
|
137
137
|
}
|
|
138
|
+
/** The `artifactType` the named tool declared at registration, for the helpers below. */
|
|
139
|
+
function declaredArtifactType(tools, toolName) {
|
|
140
|
+
return tools?.find((t) => t.toolSchema.name === toolName)?.artifactType;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Helper function to handle tool result streaming for artifact-generating tools
|
|
144
|
+
* This ensures tools like recharts that generate artifacts are streamed immediately
|
|
145
|
+
* rather than waiting for recursive completion calls.
|
|
146
|
+
*
|
|
147
|
+
* Only the emitters in TOOL_ARTIFACT_EMITTERS (or a tool that declared `artifactType`, see
|
|
148
|
+
* declaredArtifactType) stream, and only their pinned artifact type: streamed text is parsed
|
|
149
|
+
* into reply artifacts, so any other tool's markup would render.
|
|
150
|
+
*
|
|
151
|
+
* What does stream is still a raw tool artifact rather than reply prose, so `streamCallback`
|
|
152
|
+
* receives the channel tag and a public surface drops the text on that tag alone.
|
|
153
|
+
*/
|
|
154
|
+
async function handleToolResultStreaming(toolName, toolResult, streamCallback, artifactType) {
|
|
155
|
+
const filtered = filterToolArtifactMarkup(toolName, String(toolResult), artifactType);
|
|
156
|
+
if (filtered !== null) await streamCallback([filtered], { channel: "tool-artifact" });
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Strips artifact markup from a tool result before it re-enters history, so the model cannot echo
|
|
160
|
+
* it into a second card. Live-emitting backends pass `delivered` = whether their tool-artifact
|
|
161
|
+
* emit fired. The `hasDeliverablePinnedArtifact` fallback is for the OpenAI Responses path, whose
|
|
162
|
+
* artifact reaches the client through sharedToolBuilder extraction instead.
|
|
163
|
+
*
|
|
164
|
+
* The delivered/removed choice is made once per result and stamped on every block it contains.
|
|
165
|
+
* That holds because each emitter emits one pinned block; a result mixing a foreign-type block
|
|
166
|
+
* with a pinned one would label both DELIVERED.
|
|
167
|
+
*/
|
|
168
|
+
function stripUnstreamedToolResult(toolName, result, delivered) {
|
|
169
|
+
return stripToolArtifactMarkup(result, delivered ?? hasDeliverablePinnedArtifact(toolName, result) ? ARTIFACT_DELIVERED_PLACEHOLDER : ARTIFACT_REMOVED_PLACEHOLDER);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Buffers a recursive completion's text instead of streaming it live, so an <artifact> tag the
|
|
173
|
+
* model echoes back (after seeing its own tool result, even sanitized) can be stripped before the
|
|
174
|
+
* client ever renders a second, empty card for it. Only removes blocks whose `identifier` matches
|
|
175
|
+
* one already delivered this turn (stripDeliveredArtifactBlocks) - a stray "<artifact" the model's
|
|
176
|
+
* prose merely mentions, or a genuinely NEW artifact the model composes with a different
|
|
177
|
+
* identifier, must not cost the rest of a legitimate reply, unlike the tool-output-facing
|
|
178
|
+
* stripToolArtifactMarkup.
|
|
179
|
+
*
|
|
180
|
+
* One instance is created lazily by whichever level first streams an artifact in a recursive
|
|
181
|
+
* chain, and reused UNCHANGED by every deeper level (never recreated per level) - see each
|
|
182
|
+
* backend's `_internal.artifactGuard`. A chained tool call's artifact goes through `emitArtifact`
|
|
183
|
+
* on this same shared instance, which flushes any text already buffered ahead of it before
|
|
184
|
+
* sending the artifact through - so ordering survives even when the chained call happens several
|
|
185
|
+
* recursion levels below where the guard was created.
|
|
186
|
+
*/
|
|
187
|
+
function createRecursiveArtifactGuard(cb) {
|
|
188
|
+
let buffer = "";
|
|
189
|
+
let deliveredMarkup = "";
|
|
190
|
+
let meta = {};
|
|
191
|
+
const callback = (async (text, info) => {
|
|
192
|
+
for (const chunk of text) if (chunk != null) buffer += chunk;
|
|
193
|
+
if (info?.inputTokens || info?.outputTokens) meta = { ...info };
|
|
194
|
+
});
|
|
195
|
+
const emitArtifact = async (results, info) => {
|
|
196
|
+
if (buffer) {
|
|
197
|
+
const pending = buffer;
|
|
198
|
+
buffer = "";
|
|
199
|
+
const stripped = stripDeliveredArtifactBlocks(pending, deliveredMarkup);
|
|
200
|
+
if (stripped.trim()) await cb([stripped], {});
|
|
201
|
+
}
|
|
202
|
+
deliveredMarkup += results.join("");
|
|
203
|
+
await cb(results, info);
|
|
204
|
+
};
|
|
205
|
+
const markDelivered = (markup) => {
|
|
206
|
+
deliveredMarkup += markup;
|
|
207
|
+
};
|
|
208
|
+
let flushPromise = null;
|
|
209
|
+
const flush = () => {
|
|
210
|
+
if (flushPromise) return flushPromise;
|
|
211
|
+
const cleaned = stripDeliveredArtifactBlocks(buffer, deliveredMarkup).trim();
|
|
212
|
+
let resolve;
|
|
213
|
+
let reject;
|
|
214
|
+
flushPromise = new Promise((res, rej) => {
|
|
215
|
+
resolve = res;
|
|
216
|
+
reject = rej;
|
|
217
|
+
});
|
|
218
|
+
(async () => cb(cleaned ? [cleaned] : [], meta))().then(() => resolve(), reject);
|
|
219
|
+
return flushPromise;
|
|
220
|
+
};
|
|
221
|
+
return {
|
|
222
|
+
callback,
|
|
223
|
+
emitArtifact,
|
|
224
|
+
markDelivered,
|
|
225
|
+
flush
|
|
226
|
+
};
|
|
227
|
+
}
|
|
138
228
|
/**
|
|
139
229
|
* Drops the messages whose instructions assume a tool is attached (see `IMessage.requiresTool`).
|
|
140
230
|
*
|
|
@@ -850,20 +940,32 @@ var OllamaBackend = class OllamaBackend {
|
|
|
850
940
|
parallel: options.parallelToolExecution !== false,
|
|
851
941
|
maxConcurrency: options.maxParallelTools
|
|
852
942
|
});
|
|
943
|
+
const inheritedArtifactGuard = options._internal?.artifactGuard;
|
|
944
|
+
let artifactGuard = inheritedArtifactGuard;
|
|
853
945
|
const observations = [];
|
|
854
|
-
outcomes.
|
|
946
|
+
for (let i = 0; i < outcomes.length; i++) {
|
|
947
|
+
const outcome = outcomes[i];
|
|
855
948
|
const { tc } = resolved[i];
|
|
856
949
|
const params = tc.arguments || "{}";
|
|
857
950
|
if (outcome.ok) {
|
|
858
|
-
|
|
951
|
+
let emitted = false;
|
|
952
|
+
await handleToolResultStreaming(tc.name, outcome.result, async (results, artifactInfo) => {
|
|
953
|
+
emitted = true;
|
|
954
|
+
if (!artifactGuard) artifactGuard = createRecursiveArtifactGuard(callback);
|
|
955
|
+
await artifactGuard.emitArtifact(results, {
|
|
956
|
+
toolsUsed,
|
|
957
|
+
...artifactInfo
|
|
958
|
+
});
|
|
959
|
+
}, declaredArtifactType(options.tools, tc.name));
|
|
960
|
+
observations[i] = stripUnstreamedToolResult(tc.name, outcome.result, emitted);
|
|
859
961
|
this.pushToolMessages(messages, {
|
|
860
962
|
id: tc.id,
|
|
861
963
|
name: tc.name,
|
|
862
964
|
parameters: params
|
|
863
|
-
},
|
|
965
|
+
}, observations[i]);
|
|
864
966
|
} else {
|
|
865
967
|
if (outcome.error instanceof PermissionDeniedError) throw outcome.error;
|
|
866
|
-
const errorMsg = `Error running ${tc.name}: ${outcome.error instanceof Error ? outcome.error.message : "Unknown error"}
|
|
968
|
+
const errorMsg = stripToolArtifactMarkup(`Error running ${tc.name}: ${outcome.error instanceof Error ? outcome.error.message : "Unknown error"}`, ARTIFACT_REMOVED_PLACEHOLDER);
|
|
867
969
|
observations[i] = errorMsg;
|
|
868
970
|
this.pushToolMessages(messages, {
|
|
869
971
|
id: tc.id,
|
|
@@ -871,7 +973,7 @@ var OllamaBackend = class OllamaBackend {
|
|
|
871
973
|
parameters: params
|
|
872
974
|
}, errorMsg);
|
|
873
975
|
}
|
|
874
|
-
}
|
|
976
|
+
}
|
|
875
977
|
const executedToolsUsed = [...priorToolsUsed, ...resolved.map(({ tc }, i) => {
|
|
876
978
|
const entry = {
|
|
877
979
|
name: tc.name,
|
|
@@ -884,11 +986,12 @@ var OllamaBackend = class OllamaBackend {
|
|
|
884
986
|
return entry;
|
|
885
987
|
})];
|
|
886
988
|
if (options.abortSignal?.aborted) {
|
|
887
|
-
await callback([""], {
|
|
989
|
+
await (artifactGuard?.callback ?? callback)([""], {
|
|
888
990
|
inputTokens,
|
|
889
991
|
outputTokens,
|
|
890
992
|
toolsUsed: executedToolsUsed
|
|
891
993
|
});
|
|
994
|
+
if (!inheritedArtifactGuard && artifactGuard) await artifactGuard.flush();
|
|
892
995
|
return;
|
|
893
996
|
}
|
|
894
997
|
await this.complete(model, messages, {
|
|
@@ -898,9 +1001,11 @@ var OllamaBackend = class OllamaBackend {
|
|
|
898
1001
|
toolCallCount: toolCallCount + 1,
|
|
899
1002
|
accumToolsUsed: executedToolsUsed,
|
|
900
1003
|
accumInputTokens: inputTokens,
|
|
901
|
-
accumOutputTokens: outputTokens
|
|
1004
|
+
accumOutputTokens: outputTokens,
|
|
1005
|
+
artifactGuard
|
|
902
1006
|
}
|
|
903
|
-
}, callback);
|
|
1007
|
+
}, artifactGuard?.callback ?? callback);
|
|
1008
|
+
if (!inheritedArtifactGuard && artifactGuard) await artifactGuard.flush();
|
|
904
1009
|
} catch (error) {
|
|
905
1010
|
if (error instanceof Error && isUserInitiatedAbort(error, options.abortSignal)) this._logger.debug("[OllamaBackend] Ollama request cancelled by the caller");
|
|
906
1011
|
else this._logger.error("[OllamaBackend] Error during Ollama API call:", error);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as CustomCommandStore, A as createAgentDelegateTool, C as createTodoStore, D as createCoordinateTaskTool, F as PermissionManager, J as setWebSocketToolExecutor, L as wrapTools, O as createResumeAgentTool, Q as RemoteSkillSource, S as createFindDefinitionTool, T as createSkillTool, b as createGetFileStructureTool, et as CheckpointStore, j as FallbackLlmBackend, k as createBackgroundAgentTools, s as buildSandbox, tt as SessionStore, w as createWriteTodosTool } from "../AgentHistoryStore-
|
|
3
|
-
import {
|
|
4
|
-
import { a as deferredToolRegistry, i as createToolSearchTool, n as buildSupportingStores, o as NotifyingLlmBackend, r as buildLlmBackend, t as buildAgent } from "../buildAgent-
|
|
5
|
-
import { t as ApiClient } from "../ApiClient-
|
|
2
|
+
import { $ as CustomCommandStore, A as createAgentDelegateTool, C as createTodoStore, D as createCoordinateTaskTool, F as PermissionManager, J as setWebSocketToolExecutor, L as wrapTools, O as createResumeAgentTool, Q as RemoteSkillSource, S as createFindDefinitionTool, T as createSkillTool, b as createGetFileStructureTool, et as CheckpointStore, j as FallbackLlmBackend, k as createBackgroundAgentTools, s as buildSandbox, tt as SessionStore, w as createWriteTodosTool } from "../AgentHistoryStore-DIMzvf-y.mjs";
|
|
3
|
+
import { _ as requireApiUrl, d as isReadOnlyTool, n as logger, t as ConfigStore } from "../ConfigStore-DIs-K9oD.mjs";
|
|
4
|
+
import { a as deferredToolRegistry, i as createToolSearchTool, n as buildSupportingStores, o as NotifyingLlmBackend, r as buildLlmBackend, t as buildAgent } from "../buildAgent-DOvEp92a.mjs";
|
|
5
|
+
import { t as ApiClient } from "../ApiClient-BTI0-m0g.mjs";
|
|
6
6
|
import { randomUUID } from "crypto";
|
|
7
7
|
import { existsSync, realpathSync, statSync } from "fs";
|
|
8
8
|
import { isAbsolute } from "path";
|
|
@@ -575,6 +575,7 @@ var AcpServer = class {
|
|
|
575
575
|
}
|
|
576
576
|
async buildStack() {
|
|
577
577
|
const config = await this.configStore.load();
|
|
578
|
+
this.configStore.warnPendingMcpApprovals();
|
|
578
579
|
await this.loadCustomCommands();
|
|
579
580
|
const authTokens = await this.configStore.getAuthTokens();
|
|
580
581
|
if (!authTokens) throw RequestError.authRequired(void 0, "Not authenticated. Run `b4m /login` first.");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { g as
|
|
2
|
+
import { g as parseApiUrl, t as ConfigStore, v as resolveApiEndpoint } from "../ConfigStore-DIs-K9oD.mjs";
|
|
3
3
|
//#region src/commands/apiCommand.ts
|
|
4
4
|
/**
|
|
5
5
|
* External API config command (--api-url / --reset-api)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as version } from "../package-
|
|
2
|
+
import { t as version } from "../package-Dl_F2Fah.mjs";
|
|
3
3
|
import { a as fetchLatestVersion, c as isNpmPrefixWritable, i as compareSemver } from "../updateChecker-CQW8bxo6.mjs";
|
|
4
4
|
import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
|
|
5
5
|
import { execSync } from "child_process";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as CustomCommandStore, A as createAgentDelegateTool, C as createTodoStore, D as createCoordinateTaskTool, F as PermissionManager, G as classifyCommandRisk, I as generateCliTools, J as setWebSocketToolExecutor, L as wrapTools, N as ReActAgent, O as createResumeAgentTool, Q as RemoteSkillSource, S as createFindDefinitionTool, T as createSkillTool, X as buildSystemPrompt, a as loadProjectContext, b as createGetFileStructureTool, c as createSseBackend, et as CheckpointStore, i as buildProjectAgentStore, j as FallbackLlmBackend, k as createBackgroundAgentTools, n as BackgroundAgentManager, o as McpManager, r as SubagentOrchestrator, s as buildSandbox, t as AgentHistoryStore, tt as SessionStore, w as createWriteTodosTool, x as createWorkItemTools, z as SHELL_LIKE_TOOL_COMMAND_FIELDS } from "../AgentHistoryStore-
|
|
3
|
-
import {
|
|
4
|
-
import { t as ApiClient } from "../ApiClient-
|
|
2
|
+
import { $ as CustomCommandStore, A as createAgentDelegateTool, C as createTodoStore, D as createCoordinateTaskTool, F as PermissionManager, G as classifyCommandRisk, I as generateCliTools, J as setWebSocketToolExecutor, L as wrapTools, N as ReActAgent, O as createResumeAgentTool, Q as RemoteSkillSource, S as createFindDefinitionTool, T as createSkillTool, X as buildSystemPrompt, a as loadProjectContext, b as createGetFileStructureTool, c as createSseBackend, et as CheckpointStore, i as buildProjectAgentStore, j as FallbackLlmBackend, k as createBackgroundAgentTools, n as BackgroundAgentManager, o as McpManager, r as SubagentOrchestrator, s as buildSandbox, t as AgentHistoryStore, tt as SessionStore, w as createWriteTodosTool, x as createWorkItemTools, z as SHELL_LIKE_TOOL_COMMAND_FIELDS } from "../AgentHistoryStore-DIMzvf-y.mjs";
|
|
3
|
+
import { _ as requireApiUrl, d as isReadOnlyTool, n as logger, t as ConfigStore } from "../ConfigStore-DIs-K9oD.mjs";
|
|
4
|
+
import { t as ApiClient } from "../ApiClient-BTI0-m0g.mjs";
|
|
5
5
|
import { r as reconstructTurnBlocks, t as WorkItemsClient } from "../WorkItemsClient-Cow6nXx7.mjs";
|
|
6
6
|
import { randomBytes } from "crypto";
|
|
7
7
|
import { v4 } from "uuid";
|
|
@@ -250,6 +250,7 @@ async function handleHeadlessCommand(options) {
|
|
|
250
250
|
const runId = v4();
|
|
251
251
|
try {
|
|
252
252
|
const config = await configStore.load();
|
|
253
|
+
configStore.warnPendingMcpApprovals();
|
|
253
254
|
const configDirs = await configStore.getAdditionalDirectories();
|
|
254
255
|
const flagDirs = process.env.B4M_ADDITIONAL_DIRS ? parseStringArray(process.env.B4M_ADDITIONAL_DIRS, "B4M_ADDITIONAL_DIRS") : [];
|
|
255
256
|
const additionalDirectories = [.../* @__PURE__ */ new Set([
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as ConfigStore } from "../ConfigStore-
|
|
3
|
-
import { t as version } from "../package-
|
|
2
|
+
import { t as ConfigStore } from "../ConfigStore-DIs-K9oD.mjs";
|
|
3
|
+
import { t as version } from "../package-Dl_F2Fah.mjs";
|
|
4
4
|
//#region src/commands/mcpCommand.ts
|
|
5
5
|
/**
|
|
6
6
|
* External MCP commands (b4m mcp list, b4m mcp add, etc.)
|
|
@@ -70,7 +70,7 @@ async function handleMcpCommand(subcommand, argv) {
|
|
|
70
70
|
await handleDisable(config, argv.name, configStore);
|
|
71
71
|
break;
|
|
72
72
|
case "serve": {
|
|
73
|
-
const { handleMcpServeCommand } = await import("../serve-
|
|
73
|
+
const { handleMcpServeCommand } = await import("../serve-Y2zMbfGs.mjs");
|
|
74
74
|
await handleMcpServeCommand({
|
|
75
75
|
http: Boolean(argv.http),
|
|
76
76
|
port: typeof argv.port === "number" ? argv.port : void 0,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { n as getDefaultPluginsDir, r as isFeatureEnabled, t as PluginStore } from "../PluginStore-DwvOJ-G3.mjs";
|
|
3
|
-
import { t as ConfigStore } from "../ConfigStore-
|
|
3
|
+
import { t as ConfigStore } from "../ConfigStore-DIs-K9oD.mjs";
|
|
4
4
|
import { execFileSync } from "child_process";
|
|
5
5
|
import { promises } from "fs";
|
|
6
6
|
import path from "path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as version } from "../package-
|
|
2
|
+
import { t as version } from "../package-Dl_F2Fah.mjs";
|
|
3
3
|
import { c as isNpmPrefixWritable, l as setAutoUpdatePreference, n as REEXEC_GUARD_ENV, o as forceCheckForUpdate, r as checkForUpdate, s as getAutoUpdatePreference, t as INSTALL_CMD, u as shouldAttemptAutoUpdate } from "../updateChecker-CQW8bxo6.mjs";
|
|
4
4
|
import { t as checkRipgrep } from "../ripgrepCheck-BmkyTK2i.mjs";
|
|
5
5
|
import { execSync, spawnSync } from "child_process";
|