cyrus-edge-worker 0.2.0 → 0.2.2
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/dist/AgentSessionManager.d.ts +20 -0
- package/dist/AgentSessionManager.d.ts.map +1 -1
- package/dist/AgentSessionManager.js +384 -13
- package/dist/AgentSessionManager.js.map +1 -1
- package/dist/EdgeWorker.d.ts +70 -17
- package/dist/EdgeWorker.d.ts.map +1 -1
- package/dist/EdgeWorker.js +334 -179
- package/dist/EdgeWorker.js.map +1 -1
- package/dist/RepositoryRouter.d.ts +118 -0
- package/dist/RepositoryRouter.d.ts.map +1 -0
- package/dist/RepositoryRouter.js +372 -0
- package/dist/RepositoryRouter.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/procedures/registry.d.ts +4 -0
- package/dist/procedures/registry.d.ts.map +1 -1
- package/dist/procedures/registry.js +4 -0
- package/dist/procedures/registry.js.map +1 -1
- package/dist/procedures/types.d.ts +2 -0
- package/dist/procedures/types.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -16,6 +16,7 @@ export declare class AgentSessionManager {
|
|
|
16
16
|
private entries;
|
|
17
17
|
private activeTasksBySession;
|
|
18
18
|
private toolCallsByToolUseId;
|
|
19
|
+
private activeStatusActivitiesBySession;
|
|
19
20
|
private procedureRouter?;
|
|
20
21
|
private sharedApplicationServer?;
|
|
21
22
|
private getParentSessionId?;
|
|
@@ -39,6 +40,21 @@ export declare class AgentSessionManager {
|
|
|
39
40
|
* Format TodoWrite tool parameter as a nice checklist
|
|
40
41
|
*/
|
|
41
42
|
private formatTodoWriteParameter;
|
|
43
|
+
/**
|
|
44
|
+
* Format tool input for display in Linear agent activities
|
|
45
|
+
* Converts raw tool inputs into user-friendly parameter strings
|
|
46
|
+
*/
|
|
47
|
+
private formatToolParameter;
|
|
48
|
+
/**
|
|
49
|
+
* Format tool action name with description for Bash tool
|
|
50
|
+
* Puts the description in round brackets after the tool name in the action field
|
|
51
|
+
*/
|
|
52
|
+
private formatToolActionName;
|
|
53
|
+
/**
|
|
54
|
+
* Format tool result for display in Linear agent activities
|
|
55
|
+
* Converts raw tool results into formatted Markdown
|
|
56
|
+
*/
|
|
57
|
+
private formatToolResult;
|
|
42
58
|
/**
|
|
43
59
|
* Complete a session from Claude result message
|
|
44
60
|
*/
|
|
@@ -178,5 +194,9 @@ export declare class AgentSessionManager {
|
|
|
178
194
|
* Post the procedure selection result as a non-ephemeral thought
|
|
179
195
|
*/
|
|
180
196
|
postProcedureSelectionThought(linearAgentActivitySessionId: string, procedureName: string, classification: string): Promise<void>;
|
|
197
|
+
/**
|
|
198
|
+
* Handle status messages (compacting, etc.)
|
|
199
|
+
*/
|
|
200
|
+
private handleStatusMessage;
|
|
181
201
|
}
|
|
182
202
|
//# sourceMappingURL=AgentSessionManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentSessionManager.d.ts","sourceRoot":"","sources":["../src/AgentSessionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAGX,YAAY,EAEZ,UAAU,EACV,gBAAgB,
|
|
1
|
+
{"version":3,"file":"AgentSessionManager.d.ts","sourceRoot":"","sources":["../src/AgentSessionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@ export class AgentSessionManager {
|
|
|
12
12
|
entries = new Map(); // Stores a list of session entries per each session by its linearAgentActivitySessionId
|
|
13
13
|
activeTasksBySession = new Map(); // Maps session ID to active Task tool use ID
|
|
14
14
|
toolCallsByToolUseId = new Map(); // Track tool calls by their tool_use_id
|
|
15
|
+
activeStatusActivitiesBySession = new Map(); // Maps session ID to active compacting status activity ID
|
|
15
16
|
procedureRouter;
|
|
16
17
|
sharedApplicationServer;
|
|
17
18
|
getParentSessionId;
|
|
@@ -132,6 +133,317 @@ export class AgentSessionManager {
|
|
|
132
133
|
return jsonContent;
|
|
133
134
|
}
|
|
134
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Format tool input for display in Linear agent activities
|
|
138
|
+
* Converts raw tool inputs into user-friendly parameter strings
|
|
139
|
+
*/
|
|
140
|
+
formatToolParameter(toolName, toolInput) {
|
|
141
|
+
// If input is already a string, return it
|
|
142
|
+
if (typeof toolInput === "string") {
|
|
143
|
+
return toolInput;
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
switch (toolName) {
|
|
147
|
+
case "Bash":
|
|
148
|
+
case "↪ Bash": {
|
|
149
|
+
// Show command only - description goes in action field via formatToolActionName
|
|
150
|
+
return toolInput.command || JSON.stringify(toolInput);
|
|
151
|
+
}
|
|
152
|
+
case "Read":
|
|
153
|
+
case "↪ Read":
|
|
154
|
+
if (toolInput.file_path) {
|
|
155
|
+
let param = toolInput.file_path;
|
|
156
|
+
if (toolInput.offset !== undefined ||
|
|
157
|
+
toolInput.limit !== undefined) {
|
|
158
|
+
const start = toolInput.offset || 0;
|
|
159
|
+
const end = toolInput.limit ? start + toolInput.limit : "end";
|
|
160
|
+
param += ` (lines ${start + 1}-${end})`;
|
|
161
|
+
}
|
|
162
|
+
return param;
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
165
|
+
case "Edit":
|
|
166
|
+
case "↪ Edit":
|
|
167
|
+
if (toolInput.file_path) {
|
|
168
|
+
return toolInput.file_path;
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
case "Write":
|
|
172
|
+
case "↪ Write":
|
|
173
|
+
if (toolInput.file_path) {
|
|
174
|
+
return toolInput.file_path;
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
case "Grep":
|
|
178
|
+
case "↪ Grep":
|
|
179
|
+
if (toolInput.pattern) {
|
|
180
|
+
let param = `Pattern: \`${toolInput.pattern}\``;
|
|
181
|
+
if (toolInput.path) {
|
|
182
|
+
param += ` in ${toolInput.path}`;
|
|
183
|
+
}
|
|
184
|
+
if (toolInput.glob) {
|
|
185
|
+
param += ` (${toolInput.glob})`;
|
|
186
|
+
}
|
|
187
|
+
if (toolInput.type) {
|
|
188
|
+
param += ` [${toolInput.type} files]`;
|
|
189
|
+
}
|
|
190
|
+
return param;
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
case "Glob":
|
|
194
|
+
case "↪ Glob":
|
|
195
|
+
if (toolInput.pattern) {
|
|
196
|
+
let param = `Pattern: \`${toolInput.pattern}\``;
|
|
197
|
+
if (toolInput.path) {
|
|
198
|
+
param += ` in ${toolInput.path}`;
|
|
199
|
+
}
|
|
200
|
+
return param;
|
|
201
|
+
}
|
|
202
|
+
break;
|
|
203
|
+
case "Task":
|
|
204
|
+
case "↪ Task":
|
|
205
|
+
if (toolInput.description) {
|
|
206
|
+
return toolInput.description;
|
|
207
|
+
}
|
|
208
|
+
break;
|
|
209
|
+
case "WebFetch":
|
|
210
|
+
case "↪ WebFetch":
|
|
211
|
+
if (toolInput.url) {
|
|
212
|
+
return toolInput.url;
|
|
213
|
+
}
|
|
214
|
+
break;
|
|
215
|
+
case "WebSearch":
|
|
216
|
+
case "↪ WebSearch":
|
|
217
|
+
if (toolInput.query) {
|
|
218
|
+
return `Query: ${toolInput.query}`;
|
|
219
|
+
}
|
|
220
|
+
break;
|
|
221
|
+
case "NotebookEdit":
|
|
222
|
+
case "↪ NotebookEdit":
|
|
223
|
+
if (toolInput.notebook_path) {
|
|
224
|
+
let param = toolInput.notebook_path;
|
|
225
|
+
if (toolInput.cell_id) {
|
|
226
|
+
param += ` (cell ${toolInput.cell_id})`;
|
|
227
|
+
}
|
|
228
|
+
return param;
|
|
229
|
+
}
|
|
230
|
+
break;
|
|
231
|
+
default:
|
|
232
|
+
// For MCP tools or other unknown tools, try to extract meaningful info
|
|
233
|
+
if (toolName.startsWith("mcp__")) {
|
|
234
|
+
// Extract key fields that are commonly meaningful
|
|
235
|
+
const meaningfulFields = [
|
|
236
|
+
"query",
|
|
237
|
+
"id",
|
|
238
|
+
"issueId",
|
|
239
|
+
"title",
|
|
240
|
+
"name",
|
|
241
|
+
"path",
|
|
242
|
+
"file",
|
|
243
|
+
];
|
|
244
|
+
for (const field of meaningfulFields) {
|
|
245
|
+
if (toolInput[field]) {
|
|
246
|
+
return `${field}: ${toolInput[field]}`;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
// Fallback to JSON but make it compact
|
|
253
|
+
return JSON.stringify(toolInput);
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
console.error("[AgentSessionManager] Failed to format tool parameter:", error);
|
|
257
|
+
return JSON.stringify(toolInput);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Format tool action name with description for Bash tool
|
|
262
|
+
* Puts the description in round brackets after the tool name in the action field
|
|
263
|
+
*/
|
|
264
|
+
formatToolActionName(toolName, toolInput, isError) {
|
|
265
|
+
// Handle Bash tool with description
|
|
266
|
+
if (toolName === "Bash" || toolName === "↪ Bash") {
|
|
267
|
+
// Check if toolInput has a description field
|
|
268
|
+
if (toolInput &&
|
|
269
|
+
typeof toolInput === "object" &&
|
|
270
|
+
"description" in toolInput &&
|
|
271
|
+
toolInput.description) {
|
|
272
|
+
const baseName = isError ? `${toolName} (Error)` : toolName;
|
|
273
|
+
return `${baseName} (${toolInput.description})`;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// Default formatting for other tools or Bash without description
|
|
277
|
+
return isError ? `${toolName} (Error)` : toolName;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Format tool result for display in Linear agent activities
|
|
281
|
+
* Converts raw tool results into formatted Markdown
|
|
282
|
+
*/
|
|
283
|
+
formatToolResult(toolName, toolInput, result, isError) {
|
|
284
|
+
// If there's an error, wrap in error formatting
|
|
285
|
+
if (isError) {
|
|
286
|
+
return `\`\`\`\n${result}\n\`\`\``;
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
switch (toolName) {
|
|
290
|
+
case "Bash":
|
|
291
|
+
case "↪ Bash": {
|
|
292
|
+
// Show command first if not already in parameter
|
|
293
|
+
let formatted = "";
|
|
294
|
+
if (toolInput.command && !toolInput.description) {
|
|
295
|
+
formatted += `\`\`\`bash\n${toolInput.command}\n\`\`\`\n\n`;
|
|
296
|
+
}
|
|
297
|
+
// Then show output
|
|
298
|
+
if (result?.trim()) {
|
|
299
|
+
formatted += `\`\`\`\n${result}\n\`\`\``;
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
formatted += "*No output*";
|
|
303
|
+
}
|
|
304
|
+
return formatted;
|
|
305
|
+
}
|
|
306
|
+
case "Read":
|
|
307
|
+
case "↪ Read":
|
|
308
|
+
// For Read, the result is file content - use code block
|
|
309
|
+
if (result?.trim()) {
|
|
310
|
+
// Clean up the result: remove line numbers and system-reminder tags
|
|
311
|
+
let cleanedResult = result;
|
|
312
|
+
// Remove line numbers (format: " 123→")
|
|
313
|
+
cleanedResult = cleanedResult.replace(/^\s*\d+→/gm, "");
|
|
314
|
+
// Remove system-reminder blocks
|
|
315
|
+
cleanedResult = cleanedResult.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "");
|
|
316
|
+
// Trim any extra whitespace
|
|
317
|
+
cleanedResult = cleanedResult.trim();
|
|
318
|
+
// Try to detect language from file extension
|
|
319
|
+
let lang = "";
|
|
320
|
+
if (toolInput.file_path) {
|
|
321
|
+
const ext = toolInput.file_path.split(".").pop()?.toLowerCase();
|
|
322
|
+
const langMap = {
|
|
323
|
+
ts: "typescript",
|
|
324
|
+
tsx: "typescript",
|
|
325
|
+
js: "javascript",
|
|
326
|
+
jsx: "javascript",
|
|
327
|
+
py: "python",
|
|
328
|
+
rb: "ruby",
|
|
329
|
+
go: "go",
|
|
330
|
+
rs: "rust",
|
|
331
|
+
java: "java",
|
|
332
|
+
c: "c",
|
|
333
|
+
cpp: "cpp",
|
|
334
|
+
cs: "csharp",
|
|
335
|
+
php: "php",
|
|
336
|
+
swift: "swift",
|
|
337
|
+
kt: "kotlin",
|
|
338
|
+
scala: "scala",
|
|
339
|
+
sh: "bash",
|
|
340
|
+
bash: "bash",
|
|
341
|
+
zsh: "bash",
|
|
342
|
+
yml: "yaml",
|
|
343
|
+
yaml: "yaml",
|
|
344
|
+
json: "json",
|
|
345
|
+
xml: "xml",
|
|
346
|
+
html: "html",
|
|
347
|
+
css: "css",
|
|
348
|
+
scss: "scss",
|
|
349
|
+
md: "markdown",
|
|
350
|
+
sql: "sql",
|
|
351
|
+
};
|
|
352
|
+
lang = langMap[ext || ""] || "";
|
|
353
|
+
}
|
|
354
|
+
return `\`\`\`${lang}\n${cleanedResult}\n\`\`\``;
|
|
355
|
+
}
|
|
356
|
+
return "*Empty file*";
|
|
357
|
+
case "Edit":
|
|
358
|
+
case "↪ Edit": {
|
|
359
|
+
// For Edit, show changes as a diff
|
|
360
|
+
// Extract old_string and new_string from toolInput
|
|
361
|
+
if (toolInput.old_string && toolInput.new_string) {
|
|
362
|
+
// Format as a unified diff
|
|
363
|
+
const oldLines = toolInput.old_string.split("\n");
|
|
364
|
+
const newLines = toolInput.new_string.split("\n");
|
|
365
|
+
let diff = "```diff\n";
|
|
366
|
+
// Add context lines before changes (show all old lines with - prefix)
|
|
367
|
+
for (const line of oldLines) {
|
|
368
|
+
diff += `-${line}\n`;
|
|
369
|
+
}
|
|
370
|
+
// Add new lines with + prefix
|
|
371
|
+
for (const line of newLines) {
|
|
372
|
+
diff += `+${line}\n`;
|
|
373
|
+
}
|
|
374
|
+
diff += "```";
|
|
375
|
+
return diff;
|
|
376
|
+
}
|
|
377
|
+
// Fallback to result if old/new strings not available
|
|
378
|
+
if (result?.trim()) {
|
|
379
|
+
return result;
|
|
380
|
+
}
|
|
381
|
+
return "*Edit completed*";
|
|
382
|
+
}
|
|
383
|
+
case "Write":
|
|
384
|
+
case "↪ Write":
|
|
385
|
+
// For Write, just confirm
|
|
386
|
+
if (result?.trim()) {
|
|
387
|
+
return result; // In case there's an error or message
|
|
388
|
+
}
|
|
389
|
+
return "*File written successfully*";
|
|
390
|
+
case "Grep":
|
|
391
|
+
case "↪ Grep": {
|
|
392
|
+
// Format grep results
|
|
393
|
+
if (result?.trim()) {
|
|
394
|
+
const lines = result.split("\n");
|
|
395
|
+
// If it looks like file paths (files_with_matches mode)
|
|
396
|
+
if (lines.length > 0 &&
|
|
397
|
+
lines[0] &&
|
|
398
|
+
!lines[0].includes(":") &&
|
|
399
|
+
lines[0].trim().length > 0) {
|
|
400
|
+
return `Found ${lines.filter((l) => l.trim()).length} matching files:\n\`\`\`\n${result}\n\`\`\``;
|
|
401
|
+
}
|
|
402
|
+
// Otherwise it's content matches
|
|
403
|
+
return `\`\`\`\n${result}\n\`\`\``;
|
|
404
|
+
}
|
|
405
|
+
return "*No matches found*";
|
|
406
|
+
}
|
|
407
|
+
case "Glob":
|
|
408
|
+
case "↪ Glob": {
|
|
409
|
+
if (result?.trim()) {
|
|
410
|
+
const lines = result.split("\n").filter((l) => l.trim());
|
|
411
|
+
return `Found ${lines.length} matching files:\n\`\`\`\n${result}\n\`\`\``;
|
|
412
|
+
}
|
|
413
|
+
return "*No files found*";
|
|
414
|
+
}
|
|
415
|
+
case "Task":
|
|
416
|
+
case "↪ Task":
|
|
417
|
+
// Task results can be complex - keep as is but in code block if multiline
|
|
418
|
+
if (result?.trim()) {
|
|
419
|
+
if (result.includes("\n")) {
|
|
420
|
+
return `\`\`\`\n${result}\n\`\`\``;
|
|
421
|
+
}
|
|
422
|
+
return result;
|
|
423
|
+
}
|
|
424
|
+
return "*Task completed*";
|
|
425
|
+
case "WebFetch":
|
|
426
|
+
case "↪ WebFetch":
|
|
427
|
+
case "WebSearch":
|
|
428
|
+
case "↪ WebSearch":
|
|
429
|
+
// Web results are usually formatted, keep as is
|
|
430
|
+
return result || "*No results*";
|
|
431
|
+
default:
|
|
432
|
+
// For unknown tools, use code block if result has multiple lines
|
|
433
|
+
if (result?.trim()) {
|
|
434
|
+
if (result.includes("\n") && result.length > 100) {
|
|
435
|
+
return `\`\`\`\n${result}\n\`\`\``;
|
|
436
|
+
}
|
|
437
|
+
return result;
|
|
438
|
+
}
|
|
439
|
+
return "*Completed*";
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
console.error("[AgentSessionManager] Failed to format tool result:", error);
|
|
444
|
+
return result || "";
|
|
445
|
+
}
|
|
446
|
+
}
|
|
135
447
|
/**
|
|
136
448
|
* Complete a session from Claude result message
|
|
137
449
|
*/
|
|
@@ -296,6 +608,10 @@ export class AgentSessionManager {
|
|
|
296
608
|
await this.postModelNotificationThought(linearAgentActivitySessionId, systemMessage.model);
|
|
297
609
|
}
|
|
298
610
|
}
|
|
611
|
+
else if (message.subtype === "status") {
|
|
612
|
+
// Handle status updates (compacting, etc.)
|
|
613
|
+
await this.handleStatusMessage(linearAgentActivitySessionId, message);
|
|
614
|
+
}
|
|
299
615
|
break;
|
|
300
616
|
case "user": {
|
|
301
617
|
const userEntry = await this.createSessionEntry(linearAgentActivitySessionId, message);
|
|
@@ -486,17 +802,16 @@ export class AgentSessionManager {
|
|
|
486
802
|
if (toolName === "TodoWrite" || toolName === "↪ TodoWrite") {
|
|
487
803
|
return;
|
|
488
804
|
}
|
|
489
|
-
// Format
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
const wrappedResult = toolResult.content?.trim() || "";
|
|
805
|
+
// Format parameter and result using our formatters
|
|
806
|
+
const formattedParameter = this.formatToolParameter(toolName, toolInput);
|
|
807
|
+
const formattedResult = this.formatToolResult(toolName, toolInput, toolResult.content?.trim() || "", toolResult.isError);
|
|
808
|
+
// Format the action name (with description for Bash tool)
|
|
809
|
+
const formattedAction = this.formatToolActionName(toolName, toolInput, toolResult.isError);
|
|
495
810
|
content = {
|
|
496
811
|
type: "action",
|
|
497
|
-
action:
|
|
498
|
-
parameter:
|
|
499
|
-
result:
|
|
812
|
+
action: formattedAction,
|
|
813
|
+
parameter: formattedParameter,
|
|
814
|
+
result: formattedResult,
|
|
500
815
|
};
|
|
501
816
|
}
|
|
502
817
|
else {
|
|
@@ -539,7 +854,8 @@ export class AgentSessionManager {
|
|
|
539
854
|
}
|
|
540
855
|
else if (toolName === "Task") {
|
|
541
856
|
// Special handling for Task tool - add start marker and track active task
|
|
542
|
-
const
|
|
857
|
+
const toolInput = entry.metadata.toolInput || entry.content;
|
|
858
|
+
const formattedParameter = this.formatToolParameter(toolName, toolInput);
|
|
543
859
|
const displayName = toolName;
|
|
544
860
|
// Track this as the active Task for this session
|
|
545
861
|
if (entry.metadata?.toolUseId) {
|
|
@@ -548,7 +864,7 @@ export class AgentSessionManager {
|
|
|
548
864
|
content = {
|
|
549
865
|
type: "action",
|
|
550
866
|
action: displayName,
|
|
551
|
-
parameter:
|
|
867
|
+
parameter: formattedParameter,
|
|
552
868
|
// result will be added later when we get tool result
|
|
553
869
|
};
|
|
554
870
|
// Task is not ephemeral
|
|
@@ -556,7 +872,7 @@ export class AgentSessionManager {
|
|
|
556
872
|
}
|
|
557
873
|
else {
|
|
558
874
|
// Other tools - check if they're within an active Task
|
|
559
|
-
const
|
|
875
|
+
const toolInput = entry.metadata.toolInput || entry.content;
|
|
560
876
|
let displayName = toolName;
|
|
561
877
|
if (entry.metadata?.parentToolUseId) {
|
|
562
878
|
const activeTaskId = this.activeTasksBySession.get(linearAgentActivitySessionId);
|
|
@@ -564,10 +880,11 @@ export class AgentSessionManager {
|
|
|
564
880
|
displayName = `↪ ${toolName}`;
|
|
565
881
|
}
|
|
566
882
|
}
|
|
883
|
+
const formattedParameter = this.formatToolParameter(displayName, toolInput);
|
|
567
884
|
content = {
|
|
568
885
|
type: "action",
|
|
569
886
|
action: displayName,
|
|
570
|
-
parameter:
|
|
887
|
+
parameter: formattedParameter,
|
|
571
888
|
// result will be added later when we get tool result
|
|
572
889
|
};
|
|
573
890
|
// Standard tool calls are ephemeral
|
|
@@ -1031,5 +1348,59 @@ export class AgentSessionManager {
|
|
|
1031
1348
|
console.error(`[AgentSessionManager] Error posting procedure selection:`, error);
|
|
1032
1349
|
}
|
|
1033
1350
|
}
|
|
1351
|
+
/**
|
|
1352
|
+
* Handle status messages (compacting, etc.)
|
|
1353
|
+
*/
|
|
1354
|
+
async handleStatusMessage(linearAgentActivitySessionId, message) {
|
|
1355
|
+
const session = this.sessions.get(linearAgentActivitySessionId);
|
|
1356
|
+
if (!session || !session.linearAgentActivitySessionId) {
|
|
1357
|
+
console.warn(`[AgentSessionManager] No Linear session ID for session ${linearAgentActivitySessionId}`);
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
try {
|
|
1361
|
+
if (message.status === "compacting") {
|
|
1362
|
+
// Create an ephemeral thought for the compacting status
|
|
1363
|
+
const result = await this.linearClient.createAgentActivity({
|
|
1364
|
+
agentSessionId: session.linearAgentActivitySessionId,
|
|
1365
|
+
content: {
|
|
1366
|
+
type: "thought",
|
|
1367
|
+
body: "Compacting conversation history…",
|
|
1368
|
+
},
|
|
1369
|
+
ephemeral: true,
|
|
1370
|
+
});
|
|
1371
|
+
if (result.success && result.agentActivity) {
|
|
1372
|
+
const activity = await result.agentActivity;
|
|
1373
|
+
// Store the activity ID so we can replace it later
|
|
1374
|
+
this.activeStatusActivitiesBySession.set(linearAgentActivitySessionId, activity.id);
|
|
1375
|
+
console.log(`[AgentSessionManager] Posted ephemeral compacting status for session ${linearAgentActivitySessionId}`);
|
|
1376
|
+
}
|
|
1377
|
+
else {
|
|
1378
|
+
console.error(`[AgentSessionManager] Failed to post compacting status:`, result);
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
else if (message.status === null) {
|
|
1382
|
+
// Clear the status - post a non-ephemeral thought to replace the ephemeral one
|
|
1383
|
+
const result = await this.linearClient.createAgentActivity({
|
|
1384
|
+
agentSessionId: session.linearAgentActivitySessionId,
|
|
1385
|
+
content: {
|
|
1386
|
+
type: "thought",
|
|
1387
|
+
body: "Conversation history compacted",
|
|
1388
|
+
},
|
|
1389
|
+
ephemeral: false,
|
|
1390
|
+
});
|
|
1391
|
+
if (result.success) {
|
|
1392
|
+
// Clean up the stored activity ID
|
|
1393
|
+
this.activeStatusActivitiesBySession.delete(linearAgentActivitySessionId);
|
|
1394
|
+
console.log(`[AgentSessionManager] Posted non-ephemeral status clear for session ${linearAgentActivitySessionId}`);
|
|
1395
|
+
}
|
|
1396
|
+
else {
|
|
1397
|
+
console.error(`[AgentSessionManager] Failed to post status clear:`, result);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
catch (error) {
|
|
1402
|
+
console.error(`[AgentSessionManager] Error handling status message:`, error);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1034
1405
|
}
|
|
1035
1406
|
//# sourceMappingURL=AgentSessionManager.js.map
|