@myagentroam/node 0.11.45 → 0.11.47

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 (37) hide show
  1. package/dist/connector.js +4 -4
  2. package/dist/database.js +7 -5
  3. package/dist/marctl-guidance.js +2 -2
  4. package/dist/migrations/v023.js +25 -0
  5. package/dist/runner/abstract-runner.js +1 -1
  6. package/dist/runner/claude/managed-run-controller.js +1 -1
  7. package/dist/runner/claude-code-runner.js +1 -1
  8. package/dist/runner/codex/managed-run-controller.js +1 -1
  9. package/dist/runner/codex-runner.js +10 -5
  10. package/dist/runner/mar-agent/agent-network-extension.js +54 -14
  11. package/dist/runner/mar-agent/conversation-normalizer.js +43 -3
  12. package/dist/runner/mar-agent/history-projection.js +1 -1
  13. package/dist/runner/mar-agent/hosted-conversation-runtime.js +1 -1
  14. package/dist/runner/mar-agent/managed-run-controller.js +2 -2
  15. package/dist/runner/mar-agent-runner.js +5 -5
  16. package/dist/runner/opencode/managed-run-controller.js +2 -2
  17. package/dist/runner/opencode-runner.js +5 -5
  18. package/dist/runner-profiles.js +1 -1
  19. package/dist/runtime-state.js +7 -7
  20. package/dist/service/agent-network-bindings.js +8 -7
  21. package/dist/service/agent-network-invoke.js +9 -9
  22. package/dist/service/agent-network-service.js +12 -7
  23. package/dist/service/continuous-run-coordinator.js +1 -1
  24. package/dist/service/external-session-resume-service.js +1 -1
  25. package/dist/service/goal-continuation-coordinator.js +3 -3
  26. package/dist/service/native-session-watch-service.js +6 -3
  27. package/dist/service/planned-restart-handoff.js +24 -5
  28. package/dist/service/restart-session-restorer.js +2 -2
  29. package/dist/service/session-recent-activity.js +1 -1
  30. package/dist/session/native-session-projection-service.js +39 -30
  31. package/dist/session/session-catalog-service.js +116 -90
  32. package/dist/session/session-command-service.js +1 -0
  33. package/dist/session/session-context-service.js +1 -1
  34. package/dist/session/session-lifecycle-service.js +12 -10
  35. package/dist/session/session-message-service.js +4 -3
  36. package/dist/workspace/workspace-session-service.js +1 -1
  37. package/package.json +4 -4
