dsh-pre-duediligence 0.1.35 → 0.1.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # 更新日志
2
- ## [Unreleased]
2
+ ## [0.1.37] - 2026-09-15
3
+
4
+ - 简化资料采集“无需执行”清单:仅显示项目名称及可识别的简短原因,不展示内部引用 ID、技术消息或兜底说明;后台审计记录不变。
5
+
6
+ ## [0.1.36] - 2026-09-15
7
+
8
+ - 固定首页引导模板与指纹;向导仅排除未修改模板,未补全占位符不能创建尽调任务;Skill 缺主体先澄清。
9
+ - 访前菜单新建业务 Session 后、打开前,通过原生 setDraft 预填完整引导文案。两次检查草稿、附件、引用、输入修订号;不自动发送、查询或开台。刷新/切回不触发预填,缺少必要快照时跳过。现有 Host 的 IME/焦点严格保证仍不具备,详见兼容记录。
3
10
 
4
11
  ## [0.1.35] - 2026-09-15
5
12
 
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # dsh-pre-duediligence
2
2
 
3
- 0.1.35 分离资料采集与证据核验:采集仅展示来源数据,核验前置风险研判并展示机会假设、支持、反证及证据缺口。支持有真实引用的阶段性风险分级;无需执行项目合并说明。“现场验证”改为“证据验证”,待沟通事项明确为“待客户确认”。保留报告版本、历史回看及离线中文 PDF/Word 导出。详见 [发布说明](docs/RELEASE-0.1.35.md)。
3
+ 0.1.37 分离资料采集与证据核验:采集仅展示来源数据,核验前置风险研判并展示机会假设、支持、反证及证据缺口。支持有真实引用的阶段性风险分级;无需执行项目合并说明。“现场验证”改为“证据验证”,待沟通事项明确为“待客户确认”。保留报告版本、历史回看及离线中文 PDF/Word 导出。详见 [发布说明](docs/RELEASE-0.1.37.md)。
4
4
 
5
5
  ## 安装与三分钟上手
6
6
 
7
7
  访前尽调智能体:面向拜访前调查,提供企业尽调、客户尽调、客户背景调查、工商核验与风险信息整理;使用企查查 MCP,提供固定路由连续调用、主体确认、动态进度和可下载报告。
8
8
 
9
9
  ```sh
10
- dsh plugin --profile web add dsh-pre-duediligence@0.1.35
10
+ dsh plugin --profile web add dsh-pre-duediligence@0.1.37
11
11
  ```
12
12
 
13
13
  请先满足下文的 DSH 与连接器要求;Better Sidebar 仅在需要可视化工作台时选装。安装后完整停止并重启对应 Profile。
