@xqyz/xq-cli 0.3.0 → 0.3.1

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
@@ -10,12 +10,18 @@
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
- ### WorkBuddy
13
+ ### xq-cli `0.3.1` / WorkBuddy `0.10.1`
14
+
15
+ - 修复普通项目在后端 `task_status=6`(文件解析中)时被误判为多标包/EPC,导致没有调用正常大纲生成接口、任务长时间停留在解析状态的问题。
16
+ - 轮询 GET 请求统一增加网络重试,并识别 `stream has been aborted`、连接提前关闭等瞬时传输错误;不会因一次流中断误报生成失败。
17
+ - WorkBuddy 对大纲阶段的传输中断保留同一 `cid` 继续核验,禁止重复创建任务;新增回归测试覆盖该恢复路径。
18
+ - 本次配套版本:`@xqyz/xq-cli@0.3.1`、`@xqyz/workbuddy-plugin-xique@0.10.1`、Connector `0.10.1`。
14
19
 
15
- - 修复计划模式默认值:未提供 `planMode` 时明确使用快速(`--plan-mode 0`),用户明确选择规划时保留 `--plan-mode 1`,不再发生模式被错误回退的问题。
16
- - 准备发布 WorkBuddy Plugin/Connector `0.9.4`:恢复配置页“计划模式=快速/规划”选择,并将用户选择原样传递给 xq-cli。
17
- - 统一 Skill、安装脚本、MCP Server Connector 的版本指向,避免继续加载 `0.9.3` 的快速模式固定包。
18
- - 新增 [版本与迭代记录](./docs/VERSION-HISTORY.md),记录 xq-cli、Plugin、Connector 的功能、依赖、测试和发布结果。
20
+ ### WorkBuddy / SkillHub(待发布)
21
+
22
+ - 修复 SkillHub 旧版 Skill 将用户明确选择的“规划”强制改为“快速”的规则冲突;规划模式现在必须传递 `--plan-mode 1`。
23
+ - 增加 Skill 文案回归断言,禁止再次出现“固定使用计划模式=快速”或“不得接受规划模式”。
24
+ - 发布清单新增 SkillHub 同步、客户本地更新和新会话验收步骤,避免 npm Plugin 与 SkillHub Skill 版本脱节。
19
25
 
20
26
  ## [0.3.0] - 2026-08-14
21
27
 
@@ -26,6 +32,14 @@
26
32
  - AI 大纲候选不再生成本地伪章节 ID;最终保存请求与前端一致,仅提交章节内容、主题、重要度和续写标记,交由后台分配节点 ID。
27
33
  - 增加规划模式模拟 API 回归测试,覆盖意见提交、AI 候选不提前落库、候选确认和最终目录生成的顺序。
28
34
 
35
+ ## [0.10.0] - 2026-08-14
36
+
37
+ ### WorkBuddy
38
+
39
+ - 固定依赖 `@xqyz/xq-cli@0.3.0`,支持完整规划模式命令链。
40
+ - 更新 Skill、安装脚本、MCP Server、MCP App 和 Connector 启动参数到 `0.10.0`。
41
+ - 通过 32 项 WorkBuddy 功能测试和 npm 包冒烟测试;npm `latest` 已指向 `0.10.0`。
42
+
29
43
  ## [0.2.1] - 2026-08-11
30
44
 
31
45
  ### 安全性
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xqyz/xq-cli",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "CLI for xique bid-book task workflows",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/cli.mjs CHANGED
@@ -1853,8 +1853,16 @@ async function triggerOutlineGeneration(client, snapshot, params) {
1853
1853
  await setPlanModePhase(client, params.cid, 1);
1854
1854
  }
1855
1855
 
1856
- const hasTaskStatus = snapshot.task_status !== undefined && snapshot.task_status !== null;
1857
- if (hasTaskStatus && Number(snapshot.task_status) !== 0) {
1856
+ // task_status=6 means "file parsing" in the Xique backend. It is not a
1857
+ // signal that this is a multi-bid/EPC task. Only route through the
1858
+ // special-selection endpoint when the caller actually supplied a
1859
+ // multi-bid or EPC selection; ordinary tasks must use the normal
1860
+ // generation endpoint even while the task is transitioning from parse.
1861
+ const hasSpecialSelection = Boolean(
1862
+ String(params.multiBidId ?? snapshot.multiBidId ?? '').trim()
1863
+ || String(params.epcEngineerType ?? snapshot.epcEngineerType ?? '').trim()
1864
+ );
1865
+ if (hasSpecialSelection) {
1858
1866
  await getJson(client, '/proxy/multiBiddingChoice', compactObject({
1859
1867
  uuid: snapshot.uuid,
1860
1868
  multiBidId: params.multiBidId ?? snapshot.multiBidId,
@@ -2760,7 +2768,23 @@ function isContentRunningOrDone(detail) {
2760
2768
  async function pollUntil(checkFn, options) {
2761
2769
  const startedAt = Date.now();
2762
2770
  while (true) {
2763
- const result = await checkFn();
2771
+ let result;
2772
+ try {
2773
+ result = await checkFn();
2774
+ } catch (error) {
2775
+ // A transient connection reset must not turn an already accepted
2776
+ // asynchronous backend task into a false failure. Read requests
2777
+ // are retried by getJson; this catch keeps polling the same cid
2778
+ // when a response stream still closes during that retry window.
2779
+ if (!isRetryableNetworkError(error)) {
2780
+ throw error;
2781
+ }
2782
+ result = {
2783
+ done: false,
2784
+ data: null,
2785
+ progressLabel: `transient network error; retrying (${String(error?.message || error)})`,
2786
+ };
2787
+ }
2764
2788
  if (result.done) {
2765
2789
  return result.data;
2766
2790
  }
@@ -3908,7 +3932,10 @@ function normalizeApiKey(value) {
3908
3932
  async function getJson(client, url, params = {}, options = {}) {
3909
3933
  const response = await requestWithRetry(async () => {
3910
3934
  return client.get(url, { params });
3911
- }, options);
3935
+ }, {
3936
+ retries: DEFAULT_RETRY_COUNT,
3937
+ ...options,
3938
+ });
3912
3939
  return unwrapApiResponse(response);
3913
3940
  }
3914
3941
 
@@ -3964,7 +3991,7 @@ function isRetryableNetworkError(error) {
3964
3991
  if (RETRYABLE_NETWORK_CODES.has(code)) {
3965
3992
  return true;
3966
3993
  }
3967
- return /socket disconnected|econnreset|tls connection|network error|timeout/i.test(message);
3994
+ return /socket disconnected|econnreset|tls connection|network error|timeout|stream has been aborted|socket hang up|premature close|aborted/i.test(message);
3968
3995
  }
3969
3996
 
3970
3997
  function unwrapApiResponse(response) {