@myagentroam/node 0.9.144 → 0.9.146
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/runner/mar-agent/conversation-normalizer.js +2 -37
- package/dist/runner/mar-agent/hosted-conversation-runtime.js +29 -2
- package/dist/runner/mar-agent/managed-run-controller.js +43 -3
- package/dist/runner/mar-agent/runtime-model-factory.js +0 -4
- package/dist/service/scheduled-session-store.js +12 -0
- package/dist/service/scheduled-task-mcp-stdio.js +13 -6
- package/dist/service/session-schedule-service.js +6 -1
- package/package.json +4 -4
|
@@ -336,19 +336,6 @@ export class MarAgentConversationNormalizer {
|
|
|
336
336
|
if (observation.outcome === 'failed')
|
|
337
337
|
projected = projected.map((item) => item.kind === 'file_change' ? { ...item, status: 'FAILED' } : item);
|
|
338
338
|
}
|
|
339
|
-
else if (toolName === 'todo_read') {
|
|
340
|
-
if (observation.outcome !== 'completed' ||
|
|
341
|
-
record(input) === undefined ||
|
|
342
|
-
!isTodoObservationData(observation.result.data))
|
|
343
|
-
continue;
|
|
344
|
-
const todo = observation.result.data;
|
|
345
|
-
projected = this.normalize({
|
|
346
|
-
...eventMetadata(event, observation.source.callId),
|
|
347
|
-
type: 'todo.updated',
|
|
348
|
-
revision: todo.revision,
|
|
349
|
-
items: todo.items
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
339
|
else if (marAgentSubagentOperation(toolName) !== undefined) {
|
|
353
340
|
if (!isSubagentToolInput(toolName, input) ||
|
|
354
341
|
!isSubagentObservationData(observation.result.data, input))
|
|
@@ -512,10 +499,8 @@ function codeModeObservationResults(value) {
|
|
|
512
499
|
});
|
|
513
500
|
}
|
|
514
501
|
function isPersonalizedToolName(toolName) {
|
|
515
|
-
//
|
|
516
|
-
return
|
|
517
|
-
toolName === 'todo_read' ||
|
|
518
|
-
marAgentSubagentOperation(toolName) !== undefined);
|
|
502
|
+
// Todo cards come only from native todo.updated events, never tool result snapshots.
|
|
503
|
+
return toolName === 'apply_patch' || marAgentSubagentOperation(toolName) !== undefined;
|
|
519
504
|
}
|
|
520
505
|
function isApplyPatchObservationData(value) {
|
|
521
506
|
const data = record(value);
|
|
@@ -548,26 +533,6 @@ function isApplyPatchObservationData(value) {
|
|
|
548
533
|
Number.isSafeInteger(totals.deletedLines) &&
|
|
549
534
|
totals.deletedLines >= 0);
|
|
550
535
|
}
|
|
551
|
-
function isTodoObservationData(value) {
|
|
552
|
-
const data = record(value);
|
|
553
|
-
if (data === undefined ||
|
|
554
|
-
!Number.isSafeInteger(data.revision) ||
|
|
555
|
-
data.revision < 0 ||
|
|
556
|
-
!Array.isArray(data.items))
|
|
557
|
-
return false;
|
|
558
|
-
return data.items.every((entry) => {
|
|
559
|
-
const item = record(entry);
|
|
560
|
-
if (item === undefined ||
|
|
561
|
-
typeof item.id !== 'string' ||
|
|
562
|
-
item.id.trim().length === 0 ||
|
|
563
|
-
typeof item.step !== 'string' ||
|
|
564
|
-
item.step.trim().length === 0 ||
|
|
565
|
-
(item.status !== 'pending' && item.status !== 'in_progress' && item.status !== 'completed') ||
|
|
566
|
-
!Number.isSafeInteger(data.revision))
|
|
567
|
-
return false;
|
|
568
|
-
return true;
|
|
569
|
-
});
|
|
570
|
-
}
|
|
571
536
|
function isSubagentToolInput(toolName, value) {
|
|
572
537
|
const input = record(value);
|
|
573
538
|
if (input === undefined)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { LocalAgentHost, MarAgentError, createMarAgent, openMarAgentSessionCatalog } from '@myagentroam/agent';
|
|
2
|
+
import { LocalAgentHost, MarAgentError, createMarAgent, generateSessionTitle, openMarAgentSessionCatalog } from '@myagentroam/agent';
|
|
3
3
|
import { projectMarAgentHistory } from './history-projection.js';
|
|
4
4
|
import { MarAgentConversationNormalizer } from './conversation-normalizer.js';
|
|
5
5
|
import { hostedConversationGeneratedImagesDisplayDirectory, hostedConversationImageRunId, marAgentGeneratedImageSources, marAgentGeneratedImagesDirectory } from './generated-images.js';
|
|
@@ -12,6 +12,7 @@ import { createImageGenerationExtensions } from './image-generation-extensions.j
|
|
|
12
12
|
*/
|
|
13
13
|
export class MarAgentHostedConversationRuntime {
|
|
14
14
|
#createAgent;
|
|
15
|
+
#generateTitle;
|
|
15
16
|
#createHost;
|
|
16
17
|
#openCatalog;
|
|
17
18
|
#now;
|
|
@@ -22,6 +23,7 @@ export class MarAgentHostedConversationRuntime {
|
|
|
22
23
|
#registerNativeImages;
|
|
23
24
|
constructor(options = {}) {
|
|
24
25
|
this.#createAgent = options.createAgent ?? createMarAgent;
|
|
26
|
+
this.#generateTitle = options.generateTitle ?? generateSessionTitle;
|
|
25
27
|
this.#createHost = options.createHost ?? ((input) => new LocalAgentHost(input));
|
|
26
28
|
this.#openCatalog = options.openCatalog ?? openMarAgentSessionCatalog;
|
|
27
29
|
this.#now = options.now ?? Date.now;
|
|
@@ -109,7 +111,10 @@ export class MarAgentHostedConversationRuntime {
|
|
|
109
111
|
async startRun(input) {
|
|
110
112
|
if (this.#active.has(input.sessionId))
|
|
111
113
|
throw new Error('HOSTED_CONVERSATION_RUN_ACTIVE');
|
|
112
|
-
const { agent, mcp, closeImages } = await this.#createRuntime(input);
|
|
114
|
+
const { agent, mcp, closeImages, models } = await this.#createRuntime(input);
|
|
115
|
+
const titleController = new AbortController();
|
|
116
|
+
let titleTask;
|
|
117
|
+
const metadata = await agent.getSession(input.sessionId).catch(() => undefined);
|
|
113
118
|
let execution;
|
|
114
119
|
try {
|
|
115
120
|
const session = await agent.openSession(input.sessionId);
|
|
@@ -132,6 +137,13 @@ export class MarAgentHostedConversationRuntime {
|
|
|
132
137
|
const completion = (async () => {
|
|
133
138
|
try {
|
|
134
139
|
for await (const event of execution) {
|
|
140
|
+
if (event.type === 'execution.started' && metadata?.automaticTitlePending && !titleTask)
|
|
141
|
+
titleTask = this.#generateTitle({
|
|
142
|
+
models: sdkModelConfigurations(models),
|
|
143
|
+
currentModelId: input.modelId,
|
|
144
|
+
prompt: input.userPrompt,
|
|
145
|
+
signal: titleController.signal
|
|
146
|
+
}).catch(() => undefined);
|
|
135
147
|
await this.#onEvent?.(input.conversationId, event);
|
|
136
148
|
for (const projected of projectHostedEvent(normalizer, event, {
|
|
137
149
|
clientMessageId: input.clientMessageId,
|
|
@@ -140,6 +152,17 @@ export class MarAgentHostedConversationRuntime {
|
|
|
140
152
|
await input.onEvent?.(projected);
|
|
141
153
|
}
|
|
142
154
|
const result = await execution.result();
|
|
155
|
+
if (result.status === 'cancelled')
|
|
156
|
+
titleController.abort();
|
|
157
|
+
const generatedTitle = await titleTask;
|
|
158
|
+
if (generatedTitle && !titleController.signal.aborted)
|
|
159
|
+
await agent
|
|
160
|
+
.setSessionTitle(input.sessionId, generatedTitle, {
|
|
161
|
+
automatic: true,
|
|
162
|
+
expectedTitle: metadata.title,
|
|
163
|
+
executionId: execution.executionId
|
|
164
|
+
})
|
|
165
|
+
.catch(() => undefined);
|
|
143
166
|
const title = await this.#readGeneratedTitle(input.homeDirectory, input.sessionId).catch(() => undefined);
|
|
144
167
|
return {
|
|
145
168
|
status: result.status === 'completed'
|
|
@@ -160,6 +183,8 @@ export class MarAgentHostedConversationRuntime {
|
|
|
160
183
|
};
|
|
161
184
|
}
|
|
162
185
|
finally {
|
|
186
|
+
titleController.abort();
|
|
187
|
+
await titleTask;
|
|
163
188
|
settled = true;
|
|
164
189
|
this.#active.delete(input.sessionId);
|
|
165
190
|
await agent.dispose().catch(() => undefined);
|
|
@@ -178,6 +203,7 @@ export class MarAgentHostedConversationRuntime {
|
|
|
178
203
|
cancel: () => {
|
|
179
204
|
if (settled || this.#active.get(input.sessionId)?.handle !== handle)
|
|
180
205
|
return false;
|
|
206
|
+
titleController.abort();
|
|
181
207
|
execution.cancel();
|
|
182
208
|
return true;
|
|
183
209
|
}
|
|
@@ -297,6 +323,7 @@ export class MarAgentHostedConversationRuntime {
|
|
|
297
323
|
};
|
|
298
324
|
return {
|
|
299
325
|
agent: await this.#createAgent(options),
|
|
326
|
+
models,
|
|
300
327
|
closeImages,
|
|
301
328
|
...(mcp === undefined ? {} : { mcp })
|
|
302
329
|
};
|
|
@@ -4,7 +4,7 @@ import { homedir } from 'node:os';
|
|
|
4
4
|
import { access, constants } from 'node:fs/promises';
|
|
5
5
|
import { nodeExecutionEnvironment } from '../../node-execution-environment.js';
|
|
6
6
|
import { BUNDLED_RIPGREP_VERSION, bundledRipgrepPath, prependBundledRipgrepToPath } from '../../ripgrep-binary.js';
|
|
7
|
-
import { LocalAgentHost, createMarAgent } from '@myagentroam/agent';
|
|
7
|
+
import { LocalAgentHost, createMarAgent, generateSessionTitle } from '@myagentroam/agent';
|
|
8
8
|
import { marAgentReasoningEffortSchema, marAgentRuntimeModelConfigurationSchema } from '@myagentroam/protocol';
|
|
9
9
|
import { boundedConversationItemId } from '../codex/conversation-parser.js';
|
|
10
10
|
import { parseSecretEnvironment } from '../../util/secret-environment.js';
|
|
@@ -29,6 +29,7 @@ export class MarAgentManagedRunController {
|
|
|
29
29
|
#createAgent;
|
|
30
30
|
#modelFactory;
|
|
31
31
|
#computerUse;
|
|
32
|
+
#generateTitle;
|
|
32
33
|
#disposePromise;
|
|
33
34
|
#disposed = false;
|
|
34
35
|
constructor(runner, host, options = {}) {
|
|
@@ -44,6 +45,7 @@ export class MarAgentManagedRunController {
|
|
|
44
45
|
}
|
|
45
46
|
});
|
|
46
47
|
this.#computerUse = options.computerUse;
|
|
48
|
+
this.#generateTitle = options.generateTitle ?? generateSessionTitle;
|
|
47
49
|
}
|
|
48
50
|
dispose() {
|
|
49
51
|
if (this.#disposePromise !== undefined)
|
|
@@ -244,6 +246,8 @@ export class MarAgentManagedRunController {
|
|
|
244
246
|
let executionMcpBinding;
|
|
245
247
|
let computerUseBinding;
|
|
246
248
|
let executionModels = [];
|
|
249
|
+
const titleController = new AbortController();
|
|
250
|
+
let titleTask;
|
|
247
251
|
try {
|
|
248
252
|
const sessionKey = input.externalSessionId ?? input.sessionId;
|
|
249
253
|
// Reserve both identities while opening so a concurrent release can await the same runtime.
|
|
@@ -364,6 +368,9 @@ export class MarAgentManagedRunController {
|
|
|
364
368
|
...(reasoningEffort === undefined ? {} : { reasoningEffort }),
|
|
365
369
|
images: input.images
|
|
366
370
|
};
|
|
371
|
+
const metadata = input.mode === 'compact' || !runtime.automaticTitleEnabled
|
|
372
|
+
? undefined
|
|
373
|
+
: await runtime.agent.getSession(session.id).catch(() => undefined);
|
|
367
374
|
const handle = input.mode === 'plan'
|
|
368
375
|
? session.plan({
|
|
369
376
|
...runInput
|
|
@@ -372,12 +379,36 @@ export class MarAgentManagedRunController {
|
|
|
372
379
|
? session.compact(runInput)
|
|
373
380
|
: session.run(runInput);
|
|
374
381
|
this.#executions.set(input.runId, {
|
|
375
|
-
cancel: () =>
|
|
382
|
+
cancel: () => {
|
|
383
|
+
titleController.abort();
|
|
384
|
+
handle.cancel();
|
|
385
|
+
}
|
|
376
386
|
});
|
|
377
387
|
this.host.emit(input.runId, 'run.running', {}, 'RUNNING');
|
|
378
|
-
for await (const event of handle)
|
|
388
|
+
for await (const event of handle) {
|
|
389
|
+
if (event.type === 'execution.started' && metadata?.automaticTitlePending && !titleTask) {
|
|
390
|
+
titleTask = this.#generateTitle({
|
|
391
|
+
models: sdkModelConfigurations(executionModels),
|
|
392
|
+
currentModelId: input.model.id,
|
|
393
|
+
prompt: input.input,
|
|
394
|
+
signal: titleController.signal
|
|
395
|
+
}).catch(() => undefined);
|
|
396
|
+
runtime.automaticTitleTask = { cancel: () => titleController.abort(), result: titleTask };
|
|
397
|
+
}
|
|
379
398
|
this.project(input.runId, event);
|
|
399
|
+
}
|
|
380
400
|
const result = await handle.result();
|
|
401
|
+
if (result.status === 'cancelled')
|
|
402
|
+
titleController.abort();
|
|
403
|
+
const title = await titleTask;
|
|
404
|
+
if (title && !titleController.signal.aborted)
|
|
405
|
+
await runtime.agent
|
|
406
|
+
.setSessionTitle(session.id, title, {
|
|
407
|
+
automatic: true,
|
|
408
|
+
expectedTitle: metadata.title,
|
|
409
|
+
executionId: handle.executionId
|
|
410
|
+
})
|
|
411
|
+
.catch(() => undefined);
|
|
381
412
|
await this.host.syncTitle(session.id, input.cwd);
|
|
382
413
|
const status = result.status === 'completed'
|
|
383
414
|
? 'SUCCEEDED'
|
|
@@ -412,6 +443,10 @@ export class MarAgentManagedRunController {
|
|
|
412
443
|
this.host.emit(input.runId, 'run.failed', projected, 'FAILED');
|
|
413
444
|
}
|
|
414
445
|
finally {
|
|
446
|
+
titleController.abort();
|
|
447
|
+
await titleTask;
|
|
448
|
+
if (runtime !== undefined && runtime.automaticTitleTask?.result === titleTask)
|
|
449
|
+
delete runtime.automaticTitleTask;
|
|
415
450
|
this.clearInteractions(input.runId);
|
|
416
451
|
this.#normalizers.delete(input.runId);
|
|
417
452
|
this.host.active.delete(input.runId);
|
|
@@ -554,6 +589,7 @@ export class MarAgentManagedRunController {
|
|
|
554
589
|
normalizer: new MarAgentConversationNormalizer(),
|
|
555
590
|
mcpLease,
|
|
556
591
|
dynamicCredentials,
|
|
592
|
+
automaticTitleEnabled: input.externalSessionId === undefined,
|
|
557
593
|
models,
|
|
558
594
|
released: false
|
|
559
595
|
};
|
|
@@ -608,6 +644,10 @@ export class MarAgentManagedRunController {
|
|
|
608
644
|
delete runtime.idleTimer;
|
|
609
645
|
}
|
|
610
646
|
try {
|
|
647
|
+
if (runtime.automaticTitleTask !== undefined) {
|
|
648
|
+
runtime.automaticTitleTask.cancel();
|
|
649
|
+
await runtime.automaticTitleTask.result;
|
|
650
|
+
}
|
|
611
651
|
try {
|
|
612
652
|
await this.#computerUse?.releaseSession(runtime.session.id);
|
|
613
653
|
}
|
|
@@ -76,9 +76,6 @@ export class MarAgentRuntimeModelFactory {
|
|
|
76
76
|
...(configuration.responsesTransport === undefined
|
|
77
77
|
? {}
|
|
78
78
|
: { responsesTransport: configuration.responsesTransport }),
|
|
79
|
-
...(configuration.responsesEncoding === undefined
|
|
80
|
-
? {}
|
|
81
|
-
: { responsesEncoding: configuration.responsesEncoding }),
|
|
82
79
|
responsesToolNamespace: configuration.responsesToolNamespace,
|
|
83
80
|
responsesPreviousResponseId: configuration.responsesPreviousResponseId,
|
|
84
81
|
enabled: configuration.enabled
|
|
@@ -114,7 +111,6 @@ export class MarAgentRuntimeModelFactory {
|
|
|
114
111
|
}
|
|
115
112
|
}
|
|
116
113
|
: {}),
|
|
117
|
-
responsesEncoding: configuration.responsesEncoding ?? 'STANDARD',
|
|
118
114
|
responsesConfigurationUpdates: configuration.responsesConfigurationUpdates === true,
|
|
119
115
|
credentialProvider: provider
|
|
120
116
|
};
|
|
@@ -152,6 +152,18 @@ export class ScheduledSessionStore {
|
|
|
152
152
|
.prepare('SELECT * FROM scheduled_session_occurrences WHERE task_id=? ORDER BY due_at DESC LIMIT ?')
|
|
153
153
|
.all(taskId, Math.max(1, Math.min(limit, 100)));
|
|
154
154
|
}
|
|
155
|
+
recentPage(taskId, page = 1) {
|
|
156
|
+
if (!Number.isSafeInteger(page) || page < 1)
|
|
157
|
+
throw new Error('SCHEDULE_INVALID');
|
|
158
|
+
const total = this.database
|
|
159
|
+
.prepare('SELECT COUNT(*) AS count FROM scheduled_session_occurrences WHERE task_id=?')
|
|
160
|
+
.get(taskId).count;
|
|
161
|
+
const actualPage = Math.min(page, Math.max(1, Math.ceil(total / 10)));
|
|
162
|
+
const occurrences = this.database
|
|
163
|
+
.prepare('SELECT * FROM scheduled_session_occurrences WHERE task_id=? ORDER BY due_at DESC, id DESC LIMIT 10 OFFSET ?')
|
|
164
|
+
.all(taskId, (actualPage - 1) * 10);
|
|
165
|
+
return { occurrences, occurrenceTotal: total, occurrencePage: actualPage };
|
|
166
|
+
}
|
|
155
167
|
pendingProposals(taskId) {
|
|
156
168
|
return this.database
|
|
157
169
|
.prepare(`SELECT * FROM scheduled_session_proposals
|
|
@@ -7,25 +7,32 @@ const token = process.env['MAR_SCHEDULE_MCP_TOKEN'];
|
|
|
7
7
|
if (endpoint === undefined || token === undefined)
|
|
8
8
|
throw new Error('SCHEDULE_CAPABILITY_INVALID');
|
|
9
9
|
const server = new McpServer({ name: 'mar_schedule', version: '1.0.0' });
|
|
10
|
+
const scopeNote = 'Scope is limited to the MAR scheduled task managed by Node for this conversation; ' +
|
|
11
|
+
'it does not cover repository, CI, system cron, or other timers.';
|
|
12
|
+
const objectiveDescription = 'Task body for one scheduled run in this conversation. State what that run should do with enough task context. ' +
|
|
13
|
+
'Do not phrase it as a request to create or change a schedule or repeat cron/time-zone settings; MAR handles scheduling and skipped triggers.';
|
|
10
14
|
server.registerTool('mar_get_scheduled_task', {
|
|
11
|
-
description: 'Read the MAR scheduled task
|
|
15
|
+
description: 'Read the MAR scheduled task bound to this MAR-managed Workspace conversation, or null if none exists. ' +
|
|
16
|
+
scopeNote
|
|
12
17
|
}, async () => result(await request('mar_get_scheduled_task', {})));
|
|
13
18
|
if (process.env['MAR_SCHEDULE_MCP_READ_ONLY'] !== '1') {
|
|
14
19
|
server.registerTool('mar_create_scheduled_task', {
|
|
15
|
-
description: 'Create
|
|
20
|
+
description: 'Create the MAR scheduled task for this MAR-managed Workspace conversation. MAR runs it in this conversation for each admitted trigger using the connected Node time zone. ' +
|
|
21
|
+
scopeNote,
|
|
16
22
|
inputSchema: {
|
|
17
|
-
objective: z.string().min(1).max(20_000).describe(
|
|
23
|
+
objective: z.string().min(1).max(20_000).describe(objectiveDescription),
|
|
18
24
|
cron: z
|
|
19
25
|
.string()
|
|
20
26
|
.min(9)
|
|
21
27
|
.max(64)
|
|
22
|
-
.describe('Five-field cron expression interpreted in the connected MAR Node time zone.')
|
|
28
|
+
.describe('Five-field cron expression interpreted in the connected MAR Node time zone. It defines the schedule separately from the per-run task body.')
|
|
23
29
|
}
|
|
24
30
|
}, async (args) => result(await request('mar_create_scheduled_task', args)));
|
|
25
31
|
server.registerTool('mar_update_scheduled_task', {
|
|
26
|
-
description: 'Update the MAR scheduled task for this MAR-managed Workspace conversation.
|
|
32
|
+
description: 'Update the MAR scheduled task for this MAR-managed Workspace conversation. MAR runs the saved objective in this conversation for each admitted trigger using the connected Node time zone. ' +
|
|
33
|
+
scopeNote,
|
|
27
34
|
inputSchema: {
|
|
28
|
-
objective: z.string().min(1).max(20_000).describe(
|
|
35
|
+
objective: z.string().min(1).max(20_000).describe(objectiveDescription).optional(),
|
|
29
36
|
cron: z
|
|
30
37
|
.string()
|
|
31
38
|
.min(9)
|
|
@@ -30,11 +30,16 @@ export class SessionScheduleService {
|
|
|
30
30
|
const session = await this.requireSession(input);
|
|
31
31
|
const store = this.store();
|
|
32
32
|
const task = store.get(session.externalSessionId ?? session.id);
|
|
33
|
+
const page = input.occurrencePage === undefined ? 1 : input.occurrencePage;
|
|
34
|
+
if (typeof page !== 'number' || !Number.isSafeInteger(page) || page < 1)
|
|
35
|
+
throw new Error('SCHEDULE_INVALID');
|
|
33
36
|
return {
|
|
34
37
|
task: task ?? null,
|
|
35
38
|
nodeTimezone: nodeTimezone(),
|
|
36
39
|
canResolveProposals: task !== undefined && input.__requestUserId === task.ownerUserId,
|
|
37
|
-
|
|
40
|
+
...(task === undefined
|
|
41
|
+
? { occurrences: [], occurrenceTotal: 0, occurrencePage: 1 }
|
|
42
|
+
: store.recentPage(task.id, page)),
|
|
38
43
|
proposals: task === undefined ? [] : store.pendingProposals(task.id)
|
|
39
44
|
};
|
|
40
45
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.146",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"npm": "11.12.1",
|
|
35
35
|
"ws": "^8.21.3",
|
|
36
36
|
"zod": "4.4.3",
|
|
37
|
-
"@myagentroam/
|
|
38
|
-
"@myagentroam/agent": "0.9.144",
|
|
37
|
+
"@myagentroam/agent": "0.9.146",
|
|
39
38
|
"@myagentroam/code-navigation": "0.9.129",
|
|
40
|
-
"@myagentroam/protocol": "0.9.
|
|
39
|
+
"@myagentroam/protocol": "0.9.146",
|
|
40
|
+
"@myagentroam/marctl": "0.9.120"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/ws": "^8.18.1"
|