@@ -92,7 +92,7 @@ bash <(curl -fsSL https://raw.githubusercontent.com/duhu2000/dsh-pre-duediligenc
92
92
  安装脚本默认向 DSH Web profile 安装两个基础 Bundle:
93
93
 
94
94
  1. `dsh-mcp-connector@0.2.32`:提供通用 MCP 连接器与市场,通过“企查查·企业工商”完成 OAuth,并动态挂载企业、风险、知产、经营、历史和董监高 MCP。
95
- 2. `dsh-pre-duediligence@0.1.35`:提供左侧智能体入口、原生会话首页、提示词生成器、Host 执行门和 Skill。
95
+ 2. `dsh-pre-duediligence@0.1.37`:提供左侧智能体入口、原生会话首页、提示词生成器、Host 执行门和 Skill。
96
96
 
97
97
  默认不会安装 Better Sidebar。需要 Session 级可视化工作台时显式开启:
98
98
 
@@ -120,7 +120,7 @@ dsh web
120
120
 
121
121
  ~~~bash
122
122
  dsh plugin --profile web add dsh-mcp-connector@0.2.32
123
- dsh plugin --profile web add dsh-pre-duediligence@0.1.35 --allow-build=node-pty,dsh-pre-duediligence
123
+ dsh plugin --profile web add dsh-pre-duediligence@0.1.37 --allow-build=node-pty,dsh-pre-duediligence
124
124
  dsh web
125
125
  ~~~
126
126
 
@@ -136,7 +136,7 @@ dsh web
136
136
  dsh plugin --profile web list --depth 0
137
137
  ~~~
138
138
 
139
- 应始终看到所选基线的 Connector 和 `dsh-pre-duediligence@0.1.35`;仅在显式启用或原本已安装时看到 Sidebar。重启 DSH 并连接“企查查·企业工商”后,在左侧菜单点击“访前尽调”进入初始原生会话。无 Sidebar 时可继续生成提示词、回填/发送草稿并在会话中阅读报告;五项流程按钮会提示安装可选工作台。安装 Sidebar 时,右侧工作台初始仍关闭;点击业务按钮可主动打开,正式发送任务被接纳后会自动展开一次。仅回填不会展开,收起后轮询不会重新打开。其右侧“+”菜单不会列出该入口,普通会话保持 DSH 原样。
139
+ 应始终看到所选基线的 Connector 和 `dsh-pre-duediligence@0.1.37`;仅在显式启用或原本已安装时看到 Sidebar。重启 DSH 并连接“企查查·企业工商”后,在左侧菜单点击“访前尽调”进入初始原生会话。无 Sidebar 时可继续生成提示词、回填/发送草稿并在会话中阅读报告;五项流程按钮会提示安装可选工作台。安装 Sidebar 时,右侧工作台初始仍关闭;点击业务按钮可主动打开,正式发送任务被接纳后会自动展开一次。仅回填不会展开,收起后轮询不会重新打开。其右侧“+”菜单不会列出该入口,普通会话保持 DSH 原样。
140
140
 
141
141
  ### 无 Sidebar 功能边界
142
142
 
@@ -1,5 +1,13 @@
1
1
  # 访前尽调兼容与验收记录
2
2
 
3
+ ## Unreleased:原生 setDraft 预填与 UX-49 兼容边界
4
+
5
+ 审计本机 conversation 0.1.2-rc.1 及 npm next 0.1.5-rc.2:公开 InputState 缺少 IME 状态与显式输入就绪快照;setDraft(text) 调用 selectEnd,没有不改变焦点的选项。不能把 plain 提交态解释为非组合态,不能访问标为 package-internal 的 editor 绕过限制。两个版本分别使用 imageIds / attachmentIds,未知附件状态不能假定为空。
6
+
7
+ 按用户收回范围的明确要求,本轮仅在访前菜单成功创建新 Session 后、open 前,通过公开 sessions.scope / conversation.input.for / state.getSnapshot / setDraft 接入预填。参照数据清洗补全的未挂载输入机写入时机,不读取私有 editor、不修改 Host。两次检查 plain、空草稿、draftRev=0、空 imageIds/attachmentIds 和 occurrences;会话已切换或插件卸载则跳过。初始化只在 create 成功分支调用,刷新、重挂载、旧会话及切回不重放,模块内 Set 额外阻止同 ID 重入;没有生产持久化 ledger,也不声称满足完整 UX-49。Host 缺少必要快照时保留空草稿与手动向导。setDraft 无公开 IME/不抢焦点保证,未挂载写入仅缩小影响范围,不能替代严格的 Host 保证。
8
+
9
+ 测试文件 `src/initial-draft.test.ts` 是产品内核隔离测试,非真实宿主验收;`previsit-tools.test.ts` 额外验证占位符不会创建任务或调用 MCP。缺主体由 Skill 澄清,尚未运行真实模型行为验证。
10
+
3
11
  ## 0.1.25:历史阶段与扫描事实(2026-09-13)
4
12
 
5
13
  新增可选 run.result 字段保存有界摘要、经营字段及风险因子。兼容旧记录;不从当前任务填补历史缺失。隔离浏览器覆盖历史清单无导航、历史阶段不跳出历史、扫描命中关注色。真实生产 MCP 不纳入合成测试通过声明。
@@ -1,5 +1,19 @@
1
1
  # DSH-UX-001 采纳与验收记录
2
2
 
3
+ ## Unreleased:原生首页引导接入(UX-49 部分采用)
4
+
5
+ 最终本地复核:40 文件 / 274 测试、typecheck、build 通过;新增入口级主动清空不补填及 A/B 导航竞态回归。npm pack dry-run 通过(99 文件,约 13.93 MB,主要为既有中文字体);未发布 npm。下文 263/272 项记录为开发过程阶段结果,不是最终计数。
6
+
7
+ 引用权威规范 `AI-设计/DSH智能体开发交互规范方案.md` DSH-UX-001 v1.5.6 的 UX-49、第11.1及14节;UX-48 不变。模板 ID 为 `dsh-initial-draft/previsit/1`,正文严格采用第11.1节,SHA-256 在 `src/initial-draft.ts` 固定并测试。
8
+
9
+ 已实现精确模板识别、向导保护、缺项 Skill 澄清、占位符 begin 防御和产品自有初始化内核。内核只接收显式新 Session 事件、消费标记后异步二次快照、revision=0 防输入后清空竞态、存储异常/能力缺失不写入;没有发送、工具或开台能力。内核端口是内部契约,不是虚构的 DSH 公开 API。
10
+
11
+ 2026-09-15 按用户最新范围,已将原生 setDraft 接入新建访前菜单入口,创建后、打开前写入;不在挂载/恢复/切回时补写。保护已有草稿、附件、引用及输入后清空的修订记录,不自动发送、调用业务工具或展开工作台。新增真实入口函数的模拟 Host 测试,当前 `pnpm check` 40 文件 / 272 测试、类型检查和构建通过。尚未完成真实 DSH A/B/legacy/普通会话、IME、四插件组合验证,也无公开 Host 不抢焦点保证及持久化初始化 ledger。详见兼容记录,不能将此范围内实现等同于完整 UX-49 验收。
12
+
13
+ 本地验证(2026-09-15):`pnpm check` 通过,40 个测试文件 / 263 项测试、类型检查与构建通过;`git diff --check` 和 `npm pack --dry-run --ignore-scripts` 通过。`pnpm test:ui` 的 Chrome 首个场景进程未正常退出(status=null,未取得 UI 断言结果),不能计为通过。Skill 通用验证器因 Python 缺少 yaml 依赖未运行成功;仓库 Skill 契约测试已通过。完整门禁尚未通过,未 commit/push/创建 PR,无 PR CI 或真实 DSH 证据。
14
+
15
+ 补充验证:Chrome 崩溃记录显示 SIGABRT,调用栈在 macOS `_RegisterApplication`,不是页面断言失败。通过本地只读 HTTP 服务在隔离浏览器重新加载同一构建的 fixture,浅/深色 × 1440×900、390×700 四组均达到 `uiReady=true`,全部布尔 dataset 断言无 false、菜单/历史/回填及页面无横向溢出通过。这是替代浏览器回归,不改写原命令失败记录,也不是实际 DSH 的 UX-49 验收。Python 临时环境补齐 yaml 后,通用 Skill 验证器拒绝原有 DSH `whenToUse` / `user-invocable` 字段;保持 DSH 元数据不变,以本仓 Skill 契约检查为准,不为通过 Codex 格式检查删改 DSH 属性。
16
+
3
17
  ## 0.1.25:只读历史阶段与事实展示
4
18
 
5
19
  历史导航不改变当前 Session;扫描事实跟随原任务保存。执行成功与风险命中分别展示,不用绿色查询完成暗示企业安全。经营区域使用实际摘要而非固定状态占位。自动发布沿用 main CI → 注释 tag → OIDC npm 发布及 registry 核验。
@@ -0,0 +1,7 @@
1
+ # 0.1.36:访前首页原生引导
2
+
3
+ 点击访前菜单创建新业务会话后,在打开前通过原生 setDraft 预填可编辑的拜访说明。已有文字、附件、引用或输入修订记录时跳过;不自动发送、查询或展开工作台。刷新和切回旧会话不补填。
4
+
5
+ 仅完全未修改的模板从向导和主体提取排除,缺主体先澄清。保留主体绑定、历史与报告终态以及 UX-48。
6
+
7
+ 本地 274 项测试通过。现有宿主缺少公开 IME 与不抢焦点保证,本版未修改宿主;真实 DSH 组合验收尚未完成,详见兼容记录。
@@ -0,0 +1,5 @@
1
+ # 0.1.37:精简无需执行清单
2
+
3
+ 资料采集的“无需执行”仅展示项目名称及可识别的简短原因,例如“本次扫描未发现相关记录”。不展示内部引用 ID、技术消息和缺少原因时的兜底说明。后台审计记录保持不变,不改变风险判断与业务执行逻辑。
4
+
5
+ 保留 0.1.36 的原生首页引导能力及兼容边界。本地类型检查、275 项测试与构建通过。
package/install.sh CHANGED
@@ -5,7 +5,7 @@ set -euo pipefail
5
5
  readonly PROFILE_NAME="${DSH_PROFILE:-web}"
6
6
  readonly BASELINE="${DSH_PREVISIT_BASELINE:-stable}"
7
7
  readonly WORKBENCH_MODE="${DSH_PREVISIT_WORKBENCH:-off}"
8
- readonly PREVISIT_SPEC="${DSH_PRE_DUEDILIGENCE_SPEC:-dsh-pre-duediligence@0.1.35}"
8
+ readonly PREVISIT_SPEC="${DSH_PRE_DUEDILIGENCE_SPEC:-dsh-pre-duediligence@0.1.37}"
9
9
  readonly LEGACY_PREVISIT_NAME="qcc-previsit-dsh"
10
10
  readonly LEGACY_QCC_OAUTH_NAME="qcc-dsh-mcp-oauth"
11
11
 
package/lib/client.js CHANGED
@@ -177,6 +177,74 @@ function installComposerImageBridge(bridge) {
177
177
  // src/plan-card.tsx
178
178
  var import_react = require("react");
179
179
 
180
+ // src/previsit-session.ts
181
+ var PREVISIT_SESSION_ID_PREFIX = "session-dsh-pre-duediligence-";
182
+ function isPrevisitSession(sessionId) {
183
+ return /^session-dsh-pre-duediligence-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(sessionId);
184
+ }
185
+ function resolvePrevisitWorkspaceId(ctx) {
186
+ const workspace = ctx.workspaces?.list?.getSnapshot();
187
+ const current = ctx.sessions.list?.getSnapshot().current;
188
+ const items = workspace?.items ?? [];
189
+ return items.find((item) => current !== void 0 && item.sessionIds?.includes(current))?.workspaceId ?? items.find((item) => item.workspaceId === workspace?.recentWorkspaceId)?.workspaceId ?? items[0]?.workspaceId;
190
+ }
191
+ async function createPrevisitSession(ctx) {
192
+ const workspaceId = resolvePrevisitWorkspaceId(ctx);
193
+ if (!workspaceId) throw new Error("\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u5DE5\u4F5C\u7A7A\u95F4\uFF0C\u518D\u6253\u5F00\u8BBF\u524D\u5C3D\u8C03");
194
+ if (typeof ctx.sessions.create !== "function" || typeof ctx.sessions.open !== "function") {
195
+ throw new Error("\u5F53\u524D DSH \u7248\u672C\u6CA1\u6709\u53EF\u7528\u7684\u4F1A\u8BDD\u521B\u5EFA\u80FD\u529B");
196
+ }
197
+ if (typeof globalThis.crypto?.randomUUID !== "function") {
198
+ throw new Error("\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u5B89\u5168\u4F1A\u8BDD\u6807\u8BC6\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u6700\u65B0\u7248\u6D4F\u89C8\u5668");
199
+ }
200
+ const requested = PREVISIT_SESSION_ID_PREFIX + globalThis.crypto.randomUUID();
201
+ const created = await ctx.sessions.create({ workspaceId, sessionId: requested });
202
+ if (created !== requested) throw new Error("\u8BBF\u524D\u5C3D\u8C03\u4F1A\u8BDD\u6807\u8BC6\u4E0D\u5339\u914D\uFF0C\u8BF7\u91CD\u8BD5");
203
+ return created;
204
+ }
205
+
206
+ // src/session-input.ts
207
+ function resolveSessionInput(host, sessionId) {
208
+ const scope = host.sessions.scope?.(sessionId);
209
+ if (scope === void 0) return void 0;
210
+ const conversation = scope.get("conversation");
211
+ return conversation?.input?.for(scope);
212
+ }
213
+ function writeSessionDraft(actions, text) {
214
+ if (actions === void 0) return false;
215
+ actions.setDraft(text);
216
+ return true;
217
+ }
218
+ function clearSubmittedDraft(input, submitted) {
219
+ if (input?.state.getSnapshot().draft === submitted) input.setDraft("");
220
+ }
221
+
222
+ // src/initial-draft.ts
223
+ var INITIAL_DRAFT_TEXT = "\u8BF7\u5E2E\u6211\u51C6\u5907\u4E00\u6B21\u5BA2\u6237\u62DC\u8BBF\u3002\u8BF7\u586B\u5199\u4F01\u4E1A\u540D\u79F0\u548C\u5173\u6CE8\u91CD\u70B9\uFF0C\u4E5F\u53EF\u70B9\u51FB\u5DE6\u4E0A\u89D2\u300C\u63D0\u793A\u8BCD\u751F\u6210\u300D\u9009\u62E9\u89D2\u8272\u3001\u62DC\u8BBF\u573A\u666F\u548C\u62A5\u544A\u683C\u5F0F\u3002\u4F8B\u5982\uFF1A\u6211\u662F\u94F6\u884C\u5BA2\u6237\u7ECF\u7406\uFF0C\u51C6\u5907\u62DC\u8BBF\u3010\u4F01\u4E1A\u540D\u79F0\u3011\uFF0C\u91CD\u70B9\u4E86\u89E3\u7ECF\u8425\u60C5\u51B5\u4E0E\u98CE\u9669\uFF0C\u751F\u6210\u8BBF\u524D\u7B80\u62A5\u3002";
224
+ var isInitialDraft = (text) => text === INITIAL_DRAFT_TEXT;
225
+ var hasUnfilledPlaceholder = (text) => /【[^】]*】/u.test(text);
226
+ var attemptedEntries = /* @__PURE__ */ new Set();
227
+ async function prefillCreatedPrevisitSession(host, sessionId, entryStillCurrent) {
228
+ if (!isPrevisitSession(sessionId) || attemptedEntries.has(sessionId)) return false;
229
+ attemptedEntries.add(sessionId);
230
+ try {
231
+ const input = resolveSessionInput(host, sessionId);
232
+ if (!input || !entryStillCurrent()) return false;
233
+ const empty = () => {
234
+ const s = input.state.getSnapshot();
235
+ const attachments = s.attachmentIds ?? s.imageIds;
236
+ return entryStillCurrent() && s.phase === "plain" && s.draft === "" && s.draftRev === 0 && Array.isArray(attachments) && attachments.length === 0 && Array.isArray(s.occurrences) && s.occurrences.length === 0;
237
+ };
238
+ if (!empty()) return false;
239
+ await Promise.resolve();
240
+ if (!empty()) return false;
241
+ input.setDraft(INITIAL_DRAFT_TEXT);
242
+ return input.state.getSnapshot().draft === INITIAL_DRAFT_TEXT;
243
+ } catch {
244
+ return false;
245
+ }
246
+ }
247
+
180
248
  // src/composer-model.ts
181
249
  var COMPANY_PLACEHOLDER = "\uFF08\u8FD9\u91CC\u8F93\u5165\u4F01\u4E1A\u540D\uFF09";
182
250
  var ROLE_OPTIONS = [
@@ -235,6 +303,7 @@ function hasSelection(selection) {
235
303
  return selection.role !== void 0 || selection.purpose !== void 0 || selection.focus.length > 0 || selection.budget !== void 0 || selection.output !== void 0;
236
304
  }
237
305
  function routePrevisitPrompt(text) {
306
+ if (isInitialDraft(text) || hasUnfilledPlaceholder(text)) return text;
238
307
  if (!text.trim() || text.includes("\u8BF7\u4F7F\u7528 qcc-previsit-onepager")) return text;
239
308
  return text + "\n\u8BF7\u4F7F\u7528 qcc-previsit-onepager Skill \u6267\u884C\u8BBF\u524D\u5C3D\u8C03\uFF1B\u6295\u8D44\u673A\u6784\u89D2\u8272\u3001\u6DF1\u5EA6\u5C3D\u8C03\u548C\u5B8C\u6574\u62A5\u544A\u4E5F\u6CBF\u7528\u672C\u6D41\u7A0B\uFF0C\u4E0D\u5207\u6362\u4E3A ic-memo-qcc\u3002\u5148 previsit_begin\uFF0C\u518D\u901A\u8FC7 previsit_query \u7684 entity_search \u6838\u5B9E\u4E3B\u4F53\uFF0C\u4F7F\u7528 previsit_confirm_entity \u7ED1\u5B9A\u540E\u7EE7\u7EED\u67E5\u8BE2\u3002";
240
309
  }
@@ -337,7 +406,7 @@ function validateComposerText(text) {
337
406
  if (normalized === "") {
338
407
  return "\u8BF7\u8BF4\u660E\u8981\u62DC\u8BBF\u7684\u4F01\u4E1A";
339
408
  }
340
- if (normalized.includes(COMPANY_PLACEHOLDER)) {
409
+ if (normalized.includes(COMPANY_PLACEHOLDER) || hasUnfilledPlaceholder(text)) {
341
410
  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";
342
411
  }
343
412
  return void 0;
@@ -356,32 +425,6 @@ function serializePrevisitRequest(text, taskId) {
356
425
  ].join("\n");
357
426
  }
358
427
 
359
- // src/previsit-session.ts
360
- var PREVISIT_SESSION_ID_PREFIX = "session-dsh-pre-duediligence-";
361
- function isPrevisitSession(sessionId) {
362
- return /^session-dsh-pre-duediligence-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(sessionId);
363
- }
364
- function resolvePrevisitWorkspaceId(ctx) {
365
- const workspace = ctx.workspaces?.list?.getSnapshot();
366
- const current = ctx.sessions.list?.getSnapshot().current;
367
- const items = workspace?.items ?? [];
368
- return items.find((item) => current !== void 0 && item.sessionIds?.includes(current))?.workspaceId ?? items.find((item) => item.workspaceId === workspace?.recentWorkspaceId)?.workspaceId ?? items[0]?.workspaceId;
369
- }
370
- async function createPrevisitSession(ctx) {
371
- const workspaceId = resolvePrevisitWorkspaceId(ctx);
372
- if (!workspaceId) throw new Error("\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u5DE5\u4F5C\u7A7A\u95F4\uFF0C\u518D\u6253\u5F00\u8BBF\u524D\u5C3D\u8C03");
373
- if (typeof ctx.sessions.create !== "function" || typeof ctx.sessions.open !== "function") {
374
- throw new Error("\u5F53\u524D DSH \u7248\u672C\u6CA1\u6709\u53EF\u7528\u7684\u4F1A\u8BDD\u521B\u5EFA\u80FD\u529B");
375
- }
376
- if (typeof globalThis.crypto?.randomUUID !== "function") {
377
- throw new Error("\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u5B89\u5168\u4F1A\u8BDD\u6807\u8BC6\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u6700\u65B0\u7248\u6D4F\u89C8\u5668");
378
- }
379
- const requested = PREVISIT_SESSION_ID_PREFIX + globalThis.crypto.randomUUID();
380
- const created = await ctx.sessions.create({ workspaceId, sessionId: requested });
381
- if (created !== requested) throw new Error("\u8BBF\u524D\u5C3D\u8C03\u4F1A\u8BDD\u6807\u8BC6\u4E0D\u5339\u914D\uFF0C\u8BF7\u91CD\u8BD5");
382
- return created;
383
- }
384
-
385
428
  // src/report-time.ts
386
429
  function formatReportTime(value) {
387
430
  if (!value) return "";
@@ -1500,13 +1543,8 @@ function CollectionCards({ task, verification = false }) {
1500
1543
  ] }),
1501
1544
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { children: skipped.map((run) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
1502
1545
  dimensionLabel(run.dimension),
1503
- "\uFF1A",
1504
- run.message || "\u5DF2\u8BB0\u5F55\u65E0\u9700\u6267\u884C\uFF0C\u5177\u4F53\u539F\u56E0\u89C1\u539F\u4EFB\u52A1",
1505
- "\uFF08\u5F15\u7528 ",
1506
- run.id,
1507
- "\uFF09"
1508
- ] }, run.id)) }),
1509
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "qccPwNote", children: "\u65E0\u9700\u4E0B\u94BB\u4E0D\u4EE3\u8868\u98CE\u9669\u7EDD\u5BF9\u4E0D\u5B58\u5728\u3002" })
1546
+ ["\u98CE\u9669\u626B\u63CF\u4E3A 0\uFF0C\u65E0\u9700\u4E0B\u94BB", "\u626B\u63CF\u8BA1\u6570\u4E3A0\uFF0C\u65E0\u9700\u4E0B\u94BB"].includes(run.message ?? "") ? "\uFF1A\u672C\u6B21\u626B\u63CF\u672A\u53D1\u73B0\u76F8\u5173\u8BB0\u5F55" : null
1547
+ ] }, run.id)) })
1510
1548
  ] }) : null
