@h-ai/cli 0.1.0-alpha.19 → 0.1.0-alpha.20
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/dist/{chunk-BPO34NRL.js → chunk-3BBXDQ4Y.js} +5 -5
- package/dist/chunk-3BBXDQ4Y.js.map +1 -0
- package/dist/cli-config-templates-IGGO7P45.js +5 -0
- package/dist/{cli-config-templates-JCS7T3NU.js.map → cli-config-templates-IGGO7P45.js.map} +1 -1
- package/dist/index.js +67 -39
- package/dist/index.js.map +1 -1
- package/dist/{src-N4NPS7AG.js → src-QNEJJ3BV.js} +261 -103
- package/dist/src-QNEJJ3BV.js.map +1 -0
- package/package.json +2 -2
- package/templates/apps/admin/messages/en-US.json +5 -0
- package/templates/apps/admin/messages/zh-CN.json +5 -0
- package/templates/apps/admin/src/routes/+layout.svelte.hbs +5 -5
- package/templates/apps/admin/src/routes/+page.svelte.hbs +32 -12
- package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +37 -20
- package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +33 -24
- package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +16 -13
- package/templates/apps/android-app/src/lib/api.ts.hbs +4 -3
- package/templates/apps/android-app/src/lib/capacitor.ts +1 -1
- package/templates/apps/android-app/src/routes/+layout.svelte.hbs +11 -10
- package/templates/apps/android-app/src/routes/+page.svelte.hbs +17 -6
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +4 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +14 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +13 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +3 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server-app.ts.hbs +23 -3
- package/templates/apps/h5/messages/en-US.json +3 -0
- package/templates/apps/h5/messages/zh-CN.json +3 -0
- package/templates/apps/h5/src/routes/+layout.svelte.hbs +30 -29
- package/templates/apps/h5/src/routes/+page.svelte.hbs +17 -6
- package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +17 -6
- package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +17 -6
- package/templates/apps/website/src/routes/+layout.svelte.hbs +35 -26
- package/templates/apps/website/src/routes/+page.svelte.hbs +28 -10
- package/templates/apps/website/src/routes/about/+page.svelte.hbs +11 -6
- package/templates/apps/website/src/routes/contact/+page.svelte.hbs +37 -34
- package/templates/apps/website/src/routes/services/+page.svelte.hbs +27 -40
- package/templates/base/package.json.hbs +26 -21
- package/templates/base/src/app.html.hbs +4 -0
- package/templates/base/src/hooks.server.ts.hbs +17 -7
- package/templates/base/src/lib/server/init.ts.hbs +20 -12
- package/templates/base/static/favicon.png +0 -0
- package/templates/base/tests/scaffold.test.ts.hbs +9 -1
- package/templates/base/vite.config.ts.hbs +3 -3
- package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +5 -5
- package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +34 -32
- package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +46 -48
- package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +35 -31
- package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +41 -38
- package/templates/skills/AGENTS.md +11 -1
- package/templates/skills/CLAUDE.md +2 -1
- package/templates/skills/copilot-instructions.md +22 -6
- package/templates/skills/hai-ai/SKILL.md +115 -648
- package/templates/skills/hai-ai/reference.md +197 -0
- package/templates/skills/hai-api-client/SKILL.md +3 -1
- package/templates/skills/hai-app-create/SKILL.md +1 -1
- package/templates/skills/hai-app-review/SKILL.md +1 -1
- package/templates/skills/hai-deploy/SKILL.md +12 -9
- package/templates/skills/hai-kit/SKILL.md +5 -3
- package/templates/skills/hai-serv/SKILL.md +2 -0
- package/templates/skills/hai-ui/SKILL.md +25 -11
- package/dist/chunk-BPO34NRL.js.map +0 -1
- package/dist/cli-config-templates-JCS7T3NU.js +0 -5
- package/dist/src-N4NPS7AG.js.map +0 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# @h-ai/ai reference
|
|
2
|
+
|
|
3
|
+
本文件承载 `SKILL.md` 中不常用但仍需要保留的 API 参考。优先读取 `SKILL.md`;只有当任务需要完整方法清单、错误码或长示例时再读取本文件。
|
|
4
|
+
|
|
5
|
+
## 初始化与依赖
|
|
6
|
+
|
|
7
|
+
| 能力 | 是否需要 `ai.init()` | 依赖 |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `ai.tools` | 否 | 无 |
|
|
10
|
+
| `ai.stream` | 否 | 无 |
|
|
11
|
+
| `ai.llm` | 是 | OpenAI 兼容 LLM 配置 |
|
|
12
|
+
| `ai.embedding` | 是 | LLM/Embedding 模型配置 |
|
|
13
|
+
| `ai.memory` | 是 | Store + 可选 Embedding |
|
|
14
|
+
| `ai.retrieval` / `ai.rag` | 是 | Embedding + Store |
|
|
15
|
+
| `ai.knowledge` | 是 | LLM + Embedding + Store + datapipe |
|
|
16
|
+
| `ai.context` | 是 | LLM + Store + 可选 Memory/RAG/Reasoning |
|
|
17
|
+
| `ai.a2a` | 是 | A2A 配置 + executor |
|
|
18
|
+
|
|
19
|
+
关闭必须使用 `await ai.close()`,这样才能确定释放自定义 `AIStoreProvider.close()`。
|
|
20
|
+
|
|
21
|
+
## LLM
|
|
22
|
+
|
|
23
|
+
| 方法 | 说明 |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| `chat(options)` | 非流式 Chat Completion |
|
|
26
|
+
| `chatStream(options)` | 流式 Chat Completion |
|
|
27
|
+
| `ask(query, options?)` | 返回纯文本的简易问答 |
|
|
28
|
+
| `askStream(query, options?)` | 流式纯文本问答 |
|
|
29
|
+
| `listModels()` | 查询可用模型 |
|
|
30
|
+
| `getHistory(scope, options?)` | 查询会话历史 |
|
|
31
|
+
| `listSessions(objectId)` | 查询主体会话 |
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
const result = await ai.llm.chat({
|
|
35
|
+
model: 'fast',
|
|
36
|
+
messages: [
|
|
37
|
+
{ role: 'system', content: '你是一个翻译助手' },
|
|
38
|
+
{ role: 'user', content: '你好世界' },
|
|
39
|
+
],
|
|
40
|
+
})
|
|
41
|
+
if (result.success) {
|
|
42
|
+
const reply = result.data.choices[0]?.message.content ?? ''
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Tools
|
|
47
|
+
|
|
48
|
+
- `ai.tools.define({ name, description, parameters, handler })`
|
|
49
|
+
- `ai.tools.createRegistry()`
|
|
50
|
+
- `registry.register(tool)` / `registry.unregister(name)`
|
|
51
|
+
- `registry.getDefinitions()`:传给 LLM 的工具定义
|
|
52
|
+
- `registry.execute(toolCall)` / `registry.executeAll(toolCalls, { parallel })`
|
|
53
|
+
|
|
54
|
+
工具 handler 输入由 Zod schema 约束,外部输入不要绕过 schema。
|
|
55
|
+
|
|
56
|
+
## MCP
|
|
57
|
+
|
|
58
|
+
### 独立服务器
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
const mcp = createMcpServer({ name: 'my-server', version: '1.0.0' })
|
|
62
|
+
mcp.registerResource('config', 'config://app', { description: '应用配置' }, async uri => ({
|
|
63
|
+
contents: [{ uri: uri.href, text: '{}' }],
|
|
64
|
+
}))
|
|
65
|
+
await mcp.connect(new StdioServerTransport())
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `ai.mcp`
|
|
69
|
+
|
|
70
|
+
| 方法 | 说明 |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `registerTool(definition, handler)` | 注册内置工具 |
|
|
73
|
+
| `callTool(name, args, context?)` | 调用工具 |
|
|
74
|
+
| `registerResource(resource, handler)` | 注册资源 |
|
|
75
|
+
| `readResource(uri)` | 读取资源 |
|
|
76
|
+
| `registerPrompt(prompt, handler)` | 注册提示词 |
|
|
77
|
+
| `getPrompt(name, args)` | 生成提示词消息 |
|
|
78
|
+
|
|
79
|
+
## Embedding
|
|
80
|
+
|
|
81
|
+
Embedding OpenAI 客户端按 `apiKey + baseURL + timeout` 缓存;同一 key 指向不同网关时不会复用错误客户端。
|
|
82
|
+
|
|
83
|
+
| 方法 | 说明 |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| `embed(request)` | 支持单条/批量输入 |
|
|
86
|
+
| `embedText(text)` | 返回单条向量 |
|
|
87
|
+
| `embedBatch(texts)` | 返回向量数组 |
|
|
88
|
+
|
|
89
|
+
## Memory
|
|
90
|
+
|
|
91
|
+
| 方法 | 说明 |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| `extract(messages, options?)` | 从对话提取记忆并存储 |
|
|
94
|
+
| `add(entry)` | 手动添加记忆 |
|
|
95
|
+
| `get(memoryId)` / `update(memoryId, updates)` | 读取/更新 |
|
|
96
|
+
| `recall(query, options?)` | 检索相关记忆 |
|
|
97
|
+
| `injectMemories(messages, options?)` | 注入 system 记忆上下文 |
|
|
98
|
+
| `remove(memoryId)` / `clear(options?)` | 删除 |
|
|
99
|
+
| `list(options?)` / `listPage(options?)` | 列表/分页 |
|
|
100
|
+
|
|
101
|
+
推荐所有记忆操作带 `objectId`,避免不同用户或 Agent 混写。
|
|
102
|
+
|
|
103
|
+
## Retrieval / RAG
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
await ai.retrieval.addSource({
|
|
107
|
+
id: 'docs',
|
|
108
|
+
name: '产品文档',
|
|
109
|
+
collection: 'doc_vectors',
|
|
110
|
+
topK: 5,
|
|
111
|
+
minScore: 0.7,
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
const result = await ai.rag.query('核心架构是什么?', {
|
|
115
|
+
sources: ['docs'],
|
|
116
|
+
topK: 5,
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`retrieve` 会并发检索目标 source 并按 score 合并排序;无 source 时返回 `RETRIEVAL_SOURCE_NOT_FOUND`。
|
|
121
|
+
|
|
122
|
+
## Knowledge
|
|
123
|
+
|
|
124
|
+
| 方法 | 说明 |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| `setup(options?)` | 初始化 collection / 表 / 索引 |
|
|
127
|
+
| `ingest(input)` | 文档入库 |
|
|
128
|
+
| `ingestFile(input)` | 从文件导入(Node.js) |
|
|
129
|
+
| `ingestBatch(inputs, onProgress?)` | 批量导入 |
|
|
130
|
+
| `retrieve(query, options?)` | 实体增强检索 |
|
|
131
|
+
| `ask(query, options?)` | 知识库问答 |
|
|
132
|
+
| `findByEntity(entityName, options?)` | 实体关联文档 |
|
|
133
|
+
| `listEntities(options?)` / `listDocuments(options?)` | 列表 |
|
|
134
|
+
| `removeDocument(documentId, options?)` | 删除文档和关联 |
|
|
135
|
+
|
|
136
|
+
入库链路:parse/clean → chunk → embedding → vecdb upsert → reldb metadata/entity index。
|
|
137
|
+
|
|
138
|
+
## Context
|
|
139
|
+
|
|
140
|
+
`ai.context.createManager(options)` 返回有状态管理器,适合多轮对话。
|
|
141
|
+
|
|
142
|
+
常用选项:
|
|
143
|
+
|
|
144
|
+
- `scope: { objectId, sessionId }`
|
|
145
|
+
- `systemPrompt`
|
|
146
|
+
- `compress: { auto, strategy, maxTokens, preserveLastN }`
|
|
147
|
+
- `memory: { enable, enableExtract, topK }`
|
|
148
|
+
- `rag: { enable, sources, topK, minScore }`
|
|
149
|
+
- `tools`
|
|
150
|
+
|
|
151
|
+
常用方法:`addMessage`、`getMessages`、`getTokenUsage`、`chat`、`chatStream`、`save`、`reset`。
|
|
152
|
+
|
|
153
|
+
## File / Rerank / Reasoning
|
|
154
|
+
|
|
155
|
+
- `ai.file.parse({ content, filename, options })`:text/html/pdf/docx/ocr 解析。
|
|
156
|
+
- `ai.file.parseText(content, filename?)`:直接返回文本。
|
|
157
|
+
- `ai.rerank.rerank(request)` / `rerankTexts(query, texts, topN?)`:相关性重排。
|
|
158
|
+
- `ai.reasoning.run(query, options?)` / `runStream(query, options?)`:`react`、`cot`、`plan-execute`。
|
|
159
|
+
|
|
160
|
+
## A2A
|
|
161
|
+
|
|
162
|
+
| 方法 | 说明 |
|
|
163
|
+
| --- | --- |
|
|
164
|
+
| `registerExecutor(executor)` | 注册 Agent executor |
|
|
165
|
+
| `getAgentCard()` | 获取 Agent Card |
|
|
166
|
+
| `handleRequest(body, context?)` | 处理 A2A JSON-RPC 请求 |
|
|
167
|
+
| `listMessages(filter)` | 查询 A2A 消息记录 |
|
|
168
|
+
| `callRemoteAgent(remoteUrl, message, options?)` | 调用远端 Agent |
|
|
169
|
+
|
|
170
|
+
A2A 的 SDK handler 延迟创建;注册 executor 或首次处理请求时才装配运行时对象。
|
|
171
|
+
|
|
172
|
+
## 错误码速查
|
|
173
|
+
|
|
174
|
+
| 分段 | 代表错误 |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| `hai:ai:000` | `INTERNAL_ERROR` |
|
|
177
|
+
| `hai:ai:010-012` | 初始化:`NOT_INITIALIZED` / `CONFIGURATION_ERROR` / `INIT_IN_PROGRESS` |
|
|
178
|
+
| `hai:ai:020-033` | Rerank / File |
|
|
179
|
+
| `hai:ai:100-107` | LLM / 历史记录 |
|
|
180
|
+
| `hai:ai:200-204` | MCP |
|
|
181
|
+
| `hai:ai:300-302` | Embedding |
|
|
182
|
+
| `hai:ai:400-403` | Tool |
|
|
183
|
+
| `hai:ai:500-502` | Reasoning |
|
|
184
|
+
| `hai:ai:600-701` | Retrieval / RAG |
|
|
185
|
+
| `hai:ai:800-805` | Knowledge |
|
|
186
|
+
| `hai:ai:900-904` | Memory |
|
|
187
|
+
| `hai:ai:950-971` | Context / Store / Session |
|
|
188
|
+
| `hai:ai:980-984` | A2A |
|
|
189
|
+
|
|
190
|
+
## 浏览器端
|
|
191
|
+
|
|
192
|
+
浏览器端通过 `@h-ai/api-client` 或自定义 endpoint 访问服务端 AI 能力。`ai.stream` 可在浏览器直接用于解析服务端流式 chunk。
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
const response = await apiClient.ai.chats.createCompletion({ messages })
|
|
196
|
+
const memories = await apiClient.ai.memories.recall({ query: '偏好', objectId: 'user-001', topK: 5 })
|
|
197
|
+
```
|
|
@@ -94,6 +94,8 @@ await client.init({ baseUrl: 'https://api.example.com/api/v1' })
|
|
|
94
94
|
await apiClient.close()
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
> 已初始化后再次 `init()` 会返回 `CONFIG_ERROR`,不会覆盖现有 client;切换 `baseUrl` / `fetch` / `transport` 前必须先 `close()`,避免旧 transport 会话泄漏。
|
|
98
|
+
|
|
97
99
|
## Token Storage 适配器
|
|
98
100
|
|
|
99
101
|
| 工厂调用 | 存储位置 | 适用场景 |
|
|
@@ -130,7 +132,7 @@ if (login.success) {
|
|
|
130
132
|
|
|
131
133
|
| API | 用途 |
|
|
132
134
|
| --- | --- |
|
|
133
|
-
| `apiClient.init(config)` | 初始化默认 API Service client |
|
|
135
|
+
| `apiClient.init(config)` | 初始化默认 API Service client;重复初始化返回 `CONFIG_ERROR` |
|
|
134
136
|
| `apiClient.close()` | 清理 client 状态 |
|
|
135
137
|
| `apiClient.auth.setTokens(tokens)` | 写入 access token;非 httpOnly 存储会同时写入 refresh token |
|
|
136
138
|
| `apiClient.auth.clear()` | 清理 Token |
|
|
@@ -45,7 +45,7 @@ description: 对应用代码进行审查:检查 TDD 合规性、架构分层
|
|
|
45
45
|
|
|
46
46
|
### 架构分层
|
|
47
47
|
|
|
48
|
-
- [ ] `hooks.server.ts` 仅做中间件编排(初始化、i18n
|
|
48
|
+
- [ ] `hooks.server.ts` 仅做中间件编排(初始化、i18n、`handle` hook),无业务逻辑
|
|
49
49
|
- [ ] `+page.server.ts` / `+server.ts` 仅做请求处理(守卫 → 校验 → 调用服务 → 响应)
|
|
50
50
|
- [ ] 业务逻辑集中在 `$lib/server/services/`
|
|
51
51
|
- [ ] 客户端组件不直接调用数据库或服务端模块
|
|
@@ -61,6 +61,8 @@ services:
|
|
|
61
61
|
```typescript
|
|
62
62
|
import { deploy } from '@h-ai/deploy'
|
|
63
63
|
|
|
64
|
+
deploy.credentials.load()
|
|
65
|
+
|
|
64
66
|
await deploy.init({
|
|
65
67
|
provider: { type: 'vercel', token: 'vel_xxx' },
|
|
66
68
|
services: {
|
|
@@ -113,9 +115,13 @@ if (result.success) {
|
|
|
113
115
|
|
|
114
116
|
| 方法 | 签名 | 说明 |
|
|
115
117
|
| ---------------------- | -------------------------------------------------------------------------- | ------------ |
|
|
118
|
+
| `deploy.credentials.load` | `() => HaiResult<string[]>` | 加载凭证到 `process.env` |
|
|
119
|
+
| `deploy.credentials.save` | `(key: string, value: string) => HaiResult<void>` | 保存单个凭证 |
|
|
120
|
+
| `deploy.credentials.saveAll` | `(entries: Record<string, string>) => HaiResult<void>` | 批量保存凭证 |
|
|
121
|
+
| `deploy.credentials.getPath` | `() => string` | 获取凭证文件路径 |
|
|
116
122
|
| `deploy.init` | `(config: DeployConfigInput) => Promise<HaiResult<void>>` | 初始化模块 |
|
|
117
123
|
| `deploy.close` | `() => Promise<void>` | 关闭模块 |
|
|
118
|
-
| `deploy.scan` | `(appDir: string) => Promise<HaiResult<ScanResult>>` |
|
|
124
|
+
| `deploy.scan` | `(appDir: string) => Promise<HaiResult<ScanResult>>` | 扫描应用(不依赖 init) |
|
|
119
125
|
| `deploy.provisionAll` | `(projectName: string) => Promise<HaiResult<ProvisionResult[]>>` | 开通所有服务 |
|
|
120
126
|
| `deploy.deployApp` | `(appDir: string, options?) => Promise<HaiResult<DeployResult>>` | 完整部署 |
|
|
121
127
|
| `deploy.config` | `DeployConfig \| null` | 当前配置 |
|
|
@@ -125,12 +131,9 @@ if (result.success) {
|
|
|
125
131
|
|
|
126
132
|
## 凭证管理
|
|
127
133
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
| `saveCredential(key, value)` | 保存单个凭证 |
|
|
132
|
-
| `saveCredentials(entries)` | 批量保存凭证 |
|
|
133
|
-
| `getCredentialsPath()` | 获取凭证文件路径 |
|
|
134
|
+
所有凭证操作都通过 `deploy.credentials.*` 访问,模块入口不再单独导出自由函数。
|
|
135
|
+
|
|
136
|
+
> `deploy.credentials.*()` 与 `deploy.scan()` 都不依赖 `deploy.init()`,可用于 CLI 在读取 `_deploy.yml` 之前准备环境。
|
|
134
137
|
|
|
135
138
|
---
|
|
136
139
|
|
|
@@ -147,8 +150,8 @@ if (result.success) {
|
|
|
147
150
|
| `HaiDeployError.PROVISION_FAILED` | `hai:deploy:007` | 基础设施开通失败 |
|
|
148
151
|
| `HaiDeployError.ADAPTER_MISSING` | `hai:deploy:008` | SvelteKit adapter 未安装 |
|
|
149
152
|
| `HaiDeployError.SCAN_FAILED` | `hai:deploy:009` | 应用扫描失败 |
|
|
150
|
-
| `HaiDeployError.
|
|
151
|
-
| `HaiDeployError.
|
|
153
|
+
| `HaiDeployError.NOT_INITIALIZED` | `hai:deploy:010` | 模块未初始化 |
|
|
154
|
+
| `HaiDeployError.ENV_VAR_FAILED` | `hai:deploy:011` | 环境变量设置失败 |
|
|
152
155
|
| `HaiDeployError.UNSUPPORTED_TYPE` | `hai:deploy:012` | 不支持的类型 |
|
|
153
156
|
| `HaiDeployError.CONFIG_ERROR` | `hai:deploy:013` | 配置错误 |
|
|
154
157
|
| `HaiDeployError.CREDENTIAL_ERROR` | `hai:deploy:014` | 凭证读写失败 |
|
|
@@ -5,7 +5,7 @@ description: 使用 @h-ai/kit 构建 SvelteKit 请求管道、认证守卫、统
|
|
|
5
5
|
|
|
6
6
|
# hai-kit
|
|
7
7
|
|
|
8
|
-
> `@h-ai/kit` 只负责 SvelteKit
|
|
8
|
+
> `@h-ai/kit` 只负责 SvelteKit 集成:`handle` hook、guard、response、validate、client、auth、crud、A2A。公共跨端 HTTP API 契约统一使用 `@h-ai/api-contract` + `@h-ai/serv`,不要在 kit 中定义业务 API contract。
|
|
9
9
|
|
|
10
10
|
## 使用步骤
|
|
11
11
|
|
|
@@ -48,10 +48,12 @@ export const POST = kit.handler(async ({ request, locals }) => {
|
|
|
48
48
|
```ts
|
|
49
49
|
import { kit } from '@h-ai/kit'
|
|
50
50
|
|
|
51
|
-
const client = kit.client.create(
|
|
51
|
+
const client = kit.client.create()
|
|
52
52
|
export const { apiFetch } = client
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
> 同源 endpoint 优先使用 httpOnly Cookie;`auth: true` 只读取 `kit.auth.setBrowserToken()` 写入的页面内存 Token,不会默认读写 localStorage。确需 Bearer Header 时,显式传入 `BrowserTokenStore`,禁止把敏感 Token 存入 localStorage。
|
|
56
|
+
|
|
55
57
|
### 4. 同源传输加密
|
|
56
58
|
|
|
57
59
|
kit 不再维护本地传输加密实现;服务端和客户端都统一委托 `@h-ai/crypto` 的 `crypto.transport`。
|
|
@@ -100,7 +102,7 @@ export const handle = kit.createHandle({
|
|
|
100
102
|
// lib/utils/api.ts —— 业务层只看到 apiFetch
|
|
101
103
|
import { kit } from '@h-ai/kit'
|
|
102
104
|
|
|
103
|
-
export const { apiFetch } = kit.client.create(
|
|
105
|
+
export const { apiFetch } = kit.client.create()
|
|
104
106
|
```
|
|
105
107
|
|
|
106
108
|
默认协商端点:`/api/_hai/key-exchange`。如 `keyExchangePath` 自定义,浏览器端同步设置 `keyExchangeUrl`。
|
|
@@ -13,6 +13,8 @@ description: 使用 @h-ai/serv 将 oRPC contract 挂载为最小 HTTP App 抽象
|
|
|
13
13
|
|
|
14
14
|
> ⚠️ **服务端模块(Node.js / Fetch Runtime)。** 浏览器端通过 `@h-ai/api-client` 调用由本模块暴露的 HTTP API。
|
|
15
15
|
|
|
16
|
+
> 生命周期说明:`@h-ai/serv` 是无状态 HTTP App 装配器,不提供 `init()` / `close()`;依赖模块(iam/storage/ai/crypto 等)由应用先初始化,并在 `serv.listen(..., { onClose })` 中反向释放。`serv.createApp()` 的启动期配置错误会 fail-fast 抛出。
|
|
17
|
+
|
|
16
18
|
---
|
|
17
19
|
|
|
18
20
|
## 适用场景
|
|
@@ -5,7 +5,7 @@ description: 使用 @h-ai/ui 构建多端应用界面,包含三层组件架构
|
|
|
5
5
|
|
|
6
6
|
# hai-ui
|
|
7
7
|
|
|
8
|
-
> `@h-ai/ui` 是基于 Svelte 5 Runes 的多端 UI 组件库,采用 DaisyUI v5 + Tailwind CSS v4 + Bits UI v2
|
|
8
|
+
> `@h-ai/ui` 是基于 Svelte 5 Runes 的多端 UI 组件库,采用 DaisyUI v5 + Tailwind CSS v4 + Bits UI v2,内置 15 个精选 DaisyUI 主题、内置中英文 i18n、自动导入。内置 Shiki 代码高亮、Design Token 系统和 7 个移动端组件。
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -20,8 +20,9 @@ description: 使用 @h-ai/ui 构建多端应用界面,包含三层组件架构
|
|
|
20
20
|
- 构建管理后台页面(表单、表格、弹窗、导航等)
|
|
21
21
|
- 移动端/App 界面开发(SafeArea、BottomNav、PullRefresh 等)
|
|
22
22
|
- 使用 Bits UI headless 交互组件(Combobox、DatePicker、Calendar)
|
|
23
|
-
- 使用 IAM
|
|
24
|
-
- 使用 Storage
|
|
23
|
+
- 使用 IAM 场景组件(登录/注册/密码/权限守卫/用户资料表单)
|
|
24
|
+
- 使用 Storage 场景组件(文件上传/图片上传/头像上传/文件列表)
|
|
25
|
+
- 使用 CRUD 场景组件(列表过滤、详情抽屉、编辑抽屉、删除确认)
|
|
25
26
|
- 配置主题切换与 i18n 多语言
|
|
26
27
|
- 多端平台检测与适配
|
|
27
28
|
|
|
@@ -146,7 +147,7 @@ export default defineConfig({
|
|
|
146
147
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
147
148
|
<script>
|
|
148
149
|
// 防止主题切换闪烁:在 DOM 渲染前应用已保存的主题
|
|
149
|
-
(function(){var t=localStorage.getItem('
|
|
150
|
+
(function(){var t='light';try{var s=localStorage.getItem('theme');if(s)t=s}catch{}document.documentElement.setAttribute('data-theme',t)})()
|
|
150
151
|
</script>
|
|
151
152
|
%sveltekit.head%
|
|
152
153
|
</head>
|
|
@@ -175,12 +176,12 @@ const p = usePlatform()
|
|
|
175
176
|
|
|
176
177
|
## 三层组件架构
|
|
177
178
|
|
|
178
|
-
### 原子组件(Primitives,
|
|
179
|
+
### 原子组件(Primitives,20 个)
|
|
179
180
|
|
|
180
181
|
| 组件 | Props 要点 | 说明 |
|
|
181
182
|
| ------------ | ------------------------------------------------------------- | -------- |
|
|
182
183
|
| `Button` | `variant`, `size`, `loading`, `disabled`, `outline`, `circle` | 按钮 |
|
|
183
|
-
| `IconButton` | `icon: string \| Snippet`, `tooltip`, `variant`, `size`
|
|
184
|
+
| `IconButton` | `icon: trusted SVG string \| Snippet`, `tooltip`, `variant`, `size` | 图标按钮 |
|
|
184
185
|
| `Input` | `value`, `type`, `size`, `error`, `placeholder` | 输入框 |
|
|
185
186
|
| `Textarea` | `value`, `rows`, `autoResize`, `error` | 文本域 |
|
|
186
187
|
| `Select` | `value`, `options: SelectOption[]`, `placeholder` | 下拉选择 |
|
|
@@ -195,7 +196,7 @@ const p = usePlatform()
|
|
|
195
196
|
| `Spinner` | `size`, `variant` | 加载动画 |
|
|
196
197
|
| `Progress` | `value`, `max`, `striped`, `animated` | 进度条 |
|
|
197
198
|
|
|
198
|
-
### 组合组件(Compounds,
|
|
199
|
+
### 组合组件(Compounds,33 个)
|
|
199
200
|
|
|
200
201
|
由原子组件 + Bits UI headless 交互组合。
|
|
201
202
|
|
|
@@ -306,6 +307,7 @@ const p = usePlatform()
|
|
|
306
307
|
| ------------- | ---------------------------------------------- | -------- |
|
|
307
308
|
| `FileUpload` | `accept`, `maxSize`, `uploadUrl`, `autoUpload` | 文件上传 |
|
|
308
309
|
| `ImageUpload` | `value`, `uploadUrl`, `aspectRatio` | 图片上传 |
|
|
310
|
+
| `AvatarUpload` | `value`, `size`, `maxSize`, `fallback` | 头像上传 |
|
|
309
311
|
| `FileList` | `files: FileItem[]`, `layout`, `showPreview` | 文件列表 |
|
|
310
312
|
|
|
311
313
|
#### AI 场景组件
|
|
@@ -313,9 +315,21 @@ const p = usePlatform()
|
|
|
313
315
|
| 组件 | 说明 |
|
|
314
316
|
| -------------------- | --------------------------------- |
|
|
315
317
|
| `MarkdownRenderer` | Markdown 渲染(内置 Shiki 高亮) |
|
|
316
|
-
| `
|
|
318
|
+
| `AiDocumentDownloadMenu` | AI 文档下载菜单 |
|
|
319
|
+
| `AiDocumentEditor` | AI 文档编辑器(支持受控代码预览) |
|
|
320
|
+
| `AiTableEditor` | AI 表格编辑器 |
|
|
317
321
|
|
|
318
|
-
> AI 场景组件使用 Shiki(纯 ESM)进行代码高亮,支持 27 种语言,通过 CSS 变量 `--hai-hl-*` 自定义颜色。无需额外安装 Shiki
|
|
322
|
+
> AI 场景组件使用 Shiki(纯 ESM)进行代码高亮,支持 27 种语言,通过 CSS 变量 `--hai-hl-*` 自定义颜色。无需额外安装 Shiki,已内置。`AiDocumentEditor` 默认只允许 Markdown 内置预览;HTML / JS / CSS 等高风险预览需要显式启用 `allowUnsafeCodePreview`,或通过 `oncoderun` 返回受控的预览结果。
|
|
323
|
+
|
|
324
|
+
#### CRUD 场景组件
|
|
325
|
+
|
|
326
|
+
| 组件 | 说明 |
|
|
327
|
+
| ------------------- | ---- |
|
|
328
|
+
| `CrudPage` | CRUD 主页面 |
|
|
329
|
+
| `CrudFilterBar` | 过滤工具栏 |
|
|
330
|
+
| `CrudDetailDrawer` | 详情抽屉 |
|
|
331
|
+
| `CrudEditDrawer` | 编辑抽屉 |
|
|
332
|
+
| `CrudDeleteConfirm` | 删除确认框 |
|
|
319
333
|
|
|
320
334
|
---
|
|
321
335
|
|
|
@@ -363,7 +377,7 @@ const p = usePlatform()
|
|
|
363
377
|
|
|
364
378
|
## 主题系统
|
|
365
379
|
|
|
366
|
-
支持
|
|
380
|
+
支持 15 个精选 DaisyUI 主题。
|
|
367
381
|
|
|
368
382
|
```typescript
|
|
369
383
|
import { applyTheme, getCurrentTheme, isDarkTheme, THEMES, THEME_GROUPS } from '@h-ai/ui'
|
|
@@ -409,7 +423,7 @@ typescript, javascript, python, java, go, rust, c, cpp, csharp, ruby, php, swift
|
|
|
409
423
|
|
|
410
424
|
1. **Svelte 5 Runes**:使用 `$state`、`$derived`、`$effect`
|
|
411
425
|
2. **Snippet 插槽**:使用 `{#snippet name()}...{/snippet}` 语法
|
|
412
|
-
3. **自动导入例外**:`toast
|
|
426
|
+
3. **自动导入例外**:`toast`、类型导入与 `Range` 必须显式 `import`;其余公开 Svelte 组件可自动导入
|
|
413
427
|
4. **Combobox 统一单选/多选**:`MultiSelect` 已删除
|
|
414
428
|
5. **移动端样式**:务必引入 `design-tokens.css` + `mobile.css`,使用 SafeArea 包裹原生 App 页面
|
|
415
429
|
6. **`@source` 必须配置**:未配置则 TailwindCSS 无法扫描 `@h-ai/ui` 组件中的 class,样式会丢失
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/cli-config-templates.ts"],"names":[],"mappings":"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","file":"chunk-BPO34NRL.js","sourcesContent":["/**\n * @h-ai/cli — 配置文件模板\n *\n * 为各模块生成默认配置文件内容。\n * @module cli-config-templates\n */\n\nimport type { AiModuleConfig, CacheModuleConfig, CoreModuleConfig, DbModuleConfig, FeatureId, IamModuleConfig, ModuleConfigs, StorageModuleConfig } from '../cli-types.js'\n\n/**\n * 生成模块配置文件内容\n *\n * @param moduleKey - 模块标识(core/db/cache/iam/storage/ai)\n * @param configs - 用户自定义配置值\n * @returns YAML 格式的配置内容\n */\nexport function generateConfigFile(moduleKey: string, configs?: ModuleConfigs): string {\n switch (moduleKey) {\n case 'core':\n return generateCoreConfig(configs?.core)\n case 'db':\n return generateDbConfig(configs?.db)\n case 'cache':\n return generateCacheConfig(configs?.cache)\n case 'iam':\n return generateIamConfig(configs?.iam)\n case 'storage':\n return generateStorageConfig(configs?.storage)\n case 'ai':\n return generateAiConfig(configs?.ai)\n case 'deploy':\n return generateDeployConfig()\n case 'vecdb':\n return generateVecdbConfig()\n case 'reach':\n return generateReachConfig()\n case 'scheduler':\n return generateSchedulerConfig()\n case 'audit':\n return generateAuditConfig()\n case 'payment':\n return generatePaymentConfig()\n default:\n return `# ${moduleKey} 配置\\n`\n }\n}\n\nfunction generateCoreConfig(cfg?: CoreModuleConfig): string {\n const name = cfg?.name ?? 'my-app'\n const locale = cfg?.defaultLocale ?? 'zh-CN'\n const supportedLocales = locale === 'en-US'\n ? ` - en-US\\n - zh-CN`\n : ` - zh-CN\\n - en-US`\n\n return `# =============================================================================\n# 应用配置\n# =============================================================================\n\nname: ${name}\nversion: 0.1.0\nenv: \\${HAI_ENV:development}\ndebug: \\${HAI_DEBUG:false}\n\ndefaultLocale: ${locale}\nsupportedLocales:\n${supportedLocales}\n`\n}\n\nfunction generateDbConfig(cfg?: DbModuleConfig): string {\n const dbType = cfg?.type ?? 'sqlite'\n const database = cfg?.database ?? (dbType === 'sqlite' ? './data/app.db' : 'hai')\n const host = cfg?.host ?? 'localhost'\n const port = cfg?.port ?? (dbType === 'postgresql' ? 5432 : 3306)\n\n if (dbType === 'sqlite') {\n return `# =============================================================================\n# 数据库配置\n# =============================================================================\n\n# 数据库类型: sqlite | postgresql | mysql\ntype: sqlite\n\n# SQLite 数据库路径\ndatabase: \\${HAI_RELDB_DATABASE:${database}}\n\n# PostgreSQL/MySQL 配置(可选)\n# host: \\${HAI_RELDB_HOST:localhost}\n# port: \\${HAI_RELDB_PORT:5432}\n# user: \\${HAI_RELDB_USER:postgres}\n# password: \\${HAI_RELDB_PASSWORD:}\n`\n }\n\n const user = dbType === 'postgresql' ? 'postgres' : 'root'\n\n return `# =============================================================================\n# 数据库配置\n# =============================================================================\n\n# 数据库类型: sqlite | postgresql | mysql\ntype: ${dbType}\n\n# 数据库名称\ndatabase: \\${HAI_RELDB_DATABASE:${database}}\n\n# 连接配置\nhost: \\${HAI_RELDB_HOST:${host}}\nport: \\${HAI_RELDB_PORT:${port}}\nuser: \\${HAI_RELDB_USER:${user}}\npassword: \\${HAI_RELDB_PASSWORD:}\n`\n}\n\nfunction generateCacheConfig(cfg?: CacheModuleConfig): string {\n const cacheType = cfg?.type ?? 'memory'\n\n if (cacheType === 'memory') {\n return `# =============================================================================\n# 缓存配置\n# =============================================================================\n\n# 缓存类型: memory | redis\ntype: memory\n\n# Redis 配置(当 type 为 redis 时使用)\n# url: \\${HAI_CACHE_REDIS_URL:redis://localhost:6379/0}\n# host: \\${HAI_CACHE_REDIS_HOST:localhost}\n# port: \\${HAI_CACHE_REDIS_PORT:6379}\n# password: \\${HAI_CACHE_REDIS_PASSWORD:}\n# keyPrefix: \\${HAI_CACHE_KEY_PREFIX:hai:}\n`\n }\n\n const host = cfg?.host ?? 'localhost'\n const port = cfg?.port ?? 6379\n\n return `# =============================================================================\n# 缓存配置\n# =============================================================================\n\n# 缓存类型: memory | redis\ntype: redis\n\n# Redis 配置\nhost: \\${HAI_CACHE_REDIS_HOST:${host}}\nport: \\${HAI_CACHE_REDIS_PORT:${port}}\npassword: \\${HAI_CACHE_REDIS_PASSWORD:}\nkeyPrefix: \\${HAI_CACHE_KEY_PREFIX:hai:}\n`\n}\n\nfunction generateIamConfig(cfg?: IamModuleConfig): string {\n const loginPassword = cfg?.loginPassword ?? true\n const loginOtp = cfg?.loginOtp ?? false\n\n return `# =============================================================================\n# IAM 配置\n# =============================================================================\n\n# 登录配置\nlogin:\n password: ${loginPassword}\n otp: ${loginOtp}\n ldap: false\n\n# 密码策略\npassword:\n minLength: 8\n maxLength: 128\n requireUppercase: false\n requireLowercase: false\n requireNumber: false\n requireSpecialChar: false\n\n# 会话配置\nsession:\n maxAge: 86400 # 会话超时(秒),默认 24 小时\n sliding: true # 滑动窗口(每次请求刷新过期时间)\n singleDevice: false # 单设备登录\n refreshTokenMaxAge: 604800 # refreshToken 过期(秒),默认 7 天\n\n# RBAC 配置\nrbac:\n defaultRole: user\n\n# 是否自动创建默认数据\nseedDefaultData: true\n`\n}\n\nfunction generateStorageConfig(cfg?: StorageModuleConfig): string {\n const storageType = cfg?.type ?? 'local'\n\n if (storageType === 'local') {\n const localPath = cfg?.localPath ?? './data/uploads'\n return `# =============================================================================\n# 存储配置\n# =============================================================================\n\n# 默认 Provider\ndefaultProvider: local\n\n# Provider 配置\nproviders:\n local:\n type: local\n root: \\${HAI_STORAGE_PATH:${localPath}}\n maxFileSize: 10485760 # 10MB\n\n # S3 配置(可选)\n # s3:\n # type: s3\n # bucket: \\${HAI_STORAGE_S3_BUCKET}\n # region: \\${HAI_STORAGE_S3_REGION:us-east-1}\n # accessKeyId: \\${HAI_STORAGE_S3_ACCESS_KEY}\n # secretAccessKey: \\${HAI_STORAGE_S3_SECRET_KEY}\n # endpoint: \\${HAI_STORAGE_S3_ENDPOINT}\n # forcePathStyle: \\${HAI_STORAGE_S3_FORCE_PATH_STYLE:false}\n`\n }\n\n return `# =============================================================================\n# 存储配置\n# =============================================================================\n\n# 默认 Provider\ndefaultProvider: s3\n\n# Provider 配置\nproviders:\n s3:\n type: s3\n bucket: \\${HAI_STORAGE_S3_BUCKET}\n region: \\${HAI_STORAGE_S3_REGION:us-east-1}\n accessKeyId: \\${HAI_STORAGE_S3_ACCESS_KEY}\n secretAccessKey: \\${HAI_STORAGE_S3_SECRET_KEY}\n # endpoint: \\${HAI_STORAGE_S3_ENDPOINT}\n # forcePathStyle: \\${HAI_STORAGE_S3_FORCE_PATH_STYLE:false}\n\n # 本地存储(可选)\n # local:\n # type: local\n # root: \\${HAI_STORAGE_PATH:./data/uploads}\n # maxFileSize: 10485760 # 10MB\n`\n}\n\nfunction generateAiConfig(cfg?: AiModuleConfig): string {\n const model = cfg?.model ?? 'gpt-4o-mini'\n\n // AIConfigSchema 结构:llm(必填)+ 可选子模块\n // LLMConfigSchema 支持顶层 apiKey/model,以及多模型 models 数组\n return `# =============================================================================\n# AI 配置\n# =============================================================================\n\n# LLM 配置(必填)\nllm:\n # API Key(留空时自动读取 HAI_AI_LLM_API_KEY / OPENAI_API_KEY 环境变量)\n apiKey: \\${HAI_AI_LLM_API_KEY:}\n # Base URL(留空时自动读取 HAI_AI_LLM_BASE_URL / OPENAI_BASE_URL,默认 https://api.openai.com/v1)\n # baseUrl: \\${HAI_AI_LLM_BASE_URL:}\n # 默认模型\n model: ${model}\n # 全局最大 Token 数(默认 4096)\n # maxTokens: 4096\n # 采样温度(0-2,默认 0.7)\n # temperature: 0.7\n # 请求超时(毫秒,默认 60000)\n # timeout: 60000\n\n # 多模型配置(可选,用于场景路由)\n # models:\n # - id: fast\n # model: gpt-4o-mini\n # - id: smart\n # model: gpt-4o\n # apiKey: \\${HAI_AI_LLM_API_KEY:}\n\n # 场景模型映射(可选)\n # scenarios:\n # default: fast\n # analysis: smart\n`\n}\n\n/**\n * 根据选中的功能模块生成 .env.example 内容\n *\n * @param features - 选中的功能模块列表\n * @param configs - 用户自定义配置值\n * @returns .env.example 文件内容\n */\nexport function generateEnvExample(features: FeatureId[], configs?: ModuleConfigs): string {\n const sections: string[] = []\n\n // 文件头\n sections.push(`# =============================================================================\n# Environment Variables\n# =============================================================================\n#\n# Copy this file to .env and fill in actual values.\n# Config files in config/ reference these variables via \\${VAR_NAME:default} syntax.\n#\n# Naming convention: HAI_<MODULE>_<SETTING>\n# =============================================================================`)\n\n // 应用基础(始终生成)\n sections.push(`\n# =============================================================================\n# Application\n# =============================================================================\n# Environment: development | production | test\nHAI_ENV=development\n# Enable debug mode\nHAI_DEBUG=false`)\n\n // 数据库\n if (features.includes('db')) {\n const dbType = configs?.db?.type ?? 'sqlite'\n const dbDatabase = configs?.db?.database ?? (dbType === 'sqlite' ? './data/app.db' : 'hai')\n const isSqlite = dbType === 'sqlite'\n sections.push(`\n# =============================================================================\n# Database (@h-ai/reldb)\n# =============================================================================\n# Database type: sqlite | postgresql | mysql\nHAI_RELDB_TYPE=${dbType}\n# SQLite: file path; PostgreSQL/MySQL: database name\nHAI_RELDB_DATABASE=${dbDatabase}${isSqlite\n ? `\n# PostgreSQL/MySQL connection (uncomment when not using sqlite)\n# HAI_RELDB_HOST=localhost\n# HAI_RELDB_PORT=5432\n# HAI_RELDB_USER=postgres\n# HAI_RELDB_PASSWORD=`\n : `\n# Connection\nHAI_RELDB_HOST=${configs?.db?.host ?? 'localhost'}\nHAI_RELDB_PORT=${configs?.db?.port ?? (dbType === 'postgresql' ? 5432 : 3306)}\nHAI_RELDB_USER=${dbType === 'postgresql' ? 'postgres' : 'root'}\nHAI_RELDB_PASSWORD=`}`)\n }\n\n // IAM / Session\n if (features.includes('iam')) {\n sections.push(`\n# =============================================================================\n# IAM (@h-ai/iam)\n# =============================================================================\nHAI_IAM_SESSION_SECRET=change-me-to-a-strong-random-string-min-32-chars\n# HAI_IAM_PASSWORD_MIN_LENGTH=8\n# HAI_IAM_SESSION_MAX_AGE=86400\n# HAI_IAM_REFRESH_TOKEN_MAX_AGE=604800\n# HAI_IAM_MAX_LOGIN_ATTEMPTS=5\n# HAI_KIT_COOKIE_KEY= # 32-char hex for SM4-CBC cookie encryption\n`)\n }\n\n // 缓存\n if (features.includes('cache')) {\n const cacheType = configs?.cache?.type ?? 'memory'\n if (cacheType === 'redis') {\n sections.push(`\n# =============================================================================\n# Cache (@h-ai/cache)\n# =============================================================================\n# Cache type: memory | redis\nHAI_CACHE_TYPE=redis\n# Redis connection\nHAI_CACHE_REDIS_HOST=${configs?.cache?.host ?? 'localhost'}\nHAI_CACHE_REDIS_PORT=${configs?.cache?.port ?? 6379}\nHAI_CACHE_REDIS_PASSWORD=\n# HAI_CACHE_REDIS_URL=redis://localhost:6379/0\n# HAI_CACHE_REDIS_DB=0\n# HAI_CACHE_CONNECT_TIMEOUT=10000\n# HAI_CACHE_COMMAND_TIMEOUT=5000\n# HAI_CACHE_KEY_PREFIX=hai:`)\n }\n else {\n sections.push(`\n# =============================================================================\n# Cache (@h-ai/cache)\n# =============================================================================\n# Cache type: memory | redis\nHAI_CACHE_TYPE=memory\n# Redis connection (uncomment when type=redis)\n# HAI_CACHE_REDIS_URL=redis://localhost:6379/0\n# HAI_CACHE_REDIS_HOST=localhost\n# HAI_CACHE_REDIS_PORT=6379\n# HAI_CACHE_REDIS_PASSWORD=\n# HAI_CACHE_REDIS_DB=0\n# HAI_CACHE_CONNECT_TIMEOUT=10000\n# HAI_CACHE_COMMAND_TIMEOUT=5000\n# HAI_CACHE_KEY_PREFIX=hai:`)\n }\n }\n\n // 存储\n if (features.includes('storage')) {\n const storageType = configs?.storage?.type ?? 'local'\n if (storageType === 's3') {\n sections.push(`\n# =============================================================================\n# Storage (@h-ai/storage)\n# =============================================================================\n# Storage type: local | s3\nHAI_STORAGE_TYPE=s3\n# S3 / S3-compatible\nHAI_STORAGE_S3_BUCKET=\nHAI_STORAGE_S3_REGION=us-east-1\nHAI_STORAGE_S3_ACCESS_KEY=\nHAI_STORAGE_S3_SECRET_KEY=\n# HAI_STORAGE_S3_ENDPOINT= # Custom endpoint for MinIO / Aliyun OSS etc.\n# HAI_STORAGE_S3_FORCE_PATH_STYLE=false\n# Local storage (uncomment when type=local)\n# HAI_STORAGE_PATH=./data/uploads`)\n }\n else {\n sections.push(`\n# =============================================================================\n# Storage (@h-ai/storage)\n# =============================================================================\n# Storage type: local | s3\nHAI_STORAGE_TYPE=local\n# Local storage root path\nHAI_STORAGE_PATH=${configs?.storage?.localPath ?? './data/uploads'}\n# S3 / S3-compatible (uncomment when type=s3)\n# HAI_STORAGE_S3_BUCKET=\n# HAI_STORAGE_S3_REGION=us-east-1\n# HAI_STORAGE_S3_ACCESS_KEY=\n# HAI_STORAGE_S3_SECRET_KEY=\n# HAI_STORAGE_S3_ENDPOINT= # Custom endpoint for MinIO / Aliyun OSS etc.\n# HAI_STORAGE_S3_FORCE_PATH_STYLE=false`)\n }\n }\n\n // AI\n if (features.includes('ai')) {\n const provider = configs?.ai?.defaultProvider ?? 'openai'\n if (provider === 'anthropic') {\n sections.push(`\n# =============================================================================\n# AI (@h-ai/ai)\n# =============================================================================\n# OpenAI-compatible API Key (Anthropic models via OpenAI-compatible proxy)\nHAI_AI_LLM_API_KEY=\n# HAI_AI_LLM_BASE_URL= # Custom base URL\n# Optional compatibility fallback\n# OPENAI_API_KEY=`)\n }\n else if (provider === 'openai') {\n sections.push(`\n# =============================================================================\n# AI (@h-ai/ai)\n# =============================================================================\n# OpenAI / OpenAI-compatible\nHAI_AI_LLM_API_KEY=\n# HAI_AI_LLM_BASE_URL= # Custom base URL (e.g. local proxy, Azure)\n# Optional compatibility fallback\n# OPENAI_API_KEY=`)\n }\n else {\n sections.push(`\n# =============================================================================\n# AI (@h-ai/ai)\n# =============================================================================\n# OpenAI-compatible provider\nHAI_AI_LLM_API_KEY=\n# HAI_AI_LLM_BASE_URL= # Custom base URL\n# Optional compatibility fallback\n# OPENAI_API_KEY=`)\n }\n }\n\n // VecDB\n if (features.includes('vecdb')) {\n sections.push(`\n# =============================================================================\n# Vector Database (@h-ai/vecdb)\n# =============================================================================\n# Backend type: lancedb | pgvector | qdrant\nHAI_VECDB_TYPE=lancedb\n# LanceDB data path\nHAI_VECDB_PATH=./data/vecdb\n# Qdrant (uncomment when type=qdrant)\n# HAI_VECDB_QDRANT_URL=http://localhost:6333\n# HAI_VECDB_QDRANT_API_KEY=\n`)\n }\n\n // Reach\n if (features.includes('reach')) {\n sections.push(`\n# =============================================================================\n# Reach (@h-ai/reach)\n# =============================================================================\n# SMTP (uncomment when enabling email provider)\n# HAI_REACH_SMTP_HOST=smtp.example.com\n# HAI_REACH_SMTP_PORT=465\n# HAI_REACH_SMTP_USER=\n# HAI_REACH_SMTP_PASS=\n# HAI_REACH_SMTP_FROM=noreply@example.com\n`)\n }\n\n // Payment\n if (features.includes('payment')) {\n sections.push(`\n# =============================================================================\n# Payment (@h-ai/payment)\n# =============================================================================\n# WeChat Pay\n# HAI_PAYMENT_WECHAT_MCH_ID=\n# HAI_PAYMENT_WECHAT_API_V3_KEY=\n# HAI_PAYMENT_WECHAT_SERIAL_NO=\n# HAI_PAYMENT_WECHAT_PRIVATE_KEY=\n# HAI_PAYMENT_WECHAT_APP_ID=\n# Alipay\n# HAI_PAYMENT_ALIPAY_APP_ID=\n# HAI_PAYMENT_ALIPAY_PRIVATE_KEY=\n# HAI_PAYMENT_ALIPAY_PUBLIC_KEY=\n# Stripe\n# HAI_PAYMENT_STRIPE_SECRET_KEY=\n# HAI_PAYMENT_STRIPE_WEBHOOK_SECRET=\n`)\n }\n\n // 测试(始终生成)\n sections.push(`\n# =============================================================================\n# Testing\n# =============================================================================\n# E2E test mode (relaxes rate limiting etc.)\n# HAI_E2E=1\n`)\n\n return sections.join('\\n')\n}\n\nfunction generateDeployConfig(): string {\n return `# =============================================================================\n# 部署配置 (@h-ai/deploy)\n# =============================================================================\n# 部署平台凭证通过 ~/.hai/credentials.yml 管理\n# 环境变量引用格式: \\${VAR_NAME:default_value}\n\n# 部署平台\nprovider:\n type: vercel\n token: \\${HAI_DEPLOY_VERCEL_TOKEN}\n\n# 基础设施服务(按需开启)\nservices:\n # PostgreSQL 数据库 (Neon)\n # db:\n # provisioner: neon\n # apiKey: \\${HAI_DEPLOY_NEON_API_KEY}\n\n # Redis 缓存 (Upstash)\n # cache:\n # provisioner: upstash\n # email: \\${HAI_DEPLOY_UPSTASH_EMAIL}\n # apiKey: \\${HAI_DEPLOY_UPSTASH_API_KEY}\n\n # S3 存储 (Cloudflare R2)\n # storage:\n # provisioner: cloudflare-r2\n # accountId: \\${HAI_DEPLOY_CF_ACCOUNT_ID}\n # apiToken: \\${HAI_DEPLOY_CF_API_TOKEN}\n\n # 邮件 (Resend)\n # email:\n # provisioner: resend\n # apiKey: \\${HAI_DEPLOY_RESEND_API_KEY}\n\n # 短信 (阿里云)\n # sms:\n # provisioner: aliyun\n # accessKeyId: \\${HAI_DEPLOY_ALIYUN_ACCESS_KEY_ID}\n # accessKeySecret: \\${HAI_DEPLOY_ALIYUN_ACCESS_KEY_SECRET}\n`\n}\n\nfunction generateVecdbConfig(): string {\n return `# =============================================================================\n# 向量数据库配置 (@h-ai/vecdb)\n# =============================================================================\n\n# 数据库类型: lancedb | pgvector | qdrant\ntype: lancedb\n\n# LanceDB 数据目录\npath: \\${HAI_VECDB_PATH:./data/vecdb}\n\n# 距离度量: cosine | euclidean | dot\n# metric: cosine\n\n# pgvector 配置(当 type 为 pgvector 时使用)\n# type: pgvector\n# host: \\${HAI_RELDB_HOST:localhost}\n# port: \\${HAI_RELDB_PORT:5432}\n# database: \\${HAI_RELDB_DATABASE:hai}\n# user: \\${HAI_RELDB_USER:postgres}\n# password: \\${HAI_RELDB_PASSWORD:}\n# indexType: hnsw\n# tablePrefix: vec_\n\n# Qdrant 配置(当 type 为 qdrant 时使用)\n# type: qdrant\n# url: \\${HAI_VECDB_QDRANT_URL:http://localhost:6333}\n# apiKey: \\${HAI_VECDB_QDRANT_API_KEY:}\n`\n}\n\nfunction generateReachConfig(): string {\n return `# =============================================================================\n# 消息推送配置 (@h-ai/reach)\n# =============================================================================\n\nproviders:\n # 控制台输出(开发/测试用)\n - name: console_dev\n type: console\n\n # SMTP 邮件(按需开启)\n # - name: email\n # type: smtp\n # host: \\${HAI_REACH_SMTP_HOST:smtp.example.com}\n # port: \\${HAI_REACH_SMTP_PORT:465}\n # secure: true\n # user: \\${HAI_REACH_SMTP_USER:}\n # pass: \\${HAI_REACH_SMTP_PASS:}\n # from: \\${HAI_REACH_SMTP_FROM:noreply@example.com}\n\n # 阿里云短信(按需开启)\n # - name: sms\n # type: aliyun-sms\n # accessKeyId: \\${HAI_REACH_SMS_ACCESS_KEY}\n # accessKeySecret: \\${HAI_REACH_SMS_SECRET_KEY}\n # signName: MyApp\n\n# 模板(可选)\n# templates:\n# - name: verification_code\n# provider: email\n# subject: \"验证码: {code}\"\n# body: \"您的验证码是 {code},有效期 {minutes} 分钟。\"\n\n# 免打扰(可选)\n# dnd:\n# enabled: true\n# strategy: delay\n# start: \"22:00\"\n# end: \"08:00\"\n`\n}\n\nfunction generateSchedulerConfig(): string {\n return `# =============================================================================\n# 任务调度配置 (@h-ai/scheduler)\n# =============================================================================\n\n# 是否启用数据库日志(需要 @h-ai/reldb)\nenableDb: true\n\n# 执行日志表名\ntableName: hai_scheduler_logs\n\n# 任务定义表名\ntaskTableName: hai_scheduler_tasks\n\n# 分布式锁表名\nlockTableName: hai_scheduler_locks\n\n# 检查间隔(毫秒)\ntickInterval: 1000\n\n# 锁过期时间(毫秒)\nlockExpireMs: 300000\n`\n}\n\nfunction generateAuditConfig(): string {\n return `# =============================================================================\n# 审计日志配置 (@h-ai/audit)\n# =============================================================================\n\n# 审计日志表名\ntableName: hai_audit_logs\n\n# 用户表名(用于 JOIN 查询)\nuserTable: hai_iam_users\n\n# 用户表主键列名\nuserIdColumn: id\n\n# 用户名列名\nuserNameColumn: username\n`\n}\n\nfunction generatePaymentConfig(): string {\n return `# =============================================================================\n# 支付配置 (@h-ai/payment)\n# =============================================================================\n\n# 微信支付(按需开启)\n# wechat:\n# mchId: \\${HAI_PAYMENT_WECHAT_MCH_ID}\n# apiV3Key: \\${HAI_PAYMENT_WECHAT_API_V3_KEY}\n# serialNo: \\${HAI_PAYMENT_WECHAT_SERIAL_NO}\n# privateKey: \\${HAI_PAYMENT_WECHAT_PRIVATE_KEY}\n# appId: \\${HAI_PAYMENT_WECHAT_APP_ID}\n\n# 支付宝(按需开启)\n# alipay:\n# appId: \\${HAI_PAYMENT_ALIPAY_APP_ID}\n# privateKey: \\${HAI_PAYMENT_ALIPAY_PRIVATE_KEY}\n# alipayPublicKey: \\${HAI_PAYMENT_ALIPAY_PUBLIC_KEY}\n# signType: RSA2\n# sandbox: false\n\n# Stripe(按需开启)\n# stripe:\n# secretKey: \\${HAI_PAYMENT_STRIPE_SECRET_KEY}\n# webhookSecret: \\${HAI_PAYMENT_STRIPE_WEBHOOK_SECRET}\n`\n}\n"]}
|