kld-sdd 2.8.0 → 2.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kld-sdd",
3
- "version": "2.8.0",
3
+ "version": "2.8.1",
4
4
  "description": "KLD SDD OpenSpec 项目初始化工具 - 一键部署 SDD skills",
5
5
  "main": "lib/init.js",
6
6
  "bin": {
@@ -266,7 +266,7 @@ function initKbConfig(specRoot, args = {}) {
266
266
  throw new Error('KB apiKey 未配置(kb-state.json 中缺少 apiKey)。');
267
267
  }
268
268
  if (!kbParams.spaceId || !kbParams.kbId) {
269
- throw new Error('KB targets 未配置(kb-state.json 中缺少 targets[0].spaceId/kbId)。');
269
+ throw new Error('KB 上传目标未配置(请检查 kb-state.json 的 targets 与 uploadTarget)。');
270
270
  }
271
271
 
272
272
  // 4. 校验 project_id 与 spaceKey 一致性
@@ -41,11 +41,26 @@ const {
41
41
 
42
42
  function resolveUploadTarget(state, options = {}) {
43
43
  if (Boolean(options.spaceId) !== Boolean(options.kbId)) throw new Error('必须同时指定 --space-id 和 --kb-id');
44
- const targets = state.targets || [];
44
+ const targets = Array.isArray(state?.targets) ? state.targets : [];
45
45
  if (options.spaceId && options.kbId) {
46
46
  return targets.find(t => t.spaceId === options.spaceId && t.kbId === options.kbId) || options;
47
47
  }
48
- if (targets.length !== 1) throw new Error('请明确上传目标:配置一个知识库,或同时指定 --space-id 和 --kb-id;不会自动分发到多个 KB');
48
+
49
+ const configured = state?.uploadTarget;
50
+ if (configured != null) {
51
+ if (!configured.spaceId || !configured.kbId) {
52
+ throw new Error('kb-state.json 的 uploadTarget 不完整,请在 SDD 助手中重新选择 Spec 上传知识库');
53
+ }
54
+ const selected = targets.find(t => t.spaceId === configured.spaceId && t.kbId === configured.kbId);
55
+ if (!selected) {
56
+ throw new Error('kb-state.json 的 uploadTarget 已不在 targets 读取范围中,请在 SDD 助手中重新选择 Spec 上传知识库');
57
+ }
58
+ return selected;
59
+ }
60
+
61
+ if (targets.length !== 1) {
62
+ throw new Error('请明确上传目标:在 SDD 助手中选择“Spec 上传知识库”,或同时指定 --space-id 和 --kb-id;不会自动分发到多个 KB');
63
+ }
49
64
  if (!targets[0].spaceId || !targets[0].kbId) throw new Error('知识库目标缺少 spaceId/kbId');
50
65
  return targets[0];
51
66
  }
@@ -223,7 +238,7 @@ function preCheckProjectId(projectId, state, selectedTarget) {
223
238
  }
224
239
  const spaceKey = (selectedTarget || resolveUploadTarget(state)).spaceKey;
225
240
  if (!spaceKey) {
226
- console.warn('⚠️ kb-state.json targets[0].spaceKey 为空,跳过本地预检');
241
+ console.warn('⚠️ kb-state.json 的上传目标缺少 spaceKey,跳过本地预检');
227
242
  return;
228
243
  }
229
244
  if (projectId !== spaceKey) {
@@ -37,6 +37,7 @@ allowed-tools:
37
37
  | 首次配置 | 输入 API Key → 选择 Space/KB → 创建 project-identity.json |
38
38
  | 更换 API Key | 清空 apiKey,重新输入并验证当前目标权限 |
39
39
  | 更换知识库 | 清空 targets,重新选择 Space/KB |
40
+ | 指定上传知识库 | 从已选知识库中指定唯一的 Spec 写入位置;查询范围仍可多选 |
40
41
  | 查看当前配置 | 展示已配置的 Space/KB 列表与团队项目身份 |
41
42
  | 校验配置 | 探活 API + 校验 project_id 与 spaceKey 一致 |
42
43
 
@@ -107,6 +108,13 @@ SPEC_ROOT=$(node <spec-package>/skywalk-sdd/spec-root.cjs)
107
108
  2. 对每个相关 space:`GET $API/v1/spaces/{spaceId}/knowledge-bases`
108
109
  3. 向用户展示「空间名 / spaceId → KB 名 / kbId」清单,**允许多选**。
109
110
  4. 写入 `targets: [{ spaceId, spaceName, spaceKey, kbId, kbName }, …]`。
111
+ 5. `targets` 只有一个时,自动把它写入 `uploadTarget: { spaceId, kbId }`;有多个时,
112
+ 让用户从已选列表中指定一个“Spec 上传知识库”,再写入 `uploadTarget`。
113
+ `uploadTarget` 只决定写入位置,不缩小查询可用的 `targets`。
114
+
115
+ > 更新 `targets` 时必须同时校验 `uploadTarget`:它仍在列表中则保留;已被取消选择则清空并
116
+ > 立即让用户重新指定,禁止默选新的首项。旧版单目标配置没有 `uploadTarget` 时继续兼容,
117
+ > 入库器会使用唯一目标;旧版多目标配置必须补选后才能上传。
110
118
 
111
119
  > **API 返回字段说明**(临时脚本中注意字段名):
112
120
  > - Space 列表返回 `spaceId`(camelCase),不是 `id`。临时脚本中使用 `s.spaceId || s.id` 兼容。
@@ -145,13 +153,14 @@ SPEC_ROOT=$(node <spec-package>/skywalk-sdd/spec-root.cjs)
145
153
 
146
154
  ### 5. 校验配置(保存后执行)
147
155
 
148
- 1. `targets` 可保存多个连接目标。单个目标可直接使用;多个目标时,按用户本次指定的
149
- Space/KB 选择,查询、同步和上传同时传 `--space-id`、`--kb-id`。缺少明确选择时询问本次
150
- 目标,**不默选首项,不自动广播**。跨目标查询逐个执行并保留来源。
156
+ 1. `targets` 可保存多个查询目标;查询时按用户本次意图逐个选择并保留来源。
157
+ 上传和入库身份同步默认读取 `uploadTarget`,无需每次重新询问或拼接 `--space-id`、`--kb-id`。
158
+ 用户明确要求临时改投其他目标时,才用成对参数覆盖。任何场景都不默选首项、不自动广播。
151
159
  2. 对本次目标运行 `context-client.cjs --check-only`,说明可达性、权限与检索通道状态。
152
160
  断连仍允许本地编写、测试和归档,远程基线核对与正式发布保持未完成。
153
161
 
154
- 可用目标只有一个且信息完整时,不添加确认步骤。多目标选择可沿用本轮用户已明确的选择;不用额外持久化一套“默认目标”状态。
162
+ 可用目标只有一个且信息完整时,不添加确认步骤。多目标查询可沿用本轮用户已明确的选择;
163
+ 上传目标必须持久化为 `uploadTarget`,供 Skill 和 `kb-upload.cjs` 在后续会话中直接读取。
155
164
 
156
165
  ## 团队项目身份
157
166
 
@@ -184,6 +193,7 @@ SPEC_ROOT=$(node <spec-package>/skywalk-sdd/spec-root.cjs)
184
193
  - 目标 Space/KB:
185
194
  1. {spaceName}(spaceKey: {spaceKey})→ {kbName}
186
195
  2. ...
196
+ - Spec 上传知识库:{spaceName} → {kbName / 未指定}
187
197
  - project-identity.json:{已存在 / 不存在}(project_id: {值})
188
198
  - 授权/就绪:{context-client.cjs --check-only 结果}
189
199
  ```
@@ -202,5 +212,6 @@ SPEC_ROOT=$(node <spec-package>/skywalk-sdd/spec-root.cjs)
202
212
 
203
213
  - 无 `apiKey` 不得猜密钥、不得改走 login;不调用 `/auth/login` 换取另一身份。
204
214
  - 无 `targets` 不得臆造 spaceId/kbId;不猜目标 ID。
215
+ - 多个 `targets` 且无有效 `uploadTarget` 时不得上传,也不得使用 `targets[0]` 代替用户选择。
205
216
  - 完整 apiKey 只写共享 state 文件(`kb-state.json`,spec 仓根目录);聊天里最多显示前缀。
206
217
  - **共享状态**:state 文件与 `opsx-ontology-query`、`opsx-kb-ingest`、`kb-upload` 共用。配置一次,全部生效。
@@ -21,7 +21,11 @@
21
21
  "kbId": "uuid",
22
22
  "kbName": "默认知识库"
23
23
  }
24
- ]
24
+ ],
25
+ "uploadTarget": {
26
+ "spaceId": "uuid",
27
+ "kbId": "uuid"
28
+ }
25
29
  }
26
30
  ```
27
31
 
@@ -33,6 +37,7 @@
33
37
  | `projectName` | 否 | 历史兼容字段;当前配置流程不要求填写,不作为七种 Skill 使用统计或业务归属依据 |
34
38
  | `scopes` | 建议 | API Client scope 列表 |
35
39
  | `targets` | 操作前必填 | 多选;可为空仅当尚未完成选择 |
40
+ | `uploadTarget` | 多目标上传前必填 | Spec 的唯一写入位置,必须引用 `targets` 中的一项;不影响多目标查询 |
36
41
  | `updatedAt` | 建议 | ISO-8601 |
37
42
 
38
43
  ## 监控与入库分别验证
@@ -93,7 +98,7 @@ GET $API/v1/spaces?tenantKey=$TENANT_KEY
93
98
  GET $API/v1/spaces/{spaceId}/knowledge-bases
94
99
  ```
95
100
 
96
- API Key 的可见范围以实际授权结果为准,可被限制到特定 Space;不能因为配置多个 targets 就认为已获得各目标权限。多个目标必须显式选择,完整目标通过 `--space-id` 与 `--kb-id` 一起传入。
101
+ API Key 的可见范围以实际授权结果为准,可被限制到特定 Space;不能因为配置多个 targets 就认为已获得各目标权限。查询目标按本次意图明确选择;上传默认读取 `uploadTarget`,只有临时覆盖时才同时传 `--space-id` 与 `--kb-id`。
97
102
 
98
103
  ### 响应字段映射(重要)
99
104
 
@@ -28,12 +28,22 @@ description: >-
28
28
  Task Progress:
29
29
  - [ ] 1. 读 kb-state.json(spec 仓根目录)
30
30
  - [ ] 2. 无 apiKey 或无 targets → 提示用户运行 /opsx-kb-config 配置知识库
31
- - [ ] 3. 有配置 → 按意图执行入库操作(上传 / 查状态 / 列表 / 重试)
32
- - [ ] 4. 按模板输出结果
31
+ - [ ] 3. 解析上传目标:优先 `uploadTarget`;旧单目标配置兼容;多目标但未指定则停止并提示配置
32
+ - [ ] 4. 有配置 → 按意图执行入库操作(上传 / 查状态 / 列表 / 重试)
33
+ - [ ] 5. 按模板输出结果
33
34
  ```
34
35
 
35
36
  > **KB 配置**(API Key、Space/KB 选择、project-identity.json)由 `opsx-kb-config` 统一负责。如用户需要配置或更换 KB,请引导运行 `/opsx-kb-config`。
36
37
 
38
+ ### 上传目标解析(必须遵守)
39
+
40
+ 1. 用户本次明确同时提供 `--space-id` 与 `--kb-id` 时,作为临时覆盖目标。
41
+ 2. 否则读取 `kb-state.json.uploadTarget`,并确认它仍对应 `targets` 中的一项。
42
+ 3. 历史配置只有一个 `targets` 且没有 `uploadTarget` 时,兼容使用该唯一目标。
43
+ 4. 多个 `targets` 但没有有效 `uploadTarget` 时停止上传,提示在 SDD 助手中选择“Spec 上传知识库”。
44
+
45
+ 禁止直接使用 `targets[0]`,禁止把 Spec 自动广播到多个知识库。调用 `kb-upload.cjs` 时默认不再重复拼接目标参数;脚本会按同一规则读取共享配置。
46
+
37
47
  ### 4. 入库操作
38
48
 
39
49
  路径前缀:`/api/v1/spaces/{spaceId}/knowledge-bases/{kbId}/ingestions`
@@ -196,7 +206,7 @@ node skywalk-sdd/kb-sync-identity.cjs \
196
206
  - 已发布内容修改后,先同步所有受影响文件,再上传。禁止删除 ontology/artifacts 或重建身份以绕过冲突。
197
207
  - 完整 UUID 保留原值,旧短 ID 继续兼容;不得截断真实 UUID。
198
208
 
199
- 上传回执需分别检查事实保存、`publication_status` 和索引状态。HTTP 200 不是成功证明;多 KB 时明确本次 `--space-id` 与 `--kb-id`,不自动广播。
209
+ 上传回执需分别检查事实保存、`publication_status` 和索引状态。HTTP 200 不是成功证明;多 KB 时默认使用配置中的 `uploadTarget`,不自动广播。
200
210
 
201
211
  **其他影响入库的因素**:
202
212
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  需要鉴权细节、state 字段或 Archive Package 规格时再读。
4
4
 
5
- ## `.local/state.json`
5
+ ## `kb-state.json`
6
6
 
7
- 路径:`skills/opsx-kb-ingest/.local/state.json`(已 gitignore)。
7
+ 路径:`<spec-root>/kb-state.json`(已 gitignore,所有 KB Skills 共用的唯一权威配置)。
8
8
 
9
9
  ```json
10
10
  {
@@ -20,7 +20,11 @@
20
20
  "kbId": "uuid",
21
21
  "kbName": "默认知识库"
22
22
  }
23
- ]
23
+ ],
24
+ "uploadTarget": {
25
+ "spaceId": "uuid",
26
+ "kbId": "uuid"
27
+ }
24
28
  }
25
29
  ```
26
30
 
@@ -30,6 +34,7 @@
30
34
  | `tenantKey` | 是 | 列空间用;默认 `default` |
31
35
  | `apiKey` | 是 | 控制台创建的 `sk_sdd_…`,scope 至少 `archive:ingest` |
32
36
  | `targets` | 操作前必填 | 多选;可为空仅当尚未完成选择 |
37
+ | `uploadTarget` | 多目标上传前必填 | 默认写入位置,必须引用 `targets` 中的一项;旧单目标配置可省略 |
33
38
  | `updatedAt` | 建议 | ISO-8601 |
34
39
 
35
40
  示例(无密钥)见 [state.example.json](state.example.json)。
@@ -233,8 +238,11 @@ node skywalk-sdd/kb-upload.cjs --package=<zip-path> [--space-id=<id>] [--kb-id=<
233
238
  | `--package=<zip>` | 与 `--folder` 二选一 | 已打包的 zip 路径 |
234
239
  | `--minimum-level` | 否 | 上传最低等级:`propose-spec`(默认)/ `design` / `task` / `full` |
235
240
  | `--validate-only` | 否 | 仅校验不上传 |
236
- | `--space-id=<id>` | 否 | 目标 Space ID;单目标可读取配置,多目标时与 --kb-id 一起显式提供 |
237
- | `--kb-id=<id>` | 否 | 目标 KB ID;单目标可读取配置,多目标时与 --space-id 一起显式提供 |
241
+ | `--space-id=<id>` | 否 | 临时覆盖上传 Space;必须与 `--kb-id` 同时提供。默认读取 `uploadTarget` |
242
+ | `--kb-id=<id>` | 否 | 临时覆盖上传 KB;必须与 `--space-id` 同时提供。默认读取 `uploadTarget` |
243
+
244
+ 上传目标优先级:成对命令行参数 → `kb-state.json.uploadTarget` → 旧版唯一 `targets[0]`。
245
+ 多个 `targets` 没有有效 `uploadTarget` 时直接停止,不能默选首项或广播。
238
246
 
239
247
  ### project_id 解析优先级
240
248
 
@@ -0,0 +1,18 @@
1
+ {
2
+ "api": "http://10.29.213.80:8080/api",
3
+ "tenantKey": "default",
4
+ "apiKey": "",
5
+ "targets": [
6
+ {
7
+ "spaceId": "space-uuid",
8
+ "spaceKey": "project-key",
9
+ "spaceName": "项目空间",
10
+ "kbId": "knowledge-base-uuid",
11
+ "kbName": "Spec 知识库"
12
+ }
13
+ ],
14
+ "uploadTarget": {
15
+ "spaceId": "space-uuid",
16
+ "kbId": "knowledge-base-uuid"
17
+ }
18
+ }