@@ -187,7 +187,7 @@ export class SessionCatalogService {
187
187
  nativeControl: 'EXTERNAL',
188
188
  channelToken: null,
189
189
  cwd: workspace.path,
190
- model: persisted.metadata.model,
190
+ modelId: persisted.metadata.modelId,
191
191
  effort: persisted.metadata.effort,
192
192
  access: persisted.metadata.access,
193
193
  customTitle: persisted.metadata.customTitle,
@@ -283,7 +283,7 @@ export class SessionCatalogService {
283
283
  cwd,
284
284
  nativeControl: 'MAR_MANAGED',
285
285
  ...(nativeId === null ? {} : { externalSessionId: nativeId }),
286
- ...(source.model === null ? {} : { model: source.model }),
286
+ ...(source.modelId === null ? {} : { modelId: source.modelId }),
287
287
  ...(source.effort === null ? {} : { effort: source.effort }),
288
288
  ...(source.access === null ? {} : { access: source.access }),
289
289
  title
@@ -322,7 +322,7 @@ export class SessionCatalogService {
322
322
  this.options.invalidateWorkspaceSessions(session.workspaceId);
323
323
  }
324
324
  }
325
- async removeTree(root) {
325
+ async removeTree(root, cleanup) {
326
326
  if (root.externalSessionId === null)
327
327
  throw new Error('NATIVE_TRANSCRIPT_UNAVAILABLE');
328
328
  const database = this.options.database();
@@ -340,13 +340,20 @@ export class SessionCatalogService {
340
340
  const ids = [root.externalSessionId];
341
341
  const seen = new Set(ids);
342
342
  const parents = new Map();
343
+ const settle = (session, deleted) => {
344
+ if (cleanup === undefined)
345
+ return;
346
+ database.deleteSessionRecord(session.id);
347
+ this.options.forget(session, this.options.nativeIds(session));
348
+ cleanup.settled(session, deleted);
349
+ };
343
350
  const releases = [];
344
351
  const locked = new Set();
345
352
  const lock = (id) => {
346
353
  const actual = this.options.runtime.getAgentSession(id)?.id ?? id;
347
354
  if (locked.has(actual))
348
355
  return;
349
- releases.push(this.options.runtime.beginSessionHistoryMutation(actual, { allowQueued: true }));
356
+ releases.push(this.options.runtime.beginSessionHistoryMutation(actual, cleanup !== undefined && actual === root.id ? undefined : { allowQueued: true }));
350
357
  locked.add(actual);
351
358
  };
352
359
  try {
@@ -355,6 +362,9 @@ export class SessionCatalogService {
355
362
  const parent = ids[index];
356
363
  const children = [
357
364
  ...database.listChildSessionRecords(root.workspaceId, parent).map((record) => record.id),
365
+ ...(cleanup?.children.get(parent) ?? [])
366
+ .filter((session) => cleanup?.candidates.has(session.id))
367
+ .map((session) => session.externalSessionId ?? session.id),
358
368
  ...(liveChildren.get(parent) ?? [])
359
369
  ];
360
370
  for (const child of children) {
@@ -371,35 +381,64 @@ export class SessionCatalogService {
371
381
  }
372
382
  const sessions = [];
373
383
  for (const id of ids) {
374
- const session = this.options.runtime.getAgentSession(id) ??
384
+ const session = cleanup?.candidates.get(id) ??
385
+ this.options.runtime.getAgentSession(id) ??
375
386
  (await this.options.projection.resolve(id, true));
376
387
  if (session === undefined || session.workspaceId !== root.workspaceId)
377
388
  throw new Error('SESSION_NOT_FOUND');
378
389
  sessions.push(session);
379
390
  }
380
391
  // Validate every member before performing any irreversible native deletion.
381
- for (const session of sessions)
382
- await this.assertRemovable(session);
383
- const batches = new Map();
392
+ for (const session of sessions) {
393
+ const missing = cleanup !== undefined && session.externalDiscovered === false;
394
+ if (missing && !this.options.runnerAvailable(session.runner))
395
+ throw new Error('NATIVE_TRANSCRIPT_UNAVAILABLE');
396
+ await this.assertRemovable(session, cleanup?.budget, missing);
397
+ }
398
+ if (cleanup !== undefined && this.cleanupRootProtected(root, cleanup.cutoff)) {
399
+ throw new Error('SESSION_WATCHING');
400
+ }
401
+ let batch = [];
402
+ const flushBatch = async () => {
403
+ if (batch.length === 0)
404
+ return;
405
+ cleanup?.budget.check();
406
+ await this.options.runners.require(batch[0].runner).removeNativeMembers(batch);
407
+ for (const session of batch)
408
+ settle(session, true);
409
+ batch = [];
410
+ };
384
411
  for (const session of [...sessions].reverse()) {
412
+ if (cleanup !== undefined &&
413
+ (session.externalSessionId === null || session.externalDiscovered === false)) {
414
+ await flushBatch();
415
+ cleanup.budget.check();
416
+ settle(session, true);
417
+ continue;
418
+ }
385
419
  if (session.externalSessionId === null)
386
420
  continue;
387
421
  const runner = this.options.runners.require(session.runner);
388
422
  if (runner.supportsNativeBatchRemoval?.() === true) {
389
- const members = batches.get(session.runner) ?? [];
390
- members.push(session);
391
- batches.set(session.runner, members);
423
+ if (batch.length > 0 && batch[0].runner !== session.runner)
424
+ await flushBatch();
425
+ batch.push(session);
426
+ }
427
+ else {
428
+ // Preserve descendant-first order across batch and non-batch native owners.
429
+ await flushBatch();
430
+ cleanup?.budget.check();
431
+ const deleted = await this.removeNativeHistories(session, this.options.nativeIds(session));
432
+ settle(session, deleted);
392
433
  }
393
- else
394
- await this.removeNativeHistories(session, this.options.nativeIds(session));
395
434
  }
396
- for (const [runner, members] of batches)
397
- await this.options.runners.require(runner).removeNativeMembers(members);
398
- // Preserve every relationship if any native owner fails, so retries cannot
399
- // lose sight of descendants whose native cleanup was already attempted.
400
- for (const session of sessions.reverse()) {
401
- this.options.database().deleteSessionRecord(session.id);
402
- this.options.forget(session, this.options.nativeIds(session));
435
+ await flushBatch();
436
+ // Manual deletion preserves all relationships if any native owner fails.
437
+ if (cleanup === undefined) {
438
+ for (const session of sessions.reverse()) {
439
+ this.options.database().deleteSessionRecord(session.id);
440
+ this.options.forget(session, this.options.nativeIds(session));
441
+ }
403
442
  }
404
443
  }
405
444
  finally {
@@ -443,6 +482,7 @@ export class SessionCatalogService {
443
482
  let deleted = 0;
444
483
  let skipped = 0;
445
484
  let failed = 0;
485
+ const outcomes = new Map();
446
486
  const deletedByRunner = {};
447
487
  let candidateCount;
448
488
  let timedOut = false;
@@ -458,7 +498,14 @@ export class SessionCatalogService {
458
498
  candidates.set(session.id, session);
459
499
  }
460
500
  this.mergePersisted(candidates, workspaceId, false);
461
- const candidateParents = new Set([...candidates.values()].flatMap((candidate) => candidate.parentSessionId === null ? [] : [candidate.parentSessionId]));
501
+ const children = new Map();
502
+ for (const candidate of candidates.values()) {
503
+ if (candidate.parentSessionId == null)
504
+ continue;
505
+ const siblings = children.get(candidate.parentSessionId) ?? [];
506
+ siblings.push(candidate);
507
+ children.set(candidate.parentSessionId, siblings);
508
+ }
462
509
  candidateCount = candidates.size;
463
510
  for (const session of candidates.values()) {
464
511
  budget.check();
@@ -472,14 +519,6 @@ export class SessionCatalogService {
472
519
  session.lastActivityAt > 0 &&
473
520
  session.lastActivityAt >= cutoff) ||
474
521
  (session.pinOrder !== null && session.pinOrder !== undefined) ||
475
- (session.externalSessionId !== null &&
476
- (this.options.database().listChildSessionRecords(workspaceId, session.externalSessionId)
477
- .length > 0 ||
478
- candidateParents.has(session.externalSessionId) ||
479
- this.options.runtime
480
- .listAgentSessions()
481
- .some((child) => child.workspaceId === workspaceId &&
482
- child.parentSessionId === session.externalSessionId))) ||
483
522
  this.options.isWatching(session.id) ||
484
523
  this.options.isRecovering?.(session.id) ||
485
524
  this.options.runtime.sessionQueue(session.id).itemIds.length > 0 ||
@@ -487,24 +526,31 @@ export class SessionCatalogService {
487
526
  .listRunsForSession(session.id)
488
527
  .some((run) => !isTerminalRunStatus(run.status)) ||
489
528
  this.options.externalActivity(session.id) === 'BUSY') {
490
- skipped += 1;
529
+ outcomes.set(session.id, { session, status: 'skipped' });
491
530
  continue;
492
531
  }
493
532
  try {
494
- if ((await this.removeResolved(session, true, budget)) === 'deleted') {
495
- deleted += 1;
496
- deletedByRunner[session.runner] = (deletedByRunner[session.runner] ?? 0) + 1;
497
- }
498
- else
499
- skipped += 1;
533
+ await this.removeTree(session, {
534
+ candidates,
535
+ children,
536
+ cutoff,
537
+ budget,
538
+ settled: (member, wasDeleted) => {
539
+ candidates.delete(member.id);
540
+ outcomes.set(member.id, {
541
+ session: member,
542
+ status: wasDeleted ? 'deleted' : 'skipped'
543
+ });
544
+ }
545
+ });
500
546
  }
501
547
  catch (error) {
502
548
  if (error instanceof WorkspaceSessionCleanupDeadline)
503
549
  throw error;
504
550
  if (isCleanupSkip(error))
505
- skipped += 1;
551
+ outcomes.set(session.id, { session, status: 'skipped' });
506
552
  else {
507
- failed += 1;
553
+ outcomes.set(session.id, { session, status: 'failed' });
508
554
  nodeLog('workspace.session.cleanup.failed', {
509
555
  workspaceId,
510
556
  sessionId: session.id,
@@ -514,6 +560,7 @@ export class SessionCatalogService {
514
560
  }
515
561
  }
516
562
  }
563
+ budget.check();
517
564
  }
518
565
  catch (error) {
519
566
  if (!(error instanceof WorkspaceSessionCleanupDeadline))
@@ -525,6 +572,16 @@ export class SessionCatalogService {
525
572
  finally {
526
573
  this.options.invalidateWorkspaceSessions(workspaceId);
527
574
  }
575
+ for (const { session, status } of outcomes.values()) {
576
+ if (status === 'deleted') {
577
+ deleted += 1;
578
+ deletedByRunner[session.runner] = (deletedByRunner[session.runner] ?? 0) + 1;
579
+ }
580
+ else if (status === 'skipped')
581
+ skipped += 1;
582
+ else
583
+ failed += 1;
584
+ }
528
585
  const result = {
529
586
  deleted,
530
587
  skipped,
@@ -535,7 +592,7 @@ export class SessionCatalogService {
535
592
  timedOut: true,
536
593
  ...(candidateCount === undefined
537
594
  ? {}
538
- : { remaining: candidateCount - deleted - skipped - failed })
595
+ : { remaining: Math.max(0, candidateCount - outcomes.size) })
539
596
  }
540
597
  : {})
541
598
  };
@@ -559,15 +616,16 @@ export class SessionCatalogService {
559
616
  lastActivityAt: latestSessionActivityAt(projected.lastActivityAt, native.lastActivityAt)
560
617
  };
561
618
  }
562
- async assertRemovable(session) {
619
+ async assertRemovable(session, budget, missing = false) {
563
620
  if (this.options.isRecovering?.(session.id))
564
621
  throw new Error('SESSION_RESTART_PENDING');
565
622
  if (this.options.runtime
566
623
  .listRunsForSession(session.id)
567
624
  .some((run) => !isTerminalRunStatus(run.status)))
568
625
  throw new Error('SESSION_ACTIVE');
569
- if (session.externalSessionId !== null && session.nativeControl === 'EXTERNAL') {
570
- await this.options.refreshActivity(session);
626
+ if (!missing && session.externalSessionId !== null && session.nativeControl === 'EXTERNAL') {
627
+ const refresh = () => this.options.refreshActivity(session);
628
+ await (budget ? budget.read(refresh) : refresh());
571
629
  if (this.options.externalActivity(session.id) === 'BUSY')
572
630
  throw new Error('SESSION_ACTIVE');
573
631
  }
@@ -592,55 +650,22 @@ export class SessionCatalogService {
592
650
  }
593
651
  return deleted;
594
652
  }
595
- async removeResolved(session, requireCleanupSafety = false, budget) {
596
- if (session.externalSessionId === null)
597
- throw new Error('NATIVE_TRANSCRIPT_UNAVAILABLE');
598
- const releaseMutation = this.options.runtime.beginSessionHistoryMutation(session.id, requireCleanupSafety ? undefined : { allowQueued: true });
599
- try {
600
- if (this.options.isRecovering?.(session.id))
601
- throw new Error('SESSION_RESTART_PENDING');
602
- const missingCandidate = requireCleanupSafety && session.externalDiscovered === false;
603
- if (this.options.runtime
653
+ cleanupRootProtected(session, cutoff) {
654
+ // Pin updates and Watch admission do not share the history mutation queue.
655
+ const pinOrder = session.externalSessionId === null
656
+ ? undefined
657
+ : this.options
658
+ .database()
659
+ .getNativeSessionMetadata(session.runner, session.externalSessionId, session.workspaceId)?.pinOrder;
660
+ return ((session.externalDiscovered !== false &&
661
+ latestSessionActivityAt(session.lastActivityAt, this.options.runtime.getAgentSession(session.id)?.lastActivityAt ?? 0) >= cutoff) ||
662
+ (pinOrder !== undefined && pinOrder !== null) ||
663
+ this.options.isWatching(session.id) ||
664
+ this.options.isRecovering?.(session.id) === true ||
665
+ this.options.runtime.sessionQueue(session.id).itemIds.length > 0 ||
666
+ this.options.runtime
604
667
  .listRunsForSession(session.id)
605
- .some((run) => !isTerminalRunStatus(run.status)))
606
- throw new Error('SESSION_ACTIVE');
607
- if (session.nativeControl === 'EXTERNAL' && !missingCandidate) {
608
- const refresh = () => this.options.refreshActivity(session);
609
- await (budget ? budget.read(refresh) : refresh());
610
- if (this.options.externalActivity(session.id) === 'BUSY')
611
- throw new Error('SESSION_ACTIVE');
612
- }
613
- if (requireCleanupSafety) {
614
- if (this.options.isWatching(session.id))
615
- throw new Error('SESSION_WATCHING');
616
- if (this.options.runtime.sessionQueue(session.id).itemIds.length > 0)
617
- throw new Error('SESSION_QUEUE_NOT_EMPTY');
618
- // Pin updates do not share the cleanup mutation queue.
619
- const pinOrder = this.options
620
- .database()
621
- .getNativeSessionMetadata(session.runner, session.externalSessionId, session.workspaceId)?.pinOrder;
622
- if (pinOrder !== undefined && pinOrder !== null)
623
- return 'skipped';
624
- if (this.options.runtime
625
- .listRunsForSession(session.id)
626
- .some((run) => !isTerminalRunStatus(run.status)))
627
- throw new Error('SESSION_ACTIVE');
628
- }
629
- budget?.check();
630
- const nativeIds = this.options.nativeIds(session);
631
- if (missingCandidate) {
632
- this.options.database().deleteSessionRecord(session.id);
633
- this.options.forget(session, nativeIds);
634
- return 'deleted';
635
- }
636
- const deleted = await this.removeNativeHistories(session, nativeIds);
637
- this.options.database().deleteSessionRecord(session.id);
638
- this.options.forget(session, nativeIds);
639
- return deleted ? 'deleted' : 'skipped';
640
- }
641
- finally {
642
- releaseMutation();
643
- }
668
+ .some((run) => !isTerminalRunStatus(run.status)));
644
669
  }
645
670
  }
646
671
  export function rewindTitle(sourceTitle, existingTitles = []) {
@@ -674,6 +699,7 @@ function deduplicateNativeSessions(sessions) {
674
699
  function isCleanupSkip(error) {
675
700
  return (error instanceof Error &&
676
701
  (error.message === 'SESSION_ACTIVE' ||
702
+ error.message === 'SESSION_RESTART_PENDING' ||
677
703
  error.message === 'SESSION_NOT_FOUND' ||
678
704
  error.message === 'SESSION_QUEUE_NOT_EMPTY' ||
679
705
  error.message === 'SESSION_WATCHING' ||
@@ -31,6 +31,7 @@ export class SessionCommandService {
31
31
  }
32
32
  async sessionCommand(input) {
33
33
  if (typeof input.sessionId !== 'string' ||
34
+ Object.hasOwn(input, 'model') ||
34
35
  typeof input.commandId !== 'string' ||
35
36
  input.commandId.length === 0 ||
36
37
  typeof input.input !== 'string' ||
@@ -20,7 +20,7 @@ export class SessionContextService {
20
20
  return { context: null, pending: false };
21
21
  }
22
22
  const context = {
23
- model: usage.model ?? session.model,
23
+ model: usage.model ?? session.modelId,
24
24
  usedTokens: usage.usedTokens,
25
25
  maxTokens: usage.maxTokens,
26
26
  percentage: Math.round((usage.usedTokens / usage.maxTokens) * 1000) / 10
@@ -120,7 +120,8 @@ export class SessionLifecycleService {
120
120
  (input.externalSessionId !== undefined && typeof input.externalSessionId !== 'string') ||
121
121
  !validSessionTitle(input.title) ||
122
122
  !validSessionTitle(input.customTitle) ||
123
- !validSessionOption(input.model) ||
123
+ Object.hasOwn(input, 'model') ||
124
+ !validSessionOption(input.modelId) ||
124
125
  !validSessionEffort(input.effort) ||
125
126
  !validSessionOption(input.access))
126
127
  throw new Error('SESSION_INVALID');
@@ -172,7 +173,7 @@ export class SessionLifecycleService {
172
173
  const fallback = runner.defaultConfiguration(workspace, environment, executionContext);
173
174
  const configuration = {
174
175
  runner: runner.name,
175
- model: typeof input.model === 'string' ? input.model : (saved?.model ?? fallback.model),
176
+ modelId: typeof input.modelId === 'string' ? input.modelId : (saved?.modelId ?? fallback.modelId),
176
177
  effort: typeof input.effort === 'string' ? input.effort : (saved?.effort ?? fallback.effort),
177
178
  access: typeof input.access === 'string'
178
179
  ? input.access
@@ -183,7 +184,7 @@ export class SessionLifecycleService {
183
184
  if (runner.name === 'mar-agent' && !['auto', 'full-access'].includes(configuration.access))
184
185
  throw new Error('SESSION_INVALID');
185
186
  if (parentSessionId !== undefined)
186
- runner.assertChildModel(configuration.model, executionContext);
187
+ runner.assertChildModel(configuration.modelId, executionContext);
187
188
  const session = this.options.runtime.createAgentSession({
188
189
  ...(parentSessionId === undefined ? {} : { parentSessionId }),
189
190
  workspaceId: input.workspaceId,
@@ -192,7 +193,7 @@ export class SessionLifecycleService {
192
193
  ...(typeof input.externalSessionId === 'string'
193
194
  ? { externalSessionId: input.externalSessionId }
194
195
  : {}),
195
- model: configuration.model,
196
+ modelId: configuration.modelId,
196
197
  effort: configuration.effort,
197
198
  access: configuration.access,
198
199
  ...(typeof input.title === 'string' ? { title: input.title } : {}),
@@ -208,8 +209,9 @@ export class SessionLifecycleService {
208
209
  }
209
210
  async updateConfiguration(input) {
210
211
  if (typeof input.sessionId !== 'string' ||
211
- (input.model === undefined && input.effort === undefined && input.access === undefined) ||
212
- !validSessionOption(input.model) ||
212
+ (input.modelId === undefined && input.effort === undefined && input.access === undefined) ||
213
+ Object.hasOwn(input, 'model') ||
214
+ !validSessionOption(input.modelId) ||
213
215
  !validSessionEffort(input.effort) ||
214
216
  !validSessionOption(input.access))
215
217
  throw new Error('SESSION_INVALID');
@@ -222,13 +224,13 @@ export class SessionLifecycleService {
222
224
  input.access !== undefined &&
223
225
  !['auto', 'full-access'].includes(input.access))
224
226
  throw new Error('SESSION_INVALID');
225
- if (current.parentSessionId != null && typeof input.model === 'string') {
227
+ if (current.parentSessionId != null && typeof input.modelId === 'string') {
226
228
  const runner = this.options.runners.require(current.runner);
227
- runner.assertChildModel(input.model, runner.prepareExecutionContext(input));
229
+ runner.assertChildModel(input.modelId, runner.prepareExecutionContext(input));
228
230
  }
229
231
  const session = this.options.runtime.updateAgentSessionConfiguration({
230
232
  sessionId: current.id,
231
- ...(typeof input.model === 'string' ? { model: input.model } : {}),
233
+ ...(typeof input.modelId === 'string' ? { modelId: input.modelId } : {}),
232
234
  ...(typeof input.effort === 'string' ? { effort: input.effort } : {}),
233
235
  ...(typeof input.access === 'string' ? { access: input.access } : {})
234
236
  });
@@ -237,7 +239,7 @@ export class SessionLifecycleService {
237
239
  runner: session.runner,
238
240
  externalSessionId: session.externalSessionId,
239
241
  workspaceId: session.workspaceId,
240
- model: session.model,
242
+ modelId: session.modelId,
241
243
  effort: session.effort,
242
244
  access: session.access
243
245
  });
@@ -91,7 +91,8 @@ export class SessionMessageService {
91
91
  }
92
92
  async prepareMessage(input) {
93
93
  checkSessionAdmission(input);
94
- if (typeof input.sessionId !== 'string' ||
94
+ if (Object.hasOwn(input, 'model') ||
95
+ typeof input.sessionId !== 'string' ||
95
96
  typeof input.clientMessageId !== 'string' ||
96
97
  input.clientMessageId.length === 0 ||
97
98
  typeof input.content !== 'string' ||
@@ -148,7 +149,7 @@ export class SessionMessageService {
148
149
  if (session.parentSessionId != null)
149
150
  this.options.runners
150
151
  .require(session.runner)
151
- .assertChildModel(session.model, executionContext);
152
+ .assertChildModel(session.modelId, executionContext);
152
153
  const sourceContent = withSessionMessageOrigin(content, input.__marctlOrigin, session.parentSessionId);
153
154
  const goalMessage = internalGoal || internalSchedule || internalRestore
154
155
  ? undefined
@@ -296,7 +297,7 @@ export class SessionMessageService {
296
297
  cwd,
297
298
  workspacePath,
298
299
  externalSessionId: currentSession.externalSessionId,
299
- model: currentSession.model,
300
+ modelId: currentSession.modelId,
300
301
  effort: currentSession.effort,
301
302
  access: currentSession.access,
302
303
  collaborationMode: planActive ? 'plan' : 'default',
@@ -209,7 +209,7 @@ function sessionSignature(sessions) {
209
209
  session.runner,
210
210
  session.externalSessionId,
211
211
  session.nativeControl,
212
- session.model,
212
+ session.modelId,
213
213
  session.effort,
214
214
  session.access,
215
215
  session.runnerTitle,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/node",
3
- "version": "0.11.45",
3
+ "version": "0.11.47",
4
4
  "description": "MyAgentRoam Node runtime CLI.",
5
5
  "license": "Apache-2.0 AND GPL-2.0-or-later",
6
6
  "type": "module",
@@ -38,10 +38,10 @@
38
38
  "sharp": "0.35.5",
39
39
  "ws": "^8.21.3",
40
40
  "zod": "4.4.3",
41
- "@myagentroam/agent": "0.11.45",
42
41
  "@myagentroam/code-navigation": "0.11.1",
43
- "@myagentroam/marctl": "0.11.6",
44
- "@myagentroam/protocol": "0.11.45"
42
+ "@myagentroam/marctl": "0.11.8",
43
+ "@myagentroam/agent": "0.11.47",
44
+ "@myagentroam/protocol": "0.11.47"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/ws": "^8.18.1"