@h-ai/cli 0.1.0-alpha.66 → 0.1.0-alpha.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +66 -257
- package/README.ja.md +66 -257
- package/README.md +66 -257
- package/dist/{chunk-QYX6V7H2.js → chunk-7DSURTJ4.js} +22 -79
- package/dist/chunk-7DSURTJ4.js.map +1 -0
- package/dist/{chunk-FWN5B54L.js → chunk-AOQ4N657.js} +182 -10
- package/dist/chunk-AOQ4N657.js.map +1 -0
- package/dist/cli-config-templates-6AHNUGBN.js +5 -0
- package/dist/{cli-config-templates-3XSFIXBP.js.map → cli-config-templates-6AHNUGBN.js.map} +1 -1
- package/dist/{cli-skill-templates-TSYEQTCY.js → cli-skill-templates-FC3QRKDO.js} +3 -3
- package/dist/{cli-skill-templates-TSYEQTCY.js.map → cli-skill-templates-FC3QRKDO.js.map} +1 -1
- package/dist/index.js +435 -247
- package/dist/index.js.map +1 -1
- package/dist/{src-RDQ2EIBT.js → src-2V6VP4I5.js} +553 -119
- package/dist/src-2V6VP4I5.js.map +1 -0
- package/package.json +8 -8
- package/templates/README.md +48 -145
- package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +1 -1
- package/templates/apps/api/.dockerignore.hbs +14 -7
- package/templates/apps/api/.gitignore.hbs +7 -0
- package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +23 -2
- package/templates/apps/api/apps/{{projectName}}-service/README.md.hbs +28 -7
- package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +1 -2
- package/templates/apps/api/hai.build.json.hbs +1 -1
- package/templates/apps/api/images/app.Dockerfile.hbs +35 -0
- package/templates/apps/api/package.json.hbs +5 -0
- package/templates/apps/fullstack/.dockerignore.hbs +14 -9
- package/templates/apps/fullstack/.gitignore.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +23 -5
- package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +1 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/public/runtime-config.js.hbs +4 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +22 -4
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +16 -6
- package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +23 -5
- package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +1 -1
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +11 -1
- package/templates/apps/fullstack/hai.build.json.hbs +2 -2
- package/templates/apps/fullstack/images/app.Dockerfile.hbs +36 -0
- package/templates/apps/fullstack/images/web.Dockerfile.hbs +34 -0
- package/templates/apps/fullstack/package.json.hbs +2 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +23 -2
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +27 -6
- package/templates/apps/fullstack/packages/{{projectName}}-shared/.gitignore.hbs +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +32 -11
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +2 -2
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +3 -3
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +2 -2
- package/templates/apps/h5/src/routes/+layout.svelte.hbs +2 -2
- package/templates/apps/mobile-app/src/App.svelte.hbs +2 -2
- package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +2 -2
- package/templates/apps/website/src/routes/+layout.svelte.hbs +3 -3
- package/templates/apps/website/src/routes/services/+page.svelte.hbs +1 -1
- package/templates/base/.dockerignore.hbs +14 -8
- package/templates/base/.gitignore.hbs +7 -0
- package/templates/base/e2e/app.spec.ts.hbs +10 -0
- package/templates/base/hai.build.json.hbs +1 -1
- package/templates/base/{Dockerfile.hbs → images/app.Dockerfile.hbs} +19 -17
- package/templates/base/package.json.hbs +8 -3
- package/templates/base/vite.config.ts.hbs +3 -1
- package/templates/shared/.gitattributes +6 -0
- package/templates/skills/AGENTS.md +3 -3
- package/templates/skills/bridges/admin/AGENTS.md +1 -1
- package/templates/skills/bridges/api/AGENTS.md +1 -1
- package/templates/skills/bridges/fullstack/AGENTS.md.hbs +1 -1
- package/templates/skills/bridges/h5/AGENTS.md +1 -1
- package/templates/skills/bridges/mobile-app/AGENTS.md +1 -1
- package/templates/skills/bridges/website/AGENTS.md +1 -1
- package/templates/skills/hai-api-client/SKILL.md +14 -161
- package/templates/skills/hai-api-client/reference.md +166 -0
- package/templates/skills/hai-api-contract/SKILL.md +15 -273
- package/templates/skills/hai-api-contract/reference.md +278 -0
- package/templates/skills/hai-app-create/SKILL.md +2 -2
- package/templates/skills/hai-app-create/development.md +4 -4
- package/templates/skills/hai-app-create/reference.md +5 -4
- package/templates/skills/hai-app-review/SKILL.md +1 -1
- package/templates/skills/hai-app-tests/SKILL.md +4 -3
- package/templates/skills/hai-app-tests/reference.md +2 -2
- package/templates/skills/hai-app-tests/validation.md +31 -0
- package/templates/skills/hai-audit/SKILL.md +17 -142
- package/templates/skills/hai-audit/reference.md +145 -0
- package/templates/skills/hai-build/SKILL.md +14 -8
- package/templates/skills/hai-build/reference.md +10 -9
- package/templates/skills/hai-cache/SKILL.md +15 -182
- package/templates/skills/hai-cache/reference.md +187 -0
- package/templates/skills/hai-capacitor/SKILL.md +4 -3
- package/templates/skills/hai-capacitor/reference.md +6 -4
- package/templates/skills/hai-ci/SKILL.md +2 -0
- package/templates/skills/hai-core/SKILL.md +3 -3
- package/templates/skills/hai-crypto/SKILL.md +16 -252
- package/templates/skills/hai-crypto/reference.md +256 -0
- package/templates/skills/hai-datapipe/SKILL.md +15 -196
- package/templates/skills/hai-datapipe/reference.md +202 -0
- package/templates/skills/hai-deploy/SKILL.md +20 -55
- package/templates/skills/hai-deploy/middleware.md +5 -11
- package/templates/skills/hai-framework-sync/SKILL.md +2 -2
- package/templates/skills/hai-framework-sync/sync.md +1 -1
- package/templates/skills/hai-iam/SKILL.md +1 -3
- package/templates/skills/hai-kit/SKILL.md +12 -167
- package/templates/skills/hai-kit/reference.md +172 -0
- package/templates/skills/hai-payment/SKILL.md +19 -251
- package/templates/skills/hai-payment/reference.md +256 -0
- package/templates/skills/hai-pr-review/SKILL.md +4 -4
- package/templates/skills/hai-reach/SKILL.md +2 -2
- package/templates/skills/hai-reldb/SKILL.md +1 -1
- package/templates/skills/hai-scheduler/SKILL.md +15 -195
- package/templates/skills/hai-scheduler/reference.md +202 -0
- package/templates/skills/hai-serv/SKILL.md +2 -2
- package/templates/skills/hai-spec-implement/SKILL.md +1 -1
- package/templates/skills/hai-spec-implement/workflow.md +3 -3
- package/templates/skills/hai-storage/SKILL.md +17 -238
- package/templates/skills/hai-storage/reference.md +243 -0
- package/templates/skills/hai-ui/SKILL.md +1 -1
- package/templates/skills/hai-ui/reference.md +9 -5
- package/templates/skills/hai-vecdb/SKILL.md +2 -2
- package/dist/chunk-FWN5B54L.js.map +0 -1
- package/dist/chunk-QYX6V7H2.js.map +0 -1
- package/dist/cli-config-templates-3XSFIXBP.js +0 -5
- package/dist/src-RDQ2EIBT.js.map +0 -1
- package/templates/apps/api/Dockerfile.hbs +0 -35
- package/templates/apps/fullstack/Dockerfile.hbs +0 -57
- /package/templates/apps/fullstack/{docker → images/web}/19-runtime-config.envsh.hbs +0 -0
- /package/templates/apps/fullstack/{docker → images/web}/nginx.conf.hbs +0 -0
- /package/templates/apps/fullstack/{docker → images/web}/runtime-config.js.template.hbs +0 -0
- /package/templates/base/{docker → images/web}/nginx.conf.hbs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hai-datapipe
|
|
3
|
-
description: "使用 @h-ai/datapipe
|
|
3
|
+
description: "使用 @h-ai/datapipe 清洗和分块文本、组合预处理管线;用于 RAG 入库前处理,不负责 embedding。"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# hai-datapipe
|
|
@@ -15,202 +15,21 @@ description: "使用 @h-ai/datapipe 清洗文本、分块并组合 RAG 入库管
|
|
|
15
15
|
| 输出 | 清洗/分块的 HaiResult;管线工厂按签名使用 |
|
|
16
16
|
| 限制 | 纯函数,无 init/close;区分字符数和模型 token 数,分块结果不等于已生成 embedding。 |
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
## 使用路径
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
1. 直接使用 clean/chunk/pipeline,无 init/close;清洗或分块失败后不读 data。
|
|
21
|
+
2. 根据原文结构选择模式,明确 maxSize、overlap 与字符/词边界;这里不负责模型 token 预算。
|
|
22
|
+
3. 自定义正则仅来自可信配置。入库前先检查管线结果,再生成 embedding,并验证向量维度与集合匹配。
|
|
23
|
+
4. 验证空文本、非法配置、边界切分与自定义转换失败;保留文档内容及必要元数据。
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
## 按需参考
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
按本次操作读取对应小节;以已安装版本的公开类型核验签名,示例中的业务变量由应用提供。
|
|
25
28
|
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
### 直接调用(无需 init)
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
import { datapipe } from '@h-ai/datapipe'
|
|
37
|
-
|
|
38
|
-
// 清洗
|
|
39
|
-
const cleaned = datapipe.clean(htmlText, { removeHtml: true, removeUrls: true })
|
|
40
|
-
|
|
41
|
-
// 分块
|
|
42
|
-
const chunks = datapipe.chunk(cleaned.data, { mode: 'markdown', maxSize: 2000, overlap: 200 })
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### 管线模式
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
const result = await datapipe.pipeline()
|
|
49
|
-
.clean({ removeHtml: true, removeUrls: true })
|
|
50
|
-
.transform(text => text.toLowerCase())
|
|
51
|
-
.chunk({ mode: 'paragraph', maxSize: 1000, overlap: 100 })
|
|
52
|
-
.chunkTransform(chunks => chunks.filter(c => c.content.length > 50))
|
|
53
|
-
.run(rawText)
|
|
54
|
-
|
|
55
|
-
if (result.success) {
|
|
56
|
-
// result.data => { text: string, chunks: DataChunk[] }
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## 核心 API
|
|
61
|
-
|
|
62
|
-
### 清洗 — `datapipe.clean`
|
|
63
|
-
|
|
64
|
-
```text
|
|
65
|
-
datapipe.clean(text: string, options?: CleanOptionsInput): HaiResult<string>
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
**CleanOptionsInput**:
|
|
69
|
-
|
|
70
|
-
| 字段 | 类型 | 默认 | 说明 |
|
|
71
|
-
| -------------------- | ------------------ | ----- | ------------------------ |
|
|
72
|
-
| `removeHtml` | `boolean` | true | 移除 HTML 标签 |
|
|
73
|
-
| `removeUrls` | `boolean` | false | 移除 URL |
|
|
74
|
-
| `removeEmails` | `boolean` | false | 移除 Email 地址 |
|
|
75
|
-
| `normalizeWhitespace`| `boolean` | true | 多空格→单空格、去多余空行 |
|
|
76
|
-
| `trim` | `boolean` | true | 去除首尾空白 |
|
|
77
|
-
| `customReplacements` | `{ pattern, replacement }[]` | — | 自定义正则替换规则 |
|
|
78
|
-
|
|
79
|
-
### 分块 — `datapipe.chunk`
|
|
80
|
-
|
|
81
|
-
```text
|
|
82
|
-
datapipe.chunk(text: string, options: ChunkOptionsInput): HaiResult<DataChunk[]>
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
**ChunkOptionsInput**:
|
|
86
|
-
|
|
87
|
-
| 字段 | 类型 | 默认 | 说明 |
|
|
88
|
-
| ------------------ | --------- | ---- | ------------------------------ |
|
|
89
|
-
| `mode` | `ChunkMode` | — | 分块模式(必填) |
|
|
90
|
-
| `maxSize` | `number` | 1000 | 分块最大大小 |
|
|
91
|
-
| `overlap` | `number` | 0 | 重叠大小(上下文衔接) |
|
|
92
|
-
| `separator` | `string` | — | 自定义分隔符正则(mode=custom)|
|
|
93
|
-
| `markdownMinLevel` | `number` | 2 | Markdown 最低标题级别(1-6) |
|
|
94
|
-
| `markdownKeepTitle`| `boolean` | true | 分块中保留 Markdown 标题 |
|
|
95
|
-
|
|
96
|
-
**分块模式**:
|
|
97
|
-
|
|
98
|
-
| 模式 | 说明 |
|
|
99
|
-
| ----------- | --------------------------- |
|
|
100
|
-
| `sentence` | 按句子(中英文句号/问号/感叹号) |
|
|
101
|
-
| `paragraph` | 按段落(双换行) |
|
|
102
|
-
| `markdown` | 按 Markdown 标题层级 |
|
|
103
|
-
| `page` | 按分页符(\f) |
|
|
104
|
-
| `word` | 按字数 |
|
|
105
|
-
| `character` | 按字符数 |
|
|
106
|
-
| `custom` | 自定义正则分隔符 |
|
|
107
|
-
|
|
108
|
-
**DataChunk**:
|
|
109
|
-
|
|
110
|
-
```typescript
|
|
111
|
-
interface DataChunk {
|
|
112
|
-
index: number // 分块索引(从 0 开始)
|
|
113
|
-
content: string // 分块内容
|
|
114
|
-
metadata?: Record<string, unknown> // 元数据(Markdown 模式含 title、level)
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### 管线 — `datapipe.pipeline()`
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
datapipe.pipeline()
|
|
122
|
-
.clean(options) // 添加清洗步骤
|
|
123
|
-
.transform(fn) // 添加文本转换步骤(同步/异步)
|
|
124
|
-
.chunk(options) // 添加分块步骤
|
|
125
|
-
.chunkTransform(fn) // 添加分块后处理步骤
|
|
126
|
-
.run(text) // 执行管线 → Promise<HaiResult<PipelineResult>>
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
**PipelineResult**:
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
interface PipelineResult {
|
|
133
|
-
text: string // 处理后的文本(分块前的最终文本)
|
|
134
|
-
chunks: DataChunk[] // 分块列表(如果管线包含 chunk 步骤)
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## 错误码 — `HaiDatapipeError`
|
|
139
|
-
|
|
140
|
-
| 错误码 | code | 说明 |
|
|
141
|
-
|--------|------|------|
|
|
142
|
-
| `HaiDatapipeError.CLEAN_FAILED` | `hai:datapipe:001` | 清洗失败 |
|
|
143
|
-
| `HaiDatapipeError.CHUNK_FAILED` | `hai:datapipe:002` | 分块失败 |
|
|
144
|
-
| `HaiDatapipeError.TRANSFORM_FAILED` | `hai:datapipe:003` | 转换失败 |
|
|
145
|
-
| `HaiDatapipeError.PIPELINE_FAILED` | `hai:datapipe:004` | 管线执行失败 |
|
|
146
|
-
| `HaiDatapipeError.CONFIG_ERROR` | `hai:datapipe:005` | 配置错误 |
|
|
147
|
-
| `HaiDatapipeError.MISSING_SEPARATOR` | `hai:datapipe:006` | 自定义分隔符缺失 |
|
|
148
|
-
|
|
149
|
-
## 常见模式
|
|
150
|
-
|
|
151
|
-
### RAG 文档入库前处理
|
|
152
|
-
|
|
153
|
-
```typescript
|
|
154
|
-
import { datapipe } from '@h-ai/datapipe'
|
|
155
|
-
import { ai } from '@h-ai/ai'
|
|
156
|
-
import { vecdb } from '@h-ai/vecdb'
|
|
157
|
-
|
|
158
|
-
// 清洗 + Markdown 分块
|
|
159
|
-
const result = await datapipe.pipeline()
|
|
160
|
-
.clean({ removeHtml: true, removeUrls: true })
|
|
161
|
-
.chunk({ mode: 'markdown', maxSize: 1000, overlap: 100 })
|
|
162
|
-
.run(rawDocument)
|
|
163
|
-
|
|
164
|
-
if (!result.success) return result
|
|
165
|
-
|
|
166
|
-
// 生成嵌入
|
|
167
|
-
const embeddings = await ai.embedding.embedBatch(
|
|
168
|
-
result.data.chunks.map(c => c.content),
|
|
169
|
-
)
|
|
170
|
-
if (!embeddings.success) return embeddings
|
|
171
|
-
|
|
172
|
-
// 入库
|
|
173
|
-
const docs = result.data.chunks.map((chunk, i) => ({
|
|
174
|
-
id: `chunk-${i}`,
|
|
175
|
-
vector: embeddings.data[i],
|
|
176
|
-
content: chunk.content,
|
|
177
|
-
metadata: chunk.metadata,
|
|
178
|
-
}))
|
|
179
|
-
await vecdb.vector.insert('knowledge', docs)
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### 多步清洗管线
|
|
183
|
-
|
|
184
|
-
```typescript
|
|
185
|
-
const result = await datapipe.pipeline()
|
|
186
|
-
.clean({ removeHtml: true, removeEmails: true })
|
|
187
|
-
.transform(text => text.replace(/\[.*?\]/g, '')) // 移除 [注释]
|
|
188
|
-
.transform(text => text.replace(/\(https?:.*?\)/g, '')) // 移除 Markdown 链接 URL
|
|
189
|
-
.chunk({ mode: 'paragraph', maxSize: 800 })
|
|
190
|
-
.chunkTransform(chunks => chunks.filter(c => c.content.length > 20)) // 过滤过短分块
|
|
191
|
-
.run(rawText)
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### 错误分支处理
|
|
195
|
-
|
|
196
|
-
```typescript
|
|
197
|
-
import { datapipe, HaiDatapipeError } from '@h-ai/datapipe'
|
|
198
|
-
|
|
199
|
-
const result = datapipe.chunk(text, { mode: 'custom' })
|
|
200
|
-
if (!result.success) {
|
|
201
|
-
switch (result.error.code) {
|
|
202
|
-
case HaiDatapipeError.MISSING_SEPARATOR.code:
|
|
203
|
-
// mode='custom' 时需提供 separator
|
|
204
|
-
break
|
|
205
|
-
case HaiDatapipeError.CONFIG_ERROR.code:
|
|
206
|
-
// 配置参数校验失败
|
|
207
|
-
break
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
## 相关 Skills
|
|
213
|
-
|
|
214
|
-
- `hai-vecdb`:向量数据库存储(分块后入库)
|
|
215
|
-
- `hai-ai`:LLM 与 Embedding 能力
|
|
216
|
-
- `hai-core`:HaiResult 模型
|
|
29
|
+
- [运行环境](reference.md#运行环境)
|
|
30
|
+
- [适用场景](reference.md#适用场景)
|
|
31
|
+
- [使用步骤](reference.md#使用步骤)
|
|
32
|
+
- [核心 API](reference.md#核心-api)
|
|
33
|
+
- [错误码 — `HaiDatapipeError`](reference.md#错误码--haidatapipeerror)
|
|
34
|
+
- [常见模式](reference.md#常见模式)
|
|
35
|
+
- [相关 Skills](reference.md#相关-skills)
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# hai-datapipe 参考
|
|
2
|
+
|
|
3
|
+
> `@h-ai/datapipe` 提供文本清洗(clean)、多模式分块(chunk)和可组合管线(pipeline),纯函数模块,无需初始化。
|
|
4
|
+
|
|
5
|
+
## 运行环境
|
|
6
|
+
|
|
7
|
+
> **服务端模块(Node.js only)。** 通常在 AI 知识库入库或文档预处理场景中使用,由 `@h-ai/ai` 内部调用或在服务端显式调用。
|
|
8
|
+
|
|
9
|
+
## 适用场景
|
|
10
|
+
|
|
11
|
+
- 文本清洗:移除 HTML 标签、URL、Email,标准化空白
|
|
12
|
+
- 文本分块:句子、段落、Markdown 标题、字数、字符、自定义分隔符
|
|
13
|
+
- RAG 入库前的文档预处理管线
|
|
14
|
+
- 管线模式组合多步清洗 + 分块 + 自定义转换
|
|
15
|
+
|
|
16
|
+
## 使用步骤
|
|
17
|
+
|
|
18
|
+
### 直接调用(无需 init)
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { datapipe } from '@h-ai/datapipe'
|
|
22
|
+
|
|
23
|
+
// 清洗
|
|
24
|
+
const cleaned = datapipe.clean(htmlText, { removeHtml: true, removeUrls: true })
|
|
25
|
+
|
|
26
|
+
// 分块
|
|
27
|
+
if (!cleaned.success) return cleaned
|
|
28
|
+
const chunks = datapipe.chunk(cleaned.data, { mode: 'markdown', maxSize: 2000, overlap: 200 })
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 管线模式
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
const result = await datapipe.pipeline()
|
|
35
|
+
.clean({ removeHtml: true, removeUrls: true })
|
|
36
|
+
.transform(text => text.toLowerCase())
|
|
37
|
+
.chunk({ mode: 'paragraph', maxSize: 1000, overlap: 100 })
|
|
38
|
+
.chunkTransform(chunks => chunks.filter(c => c.content.length > 50))
|
|
39
|
+
.run(rawText)
|
|
40
|
+
|
|
41
|
+
if (result.success) {
|
|
42
|
+
// result.data => { text: string, chunks: DataChunk[] }
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 核心 API
|
|
47
|
+
|
|
48
|
+
### 清洗 — `datapipe.clean`
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
datapipe.clean(text: string, options?: CleanOptionsInput): HaiResult<string>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**CleanOptionsInput**:
|
|
55
|
+
|
|
56
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
57
|
+
| -------------------- | ------------------ | ----- | ------------------------ |
|
|
58
|
+
| `removeHtml` | `boolean` | true | 移除 HTML 标签 |
|
|
59
|
+
| `removeUrls` | `boolean` | false | 移除 URL |
|
|
60
|
+
| `removeEmails` | `boolean` | false | 移除 Email 地址 |
|
|
61
|
+
| `normalizeWhitespace`| `boolean` | true | 多空格→单空格、去多余空行 |
|
|
62
|
+
| `trim` | `boolean` | true | 去除首尾空白 |
|
|
63
|
+
| `customReplacements` | `{ pattern, replacement }[]` | — | 自定义正则替换规则 |
|
|
64
|
+
|
|
65
|
+
### 分块 — `datapipe.chunk`
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
datapipe.chunk(text: string, options: ChunkOptionsInput): HaiResult<DataChunk[]>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**ChunkOptionsInput**:
|
|
72
|
+
|
|
73
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
74
|
+
| ------------------ | --------- | ---- | ------------------------------ |
|
|
75
|
+
| `mode` | `ChunkMode` | — | 分块模式(必填) |
|
|
76
|
+
| `maxSize` | `number` | 1000 | 分块最大大小 |
|
|
77
|
+
| `overlap` | `number` | 0 | 重叠大小(上下文衔接) |
|
|
78
|
+
| `separator` | `string` | — | 自定义分隔符正则(mode=custom)|
|
|
79
|
+
| `markdownMinLevel` | `number` | 2 | Markdown 最低标题级别(1-6) |
|
|
80
|
+
| `markdownKeepTitle`| `boolean` | true | 分块中保留 Markdown 标题 |
|
|
81
|
+
|
|
82
|
+
**分块模式**:
|
|
83
|
+
|
|
84
|
+
| 模式 | 说明 |
|
|
85
|
+
| ----------- | --------------------------- |
|
|
86
|
+
| `sentence` | 按句子(中英文句号/问号/感叹号) |
|
|
87
|
+
| `paragraph` | 按段落(双换行) |
|
|
88
|
+
| `markdown` | 按 Markdown 标题层级 |
|
|
89
|
+
| `page` | 按分页符(\f) |
|
|
90
|
+
| `word` | 按字数 |
|
|
91
|
+
| `character` | 按字符数 |
|
|
92
|
+
| `custom` | 自定义正则分隔符 |
|
|
93
|
+
|
|
94
|
+
**DataChunk**:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
interface DataChunk {
|
|
98
|
+
index: number // 分块索引(从 0 开始)
|
|
99
|
+
content: string // 分块内容
|
|
100
|
+
metadata?: Record<string, unknown> // 元数据(Markdown 模式含 title、level)
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 管线 — `datapipe.pipeline()`
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
datapipe.pipeline()
|
|
108
|
+
.clean(options) // 添加清洗步骤
|
|
109
|
+
.transform(fn) // 添加文本转换步骤(同步/异步)
|
|
110
|
+
.chunk(options) // 添加分块步骤
|
|
111
|
+
.chunkTransform(fn) // 添加分块后处理步骤
|
|
112
|
+
.run(text) // 执行管线 → Promise<HaiResult<PipelineResult>>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**PipelineResult**:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
interface PipelineResult {
|
|
119
|
+
text: string // 处理后的文本(分块前的最终文本)
|
|
120
|
+
chunks: DataChunk[] // 分块列表(如果管线包含 chunk 步骤)
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## 错误码 — `HaiDatapipeError`
|
|
125
|
+
|
|
126
|
+
| 错误码 | code | 说明 |
|
|
127
|
+
|--------|------|------|
|
|
128
|
+
| `HaiDatapipeError.CLEAN_FAILED` | `hai:datapipe:001` | 清洗失败 |
|
|
129
|
+
| `HaiDatapipeError.CHUNK_FAILED` | `hai:datapipe:002` | 分块失败 |
|
|
130
|
+
| `HaiDatapipeError.TRANSFORM_FAILED` | `hai:datapipe:003` | 转换失败 |
|
|
131
|
+
| `HaiDatapipeError.PIPELINE_FAILED` | `hai:datapipe:004` | 管线执行失败 |
|
|
132
|
+
| `HaiDatapipeError.CONFIG_ERROR` | `hai:datapipe:005` | 配置错误 |
|
|
133
|
+
| `HaiDatapipeError.MISSING_SEPARATOR` | `hai:datapipe:006` | 自定义分隔符缺失 |
|
|
134
|
+
|
|
135
|
+
## 常见模式
|
|
136
|
+
|
|
137
|
+
### RAG 文档入库前处理
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import { datapipe } from '@h-ai/datapipe'
|
|
141
|
+
import { ai } from '@h-ai/ai'
|
|
142
|
+
import { vecdb } from '@h-ai/vecdb'
|
|
143
|
+
|
|
144
|
+
// 清洗 + Markdown 分块
|
|
145
|
+
const result = await datapipe.pipeline()
|
|
146
|
+
.clean({ removeHtml: true, removeUrls: true })
|
|
147
|
+
.chunk({ mode: 'markdown', maxSize: 1000, overlap: 100 })
|
|
148
|
+
.run(rawDocument)
|
|
149
|
+
|
|
150
|
+
if (!result.success) return result
|
|
151
|
+
|
|
152
|
+
// 生成嵌入
|
|
153
|
+
const embeddings = await ai.embedding.embedBatch(
|
|
154
|
+
result.data.chunks.map(c => c.content),
|
|
155
|
+
)
|
|
156
|
+
if (!embeddings.success) return embeddings
|
|
157
|
+
|
|
158
|
+
// 入库
|
|
159
|
+
const docs = result.data.chunks.map((chunk, i) => ({
|
|
160
|
+
id: `chunk-${i}`,
|
|
161
|
+
vector: embeddings.data[i],
|
|
162
|
+
content: chunk.content,
|
|
163
|
+
metadata: chunk.metadata,
|
|
164
|
+
}))
|
|
165
|
+
await vecdb.vector.insert('knowledge', docs)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 多步清洗管线
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const result = await datapipe.pipeline()
|
|
172
|
+
.clean({ removeHtml: true, removeEmails: true })
|
|
173
|
+
.transform(text => text.replace(/\[.*?\]/g, '')) // 移除 [注释]
|
|
174
|
+
.transform(text => text.replace(/\(https?:.*?\)/g, '')) // 移除 Markdown 链接 URL
|
|
175
|
+
.chunk({ mode: 'paragraph', maxSize: 800 })
|
|
176
|
+
.chunkTransform(chunks => chunks.filter(c => c.content.length > 20)) // 过滤过短分块
|
|
177
|
+
.run(rawText)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 错误分支处理
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { datapipe, HaiDatapipeError } from '@h-ai/datapipe'
|
|
184
|
+
|
|
185
|
+
const result = datapipe.chunk(text, { mode: 'custom' })
|
|
186
|
+
if (!result.success) {
|
|
187
|
+
switch (result.error.code) {
|
|
188
|
+
case HaiDatapipeError.MISSING_SEPARATOR.code:
|
|
189
|
+
// mode='custom' 时需提供 separator
|
|
190
|
+
break
|
|
191
|
+
case HaiDatapipeError.CONFIG_ERROR.code:
|
|
192
|
+
// 配置参数校验失败
|
|
193
|
+
break
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## 相关 Skills
|
|
199
|
+
|
|
200
|
+
- `hai-vecdb`:向量数据库存储(先生成 embedding,再入库)
|
|
201
|
+
- `hai-ai`:LLM 与 Embedding 能力
|
|
202
|
+
- `hai-core`:HaiResult 模型
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hai-deploy
|
|
3
|
-
description: "
|
|
3
|
+
description: "构建并发布或交付已有镜像:完整离线包、按服务更新、SSH 与跨平台手工部署、失败恢复;也支持 Vercel prebuilt。"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# hai-deploy
|
|
@@ -9,76 +9,41 @@ description: "部署已有构建产物:配置环境与中间件,生成 Compo
|
|
|
9
9
|
|
|
10
10
|
| 项目 | 契约 |
|
|
11
11
|
| --- | --- |
|
|
12
|
-
| 能力 |
|
|
13
|
-
| 适用场景 |
|
|
14
|
-
| 输入 |
|
|
15
|
-
| 输出 |
|
|
16
|
-
| 限制 |
|
|
12
|
+
| 能力 | 配置环境与中间件,交付完整离线包或发布选中服务 |
|
|
13
|
+
| 适用场景 | 一体化构建发布、独立打包、隔离网络手工部署、增量更新与故障排查 |
|
|
14
|
+
| 输入 | package.json、hai.build.json、运行依赖锁文件、目标环境、已有制品或明确构建要求 |
|
|
15
|
+
| 输出 | 带校验和的 tar、跨平台部署入口与分步结果,或经过 HTTP 检查的部署结果 |
|
|
16
|
+
| 限制 | SDK 只消费产物;CLI --build 显式先构建。首次安装必须完整交付,packaged 不代表服务器 ready。云资源需要外网。 |
|
|
17
17
|
|
|
18
18
|
## 操作流程
|
|
19
19
|
|
|
20
|
-
1.
|
|
21
|
-
2.
|
|
22
|
-
3.
|
|
23
|
-
4.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
1. 读取项目 scripts、images/ 中的 Dockerfile、hai.build.json 与服务目录配置。创建默认带开发期部署工具;用户明确 --no-deploy 时不生成部署入口。构建细节见 [hai-build](../hai-build/SKILL.md)。
|
|
21
|
+
2. 选择环境,验证 .env.<mode> 存在,再处理 SSH 与必要中间件。使用人类可读字段说明,复用有效配置;私有参数写 .env.local,私钥仅引用路径。环境规则见 [middleware.md](middleware.md)。
|
|
22
|
+
3. 先校验所选制品、版本、服务和 SHA-256。--build 只构建所选应用镜像;不带它时缺产物明确失败,不隐式补构建。格式版本 3 记录 appVersion、buildId、partial、hasWeb、镜像归档及显式配置的 appContainerPort/webContainerPort;部分构建也保留未选镜像端口,缺省使用部署默认值。同一应用版本可重建,镜像引用区分实际内容;禁止 latest 与无版本镜像。
|
|
23
|
+
4. 完整包自动导出实际自建中间件镜像并去重;只更新 Web 不重新打包 API/中间件。打包机需容器引擎导出中间件,服务器仅 load,禁止 pull/build。外部连接及云开通不能伪称为离线自包含服务。
|
|
24
|
+
5. --services 使用目标服务器最后成功状态为基线,检查端口/拓扑及未选依赖,保留未选配置、凭据、网络和卷。脚本先按项目/服务标签仅删除选中旧容器(保留卷),再 up -d --no-deps --no-build --pull never --no-recreate 创建新容器并保留其他容器,避免 Compose Provider 连带重建反向依赖,禁止整个项目 down。storage-init 是一次性创建 S3 桶,涉及存储初始化才运行。仅更新 storage 也需含 app 镜像的制品运行初始化;最近为 web-only 时,用 --artifact-dir 选择原完整制品,或先 pnpm build --target docker --images app,不会更新运行中的 app 服务。
|
|
25
|
+
6. --bundle-only 不连接 SSH,同时输出 tar 和 -deploy/ 操作目录。Windows deploy.ps1、Linux/macOS deploy.sh 上传并执行包内 apply.sh;完全隔离时搬运 tar,独立目录解包执行 sh apply.sh,可传部署根目录。脚本不依赖源码、Node 或 pnpm。
|
|
26
|
+
7. 工具预检、基线、上传、校验、镜像导入、服务更新和 HTTP 检查分别报告。失败返回非零退出码,结果文件保留失败阶段;只有检查成功才更新服务器 current。已有部署失败尝试恢复所选服务的旧容器和配置;数据卷保留,已写业务数据不回退,恢复后仍需验证健康。禁止把本地打包记录当服务器成功状态。
|
|
27
27
|
|
|
28
28
|
## CLI
|
|
29
29
|
|
|
30
|
-
使用 `pnpm run deploy` 明确执行项目脚本,避免与 pnpm 自身的 deploy 命令混淆。
|
|
31
|
-
|
|
32
30
|
```sh
|
|
31
|
+
pnpm run deploy --env prod --build
|
|
33
32
|
pnpm build --target docker
|
|
34
|
-
pnpm run deploy --env test
|
|
35
|
-
pnpm run deploy --env prod --skip-middleware
|
|
36
33
|
pnpm run deploy --env prod --artifact-dir .hai/build/docker/<buildId>
|
|
37
34
|
pnpm run deploy --env prod --bundle-only --output release-prod.tar
|
|
38
|
-
|
|
39
|
-
pnpm
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
API workspace 的服务目录为 apps/my-app-service。单包使用当前目录。Node/pnpm 版本以项目 engines/packageManager 为准,Windows 用 pnpm.cmd。
|
|
43
|
-
|
|
44
|
-
```yaml
|
|
45
|
-
# 服务包 config/_deploy.yml
|
|
46
|
-
provider:
|
|
47
|
-
type: docker-ssh
|
|
48
|
-
expose:
|
|
49
|
-
hostPort: 18080
|
|
50
|
-
container:
|
|
51
|
-
s3Engine: rustfs # rustfs | minio
|
|
35
|
+
pnpm build --target docker --images web
|
|
36
|
+
pnpm run deploy --env prod --services web
|
|
52
37
|
```
|
|
53
38
|
|
|
54
|
-
|
|
39
|
+
使用 pnpm run deploy,避免与 pnpm 自带 deploy 混淆。fullstack 指向 packages/<项目>-serv,API workspace 指向 apps/<项目>-service;这是扫描入口,不是镜像选择。--services 负责选择;--skip-middleware 只跳过配置及开通。--yes 复用有效配置,缺值时不盲目继续。
|
|
55
40
|
|
|
56
41
|
## SDK
|
|
57
42
|
|
|
58
|
-
|
|
59
|
-
import { deploy } from '@h-ai/deploy'
|
|
60
|
-
|
|
61
|
-
const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 18080 } } })
|
|
62
|
-
if (!initialized.success) throw new Error(initialized.error.message)
|
|
63
|
-
try {
|
|
64
|
-
const result = await deploy.deployApp('./packages/my-app-serv', {
|
|
65
|
-
environment: 'prod', envDir: '.', bundleOnly: true,
|
|
66
|
-
artifactDir: './.hai/build/docker/<buildId>', skipMiddleware: true,
|
|
67
|
-
})
|
|
68
|
-
if (!result.success) throw new Error(result.error.message)
|
|
69
|
-
// bundlePath/instructions;只有在线部署才有健康检查和可访问 URL。
|
|
70
|
-
}
|
|
71
|
-
finally {
|
|
72
|
-
await deploy.close()
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
`deploy.scan`、`deploy.credentials.getPath/load/save/saveAll` 不依赖 init。Vercel 使用 prebuilt 协议只上传 Build Output API v3 的 .vercel/output,不运行 build 命令;云认证和开通需要外网。
|
|
43
|
+
deploy.init 后检查 HaiResult.success,deploy.deployApp 接收 artifactDir、bundleOnly、selectedServices、runtime 与 onProgress;finally 中 deploy.close。deploy.scan 和 deploy.credentials.* 不依赖 init。Vercel 只消费已有 .vercel/output,不执行源码构建,也不支持 Compose 离线/部分更新。
|
|
77
44
|
|
|
78
45
|
## 离线交付与验证
|
|
79
46
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
完全离线构建另需基础镜像、Linux 依赖缓存、pnpm 和匹配 ABI/libc 的 SQLite 预编译包;Windows node_modules 不能替代。生产 HTTPS、CORS、证书和 DNS 另行配置。实际断网后验收登录、刷新、重启与持久化,不能将联网测试当作离线证明。
|
|
47
|
+
Linux 预备 Docker/Podman、支持 --pull never 的 Compose(Docker Compose v2 或 podman-compose 1.6.0 及以上)、sh、tar、sha256sum、awk、curl 及目录/容器权限。完整 tar 包含全部自建中间件归档;目标架构须匹配。包中有私有配置,安全搬运,不提交 Git。离线构建额外准备基础镜像、Linux 依赖缓存、工具链与原生预编译包;Windows node_modules 不能替代。
|
|
83
48
|
|
|
84
|
-
|
|
49
|
+
按 [分轮验证与集中修复](../hai-app-tests/validation.md) 收集适用的 typecheck、lint、build、test、scaffold gates 和 test:deploy-gates,汇总后集中修复、再验证。实际验证无 registry 网络的首次部署、登录刷新、同版本重发、只更新 Web/API、损坏归档、缺基线、健康失败与恢复。Windows/Linux/macOS 上传入口分别执行验收;原生安装包在对应 OS 验证。测试临时工程、容器、镜像、数据和进程在 finally/teardown 清理,只清理测试拥有的资源;日志、截图和报告保留到分析和交付结束再清理。
|
|
@@ -71,18 +71,12 @@ S3 是协议,不是某个容器产品。默认配置时另选 RustFS/MinIO,
|
|
|
71
71
|
|
|
72
72
|
## 离线准备与验收
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
构建与部署可分开,也可通过 pnpm run deploy --build 明确串联。构建保持环境无关;部署选择环境并只消费所选镜像。完整包自动包含 Compose 自建中间件镜像,因此导出阶段需要本地 Podman/Docker,缺镜像在打包阶段准备,不能留给隔离服务器下载。
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
--bundle-only 生成带版本 tar 与 -deploy/ 目录。操作目录含 Windows deploy.ps1、Linux/macOS deploy.sh 和目标配置。隔离服务器搬运并解包后执行 sh apply.sh。每步失败返回非零,结果写 result-<部署ID>.json;只有 HTTP 检查通过才更新服务器 current。
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
部分更新通过 --services 指定,使用服务器成功基线保留未选服务和中间件凭据。首次安装不能使用部分包。storage-init 复用应用镜像及 S3 SDK 检查/创建桶,不清空数据;只有涉及存储初始化时执行,并检查退出码。仅更新 storage 仍需含 app 镜像的制品;最近为 web-only 时,用 --artifact-dir 选择原完整制品,或先 pnpm build --target docker --images app。app 镜像仅用于初始化,不会更新 app 服务。失败恢复尝试还原容器和配置,保留数据卷,不回退已写业务数据。
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
服务器需要 Linux、Docker/Podman、Compose、sh、tar、sha256sum、awk、curl、持久化磁盘和容器/目录权限。完整交付包含自建服务镜像;自定义外部连接仍需准备服务、账号和网络可达性。云 Provider/Provisioner 需要外网,不能用于完全离线。
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
fullstack 的 hai.build.json 含 app/web 时,两镜像共用构建 ID,部署生成一个 Compose 和同源代理。API 前缀来自当前服务配置,缺省 CORS 填公开入口,明确 Origin 保留;Web 不挂载 .env.runtime。线上成功要求 API/Web 健康,手工模式返回 packaged 并提示用户自行验收。生产登录刷新还需 HTTPS、正确 CORS、受信证书与 DNS/hosts,模块不配置 TLS。
|
|
85
|
-
|
|
86
|
-
容器运行期 NODE_ENV=production;HAI_DEPLOY_ENVIRONMENT 保存文件模式,HAI_CORE_ENV 映射 development/test/production/staging。资源名附环境后缀,卷按环境隔离;私有 env 权限 600。构建上下文排除 .env.local、环境覆盖、.env.runtime、.hai/build、.hai/deploy 和 data,不把运行期凭据写入镜像。
|
|
87
|
-
|
|
88
|
-
修改后运行 deploy/CLI typecheck、lint、build、test、scaffold gates 和 test:deploy-gates。测试应分别证明构建/环境选择、SSH 上传及手工包启动、Web 登录/刷新;断网能力另做实际断网验收。测试的临时工程、容器、镜像、日志、截图、报告与辅助进程必须 finally/teardown 自动清理,失败也清理;不得删除用户已有资源。原生客户端及付费云资源单独验收并报告边界。
|
|
82
|
+
完全离线构建另需基础镜像、Linux 依赖缓存、pnpm 和匹配驱动/Node ABI/架构/libc 的原生预编译包。构建可用 --sqlite-prebuild-mirror,Podman 代理不可达可用 --no-http-proxy;不要改系统代理或让 deploy 下载编译环境。生产 HTTPS、CORS、证书、DNS 另行准备。实际断网验收登录、刷新、重启和数据持久化。
|
|
@@ -75,7 +75,7 @@ npm view @h-ai/cli dist-tags --json
|
|
|
75
75
|
| --- | --- |
|
|
76
76
|
| 自动处理 | 目标明确、可保持现有行为的依赖更新、兼容性修正、无冲突的 skills 合并和验证,直接执行 |
|
|
77
77
|
| 用户选择 | 存在多个有意义的方案且影响产品行为、架构、成本、Provider 或运维方式,展示证据、选项、推荐与取舍,等待回答 |
|
|
78
|
-
| 阻塞 |
|
|
78
|
+
| 阻塞 | 无法取得必要产物、依赖不兼容、无法无损合并、必要工具/服务/授权缺失等导致后续无法执行,先处理可自行解决的原因;仍无法推进时说明具体步骤。普通门禁失败先记录,继续独立检查,本轮汇总后集中修复;必要门禁未通过仍不能交付完成 |
|
|
79
79
|
| 不适用 | 当前应用未使用且不影响其依赖/运行的变化,记录依据;不要求用户逐项确认 |
|
|
80
80
|
|
|
81
81
|
- 尽量合并相互独立的选择,明确每个回答控制哪项改动;已给出的目标、授权和选择持续有效,不重复询问。
|
|
@@ -95,7 +95,7 @@ npm view @h-ai/cli dist-tags --json
|
|
|
95
95
|
|
|
96
96
|
### 6. 验证与交付
|
|
97
97
|
|
|
98
|
-
按应用实际 scripts 和 [
|
|
98
|
+
按应用实际 scripts 和 [分轮验证与集中修复](../hai-app-tests/validation.md) 先收集一轮适用门禁,汇总根因后集中修复、再验证;优先受影响 workspace,跨包契约验证所有消费者。按 [hai-app-tests](../hai-app-tests/SKILL.md) 选择集成/E2E,覆盖启动/关闭、变更 API、认证、持久化等实际路径;CI/发布按 [hai-ci](../hai-ci/SKILL.md) 保留失败阻断。
|
|
99
99
|
|
|
100
100
|
- 依赖升级后另核对 lockfile 与安装版本、公开入口、配置加载和关键业务流程;build 通过不能替代 typecheck 或运行验收。
|
|
101
101
|
- 检查同步后的全部相邻资源、相对引用和各工具入口;目标存在 `check:skills` 时运行,不假定应用具有框架仓库私有脚本。
|
|
@@ -45,5 +45,5 @@ PowerShell 使用 `pnpm.cmd`;占位包名替换后执行。本地来源先验
|
|
|
45
45
|
|
|
46
46
|
- 仅 skills/入口变更:检查 diff、完整目录、目标实际存在的入口及相邻资源、相对引用;排除框架仓库私有绝对路径/命令。
|
|
47
47
|
- 框架模板维护:运行已有 `check:skills` 和 CLI `test:scaffold-gates`,确认资源与路由在生成项目中可达。
|
|
48
|
-
- 同步应用依赖或运行时:按入口升级流程和 [hai-ci](../hai-ci/SKILL.md)
|
|
48
|
+
- 同步应用依赖或运行时:按入口升级流程和 [分轮验证与集中修复](../hai-app-tests/validation.md) 收集适用门禁、集中修复并复测;CI/发布遵守 [hai-ci](../hai-ci/SKILL.md),不以模板已同步代替运行验收。
|
|
49
49
|
- 双仓改动时说明来源版本/提交、改动顺序、应用私有覆盖和双方验证;涉及 PR 时按 [hai-pr-review](../hai-pr-review/SKILL.md) 关联同步说明。仅授权一个仓库时记录另一方待同步,不擅自修改。
|
|
@@ -28,14 +28,12 @@ description: "使用 @h-ai/iam 实现登录、注册、会话、OTP/LDAP/API Key
|
|
|
28
28
|
- LDAP/Reach 均可选:基础认证无需安装;默认 LDAP 关闭,选用默认客户端才安装 ldapts 并设置 login.ldap + ldap。OTP 邮件/短信由 otp.email/sms 控制,选择 Reach 标准模板或自定义发送回调;具体签名与失败处理见参考中的“可选 LDAP 与通知”。
|
|
29
29
|
- 多节点共享 DB + Redis,Memory 只用于单进程。重置的策略失败计入 maxAttempts;OTP 消费不解除 resendInterval。管理员 createUser 不受自助注册开关限制。
|
|
30
30
|
|
|
31
|
-
- 协议支持配置中的 userAgreementMarkdown/privacyPolicyMarkdown 正文及 URL;同主题优先 Markdown,由安全渲染器在弹窗显示。
|
|
32
|
-
|
|
33
31
|
- 受保护请求使用 `iam.auth.verifyToken`:当前用户状态 + 角色 JOIN + 批量权限读取,失败即拒绝;`iam.session.verifyToken` 仅验证会话快照。serv 内置 IAM 注入默认使用当前授权入口,无需手动补查。
|
|
34
32
|
- 用户批量读取用 `iam.user.getUsers(ids, { include: ['roles'] })`(最多 1000,去重保留输入顺序,缺失省略);角色筛选用 `listUsers({ roleCode })`,在分页前执行,避免 N+1 和分页后过滤。
|
|
35
33
|
|
|
36
34
|
## 按需参考
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
按任务读取 [reference.md](reference.md) 的对应小节;签名以当前源码或安装版本的公开类型为准,不默认加载全部资料。示例中的业务变量由应用提供。
|
|
39
37
|
|
|
40
38
|
- 运行环境
|
|
41
39
|
- 依赖
|