octocode-cli 1.5.1 → 1.5.3

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 (112) hide show
  1. package/README.md +28 -9
  2. package/out/chunks/chunk-375ZNU3A.js +317 -0
  3. package/out/chunks/{chunk-V64AXUWB.js → chunk-AYILFPX4.js} +1 -1
  4. package/out/chunks/chunk-BRHVQB64.js +10 -0
  5. package/out/chunks/{command-help-specs-JZXVSLZ5.js → chunk-KWJUBVXJ.js} +1 -1
  6. package/out/chunks/chunk-OMXWZJBJ.js +100 -0
  7. package/out/chunks/command-help-specs-RVJK6V6M.js +8 -0
  8. package/out/chunks/commands-JFDCC4Q7.js +8 -0
  9. package/out/chunks/{help-P7TCOYAJ.js → help-H3WGUJO7.js} +1 -1
  10. package/out/chunks/main-help-BUTDD4IR.js +10 -0
  11. package/out/chunks/{spinner-URV2OX6O.js → spinner-DXD4JQIU.js} +1 -1
  12. package/out/chunks/tool-command-L6PVHUNS.js +8 -0
  13. package/out/octocode-cli.js +1 -1
  14. package/package.json +2 -2
  15. package/skills/octocode-brainstorming/scripts/tavily-search.mjs +1 -10
  16. package/skills/octocode-chrome-devtools/scripts/cdp-runner.mjs +0 -2
  17. package/skills/octocode-chrome-devtools/scripts/cdp-sandbox.mjs +1 -5
  18. package/skills/octocode-chrome-devtools/scripts/cdp-template.mjs +1 -10
  19. package/skills/octocode-chrome-devtools/scripts/open-browser.mjs +0 -3
  20. package/skills/octocode-chrome-devtools/scripts/sourcemap-resolver.mjs +1 -4
  21. package/skills/octocode-chrome-devtools/scripts/undercover.mjs +0 -2
  22. package/skills/octocode-engineer/SKILL.md +7 -33
  23. package/skills/octocode-engineer/references/cli-reference.md +5 -11
  24. package/skills/octocode-engineer/references/externals.md +0 -4
  25. package/skills/octocode-engineer/references/quality-indicators.md +10 -50
  26. package/skills/octocode-engineer/references/tool-workflows.md +10 -13
  27. package/skills/octocode-engineer/src/analysis/dependency-summary.test.ts +2 -2
  28. package/skills/octocode-engineer/src/ast/metrics.test.ts +2 -2
  29. package/skills/octocode-engineer/src/ast/search-main.ts +2 -15
  30. package/skills/octocode-engineer/src/ast/search.ts +1 -7
  31. package/skills/octocode-engineer/src/ast/tree-sitter.test.ts +4 -4
  32. package/skills/octocode-engineer/src/ast/tree-sitter.ts +2 -2
  33. package/skills/octocode-engineer/src/collectors/chains.ts +3 -10
  34. package/skills/octocode-engineer/src/collectors/prototype-pollution.ts +3 -3
  35. package/skills/octocode-engineer/src/collectors/security.ts +3 -3
  36. package/skills/octocode-engineer/src/common/ensure-deps.ts +3 -20
  37. package/skills/octocode-engineer/src/detectors/code-quality.ts +0 -1
  38. package/skills/octocode-engineer/src/index.test.ts +1 -1
  39. package/skills/octocode-engineer/src/index.ts +1 -11
  40. package/skills/octocode-engineer/src/pipeline/affected.ts +2 -7
  41. package/skills/octocode-engineer/src/pipeline/baseline.ts +2 -8
  42. package/skills/octocode-engineer/src/pipeline/cache.ts +2 -2
  43. package/skills/octocode-engineer/src/pipeline/config-loader.test.ts +1 -2
  44. package/skills/octocode-engineer/src/pipeline/config-loader.ts +0 -9
  45. package/skills/octocode-engineer/src/pipeline/create-options.ts +2 -15
  46. package/skills/octocode-engineer/src/pipeline/reporters.ts +2 -12
  47. package/skills/octocode-engineer/src/reporting/summary-md.test.ts +2 -2
  48. package/skills/octocode-engineer/src/run.ts +1 -7
  49. package/skills/octocode-engineer/src/types/constants.ts +0 -5
  50. package/skills/octocode-engineer/src/types/core.ts +0 -5
  51. package/skills/octocode-news/eslint.config.mjs +1 -6
  52. package/skills/octocode-news/src/rss-core.ts +2 -4
  53. package/skills/octocode-research/ecosystem.config.cjs +0 -31
  54. package/skills/octocode-research/package.json +1 -1
  55. package/skills/octocode-research/scripts/server.js +272 -230
  56. package/skills/octocode-research/src/__tests__/integration/circuitBreaker.test.ts +0 -24
  57. package/skills/octocode-research/src/__tests__/integration/routes.test.ts +0 -10
  58. package/skills/octocode-research/src/__tests__/integration/serverLifecycle.test.ts +5 -22
  59. package/skills/octocode-research/src/__tests__/integration/toolsRoutes.test.ts +0 -27
  60. package/skills/octocode-research/src/__tests__/unit/circuitBreaker.test.ts +0 -29
  61. package/skills/octocode-research/src/__tests__/unit/errorHandler.test.ts +1 -12
  62. package/skills/octocode-research/src/__tests__/unit/httpPreprocess.test.ts +1 -9
  63. package/skills/octocode-research/src/__tests__/unit/logger.test.ts +0 -7
  64. package/skills/octocode-research/src/__tests__/unit/queryParser.test.ts +1 -7
  65. package/skills/octocode-research/src/__tests__/unit/responseBuilder.test.ts +0 -11
  66. package/skills/octocode-research/src/__tests__/unit/retry.test.ts +1 -18
  67. package/skills/octocode-research/src/__tests__/unit/schemas.test.ts +2 -25
  68. package/skills/octocode-research/src/index.ts +0 -27
  69. package/skills/octocode-research/src/mcpCache.ts +3 -18
  70. package/skills/octocode-research/src/middleware/errorHandler.ts +1 -4
  71. package/skills/octocode-research/src/middleware/logger.ts +1 -6
  72. package/skills/octocode-research/src/middleware/queryParser.ts +3 -22
  73. package/skills/octocode-research/src/routes/github.ts +0 -11
  74. package/skills/octocode-research/src/routes/local.ts +0 -12
  75. package/skills/octocode-research/src/routes/lsp.ts +1 -10
  76. package/skills/octocode-research/src/routes/package.ts +0 -2
  77. package/skills/octocode-research/src/routes/prompts.ts +2 -32
  78. package/skills/octocode-research/src/routes/tools.ts +12 -177
  79. package/skills/octocode-research/src/server-init.ts +0 -32
  80. package/skills/octocode-research/src/server.ts +8 -37
  81. package/skills/octocode-research/src/types/errorGuards.ts +0 -15
  82. package/skills/octocode-research/src/types/guards.ts +6 -27
  83. package/skills/octocode-research/src/types/mcp.ts +1 -8
  84. package/skills/octocode-research/src/types/responses.ts +0 -15
  85. package/skills/octocode-research/src/utils/asyncTimeout.ts +1 -63
  86. package/skills/octocode-research/src/utils/circuitBreaker.ts +43 -166
  87. package/skills/octocode-research/src/utils/colors.ts +3 -17
  88. package/skills/octocode-research/src/utils/errorQueue.ts +6 -28
  89. package/skills/octocode-research/src/utils/logger.ts +11 -93
  90. package/skills/octocode-research/src/utils/resilience.ts +22 -77
  91. package/skills/octocode-research/src/utils/responseBuilder.ts +26 -78
  92. package/skills/octocode-research/src/utils/responseFactory.ts +0 -7
  93. package/skills/octocode-research/src/utils/responseParser.ts +11 -59
  94. package/skills/octocode-research/src/utils/retry.ts +12 -75
  95. package/skills/octocode-research/src/utils/routeFactory.ts +10 -61
  96. package/skills/octocode-research/src/utils/url.ts +0 -5
  97. package/skills/octocode-research/src/validation/httpPreprocess.ts +15 -61
  98. package/skills/octocode-research/src/validation/schemas.ts +14 -101
  99. package/skills/octocode-research/src/validation/toolCallSchema.ts +5 -65
  100. package/skills/octocode-research/tsdown.config.ts +2 -7
  101. package/skills/octocode-search-skill/SKILL.md +9 -2
  102. package/skills/octocode-search-skill/references/discovery-surfaces.md +2 -1
  103. package/skills/octocode-slides/scripts/navbridge.js +1 -14
  104. package/skills/octocode-slides/scripts/presenter.js +2 -61
  105. package/skills/octocode-stats/scripts/build_dashboard.mjs +1 -19
  106. package/out/chunks/chunk-7476PETK.js +0 -309
  107. package/out/chunks/chunk-OQBJTZWK.js +0 -60
  108. package/out/chunks/chunk-UCZCF3BQ.js +0 -9
  109. package/out/chunks/commands-XBFPLHSQ.js +0 -8
  110. package/out/chunks/main-help-ULF5PAQY.js +0 -10
  111. package/out/chunks/tool-command-M6VA7P2F.js +0 -8
  112. package/skills/octocode-research/AGENTS.md +0 -349
