@h-ai/cli 0.1.0-alpha.13 → 0.1.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/dist/index.js +1 -1
- package/dist/{src-XJ6YXNAF.js → src-RZ4DPYNJ.js} +4 -4
- package/dist/{src-XJ6YXNAF.js.map → src-RZ4DPYNJ.js.map} +1 -1
- package/package.json +2 -2
- package/templates/apps/android-app/src/lib/api.ts.hbs +5 -4
- package/templates/base/package.json.hbs +21 -21
- package/templates/base/src/app.css.hbs +2 -1
- package/templates/skills/AGENTS.md +1 -0
- package/templates/skills/copilot-instructions.md +3 -0
- package/templates/skills/hai-ai/SKILL.md +44 -30
- package/templates/skills/hai-api-client/SKILL.md +94 -295
- package/templates/skills/hai-api-contract/SKILL.md +272 -0
- package/templates/skills/hai-build/SKILL.md +25 -13
- package/templates/skills/hai-capacitor/SKILL.md +7 -7
- package/templates/skills/hai-ci/SKILL.md +112 -0
- package/templates/skills/hai-core/SKILL.md +65 -2
- package/templates/skills/hai-crypto/SKILL.md +42 -1
- package/templates/skills/hai-framework-sync/SKILL.md +98 -0
- package/templates/skills/hai-iam/SKILL.md +13 -35
- package/templates/skills/hai-kit/SKILL.md +85 -412
- package/templates/skills/hai-payment/SKILL.md +8 -10
- package/templates/skills/hai-pr-review/SKILL.md +109 -0
- package/templates/skills/hai-reldb/SKILL.md +1 -1
- package/templates/skills/hai-serv/SKILL.md +658 -0
- package/templates/skills/hai-storage/SKILL.md +7 -47
- package/templates/skills/hai-ui/SKILL.md +2 -1
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.
|
|
4
|
+
"version": "0.1.0-alpha.15",
|
|
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.
|
|
37
|
+
"@h-ai/core": "0.1.0-alpha.15"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/fs-extra": "^11.0.4",
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
import { api } from '@h-ai/api-client'
|
|
8
8
|
import { createCapacitorTokenStorage } from '@h-ai/capacitor'
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
// Capacitor 静态构建后通过 Vite 的 import.meta.env 注入 PUBLIC_* 变量
|
|
11
|
+
// 此处不使用 SvelteKit 的 $env/static/public,避免脱离 SvelteKit SSR 上下文时的类型/运行时缺失
|
|
12
|
+
const API_BASE = (import.meta.env.PUBLIC_API_BASE as string | undefined) ?? 'http://localhost:3000'
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* 初始化 API 客户端
|
|
@@ -19,10 +20,10 @@ const API_BASE = import.meta.env.PUBLIC_API_BASE ?? 'http://localhost:3000'
|
|
|
19
20
|
*/
|
|
20
21
|
export async function initApi() {
|
|
21
22
|
return api.init({
|
|
22
|
-
baseUrl: API_BASE
|
|
23
|
+
baseUrl: `${API_BASE}/api/v1`,
|
|
23
24
|
auth: {
|
|
24
25
|
storage: createCapacitorTokenStorage(),
|
|
25
|
-
|
|
26
|
+
refreshPath: '/auth/refresh',
|
|
26
27
|
},
|
|
27
28
|
})
|
|
28
29
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "{{projectName}}",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.15",
|
|
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 'android-app'}}Android app built with hai Agent Framework{{/if_eq}}",
|
|
6
6
|
"keywords": ["hai", "sveltekit", "svelte5", "{{appType}}"],
|
|
@@ -21,26 +21,26 @@
|
|
|
21
21
|
"clean": "rimraf .svelte-kit build .turbo"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@h-ai/core": "^0.1.0-alpha.
|
|
25
|
-
"@h-ai/kit": "^0.1.0-alpha.
|
|
26
|
-
"@h-ai/ui": "^0.1.0-alpha.
|
|
27
|
-
"@h-ai/reldb": "^0.1.0-alpha.
|
|
28
|
-
"@h-ai/cache": "^0.1.0-alpha.
|
|
29
|
-
"@h-ai/iam": "^0.1.0-alpha.
|
|
30
|
-
"@h-ai/crypto": "^0.1.0-alpha.
|
|
31
|
-
"@h-ai/storage": "^0.1.0-alpha.
|
|
32
|
-
"@h-ai/ai": "^0.1.0-alpha.
|
|
33
|
-
"@h-ai/audit": "^0.1.0-alpha.
|
|
34
|
-
"@h-ai/reach": "^0.1.0-alpha.
|
|
35
|
-
"@h-ai/payment": "^0.1.0-alpha.
|
|
36
|
-
"@h-ai/vecdb": "^0.1.0-alpha.
|
|
37
|
-
"@h-ai/datapipe": "^0.1.0-alpha.
|
|
38
|
-
"@h-ai/scheduler": "^0.1.0-alpha.
|
|
39
|
-
"@h-ai/deploy": "^0.1.0-alpha.
|
|
40
|
-
"@h-ai/api-client": "^0.1.0-alpha.
|
|
41
|
-
"@h-ai/capacitor": "^0.1.0-alpha.
|
|
42
|
-
"@h-ai/api-client": "^0.1.0-alpha.
|
|
43
|
-
"@h-ai/capacitor": "^0.1.0-alpha.
|
|
24
|
+
"@h-ai/core": "^0.1.0-alpha.15",
|
|
25
|
+
"@h-ai/kit": "^0.1.0-alpha.15"{{#if hasUi}},
|
|
26
|
+
"@h-ai/ui": "^0.1.0-alpha.15"{{/if}}{{#if features.db}},
|
|
27
|
+
"@h-ai/reldb": "^0.1.0-alpha.15"{{/if}}{{#if features.cache}},
|
|
28
|
+
"@h-ai/cache": "^0.1.0-alpha.15"{{/if}}{{#if features.iam}},
|
|
29
|
+
"@h-ai/iam": "^0.1.0-alpha.15"{{/if}}{{#if features.crypto}},
|
|
30
|
+
"@h-ai/crypto": "^0.1.0-alpha.15"{{/if}}{{#if features.storage}},
|
|
31
|
+
"@h-ai/storage": "^0.1.0-alpha.15"{{/if}}{{#if features.ai}},
|
|
32
|
+
"@h-ai/ai": "^0.1.0-alpha.15"{{/if}}{{#if features.audit}},
|
|
33
|
+
"@h-ai/audit": "^0.1.0-alpha.15"{{/if}}{{#if features.reach}},
|
|
34
|
+
"@h-ai/reach": "^0.1.0-alpha.15"{{/if}}{{#if features.payment}},
|
|
35
|
+
"@h-ai/payment": "^0.1.0-alpha.15"{{/if}}{{#if features.vecdb}},
|
|
36
|
+
"@h-ai/vecdb": "^0.1.0-alpha.15"{{/if}}{{#if features.datapipe}},
|
|
37
|
+
"@h-ai/datapipe": "^0.1.0-alpha.15"{{/if}}{{#if features.scheduler}},
|
|
38
|
+
"@h-ai/scheduler": "^0.1.0-alpha.15"{{/if}}{{#if features.deploy}},
|
|
39
|
+
"@h-ai/deploy": "^0.1.0-alpha.15"{{/if}}{{#if features.api-client}},
|
|
40
|
+
"@h-ai/api-client": "^0.1.0-alpha.15"{{/if}}{{#if features.capacitor}},
|
|
41
|
+
"@h-ai/capacitor": "^0.1.0-alpha.15"{{/if}}{{#if isCapacitorApp}}{{#unless features.api-client}},
|
|
42
|
+
"@h-ai/api-client": "^0.1.0-alpha.15"{{/unless}}{{#unless features.capacitor}},
|
|
43
|
+
"@h-ai/capacitor": "^0.1.0-alpha.15"{{/unless}}{{/if}},
|
|
44
44
|
"zod": "^4.3.6"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
@import '@h-ai/ui/styles/mobile.css';
|
|
10
10
|
|
|
11
11
|
/* ─── 扫描 @h-ai/ui 组件中使用的 Tailwind 类名 ─── */
|
|
12
|
-
@source "../node_modules/@h-ai/ui/dist/**/*.{svelte,ts}";
|
|
12
|
+
@source "../node_modules/@h-ai/ui/dist/**/*.{svelte,js,ts}";
|
|
13
|
+
@source "../../../node_modules/@h-ai/ui/dist/**/*.{svelte,js,ts}";
|
|
13
14
|
|
|
14
15
|
/* ─── DaisyUI 主题 ─── */
|
|
15
16
|
@plugin "daisyui" {
|
|
@@ -24,3 +24,4 @@
|
|
|
24
24
|
- **框架模块**:`hai-core/`、`hai-kit/`、`hai-reldb/`、`hai-iam/`、`hai-crypto/`、`hai-cache/`、`hai-storage/`、`hai-ai/`
|
|
25
25
|
- **UI 组件**:`hai-ui/SKILL.md`
|
|
26
26
|
- **TDD 开发流程**:`hai-app-tests/`(TDD 测试先行)、`hai-app-create/`(TDD 实现)、`hai-app-review/`(TDD 重构审查)
|
|
27
|
+
- **仓库工程流程**:`hai-ci/`(CI/CD 与质量门禁)、`hai-pr-review/`(PR / Issue 交付审查与 AI Review)、`hai-framework-sync/`(两仓同步)
|
|
@@ -48,6 +48,9 @@
|
|
|
48
48
|
| `hai-app-create` | TDD 驱动的功能创建(先测试后实现) |
|
|
49
49
|
| `hai-app-review` | 应用代码审查(含 TDD 合规检查) |
|
|
50
50
|
| `hai-app-tests` | TDD 测试规范(Vitest 单元测试 + Playwright E2E) |
|
|
51
|
+
| `hai-ci` | CI/CD、GitHub Actions、质量门禁与 workflow 安全 |
|
|
52
|
+
| `hai-pr-review` | PR / Issue 交付审查、AI Review 策略、CODEOWNERS 与合并门禁 |
|
|
53
|
+
| `hai-framework-sync` | hai-framework 模板源头与应用仓库同步 |
|
|
51
54
|
|
|
52
55
|
## 开发流程
|
|
53
56
|
|
|
@@ -20,7 +20,7 @@ description: 使用 @h-ai/ai 进行 LLM 调用(OpenAI 兼容)、MCP 服务
|
|
|
20
20
|
| `ai.memory` / `ai.conversation` | ✅ | ❌(通过 API 查询) |
|
|
21
21
|
| `ai.knowledge` 知识库 | ✅ | ❌(通过 API 查询) |
|
|
22
22
|
|
|
23
|
-
浏览器端消费 AI 能力的标准模式:通过 `
|
|
23
|
+
浏览器端消费 AI 能力的标准模式:通过 `@h-ai/api-client` 的 typed contract 调用 `apiClient.ai.chats.*`;如需 SSE 流式输出,由应用显式暴露自定义流式 endpoint,再用 `fetch` / `apiFetch` 消费。
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
@@ -266,27 +266,20 @@ await mcp.connect(transport)
|
|
|
266
266
|
### 前端客户端
|
|
267
267
|
|
|
268
268
|
```typescript
|
|
269
|
-
import {
|
|
270
|
-
import { createAIClient } from '@h-ai/ai/client'
|
|
269
|
+
import { apiClient } from '@h-ai/api-client'
|
|
271
270
|
|
|
272
|
-
await
|
|
273
|
-
const client = createAIClient({ api })
|
|
271
|
+
await apiClient.init({ baseUrl: '/api/v1', auth: {} })
|
|
274
272
|
|
|
275
273
|
// 非流式
|
|
276
|
-
const response = await
|
|
277
|
-
|
|
278
|
-
// 流式
|
|
279
|
-
for await (const chunk of client.chatStream({ messages }, {
|
|
280
|
-
onProgress: (p) => { /* 处理进度 */ },
|
|
281
|
-
})) { /* ... */ }
|
|
274
|
+
const response = await apiClient.ai.chats.createCompletion({ messages })
|
|
282
275
|
|
|
283
276
|
// 便捷方法
|
|
284
|
-
const reply = await
|
|
277
|
+
const reply = await apiClient.ai.chats.sendMessage({ message: '你好', systemPrompt: '系统提示' })
|
|
285
278
|
|
|
286
279
|
// 记忆与会话查询
|
|
287
|
-
const memories = await
|
|
288
|
-
const page = await
|
|
289
|
-
const sessions = await
|
|
280
|
+
const memories = await apiClient.ai.memories.recall({ query: '用户偏好', topK: 5, objectId: 'user-001' })
|
|
281
|
+
const page = await apiClient.ai.memories.list({ objectId: 'user-001', limit: 20 })
|
|
282
|
+
const sessions = await apiClient.ai.sessions.list({ objectId: 'user-001' })
|
|
290
283
|
```
|
|
291
284
|
|
|
292
285
|
### 记忆管理 — `ai.memory`
|
|
@@ -656,36 +649,57 @@ async function manualChat(userInput: string) {
|
|
|
656
649
|
|
|
657
650
|
## 浏览器端使用
|
|
658
651
|
|
|
659
|
-
###
|
|
652
|
+
### typed 对话调用
|
|
660
653
|
|
|
661
|
-
|
|
654
|
+
浏览器 / App 通过 `@h-ai/api-client` 调用由 `@h-ai/api-contract` 定义、`@h-ai/serv` 挂载的 AI contract:
|
|
662
655
|
|
|
663
656
|
```typescript
|
|
664
|
-
import {
|
|
657
|
+
import { apiClient } from '@h-ai/api-client'
|
|
665
658
|
|
|
666
|
-
const
|
|
659
|
+
const result = await apiClient.ai.chats.createCompletion({
|
|
660
|
+
messages: [{ role: 'user', content: '你好' }],
|
|
661
|
+
})
|
|
667
662
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
content: '你好',
|
|
671
|
-
}, { signal: controller.signal })) {
|
|
672
|
-
// 每个 chunk 是 SSE data: 行的文本内容
|
|
673
|
-
appendToUI(chunk)
|
|
663
|
+
if (result.success) {
|
|
664
|
+
appendToUI(result.data.choices[0]?.message?.content ?? '')
|
|
674
665
|
}
|
|
675
|
-
|
|
676
|
-
// 主动停止
|
|
677
|
-
controller.abort()
|
|
678
666
|
```
|
|
679
667
|
|
|
680
|
-
|
|
668
|
+
### 流式对话(SSE,自定义 endpoint)
|
|
669
|
+
|
|
670
|
+
标准 `api-client` 不再提供旧的通用流式方法。若产品需要 SSE 流式输出,请在应用服务端显式定义流式 endpoint(例如 SvelteKit `+server.ts` 或 `@h-ai/serv` 自定义 route),浏览器端再用 `fetch` / `apiFetch` 消费。
|
|
681
671
|
|
|
682
672
|
```typescript
|
|
683
673
|
import { apiFetch } from '$lib/utils/api'
|
|
684
674
|
|
|
685
|
-
const
|
|
675
|
+
const controller = new AbortController()
|
|
676
|
+
|
|
677
|
+
const res = await apiFetch('/api/ai/chat-stream', {
|
|
678
|
+
method: 'POST',
|
|
679
|
+
headers: { 'Content-Type': 'application/json' },
|
|
680
|
+
body: JSON.stringify({ conversationId: 'conv-1', content: '你好' }),
|
|
681
|
+
signal: controller.signal,
|
|
682
|
+
})
|
|
683
|
+
|
|
684
|
+
const reader = res.body!.getReader()
|
|
685
|
+
const decoder = new TextDecoder()
|
|
686
|
+
while (true) {
|
|
687
|
+
const { done, value } = await reader.read()
|
|
688
|
+
if (done)
|
|
689
|
+
break
|
|
690
|
+
|
|
691
|
+
appendToUI(decoder.decode(value))
|
|
692
|
+
}
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
或直接使用原生 `fetch`(跨域公共 API 场景):
|
|
696
|
+
|
|
697
|
+
```typescript
|
|
698
|
+
const res = await fetch(`${apiBase}/ai/chat-stream`, {
|
|
686
699
|
method: 'POST',
|
|
687
700
|
headers: { 'Content-Type': 'application/json' },
|
|
688
701
|
body: JSON.stringify({ conversationId, content: userInput }),
|
|
702
|
+
signal: controller.signal,
|
|
689
703
|
})
|
|
690
704
|
|
|
691
705
|
// 手动消费 SSE 流
|