@h-ai/cli 1.0.0-beta.6 → 1.0.0-beta.7

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- export { DEPLOY_MIDDLEWARE, DeployConfigSchema, DeploymentArtifactSchema, HaiDeployError, ProviderConfigSchema, artifactChecksum, canKeepMiddleware, createDeploymentPlan, deploy, describeMiddlewareBackend, getDeployCommandState, getDeployRecovery, importDeploymentSecrets, loadDeploymentConfig, loadDeploymentEnvironment, mergeEnvironmentLayers, normalizeProjectName, parseMiddlewareField, readDeploymentArtifact, resolveDownloadProxy, resolveImageReference, saveDeploymentEnvironment, saveMiddlewareEnvironment, validateMiddlewareField } from './chunk-4XVCGFBA.js';
2
+ export { DEPLOY_MIDDLEWARE, DeployConfigSchema, DeploymentArtifactSchema, HaiDeployError, ProviderConfigSchema, artifactChecksum, canKeepMiddleware, createDeploymentPlan, deploy, describeMiddlewareBackend, getDeployCommandState, getDeployRecovery, importDeploymentSecrets, loadDeploymentConfig, loadDeploymentEnvironment, mergeEnvironmentLayers, normalizeProjectName, parseMiddlewareField, readDeploymentArtifact, resolveDownloadProxy, resolveImageReference, saveDeploymentEnvironment, saveMiddlewareEnvironment, validateMiddlewareField } from './chunk-XI5SKOOR.js';
3
3
  import './chunk-ZSDEVXZ7.js';
4
- //# sourceMappingURL=src-NXCCU6GO.js.map
5
- //# sourceMappingURL=src-NXCCU6GO.js.map
4
+ //# sourceMappingURL=src-CX5IJGYM.js.map
5
+ //# sourceMappingURL=src-CX5IJGYM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"src-CX5IJGYM.js"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@h-ai/cli",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.6",
4
+ "version": "1.0.0-beta.7",
5
5
  "description": "Hai Framework CLI for project scaffolding and code generation.",
6
6
  "license": "Apache-2.0",
7
7
  "keywords": [
@@ -30,7 +30,7 @@
30
30
  "node": "^22.23.4 || ^24.22.1 || ^26.12.1"
31
31
  },
32
32
  "dependencies": {
33
- "@h-ai/core": "1.0.0-beta.6",
33
+ "@h-ai/core": "1.0.0-beta.7",
34
34
  "cac": "^7.0.1",
35
35
  "chalk": "^6.0.1",
36
36
  "fast-wrap-ansi": "^0.2.2",
@@ -41,15 +41,15 @@
41
41
  "yaml": "^2.9.1"
42
42
  },
43
43
  "devDependencies": {
44
- "@h-ai/api-client": "1.0.0-beta.6",
45
- "@h-ai/cache": "1.0.0-beta.6",
46
- "@h-ai/crypto": "1.0.0-beta.6",
47
- "@h-ai/deploy": "1.0.0-beta.6",
48
- "@h-ai/feedback": "1.0.0-beta.6",
49
- "@h-ai/iam": "1.0.0-beta.6",
50
- "@h-ai/reach": "1.0.0-beta.6",
51
- "@h-ai/reldb": "1.0.0-beta.6",
52
- "@h-ai/storage": "1.0.0-beta.6",
44
+ "@h-ai/api-client": "1.0.0-beta.7",
45
+ "@h-ai/cache": "1.0.0-beta.7",
46
+ "@h-ai/crypto": "1.0.0-beta.7",
47
+ "@h-ai/deploy": "1.0.0-beta.7",
48
+ "@h-ai/feedback": "1.0.0-beta.7",
49
+ "@h-ai/iam": "1.0.0-beta.7",
50
+ "@h-ai/reach": "1.0.0-beta.7",
51
+ "@h-ai/reldb": "1.0.0-beta.7",
52
+ "@h-ai/storage": "1.0.0-beta.7",
53
53
  "@types/fs-extra": "^11.0.4",
54
54
  "@types/node": "^26.6.5",
55
55
  "@types/prompts": "^2.4.9",
@@ -19,9 +19,9 @@
19
19
  - `config/_core.yml`:应用元信息(名称 / 版本 / 环境 / 语言),启动时由 `core.config` 加载。
20
20
  - `config/_serv.yml`:服务端运行时设置(CORS 来源等)。
21
21
  - `config/_db.yml` / `_cache.yml` / `_iam.yml` / `_storage.yml` / `_audit.yml` / `_reach.yml`:管理及开发通知配置,初始化前使用模块公开 Schema 验证。Reach 默认控制台 Provider,生产按注释替换为 SMTP/短信/API。
22
- - `config/_ai.yml` / `_vecdb.yml` / `_payment.yml` / `_scheduler.yml`:保留未启用模块的完整注释示例;配置文件存在不代表模块已接入。先在本 workspace 安装对应依赖,再在 `src/server/runtime.ts` 按公开 Schema 校验、初始化并反序关闭,接入实际业务后按需取消注释。整份注释先去掉一层外层注释,可选字段继续按需开启。
22
+ - `config/_ai.yml` / `_vecdb.yml` / `_payment.yml` / `_kit.yml`:保留未启用模块的完整注释示例;配置文件存在不代表模块已接入。先在本 workspace 安装对应依赖,再在 `src/server/runtime.ts` 按公开 Schema 校验、初始化并反序关闭,接入实际业务后按需取消注释。整份注释先去掉一层外层注释,可选字段继续按需开启。scheduler 已用于审计任务,配置位于 `_scheduler.yml`。
23
23
  - `src/index.ts`:进程入口,通过 `src/server/runtime.ts` 先向 Core 注册各模块公开 Schema 并加载配置,再初始化 reldb → cache → crypto → storage → reach(有配置时)→ audit → iam → scheduler(有任务时);YAML 未声明的合法可选字段同样支持细项环境变量,启动失败及退出反序释放。
24
- - 选择 AI 时自动安装 reldb/vecdb/AI,并在 reldb/cache 之后初始化 vecdb、在其余依赖之后初始化 AI;关闭时先释放 AI,最后释放 vecdb/关系库,关闭失败会返回错误并保留重试义务。生产环境必须使用共享后端,根 `.env.prod` 默认连接 Compose `db/cache/storage/vecdb`,凭据和真实 Reach Provider JSON 私有注入。
24
+ - 默认不安装 AI、vecdb、payment 和 datapipe。后续接入 AI 时安装对应依赖,在 reldb/cache 之后初始化 vecdb、在其余依赖之后初始化 AI;关闭时先释放 AI,最后释放 vecdb/关系库。生产环境必须使用共享后端,根 `.env.prod` 默认连接 Compose `db/cache/storage`,新增 vecdb 后补充共享向量库配置;凭据和真实 Reach Provider JSON 私有注入。
25
25
  - `src/app-server.ts`:服务装配入口,挂载健康检查、OpenAPI、docs 与 procedures;应用名称 / 版本与 CORS 来源均取自上述配置。
26
26
  - `src/server/procedures/app-procedures.ts`:app 领域 procedures,对应 contract 中的 `app.info` / `app.echo` 路由。
27
27
  - `src/server/procedures/admin-procedures.ts`:认证、管理员用户/角色/审计管理和个人设置,使用 `.auth()` / `.permission(...)` 守卫。每个请求读取用户最新启用状态、角色和权限。
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "engines": { "node": "^22.23.4 || ^24.22.1 || ^26.12.1" },
3
3
  "name": "{{projectName}}",
4
- "version": "1.0.0-beta.6",
4
+ "version": "1.0.0-beta.7",
5
5
  "private": true,
6
6
  "packageManager": "pnpm@12.11.2",
7
7
  "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}}",
@@ -56,7 +56,9 @@
56
56
  "cap:build:ios": "pnpm compile && cap sync ios && cap build ios"{{/if}}
57
57
  },
