nx-kv 0.8.1 → 0.8.2
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/CHANGELOG.md +20 -0
- package/package.json +1 -1
- package/src/modules/localtask/index.js +18 -4
- package/src/modules/localtask/service.js +72 -11
- package/src/modules/localtask/view.jsx +127 -1
- package/src/web/public/assets/{CliHints-B0Qwrf-6.js → CliHints-DNK3TaU5.js} +1 -1
- package/src/web/public/assets/{index-D0ldg3Y8.js → index-Iz1qH6TC.js} +2 -2
- package/src/web/public/assets/{view-BIjk8I3i.js → view-7pNoeCnZ.js} +1 -1
- package/src/web/public/assets/view-CCkuLOoM.js +1 -0
- package/src/web/public/assets/{view-B9RikVKT.js → view-D_gCbqXF.js} +1 -1
- package/src/web/public/assets/{view-D1a7SUrR.js → view-Dy0w1I4l.js} +1 -1
- package/src/web/public/index.html +1 -1
- package/src/web/public/assets/view-CU5VSo_g.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
本文件记录对外可见的变更。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。
|
|
4
4
|
|
|
5
|
+
## [0.8.2] - 2026-10-12
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **实时任务 wait 返回任务时自动追加「收尾提醒」(可配置,默认开启)**,防止 agent 在长对话里
|
|
10
|
+
漂移、偶尔忘记最后再 wait 一次:
|
|
11
|
+
- wait 交付任务时在 `task.text` 末尾拼接一段固定提醒(默认大意:规划计划、完成本任务,
|
|
12
|
+
计划的最后一个动作是再次调用 `nx-kv localtask wait` 收尾本轮,拿到下一条或超时前不要提前结束)。
|
|
13
|
+
- 只作用于**返回给 agent 的载荷**,面板/库存里的任务原文保持干净、不被改写;原文已包含同样
|
|
14
|
+
追加语时幂等不重复追加。
|
|
15
|
+
- 可在「本地任务」页配置(编辑、保存、恢复默认、一键关闭),CLI/HTTP:
|
|
16
|
+
`localtask config --suffix "<文案>"`、`--no-suffix` 关闭、`--reset-suffix` 恢复默认
|
|
17
|
+
(HTTP `PATCH` 传 `"suffix": ""` 关闭);
|
|
18
|
+
`PATCH /api/localtasks/setting` 增 `suffix` 字段,设置视图增 `taskSuffix`/`defaultTaskSuffix`/`suffixEnabled`。
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- `loadStore` 重建 settings 时只保留 `timeoutSec`、把 `taskSuffix` 字段丢掉,导致
|
|
23
|
+
第一次 PATCH 关闭后第二次 PATCH 改超时,taskSuffix 会被默认值覆盖(仅 0.8.1 受影响)。
|
|
24
|
+
|
|
5
25
|
## [0.8.1] - 2026-10-12
|
|
6
26
|
|
|
7
27
|
### Added
|
package/package.json
CHANGED
|
@@ -181,10 +181,24 @@ export default {
|
|
|
181
181
|
id: 'localtask.config',
|
|
182
182
|
cli: ['localtask', 'config'],
|
|
183
183
|
http: ['PATCH', '/api/localtasks/setting'],
|
|
184
|
-
summary: '
|
|
185
|
-
flags: {
|
|
186
|
-
|
|
187
|
-
|
|
184
|
+
summary: '配置等待超时(秒)/ 收尾追加语(task.text 末尾自动追加的固定指令;置空关闭)',
|
|
185
|
+
flags: {
|
|
186
|
+
timeout: { type: 'number', hint: '超时秒数(1-600)' },
|
|
187
|
+
suffix: { type: 'string', hint: '收尾追加语文本(与 --reset-suffix/--no-suffix 互斥)' },
|
|
188
|
+
'reset-suffix': { type: 'boolean', hint: '恢复默认收尾追加语' },
|
|
189
|
+
'no-suffix': { type: 'boolean', hint: '清空并关闭收尾追加语' },
|
|
190
|
+
},
|
|
191
|
+
run: (ctx) => {
|
|
192
|
+
const patch = { timeoutSec: ctx.timeout };
|
|
193
|
+
if (ctx['no-suffix']) patch.taskSuffix = '';
|
|
194
|
+
else if (ctx['reset-suffix']) patch.taskSuffix = service.DEFAULT_TASK_SUFFIX;
|
|
195
|
+
else if (ctx.suffix !== undefined) patch.taskSuffix = ctx.suffix;
|
|
196
|
+
return service.updateSettings(patch);
|
|
197
|
+
},
|
|
198
|
+
render: (s) => {
|
|
199
|
+
const x = s.suffixEnabled ? '收尾追加语已开启' : '收尾追加语已关闭';
|
|
200
|
+
return `已配置等待超时 ${s.timeoutSec} 秒(推荐 ${s.recommendedSec},最大 ${s.maxSec})· ${x}`;
|
|
201
|
+
},
|
|
188
202
|
},
|
|
189
203
|
|
|
190
204
|
{
|
|
@@ -37,6 +37,25 @@ export const MAX_TIMEOUT_SEC = 600; // 阻塞时长上限(10 分钟)
|
|
|
37
37
|
export const MAX_SUMMARY = 2000; // 现状(状态)长度上限(原 200,已放宽)
|
|
38
38
|
export const MAX_TEXT = 20_000; // 单条任务内容长度上限
|
|
39
39
|
|
|
40
|
+
// wait 取任务返回时,在 task.text 末尾追加的「收尾指令」(可在面板/CLI 修改;置空关闭)。
|
|
41
|
+
// 作用:从每一条任务层面反复强调「计划最后再 wait 一次」,避免 agent 在长对话里漂移、漏调。
|
|
42
|
+
// 注意:命令名是 localtask 不是 sessiontask(v0.8.0 重命名后),但默认文案直接复用同一段文字。
|
|
43
|
+
export const DEFAULT_TASK_SUFFIX =
|
|
44
|
+
'规划计划,然后完成这个任务;计划的最后一个动作,是再次调用 ' +
|
|
45
|
+
'nx-kv localtask wait(带上 --cwd 当前工作目录、--summary 当前现状、--json)收尾本轮,' +
|
|
46
|
+
'在拿到下一条任务或超时之前不要提前结束。';
|
|
47
|
+
const MAX_SUFFIX_LEN = 500; // 收尾追加语长度上限
|
|
48
|
+
|
|
49
|
+
// 归一化收尾追加语:缺省(旧 store 无此字段)→ 默认;显式传 ''(清空)→ '' 表示关闭。
|
|
50
|
+
// 注意:与 timeoutSec 不同——timeoutSec 缺省→推荐值(仍开启),taskSuffix 缺省→默认文本。
|
|
51
|
+
// 因此从老 store 读 settings.taskSuffix 时,clampTaskSuffix 会自动补默认;想"关闭"必须显式 ''。
|
|
52
|
+
export function clampTaskSuffix(v) {
|
|
53
|
+
if (v === undefined || v === null) return DEFAULT_TASK_SUFFIX;
|
|
54
|
+
let s = String(v).trim();
|
|
55
|
+
if (s.length > MAX_SUFFIX_LEN) s = s.slice(0, MAX_SUFFIX_LEN);
|
|
56
|
+
return s;
|
|
57
|
+
}
|
|
58
|
+
|
|
40
59
|
// ─── 存储位置:可环境变量覆盖(测试隔离);旧名/旧文件自动兼容 ──────────
|
|
41
60
|
|
|
42
61
|
export function storePath() {
|
|
@@ -119,7 +138,11 @@ export function stampNow(d = new Date()) {
|
|
|
119
138
|
// ─── 存储读写(原子写 + 损坏容忍 + v1/v2 迁移) ───────────────────
|
|
120
139
|
|
|
121
140
|
function emptyStore() {
|
|
122
|
-
return {
|
|
141
|
+
return {
|
|
142
|
+
version: 4,
|
|
143
|
+
settings: { timeoutSec: DEFAULT_TIMEOUT_SEC, taskSuffix: DEFAULT_TASK_SUFFIX },
|
|
144
|
+
topics: {},
|
|
145
|
+
};
|
|
123
146
|
}
|
|
124
147
|
|
|
125
148
|
// 归一化超时秒数:非法/缺省 → 推荐值;超上限截断为 10 分钟
|
|
@@ -182,7 +205,14 @@ async function loadStore() {
|
|
|
182
205
|
if (!topics) return emptyStore();
|
|
183
206
|
return {
|
|
184
207
|
version: 4,
|
|
185
|
-
settings: {
|
|
208
|
+
settings: {
|
|
209
|
+
timeoutSec: clampTimeoutSec(settings && settings.timeoutSec),
|
|
210
|
+
// 旧 store 可能没存过 taskSuffix(v0.8.0 之前);clampTaskSuffix 缺省→默认文本。
|
|
211
|
+
// 显式 ''(关闭)会保留——判断条件是「字段存在且非 undefined」,不能只看 falsy。
|
|
212
|
+
taskSuffix: settings && Object.prototype.hasOwnProperty.call(settings, 'taskSuffix')
|
|
213
|
+
? clampTaskSuffix(settings.taskSuffix)
|
|
214
|
+
: DEFAULT_TASK_SUFFIX,
|
|
215
|
+
},
|
|
186
216
|
topics,
|
|
187
217
|
};
|
|
188
218
|
}
|
|
@@ -358,6 +388,10 @@ function settingsView(s) {
|
|
|
358
388
|
timeoutSec: clampTimeoutSec(s && s.timeoutSec),
|
|
359
389
|
recommendedSec: DEFAULT_TIMEOUT_SEC,
|
|
360
390
|
maxSec: MAX_TIMEOUT_SEC,
|
|
391
|
+
// wait 交付任务时追加到 task.text 末尾的收尾提醒;''=关闭;defaultTaskSuffix 供 UI 恢复默认
|
|
392
|
+
taskSuffix: clampTaskSuffix(s && s.taskSuffix),
|
|
393
|
+
defaultTaskSuffix: DEFAULT_TASK_SUFFIX,
|
|
394
|
+
suffixEnabled: !!clampTaskSuffix(s && s.taskSuffix),
|
|
361
395
|
};
|
|
362
396
|
}
|
|
363
397
|
|
|
@@ -402,14 +436,27 @@ export async function pruneTopics({ allFinished = false, dryRun = false } = {})
|
|
|
402
436
|
return { status: 'ok', dryRun: !!dryRun, count: removed.length, removed };
|
|
403
437
|
}
|
|
404
438
|
|
|
405
|
-
//
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
439
|
+
// 配置等待超时 / 任务收尾追加语(页面可调)。超时推荐 180=3 分钟、最大 600=10 分钟;
|
|
440
|
+
// taskSuffix 为 wait 返回任务时追加到 task.text 末尾的固定指令,传 '' 关闭、不传保持不变。
|
|
441
|
+
export async function updateSettings({ timeoutSec, taskSuffix } = {}) {
|
|
442
|
+
const hasTimeout = timeoutSec !== undefined && timeoutSec !== null;
|
|
443
|
+
const hasSuffix = taskSuffix !== undefined;
|
|
444
|
+
if (!hasTimeout && !hasSuffix) {
|
|
445
|
+
throw badInput(
|
|
446
|
+
'请至少指定一项:--timeout <秒>,或 --suffix "<收尾追加语>"(--no-suffix 关闭追加、--reset-suffix 恢复默认)'
|
|
447
|
+
);
|
|
410
448
|
}
|
|
411
449
|
const store = await loadStore();
|
|
412
|
-
|
|
450
|
+
const next = { ...store.settings };
|
|
451
|
+
if (hasTimeout) {
|
|
452
|
+
const n = Number(timeoutSec);
|
|
453
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
454
|
+
throw badInput(`超时时间需为 1-${MAX_TIMEOUT_SEC} 秒(推荐 ${DEFAULT_TIMEOUT_SEC})`);
|
|
455
|
+
}
|
|
456
|
+
next.timeoutSec = clampTimeoutSec(n);
|
|
457
|
+
}
|
|
458
|
+
if (hasSuffix) next.taskSuffix = clampTaskSuffix(taskSuffix);
|
|
459
|
+
store.settings = next;
|
|
413
460
|
await saveStore(store);
|
|
414
461
|
return settingsView(store.settings);
|
|
415
462
|
}
|
|
@@ -628,6 +675,16 @@ export async function reorderTasks({ cwd: rawCwd, id, beforeId, afterId } = {})
|
|
|
628
675
|
|
|
629
676
|
// ─── 阻塞等待:核心入口 ─────────────────────────────────────────────
|
|
630
677
|
|
|
678
|
+
// 把收尾追加语拼到返回给 agent 的 task.text 末尾(只改返回载荷,绝不回写库存原文)。
|
|
679
|
+
// suffix 为空 → 原样返回;已包含同样追加语(幂等)→ 不重复追加。
|
|
680
|
+
function withTaskSuffix(task, suffix) {
|
|
681
|
+
const s = clampTaskSuffix(suffix);
|
|
682
|
+
if (!task || !s) return task;
|
|
683
|
+
const base = String(task.text || '');
|
|
684
|
+
if (base.includes(s)) return task;
|
|
685
|
+
return { ...task, text: `${base.replace(/\s+$/, '')}\n\n${s}` };
|
|
686
|
+
}
|
|
687
|
+
|
|
631
688
|
/**
|
|
632
689
|
* 针对某主题(工作目录)等待用户回填下一条任务。
|
|
633
690
|
* @param {string} [cwd] 工作目录(主题按目录名识别);缺省 → 进程当前 cwd
|
|
@@ -649,15 +706,19 @@ export async function waitForTask({
|
|
|
649
706
|
const summary = normalizeSummary(rawSummary); // 现状必填
|
|
650
707
|
|
|
651
708
|
// 超时:显式 --timeout(秒/毫秒)优先;否则用页面配置;统一夹到 1-600
|
|
709
|
+
const startStore = await loadStore();
|
|
652
710
|
let sec;
|
|
653
711
|
if (timeoutSec !== undefined && timeoutSec !== null) sec = timeoutSec;
|
|
654
712
|
else if (timeoutMs !== undefined && timeoutMs !== null) sec = Number(timeoutMs) / 1000;
|
|
655
|
-
else sec =
|
|
713
|
+
else sec = startStore.settings.timeoutSec;
|
|
656
714
|
const tmo = clampTimeoutSec(sec) * 1000;
|
|
715
|
+
const suffix = startStore.settings.taskSuffix; // 返回任务时追加的收尾指令(本轮固定)
|
|
657
716
|
|
|
658
717
|
// 1. 主题队列已有 pending → 立即取走,不开窗、不阻塞;记录本轮完成总结
|
|
659
718
|
const queued = await consumeFirstPending(key, summary);
|
|
660
|
-
if (queued)
|
|
719
|
+
if (queued) {
|
|
720
|
+
return { status: 'ok', key, cwd, name, summary, task: withTaskSuffix(queued, suffix), queued: true };
|
|
721
|
+
}
|
|
661
722
|
|
|
662
723
|
// 2. 没有 pending → 起内嵌弹窗服务器
|
|
663
724
|
const server = await startPopupServer(key, cwd, summary, tmo);
|
|
@@ -722,7 +783,7 @@ export async function waitForTask({
|
|
|
722
783
|
? { status: 'timeout', key, cwd, summary, timeoutMs: tmo }
|
|
723
784
|
: r.kind === 'cancelled'
|
|
724
785
|
? { status: 'timeout', key, cwd, summary, timeoutMs: tmo, cancelled: true }
|
|
725
|
-
: { status: 'ok', key, cwd, name, summary, task: r.task, delivered: r.delivered, queued: false };
|
|
786
|
+
: { status: 'ok', key, cwd, name, summary, task: withTaskSuffix(r.task, suffix), delivered: r.delivered, queued: false };
|
|
726
787
|
} finally {
|
|
727
788
|
clearInterval(poll);
|
|
728
789
|
clearInterval(cancelPoll);
|
|
@@ -47,6 +47,13 @@ export default function SessionTaskView() {
|
|
|
47
47
|
const [timeoutSec, setTimeoutSec] = useState(180);
|
|
48
48
|
const [cfgSaving, setCfgSaving] = useState(false);
|
|
49
49
|
const [pruning, setPruning] = useState(false);
|
|
50
|
+
// 收尾追加语:task.text 末尾自动追加的固定指令(强制 agent 计划最后再 wait 一次)
|
|
51
|
+
const [taskSuffix, setTaskSuffix] = useState('');
|
|
52
|
+
const [defaultTaskSuffix, setDefaultTaskSuffix] = useState('');
|
|
53
|
+
const [suffixEnabled, setSuffixEnabled] = useState(false);
|
|
54
|
+
const [suffixEditing, setSuffixEditing] = useState(false);
|
|
55
|
+
const [suffixDraft, setSuffixDraft] = useState('');
|
|
56
|
+
const [suffixSaving, setSuffixSaving] = useState(false);
|
|
50
57
|
const [editingId, setEditingId] = useState(null);
|
|
51
58
|
const [editText, setEditText] = useState('');
|
|
52
59
|
const [editSaving, setEditSaving] = useState(false);
|
|
@@ -82,7 +89,12 @@ export default function SessionTaskView() {
|
|
|
82
89
|
|
|
83
90
|
// 同步页面上的超时配置(来源:后端 settings)
|
|
84
91
|
useEffect(() => {
|
|
85
|
-
if (overview && overview.settings)
|
|
92
|
+
if (overview && overview.settings) {
|
|
93
|
+
setTimeoutSec(overview.settings.timeoutSec);
|
|
94
|
+
setTaskSuffix(overview.settings.taskSuffix || '');
|
|
95
|
+
setDefaultTaskSuffix(overview.settings.defaultTaskSuffix || '');
|
|
96
|
+
setSuffixEnabled(!!overview.settings.suffixEnabled);
|
|
97
|
+
}
|
|
86
98
|
}, [overview]);
|
|
87
99
|
|
|
88
100
|
const saveTimeout = (sec) =>
|
|
@@ -101,6 +113,30 @@ export default function SessionTaskView() {
|
|
|
101
113
|
}
|
|
102
114
|
});
|
|
103
115
|
|
|
116
|
+
// 收尾追加语:保存(draft 是 '' 等价于关闭;非空则启用)
|
|
117
|
+
const saveSuffix = (text) =>
|
|
118
|
+
guard(async () => {
|
|
119
|
+
setSuffixSaving(true);
|
|
120
|
+
try {
|
|
121
|
+
const s = await api('/api/localtasks/setting', {
|
|
122
|
+
method: 'PATCH',
|
|
123
|
+
body: { suffix: text },
|
|
124
|
+
});
|
|
125
|
+
setTaskSuffix(s.taskSuffix);
|
|
126
|
+
setSuffixEnabled(!!s.suffixEnabled);
|
|
127
|
+
setSuffixEditing(false);
|
|
128
|
+
setSuffixDraft('');
|
|
129
|
+
toast(s.suffixEnabled ? '收尾追加语已更新' : '收尾追加语已关闭');
|
|
130
|
+
await load();
|
|
131
|
+
} finally {
|
|
132
|
+
setSuffixSaving(false);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// 显式关闭(不进入编辑,直接 PATCH suffix='')
|
|
137
|
+
const disableSuffix = () =>
|
|
138
|
+
saveSuffix('');
|
|
139
|
+
|
|
104
140
|
// 清理旧脏数据(旧模型无目录主题、空主题;等待中保留)
|
|
105
141
|
const prune = () =>
|
|
106
142
|
guard(async () => {
|
|
@@ -359,6 +395,96 @@ export default function SessionTaskView() {
|
|
|
359
395
|
</span>
|
|
360
396
|
</div>
|
|
361
397
|
|
|
398
|
+
<div className="card" style={{ padding: '10px 14px' }}>
|
|
399
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap', marginBottom: suffixEditing ? 10 : 0 }}>
|
|
400
|
+
<span style={{ fontWeight: 700 }}>收尾追加语</span>
|
|
401
|
+
<span className="muted" style={{ fontSize: 12 }}>
|
|
402
|
+
每次 wait 返回任务时,自动拼到 task.text 末尾。强制 agent 计划最后再 wait 一次,避免长对话漂移漏调。
|
|
403
|
+
</span>
|
|
404
|
+
<span style={{ marginLeft: 'auto', display: 'flex', gap: 8, alignItems: 'center' }}>
|
|
405
|
+
<span className={'tag' + (suffixEnabled ? '' : ' muted')} style={{ fontSize: 11 }}>
|
|
406
|
+
{suffixEnabled ? '已开启' : '已关闭'}
|
|
407
|
+
</span>
|
|
408
|
+
{!suffixEditing && (
|
|
409
|
+
<>
|
|
410
|
+
{suffixEnabled && (
|
|
411
|
+
<button className="btn small ghost" onClick={() => { setSuffixDraft(taskSuffix); setSuffixEditing(true); }}>
|
|
412
|
+
编辑
|
|
413
|
+
</button>
|
|
414
|
+
)}
|
|
415
|
+
{suffixEnabled ? (
|
|
416
|
+
<button
|
|
417
|
+
className="btn small ghost"
|
|
418
|
+
onClick={() => disableSuffix()}
|
|
419
|
+
disabled={suffixSaving}
|
|
420
|
+
title="关闭后,wait 返回的任务不再追加提示词"
|
|
421
|
+
>
|
|
422
|
+
关闭
|
|
423
|
+
</button>
|
|
424
|
+
) : (
|
|
425
|
+
<button
|
|
426
|
+
className="btn small"
|
|
427
|
+
onClick={() => { setSuffixDraft(defaultTaskSuffix); setSuffixEditing(true); }}
|
|
428
|
+
title="恢复默认收尾追加语并开启"
|
|
429
|
+
>
|
|
430
|
+
开启
|
|
431
|
+
</button>
|
|
432
|
+
)}
|
|
433
|
+
</>
|
|
434
|
+
)}
|
|
435
|
+
</span>
|
|
436
|
+
</div>
|
|
437
|
+
{!suffixEditing && taskSuffix && (
|
|
438
|
+
<div
|
|
439
|
+
className="muted"
|
|
440
|
+
style={{ fontSize: 12, whiteSpace: 'pre-wrap', borderLeft: '2px solid #eee', padding: '4px 0 4px 10px' }}
|
|
441
|
+
>
|
|
442
|
+
{taskSuffix}
|
|
443
|
+
</div>
|
|
444
|
+
)}
|
|
445
|
+
{suffixEditing && (
|
|
446
|
+
<div>
|
|
447
|
+
<textarea
|
|
448
|
+
value={suffixDraft}
|
|
449
|
+
onChange={(e) => setSuffixDraft(e.target.value)}
|
|
450
|
+
rows={5}
|
|
451
|
+
style={{ width: '100%', font: 'inherit', padding: 8, boxSizing: 'border-box' }}
|
|
452
|
+
placeholder="(留空 = 关闭;非空 = 启用并以这段文本作为追加语)"
|
|
453
|
+
/>
|
|
454
|
+
<div style={{ display: 'flex', gap: 8, marginTop: 8, alignItems: 'center', flexWrap: 'wrap' }}>
|
|
455
|
+
<button
|
|
456
|
+
className="btn small"
|
|
457
|
+
onClick={() => saveSuffix(suffixDraft)}
|
|
458
|
+
disabled={suffixSaving}
|
|
459
|
+
>
|
|
460
|
+
保存
|
|
461
|
+
</button>
|
|
462
|
+
<button
|
|
463
|
+
className="btn small ghost"
|
|
464
|
+
onClick={() => {
|
|
465
|
+
setSuffixEditing(false);
|
|
466
|
+
setSuffixDraft('');
|
|
467
|
+
}}
|
|
468
|
+
disabled={suffixSaving}
|
|
469
|
+
>
|
|
470
|
+
取消
|
|
471
|
+
</button>
|
|
472
|
+
<button
|
|
473
|
+
className="btn small ghost"
|
|
474
|
+
onClick={() => saveSuffix(defaultTaskSuffix)}
|
|
475
|
+
disabled={suffixSaving}
|
|
476
|
+
title="覆盖为默认文案并开启"
|
|
477
|
+
>
|
|
478
|
+
恢复默认
|
|
479
|
+
</button>
|
|
480
|
+
<span className="muted" style={{ fontSize: 11, marginLeft: 'auto' }}>
|
|
481
|
+
留空保存 = 关闭
|
|
482
|
+
</span>
|
|
483
|
+
</div>
|
|
484
|
+
</div>
|
|
485
|
+
)}
|
|
486
|
+
</div>
|
|
487
|
+
|
|
362
488
|
<div className="colhead">
|
|
363
489
|
<input
|
|
364
490
|
type="checkbox"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e,s as t,t as n}from"./index-
|
|
1
|
+
import{o as e,s as t,t as n}from"./index-Iz1qH6TC.js";var r=t();function i({module:t}){let{boot:i}=e(),a=(i?.commands||[]).filter(e=>e.module===t);return a.length?(0,r.jsxs)(`div`,{className:`cli-hint`,children:[(0,r.jsx)(`span`,{className:`cli-hint-label`,children:`CLI 等价(同构命令,加 --json 得机器可读输出):`}),a.map(e=>(0,r.jsx)(n,{className:`cli-cmd`,text:e.command,title:`点击复制:${e.usage}`,children:e.command},e.id))]}):null}export{i as t};
|