dsh-agent-board 1.1.0 → 1.1.2

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 CHANGED
@@ -14,6 +14,8 @@ DeepSeek Harness 智能看板 — 会话级任务管理 + 一次性 Worker/Verif
14
14
 
15
15
  ## 安装
16
16
 
17
+ > 宿主要求:Node ≥ 22;DSH ≥ `0.1.5-rc.1`(已通过 `peerDependencies` 声明,含预发布分支的版本范围见 package.json)
18
+
17
19
  ```sh
18
20
  dsh plugin --profile web add dsh-agent-board
19
21
  ```
package/index.mjs CHANGED
@@ -358,8 +358,8 @@ export function apply(ctx) {
358
358
  var sp = toSpawn[k]
359
359
  var rec = await spawnOneShot(sid, sp.t, sp.role)
360
360
  if (rec) {
361
- // claim 占位换成真实 run id
362
- await mutateLocked(sid, function (d) { var t = d.tasks.find(function (x) { return x.id === sp.t.id }); if (t) { if (sp.role === 'worker' && t.claimedBy === 'spawn-pending') t.claimedBy = String(rec.run.id) }; return t }, true)
361
+ // claim 占位换成真实 run id;verifier run 单独记(claimedBy 保留 worker 的,供详情页跳转会话)
362
+ await mutateLocked(sid, function (d) { var t = d.tasks.find(function (x) { return x.id === sp.t.id }); if (t) { if (sp.role === 'worker' && t.claimedBy === 'spawn-pending') t.claimedBy = String(rec.run.id); if (sp.role === 'verifier') t.verifierRun = String(rec.run.id) }; return t }, true)
363
363
  } else if (sp.role === 'worker') {
364
364
  // spawn 失败 → 回 pending(verifier spawn 失败无需处理,下轮 cycle 会重试)
365
365
  await mutateLocked(sid, function (d) { var t = d.tasks.find(function (x) { return x.id === sp.t.id }); if (t && t.status === 'in-progress' && t.claimedBy === 'spawn-pending') { t.status = 'pending'; t.claimedBy = null; t.claimedAt = null; ah(t, 'in-progress', 'pending', 'system', 'spawn 失败,回收重新排队') }; return t }, true)
@@ -519,6 +519,7 @@ export function apply(ctx) {
519
519
  var rec = await spawnOneShot(sid, t, role)
520
520
  if (rec) {
521
521
  if (role === 'worker') { await mutateLocked(sid, function (d) { var t2 = d.tasks.find(function (x) { return x.id === args.taskId }); if (t2 && t2.claimedBy === 'spawn-pending') t2.claimedBy = String(rec.run.id); return t2 }, true) }
522
+ if (role === 'verifier') { await mutateLocked(sid, function (d) { var t2 = d.tasks.find(function (x) { return x.id === args.taskId }); if (t2) t2.verifierRun = String(rec.run.id); return t2 }, true) }
522
523
  return { ok: true, runId: String(rec.run.id) }
523
524
  }
524
525
  // spawn 失败 → 回退
package/lib/client.js CHANGED
@@ -10,6 +10,9 @@ window.__ModuleLoader__.load({
10
10
  const React = require('react')
11
11
 
12
12
  function apply(ctx) {
13
+ // 硬依赖声明(见文件尾 module.exports):新版 dsh(0.1.5-rc.2)启动顺序下,
14
+ // 不声明 inject 时 apply 先于 slots/sessions/timer 服务注册执行,
15
+ // ctx.get 返回 undefined → 静默退出 → 看板按钮消失。声明后 runner 等服务就绪再 apply。
13
16
  var slots = ctx.get('slots')
14
17
  if (slots === undefined) return
15
18
  var sessionsSvc = ctx.get('sessions')
@@ -488,6 +491,7 @@ function apply(ctx) {
488
491
  function doAction(fn) { fn().then(fetchTasks).catch(function () {}) }
489
492
  function saveEdit() { setSaving(true); rpc('update-task', { taskId: task.id, title: editTitle, description: editDesc, resetToPending: true }).then(function () { setSaving(false); fetchTasks() }).catch(function () { setSaving(false) }) }
490
493
  function jumpToAgent() { if (sessionsSvc && task.claimedBy) sessionsSvc.open(task.claimedBy) }
494
+ function jumpToVerifier() { if (sessionsSvc && task.verifierRun) sessionsSvc.open(task.verifierRun) }
491
495
  function submitArbitration() { if (!arbAnswer.trim()) return; rpc('resolve-escalation', { taskId: task.id, answer: arbAnswer }).then(function (r) { setActionMsg(r && r.ok ? '✅ 裁决已转达给 Worker' : '⚠️ ' + ((r && r.error) || '失败')); setArbAnswer(''); fetchTasks() }).catch(function (e) { setActionMsg('⚠️ ' + String(e)) }) }
492
496
  function doTerminate() { rpc('terminate-agent', { taskId: task.id }).then(function (r) { setActionMsg(r && r.ok ? '⏹ 已终止 ' + (r.terminated || '') + ',任务重新排队' : '⚠️ ' + ((r && r.error) || '无活动 Agent')); fetchTasks() }).catch(function (e) { setActionMsg('⚠️ ' + String(e)) }) }
493
497
  function doDismiss() { rpc('dismiss-suspect', { taskId: task.id }).then(function () { setActionMsg('✅ 已清除卡死标记,继续观察'); fetchTasks() }).catch(function (e) { setActionMsg('⚠️ ' + String(e)) }) }
@@ -541,7 +545,8 @@ function apply(ctx) {
541
545
  task.status === 'verifying' ? React.createElement('button', { onClick: function () { doAction(function () { return rpc('verify-task', { taskId: task.id, verdict: 'approved' }) }) }, style: { fontSize: 10, padding: '3px 8px', border: 'none', borderRadius: 3, background: C.ok, color: '#fff', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 3 } }, ic('check-circle', 10), '通过') : null,
542
546
  task.status === 'verifying' ? React.createElement('button', { onClick: function () { var r = window.prompt('驳回原因:'); doAction(function () { return rpc('verify-task', { taskId: task.id, verdict: 'rejected', comment: r || '' }) }) }, style: { fontSize: 10, padding: '3px 8px', border: 'none', borderRadius: 3, background: C.err, color: '#fff', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 3 } }, ic('x-circle', 10), '驳回') : null,
543
547
  task.status === 'resolved' ? React.createElement('button', { onClick: function () { doAction(function () { return rpc('archive-task', { taskId: task.id }) }) }, style: { fontSize: 10, padding: '3px 8px', border: 'none', borderRadius: 3, background: C.text2, color: '#fff', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 3 } }, ic('archive', 10), '归档') : null,
544
- canJump ? React.createElement('button', { onClick: jumpToAgent, style: { fontSize: 10, padding: '3px 8px', border: '1px solid ' + C.brand, borderRadius: 3, background: 'transparent', color: C.brand, cursor: 'pointer' } }, '→ 跳转执行会话') : null),
548
+ canJump ? React.createElement('button', { onClick: jumpToAgent, style: { fontSize: 10, padding: '3px 8px', border: '1px solid ' + C.brand, borderRadius: 3, background: 'transparent', color: C.brand, cursor: 'pointer' } }, '→ Worker 会话') : null,
549
+ (task.verifierRun && (task.status === 'verifying' || task.status === 'resolved')) ? React.createElement('button', { onClick: jumpToVerifier, style: { fontSize: 10, padding: '3px 8px', border: '1px solid ' + C.brand, borderRadius: 3, background: 'transparent', color: C.brand, cursor: 'pointer' } }, '→ Verifier 会话') : null),
545
550
  canIntervene ? React.createElement('div', { style: { marginTop: 8, padding: '6px 8px', border: '1px dashed ' + C.warn, borderRadius: 6 } },
546
551
  React.createElement('div', { style: { fontSize: 11, fontWeight: 600, color: C.warn, marginBottom: 4, display: 'flex', alignItems: 'center', gap: 4 } }, ic('zap', 11), '高优先级介入(插入执行 Agent 队首)'),
547
552
  React.createElement('div', { style: { display: 'flex', gap: 4 } },
@@ -591,7 +596,7 @@ function apply(ctx) {
591
596
  slots.inject('shell.overlay', function () { return slots.register({ name: 'shell.overlay', id: 'task-board-top-panel' }, function () { return React.createElement(TopPanel) }) })
592
597
  }
593
598
 
594
- module.exports = { name: 'dsh-agent-board', apply: apply }
599
+ module.exports = { name: 'dsh-agent-board', inject: ['slots', 'sessions', 'timer'], apply: apply }
595
600
  return module.exports
596
601
  }
597
602
  })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-agent-board",
3
3
  "description": "DeepSeek Harness 智能看板:任务卡片 + 一次性 Worker/Verifier 派发 + 依赖调度 + 管线分档 + Team 模式(歧义上报主窗口裁决)",
4
- "version": "1.1.0",
4
+ "version": "1.1.2",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",
7
7
  "scripts": {
@@ -54,5 +54,9 @@
54
54
  "engines": {
55
55
  "node": ">=22"
56
56
  },
57
+ "peerDependencies": {
58
+ "react": ">=18",
59
+ "@deepseek-ai/dsh": ">=0.1.5-rc.1 <0.2.0-0"
60
+ },
57
61
  "license": "MIT"
58
62
  }