58
58
  "dependencies": {
59
+ {{#unless isSvelteOnlyApp}}
59
60
  "pino-pretty": "{{versions.pinoPretty}}",
61
+ {{/unless}}
60
62
  {{#if isSvelteOnlyApp}}
61
63
  "@h-ai/api-client": "{{haiPackageSpecifier}}",
62
64
  "@h-ai/capacitor": "{{haiPackageSpecifier}}",
@@ -96,6 +98,9 @@
96
98
  "@h-ai/cli": "{{haiPackageSpecifier}}",
97
99
  {{#if isSvelteOnlyApp}}
98
100
  "@h-ai/core": "{{haiPackageSpecifier}}",
101
+ {{#if features.iam}}
102
+ "@h-ai/api-contract": "{{haiPackageSpecifier}}",
103
+ {{/if}}
99
104
  {{/if}}
100
105
  "@antfu/eslint-config": "{{versions.antfuEslintConfig}}",
101
106
  "@playwright/test": "{{versions.playwright}}",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hai-ai
3
- description: "接入 @h-ai/ai 的 LLM、工具/MCP、RAG、会话记忆、图像、语音及 A2A。"
3
+ description: "接入 @h-ai/ai 的 LLM、工具/MCP、RAG、会话记忆、图像、语音、A2A 及 ACP。"
4
4
  ---
5
5
 
6
6
  # hai-ai
@@ -9,7 +9,7 @@ description: "接入 @h-ai/ai 的 LLM、工具/MCP、RAG、会话记忆、图像
9
9
 
10
10
  | 项目 | 契约 |
11
11
  | --- | --- |
12
- | 能力 | 接入 @h-ai/ai 的 LLM、工具/MCP、RAG、会话记忆、图像、语音及 A2A |
12
+ | 能力 | 接入 @h-ai/ai 的 LLM、工具/MCP、RAG、会话记忆、图像、语音、A2A 及 ACP |
13
13
  | 适用场景 | AI 应用服务端集成或浏览器代理接入 |
14
14
  | 输入 | AIConfigInput、消息/音频/图片、scope、AbortSignal |
15
15
  | 输出 | 领域操作为 HaiResult;流为 AsyncIterable,迭代可抛错 |
@@ -26,6 +26,8 @@ description: "接入 @h-ai/ai 的 LLM、工具/MCP、RAG、会话记忆、图像
26
26
 
27
27
  ## 按需参考
28
28
 
29
+ 智能体接入、工程/worktree、容器和 Git 发布见 [ACP 接入指南](acp.md)。
30
+
29
31
  详细配置、API 签名、错误码和范本在 [guide.md](guide.md)。按下列标题定位所需小节,不默认通读;用例中的业务变量需结合当前应用补齐。
30
32
 
31
33
  - 使用边界
@@ -48,3 +50,5 @@ description: "接入 @h-ai/ai 的 LLM、工具/MCP、RAG、会话记忆、图像
48
50
  公开 API 示例以安装包的实际入口为准;框架源码中的内部工厂例子仅供模块维护。HaiResult 调用先检查 success,流与浏览器 AudioClient 按显式抛错契约处理;Context flush 失败和 A2A 未知外部效果不得盲目重放。
49
51
 
50
52
  Node 自定义 SSE 使用 ai.stream 的统一编解码,不用 split/trim 手拆上游事件;encoder 的非法元数据会显式抛错。Anthropic/MiMo 的真实 HTTP 流在退出和取消时释放正文,EOF 不伪造未完成事件,不自动重连或重放业务。
53
+
54
+ 资源目录维护见 [配置与数据库资源清单](resources.md):配置只读、数据库 CRUD、来源与版本、LLM/音频/图像/MCP/检索源/ACP。
@@ -0,0 +1,143 @@
1
+ # ACP 智能体、工作区和会话
2
+
3
+ ACP 把宿主应用接到能操作工程的智能体。`ai.llm` 负责模型调用,`ai.acp` 负责智能体进程、协议、工程目录和会话;SDD、代码评审规则、预览页面、验收和业务部署仍由应用实现。仅在 Node 服务端使用,浏览器经应用自己鉴权的 API 接收事件。
4
+
5
+ ## 选择接入方式
6
+
7
+ | mode | 用途 | 模型和文件 |
8
+ | --- | --- | --- |
9
+ | `embedded` | 启动本机安装的原生 ACP 程序 | 引用 Hai `llm.models`;使用 directory 工作区 |
10
+ | `builtin-service` | 使用已构建镜像启动专属容器 | 引用 Hai 模型;workspace volume 挂 `/workspace`,状态卷挂 `/state` |
11
+ | `custom-service` | 已有原生 HTTP/WS ACP 服务 | 远端自行维护模型;传远端可见的 cwd;框架不操作远端 Git |
12
+
13
+ Codex 用 `adapter: 'codex'`,DeepSeek Harness 用 `adapter: 'deepseek-harness'`,其他已配置模型的 ACP 程序用 `adapter: 'generic'` 和 `command/args`。需生成其他原生配置时,向 `ai.init(config, { acpAdapters })` 提供可信服务端适配器;适配器返回 command、args、env、可选 files(写到隔离状态目录)。不把密钥存入 Agent 定义,`environmentRefs` 是目标变量名到宿主环境变量名的映射。
14
+
15
+ 内置 Codex/dsh 通过 stdio 使用。HTTP/WS 是锁定 SDK 2.2.0 的官方实验传输,服务必须实现相同的 ACP 传输版本;不把任意 HTTP 聊天接口当 ACP,也不自动架设 stdio 网关。自定义服务必须声明 `supportedTransports`,协议不匹配返回错误。
16
+
17
+ ## 原生 HTTP/WS 服务:Goose
18
+
19
+ Goose 1.57.0 自身提供 `goose serve` 与 `/acp` HTTP/WS,使用 custom-service 接入。先由部署方启动服务、挂载工作区/状态卷,并在 Goose 端维护模型(例如 `GOOSE_PROVIDER=openrouter`、`GOOSE_MODEL`、`OPENROUTER_API_KEY`);服务独立设置 `GOOSE_SERVER__SECRET_KEY`。Hai 只使用 `X-Secret-Key` 认证,不向服务注入 Hai 模型密钥。
20
+
21
+ ```ts
22
+ import { ai } from '@h-ai/ai'
23
+
24
+ // ai 已初始化,Goose 已运行;HAI_GOOSE_SECRET 为服务端环境变量,值与远端服务密钥一致。
25
+ async function connectGoose() {
26
+ const registered = await ai.acp.agents.register({
27
+ id: 'goose', name: 'Goose', mode: 'custom-service',
28
+ transport: 'http', url: 'http://127.0.0.1:3284/acp',
29
+ supportedTransports: ['http', 'ws'],
30
+ headerEnv: { 'X-Secret-Key': 'HAI_GOOSE_SECRET' },
31
+ })
32
+ if (!registered.success) return registered
33
+ return ai.acp.sessions.create({ agentId: 'goose', cwd: '/workspace' })
34
+ }
35
+ ```
36
+
37
+ WebSocket 改为 `transport: 'ws'` 和 `ws://` 地址。`cwd` 是远端可见路径;应用负责远程服务和存储的启动、关闭、Git、归属检查及 TLS。缺少或错误服务密钥会被 Goose 拒绝;恢复按握手能力走原生 load/resume,不用历史 prompt 模拟。依据:[Goose 固定版本接入文档](https://github.com/aaif-goose/goose/blob/v1.57.0/documentation/docs/gdk/acp/index.md)。
38
+
39
+ ## 配置和数据库共同维护
40
+
41
+ `acp.agents`、`acp.workspaces` 可以直接写在配置文件里,也可通过 register 保存到数据库。get/list 返回 `{ value, source, version? }`,配置同 ID 优先且不可修改;数据库支持完整 update 和 remove。模型、MCP 等清单也遵循此规则,见 [资源清单](resources.md)。创建会话可通过 `mcpServerIds` 绑定合并清单里的 MCP。
42
+
43
+ ## 最小本机接入
44
+
45
+ 下面的目录、Git 地址、模型和密钥由部署方提供。首次登记一次,后续用 get/list 读取;重复 register 返回冲突。普通 API 都先检查 `success`。
46
+
47
+ Windows stdio 需要系统 PowerShell 可用;npm 的 `.cmd` 包装应改用 `command: 'node.exe'` 和实际 JS 入口参数数组。框架跟踪整个进程树,关闭时清理后台子进程;系统策略阻止启动时直接返回错误。
48
+
49
+ ```ts
50
+ import { ai } from '@h-ai/ai'
51
+
52
+ async function run() {
53
+ const initialized = await ai.init({
54
+ llm: { models: [{
55
+ id: 'coding', model: 'your-responses-model', protocol: 'responses',
56
+ apiKey: process.env.MODEL_API_KEY,
57
+ baseUrl: 'https://models.example.com/v1',
58
+ capabilities: { contextWindow: 128000, maxOutputTokens: 16384, inputModalities: ['text'], outputModalities: ['text'], toolCalling: true, reasoning: { supported: false } },
59
+ }] },
60
+ })
61
+ if (!initialized.success) return initialized
62
+ try {
63
+ const agent = await ai.acp.agents.register({ id: 'coder', name: 'Codex', mode: 'embedded', adapter: 'codex', modelIds: ['coding'], defaultModelId: 'coding' })
64
+ if (!agent.success) return agent
65
+ const workspace = await ai.acp.workspaces.register({ id: 'project', storage: { type: 'directory', path: '/srv/projects/demo' }, repositories: [{ id: 'api', url: 'https://git.example.com/team/api.git', mainBranch: 'trunk' }] })
66
+ if (!workspace.success) return workspace
67
+ const ready = await ai.acp.workspaces.prepare('project')
68
+ if (!ready.success) return ready
69
+ const created = await ai.acp.sessions.create({ agentId: 'coder', workspaceId: 'project', newWorktree: true })
70
+ if (!created.success) return created
71
+ const session = created.data
72
+ const response = await session.prompt([{ type: 'text', text: '阅读工程并说明结构' }])
73
+ if (!response.success) return response
74
+ return response.data.text
75
+ }
76
+ finally { await ai.close() }
77
+ }
78
+ ```
79
+
80
+ `agents.initialize(id)` 检查模型绑定和原生配置能否生成;真正启动和握手用 `agents.check(id, { workspaceId })`。容器 Agent 的 `image` 必须与 workspace 的 image 一致。注册 volume 时固定实际选中的引擎;`auto` 优先就绪 Podman,再尝试 Docker,显式选定不可用引擎直接失败。
81
+
82
+ 生产环境先初始化共享数据库和网络向量库,或注入 shared AIStoreProvider。Agent/workspace/session 记录和 CAS 占用存入 AI Store,原生历史保存在隔离状态目录。不能把临时内存 Provider 当跨节点锁。
83
+
84
+ ## 容器运行与模型复用
85
+
86
+ 源码仓库提供 `packages/ai/models/agents` Dockerfile 和构建命令:
87
+
88
+ ```sh
89
+ pnpm --filter @h-ai/ai agent:build codex-acp
90
+ pnpm --filter @h-ai/ai agent:build deepseek-harness --engine=docker --java --rust --go
91
+ ```
92
+
93
+ Codex 镜像明确包含 `@agentclientprotocol/codex-acp@2.5.0` 和 `@openai/codex@0.165.0`。所有镜像包含 Git、Node、Python;Java/Rust/Go 按构建选项安装。镜像自行构建、推送和部署;框架启动时不偷偷构建镜像、不挂引擎 socket。Dockerfile 随 npm 包的 models/agents 一起提供。
94
+
95
+ Agent 改为 `mode: 'builtin-service', image: 'hai-ai/codex-acp:2.5.0', engine: 'auto'`;workspace 改为 `storage: { type: 'volume', name: 'project-code', image: 'hai-ai/codex-acp:2.5.0', engine: 'auto' }`。容器重建继续复用这两个命名卷,Git 和 Agent 在容器内始终看到 `/workspace`,不会混用宿主绝对 worktree 路径。工作区主目录为 `main/`,隔离 session 为 `sessions/<id>/`,上传文件放 `files/`。
96
+
97
+ Podman 不自动继承远程服务的代理变量。需要代理时,使用 Agent/workspace 的 `environmentRefs` 显式传入容器可达的地址;宿主的回环代理不能直接在容器内使用。
98
+
99
+ 模型能力配置位于 `llm.models[].capabilities`:contextWindow、maxOutputTokens、inputModalities、outputModalities、toolCalling、reasoning.supported/efforts。未知就省略;不能用请求 `maxTokens` 预算推断真实容量。dsh 自定义模型需明确上下文、输出容量、输入模态、工具和推理能力,避免其内部默认值夸大模型能力。dsh 映射 Chat Completions、Responses、Anthropic;Codex 原生要求 Responses。现有 Hai 的 Responses 转换是客户端能力,不是对外反向网关。只有 Chat Completions 的服务不会因配置了 Codex 自动变成 Responses 服务。
100
+
101
+ 模型密钥在启动时重新解析;恢复时模型名、协议、地址、能力发生变化会拒绝,密钥轮换可以继续。自定义 ACP 服务只接受 `headerEnv` 里的认证引用,不接收 Hai 模型配置。
102
+
103
+ ## 工程和 Git
104
+
105
+ 每个 Git 工程必须写明 `mainBranch`,remote 默认为 origin。`prepare` 只克隆缺失工程并校验既有工程;不自动 pull、不重置脏目录。`workspaces.importFiles(id, [{ path, content }])` 添加普通文件,拒绝路径逃逸、链接和覆盖;没有 Git 工程的工作区无需安装 Git。涉及 Git 而命令缺失返回 `ACP_GIT_NOT_FOUND`。
106
+
107
+ 当前托管 Git 面向普通仓库;发现子模块或 Git LFS 属性时返回 `ACP_UNSUPPORTED`,不把未拉取的子模块或 LFS 指针当作完整工程。需要这些能力的应用可自行准备环境并使用低层 `connect`,其 Git 生命周期由应用负责。
108
+
109
+ 创建 session 默认共享 `main/` 路径,框架会阻止另一个共享 session 同时占用它。`newWorktree: true` 从每个工程当前已提交的本地主分支创建同名分支和 worktree,普通文件单独复制;可以指定 `branch`,默认 `acp/<sessionId>`。它不会自动拉远端,也不会导入主目录未提交修改。
110
+
111
+ - `session.updateMain()`:停止本 session 的执行环境,再 fetch 各工程的明确主分支并 ff-only 更新本地主目录;不把主分支合入 session,不自动 rebase。共享主目录被其他会话占用时返回 busy。
112
+ - `session.publish({ mode: 'push-branch', message, author: { name, email } })`:提交隔离 session 修改并推送其同名分支。
113
+ - `session.publish({ mode: 'merge-main', message, author })`:提交后检查、更新登记的主分支,再合并并推送。无 force push,不静默处理冲突。
114
+
115
+ 发布仅允许框架创建的隔离 session,避免将共享目录中别人的修改算入当前任务。操作前停止受管进程/容器,避免背景工具继续写入;要继续编码显式 `sessions.resume(id)`。原生 Agent 自己创建的 worktree 不自动纳入框架发布范围。
116
+
117
+ 多个工程不是原子事务。失败时返回 `ACP_PARTIAL_FAILURE`,`error.cause.reports` 列出每个工程 success、phase、commit 和 error;已完成工程不回滚,冲突保留现场。失败于 push 后,排除权限/网络问题可重试;远端结果不明时先核对实际分支。普通文件的修改留在 session 目录,不自动纳入 Git 发布。失败创建的 worktree 也保留,避免删除已有成果。
118
+
119
+ ## 交互、事件和结果
120
+
121
+ `onEvent` 在创建会话前注册,接收原生 session/update(含 `_meta`);`session.stream(content, signal)` 提供有界 AsyncIterable,提前退出会取消该轮。prompt 返回 stopReason、text、events;有 messageId 时 text 取最后一条消息,完整消息仍在 events。没有消息边界的 Agent 只能拼接其文本,不能猜测某段是最终答案。
122
+
123
+ `promptStructured(content, zodSchema, signal)` 只接受 end_turn、完整唯一 JSON(可为完整 JSON fenced block)和通过 Schema 的内容。不提取夹在说明中的任意对象,不自动重试付费请求。需要业务证据、ID 或范围判断时由应用进一步校验。
124
+
125
+ 权限默认取消。通过 `handlers` 提供官方 SDK 类型的 permission/fs/terminal/elicitation 回调,并在 `capabilities` 声明实际实现;terminal 必须提供完整回调组。回调运行在可信服务端,应用需按用户、session 和路径授权。Agent 自带本机工具可能不经过回调,worktree 也不是安全沙箱;只读评审需要操作系统/容器权限隔离。
126
+
127
+ 图片、音频、嵌入资源和远程 MCP 按初始化能力检查。mode/config 通过原生协议操作。取消、握手/任务超时、输出超限会返回明确错误;连接关闭后不会自动重放请求。`sessions.resume` 仅在 Agent 声明 load/resume 时使用原生 ID 和原状态,不用历史 prompt 伪造恢复。`connect` 提供底层连接、认证和原生会话枚举/删除,用于应用已经管理执行环境的情况。
128
+
129
+ `session.close()` / `ai.close()` 等待拥有的进程树或容器停止后释放占用,保留目录和卷。失联或清理失败不会按 TTL 直接抢占;管理员先检查记录里的容器资源和实际执行环境,确认停止后再恢复占用记录。生产部署需监控此类故障。应用仍需负责 API 鉴权、项目归属、外部 Git 凭据及预览/业务发布。
130
+
131
+ ## 配置与错误
132
+
133
+ `acp` 可省略:requestTimeout=30000ms、promptTimeout=600000ms、cancelTimeout=5000ms、maxContentBytes=8388608、maxPendingEvents=1024。对应 `HAI_AI_ACP_REQUESTTIMEOUT`、`HAI_AI_ACP_PROMPTTIMEOUT` 等环境变量。CLI 的 `_ai.yml` 和 `.env.example` 由公共配置目录生成这些字段;仅取消需要的配置注释不会自动启动 Agent。
134
+
135
+ 错误码:070 Git 缺失;071 普通操作失败;072 参数;073 未登记;074 占用;075 不支持;076 取消;077 超时;078 输出无效/超限;079 状态冲突;080 多工程部分失败;081 已关闭;082 运行环境不可用;083 模型不兼容;084 清理失败。统一前缀 `hai:ai:`。错误不包含原始 stderr、凭据或完整命令行。
136
+
137
+ ## 事件与恢复边界
138
+
139
+ 事件保留原生内容。智能体提供 messageId 时,prompt.text 使用最后一条消息;没有 messageId 时合并本轮收到的文本。HTTP 的 session/new 响应与会话事件是独立通道,早期事件可能稍晚到达;需要严格结果时使用 promptStructured,混入说明或不完整 JSON 会返回失败,不自动截取一个看似合法的对象。
140
+
141
+ DSH 模型需要容量、输入模态、工具能力与推理声明;reasoning.supported 为 true 时需明确 efforts,false 会映射为原生 reasoningEfforts: false。Codex 原生配置会选择 api-key 认证并使用 Hai Responses provider。
142
+
143
+ 会话绑定、定义删除和工作区修改通过共享 CAS 临界区防止悬空引用;工作路径使用独立占用锁。进程或宿主异常中断后,不自动用 TTL 假定执行者已停止:需运维先核验/终止记录中的执行资源,再修复遗留占用;正常 close 后可直接 resume。框架不将 Git worktree 当成安全沙箱。
@@ -2,7 +2,7 @@
2
2
 
3
3
  从 [SKILL.md](SKILL.md) 选择主题后读取对应小节。代码片段展示 API 用法;省略的业务变量、schema、依赖与 return 上下文需由应用补齐。
4
4
 
5
- `@h-ai/ai` 统一提供 LLM、工具、MCP、Embedding、Memory、Retrieval/RAG、Knowledge、Context、File、Rerank、Image、Audio 与 A2A 能力。
5
+ `@h-ai/ai` 统一提供 LLM、工具、MCP、Embedding、Memory、Retrieval/RAG、Knowledge、Context、File、Rerank、Image、Audio、A2A 与 ACP 能力。工程智能体、工作区和会话见 [ACP 指南](acp.md),配置与数据库资源合并见 [资源清单](resources.md)。
6
6
 
7
7
  ## 使用边界
8
8
 
@@ -0,0 +1,69 @@
1
+ # 配置与数据库资源清单
2
+
3
+ AI 的可维护资源统一使用两份来源:初始化配置(通常来自 config/ai.yml)和 AIStoreProvider 数据库。按 ID 合并,同 ID 配置优先;配置条目只读,不复制到数据库。移除配置后,原来被遮蔽的数据库条目重新可见。数据库变更不会修改配置文件。
4
+
5
+ | 清单入口 | 配置数组 | 使用方 |
6
+ | --- | --- | --- |
7
+ | `ai.llm.models` | `llm.models` | LLM、embedding、rerank、ACP 原生模型配置 |
8
+ | `ai.audio.models` | `audio.models` | ASR/TTS |
9
+ | `ai.image.models` | `image.models` | 图像生成 |
10
+ | `ai.mcp.servers` | `mcp.servers` | ACP `mcpServerIds`,外部 MCP 连接资料 |
11
+ | `ai.retrieval.sources` | `retrieval.sources` | 检索源及旧 addSource/removeSource/listSources 接口 |
12
+ | `ai.acp.agents` | `acp.agents` | 智能体接入、初始化和会话 |
13
+ | `ai.acp.workspaces` | `acp.workspaces` | 工程准备、会话目录及 Git 操作 |
14
+
15
+ 这些清单支持 `list/get/register/update/remove`。`list/get` 返回 `HaiResult`,条目为 `{ value, source, version? }`;`source` 是 config 或 database,数据库 `get` 带版本。`update` 接受完整定义,不是部分 patch。编辑前 get,再把 version 传给 update/remove,过期写入返回冲突。已有运行中的 ACP 会话保留原模型绑定;新会话读取最新清单,恢复会话会校验模型与智能体定义是否仍兼容。
16
+
17
+ ```ts
18
+ import { ai } from '@h-ai/ai'
19
+
20
+ // 已按应用生命周期成功初始化 reldb、vecdb 和 ai。
21
+ async function changeModel() {
22
+ const current = await ai.llm.models.get('coding')
23
+ if (!current.success) return current
24
+ if (current.data.source === 'config') return current
25
+ return ai.llm.models.update({ ...current.data.value, temperature: 0.2 }, current.data.version)
26
+ }
27
+ ```
28
+
29
+ 配置示例(模型名、地址与路径由部署提供):
30
+
31
+ ```yaml
32
+ llm:
33
+ models:
34
+ - id: coding
35
+ model: your-model
36
+ protocol: responses
37
+ acp:
38
+ agents:
39
+ - id: coder
40
+ name: Codex
41
+ mode: embedded
42
+ adapter: codex
43
+ modelIds: [coding]
44
+ workspaces:
45
+ - id: project
46
+ storage:
47
+ type: directory
48
+ path: /srv/projects/project
49
+ repositories:
50
+ - id: api
51
+ url: https://git.example.com/team/api.git
52
+ mainBranch: trunk
53
+ mcp:
54
+ servers:
55
+ - id: docs
56
+ name: Docs
57
+ transport: stdio
58
+ command: docs-mcp
59
+ environmentRefs:
60
+ API_TOKEN: DOCS_API_TOKEN
61
+ ```
62
+
63
+ 创建会话时传 `mcpServerIds: ['docs']`;配置和数据库 MCP 条目都可选择。环境变量在实际启动时解析,不将引用替换为密钥后保存到 MCP 定义。HTTP/SSE 的 headers 使用 `headerEnv`,stdio 的环境变量使用 `environmentRefs`。这份清单只维护外部服务器;`ai.mcp.registerTool/registerResource/registerPrompt` 仍是宿主进程的函数注册,不将可执行函数存进数据库。
64
+
65
+ 框架的异步模型调用每次读取最新清单;mem0 外部运行时在初始化时读取合并快照,其内置模型配置修改后需要重新初始化 AI。音频 `getCapabilities()` 保留原同步契约,使用本进程最近一次目录读写或异步音频调用刷新的快照;跨节点修改后先 await `ai.audio.models.get/list` 再同步查询能力。清单不是业务会话历史:session、聊天记录、persona 等继续使用各自已有的持久化 API,不从配置导入运行历史。
66
+
67
+ 配置项改写返回 `hai:ai:090`,缺失为 091,版本/重复冲突为 092,无效定义为 093,存储失败为 094。工作区路径重叠、仍被会话引用等使用 ACP 错误。数据库工作区更新/删除前需关闭并移除引用它的会话记录;移除记录不删除磁盘目录、worktree 或 volume。
68
+
69
+ 清单 API 是可信服务端管理接口,模型原始定义可能包含 apiKey。应用必须鉴权并自行选择可返回浏览器的字段,不直接透传整个 value。生产继续沿用 AI 模块已有共享数据库及向量库前置要求。
@@ -22,7 +22,7 @@ README 编辑先读章节,把功能说明与示例合并到对应章节;新
22
22
 
23
23
  ### 页面与布局
24
24
 
25
- 新建工程统一采用适用的完整模块和示例,服务端包含 AI、向量库、反馈等依赖;客户端仍按类型隔离服务端模块。安装体积相应增加,示例需按实际业务替换。`--template`、`--features`、`--examples/--no-examples` 已删除,`create --yes/-y` 改为 `--defaults`,旧参数明确报错;`deploy --yes` 保持原义。已有工程的模块选择不受影响。
25
+ 每个模板只安装实际使用的模块:admin/h5 包含认证、验证码及找回密码通知,以及数据库、缓存、加密依赖;website 只包含 Core/Kit/UI;API 包含认证、通知、上传和反馈;fullstack 保留管理后台的认证、审计、存储、通知、调度和反馈;mobile-app 只使用客户端能力。AI、payment、vecdb、datapipe 不默认安装。所有项目保留完整模块 YAML 和 `.env.example`,未启用项以注释提供,只有已启用项进入公共环境默认值。后续添加对应依赖、取消所需配置注释,再接入初始化、关闭及业务路由;添加依赖不会自动启用功能。`--template`、`--features`、`--examples/--no-examples` 已删除,`create --yes/-y` 改为 `--defaults`,旧参数明确报错;`deploy --yes` 保持原义。已有工程不会自动裁剪依赖。
26
26
 
27
27
  website默认SSR;静态发布须先移除服务端业务依赖、初始化及API/actions。静态构建与实际路径验证按[hai-build](../hai-build/SKILL.md)。
28
28
 
@@ -315,7 +315,7 @@ interface CreateArticleInput {
315
315
 
316
316
  ## 初始化顺序
317
317
 
318
- CLI 项目统一忽略 `**/data/`,含根目录、workspace 子目录及 `.gitkeep`;数据库/上传文件不入 Git。Fullstack 的服务端 config 始终保留 core、serv、db、cache、iam、storage、audit、reach、ai、vecdb、payment、scheduler、feedback 共 13 份 YAML;构建部署配置统一位于项目根 hai.json,未启用模块整份注释,可选字段及替代 Provider 按块注释,`.env.example` 也保留未启用模块的注释凭据。
318
+ CLI 项目统一忽略 `**/data/`,含根目录、workspace 子目录及 `.gitkeep`;数据库/上传文件不入 Git。每个模板只安装实际使用的模块,同时在应用 config 保留 core、serv、kit、db、cache、iam、storage、audit、reach、ai、vecdb、payment、scheduler、feedback 共 14 份 YAML;纯客户端的服务端配置仅作参考。构建部署配置统一位于项目根 hai.json,未启用模块整份注释,可选字段及替代 Provider 按块注释,`.env.example` 保留全部模块变量,未启用项不进入公共环境默认值。新增功能时添加对应依赖、启用所需配置,并接入初始化、反序关闭和业务路由;添加依赖不会自动接入模块。LDAP 只有在 login.ldap 为 true 时才参与部署扫描。
319
319
 
320
320
  H5 所有页面继承根布局的 header/footer;认证页隐藏底部导航,业务页面使用 `@h-ai/ui` 的 `BottomNav` 与移动端壳样式,导航启用 centered/maxWidth/safeArea,与页面同宽。
321
321
 
@@ -27,7 +27,7 @@ description: "构建或排查 hai 应用的源码、静态网站、容器镜像
27
27
 
28
28
  ## 构建与部署
29
29
 
30
- - 新建website包含完整模块与示例,默认Node SSR;静态发布须先移除服务端业务依赖、初始化及API/actions,保留Core/Kit/UI。compile静态预渲染使用`HAI_BUILD_STATIC=1 PUBLIC_BASE_PATH=/docs-site`,docs-site替换为实际仓库名,各路径段仅ASCII字母、数字、_、.、-,无末尾/;省略/0保持SSR,根站路径留空。HAI_BUILD_STATIC仅用于compile,PUBLIC_BASE_PATH也支持image网站构建。静态拒绝服务端业务模块、自定义API/actions与未预渲染页面,不放宽生产守卫、不用SPA fallback;默认健康端点不发布。构建不读根.env,static为公开目录,拒绝.env/.env.*与符号链接。上传build使用include-hidden-files:true保留.nojekyll,验首页/深链/刷新/资产与敏感哨兵。
30
+ - 新建website只安装Core/Kit/UI,默认Node SSR,可直接切换静态发布;注释配置与环境变量参考不启用模块。后续增加的服务端业务依赖、初始化及API/actions须先移除。compile静态预渲染使用`HAI_BUILD_STATIC=1 PUBLIC_BASE_PATH=/docs-site`,docs-site替换为实际仓库名,各路径段仅ASCII字母、数字、_、.、-,无末尾/;省略/0保持SSR,根站路径留空。HAI_BUILD_STATIC仅用于compile,PUBLIC_BASE_PATH也支持image网站构建。静态拒绝服务端业务模块、自定义API/actions与未预渲染页面,不放宽生产守卫、不用SPA fallback;默认健康端点不发布。构建不读根.env,static为公开目录,拒绝.env/.env.*与符号链接。上传build使用include-hidden-files:true保留.nojekyll,验首页/深链/刷新/资产与敏感哨兵。
31
31
 
32
32
  - 创建默认包含开发期部署工具,可用 --no-deploy 关闭。每个镜像使用 images/ 中独立 Dockerfile,Web 配置位于 images/web/,不使用镜像阶段 target 配置。
33
33
  - 构建器生成 images/dependencies/ 安装输入;fetch、安装和生产依赖整理共用 pnpm store,安装与生产依赖整理共用 SQLite 驱动缓存,并复用依赖层;依赖安装在源码COPY前,前后端仅复制各自需要的源码。运行镜像去掉应用自身声明、source map和README。file: 归档、补丁、workspace 元数据必须进入下载上下文;原生依赖缓存按系统/架构/ABI 区分。基础镜像、中间件及工具指定版本,禁止 latest。
@@ -60,7 +60,7 @@ Dockerfile 在 FROM 前声明 HAI_NODE_IMAGE / 适用的 HAI_NGINX_IMAGE,构
60
60
 
61
61
  ### SvelteKit Adapter 模式
62
62
 
63
- CLI website模板默认Node SSR。新建工程包含完整模块和示例,静态发布须先移除服务端业务依赖、初始化和API/actions;在compile时使用`HAI_BUILD_STATIC=1`与可选`PUBLIC_BASE_PATH`切换完整静态预渲染,边界见本skill的静态网站说明;该模板没有使用下方VITE_ADAPTER工厂。静态产物用preview本机检查,上传build到Pages/CDN;生成的start/Docker配置属于普通SSR模式,不能用于运行静态HTML。切回SSR只需清除静态开关并重建,PUBLIC_BASE_PATH仍可按实际网站目录用于SSR或Docker;SvelteKit/Vite差异、制品格式和健康检查见[网站挂载目录](paths.md)。
63
+ CLI website模板默认Node SSR,只安装Core/Kit/UI;注释配置和环境变量参考不启用模块。后续增加的服务端业务依赖、初始化和API/actions须在静态发布前移除;在compile时使用`HAI_BUILD_STATIC=1`与可选`PUBLIC_BASE_PATH`切换完整静态预渲染,边界见本skill的静态网站说明;该模板没有使用下方VITE_ADAPTER工厂。静态产物用preview本机检查,上传build到Pages/CDN;生成的start/Docker配置属于普通SSR模式,不能用于运行静态HTML。切回SSR只需清除静态开关并重建,PUBLIC_BASE_PATH仍可按实际网站目录用于SSR或Docker;SvelteKit/Vite差异、制品格式和健康检查见[网站挂载目录](paths.md)。
64
64
 
65
65
  仅在项目实际使用 SvelteKit 和 `@h-ai/kit/adapter` 时使用;Vite SPA 不配置 SvelteKit adapter,fullstack 各前端按自身 scripts 构建。
66
66
 
@@ -61,6 +61,8 @@ lint/typecheck 只能执行已配置的规则。新增开发规范时区分可
61
61
  - 若 E2E 稳定且耗时可控,可作为 required check。
62
62
  - 若 E2E 依赖浏览器、服务、密钥或容易 flaky,先放到 `workflow_dispatch` / `schedule` / 独立 job。
63
63
  - 应用级 E2E 使用:`pnpm --filter <app> test:e2e`。
64
+ - 依赖镜像或环境开关的关键 E2E,在 CI 中必须明确准备前置并启用;准备失败应阻断,不能让缺少配置导致的 skip 冒充验收。使用 Turbo 严格环境时,将影响测试执行范围的变量放入 `env`,同时传递变量并参与缓存身份,避免命中跳过用例时的缓存。
65
+ - 真实付费服务验收限用户已授权的可信分支和事件。可复用 workflow 的 secret 仅在调用方按事件显式传入,并只向定向验收步骤注入;安装、构建和普通根测试剥离该凭据。PR 继续使用夹具。成功和失败均可保留脱敏 JSON/HTML/截图证据,不能将密钥或认证头写入制品。
64
66
 
65
67
  ### hai-framework 依赖策略
66
68