@@ -1,20 +1,10 @@
1
- /**
2
- * Bounded queue for fire-and-forget operation errors.
3
- * Provides visibility into async errors without blocking main flow.
4
- *
5
- * @module utils/errorQueue
6
- */
7
-
8
1
  interface QueuedError {
9
2
  timestamp: Date;
10
3
  error: Error;
11
4
  context?: string;
12
5
  }
13
6
 
14
- /**
15
- * Bounded error queue that stores recent errors from async operations.
16
- * Prevents unbounded memory growth while maintaining error visibility.
17
- */
7
+
18
8
  class ErrorQueue {
19
9
  private errors: QueuedError[] = [];
20
10
  private readonly maxSize: number;
@@ -23,10 +13,7 @@ class ErrorQueue {
23
13
  this.maxSize = maxSize;
24
14
  }
25
15
 
26
- /**
27
- * Add an error to the queue.
28
- * If queue is full, oldest error is removed.
29
- */
16
+
30
17
  push(error: unknown, context?: string): void {
31
18
  const normalizedError =
32
19
  error instanceof Error ? error : new Error(String(error));
@@ -37,35 +24,26 @@ class ErrorQueue {
37
24
  context,
38
25
  });
39
26
 
40
- // Bounded: remove oldest when full
41
27
  if (this.errors.length > this.maxSize) {
42
28
  this.errors.shift();
43
29
  }
44
30
  }
