dsh-pre-duediligence 0.1.0

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/lib/client.js ADDED
@@ -0,0 +1,1458 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "dsh-pre-duediligence",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ "use strict";
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
24
+
25
+ // src/client.tsx
26
+ var client_exports = {};
27
+ __export(client_exports, {
28
+ apply: () => apply,
29
+ applySelection: () => applySelection,
30
+ composeFullSentence: () => composeFullSentence,
31
+ composeImperative: () => composeImperative,
32
+ createTaskId: () => createTaskId,
33
+ generateFromSelection: () => generateFromSelection,
34
+ inject: () => inject,
35
+ serializePrevisitRequest: () => serializePrevisitRequest,
36
+ updateManualText: () => updateManualText,
37
+ validateComposerText: () => validateComposerText
38
+ });
39
+ module.exports = __toCommonJS(client_exports);
40
+
41
+ // src/workbench-v2.tsx
42
+ var import_react3 = require("react");
43
+
44
+ // src/previsit-dock.tsx
45
+ var import_react = require("react");
46
+ var import_react_dom = require("react-dom");
47
+
48
+ // src/composer-model.ts
49
+ var COMPANY_PLACEHOLDER = "\uFF08\u8FD9\u91CC\u8F93\u5165\u4F01\u4E1A\u540D\uFF09";
50
+ var ROLE_OPTIONS = [
51
+ { id: "bank_rm", label: "\u94F6\u884C/\u4FE1\u8D37\u5BA2\u6237\u7ECF\u7406", phrase: "\u94F6\u884C\u5BF9\u516C\u5BA2\u6237\u7ECF\u7406" },
52
+ { id: "sales", label: "\u9500\u552E/BD", phrase: "\u9500\u552E" },
53
+ { id: "procure", label: "\u91C7\u8D2D/\u4F9B\u5E94\u94FE", phrase: "\u91C7\u8D2D\u8D1F\u8D23\u4EBA" },
54
+ { id: "invest", label: "\u6295\u8D44\u673A\u6784", phrase: "\u6295\u8D44\u673A\u6784\u4EBA\u5458" },
55
+ { id: "gov", label: "\u653F\u5E9C/\u56ED\u533A\u62DB\u5546", phrase: "\u56ED\u533A\u62DB\u5546\u4EBA\u5458" },
56
+ { id: "other", label: "\u5176\u4ED6", phrase: "\u51C6\u5907\u62DC\u8BBF\u4F01\u4E1A\u7684\u5546\u52A1\u4EBA\u5458" }
57
+ ];
58
+ var PURPOSE_OPTIONS = [
59
+ { id: "first", label: "\u9996\u6B21\u62DC\u8BBF", phrase: "\u9996\u6B21" },
60
+ { id: "nego", label: "\u8C08\u5224\u524D\u62DC\u8BBF", phrase: "\u5728\u5546\u52A1\u8C08\u5224\u524D" },
61
+ {
62
+ id: "revisit",
63
+ label: "\u590D\u8BBF",
64
+ phrase: "\u590D\u8BBF\u524D\u66F4\u65B0\u5F0F\u5730",
65
+ extraClause: "\u5982\u6709\u6B64\u524D\u5BF9\u8BE5\u4F01\u4E1A\u7684\u5C3D\u8C03\u8BB0\u5F55\uFF0C\u8BF7\u5BF9\u6BD4\u8BF4\u660E\u53D8\u5316\uFF1B\u82E5\u65E0\u8BB0\u5F55\uFF0C\u8BF7\u7167\u5E38\u5168\u91CF\u5C3D\u8C03\u5E76\u6CE8\u660E\u662F\u9996\u6B21\u3002"
66
+ }
67
+ ];
68
+ var FOCUS_OPTIONS = [
69
+ { id: "risk", label: "\u98CE\u9669\u4E0E\u6D89\u8BC9", phrase: "\u98CE\u9669\u4E0E\u6D89\u8BC9" },
70
+ { id: "equity", label: "\u80A1\u6743\u4E0E\u5B9E\u63A7\u4EBA", phrase: "\u80A1\u6743\u4E0E\u5B9E\u63A7\u4EBA" },
71
+ { id: "finance", label: "\u7ECF\u8425\u4E0E\u8D22\u52A1", phrase: "\u7ECF\u8425\u4E0E\u8D22\u52A1" },
72
+ { id: "contact", label: "\u8054\u7CFB\u4EBA\u4E0E\u89E6\u8FBE", phrase: "\u8054\u7CFB\u4EBA\u4E0E\u89E6\u8FBE\u8DEF\u5F84" },
73
+ { id: "ipr", label: "\u77E5\u8BC6\u4EA7\u6743", phrase: "\u77E5\u8BC6\u4EA7\u6743" },
74
+ { id: "bidding", label: "\u62DB\u6295\u6807\u4E1A\u7EE9", phrase: "\u62DB\u6295\u6807\u4E1A\u7EE9" }
75
+ ];
76
+ var BUDGET_OPTIONS = [
77
+ { id: "fast", label: "3\u5206\u949F\u901F\u89C8", phrase: "\u901F\u89C8" },
78
+ { id: "standard", label: "15\u5206\u949F\u6807\u51C6", phrase: "\u6807\u51C6" },
79
+ { id: "deep", label: "\u6DF1\u5EA6\u5C3D\u8C03", phrase: "\u6DF1\u5EA6" }
80
+ ];
81
+ var OUTPUT_OPTIONS = [
82
+ { id: "onepager", label: "\u4E00\u9875\u7EB8\u7B80\u62A5", phrase: "\u4E00\u9875\u7EB8\u7B80\u62A5" },
83
+ { id: "questions", label: "\u63D0\u95EE\u6E05\u5355\u4E3A\u4E3B", phrase: "\u4EE5\u5F53\u9762\u63D0\u95EE\u6E05\u5355\u4E3A\u4E3B\u7684\u7B80\u62A5" },
84
+ { id: "full", label: "\u5B8C\u6574\u62A5\u544A", phrase: "\u5B8C\u6574\u5C3D\u8C03\u62A5\u544A" },
85
+ { id: "share", label: "\u53EF\u8F6C\u53D1\u6458\u8981", phrase: "\u9002\u5408\u8F6C\u53D1\u7ED9\u540C\u4E8B\u7684\u7B80\u77ED\u6458\u8981" }
86
+ ];
87
+ var EMPTY_SELECTION = { focus: [] };
88
+ var EMPTY_COMPOSER_STATE = {
89
+ text: "",
90
+ lastGenerated: "",
91
+ lastCompany: "",
92
+ mode: "generated"
93
+ };
94
+ function optionById(options, id) {
95
+ return id === void 0 ? void 0 : options.find((option) => option.id === id);
96
+ }
97
+ function hasSelection(selection) {
98
+ return selection.role !== void 0 || selection.purpose !== void 0 || selection.focus.length > 0 || selection.budget !== void 0 || selection.output !== void 0;
99
+ }
100
+ function composeFullSentence(selection, company = "") {
101
+ if (!hasSelection(selection) && company.trim() === "") {
102
+ return "";
103
+ }
104
+ const role = optionById(ROLE_OPTIONS, selection.role);
105
+ const purpose = optionById(PURPOSE_OPTIONS, selection.purpose);
106
+ const budget = optionById(BUDGET_OPTIONS, selection.budget);
107
+ const output = optionById(OUTPUT_OPTIONS, selection.output);
108
+ const focus = selection.focus.map((id) => optionById(FOCUS_OPTIONS, id)?.phrase).filter((phrase) => phrase !== void 0);
109
+ const target = company.trim() || COMPANY_PLACEHOLDER;
110
+ const firstClause = (role === void 0 ? "" : "\u6211\u662F" + role.phrase + "\uFF0C") + "\u51C6\u5907" + (purpose?.phrase ?? "") + "\u62DC\u8BBF" + target;
111
+ const clauses = [
112
+ firstClause,
113
+ focus.length === 0 ? void 0 : "\u8BF7\u91CD\u70B9\u770B" + focus.join("\u3001"),
114
+ budget === void 0 ? void 0 : "\u505A\u4E00\u6B21" + budget.phrase + "\u5C3D\u8C03",
115
+ output === void 0 ? void 0 : "\u8F93\u51FA" + output.phrase
116
+ ].filter((clause) => clause !== void 0);
117
+ const extraClause = purpose?.extraClause;
118
+ return clauses.join("\uFF0C") + "\u3002" + (extraClause ?? "");
119
+ }
120
+ function composeImperative(selection) {
121
+ if (!hasSelection(selection)) {
122
+ return "";
123
+ }
124
+ const role = optionById(ROLE_OPTIONS, selection.role);
125
+ const purpose = optionById(PURPOSE_OPTIONS, selection.purpose);
126
+ const budget = optionById(BUDGET_OPTIONS, selection.budget);
127
+ const output = optionById(OUTPUT_OPTIONS, selection.output);
128
+ const focus = selection.focus.map((id) => optionById(FOCUS_OPTIONS, id)?.phrase).filter((phrase) => phrase !== void 0);
129
+ const clauses = [
130
+ role === void 0 ? void 0 : "\u6309" + role.phrase + "\u89C6\u89D2",
131
+ purpose === void 0 ? void 0 : purpose.phrase + "\u5F00\u5C55\u672C\u6B21\u62DC\u8BBF\u51C6\u5907",
132
+ focus.length === 0 ? void 0 : "\u91CD\u70B9\u770B" + focus.join("\u3001"),
133
+ budget === void 0 ? void 0 : "\u505A\u4E00\u6B21" + budget.phrase + "\u5C3D\u8C03",
134
+ output === void 0 ? void 0 : "\u8F93\u51FA" + output.phrase
135
+ ].filter((clause) => clause !== void 0);
136
+ return "\u8BF7" + clauses.join("\uFF0C") + "\u3002" + (purpose?.extraClause ?? "");
137
+ }
138
+ function capturePlaceholderCompany(lastGenerated, currentText) {
139
+ const placeholderAt = lastGenerated.indexOf(COMPANY_PLACEHOLDER);
140
+ if (placeholderAt < 0) {
141
+ return void 0;
142
+ }
143
+ const prefix = lastGenerated.slice(0, placeholderAt);
144
+ const suffix = lastGenerated.slice(placeholderAt + COMPANY_PLACEHOLDER.length);
145
+ if (!currentText.startsWith(prefix) || !currentText.endsWith(suffix)) {
146
+ return void 0;
147
+ }
148
+ const captured = currentText.slice(prefix.length, currentText.length - suffix.length).trim();
149
+ return captured === "" || captured === COMPANY_PLACEHOLDER ? void 0 : captured;
150
+ }
151
+ function updateManualText(state, text) {
152
+ if (text === state.lastGenerated || text === "") {
153
+ return { ...state, text, mode: "generated" };
154
+ }
155
+ const captured = capturePlaceholderCompany(state.lastGenerated, text);
156
+ if (captured !== void 0) {
157
+ return { ...state, text, lastCompany: captured, mode: "generated" };
158
+ }
159
+ if (state.lastGenerated !== "" && text.startsWith(state.lastGenerated)) {
160
+ return { ...state, text, mode: "generated" };
161
+ }
162
+ return { ...state, text, mode: "manual" };
163
+ }
164
+ function applySelection(state, selection, companyOverride) {
165
+ if (state.mode === "manual") {
166
+ return state;
167
+ }
168
+ const captured = capturePlaceholderCompany(state.lastGenerated, state.text);
169
+ const company = companyOverride !== void 0 && companyOverride.trim() !== "" ? companyOverride.trim() : captured ?? state.lastCompany;
170
+ const tail = state.lastGenerated !== "" && state.text.startsWith(state.lastGenerated) ? state.text.slice(state.lastGenerated.length) : "";
171
+ const generated = composeFullSentence(selection, company);
172
+ return {
173
+ text: generated + tail,
174
+ lastGenerated: generated,
175
+ lastCompany: company,
176
+ mode: "generated"
177
+ };
178
+ }
179
+ function generateFromSelection(state, selection) {
180
+ if (state.mode !== "manual") {
181
+ return applySelection(state, selection);
182
+ }
183
+ const imperative = composeImperative(selection);
184
+ if (imperative === "") {
185
+ return state;
186
+ }
187
+ const separator = state.text.trim() === "" || state.text.endsWith("\n") ? "" : "\n";
188
+ return {
189
+ ...state,
190
+ text: state.text + separator + imperative,
191
+ mode: "manual"
192
+ };
193
+ }
194
+ function validateComposerText(text) {
195
+ const normalized = text.trim();
196
+ if (normalized === "") {
197
+ return "\u8BF7\u8BF4\u660E\u8981\u62DC\u8BBF\u7684\u4F01\u4E1A";
198
+ }
199
+ if (normalized.includes(COMPANY_PLACEHOLDER)) {
200
+ return "\u8BF7\u5C06\u5360\u4F4D\u7B26\u66FF\u6362\u4E3A\u4F01\u4E1A\u5B8C\u6574\u6CE8\u518C\u540D\u79F0\u3001\u7B80\u79F0\u6216\u7EDF\u4E00\u793E\u4F1A\u4FE1\u7528\u4EE3\u7801";
201
+ }
202
+ return void 0;
203
+ }
204
+ function createTaskId(now = /* @__PURE__ */ new Date(), randomValue = Math.random()) {
205
+ const date = now.toISOString().slice(0, 10).replaceAll("-", "");
206
+ const suffix = Math.floor(randomValue * 1048576).toString(36).padStart(4, "0").slice(0, 4).toUpperCase();
207
+ return "PV-" + date + "-" + suffix;
208
+ }
209
+ function serializePrevisitRequest(text, taskId) {
210
+ return [
211
+ text.trim(),
212
+ "",
213
+ "\u8BBF\u524D\u4EFB\u52A1 ID\uFF1A" + taskId,
214
+ "\u8BF7\u4F7F\u7528 qcc-previsit-onepager Skill \u6267\u884C\uFF0C\u5E76\u5728\u5B8C\u6210\u62A5\u544A\u540E\u56DE\u5199\u4EFB\u52A1\u5B8C\u6210\u6807\u8BB0\u3002"
215
+ ].join("\n");
216
+ }
217
+
218
+ // src/previsit-store.ts
219
+ var EMPTY_SESSION_STATE = {
220
+ selection: EMPTY_SELECTION,
221
+ company: "",
222
+ composer: EMPTY_COMPOSER_STATE,
223
+ task: void 0,
224
+ panel: null
225
+ };
226
+ function createPrevisitStore() {
227
+ const states = /* @__PURE__ */ new Map();
228
+ const listeners = /* @__PURE__ */ new Set();
229
+ return {
230
+ get(sessionId) {
231
+ return states.get(sessionId) ?? EMPTY_SESSION_STATE;
232
+ },
233
+ update(sessionId, fn) {
234
+ const next = fn(states.get(sessionId) ?? EMPTY_SESSION_STATE);
235
+ states.set(sessionId, next);
236
+ for (const listener of listeners) listener();
237
+ },
238
+ subscribe(listener) {
239
+ listeners.add(listener);
240
+ return () => {
241
+ listeners.delete(listener);
242
+ };
243
+ }
244
+ };
245
+ }
246
+ function summarizeSelection(state, labels) {
247
+ const s = state.selection;
248
+ const out = [];
249
+ if (state.company.trim() !== "") out.push(state.company.trim());
250
+ const role = s.role === void 0 ? void 0 : labels.role(s.role);
251
+ if (role !== void 0) out.push(role);
252
+ const purpose = s.purpose === void 0 ? void 0 : labels.purpose(s.purpose);
253
+ if (purpose !== void 0) out.push(purpose);
254
+ if (s.focus.length > 0) out.push("\u5173\u6CE8 " + s.focus.map(labels.focus).filter(Boolean).join("\u3001"));
255
+ const budget = s.budget === void 0 ? void 0 : labels.budget(s.budget);
256
+ if (budget !== void 0) out.push(budget);
257
+ const output = s.output === void 0 ? void 0 : labels.output(s.output);
258
+ if (output !== void 0) out.push(output);
259
+ return out;
260
+ }
261
+
262
+ // src/report-export.ts
263
+ function nodeText(node) {
264
+ if (typeof node.text === "string") return node.text;
265
+ if (typeof node.content === "string") return node.content;
266
+ if (node.message && typeof node.message.content === "string") return node.message.content;
267
+ if (Array.isArray(node.content)) {
268
+ return node.content.map((c) => typeof c === "string" ? c : c && typeof c.text === "string" ? c.text : "").join("");
269
+ }
270
+ if (Array.isArray(node.parts)) {
271
+ return node.parts.map((pt) => typeof pt === "string" ? pt : pt && typeof pt.text === "string" ? pt.text : "").join("");
272
+ }
273
+ return "";
274
+ }
275
+ var CARD_START = /^#{1,3}\s*(访前尽调报告|拜访作战卡)[^\n]*$|^#{1,3}\s*[①1]?\s*核心研判[^\n]*$/m;
276
+ var CARD_SHAPE = (text) => /核心研判/.test(text) && /现场必问|覆盖说明|覆盖度/.test(text);
277
+ var JUNK = /<system-reminder>|<available_skills>|<command-name>|<\/?antml/i;
278
+ var isTool = (node) => node.kind === "tool-result" || node.kind === "tool-call";
279
+ var isUserish = (node) => /user|human|system/i.test(`${node.role ?? ""} ${node.kind ?? ""}`);
280
+ function adoptTaskFromSnapshot(snapshot) {
281
+ const nodes = snapshot.nodes ?? [];
282
+ for (let idx = nodes.length - 1; idx >= 0; idx--) {
283
+ const node = nodes[idx];
284
+ if (node === void 0 || node.kind === "tool-result" || node.kind === "tool-call") continue;
285
+ const text = nodeText(node);
286
+ const m = /访前任务 ID[::]\s*(PV-[A-Z0-9-]+)/.exec(text);
287
+ if (m !== null && m[1] !== void 0) return { id: m[1], prompt: text.trim(), nodeBaseline: idx };
288
+ }
289
+ const firstTool = nodes.findIndex((n) => n.kind === "tool-result" && /mcp__(company|risk|ipr|operation|executive)|qcc/i.test(n.call?.name ?? ""));
290
+ if (firstTool !== -1) {
291
+ let prompt = "";
292
+ for (let idx = firstTool - 1; idx >= 0; idx--) {
293
+ const node = nodes[idx];
294
+ if (node === void 0 || node.kind === "tool-result" || node.kind === "tool-call") continue;
295
+ const t = nodeText(node).trim();
296
+ if (t !== "" && !/<system-reminder>/.test(t)) {
297
+ prompt = t;
298
+ break;
299
+ }
300
+ }
301
+ return { id: "\u4F1A\u8BDD\u5185\u53D1\u8D77", prompt, nodeBaseline: 0 };
302
+ }
303
+ return null;
304
+ }
305
+ function extractCardText(snapshot, baseline) {
306
+ const nodes = (snapshot.nodes ?? []).slice(baseline);
307
+ for (let idx = nodes.length - 1; idx >= 0; idx--) {
308
+ const node = nodes[idx];
309
+ if (node === void 0 || isTool(node) || isUserish(node)) continue;
310
+ const text = nodeText(node);
311
+ if (JUNK.test(text)) continue;
312
+ const m = CARD_START.exec(text);
313
+ if (m === null || m.index === void 0) continue;
314
+ let card = text.slice(m.index).trim();
315
+ for (let j = idx + 1; j < nodes.length; j++) {
316
+ const next = nodes[j];
317
+ if (next === void 0 || isTool(next) || isUserish(next)) break;
318
+ const t = nodeText(next).trim();
319
+ if (t === "" || JUNK.test(t) || !/^(#{2,4}\s|\||-\s|\d+\.\s|\*\*)/.test(t)) break;
320
+ card += "\n\n" + t;
321
+ }
322
+ if (CARD_SHAPE(card)) return card;
323
+ }
324
+ for (let idx = nodes.length - 1; idx >= 0; idx--) {
325
+ const node = nodes[idx];
326
+ if (node === void 0 || isTool(node) || isUserish(node)) continue;
327
+ const text = nodeText(node).trim();
328
+ if (text.length > 40 && !JUNK.test(text) && CARD_SHAPE(text)) return text;
329
+ }
330
+ return null;
331
+ }
332
+ var esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
333
+ var TIER_WORDS = { L1: "\u8D22\u62A5\u62AB\u9732", L2: "\u516C\u5F00\u8BB0\u5F55", L3: "\u5173\u8054\u5173\u7CFB", L4: "\u884C\u4E1A\u63A8\u65AD", L5: "\u73B0\u573A\u6838\u5B9E" };
334
+ function humanizeCell(text) {
335
+ const t = text.trim();
336
+ if (/^L[1-5](\s*[\//、]\s*L[1-5])*$/.test(t)) {
337
+ return t.split(/\s*[\//、]\s*/).map((x) => TIER_WORDS[x] ?? x).join(" / ");
338
+ }
339
+ if (t === "\u6765\u6E90\u5C42\u7EA7") return "\u6765\u6E90";
340
+ return text;
341
+ }
342
+ function stripFactIds(text) {
343
+ return text.replace(/\s*\[F-?\d{1,4}(?:\s*[\/、,,;;|]\s*F-?\d{1,4})*\]/g, "").replace(/[ \t]+([,。;:)])/g, "$1");
344
+ }
345
+ var PRIORITY_WORDS = { P0: "\u4F18\u5148", P1: "\u91CD\u8981", P2: "\u5907\u9009" };
346
+ function humanizeHypothesis(text) {
347
+ return text.replace(/^\s*H(\d+)\s*[·・::\-–]\s*(P[012])\s*[·・::\-–]\s*/, (_m, n, p) => `\u5047\u8BBE ${n}\uFF08${PRIORITY_WORDS[p] ?? p}\uFF09`).replace(/(?<![A-Za-z0-9])H(\d{1,2})(?![A-Za-z0-9])/g, "\u5047\u8BBE $1");
348
+ }
349
+ function inline(text) {
350
+ let html = esc(humanizeHypothesis(stripFactIds(text)));
351
+ html = html.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
352
+ return html;
353
+ }
354
+ var CIRCLED = { "\u2460": "1", "\u2461": "2", "\u2462": "3", "\u2463": "4", "\u2464": "5", "\u2465": "6", "\u2466": "7", "\u2467": "8", "\u2468": "9", "\u2469": "10" };
355
+ function normalizeHeading(text) {
356
+ return text.trim().replace(/^([①②③④⑤⑥⑦⑧⑨⑩])\s*/, (_m, c) => `${CIRCLED[c] ?? c}\u3001`).replace(/^(\d+)[..]\s*/, "$1\u3001");
357
+ }
358
+ function renderCardMarkdown(md) {
359
+ const lines = md.replace(/\r\n/g, "\n").split("\n");
360
+ const out = [];
361
+ let i = 0;
362
+ const flushList = (items, ordered) => {
363
+ if (!items.length) return;
364
+ const tag = ordered ? "ol" : "ul";
365
+ out.push(`<${tag}>${items.map((it) => `<li>${inline(it)}</li>`).join("")}</${tag}>`);
366
+ };
367
+ while (i < lines.length) {
368
+ const line = lines[i] ?? "";
369
+ const t = line.trim();
370
+ if (t === "") {
371
+ i++;
372
+ continue;
373
+ }
374
+ if (/^---+$/.test(t)) {
375
+ out.push("<hr/>");
376
+ i++;
377
+ continue;
378
+ }
379
+ const sep = lines[i + 1] ?? "";
380
+ if (t.startsWith("|") && /^\|[\s:|-]+\|?$/.test(sep.trim())) {
381
+ const header = t.split("|").slice(1, -1).map((c) => humanizeCell(c.trim()));
382
+ i += 2;
383
+ const rows = [];
384
+ while (i < lines.length && (lines[i] ?? "").trim().startsWith("|")) {
385
+ rows.push((lines[i] ?? "").trim().split("|").slice(1, -1).map((c) => humanizeCell(c.trim())));
386
+ i++;
387
+ }
388
+ const thead = `<thead><tr>${header.map((h2) => `<th>${inline(h2)}</th>`).join("")}</tr></thead>`;
389
+ const tbody = `<tbody>${rows.map((r) => `<tr>${r.map((c) => `<td>${inline(c)}</td>`).join("")}</tr>`).join("")}</tbody>`;
390
+ out.push(`<div class="tw"><table>${thead}${tbody}</table></div>`);
391
+ continue;
392
+ }
393
+ const h = /^(#{1,4})\s+(.*)$/.exec(t);
394
+ if (h) {
395
+ const level = (h[1] ?? "##").length;
396
+ out.push(`<h${level}>${inline(normalizeHeading(h[2] ?? ""))}</h${level}>`);
397
+ i++;
398
+ continue;
399
+ }
400
+ if (t.startsWith(">")) {
401
+ out.push(`<p class="note">${inline(t.replace(/^>\s?/, ""))}</p>`);
402
+ i++;
403
+ continue;
404
+ }
405
+ if (/^[-*]\s+/.test(t)) {
406
+ const items = [];
407
+ while (i < lines.length && /^\s*[-*]\s+/.test(lines[i] ?? "")) {
408
+ items.push((lines[i] ?? "").trim().replace(/^[-*]\s+/, ""));
409
+ i++;
410
+ }
411
+ flushList(items, false);
412
+ continue;
413
+ }
414
+ if (/^\d+\.\s+/.test(t)) {
415
+ const items = [];
416
+ while (i < lines.length && /^\s*\d+\.\s+/.test(lines[i] ?? "")) {
417
+ items.push((lines[i] ?? "").trim().replace(/^\d+\.\s+/, ""));
418
+ i++;
419
+ }
420
+ flushList(items, true);
421
+ continue;
422
+ }
423
+ out.push(`<p>${inline(t)}</p>`);
424
+ i++;
425
+ }
426
+ return out.join("\n");
427
+ }
428
+ var REPORT_CSS = `
429
+ :root{
430
+ --blue:#2563eb;--blue-dark:#1e40af;--ink:#0f172a;--body:#334155;--muted:#64748b;
431
+ --line:#e2e8f0;--line-blue:#dbeafe;--hero:#f8fbff;
432
+ --ok:#16a34a;--ok-bg:#f0fdf4;--warn:#d97706;--warn-bg:#fff7ed;--risk:#ef4444;--risk-bg:#fef2f2;
433
+ }
434
+ *{box-sizing:border-box}
435
+ body{margin:0;background:#f1f5f9;color:var(--body);
436
+ font:15px/1.75 -apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei","Noto Sans SC",sans-serif;
437
+ -webkit-font-smoothing:antialiased}
438
+ .sheet{max-width:860px;margin:24px auto;background:#fff;border:1px solid var(--line);border-radius:12px;overflow:hidden;
439
+ box-shadow:0 1px 2px rgba(15,23,42,.04),0 12px 32px -20px rgba(15,23,42,.25)}
440
+ .hero{background:var(--hero);border-bottom:1px solid var(--line-blue);padding:22px 26px 20px}
441
+ .hero .eyebrow{font-size:11px;font-weight:800;letter-spacing:.12em;color:var(--blue);margin:0 0 6px}
442
+ .hero h1{margin:0;color:var(--ink);font-size:22px;font-weight:900;line-height:1.4}
443
+ .hero .meta{margin:8px 0 0;color:var(--muted);font-size:12.5px;line-height:1.7}
444
+ .body{padding:8px 26px 26px}
445
+ /* \u5927\u6807\u9898\uFF1A\u84DD\u8272 + \u6807\u9898\u4E0B\u77ED\u6A2A\u7EBF\uFF1B\u5C0F\u6807\u9898\uFF1A\u6D45\u7070\u5E95 + \u5DE6\u4FA7\u84DD\u7AD6\u7EBF */
446
+ .body h2{position:relative;margin:26px 0 12px;padding:0 0 8px;color:var(--blue-dark);font-size:16px;font-weight:800;letter-spacing:.01em}
447
+ .body h2::after{content:"";position:absolute;left:0;bottom:0;width:32px;height:3px;border-radius:2px;background:var(--blue)}
448
+ .body h2:first-of-type{margin-top:10px}
449
+ .body h3{margin:16px 0 8px;padding:6px 10px;border-left:3px solid var(--blue);border-radius:0 4px 4px 0;background:#f5f7fa;color:var(--ink);font-size:13.5px;font-weight:800}
450
+ .body h4{margin:12px 0 4px;color:var(--ink);font-size:13px;font-weight:700}
451
+ .body h1{display:none}
452
+ .note{margin:-4px 0 10px;color:var(--muted);font-size:12px;line-height:1.7}
453
+ blockquote{margin:-4px 0 10px;padding:0;border:0;color:var(--muted);font-size:12px;line-height:1.7}
454
+ blockquote p{margin:0}
455
+ p{margin:6px 0}
456
+ strong{color:var(--ink)}
457
+ .fid{color:var(--blue);font:600 10px ui-monospace,monospace;margin-left:2px}
458
+ ul,ol{margin:6px 0;padding-left:20px}
459
+ li{margin:3px 0;line-height:1.7}
460
+ hr{border:0;border-top:1px solid var(--line);margin:16px 0}
461
+ .tw{overflow-x:auto;margin:8px 0}
462
+ table{border-collapse:collapse;width:100%;font-size:13px}
463
+ th,td{border:1px solid var(--line);padding:8px 11px;text-align:left;vertical-align:top;line-height:1.6;word-break:break-word}
464
+ th{background:#f8fafc;color:var(--muted);font-weight:700;font-size:12px;white-space:nowrap}
465
+ /* \u9996\u5217\u591A\u4E3A\u201C\u7B49\u7EA7/\u65E5\u671F/\u63A8\u8350\u7EA7\u201D\u8FD9\u7C7B\u77ED\u6807\u7B7E\uFF1A\u4E0D\u6362\u884C\u3001\u4E0D\u88AB\u6324\u6241\uFF1B\u957F\u6587\u672C\u5217\u81EA\u9002\u5E94 */
466
+ td:first-child,th:first-child{white-space:nowrap;width:1%}
467
+ td:nth-child(2){min-width:180px}
468
+ /* \u72B6\u6001\u8272\uFF1A\u51FA\u73B0\u7EA2\u7EBF/\u5173\u6CE8/\u786E\u8BA4\u7B49\u8BCD\u81EA\u52A8\u67D3\u8272\u7531\u5185\u5BB9\u51B3\u5B9A\uFF0C\u8FD9\u91CC\u7ED9\u51FA\u53EF\u7528\u7C7B */
469
+ .tag-ok{color:var(--ok);background:var(--ok-bg)}
470
+ .tag-warn{color:var(--warn);background:var(--warn-bg)}
471
+ .tag-risk{color:var(--risk);background:var(--risk-bg)}
472
+ footer{padding:14px 26px 20px;border-top:1px solid var(--line);color:var(--muted);font-size:11.5px;line-height:1.7}
473
+ @media print{body{background:#fff}.sheet{border:0;box-shadow:none;margin:0}}
474
+ `;
475
+ function deriveMeta(md, meta) {
476
+ const first = /^#?\s*(?:访前尽调报告|拜访作战卡)\s*·\s*([^\n锚]+)/m.exec(md);
477
+ const anchorLine = /锚定主体:([^\n]+?)(?:\s*生成时间|$)/m.exec(md);
478
+ const whenLine = /生成时间[::]\s*([0-9-]+)/.exec(md);
479
+ return {
480
+ company: meta?.company || (first?.[1]?.trim() ?? "\u8BBF\u524D\u5C3D\u8C03\u62A5\u544A"),
481
+ anchor: (anchorLine?.[1] ?? "").trim().replace(/[||·\s]+$/, ""),
482
+ when: meta?.generatedAt || (whenLine?.[1] ?? "")
483
+ };
484
+ }
485
+ function wrapPrevisitReport(bodyHtml, m) {
486
+ const heroMeta = [m.anchor, m.when ? `\u751F\u6210\u65F6\u95F4\uFF1A${m.when}` : ""].filter(Boolean).join("\u3000\xB7\u3000");
487
+ return `<!doctype html><html lang="zh"><head><meta charset="utf-8">
488
+ <meta name="viewport" content="width=device-width,initial-scale=1">
489
+ <title>\u8BBF\u524D\u5C3D\u8C03\u62A5\u544A \xB7 ${esc(m.company)}</title><style>${REPORT_CSS}</style></head>
490
+ <body><div class="sheet">
491
+ <div class="hero"><p class="eyebrow">\u8BBF\u524D\u5C3D\u8C03\u62A5\u544A</p><h1>${esc(m.company)}</h1>${heroMeta ? `<p class="meta">${esc(heroMeta)}</p>` : ""}</div>
492
+ <div class="body">${bodyHtml}</div>
493
+ <footer>\u6570\u636E\u6765\u6E90\uFF1A\u4F01\u67E5\u67E5\u3002\u5404\u7EF4\u5EA6\u65F6\u6548\u4E0D\u540C\uFF0C\u4E0D\u627F\u8BFA\u5B9E\u65F6\u3002\u672C\u62A5\u544A\u4E3A\u8BBF\u524D\u8F85\u52A9\u6750\u6599\uFF0C\u4E0D\u6784\u6210\u6388\u4FE1\u3001\u5408\u4F5C\u6216\u4EFB\u4F55\u5546\u4E1A\u51B3\u7B56\u4F9D\u636E\uFF0C\u4EE5\u5B98\u65B9\u516C\u793A\u4E3A\u51C6\u3002</footer>
494
+ </div></body></html>`;
495
+ }
496
+ function buildPrevisitReportHtml(cardMarkdown, meta) {
497
+ const m = deriveMeta(cardMarkdown, meta);
498
+ const body = cardMarkdown.replace(/^#\s*(?:访前尽调报告|拜访作战卡).*$/m, "").replace(/^锚定主体:.*$/m, "").trim();
499
+ return wrapPrevisitReport(renderCardMarkdown(body), m);
500
+ }
501
+ function buildPrevisitReportFromRenderedHtml(bodyHtml, plainText, meta) {
502
+ const m = deriveMeta(plainText, meta);
503
+ const body = humanizeHypothesis(stripFactIds(bodyHtml)).replace(/<(td|th)([^>]*)>\s*([^<]{1,20})\s*<\/\1>/g, (_m, tag, attrs, cell) => `<${tag}${attrs}>${esc(humanizeCell(cell))}</${tag}>`);
504
+ return wrapPrevisitReport(body, m);
505
+ }
506
+
507
+ // src/previsit-dock.tsx
508
+ var import_jsx_runtime = require("react/jsx-runtime");
509
+ function composerTextarea() {
510
+ if (typeof document === "undefined") return null;
511
+ const all = Array.from(document.querySelectorAll("textarea")).filter((t) => t.closest(".qccDock") === null && t.closest(".qccPwShell") === null && !t.disabled);
512
+ return all[all.length - 1] ?? null;
513
+ }
514
+ function writeDraft(actions, text) {
515
+ try {
516
+ actions?.setDraft(text);
517
+ } catch {
518
+ }
519
+ const apply2 = () => {
520
+ const ta = composerTextarea();
521
+ if (ta === null || ta.value === text) return;
522
+ const setter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set;
523
+ if (setter === void 0) return;
524
+ setter.call(ta, text);
525
+ ta.dispatchEvent(new Event("input", { bubbles: true }));
526
+ };
527
+ if (actions === void 0) {
528
+ apply2();
529
+ return;
530
+ }
531
+ if (typeof window !== "undefined") window.setTimeout(apply2, 30);
532
+ }
533
+ var labelOf = (options) => (id) => options.find((o) => o.id === id)?.label;
534
+ function Chips(props) {
535
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "qccDockChips", children: props.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "qccDockChip", "data-selected": props.selected.includes(option.id), onClick: () => props.onToggle(option.id), children: option.label }, option.id)) });
536
+ }
537
+ function usePrevisitComposer(args) {
538
+ const { sessionId, store } = args;
539
+ const state = (0, import_react.useSyncExternalStore)(store.subscribe, () => store.get(sessionId), () => EMPTY_SESSION_STATE);
540
+ const [error, setError] = (0, import_react.useState)();
541
+ const [submitting, setSubmitting] = (0, import_react.useState)(false);
542
+ const draft = args.readDraft();
543
+ const synced = updateManualText(state.composer, draft);
544
+ const manual = synced.mode === "manual" && draft.trim() !== "";
545
+ const write = (selection, company) => {
546
+ const base = { ...updateManualText(state.composer, args.readDraft()), lastCompany: company };
547
+ const next = applySelection(base, selection, company);
548
+ if (next.mode === "generated") args.writeDraft(next.text);
549
+ store.update(sessionId, (s) => ({ ...s, selection, company, composer: next }));
550
+ setError(void 0);
551
+ };
552
+ const toggleSingle = (key, id) => {
553
+ const next = { ...state.selection };
554
+ if (next[key] === id) delete next[key];
555
+ else next[key] = id;
556
+ write(next, state.company);
557
+ };
558
+ const toggleFocus = (id) => {
559
+ const focus = state.selection.focus.includes(id) ? state.selection.focus.filter((v) => v !== id) : [...state.selection.focus, id];
560
+ write({ ...state.selection, focus }, state.company);
561
+ };
562
+ const setCompany = (company) => write(state.selection, company);
563
+ const append = () => {
564
+ const next = generateFromSelection(updateManualText(state.composer, args.readDraft()), state.selection);
565
+ args.writeDraft(next.text);
566
+ store.update(sessionId, (s) => ({ ...s, composer: next }));
567
+ };
568
+ const reset = () => {
569
+ args.writeDraft("");
570
+ store.update(sessionId, (s) => ({ ...EMPTY_SESSION_STATE, task: s.task, panel: s.panel }));
571
+ setError(void 0);
572
+ };
573
+ const startTask = async () => {
574
+ const text = args.readDraft().trim();
575
+ const invalid = validateComposerText(text);
576
+ if (invalid !== void 0) {
577
+ setError(invalid);
578
+ return;
579
+ }
580
+ const id = createTaskId();
581
+ const prompt = serializePrevisitRequest(text, id);
582
+ setSubmitting(true);
583
+ setError(void 0);
584
+ try {
585
+ const nodeBaseline = await args.start(prompt);
586
+ store.update(sessionId, (s) => ({
587
+ ...s,
588
+ composer: { ...s.composer, text: "", lastGenerated: "", mode: "generated" },
589
+ task: { id, prompt, createdAt: (/* @__PURE__ */ new Date()).toISOString(), nodeBaseline, seenRunning: false, selection: s.selection }
590
+ }));
591
+ args.writeDraft("");
592
+ args.onStarted?.();
593
+ } catch {
594
+ setError("\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5F53\u524D\u4F1A\u8BDD\u540E\u91CD\u8BD5");
595
+ } finally {
596
+ setSubmitting(false);
597
+ }
598
+ };
599
+ const summary = summarizeSelection(state, {
600
+ role: labelOf(ROLE_OPTIONS),
601
+ purpose: labelOf(PURPOSE_OPTIONS),
602
+ focus: labelOf(FOCUS_OPTIONS),
603
+ budget: labelOf(BUDGET_OPTIONS),
604
+ output: labelOf(OUTPUT_OPTIONS)
605
+ });
606
+ return { state, manual, error, submitting, summary, toggleSingle, toggleFocus, setCompany, append, reset, startTask };
607
+ }
608
+ function PrevisitFields(props) {
609
+ const { actions: a } = props;
610
+ const st = a.state;
611
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "qccDockBody", children: [
612
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "qccDockRow", children: [
613
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "qccDockLabel", htmlFor: `${props.idPrefix}-company`, children: "\u8981\u89C1\u8C01" }),
614
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { id: `${props.idPrefix}-company`, className: "qccDockCompany", value: st.company, placeholder: "\u4F01\u4E1A\u5168\u79F0\u6216\u7EDF\u4E00\u793E\u4F1A\u4FE1\u7528\u4EE3\u7801", onChange: (e) => a.setCompany(e.target.value) })
615
+ ] }),
616
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "qccDockRow", children: [
617
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "qccDockLabel", children: "\u6211\u662F" }),
618
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Chips, { options: ROLE_OPTIONS, selected: st.selection.role === void 0 ? [] : [st.selection.role], onToggle: (id) => a.toggleSingle("role", id) })
619
+ ] }),
620
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "qccDockRow", children: [
621
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "qccDockLabel", children: "\u573A\u5408" }),
622
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Chips, { options: PURPOSE_OPTIONS, selected: st.selection.purpose === void 0 ? [] : [st.selection.purpose], onToggle: (id) => a.toggleSingle("purpose", id) })
623
+ ] }),
624
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "qccDockRow", children: [
625
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "qccDockLabel", children: "\u5173\u6CE8" }),
626
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Chips, { options: FOCUS_OPTIONS, selected: st.selection.focus, onToggle: a.toggleFocus })
627
+ ] }),
628
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "qccDockRow", children: [
629
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "qccDockLabel", children: "\u6DF1\u5EA6" }),
630
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Chips, { options: BUDGET_OPTIONS, selected: st.selection.budget === void 0 ? [] : [st.selection.budget], onToggle: (id) => a.toggleSingle("budget", id) })
631
+ ] }),
632
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "qccDockRow", children: [
633
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "qccDockLabel", children: "\u8F93\u51FA" }),
634
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Chips, { options: OUTPUT_OPTIONS, selected: st.selection.output === void 0 ? [] : [st.selection.output], onToggle: (id) => a.toggleSingle("output", id) })
635
+ ] }),
636
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "qccDockFoot", children: [
637
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "qccDockHint", "data-tone": a.error === void 0 ? void 0 : "error", children: a.error ?? (a.manual ? "\u8F93\u5165\u6846\u91CC\u6709\u4F60\u624B\u5199\u7684\u5185\u5BB9\uFF0C\u70B9\u9009\u4E0D\u4F1A\u8986\u76D6\uFF1B\u300C\u6309\u6761\u4EF6\u8865\u5145\u300D\u4F1A\u53E6\u8D77\u4E00\u53E5\u8FFD\u52A0" : "\u6761\u4EF6\u5B9E\u65F6\u5199\u8FDB\u8F93\u5165\u6846\uFF0C\u53EF\u4EE5\u76F4\u63A5\u6539\uFF1B\u6539\u597D\u540E\u70B9\u300C\u5F00\u59CB\u5C3D\u8C03\u300D") }),
638
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "qccDockActions", children: [
639
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "qccDockBtn", onClick: a.reset, children: "\u6E05\u7A7A" }),
640
+ a.manual ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "qccDockBtn", onClick: a.append, children: "\u6309\u6761\u4EF6\u8865\u5145" }) : null,
641
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "qccDockBtn qccDockPrimary", disabled: a.submitting, onClick: () => void a.startTask(), children: a.submitting ? "\u53D1\u9001\u4E2D\u2026" : props.startLabel ?? "\u5F00\u59CB\u5C3D\u8C03 \u2192" })
642
+ ] })
643
+ ] })
644
+ ] });
645
+ }
646
+
647
+ // src/better-sidebar.ts
648
+ var import_react2 = require("react");
649
+ var PREVISIT_WORKBENCH_TAB_ID = "dsh-pre-duediligence:agent";
650
+ var SUPPORTED_SIDEBAR_VERSION = /^0\.17\./u;
651
+ function assertBetterSidebar(service) {
652
+ if (!SUPPORTED_SIDEBAR_VERSION.test(service.version)) {
653
+ throw new Error("dsh-pre-duediligence requires dsh-better-sidebar 0.17.x");
654
+ }
655
+ if (!service.features.includes("targetedOpen") || !service.features.includes("stateSubscription")) {
656
+ throw new Error("dsh-better-sidebar is missing required targetedOpen/stateSubscription capabilities");
657
+ }
658
+ }
659
+ function registerWorkbenchTab(service, component) {
660
+ assertBetterSidebar(service);
661
+ return service.registerTab({
662
+ id: PREVISIT_WORKBENCH_TAB_ID,
663
+ title: "\u8BBF\u524D\u5C3D\u8C03\u667A\u80FD\u4F53",
664
+ order: 30,
665
+ single: true,
666
+ component
667
+ });
668
+ }
669
+
670
+ // src/workbench-state.ts
671
+ var PREVISIT_PHASES = ["prepare", "opportunity", "risk", "delivery"];
672
+ function hasTool(toolNames, fragments) {
673
+ return toolNames.some((name) => fragments.some((fragment) => name.includes(fragment)));
674
+ }
675
+ function isOpportunityTool(name) {
676
+ return [
677
+ "qcc-company",
678
+ "qcc-operation",
679
+ "qcc-ipr",
680
+ "get_company_",
681
+ "get_annual_reports",
682
+ "get_change_records",
683
+ "get_bidding_info",
684
+ "get_financing_records",
685
+ "get_patent_info",
686
+ "get_software_copyright_info"
687
+ ].some((fragment) => name.includes(fragment));
688
+ }
689
+ function isRiskTool(name) {
690
+ return [
691
+ "qcc-risk",
692
+ "qcc-executive",
693
+ "get_company_risk_scan",
694
+ "get_executive_risk_scan",
695
+ "get_dishonest_info",
696
+ "get_judgment_debtor_info",
697
+ "get_terminated_cases",
698
+ "get_equity_freeze",
699
+ "get_business_exception",
700
+ "get_administrative_penalty",
701
+ "get_tax_abnormal",
702
+ "get_judicial_documents"
703
+ ].some((fragment) => name.includes(fragment));
704
+ }
705
+ function deriveWorkbenchStatus(input) {
706
+ if (!input.hasTask) {
707
+ return "empty";
708
+ }
709
+ if (input.running) {
710
+ return "running";
711
+ }
712
+ if (!input.seenRunning) {
713
+ return "waiting-agent";
714
+ }
715
+ return input.lastAgentError === null ? "ready" : "failed";
716
+ }
717
+ function derivePhaseStates(input) {
718
+ const status = deriveWorkbenchStatus(input);
719
+ const opportunitySeen = input.toolNames.some(isOpportunityTool);
720
+ const riskSeen = input.toolNames.some(isRiskTool);
721
+ const entitySeen = hasTool(input.toolNames, ["get_company_by_query"]);
722
+ if (!input.hasTask) {
723
+ return PREVISIT_PHASES.map((id, index) => ({ id, progress: index === 0 ? "active" : "idle" }));
724
+ }
725
+ if (status === "ready") {
726
+ return PREVISIT_PHASES.map((id) => ({ id, progress: "done" }));
727
+ }
728
+ if (status === "failed") {
729
+ return [
730
+ { id: "prepare", progress: "done" },
731
+ { id: "opportunity", progress: opportunitySeen || entitySeen ? "done" : "failed" },
732
+ { id: "risk", progress: riskSeen ? "done" : "failed" },
733
+ { id: "delivery", progress: "failed" }
734
+ ];
735
+ }
736
+ return [
737
+ { id: "prepare", progress: "done" },
738
+ {
739
+ id: "opportunity",
740
+ progress: riskSeen ? "done" : opportunitySeen || entitySeen || input.running ? "active" : "idle"
741
+ },
742
+ {
743
+ id: "risk",
744
+ progress: input.partial && riskSeen ? "done" : riskSeen ? "active" : "idle"
745
+ },
746
+ {
747
+ id: "delivery",
748
+ progress: input.partial && riskSeen ? "active" : "idle"
749
+ }
750
+ ];
751
+ }
752
+
753
+ // src/workbench-style.ts
754
+ var WORKBENCH_CSS = String.raw`
755
+ .qccPwShell{--pw-brand:var(--dsw-alias-state-business-primary,#4176e6);--pw-brand-strong:var(--dsw-static-deepseek-600,#4868b2);--pw-brand-hover:var(--dsw-alias-button-info-hover,#679efe);--pw-surface:var(--dsw-alias-bg-layer-1,var(--background-primary,#fff));--pw-canvas:var(--dsw-alias-bg-layer-1,var(--background-primary,#fff));--pw-surface-muted:var(--dsw-alias-bg-module-platform,var(--background-secondary,#f5f6f7));--pw-ink:var(--dsw-alias-label-primary,var(--text-primary,#0f1115));--pw-muted:var(--dsw-alias-label-secondary,var(--text-secondary,#4b5563));--pw-faint:var(--dsw-alias-label-caption,#adb2b8);--pw-line:var(--dsw-alias-border-l2,var(--border-color,#e1e5ea));--pw-line-strong:var(--dsw-alias-border-l3,#d5dae2);--pw-soft:var(--dsw-alias-state-business-tertiary,#e4edfd);display:grid;grid-template-rows:auto auto minmax(0,1fr) auto;width:100%;height:100%;min-width:0;overflow:hidden;color:var(--pw-ink);background:var(--pw-surface);font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif);container-name:previsit-workbench;container-type:inline-size;-webkit-font-smoothing:antialiased}.qccPwShell button,.qccPwShell textarea{font-family:inherit}
756
+ .qccPwIcon{display:block;width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
757
+ .qccPwHeader{display:flex;min-height:68px;align-items:center;justify-content:space-between;gap:18px;padding:10px 20px;border-bottom:1px solid var(--pw-line);background:var(--pw-surface)}
758
+ .qccPwBrand{display:flex;min-width:0;align-items:center;gap:11px}.qccPwBrandIcon{display:grid;flex:0 0 36px;width:36px;height:36px;place-items:center;border-radius:10px;color:var(--pw-brand-strong);background:var(--pw-soft);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--pw-brand) 18%,transparent)}
759
+ .qccPwBrandCopy{min-width:0}.qccPwTitleRow{display:flex;align-items:center;gap:8px}.qccPwTitle{margin:0;font-size:17px;font-weight:700;line-height:1.35;letter-spacing:-.01em}.qccPwSubtitle{margin:2px 0 0;overflow:hidden;color:var(--pw-muted);font-size:14px;line-height:1.4;text-overflow:ellipsis;white-space:nowrap}
760
+ .qccPwLiveDot{width:7px;height:7px;border-radius:50%;background:#98a2b3;box-shadow:0 0 0 3px color-mix(in srgb,#98a2b3 15%,transparent)}.qccPwLiveDot[data-status='running'],.qccPwLiveDot[data-status='waiting-agent']{background:#c47b16;box-shadow:0 0 0 3px color-mix(in srgb,#c47b16 17%,transparent)}.qccPwLiveDot[data-status='ready']{background:#2c7a50;box-shadow:0 0 0 3px color-mix(in srgb,#2c7a50 17%,transparent)}.qccPwLiveDot[data-status='failed']{background:#b64141;box-shadow:0 0 0 3px color-mix(in srgb,#b64141 17%,transparent)}
761
+ .qccPwMeta{display:grid;flex:0 1 210px;min-width:0;justify-items:end;gap:4px}.qccPwStatus{display:flex;width:max-content;max-width:100%;align-items:center;gap:6px;padding:4px 8px;border:1px solid var(--pw-line);border-radius:999px;color:var(--pw-muted);background:var(--pw-surface-muted);font-size:13px;font-weight:650;line-height:1.25}.qccPwStatus:before{width:5px;height:5px;border-radius:50%;background:currentColor;content:''}.qccPwStatus[data-status='running'],.qccPwStatus[data-status='waiting-agent']{border-color:color-mix(in srgb,#b96a08 25%,var(--pw-line));color:#9a5d0a;background:color-mix(in srgb,#fff3df 75%,var(--pw-surface))}.qccPwStatus[data-status='ready']{border-color:color-mix(in srgb,#2c7a50 25%,var(--pw-line));color:#236542;background:color-mix(in srgb,#e7f5ec 75%,var(--pw-surface))}.qccPwStatus[data-status='failed']{border-color:color-mix(in srgb,#b64141 25%,var(--pw-line));color:#a13a3a;background:color-mix(in srgb,#fbeaea 75%,var(--pw-surface))}.qccPwSession{width:100%;overflow:hidden;color:var(--pw-muted);font-size:12px;line-height:1.3;text-align:right;text-overflow:ellipsis;white-space:nowrap}
762
+ .qccPwStages{display:grid;grid-template-columns:repeat(4,minmax(118px,1fr));min-height:72px;padding:0 16px;overflow-x:auto;border-bottom:1px solid var(--pw-line);background:var(--pw-surface);scrollbar-width:thin}.qccPwStage{position:relative;display:flex;min-width:100px;align-items:center;gap:9px;padding:8px 10px;border:0;color:var(--pw-muted);background:transparent;cursor:pointer;font:inherit;text-align:left}.qccPwStage:after{position:absolute;right:0;width:8px;height:8px;border-top:1px solid var(--pw-line-strong);border-right:1px solid var(--pw-line-strong);content:'';opacity:.72;transform:rotate(45deg)}.qccPwStage:last-child:after{display:none}.qccPwStage:hover{color:var(--pw-ink);background:color-mix(in srgb,var(--pw-brand) 4%,transparent)}.qccPwStage:focus-visible{outline:3px solid color-mix(in srgb,var(--pw-brand) 24%,transparent);outline-offset:-1px}.qccPwStage[data-selected='true']{color:var(--pw-brand);background:linear-gradient(180deg,color-mix(in srgb,var(--pw-soft) 82%,transparent),transparent)}
763
+ .qccPwStageIcon{display:grid;flex:0 0 29px;width:29px;height:29px;place-items:center;border:1px solid var(--pw-line-strong);border-radius:50%;color:var(--pw-muted);background:var(--pw-surface);transition:border-color 160ms ease,color 160ms ease,background 160ms ease,box-shadow 160ms ease}.qccPwStageIcon .qccPwIcon{width:14px;height:14px}.qccPwStage[data-selected='true'] .qccPwStageIcon{border-color:var(--pw-brand);color:#fff;background:var(--pw-brand);box-shadow:0 0 0 4px var(--pw-soft)}.qccPwStage[data-progress='done']:not([data-selected='true']) .qccPwStageIcon{border-color:color-mix(in srgb,#2c7a50 32%,var(--pw-line));color:#2c7a50;background:color-mix(in srgb,#e7f5ec 72%,var(--pw-surface))}.qccPwStage[data-progress='active']:not([data-selected='true']) .qccPwStageIcon{border-color:color-mix(in srgb,#b96a08 32%,var(--pw-line));color:#a35f08;background:color-mix(in srgb,#fff3df 72%,var(--pw-surface))}.qccPwStage[data-progress='failed']:not([data-selected='true']) .qccPwStageIcon{border-color:color-mix(in srgb,#b64141 32%,var(--pw-line));color:#a13a3a;background:color-mix(in srgb,#fbeaea 72%,var(--pw-surface))}
764
+ .qccPwStageCopy{display:grid;min-width:0;gap:2px}.qccPwStageCopy strong{overflow:hidden;font-size:14px;font-weight:650;text-overflow:ellipsis;white-space:nowrap}.qccPwStageCopy small{overflow:hidden;color:var(--pw-faint);font-size:12px;font-weight:450;text-overflow:ellipsis;white-space:nowrap}
765
+ .qccPwBody{min-height:0;overflow-y:auto;padding:22px;background:var(--pw-canvas);scrollbar-width:thin}.qccPwPanel{width:min(100%,1040px);margin:0 auto;outline:none}.qccPwPageHeading{display:flex;align-items:flex-start;justify-content:space-between;gap:18px;margin-bottom:16px}.qccPwPageHeading h2{margin:0;font-size:22px;font-weight:720;line-height:1.25;letter-spacing:-.02em}.qccPwPageHeading p:last-child{max-width:660px;margin:5px 0 0;color:var(--pw-muted);font-size:14px;line-height:1.55}.qccPwEyebrow{margin:0 0 5px!important;color:var(--pw-brand)!important;font-size:12px!important;font-weight:750;letter-spacing:.09em;text-transform:uppercase}.qccPwTaskId{flex:none;padding:5px 8px;border:1px solid var(--pw-line);border-radius:7px;color:var(--pw-muted);background:var(--pw-surface);font:12px ui-monospace,SFMono-Regular,Menlo,monospace}
766
+ .qccPwCard{overflow:hidden;border:1px solid var(--pw-line);border-radius:13px;background:var(--pw-surface);box-shadow:0 3px 12px color-mix(in srgb,#111923 7%,transparent)}.qccPwCard+.qccPwCard{margin-top:13px}.qccPwCardHeader{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;padding:14px 16px;border-bottom:1px solid var(--pw-line)}.qccPwCardHeader h3,.qccPwCardHeader p{margin:0}.qccPwCardHeader h3{font-size:15px}.qccPwCardHeader p{margin-top:3px;color:var(--pw-muted);font-size:12px}.qccPwMode{padding:4px 8px;border-radius:999px;color:var(--pw-brand-strong);background:var(--pw-soft);font-size:12px;font-weight:700}.qccPwMode[data-manual='true']{color:#9a5d0a;background:color-mix(in srgb,#fff3df 75%,var(--pw-surface))}
767
+ .qccPwComposer{padding:15px 16px}.qccPwComposer label{display:grid;gap:7px;color:var(--pw-ink);font-size:13px;font-weight:650}.qccPwComposer textarea{box-sizing:border-box;width:100%;min-height:110px;padding:11px 12px;border:1px solid var(--pw-line-strong);border-radius:9px;color:var(--pw-ink);background:var(--pw-surface);font:inherit;font-size:14px;line-height:1.65;resize:vertical;transition:border-color 140ms ease,box-shadow 140ms ease}.qccPwComposer textarea:hover,.qccPwComposer textarea:focus{border-color:color-mix(in srgb,var(--pw-brand) 55%,var(--pw-line))}.qccPwComposer textarea::placeholder{color:var(--pw-faint)}.qccPwComposer textarea:focus-visible,.qccPwChoice:focus-visible,.qccPwPrimary:focus-visible,.qccPwSecondary:focus-visible{outline:3px solid color-mix(in srgb,var(--pw-brand) 24%,transparent);outline-offset:-1px}.qccPwComposerHint{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:7px;color:var(--pw-muted);font-size:12px}.qccPwManualHint{margin:0 16px 14px;padding:9px 10px;border-left:3px solid #c47b16;border-radius:6px;color:#8d5a11;background:color-mix(in srgb,#fff3df 65%,var(--pw-surface));font-size:13px;line-height:1.5}
768
+ .qccPwFilters{display:grid;border-top:1px solid var(--pw-line)}.qccPwFilterRow{display:grid;grid-template-columns:112px minmax(0,1fr);gap:14px;padding:12px 16px;border-bottom:1px solid var(--pw-line)}.qccPwFilterRow:last-child{border-bottom:0}.qccPwFilterLabel{padding-top:7px}.qccPwFilterLabel strong{display:block;font-size:13px}.qccPwFilterLabel span{display:block;margin-top:2px;color:var(--pw-muted);font-size:11px;line-height:1.35}.qccPwChoices{display:flex;flex-wrap:wrap;gap:7px}.qccPwChoice{min-height:31px;padding:0 10px;border:1px solid var(--pw-line);border-radius:8px;color:var(--pw-muted);background:var(--pw-surface);cursor:pointer;font:inherit;font-size:13px}.qccPwChoice:hover{color:var(--pw-ink);background:color-mix(in srgb,var(--pw-brand) 4%,var(--pw-surface))}.qccPwChoice[aria-pressed='true']{border-color:var(--pw-brand);color:var(--pw-brand-strong);background:var(--pw-soft);font-weight:700}.qccPwError{margin:12px 16px 0;padding:8px 10px;border-left:3px solid #b64141;border-radius:6px;color:#a13a3a;background:color-mix(in srgb,#fbeaea 70%,var(--pw-surface));font-size:13px}
769
+ .qccPwGrid2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:13px}.qccPwEngine{min-height:174px;padding:16px}.qccPwEngineTop{display:flex;align-items:center;justify-content:space-between;gap:10px}.qccPwEngineTop span:first-child{display:grid;width:32px;height:32px;place-items:center;border-radius:9px;color:var(--pw-brand);background:var(--pw-soft)}.qccPwEngineTag{padding:3px 7px;border-radius:999px;color:var(--pw-muted);background:var(--pw-surface-muted);font-size:11px}.qccPwEngine h3{margin:11px 0 5px;font-size:16px}.qccPwEngine p{margin:0;color:var(--pw-muted);font-size:13px;line-height:1.55}.qccPwEngine ul{display:grid;gap:5px;margin:12px 0 0;padding:0;list-style:none}.qccPwEngine li{display:flex;gap:6px;color:var(--pw-muted);font-size:12px}.qccPwEngine li:before{color:var(--pw-brand);content:'✓'}.qccPwStateGrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px;padding:15px 16px}.qccPwState{padding:9px 7px;border:1px solid var(--pw-line);border-radius:8px;color:var(--pw-muted);background:var(--pw-surface);font-size:12px;text-align:center}
770
+ .qccPwFeedback{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;margin-bottom:13px;padding:11px 12px;border:1px solid var(--pw-line);border-radius:10px;background:var(--pw-surface-muted)}.qccPwFeedbackIcon{display:grid;width:27px;height:27px;place-items:center;border-radius:8px;color:var(--pw-muted);background:var(--pw-surface)}.qccPwFeedback[data-tone='notice']{border-color:color-mix(in srgb,#b96a08 22%,var(--pw-line));background:color-mix(in srgb,#fff3df 54%,var(--pw-surface))}.qccPwFeedback[data-tone='notice'] .qccPwFeedbackIcon{color:#a35f08;background:color-mix(in srgb,#fff3df 72%,var(--pw-surface))}.qccPwFeedback[data-tone='success']{border-color:color-mix(in srgb,#2c7a50 22%,var(--pw-line));background:color-mix(in srgb,#e7f5ec 54%,var(--pw-surface))}.qccPwFeedback[data-tone='success'] .qccPwFeedbackIcon{color:#2c7a50;background:color-mix(in srgb,#e7f5ec 72%,var(--pw-surface))}.qccPwFeedback[data-tone='error']{border-color:color-mix(in srgb,#b64141 22%,var(--pw-line));background:color-mix(in srgb,#fbeaea 54%,var(--pw-surface))}.qccPwFeedback[data-tone='error'] .qccPwFeedbackIcon{color:#b64141;background:color-mix(in srgb,#fbeaea 72%,var(--pw-surface))}.qccPwFeedback strong{display:block;margin-top:1px;font-size:13px}.qccPwFeedback p{margin:3px 0 0;color:var(--pw-muted);font-size:12px;line-height:1.5}
771
+ .qccPwToolList{display:flex;flex-wrap:wrap;gap:6px;padding:14px 16px}.qccPwToolList span{max-width:100%;overflow:hidden;padding:5px 7px;border:1px solid var(--pw-line);border-radius:7px;color:var(--pw-muted);background:var(--pw-surface-muted);font:12px ui-monospace,SFMono-Regular,Menlo,monospace;text-overflow:ellipsis;white-space:nowrap}.qccPwEmpty{padding:30px 20px;color:var(--pw-muted);font-size:13px;text-align:center}
772
+ .qccPwRiskRule{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;padding:16px}.qccPwRiskNumber{display:grid;width:38px;height:38px;place-items:center;border-radius:10px;color:var(--pw-brand);background:var(--pw-soft);font-size:17px;font-weight:750}.qccPwRiskRule h3,.qccPwRiskRule p{margin:0}.qccPwRiskRule h3{font-size:15px}.qccPwRiskRule p{margin-top:4px;color:var(--pw-muted);font-size:12px;line-height:1.55}.qccPwRiskBands{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;padding:0 16px 16px}.qccPwRiskBand{padding:11px;border-radius:9px;background:var(--pw-surface-muted)}.qccPwRiskBand b{display:block;font-size:13px}.qccPwRiskBand span{display:block;margin-top:3px;color:var(--pw-muted);font-size:11px;line-height:1.4}.qccPwRiskBand[data-tone='red']{background:color-mix(in srgb,#fbeaea 64%,var(--pw-surface))}.qccPwRiskBand[data-tone='amber']{background:color-mix(in srgb,#fff3df 64%,var(--pw-surface))}
773
+ .qccPwDeliverables{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:15px 16px}.qccPwDeliverable{display:grid;grid-template-columns:auto minmax(0,1fr);gap:9px;padding:11px;border:1px solid var(--pw-line);border-radius:9px}.qccPwDeliverable>span{display:grid;width:24px;height:24px;place-items:center;border-radius:7px;color:var(--pw-brand);background:var(--pw-soft);font-size:12px;font-weight:750}.qccPwDeliverable b{display:block;font-size:13px}.qccPwDeliverable small{display:block;margin-top:2px;color:var(--pw-muted);font-size:11px;line-height:1.4}.qccPwCoverage{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;padding:15px 16px}.qccPwMetric{padding:11px;border-radius:9px;background:var(--pw-surface-muted)}.qccPwMetric strong{display:block;color:var(--pw-brand);font-size:20px}.qccPwMetric span{color:var(--pw-muted);font-size:11px}
774
+ .qccPwFooter{display:flex;min-height:64px;align-items:center;justify-content:space-between;gap:18px;padding:10px 16px;border-top:1px solid var(--pw-line);color:var(--pw-muted);background:var(--pw-surface)}.qccPwFooterHint[data-tone='error']{color:#a13a3a;display:block!important}.qccPwFooterHint{max-width:680px;font-size:12px;line-height:1.5}.qccPwFooterActions{display:flex;align-items:center;gap:8px}.qccPwPrimary,.qccPwSecondary{display:inline-flex;min-height:40px;white-space:nowrap;align-items:center;justify-content:center;gap:10px;padding:0 15px;border-radius:8px;cursor:pointer;font:inherit;font-size:14px;font-weight:700}.qccPwPrimary{min-width:126px;border:1px solid var(--pw-brand);color:#fff;background:var(--pw-brand);box-shadow:0 4px 10px color-mix(in srgb,var(--pw-brand) 22%,transparent)}.qccPwPrimary:hover:not(:disabled){border-color:var(--pw-brand-hover);background:var(--pw-brand-hover)}.qccPwPrimary:disabled{box-shadow:none;opacity:.48;cursor:not-allowed}.qccPwSecondary{border:1px solid var(--pw-line);color:var(--pw-muted);background:var(--pw-surface)}.qccPwSecondary:hover{color:var(--pw-ink);background:var(--pw-surface-muted)}
775
+ .qccPwEntry{display:inline-flex;flex:none;align-items:center;justify-content:center;gap:6px;border:0;white-space:nowrap;color:var(--text-secondary,#475467);background:transparent;cursor:pointer;font:inherit}.qccPwInputEntry{min-height:28px;padding:4px 7px;border-radius:7px;font-size:14px}.qccPwInputEntry span{white-space:nowrap}@container (max-width:420px){.qccPwInputEntry span{display:none}}.qccPwEntry:hover,.qccPwEntry:focus-visible{color:var(--text-primary,#1f2430);background:var(--background-secondary,#f2f4f7)}.qccPwSidebarEntry{width:100%;min-height:34px;padding:7px 10px;border-radius:8px}.qccPwSidebarEntry[data-wide='false']{width:34px;padding-inline:0}.qccPwHeaderEntry{min-height:26px;padding:4px 8px;border:1px solid var(--border-color,#e5e7eb);border-radius:999px;font-size:14px}
776
+ .qccPwSteps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin:0 0 14px;padding:0;list-style:none}.qccPwStep{display:flex;align-items:center;gap:10px;min-height:56px;padding:10px 12px;border:1px solid var(--pw-line);border-radius:10px;background:var(--pw-surface);color:var(--pw-muted)}.qccPwStep[data-state='active']{border-color:var(--pw-brand);color:var(--pw-ink);box-shadow:0 0 0 3px var(--pw-soft)}.qccPwStep[data-state='done']{color:var(--pw-ink)}.qccPwStepDot{display:grid;flex:none;width:26px;height:26px;place-items:center;border-radius:50%;border:1px solid var(--pw-line-strong);font-size:12px;font-weight:700;background:var(--pw-surface)}.qccPwStep[data-state='done'] .qccPwStepDot{border-color:#2f8a4c;color:#2f8a4c;background:#e7f5ec}.qccPwStep[data-state='active'] .qccPwStepDot{border-color:var(--pw-brand);color:var(--pw-brand);background:var(--pw-soft)}.qccPwStepDot .qccPwIcon{width:14px;height:14px}.qccPwStepCopy{display:grid;min-width:0;gap:2px}.qccPwStepCopy b{font-size:14px;font-weight:650}.qccPwStepCopy small{overflow:hidden;color:var(--pw-muted);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.qccPwDims{display:flex;flex-wrap:wrap;gap:7px;padding:12px 16px 16px}.qccPwDim{display:inline-flex;align-items:center;gap:6px;padding:5px 10px;border:1px solid var(--pw-line);border-radius:999px;color:var(--pw-ink);background:var(--pw-surface);font-size:13px}.qccPwDim::before{content:'';width:7px;height:7px;border-radius:50%;background:#2f8a4c}.qccPwDim[data-status='running']{color:var(--pw-brand-strong);border-color:var(--pw-brand)}.qccPwDim[data-status='running']::before{background:var(--pw-brand);animation:qccPwPulse 1s infinite alternate}.qccPwDim[data-status='failed']{color:#a13a3a;border-color:#e5b4b4;background:#fbeaea}.qccPwDim[data-status='failed']::before{background:#b64141}@keyframes qccPwPulse{from{opacity:.3}to{opacity:1}}.qccPwStateStrip{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px;padding:12px 16px 8px}.qccPwStateStrip[data-concluded='true'] .qccPwState{opacity:.45}.qccPwState[data-hit='true']{opacity:1!important;color:var(--pw-brand-strong);border-color:var(--pw-brand);background:var(--pw-soft);font-weight:700}.qccPwNote{margin:0;padding:6px 16px 14px;color:var(--pw-ink);font-size:13px;line-height:1.6}.qccPwHypos{display:grid;gap:8px;margin:0;padding:12px 16px 16px;list-style:none}.qccPwHypos li{display:grid;grid-template-columns:auto auto minmax(0,1fr);align-items:baseline;gap:8px;font-size:14px;line-height:1.6;color:var(--pw-ink)}.qccPwHypos b{color:var(--pw-muted);font-size:12px;font-weight:700}.qccPwPri{padding:1px 7px;border-radius:999px;font-size:11px;font-weight:700;color:var(--pw-muted);background:var(--pw-surface-muted)}.qccPwPri[data-p='P0']{color:#a13a3a;background:#fbeaea}.qccPwPri[data-p='P1']{color:#8d5a11;background:#fff3df}.qccPwRiskTiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;padding:12px 16px 16px}.qccPwRiskTile{padding:12px 14px;border-radius:10px;border:1px solid var(--pw-line);background:var(--pw-surface)}.qccPwRiskTile[data-level='红线']{background:color-mix(in srgb,#fbeaea 75%,var(--pw-surface))}.qccPwRiskTile[data-level='关注']{background:color-mix(in srgb,#fff3df 75%,var(--pw-surface))}.qccPwRiskTile[data-empty='true']{opacity:.55}.qccPwRiskTileTop{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.qccPwRiskTileTop b{font-size:13px;color:var(--pw-muted)}.qccPwRiskTileTop strong{font-size:22px;font-weight:800;color:var(--pw-ink)}.qccPwRiskTile p{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;margin:6px 0 0;color:var(--pw-ink);font-size:13px;line-height:1.55}@container previsit-workbench (max-width:680px){.qccPwSteps{grid-template-columns:repeat(2,minmax(0,1fr))}.qccPwStateStrip{grid-template-columns:repeat(2,1fr)}.qccPwRiskTiles{grid-template-columns:1fr}.qccPwHeader{padding-inline:14px}.qccPwMeta{display:none}.qccPwBody{padding:15px}.qccPwStages{grid-template-columns:repeat(4,minmax(104px,1fr));padding:0 8px}.qccPwGrid2{grid-template-columns:1fr}.qccPwFilterRow{grid-template-columns:1fr;gap:7px}.qccPwFilterLabel{padding-top:0}.qccPwStateGrid{grid-template-columns:repeat(2,1fr)}.qccPwDeliverables{grid-template-columns:1fr}.qccPwFooterHint{display:none}.qccPwFooter{justify-content:flex-end}}@container previsit-workbench (max-width:520px){.qccPwHeader{min-height:56px;padding:8px 12px}.qccPwSubtitle{display:none}.qccPwBrandIcon{display:none}.qccPwStages{grid-template-columns:repeat(4,minmax(0,1fr));min-height:auto;padding:6px 6px;overflow:visible}.qccPwStage{flex-direction:column;min-width:0;gap:5px;padding:8px 2px;text-align:center}.qccPwStageIcon{flex-basis:26px;width:26px;height:26px}.qccPwStageCopy{justify-items:center;width:100%}.qccPwStageCopy strong{font-size:12px;white-space:nowrap;overflow:visible}.qccPwStageCopy small{display:none}.qccPwBody{padding:12px}.qccPwPageHeading h2{font-size:18px}.qccPwPageHeading{margin-bottom:10px}.qccPwTaskId{display:none}.qccPwComposer{padding:12px}.qccPwChoice{min-height:30px;padding:0 9px;font-size:12px}.qccPwFooter{flex-direction:column;align-items:stretch;gap:8px;padding:10px 12px}.qccPwFooterHint{display:none}.qccPwFooterActions{display:grid;grid-template-columns:1fr 1fr;gap:8px}.qccPwFooterActions .qccPwPrimary{grid-column:1/-1}.qccPwPrimary,.qccPwSecondary{min-height:38px;padding:0 10px;font-size:13px}.qccPwSteps{grid-template-columns:repeat(2,minmax(0,1fr))}.qccPwStateStrip{grid-template-columns:repeat(2,1fr)}.qccPwRiskTiles{grid-template-columns:1fr}.qccPwDeliverables{grid-template-columns:1fr}}.qccDock{--pw-brand:var(--dsw-alias-state-business-primary,#4176e6);--pw-brand-strong:var(--dsw-static-deepseek-600,#4868b2);--pw-brand-hover:var(--dsw-alias-button-info-hover,#679efe);--pw-surface:var(--dsw-alias-bg-layer-1,var(--background-primary,#fff));--pw-canvas:var(--dsw-alias-bg-layer-1,var(--background-primary,#fff));--pw-surface-muted:var(--dsw-alias-bg-module-platform,var(--background-secondary,#f5f6f7));--pw-ink:var(--dsw-alias-label-primary,var(--text-primary,#0f1115));--pw-muted:var(--dsw-alias-label-secondary,var(--text-secondary,#4b5563));--pw-faint:var(--dsw-alias-label-caption,#adb2b8);--pw-line:var(--dsw-alias-border-l2,var(--border-color,#e1e5ea));--pw-line-strong:var(--dsw-alias-border-l3,#d5dae2);--pw-soft:var(--dsw-alias-state-business-tertiary,#e4edfd);box-sizing:border-box;flex:none;width:calc(100% - var(--dsh-composer-side-clearance,16px)*2 - var(--dsh-composer-dock-inset,8px)*2);max-width:calc(var(--dsh-composer-card-max-width,780px) - var(--dsh-composer-dock-inset,8px)*2);margin:0 auto calc(0px - var(--dsh-composer-stack-gap,6px) - 3px);padding:0 var(--dsh-composer-dock-inset,8px);color:var(--pw-ink);font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif)}.qccDockPanel{position:relative;width:100%;padding:0 0 8px;border-radius:12px 12px 0 0;background:var(--dsw-alias-bg-base,#fff)}.qccDockPanel:after{content:'';position:absolute;inset:0;border:1px solid var(--dsw-alias-border-l1,#e5e7eb);border-bottom:none;border-radius:inherit;pointer-events:none}.qccDockHead{display:flex;width:100%;align-items:center;gap:10px;min-height:36px;padding:6px 12px 4px;border:0;background:transparent;color:inherit;cursor:pointer;font:inherit;text-align:left}.qccDockBrand{flex:none;display:inline-flex;align-items:center;gap:7px;color:var(--dsw-alias-label-primary,#0f1115);font-size:13px;font-weight:500}.qccDockBrand::before{content:'';width:6px;height:6px;border-radius:1px;background:var(--dsw-alias-label-tertiary,#81858c)}.qccDockSummary{display:flex;flex:1;min-width:0;flex-wrap:nowrap;align-items:center;gap:6px;overflow:hidden}.qccDockTag{flex:none;max-width:220px;overflow:hidden;padding:1px 7px;border-radius:4px;background:var(--dsw-alias-bg-module-platform,#f5f6f7);color:var(--dsw-alias-label-secondary,#4b5563);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.qccDockHint{color:var(--dsw-alias-label-tertiary,#81858c);font-size:12px;line-height:1.5}.qccDockHint[data-tone='error']{color:#c0392b}.qccDockWorkbench{flex:none;padding:2px 8px;border:1px solid var(--dsw-alias-border-l2,#e1e5ea);border-radius:5px;color:var(--dsw-alias-label-secondary,#4b5563);font-size:12px;background:transparent}.qccDockWorkbench:hover{color:var(--dsw-alias-label-primary,#0f1115);background:var(--dsw-alias-interactive-bg-hover,#f2f4f7)}.qccDockChevron{flex:none;width:7px;height:7px;margin:0 6px 3px 0;border-right:1.5px solid var(--dsw-alias-label-tertiary,#81858c);border-bottom:1.5px solid var(--dsw-alias-label-tertiary,#81858c);transform:rotate(45deg);transition:transform .15s}.qccDock[data-open='true'] .qccDockChevron{transform:rotate(-135deg);margin:4px 6px 0 0}.qccDockBody{display:grid;gap:6px;padding:4px 12px 0;border-top:1px solid var(--dsw-alias-border-l1,#eceef1);margin-top:2px;padding-top:10px}.qccDockRow{display:grid;grid-template-columns:40px minmax(0,1fr);align-items:center;gap:8px;min-height:28px}.qccDockLabel{color:var(--dsw-alias-label-tertiary,#81858c);font-size:12px;white-space:nowrap}.qccDockCompany{box-sizing:border-box;width:100%;min-height:30px;padding:3px 10px;border:1px solid var(--dsw-alias-border-l2,#e1e5ea);border-radius:5px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#0f1115);font:inherit;font-size:13px}.qccDockCompany::placeholder{color:var(--dsw-alias-label-caption,#adb2b8)}.qccDockCompany:focus{outline:0;border-color:var(--dsw-alias-label-secondary,#4b5563)}.qccDockChips{display:flex;flex-wrap:wrap;gap:6px}.qccDockChip{min-height:26px;padding:0 9px;border:1px solid var(--dsw-alias-border-l2,#e1e5ea);border-radius:5px;background:transparent;color:var(--dsw-alias-label-secondary,#4b5563);cursor:pointer;font:inherit;font-size:12.5px;line-height:1;white-space:nowrap;transition:background .12s,border-color .12s,color .12s}.qccDockChip:hover{background:var(--dsw-alias-interactive-bg-hover,#f2f4f7);color:var(--dsw-alias-label-primary,#0f1115)}.qccDockChip[data-selected='true']{border-color:var(--dsw-alias-label-primary,#0f1115);background:var(--dsw-alias-label-primary,#0f1115);color:var(--dsw-alias-bg-base,#fff)}.qccDockFoot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:4px;min-height:28px}.qccDockActions{display:flex;flex:none;gap:4px}.qccDockBtn{min-height:28px;padding:0 10px;border:1px solid transparent;border-radius:5px;background:transparent;color:var(--dsw-alias-label-secondary,#4b5563);cursor:pointer;font:inherit;font-size:12.5px;white-space:nowrap}.qccDockBtn:hover{color:var(--dsw-alias-label-primary,#0f1115);background:var(--dsw-alias-interactive-bg-hover,#f2f4f7)}.qccDockPrimary{background:var(--dsw-alias-state-business-primary,#4176e6);color:#fff;font-weight:500}.qccDockPrimary:hover{background:var(--dsw-alias-button-info-hover,#679efe);color:#fff}.qccDockPrimary:disabled{opacity:.6;cursor:default}@media(max-width:640px){.qccDockRow{grid-template-columns:1fr;gap:3px}.qccDockFoot{flex-direction:column;align-items:stretch}.qccDockActions{justify-content:flex-end}.qccDockSummary{display:none}}.qccDockFoot{flex-direction:column;align-items:stretch}.qccDockActions{justify-content:flex-end}.qccDockSummary{display:none}}.qccPwSetup{display:grid;gap:0;margin:0;padding:4px 16px 8px}.qccPwSetup>div{display:grid;grid-template-columns:64px minmax(0,1fr);gap:10px;padding:9px 0;border-bottom:1px solid var(--pw-line)}.qccPwSetup>div:last-child{border-bottom:0}.qccPwSetup dt{margin:0;color:var(--pw-muted);font-size:13px}.qccPwSetup dd{margin:0;color:var(--pw-ink);font-size:14px;line-height:1.5}.qccPwPrompt{margin:0;padding:12px 16px 16px;white-space:pre-wrap;word-break:break-word;color:var(--pw-ink);font:13px/1.6 inherit;font-family:inherit}.qccPwSetupCard .qccDockBody{padding:12px 16px 14px;gap:8px}.qccPwSetupCard .qccDockRow{min-height:32px}.qccModesHost{flex:none;width:100%;padding:0 0 14px}.qccModes{--pw-brand:var(--dsw-alias-state-business-primary,#4176e6);--pw-brand-strong:var(--dsw-static-deepseek-600,#4868b2);--pw-brand-hover:var(--dsw-alias-button-info-hover,#679efe);--pw-surface:var(--dsw-alias-bg-layer-1,var(--background-primary,#fff));--pw-canvas:var(--dsw-alias-bg-layer-1,var(--background-primary,#fff));--pw-surface-muted:var(--dsw-alias-bg-module-platform,var(--background-secondary,#f5f6f7));--pw-ink:var(--dsw-alias-label-primary,var(--text-primary,#0f1115));--pw-muted:var(--dsw-alias-label-secondary,var(--text-secondary,#4b5563));--pw-faint:var(--dsw-alias-label-caption,#adb2b8);--pw-line:var(--dsw-alias-border-l2,var(--border-color,#e1e5ea));--pw-line-strong:var(--dsw-alias-border-l3,#d5dae2);--pw-soft:var(--dsw-alias-state-business-tertiary,#e4edfd);display:flex;justify-content:center;gap:8px;width:100%;margin:6px auto 0;font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif)}.qccMode{position:relative;display:inline-flex;align-items:center;gap:7px;min-height:32px;padding:0 14px;border:1px solid var(--dsw-alias-border-l2,var(--pw-line));border-radius:5px;background:var(--dsw-alias-bg-base,#fff);color:var(--pw-ink);cursor:pointer;font:inherit;font-size:13px;font-weight:500;transition:border-color .12s,background .12s,color .12s}.qccMode svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;color:var(--pw-muted)}.qccMode:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#f2f4f7);color:var(--dsw-alias-label-primary,#0f1115)}.qccMode[data-active='true']{border-color:var(--dsw-alias-label-primary,#0f1115);background:var(--dsw-alias-label-primary,#0f1115);color:var(--dsw-alias-bg-base,#fff);font-weight:500}.qccMode[data-active='true'] svg{color:var(--dsw-alias-bg-base,#fff)}.qccMode:disabled{color:var(--pw-faint);cursor:not-allowed;background:var(--dsw-alias-bg-module-platform,var(--pw-surface-muted))}.qccMode:disabled svg{color:var(--pw-faint)}.qccMode[data-tip]::after{content:attr(data-tip);position:absolute;left:50%;bottom:calc(100% + 8px);transform:translateX(-50%);width:max-content;max-width:260px;padding:6px 10px;border-radius:5px;background:var(--pw-ink);color:#fff;font-size:12px;font-weight:400;line-height:1.5;white-space:normal;text-align:left;opacity:0;pointer-events:none;transition:opacity .12s;z-index:20;box-shadow:0 6px 20px -8px rgba(15,23,42,.4)}.qccMode[data-tip]::before{content:'';position:absolute;left:50%;bottom:calc(100% + 3px);transform:translateX(-50%);border:5px solid transparent;border-top-color:var(--pw-ink);opacity:0;pointer-events:none;transition:opacity .12s;z-index:20}.qccMode:hover::after,.qccMode:hover::before,.qccMode:focus-visible::after,.qccMode:focus-visible::before{opacity:1}@media(max-width:640px){.qccModes{flex-wrap:wrap;gap:6px}.qccMode{padding:0 10px;font-size:12px}}.qccDockWorkbench{flex:none;padding:3px 9px;border:1px solid var(--dsw-alias-border-l2,var(--pw-line));border-radius:999px;color:var(--pw-muted);font-size:12px;font-weight:600;background:var(--dsw-alias-bg-base,#fff)}.qccDockWorkbench:hover{color:var(--pw-brand-strong);border-color:var(--pw-brand)}.qccPwCompact{display:inline-flex;align-items:center;gap:6px;padding:0 4px;border:0;background:transparent;color:var(--dsw-alias-label-caption,#adb2b8);cursor:pointer;font:inherit;font-size:12px;line-height:20px}.qccPwCompact span{transition:color .12s}.qccPwCompact span[data-active='true']{color:var(--dsw-alias-label-secondary,#4b5563)}.qccPwCompact i{width:1px;height:10px;background:var(--dsw-alias-border-l2,#e1e5ea)}.qccPwCompact:hover span{color:var(--dsw-alias-label-primary,#0f1115)}html[data-qcc-compact] :is([data-chat-flow-kind='tool-call'],[data-chat-flow-kind='command']):has(+ :is([data-chat-flow-kind='tool-call'],[data-chat-flow-kind='command'],[data-chat-flow-kind='assistant-step']:not(:has(p,h1,h2,h3,h4,h5,table,ul,ol,pre,blockquote,img,[data-state='running'])))){display:none}html[data-qcc-compact] [data-chat-flow-kind='context']{display:none}html[data-qcc-compact] [data-variant='think'][data-state='ok']{display:none}html[data-qcc-compact] [data-chat-flow-kind='assistant-step']:not(:has(p,h1,h2,h3,h4,h5,table,ul,ol,pre,blockquote,img,[data-state='running'])){display:none}html[data-qcc-compact] :is([data-chat-flow-kind='tool-call'],[data-chat-flow-kind='command']){opacity:.75}.qccPwReportCard{padding:0;overflow:hidden}.qccPwReportFrame{display:block;width:100%;min-height:480px;border:0;background:#fff}.qccPwPageHeading .qccPwSecondary{flex:none;min-height:32px;padding:0 12px;font-size:13px}@media(prefers-reduced-motion:reduce){.qccPwShell *{animation:none!important;transition:none!important}}
777
+ `;
778
+
779
+ // src/stage-insights.ts
780
+ var OPPORTUNITY_DIMENSIONS = [
781
+ ["get_company_by_query", "\u4E3B\u4F53\u951A\u5B9A"],
782
+ ["get_company_registration_info", "\u5DE5\u5546\u767B\u8BB0"],
783
+ ["get_company_profile", "\u4F01\u4E1A\u753B\u50CF"],
784
+ ["get_annual_reports", "\u5E74\u62A5"],
785
+ ["get_change_records", "\u53D8\u66F4\u8BB0\u5F55"],
786
+ ["get_shareholder_info", "\u80A1\u4E1C"],
787
+ ["get_beneficial_owners", "\u5B9E\u63A7\u4EBA"],
788
+ ["get_key_personnel", "\u5173\u952E\u4EBA\u5458"],
789
+ ["get_financing_records", "\u878D\u8D44"],
790
+ ["get_bidding_info", "\u62DB\u6295\u6807"],
791
+ ["get_recruitment_info", "\u62DB\u8058"],
792
+ ["get_administrative_license", "\u884C\u653F\u8BB8\u53EF"],
793
+ ["get_qualifications", "\u8D44\u8D28"],
794
+ ["get_land_grant_info", "\u571F\u5730"],
795
+ ["get_external_investments", "\u5BF9\u5916\u6295\u8D44"],
796
+ ["get_branches", "\u5206\u652F\u673A\u6784"],
797
+ ["get_patent_info", "\u4E13\u5229"],
798
+ ["get_software_copyright_info", "\u8F6F\u8457"],
799
+ ["get_trademark", "\u5546\u6807"],
800
+ ["get_contact_info", "\u8054\u7CFB\u65B9\u5F0F"],
801
+ ["get_financial_data", "\u8D22\u52A1\u6570\u636E"],
802
+ ["get_company_announcement", "\u516C\u544A"],
803
+ ["get_listing_info", "\u4E0A\u5E02\u4FE1\u606F"],
804
+ ["get_equity_pledge_info", "\u80A1\u6743\u51FA\u8D28"]
805
+ ];
806
+ var RISK_DIMENSIONS = [
807
+ ["get_company_risk_scan", "\u98CE\u9669\u626B\u63CF"],
808
+ ["get_dishonest_info", "\u5931\u4FE1"],
809
+ ["get_judgment_debtor_info", "\u88AB\u6267\u884C"],
810
+ ["get_terminated_cases", "\u7EC8\u672C\u6848\u4EF6"],
811
+ ["get_equity_freeze", "\u80A1\u6743\u51BB\u7ED3"],
812
+ ["get_business_exception", "\u7ECF\u8425\u5F02\u5E38"],
813
+ ["get_administrative_penalty", "\u884C\u653F\u5904\u7F5A"],
814
+ ["get_tax_abnormal", "\u7A0E\u52A1\u5F02\u5E38"],
815
+ ["get_judicial_documents", "\u53F8\u6CD5\u6587\u4E66"],
816
+ ["get_court_", "\u7ACB\u6848/\u5F00\u5EAD"],
817
+ ["get_executive_risk_scan", "\u8463\u76D1\u9AD8"]
818
+ ];
819
+ function eventStatus(events, fragment) {
820
+ let seen = null;
821
+ for (const event of events) {
822
+ if (!event.name.includes(fragment)) continue;
823
+ if (event.status === "done") return "done";
824
+ if (event.status === "failed") seen = "failed";
825
+ else if (seen === null) seen = "running";
826
+ }
827
+ return seen;
828
+ }
829
+ function toDimensions(table, events) {
830
+ const out = [];
831
+ for (const [fragment, label] of table) {
832
+ const status = eventStatus(events, fragment);
833
+ if (status !== null) out.push({ label, status });
834
+ }
835
+ return out;
836
+ }
837
+ function opportunityDimensions(events) {
838
+ return toDimensions(OPPORTUNITY_DIMENSIONS, events);
839
+ }
840
+ function riskDimensions(events) {
841
+ return toDimensions(RISK_DIMENSIONS, events);
842
+ }
843
+ var BUSINESS_STATES = ["\u4EA7\u80FD\u5EFA\u8BBE\u671F", "\u5BA2\u6237\u5BFC\u5165\u671F", "\u4EA7\u80FD\u722C\u5761\u671F", "\u8BA2\u5355\u589E\u957F\u671F", "\u7A33\u5B9A\u7ECF\u8425\u671F", "\u6536\u7F29\u627F\u538B\u671F", "\u8D44\u672C\u8FD0\u4F5C\u671F", "\u98CE\u9669\u66B4\u9732\u671F"];
844
+ var EMPTY_INSIGHTS = {
845
+ found: false,
846
+ state: null,
847
+ stateUndetermined: false,
848
+ confidence: null,
849
+ industryLink: null,
850
+ hypotheses: [],
851
+ risks: [],
852
+ riskNoRecord: false,
853
+ sections: []
854
+ };
855
+ function section(md, title) {
856
+ const re = new RegExp(`^#{1,4}[^\\n]*${title}[^\\n]*$`, "m");
857
+ const m = re.exec(md);
858
+ if (m === null || m.index === void 0) return "";
859
+ const rest = md.slice(m.index + m[0].length);
860
+ const next = /^#{1,2}\s/m.exec(rest);
861
+ return next === null || next.index === void 0 ? rest : rest.slice(0, next.index);
862
+ }
863
+ var strip = (s) => s.replace(/\[F-?\d{2,4}\]/g, "").replace(/\*\*/g, "").replace(/(推理说明)|\(推理说明\)/g, "").trim();
864
+ function parseCardInsights(md) {
865
+ if (md === null || md.trim() === "") return EMPTY_INSIGHTS;
866
+ const sections = ["\u6838\u5FC3\u7814\u5224", "\u4EA7\u4E1A\u5B9A\u4F4D", "\u8FD1\u671F\u52A8\u6001", "\u4E1A\u52A1\u5047\u8BBE", "\u7EA2\u7EBF\u63D0\u793A", "\u73B0\u573A\u5FC5\u95EE", "\u89E6\u8FBE\u5F00\u573A", "\u8986\u76D6\u8BF4\u660E"].filter((t) => new RegExp(`^#{1,4}[^\\n]*${t}`, "m").test(md));
867
+ const core = section(md, "\u6838\u5FC3\u7814\u5224") || md;
868
+ const stateUndetermined = /状态未定/.test(core);
869
+ let state = null;
870
+ let best = Number.POSITIVE_INFINITY;
871
+ for (const s of BUSINESS_STATES) {
872
+ const idx = core.indexOf(s);
873
+ if (idx !== -1 && idx < best) {
874
+ best = idx;
875
+ state = s;
876
+ }
877
+ }
878
+ const conf = /状态置信度[::]\s*(中高|低|中|高)/.exec(md);
879
+ const link = /产业链环节[::]\s*([^\n||;;。]+)/.exec(md);
880
+ const hypotheses = [];
881
+ const hypoRe = /(H\d+)\s*[·・::\-–]\s*\**\s*(P[012])\**\s*[·・::\-–]\s*([^\n]+)/g;
882
+ const hypoSrc = section(md, "\u4E1A\u52A1\u5047\u8BBE") || md;
883
+ let hm;
884
+ while ((hm = hypoRe.exec(hypoSrc)) !== null) {
885
+ const id = hm[1] ?? "";
886
+ if (hypotheses.some((h) => h.id === id)) continue;
887
+ hypotheses.push({ id, priority: hm[2] ?? "", text: strip(hm[3] ?? "") });
888
+ }
889
+ const riskSrc = section(md, "\u7EA2\u7EBF\u63D0\u793A");
890
+ const risks = [];
891
+ for (const line of riskSrc.split("\n")) {
892
+ const t = line.trim();
893
+ if (!t.startsWith("|")) continue;
894
+ const cells = t.split("|").slice(1, -1).map((c) => c.trim());
895
+ const level = cells[0] ?? "";
896
+ const hit = ["\u7EA2\u7EBF", "\u5173\u6CE8", "\u4FE1\u606F"].find((l) => level.startsWith(l));
897
+ if (hit === void 0) continue;
898
+ risks.push({ level: hit, text: strip(cells[1] ?? "") });
899
+ }
900
+ return {
901
+ found: true,
902
+ state: stateUndetermined ? null : state,
903
+ stateUndetermined,
904
+ confidence: conf?.[1] ?? null,
905
+ industryLink: link?.[1] === void 0 ? null : strip(link[1]),
906
+ hypotheses,
907
+ risks,
908
+ riskNoRecord: /扫描未发现公开记录/.test(riskSrc),
909
+ sections
910
+ };
911
+ }
912
+ var has = (events, fragments, status) => events.some((e) => fragments.some((f) => e.name.includes(f)) && (status === void 0 || e.status === status));
913
+ var BASIC = ["get_company_registration_info", "get_company_profile", "get_annual_reports", "get_shareholder_info", "get_key_personnel", "get_change_records", "get_beneficial_owners"];
914
+ var STATE_TOOLS = ["get_bidding_info", "get_financing_records", "get_recruitment_info", "get_administrative_license", "get_patent_info", "get_land_grant_info", "get_external_investments", "get_qualifications", "get_software_copyright_info", "get_financial_data", "get_company_announcement"];
915
+ var DRILL = ["get_dishonest_info", "get_judgment_debtor_info", "get_terminated_cases", "get_equity_freeze", "get_business_exception", "get_administrative_penalty", "get_tax_abnormal", "get_judicial_documents", "get_court_"];
916
+ function stepOf(done, active, finished) {
917
+ if (done) return "done";
918
+ if (finished) return "done";
919
+ return active ? "active" : "idle";
920
+ }
921
+ function opportunitySteps(events, insights, finished) {
922
+ const anchorDone = has(events, ["get_company_by_query"], "done");
923
+ const basicDone = BASIC.filter((f) => has(events, [f], "done")).length;
924
+ const stateDone = insights.state !== null || insights.stateUndetermined;
925
+ const hypoDone = insights.hypotheses.length > 0;
926
+ return [
927
+ { label: "\u4E3B\u4F53\u951A\u5B9A", state: stepOf(anchorDone, has(events, ["get_company_by_query"]), finished) },
928
+ { label: "\u57FA\u7840\u4FE1\u53F7", state: stepOf(basicDone >= 3, basicDone > 0 || has(events, BASIC), finished), note: basicDone > 0 ? `${basicDone} \u9879` : void 0 },
929
+ { label: "\u72B6\u6001\u5224\u5B9A", state: stepOf(stateDone, has(events, STATE_TOOLS), finished), note: insights.stateUndetermined ? "\u72B6\u6001\u672A\u5B9A" : insights.state ?? void 0 },
930
+ { label: "\u5047\u8BBE\u53CD\u8BC1", state: stepOf(hypoDone, stateDone || has(events, STATE_TOOLS, "done"), finished), note: hypoDone ? `${insights.hypotheses.length} \u6761` : void 0 }
931
+ ];
932
+ }
933
+ function riskSteps(events, insights, finished) {
934
+ const scanDone = has(events, ["get_company_risk_scan"], "done");
935
+ const drillDone = has(events, DRILL, "done");
936
+ const execDone = has(events, ["get_executive_risk_scan"], "done");
937
+ const judged = insights.sections.includes("\u7EA2\u7EBF\u63D0\u793A");
938
+ return [
939
+ { label: "\u98CE\u9669\u626B\u63CF", state: stepOf(scanDone, has(events, ["get_company_risk_scan"]), finished) },
940
+ { label: "\u660E\u7EC6\u4E0B\u94BB", state: stepOf(drillDone, has(events, DRILL), finished), note: !drillDone && (scanDone || finished) ? "\u96F6\u8BB0\u5F55\u4E0D\u4E0B\u94BB" : void 0 },
941
+ { label: "\u8463\u76D1\u9AD8", state: stepOf(execDone, has(events, ["get_executive_risk_scan"]), finished), note: !execDone && finished ? "\u672A\u5355\u72EC\u626B\u63CF" : void 0 },
942
+ { label: "\u5F71\u54CD\u5224\u65AD", state: stepOf(judged, scanDone, finished), note: judged ? `${insights.risks.length} \u9879` : void 0 }
943
+ ];
944
+ }
945
+
946
+ // src/workbench-v2.tsx
947
+ var import_jsx_runtime2 = require("react/jsx-runtime");
948
+ var inject = ["sessions", "conversation", "betterSidebar"];
949
+ var STYLE_ID = "dsh-pre-duediligence-workbench";
950
+ var PHASE_LABELS = {
951
+ prepare: { label: "\u5C3D\u8C03\u8BBE\u5B9A", description: "\u4F01\u4E1A\u3001\u89D2\u8272\u4E0E\u8303\u56F4" },
952
+ opportunity: { label: "\u7ECF\u8425\u7814\u5224", description: "\u72B6\u6001\u3001\u5047\u8BBE\u4E0E\u53CD\u8BC1" },
953
+ risk: { label: "\u98CE\u9669\u6838\u67E5", description: "\u626B\u63CF\u3001\u4E0B\u94BB\u4E0E\u5F71\u54CD" },
954
+ delivery: { label: "\u5C3D\u8C03\u62A5\u544A", description: "\u5FC5\u95EE\u3001\u89E6\u8FBE\u4E0E\u884C\u52A8" }
955
+ };
956
+ var STATUS_LABELS = {
957
+ empty: "\u5F85\u8BBE\u5B9A",
958
+ "waiting-agent": "\u7B49\u5F85\u6267\u884C",
959
+ running: "\u6B63\u5728\u5C3D\u8C03",
960
+ ready: "\u62A5\u544A\u5DF2\u751F\u6210",
961
+ failed: "\u9700\u8981\u5904\u7406"
962
+ };
963
+ var EMPTY_RUNTIME = {
964
+ running: false,
965
+ partial: false,
966
+ lastAgentError: null,
967
+ toolNames: [],
968
+ toolEvents: [],
969
+ failedToolCount: 0
970
+ };
971
+ function Icon({ name }) {
972
+ const paths = {
973
+ briefcase: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
974
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "3", y: "7", width: "18", height: "12", rx: "2" }),
975
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 7V5h8v2M3 12h18M10 12v2h4v-2" })
976
+ ] }),
977
+ prepare: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
978
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5 4h14v16H5z" }),
979
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 8h8M8 12h8M8 16h5" })
980
+ ] }),
981
+ opportunity: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
982
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "10.5", cy: "10.5", r: "5.5" }),
983
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m15 15 4 4M10.5 7v7M7 10.5h7" })
984
+ ] }),
985
+ risk: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
986
+ /* @__PURE__ */ (0, import_jsx_runtime2.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" }),
987
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 8v5M12 17h.01" })
988
+ ] }),
989
+ delivery: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
990
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 3h8l4 4v14H6z" }),
991
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M14 3v5h5M9 13h6M9 17h6" })
992
+ ] }),
993
+ clock: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
994
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "9" }),
995
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 7v5l3 2" })
996
+ ] }),
997
+ check: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
998
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "9" }),
999
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m8 12 2.5 2.5L16 9" })
1000
+ ] }),
1001
+ warning: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1002
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 3 2.8 20h18.4z" }),
1003
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 9v4M12 17h.01" })
1004
+ ] })
1005
+ };
1006
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "qccPwIcon", viewBox: "0 0 24 24", "aria-hidden": "true", children: paths[name] });
1007
+ }
1008
+ function collectRuntime(snapshot, baseline) {
1009
+ const toolNames = /* @__PURE__ */ new Set();
1010
+ const toolEvents = [];
1011
+ for (const node of (snapshot.nodes ?? []).slice(baseline)) {
1012
+ if (node.kind !== "tool-result") continue;
1013
+ if (typeof node.call?.name === "string") {
1014
+ toolNames.add(node.call.name);
1015
+ toolEvents.push({ name: node.call.name, status: node.isError === true ? "failed" : "done" });
1016
+ }
1017
+ }
1018
+ for (const call of snapshot.runningCalls ?? []) {
1019
+ if (typeof call.name === "string") {
1020
+ toolNames.add(call.name);
1021
+ toolEvents.push({ name: call.name, status: "running" });
1022
+ }
1023
+ }
1024
+ return { toolNames: [...toolNames], toolEvents, failedToolCount: toolEvents.filter((e) => e.status === "failed").length };
1025
+ }
1026
+ function Feedback(props) {
1027
+ const icon = props.tone === "success" ? "check" : props.tone === "error" ? "warning" : "clock";
1028
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwFeedback", "data-tone": props.tone, role: props.tone === "error" ? "alert" : "status", children: [
1029
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwFeedbackIcon", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { name: icon }) }),
1030
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1031
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: props.title }),
1032
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: props.children })
1033
+ ] })
1034
+ ] });
1035
+ }
1036
+ function SetupPanel(props) {
1037
+ const actions = usePrevisitComposer({
1038
+ sessionId: props.sessionId,
1039
+ store: props.store,
1040
+ readDraft: () => composerTextarea()?.value ?? "",
1041
+ writeDraft: (text) => writeDraft(void 0, text),
1042
+ start: props.start,
1043
+ onStarted: props.onStarted
1044
+ });
1045
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "qccPwPanel", children: [
1046
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "qccPwPageHeading", children: [
1047
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1048
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "qccPwEyebrow", children: "PREVISIT" }),
1049
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: "\u5C3D\u8C03\u8BBE\u5B9A" })
1050
+ ] }),
1051
+ props.task === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwTaskId", children: props.task.id })
1052
+ ] }),
1053
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "qccPwCard qccPwSetupCard", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrevisitFields, { actions, idPrefix: `qccPw-${props.sessionId}` }) }),
1054
+ props.task === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCard", children: [
1055
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "qccPwCardHeader", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "\u5DF2\u53D1\u9001\u7684\u4EFB\u52A1" }) }) }),
1056
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("pre", { className: "qccPwPrompt", children: props.task.prompt })
1057
+ ] })
1058
+ ] });
1059
+ }
1060
+ function Steps(props) {
1061
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ol", { className: "qccPwSteps", children: props.steps.map((step, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { className: "qccPwStep", "data-state": step.state, children: [
1062
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwStepDot", children: step.state === "done" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { name: "check" }) : index + 1 }),
1063
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "qccPwStepCopy", children: [
1064
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: step.label }),
1065
+ step.note === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { children: step.note })
1066
+ ] })
1067
+ ] }, step.label)) });
1068
+ }
1069
+ function Dimensions(props) {
1070
+ const done = props.items.filter((d) => d.status === "done").length;
1071
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCard", children: [
1072
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCardHeader", children: [
1073
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: props.title }) }),
1074
+ done === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "qccPwMode", children: [
1075
+ done,
1076
+ " \u9879"
1077
+ ] })
1078
+ ] }),
1079
+ props.items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "qccPwEmpty", children: props.empty }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "qccPwDims", children: props.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwDim", "data-status": item.status, children: item.label }, item.label)) })
1080
+ ] });
1081
+ }
1082
+ function StagePanel(props) {
1083
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "qccPwPanel", children: [
1084
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "qccPwPageHeading", children: [
1085
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1086
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "qccPwEyebrow", children: props.eyebrow }),
1087
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: props.title })
1088
+ ] }),
1089
+ props.task === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwTaskId", children: props.task.id })
1090
+ ] }),
1091
+ props.children
1092
+ ] });
1093
+ }
1094
+ function OpportunityPanel(props) {
1095
+ const finished = props.status === "ready";
1096
+ const running = props.status === "running";
1097
+ const { insights } = props;
1098
+ const steps = opportunitySteps(props.events, insights, finished);
1099
+ const dims = opportunityDimensions(props.events);
1100
+ const concluded = insights.state !== null || insights.stateUndetermined;
1101
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(StagePanel, { eyebrow: "OPPORTUNITY", title: "\u7ECF\u8425\u7814\u5224", task: props.task, children: [
1102
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Steps, { steps }),
1103
+ /* @__PURE__ */ (0, import_jsx_runtime2.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" }),
1104
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCard", children: [
1105
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCardHeader", children: [
1106
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "\u7ECF\u8425\u72B6\u6001" }) }),
1107
+ insights.confidence === null ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "qccPwMode", children: [
1108
+ "\u7F6E\u4FE1\u5EA6 ",
1109
+ insights.confidence
1110
+ ] })
1111
+ ] }),
1112
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "qccPwStateStrip", "data-concluded": concluded, children: BUSINESS_STATES.map((state) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwState", "data-hit": insights.state === state, children: state }, state)) }),
1113
+ insights.stateUndetermined ? /* @__PURE__ */ (0, import_jsx_runtime2.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,
1114
+ insights.industryLink === null ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "qccPwNote", children: [
1115
+ "\u4EA7\u4E1A\u94FE\u73AF\u8282\uFF1A",
1116
+ insights.industryLink
1117
+ ] })
1118
+ ] }),
1119
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCard", children: [
1120
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCardHeader", children: [
1121
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "\u4E1A\u52A1\u5047\u8BBE" }) }),
1122
+ insights.hypotheses.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "qccPwMode", children: [
1123
+ insights.hypotheses.length,
1124
+ " \u6761"
1125
+ ] })
1126
+ ] }),
1127
+ insights.hypotheses.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.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_runtime2.jsx)("ol", { className: "qccPwHypos", children: insights.hypotheses.map((h) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { children: [
1128
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwPri", "data-p": h.priority, children: h.priority }),
1129
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: h.id }),
1130
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: h.text })
1131
+ ] }, h.id)) })
1132
+ ] })
1133
+ ] });
1134
+ }
1135
+ function RiskPanel(props) {
1136
+ const finished = props.status === "ready";
1137
+ const running = props.status === "running";
1138
+ const { insights } = props;
1139
+ const steps = riskSteps(props.events, insights, finished);
1140
+ const dims = riskDimensions(props.events);
1141
+ const real = (level) => insights.risks.filter((r) => r.level === level && !/^(无|—|-|暂无|本次.*未发现)/.test(r.text));
1142
+ const judged = insights.sections.includes("\u7EA2\u7EBF\u63D0\u793A");
1143
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(StagePanel, { eyebrow: "RISK", title: "\u98CE\u9669\u6838\u67E5", task: props.task, children: [
1144
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Steps, { steps }),
1145
+ /* @__PURE__ */ (0, import_jsx_runtime2.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" }),
1146
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCard", children: [
1147
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "qccPwCardHeader", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "\u98CE\u9669\u5206\u7EA7" }) }) }),
1148
+ !judged ? /* @__PURE__ */ (0, import_jsx_runtime2.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_runtime2.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_runtime2.jsx)("div", { className: "qccPwRiskTiles", children: ["\u7EA2\u7EBF", "\u5173\u6CE8", "\u4FE1\u606F"].map((level) => {
1149
+ const items = real(level);
1150
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwRiskTile", "data-level": level, "data-empty": items.length === 0, children: [
1151
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwRiskTileTop", children: [
1152
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: level }),
1153
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: items.length })
1154
+ ] }),
1155
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: items[0]?.text ?? "\u672C\u6B21\u672A\u53D1\u73B0" })
1156
+ ] }, level);
1157
+ }) })
1158
+ ] })
1159
+ ] });
1160
+ }
1161
+ function ReportViewer(props) {
1162
+ const ref = (0, import_react3.useRef)(null);
1163
+ const fit = () => {
1164
+ const el = ref.current;
1165
+ const h = el?.contentDocument?.documentElement?.scrollHeight;
1166
+ if (el !== null && h !== void 0 && h > 0) el.style.height = `${h + 8}px`;
1167
+ };
1168
+ (0, import_react3.useEffect)(() => {
1169
+ fit();
1170
+ }, [props.html]);
1171
+ 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, import_jsx_runtime2.jsx)("iframe", { ref, className: "qccPwReportFrame", title: "\u5C3D\u8C03\u62A5\u544A", sandbox: "allow-same-origin", srcDoc: embedded, onLoad: fit });
1173
+ }
1174
+ function DeliveryPanel(props) {
1175
+ const ready = props.status === "ready";
1176
+ if (props.reportHtml !== null) {
1177
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "qccPwPanel", children: [
1178
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "qccPwPageHeading", children: [
1179
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1180
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "qccPwEyebrow", children: "REPORT" }),
1181
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: "\u5C3D\u8C03\u62A5\u544A" })
1182
+ ] }),
1183
+ props.task === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwTaskId", children: props.task.id })
1184
+ ] }),
1185
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "qccPwCard qccPwReportCard", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportViewer, { html: props.reportHtml }) })
1186
+ ] });
1187
+ }
1188
+ const deliverables = [
1189
+ ["\u2460", "\u6838\u5FC3\u7814\u5224", "\u72B6\u6001\u3001\u673A\u4F1A\u65B9\u5411\u4E0E\u9A8C\u8BC1\u91CD\u70B9"],
1190
+ ["\u2461", "\u4EA7\u4E1A\u5B9A\u4F4D", "\u4E3B\u8425\u3001\u884C\u4E1A\u5206\u7C7B\u4E0E\u4EA7\u4E1A\u94FE\u73AF\u8282"],
1191
+ ["\u2462", "\u8FD1\u671F\u52A8\u6001", "3\u20135 \u4E2A\u5E26\u65E5\u671F\u4E0E\u6765\u6E90\u7684\u53D8\u5316"],
1192
+ ["\u2463", "\u4E1A\u52A1\u5047\u8BBE", "P0/P1 \u5047\u8BBE\u4E0E\u652F\u6301/\u53CD\u5BF9/\u672A\u77E5"],
1193
+ ["\u2464", "\u7EA2\u7EBF\u63D0\u793A", "\u98CE\u9669\u5982\u4F55\u6539\u53D8\u62DC\u8BBF\u7B56\u7565"],
1194
+ ["\u2465", "\u73B0\u573A\u5FC5\u95EE", "\u4E3A\u4EC0\u4E48\u95EE\u4E0E\u7B54 A/B \u4E0B\u4E00\u6B65"],
1195
+ ["\u2466", "\u89E6\u8FBE\u5F00\u573A", "\u6765\u6E90\u3001\u5F52\u5C5E\u3001\u7528\u9014\u4E0E\u5F00\u573A\u767D"],
1196
+ ["\u2467", "\u8986\u76D6\u8BF4\u660E", "\u5DF2\u67E5\u3001\u672A\u67E5\u3001\u5931\u8D25\u4E0E\u8BC1\u636E\u5C42\u7EA7"]
1197
+ ];
1198
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "qccPwPanel", children: [
1199
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "qccPwPageHeading", children: [
1200
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1201
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "qccPwEyebrow", children: "REPORT" }),
1202
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: "\u5C3D\u8C03\u62A5\u544A" }),
1203
+ /* @__PURE__ */ (0, import_jsx_runtime2.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
+ ] }),
1205
+ props.task === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwTaskId", children: props.task.id })
1206
+ ] }),
1207
+ props.task === void 0 ? props.cardCaptured ? /* @__PURE__ */ (0, import_jsx_runtime2.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_runtime2.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_runtime2.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_runtime2.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_runtime2.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" }),
1208
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCard", children: [
1209
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "qccPwCardHeader", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1210
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "\u62A5\u544A\u7ED3\u6784" }),
1211
+ /* @__PURE__ */ (0, import_jsx_runtime2.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
+ ] }) }),
1213
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "qccPwDeliverables", children: deliverables.map(([number, title, detail]) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwDeliverable", children: [
1214
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: number }),
1215
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1216
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", { children: title }),
1217
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { children: detail })
1218
+ ] })
1219
+ ] }, number)) })
1220
+ ] }),
1221
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCard", children: [
1222
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "qccPwCardHeader", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1223
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "\u6267\u884C\u8986\u76D6" }),
1224
+ /* @__PURE__ */ (0, import_jsx_runtime2.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
+ ] }) }),
1226
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwCoverage", children: [
1227
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwMetric", children: [
1228
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: props.toolCount }),
1229
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u5DF2\u8BC6\u522B\u5DE5\u5177\u8C03\u7528" })
1230
+ ] }),
1231
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwMetric", children: [
1232
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: props.failedToolCount }),
1233
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u5DE5\u5177\u9519\u8BEF" })
1234
+ ] }),
1235
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwMetric", children: [
1236
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: ready ? "4/4" : "\u2014" }),
1237
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u4E1A\u52A1\u9636\u6BB5" })
1238
+ ] })
1239
+ ] })
1240
+ ] })
1241
+ ] });
1242
+ }
1243
+ function extractCardFromDom() {
1244
+ if (typeof document === "undefined") return null;
1245
+ const headings = Array.from(document.querySelectorAll("h1,h2,h3,h4")).filter((h) => /核心研判/.test(h.textContent ?? "") && h.closest(".qccPwShell") === null);
1246
+ const last = headings[headings.length - 1];
1247
+ if (last === void 0) return null;
1248
+ let el = last.parentElement;
1249
+ while (el !== null && el !== document.body) {
1250
+ const t = el.textContent ?? "";
1251
+ if (/核心研判/.test(t) && /现场必问|覆盖说明/.test(t) && el.querySelector(".qccPwShell") === null) break;
1252
+ el = el.parentElement;
1253
+ }
1254
+ if (el === null || el === document.body) return null;
1255
+ const clone = el.cloneNode(true);
1256
+ clone.querySelectorAll("button,svg,script,style,textarea,input,select,[contenteditable],[role='toolbar']").forEach((n) => n.remove());
1257
+ clone.querySelectorAll("h1,h2,h3,p").forEach((n) => {
1258
+ const t = (n.textContent ?? "").trim();
1259
+ if (/^(访前尽调报告|拜访作战卡)\s*·/.test(t) || /^锚定主体:/.test(t)) n.remove();
1260
+ });
1261
+ clone.querySelectorAll("h1,h2,h3,h4").forEach((n) => {
1262
+ n.textContent = normalizeHeading(n.textContent ?? "");
1263
+ });
1264
+ clone.querySelectorAll("*").forEach((n) => {
1265
+ for (const attr of Array.from(n.attributes)) {
1266
+ if (!/^(colspan|rowspan|href)$/i.test(attr.name)) n.removeAttribute(attr.name);
1267
+ }
1268
+ });
1269
+ const text = el.textContent ?? "";
1270
+ return { html: clone.innerHTML, text };
1271
+ }
1272
+ function PrevisitWorkbenchTab(props) {
1273
+ const sessionId = props.scope.sessionId;
1274
+ const shared = (0, import_react3.useSyncExternalStore)(props.shared.subscribe, () => props.shared.get(sessionId));
1275
+ const task = shared.task;
1276
+ const setTask = (fn) => props.shared.update(sessionId, (s) => ({ ...s, task: fn(s.task) }));
1277
+ const [phase, setPhase] = (0, import_react3.useState)("prepare");
1278
+ const [runtime, setRuntime] = (0, import_react3.useState)(EMPTY_RUNTIME);
1279
+ const [completedTaskId, setCompletedTaskId] = (0, import_react3.useState)();
1280
+ const [cardText, setCardText] = (0, import_react3.useState)(null);
1281
+ const [downloadNote, setDownloadNote] = (0, import_react3.useState)();
1282
+ (0, import_react3.useInsertionEffect)(() => {
1283
+ if (!props.visible) return;
1284
+ return installStyles();
1285
+ }, [props.visible]);
1286
+ (0, import_react3.useEffect)(() => {
1287
+ const face = props.ctx.sessions.binding?.(sessionId)?.session;
1288
+ if (face === void 0) {
1289
+ return;
1290
+ }
1291
+ const refresh = () => {
1292
+ const snapshot = face.getSnapshot();
1293
+ if (task === void 0) {
1294
+ const adopted = adoptTaskFromSnapshot(snapshot);
1295
+ if (adopted !== null) {
1296
+ props.shared.update(sessionId, (s) => s.task !== void 0 ? s : {
1297
+ ...s,
1298
+ task: { ...adopted, createdAt: (/* @__PURE__ */ new Date()).toISOString(), seenRunning: snapshot.running === true || (snapshot.nodes?.length ?? 0) > adopted.nodeBaseline + 1, selection: s.selection }
1299
+ });
1300
+ }
1301
+ }
1302
+ const baseline = task?.nodeBaseline ?? (snapshot.nodes?.length ?? 0);
1303
+ const calls = collectRuntime(snapshot, baseline);
1304
+ setRuntime({
1305
+ running: snapshot.running === true,
1306
+ partial: snapshot.partial !== null && snapshot.partial !== void 0,
1307
+ lastAgentError: snapshot.lastAgentError ?? null,
1308
+ ...calls
1309
+ });
1310
+ if (snapshot.running === true) {
1311
+ setTask((current) => current === void 0 || current.seenRunning ? current : { ...current, seenRunning: true });
1312
+ }
1313
+ setCardText(extractCardText(snapshot, task?.nodeBaseline ?? 0));
1314
+ };
1315
+ refresh();
1316
+ return face.subscribe?.(refresh);
1317
+ }, [props.ctx, sessionId, task?.id, task?.nodeBaseline]);
1318
+ const progressInput = {
1319
+ hasTask: task !== void 0,
1320
+ running: runtime.running,
1321
+ seenRunning: task?.seenRunning ?? false,
1322
+ lastAgentError: runtime.lastAgentError,
1323
+ partial: runtime.partial,
1324
+ toolNames: runtime.toolNames
1325
+ };
1326
+ const status = deriveWorkbenchStatus(progressInput);
1327
+ const phaseStates = derivePhaseStates(progressInput);
1328
+ const insights = (0, import_react3.useMemo)(() => parseCardInsights(cardText), [cardText]);
1329
+ const reportHtml = (0, import_react3.useMemo)(() => {
1330
+ if (cardText !== null) return buildPrevisitReportHtml(cardText);
1331
+ if (status !== "ready" && task === void 0) return null;
1332
+ const dom = extractCardFromDom();
1333
+ return dom === null ? null : buildPrevisitReportFromRenderedHtml(dom.html, dom.text);
1334
+ }, [cardText, status, phase, runtime.toolEvents.length]);
1335
+ (0, import_react3.useEffect)(() => {
1336
+ if (status !== "ready" && status !== "failed" || task === void 0 || completedTaskId === task.id) {
1337
+ return;
1338
+ }
1339
+ setCompletedTaskId(task.id);
1340
+ setPhase("delivery");
1341
+ }, [completedTaskId, status, task]);
1342
+ const newTask = () => {
1343
+ setTask(() => void 0);
1344
+ setRuntime(EMPTY_RUNTIME);
1345
+ setPhase("prepare");
1346
+ };
1347
+ const returnToConversation = () => {
1348
+ props.store.reduce((state) => ({ ...state, panelOpen: false, bottomOpen: false }));
1349
+ };
1350
+ const downloadReport = () => {
1351
+ let html;
1352
+ let source;
1353
+ if (cardText !== null) {
1354
+ html = buildPrevisitReportHtml(cardText);
1355
+ source = cardText;
1356
+ } else {
1357
+ const dom = extractCardFromDom();
1358
+ if (dom === null) {
1359
+ setDownloadNote("\u5F53\u524D\u4F1A\u8BDD\u91CC\u8FD8\u6CA1\u6709\u751F\u6210\u5B8C\u6574\u62A5\u544A\uFF0C\u6216\u62A5\u544A\u672A\u5C55\u5F00\u5728\u5BF9\u8BDD\u533A\uFF1B\u8BF7\u5148\u56DE\u5230\u4F1A\u8BDD\u786E\u8BA4\u62A5\u544A\u5DF2\u8F93\u51FA\u3002");
1360
+ return;
1361
+ }
1362
+ html = buildPrevisitReportFromRenderedHtml(dom.html, dom.text);
1363
+ source = dom.text;
1364
+ }
1365
+ setDownloadNote(void 0);
1366
+ const company = /(?:访前尽调报告|拜访作战卡)\s*·\s*([^\n((锚|]+)/.exec(source)?.[1]?.trim() || "\u8BBF\u524D\u5C3D\u8C03\u62A5\u544A";
1367
+ const blob = new Blob([html], { type: "text/html;charset=utf-8" });
1368
+ const url = URL.createObjectURL(blob);
1369
+ const a = document.createElement("a");
1370
+ a.href = url;
1371
+ a.download = `\u8BBF\u524D\u5C3D\u8C03\u62A5\u544A_${company}.html`;
1372
+ document.body.append(a);
1373
+ a.click();
1374
+ a.remove();
1375
+ setTimeout(() => URL.revokeObjectURL(url), 0);
1376
+ };
1377
+ if (!props.visible) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, {});
1378
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "qccPwShell", "aria-label": "\u8BBF\u524D\u5C3D\u8C03\u5DE5\u4F5C\u53F0", "data-status": status, children: [
1379
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "qccPwHeader", children: [
1380
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwBrand", children: [
1381
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwBrandIcon", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { name: "briefcase" }) }),
1382
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwBrandCopy", children: [
1383
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwTitleRow", children: [
1384
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { className: "qccPwTitle", children: "\u8BBF\u524D\u5C3D\u8C03\u5DE5\u4F5C\u53F0" }),
1385
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwLiveDot", "data-status": status })
1386
+ ] }),
1387
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "qccPwSubtitle", children: "\u4F01\u67E5\u67E5\u4E8B\u5B9E\u9A71\u52A8 \xB7 \u673A\u4F1A\u4E0E\u98CE\u9669\u53CC\u5F15\u64CE" })
1388
+ ] })
1389
+ ] }),
1390
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwMeta", children: [
1391
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwStatus", "data-status": status, children: STATUS_LABELS[status] }),
1392
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "qccPwSession", children: [
1393
+ "\u5F53\u524D Session \xB7 ",
1394
+ sessionId.slice(0, 12)
1395
+ ] })
1396
+ ] })
1397
+ ] }),
1398
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("nav", { className: "qccPwStages", "aria-label": "\u8BBF\u524D\u4EFB\u52A1\u9636\u6BB5", children: PREVISIT_PHASES.map((current) => {
1399
+ const phaseState = phaseStates.find((item) => item.id === current);
1400
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { type: "button", className: "qccPwStage", "data-selected": phase === current, "data-progress": phaseState?.progress ?? "idle", onClick: () => setPhase(current), children: [
1401
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "qccPwStageIcon", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { name: current }) }),
1402
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "qccPwStageCopy", children: [
1403
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: PHASE_LABELS[current].label }),
1404
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { children: PHASE_LABELS[current].description })
1405
+ ] })
1406
+ ] }, current);
1407
+ }) }),
1408
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwBody", children: [
1409
+ phase === "prepare" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SetupPanel, { sessionId, store: props.shared, task, start: (prompt) => props.startPrompt(sessionId, prompt), onStarted: () => setPhase("opportunity") }) : null,
1410
+ phase === "opportunity" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(OpportunityPanel, { task, status, events: runtime.toolEvents, insights }) : null,
1411
+ phase === "risk" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RiskPanel, { task, status, events: runtime.toolEvents, insights }) : null,
1412
+ phase === "delivery" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DeliveryPanel, { task, status, toolCount: runtime.toolNames.length, failedToolCount: runtime.failedToolCount, cardCaptured: cardText !== null, reportHtml }) : null
1413
+ ] }),
1414
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("footer", { className: "qccPwFooter", children: [
1415
+ /* @__PURE__ */ (0, import_jsx_runtime2.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" }),
1416
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "qccPwFooterActions", children: [
1417
+ phase !== "prepare" && task !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "qccPwSecondary", onClick: newTask, children: "\u65B0\u7684\u5C3D\u8C03" }) : null,
1418
+ phase === "delivery" ? /* @__PURE__ */ (0, import_jsx_runtime2.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
+ "\u4E0B\u8F7D\u62A5\u544A",
1420
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u2193" })
1421
+ ] }) : phase !== "prepare" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { type: "button", className: "qccPwPrimary", onClick: returnToConversation, children: [
1422
+ "\u8FD4\u56DE\u4F1A\u8BDD",
1423
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u2192" })
1424
+ ] }) : null
1425
+ ] })
1426
+ ] })
1427
+ ] });
1428
+ }
1429
+ function installStyles() {
1430
+ if (document.getElementById(STYLE_ID) !== null) {
1431
+ return () => {
1432
+ };
1433
+ }
1434
+ const style = document.createElement("style");
1435
+ style.id = STYLE_ID;
1436
+ style.textContent = WORKBENCH_CSS;
1437
+ document.head.append(style);
1438
+ return () => style.remove();
1439
+ }
1440
+ function apply(ctx) {
1441
+ const service = ctx.betterSidebar;
1442
+ const shared = createPrevisitStore();
1443
+ const startPrompt = async (sessionId, prompt) => {
1444
+ const conversation = ctx.sessions.scope?.(sessionId)?.get("conversation");
1445
+ if (conversation === void 0) throw new Error("conversation unavailable");
1446
+ const baseline = ctx.sessions.binding?.(sessionId)?.session.getSnapshot().nodes?.length ?? 0;
1447
+ await conversation.send(prompt);
1448
+ return baseline;
1449
+ };
1450
+ ctx.effect(
1451
+ () => registerWorkbenchTab(service, (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrevisitWorkbenchTab, { ...props, ctx, shared, startPrompt })),
1452
+ "dsh-pre-duediligence: Better Sidebar tab"
1453
+ );
1454
+ }
1455
+
1456
+ return module.exports;
1457
+ }
1458
+ });