@bike4mind/cli 0.2.38 → 0.2.39-feat-context-telemetry.20283

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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-GVIBCLTG.js";
4
+ } from "./chunk-JWPXPARA.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;
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ChatModels
4
- } from "./chunk-GVIBCLTG.js";
4
+ } from "./chunk-JWPXPARA.js";
5
5
  import {
6
6
  DEFAULT_SANDBOX_CONFIG
7
7
  } from "./chunk-4BIBE3J7.js";
@@ -7,11 +7,11 @@ import {
7
7
  getSettingsMap,
8
8
  getSettingsValue,
9
9
  secureParameters
10
- } from "./chunk-J3D6HTCL.js";
10
+ } from "./chunk-IM7JYQUE.js";
11
11
  import {
12
12
  KnowledgeType,
13
13
  SupportedFabFileMimeTypes
14
- } from "./chunk-GVIBCLTG.js";
14
+ } from "./chunk-JWPXPARA.js";
15
15
 
16
16
  // ../../b4m-core/packages/services/dist/src/fabFileService/create.js
17
17
  import { z } from "zod";
@@ -3,7 +3,7 @@
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "@bike4mind/cli",
6
- version: "0.2.38",
6
+ version: "0.2.39-feat-context-telemetry.20283+f0547ac8a",
7
7
  type: "module",
8
8
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
9
9
  license: "UNLICENSED",
@@ -117,10 +117,10 @@ var package_default = {
117
117
  },
118
118
  devDependencies: {
119
119
  "@bike4mind/agents": "0.1.0",
120
- "@bike4mind/common": "2.59.0",
121
- "@bike4mind/mcp": "1.33.0",
122
- "@bike4mind/services": "2.55.0",
123
- "@bike4mind/utils": "2.12.0",
120
+ "@bike4mind/common": "2.59.1-feat-context-telemetry.20283+f0547ac8a",
121
+ "@bike4mind/mcp": "1.33.1-feat-context-telemetry.20283+f0547ac8a",
122
+ "@bike4mind/services": "2.55.1-feat-context-telemetry.20283+f0547ac8a",
123
+ "@bike4mind/utils": "2.12.1-feat-context-telemetry.20283+f0547ac8a",
124
124
  "@types/better-sqlite3": "^7.6.13",
125
125
  "@types/diff": "^5.0.9",
126
126
  "@types/jsonwebtoken": "^9.0.4",
@@ -138,7 +138,7 @@ var package_default = {
138
138
  optionalDependencies: {
139
139
  "@vscode/ripgrep": "^1.17.0"
140
140
  },
141
- gitHead: "eb4c0eb10388cadab99cad4ea5430c5efa1e9704"
141
+ gitHead: "f0547ac8ab4732c9c4744ad3ddeab195138c5389"
142
142
  };
143
143
 
144
144
  // src/utils/updateChecker.ts
@@ -4,7 +4,7 @@ import {
4
4
  getOpenWeatherKey,
5
5
  getSerperKey,
6
6
  getWolframAlphaKey
7
- } from "./chunk-XCFULK7Q.js";
7
+ } from "./chunk-WEGIYLXH.js";
8
8
  import {
9
9
  BFLImageService,
10
10
  BaseStorage,
@@ -16,15 +16,16 @@ import {
16
16
  OpenAIBackend,
17
17
  OpenAIImageService,
18
18
  XAIImageService
19
- } from "./chunk-J3D6HTCL.js";
19
+ } from "./chunk-IM7JYQUE.js";
20
20
  import {
21
21
  Logger
22
22
  } from "./chunk-PFBYGCOW.js";
23
23
  import {
24
24
  ConfigStore,
25
25
  logger
26
- } from "./chunk-JL37DZ2X.js";
26
+ } from "./chunk-2P56HFA4.js";
27
27
  import {
28
+ ALERT_THRESHOLDS,
28
29
  AiEvents,
29
30
  ApiKeyEvents,
30
31
  ApiKeyScope,
@@ -80,8 +81,9 @@ import {
80
81
  getDataLakeTags,
81
82
  getMcpProviderMetadata,
82
83
  getViewById,
83
- resolveNavigationIntents
84
- } from "./chunk-GVIBCLTG.js";
84
+ resolveNavigationIntents,
85
+ sanitizeTelemetryError
86
+ } from "./chunk-JWPXPARA.js";
85
87
 
