@supaku/agentfactory 0.1.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.
- package/LICENSE +21 -0
- package/dist/src/deployment/deployment-checker.d.ts +110 -0
- package/dist/src/deployment/deployment-checker.d.ts.map +1 -0
- package/dist/src/deployment/deployment-checker.js +242 -0
- package/dist/src/deployment/index.d.ts +3 -0
- package/dist/src/deployment/index.d.ts.map +1 -0
- package/dist/src/deployment/index.js +2 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +4 -0
- package/dist/src/logger.d.ts +117 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +430 -0
- package/dist/src/orchestrator/activity-emitter.d.ts +128 -0
- package/dist/src/orchestrator/activity-emitter.d.ts.map +1 -0
- package/dist/src/orchestrator/activity-emitter.js +406 -0
- package/dist/src/orchestrator/api-activity-emitter.d.ts +167 -0
- package/dist/src/orchestrator/api-activity-emitter.d.ts.map +1 -0
- package/dist/src/orchestrator/api-activity-emitter.js +469 -0
- package/dist/src/orchestrator/heartbeat-writer.d.ts +57 -0
- package/dist/src/orchestrator/heartbeat-writer.d.ts.map +1 -0
- package/dist/src/orchestrator/heartbeat-writer.js +137 -0
- package/dist/src/orchestrator/index.d.ts +20 -0
- package/dist/src/orchestrator/index.d.ts.map +1 -0
- package/dist/src/orchestrator/index.js +22 -0
- package/dist/src/orchestrator/log-analyzer.d.ts +160 -0
- package/dist/src/orchestrator/log-analyzer.d.ts.map +1 -0
- package/dist/src/orchestrator/log-analyzer.js +572 -0
- package/dist/src/orchestrator/log-config.d.ts +39 -0
- package/dist/src/orchestrator/log-config.d.ts.map +1 -0
- package/dist/src/orchestrator/log-config.js +45 -0
- package/dist/src/orchestrator/orchestrator.d.ts +246 -0
- package/dist/src/orchestrator/orchestrator.d.ts.map +1 -0
- package/dist/src/orchestrator/orchestrator.js +2525 -0
- package/dist/src/orchestrator/parse-work-result.d.ts +16 -0
- package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -0
- package/dist/src/orchestrator/parse-work-result.js +73 -0
- package/dist/src/orchestrator/progress-logger.d.ts +72 -0
- package/dist/src/orchestrator/progress-logger.d.ts.map +1 -0
- package/dist/src/orchestrator/progress-logger.js +135 -0
- package/dist/src/orchestrator/session-logger.d.ts +159 -0
- package/dist/src/orchestrator/session-logger.d.ts.map +1 -0
- package/dist/src/orchestrator/session-logger.js +275 -0
- package/dist/src/orchestrator/state-recovery.d.ts +96 -0
- package/dist/src/orchestrator/state-recovery.d.ts.map +1 -0
- package/dist/src/orchestrator/state-recovery.js +301 -0
- package/dist/src/orchestrator/state-types.d.ts +165 -0
- package/dist/src/orchestrator/state-types.d.ts.map +1 -0
- package/dist/src/orchestrator/state-types.js +7 -0
- package/dist/src/orchestrator/stream-parser.d.ts +145 -0
- package/dist/src/orchestrator/stream-parser.d.ts.map +1 -0
- package/dist/src/orchestrator/stream-parser.js +131 -0
- package/dist/src/orchestrator/types.d.ts +205 -0
- package/dist/src/orchestrator/types.d.ts.map +1 -0
- package/dist/src/orchestrator/types.js +4 -0
- package/dist/src/providers/amp-provider.d.ts +20 -0
- package/dist/src/providers/amp-provider.d.ts.map +1 -0
- package/dist/src/providers/amp-provider.js +24 -0
- package/dist/src/providers/claude-provider.d.ts +18 -0
- package/dist/src/providers/claude-provider.d.ts.map +1 -0
- package/dist/src/providers/claude-provider.js +267 -0
- package/dist/src/providers/codex-provider.d.ts +21 -0
- package/dist/src/providers/codex-provider.d.ts.map +1 -0
- package/dist/src/providers/codex-provider.js +25 -0
- package/dist/src/providers/index.d.ts +42 -0
- package/dist/src/providers/index.d.ts.map +1 -0
- package/dist/src/providers/index.js +77 -0
- package/dist/src/providers/types.d.ts +147 -0
- package/dist/src/providers/types.d.ts.map +1 -0
- package/dist/src/providers/types.js +13 -0
- package/package.json +63 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger utility for worker and orchestrator output
|
|
3
|
+
*
|
|
4
|
+
* Provides colorized, structured logging with worker/agent context.
|
|
5
|
+
* Uses ANSI escape codes directly to avoid external dependencies.
|
|
6
|
+
*/
|
|
7
|
+
// ANSI color codes
|
|
8
|
+
const colors = {
|
|
9
|
+
reset: '\x1b[0m',
|
|
10
|
+
bold: '\x1b[1m',
|
|
11
|
+
dim: '\x1b[2m',
|
|
12
|
+
// Foreground colors
|
|
13
|
+
black: '\x1b[30m',
|
|
14
|
+
red: '\x1b[31m',
|
|
15
|
+
green: '\x1b[32m',
|
|
16
|
+
yellow: '\x1b[33m',
|
|
17
|
+
blue: '\x1b[34m',
|
|
18
|
+
magenta: '\x1b[35m',
|
|
19
|
+
cyan: '\x1b[36m',
|
|
20
|
+
white: '\x1b[37m',
|
|
21
|
+
// Bright foreground colors
|
|
22
|
+
brightBlack: '\x1b[90m',
|
|
23
|
+
brightRed: '\x1b[91m',
|
|
24
|
+
brightGreen: '\x1b[92m',
|
|
25
|
+
brightYellow: '\x1b[93m',
|
|
26
|
+
brightBlue: '\x1b[94m',
|
|
27
|
+
brightMagenta: '\x1b[95m',
|
|
28
|
+
brightCyan: '\x1b[96m',
|
|
29
|
+
brightWhite: '\x1b[97m',
|
|
30
|
+
// Background colors
|
|
31
|
+
bgBlack: '\x1b[40m',
|
|
32
|
+
bgRed: '\x1b[41m',
|
|
33
|
+
bgGreen: '\x1b[42m',
|
|
34
|
+
bgYellow: '\x1b[43m',
|
|
35
|
+
bgBlue: '\x1b[44m',
|
|
36
|
+
bgMagenta: '\x1b[45m',
|
|
37
|
+
bgCyan: '\x1b[46m',
|
|
38
|
+
bgWhite: '\x1b[47m',
|
|
39
|
+
};
|
|
40
|
+
// Color palette for worker/agent identification (easy to distinguish)
|
|
41
|
+
const WORKER_COLORS = ['cyan', 'magenta', 'yellow', 'green', 'blue', 'brightCyan', 'brightMagenta', 'brightYellow'];
|
|
42
|
+
// Activity type colors
|
|
43
|
+
const ACTIVITY_COLORS = {
|
|
44
|
+
thought: 'brightBlack',
|
|
45
|
+
action: 'blue',
|
|
46
|
+
response: 'green',
|
|
47
|
+
tool_use: 'cyan',
|
|
48
|
+
tool_result: 'brightBlack',
|
|
49
|
+
};
|
|
50
|
+
// Log level styling
|
|
51
|
+
const LEVEL_STYLES = {
|
|
52
|
+
debug: { color: 'brightBlack', label: 'DBG' },
|
|
53
|
+
info: { color: 'brightBlue', label: 'INF' },
|
|
54
|
+
success: { color: 'green', label: 'OK ' },
|
|
55
|
+
warn: { color: 'yellow', label: 'WRN' },
|
|
56
|
+
error: { color: 'red', label: 'ERR' },
|
|
57
|
+
};
|
|
58
|
+
const LOG_LEVEL_PRIORITY = {
|
|
59
|
+
debug: 0,
|
|
60
|
+
info: 1,
|
|
61
|
+
success: 2,
|
|
62
|
+
warn: 3,
|
|
63
|
+
error: 4,
|
|
64
|
+
};
|
|
65
|
+
// Map to track assigned colors for worker/agent IDs
|
|
66
|
+
const colorAssignments = new Map();
|
|
67
|
+
let colorIndex = 0;
|
|
68
|
+
function getColorForId(id) {
|
|
69
|
+
if (!colorAssignments.has(id)) {
|
|
70
|
+
colorAssignments.set(id, WORKER_COLORS[colorIndex % WORKER_COLORS.length]);
|
|
71
|
+
colorIndex++;
|
|
72
|
+
}
|
|
73
|
+
return colorAssignments.get(id);
|
|
74
|
+
}
|
|
75
|
+
function colorize(text, ...colorNames) {
|
|
76
|
+
const colorCodes = colorNames.map((c) => colors[c]).join('');
|
|
77
|
+
return `${colorCodes}${text}${colors.reset}`;
|
|
78
|
+
}
|
|
79
|
+
function formatTimestamp() {
|
|
80
|
+
const now = new Date();
|
|
81
|
+
const hours = now.getHours().toString().padStart(2, '0');
|
|
82
|
+
const minutes = now.getMinutes().toString().padStart(2, '0');
|
|
83
|
+
const seconds = now.getSeconds().toString().padStart(2, '0');
|
|
84
|
+
return `${hours}:${minutes}:${seconds}`;
|
|
85
|
+
}
|
|
86
|
+
function truncate(text, maxLength) {
|
|
87
|
+
if (text.length <= maxLength)
|
|
88
|
+
return text;
|
|
89
|
+
return text.substring(0, maxLength - 3) + '...';
|
|
90
|
+
}
|
|
91
|
+
export class Logger {
|
|
92
|
+
context;
|
|
93
|
+
options;
|
|
94
|
+
constructor(context = {}, options = {}) {
|
|
95
|
+
this.context = context;
|
|
96
|
+
this.options = {
|
|
97
|
+
showTimestamp: options.showTimestamp ?? true,
|
|
98
|
+
showLevel: options.showLevel ?? true,
|
|
99
|
+
colorEnabled: options.colorEnabled ?? process.stdout.isTTY !== false,
|
|
100
|
+
minLevel: options.minLevel ?? 'info',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Create a child logger with additional context
|
|
105
|
+
*/
|
|
106
|
+
child(additionalContext) {
|
|
107
|
+
return new Logger({ ...this.context, ...additionalContext }, this.options);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Format the context prefix (worker ID, issue identifier)
|
|
111
|
+
*/
|
|
112
|
+
formatPrefix() {
|
|
113
|
+
const parts = [];
|
|
114
|
+
// Worker ID with color
|
|
115
|
+
if (this.context.workerShortId || this.context.workerId) {
|
|
116
|
+
const id = this.context.workerShortId || this.context.workerId.substring(0, 8);
|
|
117
|
+
const color = getColorForId(this.context.workerId || id);
|
|
118
|
+
if (this.options.colorEnabled) {
|
|
119
|
+
parts.push(colorize(`[${id}]`, color, 'bold'));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
parts.push(`[${id}]`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Issue identifier with rotating color for visual distinction
|
|
126
|
+
if (this.context.issueIdentifier) {
|
|
127
|
+
if (this.options.colorEnabled) {
|
|
128
|
+
const color = getColorForId(this.context.issueIdentifier);
|
|
129
|
+
parts.push(colorize(`[${this.context.issueIdentifier}]`, color, 'bold'));
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
parts.push(`[${this.context.issueIdentifier}]`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return parts.join(' ');
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Format a log line
|
|
139
|
+
*/
|
|
140
|
+
formatLine(level, message, data) {
|
|
141
|
+
const parts = [];
|
|
142
|
+
// Timestamp
|
|
143
|
+
if (this.options.showTimestamp) {
|
|
144
|
+
const ts = formatTimestamp();
|
|
145
|
+
if (this.options.colorEnabled) {
|
|
146
|
+
parts.push(colorize(ts, 'dim'));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
parts.push(ts);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Level indicator
|
|
153
|
+
if (this.options.showLevel) {
|
|
154
|
+
const style = LEVEL_STYLES[level];
|
|
155
|
+
if (this.options.colorEnabled) {
|
|
156
|
+
parts.push(colorize(style.label, style.color));
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
parts.push(style.label);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Context prefix (worker/issue)
|
|
163
|
+
const prefix = this.formatPrefix();
|
|
164
|
+
if (prefix) {
|
|
165
|
+
parts.push(prefix);
|
|
166
|
+
}
|
|
167
|
+
// Message
|
|
168
|
+
parts.push(message);
|
|
169
|
+
// Data (if any)
|
|
170
|
+
if (data && Object.keys(data).length > 0) {
|
|
171
|
+
const dataStr = this.formatData(data);
|
|
172
|
+
if (this.options.colorEnabled) {
|
|
173
|
+
parts.push(colorize(dataStr, 'dim'));
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
parts.push(dataStr);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return parts.join(' ');
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Format data object for display
|
|
183
|
+
*/
|
|
184
|
+
formatData(data) {
|
|
185
|
+
const pairs = [];
|
|
186
|
+
for (const [key, value] of Object.entries(data)) {
|
|
187
|
+
if (value === undefined)
|
|
188
|
+
continue;
|
|
189
|
+
let valueStr;
|
|
190
|
+
if (typeof value === 'string') {
|
|
191
|
+
valueStr = truncate(value, 50);
|
|
192
|
+
}
|
|
193
|
+
else if (typeof value === 'number' || typeof value === 'boolean') {
|
|
194
|
+
valueStr = String(value);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
valueStr = truncate(JSON.stringify(value), 50);
|
|
198
|
+
}
|
|
199
|
+
pairs.push(`${key}=${valueStr}`);
|
|
200
|
+
}
|
|
201
|
+
return pairs.length > 0 ? `{ ${pairs.join(', ')} }` : '';
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Check if a log level should be output
|
|
205
|
+
*/
|
|
206
|
+
shouldLog(level) {
|
|
207
|
+
return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[this.options.minLevel];
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Core log method
|
|
211
|
+
*/
|
|
212
|
+
log(level, message, data) {
|
|
213
|
+
if (!this.shouldLog(level))
|
|
214
|
+
return;
|
|
215
|
+
const line = this.formatLine(level, message, data);
|
|
216
|
+
if (level === 'error') {
|
|
217
|
+
console.error(line);
|
|
218
|
+
}
|
|
219
|
+
else if (level === 'warn') {
|
|
220
|
+
console.warn(line);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
console.log(line);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Convenience methods
|
|
227
|
+
debug(message, data) {
|
|
228
|
+
this.log('debug', message, data);
|
|
229
|
+
}
|
|
230
|
+
info(message, data) {
|
|
231
|
+
this.log('info', message, data);
|
|
232
|
+
}
|
|
233
|
+
success(message, data) {
|
|
234
|
+
this.log('success', message, data);
|
|
235
|
+
}
|
|
236
|
+
warn(message, data) {
|
|
237
|
+
this.log('warn', message, data);
|
|
238
|
+
}
|
|
239
|
+
error(message, data) {
|
|
240
|
+
this.log('error', message, data);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Log an activity (thought, action, response) with appropriate styling
|
|
244
|
+
*/
|
|
245
|
+
activity(type, content, maxLength = 80) {
|
|
246
|
+
if (!this.shouldLog('info'))
|
|
247
|
+
return;
|
|
248
|
+
const parts = [];
|
|
249
|
+
// Timestamp
|
|
250
|
+
if (this.options.showTimestamp) {
|
|
251
|
+
const ts = formatTimestamp();
|
|
252
|
+
if (this.options.colorEnabled) {
|
|
253
|
+
parts.push(colorize(ts, 'dim'));
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
parts.push(ts);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Activity type indicator
|
|
260
|
+
const activityColor = ACTIVITY_COLORS[type] || 'white';
|
|
261
|
+
const typeLabel = type.substring(0, 3).toUpperCase();
|
|
262
|
+
if (this.options.colorEnabled) {
|
|
263
|
+
parts.push(colorize(typeLabel, activityColor));
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
parts.push(typeLabel);
|
|
267
|
+
}
|
|
268
|
+
// Context prefix
|
|
269
|
+
const prefix = this.formatPrefix();
|
|
270
|
+
if (prefix) {
|
|
271
|
+
parts.push(prefix);
|
|
272
|
+
}
|
|
273
|
+
// Content (truncated)
|
|
274
|
+
const truncatedContent = truncate(content.replace(/\n/g, ' '), maxLength);
|
|
275
|
+
parts.push(truncatedContent);
|
|
276
|
+
console.log(parts.join(' '));
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Log a section header/divider
|
|
280
|
+
*/
|
|
281
|
+
section(title) {
|
|
282
|
+
const divider = '─'.repeat(60);
|
|
283
|
+
if (this.options.colorEnabled) {
|
|
284
|
+
console.log(colorize(`\n${divider}`, 'dim'));
|
|
285
|
+
console.log(colorize(` ${title}`, 'bold', 'brightWhite'));
|
|
286
|
+
console.log(colorize(`${divider}`, 'dim'));
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
console.log(`\n${divider}`);
|
|
290
|
+
console.log(` ${title}`);
|
|
291
|
+
console.log(divider);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Log a status change with visual indicator
|
|
296
|
+
*/
|
|
297
|
+
status(status, details) {
|
|
298
|
+
const statusColors = {
|
|
299
|
+
starting: 'yellow',
|
|
300
|
+
running: 'blue',
|
|
301
|
+
completed: 'green',
|
|
302
|
+
stopped: 'yellow',
|
|
303
|
+
failed: 'red',
|
|
304
|
+
claimed: 'cyan',
|
|
305
|
+
registered: 'green',
|
|
306
|
+
};
|
|
307
|
+
const color = statusColors[status.toLowerCase()] || 'white';
|
|
308
|
+
const parts = [];
|
|
309
|
+
// Timestamp
|
|
310
|
+
if (this.options.showTimestamp) {
|
|
311
|
+
const ts = formatTimestamp();
|
|
312
|
+
if (this.options.colorEnabled) {
|
|
313
|
+
parts.push(colorize(ts, 'dim'));
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
parts.push(ts);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// Status indicator
|
|
320
|
+
if (this.options.colorEnabled) {
|
|
321
|
+
parts.push(colorize('●', color));
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
parts.push('*');
|
|
325
|
+
}
|
|
326
|
+
// Context prefix
|
|
327
|
+
const prefix = this.formatPrefix();
|
|
328
|
+
if (prefix) {
|
|
329
|
+
parts.push(prefix);
|
|
330
|
+
}
|
|
331
|
+
// Status text
|
|
332
|
+
if (this.options.colorEnabled) {
|
|
333
|
+
parts.push(colorize(status.toUpperCase(), color, 'bold'));
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
parts.push(status.toUpperCase());
|
|
337
|
+
}
|
|
338
|
+
// Details
|
|
339
|
+
if (details) {
|
|
340
|
+
parts.push(details);
|
|
341
|
+
}
|
|
342
|
+
console.log(parts.join(' '));
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Log a tool call with formatted input
|
|
346
|
+
*/
|
|
347
|
+
toolCall(toolName, input) {
|
|
348
|
+
if (!this.shouldLog('info'))
|
|
349
|
+
return;
|
|
350
|
+
const parts = [];
|
|
351
|
+
// Timestamp
|
|
352
|
+
if (this.options.showTimestamp) {
|
|
353
|
+
const ts = formatTimestamp();
|
|
354
|
+
if (this.options.colorEnabled) {
|
|
355
|
+
parts.push(colorize(ts, 'dim'));
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
parts.push(ts);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Tool indicator
|
|
362
|
+
if (this.options.colorEnabled) {
|
|
363
|
+
parts.push(colorize('→', 'cyan'));
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
parts.push('→');
|
|
367
|
+
}
|
|
368
|
+
// Context prefix
|
|
369
|
+
const prefix = this.formatPrefix();
|
|
370
|
+
if (prefix) {
|
|
371
|
+
parts.push(prefix);
|
|
372
|
+
}
|
|
373
|
+
// Tool name
|
|
374
|
+
if (this.options.colorEnabled) {
|
|
375
|
+
parts.push(colorize(toolName, 'cyan', 'bold'));
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
parts.push(toolName);
|
|
379
|
+
}
|
|
380
|
+
// Formatted input (key parameters)
|
|
381
|
+
if (input) {
|
|
382
|
+
const summary = this.formatToolInput(toolName, input);
|
|
383
|
+
if (summary) {
|
|
384
|
+
if (this.options.colorEnabled) {
|
|
385
|
+
parts.push(colorize(summary, 'dim'));
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
parts.push(summary);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
console.log(parts.join(' '));
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Format tool input for display (show relevant params based on tool type)
|
|
396
|
+
*/
|
|
397
|
+
formatToolInput(toolName, input) {
|
|
398
|
+
// Show most relevant parameter based on tool type
|
|
399
|
+
const toolParams = {
|
|
400
|
+
Read: ['file_path'],
|
|
401
|
+
Write: ['file_path'],
|
|
402
|
+
Edit: ['file_path', 'old_string'],
|
|
403
|
+
Grep: ['pattern', 'path'],
|
|
404
|
+
Glob: ['pattern'],
|
|
405
|
+
Bash: ['command'],
|
|
406
|
+
Task: ['subagent_type', 'description'],
|
|
407
|
+
WebFetch: ['url'],
|
|
408
|
+
WebSearch: ['query'],
|
|
409
|
+
};
|
|
410
|
+
const relevantParams = toolParams[toolName] || Object.keys(input).slice(0, 2);
|
|
411
|
+
const values = [];
|
|
412
|
+
for (const param of relevantParams) {
|
|
413
|
+
if (input[param] !== undefined) {
|
|
414
|
+
const value = String(input[param]);
|
|
415
|
+
values.push(truncate(value, 40));
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return values.length > 0 ? values.join(' ') : '';
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Create a logger instance
|
|
423
|
+
*/
|
|
424
|
+
export function createLogger(context, options) {
|
|
425
|
+
return new Logger(context, options);
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Default logger for quick use
|
|
429
|
+
*/
|
|
430
|
+
export const logger = createLogger();
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linear Activity Emitter
|
|
3
|
+
*
|
|
4
|
+
* Emits Claude stream events to Linear as agent activities.
|
|
5
|
+
* Handles rate limiting by batching rapid activities and
|
|
6
|
+
* truncating long outputs.
|
|
7
|
+
*
|
|
8
|
+
* Mapping:
|
|
9
|
+
* - assistant message → response (persisted, user-directed communication)
|
|
10
|
+
* - tool_use → action (ephemeral)
|
|
11
|
+
* - tool_result → action (ephemeral)
|
|
12
|
+
* - result → response (persisted)
|
|
13
|
+
* - error → error (persisted)
|
|
14
|
+
*/
|
|
15
|
+
import type { AgentSession } from '@supaku/agentfactory-linear';
|
|
16
|
+
import type { ClaudeStreamHandlers } from './stream-parser';
|
|
17
|
+
/** Configuration for the activity emitter */
|
|
18
|
+
export interface ActivityEmitterConfig {
|
|
19
|
+
/** AgentSession to emit activities to */
|
|
20
|
+
session: AgentSession;
|
|
21
|
+
/** Minimum interval between activities in ms (default: 500ms) */
|
|
22
|
+
minInterval?: number;
|
|
23
|
+
/** Maximum length for tool outputs before truncation (default: 2000) */
|
|
24
|
+
maxOutputLength?: number;
|
|
25
|
+
/** Whether to include timestamps in activities (default: false) */
|
|
26
|
+
includeTimestamps?: boolean;
|
|
27
|
+
/** Optional callback when an activity is emitted */
|
|
28
|
+
onActivityEmitted?: (type: string, content: string) => void;
|
|
29
|
+
/** Optional callback when an activity is throttled */
|
|
30
|
+
onActivityThrottled?: (type: string, content: string) => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Activity Emitter
|
|
34
|
+
*
|
|
35
|
+
* Handles rate-limited emission of Claude events to Linear activities.
|
|
36
|
+
*/
|
|
37
|
+
export declare class ActivityEmitter {
|
|
38
|
+
private readonly session;
|
|
39
|
+
private readonly minInterval;
|
|
40
|
+
private readonly maxOutputLength;
|
|
41
|
+
private readonly includeTimestamps;
|
|
42
|
+
private readonly onActivityEmitted?;
|
|
43
|
+
private readonly onActivityThrottled?;
|
|
44
|
+
private lastEmitTime;
|
|
45
|
+
private queue;
|
|
46
|
+
private flushTimer;
|
|
47
|
+
private isProcessing;
|
|
48
|
+
private readonly reportedToolErrors;
|
|
49
|
+
constructor(config: ActivityEmitterConfig);
|
|
50
|
+
/**
|
|
51
|
+
* Emit a thought activity (persistent by default for visibility in Linear)
|
|
52
|
+
*/
|
|
53
|
+
emitThought(content: string, ephemeral?: boolean): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Emit a tool use activity (ephemeral by default)
|
|
56
|
+
*/
|
|
57
|
+
emitToolUse(tool: string, input: Record<string, unknown>, ephemeral?: boolean): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Emit a response activity (persisted)
|
|
60
|
+
*/
|
|
61
|
+
emitResponse(content: string): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Emit an error activity (persisted)
|
|
64
|
+
*/
|
|
65
|
+
emitError(error: Error | string): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Report a tool error as a Linear issue for tracking and improvement.
|
|
68
|
+
* Creates a bug in the Agent project backlog.
|
|
69
|
+
*
|
|
70
|
+
* @param toolName - Name of the tool that errored
|
|
71
|
+
* @param errorMessage - The error message
|
|
72
|
+
* @param context - Additional context about the error
|
|
73
|
+
* @returns The created issue, or null if creation failed or was deduplicated
|
|
74
|
+
*/
|
|
75
|
+
reportToolError(toolName: string, errorMessage: string, context?: {
|
|
76
|
+
issueIdentifier?: string;
|
|
77
|
+
additionalContext?: Record<string, unknown>;
|
|
78
|
+
}): Promise<{
|
|
79
|
+
id: string;
|
|
80
|
+
identifier: string;
|
|
81
|
+
url: string;
|
|
82
|
+
} | null>;
|
|
83
|
+
/**
|
|
84
|
+
* Get Claude stream handlers that emit to Linear
|
|
85
|
+
*/
|
|
86
|
+
getStreamHandlers(): ClaudeStreamHandlers;
|
|
87
|
+
/**
|
|
88
|
+
* Queue an activity for emission with rate limiting
|
|
89
|
+
*/
|
|
90
|
+
private queueActivity;
|
|
91
|
+
/**
|
|
92
|
+
* Process queued activities
|
|
93
|
+
*/
|
|
94
|
+
private processQueue;
|
|
95
|
+
/**
|
|
96
|
+
* Merge consecutive similar activities in the queue
|
|
97
|
+
*/
|
|
98
|
+
private mergeQueuedActivities;
|
|
99
|
+
/**
|
|
100
|
+
* Emit a single activity to Linear
|
|
101
|
+
*/
|
|
102
|
+
private emitActivity;
|
|
103
|
+
/**
|
|
104
|
+
* Summarize tool input for display
|
|
105
|
+
*/
|
|
106
|
+
private summarizeToolInput;
|
|
107
|
+
/**
|
|
108
|
+
* Truncate long output strings
|
|
109
|
+
*/
|
|
110
|
+
private truncateOutput;
|
|
111
|
+
/**
|
|
112
|
+
* Format the final result content
|
|
113
|
+
*/
|
|
114
|
+
private formatResultContent;
|
|
115
|
+
/**
|
|
116
|
+
* Flush all pending activities immediately
|
|
117
|
+
*/
|
|
118
|
+
flush(): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Helper delay function
|
|
121
|
+
*/
|
|
122
|
+
private delay;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Create an activity emitter instance
|
|
126
|
+
*/
|
|
127
|
+
export declare function createActivityEmitter(config: ActivityEmitterConfig): ActivityEmitter;
|
|
128
|
+
//# sourceMappingURL=activity-emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-emitter.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/activity-emitter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC/D,OAAO,KAAK,EAOV,oBAAoB,EACrB,MAAM,iBAAiB,CAAA;AAIxB,6CAA6C;AAC7C,MAAM,WAAW,qBAAqB;IACpC,yCAAyC;IACzC,OAAO,EAAE,YAAY,CAAA;IACrB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,oDAAoD;IACpD,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3D,sDAAsD;IACtD,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAC9D;AAgCD;;;;GAIG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAyC;IAC5E,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAyC;IAE9E,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAA6C;IAC/D,OAAO,CAAC,YAAY,CAAQ;IAE5B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAyB;gBAEhD,MAAM,EAAE,qBAAqB;IASzC;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpE;;OAEG;IACG,WAAW,CACf,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,SAAS,UAAO,GACf,OAAO,CAAC,IAAI,CAAC;IAWhB;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlD;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASrD;;;;;;;;OAQG;IACG,eAAe,CACnB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE;QACR,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAC5C,GACA,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IA2BlE;;OAEG;IACH,iBAAiB,IAAI,oBAAoB;IA0EzC;;OAEG;YACW,aAAa;IAe3B;;OAEG;YACW,YAAY;IA+B1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAiD7B;;OAEG;YACW,YAAY;IA6C1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAoC1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAe3B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,qBAAqB,GAC5B,eAAe,CAEjB"}
|