45
31
 
46
- /**
47
- * Get the most recent errors.
48
- */
32
+
49
33
  getRecent(count = 10): QueuedError[] {
50
34
  return this.errors.slice(-count);
51
35
  }
52
36
 
53
- /**
54
- * Clear all errors from the queue.
55
- */
37
+
56
38
  clear(): void {
57
39
  this.errors = [];
58
40
  }
59
41
 
60
- /**
61
- * Get current queue size.
62
- */
42
+
63
43
  get size(): number {
64
44
  return this.errors.length;
65
45
  }
66
46
  }
67
47
 
68
- /**
69
- * Global error queue instance for fire-and-forget operations.
70
- */
48
+
71
49
  export const errorQueue = new ErrorQueue();
@@ -1,23 +1,12 @@
1
1
  import { errorLog, warnLog } from './colors.js';
2
2
  import { errorQueue } from './errorQueue.js';
3
- /**
4
- * Cross-platform logging utility for Octocode Research Server
5
- *
6
- * Logs to ~/.octocode/logs/ (or %USERPROFILE%\.octocode\logs on Windows)
7
- * - errors.log: All errors and warnings
8
- * - tools.log: Tool invocation data and results
9
- *
10
- * PERFORMANCE: Uses async file operations to avoid blocking event loop
11
- */
3
+
12
4
 
13
5
  import fs from 'node:fs';
14
6
  import { promises as fsAsync } from 'node:fs';
15
7
  import path from 'node:path';
16
8
  import os from 'node:os';
17
9
 
18
- // ============================================================================
19
- // Configuration
20
- // ============================================================================
21
10
 
22
11
  const HOME = os.homedir();
23
12
  const OCTOCODE_DIR = process.env.OCTOCODE_HOME || path.join(HOME, '.octocode');
