@alpacachen/dsh-kanban 1.3.0 → 1.3.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 +53 -119
- package/README.zh.md +48 -114
- package/index.js +136 -92
- package/lib/client.js +482 -12
- package/package.json +9 -3
package/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* 职责:
|
|
8
8
|
* - 按工作区(项目)隔离:boards 以 workspaceId 为键,每个工作区一块独立看板
|
|
9
|
-
* - 磁盘持久化:经 ctx.fs 写入 <
|
|
9
|
+
* - 磁盘持久化:经 ctx.fs 写入 <workspace.path>/.dsh-kanban.json
|
|
10
10
|
* - 模型工具:经 ctx.tools.register 注册 14 个 kanban_* 工具
|
|
11
11
|
* - 浏览器数据层:经 ctx.get('webServer') 注册 /api/kanban 前缀路由
|
|
12
12
|
*
|
|
@@ -275,41 +275,53 @@ export function apply(ctx) {
|
|
|
275
275
|
]
|
|
276
276
|
|
|
277
277
|
// ---- 持久化定位 ----
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
278
|
+
const BOARD_FILE = '.dsh-kanban.json'
|
|
279
|
+
const workspaceKey = (workspace) => String(workspace.id || workspace.path)
|
|
280
|
+
const writePolicyFor = (workspace, session) => {
|
|
281
|
+
const policy = getPolicy()
|
|
282
|
+
const resolved =
|
|
283
|
+
policy && typeof policy.resolve === 'function'
|
|
284
|
+
? policy.resolve(session ? { session } : {})
|
|
285
|
+
: { mode: (policy && policy.defaultMode) || 'workspace-write' }
|
|
286
|
+
return { ...resolved, workspaceRoot: workspace.path }
|
|
281
287
|
}
|
|
282
|
-
const
|
|
283
|
-
const resolveFile = async (wsid) => {
|
|
288
|
+
const resolveFile = async (workspace) => {
|
|
284
289
|
const fs = getFs()
|
|
285
290
|
if (!fs) return null
|
|
286
291
|
try {
|
|
287
|
-
return await fs.resolve(
|
|
292
|
+
return await fs.resolve(BOARD_FILE, { cwd: workspace.path })
|
|
288
293
|
} catch (err) {
|
|
289
|
-
console.log(
|
|
294
|
+
console.log(
|
|
295
|
+
'dsh-kanban: 解析工作区看板文件失败 ' + workspaceKey(workspace) + ':' + ((err && err.message) || err),
|
|
296
|
+
)
|
|
290
297
|
return null
|
|
291
298
|
}
|
|
292
299
|
}
|
|
293
|
-
const targetOf = async (
|
|
294
|
-
|
|
295
|
-
|
|
300
|
+
const targetOf = async (workspace) => {
|
|
301
|
+
const key = workspaceKey(workspace)
|
|
302
|
+
if (!fileTargets.has(key)) fileTargets.set(key, await resolveFile(workspace))
|
|
303
|
+
return fileTargets.get(key)
|
|
304
|
+
}
|
|
305
|
+
const persistedFlag = (workspace) => {
|
|
306
|
+
const key = workspaceKey(workspace)
|
|
307
|
+
return fileTargets.has(key) && fileTargets.get(key) !== null
|
|
296
308
|
}
|
|
297
|
-
const persistedFlag = (wsid) => fileTargets.has(wsid) && fileTargets.get(wsid) !== null
|
|
298
309
|
|
|
299
310
|
// ---- 看板读写 ----
|
|
300
311
|
|
|
301
|
-
// 备份原文件为
|
|
302
|
-
const backupFile = async (
|
|
312
|
+
// 备份原文件为 .dsh-kanban.json.<suffix>(复制而非移动,保证原文件在写回前始终存在)
|
|
313
|
+
const backupFile = async (workspace, suffix, session) => {
|
|
303
314
|
const fs = getFs()
|
|
304
|
-
const target = await targetOf(
|
|
315
|
+
const target = await targetOf(workspace)
|
|
305
316
|
if (!fs || !target) return null
|
|
317
|
+
const key = workspaceKey(workspace)
|
|
306
318
|
try {
|
|
307
319
|
const text = await fs.readText(target)
|
|
308
|
-
const backupTarget = await fs.resolve(
|
|
309
|
-
await fs.writeText(backupTarget, text)
|
|
320
|
+
const backupTarget = await fs.resolve(BOARD_FILE + '.' + suffix, { cwd: workspace.path })
|
|
321
|
+
await fs.writeText(backupTarget, text, undefined, undefined, writePolicyFor(workspace, session))
|
|
310
322
|
return backupTarget
|
|
311
323
|
} catch (err) {
|
|
312
|
-
console.log('dsh-kanban: 备份失败 ' +
|
|
324
|
+
console.log('dsh-kanban: 备份失败 ' + key + ' (' + suffix + '):' + ((err && err.message) || err))
|
|
313
325
|
return null
|
|
314
326
|
}
|
|
315
327
|
}
|
|
@@ -326,14 +338,15 @@ export function apply(ctx) {
|
|
|
326
338
|
}
|
|
327
339
|
const timestamp = () => new Date().toISOString().replace(/[:.]/g, '-')
|
|
328
340
|
|
|
329
|
-
//
|
|
330
|
-
const boardOf = async (
|
|
331
|
-
|
|
341
|
+
// 首次访问某工作区时从该工作区根目录加载;异常数据一律不阻塞看板可用性
|
|
342
|
+
const boardOf = async (workspace, session) => {
|
|
343
|
+
const key = workspaceKey(workspace)
|
|
344
|
+
let board = boards.get(key)
|
|
332
345
|
if (board) return board
|
|
333
346
|
board = { schemaVersion: SCHEMA_VERSION, columns: [], labels: [], cards: [], activities: [], warnings: [] }
|
|
334
|
-
boards.set(
|
|
347
|
+
boards.set(key, board)
|
|
335
348
|
const fs = getFs()
|
|
336
|
-
const target = await targetOf(
|
|
349
|
+
const target = await targetOf(workspace)
|
|
337
350
|
let migrated = false
|
|
338
351
|
if (fs && target) {
|
|
339
352
|
try {
|
|
@@ -346,19 +359,19 @@ export function apply(ctx) {
|
|
|
346
359
|
board.cards = parsed.data.cards
|
|
347
360
|
board.activities = Array.isArray(parsed.data.activities) ? parsed.data.activities : []
|
|
348
361
|
migrated = parsed.migrated
|
|
349
|
-
// 迁移场景:写回前先把迁移前的原文件备份下来,保证可回滚
|
|
362
|
+
// schema 迁移场景:写回前先把迁移前的原文件备份下来,保证可回滚
|
|
350
363
|
if (parsed.migrated) {
|
|
351
|
-
await backupFile(
|
|
364
|
+
await backupFile(workspace, 'bak-v' + parsed.fromVersion, session)
|
|
352
365
|
}
|
|
353
366
|
} else {
|
|
354
367
|
// 损坏 / 结构无效 / 版本超前:原文件已无法安全读取,先备份再以空板继续
|
|
355
368
|
const suffix =
|
|
356
369
|
parsed.kind === 'unsupported' ? 'unsupported-v' + parsed.version : 'corrupt-' + timestamp()
|
|
357
|
-
await backupFile(
|
|
370
|
+
await backupFile(workspace, suffix, session)
|
|
358
371
|
}
|
|
359
372
|
} catch (err) {
|
|
360
373
|
// 尚无看板文件(首次使用)或 fs 读取异常,保留默认空板
|
|
361
|
-
console.log('dsh-kanban: 读取看板失败 ' +
|
|
374
|
+
console.log('dsh-kanban: 读取看板失败 ' + key + ':' + ((err && err.message) || err))
|
|
362
375
|
}
|
|
363
376
|
}
|
|
364
377
|
for (const col of board.columns) bumpSeq(col.id)
|
|
@@ -370,14 +383,15 @@ export function apply(ctx) {
|
|
|
370
383
|
if (board.labels.length === 0) {
|
|
371
384
|
board.labels = DEFAULT_LABELS.map((l) => ({ ...l }))
|
|
372
385
|
}
|
|
373
|
-
// 升级写回:迁移成功即落盘新版本,保证每个文件只迁移一次
|
|
374
|
-
if (migrated && fs && target) await save(
|
|
386
|
+
// schema 升级写回:迁移成功即落盘新版本,保证每个文件只迁移一次
|
|
387
|
+
if (migrated && fs && target) await save(workspace, session)
|
|
375
388
|
return board
|
|
376
389
|
}
|
|
377
|
-
const save = async (
|
|
390
|
+
const save = async (workspace, session) => {
|
|
378
391
|
const fs = getFs()
|
|
379
|
-
const target = await targetOf(
|
|
380
|
-
const
|
|
392
|
+
const target = await targetOf(workspace)
|
|
393
|
+
const key = workspaceKey(workspace)
|
|
394
|
+
const board = boards.get(key)
|
|
381
395
|
if (!fs || !target || !board) return
|
|
382
396
|
try {
|
|
383
397
|
await fs.writeText(
|
|
@@ -389,9 +403,12 @@ export function apply(ctx) {
|
|
|
389
403
|
cards: board.cards,
|
|
390
404
|
activities: Array.isArray(board.activities) ? board.activities : [],
|
|
391
405
|
}),
|
|
406
|
+
undefined,
|
|
407
|
+
undefined,
|
|
408
|
+
writePolicyFor(workspace, session),
|
|
392
409
|
)
|
|
393
410
|
} catch (err) {
|
|
394
|
-
console.log('dsh-kanban: 保存失败 ' +
|
|
411
|
+
console.log('dsh-kanban: 保存失败 ' + key + ':' + ((err && err.message) || err))
|
|
395
412
|
}
|
|
396
413
|
}
|
|
397
414
|
|
|
@@ -449,11 +466,11 @@ export function apply(ctx) {
|
|
|
449
466
|
}
|
|
450
467
|
|
|
451
468
|
// ---- 核心数据操作:工具与浏览器 HTTP 共用同一份逻辑 ----
|
|
452
|
-
const dispatch = async (
|
|
453
|
-
const board = await boardOf(
|
|
469
|
+
const dispatch = async (workspace, method, args, source, session) => {
|
|
470
|
+
const board = await boardOf(workspace, session)
|
|
454
471
|
const a = args || {}
|
|
455
472
|
const actor = source === 'agent' ? 'agent' : 'human'
|
|
456
|
-
const persisted = () => persistedFlag(
|
|
473
|
+
const persisted = () => persistedFlag(workspace)
|
|
457
474
|
const result = (extra) => ({ board: cloneBoard(board), persisted: persisted(), warnings: takeWarnings(board), ...extra })
|
|
458
475
|
|
|
459
476
|
switch (method) {
|
|
@@ -491,7 +508,7 @@ export function apply(ctx) {
|
|
|
491
508
|
priority: card.priority ?? null,
|
|
492
509
|
},
|
|
493
510
|
})
|
|
494
|
-
await save(
|
|
511
|
+
await save(workspace, session)
|
|
495
512
|
return result({ message: 'Card added to "' + col.title + '"' })
|
|
496
513
|
}
|
|
497
514
|
|
|
@@ -526,7 +543,7 @@ export function apply(ctx) {
|
|
|
526
543
|
if (after.priority !== before.priority) {
|
|
527
544
|
record(board, { cardId: card.id, type: 'card_priority_changed', source: actor, field: 'priority', from: before.priority, to: after.priority })
|
|
528
545
|
}
|
|
529
|
-
await save(
|
|
546
|
+
await save(workspace, session)
|
|
530
547
|
}
|
|
531
548
|
return card
|
|
532
549
|
? result({ message: 'Card updated' })
|
|
@@ -540,7 +557,7 @@ export function apply(ctx) {
|
|
|
540
557
|
if (card) {
|
|
541
558
|
record(board, { cardId: id, type: 'card_deleted', source: actor, meta: { title: card.title } })
|
|
542
559
|
}
|
|
543
|
-
await save(
|
|
560
|
+
await save(workspace, session)
|
|
544
561
|
return result({ message: 'Card deleted' })
|
|
545
562
|
}
|
|
546
563
|
|
|
@@ -562,7 +579,7 @@ export function apply(ctx) {
|
|
|
562
579
|
if (fromTitle !== target.title) {
|
|
563
580
|
record(board, { cardId: card.id, type: 'card_moved', source: actor, field: 'columnId', from: fromTitle, to: target.title, meta: { title: card.title } })
|
|
564
581
|
}
|
|
565
|
-
await save(
|
|
582
|
+
await save(workspace, session)
|
|
566
583
|
return result({ message: 'Moved to "' + target.title + '"' })
|
|
567
584
|
}
|
|
568
585
|
|
|
@@ -570,7 +587,7 @@ export function apply(ctx) {
|
|
|
570
587
|
const title = str(a.title, '').slice(0, 40) || 'New list'
|
|
571
588
|
board.columns.push({ id: nextId('c'), title })
|
|
572
589
|
record(board, { cardId: null, type: 'column_added', source: actor, meta: { column: title } })
|
|
573
|
-
await save(
|
|
590
|
+
await save(workspace, session)
|
|
574
591
|
return result({ message: 'List added: "' + title + '"' })
|
|
575
592
|
}
|
|
576
593
|
|
|
@@ -582,7 +599,7 @@ export function apply(ctx) {
|
|
|
582
599
|
if (col.title !== before) {
|
|
583
600
|
record(board, { cardId: null, type: 'column_renamed', source: actor, field: 'title', from: before, to: col.title, meta: { column: col.title } })
|
|
584
601
|
}
|
|
585
|
-
await save(
|
|
602
|
+
await save(workspace, session)
|
|
586
603
|
}
|
|
587
604
|
return col ? result({ message: 'List renamed' }) : result({ error: 'List not found' })
|
|
588
605
|
}
|
|
@@ -602,7 +619,7 @@ export function apply(ctx) {
|
|
|
602
619
|
}
|
|
603
620
|
}
|
|
604
621
|
record(board, { cardId: null, type: 'column_deleted', source: actor, meta: { column: deleted.title } })
|
|
605
|
-
await save(
|
|
622
|
+
await save(workspace, session)
|
|
606
623
|
return result({ message: 'List deleted, cards moved to "' + board.columns[0].title + '"' })
|
|
607
624
|
}
|
|
608
625
|
|
|
@@ -615,7 +632,7 @@ export function apply(ctx) {
|
|
|
615
632
|
? Math.max(0, Math.min(Math.floor(a.toIndex), board.columns.length))
|
|
616
633
|
: board.columns.length
|
|
617
634
|
board.columns.splice(toIndex, 0, col)
|
|
618
|
-
await save(
|
|
635
|
+
await save(workspace, session)
|
|
619
636
|
return result({ message: 'List order updated' })
|
|
620
637
|
}
|
|
621
638
|
|
|
@@ -625,7 +642,7 @@ export function apply(ctx) {
|
|
|
625
642
|
if (findLabel(board, name)) return result({ error: 'Label already exists' })
|
|
626
643
|
board.labels.push({ name, color: normColor(a.color) || '#94a3b8' })
|
|
627
644
|
record(board, { cardId: null, type: 'label_added', source: actor, meta: { label: name } })
|
|
628
|
-
await save(
|
|
645
|
+
await save(workspace, session)
|
|
629
646
|
return result({ message: 'Label added: "' + name + '"' })
|
|
630
647
|
}
|
|
631
648
|
|
|
@@ -652,7 +669,7 @@ export function apply(ctx) {
|
|
|
652
669
|
record(board, { cardId: null, type: 'label_color_changed', source: actor, field: 'color', from: beforeColor, to: label.color, meta: { label: label.name } })
|
|
653
670
|
}
|
|
654
671
|
}
|
|
655
|
-
await save(
|
|
672
|
+
await save(workspace, session)
|
|
656
673
|
return result({ message: 'Label updated' })
|
|
657
674
|
}
|
|
658
675
|
|
|
@@ -668,7 +685,7 @@ export function apply(ctx) {
|
|
|
668
685
|
}
|
|
669
686
|
}
|
|
670
687
|
record(board, { cardId: null, type: 'label_deleted', source: actor, meta: { label: name } })
|
|
671
|
-
await save(
|
|
688
|
+
await save(workspace, session)
|
|
672
689
|
return result({ message: 'Label deleted' })
|
|
673
690
|
}
|
|
674
691
|
|
|
@@ -677,27 +694,42 @@ export function apply(ctx) {
|
|
|
677
694
|
}
|
|
678
695
|
}
|
|
679
696
|
|
|
680
|
-
// ---- 工具执行上下文 -> 工作区
|
|
681
|
-
const
|
|
697
|
+
// ---- 工具执行上下文 / 浏览器 workspaceId -> 工作区 ----
|
|
698
|
+
const workspaceOfExec = async (exec) => {
|
|
682
699
|
const agent = exec && exec.agent
|
|
683
|
-
const
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
700
|
+
const session = agent && agent.session
|
|
701
|
+
const cwd = session && session.header && session.header.cwd
|
|
702
|
+
if (typeof cwd !== 'string' || !cwd) return null
|
|
703
|
+
const registry = getWorkspaceRegistry()
|
|
704
|
+
if (registry) {
|
|
705
|
+
try {
|
|
706
|
+
const workspace = await registry.resolveByPath(cwd)
|
|
707
|
+
if (workspace) return workspace
|
|
708
|
+
} catch (err) {
|
|
709
|
+
console.log('dsh-kanban: 解析工作区失败:' + ((err && err.message) || err))
|
|
693
710
|
}
|
|
694
711
|
}
|
|
695
|
-
|
|
712
|
+
// 未登记到 WorkspaceRegistry 的会话仍以自身 cwd 作为工作区根目录。
|
|
713
|
+
return { id: 'cwd:' + cwd, path: cwd, title: cwd }
|
|
714
|
+
}
|
|
715
|
+
const workspaceOfId = (id) => {
|
|
716
|
+
const registry = getWorkspaceRegistry()
|
|
717
|
+
return registry && typeof registry.get === 'function' ? registry.get(id) : undefined
|
|
696
718
|
}
|
|
719
|
+
const emptyBoardSummary = { columns: [], labels: [], cards: [] }
|
|
697
720
|
|
|
698
721
|
const runTool = async (method, args, exec) => {
|
|
699
|
-
const
|
|
700
|
-
|
|
722
|
+
const workspace = await workspaceOfExec(exec)
|
|
723
|
+
if (!workspace) {
|
|
724
|
+
return {
|
|
725
|
+
ok: false,
|
|
726
|
+
message: 'Cannot determine the current workspace from the tool execution context',
|
|
727
|
+
board: emptyBoardSummary,
|
|
728
|
+
warnings: [],
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
const session = exec && exec.agent && exec.agent.session
|
|
732
|
+
const r = await dispatch(workspace, method, args, 'agent', session)
|
|
701
733
|
return {
|
|
702
734
|
ok: !r.error,
|
|
703
735
|
message: r.error || r.message || 'Done',
|
|
@@ -715,8 +747,14 @@ export function apply(ctx) {
|
|
|
715
747
|
const body = raw ? JSON.parse(raw) : {}
|
|
716
748
|
const method = typeof body.method === 'string' ? body.method : 'get'
|
|
717
749
|
const args = body.args || {}
|
|
718
|
-
const
|
|
719
|
-
const
|
|
750
|
+
const workspaceId = typeof args.workspaceId === 'string' ? args.workspaceId : ''
|
|
751
|
+
const workspace = workspaceId ? workspaceOfId(workspaceId) : undefined
|
|
752
|
+
if (!workspace) {
|
|
753
|
+
res.writeHead(400, { 'content-type': 'application/json' })
|
|
754
|
+
res.end(JSON.stringify({ error: 'Unknown workspace: ' + (workspaceId || '(missing)') }))
|
|
755
|
+
return
|
|
756
|
+
}
|
|
757
|
+
const result = await dispatch(workspace, method, args, 'human')
|
|
720
758
|
res.writeHead(200, { 'content-type': 'application/json' })
|
|
721
759
|
res.end(JSON.stringify(result))
|
|
722
760
|
} catch (err) {
|
|
@@ -753,61 +791,63 @@ export function apply(ctx) {
|
|
|
753
791
|
}
|
|
754
792
|
}
|
|
755
793
|
|
|
756
|
-
// ----
|
|
794
|
+
// ---- 启动校验:逐个工作区体检 .dsh-kanban.json(只读 + 备份损坏文件)----
|
|
757
795
|
const startupState = { done: false }
|
|
758
796
|
const maybeStartupCheck = () => {
|
|
759
797
|
if (startupState.done) return
|
|
760
|
-
|
|
798
|
+
const registry = getWorkspaceRegistry()
|
|
799
|
+
if (!getFs() || !registry || typeof registry.list !== 'function') return
|
|
761
800
|
startupState.done = true
|
|
762
801
|
runStartupCheck()
|
|
763
802
|
}
|
|
764
803
|
const runStartupCheck = async () => {
|
|
765
804
|
const fs = getFs()
|
|
766
|
-
const
|
|
767
|
-
if (!fs || !
|
|
805
|
+
const registry = getWorkspaceRegistry()
|
|
806
|
+
if (!fs || !registry || typeof registry.list !== 'function') return
|
|
768
807
|
try {
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
const boardFiles = entries.filter(
|
|
772
|
-
(e) => typeof e.name === 'string' && /^kanban-board-.+\.json$/.test(e.name),
|
|
773
|
-
)
|
|
774
|
-
if (boardFiles.length === 0) {
|
|
775
|
-
console.log('dsh-kanban: 启动校验完成,未发现看板数据文件')
|
|
776
|
-
return
|
|
777
|
-
}
|
|
808
|
+
const workspaces = registry.list()
|
|
809
|
+
let found = 0
|
|
778
810
|
let corrupt = 0
|
|
779
811
|
let pendingUpgrade = 0
|
|
780
812
|
let unsupported = 0
|
|
781
813
|
let ok = 0
|
|
782
|
-
for (const
|
|
783
|
-
const
|
|
814
|
+
for (const workspace of workspaces) {
|
|
815
|
+
const key = workspaceKey(workspace)
|
|
784
816
|
try {
|
|
785
|
-
const
|
|
817
|
+
const target = await fs.resolve(BOARD_FILE, { cwd: workspace.path })
|
|
818
|
+
const text = await fs.readText(target)
|
|
819
|
+
found++
|
|
786
820
|
const parsed = parseBoardText(text)
|
|
787
821
|
if (parsed.ok) {
|
|
788
822
|
if (parsed.migrated) {
|
|
789
823
|
pendingUpgrade++
|
|
790
|
-
console.log('dsh-kanban: 启动校验 ' +
|
|
824
|
+
console.log('dsh-kanban: 启动校验 ' + key + ':schemaVersion ' + parsed.fromVersion + ',首次打开时将自动升级')
|
|
791
825
|
} else {
|
|
792
826
|
ok++
|
|
793
827
|
}
|
|
794
828
|
} else if (parsed.kind === 'unsupported') {
|
|
795
829
|
unsupported++
|
|
796
|
-
console.log('dsh-kanban: 启动校验 ' +
|
|
830
|
+
console.log('dsh-kanban: 启动校验 ' + key + ':文件由更新版本插件写入(schemaVersion ' + parsed.version + ')')
|
|
797
831
|
} else {
|
|
798
832
|
corrupt++
|
|
799
833
|
const suffix = 'corrupt-' + timestamp()
|
|
800
|
-
const backupTarget = await fs.resolve(
|
|
801
|
-
await fs.writeText(backupTarget, text)
|
|
802
|
-
console.log('dsh-kanban: 启动校验 ' +
|
|
834
|
+
const backupTarget = await fs.resolve(BOARD_FILE + '.' + suffix, { cwd: workspace.path })
|
|
835
|
+
await fs.writeText(backupTarget, text, undefined, undefined, writePolicyFor(workspace))
|
|
836
|
+
console.log('dsh-kanban: 启动校验 ' + key + ':数据文件损坏(' + parsed.kind + '),已备份为 ' + BOARD_FILE + '.' + suffix)
|
|
803
837
|
}
|
|
804
838
|
} catch (err) {
|
|
805
|
-
|
|
839
|
+
if (!err || (err.code !== 'ENOENT' && err.message !== 'ENOENT')) {
|
|
840
|
+
console.log('dsh-kanban: 启动校验 ' + key + ':检查失败 ' + ((err && err.message) || err))
|
|
841
|
+
}
|
|
806
842
|
}
|
|
807
843
|
}
|
|
844
|
+
if (found === 0) {
|
|
845
|
+
console.log('dsh-kanban: 启动校验完成,未发现看板数据文件')
|
|
846
|
+
return
|
|
847
|
+
}
|
|
808
848
|
console.log(
|
|
809
849
|
'dsh-kanban: 启动校验完成:共 ' +
|
|
810
|
-
|
|
850
|
+
found +
|
|
811
851
|
' 个看板文件,正常 ' +
|
|
812
852
|
ok +
|
|
813
853
|
',损坏并已备份 ' +
|
|
@@ -914,8 +954,10 @@ export function apply(ctx) {
|
|
|
914
954
|
},
|
|
915
955
|
},
|
|
916
956
|
async execute(args, exec) {
|
|
917
|
-
const
|
|
918
|
-
|
|
957
|
+
const workspace = await workspaceOfExec(exec)
|
|
958
|
+
if (!workspace) return { ok: false, message: 'Cannot determine the current workspace from the tool execution context', warnings: [] }
|
|
959
|
+
const session = exec && exec.agent && exec.agent.session
|
|
960
|
+
const r = await dispatch(workspace, 'getCard', args, 'agent', session)
|
|
919
961
|
if (r.error) return { ok: false, message: r.error, warnings: Array.isArray(r.warnings) ? r.warnings : [] }
|
|
920
962
|
return { ok: true, message: 'Card ' + String(args.id || '') + ' details', card: r.card, warnings: Array.isArray(r.warnings) ? r.warnings : [] }
|
|
921
963
|
},
|
|
@@ -1122,12 +1164,14 @@ export function apply(ctx) {
|
|
|
1122
1164
|
},
|
|
1123
1165
|
},
|
|
1124
1166
|
async execute(args, exec) {
|
|
1125
|
-
const
|
|
1126
|
-
|
|
1167
|
+
const workspace = await workspaceOfExec(exec)
|
|
1168
|
+
if (!workspace) return { ok: false, message: 'Cannot determine the current workspace from the tool execution context', labels: [], warnings: [] }
|
|
1169
|
+
const session = exec && exec.agent && exec.agent.session
|
|
1170
|
+
const r = await dispatch(workspace, 'get', args, 'agent', session)
|
|
1127
1171
|
const labels = (r.board && r.board.labels) || []
|
|
1128
1172
|
return {
|
|
1129
1173
|
ok: true,
|
|
1130
|
-
message: 'Labels (workspace ' +
|
|
1174
|
+
message: 'Labels (workspace ' + workspaceKey(workspace) + ')',
|
|
1131
1175
|
labels,
|
|
1132
1176
|
warnings: Array.isArray(r.warnings) ? r.warnings : [],
|
|
1133
1177
|
}
|