ralphblaster-agent 0.1.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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +294 -0
  3. package/bin/agent-dashboard.sh +168 -0
  4. package/bin/monitor-agent.sh +264 -0
  5. package/bin/ralphblaster.js +247 -0
  6. package/package.json +64 -0
  7. package/postinstall-colored.js +66 -0
  8. package/src/api-client.js +764 -0
  9. package/src/claude-plugin/.claude-plugin/plugin.json +9 -0
  10. package/src/claude-plugin/README.md +42 -0
  11. package/src/claude-plugin/skills/ralph/SKILL.md +259 -0
  12. package/src/commands/add-project.js +257 -0
  13. package/src/commands/init.js +79 -0
  14. package/src/config-file-manager.js +84 -0
  15. package/src/config.js +66 -0
  16. package/src/error-window.js +86 -0
  17. package/src/executor/claude-runner.js +716 -0
  18. package/src/executor/error-handler.js +65 -0
  19. package/src/executor/git-helper.js +196 -0
  20. package/src/executor/index.js +296 -0
  21. package/src/executor/job-handlers/clarifying-questions.js +213 -0
  22. package/src/executor/job-handlers/code-execution.js +145 -0
  23. package/src/executor/job-handlers/prd-generation.js +259 -0
  24. package/src/executor/path-helper.js +74 -0
  25. package/src/executor/prompt-validator.js +51 -0
  26. package/src/executor.js +4 -0
  27. package/src/index.js +342 -0
  28. package/src/logger.js +193 -0
  29. package/src/logging/README.md +93 -0
  30. package/src/logging/config.js +179 -0
  31. package/src/logging/destinations/README.md +290 -0
  32. package/src/logging/destinations/api-destination-unbatched.js +118 -0
  33. package/src/logging/destinations/api-destination.js +40 -0
  34. package/src/logging/destinations/base-destination.js +85 -0
  35. package/src/logging/destinations/batched-destination.js +198 -0
  36. package/src/logging/destinations/console-destination.js +172 -0
  37. package/src/logging/destinations/file-destination.js +208 -0
  38. package/src/logging/destinations/index.js +29 -0
  39. package/src/logging/destinations/progress-batch-destination-unbatched.js +92 -0
  40. package/src/logging/destinations/progress-batch-destination.js +41 -0
  41. package/src/logging/formatter.js +288 -0
  42. package/src/logging/log-manager.js +426 -0
  43. package/src/progress-throttle.js +101 -0
  44. package/src/system-monitor.js +64 -0
  45. package/src/utils/format.js +16 -0
  46. package/src/utils/log-file-helper.js +265 -0
  47. package/src/utils/progress-parser.js +250 -0
  48. package/src/worktree-manager.js +255 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Centralized logging configuration