1511
1549
  ] });
1512
1550
  }
@@ -1867,22 +1905,6 @@ function summarizeSelection(state, labels2) {
1867
1905
  return out;
1868
1906
  }
1869
1907
 
1870
- // src/session-input.ts
1871
- function resolveSessionInput(host, sessionId) {
1872
- const scope = host.sessions.scope?.(sessionId);
1873
- if (scope === void 0) return void 0;
1874
- const conversation = scope.get("conversation");
1875
- return conversation?.input?.for(scope);
1876
- }
1877
- function writeSessionDraft(actions, text) {
1878
- if (actions === void 0) return false;
1879
- actions.setDraft(text);
1880
- return true;
1881
- }
1882
- function clearSubmittedDraft(input, submitted) {
1883
- if (input?.state.getSnapshot().draft === submitted) input.setDraft("");
1884
- }
1885
-
1886
1908
  // src/previsit-dock.tsx
1887
1909
  var import_jsx_runtime8 = require("react/jsx-runtime");
1888
1910
  function writeDraft(actions, text) {
@@ -2174,7 +2196,7 @@ var import_react5 = require("react");
2174
2196
  var import_react_dom2 = require("react-dom");
2175
2197
  var import_jsx_runtime9 = require("react/jsx-runtime");
2176
2198
  function mergePromptDraft(existing, generated, mode) {
2177
- if (mode === "replace" || existing.trim() === "") return generated;
2199
+ if (mode === "replace" || existing.trim() === "" || isInitialDraft(existing)) return generated;
2178
2200
  const separator = existing.endsWith("\n") ? "" : "\n";
2179
2201
  return existing + separator + generated;
2180
2202
  }
@@ -2322,7 +2344,7 @@ function PrevisitPromptGenerator(props) {
2322
2344
  setError("\u8BF7\u81F3\u5C11\u586B\u5199\u4F01\u4E1A\u4FE1\u606F\u3002");
2323
2345
  return;
2324
2346
  }
2325
- if (draft.trim() !== "" && draft.trim() !== generated.trim()) {
2347
+ if (draft.trim() !== "" && !isInitialDraft(draft) && draft.trim() !== generated.trim()) {
2326
2348
  setConflict(true);
2327
2349
  return;
2328
2350
  }
@@ -2601,6 +2623,7 @@ function registerLeftSidebarLauncher(ctx, isActive = () => true) {
2601
2623
  openAgent: async () => {
2602
2624
  const previous = ctx.sessions.list?.getSnapshot().current;
2603
2625
  const sessionId = await createPrevisitSession(ctx);
2626
+ await prefillCreatedPrevisitSession(ctx, sessionId, () => isActive() && ctx.sessions.list?.getSnapshot().current === previous && previous !== sessionId);
2604
2627
  if (isActive() && ctx.sessions.list?.getSnapshot().current === previous) ctx.sessions.open?.(sessionId);
2605
2628
  }
2606
2629
  })
package/lib/index.js CHANGED
@@ -3,6 +3,11 @@ function isPrevisitSession(sessionId) {
3
3
  return /^session-dsh-pre-duediligence-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(sessionId);
4
4
  }
5
5
 
6
+ // src/initial-draft.ts
7
+ var INITIAL_DRAFT_TEXT = "\u8BF7\u5E2E\u6211\u51C6\u5907\u4E00\u6B21\u5BA2\u6237\u62DC\u8BBF\u3002\u8BF7\u586B\u5199\u4F01\u4E1A\u540D\u79F0\u548C\u5173\u6CE8\u91CD\u70B9\uFF0C\u4E5F\u53EF\u70B9\u51FB\u5DE6\u4E0A\u89D2\u300C\u63D0\u793A\u8BCD\u751F\u6210\u300D\u9009\u62E9\u89D2\u8272\u3001\u62DC\u8BBF\u573A\u666F\u548C\u62A5\u544A\u683C\u5F0F\u3002\u4F8B\u5982\uFF1A\u6211\u662F\u94F6\u884C\u5BA2\u6237\u7ECF\u7406\uFF0C\u51C6\u5907\u62DC\u8BBF\u3010\u4F01\u4E1A\u540D\u79F0\u3011\uFF0C\u91CD\u70B9\u4E86\u89E3\u7ECF\u8425\u60C5\u51B5\u4E0E\u98CE\u9669\uFF0C\u751F\u6210\u8BBF\u524D\u7B80\u62A5\u3002";
8
+ var isInitialDraft = (text) => text === INITIAL_DRAFT_TEXT;
9
+ var hasUnfilledPlaceholder = (text) => /【[^】]*】/u.test(text);
10
+
6
11
  // src/image-intake.ts
7
12
  import { randomUUID } from "node:crypto";
8
13
  import { mkdir, rmdir, unlink, writeFile } from "node:fs/promises";
@@ -47,6 +52,7 @@ var COMPANY_RE = new RegExp(`[\\p{Script=Han}A-Za-z0-9\uFF08\uFF09()\xB7&\uFF0B+
47
52
  var HEADER_RE = /^(?:序号|企业名称|公司名称|单位名称|统一社会信用代码|信用代码|注册号|名称|企业名单)$/i;
48
53
  var cleanCell = (value) => value.replace(/^\s*(?:[-•·●▪◦]|\d{1,4}[.)、::]?)\s*/, "").replace(/^(?:企业名称|公司名称|单位名称)\s*[::]\s*/i, "").replace(/[\s ]+/g, "").trim();
49
54
  function extractCompanyNames(text, max = IMAGE_LIMITS.maxEntries) {
55
+ if (isInitialDraft(text)) return [];
50
56
  const out = [];
51
57
  const seen = /* @__PURE__ */ new Set();
52
58
  for (const rawLine of text.split(/\r?\n/)) {
@@ -1591,6 +1597,9 @@ function registerPrevisitTools(ctx, workflow = new PrevisitWorkflowStore(), opti
1591
1597
  entities: { type: "integer", minimum: 1, maximum: 50 }
1592
1598
  }, ["query", "depth"], async (args, exec, agent) => {
1593
1599
  const query = string(args.query);
1600
+ if (!query.trim() || isInitialDraft(query) || hasUnfilledPlaceholder(query) || query.includes("\uFF08\u8FD9\u91CC\u8F93\u5165\u4F01\u4E1A\u540D\uFF09")) {
1601
+ throw new Error("\u8BF7\u5148\u63D0\u4F9B\u4F01\u4E1A\u540D\u79F0\u3001\u7B80\u79F0\u6216\u7EDF\u4E00\u793E\u4F1A\u4FE1\u7528\u4EE3\u7801\uFF0C\u5E76\u66FF\u6362\u672A\u586B\u5199\u7684\u5360\u4F4D\u7B26\uFF1B\u5C1A\u672A\u521B\u5EFA\u5C3D\u8C03\u4EFB\u52A1\u6216\u67E5\u8BE2\u4F01\u4E1A\u6570\u636E\u3002");
1602
+ }
1594
1603
  const depth = string(args.depth);
1595
1604
  if (!Object.hasOwn(DEPTHS, depth)) throw new Error("\u65E0\u6548\u5C3D\u8C03\u6863\u4F4D");
1596
1605
  const owner = ownerOf(agent);
@@ -1918,7 +1927,7 @@ function loadBundledSkill() {
1918
1927
  },
1919
1928
  metadata: {
1920
1929
  author: "QCC",
1921
- version: "0.1.35",
1930
+ version: "0.1.37",
1922
1931
  industry: "enterprise-services",
1923
1932
  mcpServers: ["qcc-company", "qcc-risk", "qcc-ipr", "qcc-operation", "qcc-executive"]
1924
1933
  }