@salesforce/b2c-dx-mcp 1.1.3 → 1.2.1

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 (50) hide show
  1. package/dist/registry.js +21 -14
  2. package/dist/server-context.d.ts +6 -4
  3. package/dist/server-context.js +8 -5
  4. package/dist/tools/diagnostics/debug-capture-at-breakpoint.js +1 -1
  5. package/dist/tools/diagnostics/debug-continue.js +1 -1
  6. package/dist/tools/diagnostics/debug-end-session.js +1 -1
  7. package/dist/tools/diagnostics/debug-evaluate.js +1 -1
  8. package/dist/tools/diagnostics/debug-get-stack.js +1 -1
  9. package/dist/tools/diagnostics/debug-get-variables.js +1 -1
  10. package/dist/tools/diagnostics/debug-list-sessions.js +1 -1
  11. package/dist/tools/diagnostics/debug-set-breakpoints.js +1 -1
  12. package/dist/tools/diagnostics/debug-start-session.js +1 -1
  13. package/dist/tools/diagnostics/debug-step.js +1 -1
  14. package/dist/tools/diagnostics/debug-wait-for-stop.js +1 -1
  15. package/dist/tools/diagnostics/index.d.ts +6 -1
  16. package/dist/tools/diagnostics/index.js +13 -1
  17. package/dist/tools/diagnostics/log-watch-registry.d.ts +94 -0
  18. package/dist/tools/diagnostics/log-watch-registry.js +249 -0
  19. package/dist/tools/diagnostics/logs-get-recent.d.ts +9 -0
  20. package/dist/tools/diagnostics/logs-get-recent.js +68 -0
  21. package/dist/tools/diagnostics/logs-list-files.d.ts +9 -0
  22. package/dist/tools/diagnostics/logs-list-files.js +36 -0
  23. package/dist/tools/diagnostics/logs-watch-list.d.ts +4 -0
  24. package/dist/tools/diagnostics/logs-watch-list.js +36 -0
  25. package/dist/tools/diagnostics/logs-watch-poll.d.ts +4 -0
  26. package/dist/tools/diagnostics/logs-watch-poll.js +63 -0
  27. package/dist/tools/diagnostics/logs-watch-start.d.ts +9 -0
  28. package/dist/tools/diagnostics/logs-watch-start.js +117 -0
  29. package/dist/tools/diagnostics/logs-watch-stop.d.ts +4 -0
  30. package/dist/tools/diagnostics/logs-watch-stop.js +36 -0
  31. package/dist/tools/docs/docs-list.d.ts +3 -0
  32. package/dist/tools/docs/docs-list.js +22 -0
  33. package/dist/tools/docs/docs-read.d.ts +3 -0
  34. package/dist/tools/docs/docs-read.js +25 -0
  35. package/dist/tools/docs/docs-schema-list.d.ts +3 -0
  36. package/dist/tools/docs/docs-schema-list.js +21 -0
  37. package/dist/tools/docs/docs-schema-read.d.ts +3 -0
  38. package/dist/tools/docs/docs-schema-read.js +25 -0
  39. package/dist/tools/docs/docs-schema-search.d.ts +3 -0
  40. package/dist/tools/docs/docs-schema-search.js +26 -0
  41. package/dist/tools/docs/docs-search.d.ts +3 -0
  42. package/dist/tools/docs/docs-search.js +27 -0
  43. package/dist/tools/docs/index.d.ts +3 -0
  44. package/dist/tools/docs/index.js +22 -0
  45. package/dist/tools/index.d.ts +1 -0
  46. package/dist/tools/index.js +1 -0
  47. package/dist/utils/constants.d.ts +2 -2
  48. package/dist/utils/constants.js +1 -1
  49. package/oclif.manifest.json +4 -2
  50. package/package.json +4 -4
package/dist/registry.js CHANGED
@@ -8,18 +8,21 @@ import { detectWorkspaceType } from '@salesforce/b2c-tooling-sdk/discovery';
8
8
  import { ALL_TOOLSETS, TOOLSETS, VALID_TOOLSET_NAMES } from './utils/index.js';
