dsh-pre-duediligence 0.1.0 → 0.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 +10 -10
- package/install.sh +2 -2
- package/lib/client.js +367 -174
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/types/left-sidebar.d.ts +44 -0
- package/lib/types/workbench-v2.d.ts +3 -2
- package/package.json +1 -1
- package/skills/qcc-previsit-onepager/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# dsh-pre-duediligence
|
|
2
2
|
|
|
3
|
-
面向 DeepSeek Harness 的 Session
|
|
3
|
+
面向 DeepSeek Harness 的 Session 级访前尽调智能体。业务人员从左侧菜单进入,在会话级工作台定义一次拜访;Agent 调用企查查五类 MCP,使用机会与风险双引擎完成经营状态识别、假设与反证、风险核验,最终交付可追溯的访前尽调报告。
|
|
4
4
|
|
|
5
5
|
## 功能概览
|
|
6
6
|
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
### 工作台
|
|
10
10
|
|
|
11
11
|
- 使用 dsh-better-sidebar 0.17.1,不再使用遮挡对话的自定义浮层
|
|
12
|
-
-
|
|
13
|
-
-
|
|
12
|
+
- 只在 DSH 左侧菜单增加“访前尽调智能体”入口;对应工作台标签在 Better Sidebar 的右侧“+”菜单中隐藏
|
|
13
|
+
- 用户点击左侧入口、工作台真实可见后才挂载业务样式;关闭后立即卸载,不影响 DSH 原页面
|
|
14
14
|
- 四阶段业务导航:
|
|
15
15
|
1. 定义拜访
|
|
16
16
|
2. 机会研判
|
|
@@ -55,7 +55,7 @@ bash <(curl -fsSL https://raw.githubusercontent.com/duhu2000/dsh-pre-duediligenc
|
|
|
55
55
|
|
|
56
56
|
1. `dsh-better-sidebar@0.17.1`:提供 Session 级右侧工作台容器。
|
|
57
57
|
2. `dsh-mcp-connector@0.2.32`:提供通用 MCP 连接器与市场,通过“企查查·企业工商”完成 OAuth,并动态挂载企业、风险、知产、经营、历史和董监高 MCP。
|
|
58
|
-
3. `dsh-pre-duediligence@0.1.
|
|
58
|
+
3. `dsh-pre-duediligence@0.1.2`:提供左侧智能体入口、访前工作台、点选拼句器和完整 Skill。
|
|
59
59
|
|
|
60
60
|
安装完成后停止旧的 DSH Web 进程并重新运行:
|
|
61
61
|
|
|
@@ -70,7 +70,7 @@ dsh web
|
|
|
70
70
|
~~~bash
|
|
71
71
|
dsh plugin --profile web add dsh-better-sidebar@0.17.1 --allow-build=node-pty
|
|
72
72
|
dsh plugin --profile web add dsh-mcp-connector@0.2.32
|
|
73
|
-
dsh plugin --profile web add dsh-pre-duediligence@0.1.
|
|
73
|
+
dsh plugin --profile web add dsh-pre-duediligence@0.1.2 --allow-build=dsh-pre-duediligence
|
|
74
74
|
dsh web
|
|
75
75
|
~~~
|
|
76
76
|
|
|
@@ -84,7 +84,7 @@ Better Sidebar 必须使用 `0.17.1`;工作台依赖它的 `targetedOpen` 与
|
|
|
84
84
|
dsh plugin --profile web list --depth 0
|
|
85
85
|
~~~
|
|
86
86
|
|
|
87
|
-
应能看到 `dsh-better-sidebar@0.17.1`、`dsh-mcp-connector@0.2.32` 和 `dsh-pre-duediligence@0.1.
|
|
87
|
+
应能看到 `dsh-better-sidebar@0.17.1`、`dsh-mcp-connector@0.2.32` 和 `dsh-pre-duediligence@0.1.2`。重启 DSH 并连接“企查查·企业工商”后,在左侧菜单点击“访前尽调智能体”打开工作台;Better Sidebar 的右侧“+”菜单不会再列出该入口。点击前 DSH 首页、输入框、消息流和 Session 头部均保持原样。
|
|
88
88
|
|
|
89
89
|
### 从旧访前尽调包迁移
|
|
90
90
|
|
|
@@ -100,7 +100,7 @@ dsh plugin --profile web remove qcc-previsit-dsh
|
|
|
100
100
|
|
|
101
101
|
如果 Web profile 已安装 `qcc-dsh-mcp-oauth`,不要让它与 MCP 连接器同时管理同名企查查 Server:
|
|
102
102
|
|
|
103
|
-
1. 先安装 `dsh-mcp-connector@0.2.32` 和 `dsh-pre-duediligence@0.1.
|
|
103
|
+
1. 先安装 `dsh-mcp-connector@0.2.32` 和 `dsh-pre-duediligence@0.1.2`,完全重启 DSH。
|
|
104
104
|
2. 打开“🧩 MCP连接器”,按界面提示迁移旧企查查授权;也可以重新连接“企查查·企业工商”。
|
|
105
105
|
3. 迁移完成后停止 DSH,执行 `dsh plugin --profile web remove qcc-dsh-mcp-oauth`。
|
|
106
106
|
4. 再次启动 DSH,在“已安装”中确认企查查连接健康,然后执行一次真实企业查询。
|
|
@@ -121,8 +121,8 @@ pnpm check 会执行 TypeScript 类型检查、Vitest 测试和 Host/Client 构
|
|
|
121
121
|
## 人工验收
|
|
122
122
|
|
|
123
123
|
1. 在 DSH 选择一个工作空间和 Session。
|
|
124
|
-
2.
|
|
125
|
-
3.
|
|
124
|
+
2. 确认左侧菜单出现“访前尽调智能体”,同时右侧 Better Sidebar 的“+”菜单不再出现该入口;首页标题、输入框、消息流和 Session 头部均保持 DSH 原样。
|
|
125
|
+
3. 点击左侧“访前尽调智能体”,确认会话级工作台打开;关闭后业务 UI 和样式不再存在。
|
|
126
126
|
4. 打开“定义拜访”,确认所有条件初始都未选择。
|
|
127
127
|
5. 选择“银行/信贷客户经理、首次拜访、风险与涉诉、股权与实控人、15分钟标准、一页纸简报”。
|
|
128
128
|
6. 将占位符替换为完整注册名称“企查查科技股份有限公司”,再切换档位,确认企业名称不丢失。
|
|
@@ -166,7 +166,7 @@ dsh-pre-duediligence/
|
|
|
166
166
|
## 安全与边界
|
|
167
167
|
|
|
168
168
|
- 插件不保存企查查 Token。
|
|
169
|
-
-
|
|
169
|
+
- 插件只在左侧栏增加独立入口,并把承载工作台的 Better Sidebar 标签从右侧“+”菜单隐藏;未点击入口时不挂载业务 DOM 或 CSS,也不修改 DSH 原生文案。
|
|
170
170
|
- 企业事实只能来自本次企查查 MCP 返回。
|
|
171
171
|
- 条件仅生成用户可见文本,不在 Client 侧调用 MCP。
|
|
172
172
|
- 用户点击“开始访前尽调”后才发送。
|
package/install.sh
CHANGED
|
@@ -5,7 +5,7 @@ set -euo pipefail
|
|
|
5
5
|
readonly PROFILE_NAME="${DSH_PROFILE:-web}"
|
|
6
6
|
readonly BETTER_SIDEBAR_SPEC="dsh-better-sidebar@0.17.1"
|
|
7
7
|
readonly MCP_CONNECTOR_SPEC="dsh-mcp-connector@0.2.32"
|
|
8
|
-
readonly PREVISIT_SPEC="${DSH_PRE_DUEDILIGENCE_SPEC:-dsh-pre-duediligence@0.1.
|
|
8
|
+
readonly PREVISIT_SPEC="${DSH_PRE_DUEDILIGENCE_SPEC:-dsh-pre-duediligence@0.1.2}"
|
|
9
9
|
readonly LEGACY_PREVISIT_NAME="qcc-previsit-dsh"
|
|
10
10
|
readonly LEGACY_QCC_OAUTH_NAME="qcc-dsh-mcp-oauth"
|
|
11
11
|
|
|
@@ -59,4 +59,4 @@ else
|
|
|
59
59
|
"重启后打开左侧“🧩 MCP连接器”,选择“企查查·企业工商”并完成 OAuth 授权。" \
|
|
60
60
|
"该连接会提供企业、风险、知产、经营、历史和董监高 MCP。"
|
|
61
61
|
fi
|
|
62
|
-
printf '%s\n' "
|
|
62
|
+
printf '%s\n' "在 DSH 左侧菜单点击“访前尽调智能体”即可打开;右侧标签菜单不再显示该入口,未点击时不会改动原页面。"
|
package/lib/client.js
CHANGED
|
@@ -39,7 +39,7 @@ __export(client_exports, {
|
|
|
39
39
|
module.exports = __toCommonJS(client_exports);
|
|
40
40
|
|
|
41
41
|
// src/workbench-v2.tsx
|
|
42
|
-
var
|
|
42
|
+
var import_react4 = require("react");
|
|
43
43
|
|
|
44
44
|
// src/previsit-dock.tsx
|
|
45
45
|
var import_react = require("react");
|
|
@@ -648,6 +648,55 @@ function PrevisitFields(props) {
|
|
|
648
648
|
var import_react2 = require("react");
|
|
649
649
|
var PREVISIT_WORKBENCH_TAB_ID = "dsh-pre-duediligence:agent";
|
|
650
650
|
var SUPPORTED_SIDEBAR_VERSION = /^0\.17\./u;
|
|
651
|
+
function treeContainsTab(node, tabId) {
|
|
652
|
+
if (node.kind === "leaf") {
|
|
653
|
+
return node.tabs.some((tab) => tab.id === tabId);
|
|
654
|
+
}
|
|
655
|
+
return node.children.some((child) => treeContainsTab(child, tabId));
|
|
656
|
+
}
|
|
657
|
+
function revealState(state, tabId) {
|
|
658
|
+
if (state.floats.some((float) => float.tab.id === tabId)) {
|
|
659
|
+
return state;
|
|
660
|
+
}
|
|
661
|
+
if (treeContainsTab(state.bottomSplits, tabId)) {
|
|
662
|
+
return state.bottomOpen ? state : { ...state, bottomOpen: true };
|
|
663
|
+
}
|
|
664
|
+
if (treeContainsTab(state.splits, tabId)) {
|
|
665
|
+
return state.panelOpen ? state : { ...state, panelOpen: true };
|
|
666
|
+
}
|
|
667
|
+
return state;
|
|
668
|
+
}
|
|
669
|
+
function createRevealController() {
|
|
670
|
+
const targets = /* @__PURE__ */ new Map();
|
|
671
|
+
const pending = /* @__PURE__ */ new Set();
|
|
672
|
+
return {
|
|
673
|
+
attach(sessionId, target) {
|
|
674
|
+
targets.set(sessionId, target);
|
|
675
|
+
if (pending.delete(sessionId)) {
|
|
676
|
+
target.store.reduce((state) => revealState(state, target.tabId));
|
|
677
|
+
}
|
|
678
|
+
return () => {
|
|
679
|
+
if (targets.get(sessionId) === target) {
|
|
680
|
+
targets.delete(sessionId);
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
},
|
|
684
|
+
request(sessionId) {
|
|
685
|
+
const target = targets.get(sessionId);
|
|
686
|
+
if (target === void 0) {
|
|
687
|
+
pending.add(sessionId);
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
target.store.reduce((state) => revealState(state, target.tabId));
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
function useWorkbenchReveal(controller, props) {
|
|
695
|
+
const sessionId = props.scope.sessionId;
|
|
696
|
+
const store = props.store;
|
|
697
|
+
const tabId = props.tab.id;
|
|
698
|
+
(0, import_react2.useEffect)(() => controller.attach(sessionId, { store, tabId }), [controller, sessionId, store, tabId]);
|
|
699
|
+
}
|
|
651
700
|
function assertBetterSidebar(service) {
|
|
652
701
|
if (!SUPPORTED_SIDEBAR_VERSION.test(service.version)) {
|
|
653
702
|
throw new Error("dsh-pre-duediligence requires dsh-better-sidebar 0.17.x");
|
|
@@ -662,10 +711,151 @@ function registerWorkbenchTab(service, component) {
|
|
|
662
711
|
id: PREVISIT_WORKBENCH_TAB_ID,
|
|
663
712
|
title: "\u8BBF\u524D\u5C3D\u8C03\u667A\u80FD\u4F53",
|
|
664
713
|
order: 30,
|
|
714
|
+
hidden: true,
|
|
665
715
|
single: true,
|
|
666
716
|
component
|
|
667
717
|
});
|
|
668
718
|
}
|
|
719
|
+
function openWorkbench(service, scope, reveal) {
|
|
720
|
+
assertBetterSidebar(service);
|
|
721
|
+
if (!service.isTabEnabled(PREVISIT_WORKBENCH_TAB_ID)) {
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
service.openTab({ type: PREVISIT_WORKBENCH_TAB_ID }, scope);
|
|
725
|
+
if (service.getSnapshot().sessionId === scope.sessionId) {
|
|
726
|
+
reveal.request(scope.sessionId);
|
|
727
|
+
}
|
|
728
|
+
return true;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// src/left-sidebar.tsx
|
|
732
|
+
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
733
|
+
var import_react3 = require("react");
|
|
734
|
+
var import_react_dom2 = require("react-dom");
|
|
735
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
736
|
+
var WORKSPACES_SLOT_SELECTOR = '[data-slot="sidebar.workspaces"]';
|
|
737
|
+
var LAUNCHER_MOUNT_SELECTOR = '[data-previsit-launcher-mount="true"]';
|
|
738
|
+
function ensureLauncherMount() {
|
|
739
|
+
const workspaceSlot = document.querySelector(WORKSPACES_SLOT_SELECTOR);
|
|
740
|
+
const parent = workspaceSlot?.parentElement;
|
|
741
|
+
if (workspaceSlot === null || parent === void 0 || parent === null) return null;
|
|
742
|
+
let mount = parent.querySelector(LAUNCHER_MOUNT_SELECTOR);
|
|
743
|
+
if (mount === null) {
|
|
744
|
+
mount = document.createElement("div");
|
|
745
|
+
mount.dataset.previsitLauncherMount = "true";
|
|
746
|
+
}
|
|
747
|
+
if (mount.parentElement !== parent) parent.insertBefore(mount, workspaceSlot);
|
|
748
|
+
return mount;
|
|
749
|
+
}
|
|
750
|
+
function LeftSidebarEntry(props) {
|
|
751
|
+
const [mount, setMount] = (0, import_react3.useState)(null);
|
|
752
|
+
const [busy, setBusy] = (0, import_react3.useState)(false);
|
|
753
|
+
const [error, setError] = (0, import_react3.useState)();
|
|
754
|
+
const wide = props.wide !== false;
|
|
755
|
+
(0, import_react3.useEffect)(() => {
|
|
756
|
+
let disposed = false;
|
|
757
|
+
const ownedMounts = /* @__PURE__ */ new Set();
|
|
758
|
+
const sync = () => {
|
|
759
|
+
if (disposed) return;
|
|
760
|
+
const next = ensureLauncherMount();
|
|
761
|
+
if (next !== null) ownedMounts.add(next);
|
|
762
|
+
setMount((current) => current === next ? current : next);
|
|
763
|
+
};
|
|
764
|
+
sync();
|
|
765
|
+
const observer = new MutationObserver(sync);
|
|
766
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
767
|
+
return () => {
|
|
768
|
+
disposed = true;
|
|
769
|
+
observer.disconnect();
|
|
770
|
+
for (const owned of ownedMounts) owned.remove();
|
|
771
|
+
};
|
|
772
|
+
}, []);
|
|
773
|
+
const launch = async () => {
|
|
774
|
+
if (busy || props.openAgent === void 0) return;
|
|
775
|
+
setBusy(true);
|
|
776
|
+
setError(void 0);
|
|
777
|
+
try {
|
|
778
|
+
await props.openAgent();
|
|
779
|
+
} catch (reason) {
|
|
780
|
+
setError(reason instanceof Error ? reason.message : String(reason));
|
|
781
|
+
} finally {
|
|
782
|
+
setBusy(false);
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
786
|
+
import_dsh_client_ui_primitives.Button,
|
|
787
|
+
{
|
|
788
|
+
type: "button",
|
|
789
|
+
variant: "ghost",
|
|
790
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives.IconAgentPresetOutline16, { size: 16 }),
|
|
791
|
+
"aria-label": "\u8BBF\u524D\u5C3D\u8C03\u667A\u80FD\u4F53",
|
|
792
|
+
"aria-busy": busy,
|
|
793
|
+
disabled: busy,
|
|
794
|
+
title: error ?? "\u6253\u5F00\u8BBF\u524D\u5C3D\u8C03\u667A\u80FD\u4F53",
|
|
795
|
+
onClick: () => {
|
|
796
|
+
void launch();
|
|
797
|
+
},
|
|
798
|
+
style: {
|
|
799
|
+
boxSizing: "border-box",
|
|
800
|
+
width: wide ? "100%" : 36,
|
|
801
|
+
height: wide ? 40 : 36,
|
|
802
|
+
justifyContent: wide ? "flex-start" : "center",
|
|
803
|
+
borderRadius: wide ? 10 : "50%",
|
|
804
|
+
paddingInline: wide ? 10 : 0,
|
|
805
|
+
whiteSpace: "nowrap"
|
|
806
|
+
},
|
|
807
|
+
children: wide ? busy ? "\u6B63\u5728\u6253\u5F00\u2026" : error === void 0 ? "\u8BBF\u524D\u5C3D\u8C03\u667A\u80FD\u4F53" : "\u6253\u5F00\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5" : null
|
|
808
|
+
}
|
|
809
|
+
);
|
|
810
|
+
if (mount === null) return button;
|
|
811
|
+
return (0, import_react_dom2.createPortal)(
|
|
812
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
813
|
+
"div",
|
|
814
|
+
{
|
|
815
|
+
"data-wide": wide,
|
|
816
|
+
style: { boxSizing: "border-box", width: wide ? "100%" : 36, paddingRight: wide ? 12 : 0 },
|
|
817
|
+
children: button
|
|
818
|
+
}
|
|
819
|
+
),
|
|
820
|
+
mount
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
var PREVISIT_SESSION_ID_PREFIX = "session-dsh-pre-duediligence-";
|
|
824
|
+
function createPrevisitSessionId() {
|
|
825
|
+
if (typeof globalThis.crypto?.randomUUID !== "function") {
|
|
826
|
+
throw new Error("\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u5B89\u5168\u4F1A\u8BDD\u6807\u8BC6\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u6700\u65B0\u7248\u6D4F\u89C8\u5668");
|
|
827
|
+
}
|
|
828
|
+
return `${PREVISIT_SESSION_ID_PREFIX}${globalThis.crypto.randomUUID()}`;
|
|
829
|
+
}
|
|
830
|
+
async function resolveSessionId(ctx) {
|
|
831
|
+
const workspace = ctx.workspaces?.list?.getSnapshot();
|
|
832
|
+
const workspaceId = workspace?.recentWorkspaceId ?? workspace?.items?.[0]?.workspaceId;
|
|
833
|
+
if (workspaceId === void 0) {
|
|
834
|
+
throw new Error("\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u5DE5\u4F5C\u7A7A\u95F4\uFF0C\u518D\u6253\u5F00\u8BBF\u524D\u5C3D\u8C03\u667A\u80FD\u4F53");
|
|
835
|
+
}
|
|
836
|
+
const create = ctx.sessions.create;
|
|
837
|
+
if (typeof create !== "function") {
|
|
838
|
+
throw new Error("\u5F53\u524D DSH \u7248\u672C\u6CA1\u6709\u53EF\u7528\u7684\u4F1A\u8BDD\u521B\u5EFA\u80FD\u529B");
|
|
839
|
+
}
|
|
840
|
+
const sessionId = await create({ workspaceId, sessionId: createPrevisitSessionId() });
|
|
841
|
+
ctx.sessions.open?.(sessionId);
|
|
842
|
+
return sessionId;
|
|
843
|
+
}
|
|
844
|
+
function registerLeftSidebarLauncher(ctx, service, reveal) {
|
|
845
|
+
ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
|
|
846
|
+
name: "sidebar.footer.action",
|
|
847
|
+
id: "dsh-pre-duediligence-launcher",
|
|
848
|
+
order: 20,
|
|
849
|
+
inject: () => ({
|
|
850
|
+
openAgent: async () => {
|
|
851
|
+
const sessionId = await resolveSessionId(ctx);
|
|
852
|
+
if (!openWorkbench(service, { sessionId }, reveal)) {
|
|
853
|
+
throw new Error("\u8BBF\u524D\u5C3D\u8C03\u5DE5\u4F5C\u53F0\u5F53\u524D\u4E0D\u53EF\u7528\uFF0C\u8BF7\u68C0\u67E5\u63D2\u4EF6\u914D\u7F6E");
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
})
|
|
857
|
+
}, LeftSidebarEntry));
|
|
858
|
+
}
|
|
669
859
|
|
|
670
860
|
// src/workbench-state.ts
|
|
671
861
|
var PREVISIT_PHASES = ["prepare", "opportunity", "risk", "delivery"];
|
|
@@ -944,8 +1134,8 @@ function riskSteps(events, insights, finished) {
|
|
|
944
1134
|
}
|
|
945
1135
|
|
|
946
1136
|
// src/workbench-v2.tsx
|
|
947
|
-
var
|
|
948
|
-
var inject = ["sessions", "conversation", "betterSidebar"];
|
|
1137
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1138
|
+
var inject = ["slots", "sessions", "workspaces", "conversation", "betterSidebar"];
|
|
949
1139
|
var STYLE_ID = "dsh-pre-duediligence-workbench";
|
|
950
1140
|
var PHASE_LABELS = {
|
|
951
1141
|
prepare: { label: "\u5C3D\u8C03\u8BBE\u5B9A", description: "\u4F01\u4E1A\u3001\u89D2\u8272\u4E0E\u8303\u56F4" },
|
|
@@ -970,40 +1160,40 @@ var EMPTY_RUNTIME = {
|
|
|
970
1160
|
};
|
|
971
1161
|
function Icon({ name }) {
|
|
972
1162
|
const paths = {
|
|
973
|
-
briefcase: /* @__PURE__ */ (0,
|
|
974
|
-
/* @__PURE__ */ (0,
|
|
975
|
-
/* @__PURE__ */ (0,
|
|
1163
|
+
briefcase: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1164
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "3", y: "7", width: "18", height: "12", rx: "2" }),
|
|
1165
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8 7V5h8v2M3 12h18M10 12v2h4v-2" })
|
|
976
1166
|
] }),
|
|
977
|
-
prepare: /* @__PURE__ */ (0,
|
|
978
|
-
/* @__PURE__ */ (0,
|
|
979
|
-
/* @__PURE__ */ (0,
|
|
1167
|
+
prepare: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1168
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M5 4h14v16H5z" }),
|
|
1169
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8 8h8M8 12h8M8 16h5" })
|
|
980
1170
|
] }),
|
|
981
|
-
opportunity: /* @__PURE__ */ (0,
|
|
982
|
-
/* @__PURE__ */ (0,
|
|
983
|
-
/* @__PURE__ */ (0,
|
|
1171
|
+
opportunity: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1172
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "10.5", cy: "10.5", r: "5.5" }),
|
|
1173
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m15 15 4 4M10.5 7v7M7 10.5h7" })
|
|
984
1174
|
] }),
|
|
985
|
-
risk: /* @__PURE__ */ (0,
|
|
986
|
-
/* @__PURE__ */ (0,
|
|
987
|
-
/* @__PURE__ */ (0,
|
|
1175
|
+
risk: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1176
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 3 3.5 7v5c0 4.6 3.1 7.5 8.5 9 5.4-1.5 8.5-4.4 8.5-9V7z" }),
|
|
1177
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 8v5M12 17h.01" })
|
|
988
1178
|
] }),
|
|
989
|
-
delivery: /* @__PURE__ */ (0,
|
|
990
|
-
/* @__PURE__ */ (0,
|
|
991
|
-
/* @__PURE__ */ (0,
|
|
1179
|
+
delivery: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1180
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M6 3h8l4 4v14H6z" }),
|
|
1181
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M14 3v5h5M9 13h6M9 17h6" })
|
|
992
1182
|
] }),
|
|
993
|
-
clock: /* @__PURE__ */ (0,
|
|
994
|
-
/* @__PURE__ */ (0,
|
|
995
|
-
/* @__PURE__ */ (0,
|
|
1183
|
+
clock: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1184
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "9" }),
|
|
1185
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 7v5l3 2" })
|
|
996
1186
|
] }),
|
|
997
|
-
check: /* @__PURE__ */ (0,
|
|
998
|
-
/* @__PURE__ */ (0,
|
|
999
|
-
/* @__PURE__ */ (0,
|
|
1187
|
+
check: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1188
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "9" }),
|
|
1189
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m8 12 2.5 2.5L16 9" })
|
|
1000
1190
|
] }),
|
|
1001
|
-
warning: /* @__PURE__ */ (0,
|
|
1002
|
-
/* @__PURE__ */ (0,
|
|
1003
|
-
/* @__PURE__ */ (0,
|
|
1191
|
+
warning: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1192
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 3 2.8 20h18.4z" }),
|
|
1193
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 9v4M12 17h.01" })
|
|
1004
1194
|
] })
|
|
1005
1195
|
};
|
|
1006
|
-
return /* @__PURE__ */ (0,
|
|
1196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "qccPwIcon", viewBox: "0 0 24 24", "aria-hidden": "true", children: paths[name] });
|
|
1007
1197
|
}
|
|
1008
1198
|
function collectRuntime(snapshot, baseline) {
|
|
1009
1199
|
const toolNames = /* @__PURE__ */ new Set();
|
|
@@ -1025,11 +1215,11 @@ function collectRuntime(snapshot, baseline) {
|
|
|
1025
1215
|
}
|
|
1026
1216
|
function Feedback(props) {
|
|
1027
1217
|
const icon = props.tone === "success" ? "check" : props.tone === "error" ? "warning" : "clock";
|
|
1028
|
-
return /* @__PURE__ */ (0,
|
|
1029
|
-
/* @__PURE__ */ (0,
|
|
1030
|
-
/* @__PURE__ */ (0,
|
|
1031
|
-
/* @__PURE__ */ (0,
|
|
1032
|
-
/* @__PURE__ */ (0,
|
|
1218
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwFeedback", "data-tone": props.tone, role: props.tone === "error" ? "alert" : "status", children: [
|
|
1219
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwFeedbackIcon", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { name: icon }) }),
|
|
1220
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1221
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: props.title }),
|
|
1222
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: props.children })
|
|
1033
1223
|
] })
|
|
1034
1224
|
] });
|
|
1035
1225
|
}
|
|
@@ -1042,51 +1232,51 @@ function SetupPanel(props) {
|
|
|
1042
1232
|
start: props.start,
|
|
1043
1233
|
onStarted: props.onStarted
|
|
1044
1234
|
});
|
|
1045
|
-
return /* @__PURE__ */ (0,
|
|
1046
|
-
/* @__PURE__ */ (0,
|
|
1047
|
-
/* @__PURE__ */ (0,
|
|
1048
|
-
/* @__PURE__ */ (0,
|
|
1049
|
-
/* @__PURE__ */ (0,
|
|
1235
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "qccPwPanel", children: [
|
|
1236
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "qccPwPageHeading", children: [
|
|
1237
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1238
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwEyebrow", children: "PREVISIT" }),
|
|
1239
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: "\u5C3D\u8C03\u8BBE\u5B9A" })
|
|
1050
1240
|
] }),
|
|
1051
|
-
props.task === void 0 ? null : /* @__PURE__ */ (0,
|
|
1241
|
+
props.task === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwTaskId", children: props.task.id })
|
|
1052
1242
|
] }),
|
|
1053
|
-
/* @__PURE__ */ (0,
|
|
1054
|
-
props.task === void 0 ? null : /* @__PURE__ */ (0,
|
|
1055
|
-
/* @__PURE__ */ (0,
|
|
1056
|
-
/* @__PURE__ */ (0,
|
|
1243
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "qccPwCard qccPwSetupCard", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PrevisitFields, { actions, idPrefix: `qccPw-${props.sessionId}` }) }),
|
|
1244
|
+
props.task === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCard", children: [
|
|
1245
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "qccPwCardHeader", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: "\u5DF2\u53D1\u9001\u7684\u4EFB\u52A1" }) }) }),
|
|
1246
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("pre", { className: "qccPwPrompt", children: props.task.prompt })
|
|
1057
1247
|
] })
|
|
1058
1248
|
] });
|
|
1059
1249
|
}
|
|
1060
1250
|
function Steps(props) {
|
|
1061
|
-
return /* @__PURE__ */ (0,
|
|
1062
|
-
/* @__PURE__ */ (0,
|
|
1063
|
-
/* @__PURE__ */ (0,
|
|
1064
|
-
/* @__PURE__ */ (0,
|
|
1065
|
-
step.note === void 0 ? null : /* @__PURE__ */ (0,
|
|
1251
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ol", { className: "qccPwSteps", children: props.steps.map((step, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { className: "qccPwStep", "data-state": step.state, children: [
|
|
1252
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwStepDot", children: step.state === "done" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { name: "check" }) : index + 1 }),
|
|
1253
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "qccPwStepCopy", children: [
|
|
1254
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("b", { children: step.label }),
|
|
1255
|
+
step.note === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: step.note })
|
|
1066
1256
|
] })
|
|
1067
1257
|
] }, step.label)) });
|
|
1068
1258
|
}
|
|
1069
1259
|
function Dimensions(props) {
|
|
1070
1260
|
const done = props.items.filter((d) => d.status === "done").length;
|
|
1071
|
-
return /* @__PURE__ */ (0,
|
|
1072
|
-
/* @__PURE__ */ (0,
|
|
1073
|
-
/* @__PURE__ */ (0,
|
|
1074
|
-
done === 0 ? null : /* @__PURE__ */ (0,
|
|
1261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCard", children: [
|
|
1262
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCardHeader", children: [
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: props.title }) }),
|
|
1264
|
+
done === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "qccPwMode", children: [
|
|
1075
1265
|
done,
|
|
1076
1266
|
" \u9879"
|
|
1077
1267
|
] })
|
|
1078
1268
|
] }),
|
|
1079
|
-
props.items.length === 0 ? /* @__PURE__ */ (0,
|
|
1269
|
+
props.items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwEmpty", children: props.empty }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "qccPwDims", children: props.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwDim", "data-status": item.status, children: item.label }, item.label)) })
|
|
1080
1270
|
] });
|
|
1081
1271
|
}
|
|
1082
1272
|
function StagePanel(props) {
|
|
1083
|
-
return /* @__PURE__ */ (0,
|
|
1084
|
-
/* @__PURE__ */ (0,
|
|
1085
|
-
/* @__PURE__ */ (0,
|
|
1086
|
-
/* @__PURE__ */ (0,
|
|
1087
|
-
/* @__PURE__ */ (0,
|
|
1273
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "qccPwPanel", children: [
|
|
1274
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "qccPwPageHeading", children: [
|
|
1275
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1276
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwEyebrow", children: props.eyebrow }),
|
|
1277
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: props.title })
|
|
1088
1278
|
] }),
|
|
1089
|
-
props.task === void 0 ? null : /* @__PURE__ */ (0,
|
|
1279
|
+
props.task === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwTaskId", children: props.task.id })
|
|
1090
1280
|
] }),
|
|
1091
1281
|
props.children
|
|
1092
1282
|
] });
|
|
@@ -1098,36 +1288,36 @@ function OpportunityPanel(props) {
|
|
|
1098
1288
|
const steps = opportunitySteps(props.events, insights, finished);
|
|
1099
1289
|
const dims = opportunityDimensions(props.events);
|
|
1100
1290
|
const concluded = insights.state !== null || insights.stateUndetermined;
|
|
1101
|
-
return /* @__PURE__ */ (0,
|
|
1102
|
-
/* @__PURE__ */ (0,
|
|
1103
|
-
/* @__PURE__ */ (0,
|
|
1104
|
-
/* @__PURE__ */ (0,
|
|
1105
|
-
/* @__PURE__ */ (0,
|
|
1106
|
-
/* @__PURE__ */ (0,
|
|
1107
|
-
insights.confidence === null ? null : /* @__PURE__ */ (0,
|
|
1291
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(StagePanel, { eyebrow: "OPPORTUNITY", title: "\u7ECF\u8425\u7814\u5224", task: props.task, children: [
|
|
1292
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Steps, { steps }),
|
|
1293
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Dimensions, { title: "\u5DF2\u53D6\u5F97", items: dims, empty: running ? "\u6B63\u5728\u5EFA\u7ACB\u4E3B\u4F53\u4E0E\u4FE1\u53F7\u96C6\u2026" : "\u5C3D\u8C03\u5F00\u59CB\u540E\u663E\u793A\u53D6\u5F97\u7684\u7EF4\u5EA6" }),
|
|
1294
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCard", children: [
|
|
1295
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCardHeader", children: [
|
|
1296
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: "\u7ECF\u8425\u72B6\u6001" }) }),
|
|
1297
|
+
insights.confidence === null ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "qccPwMode", children: [
|
|
1108
1298
|
"\u7F6E\u4FE1\u5EA6 ",
|
|
1109
1299
|
insights.confidence
|
|
1110
1300
|
] })
|
|
1111
1301
|
] }),
|
|
1112
|
-
/* @__PURE__ */ (0,
|
|
1113
|
-
insights.stateUndetermined ? /* @__PURE__ */ (0,
|
|
1114
|
-
insights.industryLink === null ? null : /* @__PURE__ */ (0,
|
|
1302
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "qccPwStateStrip", "data-concluded": concluded, children: BUSINESS_STATES.map((state) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwState", "data-hit": insights.state === state, children: state }, state)) }),
|
|
1303
|
+
insights.stateUndetermined ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwNote", children: "\u72B6\u6001\u672A\u5B9A\uFF1A\u516C\u5F00\u8BC1\u636E\u4E0D\u8DB3\uFF0C\u672C\u6B21\u964D\u7EA7\u4E3A\u6E05\u5355\u5F0F\u7B80\u62A5\u3002" }) : null,
|
|
1304
|
+
insights.industryLink === null ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "qccPwNote", children: [
|
|
1115
1305
|
"\u4EA7\u4E1A\u94FE\u73AF\u8282\uFF1A",
|
|
1116
1306
|
insights.industryLink
|
|
1117
1307
|
] })
|
|
1118
1308
|
] }),
|
|
1119
|
-
/* @__PURE__ */ (0,
|
|
1120
|
-
/* @__PURE__ */ (0,
|
|
1121
|
-
/* @__PURE__ */ (0,
|
|
1122
|
-
insights.hypotheses.length === 0 ? null : /* @__PURE__ */ (0,
|
|
1309
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCard", children: [
|
|
1310
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCardHeader", children: [
|
|
1311
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: "\u4E1A\u52A1\u5047\u8BBE" }) }),
|
|
1312
|
+
insights.hypotheses.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "qccPwMode", children: [
|
|
1123
1313
|
insights.hypotheses.length,
|
|
1124
1314
|
" \u6761"
|
|
1125
1315
|
] })
|
|
1126
1316
|
] }),
|
|
1127
|
-
insights.hypotheses.length === 0 ? /* @__PURE__ */ (0,
|
|
1128
|
-
/* @__PURE__ */ (0,
|
|
1129
|
-
/* @__PURE__ */ (0,
|
|
1130
|
-
/* @__PURE__ */ (0,
|
|
1317
|
+
insights.hypotheses.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwEmpty", children: finished ? insights.stateUndetermined ? "\u72B6\u6001\u672A\u5B9A\uFF0C\u672A\u751F\u6210\u5047\u8BBE\uFF1B\u76F8\u5173\u672A\u77E5\u5DF2\u8F6C\u5165\u73B0\u573A\u5FC5\u95EE" : insights.found ? "\u62A5\u544A\u4E2D\u672A\u8BC6\u522B\u51FA\u5047\u8BBE" : "\u62A5\u544A\u672A\u6355\u83B7" : running ? "\u72B6\u6001\u5224\u5B9A\u540E\u751F\u6210" : "\u5C3D\u8C03\u5F00\u59CB\u540E\u663E\u793A" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ol", { className: "qccPwHypos", children: insights.hypotheses.map((h) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
|
|
1318
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwPri", "data-p": h.priority, children: h.priority }),
|
|
1319
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("b", { children: h.id }),
|
|
1320
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: h.text })
|
|
1131
1321
|
] }, h.id)) })
|
|
1132
1322
|
] })
|
|
1133
1323
|
] });
|
|
@@ -1140,49 +1330,49 @@ function RiskPanel(props) {
|
|
|
1140
1330
|
const dims = riskDimensions(props.events);
|
|
1141
1331
|
const real = (level) => insights.risks.filter((r) => r.level === level && !/^(无|—|-|暂无|本次.*未发现)/.test(r.text));
|
|
1142
1332
|
const judged = insights.sections.includes("\u7EA2\u7EBF\u63D0\u793A");
|
|
1143
|
-
return /* @__PURE__ */ (0,
|
|
1144
|
-
/* @__PURE__ */ (0,
|
|
1145
|
-
/* @__PURE__ */ (0,
|
|
1146
|
-
/* @__PURE__ */ (0,
|
|
1147
|
-
/* @__PURE__ */ (0,
|
|
1148
|
-
!judged ? /* @__PURE__ */ (0,
|
|
1333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(StagePanel, { eyebrow: "RISK", title: "\u98CE\u9669\u6838\u67E5", task: props.task, children: [
|
|
1334
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Steps, { steps }),
|
|
1335
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Dimensions, { title: "\u5DF2\u6838\u67E5", items: dims, empty: running ? "\u7B49\u5F85\u98CE\u9669\u626B\u63CF\u2026" : "\u5C3D\u8C03\u5F00\u59CB\u540E\u663E\u793A\u6838\u67E5\u7684\u7EF4\u5EA6" }),
|
|
1336
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCard", children: [
|
|
1337
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "qccPwCardHeader", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: "\u98CE\u9669\u5206\u7EA7" }) }) }),
|
|
1338
|
+
!judged ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwEmpty", children: running ? "\u626B\u63CF\u4E0E\u4E0B\u94BB\u540E\u7ED9\u51FA\u5206\u7EA7" : finished ? "\u62A5\u544A\u672A\u6355\u83B7" : "\u5C3D\u8C03\u5F00\u59CB\u540E\u663E\u793A" }) : insights.riskNoRecord && insights.risks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwNote", children: "\u4F01\u4E1A\u81EA\u8EAB\u98CE\u9669\u626B\u63CF\u672A\u53D1\u73B0\u516C\u5F00\u8BB0\u5F55\uFF1B\u8FD9\u4E0D\u7B49\u4E8E\u4E0D\u5B58\u5728\u5176\u4ED6\u98CE\u9669\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "qccPwRiskTiles", children: ["\u7EA2\u7EBF", "\u5173\u6CE8", "\u4FE1\u606F"].map((level) => {
|
|
1149
1339
|
const items = real(level);
|
|
1150
|
-
return /* @__PURE__ */ (0,
|
|
1151
|
-
/* @__PURE__ */ (0,
|
|
1152
|
-
/* @__PURE__ */ (0,
|
|
1153
|
-
/* @__PURE__ */ (0,
|
|
1340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwRiskTile", "data-level": level, "data-empty": items.length === 0, children: [
|
|
1341
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwRiskTileTop", children: [
|
|
1342
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("b", { children: level }),
|
|
1343
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: items.length })
|
|
1154
1344
|
] }),
|
|
1155
|
-
/* @__PURE__ */ (0,
|
|
1345
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: items[0]?.text ?? "\u672C\u6B21\u672A\u53D1\u73B0" })
|
|
1156
1346
|
] }, level);
|
|
1157
1347
|
}) })
|
|
1158
1348
|
] })
|
|
1159
1349
|
] });
|
|
1160
1350
|
}
|
|
1161
1351
|
function ReportViewer(props) {
|
|
1162
|
-
const ref = (0,
|
|
1352
|
+
const ref = (0, import_react4.useRef)(null);
|
|
1163
1353
|
const fit = () => {
|
|
1164
1354
|
const el = ref.current;
|
|
1165
1355
|
const h = el?.contentDocument?.documentElement?.scrollHeight;
|
|
1166
1356
|
if (el !== null && h !== void 0 && h > 0) el.style.height = `${h + 8}px`;
|
|
1167
1357
|
};
|
|
1168
|
-
(0,
|
|
1358
|
+
(0, import_react4.useEffect)(() => {
|
|
1169
1359
|
fit();
|
|
1170
1360
|
}, [props.html]);
|
|
1171
1361
|
const embedded = props.html.replace("</head>", "<style>body{background:#fff}.sheet{margin:0;border:0;border-radius:0;box-shadow:none}.hero{padding:18px 20px 16px}.body{padding:6px 20px 20px}</style></head>");
|
|
1172
|
-
return /* @__PURE__ */ (0,
|
|
1362
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("iframe", { ref, className: "qccPwReportFrame", title: "\u5C3D\u8C03\u62A5\u544A", sandbox: "allow-same-origin", srcDoc: embedded, onLoad: fit });
|
|
1173
1363
|
}
|
|
1174
1364
|
function DeliveryPanel(props) {
|
|
1175
1365
|
const ready = props.status === "ready";
|
|
1176
1366
|
if (props.reportHtml !== null) {
|
|
1177
|
-
return /* @__PURE__ */ (0,
|
|
1178
|
-
/* @__PURE__ */ (0,
|
|
1179
|
-
/* @__PURE__ */ (0,
|
|
1180
|
-
/* @__PURE__ */ (0,
|
|
1181
|
-
/* @__PURE__ */ (0,
|
|
1367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "qccPwPanel", children: [
|
|
1368
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "qccPwPageHeading", children: [
|
|
1369
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1370
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwEyebrow", children: "REPORT" }),
|
|
1371
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: "\u5C3D\u8C03\u62A5\u544A" })
|
|
1182
1372
|
] }),
|
|
1183
|
-
props.task === void 0 ? null : /* @__PURE__ */ (0,
|
|
1373
|
+
props.task === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwTaskId", children: props.task.id })
|
|
1184
1374
|
] }),
|
|
1185
|
-
/* @__PURE__ */ (0,
|
|
1375
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "qccPwCard qccPwReportCard", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ReportViewer, { html: props.reportHtml }) })
|
|
1186
1376
|
] });
|
|
1187
1377
|
}
|
|
1188
1378
|
const deliverables = [
|
|
@@ -1195,46 +1385,46 @@ function DeliveryPanel(props) {
|
|
|
1195
1385
|
["\u2466", "\u89E6\u8FBE\u5F00\u573A", "\u6765\u6E90\u3001\u5F52\u5C5E\u3001\u7528\u9014\u4E0E\u5F00\u573A\u767D"],
|
|
1196
1386
|
["\u2467", "\u8986\u76D6\u8BF4\u660E", "\u5DF2\u67E5\u3001\u672A\u67E5\u3001\u5931\u8D25\u4E0E\u8BC1\u636E\u5C42\u7EA7"]
|
|
1197
1387
|
];
|
|
1198
|
-
return /* @__PURE__ */ (0,
|
|
1199
|
-
/* @__PURE__ */ (0,
|
|
1200
|
-
/* @__PURE__ */ (0,
|
|
1201
|
-
/* @__PURE__ */ (0,
|
|
1202
|
-
/* @__PURE__ */ (0,
|
|
1203
|
-
/* @__PURE__ */ (0,
|
|
1388
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "qccPwPanel", children: [
|
|
1389
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "qccPwPageHeading", children: [
|
|
1390
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1391
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwEyebrow", children: "REPORT" }),
|
|
1392
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: "\u5C3D\u8C03\u62A5\u544A" }),
|
|
1393
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "\u4E0D\u662F\u8D44\u6599\u5806\u780C\uFF0C\u53EA\u56DE\u7B54\u56DB\u4EF6\u4E8B\uFF1A\u53BB\u4E0D\u53BB\u3001\u89C1\u8C01\u3001\u804A\u4EC0\u4E48\u3001\u4EC0\u4E48\u4E0D\u80FD\u78B0\u3002" })
|
|
1204
1394
|
] }),
|
|
1205
|
-
props.task === void 0 ? null : /* @__PURE__ */ (0,
|
|
1395
|
+
props.task === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwTaskId", children: props.task.id })
|
|
1206
1396
|
] }),
|
|
1207
|
-
props.task === void 0 ? props.cardCaptured ? /* @__PURE__ */ (0,
|
|
1208
|
-
/* @__PURE__ */ (0,
|
|
1209
|
-
/* @__PURE__ */ (0,
|
|
1210
|
-
/* @__PURE__ */ (0,
|
|
1211
|
-
/* @__PURE__ */ (0,
|
|
1397
|
+
props.task === void 0 ? props.cardCaptured ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Feedback, { tone: "success", title: "\u62A5\u544A\u53EF\u4E0B\u8F7D", children: "\u5F53\u524D\u4F1A\u8BDD\u4E2D\u5DF2\u6709\u5C3D\u8C03\u62A5\u544A\uFF0C\u53EF\u76F4\u63A5\u4E0B\u8F7D\uFF1B\u65B0\u7684\u5C3D\u8C03\u5C06\u91CD\u65B0\u8BA1\u6570\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Feedback, { tone: "notice", title: "\u7B49\u5F85\u8BBE\u5B9A", children: "\u5B8C\u6210\u5C3D\u8C03\u8BBE\u5B9A\u540E\uFF0C\u62A5\u544A\u7ED3\u6784\u4E0E\u6267\u884C\u8FDB\u5EA6\u4F1A\u663E\u793A\u5728\u8FD9\u91CC\u3002" }) : ready ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Feedback, { tone: "success", title: "\u62A5\u544A\u5DF2\u751F\u6210", children: "\u6267\u884C\u5DF2\u7ED3\u675F\u3002\u53EF\u4E0B\u8F7D\u62A5\u544A\uFF0C\u6216\u56DE\u5230\u4F1A\u8BDD\u67E5\u770B\u5B8C\u6574\u5185\u5BB9\u4E0E\u4E8B\u5B9E\u5F15\u7528\u3002" }) : props.status === "failed" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Feedback, { tone: "error", title: "\u672C\u6B21\u5C3D\u8C03\u672A\u5B8C\u6574\u5B8C\u6210", children: "\u8BF7\u56DE\u5230\u4F1A\u8BDD\u67E5\u770B\u9519\u8BEF\uFF1B\u5DF2\u53D6\u5F97\u4E8B\u5B9E\u4ECD\u53EF\u4FDD\u7559\uFF0C\u5931\u8D25\u7EF4\u5EA6\u4E0D\u5F97\u5199\u6210\u96F6\u8BB0\u5F55\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Feedback, { tone: "notice", title: props.status === "running" ? "\u6B63\u5728\u751F\u6210\u62A5\u544A" : "\u7B49\u5F85\u5F00\u59CB", children: props.status === "running" && !props.cardCaptured ? "\u4F1A\u8BDD\u82E5\u505C\u5728\u5019\u9009\u4E3B\u4F53\u786E\u8BA4\uFF0C\u8BF7\u5148\u5728\u4F1A\u8BDD\u4E2D\u9009\u5B9A\u4F01\u4E1A\uFF1B\u62A5\u544A\u751F\u6210\u540E\u300C\u4E0B\u8F7D\u62A5\u544A\u300D\u624D\u53EF\u70B9\u3002" : "\u5B8C\u6210\u7ECF\u8425\u4E0E\u98CE\u9669\u4E24\u6761\u7EBF\u540E\uFF0C\u5C06\u81EA\u52A8\u5207\u6362\u5230\u672C\u9875\u3002" }),
|
|
1398
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCard", children: [
|
|
1399
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "qccPwCardHeader", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1400
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: "\u62A5\u544A\u7ED3\u6784" }),
|
|
1401
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "\u56FA\u5B9A\u516B\u6BB5\uFF0C\u53EF\u538B\u7F29\u6216\u5C55\u5F00\uFF1B\u4E8B\u5B9E\u3001\u63A8\u7406\u3001\u95EE\u9898\u548C\u8986\u76D6\u8FB9\u754C\u4E0D\u6DF7\u5199\u3002" })
|
|
1212
1402
|
] }) }),
|
|
1213
|
-
/* @__PURE__ */ (0,
|
|
1214
|
-
/* @__PURE__ */ (0,
|
|
1215
|
-
/* @__PURE__ */ (0,
|
|
1216
|
-
/* @__PURE__ */ (0,
|
|
1217
|
-
/* @__PURE__ */ (0,
|
|
1403
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "qccPwDeliverables", children: deliverables.map(([number, title, detail]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwDeliverable", children: [
|
|
1404
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: number }),
|
|
1405
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1406
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("b", { children: title }),
|
|
1407
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: detail })
|
|
1218
1408
|
] })
|
|
1219
1409
|
] }, number)) })
|
|
1220
1410
|
] }),
|
|
1221
|
-
/* @__PURE__ */ (0,
|
|
1222
|
-
/* @__PURE__ */ (0,
|
|
1223
|
-
/* @__PURE__ */ (0,
|
|
1224
|
-
/* @__PURE__ */ (0,
|
|
1411
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCard", children: [
|
|
1412
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "qccPwCardHeader", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1413
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: "\u6267\u884C\u8986\u76D6" }),
|
|
1414
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "\u8FD9\u662F\u5DE5\u4F5C\u53F0\u4ECE\u5F53\u524D Session \u8BFB\u53D6\u7684\u771F\u5B9E\u6267\u884C\u4E8B\u4EF6\uFF0C\u4E0D\u662F\u5B8C\u6574\u6027\u8BC4\u5206\u3002" })
|
|
1225
1415
|
] }) }),
|
|
1226
|
-
/* @__PURE__ */ (0,
|
|
1227
|
-
/* @__PURE__ */ (0,
|
|
1228
|
-
/* @__PURE__ */ (0,
|
|
1229
|
-
/* @__PURE__ */ (0,
|
|
1416
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwCoverage", children: [
|
|
1417
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwMetric", children: [
|
|
1418
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: props.toolCount }),
|
|
1419
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u5DF2\u8BC6\u522B\u5DE5\u5177\u8C03\u7528" })
|
|
1230
1420
|
] }),
|
|
1231
|
-
/* @__PURE__ */ (0,
|
|
1232
|
-
/* @__PURE__ */ (0,
|
|
1233
|
-
/* @__PURE__ */ (0,
|
|
1421
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwMetric", children: [
|
|
1422
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: props.failedToolCount }),
|
|
1423
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u5DE5\u5177\u9519\u8BEF" })
|
|
1234
1424
|
] }),
|
|
1235
|
-
/* @__PURE__ */ (0,
|
|
1236
|
-
/* @__PURE__ */ (0,
|
|
1237
|
-
/* @__PURE__ */ (0,
|
|
1425
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwMetric", children: [
|
|
1426
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: ready ? "4/4" : "\u2014" }),
|
|
1427
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u4E1A\u52A1\u9636\u6BB5" })
|
|
1238
1428
|
] })
|
|
1239
1429
|
] })
|
|
1240
1430
|
] })
|
|
@@ -1271,19 +1461,20 @@ function extractCardFromDom() {
|
|
|
1271
1461
|
}
|
|
1272
1462
|
function PrevisitWorkbenchTab(props) {
|
|
1273
1463
|
const sessionId = props.scope.sessionId;
|
|
1274
|
-
const shared = (0,
|
|
1464
|
+
const shared = (0, import_react4.useSyncExternalStore)(props.shared.subscribe, () => props.shared.get(sessionId));
|
|
1275
1465
|
const task = shared.task;
|
|
1276
1466
|
const setTask = (fn) => props.shared.update(sessionId, (s) => ({ ...s, task: fn(s.task) }));
|
|
1277
|
-
const [phase, setPhase] = (0,
|
|
1278
|
-
const [runtime, setRuntime] = (0,
|
|
1279
|
-
const [completedTaskId, setCompletedTaskId] = (0,
|
|
1280
|
-
const [cardText, setCardText] = (0,
|
|
1281
|
-
const [downloadNote, setDownloadNote] = (0,
|
|
1282
|
-
(
|
|
1467
|
+
const [phase, setPhase] = (0, import_react4.useState)("prepare");
|
|
1468
|
+
const [runtime, setRuntime] = (0, import_react4.useState)(EMPTY_RUNTIME);
|
|
1469
|
+
const [completedTaskId, setCompletedTaskId] = (0, import_react4.useState)();
|
|
1470
|
+
const [cardText, setCardText] = (0, import_react4.useState)(null);
|
|
1471
|
+
const [downloadNote, setDownloadNote] = (0, import_react4.useState)();
|
|
1472
|
+
useWorkbenchReveal(props.reveal, props);
|
|
1473
|
+
(0, import_react4.useInsertionEffect)(() => {
|
|
1283
1474
|
if (!props.visible) return;
|
|
1284
1475
|
return installStyles();
|
|
1285
1476
|
}, [props.visible]);
|
|
1286
|
-
(0,
|
|
1477
|
+
(0, import_react4.useEffect)(() => {
|
|
1287
1478
|
const face = props.ctx.sessions.binding?.(sessionId)?.session;
|
|
1288
1479
|
if (face === void 0) {
|
|
1289
1480
|
return;
|
|
@@ -1325,14 +1516,14 @@ function PrevisitWorkbenchTab(props) {
|
|
|
1325
1516
|
};
|
|
1326
1517
|
const status = deriveWorkbenchStatus(progressInput);
|
|
1327
1518
|
const phaseStates = derivePhaseStates(progressInput);
|
|
1328
|
-
const insights = (0,
|
|
1329
|
-
const reportHtml = (0,
|
|
1519
|
+
const insights = (0, import_react4.useMemo)(() => parseCardInsights(cardText), [cardText]);
|
|
1520
|
+
const reportHtml = (0, import_react4.useMemo)(() => {
|
|
1330
1521
|
if (cardText !== null) return buildPrevisitReportHtml(cardText);
|
|
1331
1522
|
if (status !== "ready" && task === void 0) return null;
|
|
1332
1523
|
const dom = extractCardFromDom();
|
|
1333
1524
|
return dom === null ? null : buildPrevisitReportFromRenderedHtml(dom.html, dom.text);
|
|
1334
1525
|
}, [cardText, status, phase, runtime.toolEvents.length]);
|
|
1335
|
-
(0,
|
|
1526
|
+
(0, import_react4.useEffect)(() => {
|
|
1336
1527
|
if (status !== "ready" && status !== "failed" || task === void 0 || completedTaskId === task.id) {
|
|
1337
1528
|
return;
|
|
1338
1529
|
}
|
|
@@ -1374,53 +1565,53 @@ function PrevisitWorkbenchTab(props) {
|
|
|
1374
1565
|
a.remove();
|
|
1375
1566
|
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
1376
1567
|
};
|
|
1377
|
-
if (!props.visible) return /* @__PURE__ */ (0,
|
|
1378
|
-
return /* @__PURE__ */ (0,
|
|
1379
|
-
/* @__PURE__ */ (0,
|
|
1380
|
-
/* @__PURE__ */ (0,
|
|
1381
|
-
/* @__PURE__ */ (0,
|
|
1382
|
-
/* @__PURE__ */ (0,
|
|
1383
|
-
/* @__PURE__ */ (0,
|
|
1384
|
-
/* @__PURE__ */ (0,
|
|
1385
|
-
/* @__PURE__ */ (0,
|
|
1568
|
+
if (!props.visible) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {});
|
|
1569
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "qccPwShell", "aria-label": "\u8BBF\u524D\u5C3D\u8C03\u5DE5\u4F5C\u53F0", "data-status": status, children: [
|
|
1570
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "qccPwHeader", children: [
|
|
1571
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwBrand", children: [
|
|
1572
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwBrandIcon", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { name: "briefcase" }) }),
|
|
1573
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwBrandCopy", children: [
|
|
1574
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwTitleRow", children: [
|
|
1575
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { className: "qccPwTitle", children: "\u8BBF\u524D\u5C3D\u8C03\u5DE5\u4F5C\u53F0" }),
|
|
1576
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwLiveDot", "data-status": status })
|
|
1386
1577
|
] }),
|
|
1387
|
-
/* @__PURE__ */ (0,
|
|
1578
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwSubtitle", children: "\u4F01\u67E5\u67E5\u4E8B\u5B9E\u9A71\u52A8 \xB7 \u673A\u4F1A\u4E0E\u98CE\u9669\u53CC\u5F15\u64CE" })
|
|
1388
1579
|
] })
|
|
1389
1580
|
] }),
|
|
1390
|
-
/* @__PURE__ */ (0,
|
|
1391
|
-
/* @__PURE__ */ (0,
|
|
1392
|
-
/* @__PURE__ */ (0,
|
|
1581
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwMeta", children: [
|
|
1582
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwStatus", "data-status": status, children: STATUS_LABELS[status] }),
|
|
1583
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "qccPwSession", children: [
|
|
1393
1584
|
"\u5F53\u524D Session \xB7 ",
|
|
1394
1585
|
sessionId.slice(0, 12)
|
|
1395
1586
|
] })
|
|
1396
1587
|
] })
|
|
1397
1588
|
] }),
|
|
1398
|
-
/* @__PURE__ */ (0,
|
|
1589
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("nav", { className: "qccPwStages", "aria-label": "\u8BBF\u524D\u4EFB\u52A1\u9636\u6BB5", children: PREVISIT_PHASES.map((current) => {
|
|
1399
1590
|
const phaseState = phaseStates.find((item) => item.id === current);
|
|
1400
|
-
return /* @__PURE__ */ (0,
|
|
1401
|
-
/* @__PURE__ */ (0,
|
|
1402
|
-
/* @__PURE__ */ (0,
|
|
1403
|
-
/* @__PURE__ */ (0,
|
|
1404
|
-
/* @__PURE__ */ (0,
|
|
1591
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", className: "qccPwStage", "data-selected": phase === current, "data-progress": phaseState?.progress ?? "idle", onClick: () => setPhase(current), children: [
|
|
1592
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwStageIcon", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { name: current }) }),
|
|
1593
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "qccPwStageCopy", children: [
|
|
1594
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: PHASE_LABELS[current].label }),
|
|
1595
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: PHASE_LABELS[current].description })
|
|
1405
1596
|
] })
|
|
1406
1597
|
] }, current);
|
|
1407
1598
|
}) }),
|
|
1408
|
-
/* @__PURE__ */ (0,
|
|
1409
|
-
phase === "prepare" ? /* @__PURE__ */ (0,
|
|
1410
|
-
phase === "opportunity" ? /* @__PURE__ */ (0,
|
|
1411
|
-
phase === "risk" ? /* @__PURE__ */ (0,
|
|
1412
|
-
phase === "delivery" ? /* @__PURE__ */ (0,
|
|
1599
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwBody", children: [
|
|
1600
|
+
phase === "prepare" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SetupPanel, { sessionId, store: props.shared, task, start: (prompt) => props.startPrompt(sessionId, prompt), onStarted: () => setPhase("opportunity") }) : null,
|
|
1601
|
+
phase === "opportunity" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OpportunityPanel, { task, status, events: runtime.toolEvents, insights }) : null,
|
|
1602
|
+
phase === "risk" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RiskPanel, { task, status, events: runtime.toolEvents, insights }) : null,
|
|
1603
|
+
phase === "delivery" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DeliveryPanel, { task, status, toolCount: runtime.toolNames.length, failedToolCount: runtime.failedToolCount, cardCaptured: cardText !== null, reportHtml }) : null
|
|
1413
1604
|
] }),
|
|
1414
|
-
/* @__PURE__ */ (0,
|
|
1415
|
-
/* @__PURE__ */ (0,
|
|
1416
|
-
/* @__PURE__ */ (0,
|
|
1417
|
-
phase !== "prepare" && task !== void 0 ? /* @__PURE__ */ (0,
|
|
1418
|
-
phase === "delivery" ? /* @__PURE__ */ (0,
|
|
1605
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("footer", { className: "qccPwFooter", children: [
|
|
1606
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "qccPwFooterHint", "data-tone": downloadNote === void 0 ? void 0 : "error", children: downloadNote !== void 0 ? downloadNote : phase === "prepare" ? "" : "\u5DE5\u4F5C\u53F0\u7ED1\u5B9A\u5F53\u524D\u4F1A\u8BDD\uFF0C\u4F01\u4E1A\u4E8B\u5B9E\u4E0E\u5B8C\u6574\u62A5\u544A\u4FDD\u7559\u5728\u4F1A\u8BDD\u4E2D\u3002" }),
|
|
1607
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "qccPwFooterActions", children: [
|
|
1608
|
+
phase !== "prepare" && task !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "qccPwSecondary", onClick: newTask, children: "\u65B0\u7684\u5C3D\u8C03" }) : null,
|
|
1609
|
+
phase === "delivery" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", className: "qccPwPrimary", title: "\u4E0B\u8F7D\u4E3A HTML \u6587\u4EF6\uFF0C\u53EF\u76F4\u63A5\u6253\u5F00\u6216\u6253\u5370", onClick: downloadReport, children: [
|
|
1419
1610
|
"\u4E0B\u8F7D\u62A5\u544A",
|
|
1420
|
-
/* @__PURE__ */ (0,
|
|
1421
|
-
] }) : phase !== "prepare" ? /* @__PURE__ */ (0,
|
|
1611
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u2193" })
|
|
1612
|
+
] }) : phase !== "prepare" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", className: "qccPwPrimary", onClick: returnToConversation, children: [
|
|
1422
1613
|
"\u8FD4\u56DE\u4F1A\u8BDD",
|
|
1423
|
-
/* @__PURE__ */ (0,
|
|
1614
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u2192" })
|
|
1424
1615
|
] }) : null
|
|
1425
1616
|
] })
|
|
1426
1617
|
] })
|
|
@@ -1440,6 +1631,7 @@ function installStyles() {
|
|
|
1440
1631
|
function apply(ctx) {
|
|
1441
1632
|
const service = ctx.betterSidebar;
|
|
1442
1633
|
const shared = createPrevisitStore();
|
|
1634
|
+
const reveal = createRevealController();
|
|
1443
1635
|
const startPrompt = async (sessionId, prompt) => {
|
|
1444
1636
|
const conversation = ctx.sessions.scope?.(sessionId)?.get("conversation");
|
|
1445
1637
|
if (conversation === void 0) throw new Error("conversation unavailable");
|
|
@@ -1448,9 +1640,10 @@ function apply(ctx) {
|
|
|
1448
1640
|
return baseline;
|
|
1449
1641
|
};
|
|
1450
1642
|
ctx.effect(
|
|
1451
|
-
() => registerWorkbenchTab(service, (props) => /* @__PURE__ */ (0,
|
|
1452
|
-
"dsh-pre-duediligence:
|
|
1643
|
+
() => registerWorkbenchTab(service, (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PrevisitWorkbenchTab, { ...props, ctx, shared, reveal, startPrompt })),
|
|
1644
|
+
"dsh-pre-duediligence: hidden workbench tab"
|
|
1453
1645
|
);
|
|
1646
|
+
registerLeftSidebarLauncher(ctx, service, reveal);
|
|
1454
1647
|
}
|
|
1455
1648
|
|
|
1456
1649
|
return module.exports;
|
package/lib/index.js
CHANGED
package/lib/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/skill-file.ts"],
|
|
4
|
-
"sourcesContent": ["import { readFileSync } from \"node:fs\"\nimport { fileURLToPath } from \"node:url\"\n\nimport { parseSkillFile } from \"./skill-file.js\"\n\nexport const inject = [\"skills\"] as const\n\nexport const SKILL_NAME = \"qcc-previsit-onepager\"\nexport const SKILL_DESCRIPTION =\n \"\u8C03\u7528\u4F01\u67E5\u67E5\u4E94\u7C7B MCP \u6267\u884C\u4F01\u4E1A\u8BBF\u524D\u5C3D\u8C03\uFF0C\u4EE5\u673A\u4F1A\u4E0E\u98CE\u9669\u53CC\u5F15\u64CE\u8BC6\u522B\u7ECF\u8425\u72B6\u6001\u3001\u5EFA\u7ACB\u5E76\u53CD\u8BC1\u4E1A\u52A1\u5047\u8BBE\uFF0C\u4EA4\u4ED8\u53EF\u8FFD\u6EAF\u7684\u8BBF\u524D\u5C3D\u8C03\u62A5\u544A\u3002\"\n\ntype SkillRegistration = {\n name: string\n description: string\n whenToUse: string\n content: string\n source: \"bundled\"\n resourceBase: {\n kind: \"directory\"\n path: string\n }\n metadata: Readonly<Record<string, unknown>>\n}\n\nexport type HostContext = {\n skills: {\n register(skill: SkillRegistration): () => void\n }\n}\n\nexport function loadBundledSkill(): SkillRegistration {\n const skillDirectoryUrl = new URL(\"../skills/qcc-previsit-onepager/\", import.meta.url)\n const skillSource = readFileSync(new URL(\"SKILL.md\", skillDirectoryUrl), \"utf8\")\n const { content } = parseSkillFile(skillSource)\n\n return {\n name: SKILL_NAME,\n description: SKILL_DESCRIPTION,\n whenToUse: \"\u7528\u6237\u8981\u6C42\u51C6\u5907\u5BA2\u6237\u62DC\u8BBF\u3001\u8BBF\u524D\u5C3D\u8C03\u3001\u4E00\u9875\u7EB8\u7B80\u62A5\u3001\u6388\u4FE1\u9762\u8C08\u3001\u5546\u52A1\u8C08\u5224\u3001\u7B7E\u7EA6\u6838\u67E5\u3001\u590D\u8BBF\u66F4\u65B0\u3001\u89E6\u8FBE\u8DEF\u5F84\u6216\u5F53\u9762\u63D0\u95EE\u6E05\u5355\u65F6\u4F7F\u7528\u3002\",\n content,\n source: \"bundled\",\n resourceBase: {\n kind: \"directory\",\n path: fileURLToPath(skillDirectoryUrl),\n },\n metadata: {\n author: \"QCC\",\n version: \"0.1.
|
|
4
|
+
"sourcesContent": ["import { readFileSync } from \"node:fs\"\nimport { fileURLToPath } from \"node:url\"\n\nimport { parseSkillFile } from \"./skill-file.js\"\n\nexport const inject = [\"skills\"] as const\n\nexport const SKILL_NAME = \"qcc-previsit-onepager\"\nexport const SKILL_DESCRIPTION =\n \"\u8C03\u7528\u4F01\u67E5\u67E5\u4E94\u7C7B MCP \u6267\u884C\u4F01\u4E1A\u8BBF\u524D\u5C3D\u8C03\uFF0C\u4EE5\u673A\u4F1A\u4E0E\u98CE\u9669\u53CC\u5F15\u64CE\u8BC6\u522B\u7ECF\u8425\u72B6\u6001\u3001\u5EFA\u7ACB\u5E76\u53CD\u8BC1\u4E1A\u52A1\u5047\u8BBE\uFF0C\u4EA4\u4ED8\u53EF\u8FFD\u6EAF\u7684\u8BBF\u524D\u5C3D\u8C03\u62A5\u544A\u3002\"\n\ntype SkillRegistration = {\n name: string\n description: string\n whenToUse: string\n content: string\n source: \"bundled\"\n resourceBase: {\n kind: \"directory\"\n path: string\n }\n metadata: Readonly<Record<string, unknown>>\n}\n\nexport type HostContext = {\n skills: {\n register(skill: SkillRegistration): () => void\n }\n}\n\nexport function loadBundledSkill(): SkillRegistration {\n const skillDirectoryUrl = new URL(\"../skills/qcc-previsit-onepager/\", import.meta.url)\n const skillSource = readFileSync(new URL(\"SKILL.md\", skillDirectoryUrl), \"utf8\")\n const { content } = parseSkillFile(skillSource)\n\n return {\n name: SKILL_NAME,\n description: SKILL_DESCRIPTION,\n whenToUse: \"\u7528\u6237\u8981\u6C42\u51C6\u5907\u5BA2\u6237\u62DC\u8BBF\u3001\u8BBF\u524D\u5C3D\u8C03\u3001\u4E00\u9875\u7EB8\u7B80\u62A5\u3001\u6388\u4FE1\u9762\u8C08\u3001\u5546\u52A1\u8C08\u5224\u3001\u7B7E\u7EA6\u6838\u67E5\u3001\u590D\u8BBF\u66F4\u65B0\u3001\u89E6\u8FBE\u8DEF\u5F84\u6216\u5F53\u9762\u63D0\u95EE\u6E05\u5355\u65F6\u4F7F\u7528\u3002\",\n content,\n source: \"bundled\",\n resourceBase: {\n kind: \"directory\",\n path: fileURLToPath(skillDirectoryUrl),\n },\n metadata: {\n author: \"QCC\",\n version: \"0.1.2\",\n industry: \"enterprise-services\",\n mcpServers: [\"qcc-company\", \"qcc-risk\", \"qcc-ipr\", \"qcc-operation\", \"qcc-executive\"],\n },\n }\n}\n\nexport function apply(ctx: HostContext): void {\n ctx.skills.register(loadBundledSkill())\n}\n", "export type ParsedSkillFile = {\n content: string\n frontmatter: string | null\n}\n\nexport function parseSkillFile(source: string): ParsedSkillFile {\n const normalized = source.replaceAll(\"\\r\\n\", \"\\n\")\n\n if (!normalized.startsWith(\"---\\n\")) {\n return { content: normalized.trim(), frontmatter: null }\n }\n\n const closingMarker = normalized.indexOf(\"\\n---\\n\", 4)\n\n if (closingMarker === -1) {\n throw new Error(\"SKILL.md \u7684 YAML frontmatter \u7F3A\u5C11\u7ED3\u675F\u6807\u8BB0\")\n }\n\n return {\n frontmatter: normalized.slice(4, closingMarker).trim(),\n content: normalized.slice(closingMarker + 5).trim(),\n }\n}\n"],
|
|
5
5
|
"mappings": ";AAAA,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;;;ACIvB,SAAS,eAAe,QAAiC;AAC9D,QAAM,aAAa,OAAO,WAAW,QAAQ,IAAI;AAEjD,MAAI,CAAC,WAAW,WAAW,OAAO,GAAG;AACnC,WAAO,EAAE,SAAS,WAAW,KAAK,GAAG,aAAa,KAAK;AAAA,EACzD;AAEA,QAAM,gBAAgB,WAAW,QAAQ,WAAW,CAAC;AAErD,MAAI,kBAAkB,IAAI;AACxB,UAAM,IAAI,MAAM,uEAAoC;AAAA,EACtD;AAEA,SAAO;AAAA,IACL,aAAa,WAAW,MAAM,GAAG,aAAa,EAAE,KAAK;AAAA,IACrD,SAAS,WAAW,MAAM,gBAAgB,CAAC,EAAE,KAAK;AAAA,EACpD;AACF;;;ADjBO,IAAM,SAAS,CAAC,QAAQ;AAExB,IAAM,aAAa;AACnB,IAAM,oBACX;AAqBK,SAAS,mBAAsC;AACpD,QAAM,oBAAoB,IAAI,IAAI,oCAAoC,YAAY,GAAG;AACrF,QAAM,cAAc,aAAa,IAAI,IAAI,YAAY,iBAAiB,GAAG,MAAM;AAC/E,QAAM,EAAE,QAAQ,IAAI,eAAe,WAAW;AAE9C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,aAAa;AAAA,IACb,WAAW;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,IACR,cAAc;AAAA,MACZ,MAAM;AAAA,MACN,MAAM,cAAc,iBAAiB;AAAA,IACvC;AAAA,IACA,UAAU;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU;AAAA,MACV,YAAY,CAAC,eAAe,YAAY,WAAW,iBAAiB,eAAe;AAAA,IACrF;AAAA,EACF;AACF;AAEO,SAAS,MAAM,KAAwB;AAC5C,MAAI,OAAO,SAAS,iBAAiB,CAAC;AACxC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type BetterSidebarService, type RevealController } from "./better-sidebar.js";
|
|
2
|
+
type SnapshotStore<T> = {
|
|
3
|
+
getSnapshot(): T;
|
|
4
|
+
};
|
|
5
|
+
type WorkspaceSnapshot = {
|
|
6
|
+
items?: Array<{
|
|
7
|
+
workspaceId: string;
|
|
8
|
+
sessionIds?: string[];
|
|
9
|
+
}>;
|
|
10
|
+
recentWorkspaceId?: string;
|
|
11
|
+
};
|
|
12
|
+
type SlotsService = {
|
|
13
|
+
inject(name: string, setup: () => void | (() => void)): unknown;
|
|
14
|
+
register(descriptor: {
|
|
15
|
+
name: string;
|
|
16
|
+
id: string;
|
|
17
|
+
order?: number;
|
|
18
|
+
inject?: () => Record<string, unknown>;
|
|
19
|
+
}, component: (props: LeftSidebarEntryProps) => JSX.Element): () => void;
|
|
20
|
+
};
|
|
21
|
+
export type LeftSidebarHost = {
|
|
22
|
+
slots: SlotsService;
|
|
23
|
+
sessions: {
|
|
24
|
+
list?: SnapshotStore<{
|
|
25
|
+
current?: string;
|
|
26
|
+
}>;
|
|
27
|
+
create?(options: {
|
|
28
|
+
workspaceId: string;
|
|
29
|
+
sessionId: string;
|
|
30
|
+
}): Promise<string>;
|
|
31
|
+
open?(sessionId: string): void;
|
|
32
|
+
};
|
|
33
|
+
workspaces?: {
|
|
34
|
+
list?: SnapshotStore<WorkspaceSnapshot>;
|
|
35
|
+
connectWorkspace?(workspaceId: string): Promise<string>;
|
|
36
|
+
};
|
|
37
|
+
get?(name: string): unknown;
|
|
38
|
+
};
|
|
39
|
+
type LeftSidebarEntryProps = {
|
|
40
|
+
wide?: boolean;
|
|
41
|
+
openAgent?: () => Promise<void>;
|
|
42
|
+
};
|
|
43
|
+
export declare function registerLeftSidebarLauncher(ctx: LeftSidebarHost, service: BetterSidebarService, reveal: RevealController): void;
|
|
44
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type BetterSidebarService } from "./better-sidebar.js";
|
|
2
|
-
|
|
2
|
+
import { type LeftSidebarHost } from "./left-sidebar.js";
|
|
3
|
+
export declare const inject: readonly ["slots", "sessions", "workspaces", "conversation", "betterSidebar"];
|
|
3
4
|
type SnapshotStore<T> = {
|
|
4
5
|
getSnapshot(): T;
|
|
5
6
|
subscribe?(listener: () => void): () => void;
|
|
@@ -30,7 +31,7 @@ type ConversationSnapshot = {
|
|
|
30
31
|
nodes?: ConversationNode[];
|
|
31
32
|
lastAgentError?: string | null;
|
|
32
33
|
};
|
|
33
|
-
type ClientContext = {
|
|
34
|
+
type ClientContext = LeftSidebarHost & {
|
|
34
35
|
sessions: {
|
|
35
36
|
binding?(sessionId: string): {
|
|
36
37
|
session: SnapshotStore<ConversationSnapshot>;
|
package/package.json
CHANGED