@h-ai/cli 1.0.0-beta.23 → 1.0.0-beta.25
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-V7WGSBX3.js → chunk-CWMU5QU2.js} +483 -3
- package/dist/chunk-CWMU5QU2.js.map +1 -0
- package/dist/cli-config-templates-OWLL4H6K.js +5 -0
- package/dist/{cli-config-templates-VLXJTHCQ.js.map → cli-config-templates-OWLL4H6K.js.map} +1 -1
- package/dist/index.js +29 -23
- package/dist/index.js.map +1 -1
- package/dist/metafile-esm.json +1 -1
- package/package.json +14 -14
- package/templates/base/package.json.hbs +1 -1
- package/templates/skills/hai-ai/acp.md +71 -3
- package/templates/skills/hai-ai/reference.md +13 -1
- package/dist/chunk-V7WGSBX3.js.map +0 -1
- package/dist/cli-config-templates-VLXJTHCQ.js +0 -5
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.
|
|
4
|
+
"version": "1.0.0-beta.25",
|
|
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.
|
|
33
|
+
"@h-ai/core": "1.0.0-beta.25",
|
|
34
34
|
"cac": "^7.1.0",
|
|
35
35
|
"chalk": "^6.0.1",
|
|
36
36
|
"fast-wrap-ansi": "^0.2.2",
|
|
@@ -41,18 +41,18 @@
|
|
|
41
41
|
"yaml": "^2.9.1"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@h-ai/api-client": "1.0.0-beta.
|
|
45
|
-
"@h-ai/cache": "1.0.0-beta.
|
|
46
|
-
"@h-ai/crypto": "1.0.0-beta.
|
|
47
|
-
"@h-ai/deploy": "1.0.0-beta.
|
|
48
|
-
"@h-ai/feedback": "1.0.0-beta.
|
|
49
|
-
"@h-ai/iam": "1.0.0-beta.
|
|
50
|
-
"@h-ai/kit": "1.0.0-beta.
|
|
51
|
-
"@h-ai/payment": "1.0.0-beta.
|
|
52
|
-
"@h-ai/reach": "1.0.0-beta.
|
|
53
|
-
"@h-ai/reldb": "1.0.0-beta.
|
|
54
|
-
"@h-ai/storage": "1.0.0-beta.
|
|
55
|
-
"@h-ai/vecdb": "1.0.0-beta.
|
|
44
|
+
"@h-ai/api-client": "1.0.0-beta.25",
|
|
45
|
+
"@h-ai/cache": "1.0.0-beta.25",
|
|
46
|
+
"@h-ai/crypto": "1.0.0-beta.25",
|
|
47
|
+
"@h-ai/deploy": "1.0.0-beta.25",
|
|
48
|
+
"@h-ai/feedback": "1.0.0-beta.25",
|
|
49
|
+
"@h-ai/iam": "1.0.0-beta.25",
|
|
50
|
+
"@h-ai/kit": "1.0.0-beta.25",
|
|
51
|
+
"@h-ai/payment": "1.0.0-beta.25",
|
|
52
|
+
"@h-ai/reach": "1.0.0-beta.25",
|
|
53
|
+
"@h-ai/reldb": "1.0.0-beta.25",
|
|
54
|
+
"@h-ai/storage": "1.0.0-beta.25",
|
|
55
|
+
"@h-ai/vecdb": "1.0.0-beta.25",
|
|
56
56
|
"@types/fs-extra": "^11.0.4",
|
|
57
57
|
"@types/node": "^26.6.6",
|
|
58
58
|
"@types/prompts": "^2.4.9",
|
|
@@ -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.
|
|
4
|
+
"version": "1.0.0-beta.25",
|
|
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}}",
|
|
@@ -10,13 +10,21 @@ ACP 把宿主应用接到能操作工程的智能体。`ai.llm` 负责模型调
|
|
|
10
10
|
| `builtin-service` | 使用已构建镜像启动专属容器 | 引用 Hai 模型;workspace volume 挂 `/workspace`,状态卷挂 `/state` |
|
|
11
11
|
| `custom-service` | 已有原生 HTTP/WS ACP 服务 | 远端自行维护模型;传远端可见的 cwd;框架不操作远端 Git |
|
|
12
12
|
|
|
13
|
-
Codex 用 `adapter: 'codex'`,DeepSeek Harness 用 `adapter: 'deepseek-harness'
|
|
13
|
+
Codex 用 `adapter: 'codex'`,DeepSeek Harness 用 `adapter: 'deepseek-harness'`,Goose 用 `adapter: 'goose'`。其他已配置模型的 ACP 程序用 `adapter: 'generic'` 和 `command/args`。需生成其他原生配置时,向 `ai.init(config, { acpAdapters })` 提供可信服务端适配器。适配器返回 command、args、env 和写到隔离状态目录的可选 files。`environmentRefs` 保存目标变量名到宿主环境变量名的映射。
|
|
14
14
|
|
|
15
|
-
内置 Codex
|
|
15
|
+
内置 Codex、DSH 和 Goose 通过原生 stdio 接入。HTTP/WS 是锁定 SDK 2.2.0 的官方实验传输,服务必须实现相同的 ACP 传输版本。自定义服务必须声明 `supportedTransports`,协议不匹配返回错误。
|
|
16
|
+
|
|
17
|
+
Agent 镜像按任务选择 `minimal`、`documents`、`office`、`browser` 或 `developer`。将构建后的镜像 ID 或仓库清单 digest 登记到 Runner 环境。无需在任务内安装工具链。需要直接处理文件时,也可使用具备相应权限的独立工具作业。
|
|
18
|
+
|
|
19
|
+
使用 `session.changeExecution({ mode: 'task', acceptNewSession: true, historySummary })` 切换到任务独占容器时,可带入当前用户确认过的历史摘要。摘要最多 8 KiB UTF-8,作为新会话首次请求的历史文本发送一次。会话工具和资料仍按当前授权重新核验。
|
|
20
|
+
|
|
21
|
+
受管请求可传 `workspaceId`。应用用 `acpPolicy.allowWorkspace` 核验主体,用 `resolveWorkspace` 在执行节点提供文件名到 `Uint8Array` 的映射。快照最多 8 个平铺文件、合计不超过 16 MiB 和环境 `scratchMiB`,仅挂载到独占任务的只读 `/input`。临时副本写入 `/workspace`,会话结束后回收。
|
|
16
22
|
|
|
17
23
|
Linux 上运行 embedded Codex 前,按 [Codex 沙箱前置](https://learn.chatgpt.com/docs/sandboxing) 准备 bubblewrap 和所需的 AppArmor profile,并用 `codex sandbox` 在临时目录验证读写。沙箱初始化失败应先修复宿主环境,不能通过关闭沙箱或让模型猜测文件内容完成任务。
|
|
18
24
|
|
|
19
|
-
##
|
|
25
|
+
## Goose 的原生接入
|
|
26
|
+
|
|
27
|
+
受管 Goose 使用 `goose acp`,选择 `adapter: 'goose'`、`mode: 'embedded'` 或 `'builtin-service'`,绑定登记的 Hai 模型。适配器使用独立 Goose 状态目录和逐次工具审批,模型协议支持 Chat Completions、Responses 和 Anthropic。Goose 和 DSH 的每次受管启动只注入本次选中模型的凭据。
|
|
20
28
|
|
|
21
29
|
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 模型密钥。
|
|
22
30
|
|
|
@@ -42,6 +50,66 @@ WebSocket 改为 `transport: 'ws'` 和 `ws://` 地址。`cwd` 是远端可见路
|
|
|
42
50
|
|
|
43
51
|
`acp.agents`、`acp.workspaces` 可以直接写在配置文件里,也可通过 register 保存到数据库。get/list 返回 `{ value, source, version? }`,配置同 ID 优先且不可修改;数据库支持完整 update 和 remove。模型、MCP 等清单也遵循此规则,见 [资源清单](resources.md)。创建会话可通过 `mcpServerIds` 绑定合并清单里的 MCP。
|
|
44
52
|
|
|
53
|
+
## 为受管会话绑定第三方工具
|
|
54
|
+
|
|
55
|
+
先在 `mcp.servers` 登记第三方 Streamable HTTP 服务,设置 `allowedTools` 和上游认证头引用。每个执行节点挂载自己的工具入口,并给 Worker 提供可达的地址。入口只把当前会话的短期 Bearer 传给 Agent,真实上游凭据由服务端解析。建议使用执行节点的内网服务地址和受保护的网络。
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { createServer } from 'node:http'
|
|
59
|
+
import { ai, type ACPPlatformPolicy, type MCPServiceBroker, type MCPServiceBrokerOptions } from '@h-ai/ai'
|
|
60
|
+
|
|
61
|
+
// 应用传入真实 IAM 检查。该函数复核任务归属、权限及实际工具参数。
|
|
62
|
+
function prepareTools(url: string, authorize: MCPServiceBrokerOptions['authorize']) {
|
|
63
|
+
let broker: MCPServiceBroker | undefined
|
|
64
|
+
const http = createServer((req, res) => {
|
|
65
|
+
if (broker) return void broker.handleRequest(req, res)
|
|
66
|
+
res.writeHead(503).end()
|
|
67
|
+
})
|
|
68
|
+
const policy: ACPPlatformPolicy = {
|
|
69
|
+
// 示例只给 manuals 租户的 librarian 账号开放这一个工具。
|
|
70
|
+
allowTools: (scope, _agentId, ids) =>
|
|
71
|
+
scope.tenantId === 'manuals' && scope.userId === 'librarian' && ids.every(id => id === 'manual_search'),
|
|
72
|
+
async bindTools(scope, sessionId, ids, signal) {
|
|
73
|
+
if (!broker || ids.length !== 1 || ids[0] !== 'manual_search')
|
|
74
|
+
throw new Error('Manual tool binding is unavailable')
|
|
75
|
+
const bound = await broker.bind({
|
|
76
|
+
principal: { tenantId: scope.tenantId, userId: scope.userId },
|
|
77
|
+
taskId: sessionId,
|
|
78
|
+
signal,
|
|
79
|
+
tools: [{
|
|
80
|
+
id: 'manual_search',
|
|
81
|
+
serviceId: 'manual',
|
|
82
|
+
tool: 'search_manual',
|
|
83
|
+
description: 'Search authorized manuals',
|
|
84
|
+
inputSchema: {
|
|
85
|
+
type: 'object', properties: { query: { type: 'string', maxLength: 1000 } },
|
|
86
|
+
required: ['query'], additionalProperties: false,
|
|
87
|
+
},
|
|
88
|
+
}],
|
|
89
|
+
})
|
|
90
|
+
if (!bound.success) throw new Error(bound.error.message)
|
|
91
|
+
return bound.data
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
http, policy,
|
|
96
|
+
activate() {
|
|
97
|
+
// ai.init(config, { runner, acpPolicy: policy }) 成功后,监听 HTTP 端口之前激活。
|
|
98
|
+
const created = ai.mcp.services.createBroker({ url, authorize })
|
|
99
|
+
if (created.success) broker = created.data
|
|
100
|
+
return created
|
|
101
|
+
},
|
|
102
|
+
close() { broker?.close() },
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
创建绑定时,工具入口按工具独立编译输入 Schema,并检查目录白名单。每次调用重新检查业务权限和目录,网络重定向会失败。`bindTools` 收到的是 Worker 生命周期信号。示例直接返回 `bound.data`,其中的 `signal` 会在绑定到期或被撤销时终止;默认有效期为 15 分钟,可通过 `ttlMs` 调整。会话关闭、Worker 失租或服务停止时撤销绑定。凭据在轮次中失效会取消本轮,后续调用返回 `ACP_CLOSED`。要继续使用工具,显式创建新会话,并按需带入用户授权的历史摘要。多个执行节点分别挂载自己的入口,使 Agent 始终访问签发本次凭据的节点。
|
|
108
|
+
|
|
109
|
+
应用使用 `scoped.approvals.rules(offset, limit)` 分页查看有效规则,使用 `revoke(id)` 撤销。`permissions.ruleIds` 可只启用指定持久规则,切换为 `approval: 'never'` 仍可复用同一执行安全范围的已授权操作。升级后,按旧 Worker 快照保存的规则仍可查看和撤销,继续使用时需重新授权。标准 Store 会在后台限批清理到期规则和已过期审批。
|
|
110
|
+
|
|
111
|
+
受管会话、任务索引和幂等意图的保留期至少为 7 天。对应 Runner 记录清理后,ACP 执行节点才清理关联数据。仍活动或未核验的 `unknown` 执行受保留保护。自定义关系 Store 通过 `queryKeys` 和 `removeIfUnchanged` 接入后台清理。Runner 的 `retentionMs` 控制执行记录的保留期,应用应单独保存需要长期展示的业务历史。
|
|
112
|
+
|
|
45
113
|
## 最小本机接入
|
|
46
114
|
|
|
47
115
|
下面的目录、Git 地址、模型和密钥由部署方提供。首次登记一次,后续用 get/list 读取;重复 register 返回冲突。普通 API 都先检查 `success`。
|
|
@@ -237,7 +237,19 @@ IndexTTS 的 Node HTTP 请求使用同版本 Undici fetch/Agent/FormData;模
|
|
|
237
237
|
|
|
238
238
|
## LLM 结构化输出
|
|
239
239
|
|
|
240
|
-
`ai.llm.generateObject({ schema, messages, model?, systemPrompt?, maxRepairs?, signal? })
|
|
240
|
+
`ai.llm.generateObject({ schema, messages, model?, systemPrompt?, responseFormat?, schemaName?, maxRepairs?, signal? })` 适用于意图分类等需要结构化结果的场景。默认 `responseFormat: 'json_schema'` 向上游发送严格 Schema,仅在此模式使用 `schemaName`,默认 `result`。只支持通用 JSON 模式的 Chat 网关使用 `'json_object'`,框架将 Schema 加入提示词。两种模式都在本地用相同 Zod Schema 校验。解析或校验失败时按 `maxRepairs` 重试,默认再尝试一次。
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
import { ai } from '@h-ai/ai'
|
|
244
|
+
import { z } from 'zod'
|
|
245
|
+
|
|
246
|
+
const result = await ai.llm.generateObject({
|
|
247
|
+
schema: z.object({ intent: z.enum(['question', 'request']) }), // 定义允许的分类。
|
|
248
|
+
messages: [{ role: 'user', content: '如何部署?' }], // 输入待分类文本。
|
|
249
|
+
responseFormat: 'json_object', // 用于只提供通用 JSON 的 Chat 网关。
|
|
250
|
+
})
|
|
251
|
+
if (result.success) process.stdout.write(result.data.intent) // 示例输出 question。
|
|
252
|
+
```
|
|
241
253
|
|
|
242
254
|
## A2A
|
|
243
255
|
|