dsh-aris-panel 0.1.5 → 0.1.7
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/dsh/client.js +203 -21
- package/dsh/index.mjs +17 -0
- package/dsh/workbench.mjs +214 -30
- package/mcp-servers/claude-review/README.md +3 -0
- package/package.json +51 -51
- package/skills/auto-paper-improvement-loop/SKILL.md +50 -6
- package/skills/auto-paper-improvement-loop-claude/SKILL.md +633 -0
- package/skills/auto-review-loop-claude/SKILL.md +524 -0
- package/skills/citation-audit-claude/SKILL.md +512 -0
- package/skills/experiment-audit/SKILL.md +4 -4
- package/skills/experiment-audit-claude/SKILL.md +321 -0
- package/skills/experiment-bridge/SKILL.md +13 -0
- package/skills/gpt-image-2/SKILL.md +67 -0
- package/skills/idea-creator/SKILL.md +59 -17
- package/skills/idea-discovery/SKILL.md +24 -5
- package/skills/idea-discovery-robot/SKILL.md +13 -0
- package/skills/kill-argument/SKILL.md +7 -7
- package/skills/kill-argument-claude/SKILL.md +447 -0
- package/skills/meta-apply/SKILL.md +1 -1
- package/skills/meta-apply-claude/SKILL.md +151 -0
- package/skills/novelty-check/SKILL.md +49 -8
- package/skills/novelty-check-claude/SKILL.md +151 -0
- package/skills/paper-claim-audit/SKILL.md +3 -3
- package/skills/paper-claim-audit-claude/SKILL.md +358 -0
- package/skills/paper-figure/SKILL.md +36 -2
- package/skills/paper-figure-claude/SKILL.md +327 -0
- package/skills/paper-plan-claude/SKILL.md +295 -0
- package/skills/paper-poster-html/SKILL.md +13 -0
- package/skills/paper-talk/SKILL.md +13 -0
- package/skills/paper-write/SKILL.md +81 -3
- package/skills/paper-write-claude/SKILL.md +504 -0
- package/skills/paper-writing/SKILL.md +41 -5
- package/skills/proof-checker/SKILL.md +11 -11
- package/skills/proof-checker-claude/SKILL.md +876 -0
- package/skills/rebuttal/SKILL.md +13 -0
- package/skills/research-pipeline/SKILL.md +25 -6
- package/skills/research-refine-claude/SKILL.md +740 -0
- package/skills/research-refine-pipeline/SKILL.md +13 -0
- package/skills/research-review/SKILL.md +33 -8
- package/skills/research-review-claude/SKILL.md +185 -0
- package/skills/resubmit-pipeline/SKILL.md +14 -1
- package/skills/result-to-claim/SKILL.md +2 -2
- package/skills/result-to-claim-claude/SKILL.md +321 -0
- package/skills/shared-references/effort-contract.md +1 -1
- package/skills/shared-references/fan-out-pattern.md +1 -1
- package/skills/shared-references/reviewer-routing.md +10 -10
- package/skills/skills-codex/auto-paper-improvement-loop/SKILL.md +49 -5
- package/skills/skills-codex/experiment-audit/SKILL.md +5 -5
- package/skills/skills-codex/idea-creator/SKILL.md +46 -13
- package/skills/skills-codex/idea-discovery/SKILL.md +7 -5
- package/skills/skills-codex/kill-argument/SKILL.md +5 -5
- package/skills/skills-codex/meta-apply/SKILL.md +1 -1
- package/skills/skills-codex/novelty-check/SKILL.md +49 -8
- package/skills/skills-codex/paper-claim-audit/SKILL.md +3 -3
- package/skills/skills-codex/paper-write/SKILL.md +78 -2
- package/skills/skills-codex/paper-writing/SKILL.md +17 -4
- package/skills/skills-codex/proof-checker/SKILL.md +9 -9
- package/skills/skills-codex/research-pipeline/SKILL.md +12 -6
- package/skills/skills-codex/research-review/SKILL.md +32 -7
- package/skills/skills-codex/resubmit-pipeline/SKILL.md +1 -1
- package/skills/skills-codex/result-to-claim/SKILL.md +2 -2
- package/skills/skills-codex/shared-references/effort-contract.md +1 -1
- package/skills/skills-codex/shared-references/reviewer-routing.md +7 -7
- package/skills/skills-codex-claude-review/auto-paper-improvement-loop/SKILL.md +49 -5
- package/skills/skills-codex-claude-review/auto-review-loop/SKILL.md +8 -2
- package/skills/skills-codex-claude-review/novelty-check/SKILL.md +49 -8
- package/skills/skills-codex-claude-review/paper-write/SKILL.md +78 -2
- package/skills/skills-codex-claude-review/research-review/SKILL.md +29 -1
- package/skills/skills-codex-gemini-review/auto-paper-improvement-loop/SKILL.md +61 -16
- package/skills/skills-codex-gemini-review/idea-creator/SKILL.md +37 -13
- package/skills/skills-codex-gemini-review/idea-discovery/SKILL.md +4 -4
- package/skills/skills-codex-gemini-review/novelty-check/SKILL.md +49 -8
- package/skills/skills-codex-gemini-review/paper-write/SKILL.md +78 -2
- package/skills/skills-codex-gemini-review/paper-writing/SKILL.md +17 -4
- package/skills/skills-codex-gemini-review/research-review/SKILL.md +26 -1
- package/tools/convert_skills_to_llm_chat.py +11 -11
- package/tools/generate_codex_claude_review_overrides.py +67 -11
- package/skills/skills-codex/render-html/scripts/__pycache__/render_html.cpython-314.pyc +0 -0
- package/tools/__pycache__/check_skills_inventory.cpython-314.pyc +0 -0
package/dsh/client.js
CHANGED
|
@@ -204,6 +204,39 @@ window.__ModuleLoader__.load({
|
|
|
204
204
|
|
|
205
205
|
const WB_CHANNEL = '/aris-wb'
|
|
206
206
|
const WB_TICK = String.fromCharCode(96)
|
|
207
|
+
const IEEE_CONF_VENUES = ['ICASSP', 'ICIP', 'ICC', 'GLOBECOM', 'INFOCOM', 'ISCAS', 'IJCNN', 'WCNC', 'VTC', 'ICME', 'ACSSC', 'MMSP']
|
|
208
|
+
const IEEE_JOURNAL_VENUES = ['T-PAMI', 'TIP', 'TSP', 'TWC', 'TCOM', 'JSAC', 'TASLP', 'TNNLS', 'TCSVT', 'SPL', 'TIFS', 'TCYB']
|
|
209
|
+
const CLAUDE_VARIANT_MAP = {
|
|
210
|
+
'research-review': 'research-review-claude',
|
|
211
|
+
'novelty-check': 'novelty-check-claude',
|
|
212
|
+
'research-refine': 'research-refine-claude',
|
|
213
|
+
'auto-review-loop': 'auto-review-loop-claude',
|
|
214
|
+
'paper-plan': 'paper-plan-claude',
|
|
215
|
+
'paper-figure': 'paper-figure-claude',
|
|
216
|
+
'paper-write': 'paper-write-claude',
|
|
217
|
+
'auto-paper-improvement-loop': 'auto-paper-improvement-loop-claude',
|
|
218
|
+
'proof-checker': 'proof-checker-claude',
|
|
219
|
+
'kill-argument': 'kill-argument-claude',
|
|
220
|
+
'paper-claim-audit': 'paper-claim-audit-claude',
|
|
221
|
+
'citation-audit': 'citation-audit-claude',
|
|
222
|
+
'result-to-claim': 'result-to-claim-claude',
|
|
223
|
+
'experiment-audit': 'experiment-audit-claude',
|
|
224
|
+
'meta-apply': 'meta-apply-claude',
|
|
225
|
+
}
|
|
226
|
+
const CLAUDE_VARIANT_NAMES = 'research-review、novelty-check、research-refine、auto-review-loop、paper-plan、paper-figure、paper-write、auto-paper-improvement-loop、proof-checker、kill-argument、paper-claim-audit、citation-audit、result-to-claim、experiment-audit、meta-apply'
|
|
227
|
+
const CLAUDE_WORKFLOWS = ['idea-discovery', 'idea-discovery-robot', 'research-pipeline', 'research-refine-pipeline', 'experiment-bridge', 'paper-writing', 'rebuttal', 'resubmit-pipeline', 'paper-talk', 'paper-poster-html']
|
|
228
|
+
function wbClaudeUnsupportedHint(skillName) {
|
|
229
|
+
return '当前技能「' + String(skillName || '') + '」暂无 Claude 审稿变体,也不是受支持的工作流。' +
|
|
230
|
+
'Claude 审稿可用:独立审稿/写作技能(' + CLAUDE_VARIANT_NAMES + '),或工作流(' + CLAUDE_WORKFLOWS.join('、') + ')。请改选其一,或把审稿路由改回 codex/auto。'
|
|
231
|
+
}
|
|
232
|
+
function wbStripParam(text, key) {
|
|
233
|
+
if (typeof text !== 'string' || text === '') return ''
|
|
234
|
+
const safe = String(key).replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
235
|
+
let out = text.replace(new RegExp('(^|,\\s*)' + safe + '\\s*:\\s*[^,]+', 'gi'), ',')
|
|
236
|
+
out = out.replace(/,\s*,/g, ',').replace(/^,\s*/, '').replace(/,\s*$/, '').trim()
|
|
237
|
+
return out
|
|
238
|
+
}
|
|
239
|
+
function wbStripReviewerModel(text) { return wbStripParam(text, 'reviewer-model') }
|
|
207
240
|
const FLOW_STAGES = [
|
|
208
241
|
{ id: 1, title: '课题现状与可行性', desc: '提出方向,调研现状与可行性', skills: ['research-lit', 'idea-discovery', 'arxiv', 'deepxiv'], next: '用 research-lit 调研现状,或用 idea-discovery 一次跑完「现状→想法→排名」' },
|
|
209
242
|
{ id: 2, title: '细化理解形成思路', desc: '来回交流,打磨出研究思路', skills: ['idea-creator', 'novelty-check', 'kill-argument', 'research-review'], next: 'idea-creator 补新想法、novelty-check 查新、kill-argument 对抗检验后敲定思路' },
|
|
@@ -223,7 +256,7 @@ function inferStage(ov) {
|
|
|
223
256
|
|
|
224
257
|
const WORKFLOW_CHIPS = [
|
|
225
258
|
{ num: 'W1', label: 'Idea Discovery 想法发现', entry: 'idea-discovery', when: '开始新研究,有方向但还没想法时', desc: '完整想法发现管线:多源文献调研 → 头脑风暴 8-12 个具体想法 → 可行性与算力过滤 → 深度新颖性验证 + 魔鬼代言人审 → top 2-3 想法并行 GPU 试跑(30min-2h) → 按实验信号排名 → 精炼出问题锚定提案 → claim 驱动的实验路线图。产出 IDEA_REPORT.md 排名报告 + FINAL_PROPOSAL + EXPERIMENT_PLAN。' },
|
|
226
|
-
{ num: 'W1.5', label: 'Experiment Bridge 实验桥接', entry: 'experiment-bridge', when: '已有实验计划,需要落地实现代码并跑出结果时', desc: '把实验计划变成运行结果:解析 EXPERIMENT_PLAN.md → 实现实验代码(带 argparse/日志/种子) → GPT-
|
|
259
|
+
{ num: 'W1.5', label: 'Experiment Bridge 实验桥接', entry: 'experiment-bridge', when: '已有实验计划,需要落地实现代码并跑出结果时', desc: '把实验计划变成运行结果:解析 EXPERIMENT_PLAN.md → 实现实验代码(带 argparse/日志/种子) → GPT-6-Astra 审代码抓逻辑 bug → 最小实验 sanity check → 部署 GPU 跑全套 → 收集结果更新实验追踪。' },
|
|
227
260
|
{ num: 'W2', label: 'Auto Review Loop 自动审稿循环', entry: 'auto-review-loop', when: '论文/结果需要迭代打磨、想挂机自动改进时', desc: '无人值守审稿循环:外部审稿人深审论文/claims/实验指出弱点 → 自动修复(重写章节/加 baseline/补实验) → 重新评估,循环直到 ≥6/10 或 4 轮上限;>4 GPU 小时的实验自动跳过并标记人工跟进,断点可从 REVIEW_STATE.json 恢复。' },
|
|
228
261
|
{ num: 'W3', label: 'Paper Writing 论文写作', entry: 'paper-writing', when: '叙事报告就绪、准备把研究写成论文时', desc: '从叙事报告到可投稿 PDF:claims-evidence 矩阵 + 章节规划 → 数据驱动图表 → 逐节 LaTeX → 编译 PDF 修错 + 页数检查 → 两轮外部内容审 + 最终格式检查。' },
|
|
229
262
|
{ num: 'W4', label: 'Rebuttal 回复审稿', entry: 'rebuttal', when: '收到会议/期刊审稿意见时', desc: '安全回复审稿意见:解析意见拆成 issue 卡片 → 全局策略 + 逐审稿人优先级 → 可选自动补实验 → 起草回复 → 6 项安全检查(覆盖/溯源/承诺/语气/一致性/字数) → GPT 压力测试 → 输出限字版 + 富文本版。' },
|
|
@@ -394,6 +427,14 @@ const SKILL_ZH = {
|
|
|
394
427
|
"wiki-enrich": "wiki 补全",
|
|
395
428
|
"writing-systems-papers": "系统论文写作指南",
|
|
396
429
|
"xlsx": "Excel 表格处理",
|
|
430
|
+
"research-review-claude": "研究深度审稿(Claude Code)",
|
|
431
|
+
"novelty-check-claude": "新颖性查新(Claude Code)",
|
|
432
|
+
"research-refine-claude": "研究方案精炼(Claude Code)",
|
|
433
|
+
"auto-review-loop-claude": "自动审稿循环(Claude Code)",
|
|
434
|
+
"paper-plan-claude": "论文大纲规划(Claude Code)",
|
|
435
|
+
"paper-figure-claude": "论文图表生成(Claude Code)",
|
|
436
|
+
"paper-write-claude": "论文写作(Claude Code)",
|
|
437
|
+
"auto-paper-improvement-loop-claude": "论文自动改进循环(Claude Code)",
|
|
397
438
|
}
|
|
398
439
|
|
|
399
440
|
function WbProgress(props) {
|
|
@@ -430,18 +471,68 @@ function WbTrigger(props) {
|
|
|
430
471
|
const [effort, setEffort] = React.useState('balanced')
|
|
431
472
|
const [assurance, setAssurance] = React.useState('draft')
|
|
432
473
|
const [difficulty, setDifficulty] = React.useState('medium')
|
|
474
|
+
const [illustration, setIllustration] = React.useState('figurespec')
|
|
475
|
+
const [figureCheck, setFigureCheck] = React.useState('visual')
|
|
433
476
|
const [extra, setExtra] = React.useState('')
|
|
434
477
|
const [venue, setVenue] = React.useState('')
|
|
478
|
+
const [ieeeVenue, setIeeeVenue] = React.useState('')
|
|
435
479
|
const [gpu, setGpu] = React.useState('')
|
|
436
480
|
const [reviewer, setReviewer] = React.useState('auto')
|
|
481
|
+
const [reviewerModel, setReviewerModel] = React.useState('')
|
|
482
|
+
const [codexModels, setCodexModels] = React.useState([])
|
|
483
|
+
const [claudeModels, setClaudeModels] = React.useState([])
|
|
437
484
|
const [humanCheckpoint, setHumanCheckpoint] = React.useState(false)
|
|
438
485
|
const [autoProceed, setAutoProceed] = React.useState(true)
|
|
439
486
|
const [busy, setBusy] = React.useState(false)
|
|
487
|
+
const [modelOpen, setModelOpen] = React.useState(false)
|
|
488
|
+
const modelDirtyRef = React.useRef(false)
|
|
489
|
+
|
|
490
|
+
const loadModels = function (route) {
|
|
491
|
+
const isClaude = route === 'claude'
|
|
492
|
+
if (!isClaude && route !== 'codex' && route !== 'auto') {
|
|
493
|
+
setCodexModels([])
|
|
494
|
+
if (!modelDirtyRef.current) setReviewerModel('')
|
|
495
|
+
return
|
|
496
|
+
}
|
|
497
|
+
const apply = function (ok, models, suggested) {
|
|
498
|
+
if (isClaude) setClaudeModels(models); else setCodexModels(models)
|
|
499
|
+
if (modelDirtyRef.current) return
|
|
500
|
+
const preferred = isClaude ? 'claude-fable-5' : 'gpt-5.6-sol'
|
|
501
|
+
const sug = ok && typeof suggested === 'string' && suggested !== '' ? suggested : ''
|
|
502
|
+
const hasPreferred = models.some(function (m) { return m && m.slug === preferred })
|
|
503
|
+
setReviewerModel(sug !== '' ? sug : (hasPreferred ? preferred : (models.length > 0 ? models[0].slug : preferred)))
|
|
504
|
+
}
|
|
505
|
+
if (isClaude) setClaudeModels([]); else setCodexModels([])
|
|
506
|
+
connection.rpc.call(WB_CHANNEL, isClaude ? 'claude-models' : 'codex-models', {}).then(function (res) {
|
|
507
|
+
const ok = !!(res && res.ok)
|
|
508
|
+
apply(ok, ok && Array.isArray(res.value.models) ? res.value.models : [], ok ? res.value.suggested : undefined)
|
|
509
|
+
}).catch(function () { apply(false, [], undefined) })
|
|
510
|
+
}
|
|
511
|
+
React.useEffect(function () { loadModels(reviewer) }, [reviewer])
|
|
512
|
+
React.useEffect(function () {
|
|
513
|
+
if (String(skill || '').endsWith('-claude') && reviewer !== 'claude') {
|
|
514
|
+
modelDirtyRef.current = false
|
|
515
|
+
loadModels('claude')
|
|
516
|
+
}
|
|
517
|
+
}, [skill])
|
|
440
518
|
|
|
441
519
|
const doLaunch = function () {
|
|
442
520
|
if (!skill) { setStatus('请先选择技能'); return }
|
|
521
|
+
let effSkill = skill
|
|
522
|
+
if (reviewer === 'claude' && !String(skill || '').endsWith('-claude')) {
|
|
523
|
+
effSkill = CLAUDE_VARIANT_MAP[skill] || (CLAUDE_WORKFLOWS.indexOf(String(skill || '')) !== -1 ? skill : '')
|
|
524
|
+
}
|
|
525
|
+
if (reviewer === 'claude' && !effSkill) {
|
|
526
|
+
setStatus(wbClaudeUnsupportedHint(skill))
|
|
527
|
+
return
|
|
528
|
+
}
|
|
529
|
+
const effVenue = venue === 'ieee-conf' || venue === 'ieee-journal' ? ieeeVenue : venue
|
|
530
|
+
if ((venue === 'ieee-conf' || venue === 'ieee-journal') && !ieeeVenue) {
|
|
531
|
+
setStatus('已选 IEEE 大类:请在下拉中选择具体的会议/期刊')
|
|
532
|
+
return
|
|
533
|
+
}
|
|
443
534
|
setBusy(true)
|
|
444
|
-
connection.rpc.call(WB_CHANNEL, 'launch', { sessionId: sessionId, skill: skill, args: args, autoProceed: autoProceed, effort: effort, assurance: assurance, difficulty: difficulty, venue:
|
|
535
|
+
connection.rpc.call(WB_CHANNEL, 'launch', { sessionId: sessionId, skill: effSkill || skill, args: args, autoProceed: autoProceed, effort: effort, assurance: assurance, difficulty: difficulty, illustration: illustration, figureCheck: figureCheck, venue: effVenue, gpu: gpu, reviewer: reviewer, reviewerModel: reviewerModel, humanCheckpoint: humanCheckpoint, targetSessionId: props.targetSessionId && props.targetSessionId !== '__new__' ? props.targetSessionId : undefined, newSession: props.targetSessionId === '__new__', extra: extra })
|
|
445
536
|
.then(function (res) {
|
|
446
537
|
if (res.ok) {
|
|
447
538
|
setStatus(res.value.injected ? '已注入会话(' + res.value.method + '),执行已唤醒,请到会话窗口查看进度' : '未能注入,请复制提示词手动发送:' + res.value.prompt)
|
|
@@ -458,14 +549,33 @@ function WbTrigger(props) {
|
|
|
458
549
|
if (effort !== 'balanced') params.push('effort: ' + effort)
|
|
459
550
|
if (assurance !== 'draft') params.push('assurance: ' + assurance)
|
|
460
551
|
if (difficulty !== 'medium') params.push('difficulty: ' + difficulty)
|
|
552
|
+
if (illustration && illustration !== 'figurespec') params.push('illustration: ' + illustration)
|
|
553
|
+
if (figureCheck && figureCheck !== 'visual') params.push('figure check: ' + figureCheck)
|
|
461
554
|
if (humanCheckpoint === true) params.push('human checkpoint: true')
|
|
462
|
-
|
|
555
|
+
const effVenue = venue === 'ieee-conf' || venue === 'ieee-journal' ? ieeeVenue : venue
|
|
556
|
+
if (effVenue) params.push('venue: ' + effVenue)
|
|
463
557
|
if (gpu) params.push('gpu: ' + gpu)
|
|
464
|
-
|
|
465
|
-
|
|
558
|
+
const isClaudeSkill = String(skill || '').endsWith('-claude')
|
|
559
|
+
if (reviewer !== 'auto' && (reviewer !== 'claude' || !isClaudeSkill)) params.push('reviewer: ' + reviewer)
|
|
560
|
+
let ex = extra.trim()
|
|
561
|
+
if (effVenue) ex = wbStripParam(ex, 'venue')
|
|
562
|
+
const useClaude = reviewer === 'claude' || isClaudeSkill
|
|
563
|
+
const rm = reviewerModel.trim()
|
|
564
|
+
if (rm && useClaude) {
|
|
565
|
+
params.push('reviewer-model: ' + rm)
|
|
566
|
+
ex = wbStripReviewerModel(ex)
|
|
567
|
+
} else if (rm && (reviewer === 'auto' || reviewer === 'codex')) {
|
|
568
|
+
params.push('reviewer-model: ' + rm)
|
|
569
|
+
ex = wbStripReviewerModel(ex)
|
|
570
|
+
}
|
|
466
571
|
if (ex) params.push(ex)
|
|
467
572
|
const arg = args.trim()
|
|
468
|
-
|
|
573
|
+
let effSkill = String(skill || '')
|
|
574
|
+
if (reviewer === 'claude' && !effSkill.endsWith('-claude')) {
|
|
575
|
+
effSkill = CLAUDE_VARIANT_MAP[skill] || (CLAUDE_WORKFLOWS.indexOf(skill) !== -1 ? skill : '')
|
|
576
|
+
}
|
|
577
|
+
if (reviewer === 'claude' && !effSkill) return ''
|
|
578
|
+
return '/' + effSkill + (arg ? ' "' + arg + '"' : '') + (params.length > 0 ? ' — ' + params.join(', ') : '')
|
|
469
579
|
}
|
|
470
580
|
const doCopy = function () {
|
|
471
581
|
if (!skill) { setStatus('请先选择技能'); return }
|
|
@@ -477,11 +587,13 @@ function WbTrigger(props) {
|
|
|
477
587
|
;(skills || []).forEach(function (s) {
|
|
478
588
|
selectOptions.push(h('option', { key: s.name, value: s.name }, s.name + ' — ' + (SKILL_ZH[s.name] || s.description || '').slice(0, 60)))
|
|
479
589
|
})
|
|
590
|
+
const isClaudeModel = reviewer === 'claude' || String(skill || '').endsWith('-claude')
|
|
591
|
+
const modelChoices = isClaudeModel ? claudeModels : codexModels
|
|
480
592
|
|
|
481
593
|
return h('div', { className: 'wb-trigger' },
|
|
482
594
|
h('div', { className: 'wb-guide-title' }, '技能触发'),
|
|
483
595
|
h('div', { className: 'wb-trigger-row' },
|
|
484
|
-
h('select', { className: 'wb-skill-select', value: skill, onChange: function (e) { props.onSkill(
|
|
596
|
+
h('select', { className: 'wb-skill-select', value: skill, onChange: function (e) { const v = e.target.value; props.onSkill(v); if (String(v).endsWith('-claude')) { if (reviewer !== 'claude') { modelDirtyRef.current = false; loadModels('claude') } } else if (reviewer !== 'claude') loadModels(reviewer) } }, selectOptions),
|
|
485
597
|
h('input', { className: 'wb-args', placeholder: '研究方向 (arguments):例如 discrete diffusion LMs 的 factorized gap', value: args, onChange: function (e) { props.onArgs(e.target.value) } })),
|
|
486
598
|
h('div', { className: 'wb-trigger-row wb-param-row' },
|
|
487
599
|
h('label', { className: 'wb-param-label' }, '无人值守: '),
|
|
@@ -505,28 +617,60 @@ function WbTrigger(props) {
|
|
|
505
617
|
h('option', { value: 'medium' }, 'medium (默认)'),
|
|
506
618
|
h('option', { value: 'hard' }, 'hard (更强)'),
|
|
507
619
|
h('option', { value: 'nightmare' }, 'nightmare (极限)'))),
|
|
620
|
+
h('div', { className: 'wb-trigger-row wb-param-row' },
|
|
621
|
+
h('label', { className: 'wb-param-label' }, '示意图: '),
|
|
622
|
+
h('select', { className: 'wb-param-select', value: illustration, onChange: function (e) { setIllustration(e.target.value) } },
|
|
623
|
+
h('option', { value: 'figurespec' }, 'figurespec (默认)'),
|
|
624
|
+
h('option', { value: 'gemini' }, 'gemini (AI)'),
|
|
625
|
+
h('option', { value: 'codex-image2' }, 'codex-image2 (AI)'),
|
|
626
|
+
h('option', { value: 'gpt-image-2' }, 'gpt-image-2 (本机转接)'),
|
|
627
|
+
h('option', { value: 'mermaid' }, 'mermaid'),
|
|
628
|
+
h('option', { value: 'false' }, 'false (手动)')),
|
|
629
|
+
h('label', { className: 'wb-param-label' }, '图面检查: '),
|
|
630
|
+
h('select', { className: 'wb-param-select', value: figureCheck, onChange: function (e) { setFigureCheck(e.target.value) } },
|
|
631
|
+
h('option', { value: 'visual' }, 'visual (看图评分, 默认)'),
|
|
632
|
+
h('option', { value: 'text' }, 'text (仅文字)'),
|
|
633
|
+
h('option', { value: 'off' }, 'off (跳过)'))),
|
|
508
634
|
h('div', { className: 'wb-trigger-row wb-param-row' },
|
|
509
635
|
h('label', { className: 'wb-param-label' }, '会议: '),
|
|
510
|
-
h('select', { className: 'wb-param-select', value: venue, onChange: function (e) {
|
|
636
|
+
h('select', { className: 'wb-param-select', value: venue, onChange: function (e) { const v = e.target.value; setVenue(v); if (v !== 'ieee-conf' && v !== 'ieee-journal') setIeeeVenue('') } },
|
|
511
637
|
h('option', { value: '' }, '(默认)'),
|
|
512
638
|
h('option', { value: 'ICLR' }, 'ICLR'), h('option', { value: 'NeurIPS' }, 'NeurIPS'),
|
|
513
639
|
h('option', { value: 'ICML' }, 'ICML'), h('option', { value: 'CVPR' }, 'CVPR'),
|
|
514
|
-
h('option', { value: 'AAAI' }, 'AAAI'), h('option', { value: 'ACL' }, 'ACL')
|
|
640
|
+
h('option', { value: 'AAAI' }, 'AAAI'), h('option', { value: 'ACL' }, 'ACL'),
|
|
641
|
+
h('option', { value: 'ieee-conf' }, 'IEEE Conf (IEEEtran)…'),
|
|
642
|
+
h('option', { value: 'ieee-journal' }, 'IEEE Journal (IEEEtran)…')),
|
|
643
|
+
(venue === 'ieee-conf' || venue === 'ieee-journal') ? h('select', { className: 'wb-param-select', value: ieeeVenue, onChange: function (e) { setIeeeVenue(e.target.value) } },
|
|
644
|
+
h('option', { value: '' }, '(选择具体' + (venue === 'ieee-conf' ? '会议' : '期刊') + '…)'),
|
|
645
|
+
(venue === 'ieee-conf' ? IEEE_CONF_VENUES : IEEE_JOURNAL_VENUES).map(function (v) { return h('option', { key: v, value: v }, v) })) : null,
|
|
515
646
|
h('label', { className: 'wb-param-label' }, 'GPU: '),
|
|
516
647
|
h('select', { className: 'wb-param-select', value: gpu, onChange: function (e) { setGpu(e.target.value) } },
|
|
517
648
|
h('option', { value: '' }, '(默认)'), h('option', { value: 'local' }, 'local'),
|
|
518
649
|
h('option', { value: 'remote' }, 'remote'), h('option', { value: 'vast' }, 'vast'),
|
|
519
650
|
h('option', { value: 'modal' }, 'modal')),
|
|
520
651
|
h('label', { className: 'wb-param-label' }, '审稿路由: '),
|
|
521
|
-
h('select', { className: 'wb-param-select', value: reviewer, onChange: function (e) {
|
|
652
|
+
h('select', { className: 'wb-param-select', value: reviewer, onChange: function (e) { const v = e.target.value; modelDirtyRef.current = false; setReviewer(v) } },
|
|
522
653
|
h('option', { value: 'auto' }, 'auto (默认)'), h('option', { value: 'codex' }, 'codex'),
|
|
654
|
+
h('option', { value: 'claude' }, 'claude (Claude Code)'),
|
|
523
655
|
h('option', { value: 'oracle-pro' }, 'oracle-pro'), h('option', { value: 'manual' }, 'manual')),
|
|
656
|
+
(reviewer === 'auto' || reviewer === 'codex' || reviewer === 'claude' || String(skill || '').endsWith('-claude')) ? [
|
|
657
|
+
h('label', { className: 'wb-param-label', key: 'wb-rm-label' }, '审稿模型: '),
|
|
658
|
+
h('span', { className: 'wb-model-combo', key: 'wb-rm-combo' },
|
|
659
|
+
h('input', { className: 'wb-param-input', placeholder: isClaudeModel ? '选择或手动输入;留空=claude-fable-5' : '选择或手动输入;留空=默认 gpt-5.6-sol', value: reviewerModel, onFocus: function () { setModelOpen(true) }, onBlur: function () { setTimeout(function () { setModelOpen(false) }, 150) }, onChange: function (e) { modelDirtyRef.current = true; setReviewerModel(e.target.value); setModelOpen(false) } }),
|
|
660
|
+
h('button', { type: 'button', className: 'wb-model-btn', onMouseDown: function (e) { e.preventDefault() }, onClick: function () { setModelOpen(!modelOpen) } }, '▾'),
|
|
661
|
+
modelOpen ? h('div', { className: 'wb-model-pop', key: 'wb-rm-pop' },
|
|
662
|
+
modelChoices.length > 0 ? modelChoices.map(function (m) {
|
|
663
|
+
return h('div', { className: 'wb-model-opt', key: m.slug, onMouseDown: function (e) { e.preventDefault() }, onClick: function () { modelDirtyRef.current = true; setReviewerModel(m.slug); setModelOpen(false) } },
|
|
664
|
+
(m.display || m.slug) + (Array.isArray(m.levels) && m.levels.length ? ' · 推理档:' + m.levels.join('/') : ''))
|
|
665
|
+
}) : [h('div', { className: 'wb-model-empty', key: 'empty' }, isClaudeModel ? 'Claude 模型列表加载中或不可用,可手动输入' : 'Codex 模型列表加载中或不可用,可手动输入')])
|
|
666
|
+
: null),
|
|
667
|
+
] : null,
|
|
524
668
|
h('label', { className: 'wb-param-label' }, '人工确认: '),
|
|
525
669
|
h('select', { className: 'wb-param-select', value: humanCheckpoint ? 'true' : 'false', onChange: function (e) { setHumanCheckpoint(e.target.value === 'true') } },
|
|
526
670
|
h('option', { value: 'false' }, 'false (默认)'), h('option', { value: 'true' }, 'true (暂停批准)'))),
|
|
527
671
|
h('div', { className: 'wb-trigger-row' },
|
|
528
672
|
h('input', { className: 'wb-extra', placeholder: '其他参数 key: value, key2: value2(可选,如 sources: arxiv, web / gpu: vast)', value: extra, onChange: function (e) { setExtra(e.target.value) } })),
|
|
529
|
-
skill ? h('div', { className: 'wb-cmd-preview' }, 'ARIS 命令: ' + buildCmd()) : null,
|
|
673
|
+
skill ? h('div', { className: 'wb-cmd-preview', style: buildCmd() ? undefined : { color: '#c42b1c' } }, 'ARIS 命令: ' + (buildCmd() || wbClaudeUnsupportedHint(skill))) : null,
|
|
530
674
|
h('div', { className: 'wb-trigger-row' },
|
|
531
675
|
h('button', { className: 'wb-btn', onClick: doLaunch, disabled: busy }, busy ? '触发中…' : '触发'),
|
|
532
676
|
h('button', { className: 'wb-btn wb-btn-copy', onClick: doCopy }, '复制提示词')),
|
|
@@ -534,6 +678,15 @@ function WbTrigger(props) {
|
|
|
534
678
|
status ? h('div', { className: 'wb-status' }, status) : null)
|
|
535
679
|
}
|
|
536
680
|
function wbNote(text) { return h('p', { className: 'wb-note' }, text) }
|
|
681
|
+
function wbWhen(ms) {
|
|
682
|
+
const seconds = Math.max(0, Math.round((Date.now() - ms) / 1000))
|
|
683
|
+
if (seconds < 60) return seconds + 's前'
|
|
684
|
+
const minutes = Math.round(seconds / 60)
|
|
685
|
+
if (minutes < 60) return minutes + '分钟前'
|
|
686
|
+
const hours = Math.round(minutes / 60)
|
|
687
|
+
if (hours < 24) return hours + '小时前'
|
|
688
|
+
return Math.round(hours / 24) + '天前'
|
|
689
|
+
}
|
|
537
690
|
function wbKey(label, value) {
|
|
538
691
|
return h('div', { className: 'wb-row' }, h('span', { className: 'wb-key' }, label), h('span', { className: 'wb-val' }, value))
|
|
539
692
|
}
|
|
@@ -683,19 +836,23 @@ function ArisWorkbenchView(props) {
|
|
|
683
836
|
const [args, setArgs] = React.useState('')
|
|
684
837
|
const [permPreset, setPermPreset] = React.useState('read-only')
|
|
685
838
|
const [permStatus, setPermStatus] = React.useState(undefined)
|
|
839
|
+
const [targetSessionId, setTargetSessionId] = React.useState(undefined)
|
|
840
|
+
const [workspaceId, setWorkspaceId] = React.useState(undefined)
|
|
686
841
|
|
|
687
842
|
React.useEffect(function () {
|
|
688
843
|
let live = true
|
|
689
|
-
connection.rpc.call(WB_CHANNEL, '
|
|
844
|
+
connection.rpc.call(WB_CHANNEL, 'workspaces', {})
|
|
690
845
|
.then(function (res) {
|
|
691
846
|
if (!live) return
|
|
692
|
-
const
|
|
693
|
-
if (Array.isArray(
|
|
694
|
-
setWorkspaces(
|
|
695
|
-
|
|
847
|
+
const list = res.ok && res.value ? res.value.workspaces : undefined
|
|
848
|
+
if (Array.isArray(list) && list.length > 0) {
|
|
849
|
+
setWorkspaces(list)
|
|
850
|
+
const first = list[0]
|
|
851
|
+
setWorkspaceId(first.id)
|
|
852
|
+
if (sessionId === undefined && first.sessions && first.sessions.length > 0) setSessionId(first.sessions[0].id)
|
|
696
853
|
} else {
|
|
697
854
|
setWorkspaces([])
|
|
698
|
-
setError(res.error ? res.error.message : '
|
|
855
|
+
setError(res.error ? res.error.message : 'workspaces RPC failed')
|
|
699
856
|
}
|
|
700
857
|
})
|
|
701
858
|
.catch(function (cause) { if (live) { setError(String(cause)); setWorkspaces([]) } })
|
|
@@ -765,6 +922,8 @@ function ArisWorkbenchView(props) {
|
|
|
765
922
|
const ideas = data && data.ideas
|
|
766
923
|
const exps = data && data.experiments
|
|
767
924
|
const stage = ov ? inferStage(ov) : 1
|
|
925
|
+
const curWs = workspaces && workspaceId ? workspaces.find(function (w) { return w.id === workspaceId }) : (workspaces && workspaces.length > 0 ? workspaces[0] : undefined)
|
|
926
|
+
const wsSessions = curWs && Array.isArray(curWs.sessions) ? curWs.sessions.filter(function (s) { return s.title || s.msgCount > 0 }) : []
|
|
768
927
|
|
|
769
928
|
const children = []
|
|
770
929
|
children.push(h('div', { className: 'wb-header', key: 'head' },
|
|
@@ -775,17 +934,31 @@ function ArisWorkbenchView(props) {
|
|
|
775
934
|
if (workspaces && workspaces.length > 1) {
|
|
776
935
|
children.push(h('div', { className: 'wb-picker', key: 'picker' },
|
|
777
936
|
h('label', null, '工作区: '),
|
|
778
|
-
h('select', { value:
|
|
779
|
-
workspaces.
|
|
937
|
+
h('select', { value: workspaceId, onChange: function (e) {
|
|
938
|
+
const w = workspaces.find(function (x) { return x.id === e.target.value })
|
|
939
|
+
setWorkspaceId(e.target.value)
|
|
940
|
+
setTargetSessionId(undefined)
|
|
941
|
+
if (w && w.sessions && w.sessions.length > 0) setSessionId(w.sessions[0].id)
|
|
942
|
+
} },
|
|
943
|
+
workspaces.map(function (w) {
|
|
944
|
+
const base = w.path ? String(w.path).split(/[\\/]/).filter(Boolean).pop() : ''
|
|
945
|
+
return h('option', { key: w.id, value: w.id }, w.title + (base && base !== w.title ? ' (' + base + ')' : ''))
|
|
946
|
+
}))))
|
|
780
947
|
}
|
|
781
948
|
if (workspaces && workspaces.length === 0) {
|
|
782
|
-
children.push(wbNote('
|
|
949
|
+
children.push(wbNote('无工作区数据 — 请先在 DSH 中打开一个工作区,然后点「刷新」'))
|
|
783
950
|
}
|
|
784
951
|
if (error) children.push(h('div', { className: 'wb-error', key: 'err' }, error))
|
|
785
952
|
if (sessionId === undefined && workspaces === undefined) children.push(wbNote('正在连接工作区…'))
|
|
786
953
|
if (sessionId !== undefined) {
|
|
787
954
|
|
|
788
955
|
children.push(h('div', { className: 'wb-picker', key: 'pctl' },
|
|
956
|
+
h('label', null, '会话: '),
|
|
957
|
+
h('select', { className: 'wb-perm-select', value: targetSessionId || (wsSessions.length > 0 ? wsSessions[0].id : ''), onChange: function (e) { setTargetSessionId(e.target.value) } },
|
|
958
|
+
wsSessions.map(function (s) {
|
|
959
|
+
const label = (s.title || '未命名会话') + ' [' + s.id.slice(0, 8) + ']' + (s.updatedAt ? ' · ' + wbWhen(s.updatedAt) : '') + (s.msgCount ? ' (' + s.msgCount + '条)' : '')
|
|
960
|
+
return h('option', { key: s.id, value: s.id, title: s.id }, label)
|
|
961
|
+
})),
|
|
789
962
|
h('label', null, '权限: '),
|
|
790
963
|
h('select', { className: 'wb-perm-select', value: permPreset, onChange: function (e) {
|
|
791
964
|
const v = e.target.value
|
|
@@ -800,7 +973,7 @@ function ArisWorkbenchView(props) {
|
|
|
800
973
|
permStatus ? h('span', { className: 'wb-perm-status' }, permStatus) : null))
|
|
801
974
|
children.push(h(WbPanorama, { key: 'pano', onPick: function (name) { setSkill(name) } }))
|
|
802
975
|
children.push(h(WbProgress, { key: 'progress', overview: ov, stage: stage }))
|
|
803
|
-
children.push(h(WbTrigger, { key: 'trigger', connection: connection, sessionId: sessionId, skills: skills, skill: skill, args: args, skillError: skillError, onSkill: setSkill, onArgs: setArgs }))
|
|
976
|
+
children.push(h(WbTrigger, { key: 'trigger', connection: connection, sessionId: sessionId, skills: skills, skill: skill, args: args, targetSessionId: targetSessionId, skillError: skillError, onSkill: setSkill, onArgs: setArgs }))
|
|
804
977
|
}
|
|
805
978
|
if (sessionId !== undefined && data === undefined && !error) children.push(wbNote('加载中…'))
|
|
806
979
|
if (data) {
|
|
@@ -919,6 +1092,15 @@ const WB_CSS = `.wb-overlay { position: fixed; inset: 0; z-index: 9999; backgrou
|
|
|
919
1092
|
.wb-verdict-? { background: #f6f8fa; color: #57606a; }
|
|
920
1093
|
.wb-extra { flex: 1 1 100%; background: #ffffff; color: #1f1f1f; border: 1px solid #c8c8c8; border-radius: 4px; padding: 5px 10px; font-size: 12px; min-width: 200px; }
|
|
921
1094
|
.wb-cmd-preview { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; color: #24292e; background: #f5f5f5; border: 1px solid #e0e0e0; border-radius: 6px; padding: 8px 10px; margin: 6px 0 10px; word-break: break-all; }
|
|
1095
|
+
.wb-param-input { background: #ffffff; color: #1f1f1f; border: 1px solid #c8c8c8; border-radius: 4px; padding: 3px 6px; font-size: 12px; min-width: 170px; width: 200px; }
|
|
1096
|
+
.wb-model-combo { position: relative; display: inline-flex; align-items: center; }
|
|
1097
|
+
.wb-model-btn { margin-left: 3px; padding: 2px 7px; background: #f2f2f2; color: #1f1f1f; border: 1px solid #c8c8c8; border-radius: 4px; font-size: 11px; cursor: pointer; line-height: 1.4; }
|
|
1098
|
+
.wb-model-btn:hover { background: #e3e3e3; }
|
|
1099
|
+
.wb-model-pop { position: absolute; top: calc(100% + 4px); left: 0; z-index: 80; background: #ffffff; color: #1f1f1f; border: 1px solid #c8c8c8; border-radius: 4px; box-shadow: 0 2px 10px rgba(0, 0, 0, .18); max-height: 240px; overflow-y: auto; min-width: 330px; }
|
|
1100
|
+
.wb-model-opt { padding: 6px 10px; font-size: 12px; cursor: pointer; border-bottom: 1px solid #f0f0f0; white-space: nowrap; }
|
|
1101
|
+
.wb-model-opt:hover { background: #e8f0fe; }
|
|
1102
|
+
.wb-model-opt:last-child { border-bottom: none; }
|
|
1103
|
+
.wb-model-empty { padding: 6px 10px; font-size: 12px; color: #6e7781; }
|
|
922
1104
|
|
|
923
1105
|
.wb-pano-card-when { font-size: 13px; color: #1f1f1f; }
|
|
924
1106
|
|
package/dsh/index.mjs
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { fileURLToPath } from 'node:url'
|
|
12
12
|
import * as skillFilesystem from '@deepseek-ai/dsh-skill-filesystem'
|
|
13
|
+
import * as mcpClient from '@deepseek-ai/dsh-mcp-client'
|
|
13
14
|
import { registerRunStatus } from './run-status.mjs'
|
|
14
15
|
import { registerWorkbench } from './workbench.mjs'
|
|
15
16
|
|
|
@@ -19,6 +20,7 @@ export const inject = ['skills', 'tools']
|
|
|
19
20
|
/** Package root; identical in a git checkout and under node_modules. */
|
|
20
21
|
const PACKAGE_ROOT = fileURLToPath(new URL('../', import.meta.url))
|
|
21
22
|
const SKILL_ROOT = fileURLToPath(new URL('../skills/', import.meta.url))
|
|
23
|
+
const CLAUDE_REVIEW_SERVER = fileURLToPath(new URL('../mcp-servers/claude-review/server.py', import.meta.url))
|
|
22
24
|
|
|
23
25
|
/** Codex MCP tools whose reply carries a continuation threadId. */
|
|
24
26
|
const CODEX_TOOLS = new Set(['mcp__codex__codex', 'mcp__codex__codex-reply'])
|
|
@@ -44,6 +46,21 @@ export async function apply(ctx) {
|
|
|
44
46
|
watch: false,
|
|
45
47
|
})
|
|
46
48
|
|
|
49
|
+
// Claude reviewer bridge (claude-review MCP): drives the local Claude Code CLI
|
|
50
|
+
// as an external reviewer. Each review call may carry its own `model`; the
|
|
51
|
+
// workbench picker resolves to a default of claude-fable-5. Not fatal on
|
|
52
|
+
// startup failure — the Codex route keeps working and the Claude route shows
|
|
53
|
+
// the underlying error.
|
|
54
|
+
await ctx.plugin(mcpClient, {
|
|
55
|
+
serverName: 'claude-review',
|
|
56
|
+
transport: 'stdio',
|
|
57
|
+
command: 'python',
|
|
58
|
+
args: [CLAUDE_REVIEW_SERVER],
|
|
59
|
+
cwd: PACKAGE_ROOT,
|
|
60
|
+
toolCallTimeoutMs: 1200000,
|
|
61
|
+
failOnStartupError: false,
|
|
62
|
+
})
|
|
63
|
+
|
|
47
64
|
registerRunStatus(ctx)
|
|
48
65
|
registerWorkbench(ctx)
|
|
49
66
|
|