@@ -25,24 +14,16 @@ const LOGS_DIR = path.join(OCTOCODE_DIR, 'logs');
25
14
  const ERROR_LOG = path.join(LOGS_DIR, 'errors.log');
26
15
  const TOOLS_LOG = path.join(LOGS_DIR, 'tools.log');
27
16
 
28
- // Max log file size before rotation (10MB)
29
17
  const MAX_LOG_SIZE = 10 * 1024 * 1024;
30
18
 
31
- // Max size for JSON.stringify to prevent memory spikes (100KB)
32
19
  const MAX_LOG_DATA_SIZE = 100 * 1024;
33
20
 
34
- // ============================================================================
35
- // Directory Initialization (async with sync fallback for startup)
36
- // ============================================================================
37
21
 
38
22
  let initialized = false;
39
23
  let fileLoggingEnabled = true;
40
24
  let initPromise: Promise<void> | null = null;
41
25
 
42
- /**
43
- * Ensure the logs directory exists (async).
44
- * Safe to call multiple times (idempotent).
45
- */
26
+
46
27
  async function ensureLogsDirAsync(): Promise<void> {
47
28
  if (initialized) return;
48
29
  if (initPromise) return initPromise;
@@ -64,9 +45,7 @@ async function ensureLogsDirAsync(): Promise<void> {
64
45
  return initPromise;
65
46
  }
66
47
 
67
- /**
68
- * Sync initialization for startup only (blocking but necessary)
69
- */
48
+
70
49
  function ensureLogsDirSync(): void {
71
50
  if (initialized) return;
72
51
 
@@ -87,13 +66,7 @@ function ensureLogsDirSync(): void {
87
66
  }
88
67
  }
89
68
 
90
- // ============================================================================
91
- // Log Rotation (async)
92
- // ============================================================================
93
69
 
94
- /**
95
- * Rotate log file if it exceeds max size (async).
96
- */
97
70
  async function rotateIfNeededAsync(logPath: string): Promise<void> {
98
71
  try {
99
72
  const stats = await fsAsync.stat(logPath).catch(() => null);
@@ -107,13 +80,11 @@ async function rotateIfNeededAsync(logPath: string): Promise<void> {
107
80
  await fsAsync.rename(logPath, rotatedPath);
108
81
  await cleanupOldLogsAsync(base, ext, 5);
109
82
  } catch {
110
- // Silently fail - logging should never crash the server
83
+ void 0;
111
84
  }
112
85
  }
113
86
 
114
- /**
115
- * Remove old rotated log files, keeping only the most recent ones (async).
116
- */
87
+
117
88
  async function cleanupOldLogsAsync(baseName: string, ext: string, keep: number): Promise<void> {
118
89
  try {
119
90
  const files = await fsAsync.readdir(LOGS_DIR);
@@ -122,24 +93,16 @@ async function cleanupOldLogsAsync(baseName: string, ext: string, keep: number):
122
93
  .sort()
123
94
  .reverse();
124
95
 
125
- // Remove files beyond the keep limit
126
96
  const toDelete = rotatedFiles.slice(keep);
127
97
  await Promise.all(
128
98
  toDelete.map((f) => fsAsync.unlink(path.join(LOGS_DIR, f)).catch(err => errorQueue.push(err, 'cleanupOldLogs')))
129
99
  );
130
100
  } catch {
131
- // Silently fail
101
+ void 0;
132
102
  }
133
103
  }
134
104
 
135
- // ============================================================================
136
- // Log Entry Formatting
137
- // ============================================================================
138
105
 
139
- /**
140
- * Safely stringify data with size limit to prevent memory spikes.
141
- * Uses single-pass approach with size tracking to avoid double serialization.
142
- */
143
106
  function safeStringify(data: unknown): string {
144
107
  if (data === undefined) return '';
145
108
 
@@ -148,9 +111,7 @@ function safeStringify(data: unknown): string {
148
111
  let truncated = false;
149
112
  const seen = new WeakSet<object>();
150
113
 
151
- // Custom replacer that tracks size and detects circular refs
152
114
  const replacer = (_key: string, value: unknown): unknown => {
153
- // Check for circular references
154
115
  if (value !== null && typeof value === 'object') {
155
116
  if (seen.has(value)) {
156
117
  return '[Circular]';
@@ -158,11 +119,9 @@ function safeStringify(data: unknown): string {
158
119
  seen.add(value);
159
120
  }
160
121
 
161
- // Estimate size contribution (rough but fast)
162
122
  const valueStr = typeof value === 'string' ? value : String(value ?? '');
163
- size += valueStr.length + 10; // +10 for key, quotes, colons, etc.
123
+ size += valueStr.length + 10;
164
124
 
165
- // If we've exceeded limit, mark as truncated and return placeholder
166
125
  if (size > MAX_LOG_DATA_SIZE && !truncated) {
167
126
  truncated = true;
168
127
  }
@@ -172,7 +131,6 @@ function safeStringify(data: unknown): string {
172
131
 
173
132
  const result = JSON.stringify(data, replacer, 2);
174
133
 
175
- // If truncated during serialization, return truncation notice
176
134
  if (truncated) {
177
135
  return JSON.stringify({
178
136
  _truncated: true,
@@ -187,47 +145,30 @@ function safeStringify(data: unknown): string {
187
145
  }
188
146
  }
189
147
 
190
- /**
191
- * Format a log entry with timestamp and level.
192
- */
148
+
193
149
  function formatLogEntry(level: string, message: string, data?: unknown): string {
194
150
  const timestamp = new Date().toISOString();
195
151
  const dataStr = data !== undefined ? `\n${safeStringify(data)}` : '';
196
152
  return `[${timestamp}] [${level}] ${message}${dataStr}\n`;
197
153
  }
198
154
 
199
- // ============================================================================
200
- // Core Logging Functions (async with fire-and-forget pattern)
201
- // ============================================================================
202
155
 
203
- /**
204
- * Write to a log file asynchronously (fire-and-forget).
205
- * Never blocks the event loop.
206
- */
207
156
  function writeLogAsync(logPath: string, entry: string): void {
208
157
  if (!fileLoggingEnabled) return;
209
158
 
210
- // Fire and forget - don't await
211
159
  (async () => {
212
160
  try {
213
161
  await ensureLogsDirAsync();
214
162
  await rotateIfNeededAsync(logPath);
215
163
  await fsAsync.appendFile(logPath, entry, { encoding: 'utf-8' });
216
164
  } catch (err) {
217
- // Disable file logging on persistent failure
218
165
  fileLoggingEnabled = false;
219
166
  process.stderr.write(`[Logger] File write failed, disabling: ${err}\n`);
220
167
  }
221
168
  })();
222
169
  }
223
170
 
224
- // ============================================================================
225
- // Public API - Error Logger
226
- // ============================================================================
227
171
 
228
- /**
229
- * Log an error message (async, non-blocking).
230
- */
231
172
  export function logError(message: string, error?: Error | unknown): void {
232
173
  const errorData =
233
174
  error instanceof Error
@@ -237,27 +178,19 @@ export function logError(message: string, error?: Error | unknown): void {
237
178
  const entry = formatLogEntry('ERROR', message, errorData);
238
179
  writeLogAsync(ERROR_LOG, entry);
239
180
 
240
- // Also write to console for visibility (redact stack in production)
241
181
  const consoleError = process.env.NODE_ENV === 'development'
242
182
  ? error
243
183
  : (error instanceof Error ? error.message : String(error || ''));
244
- // Use %s format specifier to prevent format string injection from user-controlled message
245
184
  console.error('%s %o', errorLog('[ERROR] ' + message), consoleError);
246
185
  }
247
186
 
248
- /**
249
- * Log a warning message (async, non-blocking).
250
- */
187
+
251
188
  export function logWarn(message: string, data?: unknown): void {
252
189
  const entry = formatLogEntry('WARN', message, data);
253
190
  writeLogAsync(ERROR_LOG, entry);
254
- // Use %s format specifier to prevent format string injection from user-controlled message
255
191
  console.warn('%s', warnLog('[WARN] ' + message));
256
192
  }
257
193
 
258
- // ============================================================================
259
- // Public API - Tools Logger
260
- // ============================================================================
261
194
 
262
195
  interface ToolLogEntry {
263
196
  tool: string;
@@ -276,35 +209,20 @@ export function logToolCall(entry: ToolLogEntry): void {
276
209
  writeLogAsync(TOOLS_LOG, logEntry);
277
210
  }
278
211
 
279
- // ============================================================================
280
- // Utility Functions
281
- // ============================================================================
282
212
 
283
- /**
284
- * Get the path to the logs directory.
285
- */
286
213
  export function getLogsPath(): string {
287
214
  return LOGS_DIR;
288
215
  }
289
216
 
290
- /**
291
- * Initialize logger synchronously (call at startup).
292
- * After startup, all operations are async.
293
- */
217
+
294
218
  export function initializeLogger(): void {
295
219
  ensureLogsDirSync();
296
220
  }
297
221
 
298
- // ============================================================================
299
- // Security Utilities
300
- // ============================================================================
301
222
 
302
223
  const SENSITIVE_KEYS = ['token', 'key', 'secret', 'password', 'auth', 'credential', 'api_key', 'apikey'];
303
224
 
304
- /**
305
- * Sanitize query parameters by redacting sensitive values.
306
- * Prevents accidental exposure of secrets in logs.
307
- */
225
+
308
226
  export function sanitizeQueryParams(query: Record<string, unknown>): Record<string, unknown> {
309
227
  const sanitized: Record<string, unknown> = {};
310
228
 
@@ -1,60 +1,39 @@
1
- /**
2
- * Resilience utilities combining circuit breaker + retry + timeout for external API calls.
3
- *
4
- * @module utils/resilience
5
- */
6
-
7
1
  import { withCircuitBreaker } from './circuitBreaker.js';
8
2
  import { withRetry, RETRY_CONFIGS } from './retry.js';
9
3
  import { withTimeout } from './asyncTimeout.js';
10
4
 
11
- /** Default timeout for MCP tool calls (30 seconds) */
5
+
12
6
  const DEFAULT_TOOL_TIMEOUT_MS = 30000;
13
7
 
14
- /** Timeout configuration per category */
8
+
15
9
  const TIMEOUT_CONFIGS = {
16
- github: 60000, // 60s for GitHub API (rate limiting, large responses)
17
- local: 30000, // 30s for local tools
18
- lsp: 30000, // 30s for LSP operations
19
- package: 30000, // 30s for package search
10
+ github: 60000,
11
+ local: 30000,
12
+ lsp: 30000,
13
+ package: 30000,
20
14
  } as const;
21
15
 
22
- /**
23
- * Per-tool circuit breaker mapping.
24
- * Isolates failures so one failing tool doesn't block unrelated tools.
25
- *
26
- * Grouping rationale:
27
- * - GitHub: Split by API endpoint (search/content/pulls have different rate limits)
28
- * - LSP: Split by operation weight (navigation vs hierarchy)
29
- * - Local: Unified (same failure mode - filesystem)
30
- * - Package: Unified (could split npm/pypi later)
31
- */
16
+
32
17
  const TOOL_CIRCUIT_MAP: Record<string, string> = {
33
- // GitHub - separate by endpoint type (rate limits differ)
34
- githubSearchCode: 'github:search', // Search API (30 req/min)
35
- githubSearchRepositories: 'github:search', // Search API
36
- githubSearchPullRequests: 'github:pulls', // PR API (separate quota)
37
- githubGetFileContent: 'github:content', // Contents API (higher limit)
38
- githubViewRepoStructure: 'github:content', // Contents API (tree)
39
-
40
- // LSP - per operation type (different failure modes)
41
- lspGotoDefinition: 'lsp:navigation', // Fast, single lookup
42
- lspFindReferences: 'lsp:navigation', // Fast, single lookup
43
- lspCallHierarchy: 'lsp:hierarchy', // Heavier, recursive operation
44
-
45
- // Local - unified (same failure mode: filesystem)
18
+ githubSearchCode: 'github:search',
19
+ githubSearchRepositories: 'github:search',
20
+ githubSearchPullRequests: 'github:pulls',
21
+ githubGetFileContent: 'github:content',
22
+ githubViewRepoStructure: 'github:content',
23
+
24
+ lspGotoDefinition: 'lsp:navigation',
25
+ lspFindReferences: 'lsp:navigation',
26
+ lspCallHierarchy: 'lsp:hierarchy',
27
+
46
28
  localSearchCode: 'local',
47
29
  localGetFileContent: 'local',
48
30
  localFindFiles: 'local',
49
31
  localViewStructure: 'local',
50
32
 
51
- // Package - unified (could split npm/pypi later if needed)
52
33
  packageSearch: 'package',
53
34
  };
54
35
 
55
- /**
56
- * Pre-configured resilience strategies
57
- */
36
+
58
37
  const RESILIENCE_CONFIGS = {
59
38
  github: {
60
39
  retry: RETRY_CONFIGS.github,
@@ -72,30 +51,6 @@ const RESILIENCE_CONFIGS = {
72
51
 
73
52
  type ResilienceCategory = keyof typeof RESILIENCE_CONFIGS;
74
53
 
75
- /**
76
- * Execute an operation with combined timeout + circuit breaker + retry protection.
77
- *
78
- * The protection layers work as follows:
79
- * 1. TIMEOUT: Wraps entire operation to prevent hanging (outermost)
80
- * 2. CIRCUIT BREAKER: If circuit is OPEN, fail fast (no retries/timeout)
81
- * 3. RETRY: If circuit is CLOSED/HALF-OPEN, retry with backoff (innermost)
82
- *
83
- * Failures (including timeouts) contribute to circuit state.
84
- *
85
- * @param category - Resilience category ('github', 'local', 'lsp')
86
- * @param operation - Async operation to execute
87
- * @param context - Context for logging
88
- * @returns Operation result
89
- *
90
- * @example
91
- * ```typescript
92
- * const result = await withResilience(
93
- * 'github',
94
- * () => githubSearchCode({ queries }),
95
- * { tool: 'githubSearchCode' }
96
- * );
97
- * ```
98
- */
99
54
  async function withResilience<T>(
100
55
  category: ResilienceCategory,
101
56
  operation: () => Promise<T>,
@@ -105,10 +60,8 @@ async function withResilience<T>(
105
60
  const timeoutMs = TIMEOUT_CONFIGS[category] || DEFAULT_TOOL_TIMEOUT_MS;
106
61
  const toolName = context?.tool || category;
107
62
 
108
- // Get tool-specific circuit name (isolates failures per tool/endpoint)
109
63
  const circuitName = TOOL_CIRCUIT_MAP[toolName] || category;
110
64
 
111
- // Timeout wraps circuit breaker wraps retry
112
65
  return withTimeout(
113
66
  () => withCircuitBreaker(circuitName, async () => {
114
67
  return withRetry(operation, config.retry, context);
@@ -118,9 +71,7 @@ async function withResilience<T>(
118
71
  );
119
72
  }
120
73
 
121
- /**
122
- * Execute GitHub API call with resilience protection
123
- */
74
+
124
75
  export async function withGitHubResilience<T>(
125
76
  operation: () => Promise<T>,
126
77
  toolName: string
@@ -128,9 +79,7 @@ export async function withGitHubResilience<T>(
128
79
  return withResilience('github', operation, { tool: toolName });
129
80
  }
130
81
 
131
- /**
132
- * Execute LSP call with resilience protection
133
- */
82
+
134
83
  export async function withLspResilience<T>(
135
84
  operation: () => Promise<T>,
136
85
  toolName: string
@@ -138,9 +87,7 @@ export async function withLspResilience<T>(
138
87
  return withResilience('lsp', operation, { tool: toolName });
139
88
  }
140
89
 
141
- /**
142
- * Execute local tool call with resilience protection
143
- */
90
+
144
91
  export async function withLocalResilience<T>(
145
92
  operation: () => Promise<T>,
146
93
  toolName: string
@@ -148,9 +95,7 @@ export async function withLocalResilience<T>(
148
95
  return withResilience('local', operation, { tool: toolName });
149
96
  }
150
97
 
151
- /**
152
- * Execute package API call (npm/PyPI) with resilience protection
153
- */
98
+
154
99
  export async function withPackageResilience<T>(
155
100
  operation: () => Promise<T>,
156
101
  toolName: string