@yolk_vat-y/dsh-project-memory 0.5.12 → 0.5.14
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/CHANGELOG.md +165 -0
- package/README.md +6 -12
- package/README.zh-CN.md +6 -12
- package/client/client.js +193 -125
- package/client/client.js.map +1 -1
- package/package.json +11 -11
- package/src/audit.js +52 -3
- package/src/auto-inject.js +64 -16
- package/src/client/ShowTaskPanelNode.tsx +51 -0
- package/src/client/TaskPanel.tsx +8 -8
- package/src/client/client.ts +10 -31
- package/src/client/slash.ts +33 -17
- package/src/client/task-ui-store.ts +43 -0
- package/src/index.js +8 -3
- package/src/insight-store.js +2 -17
- package/src/llm.js +4 -1
- package/src/readiness.js +26 -1
- package/src/store.js +8 -22
- package/src/tools/forget.js +1 -1
- package/src/tools/lesson-tools.js +1 -0
- package/src/tools/remember.js +5 -3
- package/src/tools/task-tools.js +8 -7
- package/src/tools/watch-repo.js +1 -1
- package/src/util/fs.js +33 -1
package/client/client.js
CHANGED
|
@@ -365,6 +365,20 @@ window.__ModuleLoader__.load({
|
|
|
365
365
|
* - 启动/刷新强制 closed: true,面板默认不显示
|
|
366
366
|
*/
|
|
367
367
|
const STORAGE_KEY = "dsh-pm-task-panel-ui";
|
|
368
|
+
/**
|
|
369
|
+
* 面板的三个视图页。**单一事实来源**:面板的切页按钮与 `/` 菜单的三行都读它。
|
|
370
|
+
* 两边各抄一份必然漂移 —— 实测就是这样:菜单行去执行宿主命令"开记忆页",而面板的 view
|
|
371
|
+
* 是组件内部 state,谁也够不着它,于是点击没有任何可见效果。
|
|
372
|
+
*/
|
|
373
|
+
const PANEL_VIEWS = [
|
|
374
|
+
"task",
|
|
375
|
+
"project",
|
|
376
|
+
"global"
|
|
377
|
+
];
|
|
378
|
+
/** 把任意值收敛成一个合法视图页(脏 localStorage / 外部传入都要过这一关)。 */
|
|
379
|
+
function normalizeView(value) {
|
|
380
|
+
return PANEL_VIEWS.includes(value) ? value : "task";
|
|
381
|
+
}
|
|
368
382
|
function defaultPosition() {
|
|
369
383
|
if (typeof window !== "undefined") return {
|
|
370
384
|
x: Math.max(16, window.innerWidth - 408),
|
|
@@ -391,7 +405,8 @@ window.__ModuleLoader__.load({
|
|
|
391
405
|
minimized: parsed.minimized !== false,
|
|
392
406
|
closed: true,
|
|
393
407
|
theme: typeof parsed.theme === "string" ? parsed.theme : "native",
|
|
394
|
-
showHints: parsed.showHints !== false
|
|
408
|
+
showHints: parsed.showHints !== false,
|
|
409
|
+
view: normalizeView(parsed.view)
|
|
395
410
|
};
|
|
396
411
|
}
|
|
397
412
|
} catch {}
|
|
@@ -401,7 +416,8 @@ window.__ModuleLoader__.load({
|
|
|
401
416
|
minimized: true,
|
|
402
417
|
closed: true,
|
|
403
418
|
theme: "native",
|
|
404
|
-
showHints: true
|
|
419
|
+
showHints: true,
|
|
420
|
+
view: "task"
|
|
405
421
|
};
|
|
406
422
|
}
|
|
407
423
|
function persistUI(state) {
|
|
@@ -455,6 +471,36 @@ window.__ModuleLoader__.load({
|
|
|
455
471
|
closed: false
|
|
456
472
|
});
|
|
457
473
|
},
|
|
474
|
+
/**
|
|
475
|
+
* 切页但不动开合状态(面板里那个循环按钮用)。
|
|
476
|
+
* 非法值一律忽略 —— 这个入口会被菜单行与脏 localStorage 碰到,静默归一比抛错合适。
|
|
477
|
+
*/
|
|
478
|
+
setView(view) {
|
|
479
|
+
if (!PANEL_VIEWS.includes(view)) return;
|
|
480
|
+
if (uiState.view === view) return;
|
|
481
|
+
setUIState({
|
|
482
|
+
...uiState,
|
|
483
|
+
view
|
|
484
|
+
});
|
|
485
|
+
},
|
|
486
|
+
/**
|
|
487
|
+
* 打开面板并切到指定页 —— `/` 菜单那三行的**全部**动作。
|
|
488
|
+
*
|
|
489
|
+
* 纯客户端:不再绕 `remote.commands.execute('/tasks insight list …')` 一圈。那条路
|
|
490
|
+
* 只在对话里留下一个命令节点,而客户端渲染命令节点的是按**命令名**分发的
|
|
491
|
+
* `TaskCommandNode`(`name === 'tasks'`),它拿任务解析器去解记忆载荷,解析必然失败
|
|
492
|
+
* —— 于是点菜单"开记忆页"什么都不会发生。
|
|
493
|
+
* @param view - 目标视图页;非法值直接忽略(不打开面板,避免"点了没反应还弹窗")。
|
|
494
|
+
*/
|
|
495
|
+
openView(view) {
|
|
496
|
+
if (!PANEL_VIEWS.includes(view)) return;
|
|
497
|
+
setUIState({
|
|
498
|
+
...uiState,
|
|
499
|
+
view,
|
|
500
|
+
minimized: false,
|
|
501
|
+
closed: false
|
|
502
|
+
});
|
|
503
|
+
},
|
|
458
504
|
minimize() {
|
|
459
505
|
setUIState({
|
|
460
506
|
...uiState,
|
|
@@ -668,92 +714,92 @@ window.__ModuleLoader__.load({
|
|
|
668
714
|
document.head.appendChild(tag);
|
|
669
715
|
}
|
|
670
716
|
var TaskPanel_module_css_default = {
|
|
671
|
-
"
|
|
717
|
+
"badge": "vZSZnG_badge",
|
|
718
|
+
"badgeArchived": "vZSZnG_badgeArchived",
|
|
719
|
+
"badgeDraft": "vZSZnG_badgeDraft",
|
|
720
|
+
"boundBadge": "vZSZnG_boundBadge",
|
|
721
|
+
"boundaryFallback": "vZSZnG_boundaryFallback",
|
|
722
|
+
"card": "vZSZnG_card",
|
|
723
|
+
"cardBody": "vZSZnG_cardBody",
|
|
724
|
+
"cardBound": "vZSZnG_cardBound",
|
|
725
|
+
"cardFooter": "vZSZnG_cardFooter",
|
|
726
|
+
"cardHead": "vZSZnG_cardHead",
|
|
727
|
+
"cardMeta": "vZSZnG_cardMeta",
|
|
728
|
+
"cardTitle": "vZSZnG_cardTitle",
|
|
729
|
+
"cardTitleEditable": "vZSZnG_cardTitleEditable",
|
|
730
|
+
"cardTitleRow": "vZSZnG_cardTitleRow",
|
|
731
|
+
"chevron": "vZSZnG_chevron",
|
|
732
|
+
"counts": "vZSZnG_counts",
|
|
733
|
+
"dragGhost": "vZSZnG_dragGhost",
|
|
734
|
+
"dragGhostCard": "vZSZnG_dragGhostCard",
|
|
735
|
+
"dragGhostClose": "vZSZnG_dragGhostClose",
|
|
736
|
+
"dragGhostContent": "vZSZnG_dragGhostContent",
|
|
672
737
|
"dragHandle": "vZSZnG_dragHandle",
|
|
738
|
+
"dropPulse": "vZSZnG_dropPulse",
|
|
739
|
+
"dropTargetAfter": "vZSZnG_dropTargetAfter",
|
|
740
|
+
"dropTargetBefore": "vZSZnG_dropTargetBefore",
|
|
741
|
+
"editorArea": "vZSZnG_editorArea",
|
|
742
|
+
"emptyDesc": "vZSZnG_emptyDesc",
|
|
743
|
+
"emptyState": "vZSZnG_emptyState",
|
|
744
|
+
"emptyTitle": "vZSZnG_emptyTitle",
|
|
745
|
+
"fileDot": "vZSZnG_fileDot",
|
|
746
|
+
"fileLine": "vZSZnG_fileLine",
|
|
747
|
+
"filePath": "vZSZnG_filePath",
|
|
748
|
+
"fileRow": "vZSZnG_fileRow",
|
|
749
|
+
"filesList": "vZSZnG_filesList",
|
|
750
|
+
"handleGrip": "vZSZnG_handleGrip",
|
|
751
|
+
"header": "vZSZnG_header",
|
|
752
|
+
"headerIcon": "vZSZnG_headerIcon",
|
|
673
753
|
"headerIconBtn": "vZSZnG_headerIconBtn",
|
|
754
|
+
"headerLeft": "vZSZnG_headerLeft",
|
|
755
|
+
"headerRight": "vZSZnG_headerRight",
|
|
756
|
+
"headerTitle": "vZSZnG_headerTitle",
|
|
757
|
+
"hintsOff": "vZSZnG_hintsOff",
|
|
758
|
+
"kindBadge": "vZSZnG_kindBadge",
|
|
759
|
+
"memActs": "vZSZnG_memActs",
|
|
760
|
+
"memBody": "vZSZnG_memBody",
|
|
674
761
|
"memCount": "vZSZnG_memCount",
|
|
762
|
+
"memLabel": "vZSZnG_memLabel",
|
|
763
|
+
"memList": "vZSZnG_memList",
|
|
764
|
+
"memMeta": "vZSZnG_memMeta",
|
|
765
|
+
"memNew": "vZSZnG_memNew",
|
|
766
|
+
"memNewRow": "vZSZnG_memNewRow",
|
|
767
|
+
"memRow": "vZSZnG_memRow",
|
|
768
|
+
"memRowArchived": "vZSZnG_memRowArchived",
|
|
769
|
+
"memRowMain": "vZSZnG_memRowMain",
|
|
675
770
|
"memTitle": "vZSZnG_memTitle",
|
|
676
|
-
"
|
|
771
|
+
"memToolbar": "vZSZnG_memToolbar",
|
|
677
772
|
"memToolbarActs": "vZSZnG_memToolbarActs",
|
|
678
|
-
"
|
|
773
|
+
"memoryPane": "vZSZnG_memoryPane",
|
|
774
|
+
"miniBar": "vZSZnG_miniBar",
|
|
679
775
|
"miniChevron": "vZSZnG_miniChevron",
|
|
680
|
-
"
|
|
681
|
-
"memRowArchived": "vZSZnG_memRowArchived",
|
|
682
|
-
"filePath": "vZSZnG_filePath",
|
|
683
|
-
"notice": "vZSZnG_notice",
|
|
684
|
-
"fileDot": "vZSZnG_fileDot",
|
|
685
|
-
"cardTitle": "vZSZnG_cardTitle",
|
|
686
|
-
"cardTitleRow": "vZSZnG_cardTitleRow",
|
|
776
|
+
"miniIcon": "vZSZnG_miniIcon",
|
|
687
777
|
"miniText": "vZSZnG_miniText",
|
|
688
|
-
"stepContent": "vZSZnG_stepContent",
|
|
689
|
-
"fileLine": "vZSZnG_fileLine",
|
|
690
|
-
"boundBadge": "vZSZnG_boundBadge",
|
|
691
|
-
"card": "vZSZnG_card",
|
|
692
|
-
"updated": "vZSZnG_updated",
|
|
693
778
|
"muted": "vZSZnG_muted",
|
|
694
|
-
"
|
|
695
|
-
"
|
|
696
|
-
"memToolbar": "vZSZnG_memToolbar",
|
|
697
|
-
"syncHint": "vZSZnG_syncHint",
|
|
698
|
-
"miniIcon": "vZSZnG_miniIcon",
|
|
699
|
-
"dropTargetAfter": "vZSZnG_dropTargetAfter",
|
|
700
|
-
"stepPending": "vZSZnG_stepPending",
|
|
701
|
-
"dragGhostCard": "vZSZnG_dragGhostCard",
|
|
702
|
-
"stepEditable": "vZSZnG_stepEditable",
|
|
703
|
-
"sectionCount": "vZSZnG_sectionCount",
|
|
704
|
-
"stepToggle": "vZSZnG_stepToggle",
|
|
705
|
-
"hintsOff": "vZSZnG_hintsOff",
|
|
706
|
-
"boundaryFallback": "vZSZnG_boundaryFallback",
|
|
707
|
-
"emptyTitle": "vZSZnG_emptyTitle",
|
|
708
|
-
"memRowMain": "vZSZnG_memRowMain",
|
|
709
|
-
"cardHead": "vZSZnG_cardHead",
|
|
710
|
-
"header": "vZSZnG_header",
|
|
711
|
-
"editorArea": "vZSZnG_editorArea",
|
|
712
|
-
"badgeArchived": "vZSZnG_badgeArchived",
|
|
713
|
-
"stepRun": "vZSZnG_stepRun",
|
|
714
|
-
"miniBar": "vZSZnG_miniBar",
|
|
715
|
-
"stepDragging": "vZSZnG_stepDragging",
|
|
716
|
-
"memoryPane": "vZSZnG_memoryPane",
|
|
717
|
-
"dragGhostClose": "vZSZnG_dragGhostClose",
|
|
718
|
-
"cardMeta": "vZSZnG_cardMeta",
|
|
719
|
-
"stepRow": "vZSZnG_stepRow",
|
|
720
|
-
"filesList": "vZSZnG_filesList",
|
|
721
|
-
"memNewRow": "vZSZnG_memNewRow",
|
|
722
|
-
"cardBody": "vZSZnG_cardBody",
|
|
723
|
-
"stepContentDone": "vZSZnG_stepContentDone",
|
|
724
|
-
"cardTitleEditable": "vZSZnG_cardTitleEditable",
|
|
725
|
-
"dropPulse": "vZSZnG_dropPulse",
|
|
726
|
-
"kindBadge": "vZSZnG_kindBadge",
|
|
727
|
-
"headerRight": "vZSZnG_headerRight",
|
|
728
|
-
"trackFill": "vZSZnG_trackFill",
|
|
729
|
-
"progressText": "vZSZnG_progressText",
|
|
779
|
+
"notice": "vZSZnG_notice",
|
|
780
|
+
"panel": "vZSZnG_panel",
|
|
730
781
|
"panelIn": "vZSZnG_panelIn",
|
|
731
|
-
"
|
|
732
|
-
"
|
|
733
|
-
"
|
|
734
|
-
"track": "vZSZnG_track",
|
|
782
|
+
"progressText": "vZSZnG_progressText",
|
|
783
|
+
"section": "vZSZnG_section",
|
|
784
|
+
"sectionCount": "vZSZnG_sectionCount",
|
|
735
785
|
"sectionLabel": "vZSZnG_sectionLabel",
|
|
736
|
-
"
|
|
786
|
+
"stepContent": "vZSZnG_stepContent",
|
|
787
|
+
"stepContentDone": "vZSZnG_stepContentDone",
|
|
788
|
+
"stepContentRun": "vZSZnG_stepContentRun",
|
|
737
789
|
"stepDone": "vZSZnG_stepDone",
|
|
738
|
-
"
|
|
739
|
-
"
|
|
740
|
-
"
|
|
741
|
-
"
|
|
742
|
-
"
|
|
743
|
-
"
|
|
744
|
-
"
|
|
790
|
+
"stepDragging": "vZSZnG_stepDragging",
|
|
791
|
+
"stepEditable": "vZSZnG_stepEditable",
|
|
792
|
+
"stepInput": "vZSZnG_stepInput",
|
|
793
|
+
"stepPending": "vZSZnG_stepPending",
|
|
794
|
+
"stepRow": "vZSZnG_stepRow",
|
|
795
|
+
"stepRun": "vZSZnG_stepRun",
|
|
796
|
+
"stepToggle": "vZSZnG_stepToggle",
|
|
745
797
|
"stepsList": "vZSZnG_stepsList",
|
|
746
|
-
"
|
|
747
|
-
"emptyState": "vZSZnG_emptyState",
|
|
748
|
-
"memBody": "vZSZnG_memBody",
|
|
749
|
-
"headerLeft": "vZSZnG_headerLeft",
|
|
750
|
-
"memRow": "vZSZnG_memRow",
|
|
751
|
-
"badgeDraft": "vZSZnG_badgeDraft",
|
|
752
|
-
"badge": "vZSZnG_badge",
|
|
753
|
-
"headerIcon": "vZSZnG_headerIcon",
|
|
798
|
+
"syncHint": "vZSZnG_syncHint",
|
|
754
799
|
"taskList": "vZSZnG_taskList",
|
|
755
|
-
"
|
|
756
|
-
"
|
|
800
|
+
"track": "vZSZnG_track",
|
|
801
|
+
"trackFill": "vZSZnG_trackFill",
|
|
802
|
+
"updated": "vZSZnG_updated"
|
|
757
803
|
};
|
|
758
804
|
//#endregion
|
|
759
805
|
//#region src/client/TaskComponents.tsx
|
|
@@ -1769,11 +1815,7 @@ window.__ModuleLoader__.load({
|
|
|
1769
1815
|
"in_progress",
|
|
1770
1816
|
"completed"
|
|
1771
1817
|
];
|
|
1772
|
-
const VIEW_CYCLE =
|
|
1773
|
-
"task",
|
|
1774
|
-
"project",
|
|
1775
|
-
"global"
|
|
1776
|
-
];
|
|
1818
|
+
const VIEW_CYCLE = PANEL_VIEWS;
|
|
1777
1819
|
function getT(ctx) {
|
|
1778
1820
|
return createTranslate(ctx?.locale?.getSnapshot?.()?.active === "zh" ? zh : en);
|
|
1779
1821
|
}
|
|
@@ -1816,14 +1858,14 @@ window.__ModuleLoader__.load({
|
|
|
1816
1858
|
const [syncedAt, setSyncedAt] = (0, react.useState)(0);
|
|
1817
1859
|
const [syncError, setSyncError] = (0, react.useState)(null);
|
|
1818
1860
|
const showHints = ui.showHints;
|
|
1819
|
-
const
|
|
1861
|
+
const dataActions = useTaskDataActions();
|
|
1862
|
+
const uiActions = useTaskUIActions();
|
|
1863
|
+
const view = ui.view;
|
|
1820
1864
|
const cycleView = () => {
|
|
1821
1865
|
const i = VIEW_CYCLE.indexOf(view);
|
|
1822
|
-
setView(VIEW_CYCLE[(i + 1) % VIEW_CYCLE.length]);
|
|
1866
|
+
uiActions.setView(VIEW_CYCLE[(i + 1) % VIEW_CYCLE.length]);
|
|
1823
1867
|
};
|
|
1824
1868
|
const viewTitle = view === "task" ? t("panel.title") : view === "global" ? t("view.global") : t("view.project");
|
|
1825
|
-
const dataActions = useTaskDataActions();
|
|
1826
|
-
const uiActions = useTaskUIActions();
|
|
1827
1869
|
const tasks = Array.isArray(data.tasks) ? data.tasks : [];
|
|
1828
1870
|
const activeTasks = tasks.filter((task) => !task.archived);
|
|
1829
1871
|
const boundTask = data.boundTaskId ? tasks.find((task) => task.id === data.boundTaskId) ?? null : null;
|
|
@@ -2302,6 +2344,53 @@ window.__ModuleLoader__.load({
|
|
|
2302
2344
|
});
|
|
2303
2345
|
}
|
|
2304
2346
|
//#endregion
|
|
2347
|
+
//#region src/client/ShowTaskPanelNode.tsx
|
|
2348
|
+
/**
|
|
2349
|
+
* `show_task_panel` 工具调用的会话内视图 —— 它的作用就是**把面板打开**。
|
|
2350
|
+
*
|
|
2351
|
+
* 为什么这件事必须在这里做:面板的显示状态(closed / minimized)是**浏览器侧**的
|
|
2352
|
+
* (`task-ui-store.ts`),宿主进程碰不到它。宿主侧原本写的是
|
|
2353
|
+
* `exec.ctx.events.emit('dsh:task-panel:show')`,而宿主契约里根本没有 `ctx`:
|
|
2354
|
+
*
|
|
2355
|
+
* packages/core/tools/src/index.ts:418
|
|
2356
|
+
* export interface ToolRunContext extends ToolExecution {
|
|
2357
|
+
* deferContext(context: UserMessage): void
|
|
2358
|
+
* concludeTurn(): void
|
|
2359
|
+
* }
|
|
2360
|
+
*
|
|
2361
|
+
* 于是那个工具每次都只返回「无法获取上下文」,面板从来不会打开 —— 插件里唯一的
|
|
2362
|
+
* 宿主命令之外,这是第二个"写了但没生效"的面(详见 CHANGELOG 0.5.14)。
|
|
2363
|
+
*
|
|
2364
|
+
* 正确的位置是宿主给出的扩展点:`ui-tool` 注册了 `conversation.chat.node`(key `tool-call`),
|
|
2365
|
+
* 其下有个按**工具名**分发的子槽 `tool.call.toolview`(契约原文:*Any name is allowed,
|
|
2366
|
+
* including tools registered by your package. Register with `key: '<tool name>'`*)。
|
|
2367
|
+
* 在这里认领 `show_task_panel` 这个 key,工具结果一渲染就把面板打开。
|
|
2368
|
+
*/
|
|
2369
|
+
/**
|
|
2370
|
+
* 只在**现场执行**时打开面板。
|
|
2371
|
+
*
|
|
2372
|
+
* 历史节点在刷新 / 切换会话后挂载时会**直接**处于 `result` 阶段;现场调用则会先经过
|
|
2373
|
+
* `preparing` / `start`。这与 `/tasks` 命令节点用的判据同款(见 `TaskCommandNode.tsx`
|
|
2374
|
+
* 的 `live` ref):刷新后只展示、不再开面板,否则每次打开会话都会弹一次面板。
|
|
2375
|
+
*/
|
|
2376
|
+
function ShowTaskPanelNode(props) {
|
|
2377
|
+
const phase = props?.phase;
|
|
2378
|
+
const live = (0, react.useRef)(phase !== "result");
|
|
2379
|
+
(0, react.useEffect)(() => {
|
|
2380
|
+
if (phase !== "result" || !live.current) return;
|
|
2381
|
+
live.current = false;
|
|
2382
|
+
taskUIStore.actions.open();
|
|
2383
|
+
}, [phase]);
|
|
2384
|
+
return null;
|
|
2385
|
+
}
|
|
2386
|
+
/** 把 `show_task_panel` 的视图注册进宿主的 `tool.call.toolview` 槽。 */
|
|
2387
|
+
function registerShowTaskPanelView(slots) {
|
|
2388
|
+
slots.inject("tool.call.toolview", () => slots.register({
|
|
2389
|
+
name: "tool.call.toolview",
|
|
2390
|
+
key: "show_task_panel"
|
|
2391
|
+
}, ShowTaskPanelNode));
|
|
2392
|
+
}
|
|
2393
|
+
//#endregion
|
|
2305
2394
|
//#region src/client/slash.ts
|
|
2306
2395
|
/** 源的稳定标识:同一 trigger 内唯一,重复注册会抛错。 */
|
|
2307
2396
|
const SLASH_SOURCE_NAME = "project-memory";
|
|
@@ -2312,7 +2401,7 @@ window.__ModuleLoader__.load({
|
|
|
2312
2401
|
descriptionKey: "slash.tasks-desc",
|
|
2313
2402
|
icon: IconChecklistOutline16,
|
|
2314
2403
|
match: ["tasks", "task"],
|
|
2315
|
-
|
|
2404
|
+
view: "task"
|
|
2316
2405
|
},
|
|
2317
2406
|
{
|
|
2318
2407
|
labelKey: "view.project",
|
|
@@ -2323,7 +2412,7 @@ window.__ModuleLoader__.load({
|
|
|
2323
2412
|
"project",
|
|
2324
2413
|
"insight"
|
|
2325
2414
|
],
|
|
2326
|
-
|
|
2415
|
+
view: "project"
|
|
2327
2416
|
},
|
|
2328
2417
|
{
|
|
2329
2418
|
labelKey: "view.global",
|
|
@@ -2334,7 +2423,7 @@ window.__ModuleLoader__.load({
|
|
|
2334
2423
|
"global",
|
|
2335
2424
|
"insight"
|
|
2336
2425
|
],
|
|
2337
|
-
|
|
2426
|
+
view: "global"
|
|
2338
2427
|
}
|
|
2339
2428
|
];
|
|
2340
2429
|
/** 按当前语言取翻译函数。 */
|
|
@@ -2361,7 +2450,6 @@ window.__ModuleLoader__.load({
|
|
|
2361
2450
|
description: t(row.descriptionKey),
|
|
2362
2451
|
icon: row.icon,
|
|
2363
2452
|
section: t("slash.group"),
|
|
2364
|
-
line: row.line,
|
|
2365
2453
|
terms: [title, ...row.match].map((term) => term.toLowerCase())
|
|
2366
2454
|
};
|
|
2367
2455
|
}).filter((row) => query === "" || row.terms.some((term) => term.startsWith(query))).map(({ terms: _terms, ...candidate }) => candidate);
|
|
@@ -2385,13 +2473,18 @@ window.__ModuleLoader__.load({
|
|
|
2385
2473
|
}
|
|
2386
2474
|
}
|
|
2387
2475
|
/**
|
|
2388
|
-
* 一次菜单点击:消费掉触发 token
|
|
2476
|
+
* 一次菜单点击:消费掉触发 token 后**直接打开面板的对应页**。
|
|
2389
2477
|
*
|
|
2390
|
-
*
|
|
2391
|
-
*
|
|
2392
|
-
*
|
|
2478
|
+
* 这三行是「打开某个视图」,不是「执行某条命令」,所以走客户端自己的 UI store:
|
|
2479
|
+
* 面板的 `closed` / `view` 都是浏览器侧状态,宿主命令碰不到它们。旧实现执行
|
|
2480
|
+
* `remote.commands.execute('/tasks insight list project')`,只在对话里留下一个命令节点,
|
|
2481
|
+
* 而客户端渲染命令节点的是按**命令名**分发的 `TaskCommandNode`(`name === 'tasks'`),
|
|
2482
|
+
* 它拿任务解析器去解记忆载荷 → 解析失败 → 对面板零影响。**这就是"点了没反应"的原因。**
|
|
2483
|
+
*
|
|
2484
|
+
* 不返回 claim(回填 `/xxx ` 再等回车):claim 会多要一次回车,而这三行没有参数要填。
|
|
2485
|
+
* 消费失败时仍然切页 —— 草稿里残留的触发文本要用户自己清掉,比"点了完全没反应"好。
|
|
2393
2486
|
* @param t - 翻译函数(按当前语言把候选 name 映射回 ROWS)。
|
|
2394
|
-
* @param deps -
|
|
2487
|
+
* @param deps - 会话服务与 UI store 动作。
|
|
2395
2488
|
* @param pick - 宿主给的点击载荷。
|
|
2396
2489
|
* @returns PickOutcome;拿不到可用形状时返回 undefined(菜单照常关闭,草稿不动)。
|
|
2397
2490
|
*/
|
|
@@ -2401,9 +2494,11 @@ window.__ModuleLoader__.load({
|
|
|
2401
2494
|
const row = ROWS.find((candidate) => t(candidate.labelKey) === title);
|
|
2402
2495
|
if (row === void 0) return void 0;
|
|
2403
2496
|
consumeSpan(deps, pick);
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
})
|
|
2497
|
+
try {
|
|
2498
|
+
deps.openView(row.view);
|
|
2499
|
+
} catch (err) {
|
|
2500
|
+
console.warn(`[dsh-project-memory] open view ${row.view} failed:`, err);
|
|
2501
|
+
}
|
|
2407
2502
|
return "handled";
|
|
2408
2503
|
}
|
|
2409
2504
|
/**
|
|
@@ -2452,34 +2547,6 @@ window.__ModuleLoader__.load({
|
|
|
2452
2547
|
"locale"
|
|
2453
2548
|
];
|
|
2454
2549
|
/**
|
|
2455
|
-
* 执行一条命令行,映射成 composer 的 SubmitOutcome。
|
|
2456
|
-
* 与 TaskPanel 走同一个 remote.commands.execute 通道(同样的返回信封)。
|
|
2457
|
-
* @param commands - ctx.remote.commands
|
|
2458
|
-
* @param session - 会话投影(只读 sessionId)
|
|
2459
|
-
* @param line - 完整命令行(含前导斜杠)
|
|
2460
|
-
* @param attachments - 提交附件(菜单路径恒为空)
|
|
2461
|
-
* @returns {kind:'success'|'error', text?}
|
|
2462
|
-
*/
|
|
2463
|
-
async function runCommand(commands, session, line, attachments = []) {
|
|
2464
|
-
const sessionId = session?.sessionId;
|
|
2465
|
-
if (typeof sessionId !== "string" || !commands || typeof commands.execute !== "function") return {
|
|
2466
|
-
kind: "error",
|
|
2467
|
-
text: `no session / commands service for ${line}`
|
|
2468
|
-
};
|
|
2469
|
-
const envelope = await commands.execute(sessionId, line, [...attachments]);
|
|
2470
|
-
if (envelope && typeof envelope === "object" && envelope.ok === false) return {
|
|
2471
|
-
kind: "error",
|
|
2472
|
-
text: `command.execute failed: ${envelope.error?.code ?? "unknown"}`
|
|
2473
|
-
};
|
|
2474
|
-
const execution = envelope && typeof envelope === "object" && "value" in envelope ? envelope.value : envelope;
|
|
2475
|
-
const result = execution?.result ?? execution;
|
|
2476
|
-
if (result?.kind === "error") return {
|
|
2477
|
-
kind: "error",
|
|
2478
|
-
text: result.text ?? `${line} failed`
|
|
2479
|
-
};
|
|
2480
|
-
return { kind: "success" };
|
|
2481
|
-
}
|
|
2482
|
-
/**
|
|
2483
2550
|
* 注册自建的 `/` 菜单源(见 slash.ts)。
|
|
2484
2551
|
*
|
|
2485
2552
|
* 整段都是**可选增强**:宿主没有 `inputTriggers` 服务、或该服务换了契约时,绝不能因此
|
|
@@ -2506,7 +2573,7 @@ window.__ModuleLoader__.load({
|
|
|
2506
2573
|
}
|
|
2507
2574
|
const source = createSlashSource(scope, {
|
|
2508
2575
|
sessions: scope.sessions,
|
|
2509
|
-
|
|
2576
|
+
openView: (view) => taskUIStore.actions.openView(view)
|
|
2510
2577
|
});
|
|
2511
2578
|
scope.effect(() => inputTriggers.registerSource(source), "dsh-project-memory: slash source");
|
|
2512
2579
|
} catch (err) {
|
|
@@ -2530,6 +2597,7 @@ window.__ModuleLoader__.load({
|
|
|
2530
2597
|
name: "conversation.chat.commandview",
|
|
2531
2598
|
key
|
|
2532
2599
|
}, TaskCommandNode));
|
|
2600
|
+
registerShowTaskPanelView(slots);
|
|
2533
2601
|
} catch (err) {
|
|
2534
2602
|
console.warn(`[${NS}] task panel registration failed:`, err);
|
|
2535
2603
|
}
|