9
9
  import { createCartridgesTools } from './tools/cartridges/index.js';
10
10
  import { createDiagnosticsTools } from './tools/diagnostics/index.js';
11
+ import { createDocsTools } from './tools/docs/index.js';
11
12
  import { createMrtTools } from './tools/mrt/index.js';
12
13
  import { createPwav3Tools } from './tools/pwav3/index.js';
13
14
  import { createScapiTools } from './tools/scapi/index.js';
14
15
  import { createStorefrontNextTools } from './tools/storefrontnext/index.js';
15
16
  /**
16
- * Base toolset that is always enabled.
17
- * Provides SCAPI discovery and custom API scaffolding tools.
17
+ * Base toolsets that are always enabled regardless of detected project type.
18
+ * - SCAPI: SCAPI discovery and custom API scaffolding tools.
19
+ * - DIAGNOSTICS: script debugger, log inspection, and docs tools — useful in
20
+ * every project type, so they are always available.
18
21
  */
19
- const BASE_TOOLSET = 'SCAPI';
22
+ const BASE_TOOLSETS = ['SCAPI', 'DIAGNOSTICS'];
20
23
  /**
21
24
  * Toolset mapping by project type.
22
- * Each project type enables specific toolsets IN ADDITION to the base toolset.
25
+ * Each project type enables specific toolsets IN ADDITION to the base toolsets.
23
26
  */
