@h-ai/cli 0.1.0-alpha5

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 (109) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +167 -0
  3. package/dist/chunk-2H7UOFLK.js +10 -0
  4. package/dist/chunk-2H7UOFLK.js.map +1 -0
  5. package/dist/chunk-LANIDJC7.js +659 -0
  6. package/dist/chunk-LANIDJC7.js.map +1 -0
  7. package/dist/chunk-YV7WPUI6.js +206 -0
  8. package/dist/chunk-YV7WPUI6.js.map +1 -0
  9. package/dist/config-templates-S5RI2MC6.js +5 -0
  10. package/dist/config-templates-S5RI2MC6.js.map +1 -0
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.js +1645 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/skill-templates-N5DU5FNX.js +5 -0
  15. package/dist/skill-templates-N5DU5FNX.js.map +1 -0
  16. package/dist/src-XJ6YXNAF.js +15030 -0
  17. package/dist/src-XJ6YXNAF.js.map +1 -0
  18. package/package.json +59 -0
  19. package/templates/README.md +126 -0
  20. package/templates/apps/admin/messages/en-US.json +33 -0
  21. package/templates/apps/admin/messages/zh-CN.json +33 -0
  22. package/templates/apps/admin/src/routes/+layout.svelte.hbs +30 -0
  23. package/templates/apps/admin/src/routes/+page.svelte.hbs +35 -0
  24. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +44 -0
  25. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +45 -0
  26. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +37 -0
  27. package/templates/apps/admin/src/routes/api/health/+server.ts +12 -0
  28. package/templates/apps/android-app/.env.hbs +3 -0
  29. package/templates/apps/android-app/capacitor.config.ts.hbs +12 -0
  30. package/templates/apps/android-app/messages/en-US.json +24 -0
  31. package/templates/apps/android-app/messages/zh-CN.json +24 -0
  32. package/templates/apps/android-app/src/lib/api.ts.hbs +30 -0
  33. package/templates/apps/android-app/src/lib/capacitor.ts +21 -0
  34. package/templates/apps/android-app/src/routes/+layout.svelte.hbs +42 -0
  35. package/templates/apps/android-app/src/routes/+layout.ts +7 -0
  36. package/templates/apps/android-app/src/routes/+page.svelte.hbs +27 -0
  37. package/templates/apps/api/src/routes/+layout.svelte +14 -0
  38. package/templates/apps/api/src/routes/+page.svelte +11 -0
  39. package/templates/apps/api/src/routes/api/v1/health/+server.ts +14 -0
  40. package/templates/apps/api/src/routes/api/v1/items/+server.ts +37 -0
  41. package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +30 -0
  42. package/templates/apps/h5/messages/en-US.json +37 -0
  43. package/templates/apps/h5/messages/zh-CN.json +37 -0
  44. package/templates/apps/h5/src/routes/+layout.svelte.hbs +57 -0
  45. package/templates/apps/h5/src/routes/+page.svelte.hbs +27 -0
  46. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +27 -0
  47. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +27 -0
  48. package/templates/apps/website/messages/en-US.json +32 -0
  49. package/templates/apps/website/messages/zh-CN.json +32 -0
  50. package/templates/apps/website/src/routes/+layout.svelte.hbs +66 -0
  51. package/templates/apps/website/src/routes/+page.svelte.hbs +33 -0
  52. package/templates/apps/website/src/routes/about/+page.svelte.hbs +27 -0
  53. package/templates/apps/website/src/routes/api/health/+server.ts +12 -0
  54. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +59 -0
  55. package/templates/apps/website/src/routes/services/+page.svelte.hbs +63 -0
  56. package/templates/base/e2e/helpers.ts +49 -0
  57. package/templates/base/package.json.hbs +67 -0
  58. package/templates/base/playwright.config.ts +32 -0
  59. package/templates/base/src/app.css +2 -0
  60. package/templates/base/src/app.d.ts.hbs +18 -0
  61. package/templates/base/src/app.html.hbs +16 -0
  62. package/templates/base/src/hooks.server.ts.hbs +123 -0
  63. package/templates/base/src/lib/server/init.ts.hbs +190 -0
  64. package/templates/base/svelte.config.js.hbs +30 -0
  65. package/templates/base/tsconfig.json +8 -0
  66. package/templates/base/vite.config.ts.hbs +27 -0
  67. package/templates/features/ai/routes/api/chat/+server.ts +26 -0
  68. package/templates/features/datapipe/routes/api/datapipe/pipeline/+server.ts +41 -0
  69. package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +21 -0
  70. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +98 -0
  71. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +124 -0
  72. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +98 -0
  73. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +114 -0
  74. package/templates/features/iam/routes-shared/api/auth/login/+server.ts +32 -0
  75. package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +15 -0
  76. package/templates/features/iam/routes-shared/api/auth/me/+server.ts +12 -0
  77. package/templates/features/iam/routes-shared/api/auth/register/+server.ts +26 -0
  78. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +30 -0
  79. package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +42 -0
  80. package/templates/features/payment/routes/api/v1/payment/query/[orderNo]/+server.ts +25 -0
  81. package/templates/features/storage/routes/api/upload/+server.ts +35 -0
  82. package/templates/features/vecdb/routes/api/vecdb/search/+server.ts +36 -0
  83. package/templates/i18n/project.inlang/settings.json +11 -0
  84. package/templates/skills/AGENTS.md +26 -0
  85. package/templates/skills/CLAUDE.md +12 -0
  86. package/templates/skills/copilot-instructions.md +61 -0
  87. package/templates/skills/hai-ai/SKILL.md +659 -0
  88. package/templates/skills/hai-api-client/SKILL.md +346 -0
  89. package/templates/skills/hai-app-create/SKILL.md +371 -0
  90. package/templates/skills/hai-app-review/SKILL.md +156 -0
  91. package/templates/skills/hai-app-tests/SKILL.md +468 -0
  92. package/templates/skills/hai-audit/SKILL.md +141 -0
  93. package/templates/skills/hai-build/SKILL.md +319 -0
  94. package/templates/skills/hai-cache/SKILL.md +184 -0
  95. package/templates/skills/hai-capacitor/SKILL.md +389 -0
  96. package/templates/skills/hai-core/SKILL.md +544 -0
  97. package/templates/skills/hai-crypto/SKILL.md +183 -0
  98. package/templates/skills/hai-datapipe/SKILL.md +214 -0
  99. package/templates/skills/hai-deploy/SKILL.md +210 -0
  100. package/templates/skills/hai-iam/SKILL.md +355 -0
  101. package/templates/skills/hai-kit/SKILL.md +319 -0
  102. package/templates/skills/hai-payment/SKILL.md +289 -0
  103. package/templates/skills/hai-reach/SKILL.md +325 -0
  104. package/templates/skills/hai-reldb/SKILL.md +459 -0
  105. package/templates/skills/hai-scheduler/SKILL.md +242 -0
  106. package/templates/skills/hai-storage/SKILL.md +230 -0
  107. package/templates/skills/hai-ui/SKILL.md +275 -0
  108. package/templates/skills/hai-vecdb/SKILL.md +273 -0
  109. package/templates/skills/opencode.json +11 -0
