dsh-sa-workbench 0.1.27 → 0.1.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/README.md +1 -1
- package/client.js +14 -14
- package/modules/dsh-pm-ui/client.js +14 -14
- package/modules/dsh-pm-ui/package.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SA 工作台 · dsh-sa-workbench
|
|
2
2
|
|
|
3
|
-
在 DeepSeek Harness 桌面版插件页输入 `dsh-sa-workbench` 安装。已安装后通过同一插件页检查、选择并更新版本,无须安装 EXE
|
|
3
|
+
在 DeepSeek Harness 桌面版插件页输入 `dsh-sa-workbench` 安装。已安装后通过同一插件页检查、选择并更新版本,无须安装 EXE。公开 npm 安装名已可用;正式版本与验收记录以仓库交付说明为准。
|
|
4
4
|
|
|
5
5
|
需求总览、版本计划、业务资料上传、需求/高阶方案/PRD/原型、节点 Skill、文档历史和交付归档在一个包里同步更新。复用 DSH 的模型、会话、权限和工具,不包含模型凭据或业务资料。
|
|
6
6
|
|
package/client.js
CHANGED
|
@@ -27,7 +27,7 @@ window.__ModuleLoader__.load({
|
|
|
27
27
|
|
|
28
28
|
var PANEL_KEY = 'pm'
|
|
29
29
|
var API = '/pm/api'
|
|
30
|
-
function saAppearance(){try{return localStorage.getItem('sa-workbench-appearance')==='
|
|
30
|
+
function saAppearance(){try{return localStorage.getItem('sa-workbench-appearance')==='dark'?'dark':'light'}catch(err){return 'light'}}
|
|
31
31
|
function setSaAppearance(next){try{localStorage.setItem('sa-workbench-appearance',next)}catch(err){}pmBus.set({appearance:next})}
|
|
32
32
|
function bindSaShell(appearance){
|
|
33
33
|
if(typeof document==='undefined')return function(){};
|
|
@@ -36,7 +36,7 @@ window.__ModuleLoader__.load({
|
|
|
36
36
|
return function(){if(previousShell===undefined)delete root.dataset.saShell;else root.dataset.saShell=previousShell;if(previousAppearance===undefined)delete root.dataset.saAppearance;else root.dataset.saAppearance=previousAppearance}
|
|
37
37
|
}
|
|
38
38
|
function toggleSaAppearance(){var next=(pmBus.state.appearance || saAppearance())==='dark'?'light':'dark';try{localStorage.setItem('sa-workbench-appearance',next)}catch(err){}pmBus.set({appearance:next})}
|
|
39
|
-
var CLIENT_VERSION = '0.1.
|
|
39
|
+
var CLIENT_VERSION = '0.1.28'
|
|
40
40
|
|
|
41
41
|
// A session may disappear or fail to open after selection. Keep failures
|
|
42
42
|
// inside the conversation pane, and release even a rejected/pending ref.
|
|
@@ -2338,7 +2338,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
|
|
|
2338
2338
|
// 全局选择总线:左轨(常驻)与 SA 总览页(main 面板)共享选中态
|
|
2339
2339
|
// -----------------------------------------------------------------------
|
|
2340
2340
|
var pmBus = {
|
|
2341
|
-
state: { selectedId: null, activeSessionId: null, nav:
|
|
2341
|
+
state: { selectedId: null, activeSessionId: null, nav: 'home', selectedVersion: null, tabs: {}, scrolls: {}, files: {}, focus: false },
|
|
2342
2342
|
listeners: [],
|
|
2343
2343
|
set: function (patch) {
|
|
2344
2344
|
var changed = false
|
|
@@ -2642,9 +2642,9 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
|
|
|
2642
2642
|
)
|
|
2643
2643
|
}
|
|
2644
2644
|
|
|
2645
|
-
return e('div', { className: 'pmw-nav', 'data-sa-appearance':bus.appearance || saAppearance() },
|
|
2645
|
+
return e('div', { className: 'pmw-nav', 'data-sa-appearance':bus.appearance || saAppearance(), 'data-sa-setup':data.data && (data.data.setupRequired || data.data.restartRequired)?'true':'false' },
|
|
2646
2646
|
e('div',{className:'glass-workspace'},e('span',{className:'glass-workspace-icon'},e(UiIcon,{name:'grid'})),e('span',null,e('strong',{className:'glass-workspace-title'},data.data && data.data.workspace && data.data.workspace.title || '项目工作空间'),e('small',null,'SA 项目工作空间'))),
|
|
2647
|
-
e('div', { className: 'pmw-nav__top' },
|
|
2647
|
+
e('style',null,'.pmw-nav[data-sa-setup="true"] .pmw-nav__top,.pmw-nav[data-sa-setup="true"] .pmw-nav__scroll{display:none}.pmw-nav[data-sa-setup="true"]:after{content:"完成目录设置后,即可开始使用工作台";padding:20px;font-size:13px;line-height:1.7;opacity:.7}'),e('div', { className: 'pmw-nav__top' },
|
|
2648
2648
|
e('button', {
|
|
2649
2649
|
className: 'pmw-btn pmw-btn--primary pmw-nav__new',
|
|
2650
2650
|
onClick: function () {
|
|
@@ -2867,11 +2867,11 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
|
|
|
2867
2867
|
e('div',{className:'pmw-dialog__foot'},e('button',{className:'pmw-btn',onClick:props.onCancel},'取消'),e('button',{className:'pmw-btn pmw-btn--primary',disabled:loading || !value || !value.current,onClick:function(){props.onSelect(value.current)}},'选择此目录'))))
|
|
2868
2868
|
}
|
|
2869
2869
|
|
|
2870
|
-
function SettingsPanel() {
|
|
2870
|
+
function SettingsPanel(props) {
|
|
2871
2871
|
var route=usePmBus()
|
|
2872
2872
|
var ds=useState(null), data=ds[0], setData=ds[1]
|
|
2873
2873
|
var fs=useState(null), draft=fs[0], setDraft=fs[1]
|
|
2874
|
-
var ts=useState(pmBus.state.settingsTab || 'directories'), tab=ts[0], setTab=ts[1]
|
|
2874
|
+
var ts=useState(props && props.onboarding ? 'directories' : pmBus.state.settingsTab || 'directories'), tab=ts[0], setTab=ts[1]
|
|
2875
2875
|
var ns=useState(pmBus.state.settingsNode || 'intake'), node=ns[0], setNode=ns[1]
|
|
2876
2876
|
var ss=useState(null), skill=ss[0], setSkill=ss[1]
|
|
2877
2877
|
var cs=useState(''), content=cs[0], setContent=cs[1]
|
|
@@ -2897,26 +2897,26 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
|
|
|
2897
2897
|
finally {if(mounted.current)setPicking(null)}
|
|
2898
2898
|
}
|
|
2899
2899
|
useEffect(function(){load()},[])
|
|
2900
|
-
useEffect(function(){setTab(route.settingsTab || 'directories');setNode(route.settingsNode || 'intake')},[route.settingsTab,route.settingsNode])
|
|
2900
|
+
useEffect(function(){setTab(props && props.onboarding ? 'directories' : route.settingsTab || 'directories');setNode(route.settingsNode || 'intake')},[route.settingsTab,route.settingsNode])
|
|
2901
2901
|
function openSkill(name){var id=++request.current;setSkill(null);setError(null);apiGet('/skill?name='+encodeURIComponent(name)).then(function(body){if(id!==request.current)return;var cached=pmBus.skillEdits[name];setSkill(cached?Object.assign({},body.skill,{fingerprint:cached.fingerprint}):body.skill);setContent(cached?cached.content:body.skill.content);setCopyName('user-'+body.skill.name);if(cached && cached.fingerprint!==body.skill.fingerprint)setError('这份 Skill 已在其他位置修改,请先重新加载,再合并你的修改。')}).catch(function(err){if(id===request.current)setError(err.message)})}
|
|
2902
2902
|
useEffect(function(){if(draft && tab==='skills')openSkill(draft.nodeSkills[node])},[tab,node,draft && draft.nodeSkills[node]])
|
|
2903
2903
|
function changeField(key,value){setDraft(function(prev){var next=Object.assign({},prev);if(key==='workspaceRoot' && data && data.settings.setupRequired){var sep=value.indexOf('\\')>=0?'\\':'/',base=String(value).replace(/[\\/]+$/,'');['knowledgeDir','prdArchiveDir','skillsDir'].forEach(function(k){var child={knowledgeDir:'knowledge',prdArchiveDir:'prd-archive',skillsDir:'skills'}[k];if(prev[k]===String(prev.workspaceRoot).replace(/[\\/]+$/,'')+sep+child)next[k]=base+sep+child})}next[key]=value;return next});setMessage(null)}
|
|
2904
2904
|
function changeBinding(name){setDraft(function(prev){var next=Object.assign({},prev,{nodeSkills:Object.assign({},prev.nodeSkills)});next.nodeSkills[node]=name;return next});setMessage(null)}
|
|
2905
|
-
function save(){setBusy(true);setError(null);apiSend('POST','/settings',Object.assign({},draft,{expectedFingerprint:data.settings.fingerprint})).then(function(body){setData(function(prev){return Object.assign({},prev,{settings:body.settings})});setDraft(body.settings);setMessage(body.settings.restartRequired?'
|
|
2905
|
+
function save(){setBusy(true);setError(null);apiSend('POST','/settings',Object.assign({},draft,{expectedFingerprint:data.settings.fingerprint})).then(function(body){setData(function(prev){return Object.assign({},prev,{settings:body.settings})});setDraft(body.settings);if(props && props.onboarding && !body.settings.restartRequired){props.onComplete();return}setMessage(body.settings.restartRequired?'目录已保存。请完整退出 DSH(包括托盘),再重新打开,即可进入需求总览。':'已保存,下次推进节点时使用当前配置。')}).catch(function(err){setError(err.message)}).finally(function(){setBusy(false)})}
|
|
2906
2906
|
function editSkill(stamp){setBusy(true);setError(null);apiSend('POST','/skill',{name:skill.name,content:content,stamp:stamp,expectedFingerprint:skill.fingerprint}).then(function(body){delete pmBus.skillEdits[skill.name];setSkill(body.skill);setContent(body.skill.content);setMessage(stamp?'已恢复历史版本,原内容已保留为快照。':'Skill 已保存,下次加载使用新版。');return apiGet('/settings').then(function(latest){setData(latest)})}).catch(function(err){setError(err.message)}).finally(function(){setBusy(false)})}
|
|
2907
2907
|
function copySkill(){setBusy(true);setError(null);apiSend('POST','/skill',{operation:'copy',name:skill.name,newName:copyName}).then(function(body){var copied=body.skill;return apiSend('POST','/settings',{expectedFingerprint:data.settings.fingerprint,nodeSkills:(function(){var bindings={};bindings[node]=copied.name;return bindings})()}).then(function(saved){return apiGet('/settings').then(function(latest){setData(latest);setDraft(function(prev){return Object.assign({},prev,{fingerprint:saved.settings.fingerprint,nodeSkills:Object.assign({},prev.nodeSkills,saved.settings.nodeSkills)})});setSkill(copied);setContent(copied.content);setMessage('已复制并绑定到'+(data.settings.nodes.find(function(n){return n.id===node}) || {}).title+'节点,可以开始编辑。')})})}).catch(function(err){setError(err.message)}).finally(function(){setBusy(false)})}
|
|
2908
2908
|
if(!data || !draft)return e('section',{className:'pmw-settings'},e('h1',null,'SA 设置'),error ? e('div',{className:'pmw-settings__message is-error'},error,e('button',{className:'pmw-btn',onClick:load},'重新加载')) : e('p',{className:'pmw-settings__intro'},'正在读取配置…'))
|
|
2909
2909
|
var dirty=JSON.stringify([draft.workspaceRoot,draft.knowledgeDir,draft.prdArchiveDir,draft.skillsDir,draft.nodeSkills])!==JSON.stringify([data.settings.workspaceRoot,data.settings.knowledgeDir,data.settings.prdArchiveDir,data.settings.skillsDir,data.settings.nodeSkills])
|
|
2910
2910
|
return e('section',{className:'pmw-settings','aria-label':'SA 设置'},
|
|
2911
|
-
route.settingsReturn && e('button',{className:'pmw-btn pmw-btn--ghost pmw-settings-back',onClick:function(){var target=route.settingsReturn,tabs=Object.assign({},route.tabs);tabs[target.id]=target.stage;pmBus.set({selectedId:target.id,activeSessionId:target.sessionId,nav:'home',tabs:tabs,settingsReturn:null})}},'← 返回「'+route.settingsReturn.title+'」'),
|
|
2912
|
-
e('p',{className:'pmw-settings__eyebrow'},'SA WORKBENCH'),e('h1',null,data.settings.setupRequired?'设置你的 SA 工作台':'SA 设置'),e('p',{className:'pmw-settings__intro'},data.settings.setupRequired?'
|
|
2913
|
-
e('div',{className:'pmw-settings__tabs',role:'tablist'},['directories','skills'].map(function(id){return e('button',{key:id,role:'tab','aria-selected':tab===id,onClick:function(){setTab(id);setError(null);setMessage(null)}},id==='directories'?'目录与资料':'节点 Skill')})),
|
|
2911
|
+
!(props && props.onboarding) && route.settingsReturn && e('button',{className:'pmw-btn pmw-btn--ghost pmw-settings-back',onClick:function(){var target=route.settingsReturn,tabs=Object.assign({},route.tabs);tabs[target.id]=target.stage;pmBus.set({selectedId:target.id,activeSessionId:target.sessionId,nav:'home',tabs:tabs,settingsReturn:null})}},'← 返回「'+route.settingsReturn.title+'」'),
|
|
2912
|
+
e('p',{className:'pmw-settings__eyebrow'},'SA WORKBENCH'),e('h1',null,data.settings.setupRequired?'设置你的 SA 工作台':'SA 设置'),e('p',{className:'pmw-settings__intro'},data.settings.setupRequired?'首次使用可直接确认默认目录,或选择已有资料目录。保存后进入需求总览;更改工作目录后需完整退出并重开 DSH。':'配置资料位置和节点工作方法,让工作台适配你的流程。'),
|
|
2913
|
+
!(props && props.onboarding) && e('div',{className:'pmw-settings__tabs',role:'tablist'},['directories','skills'].map(function(id){return e('button',{key:id,role:'tab','aria-selected':tab===id,onClick:function(){setTab(id);setError(null);setMessage(null)}},id==='directories'?'目录与资料':'节点 Skill')})),
|
|
2914
2914
|
error && e('div',{role:'alert',className:'pmw-settings__message is-error'},error,e('button',{className:'pmw-btn pmw-btn--ghost',onClick:function(){load();if(skill){delete pmBus.skillEdits[skill.name];openSkill(skill.name)}}},'重新加载')),
|
|
2915
2915
|
message && e('div',{role:'status',className:'pmw-settings__message'},message),
|
|
2916
2916
|
tab==='directories' ? e('div',null,
|
|
2917
2917
|
[['workspaceRoot','工作目录','存放需求记录、方案、PRD 和原型;切换在下次启动生效。'],['knowledgeDir','知识库目录','业务资料、术语、规范和 PRD 模板;保存后生效。'],['prdArchiveDir','归档库目录','按交付版本整理的定稿 PRD;保存后生效。'],['skillsDir','我的 Skill 目录','用户副本与配套资源保存在这里,插件升级会保留它们。']].map(function(field){return e('div',{key:field[0],className:'pmw-settings__field'},e('label',{htmlFor:'pmw-dir-'+field[0]},e('strong',null,field[1])),e('p',{id:'pmw-dir-'+field[0]+'-hint'},field[2]),e('div',{className:'pmw-settings__directory'},e('input',{id:'pmw-dir-'+field[0],'aria-label':field[1],'aria-describedby':'pmw-dir-'+field[0]+'-hint',value:draft[field[0]],onChange:function(ev){changeField(field[0],ev.target.value)}}),e('button',{type:'button',className:'pmw-btn','aria-label':'浏览'+field[1],disabled:busy || !!picking,onClick:function(){browseDirectory(field)}},e(UiIcon,{name:'folder'}),picking===field[0]?'选择中…':'浏览目录')))}),
|
|
2918
2918
|
e('div',{className:'pmw-settings__message'},'当前工作目录:'+data.settings.activeWorkspaceRoot,data.settings.restartRequired && e('div',null,'下次启动切换到:'+data.settings.workspaceRoot),e('div',null,'完整需求归档:'+data.settings.requirementArchiveDir),e('div',null,'切换目录不会迁移原有资料。')),
|
|
2919
|
-
e('div',{className:'pmw-settings__actions'},e('button',{className:'pmw-btn pmw-btn--primary',disabled:busy || !!picking || (!dirty && !data.settings.setupRequired),onClick:save},busy?'保存中…':'保存目录配置'),dirty && e('span',{className:'pmw-settings__caption'},'有未保存的修改')),
|
|
2919
|
+
e('div',{className:'pmw-settings__actions'},e('button',{className:'pmw-btn pmw-btn--primary',disabled:busy || !!picking || (!dirty && !data.settings.setupRequired),onClick:save},busy?'保存中…':data.settings.setupRequired?(draft.workspaceRoot===data.settings.activeWorkspaceRoot?'使用默认目录,进入工作台':'保存目录,完成设置'):'保存目录配置'),dirty && e('span',{className:'pmw-settings__caption'},'有未保存的修改')),
|
|
2920
2920
|
e('p',{className:'pmw-settings__path'},'配置文件:'+data.settings.settingsFile)) :
|
|
2921
2921
|
e('div',null,e('div',{className:'pmw-settings__actions'},e('p',{className:'pmw-settings__caption'},'每个节点绑定一份主 Skill。将 Skill 文件夹放入“我的 Skill 目录”,展开选择框即可发现。'),e('button',{type:'button',className:'pmw-btn pmw-btn--ghost',disabled:refreshing,onClick:refreshCatalog},refreshing?'刷新中…':'刷新列表')),
|
|
2922
2922
|
e('div',{className:'pmw-settings__split'},
|
|
@@ -3519,7 +3519,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
|
|
|
3519
3519
|
|
|
3520
3520
|
var children = []
|
|
3521
3521
|
|
|
3522
|
-
if (data.data && (data.data.setupRequired || data.data.restartRequired)) return e('div',{className:'pmw-root','data-sa-appearance':bus.appearance || saAppearance()},e(SettingsPanel))
|
|
3522
|
+
if (data.data && (data.data.setupRequired || data.data.restartRequired)) return e('div',{className:'pmw-root','data-sa-appearance':bus.appearance || saAppearance()},e(SettingsPanel,{onboarding:true,onComplete:function(){pmBus.set({nav:'home',selectedId:null,activeSessionId:null,settingsReturn:null});setView('home');reload()}}))
|
|
3523
3523
|
if (view === 'settings') return e('div', { className: 'pmw-root', 'data-sa-appearance':bus.appearance || saAppearance() }, e(SettingsPanel))
|
|
3524
3524
|
|
|
3525
3525
|
// header(纯标题,动作全部收进各自语境:Tab 空态/地铁图归档站/右栏线程条)
|
|
@@ -27,7 +27,7 @@ window.__ModuleLoader__.load({
|
|
|
27
27
|
|
|
28
28
|
var PANEL_KEY = 'pm'
|
|
29
29
|
var API = '/pm/api'
|
|
30
|
-
function saAppearance(){try{return localStorage.getItem('sa-workbench-appearance')==='
|
|
30
|
+
function saAppearance(){try{return localStorage.getItem('sa-workbench-appearance')==='dark'?'dark':'light'}catch(err){return 'light'}}
|
|
31
31
|
function setSaAppearance(next){try{localStorage.setItem('sa-workbench-appearance',next)}catch(err){}pmBus.set({appearance:next})}
|
|
32
32
|
function bindSaShell(appearance){
|
|
33
33
|
if(typeof document==='undefined')return function(){};
|
|
@@ -36,7 +36,7 @@ window.__ModuleLoader__.load({
|
|
|
36
36
|
return function(){if(previousShell===undefined)delete root.dataset.saShell;else root.dataset.saShell=previousShell;if(previousAppearance===undefined)delete root.dataset.saAppearance;else root.dataset.saAppearance=previousAppearance}
|
|
37
37
|
}
|
|
38
38
|
function toggleSaAppearance(){var next=(pmBus.state.appearance || saAppearance())==='dark'?'light':'dark';try{localStorage.setItem('sa-workbench-appearance',next)}catch(err){}pmBus.set({appearance:next})}
|
|
39
|
-
var CLIENT_VERSION = '0.1.
|
|
39
|
+
var CLIENT_VERSION = '0.1.28'
|
|
40
40
|
|
|
41
41
|
// A session may disappear or fail to open after selection. Keep failures
|
|
42
42
|
// inside the conversation pane, and release even a rejected/pending ref.
|
|
@@ -2338,7 +2338,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
|
|
|
2338
2338
|
// 全局选择总线:左轨(常驻)与 SA 总览页(main 面板)共享选中态
|
|
2339
2339
|
// -----------------------------------------------------------------------
|
|
2340
2340
|
var pmBus = {
|
|
2341
|
-
state: { selectedId: null, activeSessionId: null, nav:
|
|
2341
|
+
state: { selectedId: null, activeSessionId: null, nav: 'home', selectedVersion: null, tabs: {}, scrolls: {}, files: {}, focus: false },
|
|
2342
2342
|
listeners: [],
|
|
2343
2343
|
set: function (patch) {
|
|
2344
2344
|
var changed = false
|
|
@@ -2642,9 +2642,9 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
|
|
|
2642
2642
|
)
|
|
2643
2643
|
}
|
|
2644
2644
|
|
|
2645
|
-
return e('div', { className: 'pmw-nav', 'data-sa-appearance':bus.appearance || saAppearance() },
|
|
2645
|
+
return e('div', { className: 'pmw-nav', 'data-sa-appearance':bus.appearance || saAppearance(), 'data-sa-setup':data.data && (data.data.setupRequired || data.data.restartRequired)?'true':'false' },
|
|
2646
2646
|
e('div',{className:'glass-workspace'},e('span',{className:'glass-workspace-icon'},e(UiIcon,{name:'grid'})),e('span',null,e('strong',{className:'glass-workspace-title'},data.data && data.data.workspace && data.data.workspace.title || '项目工作空间'),e('small',null,'SA 项目工作空间'))),
|
|
2647
|
-
e('div', { className: 'pmw-nav__top' },
|
|
2647
|
+
e('style',null,'.pmw-nav[data-sa-setup="true"] .pmw-nav__top,.pmw-nav[data-sa-setup="true"] .pmw-nav__scroll{display:none}.pmw-nav[data-sa-setup="true"]:after{content:"完成目录设置后,即可开始使用工作台";padding:20px;font-size:13px;line-height:1.7;opacity:.7}'),e('div', { className: 'pmw-nav__top' },
|
|
2648
2648
|
e('button', {
|
|
2649
2649
|
className: 'pmw-btn pmw-btn--primary pmw-nav__new',
|
|
2650
2650
|
onClick: function () {
|
|
@@ -2867,11 +2867,11 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
|
|
|
2867
2867
|
e('div',{className:'pmw-dialog__foot'},e('button',{className:'pmw-btn',onClick:props.onCancel},'取消'),e('button',{className:'pmw-btn pmw-btn--primary',disabled:loading || !value || !value.current,onClick:function(){props.onSelect(value.current)}},'选择此目录'))))
|
|
2868
2868
|
}
|
|
2869
2869
|
|
|
2870
|
-
function SettingsPanel() {
|
|
2870
|
+
function SettingsPanel(props) {
|
|
2871
2871
|
var route=usePmBus()
|
|
2872
2872
|
var ds=useState(null), data=ds[0], setData=ds[1]
|
|
2873
2873
|
var fs=useState(null), draft=fs[0], setDraft=fs[1]
|
|
2874
|
-
var ts=useState(pmBus.state.settingsTab || 'directories'), tab=ts[0], setTab=ts[1]
|
|
2874
|
+
var ts=useState(props && props.onboarding ? 'directories' : pmBus.state.settingsTab || 'directories'), tab=ts[0], setTab=ts[1]
|
|
2875
2875
|
var ns=useState(pmBus.state.settingsNode || 'intake'), node=ns[0], setNode=ns[1]
|
|
2876
2876
|
var ss=useState(null), skill=ss[0], setSkill=ss[1]
|
|
2877
2877
|
var cs=useState(''), content=cs[0], setContent=cs[1]
|
|
@@ -2897,26 +2897,26 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
|
|
|
2897
2897
|
finally {if(mounted.current)setPicking(null)}
|
|
2898
2898
|
}
|
|
2899
2899
|
useEffect(function(){load()},[])
|
|
2900
|
-
useEffect(function(){setTab(route.settingsTab || 'directories');setNode(route.settingsNode || 'intake')},[route.settingsTab,route.settingsNode])
|
|
2900
|
+
useEffect(function(){setTab(props && props.onboarding ? 'directories' : route.settingsTab || 'directories');setNode(route.settingsNode || 'intake')},[route.settingsTab,route.settingsNode])
|
|
2901
2901
|
function openSkill(name){var id=++request.current;setSkill(null);setError(null);apiGet('/skill?name='+encodeURIComponent(name)).then(function(body){if(id!==request.current)return;var cached=pmBus.skillEdits[name];setSkill(cached?Object.assign({},body.skill,{fingerprint:cached.fingerprint}):body.skill);setContent(cached?cached.content:body.skill.content);setCopyName('user-'+body.skill.name);if(cached && cached.fingerprint!==body.skill.fingerprint)setError('这份 Skill 已在其他位置修改,请先重新加载,再合并你的修改。')}).catch(function(err){if(id===request.current)setError(err.message)})}
|
|
2902
2902
|
useEffect(function(){if(draft && tab==='skills')openSkill(draft.nodeSkills[node])},[tab,node,draft && draft.nodeSkills[node]])
|
|
2903
2903
|
function changeField(key,value){setDraft(function(prev){var next=Object.assign({},prev);if(key==='workspaceRoot' && data && data.settings.setupRequired){var sep=value.indexOf('\\')>=0?'\\':'/',base=String(value).replace(/[\\/]+$/,'');['knowledgeDir','prdArchiveDir','skillsDir'].forEach(function(k){var child={knowledgeDir:'knowledge',prdArchiveDir:'prd-archive',skillsDir:'skills'}[k];if(prev[k]===String(prev.workspaceRoot).replace(/[\\/]+$/,'')+sep+child)next[k]=base+sep+child})}next[key]=value;return next});setMessage(null)}
|
|
2904
2904
|
function changeBinding(name){setDraft(function(prev){var next=Object.assign({},prev,{nodeSkills:Object.assign({},prev.nodeSkills)});next.nodeSkills[node]=name;return next});setMessage(null)}
|
|
2905
|
-
function save(){setBusy(true);setError(null);apiSend('POST','/settings',Object.assign({},draft,{expectedFingerprint:data.settings.fingerprint})).then(function(body){setData(function(prev){return Object.assign({},prev,{settings:body.settings})});setDraft(body.settings);setMessage(body.settings.restartRequired?'
|
|
2905
|
+
function save(){setBusy(true);setError(null);apiSend('POST','/settings',Object.assign({},draft,{expectedFingerprint:data.settings.fingerprint})).then(function(body){setData(function(prev){return Object.assign({},prev,{settings:body.settings})});setDraft(body.settings);if(props && props.onboarding && !body.settings.restartRequired){props.onComplete();return}setMessage(body.settings.restartRequired?'目录已保存。请完整退出 DSH(包括托盘),再重新打开,即可进入需求总览。':'已保存,下次推进节点时使用当前配置。')}).catch(function(err){setError(err.message)}).finally(function(){setBusy(false)})}
|
|
2906
2906
|
function editSkill(stamp){setBusy(true);setError(null);apiSend('POST','/skill',{name:skill.name,content:content,stamp:stamp,expectedFingerprint:skill.fingerprint}).then(function(body){delete pmBus.skillEdits[skill.name];setSkill(body.skill);setContent(body.skill.content);setMessage(stamp?'已恢复历史版本,原内容已保留为快照。':'Skill 已保存,下次加载使用新版。');return apiGet('/settings').then(function(latest){setData(latest)})}).catch(function(err){setError(err.message)}).finally(function(){setBusy(false)})}
|
|
2907
2907
|
function copySkill(){setBusy(true);setError(null);apiSend('POST','/skill',{operation:'copy',name:skill.name,newName:copyName}).then(function(body){var copied=body.skill;return apiSend('POST','/settings',{expectedFingerprint:data.settings.fingerprint,nodeSkills:(function(){var bindings={};bindings[node]=copied.name;return bindings})()}).then(function(saved){return apiGet('/settings').then(function(latest){setData(latest);setDraft(function(prev){return Object.assign({},prev,{fingerprint:saved.settings.fingerprint,nodeSkills:Object.assign({},prev.nodeSkills,saved.settings.nodeSkills)})});setSkill(copied);setContent(copied.content);setMessage('已复制并绑定到'+(data.settings.nodes.find(function(n){return n.id===node}) || {}).title+'节点,可以开始编辑。')})})}).catch(function(err){setError(err.message)}).finally(function(){setBusy(false)})}
|
|
2908
2908
|
if(!data || !draft)return e('section',{className:'pmw-settings'},e('h1',null,'SA 设置'),error ? e('div',{className:'pmw-settings__message is-error'},error,e('button',{className:'pmw-btn',onClick:load},'重新加载')) : e('p',{className:'pmw-settings__intro'},'正在读取配置…'))
|
|
2909
2909
|
var dirty=JSON.stringify([draft.workspaceRoot,draft.knowledgeDir,draft.prdArchiveDir,draft.skillsDir,draft.nodeSkills])!==JSON.stringify([data.settings.workspaceRoot,data.settings.knowledgeDir,data.settings.prdArchiveDir,data.settings.skillsDir,data.settings.nodeSkills])
|
|
2910
2910
|
return e('section',{className:'pmw-settings','aria-label':'SA 设置'},
|
|
2911
|
-
route.settingsReturn && e('button',{className:'pmw-btn pmw-btn--ghost pmw-settings-back',onClick:function(){var target=route.settingsReturn,tabs=Object.assign({},route.tabs);tabs[target.id]=target.stage;pmBus.set({selectedId:target.id,activeSessionId:target.sessionId,nav:'home',tabs:tabs,settingsReturn:null})}},'← 返回「'+route.settingsReturn.title+'」'),
|
|
2912
|
-
e('p',{className:'pmw-settings__eyebrow'},'SA WORKBENCH'),e('h1',null,data.settings.setupRequired?'设置你的 SA 工作台':'SA 设置'),e('p',{className:'pmw-settings__intro'},data.settings.setupRequired?'
|
|
2913
|
-
e('div',{className:'pmw-settings__tabs',role:'tablist'},['directories','skills'].map(function(id){return e('button',{key:id,role:'tab','aria-selected':tab===id,onClick:function(){setTab(id);setError(null);setMessage(null)}},id==='directories'?'目录与资料':'节点 Skill')})),
|
|
2911
|
+
!(props && props.onboarding) && route.settingsReturn && e('button',{className:'pmw-btn pmw-btn--ghost pmw-settings-back',onClick:function(){var target=route.settingsReturn,tabs=Object.assign({},route.tabs);tabs[target.id]=target.stage;pmBus.set({selectedId:target.id,activeSessionId:target.sessionId,nav:'home',tabs:tabs,settingsReturn:null})}},'← 返回「'+route.settingsReturn.title+'」'),
|
|
2912
|
+
e('p',{className:'pmw-settings__eyebrow'},'SA WORKBENCH'),e('h1',null,data.settings.setupRequired?'设置你的 SA 工作台':'SA 设置'),e('p',{className:'pmw-settings__intro'},data.settings.setupRequired?'首次使用可直接确认默认目录,或选择已有资料目录。保存后进入需求总览;更改工作目录后需完整退出并重开 DSH。':'配置资料位置和节点工作方法,让工作台适配你的流程。'),
|
|
2913
|
+
!(props && props.onboarding) && e('div',{className:'pmw-settings__tabs',role:'tablist'},['directories','skills'].map(function(id){return e('button',{key:id,role:'tab','aria-selected':tab===id,onClick:function(){setTab(id);setError(null);setMessage(null)}},id==='directories'?'目录与资料':'节点 Skill')})),
|
|
2914
2914
|
error && e('div',{role:'alert',className:'pmw-settings__message is-error'},error,e('button',{className:'pmw-btn pmw-btn--ghost',onClick:function(){load();if(skill){delete pmBus.skillEdits[skill.name];openSkill(skill.name)}}},'重新加载')),
|
|
2915
2915
|
message && e('div',{role:'status',className:'pmw-settings__message'},message),
|
|
2916
2916
|
tab==='directories' ? e('div',null,
|
|
2917
2917
|
[['workspaceRoot','工作目录','存放需求记录、方案、PRD 和原型;切换在下次启动生效。'],['knowledgeDir','知识库目录','业务资料、术语、规范和 PRD 模板;保存后生效。'],['prdArchiveDir','归档库目录','按交付版本整理的定稿 PRD;保存后生效。'],['skillsDir','我的 Skill 目录','用户副本与配套资源保存在这里,插件升级会保留它们。']].map(function(field){return e('div',{key:field[0],className:'pmw-settings__field'},e('label',{htmlFor:'pmw-dir-'+field[0]},e('strong',null,field[1])),e('p',{id:'pmw-dir-'+field[0]+'-hint'},field[2]),e('div',{className:'pmw-settings__directory'},e('input',{id:'pmw-dir-'+field[0],'aria-label':field[1],'aria-describedby':'pmw-dir-'+field[0]+'-hint',value:draft[field[0]],onChange:function(ev){changeField(field[0],ev.target.value)}}),e('button',{type:'button',className:'pmw-btn','aria-label':'浏览'+field[1],disabled:busy || !!picking,onClick:function(){browseDirectory(field)}},e(UiIcon,{name:'folder'}),picking===field[0]?'选择中…':'浏览目录')))}),
|
|
2918
2918
|
e('div',{className:'pmw-settings__message'},'当前工作目录:'+data.settings.activeWorkspaceRoot,data.settings.restartRequired && e('div',null,'下次启动切换到:'+data.settings.workspaceRoot),e('div',null,'完整需求归档:'+data.settings.requirementArchiveDir),e('div',null,'切换目录不会迁移原有资料。')),
|
|
2919
|
-
e('div',{className:'pmw-settings__actions'},e('button',{className:'pmw-btn pmw-btn--primary',disabled:busy || !!picking || (!dirty && !data.settings.setupRequired),onClick:save},busy?'保存中…':'保存目录配置'),dirty && e('span',{className:'pmw-settings__caption'},'有未保存的修改')),
|
|
2919
|
+
e('div',{className:'pmw-settings__actions'},e('button',{className:'pmw-btn pmw-btn--primary',disabled:busy || !!picking || (!dirty && !data.settings.setupRequired),onClick:save},busy?'保存中…':data.settings.setupRequired?(draft.workspaceRoot===data.settings.activeWorkspaceRoot?'使用默认目录,进入工作台':'保存目录,完成设置'):'保存目录配置'),dirty && e('span',{className:'pmw-settings__caption'},'有未保存的修改')),
|
|
2920
2920
|
e('p',{className:'pmw-settings__path'},'配置文件:'+data.settings.settingsFile)) :
|
|
2921
2921
|
e('div',null,e('div',{className:'pmw-settings__actions'},e('p',{className:'pmw-settings__caption'},'每个节点绑定一份主 Skill。将 Skill 文件夹放入“我的 Skill 目录”,展开选择框即可发现。'),e('button',{type:'button',className:'pmw-btn pmw-btn--ghost',disabled:refreshing,onClick:refreshCatalog},refreshing?'刷新中…':'刷新列表')),
|
|
2922
2922
|
e('div',{className:'pmw-settings__split'},
|
|
@@ -3519,7 +3519,7 @@ div:has(> [data-slot='sidebar.footer.action']) { display: contents; }
|
|
|
3519
3519
|
|
|
3520
3520
|
var children = []
|
|
3521
3521
|
|
|
3522
|
-
if (data.data && (data.data.setupRequired || data.data.restartRequired)) return e('div',{className:'pmw-root','data-sa-appearance':bus.appearance || saAppearance()},e(SettingsPanel))
|
|
3522
|
+
if (data.data && (data.data.setupRequired || data.data.restartRequired)) return e('div',{className:'pmw-root','data-sa-appearance':bus.appearance || saAppearance()},e(SettingsPanel,{onboarding:true,onComplete:function(){pmBus.set({nav:'home',selectedId:null,activeSessionId:null,settingsReturn:null});setView('home');reload()}}))
|
|
3523
3523
|
if (view === 'settings') return e('div', { className: 'pmw-root', 'data-sa-appearance':bus.appearance || saAppearance() }, e(SettingsPanel))
|
|
3524
3524
|
|
|
3525
3525
|
// header(纯标题,动作全部收进各自语境:Tab 空态/地铁图归档站/右栏线程条)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"0.1.
|
|
1
|
+
{"type":"module","version":"0.1.28"}
|