@myagentroam/marctl 0.10.9 → 0.10.10
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/package.json +1 -1
- package/src/i18n/en-US.mjs +26 -4
- package/src/i18n/zh-CN.mjs +24 -4
- package/src/sessions.mjs +70 -12
package/package.json
CHANGED
package/src/i18n/en-US.mjs
CHANGED
|
@@ -48,10 +48,19 @@ Usage:
|
|
|
48
48
|
{program} current [--json]
|
|
49
49
|
{program} list [--query <title>] [--parent <session-id>]
|
|
50
50
|
[--cursor <cursor>] [--limit <1..100>] [--json]
|
|
51
|
-
{program} show <session-id> [--json]
|
|
52
|
-
{program} config <session-id>
|
|
53
|
-
|
|
54
|
-
{program}
|
|
51
|
+
{program} show [<session-id>] [--json]
|
|
52
|
+
{program} config [<session-id>]
|
|
53
|
+
[--model <id>] [--effort <value>] [--json]
|
|
54
|
+
{program} rename [<session-id>] --title <name> [--json]
|
|
55
|
+
{program} schedule list [--cursor <cursor>] [--limit <1..100>] [--json]
|
|
56
|
+
{program} schedule get [<session-id>] [--json]
|
|
57
|
+
{program} schedule create [<session-id>] --cron <cron>
|
|
58
|
+
(-m <text> | --message-file <file|->) [--json]
|
|
59
|
+
{program} schedule update [<session-id>]
|
|
60
|
+
--expected-revision <revision>
|
|
61
|
+
[--cron <cron>] [-m <text> | --message-file <file|->] [--json]
|
|
62
|
+
{program} graph [<session-id>] [--limit <1..100>] [--json]
|
|
63
|
+
{program} history [<session-id>]
|
|
55
64
|
[--cursor <cursor>] [--limit <1..100>] [--json]
|
|
56
65
|
|
|
57
66
|
{program} start --runner <runner>
|
|
@@ -72,6 +81,10 @@ Usage:
|
|
|
72
81
|
--run <run-id> --timeout <30s|5m> [--json]
|
|
73
82
|
|
|
74
83
|
Input:
|
|
84
|
+
show/config/history/graph/rename may omit the ID.
|
|
85
|
+
schedule get/create/update follow the same rule.
|
|
86
|
+
They use the current Session; without one, specify an ID explicitly.
|
|
87
|
+
send/goal/stop/wait always require an explicit Session ID.
|
|
75
88
|
Runners: mar-agent, codex, claude-code, opencode; actual capabilities apply.
|
|
76
89
|
-m / --message supplies text; it is mutually exclusive with --message-file.
|
|
77
90
|
Files use UTF-8; - reads stdin. Repeat --image for PNG/JPEG/GIF/WebP files.
|
|
@@ -80,6 +93,14 @@ Input:
|
|
|
80
93
|
Config requires model or effort; other fields and permissions are unchanged.
|
|
81
94
|
Use --effort "" for the Runner default. Active execution is not restarted.
|
|
82
95
|
|
|
96
|
+
Titles and scheduled tasks:
|
|
97
|
+
rename uses the existing title update; no parent-tree restriction.
|
|
98
|
+
It does not restart execution. schedule list reads local Workspace tasks.
|
|
99
|
+
schedule get/create/update share MCP task data.
|
|
100
|
+
Schedule text is limited to 20,000 characters; update requires cron or text.
|
|
101
|
+
Other-owner edits create PENDING proposals; scheduled callers are read-only.
|
|
102
|
+
Read the current revision before updating; a version conflict is not retried.
|
|
103
|
+
|
|
83
104
|
Reading JSON:
|
|
84
105
|
show: session.activity, session.model, session.effort,
|
|
85
106
|
session.customTitle / session.runnerTitle, runs[] (id/status),
|
|
@@ -243,6 +264,7 @@ or Server connection is required.`
|
|
|
243
264
|
sessionWaitTimeout: 'Waiting timed out; the target Run was not stopped.',
|
|
244
265
|
|
|
245
266
|
userContextUnavailable: 'This Node session has no valid marctl user authorization.',
|
|
267
|
+
sessionContextRequired: 'No current Session is available; specify a Session ID explicitly.',
|
|
246
268
|
serverUrlInvalid: 'MAR_CTL_SERVER_URL is invalid.',
|
|
247
269
|
serverUrlTransport: 'MAR_CTL_SERVER_URL must use HTTPS or loopback HTTP.',
|
|
248
270
|
serverUrlOrigin: 'MAR_CTL_SERVER_URL must be an origin without credentials or query data.',
|
package/src/i18n/zh-CN.mjs
CHANGED
|
@@ -47,10 +47,19 @@ ${configurationHelp}
|
|
|
47
47
|
{program} current [--json]
|
|
48
48
|
{program} list [--query <title>] [--parent <session-id>]
|
|
49
49
|
[--cursor <cursor>] [--limit <1..100>] [--json]
|
|
50
|
-
{program} show <session-id> [--json]
|
|
51
|
-
{program} config <session-id>
|
|
52
|
-
|
|
53
|
-
{program}
|
|
50
|
+
{program} show [<session-id>] [--json]
|
|
51
|
+
{program} config [<session-id>]
|
|
52
|
+
[--model <id>] [--effort <value>] [--json]
|
|
53
|
+
{program} rename [<session-id>] --title <name> [--json]
|
|
54
|
+
{program} schedule list [--cursor <cursor>] [--limit <1..100>] [--json]
|
|
55
|
+
{program} schedule get [<session-id>] [--json]
|
|
56
|
+
{program} schedule create [<session-id>] --cron <cron>
|
|
57
|
+
(-m <text> | --message-file <file|->) [--json]
|
|
58
|
+
{program} schedule update [<session-id>]
|
|
59
|
+
--expected-revision <revision>
|
|
60
|
+
[--cron <cron>] [-m <text> | --message-file <file|->] [--json]
|
|
61
|
+
{program} graph [<session-id>] [--limit <1..100>] [--json]
|
|
62
|
+
{program} history [<session-id>]
|
|
54
63
|
[--cursor <cursor>] [--limit <1..100>] [--json]
|
|
55
64
|
|
|
56
65
|
{program} start --runner <runner>
|
|
@@ -71,6 +80,9 @@ ${configurationHelp}
|
|
|
71
80
|
--run <run-id> --timeout <30s|5m> [--json]
|
|
72
81
|
|
|
73
82
|
输入:
|
|
83
|
+
show/config/history/graph/rename 和 schedule get/create/update 可省略 ID,
|
|
84
|
+
使用当前会话;没有当前会话时请显式指定 ID。
|
|
85
|
+
send/goal/stop/wait 始终要求显式会话 ID。
|
|
74
86
|
Runner:mar-agent、codex、claude-code、opencode,操作以实际能力为准。
|
|
75
87
|
-m / --message 直接传文本,与 --message-file 互斥;
|
|
76
88
|
文件用 UTF-8,- 从 stdin 读取。
|
|
@@ -79,6 +91,13 @@ ${configurationHelp}
|
|
|
79
91
|
config 至少指定 model 或 effort;未指定字段和权限不变。
|
|
80
92
|
--effort "" 使用 Runner 默认值,不重启当前执行。
|
|
81
93
|
|
|
94
|
+
标题与定时任务:
|
|
95
|
+
rename 复用现有标题更新,不限制 parent 树、不重启执行。
|
|
96
|
+
schedule list 读取本地 Workspace 任务,get/create/update 与 MCP 共用任务数据。
|
|
97
|
+
任务正文最多 20,000 字符;update 至少指定 cron 或正文。
|
|
98
|
+
修改其他用户的任务会生成 PENDING 提议;定时来源只读。
|
|
99
|
+
更新前读取当前 revision;版本冲突不会自动重试。
|
|
100
|
+
|
|
82
101
|
读取 JSON:
|
|
83
102
|
show:session.activity、session.model、session.effort、
|
|
84
103
|
session.customTitle / session.runnerTitle、runs[](id/status)、
|
|
@@ -230,6 +249,7 @@ ${configurationHelp}`,
|
|
|
230
249
|
sessionWaitTimeout: '等待超时,未停止目标 Run。',
|
|
231
250
|
|
|
232
251
|
userContextUnavailable: '此 Node 会话没有有效的 marctl 用户授权。',
|
|
252
|
+
sessionContextRequired: '当前上下文没有会话,请显式指定会话 ID。',
|
|
233
253
|
serverUrlInvalid: 'MAR_CTL_SERVER_URL 无效。',
|
|
234
254
|
serverUrlTransport: 'MAR_CTL_SERVER_URL 必须使用 HTTPS 或回环 HTTP。',
|
|
235
255
|
serverUrlOrigin: 'MAR_CTL_SERVER_URL 必须是不含凭据或查询参数的 Origin。',
|
package/src/sessions.mjs
CHANGED
|
@@ -5,6 +5,16 @@ import { MarctlError } from './config.mjs';
|
|
|
5
5
|
import { createTranslator } from './i18n/index.mjs';
|
|
6
6
|
|
|
7
7
|
const terminal = new Set(['SUCCEEDED', 'FAILED', 'CANCELLED', 'INTERRUPTED']);
|
|
8
|
+
const currentSessionActions = new Set([
|
|
9
|
+
'show',
|
|
10
|
+
'config',
|
|
11
|
+
'history',
|
|
12
|
+
'graph',
|
|
13
|
+
'rename',
|
|
14
|
+
'schedule.get',
|
|
15
|
+
'schedule.create',
|
|
16
|
+
'schedule.update'
|
|
17
|
+
]);
|
|
8
18
|
const commands = {
|
|
9
19
|
current: [],
|
|
10
20
|
list: ['cursor', 'limit', 'query', 'parent'],
|
|
@@ -22,6 +32,11 @@ const commands = {
|
|
|
22
32
|
'client-message-id'
|
|
23
33
|
],
|
|
24
34
|
config: ['model', 'effort'],
|
|
35
|
+
rename: ['title'],
|
|
36
|
+
'schedule.list': ['cursor', 'limit'],
|
|
37
|
+
'schedule.get': [],
|
|
38
|
+
'schedule.create': ['cron', 'message', 'message-file'],
|
|
39
|
+
'schedule.update': ['cron', 'message', 'message-file', 'expected-revision'],
|
|
25
40
|
send: ['message', 'message-file', 'image', 'steer', 'queue', 'client-message-id'],
|
|
26
41
|
stop: ['run'],
|
|
27
42
|
'goal.get': [],
|
|
@@ -31,6 +46,7 @@ const commands = {
|
|
|
31
46
|
};
|
|
32
47
|
const fieldNames = {
|
|
33
48
|
parent: 'parentSessionId',
|
|
49
|
+
'expected-revision': 'expectedRevision',
|
|
34
50
|
'message-file': 'messageFile',
|
|
35
51
|
'client-message-id': 'clientMessageId',
|
|
36
52
|
run: 'runId',
|
|
@@ -51,13 +67,17 @@ export function parseSessionArgs(argv, translate = createTranslator()) {
|
|
|
51
67
|
return { command: 'sessions', help: true };
|
|
52
68
|
const input = [...argv];
|
|
53
69
|
let action = input.shift();
|
|
54
|
-
if (action === 'goal') action += '.' + input.shift();
|
|
70
|
+
if (action === 'goal' || action === 'schedule') action += '.' + input.shift();
|
|
55
71
|
if (!Object.hasOwn(commands, action)) throw invalid();
|
|
56
72
|
const args = { command: 'sessions', action };
|
|
57
|
-
if (!['current', 'list', 'start'].includes(action)) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
73
|
+
if (!['current', 'list', 'start', 'schedule.list'].includes(action)) {
|
|
74
|
+
if ((input[0] === undefined || input[0].startsWith('-')) && !currentSessionActions.has(action))
|
|
75
|
+
throw invalid();
|
|
76
|
+
if (input[0] !== undefined && !input[0].startsWith('-')) {
|
|
77
|
+
const sessionId = input.shift();
|
|
78
|
+
if (!sessionId || sessionId.length > 512) throw invalid();
|
|
79
|
+
args.sessionId = sessionId;
|
|
80
|
+
}
|
|
61
81
|
}
|
|
62
82
|
while (input.length > 0) {
|
|
63
83
|
const rawFlag = input.shift();
|
|
@@ -86,8 +106,13 @@ export function parseSessionArgs(argv, translate = createTranslator()) {
|
|
|
86
106
|
if (name === 'image') {
|
|
87
107
|
(args.images ??= []).push(value);
|
|
88
108
|
if (args.images.length > 5) throw invalid();
|
|
89
|
-
} else if (name === 'limit') {
|
|
90
|
-
if (
|
|
109
|
+
} else if (name === 'limit' || name === 'expected-revision') {
|
|
110
|
+
if (
|
|
111
|
+
!/^[1-9][0-9]*$/u.test(value) ||
|
|
112
|
+
!Number.isSafeInteger(Number(value)) ||
|
|
113
|
+
(name === 'limit' && Number(value) > 100)
|
|
114
|
+
)
|
|
115
|
+
throw invalid();
|
|
91
116
|
args[key] = Number(value);
|
|
92
117
|
} else if (name === 'timeout') {
|
|
93
118
|
const match = /^([1-9][0-9]*)(ms|s|m)$/u.exec(value);
|
|
@@ -100,7 +125,7 @@ export function parseSessionArgs(argv, translate = createTranslator()) {
|
|
|
100
125
|
throw invalid('errors.sessionDeliveryRequired');
|
|
101
126
|
if (args.message !== undefined && args.messageFile !== undefined) throw invalid();
|
|
102
127
|
if (
|
|
103
|
-
['start', 'send', 'goal.set'].includes(action) &&
|
|
128
|
+
['start', 'send', 'goal.set', 'schedule.create'].includes(action) &&
|
|
104
129
|
args.messageFile === undefined &&
|
|
105
130
|
args.message === undefined &&
|
|
106
131
|
!args.images?.length
|
|
@@ -113,17 +138,37 @@ export function parseSessionArgs(argv, translate = createTranslator()) {
|
|
|
113
138
|
throw invalid();
|
|
114
139
|
if (action === 'wait' && (args.runId === undefined || args.timeoutMs === undefined))
|
|
115
140
|
throw invalid();
|
|
141
|
+
if (action === 'rename' && args.title !== undefined) args.title = args.title.trim();
|
|
116
142
|
if (args.title !== undefined && args.title.length > 160) throw invalid();
|
|
117
143
|
if (args.model !== undefined && (args.model.trim().length === 0 || args.model.length > 120))
|
|
118
144
|
throw invalid();
|
|
119
145
|
if (args.effort !== undefined && args.effort.length > 120) throw invalid();
|
|
120
146
|
if (action === 'config' && args.model === undefined && args.effort === undefined) throw invalid();
|
|
147
|
+
if (action === 'rename') {
|
|
148
|
+
if (args.title === undefined || args.title.trim().length === 0) throw invalid();
|
|
149
|
+
}
|
|
150
|
+
if (action === 'schedule.create' && args.cron === undefined) throw invalid();
|
|
151
|
+
if (args.cron !== undefined && (args.cron.trim().length === 0 || args.cron.length > 512))
|
|
152
|
+
throw invalid();
|
|
153
|
+
if (
|
|
154
|
+
action === 'schedule.update' &&
|
|
155
|
+
(args.expectedRevision === undefined ||
|
|
156
|
+
(args.cron === undefined && args.message === undefined && args.messageFile === undefined))
|
|
157
|
+
)
|
|
158
|
+
throw invalid();
|
|
121
159
|
if (args.query !== undefined && args.query.length > 160) throw invalid();
|
|
122
160
|
if (args.parentSessionId !== undefined && args.parentSessionId.length > 512) throw invalid();
|
|
123
161
|
return args;
|
|
124
162
|
}
|
|
125
163
|
|
|
126
164
|
export async function runSessionCommand({ args, client, env, stdin, WebSocketClass, translate }) {
|
|
165
|
+
const targeted = !['current', 'list', 'start', 'schedule.list'].includes(args.action);
|
|
166
|
+
const sessionId =
|
|
167
|
+
args.sessionId ?? (currentSessionActions.has(args.action) ? env.MAR_CTL_SESSION_ID : undefined);
|
|
168
|
+
if (targeted && !sessionId)
|
|
169
|
+
throw new MarctlError(translate('errors.sessionContextRequired'), {
|
|
170
|
+
code: 'MARCTL_SESSION_CONTEXT_REQUIRED'
|
|
171
|
+
});
|
|
127
172
|
if (args.action === 'wait') {
|
|
128
173
|
const controller = new AbortController();
|
|
129
174
|
const cancel = () => controller.abort();
|
|
@@ -132,7 +177,7 @@ export async function runSessionCommand({ args, client, env, stdin, WebSocketCla
|
|
|
132
177
|
try {
|
|
133
178
|
return await waitForSessionRun({
|
|
134
179
|
client,
|
|
135
|
-
sessionId
|
|
180
|
+
sessionId,
|
|
136
181
|
runId: args.runId,
|
|
137
182
|
timeoutMs: args.timeoutMs,
|
|
138
183
|
WebSocketClass,
|
|
@@ -155,9 +200,12 @@ export async function runSessionCommand({ args, client, env, stdin, WebSocketCla
|
|
|
155
200
|
'cursor',
|
|
156
201
|
'limit',
|
|
157
202
|
'query',
|
|
158
|
-
'runId'
|
|
203
|
+
'runId',
|
|
204
|
+
'cron',
|
|
205
|
+
'expectedRevision'
|
|
159
206
|
])
|
|
160
207
|
if (args[name] !== undefined) body[name] = args[name];
|
|
208
|
+
if (targeted) body.sessionId = sessionId;
|
|
161
209
|
if (args.action === 'current' && env.MAR_CTL_SESSION_ID) body.sessionId = env.MAR_CTL_SESSION_ID;
|
|
162
210
|
if (args.action === 'start' && env.MAR_CTL_SESSION_ID)
|
|
163
211
|
body.parentSessionId = env.MAR_CTL_SESSION_ID;
|
|
@@ -167,7 +215,7 @@ export async function runSessionCommand({ args, client, env, stdin, WebSocketCla
|
|
|
167
215
|
body.content = await messageContent(
|
|
168
216
|
args,
|
|
169
217
|
stdin,
|
|
170
|
-
args.action === 'goal.set' ? 20000 : 100000,
|
|
218
|
+
args.action === 'goal.set' || args.action.startsWith('schedule.') ? 20000 : 100000,
|
|
171
219
|
translate
|
|
172
220
|
);
|
|
173
221
|
if (args.images !== undefined) {
|
|
@@ -189,7 +237,17 @@ export async function runSessionCommand({ args, client, env, stdin, WebSocketCla
|
|
|
189
237
|
} catch (error) {
|
|
190
238
|
if (body.clientMessageId !== undefined) error.clientMessageId = body.clientMessageId;
|
|
191
239
|
if (
|
|
192
|
-
[
|
|
240
|
+
[
|
|
241
|
+
'start',
|
|
242
|
+
'send',
|
|
243
|
+
'config',
|
|
244
|
+
'rename',
|
|
245
|
+
'schedule.create',
|
|
246
|
+
'schedule.update',
|
|
247
|
+
'stop',
|
|
248
|
+
'goal.set',
|
|
249
|
+
'goal.clear'
|
|
250
|
+
].includes(args.action) &&
|
|
193
251
|
['MARCTL_REQUEST_TIMEOUT', 'MARCTL_SERVER_UNREACHABLE', 'MARCTL_RESPONSE_INVALID'].includes(
|
|
194
252
|
error.code
|
|
195
253
|
)
|