nx-kv 0.8.1 → 0.8.3

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.
@@ -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) setTimeoutSec(overview.settings.timeoutSec);
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-D0ldg3Y8.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};
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};