@bike4mind/cli 0.4.0 → 0.6.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/dist/{ConfigStore-DBUmvCfe.mjs → ConfigStore-Dt6utdSA.mjs} +53 -2
- 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 +326 -9
- package/dist/{tools-DiSJh1Dv.mjs → tools-dIVxi-6-.mjs} +480 -114
- package/dist/{updateChecker-DcJC1C8S.mjs → updateChecker-DZXWZfKF.mjs} +1 -1
- package/package.json +19 -19
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as RechartsChartTypeList, A as ImageGenerationUsageTransaction, At as secureParameters, B as NotFoundError, C as FileEvents, Ct as getMcpProviderMetadata, D as GenericCreditAddTransaction, Dt as obfuscateApiKey, E as GenerateImageToolCallSchema, Et as isGPTImageModel, F as KnowledgeType, G as ProfileEvents, H as OpenAIImageGenerationInput, I as LLMEvents, J as PurchaseTransaction, K as ProjectEvents, L as MiscEvents, M as InboxEvents, N as InviteEvents, Nt as CollectionType, O as GenericCreditDeductTransaction, Ot as resolveNavigationIntents, P as InviteType, Q as ReceivedCreditTransaction, R as ModalEvents, S as FeedbackEvents, St as getDataLakeTags, T as GEMINI_IMAGE_MODELS, Tt as isGPTImage2Model, U as Permission, V as OpenAIEmbeddingModel, W as PermissionDeniedError, X as REASONING_SUPPORTED_MODELS, Y as QuestMasterParamsSchema, Z as RealtimeVoiceUsageTransaction, _ as CompletionApiUsageTransaction, _t as VideoModels, a as ApiKeyEvents, at as SessionEvents, b as FIXED_TEMPERATURE_MODELS, bt as b4mLLMTools, c as AppFileEvents, ct as SupportedFabFileMimeTypes, d as BFL_IMAGE_MODELS, dt as TextGenerationUsageTransaction, et as RegInviteEvents, f as BFL_SAFETY_TOLERANCE, ft as ToolUsageTransaction, g as ChatModels, gt as VideoGenerationUsageTransaction, h as ChatCompletionCreateInputSchema, ht as VIDEO_SIZE_CONSTRAINTS, i as AiEvents, it as ResearchTaskType, j as ImageModels, k as ImageEditUsageTransaction, kt as sanitizeTelemetryError, l as ArtifactTypeSchema, lt as TagType, mt as UiNavigationEvents, n as logger, nt as ResearchTaskExecutionType, o as ApiKeyScope, ot as SpeechToTextModels, p as BedrockEmbeddingModel, pt as TransferCreditTransaction, q as PromptMetaZodSchema, r as ALERT_THRESHOLDS, rt as ResearchTaskPeriodicFrequencyType, s as ApiKeyType, st as SubscriptionCreditTransaction, t as ConfigStore, tt as ResearchModeParamsSchema, u as AuthEvents, ut as TaskScheduleHandler, v as DashboardParamsSchema, vt as VoyageAIEmbeddingModel, w as FriendshipEvents, wt as getViewById, x as FavoriteDocumentType, xt as getAccessibleDataLakes, y as ElabsEvents, yt as XAI_IMAGE_MODELS, z as ModelBackend } from "./ConfigStore-
|
|
2
|
+
import { $ as RechartsChartTypeList, A as ImageGenerationUsageTransaction, At as secureParameters, B as NotFoundError, C as FileEvents, Ct as getMcpProviderMetadata, D as GenericCreditAddTransaction, Dt as obfuscateApiKey, E as GenerateImageToolCallSchema, Et as isGPTImageModel, F as KnowledgeType, G as ProfileEvents, H as OpenAIImageGenerationInput, I as LLMEvents, J as PurchaseTransaction, K as ProjectEvents, L as MiscEvents, M as InboxEvents, N as InviteEvents, Nt as CollectionType, O as GenericCreditDeductTransaction, Ot as resolveNavigationIntents, P as InviteType, Q as ReceivedCreditTransaction, R as ModalEvents, S as FeedbackEvents, St as getDataLakeTags, T as GEMINI_IMAGE_MODELS, Tt as isGPTImage2Model, U as Permission, V as OpenAIEmbeddingModel, W as PermissionDeniedError, X as REASONING_SUPPORTED_MODELS, Y as QuestMasterParamsSchema, Z as RealtimeVoiceUsageTransaction, _ as CompletionApiUsageTransaction, _t as VideoModels, a as ApiKeyEvents, at as SessionEvents, b as FIXED_TEMPERATURE_MODELS, bt as b4mLLMTools, c as AppFileEvents, ct as SupportedFabFileMimeTypes, d as BFL_IMAGE_MODELS, dt as TextGenerationUsageTransaction, et as RegInviteEvents, f as BFL_SAFETY_TOLERANCE, ft as ToolUsageTransaction, g as ChatModels, gt as VideoGenerationUsageTransaction, h as ChatCompletionCreateInputSchema, ht as VIDEO_SIZE_CONSTRAINTS, i as AiEvents, it as ResearchTaskType, j as ImageModels, k as ImageEditUsageTransaction, kt as sanitizeTelemetryError, l as ArtifactTypeSchema, lt as TagType, mt as UiNavigationEvents, n as logger, nt as ResearchTaskExecutionType, o as ApiKeyScope, ot as SpeechToTextModels, p as BedrockEmbeddingModel, pt as TransferCreditTransaction, q as PromptMetaZodSchema, r as ALERT_THRESHOLDS, rt as ResearchTaskPeriodicFrequencyType, s as ApiKeyType, st as SubscriptionCreditTransaction, t as ConfigStore, tt as ResearchModeParamsSchema, u as AuthEvents, ut as TaskScheduleHandler, v as DashboardParamsSchema, vt as VoyageAIEmbeddingModel, w as FriendshipEvents, wt as getViewById, x as FavoriteDocumentType, xt as getAccessibleDataLakes, y as ElabsEvents, yt as XAI_IMAGE_MODELS, z as ModelBackend } from "./ConfigStore-Dt6utdSA.mjs";
|
|
3
3
|
import { n as isPathAllowed, t as assertPathAllowed } from "./pathValidation-CIytuhr3-Dt5dntLx.mjs";
|
|
4
4
|
import { execFile, execFileSync, spawn } from "child_process";
|
|
5
5
|
import { createHash, randomBytes } from "crypto";
|
|
@@ -522,6 +522,18 @@ const COMMANDS = [
|
|
|
522
522
|
{
|
|
523
523
|
name: "dirs",
|
|
524
524
|
description: "List all accessible directories"
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
name: "decisions",
|
|
528
|
+
description: "Show decision log for current session"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: "blockers",
|
|
532
|
+
description: "Show tracked blockers for current session"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
name: "handoff",
|
|
536
|
+
description: "Show or generate the session handoff for cross-session continuity"
|
|
525
537
|
}
|
|
526
538
|
];
|
|
527
539
|
/**
|
|
@@ -3015,7 +3027,18 @@ EXAMPLES:
|
|
|
3015
3027
|
- "what packages installed?" → ${TOOL_GLOB_FILES} "**/package.json" → ${TOOL_FILE_READ}
|
|
3016
3028
|
- "find all components using React hooks" → ${TOOL_SUBAGENT_DELEGATE}(task="find all components using React hooks", type="explore")
|
|
3017
3029
|
|
|
3018
|
-
Remember: Use context from previous messages to understand follow-up questions
|
|
3030
|
+
Remember: Use context from previous messages to understand follow-up questions.
|
|
3031
|
+
|
|
3032
|
+
DURABLE WORKFLOW TRACKING:
|
|
3033
|
+
You have tools for tracking decisions and blockers during your work. These create an audit trail that persists across sessions, enabling anyone to understand why things were done and what's still outstanding.
|
|
3034
|
+
|
|
3035
|
+
- log_decision: When you make a significant decision (architecture choice, scope narrowing, interpretation of ambiguous requirements, trade-off between alternatives), log it with rationale. Do NOT log trivial decisions. Log decisions that would matter if someone needed to understand WHY you did something or if they needed to resume this work.
|
|
3036
|
+
|
|
3037
|
+
- track_blocker: When you encounter something blocking progress (missing information, unclear requirements, external dependencies, ambiguous specs that need human clarification), track it. This makes blockers visible so they can be addressed.
|
|
3038
|
+
|
|
3039
|
+
- resolve_blocker: When a blocker is cleared, record how it was resolved. Use the blocker ID from the track_blocker output.
|
|
3040
|
+
|
|
3041
|
+
These tools are lightweight — use them naturally as part of your work, not as a ceremony.${directoriesSection}${projectContextSection}${skillsSection}${featureModulesSection}`;
|
|
3019
3042
|
}
|
|
3020
3043
|
/**
|
|
3021
3044
|
* Build the dynamic agent creation prompt section
|
|
@@ -3080,8 +3103,7 @@ var AIImageService = class {
|
|
|
3080
3103
|
}
|
|
3081
3104
|
};
|
|
3082
3105
|
//#endregion
|
|
3083
|
-
//#region ../../b4m-core/
|
|
3084
|
-
var BaseStorage = class {};
|
|
3106
|
+
//#region ../../b4m-core/observability/dist/index.mjs
|
|
3085
3107
|
var Logger = class Logger {
|
|
3086
3108
|
static globalInstance = new Logger();
|
|
3087
3109
|
metadata = {};
|
|
@@ -3285,6 +3307,9 @@ var Logger = class Logger {
|
|
|
3285
3307
|
blue: `\x1b[34m${args.join(" ")}\x1b[0m`
|
|
3286
3308
|
});
|
|
3287
3309
|
};
|
|
3310
|
+
//#endregion
|
|
3311
|
+
//#region ../../b4m-core/utils/dist/index.mjs
|
|
3312
|
+
var BaseStorage = class {};
|
|
3288
3313
|
dotenv.config();
|
|
3289
3314
|
/**
|
|
3290
3315
|
* Execute an array of async tasks either in parallel (with concurrency limiting)
|
|
@@ -4741,6 +4766,8 @@ var OpenAIBackend = class {
|
|
|
4741
4766
|
...options
|
|
4742
4767
|
};
|
|
4743
4768
|
const toolCallCount = options._internal?.toolCallCount ?? 0;
|
|
4769
|
+
const accumInputTokens = options._internal?.accumInputTokens ?? 0;
|
|
4770
|
+
const accumOutputTokens = options._internal?.accumOutputTokens ?? 0;
|
|
4744
4771
|
if (toolCallCount >= 10 && options.tools?.length) {
|
|
4745
4772
|
this.logger.warn(`⚠️ Max tool calls limit (10) reached. Disabling tools to prevent infinite loops.`);
|
|
4746
4773
|
await this.complete(model, messages, {
|
|
@@ -4923,7 +4950,9 @@ var OpenAIBackend = class {
|
|
|
4923
4950
|
tools: anyMcpTool ? options.tools : void 0,
|
|
4924
4951
|
_internal: {
|
|
4925
4952
|
...options._internal,
|
|
4926
|
-
toolCallCount: toolCallCount + 1
|
|
4953
|
+
toolCallCount: toolCallCount + 1,
|
|
4954
|
+
accumInputTokens: accumInputTokens + (response.usage?.prompt_tokens || 0),
|
|
4955
|
+
accumOutputTokens: accumOutputTokens + (response.usage?.completion_tokens || 0)
|
|
4927
4956
|
}
|
|
4928
4957
|
}, recursiveCallback, toolsUsed);
|
|
4929
4958
|
if (anyArtifactWasStreamed && recursiveBuffer) {
|
|
@@ -4934,8 +4963,8 @@ var OpenAIBackend = class {
|
|
|
4934
4963
|
} else {
|
|
4935
4964
|
this.logger.debug(`[Tool Execution] executeTools=false, passing tool calls to callback`);
|
|
4936
4965
|
await callback([null], {
|
|
4937
|
-
inputTokens: response.usage?.prompt_tokens || 0,
|
|
4938
|
-
outputTokens: response.usage?.completion_tokens || 0,
|
|
4966
|
+
inputTokens: accumInputTokens + (response.usage?.prompt_tokens || 0),
|
|
4967
|
+
outputTokens: accumOutputTokens + (response.usage?.completion_tokens || 0),
|
|
4939
4968
|
toolsUsed: toolsUsed.length > 0 ? toolsUsed : void 0
|
|
4940
4969
|
});
|
|
4941
4970
|
return;
|
|
@@ -4949,8 +4978,8 @@ var OpenAIBackend = class {
|
|
|
4949
4978
|
if (cacheStats) logCacheStats(this.logger, cacheStats, { streaming: false });
|
|
4950
4979
|
}
|
|
4951
4980
|
await callback(streamedText, {
|
|
4952
|
-
inputTokens: response.usage?.prompt_tokens || 0,
|
|
4953
|
-
outputTokens: response.usage?.completion_tokens || 0,
|
|
4981
|
+
inputTokens: accumInputTokens + (response.usage?.prompt_tokens || 0),
|
|
4982
|
+
outputTokens: accumOutputTokens + (response.usage?.completion_tokens || 0),
|
|
4954
4983
|
toolsUsed: toolsUsed.length > 0 ? toolsUsed : void 0,
|
|
4955
4984
|
cacheStats
|
|
4956
4985
|
});
|
|
@@ -4989,8 +5018,8 @@ var OpenAIBackend = class {
|
|
|
4989
5018
|
if (c.delta.content) streamedText[c.index] = (streamedText[c.index] || "") + c.delta.content;
|
|
4990
5019
|
});
|
|
4991
5020
|
await callback(streamedText, {
|
|
4992
|
-
inputTokens,
|
|
4993
|
-
outputTokens,
|
|
5021
|
+
inputTokens: accumInputTokens + inputTokens,
|
|
5022
|
+
outputTokens: accumOutputTokens + outputTokens,
|
|
4994
5023
|
toolsUsed: toolsUsed.length > 0 ? toolsUsed : void 0
|
|
4995
5024
|
});
|
|
4996
5025
|
}
|
|
@@ -5095,8 +5124,8 @@ var OpenAIBackend = class {
|
|
|
5095
5124
|
thisToolHadArtifact = true;
|
|
5096
5125
|
anyArtifactWasStreamed = true;
|
|
5097
5126
|
await callback(results, {
|
|
5098
|
-
inputTokens,
|
|
5099
|
-
outputTokens,
|
|
5127
|
+
inputTokens: accumInputTokens + inputTokens,
|
|
5128
|
+
outputTokens: accumOutputTokens + outputTokens,
|
|
5100
5129
|
toolsUsed: toolsUsed.length > 0 ? toolsUsed : void 0,
|
|
5101
5130
|
cacheStats
|
|
5102
5131
|
});
|
|
@@ -5119,7 +5148,9 @@ var OpenAIBackend = class {
|
|
|
5119
5148
|
tools: anyMcpTool ? options.tools : void 0,
|
|
5120
5149
|
_internal: {
|
|
5121
5150
|
...options._internal,
|
|
5122
|
-
toolCallCount: toolCallCount + 1
|
|
5151
|
+
toolCallCount: toolCallCount + 1,
|
|
5152
|
+
accumInputTokens: accumInputTokens + inputTokens,
|
|
5153
|
+
accumOutputTokens: accumOutputTokens + outputTokens
|
|
5123
5154
|
}
|
|
5124
5155
|
}, async (results, meta) => {
|
|
5125
5156
|
for (const r of results) if (r != null) recursiveBuffer += r;
|
|
@@ -5132,14 +5163,16 @@ var OpenAIBackend = class {
|
|
|
5132
5163
|
tools: anyMcpTool ? options.tools : void 0,
|
|
5133
5164
|
_internal: {
|
|
5134
5165
|
...options._internal,
|
|
5135
|
-
toolCallCount: toolCallCount + 1
|
|
5166
|
+
toolCallCount: toolCallCount + 1,
|
|
5167
|
+
accumInputTokens: accumInputTokens + inputTokens,
|
|
5168
|
+
accumOutputTokens: accumOutputTokens + outputTokens
|
|
5136
5169
|
}
|
|
5137
5170
|
}, callback, toolsUsed);
|
|
5138
5171
|
} else {
|
|
5139
5172
|
this.logger.debug(`[Tool Execution] executeTools=false, passing tool calls to callback`);
|
|
5140
5173
|
await callback([null], {
|
|
5141
|
-
inputTokens,
|
|
5142
|
-
outputTokens,
|
|
5174
|
+
inputTokens: accumInputTokens + inputTokens,
|
|
5175
|
+
outputTokens: accumOutputTokens + outputTokens,
|
|
5143
5176
|
toolsUsed: toolsUsed.length > 0 ? toolsUsed : void 0,
|
|
5144
5177
|
cacheStats
|
|
5145
5178
|
});
|
|
@@ -6675,15 +6708,26 @@ const webSearchTool = {
|
|
|
6675
6708
|
};
|
|
6676
6709
|
//#endregion
|
|
6677
6710
|
//#region ../../b4m-core/services/dist/llm/tools/implementation/webfetch/index.mjs
|
|
6711
|
+
const DEFAULT_TIMEOUT_MS = 6e4;
|
|
6712
|
+
const PDF_TIMEOUT_MS = 9e4;
|
|
6713
|
+
function isPdfUrl(url) {
|
|
6714
|
+
try {
|
|
6715
|
+
const { pathname } = new URL(url);
|
|
6716
|
+
return pathname.toLowerCase().endsWith(".pdf");
|
|
6717
|
+
} catch {
|
|
6718
|
+
return false;
|
|
6719
|
+
}
|
|
6720
|
+
}
|
|
6678
6721
|
/**
|
|
6679
6722
|
* Fetch URL content using Firecrawl (shared function, no ToolContext)
|
|
6680
6723
|
* Pattern follows serpApiSearch from websearch tool
|
|
6681
6724
|
*
|
|
6682
6725
|
* @param adapters - Database adapters for fetching Firecrawl API key
|
|
6683
6726
|
* @param url - URL to fetch
|
|
6727
|
+
* @param options - Optional configuration (e.g. maxTimeoutMs for Lambda-constrained callers)
|
|
6684
6728
|
* @returns Markdown content and title
|
|
6685
6729
|
*/
|
|
6686
|
-
async function firecrawlFetch(adapters, url) {
|
|
6730
|
+
async function firecrawlFetch(adapters, url, options) {
|
|
6687
6731
|
if (!/^https?:\/\/.+/i.test(url)) throw new Error(`Invalid URL format: ${url}. URL must start with http:// or https://`);
|
|
6688
6732
|
const apiKeySetting = await adapters.db.adminSettings.findBySettingName("FirecrawlApiKey");
|
|
6689
6733
|
if (!apiKeySetting?.settingValue) {
|
|
@@ -6691,45 +6735,45 @@ async function firecrawlFetch(adapters, url) {
|
|
|
6691
6735
|
throw new Error("Firecrawl API key not configured");
|
|
6692
6736
|
}
|
|
6693
6737
|
const app = new FirecrawlApp({ apiKey: apiKeySetting.settingValue });
|
|
6694
|
-
const
|
|
6695
|
-
const
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
console.
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
}
|
|
6738
|
+
const isPdf = isPdfUrl(url);
|
|
6739
|
+
const desiredTimeout = isPdf ? PDF_TIMEOUT_MS : DEFAULT_TIMEOUT_MS;
|
|
6740
|
+
const timeoutMs = options?.maxTimeoutMs ? Math.min(desiredTimeout, options.maxTimeoutMs) : desiredTimeout;
|
|
6741
|
+
console.log(`📥 WebFetch Tool: Scraping URL with Firecrawl${isPdf ? " (PDF mode, extended timeout)" : ""}...`);
|
|
6742
|
+
const baseParams = {
|
|
6743
|
+
formats: ["markdown"],
|
|
6744
|
+
timeout: timeoutMs
|
|
6745
|
+
};
|
|
6746
|
+
let result;
|
|
6747
|
+
if (isPdf) result = await app.scrapeUrl(url, baseParams);
|
|
6748
|
+
else try {
|
|
6749
|
+
result = await app.scrapeUrl(url, {
|
|
6750
|
+
...baseParams,
|
|
6751
|
+
actions: [{
|
|
6752
|
+
type: "wait",
|
|
6753
|
+
milliseconds: 1e3
|
|
6754
|
+
}]
|
|
6755
|
+
});
|
|
6756
|
+
} catch (scrapeError) {
|
|
6757
|
+
if ((scrapeError instanceof Error ? scrapeError.message : "").includes("Actions are not supported")) {
|
|
6758
|
+
console.log("📥 WebFetch Tool: Actions not supported, retrying without actions...");
|
|
6759
|
+
result = await app.scrapeUrl(url, baseParams);
|
|
6760
|
+
} else throw scrapeError;
|
|
6761
|
+
}
|
|
6762
|
+
if (!result || result.error) {
|
|
6763
|
+
const errorMessage = result?.error || "Unknown error";
|
|
6764
|
+
console.error("❌ WebFetch Tool: Firecrawl error:", errorMessage);
|
|
6765
|
+
throw new Error(`Failed to fetch content from URL: ${errorMessage}`);
|
|
6766
|
+
}
|
|
6767
|
+
if (!("markdown" in result) || !result.markdown) {
|
|
6768
|
+
console.error("❌ WebFetch Tool: No markdown content returned");
|
|
6769
|
+
throw new Error("No content could be extracted from the URL");
|
|
6770
|
+
}
|
|
6771
|
+
const markdown = result.markdown.slice(0, 5e4);
|
|
6772
|
+
console.log(`📄 WebFetch Tool: Extracted ${markdown.length} characters of content`);
|
|
6773
|
+
return {
|
|
6774
|
+
markdown,
|
|
6775
|
+
title: result.metadata?.title
|
|
6776
|
+
};
|
|
6733
6777
|
}
|
|
6734
6778
|
const webFetchTool = {
|
|
6735
6779
|
name: "web_fetch",
|
|
@@ -6785,6 +6829,14 @@ const webFetchTool = {
|
|
|
6785
6829
|
await context.statusUpdate({}, `WebFetch: ${statusLabel}`);
|
|
6786
6830
|
return userMessage;
|
|
6787
6831
|
}
|
|
6832
|
+
if (error instanceof FirecrawlError && error.statusCode === 500 && errorMessage.includes("PDF")) {
|
|
6833
|
+
context.logger.warn("WebFetch PDF too large for Firecrawl", {
|
|
6834
|
+
url: params.url,
|
|
6835
|
+
error: errorMessage
|
|
6836
|
+
});
|
|
6837
|
+
await context.statusUpdate({}, "WebFetch: PDF too large");
|
|
6838
|
+
return `This PDF is too large to process via URL. Please download the file and upload it directly instead.`;
|
|
6839
|
+
}
|
|
6788
6840
|
if ([
|
|
6789
6841
|
"no response received",
|
|
6790
6842
|
"econnrefused",
|
|
@@ -6821,17 +6873,49 @@ const webFetchTool = {
|
|
|
6821
6873
|
})
|
|
6822
6874
|
};
|
|
6823
6875
|
//#endregion
|
|
6824
|
-
//#region ../../b4m-core/services/dist/jsonSanitize-
|
|
6876
|
+
//#region ../../b4m-core/services/dist/jsonSanitize-DPYPbara.mjs
|
|
6825
6877
|
/**
|
|
6826
6878
|
* Sanitize a JSON string by escaping control characters inside string literals.
|
|
6827
6879
|
* LLMs sometimes return JSON with unescaped newlines/tabs inside string values,
|
|
6828
6880
|
* which causes JSON.parse to fail with "Bad control character in string literal".
|
|
6829
6881
|
*
|
|
6830
6882
|
* Covers all U+0000–U+001F control characters per JSON RFC 8259.
|
|
6883
|
+
*
|
|
6884
|
+
* Also applies a lookahead heuristic to escape unescaped double-quotes inside
|
|
6885
|
+
* string values — the most common LLM JSON failure mode (e.g., code snippets
|
|
6886
|
+
* containing logger.error("msg") inside a JSON string).
|
|
6887
|
+
*
|
|
6888
|
+
* Returns the sanitized string and the number of quotes repaired.
|
|
6889
|
+
* If the JSON is already valid, it is returned unchanged (zero repairs).
|
|
6831
6890
|
*/
|
|
6832
6891
|
function sanitizeJsonString(jsonStr) {
|
|
6892
|
+
const { result } = sanitizeJsonStringWithMeta(jsonStr);
|
|
6893
|
+
return result;
|
|
6894
|
+
}
|
|
6895
|
+
function sanitizeJsonStringWithMeta(jsonStr, options) {
|
|
6896
|
+
try {
|
|
6897
|
+
JSON.parse(jsonStr);
|
|
6898
|
+
return {
|
|
6899
|
+
result: jsonStr,
|
|
6900
|
+
repairedQuotes: 0
|
|
6901
|
+
};
|
|
6902
|
+
} catch {}
|
|
6833
6903
|
let result = "";
|
|
6834
6904
|
let inString = false;
|
|
6905
|
+
/**
|
|
6906
|
+
* Tracks whether we are in a key position (true) or value position (false).
|
|
6907
|
+
* Starts as true — the first string in valid JSON must be a key.
|
|
6908
|
+
* Flips to false after a key-closing quote + colon pair.
|
|
6909
|
+
* Flips back to true after a value-closing quote (or structural char) + comma/`{`/`[`.
|
|
6910
|
+
*
|
|
6911
|
+
* This is used to disambiguate `:` after a `"` inside a string:
|
|
6912
|
+
* - In key position: `"` + `:` → structural (closes the key, colon follows)
|
|
6913
|
+
* - In value position: `"` + `:` → embedded (e.g., `"status": it was null"`)
|
|
6914
|
+
*/
|
|
6915
|
+
let inKey = true;
|
|
6916
|
+
/** Tracks nested structure context for truncation repair. */
|
|
6917
|
+
const structureStack = [];
|
|
6918
|
+
let repairedQuotes = 0;
|
|
6835
6919
|
let i = 0;
|
|
6836
6920
|
while (i < jsonStr.length) {
|
|
6837
6921
|
const char = jsonStr[i];
|
|
@@ -6841,8 +6925,25 @@ function sanitizeJsonString(jsonStr) {
|
|
|
6841
6925
|
continue;
|
|
6842
6926
|
}
|
|
6843
6927
|
if (char === "\"") {
|
|
6844
|
-
|
|
6845
|
-
|
|
6928
|
+
if (!inString) {
|
|
6929
|
+
inString = true;
|
|
6930
|
+
result += char;
|
|
6931
|
+
i++;
|
|
6932
|
+
continue;
|
|
6933
|
+
}
|
|
6934
|
+
let j = i + 1;
|
|
6935
|
+
while (j < jsonStr.length && (jsonStr[j] === " " || jsonStr[j] === " " || jsonStr[j] === "\r" || jsonStr[j] === "\n")) j++;
|
|
6936
|
+
const nextNonWs = j < jsonStr.length ? jsonStr[j] : "";
|
|
6937
|
+
if (nextNonWs === "," || nextNonWs === "}" || nextNonWs === "]" || nextNonWs === "" || nextNonWs === ":" && inKey) {
|
|
6938
|
+
inString = false;
|
|
6939
|
+
result += char;
|
|
6940
|
+
i++;
|
|
6941
|
+
if (nextNonWs === ":") inKey = false;
|
|
6942
|
+
else if (nextNonWs === "," || nextNonWs === "}" || nextNonWs === "]") inKey = true;
|
|
6943
|
+
continue;
|
|
6944
|
+
}
|
|
6945
|
+
result += "\\\"";
|
|
6946
|
+
repairedQuotes++;
|
|
6846
6947
|
i++;
|
|
6847
6948
|
continue;
|
|
6848
6949
|
}
|
|
@@ -6869,10 +6970,45 @@ function sanitizeJsonString(jsonStr) {
|
|
|
6869
6970
|
break;
|
|
6870
6971
|
}
|
|
6871
6972
|
else result += char;
|
|
6872
|
-
} else
|
|
6973
|
+
} else {
|
|
6974
|
+
result += char;
|
|
6975
|
+
if (char === "{") {
|
|
6976
|
+
structureStack.push("{");
|
|
6977
|
+
inKey = true;
|
|
6978
|
+
} else if (char === "[") {
|
|
6979
|
+
structureStack.push("[");
|
|
6980
|
+
inKey = false;
|
|
6981
|
+
} else if (char === "}" || char === "]") {
|
|
6982
|
+
if (structureStack.length > 0) structureStack.pop();
|
|
6983
|
+
inKey = (structureStack.length > 0 ? structureStack[structureStack.length - 1] : null) !== "[";
|
|
6984
|
+
} else if (char === ",") {
|
|
6985
|
+
if ((structureStack.length > 0 ? structureStack[structureStack.length - 1] : null) === "{") inKey = true;
|
|
6986
|
+
}
|
|
6987
|
+
}
|
|
6873
6988
|
i++;
|
|
6874
6989
|
}
|
|
6875
|
-
|
|
6990
|
+
if (inString) {
|
|
6991
|
+
if (options?.attemptTruncationRepair && structureStack.length > 0) {
|
|
6992
|
+
const closing = [...structureStack].reverse().map((c) => c === "{" ? "}" : "]").join("");
|
|
6993
|
+
const salvage = result + "\"" + closing;
|
|
6994
|
+
try {
|
|
6995
|
+
JSON.parse(salvage);
|
|
6996
|
+
return {
|
|
6997
|
+
result: salvage,
|
|
6998
|
+
repairedQuotes,
|
|
6999
|
+
truncationRepaired: true
|
|
7000
|
+
};
|
|
7001
|
+
} catch {}
|
|
7002
|
+
}
|
|
7003
|
+
return {
|
|
7004
|
+
result: jsonStr,
|
|
7005
|
+
repairedQuotes: 0
|
|
7006
|
+
};
|
|
7007
|
+
}
|
|
7008
|
+
return {
|
|
7009
|
+
result,
|
|
7010
|
+
repairedQuotes
|
|
7011
|
+
};
|
|
6876
7012
|
}
|
|
6877
7013
|
//#endregion
|
|
6878
7014
|
//#region ../../b4m-core/quantum/dist/index.mjs
|
|
@@ -8720,7 +8856,7 @@ No markdown, no explanation, no code blocks — just the raw JSON object.`;
|
|
|
8720
8856
|
"Minimize: sum(error^2)"
|
|
8721
8857
|
].join("\n");
|
|
8722
8858
|
//#endregion
|
|
8723
|
-
//#region ../../b4m-core/services/dist/tools-
|
|
8859
|
+
//#region ../../b4m-core/services/dist/tools-B55E_Q3K.mjs
|
|
8724
8860
|
async function performDeepResearch(context, params, config) {
|
|
8725
8861
|
const maxDepth = config.maxDepth || 7;
|
|
8726
8862
|
const duration = config.duration || 4.5;
|
|
@@ -15760,56 +15896,6 @@ z.object({
|
|
|
15760
15896
|
embargoDetected: z.boolean().prefault(false),
|
|
15761
15897
|
suggestedTags: z.array(z.string()).prefault([])
|
|
15762
15898
|
});
|
|
15763
|
-
z.object({
|
|
15764
|
-
userId: z.string(),
|
|
15765
|
-
sessionId: z.string(),
|
|
15766
|
-
questId: z.string(),
|
|
15767
|
-
message: z.string().min(1, "Message cannot be empty"),
|
|
15768
|
-
messageFileIds: z.array(z.string()),
|
|
15769
|
-
historyCount: z.number(),
|
|
15770
|
-
fabFileIds: z.array(z.string()),
|
|
15771
|
-
params: ChatCompletionCreateInputSchema,
|
|
15772
|
-
dashboardParams: DashboardParamsSchema.optional(),
|
|
15773
|
-
enableQuestMaster: z.boolean().optional(),
|
|
15774
|
-
enableMementos: z.boolean().optional(),
|
|
15775
|
-
enableArtifacts: z.boolean().optional(),
|
|
15776
|
-
enableAgents: z.boolean().optional(),
|
|
15777
|
-
enableLattice: z.boolean().optional(),
|
|
15778
|
-
promptMeta: PromptMetaZodSchema,
|
|
15779
|
-
tools: z.array(z.union([b4mLLMTools, z.string()])).optional(),
|
|
15780
|
-
mcpServers: z.array(z.string()).optional(),
|
|
15781
|
-
projectId: z.string().optional(),
|
|
15782
|
-
organizationId: z.string().nullable().optional(),
|
|
15783
|
-
questMaster: QuestMasterParamsSchema.optional(),
|
|
15784
|
-
toolPromptId: z.string().optional(),
|
|
15785
|
-
researchMode: ResearchModeParamsSchema.optional(),
|
|
15786
|
-
fallbackModel: z.string().optional(),
|
|
15787
|
-
embeddingModel: z.string().optional(),
|
|
15788
|
-
queryComplexity: z.string(),
|
|
15789
|
-
imageConfig: GenerateImageToolCallSchema.optional(),
|
|
15790
|
-
deepResearchConfig: z.object({
|
|
15791
|
-
maxDepth: z.number().optional(),
|
|
15792
|
-
duration: z.number().optional(),
|
|
15793
|
-
searchers: z.array(z.any()).optional()
|
|
15794
|
-
}).optional(),
|
|
15795
|
-
extraContextMessages: z.array(z.object({
|
|
15796
|
-
role: z.enum([
|
|
15797
|
-
"user",
|
|
15798
|
-
"assistant",
|
|
15799
|
-
"system",
|
|
15800
|
-
"function",
|
|
15801
|
-
"tool"
|
|
15802
|
-
]),
|
|
15803
|
-
content: z.union([z.string(), z.array(z.any())]),
|
|
15804
|
-
fabFileIds: z.array(z.string()).optional()
|
|
15805
|
-
})).optional(),
|
|
15806
|
-
/** User's timezone (IANA format, e.g., "America/New_York") */
|
|
15807
|
-
timezone: z.string().optional(),
|
|
15808
|
-
/** Persona-based sub-agent filter — only these agent names are available for delegation */
|
|
15809
|
-
allowedAgents: z.array(z.string()).optional(),
|
|
15810
|
-
/** When true, Quest Processor injects Slack-specific tool configs (help, notebooks, curated files) */
|
|
15811
|
-
enableSlackTools: z.boolean().optional()
|
|
15812
|
-
});
|
|
15813
15899
|
/**
|
|
15814
15900
|
* Regex patterns for extracting GitHub entities from text
|
|
15815
15901
|
*/
|
|
@@ -16307,6 +16393,56 @@ var CombinedExtractor = class {
|
|
|
16307
16393
|
}
|
|
16308
16394
|
};
|
|
16309
16395
|
new CombinedExtractor();
|
|
16396
|
+
z.object({
|
|
16397
|
+
userId: z.string(),
|
|
16398
|
+
sessionId: z.string(),
|
|
16399
|
+
questId: z.string(),
|
|
16400
|
+
message: z.string().min(1, "Message cannot be empty"),
|
|
16401
|
+
messageFileIds: z.array(z.string()),
|
|
16402
|
+
historyCount: z.number(),
|
|
16403
|
+
fabFileIds: z.array(z.string()),
|
|
16404
|
+
params: ChatCompletionCreateInputSchema,
|
|
16405
|
+
dashboardParams: DashboardParamsSchema.optional(),
|
|
16406
|
+
enableQuestMaster: z.boolean().optional(),
|
|
16407
|
+
enableMementos: z.boolean().optional(),
|
|
16408
|
+
enableArtifacts: z.boolean().optional(),
|
|
16409
|
+
enableAgents: z.boolean().optional(),
|
|
16410
|
+
enableLattice: z.boolean().optional(),
|
|
16411
|
+
promptMeta: PromptMetaZodSchema,
|
|
16412
|
+
tools: z.array(z.union([b4mLLMTools, z.string()])).optional(),
|
|
16413
|
+
mcpServers: z.array(z.string()).optional(),
|
|
16414
|
+
projectId: z.string().optional(),
|
|
16415
|
+
organizationId: z.string().nullable().optional(),
|
|
16416
|
+
questMaster: QuestMasterParamsSchema.optional(),
|
|
16417
|
+
toolPromptId: z.string().optional(),
|
|
16418
|
+
researchMode: ResearchModeParamsSchema.optional(),
|
|
16419
|
+
fallbackModel: z.string().optional(),
|
|
16420
|
+
embeddingModel: z.string().optional(),
|
|
16421
|
+
queryComplexity: z.string(),
|
|
16422
|
+
imageConfig: GenerateImageToolCallSchema.optional(),
|
|
16423
|
+
deepResearchConfig: z.object({
|
|
16424
|
+
maxDepth: z.number().optional(),
|
|
16425
|
+
duration: z.number().optional(),
|
|
16426
|
+
searchers: z.array(z.any()).optional()
|
|
16427
|
+
}).optional(),
|
|
16428
|
+
extraContextMessages: z.array(z.object({
|
|
16429
|
+
role: z.enum([
|
|
16430
|
+
"user",
|
|
16431
|
+
"assistant",
|
|
16432
|
+
"system",
|
|
16433
|
+
"function",
|
|
16434
|
+
"tool"
|
|
16435
|
+
]),
|
|
16436
|
+
content: z.union([z.string(), z.array(z.any())]),
|
|
16437
|
+
fabFileIds: z.array(z.string()).optional()
|
|
16438
|
+
})).optional(),
|
|
16439
|
+
/** User's timezone (IANA format, e.g., "America/New_York") */
|
|
16440
|
+
timezone: z.string().optional(),
|
|
16441
|
+
/** Persona-based sub-agent filter — only these agent names are available for delegation */
|
|
16442
|
+
allowedAgents: z.array(z.string()).optional(),
|
|
16443
|
+
/** When true, Quest Processor injects Slack-specific tool configs (help, notebooks, curated files) */
|
|
16444
|
+
enableSlackTools: z.boolean().optional()
|
|
16445
|
+
});
|
|
16310
16446
|
(class AnomalyAlertService {
|
|
16311
16447
|
static {
|
|
16312
16448
|
this.MAX_CACHE_ENTRIES = 1e3;
|
|
@@ -23479,4 +23615,234 @@ function createGetFileStructureTool() {
|
|
|
23479
23615
|
};
|
|
23480
23616
|
}
|
|
23481
23617
|
//#endregion
|
|
23482
|
-
|
|
23618
|
+
//#region src/tools/decisionLogTool.ts
|
|
23619
|
+
/**
|
|
23620
|
+
* Validate log_decision parameters
|
|
23621
|
+
* @throws Error if validation fails
|
|
23622
|
+
*/
|
|
23623
|
+
function validateParams(args) {
|
|
23624
|
+
const params = args;
|
|
23625
|
+
if (typeof params.summary !== "string" || params.summary.trim() === "") throw new Error("log_decision: summary must be a non-empty string");
|
|
23626
|
+
if (typeof params.rationale !== "string" || params.rationale.trim() === "") throw new Error("log_decision: rationale must be a non-empty string");
|
|
23627
|
+
if (params.alternatives !== void 0) {
|
|
23628
|
+
if (!Array.isArray(params.alternatives)) throw new Error("log_decision: alternatives must be an array of strings");
|
|
23629
|
+
for (const alt of params.alternatives) if (typeof alt !== "string") throw new Error("log_decision: each alternative must be a string");
|
|
23630
|
+
}
|
|
23631
|
+
if (params.context !== void 0 && typeof params.context !== "string") throw new Error("log_decision: context must be a string");
|
|
23632
|
+
return {
|
|
23633
|
+
summary: params.summary.trim(),
|
|
23634
|
+
rationale: params.rationale.trim(),
|
|
23635
|
+
alternatives: params.alternatives,
|
|
23636
|
+
context: typeof params.context === "string" ? params.context.trim() : void 0
|
|
23637
|
+
};
|
|
23638
|
+
}
|
|
23639
|
+
/**
|
|
23640
|
+
* Format decisions for display output
|
|
23641
|
+
*/
|
|
23642
|
+
function formatDecisionsOutput(decisions) {
|
|
23643
|
+
if (decisions.length === 0) return "No decisions logged in this session.";
|
|
23644
|
+
return decisions.map((decision, index) => {
|
|
23645
|
+
const lines = [`${index + 1}. **${decision.summary}**`, ` Rationale: ${decision.rationale}`];
|
|
23646
|
+
if (decision.alternatives && decision.alternatives.length > 0) lines.push(` Alternatives considered: ${decision.alternatives.join(", ")}`);
|
|
23647
|
+
if (decision.context) lines.push(` Context: ${decision.context}`);
|
|
23648
|
+
const timestamp = new Date(decision.timestamp).toLocaleTimeString();
|
|
23649
|
+
lines.push(` Logged at: ${timestamp}`);
|
|
23650
|
+
return lines.join("\n");
|
|
23651
|
+
}).join("\n\n");
|
|
23652
|
+
}
|
|
23653
|
+
/**
|
|
23654
|
+
* Create the log_decision tool.
|
|
23655
|
+
*
|
|
23656
|
+
* Allows the AI to record significant decisions with rationale during a session.
|
|
23657
|
+
* Decisions are persisted in the session's workflow state for audit trail
|
|
23658
|
+
* and cross-session continuity.
|
|
23659
|
+
*/
|
|
23660
|
+
function createDecisionLogTool(store) {
|
|
23661
|
+
return {
|
|
23662
|
+
toolFn: async (args) => {
|
|
23663
|
+
const params = validateParams(args);
|
|
23664
|
+
const decision = {
|
|
23665
|
+
id: v4(),
|
|
23666
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23667
|
+
summary: params.summary,
|
|
23668
|
+
rationale: params.rationale,
|
|
23669
|
+
alternatives: params.alternatives,
|
|
23670
|
+
context: params.context
|
|
23671
|
+
};
|
|
23672
|
+
store.decisions.push(decision);
|
|
23673
|
+
if (store.onUpdate) store.onUpdate(store.decisions);
|
|
23674
|
+
return `Decision logged (#${store.decisions.length}): ${decision.summary}`;
|
|
23675
|
+
},
|
|
23676
|
+
toolSchema: {
|
|
23677
|
+
name: "log_decision",
|
|
23678
|
+
description: `Record a significant decision with its rationale for audit trail and session continuity.
|
|
23679
|
+
|
|
23680
|
+
**When to use:**
|
|
23681
|
+
- Architecture or design choices (e.g., "chose Zustand over Redux because...")
|
|
23682
|
+
- Scope narrowing or direction changes in research
|
|
23683
|
+
- Trade-off decisions between viable alternatives
|
|
23684
|
+
- Interpretation of ambiguous requirements
|
|
23685
|
+
|
|
23686
|
+
**When NOT to use:**
|
|
23687
|
+
- Routine operations (reading files, running tests)
|
|
23688
|
+
- Trivial choices that wouldn't matter to someone resuming this work
|
|
23689
|
+
- Implementation details that are obvious from the code
|
|
23690
|
+
|
|
23691
|
+
Log decisions that would matter if someone needed to understand WHY you did something.`,
|
|
23692
|
+
parameters: {
|
|
23693
|
+
type: "object",
|
|
23694
|
+
properties: {
|
|
23695
|
+
summary: {
|
|
23696
|
+
type: "string",
|
|
23697
|
+
description: "What was decided — a clear, concise statement"
|
|
23698
|
+
},
|
|
23699
|
+
rationale: {
|
|
23700
|
+
type: "string",
|
|
23701
|
+
description: "Why this decision was made — the reasoning behind it"
|
|
23702
|
+
},
|
|
23703
|
+
alternatives: {
|
|
23704
|
+
type: "array",
|
|
23705
|
+
items: { type: "string" },
|
|
23706
|
+
description: "What alternatives were considered (optional)"
|
|
23707
|
+
},
|
|
23708
|
+
context: {
|
|
23709
|
+
type: "string",
|
|
23710
|
+
description: "What triggered this decision — the situation or constraint (optional)"
|
|
23711
|
+
}
|
|
23712
|
+
},
|
|
23713
|
+
required: ["summary", "rationale"]
|
|
23714
|
+
}
|
|
23715
|
+
}
|
|
23716
|
+
};
|
|
23717
|
+
}
|
|
23718
|
+
/**
|
|
23719
|
+
* Create a new empty DecisionStore
|
|
23720
|
+
*/
|
|
23721
|
+
function createDecisionStore(onUpdate) {
|
|
23722
|
+
return {
|
|
23723
|
+
decisions: [],
|
|
23724
|
+
onUpdate
|
|
23725
|
+
};
|
|
23726
|
+
}
|
|
23727
|
+
//#endregion
|
|
23728
|
+
//#region src/tools/blockerTool.ts
|
|
23729
|
+
/**
|
|
23730
|
+
* Format blockers for display output
|
|
23731
|
+
*/
|
|
23732
|
+
function formatBlockersOutput(blockers) {
|
|
23733
|
+
if (blockers.length === 0) return "No blockers tracked in this session.";
|
|
23734
|
+
const open = blockers.filter((b) => b.status === "open");
|
|
23735
|
+
const resolved = blockers.filter((b) => b.status === "resolved");
|
|
23736
|
+
const lines = [];
|
|
23737
|
+
if (open.length > 0) {
|
|
23738
|
+
lines.push(`**Open blockers (${open.length}):**`);
|
|
23739
|
+
for (const blocker of open) lines.push(` - [${blocker.id.slice(0, 8)}] ${blocker.description}`);
|
|
23740
|
+
}
|
|
23741
|
+
if (resolved.length > 0) {
|
|
23742
|
+
if (open.length > 0) lines.push("");
|
|
23743
|
+
lines.push(`**Resolved blockers (${resolved.length}):**`);
|
|
23744
|
+
for (const blocker of resolved) {
|
|
23745
|
+
lines.push(` - [${blocker.id.slice(0, 8)}] ${blocker.description}`);
|
|
23746
|
+
lines.push(` Resolution: ${blocker.resolution ?? "(no resolution recorded)"}`);
|
|
23747
|
+
}
|
|
23748
|
+
}
|
|
23749
|
+
return lines.join("\n");
|
|
23750
|
+
}
|
|
23751
|
+
/**
|
|
23752
|
+
* Create the track_blocker and resolve_blocker tools.
|
|
23753
|
+
*
|
|
23754
|
+
* Allows the AI to track what's blocking progress and record resolutions.
|
|
23755
|
+
* Blockers are persisted in the session's workflow state for audit trail
|
|
23756
|
+
* and cross-session continuity.
|
|
23757
|
+
*/
|
|
23758
|
+
function createBlockerTools(store) {
|
|
23759
|
+
return [{
|
|
23760
|
+
toolFn: async (args) => {
|
|
23761
|
+
const params = args;
|
|
23762
|
+
if (typeof params.description !== "string" || params.description.trim() === "") throw new Error("track_blocker: description must be a non-empty string");
|
|
23763
|
+
const blocker = {
|
|
23764
|
+
id: v4(),
|
|
23765
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23766
|
+
description: params.description.trim(),
|
|
23767
|
+
status: "open"
|
|
23768
|
+
};
|
|
23769
|
+
store.blockers.push(blocker);
|
|
23770
|
+
if (store.onUpdate) store.onUpdate(store.blockers);
|
|
23771
|
+
const openCount = store.blockers.filter((b) => b.status === "open").length;
|
|
23772
|
+
return `Blocker tracked [${blocker.id.slice(0, 8)}]: ${blocker.description}\n(${openCount} open blocker${openCount === 1 ? "" : "s"})`;
|
|
23773
|
+
},
|
|
23774
|
+
toolSchema: {
|
|
23775
|
+
name: "track_blocker",
|
|
23776
|
+
description: `Track something that is blocking progress.
|
|
23777
|
+
|
|
23778
|
+
**When to use:**
|
|
23779
|
+
- Missing information or unclear requirements
|
|
23780
|
+
- External dependencies (waiting on API access, credentials, data)
|
|
23781
|
+
- Technical constraints discovered during work
|
|
23782
|
+
- Ambiguous requirements that need human clarification
|
|
23783
|
+
|
|
23784
|
+
**When NOT to use:**
|
|
23785
|
+
- Normal challenges that are part of the work
|
|
23786
|
+
- Things you can resolve immediately`,
|
|
23787
|
+
parameters: {
|
|
23788
|
+
type: "object",
|
|
23789
|
+
properties: { description: {
|
|
23790
|
+
type: "string",
|
|
23791
|
+
description: "What is blocking progress — be specific about what is needed to unblock"
|
|
23792
|
+
} },
|
|
23793
|
+
required: ["description"]
|
|
23794
|
+
}
|
|
23795
|
+
}
|
|
23796
|
+
}, {
|
|
23797
|
+
toolFn: async (args) => {
|
|
23798
|
+
const params = args;
|
|
23799
|
+
if (typeof params.blocker_id !== "string" || params.blocker_id.trim() === "") throw new Error("resolve_blocker: blocker_id must be a non-empty string");
|
|
23800
|
+
if (typeof params.resolution !== "string" || params.resolution.trim() === "") throw new Error("resolve_blocker: resolution must be a non-empty string");
|
|
23801
|
+
const blockerId = params.blocker_id.trim();
|
|
23802
|
+
const blocker = store.blockers.find((b) => b.id === blockerId || b.id.startsWith(blockerId));
|
|
23803
|
+
if (!blocker) {
|
|
23804
|
+
const openBlockers = store.blockers.filter((b) => b.status === "open");
|
|
23805
|
+
if (openBlockers.length === 0) return "No open blockers to resolve.";
|
|
23806
|
+
return `Blocker not found. Open blockers:\n${openBlockers.map((b) => ` [${b.id.slice(0, 8)}] ${b.description}`).join("\n")}`;
|
|
23807
|
+
}
|
|
23808
|
+
if (blocker.status === "resolved") return `Blocker [${blocker.id.slice(0, 8)}] is already resolved.`;
|
|
23809
|
+
blocker.status = "resolved";
|
|
23810
|
+
blocker.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
23811
|
+
blocker.resolution = params.resolution.trim();
|
|
23812
|
+
if (store.onUpdate) store.onUpdate(store.blockers);
|
|
23813
|
+
const openCount = store.blockers.filter((b) => b.status === "open").length;
|
|
23814
|
+
return `Blocker resolved [${blocker.id.slice(0, 8)}]: ${blocker.resolution}\n(${openCount} open blocker${openCount === 1 ? "" : "s"} remaining)`;
|
|
23815
|
+
},
|
|
23816
|
+
toolSchema: {
|
|
23817
|
+
name: "resolve_blocker",
|
|
23818
|
+
description: `Mark a blocker as resolved with a description of how it was resolved.
|
|
23819
|
+
|
|
23820
|
+
Use the blocker ID (or its first 8 characters) from the track_blocker output.`,
|
|
23821
|
+
parameters: {
|
|
23822
|
+
type: "object",
|
|
23823
|
+
properties: {
|
|
23824
|
+
blocker_id: {
|
|
23825
|
+
type: "string",
|
|
23826
|
+
description: "The ID of the blocker to resolve (full ID or first 8 characters)"
|
|
23827
|
+
},
|
|
23828
|
+
resolution: {
|
|
23829
|
+
type: "string",
|
|
23830
|
+
description: "How the blocker was resolved"
|
|
23831
|
+
}
|
|
23832
|
+
},
|
|
23833
|
+
required: ["blocker_id", "resolution"]
|
|
23834
|
+
}
|
|
23835
|
+
}
|
|
23836
|
+
}];
|
|
23837
|
+
}
|
|
23838
|
+
/**
|
|
23839
|
+
* Create a new empty BlockerStore
|
|
23840
|
+
*/
|
|
23841
|
+
function createBlockerStore(onUpdate) {
|
|
23842
|
+
return {
|
|
23843
|
+
blockers: [],
|
|
23844
|
+
onUpdate
|
|
23845
|
+
};
|
|
23846
|
+
}
|
|
23847
|
+
//#endregion
|
|
23848
|
+
export { processFileReferences as $, getApiUrl as A, registerFeatureModuleTools as B, WebSocketLlmBackend as C, formatStep as D, substituteArguments as E, DEFAULT_AGENT_MODEL as F, isReadOnlyTool as G, OllamaBackend as H, DEFAULT_MAX_ITERATIONS as I, CheckpointStore as J, ReActAgent as K, DEFAULT_RETRY_CONFIG as L, PermissionManager as M, generateCliTools as N, extractCompactInstructions as O, ALWAYS_DENIED_FOR_AGENTS as P, hasFileReferences as Q, DEFAULT_THOROUGHNESS as R, FallbackLlmBackend as S, McpManager as T, buildCoreSystemPrompt as U, setWebSocketToolExecutor as V, buildSkillsPromptSection as W, SessionStore as X, CommandHistoryStore as Y, OAuthClient as Z, createSkillTool as _, createDecisionStore as a, WebSocketToolExecutor as b, createFindDefinitionTool as c, createCoordinateTaskTool as d, searchCommands as et, createBackgroundAgentTools as f, SubagentOrchestrator as g, AgentStore as h, createDecisionLogTool as i, warmFileCache as it, getEnvironmentName as j, loadContextFiles as k, createTodoStore as l, createAgentDelegateTool as m, createBlockerTools as n, formatFileSize$1 as nt, formatDecisionsOutput as o, BackgroundAgentManager as p, CustomCommandStore as q, formatBlockersOutput as r, searchFiles as rt, createGetFileStructureTool as s, createBlockerStore as t, mergeCommands as tt, createWriteTodosTool as u, parseAgentConfig as v, ServerLlmBackend as w, WebSocketConnectionManager as x, ApiClient as y, clearFeatureModuleTools as z };
|