@h-ai/cli 0.1.0-alpha.36 → 0.1.0-alpha.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/package.json +2 -2
  2. package/templates/base/package.json.hbs +1 -1
  3. package/templates/skills/hai-ai/SKILL.md +74 -31
  4. package/templates/skills/hai-ai/reference.md +25 -11
  5. package/templates/skills/hai-api-client/SKILL.md +14 -0
  6. package/templates/skills/hai-api-contract/SKILL.md +10 -0
  7. package/templates/skills/hai-app-create/SKILL.md +10 -0
  8. package/templates/skills/hai-app-review/SKILL.md +10 -0
  9. package/templates/skills/hai-app-tests/SKILL.md +10 -0
  10. package/templates/skills/hai-audit/SKILL.md +10 -0
  11. package/templates/skills/hai-build/SKILL.md +10 -0
  12. package/templates/skills/hai-cache/SKILL.md +10 -0
  13. package/templates/skills/hai-capacitor/SKILL.md +10 -0
  14. package/templates/skills/hai-ci/SKILL.md +10 -0
  15. package/templates/skills/hai-core/SKILL.md +10 -0
  16. package/templates/skills/hai-crypto/SKILL.md +10 -0
  17. package/templates/skills/hai-datapipe/SKILL.md +10 -0
  18. package/templates/skills/hai-deploy/SKILL.md +10 -0
  19. package/templates/skills/hai-framework-sync/SKILL.md +10 -0
  20. package/templates/skills/hai-iam/SKILL.md +31 -0
  21. package/templates/skills/hai-kit/SKILL.md +12 -0
  22. package/templates/skills/hai-payment/SKILL.md +10 -0
  23. package/templates/skills/hai-pr-review/SKILL.md +10 -0
  24. package/templates/skills/hai-reach/SKILL.md +12 -0
  25. package/templates/skills/hai-reldb/SKILL.md +10 -0
  26. package/templates/skills/hai-scheduler/SKILL.md +10 -0
  27. package/templates/skills/hai-serv/SKILL.md +16 -4
  28. package/templates/skills/hai-storage/SKILL.md +10 -0
  29. package/templates/skills/hai-ui/SKILL.md +10 -0
  30. package/templates/skills/hai-vecdb/SKILL.md +10 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@h-ai/cli",
3
3
  "type": "module",
4
- "version": "0.1.0-alpha.36",
4
+ "version": "0.1.0-alpha.37",
5
5
  "description": "Hai Framework CLI for project scaffolding and code generation.",
6
6
  "license": "Apache-2.0",
