sidekick-shared 0.27.6 → 0.28.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.
Files changed (269) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +58 -18
  3. package/dist/browser.d.ts +13 -2
  4. package/dist/browser.js +30 -2
  5. package/dist/claudePaths.d.ts +11 -0
  6. package/dist/claudePaths.js +61 -0
  7. package/dist/claudeProfiles.d.ts +2 -9
  8. package/dist/claudeProfiles.js +10 -25
  9. package/dist/codexPaths.d.ts +22 -0
  10. package/dist/codexPaths.js +67 -0
  11. package/dist/codexProfiles.d.ts +1 -4
  12. package/dist/codexProfiles.js +5 -43
  13. package/dist/doctor.js +2 -2
  14. package/dist/esm/accountChangeSignal.js +15 -0
  15. package/dist/esm/accountChanges.js +152 -0
  16. package/dist/esm/accountHealth.js +288 -0
  17. package/dist/esm/accountLaunch.js +145 -0
  18. package/dist/esm/accountLease.js +60 -0
  19. package/dist/esm/accountManager.js +606 -0
  20. package/dist/esm/accountRegistry.js +214 -0
  21. package/dist/esm/accountStatus.js +51 -0
  22. package/dist/esm/accountSwitch.js +74 -0
  23. package/dist/esm/accountSync.js +156 -0
  24. package/dist/esm/accountSyncTypes.js +4 -0
  25. package/dist/esm/accounts.js +1291 -0
  26. package/dist/esm/aggregation/EventAggregator.js +2034 -0
  27. package/dist/esm/aggregation/FrequencyTracker.js +69 -0
  28. package/dist/esm/aggregation/HeatmapTracker.js +89 -0
  29. package/dist/esm/aggregation/PatternExtractor.js +168 -0
  30. package/dist/esm/aggregation/costProvenance.js +31 -0
  31. package/dist/esm/aggregation/snapshot.js +161 -0
  32. package/dist/esm/aggregation/types.js +5 -0
  33. package/dist/esm/analytics/codeImpact.js +18 -0
  34. package/dist/esm/analytics/compactionLedger.js +37 -0
  35. package/dist/esm/analytics/qualityScore.js +112 -0
  36. package/dist/esm/autoSwitch.js +185 -0
  37. package/dist/esm/browser.js +34 -0
  38. package/dist/esm/claudeCredentialDoctor.js +239 -0
  39. package/dist/esm/claudeCredentialLedger.js +91 -0
  40. package/dist/esm/claudeCredentials.js +111 -0
  41. package/dist/esm/claudeLiveGuard.js +43 -0
  42. package/dist/esm/claudePaths.js +22 -0
  43. package/dist/esm/claudeProfiles.js +142 -0
  44. package/dist/esm/claudeRefreshLock.js +106 -0
  45. package/dist/esm/codexAuth.js +101 -0
  46. package/dist/esm/codexCredentialDoctor.js +265 -0
  47. package/dist/esm/codexCredentialStore.js +164 -0
  48. package/dist/esm/codexKeepAlive.js +112 -0
  49. package/dist/esm/codexPaths.js +172 -0
  50. package/dist/esm/codexProfiles.js +1251 -0
  51. package/dist/esm/codexQuota.js +564 -0
  52. package/dist/esm/codexQuotaWatcher.js +363 -0
  53. package/dist/esm/context/composer.js +71 -0
  54. package/dist/esm/context/sessionContext.js +546 -0
  55. package/dist/esm/credentialIO.js +283 -0
  56. package/dist/esm/credentials.js +49 -0
  57. package/dist/esm/doctor.js +305 -0
  58. package/dist/esm/ensureDefaultAccounts.js +62 -0
  59. package/dist/esm/errorHistory.js +56 -0
  60. package/dist/esm/extractors/errorTaxonomy.js +43 -0
  61. package/dist/esm/extractors/gatherAssets.js +32 -0
  62. package/dist/esm/extractors/sessionAssets.js +176 -0
  63. package/dist/esm/extractors/sources/claudeAssets.js +158 -0
  64. package/dist/esm/extractors/sources/codexAssets.js +234 -0
  65. package/dist/esm/extractors/tokenUsage.js +41 -0
  66. package/dist/esm/extractors/toolCall.js +142 -0
  67. package/dist/esm/failingTools.js +65 -0
  68. package/dist/esm/fileHead.js +27 -0
  69. package/dist/esm/formatters/eventHighlighter.js +332 -0
  70. package/dist/esm/formatters/noiseClassifier.js +209 -0
  71. package/dist/esm/formatters/sessionDump.js +328 -0
  72. package/dist/esm/formatters/toolSummary.js +226 -0
  73. package/dist/esm/formatting.js +82 -0
  74. package/dist/esm/handoffUrl.js +23 -0
  75. package/dist/esm/historicalStore.js +305 -0
  76. package/dist/esm/humanPrompt.js +88 -0
  77. package/dist/esm/index.js +213 -0
  78. package/dist/esm/keepAlive.js +189 -0
  79. package/dist/esm/liveCredentialGuard.js +33 -0
  80. package/dist/esm/modelAliases.js +51 -0
  81. package/dist/esm/modelCatalog.js +139 -0
  82. package/dist/esm/modelContext.js +280 -0
  83. package/dist/esm/modelInfo.js +832 -0
  84. package/dist/esm/multiProviderQuotaService.js +450 -0
  85. package/dist/esm/node.js +46 -0
  86. package/dist/esm/observedContextWindows.js +165 -0
  87. package/dist/esm/observedSessionCollector.js +939 -0
  88. package/dist/esm/parsers/changelogParser.js +71 -0
  89. package/dist/esm/parsers/codexHistory.js +89 -0
  90. package/dist/esm/parsers/codexParser.js +906 -0
  91. package/dist/esm/parsers/debugLogParser.js +126 -0
  92. package/dist/esm/parsers/jsonl.js +66 -0
  93. package/dist/esm/parsers/mcpToolName.js +28 -0
  94. package/dist/esm/parsers/openCodeParser.js +625 -0
  95. package/dist/esm/parsers/planExtractor.js +335 -0
  96. package/dist/esm/parsers/sessionActivityDetector.js +246 -0
  97. package/dist/esm/parsers/sessionPathResolver.js +713 -0
  98. package/dist/esm/parsers/subagentScanner.js +360 -0
  99. package/dist/esm/parsers/subagentStatsCache.js +45 -0
  100. package/dist/esm/parsers/subagentTraceParser.js +325 -0
  101. package/dist/esm/paths.js +134 -0
  102. package/dist/esm/peakHours.js +194 -0
  103. package/dist/esm/phrases.js +1330 -0
  104. package/dist/esm/pricingCatalog.js +247 -0
  105. package/dist/esm/processDetection.js +200 -0
  106. package/dist/esm/projectMigration.js +59 -0
  107. package/dist/esm/promptHistory.js +1221 -0
  108. package/dist/esm/providerFailure.js +362 -0
  109. package/dist/esm/providerIds.js +6 -0
  110. package/dist/esm/providerQuota.js +1 -0
  111. package/dist/esm/providerServiceStatus.js +145 -0
  112. package/dist/esm/providerServiceStatusTypes.js +1 -0
  113. package/dist/esm/providerStatus.js +117 -0
  114. package/dist/esm/providers/claudeCode.js +575 -0
  115. package/dist/esm/providers/claudeListing.js +121 -0
  116. package/dist/esm/providers/codex.js +1034 -0
  117. package/dist/esm/providers/codexDatabase.js +297 -0
  118. package/dist/esm/providers/codexRollouts.js +215 -0
  119. package/dist/esm/providers/detect.js +185 -0
  120. package/dist/esm/providers/diagnostics.js +83 -0
  121. package/dist/esm/providers/directoryListingCache.js +206 -0
  122. package/dist/esm/providers/factory.js +54 -0
  123. package/dist/esm/providers/openCode.js +2008 -0
  124. package/dist/esm/providers/openCodeDatabase.js +419 -0
  125. package/dist/esm/providers/rolloutWalker.js +252 -0
  126. package/dist/esm/providers/types.js +12 -0
  127. package/dist/esm/quota.js +182 -0
  128. package/dist/esm/quotaHistory.js +364 -0
  129. package/dist/esm/quotaPoller.js +230 -0
  130. package/dist/esm/quotaPresentation.js +97 -0
  131. package/dist/esm/quotaResolver.js +231 -0
  132. package/dist/esm/quotaSnapshots.js +130 -0
  133. package/dist/esm/quotaThresholds.js +85 -0
  134. package/dist/esm/readers/decisions.js +24 -0
  135. package/dist/esm/readers/handoff.js +20 -0
  136. package/dist/esm/readers/helpers.js +27 -0
  137. package/dist/esm/readers/history.js +9 -0
  138. package/dist/esm/readers/notes.js +48 -0
  139. package/dist/esm/readers/plans.js +225 -0
  140. package/dist/esm/readers/tasks.js +19 -0
  141. package/dist/esm/report/htmlHelpers.js +280 -0
  142. package/dist/esm/report/htmlReportGenerator.js +704 -0
  143. package/dist/esm/report/index.js +7 -0
  144. package/dist/esm/report/logo.js +2 -0
  145. package/dist/esm/report/openBrowser.js +19 -0
  146. package/dist/esm/report/sessionReportInputs.js +33 -0
  147. package/dist/esm/report/transcriptParser.js +83 -0
  148. package/dist/esm/report/types.js +4 -0
  149. package/dist/esm/schemas/accountManager.js +204 -0
  150. package/dist/esm/schemas/accountStatus.js +25 -0
  151. package/dist/esm/schemas/assistantTurn.js +74 -0
  152. package/dist/esm/schemas/index.js +25 -0
  153. package/dist/esm/schemas/observedSessionV1.js +77 -0
  154. package/dist/esm/schemas/providerFailure.js +37 -0
  155. package/dist/esm/schemas/quota.js +132 -0
  156. package/dist/esm/schemas/quotaHistory.js +40 -0
  157. package/dist/esm/schemas/sessionEvent.js +216 -0
  158. package/dist/esm/schemas/stateFile.js +75 -0
  159. package/dist/esm/schemas/tokenEstimation.js +7 -0
  160. package/dist/esm/schemas/transcript.js +86 -0
  161. package/dist/esm/schemas/usageNormalization.js +38 -0
  162. package/dist/esm/search/advancedFilter.js +197 -0
  163. package/dist/esm/search/sessionSearch.js +66 -0
  164. package/dist/esm/sessionFingerprint.js +40 -0
  165. package/dist/esm/sessionMonitor.js +198 -0
  166. package/dist/esm/sessionPreviews.js +522 -0
  167. package/dist/esm/sessionPromptHistory.js +254 -0
  168. package/dist/esm/sessionPromptSignals.js +364 -0
  169. package/dist/esm/sessionStats.js +160 -0
  170. package/dist/esm/sessionTokenTotals.js +98 -0
  171. package/dist/esm/sessionTranscripts.js +49 -0
  172. package/dist/esm/stateFile.js +119 -0
  173. package/dist/esm/statusline/BurnRateCalculator.js +40 -0
  174. package/dist/esm/statusline/claudeStatuslinePayload.js +148 -0
  175. package/dist/esm/statusline/formatter.js +122 -0
  176. package/dist/esm/statusline/index.js +8 -0
  177. package/dist/esm/terminalSync.js +95 -0
  178. package/dist/esm/testing/credentialGuard.js +197 -0
  179. package/dist/esm/testing/index.js +12 -0
  180. package/dist/esm/testing/sessionLogFixtures.js +128 -0
  181. package/dist/esm/tokenEstimation.js +67 -0
  182. package/dist/esm/tokenSummary.js +113 -0
  183. package/dist/esm/toolCategory.js +82 -0
  184. package/dist/esm/transcript.js +257 -0
  185. package/dist/esm/turns/assistantTurn.js +373 -0
  186. package/dist/esm/types/codex.js +23 -0
  187. package/dist/esm/types/decisionLog.js +5 -0
  188. package/dist/esm/types/historicalData.js +47 -0
  189. package/dist/esm/types/knowledgeNote.js +15 -0
  190. package/dist/esm/types/observedSessionV1.js +257 -0
  191. package/dist/esm/types/opencode.js +12 -0
  192. package/dist/esm/types/plan.js +7 -0
  193. package/dist/esm/types/sessionEvent.js +10 -0
  194. package/dist/esm/types/taskPersistence.js +12 -0
  195. package/dist/esm/usage/billingBlocks.js +148 -0
  196. package/dist/esm/usage/claudeUsageDedupe.js +189 -0
  197. package/dist/esm/usage/importSessionHistory.js +84 -0
  198. package/dist/esm/usage/subagentUsage.js +18 -0
  199. package/dist/esm/usage/usageEvents.js +402 -0
  200. package/dist/esm/usage/usageReports.js +202 -0
  201. package/dist/esm/usageNormalization.js +95 -0
  202. package/dist/esm/watchers/eventBridge.js +219 -0
  203. package/dist/esm/watchers/factory.js +63 -0
  204. package/dist/esm/watchers/jsonlTail.js +289 -0
  205. package/dist/esm/watchers/jsonlWatcher.js +435 -0
  206. package/dist/esm/watchers/providerReaderWatcher.js +118 -0
  207. package/dist/esm/watchers/sqliteWatcher.js +285 -0
  208. package/dist/esm/watchers/types.js +4 -0
  209. package/dist/esm/workspaceRoots.js +56 -0
  210. package/dist/esm/writers/atomic.js +375 -0
  211. package/dist/esm/writers/decisions.js +51 -0
  212. package/dist/esm/writers/notes.js +46 -0
  213. package/dist/esm/writers/tasks.js +63 -0
  214. package/dist/esm/zaiQuota.js +323 -0
  215. package/dist/esm/zaiQuotaApi.js +271 -0
  216. package/dist/esm/zaiQuotaWatcher.js +265 -0
  217. package/dist/fileHead.d.ts +22 -0
  218. package/dist/fileHead.js +33 -0
  219. package/dist/index.d.ts +16 -7
  220. package/dist/index.js +49 -15
  221. package/dist/node.d.ts +13 -1
  222. package/dist/node.js +43 -2
  223. package/dist/parsers/codexHistory.js +2 -2
  224. package/dist/parsers/codexParser.d.ts +12 -0
  225. package/dist/parsers/codexParser.js +34 -12
  226. package/dist/parsers/debugLogParser.js +2 -2
  227. package/dist/parsers/sessionPathResolver.js +5 -4
  228. package/dist/promptHistory.d.ts +32 -0
  229. package/dist/promptHistory.js +115 -59
  230. package/dist/providerFailure.d.ts +12 -6
  231. package/dist/providerFailure.js +45 -0
  232. package/dist/providers/claudeCode.js +7 -99
  233. package/dist/providers/claudeListing.d.ts +22 -0
  234. package/dist/providers/claudeListing.js +158 -0
  235. package/dist/providers/codex.d.ts +3 -1
  236. package/dist/providers/codex.js +26 -227
  237. package/dist/providers/codexRollouts.d.ts +44 -0
  238. package/dist/providers/codexRollouts.js +261 -0
  239. package/dist/providers/detect.js +4 -4
  240. package/dist/readers/plans.js +3 -3
  241. package/dist/schemas/index.d.ts +2 -0
  242. package/dist/schemas/index.js +7 -2
  243. package/dist/schemas/providerFailure.d.ts +154 -0
  244. package/dist/schemas/providerFailure.js +40 -0
  245. package/dist/sessionPromptHistory.d.ts +12 -7
  246. package/dist/sessionPromptHistory.js +15 -3
  247. package/dist/sessionPromptSignals.d.ts +9 -0
  248. package/dist/sessionPromptSignals.js +13 -0
  249. package/dist/testing/credentialGuard.d.ts +23 -0
  250. package/dist/testing/credentialGuard.js +233 -0
  251. package/dist/testing/index.d.ts +14 -0
  252. package/dist/testing/index.js +22 -0
  253. package/dist/testing/sessionLogFixtures.d.ts +28 -0
  254. package/dist/testing/sessionLogFixtures.js +169 -0
  255. package/dist/tokenEstimation.d.ts +2 -0
  256. package/dist/tokenEstimation.js +21 -11
  257. package/dist/toolCategory.d.ts +18 -0
  258. package/dist/toolCategory.js +86 -0
  259. package/dist/types/codex.d.ts +4 -0
  260. package/dist/usage/usageEvents.d.ts +16 -0
  261. package/dist/usage/usageEvents.js +53 -9
  262. package/dist/watchers/jsonlTail.d.ts +26 -1
  263. package/dist/watchers/jsonlTail.js +136 -28
  264. package/dist/watchers/jsonlWatcher.js +7 -0
  265. package/dist/watchers/providerReaderWatcher.js +1 -0
  266. package/dist/watchers/types.d.ts +6 -0
  267. package/dist/workspaceRoots.d.ts +23 -0
  268. package/dist/workspaceRoots.js +93 -0
  269. package/package.json +22 -2
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Debug log parser for Claude Code debug logs.
3
+ *
4
+ * Claude Code writes debug logs to ~/.claude/debug/. This module parses
5
+ * them into structured entries with level filtering and duplicate collapsing.
6
+ *
7
+ * @module parsers/debugLogParser
8
+ */
9
+ import * as fs from 'fs';
10
+ import * as path from 'path';
11
+ import { getLiveClaudeHome } from '../claudePaths';
12
+ // ── Constants ──
13
+ const LOG_LINE_PATTERN = /^(\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}[.\d]*Z?)\s+(DEBUG|INFO|WARN|ERROR)\s+(.*)$/;
14
+ const LEVEL_ORDER = {
15
+ DEBUG: 0,
16
+ INFO: 1,
17
+ WARN: 2,
18
+ ERROR: 3,
19
+ };
20
+ // ── Public API ──
21
+ /**
22
+ * Parses debug log content into structured entries.
23
+ *
24
+ * Handles multi-line entries (continuation lines without timestamps).
25
+ *
26
+ * @param content - Raw log file content
27
+ * @returns Array of parsed log entries
28
+ */
29
+ export function parseDebugLog(content) {
30
+ const lines = content.split('\n');
31
+ const entries = [];
32
+ let current = null;
33
+ for (let i = 0; i < lines.length; i++) {
34
+ const line = lines[i];
35
+ const match = line.match(LOG_LINE_PATTERN);
36
+ if (match) {
37
+ // Save previous entry
38
+ if (current)
39
+ entries.push(current);
40
+ current = {
41
+ timestamp: match[1],
42
+ level: match[2],
43
+ message: match[3],
44
+ fullContent: line,
45
+ lineNumber: i + 1,
46
+ };
47
+ }
48
+ else if (current && line.trim()) {
49
+ // Continuation line
50
+ current.fullContent += '\n' + line;
51
+ }
52
+ }
53
+ // Don't forget the last entry
54
+ if (current)
55
+ entries.push(current);
56
+ return entries;
57
+ }
58
+ /**
59
+ * Filters log entries by minimum level.
60
+ *
61
+ * @param entries - Array of log entries
62
+ * @param minLevel - Minimum level to include
63
+ * @returns Filtered entries at or above the minimum level
64
+ */
65
+ export function filterByLevel(entries, minLevel) {
66
+ const minOrder = LEVEL_ORDER[minLevel];
67
+ return entries.filter((e) => LEVEL_ORDER[e.level] >= minOrder);
68
+ }
69
+ /**
70
+ * Collapses consecutive identical log messages into single entries with counts.
71
+ *
72
+ * @param entries - Array of log entries
73
+ * @returns Collapsed entries with duplicateCount set on collapsed items
74
+ */
75
+ export function collapseDuplicates(entries) {
76
+ if (entries.length === 0)
77
+ return [];
78
+ const result = [];
79
+ let current = { ...entries[0], duplicateCount: 1 };
80
+ for (let i = 1; i < entries.length; i++) {
81
+ if (entries[i].message === current.message && entries[i].level === current.level) {
82
+ current.duplicateCount = (current.duplicateCount || 1) + 1;
83
+ }
84
+ else {
85
+ result.push(current);
86
+ current = { ...entries[i], duplicateCount: 1 };
87
+ }
88
+ }
89
+ result.push(current);
90
+ return result;
91
+ }
92
+ /**
93
+ * Discovers available debug log files.
94
+ *
95
+ * @returns Array of debug log file info, sorted by mtime (most recent first)
96
+ */
97
+ export function discoverDebugLogs() {
98
+ const debugDir = path.join(getLiveClaudeHome(), 'debug');
99
+ try {
100
+ if (!fs.existsSync(debugDir))
101
+ return [];
102
+ return fs
103
+ .readdirSync(debugDir)
104
+ .filter((f) => f.endsWith('.log') || f.endsWith('.txt'))
105
+ .map((name) => {
106
+ const fullPath = path.join(debugDir, name);
107
+ try {
108
+ const stat = fs.statSync(fullPath);
109
+ return {
110
+ path: fullPath,
111
+ name,
112
+ mtime: stat.mtime,
113
+ size: stat.size,
114
+ };
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ })
120
+ .filter((f) => f !== null)
121
+ .sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
122
+ }
123
+ catch {
124
+ return [];
125
+ }
126
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Line-buffered JSONL parser with optional Zod schema validation.
3
+ * Ported from sidekick-vscode/src/services/JsonlParser.ts
4
+ */
5
+ export class JsonlParser {
6
+ buffer = '';
7
+ onEvent;
8
+ onError;
9
+ schema;
10
+ constructor(callbacks, options) {
11
+ this.onEvent = callbacks.onEvent;
12
+ this.onError = callbacks.onError;
13
+ this.schema = options?.schema;
14
+ }
15
+ processChunk(chunk) {
16
+ this.buffer += chunk;
17
+ const lines = this.buffer.split('\n');
18
+ this.buffer = lines.pop() || '';
19
+ for (const line of lines) {
20
+ this.parseLine(line);
21
+ }
22
+ }
23
+ flush() {
24
+ if (this.buffer.trim().length > 0) {
25
+ this.parseLine(this.buffer);
26
+ this.buffer = '';
27
+ }
28
+ }
29
+ reset() {
30
+ this.buffer = '';
31
+ }
32
+ parseLine(line) {
33
+ const trimmed = line.trim();
34
+ if (!trimmed || !trimmed.startsWith('{'))
35
+ return;
36
+ try {
37
+ const raw = JSON.parse(trimmed);
38
+ if (this.schema) {
39
+ const result = this.schema.safeParse(raw);
40
+ if (result.success) {
41
+ this.onEvent(result.data);
42
+ }
43
+ else if (this.onError) {
44
+ this.onError(new Error(`Schema validation failed: ${result.error.message}`), line);
45
+ }
46
+ }
47
+ else {
48
+ this.onEvent(raw);
49
+ }
50
+ }
51
+ catch (error) {
52
+ if (this.onError) {
53
+ this.onError(error instanceof Error ? error : new Error(String(error)), line);
54
+ }
55
+ }
56
+ }
57
+ }
58
+ /** Truncation patterns from SessionMonitor. */
59
+ export const TRUNCATION_PATTERNS = [
60
+ { regex: /\[Response truncated/, name: 'Response truncated' },
61
+ { regex: /\[WARNING: Tool output was truncated/, name: 'Tool output truncated' },
62
+ { regex: /content_too_long/, name: 'Content too long' },
63
+ { regex: /<response clipped>/, name: 'Response clipped' },
64
+ { regex: /\[Content truncated/, name: 'Content truncated' },
65
+ { regex: /\[\.\.\.truncated/, name: 'Truncated' },
66
+ ];
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Claude Code exposes MCP tools under composite identifiers of the form
3
+ * `mcp__<server>__<tool>`. Splitting them correctly is subtle enough that
4
+ * consumers keep re-implementing it by hand (usually with a plain
5
+ * `split('__')`, which mangles server names containing single underscores).
6
+ * This module is the canonical splitter. Browser-safe: no Node imports.
7
+ *
8
+ * @module mcpToolName
9
+ */
10
+ const MCP_TOOL_NAME_PATTERN = /^mcp__([^_]+(?:_[^_]+)*)__(.+)$/;
11
+ /**
12
+ * Splits a Claude Code MCP tool identifier `mcp__<server>__<tool>` into parts.
13
+ *
14
+ * The server name ends at the first double underscore after the prefix, so
15
+ * single underscores stay inside it (`mcp__plugin_context7_context7__query-docs`
16
+ * → server `plugin_context7_context7`) and the tool keeps any further double
17
+ * underscores (`mcp__a__b__c` → tool `b__c`).
18
+ *
19
+ * Returns `null` for anything that is not a well-formed MCP tool id: a
20
+ * non-`mcp__` name, a missing or empty server or tool part, or a
21
+ * case-mismatched prefix. No trimming is applied.
22
+ */
23
+ export function parseMcpToolName(name) {
24
+ const match = MCP_TOOL_NAME_PATTERN.exec(name);
25
+ if (!match)
26
+ return null;
27
+ return { serverName: match[1], toolName: match[2] };
28
+ }