@myagentroam/node 0.9.150 → 0.9.152
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.
|
@@ -219,7 +219,7 @@ export class MarAgentManagedRunController {
|
|
|
219
219
|
if (!execution)
|
|
220
220
|
return false;
|
|
221
221
|
execution.cancel();
|
|
222
|
-
this.host.emit(runId, 'run.cancelling', { intent }
|
|
222
|
+
this.host.emit(runId, 'run.cancelling', { intent });
|
|
223
223
|
return true;
|
|
224
224
|
}
|
|
225
225
|
respondUserInput(runId, requestId, answers) {
|
|
@@ -236,6 +236,20 @@ export class MarAgentManagedRunController {
|
|
|
236
236
|
return true;
|
|
237
237
|
}
|
|
238
238
|
async run(input) {
|
|
239
|
+
const controller = new AbortController();
|
|
240
|
+
const titleController = new AbortController();
|
|
241
|
+
let cancelExecution;
|
|
242
|
+
// Own cancellation before any asynchronous preparation, not only after SDK admission.
|
|
243
|
+
this.#executions.set(input.runId, {
|
|
244
|
+
cancel: () => {
|
|
245
|
+
if (controller.signal.aborted)
|
|
246
|
+
return;
|
|
247
|
+
controller.abort();
|
|
248
|
+
titleController.abort();
|
|
249
|
+
cancelExecution?.();
|
|
250
|
+
},
|
|
251
|
+
cancelTitle: () => titleController.abort()
|
|
252
|
+
});
|
|
239
253
|
this.host.active.add(input.runId);
|
|
240
254
|
this.host.adopt({
|
|
241
255
|
runId: input.runId,
|
|
@@ -253,9 +267,10 @@ export class MarAgentManagedRunController {
|
|
|
253
267
|
let executionMcpBinding;
|
|
254
268
|
let computerUseBinding;
|
|
255
269
|
let executionModels = [];
|
|
256
|
-
const titleController = new AbortController();
|
|
257
270
|
let titleTask;
|
|
271
|
+
let cancelledDuringPreparation = false;
|
|
258
272
|
try {
|
|
273
|
+
controller.signal.throwIfAborted();
|
|
259
274
|
const sessionKey = input.externalSessionId ?? input.sessionId;
|
|
260
275
|
// Reserve both identities while opening so a concurrent release can await the same runtime.
|
|
261
276
|
const acquisitionKeys = [...new Set([sessionKey, input.sessionId])];
|
|
@@ -273,6 +288,7 @@ export class MarAgentManagedRunController {
|
|
|
273
288
|
if (this.#runtimeAcquisitions.get(key) === acquisition)
|
|
274
289
|
this.#runtimeAcquisitions.delete(key);
|
|
275
290
|
}
|
|
291
|
+
controller.signal.throwIfAborted();
|
|
276
292
|
if (this.#disposed ||
|
|
277
293
|
this.#sessionReleases.has(sessionKey) ||
|
|
278
294
|
this.#sessionReleases.has(input.sessionId) ||
|
|
@@ -284,6 +300,7 @@ export class MarAgentManagedRunController {
|
|
|
284
300
|
throw new Error('MAR_AGENT_SESSION_RUNTIME_ACTIVE');
|
|
285
301
|
runtime.activeRunId = input.runId;
|
|
286
302
|
await runtime.mcpLease.pool.refreshForExecution();
|
|
303
|
+
controller.signal.throwIfAborted();
|
|
287
304
|
const executionMcpServers = input.mcpServers
|
|
288
305
|
.filter(isExecutionScopedMcp)
|
|
289
306
|
.map((server) => ({ ...server, lifecycle: 'EXECUTION' }));
|
|
@@ -294,6 +311,7 @@ export class MarAgentManagedRunController {
|
|
|
294
311
|
enabled: input.computerUseEnabled === true,
|
|
295
312
|
modelSupportsImages: input.model.inputCapabilities.includes('IMAGE')
|
|
296
313
|
});
|
|
314
|
+
controller.signal.throwIfAborted();
|
|
297
315
|
if (this.#disposed ||
|
|
298
316
|
this.#sessionReleases.has(sessionKey) ||
|
|
299
317
|
this.#sessionReleases.has(input.sessionId) ||
|
|
@@ -309,6 +327,7 @@ export class MarAgentManagedRunController {
|
|
|
309
327
|
authorizationScope: runtime.session.id
|
|
310
328
|
});
|
|
311
329
|
}
|
|
330
|
+
controller.signal.throwIfAborted();
|
|
312
331
|
const userTools = executionMcpLease?.pool.definitions() ?? [];
|
|
313
332
|
const nodeTools = computerUseBinding?.tools ?? [];
|
|
314
333
|
if (userTools.some((tool) => tool.name.startsWith('mcp__computer__')))
|
|
@@ -378,6 +397,7 @@ export class MarAgentManagedRunController {
|
|
|
378
397
|
const metadata = input.mode === 'compact' || !runtime.automaticTitleEnabled
|
|
379
398
|
? undefined
|
|
380
399
|
: await runtime.agent.getSession(session.id).catch(() => undefined);
|
|
400
|
+
controller.signal.throwIfAborted();
|
|
381
401
|
const handle = input.mode === 'plan'
|
|
382
402
|
? session.plan({
|
|
383
403
|
...runInput
|
|
@@ -385,10 +405,7 @@ export class MarAgentManagedRunController {
|
|
|
385
405
|
: input.mode === 'compact'
|
|
386
406
|
? session.compact(runInput)
|
|
387
407
|
: session.run(runInput);
|
|
388
|
-
|
|
389
|
-
cancel: () => handle.cancel(),
|
|
390
|
-
cancelTitle: () => titleController.abort()
|
|
391
|
-
});
|
|
408
|
+
cancelExecution = () => handle.cancel();
|
|
392
409
|
this.host.emit(input.runId, 'run.running', {}, 'RUNNING');
|
|
393
410
|
for await (const event of handle) {
|
|
394
411
|
if (event.type === 'execution.started' && metadata?.automaticTitlePending && !titleTask) {
|
|
@@ -430,20 +447,26 @@ export class MarAgentManagedRunController {
|
|
|
430
447
|
}, status);
|
|
431
448
|
}
|
|
432
449
|
catch (error) {
|
|
433
|
-
if (
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
450
|
+
if (controller.signal.aborted && cancelExecution === undefined) {
|
|
451
|
+
// Keep the Run owned until preparation and its resources actually settle.
|
|
452
|
+
cancelledDuringPreparation = true;
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
if (runtime !== undefined)
|
|
456
|
+
this.#prepareRuntimeForTerminal(input.runId, runtime);
|
|
457
|
+
const projected = runnerErrorProjection(error, 'MAR_AGENT_RUN_FAILED');
|
|
458
|
+
this.host.emitItem(input.runId, {
|
|
459
|
+
itemId: boundedConversationItemId('mar-agent-error', input.runId),
|
|
460
|
+
kind: 'error',
|
|
461
|
+
status: 'FAILED',
|
|
462
|
+
payload: {
|
|
463
|
+
...projected,
|
|
464
|
+
recoverable: true,
|
|
465
|
+
retryAfterMs: null
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
this.host.emit(input.runId, 'run.failed', projected, 'FAILED');
|
|
469
|
+
}
|
|
447
470
|
}
|
|
448
471
|
finally {
|
|
449
472
|
titleController.abort();
|
|
@@ -452,14 +475,16 @@ export class MarAgentManagedRunController {
|
|
|
452
475
|
delete runtime.automaticTitleTask;
|
|
453
476
|
this.clearInteractions(input.runId);
|
|
454
477
|
this.#normalizers.delete(input.runId);
|
|
455
|
-
this.host.active.delete(input.runId);
|
|
456
|
-
this.#executions.delete(input.runId);
|
|
457
478
|
await closeImageCredentialProviders(executionModels);
|
|
458
479
|
await computerUseBinding?.close().catch(() => undefined);
|
|
459
480
|
runtime?.host.unbindExecutionMcp(executionMcpBinding);
|
|
460
481
|
await executionMcpLease?.release().catch(() => undefined);
|
|
461
482
|
if (runtime !== undefined)
|
|
462
483
|
await this.#finishRuntimeExecution(input.runId, runtime).catch(() => undefined);
|
|
484
|
+
this.host.active.delete(input.runId);
|
|
485
|
+
this.#executions.delete(input.runId);
|
|
486
|
+
if (cancelledDuringPreparation)
|
|
487
|
+
this.host.emit(input.runId, 'run.cancelled', { status: 'CANCELLED' }, 'CANCELLED');
|
|
463
488
|
}
|
|
464
489
|
}
|
|
465
490
|
#prepareRuntimeForTerminal(runId, runtime) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const MAX_INITIAL_TURN_PAGE_SIZE = 30;
|
|
2
2
|
function conversationSegmentPrefix(turn) {
|
|
3
3
|
const user = turn.items.find((item) => item.kind === 'user_message');
|
|
4
4
|
const payload = typeof user?.payload === 'object' && user.payload !== null && !Array.isArray(user.payload)
|
|
@@ -89,14 +89,16 @@ export class ConversationSegmentService {
|
|
|
89
89
|
const boundary = input.cursor === undefined ? undefined : decodeCursor(input.cursor, session.id);
|
|
90
90
|
const collected = [];
|
|
91
91
|
const visited = new Set();
|
|
92
|
-
let turnCursor;
|
|
92
|
+
let turnCursor = boundary?.turnCursor ?? undefined;
|
|
93
|
+
let oldestTurnCursor = null;
|
|
93
94
|
let locatingBoundary = boundary !== undefined;
|
|
94
95
|
let hasOlder = false;
|
|
95
96
|
let metadata;
|
|
96
97
|
while (collected.length < limit) {
|
|
97
98
|
const page = await this.readTurns(session, {
|
|
98
99
|
...(turnCursor === undefined ? {} : { cursor: turnCursor }),
|
|
99
|
-
|
|
100
|
+
// Preserve the bounded live window without crossing its deferred history boundary.
|
|
101
|
+
limit: boundary === undefined ? Math.min(limit, MAX_INITIAL_TURN_PAGE_SIZE) : 1
|
|
100
102
|
});
|
|
101
103
|
metadata ??= {
|
|
102
104
|
snapshotSequence: page.snapshotSequence,
|
|
@@ -123,6 +125,7 @@ export class ConversationSegmentService {
|
|
|
123
125
|
const take = eligible.slice(-remaining);
|
|
124
126
|
hasOlder = eligible.length > take.length || page.nextCursor !== null;
|
|
125
127
|
collected.unshift(...take);
|
|
128
|
+
oldestTurnCursor = turnCursor ?? null;
|
|
126
129
|
}
|
|
127
130
|
if (boundary === undefined && page.deferredOlderHistory === true)
|
|
128
131
|
break;
|
|
@@ -140,7 +143,8 @@ export class ConversationSegmentService {
|
|
|
140
143
|
: encodeCursor({
|
|
141
144
|
version: 1,
|
|
142
145
|
sessionId: session.id,
|
|
143
|
-
beforeSegmentId: collected[0].id
|
|
146
|
+
beforeSegmentId: collected[0].id,
|
|
147
|
+
turnCursor: oldestTurnCursor
|
|
144
148
|
});
|
|
145
149
|
return {
|
|
146
150
|
...(metadata ?? {
|
|
@@ -164,7 +168,10 @@ function decodeCursor(value, sessionId) {
|
|
|
164
168
|
if (decoded.version !== 1 ||
|
|
165
169
|
decoded.sessionId !== sessionId ||
|
|
166
170
|
typeof decoded.beforeSegmentId !== 'string' ||
|
|
167
|
-
decoded.beforeSegmentId.length === 0
|
|
171
|
+
decoded.beforeSegmentId.length === 0 ||
|
|
172
|
+
(decoded.turnCursor !== undefined &&
|
|
173
|
+
decoded.turnCursor !== null &&
|
|
174
|
+
(typeof decoded.turnCursor !== 'string' || decoded.turnCursor.length === 0)))
|
|
168
175
|
throw new Error('EVENT_CURSOR_INVALID');
|
|
169
176
|
return decoded;
|
|
170
177
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.152",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"ws": "^8.21.3",
|
|
36
36
|
"zod": "4.4.3",
|
|
37
37
|
"@myagentroam/marctl": "0.9.120",
|
|
38
|
-
"@myagentroam/
|
|
38
|
+
"@myagentroam/protocol": "0.9.152",
|
|
39
39
|
"@myagentroam/code-navigation": "0.9.129",
|
|
40
|
-
"@myagentroam/
|
|
40
|
+
"@myagentroam/agent": "0.9.152"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/ws": "^8.18.1"
|