7
7
  "keywords": [
@@ -34,7 +34,7 @@
34
34
  "ora": "^9.1.0",
35
35
  "prompts": "^2.4.2",
36
36
  "yaml": "^2.7.0",
37
- "@h-ai/core": "0.1.0-alpha.36"
37
+ "@h-ai/core": "0.1.0-alpha.37"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/fs-extra": "^11.0.4",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "{{projectName}}",
3
- "version": "0.1.0-alpha.36",
3
+ "version": "0.1.0-alpha.37",
4
4
  "private": true,
5
5
  "description": "{{#if_eq appType 'admin'}}Enterprise management system built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'website'}}Enterprise website built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'h5'}}Mobile H5 app built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'api'}}REST API service built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'mobile-app'}}Mobile app built with hai Agent Framework{{/if_eq}}",
6
6
  "keywords": ["hai", {{#unless isSvelteOnlyApp}}"sveltekit", {{/unless}}"svelte5", "{{appType}}"],
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hai-ai
3
- description: 使用 @h-ai/ai 进行 LLM 调用、工具与 MCP、流式处理、记忆与上下文、RAG、语音识别与合成、A2A;当需求涉及 AI 对话、Audio、会话或 AI 客户端时使用。
3
+ description: "Use when: using @h-ai/ai for LLM calls, tools, MCP, streaming, memory/context, RAG, audio, A2A, or the AI client. 当需求涉及 AI 对话、工具、Audio、会话、知识库或 AI 客户端时使用。"
4
4
  ---
5
5
 
6
6
  # hai-ai — @h-ai/ai 快速指南
@@ -9,11 +9,22 @@ description: 使用 @h-ai/ai 进行 LLM 调用、工具与 MCP、流式处理、
9
9
 
10
10
  > 详细 API 表、错误码与长示例见同目录 `reference.md`。只有需要完整契约或边界用例时再读取,避免把长参考塞进上下文。
11
11
 
12
+ ## 能力契约
13
+
14
+ | 项目 | 契约 |
15
+ | --- | --- |
16
+ | 能力 | LLM/流式生成、结构化 Tool、MCP、Embedding、Memory、RAG/Knowledge、Context、Audio、A2A |
17
+ | 适用场景 | 服务端 AI 对话、Agent 工具链、知识问答、长期记忆、语音交互和 Agent-to-Agent;浏览器通过 client/API 代理 |
18
+ | 输入 | `AIConfigInput`、消息/文本/音频、Zod Tool schema、`objectId/sessionId/scope`、`AbortSignal` |
19
+ | 输出 | 领域操作返回 `HaiResult<T>`;流式 API 返回 `AsyncIterable`;Tool 返回 `ToolMessage`;客户端传输可能抛异常 |
20
+ | 限制 | 框架不替代业务授权、沙箱、人工确认和网络出口策略;临时 Store 不持久化;Prompt、检索内容和模型 Tool Call 均视为不可信输入 |
21
+
12
22
  ## 使用边界
13
23
 
14
24
  - `ai.tools`、`ai.stream` 是纯函数能力,无需 `ai.init()`。
15
25
  - `ai.llm`、`ai.embedding`、`ai.memory`、`ai.retrieval`、`ai.rag`、`ai.knowledge`、`ai.context`、`ai.audio`、`ai.a2a` 需要先 `await ai.init(...)`。
16
- - 默认 DB Provider 需要在 `ai.init()` 前完成 `reldb.init()` 与 `vecdb.init()`;自定义 `AIStoreProvider` 可跳过这两个依赖。
26
+ - 未初始化 reldb/vecdb 时,`ai.init()` 使用进程内临时 Store,适合 LLM-only 与本地原型;数据在 `ai.close()` 或进程退出后丢失。
27
+ - reldb 与 vecdb 均已初始化时自动使用持久化 DB Provider;生产 Memory/Context/Persona/Knowledge 应使用该路径或自定义 `AIStoreProvider`。
17
28
  - 浏览器端不要直接调用 Node-only 能力;通过 `@h-ai/api-client` 或应用自定义 API/SSE endpoint 代理。
18
29
  - 公共 API 返回 `HaiResult<T>` 时按 `if (!result.success) return result` 处理;不要用 `try/catch` 包裹正常业务错误。
19
30
 
@@ -22,20 +33,27 @@ description: 使用 @h-ai/ai 进行 LLM 调用、工具与 MCP、流式处理、
22
33
  ```ts
23
34
  import { core } from '@h-ai/core'
24
35
  import { ai } from '@h-ai/ai'
25
- import { reldb } from '@h-ai/reldb'
26
- import { vecdb } from '@h-ai/vecdb'
27
-
28
- await reldb.init(core.config.get('db'))
29
- await vecdb.init(core.config.get('vecdb'))
30
36
 
31
37
  const init = await ai.init(core.config.get('ai'))
32
38
  if (!init.success) return init
33
39
 
34
- // ... 使用 ai.llm / ai.memory / ai.knowledge 等
40
+ // LLM-only:未初始化 DB 时使用进程内临时 Store
41
+ // ... 使用 ai.llm
35
42
 
36
43
  await ai.close()
37
44
  ```
38
45
 
46
+ 需要持久化时先初始化 DB:
47
+
48
+ ```ts
49
+ import { reldb } from '@h-ai/reldb'
50
+ import { vecdb } from '@h-ai/vecdb'
51
+
52
+ await reldb.init(core.config.get('db'))
53
+ await vecdb.init(core.config.get('vecdb'))
54
+ await ai.init(core.config.get('ai'))
55
+ ```
56
+
39
57
  自定义存储:
40
58
 
41
59
  ```ts
@@ -72,10 +90,11 @@ knowledge:
72
90
  maxSize: 1500
73
91
  overlap: 200
74
92
 
75
- # 可选:真·mem0ai/oss 引擎(嵌入式,LLM/Embedder 从 llm 配置提取,向量库复用底层 vecdb 后端或退回 mem0 自带存储)
93
+ # 可选:mem0ai/oss 引擎;无法映射持久化后端时默认 fail-fast
76
94
  memory:
77
95
  provider: mem0
78
96
  defaultTopK: 10
97
+ # allowEphemeralFallback: true # 仅明确接受重启丢失数据时开启
79
98
  ```
80
99
 
81
100
  `ai.config` 是脱敏快照;`apiKey`、`privateKey`、URL 内嵌凭证会被隐藏。
@@ -89,17 +108,22 @@ memory:
89
108
  | 多协议 | 模型 `api: chat/responses/anthropic` | 底层走 Chat Completions / Responses / Anthropic,公共形状不变 |
90
109
  | 请求取消 | `ai.llm.chat({ messages, signal })` | 传 `AbortSignal`,`abort()` 立即停上游生成 |
91
110
  | 临时模型 | `ai.llm.chat({ messages, tempModel })` | 单次请求级临时端点,客户端按 TTL 缓存 |
92
- | 工具定义 | `ai.tools.define(...)` | Zod schema 转 JSON Schema |
93
- | 工具执行 | `registry.executeAll(toolCalls)` | 支持并行执行 |
111
+ | 工具定义 | `ai.tools.define(...)` | Zod schema 转 JSON Schema;`handler(input, ctx)` 第二参为执行上下文 |
112
+ | 工具注册 | `registry.register/replace` | `register` 默认拒绝同名并返回 HaiResult;只有 `replace` 可显式替换 |
113
+ | 工具执行 | `registry.execute(tc, { signal, objectId, sessionId, deadline?, timeoutMs?, authorize? })` / `executeAll(...)` | Registry/单次授权必须同时通过;默认串行,支持取消/超时;只有确认无副作用时才 `parallel: true` |
94
114
  | MCP 服务 | `createMcpServer(...)` | 按需连接 HTTP/SSE/Stdio transport |
95
115
  | Embedding | `ai.embedding.embedText(text)` | 批量用 `embedBatch` |
96
116
  | 记忆 | `ai.memory.extract/recall/injectMemories` | 用 `objectId` 做主体隔离,`scope` 做业务作用域隔离;scope 隔离越细,`candidateMultiplier` 调大以防漏召回 |
97
- | 角色人格 | `ai.persona.save/get/compose` | 定义 AI 身份(systemPrompt + traits),`compose` 组合系统提示词,`scope: { personaId }` 关联长期记忆 |
117
+ | 记忆作用域 | `ai.memory.scoped({ objectId, scope })` | **多租户推荐入口**:所有操作自动绑定 objectId/scope(含归属校验);`clear` 仅清作用域内 |
118
+ | 记忆管理 | `ai.memory.admin.clearAll({ confirm: true })` | 唯一的全局清空入口(需显式确认);`ai.memory.clear()` 空过滤会被拒绝,防误清全局 |
119
+ | 角色人格 | `ai.persona.save/get/compose` | 定义 AI 身份(systemPrompt + traits),`compose` 组合系统提示词;按 `objectId` 隔离多租户(不传默认 `system` 平台角色),`scope: { personaId }` 关联长期记忆 |
98
120
  | Retrieval/RAG | `ai.retrieval.retrieve` / `ai.rag.query` | Retrieval source 先注册或由配置预置 |
99
121
  | Knowledge | `ai.knowledge.setup/ingest/ask` | 入库前会调用 datapipe 清洗分块 |
100
122
  | Context | `ai.context.createManager` | 编排 LLM + Memory + RAG + 压缩;`manager.consolidate()` 把会话固化为长期记忆 |
101
- | 语音识别 | `ai.audio.transcribe` / `transcribeStream` | 完整或持续音频输入 |
102
- | 语音合成 | `ai.audio.synthesize` / `synthesizeStream` | 带稳定 ID 的文本段映射为结构化音频事件 |
123
+ | Context 并发 | `createManager({ concurrency: 'reject' \| 'queue' })` | 默认单活动生成防消息乱序;活动生成期间新 chat 返回 `CONTEXT_BUSY`(reject)或排队(queue) |
124
+ | Context 重置 | `await manager.reset({ preserveSystemPrompt?, cancelActiveTurn?, waitForMemoryTasks? })` | 异步:终止活动生成、清空消息/摘要/轮次,默认保留系统提示词 |
125
+ | 语音识别 | `ai.audio.transcribe` / `transcribeStream` | 完整音频返回 `HaiResult`;持续音频输入用 `AudioInputStream` 流式返回临时文本 |
126
+ | 语音合成 | `ai.audio.synthesize` / `synthesizeStream` | `text` 可为字符串或 `AsyncIterable<string>`(可接 LLM 文本流边生成边合成) |
103
127
  | A2A | `ai.a2a.registerExecutor/handleRequest` | 延迟初始化 SDK handler |
104
128
 
105
129
  ## LLM + 工具调用
@@ -107,15 +131,19 @@ memory:
107
131
  ```ts
108
132
  import { z } from 'zod'
109
133
 
110
- const registry = ai.tools.createRegistry()
111
- registry.register(ai.tools.define({
134
+ const registry = ai.tools.createRegistry({
135
+ authorize: ({ toolName, context }) => canExecuteTool(context.objectId, toolName),
136
+ })
137
+ const registered = registry.register(ai.tools.define({
112
138
  name: 'get_weather',
113
139
  description: '获取天气',
114
140
  parameters: z.object({ city: z.string() }),
115
141
  handler: async ({ city }) => ({ city, temperature: 20 }),
116
142
  }))
143
+ if (!registered.success) return registered
117
144
 
118
145
  const messages: ChatMessage[] = [{ role: 'user', content: '北京天气?' }]
146
+ const objectId = 'user-001'
119
147
  let result = await ai.llm.chat({ messages, tools: registry.getDefinitions() })
120
148
 
121
149
  while (result.success && result.data.choices[0]?.finish_reason === 'tool_calls') {
@@ -123,7 +151,7 @@ while (result.success && result.data.choices[0]?.finish_reason === 'tool_calls')
123
151
  const toolCalls = assistant.tool_calls ?? []
124
152
  messages.push(assistant)
125
153
 
126
- const toolMessages = await registry.executeAll(toolCalls, { parallel: true })
154
+ const toolMessages = await registry.executeAll(toolCalls, { objectId })
127
155
  if (!toolMessages.success) return toolMessages
128
156
  messages.push(...toolMessages.data)
129
157
 
@@ -184,7 +212,7 @@ await server.connect(new StreamableHTTPServerTransport({ sessionIdGenerator: cry
184
212
 
185
213
  ## 记忆、RAG 与知识库
186
214
 
187
- `memory.provider` 默认为 `native`(推荐):HAI 原生引擎,复用 vecdb/reldb/LLM/Embedding,`extract` 采用 **Mem0 式批量合并**(一次 LLM 调用对整批事实与相关既有记忆做 ADD/UPDATE/DELETE/NONE,支持 `category`)。`mem0` 则直接使用 `mem0ai/oss` 的 `Memory` 引擎:LLM/Embedder 从 `llm` 配置提取(OpenAI 兼容),向量库从底层 vecdb 后端提取(qdrant/pgvector 复用,lancedb/chroma 退回 mem0 自带 in-memory 存储)。两者对外 `ai.memory.*` API 完全一致。
215
+ `memory.provider` 默认为 `native`(推荐):HAI 原生引擎,复用 vecdb/reldb/LLM/Embedding,`extract` 采用 **Mem0 式批量合并**(一次 LLM 调用对整批事实与相关既有记忆做 ADD/UPDATE/DELETE/NONE,支持 `category`)。`mem0` 则直接使用 `mem0ai/oss` 的 `Memory` 引擎:LLM/Embedder 从 `llm` 配置提取(OpenAI 兼容),向量库从底层 vecdb 后端提取(qdrant/pgvector 复用)。**mem0 无法映射 lancedb/chroma 等后端时默认 fail-fast**(初始化失败,避免重启后记忆静默丢失);只有显式 `memory.allowEphemeralFallback: true` 才退回 mem0 自带 in-memory 存储。两者对外 `ai.memory.*` API 完全一致。
188
216
 
189
217
  ```ts
190
218
  const enriched = await ai.memory.injectMemories(messages, { objectId: 'user-001', topK: 5 })
@@ -230,28 +258,28 @@ await managerResult.data.save()
230
258
 
231
259
  ### 真实对话状态(Conversation Commit Layer)
232
260
 
233
- `turnCommit: 'manual'` 时,`chat` / `chatStream` 不自动写入生成文本,只返回 `turnId`;由调用方提交**实际发生的内容**(TTS 播放 / 主持人打断等场景):
261
+ `turnCommit: 'manual'` 时,`chat` / `chatStream` 不自动写入生成文本,只返回 `turnId`;由调用方提交**实际发生的内容**(TTS 播放、被打断等场景)。`chatStream` 在调用上游模型前就产出 `turn_started`(事件序列 `turn_started → delta* → done`,中途取消 `→ cancelled`),取消时保留 `turnId` 与已生成文本:
234
262
 
235
263
  ```ts
236
264
  const m = ai.context.createManager({ turnCommit: 'manual', scope }).data
237
- for await (const ev of m.chatStream('展开讲讲')) {
265
+ const controller = new AbortController()
266
+ for await (const ev of m.chatStream('展开讲讲', { signal: controller.signal })) {
238
267
  if (ev.type === 'delta') feedTts(ev.text)
239
- else if (ev.type === 'done') {
240
- interrupted
241
- ? await m.interruptTurn(ev.turnId, { text: spokenSoFar }) // 只提交播放出去的部分
242
- : await m.commitTurn(ev.turnId) // 完整提交
243
- }
268
+ else if (ev.type === 'done') await m.commitTurn(ev.turnId) // 完整提交
269
+ else if (ev.type === 'cancelled') await m.interruptTurn(ev.turnId, { text: spokenSoFar }) // 只提交播放出去的部分
244
270
  }
245
271
  ```
246
272
 
247
273
  - 只有 `committed` 的内容进入上下文与记忆;`getTurns()` 可观测 `generated` / `committed` / `status`。
274
+ - 主持人抢话时可在 `turn_started` / 迭代过程中随时 `interruptTurn`;轮次进入终态后即便上游流恰好正常结束,`chatStream` 也**不会再产出 `done`**,业务层不会误判为正常完成。
248
275
 
249
276
 
250
277
  ## 语音(Audio)
251
278
 
252
- 模型必须声明允许的操作;框架会在厂商调用前拒绝 ASR/TTS 模型混用:
279
+ `ai.audio` 提供 ASR/TTS,Provider(OpenAI / MiMo / Qwen / 豆包)作为内部实现,凭据未配置时回退平台环境变量。调用方只表达「音频还是文本、完整还是流式」,不感知 WebSocket / SSE / 厂商事件。
253
280
 
254
281
  ```yaml
282
+ # ai.init 配置片段
255
283
  audio:
256
284
  models:
257
285
  - { id: asr, provider: qwen, model: qwen3-asr-flash-realtime, operations: [transcribe] }
@@ -261,15 +289,30 @@ audio:
261
289
  ```
262
290
 
263
291
  ```ts
264
- for await (const event of ai.audio.synthesizeStream({ text: { id: 'seg-1', text: '欢迎。' } })) {
265
- if (event.type === 'audio')
266
- await player.write(event.data)
292
+ // 完整识别 / 合成(HaiResult)
293
+ const t = await ai.audio.transcribe({ audio: { data: wavBytes, format: 'wav' }, language: 'zh' })
294
+ if (!t.success) return t
295
+ const s = await ai.audio.synthesize({ text: '欢迎', voice: 'Cherry', format: 'pcm16' })
296
+
297
+ // 实时识别:持续音频输入 → 增量文本(chunk.final 标记语句最终态,可直接覆盖临时文本)
298
+ for await (const chunk of ai.audio.transcribeStream({ audio: { chunks: micChunks, format: 'pcm16', sampleRate: 16000 } })) {
299
+ updateTranscript(chunk.text, chunk.final)
267
300
  }
268
301
 
269
- const caps = ai.audio.getCapabilities({ operation: 'synthesize', model: 'tts' })
302
+ // 分段合成:稳定 ID 关联文本与音频,支持 AbortSignal 打断
303
+ const controller = new AbortController()
304
+ for await (const event of ai.audio.synthesizeStream({ text: { id: 'seg-1', text: '欢迎。' }, voice: 'Cherry', signal: controller.signal })) {
305
+ if (event.type === 'segment_started')
306
+ prepareDecoder(event.format, event.sampleRate, event.channels) // 真实输出格式来自服务端解析后的 Provider 输出
307
+ else if (event.type === 'audio')
308
+ await player.write(event.data)
309
+ }
270
310
  ```
271
311
 
272
- 浏览器客户端配置 `audio: { url, getTicket }`;`getTicket` 通过已登录 HTTP 请求获取短期、一次性 ticket,禁止把 IAM access token 放入 WebSocket URL。
312
+ - 流式方法是 `AsyncIterable`,迭代期间的连接/协议/上游错误会终止迭代(抛出),不返回 `HaiResult`。
313
+ - `segment_started` 携带服务端解析 Provider 后的真实输出参数(`format` / `sampleRate?` / `channels?`);播放器据此解码,不按请求参数猜测格式。
314
+ - 平台不支持的输入方式(如 OpenAI/MiMo 的持续音频输入)会抛 `AUDIO_UNSUPPORTED_INPUT`,不伪装成实时。
315
+ - 浏览器/移动端经 `@h-ai/serv` 统一语音 WebSocket 入口访问;客户端用已登录 HTTP 请求获取短期一次性 ticket,`@h-ai/ai/client` 通过 `audio.getTicket` 建连,不把 IAM access token 放入 URL。浏览器客户端区分正常结束、取消(`AUDIO_CANCELLED`)与 `end` 前异常断连(`AUDIO_CONNECTION_FAILED`);服务端 error 帧保留领域错误码,`synthesize` 不返回未完成的部分音频。
273
316
 
274
317
 
275
318
  ## SvelteKit API 端点模式
@@ -4,6 +4,8 @@
4
4
 
5
5
  ## 初始化与依赖
6
6
 
7
+ 未初始化 reldb/vecdb 时,`ai.init()` 自动使用进程内临时 Store;两者均已初始化时使用持久化 DB Provider。需要跨进程持久化时必须使用 DB 或自定义 Provider。
8
+
7
9
  | 能力 | 是否需要 `ai.init()` | 依赖 |
8
10
  | --- | --- | --- |
9
11
  | `ai.tools` | 否 | 无 |
@@ -46,10 +48,12 @@ if (result.success) {
46
48
  ## Tools
47
49
 
48
50
  - `ai.tools.define({ name, description, parameters, handler })`
49
- - `ai.tools.createRegistry()`
50
- - `registry.register(tool)` / `registry.unregister(name)`
51
+ - `ai.tools.createRegistry({ authorize? })`
52
+ - `registry.register(tool)` / `registry.registerMany(tools)`:返回 `HaiResult<void>`,默认拒绝同名
53
+ - `registry.replace(tool)`:显式替换已存在工具
54
+ - `registry.unregister(name)`
51
55
  - `registry.getDefinitions()`:传给 LLM 的工具定义
52
- - `registry.execute(toolCall)` / `registry.executeAll(toolCalls, { parallel })`
56
+ - `registry.execute(toolCall, { signal, objectId, sessionId, deadline?, timeoutMs?, authorize? })` / `registry.executeAll(toolCalls, { parallel?, ...ctx })`;默认串行;Registry/单次授权均 fail-closed;handler `(input, ctx)` 可响应取消/超时(默认 30s)
53
57
 
54
58
  工具 handler 输入由 Zod schema 约束,外部输入不要绕过 schema。
55
59
 
@@ -103,8 +107,8 @@ Embedding OpenAI 客户端按 `apiKey + baseURL + timeout` 缓存;同一 key
103
107
  Memory 后端通过 `memory.provider` 选择:
104
108
 
105
109
  - `native`(默认):HAI 原生引擎,复用 vecdb/reldb/LLM/Embedding。`extract` 采用 Mem0 式批量合并(ADD/UPDATE/DELETE/NONE + `category`);`maxEntriesPerObject`(单主体配额)/`maxEntriesGlobal`(全局上限)/`recencyDecay`/`embeddingEnabled`/`writebackRelatedTopK` 作用于此后端;淘汰按 `objectId` 分区。
106
- - `mem0`:直接使用 `mem0ai/oss` 的 `Memory` 引擎(嵌入式)。LLM/Embedder 从 `llm` 配置提取(OpenAI 兼容,场景模型 `extraction` / `embedding`);向量库从底层 vecdb 后端提取(`storeProvider.getVectorBackend()`),qdrant/pgvector 复用同一后端,lancedb/chroma 退回 mem0 自带 in-memory 存储;历史默认禁用。
107
- - 两者对外 API(extract/recall/injectMemories/add/update/get/remove/list/listPage/clear)完全一致;`objectId` 隔离不同主体的记忆,`scope`(key-value)用于业务作用域隔离(recall/list/listPage/clear 均严格过滤)。mem0 后端 `update` 涉及 type/importance/metadata 时会重建记忆并重新分配 `id`。
110
+ - `mem0`:直接使用 `mem0ai/oss` 的 `Memory` 引擎(嵌入式)。LLM/Embedder 从 `llm` 配置提取(OpenAI 兼容,场景模型 `extraction` / `embedding`);向量库从底层 vecdb 后端提取(`storeProvider.getVectorBackend()`),qdrant/pgvector 复用同一后端;无法映射 lancedb/chroma 等后端时**默认 fail-fast**(除非 `memory.allowEphemeralFallback: true` 才退回 mem0 in-memory);历史默认禁用。
111
+ - 两者对外 API(extract/recall/injectMemories/add/update/get/remove/list/listPage/clear)完全一致;`objectId` 隔离不同主体的记忆,`scope`(key-value)用于业务作用域隔离(recall/list/listPage/clear 均严格过滤)。mem0 后端 `extract` 在框架层分类打分后以 `infer:false` 写入(保留 `hai_type`/`hai_importance`),`recall` 支持 `types`/`recencyWeight`,与 native 一致;mem0 后端 `update` 涉及 type/importance/metadata 时会重建记忆并重新分配 `id`。
108
112
 
109
113
  ## Retrieval / RAG
110
114
 
@@ -168,13 +172,21 @@ const result = await ai.rag.query('核心架构是什么?', {
168
172
  | 方法 | 返回 | 说明 |
169
173
  | --- | --- | --- |
170
174
  | `transcribe(request)` | `Promise<HaiResult<TranscriptionResult>>` | 完整音频 → 完整文本 |
171
- | `transcribeStream(request)` | `AsyncIterable<TranscriptionEvent>` | 完整或持续音频 → 识别/VAD 领域事件 |
175
+ | `transcribeStream(request)` | `AsyncIterable<TranscriptionEvent>` | 完整音频或 `AudioInputStream` → `speech_started` / `{type:'transcript',text,final}` / `speech_stopped`(VAD 平台产出语音起止事件) |
172
176
  | `synthesize(request)` | `Promise<HaiResult<SynthesisResult>>` | 完整文本 → 完整音频 |
173
- | `synthesizeStream(request)` | `AsyncIterable<SynthesisEvent>` | 带 ID 文本段 → `segment_started → audio* → segment_done` |
174
- | `getCapabilities({ operation, model? })` | `HaiResult<AudioModelCapabilities>` | 按操作查询能力,并拒绝操作不匹配模型 |
177
+ | `synthesizeStream(request)` | `AsyncIterable<SynthesisEvent>` | 带 ID 文本段 → `segment_started → audio* → segment_done`,事件均可关联 `segmentId`;`segment_started` 携带服务端解析后的真实 `format` / `sampleRate?` / `channels?` |
178
+ | `getCapabilities({ operation, model? })` | `HaiResult<AudioModelCapabilities>` | 按模型与操作查询 `transcribe` / `synthesize` 能力分支,并拒绝操作不匹配模型 |
179
+
180
+ - 音频类型:`AudioContent { data: Uint8Array, format: 'pcm16'|'wav'|'mp3'|'opus', sampleRate?, channels? }`;`pcm16` 等裸音频必须传 `sampleRate`。
181
+ - 请求可选:识别 `contextHints?: string[]`(热词/提示);合成 `instruction?: string`(自然语言风格指令);均支持 `signal: AbortSignal`。
182
+ - 模型配置:`audio.models: [{ id, provider: 'openai'|'mimo'|'qwen'|'doubao', model, operations, apiKey?, baseUrl?, appKey?, accessKey?, resourceId?, workspaceId? }]`;`operations` 必须明确为识别、合成或两者。
183
+ - 凭据环境变量回退:`HAI_AI_AUDIO_<PROVIDER>_API_KEY` 或 `OPENAI_API_KEY` / `MIMO_API_KEY` / `DASHSCOPE_API_KEY` / `VOLC_API_KEY`(豆包旧版控制台额外 `VOLC_APP_KEY` / `VOLC_ACCESS_KEY`)。
184
+ - 资源上限:`audio.maxAudioBytes`(默 10 MiB)、`audio.maxStreamDurationMs`(默 5 分钟);所有请求支持 `signal: AbortSignal` 打断。
185
+ - Provider 为内部实现,不从根入口导出;不支持的输入方式招 `AUDIO_UNSUPPORTED_INPUT`,不伪装实时。取消 → `AUDIO_CANCELLED`,超时 → `AUDIO_TIMEOUT`,连接失败或 `end` 前异常断连 → `AUDIO_CONNECTION_FAILED`。浏览器客户端(`@h-ai/ai/client`)严格区分正常结束 / 取消 / 异常断连:取消招 `AUDIO_CANCELLED`、`end` 前断连招 `AUDIO_CONNECTION_FAILED`、服务端 error 帧保留其领域错误码,`synthesize` 不把未完成的部分音频当作成功返回。
175
186
 
176
- - 模型配置必须包含 `operations: ['transcribe'] | ['synthesize'] | ['transcribe','synthesize']`。
177
- - 浏览器端使用 `audio: { url, getTicket }`;ticket 由已登录 HTTP 请求签发且一次性消费,IAM access token 不进入 WebSocket URL。
187
+ ## LLM 结构化输出
188
+
189
+ `ai.llm.generateObject({ schema, messages, model?, systemPrompt?, maxRepairs?, signal? })`:按 Zod schema 约束模型输出(json_schema)并解析为对象,解析/校验失败自动带错误提示重试(默 1 次)。适用于“是否为问题/意图分类/置信度”等需要稳定结构结果的场景,避免手写 `JSON.parse`。
178
190
 
179
191
  ## A2A
180
192
 
@@ -201,7 +213,7 @@ A2A 服务端 SDK handler 在注册 executor 时延迟创建;远端客户端
201
213
  | `hai:ai:100-107` | LLM / 历史记录 |
202
214
  | `hai:ai:200-204` | MCP |
203
215
  | `hai:ai:300-302` | Embedding |
204
- | `hai:ai:400-403` | Tool |
216
+ | `hai:ai:400-405` | Tool(含重复注册、授权拒绝) |
205
217
  | `hai:ai:500-502` | Reasoning |
206
218
  | `hai:ai:600-701` | Retrieval / RAG |
207
219
  | `hai:ai:800-805` | Knowledge |
@@ -217,3 +229,5 @@ A2A 服务端 SDK handler 在注册 executor 时延迟创建;远端客户端
217
229
  const response = await apiClient.ai.chats.createCompletion({ messages })
218
230
  const memories = await apiClient.ai.memories.recall({ query: '偏好', objectId: 'user-001', topK: 5 })
219
231
  ```
232
+
233
+ 语音:`@h-ai/ai/client` 的 `createAIClient({ api, audio: { url, getTicket } })` 提供 `client.audio.transcribe/transcribeStream/synthesize/synthesizeStream`。`getTicket(request)` 接收本次操作摘要(`operation` / `model`),应通过已登录 HTTP 请求签发与本次操作严格绑定的短期、一次性 Audio ticket(推荐 `iam.ticket.issue({ grant })`);IAM access token 不进入 WebSocket URL。
@@ -5,6 +5,16 @@ description: 使用 @h-ai/api-client 构建多端共用的 oRPC/OpenAPI typed cl
5
5
 
6
6
  # hai-api-client
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/api-client 构建多端共用的 oRPC/OpenAPI typed client,通过 apiClient.init() 初始化,支持 Bearer Token 自动管理、401 刷新重试与 contract 嵌套方法调用;当需求涉及客户端 API 请求、Token 管理或多端数据层时使用。 |
13
+ | 适用场景 | 当任务与 `hai-api-client` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/api-client` 是跨端 typed API client。公共 HTTP API 由 `@h-ai/api-contract` 定义,服务端由 `@h-ai/serv` 挂载,客户端直接调用 `apiClient.<domain>.<group>.<operation>()`。
9
19
 
10
20
  ## 使用步骤
@@ -71,6 +81,10 @@ if (login.success) {
71
81
  }
72
82
 
73
83
  const me = await apiClient.iam.auth.currentUser()
84
+ if (me.success) {
85
+ // currentUser 返回服务端最新角色/权限;不要把权限快照持久化到 localStorage。
86
+ const { roles, permissions, ...user } = me.data
87
+ }
74
88
  const upload = await apiClient.storage.presignedUrls.createUpload({ key: 'avatar.png' })
75
89
  const answer = await apiClient.ai.chats.sendMessage({ message: 'hello' })
76
90
  ```
@@ -5,6 +5,16 @@ description: 使用 @h-ai/api-contract 定义或扩展 oRPC HTTP API 契约;
5
5
 
6
6
  # hai-api-contract
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/api-contract 定义或扩展 oRPC HTTP API 契约;当需求涉及定义新领域 contract、组合应用级 contract、使用内置 IAM/Storage/AI/Payment 契约、编写自定义 procedure 输入输出 Schema 或为 @h-ai/api-client/@h-ai/serv 提供接口真相源时使用。 |
13
+ | 适用场景 | 当任务与 `hai-api-contract` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/api-contract` 是 hai-framework 的公共 HTTP API 契约包,使用 oRPC contract + Zod v4 作为唯一接口真相源。本包只描述接口边界,不包含任何 procedure 实现。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 以 TDD 方式在应用中创建新功能:先编写测试定义
5
5
 
6
6
  # hai-app-create — TDD 驱动的应用功能创建规范
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 以 TDD 方式在应用中创建新功能:先编写测试定义行为,再编码实现直至测试通过;当需求涉及新增页面/路由、API、服务、数据模型、组件时使用。 |
13
+ | 适用场景 | 当任务与 `hai-app-create` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 明确的功能需求、目标路径、现有实现、仓库规范与验收条件 |
15
+ | 输出 | 最小必要的代码、类型、测试和同步文档,以及实际验证结果 |
16
+ | 限制 | 不为假设需求增加抽象,不绕过生命周期/HaiResult/i18n 约定,不覆盖用户已有改动 |
17
+
8
18
  > 面向 AI 助手的应用功能创建指南。**必须遵循 TDD**:先写测试(Red)→ 再实现(Green)→ 再重构(Refactor)。
9
19
  > 若目标是纯 API service workspace,优先围绕 `apps/*-contract`、`apps/*-service` 与测试组织改动,而不是套用页面/路由脚手架。
10
20
 
@@ -5,6 +5,16 @@ description: 对应用代码进行审查:路由安全 → 认证授权 → i18
5
5
 
6
6
  # hai-app-review — 应用代码审查规范
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 对应用代码进行审查:路由安全 → 认证授权 → i18n → 组件使用 → API 端点 / service workspace → 服务层 → 性能,并补充产品体验与交互走查;当需求涉及代码审查、规范化、质量检查时使用。 |
13
+ | 适用场景 | 当任务与 `hai-app-review` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 用户指定的审查范围、代码/差异、仓库规范与可复现证据 |
15
+ | 输出 | 按优先级排列的问题、影响、定位和修正建议;仅在用户要求时实施修改 |
16
+ | 限制 | 不把风格偏好当缺陷,不猜测未读取的实现,不在审查请求中擅自发布或改动外部状态 |
17
+
8
18
  > 面向 AI 助手的应用代码审查指南。用于审查使用 hai-framework 构建的 SvelteKit 应用、纯 Svelte/Vite 客户端与 API service workspace。本技能也是 TDD Refactor 阶段的执行入口。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 以 TDD 驱动应用开发:先分析需求、生成单元测试
5
5
 
6
6
  # hai-app-tests — TDD 驱动的应用测试规范
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 以 TDD 驱动应用开发:先分析需求、生成单元测试(Vitest)与 E2E 测试(Playwright),确认测试全部失败后再编码实现直至测试通过;当需求涉及应用测试、TDD 流程、覆盖率提升、E2E 测试时使用。 |
13
+ | 适用场景 | 当任务与 `hai-app-tests` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > 面向 AI 助手的 TDD 测试指南。**测试先行**:先写测试定义行为,再写实现让测试通过。涵盖 Vitest 单元测试与 Playwright E2E 测试。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/audit 进行审计日志的记录、查询、清理与
5
5
 
6
6
  # @h-ai/audit — 审计日志模块
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/audit 进行审计日志的记录、查询、清理与统计。当需求涉及操作审计、安全事件追踪、用户活动日志时使用。 |
13
+ | 适用场景 | 当任务与 `hai-audit` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  统一审计日志模块,基于 `@h-ai/reldb` 实现持久化,提供审计日志的记录、分页查询、清理与统计。
9
19
 
10
20
  ## 运行环境
@@ -5,6 +5,16 @@ description: 应用开发入口技能。提供项目架构总览(SSR/SPA/原
5
5
 
6
6
  # hai-build — 应用开发入口
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 应用开发入口技能。提供项目架构总览(SSR/SPA/原生 App 多端)、TDD 开发工作流、模块初始化顺序与技能导航。当用户需要了解项目结构、查找正确的技能、或开始新任务时触发。 |
13
+ | 适用场景 | 当任务与 `hai-build` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 用户目标、仓库与运行环境上下文、现有配置、授权范围和质量门禁 |
15
+ | 输出 | 与目标匹配的配置/代码/文档或审查结论,以及可复现的验证结果 |
16
+ | 限制 | 不扩张用户授权,不输出或固化密钥,不跳过失败门禁,不假定外部服务状态 |
17
+
8
18
  > 本技能是 hai-framework 应用开发的起点。帮助理解项目结构、定位正确的技能、并遵循 **TDD 驱动的标准工作流**。支持 SSR Web、SPA、Android/iOS 原生 App 等多端构建。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/cache 进行内存或 Redis 缓存操作(kv/hash/lis
5
5
 
6
6
  # hai-cache
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/cache 进行内存或 Redis 缓存操作(kv/hash/list/set/zset/分布式锁);当需求涉及缓存读写、TTL 管理、集合运算、排行榜、缓存一致性策略或分布式互斥锁时使用。 |
13
+ | 适用场景 | 当任务与 `hai-cache` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/cache` 提供统一缓存接口,支持 Memory 与 Redis 后端,包含 KV / Hash / List / Set / ZSet / 分布式锁 六类操作。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/capacitor 桥接 Capacitor 原生能力(Token 安全
5
5
 
6
6
  # hai-capacitor
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/capacitor 桥接 Capacitor 原生能力(Token 安全存储、设备信息、推送通知、相机、状态栏),构建 Android/iOS 原生应用;当需求涉及原生 App 开发、Capacitor 集成、安全存储或原生设备功能时使用。 |
13
+ | 适用场景 | 当任务与 `hai-capacitor` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 用户目标、仓库与运行环境上下文、现有配置、授权范围和质量门禁 |
15
+ | 输出 | 与目标匹配的配置/代码/文档或审查结论,以及可复现的验证结果 |
16
+ | 限制 | 不扩张用户授权,不输出或固化密钥,不跳过失败门禁,不假定外部服务状态 |
17
+
8
18
  > `@h-ai/capacitor` 是 hai-framework 的 Capacitor 原生桥接模块,封装常用原生能力为统一 API,返回 `HaiResult<T>`。与 `@h-ai/api-client` 配合时,Token 仅存于原生安全存储,不回退到 Web `localStorage`。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 设计和维护 hai-framework 应用仓库的 CI/CD、GitHub Action
5
5
 
6
6
  # hai-ci — CI/CD 与质量门禁规范
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 设计和维护 hai-framework 应用仓库的 CI/CD、GitHub Actions、质量门禁、secret scan 与 workflow 安全;当需求涉及 CI、GitHub Actions、required checks、泄漏扫描或 release workflow 编排时使用。 |
13
+ | 适用场景 | 当任务与 `hai-ci` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 用户目标、仓库与运行环境上下文、现有配置、授权范围和质量门禁 |
15
+ | 输出 | 与目标匹配的配置/代码/文档或审查结论,以及可复现的验证结果 |
16
+ | 限制 | 不扩张用户授权,不输出或固化密钥,不跳过失败门禁,不假定外部服务状态 |
17
+
8
18
  > 面向 AI 助手和团队成员的仓库自动化指南。目标是让每个 PR 都能被机器稳定验证,同时避免把 secrets 暴露给不可信 PR 或第三方 Action。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/core 进行配置加载、日志记录、i18n 国际
5
5
 
6
6
  # hai-core
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/core 进行配置加载、日志记录、i18n 国际化、HaiResult 错误处理、Zod 校验错误本地化与模块生命周期管理;当需求涉及 core.init、core.logger、core.config、core.i18n、core.zodValidation、ok/err 或模块初始化模式时使用。 |
13
+ | 适用场景 | 当任务与 `hai-core` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/core` 是 hai-framework 的基础模块,提供配置管理、结构化日志、国际化、HaiResult 错误模型、Zod 校验错误本地化与模块生命周期工具。所有其他模块均依赖 core。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/crypto 进行加密(非对称/哈希/对称)、密
5
5
 
6
6
  # hai-crypto
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/crypto 进行加密(非对称/哈希/对称)、密码哈希与传输加密;当需求涉及加密、解密、签名、验签、哈希、密码存储、密钥管理或 crypto.transport 时使用。 |
13
+ | 适用场景 | 当任务与 `hai-crypto` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/crypto` 提供非对称加密、哈希、对称加密与密码哈希能力,支持 Node.js 与浏览器双端。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/datapipe 进行文本清洗(HTML/URL/空白移除)
5
5
 
6
6
  # hai-datapipe
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/datapipe 进行文本清洗(HTML/URL/空白移除)、多模式分块(句子/段落/Markdown/字符/自定义)和管线组合;当需求涉及文本预处理、文档分块、数据清洗或 RAG 入库前处理时使用。 |
13
+ | 适用场景 | 当任务与 `hai-datapipe` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/datapipe` 提供文本清洗(clean)、多模式分块(chunk)和可组合管线(pipeline),纯函数模块,无需初始化。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/deploy 进行自动化部署:Vercel 部署 + 基础
5
5
 
6
6
  # hai-deploy
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/deploy 进行自动化部署:Vercel 部署 + 基础设施开通(Neon/Upstash/R2/Resend/Aliyun);当需求涉及应用部署、环境配置、凭证管理或云服务开通时使用。 |
13
+ | 适用场景 | 当任务与 `hai-deploy` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 用户目标、仓库与运行环境上下文、现有配置、授权范围和质量门禁 |
15
+ | 输出 | 与目标匹配的配置/代码/文档或审查结论,以及可复现的验证结果 |
16
+ | 限制 | 不扩张用户授权,不输出或固化密钥,不跳过失败门禁,不假定外部服务状态 |
17
+
8
18
  > `@h-ai/deploy` 提供自动化部署能力,将 SvelteKit 应用部署到 Vercel,并自动开通 PostgreSQL (Neon)、Redis (Upstash)、S3 (Cloudflare R2)、邮件 (Resend)、短信 (阿里云) 等基础设施服务。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 管理 hai-framework 与应用仓库之间的依赖、技能模板
5
5
 
6
6
  # hai-framework-sync — hai-framework 与应用仓库同步规范
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 管理 hai-framework 与应用仓库之间的依赖、技能模板、Copilot/AGENTS 指令和本地联调同步;当需求涉及 hai-framework 源头修改、skills 同步、framework:use:local、framework:watch、版本漂移或双仓 PR 时使用。 |
13
+ | 适用场景 | 当任务与 `hai-framework-sync` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 用户目标、仓库与运行环境上下文、现有配置、授权范围和质量门禁 |
15
+ | 输出 | 与目标匹配的配置/代码/文档或审查结论,以及可复现的验证结果 |
16
+ | 限制 | 不扩张用户授权,不输出或固化密钥,不跳过失败门禁,不假定外部服务状态 |
17
+
8
18
  > hai-framework 是能力与 skill 模板源头;应用仓库消费这些能力,并可以有少量项目本地覆盖。同步的目标是减少漂移,而不是把两个仓库混成一个仓库。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/iam 进行身份认证(密码/OTP/LDAP/API Key)、
5
5
 
6
6
  # hai-iam
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/iam 进行身份认证(密码/OTP/LDAP/API Key)、统一 Bearer Token 管理(TokenPair/refresh/revoke)与 RBAC 授权;当需求涉及登录、注册、权限检查、角色管理、Token 认证或通过 @h-ai/api-contract 暴露 IAM API 时使用。 |
13
+ | 适用场景 | 当任务与 `hai-iam` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/iam` 是统一的身份与访问管理模块,支持多种认证策略(密码/OTP/LDAP/API Key)、Bearer Token 管理和 RBAC 授权。依赖 `@h-ai/reldb`(持久化)、`@h-ai/cache`(Token + 权限缓存)、`@h-ai/crypto`(密码哈希)、`@h-ai/audit`(审计日志)。
9
19
 
10
20
  ---
@@ -145,6 +155,22 @@ interface TokenPair {
145
155
  - 创建全新的 session,返回新的 TokenPair
146
156
  - 旧 refreshToken 立即失效,防止重放攻击
147
157
 
158
+ ### 一次性票据 — `iam.ticket`
159
+
160
+ 短期、一次性能力票据,用于无法携带 Bearer Token 的通道(如 WebSocket URL)。密码学安全随机、TTL、原子单次消费、用途绑定。
161
+
162
+ | 方法 | 签名 | 说明 |
163
+ | ---------- | -------------------------------------------------------------------------------------- | ------------------------------------- |
164
+ | `issue` | `({ subjectId, purpose, grant?, ttlMs? }) => Promise<HaiResult<{ ticket, expiresAt }>>` | 签发(默认 30s) |
165
+ | `consume` | `(ticket, { purpose? }?) => Promise<HaiResult<{ subjectId, purpose, grant }>>` | 原子消费(单次有效,用途不符拒绝) |
166
+
167
+ ```ts
168
+ const issued = await iam.ticket.issue({ subjectId, purpose: 'ai-audio', grant: { operation: 'transcribe' } })
169
+ const consumed = await iam.ticket.consume(ticket, { purpose: 'ai-audio' }) // 并发消费仅一个成功
170
+ ```
171
+
172
+ 错误码:`TICKET_INVALID`(hai:iam:110) / `TICKET_EXPIRED`(hai:iam:111) / `TICKET_ISSUE_FAILED`(hai:iam:112)。
173
+
148
174
  ### 用户管理 — `iam.user`
149
175
 
150
176
  | 方法 | 签名 | 说明 |
@@ -312,6 +338,11 @@ if (login.success) {
312
338
 
313
339
  // 获取当前用户
314
340
  const me = await apiClient.iam.auth.currentUser()
341
+ if (me.success) {
342
+ // 返回 User + 服务端当前会话的 roles/permissions。
343
+ // 身份资料与访问范围可在状态层拆开,但不要持久化权限快照。
344
+ const { roles, permissions, ...user } = me.data
345
+ }
315
346
 
316
347
  // Token 过期时,api-client 自动调用 refreshPath 刷新
317
348
  // 刷新失败时,清除 Token 并跳转登录页
@@ -5,6 +5,16 @@ description: 使用 @h-ai/kit 构建 SvelteKit 请求管道、认证守卫、统
5
5
 
6
6
  # hai-kit
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/kit 构建 SvelteKit 请求管道、认证守卫、统一响应、Zod 校验、浏览器端 apiFetch、A2A 与双构建适配;当需求涉及 hooks.server.ts、权限守卫、CORS、限流、同源 transport 或 SvelteKit API endpoint 时使用。 |
13
+ | 适用场景 | 当任务与 `hai-kit` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@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
19
 
10
20
  ## 使用步骤
@@ -83,6 +93,8 @@ export const handle = kit.createHandle({
83
93
  })
84
94
  ```
85
95
 
96
+ 需要保护会话 Cookie 时配置 `crypto.encryptedCookies`,并通过 `crypto.cookieEncryptionKey` 或 `HAI_KIT_COOKIE_KEY` 提供密钥。缺少密钥会在 `createHandle()` 时失败;加解密错误不会回退到明文 Cookie。
97
+
86
98
  ```ts
87
99
  // routes/+layout.svelte
88
100
  <script lang='ts'>
@@ -5,6 +5,16 @@ description: 使用 @h-ai/payment 接入微信支付、支付宝、Stripe 统一
5
5
 
6
6
  # hai-payment
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/payment 接入微信支付、支付宝、Stripe 统一支付;支持创建订单、回调验签、订单查询与退款;当需求涉及支付接入、订单创建、支付回调、退款或客户端调起支付时使用。 |
13
+ | 适用场景 | 当任务与 `hai-payment` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/payment` 是 hai-framework 的统一支付模块,通过 Provider 模式支持微信支付、支付宝、Stripe。服务端处理订单和回调,客户端调起支付。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 审查 Pull Request 的交付质量、scope、风险、验证方式
5
5
 
6
6
  # hai-pr-review — PR 审查与 AI Review 规范
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 审查 Pull Request 的交付质量、scope、风险、验证方式、AI-assisted 说明与合并准备度;当需求涉及 PR review、AI Review 策略、PR 模板、CODEOWNERS 或合并门禁时使用。 |
13
+ | 适用场景 | 当任务与 `hai-pr-review` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 用户指定的审查范围、代码/差异、仓库规范与可复现证据 |
15
+ | 输出 | 按优先级排列的问题、影响、定位和修正建议;仅在用户要求时实施修改 |
16
+ | 限制 | 不把风格偏好当缺陷,不猜测未读取的实现,不在审查请求中擅自发布或改动外部状态 |
17
+
8
18
  > PR 是团队协作和 AI 辅助开发的交付边界。AI 可以帮助发现问题,但不能替代确定性 CI 和人类最终责任。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/reach 进行邮件、短信和 API 回调发送;当
5
5
 
6
6
  # hai-reach
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/reach 进行邮件、短信和 API 回调发送;当需求涉及用户触达、消息通知、验证码发送、多渠道模板管理时使用。 |
13
+ | 适用场景 | 当任务与 `hai-reach` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/reach` 提供统一的用户触达接口,支持同时注册多个 Provider(SMTP 邮件、短信、API 回调),内置模板引擎与免打扰(DND)机制。
9
19
 
10
20
  ---
@@ -78,6 +88,8 @@ dnd:
78
88
  end: '08:00'
79
89
  ```
80
90
 
91
+ API Provider 只接受 HTTP(S) URL。回调地址若来自不可信输入,业务层必须先做域名 allowlist,并由企业网络出口策略限制内网访问;不要在日志中记录完整 URL、收件人或第三方响应体。
92
+
81
93
  ### 2. 初始化与关闭
82
94
 
83
95
  ```typescript
@@ -5,6 +5,16 @@ description: 使用 @h-ai/reldb 进行 SQLite/PostgreSQL/MySQL 的初始化、SQ
5
5
 
6
6
  # hai-reldb
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/reldb 进行 SQLite/PostgreSQL/MySQL 的初始化、SQL/DDL/CRUD/事务与分页操作;当需求涉及数据库访问、CRUD 仓库、事务处理、分页查询或 HaiReldbError 分支处理时使用。 |
13
+ | 适用场景 | 当任务与 `hai-reldb` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/reldb` 提供统一的数据库操作接口,支持 SQLite、PostgreSQL、MySQL,包含 DDL、SQL、CRUD 抽象、事务与分页。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/scheduler 进行统一定时任务管理、任务持
5
5
 
6
6
  # hai-scheduler
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/scheduler 进行统一定时任务管理、任务持久化、手工触发、触发来源审计、全局生命周期回调与执行日志查询;当需求涉及 cron 调度、JS 函数字符串任务、API 任务、分布式锁或任务事件回调时使用。 |
13
+ | 适用场景 | 当任务与 `hai-scheduler` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/scheduler` 使用统一任务模型管理 API / JS / Hook 三类执行路径,支持持久化、手工触发来源记录、分布式锁与全局生命周期回调。
9
19
 
10
20
  ## 运行环境
@@ -5,6 +5,16 @@ description: 使用 @h-ai/serv 将 oRPC contract 挂载为最小 HTTP App 抽象
5
5
 
6
6
  # hai-serv
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/serv 将 oRPC contract 挂载为最小 HTTP App 抽象;当需求涉及创建 API 服务、装配 procedure、挂载 OpenAPI 文档、配置健康检查、添加认证/权限 pipeline 包装器或切换 Node/Fetch 运行时适配器时使用。 |
13
+ | 适用场景 | 当任务与 `hai-serv` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/serv` 是 hai-framework 的 API Service 运行时,对外暴露最小 HTTP App 抽象,将 `@h-ai/api-contract` 的领域 contract 挂载成跨端可访问的 HTTP API;Hono 是内部实现细节,应用代码不要直接 import 或暴露 Hono。
9
19
 
10
20
  ---
@@ -90,15 +100,17 @@ const app = serv.createApp({
90
100
  iam,
91
101
  audio: {
92
102
  ai,
93
- verifyTicket: consumeAudioTicket, // 校验用途/时效并原子消费,返回 ServSession
94
- authorize: (session, request) => authorizeAudioRequest(session, request),
103
+ verifyTicket: consumeAudioTicket, // 校验用途/时效并原子消费,返回 { session, grant? }(推荐 iam.ticket.consume)
104
+ authorize: (session, request, grant) => authorizeAudioRequest(session, request, grant),
95
105
  onSessionEnd: (session, request) => releaseAudioConcurrency(session.userId, request.operation),
96
106
  },
97
107
  })
98
108
  ```
99
109
 
100
- - ticket 由已登录 HTTP 请求签发,短期有效且只能消费一次;普通 IAM access token 禁止进入 WebSocket URL。
101
- - `authorize` 返回的 `AuthorizedAudioRequest` 是唯一会传给 `ai.audio` 的模型、音色与格式配置;未提供时客户端的付费参数会被忽略。
110
+ - ticket 由已登录 HTTP 请求签发(推荐 `iam.ticket.issue`),短期有效且只能消费一次;连接建立即鉴权(独立预鉴权超时,默认 5s),未鉴权不处理任何业务帧;普通 IAM access token 禁止进入 WebSocket URL。
111
+ - `verifyTicket` 返回 `HaiResult<AudioTicketVerification>`(`{ session, grant? }`);`grant` 承载票据绑定的操作/模型/会话,供 `authorize` 交叉校验 `start` 未越权。
112
+ - 每帧经运行时 Zod 校验并按严格状态机接受(识别只收音频、合成只收文本、`start`/`done` 各一次、`segmentId` 会话内唯一);输入队列、消息积压、发送缓冲均有上限(`preAuthTimeoutMs`/`maxPendingMessages`/`maxSendBufferBytes` 等可调),超限或取消时以领域错误关闭并级联中止上游。
113
+ - `authorize` 返回的 `AuthorizedAudioRequest` 是唯一会传给 `ai.audio` 的模型、音色与格式配置;未提供时客户端的付费参数会被忽略(若票据 `grant.model` 存在则采用之)。
102
114
  - IAM 权限、Persona、套餐配额和并发计数属于应用策略;框架提供校验与结束钩子,不硬编码业务权限名或存储。
103
115
 
104
116
  ### 3. 扩展应用自有 contract + procedures
@@ -5,6 +5,16 @@ description: 使用 @h-ai/storage 进行文件存储操作(本地/S3),包
5
5
 
6
6
  # hai-storage
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/storage 进行文件存储操作(本地/S3),包括 file/dir/presign 三组能力;当需求涉及文件上传下载、目录批量删除、S3 预签名 URL 或客户端直传时使用。 |
13
+ | 适用场景 | 当任务与 `hai-storage` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/storage` 提供统一文件存储接口,支持本地文件系统(LocalProvider)和 S3 兼容存储(S3Provider),通过 `storage.file`、`storage.dir`、`storage.presign` 三组接口访问能力。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/ui 构建多端应用界面,包含三层组件架构
5
5
 
6
6
  # hai-ui
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/ui 构建多端应用界面,包含三层组件架构(原子/组合/场景)、DaisyUI 样式 + Bits UI headless 交互、移动端组件(SafeArea/BottomNav/PullRefresh/ActionSheet/SwipeCell/InfiniteScroll/AppBar)、Design Token 系统与平台检测;当需求涉及界面、表单、表格、移动端适配或主题切换时使用。 |
13
+ | 适用场景 | 当任务与 `hai-ui` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/ui` 是基于 Svelte 5 Runes 的多端 UI 组件库,采用 DaisyUI v5 + Tailwind CSS v4 + Bits UI v2,内置 15 个精选 DaisyUI 主题、内置中英文 i18n、自动导入。内置 Shiki 代码高亮、Mermaid 图表渲染、Design Token 系统和 7 个移动端组件。
9
19
 
10
20
  ---
@@ -5,6 +5,16 @@ description: 使用 @h-ai/vecdb 进行向量数据库操作(LanceDB/pgvector/Q
5
5
 
6
6
  # hai-vecdb
7
7
 
8
+ ## 能力契约
9
+
10
+ | 项目 | 契约 |
11
+ | --- | --- |
12
+ | 能力 | 使用 @h-ai/vecdb 进行向量数据库操作(LanceDB/pgvector/Qdrant/Chroma)的集合管理与向量增删改查;当需求涉及向量存储、相似度搜索、嵌入检索或语义搜索时使用。 |
13
+ | 适用场景 | 当任务与 `hai-vecdb` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
+ | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
+ | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
+ | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
17
+
8
18
  > `@h-ai/vecdb` 提供统一的向量数据库操作接口,支持 LanceDB、pgvector、Qdrant、Chroma,包含集合管理和向量 CRUD/搜索。
9
19
 
10
20
  ---