@weibaohui/experts-management 0.3.0 → 0.4.1
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/client/bundle.js +13 -3
- package/client/index.js +8 -2
- package/package.json +2 -2
- package/src/index.js +4 -8
package/client/bundle.js
CHANGED
|
@@ -19,7 +19,8 @@ window.__ModuleLoader__.load({
|
|
|
19
19
|
* title / hint / rows: [[label, value], ...] / initialPrompt
|
|
20
20
|
* run: async (prompt) => { jobId } — 发起执行
|
|
21
21
|
* poll: async (jobId) => { status, output, code }
|
|
22
|
-
* labels: { copy, copied, run, running, done, failed, outputLabel, close }
|
|
22
|
+
* labels: { copy, copied, run, running, done, failed, outputLabel, openSession, close }
|
|
23
|
+
* onOpenSession: (sessionId) => void — 可选;job 出现 sessionId 时渲染「打开会话」
|
|
23
24
|
* onClose
|
|
24
25
|
*
|
|
25
26
|
* 全部样式内联(主题 token + 回退值),消费者无需自带 CSS。
|
|
@@ -80,6 +81,8 @@ window.__ModuleLoader__.load({
|
|
|
80
81
|
setJob({ jobId: r.jobId, status: 'running', output: '', code: null })
|
|
81
82
|
}).catch(function (e) { setError(String(e && e.message)) }).finally(function () { setBusy(false) })
|
|
82
83
|
}
|
|
84
|
+
var canOpenSession = typeof props.onOpenSession === 'function' && job !== null && job.sessionId
|
|
85
|
+
var openSession = function () { props.onOpenSession(job.sessionId) }
|
|
83
86
|
var copy = function () {
|
|
84
87
|
if (typeof navigator !== 'undefined' && navigator.clipboard && navigator.clipboard.writeText) {
|
|
85
88
|
navigator.clipboard.writeText(prompt).then(function () { setCopied(true); setTimeout(function () { setCopied(false) }, 1500) }).catch(function () {})
|
|
@@ -103,6 +106,7 @@ window.__ModuleLoader__.load({
|
|
|
103
106
|
h('div', { style: { fontSize: 12, opacity: .7, margin: '4px 0' } }, (labels.outputLabel || 'Output') + ' · ' + statusText),
|
|
104
107
|
h('pre', { style: { maxHeight: 220, margin: 0, overflow: 'auto', whiteSpace: 'pre-wrap', fontSize: 12, background: 'var(--dsw-alias-bg-layer-2,transparent)', border: '1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.2))', borderRadius: '8px', padding: '8px' } }, job.output || '…')) : null,
|
|
105
108
|
h('div', { style: { display: 'flex', gap: 8 } },
|
|
109
|
+
canOpenSession ? h('button', { onClick: openSession, style: btnStyle }, labels.openSession || 'Open chat') : null,
|
|
106
110
|
h('button', { onClick: copy, style: btnStyle }, copied ? (labels.copied || 'Copied') : (labels.copy || 'Copy')),
|
|
107
111
|
h('button', { onClick: doRun, disabled: busy || (job !== null && job.status === 'running'), style: primaryStyle }, job !== null && job.status === 'running' ? (labels.running || 'Running…') : (labels.run || 'Run')))))
|
|
108
112
|
}
|
|
@@ -196,6 +200,7 @@ window.__ModuleLoader__.load({
|
|
|
196
200
|
installing: '安装中…',
|
|
197
201
|
installedDone: '已安装到用户库',
|
|
198
202
|
shareBtn: '分享',
|
|
203
|
+
openChat: '打开对话',
|
|
199
204
|
shareTitle: '分享专家到官方仓库',
|
|
200
205
|
shareHint: 'AI 将读取本机令牌,fork 官方仓库 → 建分支 → 提交该专家目录 → 创建 PR。确认或修改提示词后,复制到当前会话发送执行。',
|
|
201
206
|
shareParamName: '专家名',
|
|
@@ -293,6 +298,7 @@ window.__ModuleLoader__.load({
|
|
|
293
298
|
installing: 'Installing…',
|
|
294
299
|
installedDone: 'Installed to the user library',
|
|
295
300
|
shareBtn: 'Share',
|
|
301
|
+
openChat: 'Open chat',
|
|
296
302
|
shareTitle: 'Share expert to the official repo',
|
|
297
303
|
shareHint: 'AI will read the local token, fork the official repo → create a branch → commit the expert directory → open a PR. Review or edit the prompt, then copy it into the conversation to run.',
|
|
298
304
|
shareParamName: 'Expert',
|
|
@@ -791,6 +797,8 @@ window.__ModuleLoader__.load({
|
|
|
791
797
|
return shareDialogComponent
|
|
792
798
|
}
|
|
793
799
|
|
|
800
|
+
let sessionsApi = null // 「打开对话」用的宿主 sessions 服务(apply 时动态注入捕获)
|
|
801
|
+
|
|
794
802
|
/** 专家分享提示词:提交到 ntd-resource 的 experts/ 子树(与技能分享同管线、同 token)。 */
|
|
795
803
|
const EXPERT_SHARE_PROMPT = [
|
|
796
804
|
'请把本地专家「{{expertName}}」{{version}}打包提交到 GitCode 官方仓库 weibaohui/ntd-resource 的 experts/ 子树,作为一个 PR 供维护者审核。',
|
|
@@ -817,7 +825,7 @@ window.__ModuleLoader__.load({
|
|
|
817
825
|
'- 全程与最终汇报都使用中文。',
|
|
818
826
|
].join('\n')
|
|
819
827
|
|
|
820
|
-
function DetailModal({ name, source, t, onClose, onInstalled, onDeleted, onToast }) {
|
|
828
|
+
function DetailModal({ name, source, t, onClose, onInstalled, onDeleted, onToast, onOpenSession }) {
|
|
821
829
|
const [detail, setDetail] = useState(null)
|
|
822
830
|
const [error, setError] = useState('')
|
|
823
831
|
const [busy, setBusy] = useState(false)
|
|
@@ -1032,9 +1040,10 @@ window.__ModuleLoader__.load({
|
|
|
1032
1040
|
title: t('shareTitle'), hint: t('shareHint'),
|
|
1033
1041
|
rows: [[t('shareParamName'), detail.name], [t('shareParamVersion'), detail.version || '1.0.0'], [t('shareParamDir'), detail.dir]],
|
|
1034
1042
|
initialPrompt: PluginKit.substituteParams(EXPERT_SHARE_PROMPT, { expertName: detail.name, version: detail.version || '1.0.0', resourceDir: detail.dir, settingsFile: shareSettingsFile }),
|
|
1035
|
-
labels: { copy: t('copyPrompt'), copied: t('copied'), run: t('runBtn'), running: t('running'), done: t('runDone'), failed: t('runFailed'), outputLabel: t('outputLabel') },
|
|
1043
|
+
labels: { copy: t('copyPrompt'), copied: t('copied'), run: t('runBtn'), running: t('running'), done: t('runDone'), failed: t('runFailed'), outputLabel: t('outputLabel'), openSession: t('openChat') },
|
|
1036
1044
|
run: (prompt) => fetchJson(`${API}/share/run`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt, dir: detail.dir }) }),
|
|
1037
1045
|
poll: (id) => fetchJson(`${API}/share/run?id=${encodeURIComponent(id)}`),
|
|
1046
|
+
onOpenSession: (sessionId) => { setShareOpen(false); if (onOpenSession) onOpenSession(sessionId) },
|
|
1038
1047
|
onClose: () => setShareOpen(false),
|
|
1039
1048
|
}) : null))
|
|
1040
1049
|
}
|
|
@@ -1188,6 +1197,7 @@ window.__ModuleLoader__.load({
|
|
|
1188
1197
|
: null,
|
|
1189
1198
|
selected !== null ? h(DetailModal, {
|
|
1190
1199
|
name: selected.name, source: selected.source, t, onClose: () => setSelected(null),
|
|
1200
|
+
onOpenSession: (sessionId) => { try { sessionsApi.open(sessionId) } catch (e) { showToast(String(e && e.message)) } },
|
|
1191
1201
|
onInstalled: () => { setSelected(null); showToast(t('installedDone')); reload() },
|
|
1192
1202
|
onDeleted: () => { setSelected(null); showToast(t('removedDone')); reload() },
|
|
1193
1203
|
}) : null,
|
package/client/index.js
CHANGED
|
@@ -83,6 +83,7 @@ const ZH = {
|
|
|
83
83
|
installing: '安装中…',
|
|
84
84
|
installedDone: '已安装到用户库',
|
|
85
85
|
shareBtn: '分享',
|
|
86
|
+
openChat: '打开对话',
|
|
86
87
|
shareTitle: '分享专家到官方仓库',
|
|
87
88
|
shareHint: 'AI 将读取本机令牌,fork 官方仓库 → 建分支 → 提交该专家目录 → 创建 PR。确认或修改提示词后,复制到当前会话发送执行。',
|
|
88
89
|
shareParamName: '专家名',
|
|
@@ -180,6 +181,7 @@ const EN = {
|
|
|
180
181
|
installing: 'Installing…',
|
|
181
182
|
installedDone: 'Installed to the user library',
|
|
182
183
|
shareBtn: 'Share',
|
|
184
|
+
openChat: 'Open chat',
|
|
183
185
|
shareTitle: 'Share expert to the official repo',
|
|
184
186
|
shareHint: 'AI will read the local token, fork the official repo → create a branch → commit the expert directory → open a PR. Review or edit the prompt, then copy it into the conversation to run.',
|
|
185
187
|
shareParamName: 'Expert',
|
|
@@ -678,6 +680,8 @@ function getShareDialogComponent() {
|
|
|
678
680
|
return shareDialogComponent
|
|
679
681
|
}
|
|
680
682
|
|
|
683
|
+
let sessionsApi = null // 「打开对话」用的宿主 sessions 服务(apply 时动态注入捕获)
|
|
684
|
+
|
|
681
685
|
/** 专家分享提示词:提交到 ntd-resource 的 experts/ 子树(与技能分享同管线、同 token)。 */
|
|
682
686
|
const EXPERT_SHARE_PROMPT = [
|
|
683
687
|
'请把本地专家「{{expertName}}」{{version}}打包提交到 GitCode 官方仓库 weibaohui/ntd-resource 的 experts/ 子树,作为一个 PR 供维护者审核。',
|
|
@@ -704,7 +708,7 @@ const EXPERT_SHARE_PROMPT = [
|
|
|
704
708
|
'- 全程与最终汇报都使用中文。',
|
|
705
709
|
].join('\n')
|
|
706
710
|
|
|
707
|
-
function DetailModal({ name, source, t, onClose, onInstalled, onDeleted, onToast }) {
|
|
711
|
+
function DetailModal({ name, source, t, onClose, onInstalled, onDeleted, onToast, onOpenSession }) {
|
|
708
712
|
const [detail, setDetail] = useState(null)
|
|
709
713
|
const [error, setError] = useState('')
|
|
710
714
|
const [busy, setBusy] = useState(false)
|
|
@@ -919,9 +923,10 @@ function DetailModal({ name, source, t, onClose, onInstalled, onDeleted, onToast
|
|
|
919
923
|
title: t('shareTitle'), hint: t('shareHint'),
|
|
920
924
|
rows: [[t('shareParamName'), detail.name], [t('shareParamVersion'), detail.version || '1.0.0'], [t('shareParamDir'), detail.dir]],
|
|
921
925
|
initialPrompt: PluginKit.substituteParams(EXPERT_SHARE_PROMPT, { expertName: detail.name, version: detail.version || '1.0.0', resourceDir: detail.dir, settingsFile: shareSettingsFile }),
|
|
922
|
-
labels: { copy: t('copyPrompt'), copied: t('copied'), run: t('runBtn'), running: t('running'), done: t('runDone'), failed: t('runFailed'), outputLabel: t('outputLabel') },
|
|
926
|
+
labels: { copy: t('copyPrompt'), copied: t('copied'), run: t('runBtn'), running: t('running'), done: t('runDone'), failed: t('runFailed'), outputLabel: t('outputLabel'), openSession: t('openChat') },
|
|
923
927
|
run: (prompt) => fetchJson(`${API}/share/run`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt, dir: detail.dir }) }),
|
|
924
928
|
poll: (id) => fetchJson(`${API}/share/run?id=${encodeURIComponent(id)}`),
|
|
929
|
+
onOpenSession: (sessionId) => { setShareOpen(false); if (onOpenSession) onOpenSession(sessionId) },
|
|
925
930
|
onClose: () => setShareOpen(false),
|
|
926
931
|
}) : null))
|
|
927
932
|
}
|
|
@@ -1075,6 +1080,7 @@ function ExpertsPage({ t, embedded, onClose }) {
|
|
|
1075
1080
|
: null,
|
|
1076
1081
|
selected !== null ? h(DetailModal, {
|
|
1077
1082
|
name: selected.name, source: selected.source, t, onClose: () => setSelected(null),
|
|
1083
|
+
onOpenSession: (sessionId) => { try { sessionsApi.open(sessionId) } catch (e) { showToast(String(e && e.message)) } },
|
|
1078
1084
|
onInstalled: () => { setSelected(null); showToast(t('installedDone')); reload() },
|
|
1079
1085
|
onDeleted: () => { setSelected(null); showToast(t('removedDone')); reload() },
|
|
1080
1086
|
}) : null,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weibaohui/experts-management",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "dsh 插件 · 专家管理:管理 ntd 格式的专家与专家团队(plugin.json + Agent MD + 技能集),浏览/安装 50+ 内置专家市场;每个专家注册为「仅用户可调用」的技能,在对话输入框用 /expert-名称 即可以该专家的身份执行任务(宿主确定性注入角色定义与技能清单,不占用模型目录 token)。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"node": ">=22.5"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@weibaohui/dsh-plugin-kit": "^0.
|
|
47
|
+
"@weibaohui/dsh-plugin-kit": "^0.2.0",
|
|
48
48
|
"yaml": "^2.9.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
package/src/index.js
CHANGED
|
@@ -557,7 +557,7 @@ const MD_MAX_CHARS = 512 * 1024
|
|
|
557
557
|
|
|
558
558
|
module.exports = {
|
|
559
559
|
name: 'experts-management',
|
|
560
|
-
inject: ['skills', 'webServer', 'settings'],
|
|
560
|
+
inject: ['skills', 'webServer', 'settings', 'agents', 'agentDefaultModel', 'sessions'],
|
|
561
561
|
__internals: {
|
|
562
562
|
extractFrontmatter, parseFrontmatter, parseAgentMd, parseSkillMd, parsePluginJson,
|
|
563
563
|
localized, truncateDescription, resolveWithin, isSafeExpertName,
|
|
@@ -811,14 +811,10 @@ module.exports = {
|
|
|
811
811
|
})
|
|
812
812
|
|
|
813
813
|
// ── HTTP API ─────────────────────────────────────────────────────────
|
|
814
|
-
// 分享执行:进程内 agents 服务(web app 自身)可用则流式,否则 headless spawn
|
|
815
814
|
const shareRunJobs = new Map()
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
ctx.inject(['agents', 'agentDefaultModel', 'sessions'], (svcs) => { shareServices = svcs })
|
|
820
|
-
}
|
|
821
|
-
} catch {}
|
|
815
|
+
// 分享执行:进程内 agents 服务(静态注入,apply 时已就绪)。动态 ctx.inject
|
|
816
|
+
// 在 apply 内不触发是平台 gotcha(skills-management 同款教训)——改静态捕获
|
|
817
|
+
const shareServices = { agents: ctx.agents, agentDefaultModel: ctx.agentDefaultModel, sessions: ctx.sessions }
|
|
822
818
|
ctx.effect(() => ctx.webServer.register({
|
|
823
819
|
kind: 'prefix',
|
|
824
820
|
path: '/experts-management/api',
|