@@ -0,0 +1,659 @@
1
+ ---
2
+ name: hai-ai
3
+ description: 使用 @h-ai/ai 进行 LLM 调用(OpenAI 兼容)、MCP 服务器创建、工具定义与注册、流式处理、记忆管理(objectId 隔离)、上下文压缩与会话持久化;当需求涉及 AI 对话、工具调用、MCP 协议、流式响应、记忆提取注入、上下文摘要压缩、会话管理或 AI 客户端时使用。
4
+ ---
5
+
6
+ # hai-ai
7
+
8
+ > `@h-ai/ai` 提供统一的 AI 能力,支持 LLM 调用(OpenAI 兼容 API)、MCP 服务器、工具定义与注册、流式处理、记忆管理(objectId 隔离)、上下文压缩与会话持久化。支持 Node.js 与浏览器双端。
9
+
10
+ ---
11
+
12
+ ## 依赖
13
+
14
+ | 模块 | 用途 | 是否必需 | 初始化要求 |
15
+ | --- | --- | --- | --- |
16
+ | `@h-ai/reldb` | 数据库(对话记录/会话/记忆/知识库持久化) | **必需** | 需在 `ai.init()` 前初始化 |
17
+ | `@h-ai/vecdb` | 向量数据库(记忆向量检索/知识库检索) | **必需** | 需在 `ai.init()` 前初始化 |
18
+ | `@h-ai/datapipe` | 数据管道(知识库文档切分) | 内部使用 | 无需手动初始化 |
19
+
20
+ > `ai.tools` 和 `ai.stream` 为纯函数子系统,无需 init 即可使用。
21
+
22
+ ---
23
+
24
+ ## 适用场景
25
+
26
+ - 调用 LLM 进行对话(非流式/流式)
27
+ - 定义和执行工具(Function Calling)
28
+ - 创建 MCP 服务器(Streamable HTTP/SSE/Stdio)
29
+ - 注册 MCP 资源与提示词
30
+ - 自动提取和管理对话记忆
31
+ - 上下文压缩与 Token 控制
32
+ - 会话持久化与恢复(配合 reldb/vecdb)
33
+ - 前端 AI 客户端集成(记忆/会话查询)
34
+
35
+ ---
36
+
37
+ ## 使用步骤
38
+
39
+ ### 1. 配置
40
+
41
+ ```yaml
42
+ # config/_ai.yml
43
+ llm:
44
+ apiKey: ${HAI_AI_LLM_API_KEY:}
45
+ baseUrl: ${HAI_AI_LLM_BASE_URL:https://api.openai.com/v1}
46
+ model: ${HAI_AI_LLM_MODEL:gpt-4o-mini}
47
+ maxTokens: ${HAI_AI_LLM_MAX_TOKENS:4096}
48
+ temperature: 0.7
49
+ timeout: 60000
50
+
51
+ # 存储配置(可选)
52
+ store:
53
+ mode: memory # memory | persistent(需 reldb + vecdb 已初始化)
54
+
55
+ # 记忆管理(可选)
56
+ memory:
57
+ maxEntries: 1000 # 最大记忆条数
58
+ extractModel: gpt-4o-mini # 提取用模型(默认用 LLM 配置模型)
59
+ apiKey: # 可选,覆盖 LLM apiKey
60
+ baseUrl: # 可选,覆盖 LLM baseUrl
61
+ recencyDecay: 0.95 # 时间衰减系数
62
+ embeddingEnabled: true # 启用向量检索
63
+ defaultTopK: 10 # 默认检索数量
64
+
65
+ # Token 估算(可选)
66
+ token:
67
+ tokenRatio: 0.25 # Token 估算系数(4 字符 ≈ 1 token)
68
+
69
+ # 摘要生成(可选)
70
+ summary:
71
+ systemPrompt: # 自定义摘要系统提示词
72
+
73
+ # 上下文压缩(可选)
74
+ compress:
75
+ defaultStrategy: hybrid # 压缩策略:summary | sliding-window | hybrid
76
+ defaultMaxTokens: 0 # 0 = 取模型 maxTokens 的 80%
77
+ preserveLastN: 4 # 保留最近 N 条消息
78
+
79
+ # 知识库(可选)
80
+ knowledge:
81
+ collection: hai_ai_knowledge
82
+ dimension: 1536
83
+ enableEntityExtraction: true
84
+ cleanOptions:
85
+ removeHtml: true
86
+ normalizeWhitespace: true
87
+ chunkOptions:
88
+ mode: markdown # sentence | paragraph | markdown | page | custom
89
+ maxSize: 1500
90
+ overlap: 200
91
+ ```
92
+
93
+ ### 2. 初始化与关闭
94
+
95
+ ```typescript
96
+ import { ai } from '@h-ai/ai'
97
+ import { reldb } from '@h-ai/reldb'
98
+ import { vecdb } from '@h-ai/vecdb'
99
+
100
+ // 先初始化依赖
101
+ await reldb.init(core.config.get('db'))
102
+ await vecdb.init(core.config.get('vecdb'))
103
+
104
+ // 再初始化 AI 模块(自动使用已初始化的 reldb 和 vecdb 单例)
105
+ ai.init(core.config.get('ai'))
106
+ // 使用后
107
+ ai.close()
108
+ ```
109
+
110
+ **特殊说明**:`ai.tools` 和 `ai.stream` 无需 init 即可使用;`ai.llm` 和 `ai.mcp` 操作需要先 init。
111
+
112
+ ---
113
+
114
+ ## 核心 API
115
+
116
+ ### LLM 操作 — `ai.llm`
117
+
118
+ | 方法 | 签名 | 说明 |
119
+ | ------------ | ------------------------------------------------------ | ---------------- |
120
+ | `chat` | `(options) => Promise<HaiResult<ChatCompletionResponse>>` | 对话(非流式) |
121
+ | `chatStream` | `(options) => AsyncIterable<ChatCompletionChunk>` | 对话(流式) |
122
+ | `listModels` | `() => Promise<HaiResult<string[]>>` | 获取可用模型列表 |
123
+
124
+ ```typescript
125
+ // 非流式
126
+ const result = await ai.llm.chat({
127
+ messages: [
128
+ { role: 'system', content: '你是一个有帮助的助手' },
129
+ { role: 'user', content: '你好' },
130
+ ],
131
+ tools: registry.getDefinitions(), // 可选
132
+ })
133
+ if (result.success) {
134
+ const message = result.data.choices[0].message
135
+ }
136
+
137
+ // 流式
138
+ for await (const chunk of ai.llm.chatStream({ messages })) {
139
+ const delta = chunk.choices[0]?.delta?.content
140
+ if (delta)
141
+ process.stdout.write(delta)
142
+ }
143
+ ```
144
+
145
+ ### 工具定义 — `ai.tools`
146
+
147
+ ```typescript
148
+ import { ai } from '@h-ai/ai'
149
+ import { z } from 'zod'
150
+
151
+ // 定义工具(Zod Schema 自动转 JSON Schema)
152
+ const weatherTool = ai.tools.define({
153
+ name: 'get_weather',
154
+ description: '获取天气信息',
155
+ parameters: z.object({
156
+ city: z.string().describe('城市名称'),
157
+ unit: z.enum(['celsius', 'fahrenheit']).optional(),
158
+ }),
159
+ handler: async ({ city, unit }) => {
160
+ return { temperature: 20, city, unit: unit ?? 'celsius' }
161
+ },
162
+ })
163
+
164
+ // 注册表管理
165
+ const registry = ai.tools.createRegistry()
166
+ registry.register(weatherTool)
167
+
168
+ // 获取 OpenAI 工具定义(传递给 LLM)
169
+ const definitions = registry.getDefinitions()
170
+
171
+ // 执行 LLM 返回的工具调用
172
+ const toolMessage = await registry.execute(toolCall)
173
+ const toolMessages = await registry.executeAll(toolCalls, { parallel: true })
174
+ ```
175
+
176
+ > `ai.tools.define` 和 `ai.tools.createRegistry` 也可通过 `defineTool` / `createToolRegistry` 直接导入,两者等价。
177
+
178
+ ### 流处理 — `ai.stream`
179
+
180
+ ```typescript
181
+ import { ai } from '@h-ai/ai'
182
+
183
+ const processor = ai.stream.createProcessor()
184
+ for await (const chunk of ai.llm.chatStream({ messages })) {
185
+ const delta = processor.process(chunk)
186
+ if (delta?.content) { /* 实时显示 */ }
187
+ }
188
+
189
+ const result = processor.getResult()
190
+ // { content: string, toolCalls: ToolCall[], finishReason: string | null }
191
+ const message = processor.toAssistantMessage()
192
+ // { role: 'assistant', content: '...', tool_calls?: [...] }
193
+
194
+ // 快捷收集全部内容
195
+ const collected = await ai.stream.collect(stream)
196
+ ```
197
+
198
+ > `ai.stream.createProcessor` / `ai.stream.collect` 也可通过 `createStreamProcessor` / `collectStream` 直接导入。
199
+
200
+ ### MCP 服务器 — `createMcpServer`
201
+
202
+ ```typescript
203
+ import { createMcpServer, StreamableHTTPServerTransport } from '@h-ai/ai'
204
+ import { z } from 'zod'
205
+
206
+ const mcp = createMcpServer({ name: 'my-server', version: '1.0.0' })
207
+
208
+ // 注册工具
209
+ mcp.registerTool('search', {
210
+ description: '搜索',
211
+ inputSchema: { query: z.string() },
212
+ }, async ({ query }) => ({
213
+ content: [{ type: 'text', text: `Results for ${query}` }],
214
+ }))
215
+
216
+ // 注册资源
217
+ mcp.registerResource('config', 'config://app', {
218
+ description: '应用配置',
219
+ }, async uri => ({
220
+ contents: [{ uri: uri.href, text: '{}' }],
221
+ }))
222
+
223
+ // 注册提示词
224
+ mcp.registerPrompt('summarize', {
225
+ description: '总结文本',
226
+ argsSchema: { text: z.string() },
227
+ }, async ({ text }) => ({
228
+ messages: [{ role: 'user', content: { type: 'text', text } }],
229
+ }))
230
+
231
+ // 连接传输层
232
+ const transport = new StreamableHTTPServerTransport({
233
+ sessionIdGenerator: () => randomUUID(),
234
+ })
235
+ await mcp.connect(transport)
236
+ ```
237
+
238
+ **传输层选项**:`StreamableHTTPServerTransport`(推荐,Web 场景)、`SSEServerTransport`、`StdioServerTransport`
239
+
240
+ ### MCP 操作 — `ai.mcp`
241
+
242
+ | 方法 | 签名 | 说明 |
243
+ | ------------------ | ---------------------------------- | ---------- |
244
+ | `registerTool` | `(def, handler) => void` | 注册工具 |
245
+ | `callTool` | `(name, input) => Promise<HaiResult>` | 调用工具 |
246
+ | `registerResource` | `(def, reader) => void` | 注册资源 |
247
+ | `readResource` | `(uri) => Promise<HaiResult>` | 读取资源 |
248
+ | `registerPrompt` | `(def, generator) => void` | 注册提示词 |
249
+ | `getPrompt` | `(name, args) => Promise<HaiResult>` | 获取提示词 |
250
+
251
+ ### 前端客户端
252
+
253
+ ```typescript
254
+ import { api } from '@h-ai/api-client'
255
+ import { createAIClient } from '@h-ai/ai/client'
256
+
257
+ await api.init({ baseUrl: '/api', auth: { ... } })
258
+ const client = createAIClient({ api })
259
+
260
+ // 非流式
261
+ const response = await client.chat({ messages })
262
+
263
+ // 流式
264
+ for await (const chunk of client.chatStream({ messages }, {
265
+ onProgress: (p) => { /* 处理进度 */ },
266
+ })) { /* ... */ }
267
+
268
+ // 便捷方法
269
+ const reply = await client.sendMessage('你好', '系统提示')
270
+
271
+ // 记忆与会话查询
272
+ const memories = await client.recallMemories('用户偏好', { topK: 5, objectId: 'user-001' })
273
+ const page = await client.listMemories({ objectId: 'user-001', offset: 0, limit: 20 })
274
+ const sessions = await client.listSessions('user-001')
275
+ ```
276
+
277
+ ### 记忆管理 — `ai.memory`
278
+
279
+ | 方法 | 签名 | 说明 |
280
+ | ----------------- | ------------------------------------------------------------- | ---------------------------------- |
281
+ | `extract` | `(messages, options?) => Promise<HaiResult<MemoryEntry[]>>` | 从对话中自动提取记忆(LLM 驱动) |
282
+ | `add` | `(entry) => Promise<HaiResult<MemoryEntry>>` | 手动添加一条记忆 |
283
+ | `get` | `(memoryId) => Promise<HaiResult<MemoryEntry>>` | 获取指定记忆 |
284
+ | `recall` | `(query, options?) => Promise<HaiResult<MemoryEntry[]>>` | 按查询检索最相关的记忆 |
285
+ | `injectMemories` | `(messages, options?) => Promise<HaiResult<ChatMessage[]>>` | 将相关记忆自动注入消息列表 |
286
+ | `remove` | `(memoryId) => Promise<HaiResult<void>>` | 删除指定记忆 |
287
+ | `list` | `(options?) => Promise<HaiResult<MemoryEntry[]>>` | 列出记忆(支持类型/objectId 过滤) |
288
+ | `listPage` | `(options?) => Promise<HaiResult<StorePage<MemoryEntry>>>` | 分页列出记忆 |
289
+ | `clear` | `(options?) => Promise<HaiResult<void>>` | 清空记忆(支持按类型/objectId 清空)|
290
+
291
+ ```typescript
292
+ // 从对话中自动提取记忆
293
+ const extracted = await ai.memory.extract(messages, { objectId: 'user-001' })
294
+ if (extracted.success) {
295
+ // extracted.data: MemoryEntry[](已自动存储)
296
+ }
297
+
298
+ // 手动添加记忆
299
+ await ai.memory.add({
300
+ content: '用户偏好使用中文',
301
+ type: 'preference', // fact | preference | event | entity | instruction
302
+ importance: 0.8,
303
+ objectId: 'user-001', // 可选,不传为全局
304
+ })
305
+
306
+ // 检索相关记忆
307
+ const memories = await ai.memory.recall('语言偏好', { topK: 5, objectId: 'user-001' })
308
+
309
+ // 将记忆注入消息列表(自动检索 + 格式化 + 插入 system prompt)
310
+ const enriched = await ai.memory.injectMemories(messages, { topK: 5, position: 'system' })
311
+ if (enriched.success) {
312
+ const response = await ai.llm.chat({ messages: enriched.data })
313
+ }
314
+ ```
315
+
316
+ ### Token 估算 — `ai.token`
317
+
318
+ | 方法 | 签名 | 说明 |
319
+ | ------------------ | ----------------------------------- | ------------------------ |
320
+ | `estimateMessages` | `(messages) => HaiResult<number>` | 估算消息列表的 Token 数 |
321
+ | `estimateText` | `(text) => number` | 估算纯文本的 Token 数 |
322
+
323
+ ```typescript
324
+ // 估算消息列表 Token 数
325
+ const tokens = ai.token.estimateMessages(messages)
326
+ if (tokens.success) {
327
+ // tokens.data — 估算的 Token 数
328
+ }
329
+
330
+ // 估算纯文本 Token 数
331
+ const count = ai.token.estimateText('Hello world')
332
+ ```
333
+
334
+ ### 消息摘要 — `ai.summary`
335
+
336
+ | 方法 | 签名 | 说明 |
337
+ | ----------- | ----------------------------------------------------------------- | ----------------------------- |
338
+ | `summarize` | `(messages, options?) => Promise<HaiResult<SummaryResult>>` | 对消息生成摘要(支持增量) |
339
+ | `generate` | `(text, options?) => Promise<HaiResult<SummaryResult>>` | 对纯文本生成摘要 |
340
+
341
+ ### 上下文压缩 — `ai.compress`
342
+
343
+ | 方法 | 签名 | 说明 |
344
+ | ------------- | ----------------------------------------------------------------- | ------------------------------------- |
345
+ | `tryCompress` | `(messages, options?) => Promise<HaiResult<CompressResult>>` | 压缩消息列表至指定 Token 预算 |
346
+
347
+ ```typescript
348
+ // 压缩超长对话
349
+ const result = await ai.compress.tryCompress(messages, {
350
+ strategy: 'hybrid', // summary | sliding-window | hybrid
351
+ maxTokens: 4000,
352
+ preserveLastN: 4,
353
+ })
354
+ if (result.success) {
355
+ // result.data.messages — 压缩后的消息列表
356
+ // result.data.originalTokens / compressedTokens — 压缩前后 Token 数
357
+ // result.data.summary — 生成的摘要文本
358
+ }
359
+ ```
360
+
361
+ ### 上下文管理 — `ai.context`
362
+
363
+ | 方法 | 签名 | 说明 |
364
+ | ---------------- | ----------------------------------------------------------------- | ------------------------------------------------------- |
365
+ | `createManager` | `(options?) => HaiResult<ContextManager>` | 创建有状态上下文管理器(压缩 + LLM/Memory/RAG 编排) |
366
+ | `restoreManager` | `(scope, options?) => Promise<HaiResult<ContextManager>>` | 从持久化存储恢复上下文管理器 |
367
+ | `listSessions` | `(objectId) => Promise<HaiResult<SessionInfo[]>>` | 列出指定对象的所有会话 |
368
+ | `renameSession` | `(sessionId, title) => Promise<HaiResult<void>>` | 重命名会话 |
369
+ | `removeSession` | `(sessionId) => Promise<HaiResult<void>>` | 删除会话 |
370
+
371
+ **ContextManagerOptions**(嵌套子模块配置):
372
+ - `scope?: InteractionScope` — 交互作用域
373
+ - `systemPrompt?: string` — 系统提示词
374
+ - `model?: string` / `temperature?: number` — LLM 参数覆盖
375
+ - `compress?: CompressOptions & { auto?: boolean }` — 压缩配置(maxTokens/strategy/preserveLastN/auto 等)
376
+ - `memory?: { enable?, enableExtract?, topK?, maxTokens?, position? }` — 记忆配置
377
+ - `rag?: { enable?, sources?, topK?, minScore?, enableRerank? }` — RAG 配置
378
+ - `reasoning?: { enable?, strategy?, maxRounds? }` — 推理配置
379
+ - `tools?: ToolRegistryOperations` — 工具注册表
380
+
381
+ **ContextManager 方法**:
382
+ - `addMessage(msg)` — 追加消息(自动压缩)
383
+ - `getMessages()` / `getTokenUsage()` / `getSummaries()` — 查询状态
384
+ - `chat(message, options?)` — 发送消息并获取回复(编排 LLM + Memory + RAG + Reasoning)
385
+ - `chatStream(message, options?)` — 流式对话(产出 delta*/done 事件)
386
+ - `save()` — 持久化 / `reset()` — 重置
387
+
388
+ ```typescript
389
+ // 创建管理器并直接对话(推荐)
390
+ const managerResult = ai.context.createManager({
391
+ scope: { objectId: 'user-001', sessionId: 'sess-001' },
392
+ systemPrompt: '你是一个友好的助手。',
393
+ compress: { maxTokens: 8000, strategy: 'hybrid', auto: true },
394
+ memory: { enable: true, enableExtract: true },
395
+ })
396
+ if (managerResult.success) {
397
+ const manager = managerResult.data
398
+ const result = await manager.chat('你好')
399
+ // result.data.reply / result.data.model / result.data.usage
400
+ await manager.save()
401
+ }
402
+
403
+ // 流式对话
404
+ for await (const event of manager.chatStream('讲个故事')) {
405
+ if (event.type === 'delta') process.stdout.write(event.text)
406
+ }
407
+
408
+ // 恢复已有会话
409
+ const restored = await ai.context.restoreManager(
410
+ { objectId: 'user-001', sessionId: 'sess-001' },
411
+ { compress: { maxTokens: 8000 }, memory: { enable: true } },
412
+ )
413
+
414
+ // 列出对象的所有会话
415
+ const sessions = await ai.context.listSessions('user-001')
416
+ ```
417
+
418
+ ---
419
+
420
+ ## 错误码 — `HaiAIError`
421
+
422
+ | 错误码 | code | 说明 |
423
+ | --------------------------------------------------- | -------------- | -------------------- |
424
+ | `HaiAIError.INTERNAL_ERROR` | `hai:ai:000` | 内部错误 |
425
+ | `HaiAIError.NOT_INITIALIZED` | `hai:ai:010` | 服务未初始化 |
426
+ | `HaiAIError.CONFIGURATION_ERROR` | `hai:ai:011` | 配置错误 |
427
+ | `HaiAIError.INIT_IN_PROGRESS` | `hai:ai:012` | 初始化进行中 |
428
+ | `HaiAIError.RERANK_API_ERROR` | `hai:ai:020` | Rerank API 调用错误 |
429
+ | `HaiAIError.RERANK_INVALID_REQUEST` | `hai:ai:021` | Rerank 请求参数无效 |
430
+ | `HaiAIError.FILE_PARSE_FAILED` | `hai:ai:030` | 文件解析失败 |
431
+ | `HaiAIError.FILE_UNSUPPORTED_FORMAT` | `hai:ai:031` | 不支持的文件格式 |
432
+ | `HaiAIError.FILE_OCR_FAILED` | `hai:ai:032` | OCR 识别失败 |
433
+ | `HaiAIError.FILE_INVALID_CONTENT` | `hai:ai:033` | 文件内容无效 |
434
+ | `HaiAIError.API_ERROR` | `hai:ai:100` | API 调用错误 |
435
+ | `HaiAIError.INVALID_REQUEST` | `hai:ai:101` | 无效请求 |
436
+ | `HaiAIError.RATE_LIMITED` | `hai:ai:102` | 速率限制 |
437
+ | `HaiAIError.TIMEOUT` | `hai:ai:103` | 请求超时 |
438
+ | `HaiAIError.MODEL_NOT_FOUND` | `hai:ai:104` | 模型未找到 |
439
+ | `HaiAIError.CONTEXT_LENGTH_EXCEEDED` | `hai:ai:105` | 上下文长度超限 |
440
+ | `HaiAIError.LLM_RECORD_FAILED` | `hai:ai:106` | 对话记录保存失败 |
441
+ | `HaiAIError.LLM_HISTORY_FAILED` | `hai:ai:107` | 对话历史查询失败 |
442
+ | `HaiAIError.MCP_CONNECTION_ERROR` | `hai:ai:200` | MCP 连接错误 |
443
+ | `HaiAIError.MCP_PROTOCOL_ERROR` | `hai:ai:201` | MCP 协议错误 |
444
+ | `HaiAIError.MCP_TOOL_ERROR` | `hai:ai:202` | MCP 工具错误 |
445
+ | `HaiAIError.MCP_RESOURCE_ERROR` | `hai:ai:203` | MCP 资源错误 |
446
+ | `HaiAIError.MCP_SERVER_ERROR` | `hai:ai:204` | MCP 服务器错误 |
447
+ | `HaiAIError.EMBEDDING_API_ERROR` | `hai:ai:300` | Embedding 调用错误 |
448
+ | `HaiAIError.EMBEDDING_MODEL_NOT_FOUND` | `hai:ai:301` | Embedding 模型未找到 |
449
+ | `HaiAIError.EMBEDDING_INPUT_TOO_LONG` | `hai:ai:302` | Embedding 输入过长 |
450
+ | `HaiAIError.TOOL_NOT_FOUND` | `hai:ai:400` | 工具未找到 |
451
+ | `HaiAIError.TOOL_VALIDATION_FAILED` | `hai:ai:401` | 工具验证失败 |
452
+ | `HaiAIError.TOOL_EXECUTION_FAILED` | `hai:ai:402` | 工具执行失败 |
453
+ | `HaiAIError.TOOL_TIMEOUT` | `hai:ai:403` | 工具执行超时 |
454
+ | `HaiAIError.REASONING_FAILED` | `hai:ai:500` | 推理执行失败 |
455
+ | `HaiAIError.REASONING_MAX_ROUNDS` | `hai:ai:501` | 推理轮次超限 |
456
+ | `HaiAIError.REASONING_STRATEGY_NOT_FOUND` | `hai:ai:502` | 推理策略未找到 |
457
+ | `HaiAIError.RETRIEVAL_FAILED` | `hai:ai:600` | 检索执行失败 |
458
+ | `HaiAIError.RETRIEVAL_SOURCE_NOT_FOUND` | `hai:ai:601` | 检索源未配置 |
459
+ | `HaiAIError.RAG_FAILED` | `hai:ai:700` | RAG 执行失败 |
460
+ | `HaiAIError.RAG_CONTEXT_BUILD_FAILED` | `hai:ai:701` | RAG 上下文构建失败 |
461
+ | `HaiAIError.KNOWLEDGE_SETUP_FAILED` | `hai:ai:800` | 知识库初始化失败 |
462
+ | `HaiAIError.KNOWLEDGE_INGEST_FAILED` | `hai:ai:801` | 知识入库失败 |
463
+ | `HaiAIError.KNOWLEDGE_RETRIEVE_FAILED` | `hai:ai:802` | 知识检索失败 |
464
+ | `HaiAIError.KNOWLEDGE_ENTITY_EXTRACT_FAILED` | `hai:ai:803` | 实体提取失败 |
465
+ | `HaiAIError.KNOWLEDGE_NOT_SETUP` | `hai:ai:804` | 知识库未初始化 |
466
+ | `HaiAIError.KNOWLEDGE_COLLECTION_NOT_FOUND` | `hai:ai:805` | 集合不存在 |
467
+ | `HaiAIError.MEMORY_EXTRACT_FAILED` | `hai:ai:900` | 记忆提取失败 |
468
+ | `HaiAIError.MEMORY_STORE_FAILED` | `hai:ai:901` | 记忆存储失败 |
469
+ | `HaiAIError.MEMORY_RECALL_FAILED` | `hai:ai:902` | 记忆召回失败 |
470
+ | `HaiAIError.MEMORY_NOT_FOUND` | `hai:ai:903` | 记忆条目不存在 |
471
+ | `HaiAIError.MEMORY_ENRICH_FAILED` | `hai:ai:904` | 记忆注入失败 |
472
+ | `HaiAIError.CONTEXT_COMPRESS_FAILED` | `hai:ai:950` | 上下文压缩失败 |
473
+ | `HaiAIError.CONTEXT_SUMMARIZE_FAILED` | `hai:ai:951` | 上下文摘要失败 |
474
+ | `HaiAIError.CONTEXT_TOKEN_ESTIMATE_FAILED` | `hai:ai:952` | Token 估算失败 |
475
+ | `HaiAIError.CONTEXT_BUDGET_EXCEEDED` | `hai:ai:953` | Token 预算超限 |
476
+ | `HaiAIError.STORE_FAILED` | `hai:ai:960` | 存储操作失败 |
477
+ | `HaiAIError.STORE_NOT_AVAILABLE` | `hai:ai:961` | 存储后端不可用 |
478
+ | `HaiAIError.SESSION_NOT_FOUND` | `hai:ai:970` | 会话不存在 |
479
+ | `HaiAIError.SESSION_FAILED` | `hai:ai:971` | 会话操作失败 |
480
+ | `HaiAIError.A2A_NOT_CONFIGURED` | `hai:ai:980` | A2A 服务未配置 |
481
+ | `HaiAIError.A2A_HANDLE_FAILED` | `hai:ai:981` | A2A 请求处理失败 |
482
+ | `HaiAIError.A2A_REMOTE_CALL_FAILED` | `hai:ai:982` | A2A 远端调用失败 |
483
+ | `HaiAIError.A2A_AUTH_FAILED` | `hai:ai:983` | A2A 认证失败 |
484
+ | `HaiAIError.A2A_LIST_MESSAGES_FAILED` | `hai:ai:984` | A2A 消息查询失败 |
485
+
486
+ ---
487
+
488
+ ## 常见模式
489
+
490
+ ### 带工具调用的对话循环
491
+
492
+ ```typescript
493
+ const registry = ai.tools.createRegistry()
494
+ registry.register(weatherTool)
495
+
496
+ const messages: ChatMessage[] = [
497
+ { role: 'user', content: '北京天气怎么样?' },
498
+ ]
499
+
500
+ let result = await ai.llm.chat({
501
+ messages,
502
+ tools: registry.getDefinitions(),
503
+ })
504
+
505
+ while (result.success && result.data.choices[0].finish_reason === 'tool_calls') {
506
+ const toolCalls = result.data.choices[0].message.tool_calls!
507
+ messages.push(result.data.choices[0].message)
508
+
509
+ const toolMessages = await registry.executeAll(toolCalls)
510
+ if (toolMessages.success)
511
+ messages.push(...toolMessages.data)
512
+
513
+ result = await ai.llm.chat({ messages, tools: registry.getDefinitions() })
514
+ }
515
+ ```
516
+
517
+ ### 知识库完整流程(文档入库 → 问答)
518
+
519
+ ```typescript
520
+ import { ai } from '@h-ai/ai'
521
+
522
+ // 初始化
523
+ await ai.knowledge.setup()
524
+
525
+ // 导入多篇文档
526
+ for (const doc of documents) {
527
+ const result = await ai.knowledge.ingest({
528
+ documentId: doc.id,
529
+ content: doc.content,
530
+ title: doc.title,
531
+ enableEntityExtraction: true,
532
+ })
533
+ if (!result.success) {
534
+ // 按错误码处理
535
+ switch (result.error.code) {
536
+ case HaiAIError.KNOWLEDGE_INGEST_FAILED:
537
+ // 入库失败
538
+ break
539
+ case HaiAIError.EMBEDDING_API_ERROR:
540
+ // 嵌入调用失败
541
+ break
542
+ }
543
+ }
544
+ }
545
+
546
+ // 问答
547
+ const answer = await ai.knowledge.ask('项目核心架构是什么?')
548
+ if (answer.success) {
549
+ // answer.data.answer — LLM 生成的回答
550
+ // answer.data.citations — 信源引用列表
551
+ }
552
+ ```
553
+
554
+ ### SvelteKit API 端点
555
+
556
+ ```typescript
557
+ // src/routes/api/ai/+server.ts
558
+ export async function POST(event) {
559
+ const { valid, data } = await kit.validate.form(event.request, ChatSchema)
560
+ if (!valid)
561
+ return kit.response.badRequest('Invalid request')
562
+
563
+ const result = await ai.llm.chat({ messages: data!.messages })
564
+ if (!result.success)
565
+ return kit.response.error(result.error.code, result.error.message)
566
+
567
+ return kit.response.ok(result.data)
568
+ }
569
+ ```
570
+
571
+ ### 记忆增强的多轮对话
572
+
573
+ ```typescript
574
+ import { ai } from '@h-ai/ai'
575
+
576
+ const messages: ChatMessage[] = [
577
+ { role: 'system', content: '你是一个有帮助的助手' },
578
+ ]
579
+
580
+ async function chat(userInput: string) {
581
+ messages.push({ role: 'user', content: userInput })
582
+
583
+ // 1. 注入相关记忆到消息列表
584
+ const enriched = await ai.memory.injectMemories(messages, {
585
+ topK: 5,
586
+ position: 'system',
587
+ })
588
+ if (!enriched.success) return
589
+
590
+ // 2. 压缩上下文以适应 Token 限制
591
+ const compressed = await ai.compress.tryCompress(enriched.data, {
592
+ maxTokens: 4000,
593
+ strategy: 'hybrid',
594
+ })
595
+ if (!compressed.success) return
596
+
597
+ // 3. 调用 LLM
598
+ const result = await ai.llm.chat({ messages: compressed.data.messages })
599
+ if (!result.success) return
600
+
601
+ const reply = result.data.choices[0].message
602
+ messages.push(reply)
603
+
604
+ // 4. 从新对话中提取记忆(异步,不阻塞响应)
605
+ ai.memory.extract(messages.slice(-2))
606
+
607
+ return reply.content
608
+ }
609
+ ```
610
+
611
+ ### 有状态上下文管理器
612
+
613
+ ```typescript
614
+ import { ai } from '@h-ai/ai'
615
+
616
+ // 创建管理器(嵌套配置 + 对话编排)
617
+ const managerResult = ai.context.createManager({
618
+ scope: { objectId: 'user-001', sessionId: 'sess-001' },
619
+ systemPrompt: '你是一个友好的助手。',
620
+ compress: { maxTokens: 8000, strategy: 'hybrid', preserveLastN: 4, auto: true },
621
+ memory: { enable: true, enableExtract: true },
622
+ })
623
+ if (!managerResult.success) throw new Error(managerResult.error.message)
624
+ const manager = managerResult.data
625
+
626
+ // 方式一:直接对话(推荐,自动编排 LLM + Memory + 压缩)
627
+ const result = await manager.chat('你好')
628
+ if (result.success) {
629
+ // result.data.reply / result.data.model / result.data.usage
630
+ }
631
+
632
+ // 流式对话
633
+ for await (const event of manager.chatStream('讲个故事')) {
634
+ if (event.type === 'delta') process.stdout.write(event.text)
635
+ }
636
+
637
+ // 方式二:手动管理消息
638
+ async function manualChat(userInput: string) {
639
+ await manager.addMessage({ role: 'user', content: userInput })
640
+ const msgs = manager.getMessages()
641
+ if (!msgs.success) return
642
+ const chatResult = await ai.llm.chat({ messages: msgs.data })
643
+ if (!chatResult.success) return
644
+ await manager.addMessage(chatResult.data.choices[0].message)
645
+ await manager.save()
646
+ return chatResult.data.choices[0].message.content
647
+ }
648
+ ```
649
+
650
+ ---
651
+
652
+ ## 相关 Skills
653
+
654
+ - `hai-build`:模块初始化顺序
655
+ - `hai-core`:配置与 HaiResult 模型
656
+ - `hai-kit`:SvelteKit API 端点集成
657
+ - `hai-vecdb`:向量数据库(Retrieval / RAG / Knowledge 的存储层)
658
+ - `hai-reldb`:关系数据库(Knowledge 实体索引的存储层)
659
+ - `hai-datapipe`:数据清洗与分块(Knowledge 入库前的数据处理)