@myagentroam/node 0.10.40 → 0.10.41
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/claude-agent-sdk.js +8 -5
- package/dist/connector.js +36 -72
- package/dist/mcp/configuration.js +107 -0
- package/dist/mcp/naming.js +42 -0
- package/dist/runner/abstract-runner.js +3 -154
- package/dist/runner/claude/managed-run-controller.js +1 -4
- package/dist/runner/claude-code-runner.js +2 -2
- package/dist/runner/codex/managed-run-controller.js +6 -8
- package/dist/runner/codex-runner.js +2 -2
- package/dist/runner/mar-agent/computer-use-skill.js +6 -3
- package/dist/runner/mar-agent/computer-use.js +2 -1
- package/dist/runner/mar-agent/managed-run-controller.js +10 -11
- package/dist/runner/mar-agent/mcp-client-pool.js +3 -5
- package/dist/runner/opencode/managed-run-controller.js +1 -4
- package/dist/runner/opencode-runner.js +2 -2
- package/dist/service/continuous-run-coordinator.js +11 -18
- package/dist/service/{goal-mcp-server.js → goal-mcp-bridge.js} +19 -14
- package/dist/service/goal-mcp-stdio.js +5 -4
- package/dist/service/goal-runtime.js +21 -36
- package/dist/service/hosted-conversation-node-service.js +2 -0
- package/dist/service/mcp-installation-verifier.js +2 -1
- package/dist/service/mcp-node-operation-service.js +3 -1
- package/dist/service/{mail-notification-mcp-server.js → notification-mcp-bridge.js} +30 -22
- package/dist/service/{mail-notification-mcp-stdio.js → notification-mcp-stdio.js} +9 -8
- package/dist/service/restart-session-restorer.js +2 -2
- package/dist/service/{scheduled-task-mcp-server.js → schedule-mcp-bridge.js} +25 -19
- package/dist/service/{scheduled-task-mcp-stdio.js → schedule-mcp-stdio.js} +8 -7
- package/dist/service/session-catalog-service.js +3 -3
- package/package.json +4 -4
- /package/dist/{mcp-installation-model.js → mcp/model.js} +0 -0
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import { NODE_MCP, NODE_MCP_VERSION } from '../mcp/naming.js';
|
|
1
2
|
import { randomUUID } from 'node:crypto';
|
|
2
3
|
import { connect } from 'node:net';
|
|
3
4
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
5
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
5
6
|
import { z } from 'zod';
|
|
6
7
|
import { notificationInputSchema } from '@myagentroam/protocol';
|
|
7
|
-
const endpoint = process.env['
|
|
8
|
-
const token = process.env['
|
|
8
|
+
const endpoint = process.env['MAR_NOTIFICATION_MCP_ENDPOINT'];
|
|
9
|
+
const token = process.env['MAR_NOTIFICATION_MCP_TOKEN'];
|
|
9
10
|
if (endpoint === undefined || token === undefined)
|
|
10
11
|
throw new Error('MAIL_CAPABILITY_INVALID');
|
|
11
|
-
const server = new McpServer({ name:
|
|
12
|
-
server.registerTool(
|
|
12
|
+
const server = new McpServer({ name: NODE_MCP.notification.name, version: NODE_MCP_VERSION });
|
|
13
|
+
server.registerTool(NODE_MCP.notification.tools.email, {
|
|
13
14
|
description: 'Send a notification email to the specified recipient from this MAR-managed Workspace conversation. The Agent works with files and tools on the authorized MAR Node; the MAR Server sends email using its administrator-configured SMTP account. This is not the browser or Node local email account, nor a repository cron/CI notification. This tool cannot access SMTP credentials. Omit the template to use the built-in notification template in the sender’s preferred language; optionally select notification-en-US or notification-zh-CN. Each call may send a real email; do not retry after an uncertain result.',
|
|
14
15
|
inputSchema: {
|
|
15
16
|
templateId: z
|
|
@@ -30,8 +31,8 @@ server.registerTool('mar_send_email_notification', {
|
|
|
30
31
|
const value = await request({ ...args, callId: randomUUID() });
|
|
31
32
|
return { content: [{ type: 'text', text: JSON.stringify(value) }] };
|
|
32
33
|
});
|
|
33
|
-
if (process.env['
|
|
34
|
-
server.registerTool(
|
|
34
|
+
if (process.env['MAR_NOTIFICATION_MCP_CHANNELS'] === '1') {
|
|
35
|
+
server.registerTool(NODE_MCP.notification.tools.send, {
|
|
35
36
|
description: 'Send a real notification from the current authorized Workspace execution. Defaults to push to the initiating user; email requires an explicitly authorized recipientEmail. Channels and registered Push clients are independent. Push may be suppressed while any workbench connection is open or unavailable due to system, browser, or OS settings. Acceptance is not delivery. Do not disclose secrets or send to unauthorized recipients. Each invocation is a new side effect; do not retry after an uncertain or partial result.',
|
|
36
37
|
inputSchema: {
|
|
37
38
|
channels: z
|
|
@@ -55,12 +56,12 @@ if (process.env['MAR_NOTIFICATION_CHANNELS'] === '1') {
|
|
|
55
56
|
}
|
|
56
57
|
}, async (args) => {
|
|
57
58
|
const input = notificationInputSchema.parse(args);
|
|
58
|
-
const value = await request({ ...input, callId: randomUUID() },
|
|
59
|
+
const value = await request({ ...input, callId: randomUUID() }, NODE_MCP.notification.tools.send);
|
|
59
60
|
return { content: [{ type: 'text', text: JSON.stringify(value) }] };
|
|
60
61
|
});
|
|
61
62
|
}
|
|
62
63
|
await server.connect(new StdioServerTransport());
|
|
63
|
-
function request(args, tool =
|
|
64
|
+
function request(args, tool = NODE_MCP.notification.tools.email) {
|
|
64
65
|
return new Promise((resolve, reject) => {
|
|
65
66
|
const socket = connect(endpoint);
|
|
66
67
|
socket.setTimeout(35_000, () => socket.destroy(new Error('MAIL_DELIVERY_UNCERTAIN')));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { serializeComposerTag } from '@myagentroam/protocol';
|
|
1
|
+
import { parseComposerTags, serializeComposerTag } from '@myagentroam/protocol';
|
|
2
2
|
import { parseMessageAttachments } from '../util/node-operation-parsers.js';
|
|
3
3
|
import { RESTART_NOTICE } from './planned-restart-handoff.js';
|
|
4
4
|
/** Rebuild inputs through the existing preparation and FIFO boundary. */
|
|
@@ -70,7 +70,7 @@ export class RestartSessionRestorer {
|
|
|
70
70
|
sessionId: session.id,
|
|
71
71
|
content,
|
|
72
72
|
clientMessageId: input.clientMessageId,
|
|
73
|
-
...(content
|
|
73
|
+
...(parseComposerTags(content)[0]?.kind === 'mar_restart'
|
|
74
74
|
? { __runnerContent: `${content}${RESTART_NOTICE}` }
|
|
75
75
|
: {}),
|
|
76
76
|
attachments: input.attachments,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NODE_MCP } from '../mcp/naming.js';
|
|
1
2
|
import { randomBytes, randomUUID } from 'node:crypto';
|
|
2
3
|
import { existsSync } from 'node:fs';
|
|
3
4
|
import { unlink } from 'node:fs/promises';
|
|
@@ -5,7 +6,7 @@ import { createServer } from 'node:net';
|
|
|
5
6
|
import { tmpdir } from 'node:os';
|
|
6
7
|
import { join } from 'node:path';
|
|
7
8
|
import { fileURLToPath } from 'node:url';
|
|
8
|
-
export class
|
|
9
|
+
export class ScheduleMcpBridge {
|
|
9
10
|
store;
|
|
10
11
|
changed;
|
|
11
12
|
proposed;
|
|
@@ -24,23 +25,28 @@ export class ScheduledTaskMcpServer {
|
|
|
24
25
|
this.create = create;
|
|
25
26
|
this.resolveSessionId = resolveSessionId;
|
|
26
27
|
}
|
|
27
|
-
async
|
|
28
|
+
async prepare(capability) {
|
|
28
29
|
await this.#listen();
|
|
30
|
+
const args = scheduleMcpStdioArgs();
|
|
29
31
|
const token = randomBytes(32).toString('base64url');
|
|
30
|
-
const secretName = `MAR_SCHEDULE_MCP_${randomBytes(16).toString('hex').toUpperCase()}`;
|
|
31
32
|
this.#capabilities.set(token, capability);
|
|
32
33
|
return {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
name: NODE_MCP.schedule.name,
|
|
35
|
+
origin: 'BUILTIN',
|
|
36
|
+
lifecycle: 'EXECUTION',
|
|
37
|
+
transport: 'STDIO',
|
|
38
|
+
command: process.execPath,
|
|
39
|
+
args,
|
|
40
|
+
environment: {
|
|
41
|
+
MAR_SCHEDULE_MCP_ENDPOINT: this.#endpoint,
|
|
42
|
+
MAR_SCHEDULE_MCP_TOKEN: token,
|
|
43
|
+
MAR_SCHEDULE_MCP_READ_ONLY: capability.readonly ? '1' : '0'
|
|
42
44
|
},
|
|
43
|
-
|
|
45
|
+
allowedToolCallers: {
|
|
46
|
+
[NODE_MCP.schedule.tools.get]: ['direct', 'programmatic'],
|
|
47
|
+
[NODE_MCP.schedule.tools.create]: ['direct', 'programmatic'],
|
|
48
|
+
[NODE_MCP.schedule.tools.update]: ['direct', 'programmatic']
|
|
49
|
+
}
|
|
44
50
|
};
|
|
45
51
|
}
|
|
46
52
|
revoke(executionId) {
|
|
@@ -95,11 +101,11 @@ export class ScheduledTaskMcpServer {
|
|
|
95
101
|
(task !== undefined &&
|
|
96
102
|
(task.id !== capability.taskId || task.revision !== capability.revision)))
|
|
97
103
|
throw new Error('SCHEDULE_CAPABILITY_STALE');
|
|
98
|
-
if (request.tool ===
|
|
104
|
+
if (request.tool === NODE_MCP.schedule.tools.get) {
|
|
99
105
|
socket.end(`${JSON.stringify({ result: task ?? null })}\n`);
|
|
100
106
|
return;
|
|
101
107
|
}
|
|
102
|
-
if (request.tool ===
|
|
108
|
+
if (request.tool === NODE_MCP.schedule.tools.create) {
|
|
103
109
|
if (capability.readonly)
|
|
104
110
|
throw new Error('SCHEDULE_READ_ONLY');
|
|
105
111
|
if (task !== undefined)
|
|
@@ -126,7 +132,7 @@ export class ScheduledTaskMcpServer {
|
|
|
126
132
|
socket.end(`${JSON.stringify({ result: created })}\n`);
|
|
127
133
|
return;
|
|
128
134
|
}
|
|
129
|
-
if (request.tool !==
|
|
135
|
+
if (request.tool !== NODE_MCP.schedule.tools.update)
|
|
130
136
|
throw new Error('SCHEDULE_TOOL_INVALID');
|
|
131
137
|
if (capability.readonly)
|
|
132
138
|
throw new Error('SCHEDULE_READ_ONLY');
|
|
@@ -171,11 +177,11 @@ function record(value) {
|
|
|
171
177
|
? value
|
|
172
178
|
: {};
|
|
173
179
|
}
|
|
174
|
-
function
|
|
175
|
-
const javascript = fileURLToPath(new URL('./
|
|
180
|
+
function scheduleMcpStdioArgs() {
|
|
181
|
+
const javascript = fileURLToPath(new URL('./schedule-mcp-stdio.js', import.meta.url));
|
|
176
182
|
if (existsSync(javascript))
|
|
177
183
|
return [javascript];
|
|
178
|
-
const typescript = fileURLToPath(new URL('./
|
|
184
|
+
const typescript = fileURLToPath(new URL('./schedule-mcp-stdio.ts', import.meta.url));
|
|
179
185
|
if (!existsSync(typescript))
|
|
180
186
|
throw new Error('SCHEDULE_MCP_STDIO_ENTRY_UNAVAILABLE');
|
|
181
187
|
return ['--import', import.meta.resolve('tsx'), typescript];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NODE_MCP, NODE_MCP_VERSION } from '../mcp/naming.js';
|
|
1
2
|
import { connect } from 'node:net';
|
|
2
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
4
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -6,17 +7,17 @@ const endpoint = process.env['MAR_SCHEDULE_MCP_ENDPOINT'];
|
|
|
6
7
|
const token = process.env['MAR_SCHEDULE_MCP_TOKEN'];
|
|
7
8
|
if (endpoint === undefined || token === undefined)
|
|
8
9
|
throw new Error('SCHEDULE_CAPABILITY_INVALID');
|
|
9
|
-
const server = new McpServer({ name:
|
|
10
|
+
const server = new McpServer({ name: NODE_MCP.schedule.name, version: NODE_MCP_VERSION });
|
|
10
11
|
const scopeNote = 'Scope is limited to the MAR scheduled task managed by Node for this conversation; ' +
|
|
11
12
|
'it does not cover repository, CI, system cron, or other timers.';
|
|
12
13
|
const objectiveDescription = 'Task body for one scheduled run in this conversation. State what that run should do with enough task context. ' +
|
|
13
14
|
'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.';
|
|
14
|
-
server.registerTool(
|
|
15
|
+
server.registerTool(NODE_MCP.schedule.tools.get, {
|
|
15
16
|
description: 'Read the MAR scheduled task bound to this MAR-managed Workspace conversation, or null if none exists. ' +
|
|
16
17
|
scopeNote
|
|
17
|
-
}, async () => result(await request(
|
|
18
|
+
}, async () => result(await request(NODE_MCP.schedule.tools.get, {})));
|
|
18
19
|
if (process.env['MAR_SCHEDULE_MCP_READ_ONLY'] !== '1') {
|
|
19
|
-
server.registerTool(
|
|
20
|
+
server.registerTool(NODE_MCP.schedule.tools.create, {
|
|
20
21
|
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
22
|
scopeNote,
|
|
22
23
|
inputSchema: {
|
|
@@ -27,8 +28,8 @@ if (process.env['MAR_SCHEDULE_MCP_READ_ONLY'] !== '1') {
|
|
|
27
28
|
.max(64)
|
|
28
29
|
.describe('Five-field cron expression interpreted in the connected MAR Node time zone. It defines the schedule separately from the per-run task body.')
|
|
29
30
|
}
|
|
30
|
-
}, async (args) => result(await request(
|
|
31
|
-
server.registerTool(
|
|
31
|
+
}, async (args) => result(await request(NODE_MCP.schedule.tools.create, args)));
|
|
32
|
+
server.registerTool(NODE_MCP.schedule.tools.update, {
|
|
32
33
|
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
34
|
scopeNote,
|
|
34
35
|
inputSchema: {
|
|
@@ -40,7 +41,7 @@ if (process.env['MAR_SCHEDULE_MCP_READ_ONLY'] !== '1') {
|
|
|
40
41
|
.describe('Replacement five-field cron expression in the connected MAR Node time zone.')
|
|
41
42
|
.optional()
|
|
42
43
|
}
|
|
43
|
-
}, async (args) => result(await request(
|
|
44
|
+
}, async (args) => result(await request(NODE_MCP.schedule.tools.update, args)));
|
|
44
45
|
}
|
|
45
46
|
await server.connect(new StdioServerTransport());
|
|
46
47
|
function request(tool, args) {
|
|
@@ -294,9 +294,9 @@ export class SessionCatalogService {
|
|
|
294
294
|
(!this.options.runnerAvailable(session.runner) ||
|
|
295
295
|
this.options.runtime.getAgentSession(session.id) !== undefined)) ||
|
|
296
296
|
(!missingCandidate &&
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
297
|
+
Number.isFinite(session.lastActivityAt) &&
|
|
298
|
+
session.lastActivityAt > 0 &&
|
|
299
|
+
session.lastActivityAt >= cutoff) ||
|
|
300
300
|
(session.pinOrder !== null && session.pinOrder !== undefined) ||
|
|
301
301
|
this.options.isWatching(session.id) ||
|
|
302
302
|
this.options.isRecovering?.(session.id) ||
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.41",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"playwright": "1.62.1",
|
|
38
38
|
"ws": "^8.21.3",
|
|
39
39
|
"zod": "4.4.3",
|
|
40
|
-
"@myagentroam/agent": "0.10.
|
|
40
|
+
"@myagentroam/agent": "0.10.41",
|
|
41
|
+
"@myagentroam/protocol": "0.10.41",
|
|
41
42
|
"@myagentroam/code-navigation": "0.10.1",
|
|
42
|
-
"@myagentroam/marctl": "0.10.7"
|
|
43
|
-
"@myagentroam/protocol": "0.10.40"
|
|
43
|
+
"@myagentroam/marctl": "0.10.7"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/ws": "^8.18.1"
|
|
File without changes
|