@bike4mind/cli 0.2.20-feat-web-fetch-tool.18049 → 0.2.20-feat-cli-smart-stream-logging.18065
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/bin/bike4mind-cli.mjs +10 -0
- package/dist/{artifactExtractor-HVF42WXK.js → artifactExtractor-4EVH663R.js} +1 -1
- package/dist/{chunk-V2UQMO2S.js → chunk-AKCBPXLX.js} +2 -2
- package/dist/{chunk-T5NXFTZC.js → chunk-DTPBHKQL.js} +232 -3
- package/dist/{chunk-VAFY6X3M.js → chunk-EP4OGIQI.js} +57 -4
- package/dist/{chunk-NAZHGW73.js → chunk-RRYX2K7W.js} +2 -2
- package/dist/{chunk-W5U65OA2.js → chunk-XWI42ILN.js} +2 -2
- package/dist/{create-2H5YR4KE.js → create-KAKBAGES.js} +3 -3
- package/dist/index.js +190 -128
- package/dist/{llmMarkdownGenerator-UU65W336.js → llmMarkdownGenerator-CSIFMRI3.js} +1 -1
- package/dist/{markdownGenerator-EUNRHSE3.js → markdownGenerator-5L737COC.js} +1 -1
- package/dist/{mementoService-TBB3M45P.js → mementoService-7OF7S4V3.js} +3 -3
- package/dist/{src-MLAUU67W.js → src-TO27QQZM.js} +2 -2
- package/dist/{src-FQOHXWN2.js → src-ZECC33CL.js} +5 -1
- package/dist/{subtractCredits-OKODPLEC.js → subtractCredits-MGHZAPOE.js} +3 -3
- package/package.json +6 -6
package/bin/bike4mind-cli.mjs
CHANGED
|
@@ -36,6 +36,11 @@ const argv = await yargs(hideBin(process.argv))
|
|
|
36
36
|
description: 'Show debug logs in console',
|
|
37
37
|
default: false,
|
|
38
38
|
})
|
|
39
|
+
.option('debug-stream', {
|
|
40
|
+
type: 'boolean',
|
|
41
|
+
description: 'Ultra-verbose: log every SSE event (for debugging stream parser)',
|
|
42
|
+
default: false,
|
|
43
|
+
})
|
|
39
44
|
.option('no-project-config', {
|
|
40
45
|
type: 'boolean',
|
|
41
46
|
description: 'Disable loading project-specific configuration (.bike4mind/)',
|
|
@@ -94,6 +99,11 @@ if (argv.verbose) {
|
|
|
94
99
|
process.env.B4M_VERBOSE = '1';
|
|
95
100
|
process.env.LOG_LEVEL = 'debug'; // Enable debug logs in core packages
|
|
96
101
|
}
|
|
102
|
+
if (argv['debug-stream']) {
|
|
103
|
+
process.env.B4M_DEBUG_STREAM = '1';
|
|
104
|
+
process.env.B4M_VERBOSE = '1'; // Ultra-verbose implies verbose
|
|
105
|
+
process.env.LOG_LEVEL = 'debug';
|
|
106
|
+
}
|
|
97
107
|
if (argv['no-project-config']) {
|
|
98
108
|
process.env.B4M_NO_PROJECT_CONFIG = '1';
|
|
99
109
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
CurationArtifactType
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DTPBHKQL.js";
|
|
5
5
|
|
|
6
6
|
// ../../b4m-core/packages/services/dist/src/notebookCurationService/artifactExtractor.js
|
|
7
7
|
var ARTIFACT_TAG_REGEX = /<artifact\s+(.*?)>([\s\S]*?)<\/artifact>/gi;
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
getSettingsMap,
|
|
8
8
|
getSettingsValue,
|
|
9
9
|
secureParameters
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-EP4OGIQI.js";
|
|
11
11
|
import {
|
|
12
12
|
KnowledgeType,
|
|
13
13
|
SupportedFabFileMimeTypes
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-DTPBHKQL.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/fabFileService/create.js
|
|
17
17
|
import { z } from "zod";
|
|
@@ -209,7 +209,6 @@ var b4mLLMTools = z3.enum([
|
|
|
209
209
|
"edit_image",
|
|
210
210
|
"weather_info",
|
|
211
211
|
"web_search",
|
|
212
|
-
"web_fetch",
|
|
213
212
|
"math_evaluate",
|
|
214
213
|
"mermaid_chart",
|
|
215
214
|
"current_datetime",
|
|
@@ -4667,8 +4666,66 @@ function formatPageList(pagesResponse, siteUrl) {
|
|
|
4667
4666
|
results
|
|
4668
4667
|
};
|
|
4669
4668
|
}
|
|
4669
|
+
function formatPageRestrictions(restrictionsResponse, pageId) {
|
|
4670
|
+
if (!restrictionsResponse || typeof restrictionsResponse !== "object" || restrictionsResponse.error) {
|
|
4671
|
+
return {
|
|
4672
|
+
pageId,
|
|
4673
|
+
hasRestrictions: false,
|
|
4674
|
+
restrictions: []
|
|
4675
|
+
};
|
|
4676
|
+
}
|
|
4677
|
+
const restrictions = [];
|
|
4678
|
+
const operationsMap = {};
|
|
4679
|
+
if (Array.isArray(restrictionsResponse.results)) {
|
|
4680
|
+
for (const item of restrictionsResponse.results) {
|
|
4681
|
+
if (item.operation && item.restrictions) {
|
|
4682
|
+
operationsMap[item.operation] = item;
|
|
4683
|
+
}
|
|
4684
|
+
}
|
|
4685
|
+
} else {
|
|
4686
|
+
for (const operation of RESTRICTION_OPERATIONS) {
|
|
4687
|
+
if (restrictionsResponse[operation]) {
|
|
4688
|
+
operationsMap[operation] = restrictionsResponse[operation];
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4691
|
+
}
|
|
4692
|
+
for (const [operation, opData] of Object.entries(operationsMap)) {
|
|
4693
|
+
if (!opData?.restrictions)
|
|
4694
|
+
continue;
|
|
4695
|
+
const subjects = [];
|
|
4696
|
+
const users = opData.restrictions.user?.results || opData.restrictions.user || [];
|
|
4697
|
+
for (const user of users) {
|
|
4698
|
+
subjects.push({
|
|
4699
|
+
type: "user",
|
|
4700
|
+
identifier: user.accountId || user.username || user.key,
|
|
4701
|
+
displayName: user.displayName || user.publicName
|
|
4702
|
+
});
|
|
4703
|
+
}
|
|
4704
|
+
const groups = opData.restrictions.group?.results || opData.restrictions.group || [];
|
|
4705
|
+
for (const group of groups) {
|
|
4706
|
+
subjects.push({
|
|
4707
|
+
type: "group",
|
|
4708
|
+
identifier: group.name || group.id,
|
|
4709
|
+
displayName: group.name
|
|
4710
|
+
});
|
|
4711
|
+
}
|
|
4712
|
+
if (subjects.length > 0) {
|
|
4713
|
+
restrictions.push({
|
|
4714
|
+
operation,
|
|
4715
|
+
subjects
|
|
4716
|
+
});
|
|
4717
|
+
}
|
|
4718
|
+
}
|
|
4719
|
+
return {
|
|
4720
|
+
pageId,
|
|
4721
|
+
hasRestrictions: restrictions.length > 0,
|
|
4722
|
+
restrictions
|
|
4723
|
+
};
|
|
4724
|
+
}
|
|
4670
4725
|
|
|
4671
4726
|
// ../../b4m-core/packages/common/dist/src/confluence/api.js
|
|
4727
|
+
var RESTRICTION_OPERATIONS = ["read", "update"];
|
|
4728
|
+
var RESTRICTION_SUBJECT_TYPES = ["user", "group"];
|
|
4672
4729
|
var ConfluenceApi = class {
|
|
4673
4730
|
config;
|
|
4674
4731
|
constructor(config) {
|
|
@@ -4735,11 +4792,15 @@ var ConfluenceApi = class {
|
|
|
4735
4792
|
if (response.status === 204) {
|
|
4736
4793
|
return void 0;
|
|
4737
4794
|
}
|
|
4795
|
+
const responseText = await response.text();
|
|
4796
|
+
if (!responseText || responseText.trim() === "") {
|
|
4797
|
+
return void 0;
|
|
4798
|
+
}
|
|
4738
4799
|
const contentType = response.headers.get("content-type") || "";
|
|
4739
4800
|
if (contentType.includes("application/json")) {
|
|
4740
|
-
return
|
|
4801
|
+
return JSON.parse(responseText);
|
|
4741
4802
|
}
|
|
4742
|
-
return
|
|
4803
|
+
return responseText;
|
|
4743
4804
|
}
|
|
4744
4805
|
/**
|
|
4745
4806
|
* Make v1 API request
|
|
@@ -4942,6 +5003,17 @@ var ConfluenceApi = class {
|
|
|
4942
5003
|
}
|
|
4943
5004
|
return formatSpaceResponse(results[0], this.config.siteUrl);
|
|
4944
5005
|
}
|
|
5006
|
+
/**
|
|
5007
|
+
* Get details about a specific Confluence space by ID (v2 API)
|
|
5008
|
+
*/
|
|
5009
|
+
async getSpaceById(params) {
|
|
5010
|
+
const { spaceId } = params;
|
|
5011
|
+
if (!spaceId) {
|
|
5012
|
+
throw new Error("spaceId is required to fetch space details.");
|
|
5013
|
+
}
|
|
5014
|
+
const space = await this.get(`/spaces/${spaceId}`);
|
|
5015
|
+
return formatSpaceResponse(space, this.config.siteUrl);
|
|
5016
|
+
}
|
|
4945
5017
|
/**
|
|
4946
5018
|
* Get child pages for a given page
|
|
4947
5019
|
*/
|
|
@@ -5177,6 +5249,161 @@ var ConfluenceApi = class {
|
|
|
5177
5249
|
throw error;
|
|
5178
5250
|
}
|
|
5179
5251
|
}
|
|
5252
|
+
// ============================================================================
|
|
5253
|
+
// Page Restrictions API (v1)
|
|
5254
|
+
// ============================================================================
|
|
5255
|
+
/**
|
|
5256
|
+
* Validate that a user exists by account ID
|
|
5257
|
+
* @throws Error if user does not exist
|
|
5258
|
+
*/
|
|
5259
|
+
async validateUserExists(accountId) {
|
|
5260
|
+
try {
|
|
5261
|
+
const user = await this.getV1("/user", { accountId });
|
|
5262
|
+
if (!user || user.error) {
|
|
5263
|
+
throw new Error(`User with account ID "${accountId}" not found.`);
|
|
5264
|
+
}
|
|
5265
|
+
return {
|
|
5266
|
+
accountId: user.accountId,
|
|
5267
|
+
displayName: user.displayName || user.publicName || accountId
|
|
5268
|
+
};
|
|
5269
|
+
} catch (error) {
|
|
5270
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
5271
|
+
throw error;
|
|
5272
|
+
}
|
|
5273
|
+
throw new Error(`User with account ID "${accountId}" not found or access denied.`);
|
|
5274
|
+
}
|
|
5275
|
+
}
|
|
5276
|
+
/**
|
|
5277
|
+
* Validate that a group exists by name
|
|
5278
|
+
* @throws Error if group does not exist
|
|
5279
|
+
*/
|
|
5280
|
+
async validateGroupExists(groupName) {
|
|
5281
|
+
try {
|
|
5282
|
+
const group = await this.getV1(`/group/${encodeURIComponent(groupName)}`);
|
|
5283
|
+
if (!group || group.error) {
|
|
5284
|
+
throw new Error(`Group "${groupName}" not found.`);
|
|
5285
|
+
}
|
|
5286
|
+
return { name: group.name || groupName };
|
|
5287
|
+
} catch (error) {
|
|
5288
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
5289
|
+
throw error;
|
|
5290
|
+
}
|
|
5291
|
+
throw new Error(`Group "${groupName}" not found or access denied.`);
|
|
5292
|
+
}
|
|
5293
|
+
}
|
|
5294
|
+
/**
|
|
5295
|
+
* Get current restrictions for a Confluence page
|
|
5296
|
+
*/
|
|
5297
|
+
async getPageRestrictions(params) {
|
|
5298
|
+
const { pageId } = params;
|
|
5299
|
+
if (!pageId) {
|
|
5300
|
+
throw new Error("pageId is required to get page restrictions.");
|
|
5301
|
+
}
|
|
5302
|
+
const result = await this.getV1(`/content/${pageId}/restriction`, {
|
|
5303
|
+
expand: "restrictions.user,restrictions.group"
|
|
5304
|
+
});
|
|
5305
|
+
return formatPageRestrictions(result, pageId);
|
|
5306
|
+
}
|
|
5307
|
+
/**
|
|
5308
|
+
* Add a restriction to a Confluence page
|
|
5309
|
+
* Validates that the user/group exists before applying the restriction.
|
|
5310
|
+
* Automatically includes the current user in restrictions to prevent self-lockout.
|
|
5311
|
+
*/
|
|
5312
|
+
async addPageRestriction(params) {
|
|
5313
|
+
const { pageId, operation, restrictionType, subject, skipValidation = false } = params;
|
|
5314
|
+
if (!pageId || !operation || !restrictionType || !subject) {
|
|
5315
|
+
throw new Error("pageId, operation, restrictionType, and subject are required to add a page restriction.");
|
|
5316
|
+
}
|
|
5317
|
+
let subjectDisplayName;
|
|
5318
|
+
if (!skipValidation) {
|
|
5319
|
+
if (restrictionType === "user") {
|
|
5320
|
+
const userInfo = await this.validateUserExists(subject);
|
|
5321
|
+
subjectDisplayName = userInfo.displayName;
|
|
5322
|
+
} else {
|
|
5323
|
+
const groupInfo = await this.validateGroupExists(subject);
|
|
5324
|
+
subjectDisplayName = groupInfo.name;
|
|
5325
|
+
}
|
|
5326
|
+
}
|
|
5327
|
+
const currentUser = await this.getCurrentUser();
|
|
5328
|
+
const currentUserAccountId = currentUser.accountId;
|
|
5329
|
+
if (!currentUserAccountId) {
|
|
5330
|
+
throw new Error("Unable to determine current user account ID. Cannot add restrictions safely.");
|
|
5331
|
+
}
|
|
5332
|
+
const userList = [];
|
|
5333
|
+
userList.push({ accountId: currentUserAccountId });
|
|
5334
|
+
if (restrictionType === "user" && subject !== currentUserAccountId) {
|
|
5335
|
+
userList.push({ accountId: subject });
|
|
5336
|
+
}
|
|
5337
|
+
const restrictionPayload = [
|
|
5338
|
+
{
|
|
5339
|
+
operation,
|
|
5340
|
+
restrictions: {
|
|
5341
|
+
user: userList,
|
|
5342
|
+
...restrictionType === "group" ? { group: [{ name: subject }] } : {}
|
|
5343
|
+
}
|
|
5344
|
+
}
|
|
5345
|
+
];
|
|
5346
|
+
await this.postV1(`/content/${pageId}/restriction`, restrictionPayload);
|
|
5347
|
+
return {
|
|
5348
|
+
success: true,
|
|
5349
|
+
pageId,
|
|
5350
|
+
operation,
|
|
5351
|
+
restrictionType,
|
|
5352
|
+
subject,
|
|
5353
|
+
subjectDisplayName
|
|
5354
|
+
};
|
|
5355
|
+
}
|
|
5356
|
+
/**
|
|
5357
|
+
* Remove a restriction from a Confluence page
|
|
5358
|
+
* First checks if the restriction exists to avoid 404 errors
|
|
5359
|
+
*/
|
|
5360
|
+
async removePageRestriction(params) {
|
|
5361
|
+
const { pageId, operation, restrictionType, subject } = params;
|
|
5362
|
+
if (!pageId || !operation || !restrictionType || !subject) {
|
|
5363
|
+
throw new Error("pageId, operation, restrictionType, and subject are required to remove a page restriction.");
|
|
5364
|
+
}
|
|
5365
|
+
const currentRestrictions = await this.getPageRestrictions({ pageId });
|
|
5366
|
+
const operationRestriction = currentRestrictions.restrictions.find((r) => r.operation === operation);
|
|
5367
|
+
if (!operationRestriction) {
|
|
5368
|
+
return {
|
|
5369
|
+
success: true,
|
|
5370
|
+
pageId,
|
|
5371
|
+
operation,
|
|
5372
|
+
restrictionType,
|
|
5373
|
+
subject,
|
|
5374
|
+
skipped: true,
|
|
5375
|
+
message: `No ${operation} restrictions exist on this page.`
|
|
5376
|
+
};
|
|
5377
|
+
}
|
|
5378
|
+
const subjectExists = operationRestriction.subjects.some((s) => s.type === restrictionType && s.identifier === subject);
|
|
5379
|
+
if (!subjectExists) {
|
|
5380
|
+
return {
|
|
5381
|
+
success: true,
|
|
5382
|
+
pageId,
|
|
5383
|
+
operation,
|
|
5384
|
+
restrictionType,
|
|
5385
|
+
subject,
|
|
5386
|
+
skipped: true,
|
|
5387
|
+
message: `Restriction for ${restrictionType} "${subject}" on ${operation} operation does not exist.`
|
|
5388
|
+
};
|
|
5389
|
+
}
|
|
5390
|
+
let deletePath;
|
|
5391
|
+
let deleteQuery;
|
|
5392
|
+
if (restrictionType === "user") {
|
|
5393
|
+
deletePath = `/content/${pageId}/restriction/byOperation/${operation}/user`;
|
|
5394
|
+
deleteQuery = { accountId: subject };
|
|
5395
|
+
} else {
|
|
5396
|
+
deletePath = `/content/${pageId}/restriction/byOperation/${operation}/group/${encodeURIComponent(subject)}`;
|
|
5397
|
+
}
|
|
5398
|
+
await this.request("DELETE", deletePath, { query: deleteQuery, useV1: true });
|
|
5399
|
+
return {
|
|
5400
|
+
success: true,
|
|
5401
|
+
pageId,
|
|
5402
|
+
operation,
|
|
5403
|
+
restrictionType,
|
|
5404
|
+
subject
|
|
5405
|
+
};
|
|
5406
|
+
}
|
|
5180
5407
|
};
|
|
5181
5408
|
|
|
5182
5409
|
// ../../b4m-core/packages/common/dist/src/jira/format.js
|
|
@@ -6836,6 +7063,8 @@ export {
|
|
|
6836
7063
|
extractSnippetMeta,
|
|
6837
7064
|
searchSchema,
|
|
6838
7065
|
LinkedInApi,
|
|
7066
|
+
RESTRICTION_OPERATIONS,
|
|
7067
|
+
RESTRICTION_SUBJECT_TYPES,
|
|
6839
7068
|
ConfluenceApi,
|
|
6840
7069
|
formatIssueResponse,
|
|
6841
7070
|
formatProjectResponse,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
dayjsConfig_default,
|
|
14
14
|
extractSnippetMeta,
|
|
15
15
|
settingsMap
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-DTPBHKQL.js";
|
|
17
17
|
import {
|
|
18
18
|
Logger
|
|
19
19
|
} from "./chunk-OCYRD7D6.js";
|
|
@@ -205,7 +205,8 @@ function obfuscateApiKey(apiKey) {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
// ../../b4m-core/packages/utils/dist/src/llm/anthropicBackend.js
|
|
208
|
-
import { Anthropic } from "@anthropic-ai/sdk";
|
|
208
|
+
import { Anthropic, RateLimitError } from "@anthropic-ai/sdk";
|
|
209
|
+
import { CloudWatchClient, PutMetricDataCommand, StandardUnit } from "@aws-sdk/client-cloudwatch";
|
|
209
210
|
|
|
210
211
|
// ../../b4m-core/packages/utils/dist/src/llm/backend.js
|
|
211
212
|
var DEFAULT_MAX_TOOL_CALLS = 10;
|
|
@@ -1952,9 +1953,44 @@ var AnthropicBackend = class {
|
|
|
1952
1953
|
isThinkingEnabled = false;
|
|
1953
1954
|
// Track if thinking is enabled for current request
|
|
1954
1955
|
constructor(apiKey, logger) {
|
|
1955
|
-
this._api = new Anthropic({ apiKey });
|
|
1956
|
+
this._api = new Anthropic({ apiKey, maxRetries: 5 });
|
|
1956
1957
|
this.logger = logger ?? new Logger();
|
|
1957
1958
|
}
|
|
1959
|
+
/**
|
|
1960
|
+
* Emit a CloudWatch metric when a rate limit error occurs.
|
|
1961
|
+
* This helps monitor and alert on Anthropic API rate limiting issues.
|
|
1962
|
+
*/
|
|
1963
|
+
async emitRateLimitMetric(model) {
|
|
1964
|
+
try {
|
|
1965
|
+
const client = new CloudWatchClient({
|
|
1966
|
+
region: process.env.AWS_REGION || "us-east-2"
|
|
1967
|
+
});
|
|
1968
|
+
const command = new PutMetricDataCommand({
|
|
1969
|
+
Namespace: "Lumina5/AnthropicAPI",
|
|
1970
|
+
MetricData: [
|
|
1971
|
+
{
|
|
1972
|
+
MetricName: "RateLimitError",
|
|
1973
|
+
Value: 1,
|
|
1974
|
+
Unit: StandardUnit.Count,
|
|
1975
|
+
Timestamp: /* @__PURE__ */ new Date(),
|
|
1976
|
+
Dimensions: [
|
|
1977
|
+
{ Name: "Model", Value: model },
|
|
1978
|
+
// SEED_STAGE_NAME is set via DEFAULT_LAMBDA_ENVIRONMENT in infra/constants.ts
|
|
1979
|
+
// and maps to $app.stage. The alarm in infra/alarms.ts filters by Stage dimension.
|
|
1980
|
+
// Fallback to 'local' for non-Lambda contexts (local dev, tests).
|
|
1981
|
+
{ Name: "Stage", Value: process.env.SEED_STAGE_NAME || "local" }
|
|
1982
|
+
]
|
|
1983
|
+
}
|
|
1984
|
+
]
|
|
1985
|
+
});
|
|
1986
|
+
await client.send(command);
|
|
1987
|
+
this.logger.info("[AnthropicBackend] Emitted RateLimitError metric to CloudWatch", { model });
|
|
1988
|
+
} catch (metricsError) {
|
|
1989
|
+
this.logger.warn("[AnthropicBackend] Failed to emit CloudWatch metric", {
|
|
1990
|
+
error: metricsError instanceof Error ? metricsError.message : String(metricsError)
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1958
1994
|
/**
|
|
1959
1995
|
* Get thinking blocks from the last assistant content.
|
|
1960
1996
|
* Filters to only include thinking/redacted_thinking blocks.
|
|
@@ -2368,6 +2404,13 @@ var AnthropicBackend = class {
|
|
|
2368
2404
|
}
|
|
2369
2405
|
const hasToolsToExecute = func.some((f) => f && f.name);
|
|
2370
2406
|
if (!hasToolsToExecute) {
|
|
2407
|
+
if (options.tools && options.tools.length > 0) {
|
|
2408
|
+
const mcpToolCount = options.tools.filter((t) => t._isMcpTool).length;
|
|
2409
|
+
const hasContent = collectedContent.some((c) => c?.type === "text" && c?.text?.trim());
|
|
2410
|
+
if (!hasContent && mcpToolCount > 0) {
|
|
2411
|
+
this.logger.warn(`\u26A0\uFE0F [AnthropicBackend] Model returned empty content with ${mcpToolCount} MCP tools available. Total tools: ${options.tools.length}. This may indicate tool overload or model confusion.`);
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2371
2414
|
await cb([], { toolsUsed });
|
|
2372
2415
|
}
|
|
2373
2416
|
resolve();
|
|
@@ -2523,7 +2566,17 @@ var AnthropicBackend = class {
|
|
|
2523
2566
|
}
|
|
2524
2567
|
}
|
|
2525
2568
|
} catch (error) {
|
|
2526
|
-
|
|
2569
|
+
if (error instanceof RateLimitError) {
|
|
2570
|
+
this.logger.error("[AnthropicBackend] Rate limit error after all retries exhausted", {
|
|
2571
|
+
model,
|
|
2572
|
+
status: error.status,
|
|
2573
|
+
message: error.message
|
|
2574
|
+
});
|
|
2575
|
+
this.emitRateLimitMetric(model).catch(() => {
|
|
2576
|
+
});
|
|
2577
|
+
} else {
|
|
2578
|
+
this.logger.debug("Error in complete:", error);
|
|
2579
|
+
}
|
|
2527
2580
|
throw error;
|
|
2528
2581
|
}
|
|
2529
2582
|
}
|
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
getSettingsByNames,
|
|
7
7
|
obfuscateApiKey,
|
|
8
8
|
secureParameters
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-EP4OGIQI.js";
|
|
10
10
|
import {
|
|
11
11
|
ApiKeyType,
|
|
12
12
|
MementoTier,
|
|
13
13
|
isSupportedEmbeddingModel
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-DTPBHKQL.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/apiKeyService/get.js
|
|
17
17
|
import { z } from "zod";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BadRequestError,
|
|
4
4
|
secureParameters
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-EP4OGIQI.js";
|
|
6
6
|
import {
|
|
7
7
|
CompletionApiUsageTransaction,
|
|
8
8
|
GenericCreditDeductTransaction,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
RealtimeVoiceUsageTransaction,
|
|
12
12
|
TextGenerationUsageTransaction,
|
|
13
13
|
TransferCreditTransaction
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-DTPBHKQL.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/creditService/subtractCredits.js
|
|
17
17
|
import { z } from "zod";
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createFabFile,
|
|
4
4
|
createFabFileSchema
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-AKCBPXLX.js";
|
|
6
|
+
import "./chunk-EP4OGIQI.js";
|
|
7
|
+
import "./chunk-DTPBHKQL.js";
|
|
8
8
|
import "./chunk-OCYRD7D6.js";
|
|
9
9
|
export {
|
|
10
10
|
createFabFile,
|
package/dist/index.js
CHANGED
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
getEffectiveApiKey,
|
|
5
5
|
getOpenWeatherKey,
|
|
6
6
|
getSerperKey
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RRYX2K7W.js";
|
|
8
8
|
import {
|
|
9
9
|
ConfigStore
|
|
10
10
|
} from "./chunk-VFQF2JIT.js";
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-XWI42ILN.js";
|
|
12
|
+
import "./chunk-AKCBPXLX.js";
|
|
13
13
|
import {
|
|
14
14
|
BFLImageService,
|
|
15
15
|
BaseStorage,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
OpenAIBackend,
|
|
22
22
|
OpenAIImageService,
|
|
23
23
|
XAIImageService
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-EP4OGIQI.js";
|
|
25
25
|
import {
|
|
26
26
|
AiEvents,
|
|
27
27
|
ApiKeyEvents,
|
|
@@ -75,7 +75,7 @@ import {
|
|
|
75
75
|
XAI_IMAGE_MODELS,
|
|
76
76
|
b4mLLMTools,
|
|
77
77
|
getMcpProviderMetadata
|
|
78
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-DTPBHKQL.js";
|
|
79
79
|
import {
|
|
80
80
|
Logger
|
|
81
81
|
} from "./chunk-OCYRD7D6.js";
|
|
@@ -5608,7 +5608,7 @@ var webSearchTool = {
|
|
|
5608
5608
|
},
|
|
5609
5609
|
toolSchema: {
|
|
5610
5610
|
name: "web_search",
|
|
5611
|
-
description: "Search the web using Google Search API
|
|
5611
|
+
description: "Search the web using Google Search API",
|
|
5612
5612
|
parameters: {
|
|
5613
5613
|
type: "object",
|
|
5614
5614
|
properties: {
|
|
@@ -5629,109 +5629,6 @@ var webSearchTool = {
|
|
|
5629
5629
|
})
|
|
5630
5630
|
};
|
|
5631
5631
|
|
|
5632
|
-
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/webfetch/index.js
|
|
5633
|
-
import FirecrawlApp2 from "@mendable/firecrawl-js";
|
|
5634
|
-
async function firecrawlFetch(adapters, url) {
|
|
5635
|
-
const urlPattern = /^https?:\/\/.+/i;
|
|
5636
|
-
if (!urlPattern.test(url)) {
|
|
5637
|
-
throw new Error(`Invalid URL format: ${url}. URL must start with http:// or https://`);
|
|
5638
|
-
}
|
|
5639
|
-
const apiKeySetting = await adapters.db.adminSettings.findBySettingName("FirecrawlApiKey");
|
|
5640
|
-
if (!apiKeySetting?.settingValue) {
|
|
5641
|
-
console.error("\u274C WebFetch Tool: Firecrawl API key not configured");
|
|
5642
|
-
throw new Error("Firecrawl API key not configured");
|
|
5643
|
-
}
|
|
5644
|
-
const app = new FirecrawlApp2({ apiKey: apiKeySetting.settingValue });
|
|
5645
|
-
const controller = new AbortController();
|
|
5646
|
-
const timeoutId = setTimeout(() => controller.abort(), 6e4);
|
|
5647
|
-
try {
|
|
5648
|
-
console.log("\u{1F4E5} WebFetch Tool: Scraping URL with Firecrawl...");
|
|
5649
|
-
const result = await app.scrapeUrl(url, {
|
|
5650
|
-
formats: ["markdown"],
|
|
5651
|
-
actions: [
|
|
5652
|
-
{
|
|
5653
|
-
type: "wait",
|
|
5654
|
-
milliseconds: 1e3
|
|
5655
|
-
// Wait for JavaScript to execute
|
|
5656
|
-
}
|
|
5657
|
-
]
|
|
5658
|
-
});
|
|
5659
|
-
clearTimeout(timeoutId);
|
|
5660
|
-
if (!result || result.error) {
|
|
5661
|
-
const errorMessage = result?.error || "Unknown error";
|
|
5662
|
-
console.error("\u274C WebFetch Tool: Firecrawl error:", errorMessage);
|
|
5663
|
-
throw new Error(`Failed to fetch content from URL: ${errorMessage}`);
|
|
5664
|
-
}
|
|
5665
|
-
if (!("markdown" in result) || !result.markdown) {
|
|
5666
|
-
console.error("\u274C WebFetch Tool: No markdown content returned");
|
|
5667
|
-
throw new Error("No content could be extracted from the URL");
|
|
5668
|
-
}
|
|
5669
|
-
const markdown = result.markdown.slice(0, 5e4);
|
|
5670
|
-
console.log(`\u{1F4C4} WebFetch Tool: Extracted ${markdown.length} characters of content`);
|
|
5671
|
-
return {
|
|
5672
|
-
markdown,
|
|
5673
|
-
title: result.metadata?.title
|
|
5674
|
-
};
|
|
5675
|
-
} catch (error) {
|
|
5676
|
-
clearTimeout(timeoutId);
|
|
5677
|
-
throw error;
|
|
5678
|
-
}
|
|
5679
|
-
}
|
|
5680
|
-
var webFetchTool = {
|
|
5681
|
-
name: "web_fetch",
|
|
5682
|
-
implementation: (context) => ({
|
|
5683
|
-
toolFn: async (value) => {
|
|
5684
|
-
const params = value;
|
|
5685
|
-
console.log("\u{1F310} WebFetch Tool: Starting fetch for URL:", params.url);
|
|
5686
|
-
try {
|
|
5687
|
-
await context.statusUpdate({}, `Fetching content from ${params.url}...`);
|
|
5688
|
-
const result = await firecrawlFetch({ db: context.db }, params.url);
|
|
5689
|
-
const citable = {
|
|
5690
|
-
id: params.url,
|
|
5691
|
-
type: "web_url",
|
|
5692
|
-
title: result.title || params.url,
|
|
5693
|
-
url: params.url,
|
|
5694
|
-
description: result.markdown.slice(0, 200) + (result.markdown.length > 200 ? "..." : ""),
|
|
5695
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5696
|
-
status: "complete",
|
|
5697
|
-
metadata: {
|
|
5698
|
-
sourceSystem: "web_fetch",
|
|
5699
|
-
contentLength: result.markdown.length
|
|
5700
|
-
}
|
|
5701
|
-
};
|
|
5702
|
-
await context.statusUpdate({
|
|
5703
|
-
promptMeta: {
|
|
5704
|
-
citables: [citable]
|
|
5705
|
-
}
|
|
5706
|
-
}, "WebFetch completed successfully");
|
|
5707
|
-
console.log(`\u{1F4DA} WebFetch Tool: Stored citable source for ${params.url}`);
|
|
5708
|
-
return result.markdown;
|
|
5709
|
-
} catch (error) {
|
|
5710
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
5711
|
-
console.error("\u274C WebFetch Tool: Error during fetch:", error);
|
|
5712
|
-
await context.statusUpdate({}, `WebFetch failed: ${errorMessage}`);
|
|
5713
|
-
context.logger.error("WebFetch error:", error);
|
|
5714
|
-
throw error;
|
|
5715
|
-
}
|
|
5716
|
-
},
|
|
5717
|
-
toolSchema: {
|
|
5718
|
-
name: "web_fetch",
|
|
5719
|
-
description: 'Fetches and reads the FULL CONTENT of a specific URL that the user provides. Use this when the user gives you a direct URL link (e.g., "fetch https://example.com", "read this article https://...", "summarize the content at https://..."). This tool downloads the entire page content and converts it to markdown for you to read. You can then answer questions, summarize, or extract information from the content yourself. DO NOT use web_search when the user provides a specific URL - always use web_fetch instead.',
|
|
5720
|
-
parameters: {
|
|
5721
|
-
type: "object",
|
|
5722
|
-
properties: {
|
|
5723
|
-
url: {
|
|
5724
|
-
type: "string",
|
|
5725
|
-
format: "uri",
|
|
5726
|
-
description: "The URL to fetch content from (must be http or https)"
|
|
5727
|
-
}
|
|
5728
|
-
},
|
|
5729
|
-
required: ["url"]
|
|
5730
|
-
}
|
|
5731
|
-
}
|
|
5732
|
-
})
|
|
5733
|
-
};
|
|
5734
|
-
|
|
5735
5632
|
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/math/index.js
|
|
5736
5633
|
import { create as create6, all } from "mathjs";
|
|
5737
5634
|
var math = create6(all, {
|
|
@@ -9631,7 +9528,6 @@ var tools = {
|
|
|
9631
9528
|
image_generation: imageGenerationTool,
|
|
9632
9529
|
edit_image: imageEditTool,
|
|
9633
9530
|
web_search: webSearchTool,
|
|
9634
|
-
web_fetch: webFetchTool,
|
|
9635
9531
|
math_evaluate: mathTool,
|
|
9636
9532
|
mermaid_chart: mermaidChartTool,
|
|
9637
9533
|
current_datetime: currentDateTimeTool,
|
|
@@ -10247,14 +10143,14 @@ var ServerToolExecutor = class {
|
|
|
10247
10143
|
const errorMessage = err?.response?.data?.error || err?.message || "Unknown error";
|
|
10248
10144
|
const status = err?.response?.status || "unknown";
|
|
10249
10145
|
logger.error(`[ServerToolExecutor] Request failed for ${toolName}: ${errorMessage} (status: ${status})`);
|
|
10250
|
-
logger.
|
|
10146
|
+
logger.error(`[ServerToolExecutor] Full error: ${JSON.stringify(err, null, 2)}`);
|
|
10251
10147
|
return `Error executing ${toolName}: ${errorMessage}`;
|
|
10252
10148
|
}
|
|
10253
10149
|
}
|
|
10254
10150
|
};
|
|
10255
10151
|
|
|
10256
10152
|
// src/llm/ToolRouter.ts
|
|
10257
|
-
var SERVER_TOOLS = ["weather_info", "web_search"
|
|
10153
|
+
var SERVER_TOOLS = ["weather_info", "web_search"];
|
|
10258
10154
|
var LOCAL_TOOLS = [
|
|
10259
10155
|
"file_read",
|
|
10260
10156
|
"create_file",
|
|
@@ -10723,8 +10619,7 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
|
|
|
10723
10619
|
// Server-side tools (executed via /api/ai/v1/tools Lambda)
|
|
10724
10620
|
// Routed by ToolRouter to use B4M company API keys
|
|
10725
10621
|
weather_info: {},
|
|
10726
|
-
web_search: {}
|
|
10727
|
-
web_fetch: {}
|
|
10622
|
+
web_search: {}
|
|
10728
10623
|
// Disable web-only tools
|
|
10729
10624
|
// blog_publish: undefined,
|
|
10730
10625
|
// blog_edit: undefined,
|
|
@@ -11615,6 +11510,169 @@ var MessageBuilder = class {
|
|
|
11615
11510
|
// src/llm/ServerLlmBackend.ts
|
|
11616
11511
|
import { createParser } from "eventsource-parser";
|
|
11617
11512
|
import { isAxiosError } from "axios";
|
|
11513
|
+
|
|
11514
|
+
// src/utils/StreamLogger.ts
|
|
11515
|
+
var StreamLogger = class _StreamLogger {
|
|
11516
|
+
constructor(logger2, context, verbose = false, ultraVerbose = false) {
|
|
11517
|
+
// State tracking
|
|
11518
|
+
this.startEventNum = 0;
|
|
11519
|
+
this.currentEventNum = 0;
|
|
11520
|
+
this.lastLoggedLength = 0;
|
|
11521
|
+
this.totalLength = 0;
|
|
11522
|
+
this.lastLogTime = 0;
|
|
11523
|
+
this.streamStartTime = 0;
|
|
11524
|
+
this.lastPreview = "";
|
|
11525
|
+
this.logger = logger2;
|
|
11526
|
+
this.context = context;
|
|
11527
|
+
this.verbose = verbose;
|
|
11528
|
+
this.ultraVerbose = ultraVerbose;
|
|
11529
|
+
}
|
|
11530
|
+
static {
|
|
11531
|
+
// Configuration thresholds
|
|
11532
|
+
this.CHAR_THRESHOLD = 200;
|
|
11533
|
+
}
|
|
11534
|
+
static {
|
|
11535
|
+
this.TIME_THRESHOLD_MS = 500;
|
|
11536
|
+
}
|
|
11537
|
+
static {
|
|
11538
|
+
this.PREVIEW_LENGTH = 30;
|
|
11539
|
+
}
|
|
11540
|
+
static {
|
|
11541
|
+
this.MAX_FULL_TEXT_LENGTH = 1e4;
|
|
11542
|
+
}
|
|
11543
|
+
/**
|
|
11544
|
+
* Called when stream starts
|
|
11545
|
+
*/
|
|
11546
|
+
streamStart() {
|
|
11547
|
+
this.streamStartTime = Date.now();
|
|
11548
|
+
this.lastLogTime = this.streamStartTime;
|
|
11549
|
+
this.startEventNum = 0;
|
|
11550
|
+
this.currentEventNum = 0;
|
|
11551
|
+
this.lastLoggedLength = 0;
|
|
11552
|
+
this.totalLength = 0;
|
|
11553
|
+
this.lastPreview = "";
|
|
11554
|
+
this.logger.debug(`[${this.context}] Stream started`);
|
|
11555
|
+
}
|
|
11556
|
+
/**
|
|
11557
|
+
* Called on each SSE event
|
|
11558
|
+
*/
|
|
11559
|
+
onEvent(eventNum, eventData) {
|
|
11560
|
+
this.currentEventNum = eventNum;
|
|
11561
|
+
if (this.ultraVerbose) {
|
|
11562
|
+
this.logger.debug(`[${this.context}] SSE event #${eventNum}, data: ${eventData.substring(0, 100)}`);
|
|
11563
|
+
}
|
|
11564
|
+
}
|
|
11565
|
+
/**
|
|
11566
|
+
* Called when content is accumulated
|
|
11567
|
+
*/
|
|
11568
|
+
onContent(eventNum, textChunk, totalAccumulated) {
|
|
11569
|
+
this.currentEventNum = eventNum;
|
|
11570
|
+
this.totalLength = totalAccumulated.length;
|
|
11571
|
+
const rawPreview = totalAccumulated.slice(-_StreamLogger.PREVIEW_LENGTH);
|
|
11572
|
+
this.lastPreview = this.sanitizePreview(rawPreview);
|
|
11573
|
+
if (this.ultraVerbose) {
|
|
11574
|
+
this.logger.debug(`[${this.context}] Content event #${eventNum}, chunk: "${textChunk}"`);
|
|
11575
|
+
this.logger.debug(`[${this.context}] Accumulated text length: ${this.totalLength}`);
|
|
11576
|
+
return;
|
|
11577
|
+
}
|
|
11578
|
+
if (!this.verbose) {
|
|
11579
|
+
return;
|
|
11580
|
+
}
|
|
11581
|
+
const charsDelta = this.totalLength - this.lastLoggedLength;
|
|
11582
|
+
const timeDelta = Date.now() - this.lastLogTime;
|
|
11583
|
+
if (charsDelta >= _StreamLogger.CHAR_THRESHOLD || timeDelta >= _StreamLogger.TIME_THRESHOLD_MS) {
|
|
11584
|
+
this.flushBatch();
|
|
11585
|
+
}
|
|
11586
|
+
}
|
|
11587
|
+
/**
|
|
11588
|
+
* Called for non-content events (tool_use, errors, etc.)
|
|
11589
|
+
* These are always logged immediately (critical events)
|
|
11590
|
+
*/
|
|
11591
|
+
onCriticalEvent(eventNum, eventType, description) {
|
|
11592
|
+
this.currentEventNum = eventNum;
|
|
11593
|
+
if (this.verbose && !this.ultraVerbose) {
|
|
11594
|
+
const charsDelta = this.totalLength - this.lastLoggedLength;
|
|
11595
|
+
if (charsDelta > 0) {
|
|
11596
|
+
this.flushBatch();
|
|
11597
|
+
}
|
|
11598
|
+
}
|
|
11599
|
+
this.logger.debug(`[${this.context}] ${eventType} event #${eventNum}: ${description}`);
|
|
11600
|
+
}
|
|
11601
|
+
/**
|
|
11602
|
+
* Called when stream completes
|
|
11603
|
+
*/
|
|
11604
|
+
streamComplete(totalText) {
|
|
11605
|
+
if (this.verbose && !this.ultraVerbose) {
|
|
11606
|
+
const charsDelta = this.totalLength - this.lastLoggedLength;
|
|
11607
|
+
if (charsDelta > 0) {
|
|
11608
|
+
this.flushBatch();
|
|
11609
|
+
}
|
|
11610
|
+
}
|
|
11611
|
+
const totalTime = Date.now() - this.streamStartTime;
|
|
11612
|
+
this.logger.debug(
|
|
11613
|
+
`[${this.context}] Stream complete: ${this.currentEventNum} events, ${this.totalLength} chars, ${(totalTime / 1e3).toFixed(2)}s`
|
|
11614
|
+
);
|
|
11615
|
+
if (totalText.length > _StreamLogger.MAX_FULL_TEXT_LENGTH) {
|
|
11616
|
+
const truncated = totalText.substring(0, _StreamLogger.MAX_FULL_TEXT_LENGTH);
|
|
11617
|
+
this.logger.debug(
|
|
11618
|
+
`[${this.context}] Full text (truncated to ${_StreamLogger.MAX_FULL_TEXT_LENGTH} chars):
|
|
11619
|
+
${truncated}
|
|
11620
|
+
... [+${totalText.length - _StreamLogger.MAX_FULL_TEXT_LENGTH} more chars]`
|
|
11621
|
+
);
|
|
11622
|
+
} else if (totalText.length > 0) {
|
|
11623
|
+
this.logger.debug(`[${this.context}] Full text:
|
|
11624
|
+
${totalText}`);
|
|
11625
|
+
}
|
|
11626
|
+
}
|
|
11627
|
+
/**
|
|
11628
|
+
* Called when stream fails
|
|
11629
|
+
*/
|
|
11630
|
+
streamError(error) {
|
|
11631
|
+
if (this.verbose && !this.ultraVerbose) {
|
|
11632
|
+
const charsDelta = this.totalLength - this.lastLoggedLength;
|
|
11633
|
+
if (charsDelta > 0) {
|
|
11634
|
+
this.flushBatch();
|
|
11635
|
+
}
|
|
11636
|
+
}
|
|
11637
|
+
this.logger.error(`[${this.context}] Stream error:`, error);
|
|
11638
|
+
}
|
|
11639
|
+
/**
|
|
11640
|
+
* Flush the current batch to console
|
|
11641
|
+
*/
|
|
11642
|
+
flushBatch() {
|
|
11643
|
+
const charsDelta = this.totalLength - this.lastLoggedLength;
|
|
11644
|
+
const timeDelta = Date.now() - this.lastLogTime;
|
|
11645
|
+
const eventRange = this.startEventNum === this.currentEventNum ? `#${this.currentEventNum}` : `#${this.startEventNum}-${this.currentEventNum}`;
|
|
11646
|
+
const preview = this.lastPreview.length > 0 ? ` "...${this.lastPreview}"` : "";
|
|
11647
|
+
this.logger.debug(
|
|
11648
|
+
`[${this.context}] Streaming... events ${eventRange}, ${this.totalLength} chars (+${charsDelta}, ${(timeDelta / 1e3).toFixed(1)}s)${preview}`
|
|
11649
|
+
);
|
|
11650
|
+
this.lastLoggedLength = this.totalLength;
|
|
11651
|
+
this.lastLogTime = Date.now();
|
|
11652
|
+
this.startEventNum = this.currentEventNum + 1;
|
|
11653
|
+
}
|
|
11654
|
+
/**
|
|
11655
|
+
* Sanitize preview text for single-line display
|
|
11656
|
+
* Replaces newlines and control characters with spaces
|
|
11657
|
+
*/
|
|
11658
|
+
sanitizePreview(text) {
|
|
11659
|
+
return text.replace(/[\r\n\t]/g, " ").replace(/\s+/g, " ");
|
|
11660
|
+
}
|
|
11661
|
+
/**
|
|
11662
|
+
* Reset state for new stream
|
|
11663
|
+
*/
|
|
11664
|
+
reset() {
|
|
11665
|
+
this.startEventNum = 0;
|
|
11666
|
+
this.currentEventNum = 0;
|
|
11667
|
+
this.lastLoggedLength = 0;
|
|
11668
|
+
this.totalLength = 0;
|
|
11669
|
+
this.lastLogTime = 0;
|
|
11670
|
+
this.streamStartTime = 0;
|
|
11671
|
+
this.lastPreview = "";
|
|
11672
|
+
}
|
|
11673
|
+
};
|
|
11674
|
+
|
|
11675
|
+
// src/llm/ServerLlmBackend.ts
|
|
11618
11676
|
function stripThinkingBlocks(text) {
|
|
11619
11677
|
return text.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
|
|
11620
11678
|
}
|
|
@@ -11639,6 +11697,10 @@ var ServerLlmBackend = class {
|
|
|
11639
11697
|
logger.debug("[ServerLlmBackend] Making streaming request...");
|
|
11640
11698
|
const response = await this.makeStreamingRequest(model, messages, options);
|
|
11641
11699
|
logger.debug("[ServerLlmBackend] Got response, setting up SSE parser");
|
|
11700
|
+
const isVerbose = process.env.B4M_VERBOSE === "1";
|
|
11701
|
+
const isUltraVerbose = process.env.B4M_DEBUG_STREAM === "1";
|
|
11702
|
+
const streamLogger = new StreamLogger(logger, "ServerLlmBackend", isVerbose, isUltraVerbose);
|
|
11703
|
+
streamLogger.streamStart();
|
|
11642
11704
|
let eventCount = 0;
|
|
11643
11705
|
let accumulatedText = "";
|
|
11644
11706
|
let lastUsageInfo = {};
|
|
@@ -11648,12 +11710,13 @@ var ServerLlmBackend = class {
|
|
|
11648
11710
|
const parser = createParser({
|
|
11649
11711
|
onEvent: (event) => {
|
|
11650
11712
|
eventCount++;
|
|
11651
|
-
|
|
11713
|
+
streamLogger.onEvent(eventCount, event.data || "");
|
|
11652
11714
|
const data = event.data;
|
|
11653
11715
|
if (data === "[DONE]") {
|
|
11654
11716
|
receivedDone = true;
|
|
11655
|
-
|
|
11717
|
+
streamLogger.onCriticalEvent(eventCount, "[DONE]", `accumulated text length: ${accumulatedText.length}`);
|
|
11656
11718
|
const cleanedText = stripThinkingBlocks(accumulatedText);
|
|
11719
|
+
streamLogger.streamComplete(accumulatedText);
|
|
11657
11720
|
if (toolsUsed.length > 0) {
|
|
11658
11721
|
const info = {
|
|
11659
11722
|
toolsUsed,
|
|
@@ -11682,9 +11745,8 @@ var ServerLlmBackend = class {
|
|
|
11682
11745
|
}
|
|
11683
11746
|
try {
|
|
11684
11747
|
const parsed = JSON.parse(data);
|
|
11685
|
-
logger.debug(`[ServerLlmBackend] Parsed event type: ${parsed.type}`);
|
|
11686
11748
|
if (parsed.type === "error") {
|
|
11687
|
-
|
|
11749
|
+
streamLogger.onCriticalEvent(eventCount, "ERROR", parsed.message || "Server error");
|
|
11688
11750
|
reject(new Error(parsed.message || "Server error"));
|
|
11689
11751
|
return;
|
|
11690
11752
|
}
|
|
@@ -11697,9 +11759,9 @@ var ServerLlmBackend = class {
|
|
|
11697
11759
|
outputTokens: parsed.usage.outputTokens
|
|
11698
11760
|
};
|
|
11699
11761
|
}
|
|
11700
|
-
|
|
11762
|
+
streamLogger.onContent(eventCount, textChunk, accumulatedText);
|
|
11701
11763
|
} else if (parsed.type === "tool_use") {
|
|
11702
|
-
|
|
11764
|
+
streamLogger.onCriticalEvent(eventCount, "TOOL_USE", `tools: ${parsed.tools?.length}`);
|
|
11703
11765
|
if (parsed.tools && parsed.tools.length > 0) {
|
|
11704
11766
|
for (const tool of parsed.tools) {
|
|
11705
11767
|
logger.debug(`TOOL REQUEST: ${tool.name}`);
|
|
@@ -11720,7 +11782,7 @@ var ServerLlmBackend = class {
|
|
|
11720
11782
|
}
|
|
11721
11783
|
if (parsed.thinking && parsed.thinking.length > 0) {
|
|
11722
11784
|
thinkingBlocks = parsed.thinking;
|
|
11723
|
-
|
|
11785
|
+
streamLogger.onCriticalEvent(eventCount, "THINKING", `${thinkingBlocks.length} thinking blocks`);
|
|
11724
11786
|
}
|
|
11725
11787
|
if (parsed.usage) {
|
|
11726
11788
|
lastUsageInfo = {
|
|
@@ -11730,7 +11792,7 @@ var ServerLlmBackend = class {
|
|
|
11730
11792
|
}
|
|
11731
11793
|
}
|
|
11732
11794
|
} catch (parseError) {
|
|
11733
|
-
|
|
11795
|
+
streamLogger.streamError(parseError);
|
|
11734
11796
|
}
|
|
11735
11797
|
}
|
|
11736
11798
|
});
|
|
@@ -12078,7 +12140,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
|
|
|
12078
12140
|
// package.json
|
|
12079
12141
|
var package_default = {
|
|
12080
12142
|
name: "@bike4mind/cli",
|
|
12081
|
-
version: "0.2.20-feat-
|
|
12143
|
+
version: "0.2.20-feat-cli-smart-stream-logging.18065+d52838015",
|
|
12082
12144
|
type: "module",
|
|
12083
12145
|
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
12084
12146
|
license: "UNLICENSED",
|
|
@@ -12185,10 +12247,10 @@ var package_default = {
|
|
|
12185
12247
|
},
|
|
12186
12248
|
devDependencies: {
|
|
12187
12249
|
"@bike4mind/agents": "0.1.0",
|
|
12188
|
-
"@bike4mind/common": "2.44.1-feat-
|
|
12189
|
-
"@bike4mind/mcp": "1.24.1-feat-
|
|
12190
|
-
"@bike4mind/services": "2.42.1-feat-
|
|
12191
|
-
"@bike4mind/utils": "2.2.2-feat-
|
|
12250
|
+
"@bike4mind/common": "2.44.1-feat-cli-smart-stream-logging.18065+d52838015",
|
|
12251
|
+
"@bike4mind/mcp": "1.24.1-feat-cli-smart-stream-logging.18065+d52838015",
|
|
12252
|
+
"@bike4mind/services": "2.42.1-feat-cli-smart-stream-logging.18065+d52838015",
|
|
12253
|
+
"@bike4mind/utils": "2.2.2-feat-cli-smart-stream-logging.18065+d52838015",
|
|
12192
12254
|
"@types/better-sqlite3": "^7.6.13",
|
|
12193
12255
|
"@types/diff": "^5.0.9",
|
|
12194
12256
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -12205,7 +12267,7 @@ var package_default = {
|
|
|
12205
12267
|
optionalDependencies: {
|
|
12206
12268
|
"@vscode/ripgrep": "^1.17.0"
|
|
12207
12269
|
},
|
|
12208
|
-
gitHead: "
|
|
12270
|
+
gitHead: "d5283801593920282f1b31c29b56dea473919327"
|
|
12209
12271
|
};
|
|
12210
12272
|
|
|
12211
12273
|
// src/config/constants.ts
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
findMostSimilarMemento,
|
|
4
4
|
getRelevantMementos
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-RRYX2K7W.js";
|
|
6
|
+
import "./chunk-EP4OGIQI.js";
|
|
7
|
+
import "./chunk-DTPBHKQL.js";
|
|
8
8
|
import "./chunk-OCYRD7D6.js";
|
|
9
9
|
export {
|
|
10
10
|
findMostSimilarMemento,
|
|
@@ -129,8 +129,8 @@ import {
|
|
|
129
129
|
validateMermaidSyntax,
|
|
130
130
|
warmUpSettingsCache,
|
|
131
131
|
withRetry
|
|
132
|
-
} from "./chunk-
|
|
133
|
-
import "./chunk-
|
|
132
|
+
} from "./chunk-EP4OGIQI.js";
|
|
133
|
+
import "./chunk-DTPBHKQL.js";
|
|
134
134
|
import {
|
|
135
135
|
Logger,
|
|
136
136
|
NotificationDeduplicator,
|
|
@@ -160,6 +160,8 @@ import {
|
|
|
160
160
|
QuestResourceSchema,
|
|
161
161
|
QuestSchema,
|
|
162
162
|
QuestStatusSchema,
|
|
163
|
+
RESTRICTION_OPERATIONS,
|
|
164
|
+
RESTRICTION_SUBJECT_TYPES,
|
|
163
165
|
RapidReplyFallbackBehaviors,
|
|
164
166
|
RapidReplyResponseStylesCommon,
|
|
165
167
|
RapidReplySettingsSchema,
|
|
@@ -306,7 +308,7 @@ import {
|
|
|
306
308
|
validateReactArtifactV2,
|
|
307
309
|
validateSvgArtifactV2,
|
|
308
310
|
wikiMarkupToAdf
|
|
309
|
-
} from "./chunk-
|
|
311
|
+
} from "./chunk-DTPBHKQL.js";
|
|
310
312
|
export {
|
|
311
313
|
ALL_IMAGE_MODELS,
|
|
312
314
|
ALL_IMAGE_SIZES,
|
|
@@ -468,6 +470,8 @@ export {
|
|
|
468
470
|
QuestResourceSchema,
|
|
469
471
|
QuestSchema,
|
|
470
472
|
QuestStatusSchema,
|
|
473
|
+
RESTRICTION_OPERATIONS,
|
|
474
|
+
RESTRICTION_SUBJECT_TYPES,
|
|
471
475
|
RapidReplyFallbackBehaviors,
|
|
472
476
|
RapidReplyResponseStylesCommon,
|
|
473
477
|
RapidReplySettingsSchema,
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
SubtractCreditsSchema,
|
|
4
4
|
subtractCredits
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-XWI42ILN.js";
|
|
6
|
+
import "./chunk-EP4OGIQI.js";
|
|
7
|
+
import "./chunk-DTPBHKQL.js";
|
|
8
8
|
import "./chunk-OCYRD7D6.js";
|
|
9
9
|
export {
|
|
10
10
|
SubtractCreditsSchema,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.2.20-feat-
|
|
3
|
+
"version": "0.2.20-feat-cli-smart-stream-logging.18065+d52838015",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -107,10 +107,10 @@
|
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
109
|
"@bike4mind/agents": "0.1.0",
|
|
110
|
-
"@bike4mind/common": "2.44.1-feat-
|
|
111
|
-
"@bike4mind/mcp": "1.24.1-feat-
|
|
112
|
-
"@bike4mind/services": "2.42.1-feat-
|
|
113
|
-
"@bike4mind/utils": "2.2.2-feat-
|
|
110
|
+
"@bike4mind/common": "2.44.1-feat-cli-smart-stream-logging.18065+d52838015",
|
|
111
|
+
"@bike4mind/mcp": "1.24.1-feat-cli-smart-stream-logging.18065+d52838015",
|
|
112
|
+
"@bike4mind/services": "2.42.1-feat-cli-smart-stream-logging.18065+d52838015",
|
|
113
|
+
"@bike4mind/utils": "2.2.2-feat-cli-smart-stream-logging.18065+d52838015",
|
|
114
114
|
"@types/better-sqlite3": "^7.6.13",
|
|
115
115
|
"@types/diff": "^5.0.9",
|
|
116
116
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -127,5 +127,5 @@
|
|
|
127
127
|
"optionalDependencies": {
|
|
128
128
|
"@vscode/ripgrep": "^1.17.0"
|
|
129
129
|
},
|
|
130
|
-
"gitHead": "
|
|
130
|
+
"gitHead": "d5283801593920282f1b31c29b56dea473919327"
|
|
131
131
|
}
|