@myagentroam/node 0.9.105 → 0.9.106

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
@@ -856,6 +856,7 @@ export class NodeConnector {
856
856
  runtime: this.runtime,
857
857
  runners: this.runners,
858
858
  projection: this.nativeSessionProjectionService,
859
+ resolveForCommand: (sessionId) => this.externalSessionResumeService.resolveForMessage(sessionId),
859
860
  profiles: () => this.runnerService.profiles(),
860
861
  present: (session) => this.sessionPresentationService.present(session),
861
862
  resumeQueueAfterCommandRun: (sessionId) => this.workspaceQueueWorkbenchService.resumeAfterCommandRun(sessionId),
@@ -43,21 +43,17 @@ export function codexOfficialTurn(session, value, sequence, managedTurn) {
43
43
  if (items.length === 0)
44
44
  return undefined;
45
45
  if (managedTurn !== undefined) {
46
+ const officialComplete = value.status === 'completed' ||
47
+ value.status === 'failed' ||
48
+ value.status === 'interrupted' ||
49
+ (value.status === undefined && codexTimestamp(value.completedAt) !== null);
46
50
  const localUser = managedTurn.items.find((item) => item.kind === 'user_message');
47
51
  const officialNativeItemIds = codexNativeItemIds(value.items);
48
52
  const officialAssistantCount = items.filter((item) => item.kind === 'assistant_message').length;
49
53
  const officialAssistantMessage = officialAssistantCount > 0;
50
54
  const managedAssistants = managedTurn.items.filter((item) => item.kind === 'assistant_message' && conversationItemNativeId(item.id) === undefined);
51
55
  const managedAssistantCandidates = officialAssistantCount === 0 ? [] : managedAssistants.slice(-officialAssistantCount);
52
- const assistantLength = (values) => values.reduce((length, item) => {
53
- if (item.kind !== 'assistant_message' || !isPlainRecord(item.payload))
54
- return length;
55
- return length + (typeof item.payload.text === 'string' ? item.payload.text.length : 0);
56
- }, 0);
57
- const preferLocalAssistant = officialAssistantMessage &&
58
- (assistantLength(managedAssistantCandidates) > assistantLength(items) ||
59
- ((managedTurn.completedAt ?? 0) > (completedAt ?? 0) &&
60
- assistantLength(managedAssistantCandidates) > 0));
56
+ const preferLocalAssistant = officialAssistantMessage && !officialComplete;
61
57
  const replacedManagedAssistantIds = new Set(preferLocalAssistant
62
58
  ? []
63
59
  : officialAssistantCount === 0
@@ -66,6 +62,8 @@ export function codexOfficialTurn(session, value, sequence, managedTurn) {
66
62
  const localLiveItems = managedTurn.items.filter((item) => {
67
63
  if (item.kind === 'user_message')
68
64
  return false;
65
+ if (preferLocalAssistant && item.kind === 'assistant_message')
66
+ return true;
69
67
  // `item/agentMessage/delta` uses a synthetic runtime ID. Once
70
68
  // `thread/read` returns the final Agent message, it is the same reply
71
69
  // without a shared native item ID and must replace that transient item.
@@ -112,15 +110,6 @@ export function codexOfficialTurn(session, value, sequence, managedTurn) {
112
110
  replacement = officialAssistants.find((item) => !consumedOfficialIds.has(item.id));
113
111
  }
114
112
  if (replacement !== undefined) {
115
- if (managedItem.kind === 'assistant_message' &&
116
- replacement.kind === 'assistant_message' &&
117
- (assistantLength([managedItem]) > assistantLength([replacement]) ||
118
- ((managedTurn.completedAt ?? 0) > (completedAt ?? 0) &&
119
- assistantLength([managedItem]) > 0))) {
120
- reconciledItems.push(managedItem);
121
- consumedOfficialIds.add(replacement.id);
122
- continue;
123
- }
124
113
  if (!consumedOfficialIds.has(replacement.id)) {
125
114
  reconciledItems.push(replacement);
126
115
  consumedOfficialIds.add(replacement.id);
@@ -134,13 +123,13 @@ export function codexOfficialTurn(session, value, sequence, managedTurn) {
134
123
  reconciledItems.push(item);
135
124
  return {
136
125
  ...managedTurn,
137
- status: 'SUCCEEDED',
126
+ status: officialComplete ? 'SUCCEEDED' : managedTurn.status,
138
127
  // Reconcile against the managed runtime order. Official items replace
139
128
  // matching live projections in place; newly visible terminal items such
140
129
  // as a plan are appended after the commentary and tools that preceded it.
141
130
  items: reconciledItems,
142
131
  startedAt,
143
- completedAt
132
+ completedAt: officialComplete ? completedAt : null
144
133
  };
145
134
  }
146
135
  return {
@@ -20,7 +20,7 @@ export function projectMarAgentHistory(session, entries, options = {}) {
20
20
  rewind: { before: previous?.id ?? null, after: turnId },
21
21
  items: [],
22
22
  startedAt: at,
23
- completedAt: at
23
+ completedAt: null
24
24
  };
25
25
  turns.set(turnId, created);
26
26
  return created;
@@ -32,13 +32,17 @@ export function projectMarAgentHistory(session, entries, options = {}) {
32
32
  items.push(item);
33
33
  else
34
34
  items[index] = { ...items[index], ...item, startedAt: items[index].startedAt };
35
- turns.set(turn.id, { ...turn, items, completedAt: item.completedAt ?? turn.completedAt });
35
+ turns.set(turn.id, { ...turn, items });
36
36
  };
37
37
  for (const entry of entries) {
38
38
  if (entry.kind === 'user') {
39
39
  const at = Date.parse(entry.timestamp);
40
40
  const turn = ensure(entry.turnId, at);
41
- const id = `${entry.turnId}:user`;
41
+ // SDK mailbox messages are persisted as additional turn.user records in the same Turn.
42
+ // The first input keeps its existing identity; later inputs use their storage sequence.
43
+ const id = turn.userItemId === null
44
+ ? `${entry.turnId}:user`
45
+ : `${entry.turnId}:user:${entry.sequence}`;
42
46
  const images = entry.images;
43
47
  const registeredImages = images === undefined ? [] : (options.registerInputImages?.(entry) ?? []);
44
48
  replace(turn, historyItem(session, turn, id, 'user_message', 'COMPLETED', {
@@ -56,7 +60,8 @@ export function projectMarAgentHistory(session, entries, options = {}) {
56
60
  }
57
61
  : {})
58
62
  }, at));
59
- turns.set(entry.turnId, { ...turns.get(entry.turnId), userItemId: id });
63
+ if (turn.userItemId === null)
64
+ turns.set(entry.turnId, { ...turns.get(entry.turnId), userItemId: id });
60
65
  continue;
61
66
  }
62
67
  const event = entry.event;
@@ -1,5 +1,4 @@
1
1
  import { boundedConversationItemId, compactRunnerText } from '../codex/conversation-parser.js';
2
- import { runtimeAssistantProjectionMoreComplete } from '../../util/runner-native-session-parsers.js';
3
2
  import { stripMissionStartPrompt } from '../../service/mission-runtime.js';
4
3
  import { normalizeOpenCodeTool } from './tool-normalizer.js';
5
4
  export function openCodeConversationPage(session, messages, input, managedTurn) {
@@ -73,9 +72,14 @@ function openCodeTurn(session, user, userParts, assistants, sequence, managed) {
73
72
  const completedAt = Math.max(startedAt ?? 0, ...assistants.map(({ info }) => number(record(info.time)?.completed) ?? 0)) || startedAt;
74
73
  const id = managed?.id ?? `${session.id}:official:${nativeTurnId}`;
75
74
  const runId = managed?.runId ?? null;
76
- const projectedItems = runtimeAssistantProjectionMoreComplete(managed, items)
77
- ? managed.items
78
- : items;
75
+ const officialAssistantIds = new Set(assistants.flatMap(({ parts }) => parts.flatMap((part) => {
76
+ const value = record(part);
77
+ return value?.type === 'text' && typeof value.id === 'string'
78
+ ? [`${managed?.runId}:${boundedConversationItemId('opencode', value.id)}`]
79
+ : [];
80
+ })));
81
+ const pendingOfficialReply = managed?.items.some((item) => item.kind === 'assistant_message' && !officialAssistantIds.has(item.id));
82
+ const projectedItems = pendingOfficialReply ? managed.items : items;
79
83
  return {
80
84
  id,
81
85
  sessionId: session.id,
@@ -13,6 +13,11 @@ export function convergeConversationWatchPage(previous, previousObserved, next,
13
13
  const authority = isConversationHistorySource(previousAuthority)
14
14
  ? previousAuthority
15
15
  : previous?.source;
16
+ if (next.deferredOlderHistory === true && previous !== undefined)
17
+ return {
18
+ page: composeConversationRuntimePage(previous, next),
19
+ authority: authority ?? next.source
20
+ };
16
21
  if (previous === undefined ||
17
22
  authority === undefined ||
18
23
  sourceRank(next.source) >= sourceRank(authority))
@@ -91,13 +96,37 @@ export class ConversationHistoryService {
91
96
  const snapshotSequence = this.options.snapshotSequence();
92
97
  const readAt = Date.now();
93
98
  const activeCursor = decodeActiveHistoryCursor(input.cursor, session.id);
94
- if (activeCursor !== undefined || this.options.hasManagedActiveRun(session))
99
+ if (activeCursor !== undefined ||
100
+ this.options.hasManagedActiveRun(session) ||
101
+ this.hasManagedRuntimeHistory(session))
95
102
  return this.readManagedActive(session, input, activeCursor, snapshotSequence, readAt);
96
103
  return this.readHistory(session, input, snapshotSequence, readAt);
97
104
  }
98
105
  async readHistoryPage(session, input) {
106
+ if (this.hasManagedRuntimeHistory(session)) {
107
+ const runtimeTurns = this.options.runtime.listConversationTurns({
108
+ sessionId: session.id,
109
+ limit: 500
110
+ }).turns;
111
+ const olderCursor = this.options.hasManagedActiveRun(session)
112
+ ? {
113
+ sessionId: session.id,
114
+ stage: 'OFFICIAL',
115
+ beforeAt: oldestTurnActivityAt(runtimeTurns),
116
+ cursor: null
117
+ }
118
+ : undefined;
119
+ return this.readManagedActive(session, input, olderCursor, this.options.snapshotSequence(), Date.now());
120
+ }
99
121
  return this.readHistory(session, input, this.options.snapshotSequence(), Date.now());
100
122
  }
123
+ hasManagedRuntimeHistory(session) {
124
+ return (session.runner === 'mar-agent' &&
125
+ session.nativeControl === 'MAR_MANAGED' &&
126
+ this.options.runtime.getAgentSession(session.id) !== undefined &&
127
+ this.options.runtime.listConversationTurns({ sessionId: session.id, limit: 1 }).turns.length >
128
+ 0);
129
+ }
101
130
  async readHistory(session, input, snapshotSequence, readAt) {
102
131
  const selected = await this.readRunnerHistory(session, input);
103
132
  if (selected.page?.source === 'native')
@@ -113,9 +142,9 @@ export class ConversationHistoryService {
113
142
  ? []
114
143
  : this.options.runtime.listConversationTurns({ sessionId: session.id, limit: 500 }).turns;
115
144
  const initialOfficialTurns = official.turns;
116
- const lastRepresentedRuntimeIndex = runtimeTurns.findLastIndex((turn) => initialOfficialTurns.some((officialTurn) => sameHistoryConversationTurn(officialTurn, turn)));
145
+ const lastRepresentedRuntimeIndex = runtimeTurns.findLastIndex((turn) => initialOfficialTurns.some((officialTurn) => sameConversationTurn(officialTurn, turn)));
117
146
  const officialHasTurns = initialOfficialTurns.length > 0;
118
- const absentLocalTurns = runtimeTurns.filter((turn, index) => !initialOfficialTurns.some((officialTurn) => sameHistoryConversationTurn(officialTurn, turn)) &&
147
+ const absentLocalTurns = runtimeTurns.filter((turn, index) => !initialOfficialTurns.some((officialTurn) => sameConversationTurn(officialTurn, turn)) &&
119
148
  (!officialHasTurns || index > lastRepresentedRuntimeIndex));
120
149
  const missingLocalTurns = absentLocalTurns.slice(-limit);
121
150
  if (input.cursor === undefined &&
@@ -130,7 +159,7 @@ export class ConversationHistoryService {
130
159
  const runtimeTurnsByOfficialId = new Map();
131
160
  const runtimeSupplementalItemsByOfficialId = new Map();
132
161
  for (const officialTurn of officialTurns) {
133
- const runtimeTurn = runtimeTurns.find((candidate) => sameHistoryConversationTurn(officialTurn, candidate));
162
+ const runtimeTurn = runtimeTurns.find((candidate) => sameConversationTurn(officialTurn, candidate));
134
163
  if (runtimeTurn === undefined)
135
164
  continue;
136
165
  runtimeTurnsByOfficialId.set(officialTurn.id, runtimeTurn);
@@ -459,7 +488,7 @@ function latestTurnActivityAt(turn) {
459
488
  return Math.max(turn.startedAt ?? 0, turn.completedAt ?? 0);
460
489
  }
461
490
  function oldestTurnActivityAt(turns) {
462
- return turns.length === 0 ? 0 : Math.min(...turns.map(latestTurnActivityAt));
491
+ return turns.length === 0 ? 0 : Math.min(...turns.map(earliestTurnActivityAt));
463
492
  }
464
493
  function mergeRuntimeUserImageReferences(officialTurn, runtimeTurn, attachments) {
465
494
  const officialUser = officialTurn.items.find((item) => item.kind === 'user_message');
@@ -524,9 +553,6 @@ function mergeRuntimeUserImageReferences(officialTurn, runtimeTurn, attachments)
524
553
  : item)
525
554
  };
526
555
  }
527
- function sameHistoryConversationTurn(left, right) {
528
- return sameConversationTurn(left, right) || (left.runId !== null && left.runId === right.runId);
529
- }
530
556
  function sameConversationTurn(left, right) {
531
557
  if (left.id === right.id)
532
558
  return true;
@@ -6,7 +6,7 @@ function conversationSegmentPrefix(turn) {
6
6
  : undefined;
7
7
  const clientMessageId = payload?.clientMessageId;
8
8
  return typeof clientMessageId === 'string' && clientMessageId.length > 0
9
- ? `${turn.sessionId}:message:${clientMessageId}`
9
+ ? `message:${clientMessageId}`
10
10
  : turn.id;
11
11
  }
12
12
  export function conversationSegments(turn) {
@@ -115,6 +115,7 @@ export class NativeSessionWatchService {
115
115
  mode: this.options.managedActive(session) ? 'RUNNING' : 'HISTORY',
116
116
  expiresAt: Date.now() + TTL_MS,
117
117
  refresh: undefined,
118
+ refreshMode: undefined,
118
119
  sessionSignature: undefined,
119
120
  signature: undefined,
120
121
  page: undefined,
@@ -202,7 +203,7 @@ export class NativeSessionWatchService {
202
203
  get size() {
203
204
  return this.watches.size;
204
205
  }
205
- async refresh(sessionId, limit = 10, emit = true) {
206
+ async refresh(sessionId, limit = 10, mode = 'observation') {
206
207
  const watch = this.watches.get(sessionId);
207
208
  if (watch === undefined)
208
209
  return undefined;
@@ -212,20 +213,19 @@ export class NativeSessionWatchService {
212
213
  this.stop(sessionId);
213
214
  return undefined;
214
215
  }
215
- const refresh = this.performRefresh(sessionId, watch, limit, emit);
216
- watch.refresh = refresh;
217
- try {
218
- return await refresh;
219
- }
220
- finally {
216
+ const refresh = this.performRefresh(sessionId, watch, limit, mode).finally(() => {
221
217
  if (this.watches.get(sessionId) === watch) {
222
218
  watch.refresh = undefined;
219
+ watch.refreshMode = undefined;
223
220
  clearTimeout(watch.timer);
224
221
  watch.timer = this.refreshTimer(sessionId);
225
222
  }
226
- }
223
+ });
224
+ watch.refresh = refresh;
225
+ watch.refreshMode = mode;
226
+ return refresh;
227
227
  }
228
- async performRefresh(sessionId, watch, limit, emit) {
228
+ async performRefresh(sessionId, watch, limit, mode) {
229
229
  let stage = 'resolve';
230
230
  let session;
231
231
  const readHistoricalPage = watch.mode === 'HISTORY' && this.options.readHistoryPage !== undefined;
@@ -238,7 +238,7 @@ export class NativeSessionWatchService {
238
238
  return undefined;
239
239
  }
240
240
  watch.session = session;
241
- if (emit && this.options.managedActive(session))
241
+ if (mode === 'observation' && this.options.managedActive(session))
242
242
  return watch.page;
243
243
  stage = 'refresh_activity';
244
244
  await this.options.refreshActivity(session);
@@ -249,14 +249,14 @@ export class NativeSessionWatchService {
249
249
  const page = await (readHistoricalPage
250
250
  ? this.options.readHistoryPage(session, limit)
251
251
  : this.options.readPage(session, limit));
252
- if (emit && revisionBeforeRead !== watch.eventRevision)
252
+ if (mode === 'observation' && revisionBeforeRead !== watch.eventRevision)
253
253
  return watch.page;
254
254
  stage = 'present_session';
255
255
  const presented = this.options.present(session);
256
256
  const sessionSignature = JSON.stringify(presented);
257
257
  if (sessionSignature !== watch.sessionSignature) {
258
258
  watch.sessionSignature = sessionSignature;
259
- if (emit)
259
+ if (mode === 'observation')
260
260
  this.options.emitSession(presented);
261
261
  }
262
262
  watch.failures = 0;
@@ -288,11 +288,13 @@ export class NativeSessionWatchService {
288
288
  watch.page = accepted;
289
289
  }
290
290
  stage = 'emit_page';
291
- if (emit && completingConvergence)
291
+ if (completingConvergence && accepted.source === 'runtime')
292
+ this.releasePendingEvents(session.id);
293
+ else if (completingConvergence)
292
294
  this.emitSnapshotToLeases(session, accepted, true);
293
- else if (emit && changed)
295
+ else if (changed)
294
296
  this.emitObservedPage(session, accepted);
295
- return emit ? accepted : page;
297
+ return mode === 'initial' ? page : accepted;
296
298
  }
297
299
  catch (error) {
298
300
  watch.failures += 1;
@@ -345,15 +347,19 @@ export class NativeSessionWatchService {
345
347
  const activeAtStart = this.options.managedActive(session);
346
348
  if (watch !== undefined)
347
349
  watch.mode = activeAtStart ? 'RUNNING' : watch.mode;
348
- const cached = !activeAtStart && watch?.page !== undefined ? watch.page : undefined;
349
- let page = activeAtStart
350
- ? watch === undefined
351
- ? undefined
352
- : this.composeRuntimePage(watch.page, await this.readRuntimePage(watch, session))
353
- : (cached ??
354
- (watch === undefined
355
- ? undefined
356
- : await this.refresh(session.id, INITIAL_TURN_LIMIT, false)));
350
+ let page;
351
+ if (watch !== undefined) {
352
+ if (activeAtStart)
353
+ page = this.composeRuntimePage(watch.page, await this.readRuntimePage(watch, session));
354
+ else {
355
+ // An initial subscription must read after any older observation, not join its
356
+ // potentially smaller or already-stale page.
357
+ if (watch.refresh !== undefined &&
358
+ (watch.page !== undefined || watch.refreshMode === 'observation'))
359
+ await watch.refresh;
360
+ page = await this.refresh(session.id, INITIAL_TURN_LIMIT, 'initial');
361
+ }
362
+ }
357
363
  if (page === undefined)
358
364
  throw new Error('NATIVE_TRANSCRIPT_UNAVAILABLE');
359
365
  if (lease.snapshotSent)
@@ -506,7 +512,7 @@ export class NativeSessionWatchService {
506
512
  watch.mode !== 'CONVERGING' ||
507
513
  watch.transitionGeneration !== generation)
508
514
  return;
509
- await this.refresh(session.id, INITIAL_TURN_LIMIT, true);
515
+ await this.refresh(session.id, INITIAL_TURN_LIMIT);
510
516
  }
511
517
  emitLeaseEvent(lease, event) {
512
518
  this.options.emitWatchEvent?.({
@@ -146,7 +146,12 @@ export class RunEventService {
146
146
  }
147
147
  if (!terminalExecution)
148
148
  return;
149
- if (targetsCurrentTurn && createdTurn === undefined) {
149
+ // A completed reply has already been delivered through its own stream event. Only a
150
+ // continuing Run, an exceptional termination, or a pending item needs a final Turn update.
151
+ if (targetsCurrentTurn &&
152
+ createdTurn === undefined &&
153
+ (finalStatus !== 'SUCCEEDED' ||
154
+ targetTurn?.items.some((item) => item.status === 'PENDING' || item.status === 'IN_PROGRESS'))) {
150
155
  const turn = this.options.runtime.conversationTurnForRun(runId);
151
156
  if (turn !== undefined)
152
157
  this.options.emitWorkbench('conversation', { turn });
@@ -39,15 +39,19 @@ export class SessionCommandService {
39
39
  (await this.options.projection.resolveCurrent(input.sessionId));
40
40
  if (resolved === undefined)
41
41
  throw new Error('SESSION_NOT_FOUND');
42
- if (resolved.nativeControl === 'EXTERNAL')
43
- throw new Error('SESSION_ACTIVATION_REQUIRED');
44
- const session = resolved;
45
42
  const command = this.options
46
43
  .profiles()
47
- .find((profile) => profile.runner === session.runner)
44
+ .find((profile) => profile.runner === resolved.runner)
48
45
  ?.commands.find((candidate) => isPlainRecord(candidate) && candidate.id === input.commandId);
46
+ if (resolved.nativeControl === 'EXTERNAL' && command?.source !== 'MAR_RUNTIME')
47
+ throw new Error('SESSION_ACTIVATION_REQUIRED');
49
48
  if (command?.available !== true)
50
49
  throw new Error('RUNNER_COMMAND_UNAVAILABLE');
50
+ const session = resolved.nativeControl === 'EXTERNAL' && command.source === 'MAR_RUNTIME'
51
+ ? await this.options.resolveForCommand(input.sessionId)
52
+ : resolved;
53
+ if (session.nativeControl === 'EXTERNAL')
54
+ throw new Error('SESSION_ACTIVATION_REQUIRED');
51
55
  if ((command.interaction === 'IMMEDIATE_ACTION' ||
52
56
  command.interaction === 'DESTRUCTIVE_ACTION') &&
53
57
  this.options.runtime.hasActiveSessionLease(session.id))
@@ -159,7 +159,9 @@ export function nativeConversationPage(session, history, input, runtimeTurns = [
159
159
  const runtimeErrors = (runtimeTurn?.items ?? [])
160
160
  .filter((item) => item.kind === 'error')
161
161
  .map((item) => ({ ...item, turnId, runId: runtimeTurn?.runId ?? null }));
162
- const items = runtimeAssistantProjectionMoreComplete(runtimeTurn, nativeItems)
162
+ // Native transcripts do not expose a terminal event for an individual response.
163
+ // Once linked to a managed Run, the Runtime owns that Turn until it leaves memory.
164
+ const items = runtimeTurn !== undefined
163
165
  ? runtimeTurn.items.map((item) => ({
164
166
  ...item,
165
167
  turnId,
@@ -225,22 +227,6 @@ export function nativeConversationPage(session, history, input, runtimeTurns = [
225
227
  : precedingWindow
226
228
  };
227
229
  }
228
- export function runtimeAssistantProjectionMoreComplete(runtimeTurn, projectedItems) {
229
- if (runtimeTurn === undefined)
230
- return false;
231
- const assistantStats = (items) => items.reduce((stats, item) => {
232
- if (item.kind !== 'assistant_message' || !isPlainRecord(item.payload))
233
- return stats;
234
- return {
235
- count: stats.count + 1,
236
- characters: stats.characters +
237
- (typeof item.payload.text === 'string' ? item.payload.text.length : 0)
238
- };
239
- }, { count: 0, characters: 0 });
240
- const runtime = assistantStats(runtimeTurn.items);
241
- const projected = assistantStats(projectedItems);
242
- return runtime.count > projected.count || runtime.characters > projected.characters;
243
- }
244
230
  function runtimeTurnClientMessageId(turn) {
245
231
  const user = turn.items.find((item) => item.kind === 'user_message');
246
232
  return isPlainRecord(user?.payload) && typeof user.payload.clientMessageId === 'string'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/node",
3
- "version": "0.9.105",
3
+ "version": "0.9.106",
4
4
  "description": "MyAgentRoam Node runtime CLI.",
5
5
  "license": "Apache-2.0 AND GPL-2.0-or-later",
6
6
  "type": "module",
@@ -30,9 +30,9 @@
30
30
  "npm": "11.12.1",
31
31
  "ws": "^8.21.3",
32
32
  "zod": "4.4.3",
33
- "@myagentroam/agent": "0.9.105",
34
- "@myagentroam/code-navigation": "0.9.105",
35
- "@myagentroam/protocol": "0.9.105"
33
+ "@myagentroam/agent": "0.9.106",
34
+ "@myagentroam/code-navigation": "0.9.106",
35
+ "@myagentroam/protocol": "0.9.106"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/ws": "^8.18.1"