24
27
  const PROJECT_TYPE_TOOLSETS = {
25
28
  cartridges: ['CARTRIDGES'],
@@ -27,25 +30,27 @@ const PROJECT_TYPE_TOOLSETS = {
27
30
  'storefront-next': ['STOREFRONTNEXT', 'MRT', 'CARTRIDGES'],
28
31
  };
29
32
  /**
30
- * Gets toolsets for a project type, always including the base toolset.
33
+ * Gets toolsets for a project type, always including the base toolsets.
31
34
  */
32
35
  function getToolsetsForProjectType(projectType) {
33
36
  const additionalToolsets = PROJECT_TYPE_TOOLSETS[projectType] ?? [];
34
- return [...additionalToolsets, BASE_TOOLSET];
37
+ return [...additionalToolsets, ...BASE_TOOLSETS];
35
38
  }
36
39
  /**
37
40
  * Maps multiple detected project types to a union of MCP toolsets.
38
41
  *
39
42
  * Combines toolsets from all matched project types, enabling hybrid
40
- * project support (e.g., cartridges + pwa-kit-v3 gets CARTRIDGES + PWAV3 + MRT + SCAPI).
43
+ * project support (e.g., cartridges + pwa-kit-v3 gets CARTRIDGES + PWAV3 + MRT + SCAPI + DIAGNOSTICS).
41
44
  *
42
45
  * @param projectTypes - Array of detected project types
43
- * @returns Union of all toolsets for the detected project types (always includes base toolset)
46
+ * @returns Union of all toolsets for the detected project types (always includes base toolsets)
44
47
  */
45
48
  function getToolsetsForProjectTypes(projectTypes) {
46
49
  const toolsetSet = new Set();
47
- // Always include base toolset
48
- toolsetSet.add(BASE_TOOLSET);
50
+ // Always include base toolsets
51
+ for (const base of BASE_TOOLSETS) {
52
+ toolsetSet.add(base);
53
+ }
49
54
  // Add toolsets for each detected project type
50
55
  for (const projectType of projectTypes) {
51
56
  for (const toolset of getToolsetsForProjectType(projectType)) {
@@ -65,6 +70,7 @@ function getToolsetsForProjectTypes(projectTypes) {
65
70
  export function createToolRegistry(loadServices, serverContext) {
66
71
  const registry = {
67
72
  CARTRIDGES: [],
73
+ DIAGNOSTICS: [],
68
74
  MRT: [],
69
75
  PWAV3: [],
70
76
  SCAPI: [],
@@ -74,6 +80,7 @@ export function createToolRegistry(loadServices, serverContext) {
74
80
  const allTools = [
75
81
  ...createCartridgesTools(loadServices),
76
82
  ...createDiagnosticsTools(loadServices, serverContext),
83
+ ...createDocsTools(loadServices),
77
84
  ...createMrtTools(loadServices),
78
85
  ...createPwav3Tools(loadServices),
79
86
  ...createScapiTools(loadServices),
@@ -89,7 +96,7 @@ export function createToolRegistry(loadServices, serverContext) {
89
96
  }
90
97
  /**
91
98
  * Performs workspace auto-discovery and returns appropriate toolsets.
92
- * Always includes BASE_TOOLSET even if no project types are detected.
99
+ * Always includes the BASE_TOOLSETS even if no project types are detected.
93
100
  *
94
101
  * @param flags - Startup flags containing projectDirectory
95
102
  * @param reason - Reason for triggering auto-discovery (for logging)
@@ -125,8 +132,8 @@ async function performAutoDiscovery(flags, reason) {
125
132
  * 2. Start with all tools from --toolsets (or auto-discovered toolsets)
126
133
  * 3. Add individual tools from --tools (can be from any toolset)
127
134
  *
128
- * Auto-discovery always enables at least the BASE_TOOLSET (SCAPI), even if no
129
- * project types are detected in the workspace.
135
+ * Auto-discovery always enables at least the BASE_TOOLSETS (SCAPI + DIAGNOSTICS),
136
+ * even if no project types are detected in the workspace.
130
137
  *
131
138
  * Example:
132
139
  * --toolsets STOREFRONTNEXT,MRT --tools cartridge_deploy
@@ -173,7 +180,7 @@ export async function registerToolsets(flags, server, loadServices, serverContex
173
180
  // Auto-discovery: If no valid toolsets AND no valid individual tools, detect workspace type.
174
181
  // This handles both: (1) no flags provided, and (2) all provided flags are invalid.
175
182
  // Auto-discovery enables appropriate toolsets based on workspace type,
176
- // or at minimum BASE_TOOLSET if no project types are detected.
183
+ // or at minimum the BASE_TOOLSETS if no project types are detected.
177
184
  if (toolsetsToEnable.size === 0 && validIndividualTools.length === 0) {
178
185
  const discoveredToolsets = await performAutoDiscovery(flags, 'no valid toolsets or tools');
179
186
  for (const toolset of discoveredToolsets) {
@@ -1,8 +1,9 @@
1
+ import { LogWatchRegistry } from './tools/diagnostics/log-watch-registry.js';
1
2
  import { DebugSessionRegistry } from './tools/diagnostics/session-registry.js';
2
3
  /**
3
4
  * Server-scoped persistent state that lives for the lifetime of the MCP
4
5
  * server process. Holds registries for stateful resources (debug sessions,
5
- * future log watches) that need to span multiple tool invocations.
6
+ * log watches) that need to span multiple tool invocations.
6
7
  *
7
8
  * ## Multi-agent / shared-state caveats
8
9
  *
@@ -16,12 +17,13 @@ import { DebugSessionRegistry } from './tools/diagnostics/session-registry.js';
16
17
  * client would also share the same context. Tools that mutate registries
17
18
  * (like the debug tools) should not assume single-tenant access.
18
19
  *
19
- * The debug registry already handles concurrent sessions via session IDs
20
- * and host:client_id pairs, so multi-agent use is functional but agents
21
- * may see each other's sessions via `debug_list_sessions`.
20
+ * Both registries dedup on a stable key (host:client_id for debug,
21
+ * hostname for log watches), so multi-agent use is functional but agents
22
+ * may see each other's sessions/watches via list tools.
22
23
  */
23
24
  export declare class ServerContext {
24
25
  readonly debugSessions: DebugSessionRegistry;
26
+ readonly logWatches: LogWatchRegistry;
25
27
  constructor();
26
28
  destroyAll(): Promise<void>;
27
29
  }
@@ -3,11 +3,12 @@
3
3
  * SPDX-License-Identifier: Apache-2
4
4
  * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
5
  */
6
+ import { LogWatchRegistry } from './tools/diagnostics/log-watch-registry.js';
6
7
  import { DebugSessionRegistry } from './tools/diagnostics/session-registry.js';
7
8
  /**
8
9
  * Server-scoped persistent state that lives for the lifetime of the MCP
9
10
  * server process. Holds registries for stateful resources (debug sessions,
10
- * future log watches) that need to span multiple tool invocations.
11
+ * log watches) that need to span multiple tool invocations.
11
12
  *
12
13
  * ## Multi-agent / shared-state caveats
13
14
  *
@@ -21,17 +22,19 @@ import { DebugSessionRegistry } from './tools/diagnostics/session-registry.js';
21
22
  * client would also share the same context. Tools that mutate registries
22
23
  * (like the debug tools) should not assume single-tenant access.
23
24
  *
24
- * The debug registry already handles concurrent sessions via session IDs
25
- * and host:client_id pairs, so multi-agent use is functional but agents
26
- * may see each other's sessions via `debug_list_sessions`.
25
+ * Both registries dedup on a stable key (host:client_id for debug,
26
+ * hostname for log watches), so multi-agent use is functional but agents
27
+ * may see each other's sessions/watches via list tools.
27
28
  */
28
29
  export class ServerContext {
29
30
  debugSessions;
31
+ logWatches;
30
32
  constructor() {
31
33
  this.debugSessions = new DebugSessionRegistry();
34
+ this.logWatches = new LogWatchRegistry();
32
35
  }
33
36
  async destroyAll() {
34
- await this.debugSessions.destroyAll();
37
+ await Promise.allSettled([this.debugSessions.destroyAll(), this.logWatches.destroyAll()]);
35
38
  }
36
39
  }
37
40
  //# sourceMappingURL=server-context.js.map
@@ -16,7 +16,7 @@ export function createDebugCaptureAtBreakpointTool(loadServices, serverContext)
16
16
  'Use trigger_url to have the tool fire the request itself (recommended) — this avoids needing to coordinate a separate request while the tool blocks. ' +
17
17
  'Without trigger_url, the tool BLOCKS until the breakpoint is hit or timeout expires and requires the user to trigger a request externally. ' +
18
18
  'For more control, use the non-blocking workflow: debug_set_breakpoints → trigger request → debug_list_sessions (check halted_threads) → debug_get_variables.',
19
- toolsets: ['CARTRIDGES', 'SCAPI'],
19
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
20
20
  inputSchema: {
21
21
  session_id: z.string().describe('Session ID returned by debug_start_session.'),
22
22
  file: z.string().describe('Local file path or server script path for the breakpoint.'),
@@ -11,7 +11,7 @@ export function createDebugContinueTool(loadServices, serverContext) {
11
11
  name: 'debug_continue',
12
12
  description: 'Resume execution of a halted thread. ' +
13
13
  'The thread runs until the next breakpoint or completes the current request.',
14
- toolsets: ['CARTRIDGES', 'SCAPI'],
14
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
15
15
  inputSchema: {
16
16
  session_id: z.string().describe('Session ID returned by debug_start_session.'),
17
17
  thread_id: z.number().int().describe('Thread ID of the halted thread to resume.'),
@@ -11,7 +11,7 @@ export function createDebugEndSessionTool(loadServices, serverContext) {
11
11
  name: 'debug_end_session',
12
12
  description: 'End a script debugger session and free its slot on the instance. ' +
13
13
  'IMPORTANT: Always call this when finished debugging — leaving sessions open can interfere with other debuggers and consumes a debugger client slot.',
14
- toolsets: ['CARTRIDGES', 'SCAPI'],
14
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
15
15
  inputSchema: {
16
16
  session_id: z.string().describe('Session ID returned by debug_start_session.'),
17
17
  clear_breakpoints: z
@@ -11,7 +11,7 @@ export function createDebugEvaluateTool(loadServices, serverContext) {
11
11
  name: 'debug_evaluate',
12
12
  description: 'Evaluate a JavaScript expression in the context of a halted thread and stack frame. ' +
13
13
  'WARNING: Expressions may have side effects (modify variables, call functions). Use with care.',
14
- toolsets: ['CARTRIDGES', 'SCAPI'],
14
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
15
15
  inputSchema: {
16
16
  session_id: z.string().describe('Session ID returned by debug_start_session.'),
17
17
  thread_id: z.number().int().describe('Thread ID from debug_wait_for_stop or debug_list_sessions.'),
@@ -12,7 +12,7 @@ export function createDebugGetStackTool(loadServices, serverContext) {
12
12
  name: 'debug_get_stack',
13
13
  description: 'Get the call stack for a halted thread. ' +
14
14
  'Returns frames with mapped local file paths and server script paths.',
15
- toolsets: ['CARTRIDGES', 'SCAPI'],
15
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
16
16
  inputSchema: {
17
17
  session_id: z.string().describe('Session ID returned by debug_start_session.'),
18
18
  thread_id: z.number().int().describe('Thread ID from debug_wait_for_stop or debug_list_sessions.'),
@@ -12,7 +12,7 @@ export function createDebugGetVariablesTool(loadServices, serverContext) {
12
12
  name: 'debug_get_variables',
13
13
  description: 'Get variables for a stack frame in a halted thread. ' +
14
14
  'Defaults to top-frame locals. Use scope to filter (local/closure/global) or object_path to drill into nested objects.',
15
- toolsets: ['CARTRIDGES', 'SCAPI'],
15
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
16
16
  inputSchema: {
17
17
  session_id: z.string().describe('Session ID returned by debug_start_session.'),
18
18
  thread_id: z.number().int().describe('Thread ID from debug_wait_for_stop or debug_list_sessions.'),
@@ -11,7 +11,7 @@ export function createDebugListSessionsTool(loadServices, serverContext) {
11
11
  name: 'debug_list_sessions',
12
12
  description: 'List active script debugger sessions with their breakpoints and any halted threads. ' +
13
13
  'Use this to discover orphaned sessions, check whether breakpoints are armed, and poll for halted threads in the non-blocking debug workflow.',
14
- toolsets: ['CARTRIDGES', 'SCAPI'],
14
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
15
15
  inputSchema: {},
16
16
  async execute(_args, context) {
17
17
  const registry = getRegistry(context);
@@ -13,7 +13,7 @@ export function createDebugSetBreakpointsTool(loadServices, serverContext) {
13
13
  description: 'Set breakpoints in a debug session. Replaces all previously set breakpoints. ' +
14
14
  'Accepts local file paths (mapped to server paths via cartridge discovery), cartridge-prefixed paths, or server paths starting with /. ' +
15
15
  'Check the "verified" field and "warnings" — unmapped paths are flagged.',
16
- toolsets: ['CARTRIDGES', 'SCAPI'],
16
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
17
17
  inputSchema: {
18
18
  session_id: z.string().describe('Session ID returned by debug_start_session.'),
19
19
  breakpoints: z
@@ -15,7 +15,7 @@ export function createDebugStartSessionTool(loadServices, serverContext) {
15
15
  'Returns a session_id for use with other debug tools, plus discovered cartridge mappings. ' +
16
16
  'WARNING: Debug sessions halt remote request threads on the instance. Always call debug_end_session when finished. ' +
17
17
  'Requires Basic auth credentials (username/password) and the script debugger enabled in Business Manager.',
18
- toolsets: ['CARTRIDGES', 'SCAPI'],
18
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
19
19
  inputSchema: {
20
20
  cartridge_directory: z
21
21
  .string()
@@ -15,7 +15,7 @@ function createStepTool(action, description, loadServices, serverContext) {
15
15
  return createToolAdapter({
16
16
  name: `debug_${action}`,
17
17
  description: description + ' Follow with debug_wait_for_stop to see where execution landed.',
18
- toolsets: ['CARTRIDGES', 'SCAPI'],
18
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
19
19
  inputSchema: {
20
20
  session_id: z.string().describe('Session ID returned by debug_start_session.'),
21
21
  thread_id: z.number().int().describe('Thread ID of the halted thread to step.'),
@@ -15,7 +15,7 @@ export function createDebugWaitForStopTool(loadServices, serverContext) {
15
15
  description: 'Wait for a thread to halt at a breakpoint or step. ' +
16
16
  'Returns immediately if a thread is already halted; otherwise BLOCKS until a halt occurs or the timeout expires. ' +
17
17
  'Preferred non-blocking alternative: after debug_set_breakpoints, trigger the request yourself, then use debug_list_sessions to check halted_threads before calling debug_get_stack/debug_get_variables.',
18
- toolsets: ['CARTRIDGES', 'SCAPI'],
18
+ toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'SCAPI'],
19
19
  inputSchema: {
20
20
  session_id: z.string().describe('Session ID returned by debug_start_session.'),
21
21
  timeout_ms: z
@@ -1,4 +1,9 @@
1
1
  import type { McpTool } from '../../utils/index.js';
2
2
  import type { Services } from '../../services.js';
3
3
  import type { ServerContext } from '../../server-context.js';
4
- export declare function createDiagnosticsTools(loadServices: () => Promise<Services> | Services, serverContext?: ServerContext): McpTool[];
4
+ import { type LogsListFilesInjections } from './logs-list-files.js';
5
+ import { type LogsGetRecentInjections } from './logs-get-recent.js';
6
+ import { type LogsWatchStartInjections } from './logs-watch-start.js';
7
+ export interface DiagnosticsToolInjections extends LogsGetRecentInjections, LogsListFilesInjections, LogsWatchStartInjections {
8
+ }
9
+ export declare function createDiagnosticsTools(loadServices: () => Promise<Services> | Services, serverContext?: ServerContext, injections?: DiagnosticsToolInjections): McpTool[];
@@ -14,7 +14,13 @@ import { createDebugEvaluateTool } from './debug-evaluate.js';
14
14
  import { createDebugContinueTool } from './debug-continue.js';
15
15
  import { createDebugStepTools } from './debug-step.js';
16
16
  import { createDebugCaptureAtBreakpointTool } from './debug-capture-at-breakpoint.js';
17
- export function createDiagnosticsTools(loadServices, serverContext) {
17
+ import { createLogsListFilesTool } from './logs-list-files.js';
18
+ import { createLogsGetRecentTool } from './logs-get-recent.js';
19
+ import { createLogsWatchStartTool } from './logs-watch-start.js';
20
+ import { createLogsWatchPollTool } from './logs-watch-poll.js';
21
+ import { createLogsWatchStopTool } from './logs-watch-stop.js';
22
+ import { createLogsWatchListTool } from './logs-watch-list.js';
23
+ export function createDiagnosticsTools(loadServices, serverContext, injections) {
18
24
  return [
19
25
  createDebugListSessionsTool(loadServices, serverContext),
20
26
  createDebugStartSessionTool(loadServices, serverContext),
@@ -27,6 +33,12 @@ export function createDiagnosticsTools(loadServices, serverContext) {
27
33
  createDebugContinueTool(loadServices, serverContext),
28
34
  ...createDebugStepTools(loadServices, serverContext),
29
35
  createDebugCaptureAtBreakpointTool(loadServices, serverContext),
36
+ createLogsListFilesTool(loadServices, serverContext, injections),
37
+ createLogsGetRecentTool(loadServices, serverContext, injections),
38
+ createLogsWatchStartTool(loadServices, serverContext, injections),
39
+ createLogsWatchPollTool(loadServices, serverContext),
40
+ createLogsWatchStopTool(loadServices, serverContext),
41
+ createLogsWatchListTool(loadServices, serverContext),
30
42
  ];
31
43
  }
32
44
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,94 @@
1
+ import type { LogEntry, LogFile, TailLogsResult } from '@salesforce/b2c-tooling-sdk/operations/logs';
2
+ import type { ToolExecutionContext } from '../adapter.js';
3
+ /** Maximum number of buffered entries before oldest are evicted. */
4
+ export declare const DEFAULT_BUFFER_CAP = 5000;
5
+ /**
6
+ * Maximum cumulative bytes buffered before oldest entries are evicted.
7
+ * Guards against a small number of pathologically large entries (e.g. multi-MB
8
+ * stack traces) blowing past the count cap's intended memory bound.
9
+ */
10
+ export declare const DEFAULT_BUFFER_BYTES_CAP: number;
11
+ export interface PollWaiter {
12
+ resolve: () => void;
13
+ timer: ReturnType<typeof setTimeout>;
14
+ }
15
+ export interface LogWatchEntry {
16
+ watchId: string;
17
+ hostname: string;
18
+ prefixes: string[];
19
+ buffer: LogEntry[];
20
+ /** Running byte size of `buffer` (raw + message), used for the byte cap. */
21
+ bufferBytes: number;
22
+ rotations: LogFile[];
23
+ /** Cumulative deduped list of every file ever discovered (for logs_watch_list). */
24
+ filesDiscovered: LogFile[];
25
+ /** Files discovered since the last poll drain (what logs_watch_poll returns). */
26
+ pendingFilesDiscovered: LogFile[];
27
+ errors: Array<{
28
+ message: string;
29
+ at: string;
30
+ }>;
31
+ totalEntriesSeen: number;
32
+ droppedEntries: number;
33
+ bufferCap: number;
34
+ bufferBytesCap: number;
35
+ stop: () => Promise<void>;
36
+ done: Promise<void>;
37
+ pollWaiters: PollWaiter[];
38
+ createdAt: number;
39
+ lastActivityAt: number;
40
+ stopped: boolean;
41
+ }
42
+ export interface RegisterWatchOptions {
43
+ hostname: string;
44
+ prefixes: string[];
45
+ tailResult: TailLogsResult;
46
+ bufferCap?: number;
47
+ bufferBytesCap?: number;
48
+ }
49
+ export declare class LogWatchRegistry {
50
+ private cleanupTimer;
51
+ private readonly watches;
52
+ constructor();
53
+ /**
54
+ * Append a log entry to a watch buffer. Evicts oldest if over cap.
55
+ * Resolves any pending poll waiters.
56
+ */
57
+ appendEntry(watchId: string, entry: LogEntry): void;
58
+ appendError(watchId: string, err: Error): void;
59
+ /**
60
+ * Append a discovered file (deduped by name).
61
+ */
62
+ appendFileDiscovered(watchId: string, file: LogFile): void;
63
+ appendRotation(watchId: string, file: LogFile): void;
64
+ destroyAll(): Promise<void>;
65
+ destroyWatch(watchId: string): Promise<void>;
66
+ /**
67
+ * Drain buffered entries (up to maxEntries) and any rotation/error events
68
+ * from the watch. Removes drained items from the underlying buffers.
69
+ */
70
+ drain(watchId: string, maxEntries: number): {
71
+ entries: LogEntry[];
72
+ errors: Array<{
73
+ message: string;
74
+ at: string;
75
+ }>;
76
+ filesDiscovered: LogFile[];
77
+ rotations: LogFile[];
78
+ truncated: boolean;
79
+ };
80
+ findByHostname(hostname: string): LogWatchEntry | undefined;
81
+ getWatch(watchId: string): LogWatchEntry | undefined;
82
+ getWatchOrThrow(watchId: string): LogWatchEntry;
83
+ listWatches(): LogWatchEntry[];
84
+ registerWatch(opts: RegisterWatchOptions): LogWatchEntry;
85
+ /**
86
+ * Wait until at least one entry is buffered (or rotation/error event), or until
87
+ * timeout elapses. Returns immediately if the buffer is non-empty.
88
+ */
89
+ waitForActivity(watchId: string, timeoutMs: number): Promise<void>;
90
+ private cleanupIdleWatches;
91
+ private flushWaiters;
92
+ }
93
+ export declare function getLogWatchRegistry(context: ToolExecutionContext): LogWatchRegistry;
94
+ export declare function getLogWatchEntry(context: ToolExecutionContext, watchId: string): LogWatchEntry;