3
+ *
4
+ * This module consolidates all logging-related configuration from:
5
+ * - src/config.js (logLevel, consoleColors, consoleFormat)
6
+ * - src/setup-log-batcher.js (maxBatchSize, flushInterval, useBatchEndpoint)
7
+ * - Environment variables (RALPHBLASTER_* with RALPH_* fallback for backward compatibility)
8
+ *
9
+ * @module logging/config
10
+ */
11
+
12
+ /**
13
+ * Parse boolean from environment variable
14
+ * Treats 'false', '0', and empty string as false, everything else as true
15
+ * @param {string} value - Environment variable value
16
+ * @param {boolean} defaultValue - Default if not set
17
+ * @returns {boolean}
18
+ */
19
+ function parseEnvBoolean(value, defaultValue) {
20
+ if (value === undefined || value === null) return defaultValue;
21
+ return value !== 'false' && value !== '0' && value !== '';
22
+ }
23
+
24
+ /**
25
+ * Parse positive integer from environment variable
26
+ * @param {string} value - Environment variable value
27
+ * @param {number} defaultValue - Default if not set or invalid
28
+ * @returns {number}
29
+ */
30
+ function parseEnvInt(value, defaultValue) {
31
+ if (value === undefined || value === null) return defaultValue;
32
+ const parsed = parseInt(value, 10);
33
+ if (isNaN(parsed) || parsed <= 0) {
34
+ console.warn(`Invalid numeric value "${value}", using default: ${defaultValue}`);
35
+ return defaultValue;
36
+ }
37
+ return parsed;
38
+ }
39
+
40
+ /**
41
+ * Valid log levels in order of severity
42
+ * @type {string[]}
43
+ */
44
+ const VALID_LOG_LEVELS = ['error', 'warn', 'info', 'debug'];
45
+
46
+ /**
47
+ * Valid console format options
48
+ * @type {string[]}
49
+ */
50
+ const VALID_CONSOLE_FORMATS = ['pretty', 'json'];
51
+
52
+ /**
53
+ * Validate that a log level is valid
54
+ * @param {string} level - Log level to validate
55
+ * @returns {boolean} True if valid
56
+ */
57
+ function isValidLogLevel(level) {
58
+ return VALID_LOG_LEVELS.includes(level);
59
+ }
60
+
61
+ /**
62
+ * Validate that a console format is valid
63
+ * @param {string} format - Console format to validate
64
+ * @returns {boolean} True if valid
65
+ */
66
+ function isValidConsoleFormat(format) {
67
+ return VALID_CONSOLE_FORMATS.includes(format);
68
+ }
69
+
70
+ // Read configuration from environment variables with validation
71
+ const rawLogLevel = process.env.RALPHBLASTER_LOG_LEVEL || 'info';
72
+ const logLevel = isValidLogLevel(rawLogLevel) ? rawLogLevel : 'info';
73
+
74
+ // Warn if invalid log level was provided
75
+ if (!isValidLogLevel(rawLogLevel)) {
76
+ console.warn(`Invalid log level "${rawLogLevel}", using default: info. Valid levels: ${VALID_LOG_LEVELS.join(', ')}`);
77
+ }
78
+
79
+ const rawConsoleFormat = process.env.RALPHBLASTER_CONSOLE_FORMAT || 'pretty';
80
+ const consoleFormat = isValidConsoleFormat(rawConsoleFormat) ? rawConsoleFormat : 'pretty';
81
+
82
+ // Warn if invalid console format was provided
83
+ if (!isValidConsoleFormat(rawConsoleFormat)) {
84
+ console.warn(`Invalid console format "${rawConsoleFormat}", using default: pretty. Valid formats: ${VALID_CONSOLE_FORMATS.join(', ')}`);
85
+ }
86
+
87
+ /**
88
+ * Centralized logging configuration object
89
+ * All logging-related settings are defined here in one place
90
+ */
91
+ const loggingConfig = {
92
+ // ===== Console Output Settings =====
93
+
94
+ /**
95
+ * Log level - controls which messages are displayed
96
+ * @type {'error' | 'warn' | 'info' | 'debug'}
97
+ * @default 'info'
98
+ */
99
+ logLevel,
100
+
101
+ /**
102
+ * Enable/disable colored console output
103
+ * Set to 'false' to disable colors (useful for log files or CI environments)
104
+ * @type {boolean}
105
+ * @default true
106
+ */
107
+ consoleColors: parseEnvBoolean(process.env.RALPHBLASTER_CONSOLE_COLORS, true),
108
+
109
+ /**
110
+ * Console output format
111
+ * - 'pretty': Human-readable format with colors (default)
112
+ * - 'json': Structured JSON format for machine parsing
113
+ * @type {'pretty' | 'json'}
114
+ * @default 'pretty'
115
+ */
116
+ consoleFormat,
117
+
118
+ // ===== Log Batching Settings =====
119
+ // These settings control how logs are batched before being sent to the API
120
+ // to reduce the number of API calls and improve performance
121
+
122
+ /**
123
+ * Maximum number of logs to batch before forcing a flush
124
+ * Larger values reduce API calls but may delay log visibility
125
+ * Phase 1.3: Increased from 10 to 50 to match progress batch size
126
+ * Expected impact: 80% reduction in log API calls (50 req/s → 10 req/s)
127
+ * @type {number}
128
+ * @default 50
129
+ */
130
+ maxBatchSize: parseEnvInt(process.env.RALPHBLASTER_MAX_BATCH_SIZE, 50),
131
+
132
+ /**
133
+ * Time in milliseconds between automatic log flushes
134
+ * Smaller values improve log visibility but increase API calls
135
+ * @type {number}
136
+ * @default 2000 (2 seconds)
137
+ */
138
+ flushInterval: parseEnvInt(process.env.RALPHBLASTER_FLUSH_INTERVAL, 2000),
139
+
140
+ /**
141
+ * Whether to use the batch endpoint for sending logs
142
+ * When true, tries to send logs in a single batch API call
143
+ * Falls back to individual calls if batch endpoint fails
144
+ * @type {boolean}
145
+ * @default true
146
+ */
147
+ useBatchEndpoint: parseEnvBoolean(process.env.RALPHBLASTER_USE_BATCH_ENDPOINT, true),
148
+
149
+ // ===== Agent Identification =====
150
+
151
+ /**
152
+ * Agent ID for multi-agent support
153
+ * Used to identify which agent instance is running in multi-agent deployments
154
+ * @type {string}
155
+ * @default 'agent-default'
156
+ */
157
+ agentId: process.env.RALPHBLASTER_AGENT_ID || 'agent-default',
158
+
159
+ // ===== Validation Helpers =====
160
+
161
+ /**
162
+ * Valid log levels
163
+ * @type {string[]}
164
+ * @readonly
165
+ */
166
+ validLogLevels: VALID_LOG_LEVELS,
167
+
168
+ /**
169
+ * Valid console formats
170
+ * @type {string[]}
171
+ * @readonly
172
+ */
173
+ validConsoleFormats: VALID_CONSOLE_FORMATS
174
+ };
175
+
176
+ // Freeze the configuration to prevent accidental modifications
177
+ Object.freeze(loggingConfig);
178
+
179
+ module.exports = loggingConfig;
@@ -0,0 +1,290 @@
1
+ # Log Destinations
2
+
3
+ This directory contains the log destination abstraction layer for Ralph's logging system. Each destination represents a different output target for log messages (console, file, API, etc.).
4
+
5
+ ## Architecture
6
+
7
+ All destinations extend `BaseDestination` and implement a common interface:
8
+
9
+ - `write(level, message, metadata)` - Write a log entry
10
+ - `flush()` - Flush any buffered logs
11
+ - `close()` - Clean up resources and ensure no logs are lost
12
+ - `shouldLog(level)` - Filter logs based on level
13
+ - `handleError(error, level, message)` - Handle write errors gracefully
14
+
15
+ This pluggable architecture allows destinations to be added, removed, or replaced independently.
16
+
17
+ ## Available Destinations
18
+
19
+ ### BaseDestination
20
+
21
+ Abstract base class defining the common interface. All destinations must extend this class.
22
+
23
+ **Key features:**
24
+ - Defines standard lifecycle methods (write, flush, close)
25
+ - Provides default error handling
26
+ - Manages shutdown state
27
+
28
+ ### ConsoleDestination
29
+
30
+ Outputs logs to console (stdout/stderr) with formatting and colors.
31
+
32
+ **Configuration:**
33
+ ```javascript
34
+ const destination = new ConsoleDestination({
35
+ colors: true, // Enable ANSI colors
36
+ format: 'pretty', // 'pretty' or 'json'
37
+ minLevel: 'info' // Minimum log level to output
38
+ });
39
+ ```
40
+
41
+ **Features:**
42
+ - Pretty formatting for human readability
43
+ - JSON format for machine parsing
44
+ - Color-coded by log level
45
+ - Redacts sensitive data
46
+ - No buffering - immediate output
47
+
48
+ ### FileDestination
49
+
50
+ Writes logs to job-specific files in `.rb-logs/` directory.
51
+
52
+ **Configuration:**
53
+ ```javascript
54
+ const destination = new FileDestination({
55
+ workingDir: '/path/to/work',
56
+ job: { id: 123, task_title: 'Generate PRD' },
57
+ startTime: Date.now(),
58
+ jobType: 'PRD Generation',
59
+ useStream: true // Use streams vs batch writes
60
+ });
61
+ ```
62
+
63
+ **Features:**
64
+ - Creates organized log files per job
65
+ - Streaming mode for real-time output
66
+ - Batch mode for complete output
67
+ - Automatic header/footer formatting
68
+ - Safe error handling
69
+
70
+ ### ApiDestination
71
+
72
+ Sends logs to API with intelligent batching to reduce overhead.
73
+
74
+ **Configuration:**
75
+ ```javascript
76
+ const destination = new ApiDestination({
77
+ apiClient: apiClientInstance,
78
+ jobId: 123,
79
+ maxBatchSize: 10, // Flush after N logs
80
+ flushInterval: 2000, // Flush every N ms
81
+ useBatchEndpoint: true // Try batch endpoint first
82
+ });
83
+ ```
84
+
85
+ **Features:**
86
+ - Batches multiple logs into single API calls
87
+ - Automatic periodic flushing
88
+ - Fallback to individual sends on batch failure
89
+ - Graceful shutdown with final flush
90
+
91
+ ## Usage Example
92
+
93
+ ### Single Destination
94
+
95
+ ```javascript
96
+ const { ConsoleDestination } = require('./logging/destinations');
97
+
98
+ const logger = new ConsoleDestination({
99
+ colors: true,
100
+ format: 'pretty',
101
+ minLevel: 'debug'
102
+ });
103
+
104
+ await logger.write('info', 'Job started', { jobId: 123 });
105
+ await logger.write('debug', 'Processing file', { file: 'example.js' });
106
+ await logger.close();
107
+ ```
108
+
109
+ ### Multiple Destinations (with LogManager)
110
+
111
+ ```javascript
112
+ const { ConsoleDestination, FileDestination, ApiDestination } = require('./logging/destinations');
113
+
114
+ // Create destinations
115
+ const console = new ConsoleDestination({ minLevel: 'info' });
116
+ const file = new FileDestination({
117
+ workingDir: '/tmp',
118
+ job: { id: 1, task_title: 'Test' },
119
+ startTime: Date.now(),
120
+ jobType: 'Test'
121
+ });
122
+ const api = new ApiDestination({
123
+ apiClient,
124
+ jobId: 1
125
+ });
126
+
127
+ // Use with LogManager (future implementation)
128
+ const manager = new LogManager([console, file, api]);
129
+ await manager.log('info', 'Message to all destinations');
130
+ await manager.close(); // Closes all destinations
131
+ ```
132
+
133
+ ## Creating Custom Destinations
134
+
135
+ Extend `BaseDestination` and implement the required methods:
136
+
137
+ ```javascript
138
+ const BaseDestination = require('./base-destination');
139
+
140
+ class CustomDestination extends BaseDestination {
141
+ constructor(config) {
142
+ super(config);
143
+ // Initialize your destination
144
+ }
145
+
146
+ async write(level, message, metadata = {}) {
147
+ // Write log to your destination
148
+ }
149
+
150
+ async flush() {
151
+ // Flush any buffers
152
+ }
153
+
154
+ async close() {
155
+ this.isShuttingDown = true;
156
+ await this.flush();
157
+ // Clean up resources
158
+ }
159
+ }
160
+
161
+ module.exports = CustomDestination;
162
+ ```
163
+
164
+ ## Design Principles
165
+
166
+ 1. **Independence** - Each destination operates independently without dependencies on other destinations
167
+ 2. **Graceful Degradation** - Errors in one destination don't affect others
168
+ 3. **No Job Context** - Destinations accept context as parameters, not through global state
169
+ 4. **Async Support** - All operations support async/await for I/O operations
170
+ 5. **Pluggable** - Destinations can be added/removed without code changes
171
+ 6. **Testable** - Pure functions and dependency injection make testing easy
172
+
173
+ ## Error Handling
174
+
175
+ Destinations handle their own errors gracefully:
176
+
177
+ - **ConsoleDestination** - Attempts to write error to stderr
178
+ - **FileDestination** - Falls back to console.error
179
+ - **ApiDestination** - Silently fails to prevent cascading errors
180
+
181
+ This prevents log failures from disrupting the application while still providing feedback when possible.
182
+
183
+ ### BatchedDestination
184
+
185
+ Generic batching wrapper that can wrap any destination to add batching capabilities.
186
+
187
+ **Configuration:**
188
+ ```javascript
189
+ const { BatchedDestination, ConsoleDestination } = require('./logging/destinations');
190
+
191
+ // Wrap any destination with batching
192
+ const console = new ConsoleDestination();
193
+ const batchedConsole = new BatchedDestination(console, {
194
+ maxBatchSize: 10, // Flush after N logs
195
+ flushInterval: 2000, // Flush every N ms
196
+ useBatchSend: true // Try sendBatch() if available
197
+ });
198
+ ```
199
+
200
+ **Features:**
201
+ - Wraps any BaseDestination implementation
202
+ - Buffers logs and sends in batches
203
+ - Automatic periodic flushing
204
+ - Graceful fallback to individual sends
205
+ - Composable - can wrap any destination
206
+
207
+ **How it works:**
208
+ 1. Buffers incoming logs until `maxBatchSize` is reached
209
+ 2. Flushes automatically every `flushInterval` milliseconds
210
+ 3. If destination implements `sendBatch()`, uses it for efficiency
211
+ 4. Falls back to individual `write()` calls if batch sending fails
212
+ 5. Ensures all logs are flushed on `close()`
213
+
214
+ ### ApiDestinationUnbatched
215
+
216
+ Low-level API destination without batching. Used internally by ApiDestination.
217
+
218
+ **Note:** This should not be used directly - use `ApiDestination` instead, which wraps this with `BatchedDestination` for optimal performance.
219
+
220
+ ## Batching Pattern
221
+
222
+ The batching pattern is composable and can be applied to any destination:
223
+
224
+ ```javascript
225
+ // Example 1: Batched API destination (built-in)
226
+ const api = new ApiDestination({ apiClient, jobId });
227
+
228
+ // Example 2: Manual batching of any destination
229
+ const file = new FileDestination({ workingDir, job, startTime, jobType });
230
+ const batchedFile = new BatchedDestination(file, {
231
+ maxBatchSize: 20,
232
+ flushInterval: 5000
233
+ });
234
+
235
+ // Example 3: Custom destination with batching
236
+ class SyslogDestination extends BaseDestination {
237
+ async write(level, message, metadata) {
238
+ // Send single log to syslog
239
+ }
240
+
241
+ async sendBatch(logs) {
242
+ // Optional: efficient batch send
243
+ }
244
+ }
245
+
246
+ const syslog = new SyslogDestination(config);
247
+ const batchedSyslog = new BatchedDestination(syslog, {
248
+ maxBatchSize: 50,
249
+ flushInterval: 1000
250
+ });
251
+ ```
252
+
253
+ ## Migration from SetupLogBatcher
254
+
255
+ The old `SetupLogBatcher` class is deprecated. Migrate to the new destination-based approach:
256
+
257
+ **Before:**
258
+ ```javascript
259
+ const SetupLogBatcher = require('./setup-log-batcher');
260
+ const batcher = new SetupLogBatcher(apiClient, jobId, {
261
+ maxBatchSize: 10,
262
+ flushInterval: 2000,
263
+ useBatchEndpoint: true
264
+ });
265
+ batcher.add('info', 'message', metadata);
266
+ await batcher.flush();
267
+ await batcher.shutdown();
268
+ ```
269
+
270
+ **After:**
271
+ ```javascript
272
+ const { ApiDestination } = require('./logging/destinations');
273
+ const destination = new ApiDestination({
274
+ apiClient,
275
+ jobId,
276
+ maxBatchSize: 10,
277
+ flushInterval: 2000,
278
+ useBatchEndpoint: true
279
+ });
280
+ await destination.write('info', 'message', metadata);
281
+ await destination.flush();
282
+ await destination.close();
283
+ ```
284
+
285
+ The old `SetupLogBatcher` is maintained for backward compatibility but internally uses the new destination-based implementation.
286
+
287
+ ## Next Steps
288
+
289
+ - **LogManager** (Task #1) - Coordinates multiple destinations
290
+ - **Unit Tests** (Task #7) - Comprehensive test coverage for all destinations
@@ -0,0 +1,118 @@
1
+ const BaseDestination = require('./base-destination');
2
+
3
+ /**
4
+ * ApiDestinationUnbatched - Sends individual logs to API
5
+ *
6
+ * Provides direct API logging without batching. Designed to be wrapped by
7
+ * BatchedDestination for efficient batched sending.
8
+ *
9
+ * This class should NOT be used directly - use ApiDestination (which wraps
10
+ * this with BatchedDestination) for production use.
11
+ *
12
+ * Supports both single log and batch log endpoints:
13
+ * - write() - sends single log via apiClient.addSetupLog()
14
+ * - sendBatch() - sends multiple logs via apiClient.addSetupLogBatch()
15
+ */
16
+ class ApiDestinationUnbatched extends BaseDestination {
17
+ /**
18
+ * Create a new unbatched API destination
19
+ * @param {Object} config - Configuration options
20
+ * @param {Object} config.apiClient - API client with addSetupLog() and addSetupLogBatch() methods
21
+ * @param {number} config.jobId - Job ID to associate logs with
22
+ * @param {boolean} [config.useBatchEndpoint=true] - Whether to use batch endpoint for sendBatch()
23
+ */
24
+ constructor(config) {
25
+ super(config);
26
+
27
+ if (!config.apiClient) {
28
+ throw new Error('ApiDestinationUnbatched requires apiClient in config');
29
+ }
30
+ if (config.jobId === undefined || config.jobId === null) {
31
+ throw new Error('ApiDestinationUnbatched requires jobId in config');
32
+ }
33
+
34
+ this.apiClient = config.apiClient;
35
+ this.jobId = config.jobId;
36
+ this.useBatchEndpoint = config.useBatchEndpoint !== false;
37
+ }
38
+
39
+ /**
40
+ * Write a single log entry to the API
41
+ * @param {string} level - Log level
42
+ * @param {string} message - Log message
43
+ * @param {Object} [metadata={}] - Structured metadata
44
+ * @returns {Promise<void>}
45
+ */
46
+ async write(level, message, metadata = {}) {
47
+ try {
48
+ await this.apiClient.addSetupLog(
49
+ this.jobId,
50
+ level,
51
+ message,
52
+ metadata && Object.keys(metadata).length > 0 ? metadata : null
53
+ );
54
+ } catch (error) {
55
+ this.handleError(error, level, message);
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Send multiple log entries in a single batch API call
61
+ * This is called by BatchedDestination when flushing buffered logs.
62
+ * @param {Array<Object>} logs - Array of log entries with {timestamp, level, message, metadata}
63
+ * @returns {Promise<void>}
64
+ */
65
+ async sendBatch(logs) {
66
+ if (logs.length === 0) return;
67
+
68
+ try {
69
+ if (this.useBatchEndpoint && this.apiClient.addSetupLogBatch) {
70
+ // Use efficient batch endpoint
71
+ await this.apiClient.addSetupLogBatch(this.jobId, logs);
72
+ } else {
73
+ // Fall back to individual sends
74
+ await this.sendIndividually(logs);
75
+ }
76
+ } catch (error) {
77
+ // Re-throw to let BatchedDestination handle fallback
78
+ throw error;
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Send logs individually
84
+ * Used as fallback when batch endpoint fails or is unavailable.
85
+ * @param {Array<Object>} logs - Array of log entries
86
+ * @returns {Promise<void>}
87
+ * @private
88
+ */
89
+ async sendIndividually(logs) {
90
+ const promises = logs.map(log =>
91
+ this.apiClient.addSetupLog(this.jobId, log.level, log.message, log.metadata)
92
+ .catch((error) => {
93
+ // Silently fail individual logs to prevent cascading errors
94
+ this.handleError(error, log.level, log.message);
95
+ })
96
+ );
97
+
98
+ await Promise.all(promises);
99
+ }
100
+
101
+ /**
102
+ * Handle errors during API operations
103
+ * Silently fails to prevent cascading errors, but could be enhanced
104
+ * to report to a fallback destination (e.g., console or file)
105
+ * @param {Error} error - The error that occurred
106
+ * @param {string} level - Log level of failed write
107
+ * @param {string} message - Log message of failed write
108
+ * @protected
109
+ */
110
+ handleError(error, level, message) {
111
+ // Silently fail - setup logs are best-effort and shouldn't disrupt job execution
112
+ // Logging errors about logging would create cascading failures and noise
113
+ // If API logging fails, the job continues unaffected
114
+ // console.error(`[ApiDestination Error] Failed to send log: ${error.message}`);
115
+ }
116
+ }
117
+
118
+ module.exports = ApiDestinationUnbatched;
@@ -0,0 +1,40 @@
1
+ const BatchedDestination = require('./batched-destination');
2
+ const ApiDestinationUnbatched = require('./api-destination-unbatched');
3
+
4
+ /**
5
+ * ApiDestination - Sends logs to API with batching
6
+ *
7
+ * Provides API-based logging with automatic batching to reduce overhead.
8
+ * Wraps ApiDestinationUnbatched with BatchedDestination for efficient sending.
9
+ * Batches multiple log entries and flushes automatically based on buffer size or time interval.
10
+ *
11
+ * This is a convenience factory that creates a properly configured batched API destination.
12
+ */
13
+ class ApiDestination extends BatchedDestination {
14
+ /**
15
+ * Create a new batched API destination
16
+ * @param {Object} config - Configuration options
17
+ * @param {Object} config.apiClient - API client with addSetupLog() and addSetupLogBatch() methods
18
+ * @param {number} config.jobId - Job ID to associate logs with
19
+ * @param {number} [config.maxBatchSize=10] - Maximum logs to buffer before flushing
20
+ * @param {number} [config.flushInterval=2000] - Interval in ms to auto-flush
21
+ * @param {boolean} [config.useBatchEndpoint=true] - Whether to use batch endpoint
22
+ */
23
+ constructor(config) {
24
+ // Create unbatched API destination
25
+ const unbatchedDestination = new ApiDestinationUnbatched({
26
+ apiClient: config.apiClient,
27
+ jobId: config.jobId,
28
+ useBatchEndpoint: config.useBatchEndpoint
29
+ });
30
+
31
+ // Wrap it with batching
32
+ super(unbatchedDestination, {
33
+ maxBatchSize: config.maxBatchSize,
34
+ flushInterval: config.flushInterval,
35
+ useBatchSend: config.useBatchEndpoint
36
+ });
37
+ }
38
+ }
39
+
40
+ module.exports = ApiDestination;