@suifei/dsh-ai-team 0.3.26 → 0.3.28
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 +12 -0
- package/client.js +78 -7
- package/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.28 — 2026-11-10
|
|
4
|
+
|
|
5
|
+
- 收件箱决策项增加逐条「采纳」与「全部采纳建议」;建议直接填入可编辑输入框,不再手抄;
|
|
6
|
+
- 提交仍要求所有问题有答案,采纳后可继续修改。
|
|
7
|
+
|
|
8
|
+
## 0.3.27 — 2026-11-10
|
|
9
|
+
|
|
10
|
+
- 主对话「任务」模式拆成标题 + 验收标准;不再把 Human 原话直接当 resultDefinition;
|
|
11
|
+
- 开启 QA 时必须逐行填写 checklist,否则不能提交;
|
|
12
|
+
- 修复真实项目 #3/#4 的根因:重复创建、宽泛结果定义、QA 空清单;
|
|
13
|
+
- 重复 Task 的第二条会打开已有卡,不再静默新建。
|
|
14
|
+
|
|
3
15
|
## 0.3.26 — 2026-11-10
|
|
4
16
|
|
|
5
17
|
- Task 创建增加重复保护:相同 title/resultDefinition/owner 的 active Task 会被拒绝并返回已有 Task;
|
package/client.js
CHANGED
|
@@ -34,7 +34,12 @@ window.__ModuleLoader__.load({
|
|
|
34
34
|
tabSituation: '态势',
|
|
35
35
|
tabsAria: '项目视图',
|
|
36
36
|
composer: '写一条消息…',
|
|
37
|
-
taskPlaceholder: '
|
|
37
|
+
taskPlaceholder: '任务标题:要做什么',
|
|
38
|
+
taskDefinitionPlaceholder: '验收标准(必填):怎样算完成、拿什么证据',
|
|
39
|
+
taskDefinitionAria: 'Task 验收标准',
|
|
40
|
+
qaChecklistPlaceholder: 'QA 清单,每行一条(开启 QA 时必填)',
|
|
41
|
+
qaChecklistAria: 'QA 验收清单',
|
|
42
|
+
taskDefinitionRequired: '请先写验收标准,再创建 Task。',
|
|
38
43
|
discuss: '讨论',
|
|
39
44
|
taskMode: '任务',
|
|
40
45
|
send: '发送',
|
|
@@ -110,6 +115,9 @@ window.__ModuleLoader__.load({
|
|
|
110
115
|
decisionChoose: '请选择…',
|
|
111
116
|
decisionAnswer: '填写你的决定',
|
|
112
117
|
decisionRecommend: '推荐',
|
|
118
|
+
decisionAdopt: '采纳',
|
|
119
|
+
decisionAdoptAll: '全部采纳建议',
|
|
120
|
+
decisionAdoptHint: '建议可直接采纳,再按需修改',
|
|
113
121
|
decisionSubmit: '提交决策',
|
|
114
122
|
decisionSubmitted: '决策已提交给团队。',
|
|
115
123
|
inboxEmptyAction: '看任务看板',
|
|
@@ -341,7 +349,12 @@ window.__ModuleLoader__.load({
|
|
|
341
349
|
tabSituation: 'Situation',
|
|
342
350
|
tabsAria: 'Project views',
|
|
343
351
|
composer: 'Write a message…',
|
|
344
|
-
taskPlaceholder: '
|
|
352
|
+
taskPlaceholder: 'Task title: what to do',
|
|
353
|
+
taskDefinitionPlaceholder: 'Definition of done (required): how it is accepted, with what evidence',
|
|
354
|
+
taskDefinitionAria: 'Definition of done',
|
|
355
|
+
qaChecklistPlaceholder: 'QA checklist, one per line (required when QA is on)',
|
|
356
|
+
qaChecklistAria: 'QA checklist',
|
|
357
|
+
taskDefinitionRequired: 'Write the definition of done before creating a Task.',
|
|
345
358
|
discuss: 'Discuss',
|
|
346
359
|
taskMode: 'Task',
|
|
347
360
|
send: 'Send',
|
|
@@ -417,6 +430,9 @@ window.__ModuleLoader__.load({
|
|
|
417
430
|
decisionChoose: 'Choose…',
|
|
418
431
|
decisionAnswer: 'Write your decision',
|
|
419
432
|
decisionRecommend: 'Recommended',
|
|
433
|
+
decisionAdopt: 'Adopt',
|
|
434
|
+
decisionAdoptAll: 'Adopt all suggestions',
|
|
435
|
+
decisionAdoptHint: 'Adopt a suggestion, then edit if needed',
|
|
420
436
|
decisionSubmit: 'Submit decision',
|
|
421
437
|
decisionSubmitted: 'Decision sent to the team.',
|
|
422
438
|
inboxEmptyAction: 'Open the board',
|
|
@@ -970,6 +986,10 @@ window.__ModuleLoader__.load({
|
|
|
970
986
|
.at-inboxoptions { display: block; color: var(--dsw-alias-label-tertiary); font-size: 11px; }
|
|
971
987
|
.at-inboxrecommend { display: block; color: var(--dsw-alias-state-business-primary); font-size: 11px; }
|
|
972
988
|
.at-decision { display: flex; flex-direction: column; gap: 8px; margin: 6px 0 4px; }
|
|
989
|
+
.at-decisionhead { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
990
|
+
.at-decisionhint { color: var(--dsw-alias-label-tertiary); font-size: 11px; }
|
|
991
|
+
.at-decisionrecommend { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 3px; color: var(--dsw-alias-state-business-primary); font-size: 11px; }
|
|
992
|
+
.at-adopt { flex: 0 0 auto; padding: 0; border: 0; background: transparent; color: var(--dsw-alias-state-business-primary); font: inherit; font-size: 11px; cursor: pointer; text-decoration: underline; }
|
|
973
993
|
.at-decisionselect, .at-decisioninput { width: 100%; margin-top: 4px; padding: 4px 6px; border: 1px solid var(--dsw-alias-border-l2); border-radius: var(--dsw-radius-sm); background: var(--dsw-alias-bg-base); color: var(--dsw-alias-label-primary); font: inherit; font-size: 12px; line-height: 18px; }
|
|
974
994
|
.at-decision .at-btn { align-self: flex-start; }
|
|
975
995
|
.at-inboxtitle { color: var(--dsw-alias-label-primary); font-size: 13px; line-height: 20px; }
|
|
@@ -978,6 +998,9 @@ window.__ModuleLoader__.load({
|
|
|
978
998
|
.at-inboxactions { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
|
|
979
999
|
.at-qacheck { display: inline-flex; align-items: center; gap: 4px; color: var(--dsw-alias-label-tertiary); font-size: 11px; white-space: nowrap; }
|
|
980
1000
|
.at-qacheck input { accent-color: var(--dsw-alias-state-business-primary); }
|
|
1001
|
+
.at-taskfields { display: flex; flex-direction: column; gap: 6px; padding: 0 10px 8px; }
|
|
1002
|
+
.at-taskdef, .at-taskqa { width: 100%; box-sizing: border-box; resize: vertical; min-height: 42px; padding: 7px 8px; border: 1px solid var(--dsw-alias-border-l2); border-radius: var(--dsw-radius-sm); background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); font: inherit; font-size: 12px; line-height: 18px; }
|
|
1003
|
+
.at-taskdef::placeholder, .at-taskqa::placeholder { color: var(--dsw-alias-label-caption); }
|
|
981
1004
|
.at-qabadge { display: inline-flex; align-items: center; margin-left: 5px; padding: 0 5px; border: 1px solid var(--dsw-alias-state-business-primary); border-radius: 999px; color: var(--dsw-alias-state-business-primary); font-size: 9px; line-height: 15px; vertical-align: 1px; }
|
|
982
1005
|
.at-talented { opacity: 0.82; }
|
|
983
1006
|
.at-btn-small { min-height: 24px; padding: 0 8px; font-size: 11px; }
|
|
@@ -1637,6 +1660,9 @@ window.__ModuleLoader__.load({
|
|
|
1637
1660
|
const [answers, setAnswers] = React.useState(() => questions.map(() => ''));
|
|
1638
1661
|
const [busy, setBusy] = React.useState(false);
|
|
1639
1662
|
const setAnswer = (index, value) => setAnswers((prev) => prev.map((entry, i) => i === index ? value : entry));
|
|
1663
|
+
const recommendations = questions.map((question) => typeof question.recommendation === 'string' ? question.recommendation.trim() : '');
|
|
1664
|
+
const hasRecommendations = recommendations.some((value) => value !== '');
|
|
1665
|
+
const adoptAll = () => setAnswers((prev) => prev.map((entry, index) => recommendations[index] || entry));
|
|
1640
1666
|
const complete = questions.every((question, index) => answers[index].trim() !== '');
|
|
1641
1667
|
const submit = async () => {
|
|
1642
1668
|
if (!complete || busy) return;
|
|
@@ -1648,6 +1674,9 @@ window.__ModuleLoader__.load({
|
|
|
1648
1674
|
}
|
|
1649
1675
|
};
|
|
1650
1676
|
return h('div', { className: 'at-decision' },
|
|
1677
|
+
hasRecommendations ? h('div', { className: 'at-decisionhead' },
|
|
1678
|
+
h('span', { className: 'at-decisionhint' }, t('decisionAdoptHint')),
|
|
1679
|
+
h('button', { className: 'at-btn at-btn-small', type: 'button', onClick: adoptAll }, t('decisionAdoptAll'))) : null,
|
|
1651
1680
|
h('ol', { className: 'at-inboxquestions' }, questions.map((question, index) => h('li', { key: question.id ?? index },
|
|
1652
1681
|
h('span', { className: 'at-inboxquestion' }, question.text),
|
|
1653
1682
|
Array.isArray(question.options) && question.options.length
|
|
@@ -1655,7 +1684,9 @@ window.__ModuleLoader__.load({
|
|
|
1655
1684
|
h('option', { value: '' }, t('decisionChoose')),
|
|
1656
1685
|
question.options.map((option) => h('option', { key: option, value: option }, option)))
|
|
1657
1686
|
: h('input', { className: 'at-decisioninput', value: answers[index], placeholder: question.recommendation ?? t('decisionAnswer'), onChange: (event) => setAnswer(index, event.target.value) }),
|
|
1658
|
-
question.recommendation ? h('
|
|
1687
|
+
question.recommendation ? h('div', { className: 'at-decisionrecommend' },
|
|
1688
|
+
h('span', null, t('decisionRecommend') + ':' + question.recommendation),
|
|
1689
|
+
h('button', { className: 'at-adopt', type: 'button', onClick: () => setAnswer(index, question.recommendation) }, t('decisionAdopt'))) : null))),
|
|
1659
1690
|
h('button', { className: 'at-btn at-btn-primary at-btn-small', type: 'button', disabled: !complete || busy, onClick: submit }, busy ? t('saving') : t('decisionSubmit')));
|
|
1660
1691
|
}
|
|
1661
1692
|
|
|
@@ -1919,8 +1950,12 @@ window.__ModuleLoader__.load({
|
|
|
1919
1950
|
h('button', { className: 'at-send', type: 'button', disabled: !reply.trim(), onClick: onReplySend }, t('send'))))) : null);
|
|
1920
1951
|
}
|
|
1921
1952
|
|
|
1922
|
-
function Composer({ t, mode, draft, disabled, qaRequired, onQaRequired, onMode, onDraft, onSend }) {
|
|
1923
|
-
const send = () => {
|
|
1953
|
+
function Composer({ t, mode, draft, definition, qaChecklist, disabled, qaRequired, onQaRequired, onDefinition, onQaChecklist, onMode, onDraft, onSend }) {
|
|
1954
|
+
const send = () => {
|
|
1955
|
+
if (!draft.trim() || disabled) return;
|
|
1956
|
+
if (mode === 'task' && (!definition.trim() || (qaRequired && !qaChecklist.trim()))) return;
|
|
1957
|
+
onSend();
|
|
1958
|
+
};
|
|
1924
1959
|
return h('div', { className: 'at-composer' },
|
|
1925
1960
|
h('div', { className: 'at-composerinner' },
|
|
1926
1961
|
h('div', { className: cx('at-box', 'at-composerbox', mode === 'task' && 'at-taskmode') },
|
|
@@ -1938,6 +1973,25 @@ window.__ModuleLoader__.load({
|
|
|
1938
1973
|
}
|
|
1939
1974
|
},
|
|
1940
1975
|
}),
|
|
1976
|
+
mode === 'task' ? h('div', { className: 'at-taskfields' },
|
|
1977
|
+
h('textarea', {
|
|
1978
|
+
className: 'at-taskdef',
|
|
1979
|
+
rows: 2,
|
|
1980
|
+
value: definition,
|
|
1981
|
+
disabled,
|
|
1982
|
+
placeholder: t('taskDefinitionPlaceholder'),
|
|
1983
|
+
'aria-label': t('taskDefinitionAria'),
|
|
1984
|
+
onChange: (event) => onDefinition(event.target.value),
|
|
1985
|
+
}),
|
|
1986
|
+
qaRequired ? h('textarea', {
|
|
1987
|
+
className: 'at-taskqa',
|
|
1988
|
+
rows: 2,
|
|
1989
|
+
value: qaChecklist,
|
|
1990
|
+
disabled,
|
|
1991
|
+
placeholder: t('qaChecklistPlaceholder'),
|
|
1992
|
+
'aria-label': t('qaChecklistAria'),
|
|
1993
|
+
onChange: (event) => onQaChecklist(event.target.value),
|
|
1994
|
+
}) : null) : null,
|
|
1941
1995
|
h('div', { className: 'at-barrow' },
|
|
1942
1996
|
h('div', { className: 'at-mode', role: 'group', 'aria-label': t('modeAria') },
|
|
1943
1997
|
h('button', { type: 'button', 'aria-pressed': mode === 'discuss', onClick: () => onMode('discuss') }, t('discuss')),
|
|
@@ -1946,7 +2000,7 @@ window.__ModuleLoader__.load({
|
|
|
1946
2000
|
h('input', { type: 'checkbox', checked: qaRequired, onChange: (event) => onQaRequired(event.target.checked) }),
|
|
1947
2001
|
h('span', null, t('qaRequired'))) : null,
|
|
1948
2002
|
h('span', { className: 'at-hint' }, t('enterHint')),
|
|
1949
|
-
h('button', { className: 'at-send', type: 'button', disabled: disabled || !draft.trim(), onClick: send }, mode === 'task' ? t('createTask') : t('send'))))));
|
|
2003
|
+
h('button', { className: 'at-send', type: 'button', disabled: disabled || !draft.trim() || (mode === 'task' && (!definition.trim() || (qaRequired && !qaChecklist.trim()))), onClick: send }, mode === 'task' ? t('createTask') : t('send'))))));
|
|
1950
2004
|
}
|
|
1951
2005
|
|
|
1952
2006
|
function QuadrantCard({ t, meta, quadrant, tasks, items, count, onItem, onViewAll }) {
|
|
@@ -2119,6 +2173,8 @@ window.__ModuleLoader__.load({
|
|
|
2119
2173
|
const [threadOpen, setThreadOpen] = React.useState(false);
|
|
2120
2174
|
const [mode, setMode] = React.useState('discuss');
|
|
2121
2175
|
const [qaTask, setQaTask] = React.useState(false);
|
|
2176
|
+
const [taskDefinition, setTaskDefinition] = React.useState('');
|
|
2177
|
+
const [qaChecklistText, setQaChecklistText] = React.useState('');
|
|
2122
2178
|
const [draft, setDraft] = React.useState('');
|
|
2123
2179
|
const [note, setNote] = React.useState('');
|
|
2124
2180
|
const [rightNote, setRightNote] = React.useState('');
|
|
@@ -2821,7 +2877,18 @@ window.__ModuleLoader__.load({
|
|
|
2821
2877
|
if (!project?.workspacePath) { say(t('workspaceRequired')); return; }
|
|
2822
2878
|
try {
|
|
2823
2879
|
if (mode === 'task') {
|
|
2824
|
-
|
|
2880
|
+
const definition = taskDefinition.trim();
|
|
2881
|
+
const checklist = qaChecklistText.split(/\r?\n/).map((item) => item.trim()).filter(Boolean);
|
|
2882
|
+
if (definition === '') { say(t('taskDefinitionRequired')); return; }
|
|
2883
|
+
if (qaTask && checklist.length === 0) { say(t('qaNeedsChecklist')); return; }
|
|
2884
|
+
await runCommand('task.create', {
|
|
2885
|
+
title: text,
|
|
2886
|
+
resultDefinition: definition,
|
|
2887
|
+
qaRequired: qaTask,
|
|
2888
|
+
...(qaTask ? { qaChecklist: checklist } : {}),
|
|
2889
|
+
});
|
|
2890
|
+
setTaskDefinition('');
|
|
2891
|
+
setQaChecklistText('');
|
|
2825
2892
|
} else {
|
|
2826
2893
|
await runCommand('stream.post', { body: text });
|
|
2827
2894
|
}
|
|
@@ -3171,7 +3238,11 @@ window.__ModuleLoader__.load({
|
|
|
3171
3238
|
draft,
|
|
3172
3239
|
disabled: !project || !project.workspacePath,
|
|
3173
3240
|
qaRequired: qaTask,
|
|
3241
|
+
definition: taskDefinition,
|
|
3242
|
+
qaChecklist: qaChecklistText,
|
|
3174
3243
|
onQaRequired: setQaTask,
|
|
3244
|
+
onDefinition: setTaskDefinition,
|
|
3245
|
+
onQaChecklist: setQaChecklistText,
|
|
3175
3246
|
onMode: setMode,
|
|
3176
3247
|
onDraft: setDraft,
|
|
3177
3248
|
onSend: send,
|
package/index.js
CHANGED
|
@@ -34,7 +34,7 @@ export const name = 'ai-team';
|
|
|
34
34
|
/** The workbench only makes sense where the Web carrier exists. */
|
|
35
35
|
export const inject = ['webServer', 'permissionPresets', 'sandboxPolicy'];
|
|
36
36
|
|
|
37
|
-
const VERSION = '0.3.
|
|
37
|
+
const VERSION = '0.3.28';
|
|
38
38
|
const PROJECT_ID = 'prj_main';
|
|
39
39
|
const HUMAN_ID = 'mem_human';
|
|
40
40
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suifei/dsh-ai-team",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.28",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "文渊阁 (Wenyuan Pavilion) — AI Team mode for DeepSeek Harness: concurrent projects, owned tasks, threads, inbox and an append-only team ledger",
|
|
6
6
|
"license": "MIT",
|