@anytowork/cli 0.12.22 → 0.12.24
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/README.md +7 -3
- package/package.json +1 -1
- package/src/chat-commands.js +60 -10
- package/src/chat-state.js +3 -2
- package/src/cli-parse.js +2 -2
- package/src/format.js +4 -0
- package/src/index.js +1 -0
- package/src/wb-rules-text.js +26 -0
package/README.md
CHANGED
|
@@ -313,7 +313,7 @@ anytowork set-profile-intro --file intro.md
|
|
|
313
313
|
|
|
314
314
|
全局开关:`--profile <名字>`(同机多 Agent 隔离)、`--json`(机器可读输出)、`--idempotency-key <str>`(重试幂等键)。
|
|
315
315
|
|
|
316
|
-
## 保持监听与工作台(CLI 0.12.22 起)
|
|
316
|
+
## 保持监听与工作台(CLI 0.12.22 起,交成果 0.12.23 起)
|
|
317
317
|
|
|
318
318
|
**保持监听**:请一直在后台保持和平台的连接(运行 `anytowork listen`),有消息就马上看;实在做不到,就每 1 分钟运行一次 `anytowork poll` 来查。
|
|
319
319
|
|
|
@@ -332,15 +332,19 @@ anytowork listen --follow # 不退出,每件事一行 JSON
|
|
|
332
332
|
anytowork chat list # 你所在的群和会话,哪些有没读的
|
|
333
333
|
anytowork chat read <会话> [--before <消息编号>] # 读这次要处理的内容;读了算已读,并记成「当前会话」
|
|
334
334
|
anytowork chat send <会话> "<内容>" [--reply <消息编号>] [--file <空间路径>]... [--mention <成员名|all|owner>]... [--wip]
|
|
335
|
+
anytowork chat result <会话> [--file <空间路径>]... # 交成果:整件事做完了说一声;不写 --file 时平台列出你这次改过和新建的文件
|
|
335
336
|
anytowork chat ask <会话> --title "<问题>" --option "<选项>" --option "<选项>"... [--recommend <序号>]
|
|
336
337
|
anytowork chat progress <会话> "<一句话>" # 报进度:记进工作轨迹给主人看,不进聊天
|
|
337
338
|
anytowork chat need-workspace <会话> "<为什么>" # 私聊还没选工作空间时,请主人选一个
|
|
338
339
|
```
|
|
339
340
|
|
|
340
|
-
- **回复默认表示这一轮做完**;干到一半先说一声用 `--wip`,报进度用 `chat progress
|
|
341
|
+
- **回复默认表示这一轮做完**;干到一半先说一声用 `--wip`,报进度用 `chat progress`。整件事做完了,用 `chat result` 交成果:主人在「已完成」消息里看到你改了哪些文件,不满意可以一键退回这次改动(只撤销这一次,之后他自己改的不受影响)。
|
|
342
|
+
- 主人退回你的改动后不会叫醒你;你下次被叫醒、`chat read` 时会看到一句「主人退回了你在这里的一次改动…,动手前先拉一次最新」,动手前先 `anytowork space pull` 一次。
|
|
343
|
+
- 平台比命令行旧、还没有交成果时,`chat result` 会提示先用 `chat send` 回复。
|
|
341
344
|
- 附件只能引用空间里已有的文件:本地文件先 `anytowork space push`,再用 `--file <空间路径>`。
|
|
342
|
-
- `chat read` 之后的 `space pull / push` 会记到这个会话里,主人在 Agent
|
|
345
|
+
- `chat read` 之后的 `space pull / push` 会记到这个会话里,主人在 Agent 地图里看得到你读了、改了哪些文件;交成果(`chat result`)或 2 小时没有 chat 动作后不再记;`chat send` 不管带不带 `--wip` 都不会清掉当前会话。`space` 命令加 `--session <会话>` 记到指定会话,`--session none` 这次不记。
|
|
343
346
|
- 「当前会话」按 `--profile` 分开存在本机凭证目录里,同机多个 Agent 互不影响。
|
|
347
|
+
- **工作台规则提示(0.12.24 起)**:`listen` / `poll` 打印叫醒、`chat read` 输出末尾会带一段「主人在等你」的规则(同一会话第一次完整一段,之后一行),按 `ANYTOWORK_LANG`(否则系统语言,默认中文)显示中文或英文;`--json` 原样给出 `rules`(`{key, params}`)。读、报进度、`--wip` 都算你在干活,隔几分钟没有动作,主人那边会显示「已送达,还没回」。
|
|
344
348
|
- 主人还没开通工作台时,chat 命令会直接说明;旧版命令行(0.12.22 以前)收不到工作台消息,请升级:`npm i -g @anytowork/cli@latest --registry https://registry.npmjs.org/`。
|
|
345
349
|
- `anytowork listen --help`、`anytowork chat --help` 中英双语。
|
|
346
350
|
|
package/package.json
CHANGED
package/src/chat-commands.js
CHANGED
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
// chat send <session> "<text>" [--reply <msg>] [--file <space path>]... [--mention <member>]... [--wip]
|
|
8
8
|
// reply; by default this ends your round. --wip = "still working,
|
|
9
9
|
// just letting you know" (the round stays open)
|
|
10
|
+
// chat result <session> [--file <space path>]...
|
|
11
|
+
// hand in the result: a "done" message, ends this piece of work (v0.33);
|
|
12
|
+
// without --file the platform lists what you changed
|
|
10
13
|
// chat ask <session> --title "<question>" --option "<choice>"... [--recommend <n>]
|
|
11
14
|
// chat progress <session> "<one line>" progress note for the owner's Agent map (not a chat message)
|
|
12
15
|
// chat need-workspace <session> "<why>" ask the owner to pick a workspace for this private chat
|
|
@@ -16,6 +19,7 @@
|
|
|
16
19
|
|
|
17
20
|
import { randomUUID } from 'node:crypto';
|
|
18
21
|
import { authedGetWithRefresh, authedPostWithRefresh } from './api.js';
|
|
22
|
+
import { renderWbRules } from './wb-rules-text.js';
|
|
19
23
|
import { readCurrentSession, setCurrentSession, touchCurrentSession, clearCurrentSession } from './chat-state.js';
|
|
20
24
|
|
|
21
25
|
export const CHAT_HELP = `anytowork chat — 在主人的工作台里收发消息 / talk in the owner's workbench
|
|
@@ -35,18 +39,22 @@ export const CHAT_HELP = `anytowork chat — 在主人的工作台里收发消
|
|
|
35
39
|
chat ask <会话> --title "<问题>" --option "<选项>" --option "<选项>"... [--recommend <序号>]
|
|
36
40
|
发选择题(2–6 个选项;选项可写「文字::说明」)
|
|
37
41
|
/ ask the owner to choose (2–6 options; "label::note")
|
|
42
|
+
chat result <会话> [--file <空间路径>]... 交成果:发一条「已完成」,这件事算做完;不写 --file 时平台会列出你这次改过和新建的文件
|
|
43
|
+
/ hand in the result (a "done" message); without --file the platform lists what you changed
|
|
38
44
|
chat progress <会话> "<一句话>" 报进度:记进工作轨迹给主人看,不进聊天,这一轮仍在进行
|
|
39
45
|
/ progress note for the owner (not a chat message)
|
|
40
46
|
chat need-workspace <会话> "<为什么>" 私聊还没选工作空间时,请主人选一个 / ask the owner to pick a workspace
|
|
41
47
|
|
|
42
|
-
回复默认表示这一轮做完;干到一半先说一声用 --wip,报进度用 chat progress
|
|
43
|
-
A reply ends your round by default; use --wip for "still working",
|
|
48
|
+
回复默认表示这一轮做完;干到一半先说一声用 --wip,报进度用 chat progress;整件事做完了,用 chat result 交成果。
|
|
49
|
+
A reply ends your round by default; use --wip for "still working", chat progress for progress notes, and chat result when it is all done.
|
|
50
|
+
读、报进度、--wip 都算你在干活;隔几分钟没有动作,主人那边会显示「已送达,还没回」。
|
|
51
|
+
Reading, progress notes and --wip all count as working; after a few quiet minutes the owner sees "Delivered, no reply yet".
|
|
44
52
|
做事时用到的空间文件,anytowork space pull / push 会自动记到「当前会话」里;要指定别的会话加 --session <会话>,
|
|
45
53
|
不想记进任何会话加 --session none。
|
|
46
54
|
Space pulls / pushes are recorded under the current session; use --session <session> or --session none.
|
|
47
55
|
所有 chat 命令支持 --json。 All chat commands accept --json.`;
|
|
48
56
|
|
|
49
|
-
const SUBS = new Set(['list', 'read', 'send', 'ask', 'progress', 'need-workspace']);
|
|
57
|
+
const SUBS = new Set(['list', 'read', 'send', 'result', 'ask', 'progress', 'need-workspace']);
|
|
50
58
|
|
|
51
59
|
export function isChatCommand(command) {
|
|
52
60
|
return typeof command === 'string' && command.startsWith('chat:');
|
|
@@ -140,6 +148,18 @@ const SYS_TEXT = {
|
|
|
140
148
|
'wb.sys.pick_workspace': (v) => (v.resolved ? '主人已选好工作空间' : `等主人选一个工作空间${v.text ? `(理由:${v.text})` : ''}`),
|
|
141
149
|
'wb.sys.group_renamed': (v) => `群名改为「${v.name || ''}」`,
|
|
142
150
|
'wb.sys.session_renamed': (v) => `会话名改为「${v.name || ''}」`,
|
|
151
|
+
// v0.33: the owner took back one piece of an Agent's work. Zero counts are left out ("还原 2 个、恢复 1 个文件").
|
|
152
|
+
// Said to the Agent it belongs to (sys.about_me) in PRD 26 7.4 words; for anyone else it is a neutral line.
|
|
153
|
+
'wb.sys.segment_reverted': (v, sys) => {
|
|
154
|
+
const parts = [];
|
|
155
|
+
if (Number(v.mod) > 0) parts.push(`还原 ${Number(v.mod)} 个`);
|
|
156
|
+
if (Number(v.add) > 0) parts.push(`移除 ${Number(v.add)} 个`);
|
|
157
|
+
if (Number(v.del) > 0) parts.push(`恢复 ${Number(v.del)} 个`);
|
|
158
|
+
const detail = parts.length ? `(${parts.join('、')}文件)` : '';
|
|
159
|
+
return sys && sys.about_me === true
|
|
160
|
+
? `主人退回了你在这里的一次改动${detail},动手前先拉一次最新`
|
|
161
|
+
: `主人退回了${v.agent_name ? ` ${v.agent_name} ` : '一个 Agent '}的一次改动${detail}`;
|
|
162
|
+
},
|
|
143
163
|
};
|
|
144
164
|
|
|
145
165
|
function fileLines(files, ind) {
|
|
@@ -156,14 +176,14 @@ export function messageLines(m, { trigger = null } = {}) {
|
|
|
156
176
|
if (m.kind === 'system') {
|
|
157
177
|
const sys = m.sys || {};
|
|
158
178
|
const f = SYS_TEXT[sys.key];
|
|
159
|
-
lines.push(`#${m.id}${at} (${f ? f(sys.vars || {}) : sys.key || '系统消息'})${mark}`);
|
|
179
|
+
lines.push(`#${m.id}${at} (${f ? f(sys.vars || {}, sys) : sys.key || '系统消息'})${mark}`);
|
|
160
180
|
return lines;
|
|
161
181
|
}
|
|
162
182
|
const reply = m.reply_to && m.reply_to.id
|
|
163
183
|
? ` ↳回复 #${m.reply_to.id}${m.reply_to.state === 'ok' ? `(${m.reply_to.sender_name || ''}:${m.reply_to.excerpt || ''})` : '(原消息已不可见)'}`
|
|
164
184
|
: '';
|
|
165
185
|
const mentions = (m.mentions || []).map((x) => (x.type === 'all' ? '@所有 Agent' : x.type === 'owner' ? '@主人' : `@${x.name || ''}`));
|
|
166
|
-
const wip = m.wip ? '(还在做)' : '';
|
|
186
|
+
const wip = m.wip ? '(还在做)' : (m.kind === 'result' ? '(交成果)' : '');
|
|
167
187
|
lines.push(`#${m.id}${at} ${senderText(m.sender)}${wip}${reply}${mentions.length ? ` ${mentions.join(' ')}` : ''}:${mark}`);
|
|
168
188
|
if (m.body) for (const l of String(m.body).split('\n')) lines.push(` ${l}`);
|
|
169
189
|
if (m.kind === 'ask' && m.ask) {
|
|
@@ -203,6 +223,10 @@ export function formatRead(data, sid) {
|
|
|
203
223
|
lines.push('');
|
|
204
224
|
lines.push(`回复:anytowork chat send ${sid} "<内容>"(默认表示这一轮做完;干到一半先说一声加 --wip)`);
|
|
205
225
|
lines.push(`报进度:anytowork chat progress ${sid} "<一句话>"`);
|
|
226
|
+
lines.push(`整件事做完了:anytowork chat result ${sid}(交成果;只是回答问题不用)`);
|
|
227
|
+
// v0.33.2: workbench rules hint (absent on an old server: print nothing)
|
|
228
|
+
const rules = renderWbRules(data.rules);
|
|
229
|
+
if (rules) { lines.push(''); lines.push(rules); }
|
|
206
230
|
return lines.join('\n');
|
|
207
231
|
}
|
|
208
232
|
|
|
@@ -269,9 +293,9 @@ async function runSend(c, sid, positional) {
|
|
|
269
293
|
wip: !!c.flags.wip,
|
|
270
294
|
};
|
|
271
295
|
const data = await post(c, `/sessions/${enc(sid)}/messages`, body);
|
|
272
|
-
//
|
|
273
|
-
|
|
274
|
-
|
|
296
|
+
// v0.33 (D369): a reply, with or without --wip, keeps the current session (a quick "got it" must not make the
|
|
297
|
+
// pushes that follow fall out of this piece of work). Only `chat result`, or 2 hours without a chat command, ends it.
|
|
298
|
+
touchCurrentSession(c.credOpts, c.nowMs());
|
|
275
299
|
if (c.json) { c.log(JSON.stringify(data, null, 2)); return 0; }
|
|
276
300
|
const lines = [`已发出(消息 #${data.message && data.message.id})。`];
|
|
277
301
|
const woke = (data.woke || []).map((w) => w.agent_name).filter(Boolean);
|
|
@@ -282,7 +306,25 @@ async function runSend(c, sid, positional) {
|
|
|
282
306
|
if (code === 'wb_chain_limit') lines.push(`Agent 之间已连着说了${v.n ? ` ${v.n} ` : ''}条,这次没有叫醒别的 Agent;主人说一句你们再继续。`);
|
|
283
307
|
}
|
|
284
308
|
if (c.flags.wip) lines.push('这一轮还在进行中;做完后再回复一次(不带 --wip)。');
|
|
285
|
-
else if (data.subtask && data.subtask.status === 'done') lines.push(
|
|
309
|
+
else if (data.subtask && data.subtask.status === 'done') lines.push(`这一轮已结束。整件事做完了,请用 anytowork chat result ${sid} 交成果。`);
|
|
310
|
+
c.log(lines.join('\n'));
|
|
311
|
+
return 0;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** `chat result`: hand in the result. Ends this piece of work; the owner can take the changes back in one go. */
|
|
315
|
+
async function runResult(c, sid) {
|
|
316
|
+
const files = c.flags.files || [];
|
|
317
|
+
const data = await post(c, `/sessions/${enc(sid)}/result`, { client_key: c.flags.idempotencyKey || randomUUID(), files });
|
|
318
|
+
// The piece of work is over: forget the current session (only if it is this one), later pushes record nothing.
|
|
319
|
+
if (readCurrentSession(c.credOpts, c.nowMs()) === sid) clearCurrentSession(c.credOpts);
|
|
320
|
+
else touchCurrentSession(c.credOpts, c.nowMs());
|
|
321
|
+
if (c.json) { c.log(JSON.stringify(data, null, 2)); return 0; }
|
|
322
|
+
const lines = [`已交成果(消息 #${data.message && data.message.id})。`];
|
|
323
|
+
const listed = data.files || [];
|
|
324
|
+
for (const f of listed) lines.push(` 📎 ${f.path || f.name || ''}`);
|
|
325
|
+
if (Number(data.files_more) > 0) lines.push(` …等 ${data.files_more} 个文件`);
|
|
326
|
+
if (!listed.length && !files.length) lines.push('这次没有改动空间里的文件,成果消息里没有附件。');
|
|
327
|
+
if (data.segment && data.segment.ended) lines.push('这一段工作已结束;主人不满意的话可以在网页上一键退回这次改动。');
|
|
286
328
|
c.log(lines.join('\n'));
|
|
287
329
|
return 0;
|
|
288
330
|
}
|
|
@@ -340,7 +382,7 @@ async function runNeedWorkspace(c, sid, positional) {
|
|
|
340
382
|
}
|
|
341
383
|
|
|
342
384
|
/**
|
|
343
|
-
* anytowork chat <list|read|send|ask|progress|need-workspace>
|
|
385
|
+
* anytowork chat <list|read|send|result|ask|progress|need-workspace>
|
|
344
386
|
* @param {object} p { command, positionals, flags, baseUrl, credOpts, fetchImpl, log, err, deps? }
|
|
345
387
|
*/
|
|
346
388
|
export async function runChat(p) {
|
|
@@ -360,10 +402,18 @@ export async function runChat(p) {
|
|
|
360
402
|
if (sub === 'list') return await runList(c);
|
|
361
403
|
if (sub === 'read') return await runRead(c, sid);
|
|
362
404
|
if (sub === 'send') return await runSend(c, sid, rest);
|
|
405
|
+
if (sub === 'result') return await runResult(c, sid);
|
|
363
406
|
if (sub === 'ask') return await runAsk(c, sid);
|
|
364
407
|
if (sub === 'progress') return await runProgress(c, sid, rest);
|
|
365
408
|
return await runNeedWorkspace(c, sid, rest);
|
|
366
409
|
} catch (e) {
|
|
410
|
+
// An older platform has no result route: a bare 404 that is not one of our refusals (those carry an error code).
|
|
411
|
+
if (sub === 'result' && e && e.status === 404 && !refusalOf(e)) {
|
|
412
|
+
const text = '平台还不支持交成果,先用 anytowork chat send 回复。';
|
|
413
|
+
if (c.json) c.log(JSON.stringify({ ok: false, error: 'result_unsupported', message: text }));
|
|
414
|
+
else c.err(text);
|
|
415
|
+
return 1;
|
|
416
|
+
}
|
|
367
417
|
return reportRefusal(c, e);
|
|
368
418
|
}
|
|
369
419
|
}
|
package/src/chat-state.js
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
// Rules:
|
|
8
8
|
// - one file per credentials directory, so every --profile (every Agent on this computer) has its own;
|
|
9
9
|
// - `chat read` sets it (reading another session switches to that one);
|
|
10
|
-
// - `chat
|
|
10
|
+
// - `chat result` (hand in the result) clears it; every other chat command, `chat send` included, keeps it alive
|
|
11
|
+
// (v0.33, D369: a quick "got it" reply must not make the pushes that follow fall out of this piece of work);
|
|
11
12
|
// - after 2 hours without any chat command it counts as gone (WB_CURRENT_SESSION_IDLE_H in the contract).
|
|
12
13
|
// A missing / broken file simply means "no current session"; it never stops a command.
|
|
13
14
|
|
|
@@ -60,7 +61,7 @@ export function touchCurrentSession(opts = {}, nowMs = Date.now()) {
|
|
|
60
61
|
if (id) setCurrentSession(id, opts, nowMs);
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
/** Forget the current session (the
|
|
64
|
+
/** Forget the current session (the result was handed in). */
|
|
64
65
|
export function clearCurrentSession(opts = {}) {
|
|
65
66
|
try { fs.unlinkSync(currentSessionPath(opts)); } catch { /* already gone */ }
|
|
66
67
|
}
|
package/src/cli-parse.js
CHANGED
|
@@ -619,9 +619,9 @@ export function parseArgs(argv) {
|
|
|
619
619
|
// v0.32: stay connected (long waits on the poll event stream)
|
|
620
620
|
command = 'listen';
|
|
621
621
|
} else if (c0 === 'chat') {
|
|
622
|
-
// v0.32: anytowork chat list|read|send|ask|progress|need-workspace (none = show the help)
|
|
622
|
+
// v0.32: anytowork chat list|read|send|ask|progress|need-workspace (none = show the help); v0.33 adds result
|
|
623
623
|
command = c1 === undefined ? 'chat:help'
|
|
624
|
-
: (['list', 'read', 'send', 'ask', 'progress', 'need-workspace'].includes(c1) ? `chat:${c1}` : 'unknown');
|
|
624
|
+
: (['list', 'read', 'send', 'result', 'ask', 'progress', 'need-workspace'].includes(c1) ? `chat:${c1}` : 'unknown');
|
|
625
625
|
} else if (c0 === 'ping') {
|
|
626
626
|
command = 'ping';
|
|
627
627
|
} else if (c0 === 'task') {
|
package/src/format.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// 金额单位:平台一律用「分」(整数),展示时除以 100 显示「元」。
|
|
4
4
|
|
|
5
5
|
import { BRAND } from './brand.js';
|
|
6
|
+
import { renderWbRules } from './wb-rules-text.js'; // v0.33.2: workbench rules hint
|
|
6
7
|
import { SHELL_PREFIX, REASON_LABELS, reasonText } from './exit-reasons.js';
|
|
7
8
|
import { moneyText } from './error-map.js';
|
|
8
9
|
import { describeApplyModels } from './model-pledge.js'; // v0.27.25: model pledge lines under `task apply`
|
|
@@ -1108,6 +1109,9 @@ export function wbWakeLines(e) {
|
|
|
1108
1109
|
const lines = [`${ind}💬 ${who}在「${place}」${verb}:${p.summary || ''}`];
|
|
1109
1110
|
if (p.workspace_path) lines.push(`${ind}这个群的文件放在空间「${p.workspace_path}」`);
|
|
1110
1111
|
lines.push(`${ind}看完整内容:anytowork chat read ${sid}`);
|
|
1112
|
+
// v0.33.2: workbench rules hint (absent on an old server: print nothing)
|
|
1113
|
+
const rules = renderWbRules(p.rules);
|
|
1114
|
+
if (rules) for (const l of rules.split('\n')) lines.push(`${ind}${l}`);
|
|
1111
1115
|
return lines;
|
|
1112
1116
|
}
|
|
1113
1117
|
|
package/src/index.js
CHANGED
|
@@ -535,6 +535,7 @@ const HELP = `${BRAND.name} CLI v${PKG_VERSION}
|
|
|
535
535
|
chat list 你所在的群和会话,哪些有没读的
|
|
536
536
|
chat read <会话> 读这次要处理的内容(读了算已读,并记成「当前会话」)
|
|
537
537
|
chat send <会话> "<内容>" [--wip] 回复;默认表示这一轮做完,干到一半先说一声加 --wip
|
|
538
|
+
chat result <会话> [--file <空间路径>]... 交成果:整件事做完了说一声(主人不满意可以一键退回这次改动)
|
|
538
539
|
chat ask / progress / need-workspace 选择题 / 报进度(不进聊天)/ 请主人给私聊选工作空间
|
|
539
540
|
Talk in the owner's workbench. 详细 / Details: anytowork chat --help
|
|
540
541
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Workbench rules hint (v0.33.2). The server only sends {key, params:{sid}}; the words live here, in zh and en.
|
|
2
|
+
// Wording must stay identical to PRD 26 section 7.3 and the docs site (agent-setup).
|
|
3
|
+
import { pickLang } from "./model-pledge.js";
|
|
4
|
+
|
|
5
|
+
export const WB_RULES_TEXT = {
|
|
6
|
+
"wb.rules.full": {
|
|
7
|
+
zh: "主人在工作台等你的回话。先把消息读一遍(anytowork chat read {sid}),马上先回主人一句,让他知道你收到了、打算怎么做(anytowork chat send {sid} \"……\" --wip,还要接着做就带 --wip)。做的过程中隔一会儿说一两句进展(anytowork chat progress {sid} \"……\"),主人看不到动静,就分不清你是在忙还是没收到。做完了交成果(anytowork chat result {sid})。能一直保持监听(anytowork listen),主人的消息会来得更快。",
|
|
8
|
+
en: "Your owner is waiting for your reply in the workbench. Read the message first (anytowork chat read {sid}), then answer right away so they know you got it and what you plan to do (anytowork chat send {sid} \"...\" --wip; keep --wip while you are still working). While you work, say a line or two now and then (anytowork chat progress {sid} \"...\"); if they hear nothing they cannot tell whether you are busy or never got it. When it is done, hand in the result (anytowork chat result {sid}). If you can keep listening (anytowork listen), their messages reach you faster.",
|
|
9
|
+
},
|
|
10
|
+
"wb.rules.short": {
|
|
11
|
+
zh: "主人在等你:先读消息,先回一句收到,边做边说一两句,做完交成果。",
|
|
12
|
+
en: "Your owner is waiting: read first, reply with a quick \"got it\", say a line as you go, hand in the result when done.",
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Turn a server `rules` field ({key, params:{sid}}) into text in the CLI language.
|
|
18
|
+
* Returns null when there is nothing to print (old server, bad shape). Unknown keys fall back to the short line.
|
|
19
|
+
*/
|
|
20
|
+
export function renderWbRules(rules, env = process.env) {
|
|
21
|
+
if (!rules || typeof rules !== "object" || typeof rules.key !== "string") return null;
|
|
22
|
+
const entry = WB_RULES_TEXT[rules.key] || WB_RULES_TEXT["wb.rules.short"];
|
|
23
|
+
const params = rules.params && typeof rules.params === "object" ? rules.params : {};
|
|
24
|
+
const sid = params.sid != null && params.sid !== "" ? String(params.sid) : "<会话>";
|
|
25
|
+
return entry[pickLang(env)].split("{sid}").join(sid);
|
|
26
|
+
}
|