@myagentroam/node 0.9.158 → 0.9.160

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/connector.js CHANGED
@@ -756,6 +756,7 @@ export class NodeConnector {
756
756
  mcps: (workspaceId) => this.database?.effectiveMcpInstallations(workspaceId) ?? [],
757
757
  retainEnvironment: (environment) => this.gitExecution().retain(environment),
758
758
  goalCurrent: (input) => input.goal === undefined || this.goalGenerationCurrent(input.sessionId, input.goal),
759
+ goalActive: (sessionId) => this.goalRuntime.get(sessionId)?.status === 'active',
759
760
  afterExecutionStarted: async (input) => {
760
761
  if (input.goal === undefined)
761
762
  return;
@@ -22,6 +22,8 @@ export class NodeRuntimeState {
22
22
  retainedExecutionTurns = new Map();
23
23
  runSequences = new Map();
24
24
  turns = new Map();
25
+ /** New Sessions retain their full history until the bounded Runtime window drops a Turn. */
26
+ completeHistorySessions = new Set();
25
27
  approvals = new Map();
26
28
  /** A Session owns at most one running turn; Workspace sessions may run concurrently. */
27
29
  leases = new Map();
@@ -84,6 +86,8 @@ export class NodeRuntimeState {
84
86
  createdAt: input.createdAt ?? now
85
87
  };
86
88
  this.sessions.set(value.id, value);
89
+ if (input.externalSessionId === undefined)
90
+ this.completeHistorySessions.add(value.id);
87
91
  return value;
88
92
  }
89
93
  /** Internal envelope compatibility for a Run already accepted in this process. */
@@ -114,6 +118,8 @@ export class NodeRuntimeState {
114
118
  createdAt: now
115
119
  };
116
120
  this.sessions.set(session.id, session);
121
+ if (input.externalSessionId === undefined)
122
+ this.completeHistorySessions.add(session.id);
117
123
  }
118
124
  const existing = this.getRun(input.runId);
119
125
  if (existing !== undefined)
@@ -200,6 +206,8 @@ export class NodeRuntimeState {
200
206
  const paused = this.pausedQueues.has(id);
201
207
  this.sessions.delete(id);
202
208
  this.sessions.set(nativeSessionId, next);
209
+ if (this.completeHistorySessions.delete(id))
210
+ this.completeHistorySessions.add(nativeSessionId);
203
211
  this.promotedSessionAliases.set(id, nativeSessionId);
204
212
  for (const [alias, target] of this.promotedSessionAliases)
205
213
  if (target === id)
@@ -749,6 +757,7 @@ export class NodeRuntimeState {
749
757
  const slice = all.slice(start, end);
750
758
  return {
751
759
  turns: slice,
760
+ historyComplete: this.completeHistorySessions.has(input.sessionId),
752
761
  nextCursor: start > 0 ? encodeCursor(input.sessionId, start) : null
753
762
  };
754
763
  }
@@ -908,6 +917,8 @@ export class NodeRuntimeState {
908
917
  const retainedCompleted = new Set(completed.slice(-NodeRuntimeState.MAX_COMPLETED_TURNS_PER_SESSION).map((turn) => turn.id));
909
918
  const retainedTurns = turns.filter((turn) => !terminalTurn(turn.status) || retainedCompleted.has(turn.id));
910
919
  const retainedTurnIds = new Set(retainedTurns.map((turn) => turn.id));
920
+ if (retainedTurns.length < (this.turns.get(run.sessionId)?.length ?? 0))
921
+ this.completeHistorySessions.delete(run.sessionId);
911
922
  this.turns.set(run.sessionId, retainedTurns);
912
923
  for (const [executionId, execution] of this.executions) {
913
924
  if (execution.runId !== runId)
@@ -947,6 +958,7 @@ export class NodeRuntimeState {
947
958
  .filter((execution) => runIds.has(execution.runId))
948
959
  .map((execution) => execution.id));
949
960
  this.sessions.delete(sessionId);
961
+ this.completeHistorySessions.delete(sessionId);
950
962
  this.removePromotedSessionAliases(sessionId);
951
963
  this.turns.delete(sessionId);
952
964
  this.pruneRetainedExecutionTurns(sessionId, new Set());
@@ -998,6 +1010,7 @@ export class NodeRuntimeState {
998
1010
  if (this.sessionQueue(sessionId).itemIds.length > 0)
999
1011
  throw new Error('SESSION_QUEUE_NOT_EMPTY');
1000
1012
  this.turns.delete(sessionId);
1013
+ this.completeHistorySessions.delete(sessionId);
1001
1014
  this.pruneRetainedExecutionTurns(sessionId, new Set());
1002
1015
  for (const key of this.failedMessageSubmissions.keys())
1003
1016
  if (key.startsWith(`${sessionId}\u0000`))
@@ -1017,6 +1030,7 @@ export class NodeRuntimeState {
1017
1030
  const queueItemIds = new Set([...sessionIds].flatMap((sessionId) => this.queuedItems.get(sessionId) ?? []));
1018
1031
  for (const sessionId of sessionIds) {
1019
1032
  this.sessions.delete(sessionId);
1033
+ this.completeHistorySessions.delete(sessionId);
1020
1034
  this.removePromotedSessionAliases(sessionId);
1021
1035
  this.turns.delete(sessionId);
1022
1036
  this.pruneRetainedExecutionTurns(sessionId, new Set());
@@ -7,6 +7,7 @@ export class ContinuousRunCoordinator {
7
7
  dispatchedExecutions = new Set();
8
8
  startedExecutions = new Set();
9
9
  scheduledSessions = new Map();
10
+ immediateQueueItems = new Set();
10
11
  constructor(options) {
11
12
  this.options = options;
12
13
  }
@@ -106,10 +107,13 @@ export class ContinuousRunCoordinator {
106
107
  if (startsAcceptedRun || !input.queueBefore.paused || input.intent !== 'QUEUE')
107
108
  this.options.runtime.resumeSessionQueue(sessionId);
108
109
  if (input.activeRunId !== undefined && active?.id === input.activeRunId) {
110
+ if (item !== undefined)
111
+ this.immediateQueueItems.add(item.id);
109
112
  if (executionEnded) {
110
113
  if (item !== undefined)
111
114
  this.options.runtime.prioritizeQueueItem(item.id);
112
- this.schedule(sessionId);
115
+ this.publish(sessionId);
116
+ this.scheduleImmediate(sessionId);
113
117
  return 'RESTARTING';
114
118
  }
115
119
  if (this.options.runtime.currentExecutionId(active.id) === undefined &&
@@ -126,6 +130,13 @@ export class ContinuousRunCoordinator {
126
130
  this.schedule(sessionId);
127
131
  return 'STARTED';
128
132
  }
133
+ if (item !== undefined &&
134
+ prepared?.goal === undefined &&
135
+ this.options.goalActive?.(sessionId)) {
136
+ if (this.options.runtime.sessionQueue(sessionId).version !== queueVersionBeforeSettle)
137
+ this.publish(sessionId);
138
+ return 'QUEUED';
139
+ }
129
140
  if (active === undefined && item !== undefined) {
130
141
  if (input.queueBefore.paused && input.intent === 'SEND')
131
142
  this.options.runtime.prioritizeQueueItem(item.id);
@@ -133,10 +144,12 @@ export class ContinuousRunCoordinator {
133
144
  return 'STARTED';
134
145
  }
135
146
  if (executionEnded && item !== undefined) {
136
- if (input.intent === 'SEND')
147
+ if (input.queueBefore.paused && input.intent === 'SEND') {
137
148
  this.options.runtime.prioritizeQueueItem(item.id);
149
+ this.publish(sessionId);
150
+ }
138
151
  this.schedule(sessionId);
139
- return 'STARTED';
152
+ return this.nextQueueItem(sessionId) === item.id ? 'STARTED' : 'QUEUED';
140
153
  }
141
154
  if (this.options.runtime.sessionQueue(sessionId).version !== queueVersionBeforeSettle)
142
155
  this.publish(sessionId);
@@ -144,11 +157,18 @@ export class ContinuousRunCoordinator {
144
157
  }
145
158
  executeQueueItem(itemId) {
146
159
  const item = this.requirePreparedItem(itemId);
160
+ this.immediateQueueItems.add(item.id);
147
161
  this.options.runtime.resumeSessionQueue(item.sessionId);
148
162
  this.options.runtime.prioritizeQueueItem(item.id);
149
163
  const active = this.options.runtime.activeSessionRun(item.sessionId);
150
164
  if (active !== undefined) {
151
- this.replace(item.id, active.id, false);
165
+ if (this.options.runtime.currentExecutionId(active.id) !== undefined)
166
+ this.replace(item.id, active.id, false);
167
+ else {
168
+ this.publish(item.sessionId);
169
+ if (this.isMessageRun(active))
170
+ this.scheduleImmediate(item.sessionId);
171
+ }
152
172
  return { run: active, delivery: 'RESTARTING' };
153
173
  }
154
174
  this.startIdleQueue(item.sessionId);
@@ -222,6 +242,13 @@ export class ContinuousRunCoordinator {
222
242
  this.scheduledSessions.set(sessionId, timer);
223
243
  timer.unref();
224
244
  }
245
+ scheduleImmediate(sessionId) {
246
+ const timer = this.scheduledSessions.get(sessionId);
247
+ if (timer !== undefined)
248
+ clearTimeout(timer);
249
+ this.scheduledSessions.delete(sessionId);
250
+ this.schedule(sessionId);
251
+ }
225
252
  async dispatch(sessionId) {
226
253
  const active = this.options.runtime.activeSessionRun(sessionId);
227
254
  if (active === undefined)
@@ -233,7 +260,7 @@ export class ContinuousRunCoordinator {
233
260
  ? this.preparedInputs.get(active.id)
234
261
  : this.preparedInputs.get(executionId);
235
262
  if (executionId === undefined && pending === undefined) {
236
- const itemId = this.options.runtime.sessionQueue(sessionId).itemIds[0];
263
+ const itemId = this.nextQueueItem(sessionId);
237
264
  if (itemId === undefined)
238
265
  return;
239
266
  pending = this.preparedInputs.get(itemId);
@@ -247,10 +274,12 @@ export class ContinuousRunCoordinator {
247
274
  this.schedule(sessionId);
248
275
  return;
249
276
  }
277
+ this.prioritizeNextQueueItem(sessionId, itemId);
250
278
  if (this.options.runtime.claimNextQueueItem(sessionId, withNonImageAttachmentPrompt(item.content, pending.attachmentPaths)) === undefined)
251
279
  return;
252
280
  const execution = this.options.runtime.createExecution(active.id);
253
281
  executionId = execution.id;
282
+ this.immediateQueueItems.delete(itemId);
254
283
  this.preparedInputs.delete(itemId);
255
284
  this.moveEnvironmentLease(itemId, execution.id);
256
285
  this.preparedInputs.set(execution.id, { ...pending, runId: execution.id });
@@ -369,6 +398,7 @@ export class ContinuousRunCoordinator {
369
398
  }
370
399
  }
371
400
  remove(id) {
401
+ this.immediateQueueItems.delete(id);
372
402
  this.environmentLeases.get(id)?.();
373
403
  this.environmentLeases.delete(id);
374
404
  this.preparedInputs.delete(id);
@@ -408,6 +438,7 @@ export class ContinuousRunCoordinator {
408
438
  this.preparedInputs.clear();
409
439
  this.dispatchedExecutions.clear();
410
440
  this.startedExecutions.clear();
441
+ this.immediateQueueItems.clear();
411
442
  for (const timer of this.scheduledSessions.values())
412
443
  clearTimeout(timer);
413
444
  this.scheduledSessions.clear();
@@ -417,8 +448,7 @@ export class ContinuousRunCoordinator {
417
448
  this.schedule(sessionId);
418
449
  return;
419
450
  }
420
- const queue = this.options.runtime.sessionQueue(sessionId);
421
- const itemId = queue.paused ? undefined : queue.itemIds[0];
451
+ const itemId = this.nextQueueItem(sessionId);
422
452
  if (itemId === undefined)
423
453
  return;
424
454
  const pending = this.preparedInputs.get(itemId);
@@ -432,13 +462,30 @@ export class ContinuousRunCoordinator {
432
462
  this.startIdleQueue(sessionId);
433
463
  return;
434
464
  }
465
+ this.prioritizeNextQueueItem(sessionId, itemId);
435
466
  const { run, turn } = this.options.runtime.startRunFromQueueItem(itemId, withNonImageAttachmentPrompt(item.content, pending.attachmentPaths));
467
+ this.immediateQueueItems.delete(itemId);
436
468
  this.preparedInputs.delete(itemId);
437
469
  this.preparedInputs.set(run.id, { ...pending, runId: run.id });
438
470
  this.options.emitQueue(run.workspaceId, sessionId);
439
471
  this.options.emitConversation(turn);
440
472
  this.schedule(sessionId);
441
473
  }
474
+ nextQueueItem(sessionId) {
475
+ const queue = this.options.runtime.sessionQueue(sessionId);
476
+ if (queue.paused)
477
+ return undefined;
478
+ const immediate = queue.itemIds.find((id) => this.immediateQueueItems.has(id));
479
+ if (immediate !== undefined)
480
+ return immediate;
481
+ if (this.options.goalActive?.(sessionId))
482
+ return queue.itemIds.find((id) => this.preparedInputs.get(id)?.goal !== undefined);
483
+ return queue.itemIds[0];
484
+ }
485
+ prioritizeNextQueueItem(sessionId, itemId) {
486
+ if (this.options.runtime.sessionQueue(sessionId).itemIds[0] !== itemId)
487
+ this.options.runtime.prioritizeQueueItem(itemId);
488
+ }
442
489
  requirePreparedItem(itemId) {
443
490
  const item = this.options.runtime.getQueueItem(itemId);
444
491
  if (item === undefined)
@@ -373,7 +373,7 @@ export class ConversationHistoryService {
373
373
  beforeAt,
374
374
  cursor: runtimePage.nextCursor
375
375
  })
376
- : session.externalSessionId === null
376
+ : session.externalSessionId === null || runtimePage.historyComplete === true
377
377
  ? null
378
378
  : encodeActiveHistoryCursor({
379
379
  sessionId: session.id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/node",
3
- "version": "0.9.158",
3
+ "version": "0.9.160",
4
4
  "description": "MyAgentRoam Node runtime CLI.",
5
5
  "license": "Apache-2.0 AND GPL-2.0-or-later",
6
6
  "type": "module",
@@ -36,10 +36,10 @@
36
36
  "playwright": "1.62.1",
37
37
  "ws": "^8.21.3",
38
38
  "zod": "4.4.3",
39
+ "@myagentroam/agent": "0.9.160",
39
40
  "@myagentroam/code-navigation": "0.9.129",
40
- "@myagentroam/agent": "0.9.158",
41
- "@myagentroam/protocol": "0.9.158",
42
- "@myagentroam/marctl": "0.9.120"
41
+ "@myagentroam/marctl": "0.9.120",
42
+ "@myagentroam/protocol": "0.9.160"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/ws": "^8.18.1"