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

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