@h-ai/cli 0.1.0-alpha.36 → 0.1.0-alpha.38
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-5IGMJVV5.js → chunk-WUYLYCW2.js} +17 -8
- package/dist/chunk-WUYLYCW2.js.map +1 -0
- package/dist/{cli-skill-templates-JMSV2SVW.js → cli-skill-templates-ZIWYMS4Y.js} +3 -3
- package/dist/{cli-skill-templates-JMSV2SVW.js.map → cli-skill-templates-ZIWYMS4Y.js.map} +1 -1
- package/dist/index.js +9 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +7 -2
- package/templates/base/package.json.hbs +1 -1
- package/templates/skills/bridges/fullstack/{AGENTS.md → AGENTS.md.hbs} +10 -10
- package/templates/skills/bridges/fullstack/{CLAUDE.md → CLAUDE.md.hbs} +1 -1
- package/templates/skills/bridges/fullstack/{copilot-instructions.md → copilot-instructions.md.hbs} +5 -5
- package/templates/skills/hai-ai/SKILL.md +74 -31
- package/templates/skills/hai-ai/reference.md +25 -11
- package/templates/skills/hai-api-client/SKILL.md +14 -0
- package/templates/skills/hai-api-contract/SKILL.md +10 -0
- package/templates/skills/hai-app-create/SKILL.md +10 -0
- package/templates/skills/hai-app-review/SKILL.md +10 -0
- package/templates/skills/hai-app-tests/SKILL.md +10 -0
- package/templates/skills/hai-audit/SKILL.md +10 -0
- package/templates/skills/hai-build/SKILL.md +10 -0
- package/templates/skills/hai-cache/SKILL.md +10 -0
- package/templates/skills/hai-capacitor/SKILL.md +10 -0
- package/templates/skills/hai-ci/SKILL.md +10 -0
- package/templates/skills/hai-core/SKILL.md +10 -0
- package/templates/skills/hai-crypto/SKILL.md +10 -0
- package/templates/skills/hai-datapipe/SKILL.md +10 -0
- package/templates/skills/hai-deploy/SKILL.md +10 -0
- package/templates/skills/hai-framework-sync/SKILL.md +10 -0
- package/templates/skills/hai-iam/SKILL.md +31 -0
- package/templates/skills/hai-kit/SKILL.md +12 -0
- package/templates/skills/hai-payment/SKILL.md +10 -0
- package/templates/skills/hai-pr-review/SKILL.md +10 -0
- package/templates/skills/hai-reach/SKILL.md +12 -0
- package/templates/skills/hai-reldb/SKILL.md +10 -0
- package/templates/skills/hai-scheduler/SKILL.md +10 -0
- package/templates/skills/hai-serv/SKILL.md +16 -4
- package/templates/skills/hai-storage/SKILL.md +10 -0
- package/templates/skills/hai-ui/SKILL.md +10 -0
- package/templates/skills/hai-vecdb/SKILL.md +10 -0
- package/dist/chunk-5IGMJVV5.js.map +0 -1
|
@@ -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, // 校验用途/时效并原子消费,返回
|
|
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
|
|
101
|
-
- `
|
|
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
|
---
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/cli-skill-templates.ts"],"names":[],"mappings":"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","file":"chunk-5IGMJVV5.js","sourcesContent":["/**\n * @h-ai/cli — Skill 模板生成\n *\n * 将 Skill 模板文件复制到用户项目中,供 AI 编程助手使用。\n * @module cli-skill-templates\n */\n\nimport type { AppType } from '../cli-types.js'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport fse from 'fs-extra'\n\n/**\n * 模块名到 Skill 目录名的映射\n */\nconst MODULE_SKILL_MAP: Record<string, string> = {\n 'db': 'hai-reldb',\n 'reldb': 'hai-reldb',\n 'cache': 'hai-cache',\n 'iam': 'hai-iam',\n 'storage': 'hai-storage',\n 'ai': 'hai-ai',\n 'crypto': 'hai-crypto',\n 'payment': 'hai-payment',\n 'vecdb': 'hai-vecdb',\n 'datapipe': 'hai-datapipe',\n 'reach': 'hai-reach',\n 'scheduler': 'hai-scheduler',\n 'audit': 'hai-audit',\n 'deploy': 'hai-deploy',\n 'kit': 'hai-kit',\n 'ui': 'hai-ui',\n 'api-client': 'hai-api-client',\n 'capacitor': 'hai-capacitor',\n}\n\n/**\n * 各 appType 互斥的 Skill。\n *\n * 生成样板工程时,默认复制 templates/skills 下所有 hai-* Skill,\n * 仅排除与当前样板技术栈明显冲突的少数 Skill。\n */\nconst SKILL_EXCLUSIONS_BY_APP_TYPE: Partial<Record<AppType, string[]>> = {\n 'admin': ['hai-serv', 'hai-api-contract', 'hai-api-client', 'hai-capacitor'],\n 'website': ['hai-serv', 'hai-api-contract', 'hai-api-client', 'hai-capacitor'],\n 'h5': ['hai-serv', 'hai-api-contract', 'hai-api-client', 'hai-capacitor'],\n 'api': ['hai-ui', 'hai-kit', 'hai-capacitor'],\n 'mobile-app': ['hai-core', 'hai-kit', 'hai-serv', 'hai-api-contract'],\n 'fullstack': ['hai-kit'],\n}\n\nconst WORKFLOW_SKILLS = [\n 'hai-build',\n 'hai-app-create',\n 'hai-app-review',\n 'hai-app-tests',\n]\n\nconst PACKAGE_SKILL_MAP: Record<string, string> = {\n '@h-ai/api-contract': 'hai-api-contract',\n '@h-ai/api-client': 'hai-api-client',\n '@h-ai/core': 'hai-core',\n '@h-ai/serv': 'hai-serv',\n '@h-ai/kit': 'hai-kit',\n '@h-ai/ui': 'hai-ui',\n '@h-ai/reldb': 'hai-reldb',\n '@h-ai/cache': 'hai-cache',\n '@h-ai/iam': 'hai-iam',\n '@h-ai/storage': 'hai-storage',\n '@h-ai/ai': 'hai-ai',\n '@h-ai/crypto': 'hai-crypto',\n '@h-ai/payment': 'hai-payment',\n '@h-ai/vecdb': 'hai-vecdb',\n '@h-ai/datapipe': 'hai-datapipe',\n '@h-ai/reach': 'hai-reach',\n '@h-ai/scheduler': 'hai-scheduler',\n '@h-ai/audit': 'hai-audit',\n '@h-ai/deploy': 'hai-deploy',\n '@h-ai/capacitor': 'hai-capacitor',\n}\n\nconst SKILL_TARGET_DIRS = ['.agents/skills'] as const\n\nconst BRIDGE_FILES = [\n {\n source: 'copilot-instructions.md',\n destination: '.github/copilot-instructions.md',\n },\n {\n source: 'CLAUDE.md',\n destination: 'CLAUDE.md',\n },\n {\n source: 'AGENTS.md',\n destination: 'AGENTS.md',\n },\n {\n source: 'opencode.json',\n destination: 'opencode.json',\n },\n] as const\n\nconst BRIDGE_PROFILE_REGEX = /^[a-z0-9-]+$/\n\nasync function listTemplateSkillNames(templatesDir: string): Promise<string[]> {\n const entries = await fse.readdir(templatesDir, { withFileTypes: true })\n const skillNames: string[] = []\n\n for (const entry of entries) {\n if (!entry.isDirectory() || !entry.name.startsWith('hai-')) {\n continue\n }\n\n const skillFilePath = path.join(templatesDir, entry.name, 'SKILL.md')\n if (await fse.pathExists(skillFilePath)) {\n skillNames.push(entry.name)\n }\n }\n\n return skillNames.sort((a, b) => a.localeCompare(b))\n}\n\nexport function resolveCompatibleSkillNames(\n skillNames: string[],\n appType?: AppType,\n): string[] {\n const excludedSkills = new Set(appType ? SKILL_EXCLUSIONS_BY_APP_TYPE[appType] ?? [] : [])\n return skillNames.filter(skillName => !excludedSkills.has(skillName))\n}\n\n/**\n * 获取 templates/skills/ 目录的绝对路径\n *\n * 兼容两种运行环境:\n * - 构建后:dist/cli-skill-templates.js → ../templates/skills\n * - 测试时:src/commands/cli-skill-templates.ts → ../../templates/skills\n */\nfunction getSkillTemplatesDir(): string {\n const currentDir = path.dirname(fileURLToPath(import.meta.url))\n const distPath = path.resolve(currentDir, '..', 'templates', 'skills')\n if (fse.pathExistsSync(distPath)) {\n return distPath\n }\n return path.resolve(currentDir, '..', '..', 'templates', 'skills')\n}\n\n/**\n * 复制单个 Skill 目录到项目\n *\n * @param templatesDir - Skill 模板根目录\n * @param skillName - Skill 目录名(如 'hai-reldb')\n * @param projectPath - 用户项目根目录\n */\nasync function copySkill(\n templatesDir: string,\n skillName: string,\n projectPath: string,\n targetDirs: readonly string[] = SKILL_TARGET_DIRS,\n overwrite = true,\n): Promise<string[]> {\n const src = path.join(templatesDir, skillName)\n\n if (!(await fse.pathExists(src))) {\n return []\n }\n\n const copiedFiles: string[] = []\n\n for (const targetDir of targetDirs) {\n const dest = path.join(projectPath, targetDir, skillName)\n const skillFilePath = path.join(dest, 'SKILL.md')\n\n if (!overwrite && await fse.pathExists(skillFilePath)) {\n continue\n }\n\n await fse.copy(src, dest, { overwrite: true })\n copiedFiles.push(`${targetDir}/${skillName}/SKILL.md`)\n }\n\n return copiedFiles\n}\n\nasync function copySkills(\n templatesDir: string,\n skillNames: string[],\n projectPath: string,\n targetDirs: readonly string[] = SKILL_TARGET_DIRS,\n overwrite = true,\n): Promise<string[]> {\n const copiedFiles: string[] = []\n\n for (const skillName of new Set(skillNames)) {\n copiedFiles.push(...await copySkill(templatesDir, skillName, projectPath, targetDirs, overwrite))\n }\n\n return copiedFiles\n}\n\n/**\n * 复制桥接文件到项目\n *\n * @param templatesDir - Skill 模板根目录\n * @param projectPath - 用户项目根目录\n */\nasync function copyBridgeFiles(\n templatesDir: string,\n projectPath: string,\n overwrite = true,\n appType?: string,\n): Promise<string[]> {\n const copiedFiles: string[] = []\n\n for (const file of BRIDGE_FILES) {\n const src = await resolveBridgeSource(templatesDir, file.source, appType)\n const dest = path.join(projectPath, file.destination)\n\n if (!src) {\n continue\n }\n\n if (!overwrite && await fse.pathExists(dest)) {\n continue\n }\n\n await fse.copy(src, dest, { overwrite })\n copiedFiles.push(file.destination)\n }\n\n return copiedFiles\n}\n\nasync function resolveBridgeSource(\n templatesDir: string,\n source: string,\n appType?: string,\n): Promise<string | null> {\n const profile = appType && BRIDGE_PROFILE_REGEX.test(appType) ? appType : 'generic'\n const candidates = [\n path.join(templatesDir, 'bridges', profile, source),\n path.join(templatesDir, 'bridges', 'generic', source),\n path.join(templatesDir, source),\n ]\n\n for (const candidate of candidates) {\n if (await fse.pathExists(candidate)) {\n return candidate\n }\n }\n\n return null\n}\n\n/**\n * 为新项目生成完整的 Skill 文件。\n *\n * 默认复制 templates/skills 下所有 hai-* Skill,再按 appType 排除互斥项。\n *\n * @param projectPath - 用户项目根目录\n * @param _features - 预留参数;保留签名兼容 createProject 调用方\n * @param appType - 应用类型(api 类型不复制 UI Skill)\n */\nexport async function generateSkillFiles(\n projectPath: string,\n _features: string[],\n appType?: string,\n): Promise<string[]> {\n const templatesDir = getSkillTemplatesDir()\n\n if (!(await fse.pathExists(templatesDir))) {\n return []\n }\n\n const copiedFiles: string[] = []\n\n const templateSkillNames = await listTemplateSkillNames(templatesDir)\n const compatibleSkillNames = resolveCompatibleSkillNames(templateSkillNames, appType as AppType | undefined)\n\n copiedFiles.push(...await copySkills(templatesDir, compatibleSkillNames, projectPath))\n\n // 复制桥接文件\n copiedFiles.push(...await copyBridgeFiles(templatesDir, projectPath, true, appType))\n\n return copiedFiles\n}\n\n/**\n * 为已有项目添加单个模块的 Skill 文件\n *\n * 在 `hai add <module>` 时调用,仅复制对应模块的 Skill 文件。\n *\n * @param projectPath - 用户项目根目录\n * @param moduleId - 模块标识(如 'db'、'iam')\n * @returns 复制的文件路径,若模块无对应 Skill 则返回 null\n */\nexport async function generateModuleSkillFile(\n projectPath: string,\n moduleId: string,\n): Promise<string[] | null> {\n const skillName = MODULE_SKILL_MAP[moduleId]\n if (!skillName) {\n return null\n }\n\n const templatesDir = getSkillTemplatesDir()\n if (!(await fse.pathExists(templatesDir))) {\n return null\n }\n\n const missingTargetDirs: string[] = []\n\n for (const targetDir of SKILL_TARGET_DIRS) {\n const skillFilePath = path.join(projectPath, targetDir, skillName, 'SKILL.md')\n if (!(await fse.pathExists(skillFilePath))) {\n missingTargetDirs.push(targetDir)\n }\n }\n\n const copiedBridgeFiles = await copyBridgeFiles(templatesDir, projectPath, false)\n if (missingTargetDirs.length === 0) {\n return copiedBridgeFiles.length > 0 ? copiedBridgeFiles : null\n }\n\n const copiedSkillFiles = await copySkill(templatesDir, skillName, projectPath, missingTargetDirs)\n const copiedFiles = [...copiedBridgeFiles, ...copiedSkillFiles]\n\n if (copiedFiles.length === 0) {\n return null\n }\n\n return copiedFiles\n}\n\nexport function resolveSkillNamesForPackages(packageNames: string[]): string[] {\n const skillNames = [...WORKFLOW_SKILLS]\n\n for (const packageName of packageNames) {\n const skillName = PACKAGE_SKILL_MAP[packageName]\n if (skillName) {\n skillNames.push(skillName)\n }\n }\n\n return [...new Set(skillNames)]\n}\n\nexport async function generateProjectAiSupport(\n projectPath: string,\n skillNames: string[],\n options: {\n overwriteSkills?: boolean\n overwriteBridgeFiles?: boolean\n appType?: string\n } = {},\n): Promise<string[]> {\n const templatesDir = getSkillTemplatesDir()\n\n if (!(await fse.pathExists(templatesDir))) {\n return []\n }\n\n const {\n overwriteSkills = true,\n overwriteBridgeFiles = true,\n } = options\n\n const copiedFiles: string[] = []\n copiedFiles.push(...await copySkills(templatesDir, skillNames, projectPath, SKILL_TARGET_DIRS, overwriteSkills))\n copiedFiles.push(...await copyBridgeFiles(templatesDir, projectPath, overwriteBridgeFiles, options.appType))\n\n return copiedFiles\n}\n"]}
|