86
88
  // src/utils/fileSearch.ts
87
89
  import * as fs from "fs";
@@ -13860,6 +13862,354 @@ var CombinedExtractor = class {
13860
13862
  };
13861
13863
  var combinedExtractor = new CombinedExtractor();
13862
13864
 
13865
+ // ../../b4m-core/packages/services/dist/src/telemetry/AnomalyAlertService.js
13866
+ var AnomalyAlertService = class _AnomalyAlertService {
13867
+ constructor(loggerOrConfig, alertConfig) {
13868
+ this.dedupCache = /* @__PURE__ */ new Map();
13869
+ if (typeof loggerOrConfig.logger !== "undefined") {
13870
+ const config = loggerOrConfig;
13871
+ this.logger = config.logger;
13872
+ this.config = config.alertConfig;
13873
+ this.cacheRepository = config.cacheRepository;
13874
+ this.slackSender = config.slackSender;
13875
+ } else {
13876
+ this.logger = loggerOrConfig;
13877
+ this.config = alertConfig;
13878
+ }
13879
+ }
13880
+ /**
13881
+ * Check if Slack alerting is properly configured
13882
+ */
13883
+ isSlackConfigured() {
13884
+ return !!(this.config.slackWorkspaceId && this.config.slackChannelId && this.slackSender);
13885
+ }
13886
+ /**
13887
+ * Check if an alert should be sent and send it if appropriate
13888
+ */
13889
+ async checkAndAlert(telemetry) {
13890
+ if (!this.config.enabled || !this.isSlackConfigured()) {
13891
+ return false;
13892
+ }
13893
+ const { anomalies } = telemetry;
13894
+ const threshold = this.config.alertThreshold ?? ALERT_THRESHOLDS.warning;
13895
+ if (anomalies.anomalyScore < threshold) {
13896
+ return false;
13897
+ }
13898
+ const isDup = await this.checkDeduplication(anomalies.dedupKey);
13899
+ if (isDup) {
13900
+ this.logger.info(`\u{1F4CA} [AnomalyAlert] Suppressed duplicate alert: ${anomalies.dedupKey}`);
13901
+ return false;
13902
+ }
13903
+ try {
13904
+ const message = this.formatSlackMessage(telemetry);
13905
+ await this.sendSlackAlert(message);
13906
+ this.logger.info(`\u{1F4CA} [AnomalyAlert] Alert sent for ${anomalies.primaryAnomaly} (score: ${anomalies.anomalyScore})`);
13907
+ return true;
13908
+ } catch (error) {
13909
+ this.logger.error(`\u{1F4CA} [AnomalyAlert] Failed to send alert:`, error);
13910
+ return false;
13911
+ }
13912
+ }
13913
+ /**
13914
+ * Check deduplication and claim the key atomically.
13915
+ * Uses distributed MongoDB cache when available, falls back to in-memory.
13916
+ *
13917
+ * @returns true if this is a duplicate (should not send alert), false if we can proceed
13918
+ */
13919
+ async checkDeduplication(dedupKey) {
13920
+ const windowMs = (this.config.dedupWindowMinutes ?? 5) * 60 * 1e3;
13921
+ const cacheKey = `${_AnomalyAlertService.DEDUP_KEY_PREFIX}${dedupKey}`;
13922
+ if (this.cacheRepository) {
13923
+ try {
13924
+ const result = await this.cacheRepository.claimDedup(cacheKey, { dedupKey, claimedAt: Date.now(), count: 1 }, windowMs);
13925
+ return !result.claimed;
13926
+ } catch (error) {
13927
+ this.logger.warn(`\u{1F4CA} [AnomalyAlert] Distributed dedup failed, using in-memory:`, error);
13928
+ }
13929
+ }
13930
+ return this.checkInMemoryDedup(dedupKey, windowMs);
13931
+ }
13932
+ /**
13933
+ * In-memory deduplication check and record (fallback)
13934
+ */
13935
+ checkInMemoryDedup(dedupKey, windowMs) {
13936
+ const entry = this.dedupCache.get(dedupKey);
13937
+ if (entry) {
13938
+ const timeSinceLastAlert = Date.now() - entry.lastAlertTime;
13939
+ if (timeSinceLastAlert < windowMs) {
13940
+ return true;
13941
+ }
13942
+ }
13943
+ this.recordInMemoryAlert(dedupKey);
13944
+ return false;
13945
+ }
13946
+ /**
13947
+ * Record an alert in the in-memory cache
13948
+ */
13949
+ recordInMemoryAlert(dedupKey) {
13950
+ const existing = this.dedupCache.get(dedupKey);
13951
+ this.dedupCache.set(dedupKey, {
13952
+ dedupKey,
13953
+ lastAlertTime: Date.now(),
13954
+ count: (existing?.count ?? 0) + 1
13955
+ });
13956
+ const oneHourAgo = Date.now() - 60 * 60 * 1e3;
13957
+ for (const [key, entry] of this.dedupCache.entries()) {
13958
+ if (entry.lastAlertTime < oneHourAgo) {
13959
+ this.dedupCache.delete(key);
13960
+ }
13961
+ }
13962
+ if (this.dedupCache.size > _AnomalyAlertService.MAX_CACHE_ENTRIES) {
13963
+ const entries = Array.from(this.dedupCache.entries()).sort((a, b) => a[1].lastAlertTime - b[1].lastAlertTime);
13964
+ const toRemove = entries.slice(0, this.dedupCache.size - _AnomalyAlertService.MAX_CACHE_ENTRIES);
13965
+ for (const [key] of toRemove) {
13966
+ this.dedupCache.delete(key);
13967
+ }
13968
+ }
13969
+ }
13970
+ /**
13971
+ * Format telemetry into a Slack Block Kit message
13972
+ */
13973
+ formatSlackMessage(telemetry) {
13974
+ const { anomalies, model, contextWindow, performance: performance2, tools, subagents } = telemetry;
13975
+ const isCritical = anomalies.anomalyScore >= (this.config.criticalThreshold ?? ALERT_THRESHOLDS.critical);
13976
+ const emoji = this.getSeverityEmoji(anomalies.severity);
13977
+ const severityText = anomalies.severity.toUpperCase();
13978
+ const title = `${emoji} Context Telemetry Alert: ${this.formatAnomalyType(anomalies.primaryAnomaly)}`;
13979
+ const summaryText = `${severityText} anomaly detected (score: ${anomalies.anomalyScore}) - ${anomalies.primaryAnomaly}`;
13980
+ const blocks = [
13981
+ // Header
13982
+ {
13983
+ type: "header",
13984
+ text: {
13985
+ type: "plain_text",
13986
+ text: title,
13987
+ emoji: true
13988
+ }
13989
+ },
13990
+ // Severity and score
13991
+ {
13992
+ type: "section",
13993
+ fields: [
13994
+ {
13995
+ type: "mrkdwn",
13996
+ text: `*Severity:*
13997
+ ${emoji} ${severityText}`
13998
+ },
13999
+ {
14000
+ type: "mrkdwn",
14001
+ text: `*Anomaly Score:*
14002
+ ${anomalies.anomalyScore}/100`
14003
+ },
14004
+ {
14005
+ type: "mrkdwn",
14006
+ text: `*Model:*
14007
+ ${model.modelId}`
14008
+ },
14009
+ {
14010
+ type: "mrkdwn",
14011
+ text: `*Provider:*
14012
+ ${model.provider}`
14013
+ }
14014
+ ]
14015
+ },
14016
+ // Divider
14017
+ { type: "divider" }
14018
+ ];
14019
+ const anomalyDetails = this.buildAnomalyDetails(anomalies);
14020
+ if (anomalyDetails.length > 0) {
14021
+ blocks.push({
14022
+ type: "section",
14023
+ text: {
14024
+ type: "mrkdwn",
14025
+ text: `*Detected Anomalies:*
14026
+ ${anomalyDetails.join("\n")}`
14027
+ }
14028
+ });
14029
+ }
14030
+ blocks.push({
14031
+ type: "section",
14032
+ fields: [
14033
+ {
14034
+ type: "mrkdwn",
14035
+ text: `*Input Tokens:*
14036
+ ${contextWindow.inputTokens.toLocaleString()}`
14037
+ },
14038
+ {
14039
+ type: "mrkdwn",
14040
+ text: `*Utilization:*
14041
+ ${contextWindow.utilizationPercentage.toFixed(1)}%`
14042
+ },
14043
+ {
14044
+ type: "mrkdwn",
14045
+ text: `*Response Time:*
14046
+ ${performance2.totalResponseTimeMs.toLocaleString()}ms`
14047
+ },
14048
+ {
14049
+ type: "mrkdwn",
14050
+ text: `*First Token:*
14051
+ ${performance2.firstTokenTimeMs?.toLocaleString() ?? "N/A"}ms`
14052
+ }
14053
+ ]
14054
+ });
14055
+ const failedTools = tools?.filter((t) => t.failureCount > 0) ?? [];
14056
+ if (failedTools.length > 0) {
14057
+ const toolDetails = failedTools.map((t) => `\u2022 \`${t.toolName}\`: ${t.failureCount} failures${t.lastError ? ` - ${sanitizeTelemetryError(t.lastError, 50)}` : ""}`).join("\n");
14058
+ blocks.push({
14059
+ type: "section",
14060
+ text: {
14061
+ type: "mrkdwn",
14062
+ text: `*Tool Failures:*
14063
+ ${toolDetails}`
14064
+ }
14065
+ });
14066
+ }
14067
+ const timedOutAgents = subagents?.filter((s) => s.timeoutCount > 0) ?? [];
14068
+ if (timedOutAgents.length > 0) {
14069
+ const agentDetails = timedOutAgents.map((s) => `\u2022 \`${s.agentName}\`: ${s.timeoutCount} timeouts, ${s.totalDurationMs.toLocaleString()}ms total`).join("\n");
14070
+ blocks.push({
14071
+ type: "section",
14072
+ text: {
14073
+ type: "mrkdwn",
14074
+ text: `*Subagent Timeouts:*
14075
+ ${agentDetails}`
14076
+ }
14077
+ });
14078
+ }
14079
+ if (model.fallbackUsed) {
14080
+ blocks.push({
14081
+ type: "section",
14082
+ text: {
14083
+ type: "mrkdwn",
14084
+ text: `*Fallback Used:*
14085
+ ${model.originalModelId} \u2192 ${model.modelId}
14086
+ Reason: ${model.fallbackReason ?? "Unknown"}`
14087
+ }
14088
+ });
14089
+ }
14090
+ blocks.push({ type: "divider" }, {
14091
+ type: "context",
14092
+ elements: [
14093
+ {
14094
+ type: "mrkdwn",
14095
+ text: `Timestamp: ${telemetry.timestamp} | Dedup Key: \`${anomalies.dedupKey}\``
14096
+ }
14097
+ ]
14098
+ });
14099
+ if (isCritical) {
14100
+ blocks.splice(1, 0, {
14101
+ type: "section",
14102
+ text: {
14103
+ type: "mrkdwn",
14104
+ text: "<!here> Critical anomaly requires attention!"
14105
+ }
14106
+ });
14107
+ }
14108
+ return {
14109
+ text: summaryText,
14110
+ blocks
14111
+ };
14112
+ }
14113
+ /**
14114
+ * Build list of detected anomaly details
14115
+ */
14116
+ buildAnomalyDetails(anomalies) {
14117
+ const details = [];
14118
+ if (anomalies.contextOverflow) {
14119
+ details.push("\u{1F6A8} Context window overflow detected");
14120
+ }
14121
+ if (anomalies.criticalUtilization) {
14122
+ details.push("\u26A0\uFE0F Critical context utilization (\u226595%)");
14123
+ } else if (anomalies.highUtilization) {
14124
+ details.push("\u26A0\uFE0F High context utilization (\u226590%)");
14125
+ }
14126
+ if (anomalies.criticalTruncation) {
14127
+ details.push("\u26A0\uFE0F Critical message truncation (\u226575%)");
14128
+ } else if (anomalies.highTruncation) {
14129
+ details.push("\u26A0\uFE0F High message truncation (\u226550%)");
14130
+ }
14131
+ if (anomalies.toolFailureSpike) {
14132
+ details.push("\u{1F527} Tool failure spike (\u22653 failures)");
14133
+ }
14134
+ if (anomalies.toolTimeout) {
14135
+ details.push("\u23F1\uFE0F Tool timeout detected (>30s)");
14136
+ }
14137
+ if (anomalies.subagentTimeout) {
14138
+ details.push("\u{1F916} Subagent timeout detected (>5min)");
14139
+ }
14140
+ if (anomalies.slowTotalResponse) {
14141
+ details.push("\u{1F40C} Slow total response time (>60s)");
14142
+ }
14143
+ if (anomalies.slowFirstToken) {
14144
+ details.push("\u{1F40C} Slow first token time (>10s)");
14145
+ }
14146
+ return details;
14147
+ }
14148
+ /**
14149
+ * Get emoji for severity level
14150
+ */
14151
+ getSeverityEmoji(severity) {
14152
+ switch (severity) {
14153
+ case "critical":
14154
+ return "\u{1F534}";
14155
+ case "high":
14156
+ return "\u{1F7E0}";
14157
+ case "medium":
14158
+ return "\u{1F7E1}";
14159
+ case "low":
14160
+ return "\u{1F7E2}";
14161
+ default:
14162
+ return "\u26AA";
14163
+ }
14164
+ }
14165
+ /**
14166
+ * Format anomaly type for display
14167
+ */
14168
+ formatAnomalyType(type) {
14169
+ switch (type) {
14170
+ case "context_overflow":
14171
+ return "Context Overflow";
14172
+ case "high_truncation":
14173
+ return "High Truncation";
14174
+ case "tool_failure":
14175
+ return "Tool Failure";
14176
+ case "subagent_timeout":
14177
+ return "Subagent Timeout";
14178
+ case "slow_response":
14179
+ return "Slow Response";
14180
+ case "multiple":
14181
+ return "Multiple Anomalies";
14182
+ case "none":
14183
+ return "Unknown";
14184
+ default:
14185
+ return type;
14186
+ }
14187
+ }
14188
+ /**
14189
+ * Send the formatted message to Slack using the configured sender
14190
+ */
14191
+ async sendSlackAlert(message) {
14192
+ if (!this.slackSender || !this.config.slackWorkspaceId || !this.config.slackChannelId) {
14193
+ throw new Error("Slack integration not configured");
14194
+ }
14195
+ await this.slackSender.sendMessage(this.config.slackWorkspaceId, this.config.slackChannelId, message);
14196
+ }
14197
+ /**
14198
+ * Get deduplication statistics for monitoring
14199
+ */
14200
+ getDedupStats() {
14201
+ const fiveMinutesAgo = Date.now() - 5 * 60 * 1e3;
14202
+ const recentAlerts = Array.from(this.dedupCache.values()).filter((e) => e.lastAlertTime >= fiveMinutesAgo).length;
14203
+ return {
14204
+ totalEntries: this.dedupCache.size,
14205
+ recentAlerts,
14206
+ distributedDedupEnabled: !!this.cacheRepository
14207
+ };
14208
+ }
14209
+ };
14210
+ AnomalyAlertService.MAX_CACHE_ENTRIES = 1e3;
14211
+ AnomalyAlertService.DEDUP_KEY_PREFIX = "anomaly-alert-dedup:";
14212
+
13863
14213
  // ../../b4m-core/packages/services/dist/src/llm/ChatCompletionProcess.js
13864
14214
  var DISABLE_SERVER_THROTTLING = process.env.DISABLE_SERVER_THROTTLING === "true";
13865
14215
  var questSaveMutex = new Mutex();
@@ -19,7 +19,7 @@ import {
19
19
  dayjsConfig_default,
20
20
  extractSnippetMeta,
21
21
  settingsMap
22
- } from "./chunk-GVIBCLTG.js";
22
+ } from "./chunk-JWPXPARA.js";
23
23
 
24
24
  // ../../b4m-core/packages/utils/dist/src/storage/S3Storage.js
25
25
  import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";