@kanyun-ai-infra/agenthub 0.1.1 → 0.2.0

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 CHANGED
@@ -1,51 +1,54 @@
1
1
  # @kanyun-ai-infra/agenthub
2
2
 
3
- Typed TypeScript client for the **agenthub Control Plane API**.
3
+ 用于 **agenthub Control Plane API** 的类型化 TypeScript 客户端。
4
4
 
5
- It talks directly to the agenthub Control Plane and is meant for backend
6
- services, CI, and tooling that drive the
7
- `project → workload → revision → session` lifecycle programmatically.
5
+ 它直接调用 agenthub Control Plane,适合后端服务、CI 和工具以编程方式驱动
6
+ `project -> workload -> revision -> session` 生命周期。
8
7
 
9
- Two surfaces are involved:
8
+ 接入时会遇到两个入口:
10
9
 
11
- | Surface | URL | Audience |
10
+ | 入口 | URL | 用途 |
12
11
  | --- | --- | --- |
13
- | **Control Plane API** | `https://agenthub-plane.zhenguanyu.com` | This SDK / your services — pass it as `controlPlaneUrl`. |
14
- | **Admin portal** | `https://agenthub.zhenguanyu.com` | Humans who publish and manage agents — and where you **issue an API token**. |
12
+ | **Control Plane API** | `https://agenthub-plane.zhenguanyu.com` | SDK / 你的服务调用。作为 `controlPlaneUrl` 传入。 |
13
+ | **管理门户** | `https://agenthub.zhenguanyu.com` | 人工发布和管理 agent,并在这里**签发 API token**。 |
15
14
 
16
- The two use different token audiences: a portal session token will **not** work
17
- against the Control Plane, and vice versa. Always pair the platform-api token
18
- issued from the portal with the `agenthub-plane` Control Plane URL.
15
+ 两者使用不同的 token audience:Portal 登录态 token 不能调用 Control Plane,反过来也一样。
16
+ 请始终把管理门户签发的 platform-api token 和 `agenthub-plane` Control Plane URL 配套使用。
19
17
 
20
- ## Install
18
+ ## 安装
21
19
 
22
20
  ```bash
23
21
  pnpm add @kanyun-ai-infra/agenthub
24
- # or: npm i @kanyun-ai-infra/agenthub
22
+ # 或:npm i @kanyun-ai-infra/agenthub
25
23
  ```
26
24
 
27
- Requires Node 18+ (uses the global `fetch`).
25
+ 需要 Node 18+,因为 SDK 使用全局 `fetch`。
28
26
 
29
- ## Quickstart
27
+ 如果调用方是 Java、Python、Go 或 Shell,请优先看 raw HTTP 指南和 REST 参考:
28
+ [`docs/user-guide/agenthub-http-quickstart.md`](../../docs/user-guide/agenthub-http-quickstart.md),
29
+ [`docs/user-guide/agenthub-rest-api.md`](../../docs/user-guide/agenthub-rest-api.md)。
30
+
31
+ ## 快速开始
30
32
 
31
33
  ```ts
32
34
  import { PilotPlatformClient } from "@kanyun-ai-infra/agenthub";
33
35
 
34
36
  const agenthub = new PilotPlatformClient({
35
37
  controlPlaneUrl: "https://agenthub-plane.zhenguanyu.com",
36
- token: process.env.PILOT_TOKEN, // platform-api token from the admin portal
38
+ token: process.env.PILOT_TOKEN, // 管理门户签发的 platform-api token
37
39
  });
38
40
 
39
- // 1. Project — the tenant/root grouping. The default runtime template lets
40
- // callers publish revisions without picking one each time (see below).
41
+ // 1. Project:租户 / 根分组。默认 runtime template 让调用方发布
42
+ // Revision 时不必每次手选模板。
41
43
  const project = await agenthub.projects.create({
42
44
  slug: "acme",
43
45
  displayName: "Acme",
44
46
  defaultRuntimeTemplateRefName: "pilot-v2-pod-agent",
45
47
  });
46
48
 
47
- // 2. Workload — a runnable agent/app in the project
48
- await agenthub.workloads.create({
49
+ // 2. Agent:Project 下一个可运行的 agent/app
50
+ // (`agents` 是 `workloads` 的别名,下文「术语别名」有说明)
51
+ await agenthub.agents.create({
49
52
  projectId: project.id,
50
53
  slug: "support-bot",
51
54
  displayName: "Support Bot",
@@ -56,11 +59,12 @@ await agenthub.workloads.create({
56
59
  },
57
60
  });
58
61
 
59
- // 3. Revision — an immutable published version. Runtime source is inherited
60
- // from the project default; override per revision with `runtime.profileRef`.
61
- const revision = await agenthub.workloads.publishRevision({
62
+ // 3. Version:Agent 的不可变发布版本(`publishVersion` 是 `publishRevision`
63
+ // 的别名)。Runtime source 默认继承 Project default;要按版本覆盖传
64
+ // `runtime.profileRef`。
65
+ const version = await agenthub.agents.publishVersion({
62
66
  projectId: project.id,
63
- workloadSlug: "support-bot",
67
+ agentSlug: "support-bot",
64
68
  version: "v1",
65
69
  workerContract: { kind: "managed_agent" },
66
70
  setDefault: true,
@@ -70,79 +74,103 @@ const revision = await agenthub.workloads.publishRevision({
70
74
  },
71
75
  });
72
76
 
73
- // 4. Session — a runtime allocation against the default (or a specific) revision
77
+ // 4. Session:基于默认 Version 或指定 Version 分配一次运行时
78
+ // (Session 接口仍用 `workloadId` 字段 —— 核心模型保持 workload 命名)
74
79
  const session = await agenthub.sessions.create({
75
80
  projectId: project.id,
76
- workloadId: revision.workloadId,
81
+ workloadId: version.workloadId,
77
82
  });
78
83
 
79
- const ready = await agenthub.sessions.wait(session.sessionId); // resolves when status === "ready"
84
+ const ready = await agenthub.sessions.wait(session.sessionId); // status === "ready" 时返回
80
85
  ```
81
86
 
82
- ## Client configuration
87
+ ## Client 配置
83
88
 
84
89
  `new PilotPlatformClient(config)`
85
90
 
86
- | Option | Required | Description |
91
+ | 选项 | 必填 | 说明 |
87
92
  | --- | --- | --- |
88
- | `controlPlaneUrl` | yes¹ | Control Plane origin. Relative request paths are composed under it; cross-origin paths are rejected before the token is sent. |
89
- | `token` | yes¹ | Platform-api token. Sent as `Authorization: Bearer <token>` on every request. |
90
- | `fetch` | no | Custom `fetch` implementation (defaults to the global). |
91
- | `signal` | no | Default `AbortSignal` applied to every request. |
92
- | `defaultHeaders` | no | Extra headers merged into every request. |
93
- | `userAgent` | no | Overrides the default `@kanyun-ai-infra/agenthub/<version>` UA. |
94
- | `pilotApiVersion` | no | Pins the `x-pilot-api-version` header (defaults to the v2 wire version). |
93
+ | `controlPlaneUrl` | 是¹ | Control Plane 源地址。相对路径会拼到它下面;跨 origin 路径会在发 token 前被拒绝。 |
94
+ | `token` | 是¹ | Platform-api token。每个请求都会作为 `Authorization: Bearer <token>` 发送。 |
95
+ | `fetch` | 否 | 自定义 `fetch` 实现,默认使用全局 `fetch`。 |
96
+ | `signal` | 否 | 应用于每个请求的默认 `AbortSignal`。 |
97
+ | `defaultHeaders` | 否 | 合并到每个请求的额外 header。 |
98
+ | `userAgent` | 否 | 覆盖默认 `@kanyun-ai-infra/agenthub/<version>` UA。 |
99
+ | `pilotApiVersion` | 否 | 固定 `x-pilot-api-version` header,默认使用 v2 wire version。 |
95
100
 
96
- ¹ `controlPlaneUrl` falls back to `PILOT_CONTROL_PLANE_URL` then
97
- `KANYUN_PILOT_CONTROL_PLANE_URL`; `token` falls back to `PILOT_TOKEN`. Missing
98
- either produces a typed SDK error before any request is sent.
101
+ ¹ `controlPlaneUrl` 会依次回退到 `PILOT_CONTROL_PLANE_URL`、
102
+ `KANYUN_PILOT_CONTROL_PLANE_URL`;`token` 会回退到 `PILOT_TOKEN`。任意一项缺失时,
103
+ SDK 会在发送请求前抛出类型化错误。
99
104
 
100
- ### Getting a token
105
+ ### 获取 token
101
106
 
102
- Sign in to the **admin portal** at <https://agenthub.zhenguanyu.com> and issue a
103
- **platform-api token**. That token is scoped to the Control Plane API
104
- (`agenthub-plane.zhenguanyu.com`); store it as `PILOT_TOKEN` (or pass it as
105
- `token`). Tokens are bearer credentials — keep them out of source control and
106
- rotate from the portal if leaked.
107
+ 登录 **管理门户** <https://agenthub.zhenguanyu.com> 并签发 **platform-api token**。
108
+ 该 token 的作用域是 Control Plane API(`agenthub-plane.zhenguanyu.com`);可以存为
109
+ `PILOT_TOKEN`,也可以显式传给 `token`。Token 是 Bearer 凭据,请不要提交到代码仓库;
110
+ 泄露后需要在门户里轮换。
107
111
 
108
- ## Core model
112
+ ## 核心模型
109
113
 
110
114
  ```text
111
- Project → Workload → Revision → Session
115
+ Project -> Workload -> Revision -> Session
112
116
  ```
113
117
 
114
- - **Project** — tenant/root grouping; owns workloads and runtime templates.
115
- - **Workload** — a logical runnable app. `kind` is `"managed_agent"` (platform
116
- runs the agent loop from `model` + `systemPrompt`) or `"self_managed"` (you
117
- ship the worker).
118
- - **Revision** — an immutable published version of a workload, bound to one
119
- runtime source. Mark one as the project/workload default with `setDefault`.
120
- - **Session** — a startup/runtime allocation against a revision.
118
+ - **Project**:租户 / 根分组,拥有 workloads 和 runtime templates。
119
+ - **Workload**:一个逻辑可运行应用。`kind` 是 `"managed_agent"`(平台基于
120
+ `model` + `systemPrompt` 运行 agent loop)或 `"self_managed"`(你自己提供 worker)。
121
+ - **Revision**:Workload 的不可变发布版本,绑定一个 runtime source。用 `setDefault`
122
+ 标记 project/workload 默认版本。
123
+ - **Session**:基于某个 Revision 发起的一次 startup/runtime allocation。
124
+
125
+ Workloads 和 runtime templates 都是 **project-scoped**。Revision 必须在同一个 Project
126
+ 内解析到 Workload 和 runtime source;唯一例外是下文的 platform-shared templates。
127
+
128
+ ### 术语别名(agent / version)
129
+
130
+ 为降低理解成本,SDK 为核心概念提供了一组**别名**——语义完全一致,只是更口语化:
131
+
132
+ | 规范名(核心模型) | 友好别名 | 说明 |
133
+ | --- | --- | --- |
134
+ | `agenthub.workloads` | `agenthub.agents` | **同一个资源实例**,方法完全一致。 |
135
+ | `workloads.publishRevision({ workloadSlug })` | `agents.publishVersion({ agentSlug })` | 同一个调用;友好版用 `agentSlug`,内部映射回 `workloadSlug` 后发出,wire body 完全一致。 |
136
+ | 概念 “Workload” / “Revision” | “Agent” / “Version” | 仅命名差异。 |
137
+
138
+ `agentSlug` 仅在 `publishVersion` 上;`publishRevision` 仍用 `workloadSlug`。
139
+ `applyRevisionManifest` 两个拼写都接受(同时给出时 `workloadSlug` 优先)。
140
+
141
+ 别名是**附加糖**:`workloads` / `publishRevision` / `workloadSlug` 一直保留,行为不变;
142
+ 返回结果的字段名(`workloadId` / `revisionId`)以及 `sessions.create({ workloadId })`
143
+ 仍沿用核心模型命名。挑读起来顺的那套写即可。
121
144
 
122
- Workloads and runtime templates are **project-scoped**. A revision must resolve
123
- its workload and runtime source inside the same project (the one exception is
124
- platform-shared templates, below).
145
+ ```ts
146
+ // 下面两段完全等价
147
+ await agenthub.agents.publishVersion({ projectId, agentSlug: "support-bot", version: "v1", workerContract: { kind: "managed_agent" } });
148
+ await agenthub.workloads.publishRevision({ projectId, workloadSlug: "support-bot", version: "v1", workerContract: { kind: "managed_agent" } });
149
+ ```
125
150
 
126
- ## API reference
151
+ ## API 参考
127
152
 
128
153
  ### `agenthub.projects`
129
154
 
130
- | Method | Description |
155
+ | 方法 | 说明 |
131
156
  | --- | --- |
132
- | `create({ slug, displayName, description?, defaultRuntimeTemplateRefName? })` | Create a project. Duplicate slug → `409 PROJECT_SLUG_CONFLICT`. |
133
- | `list()` | List projects in the token's effective scope. |
134
- | `get(projectId)` | Fetch one project. |
157
+ | `create({ slug, displayName, description?, defaultRuntimeTemplateRefName? })` | 创建 Project。slug 重复时返回 `409 PROJECT_SLUG_CONFLICT`。 |
158
+ | `list()` | 列出 token 有效 scope 内的 Project。 |
159
+ | `get(projectId)` | 查询单个 Project。 |
160
+
161
+ ### `agenthub.workloads`(别名 `agenthub.agents`)
135
162
 
136
- ### `agenthub.workloads`
163
+ > `agenthub.agents` 与 `agenthub.workloads` 是同一个对象,下表方法两边都能调。
137
164
 
138
- | Method | Description |
165
+ | 方法 | 说明 |
139
166
  | --- | --- |
140
- | `create(req, { dryRun? })` | Create a workload from structured input. Returns `{ mode, status, workloadId?, workload }`. |
141
- | `publishRevision(req, { dryRun? })` | Publish a revision. Returns `{ mode, status, workloadId, revisionId?, runtimeTemplateId, resolved }`. |
142
- | `applyManifest({ projectId, manifest, dryRun? })` | Advanced/GitOps: apply a raw workload manifest. |
143
- | `applyRevisionManifest({ projectId, workloadSlug, manifest, dryRun? })` | Advanced/GitOps: apply a raw revision manifest. |
167
+ | `create(req, { dryRun? })` | 用结构化输入创建 Workload。返回 `{ mode, status, workloadId?, workload }`。 |
168
+ | `publishRevision(req, { dryRun? })` | 发布 Revision。返回 `{ mode, status, workloadId, revisionId?, runtimeTemplateId, resolved }`。 |
169
+ | `publishVersion(req, { dryRun? })` | `publishRevision` 的友好别名;`req` 用 `agentSlug` 代替 `workloadSlug`。返回结构与 `publishRevision` **完全相同**(字段仍是 `workloadId` / `revisionId`,不会改名为 `agentId` / `versionId`)。 |
170
+ | `applyManifest({ projectId, manifest, dryRun? })` | 高级 / GitOps:apply raw workload manifest。 |
171
+ | `applyRevisionManifest({ projectId, workloadSlug \| agentSlug, manifest, dryRun? })` | 高级 / GitOps:apply raw revision manifest。两个 slug 拼写都接受,同时给出时 `workloadSlug` 优先。 |
144
172
 
145
- `req` for `create`:
173
+ `create` 的 `req`:
146
174
 
147
175
  ```ts
148
176
  {
@@ -162,7 +190,7 @@ platform-shared templates, below).
162
190
  }
163
191
  ```
164
192
 
165
- `req` for `publishRevision`:
193
+ `publishRevision` 的 `req`:
166
194
 
167
195
  ```ts
168
196
  {
@@ -178,36 +206,129 @@ platform-shared templates, below).
178
206
  }
179
207
  ```
180
208
 
181
- `manifest` (for the `apply*` methods) accepts a manifest object, `{ yaml }`, or
182
- `{ json }`.
209
+ `apply*` 方法里的 `manifest` 可以是 manifest 对象、`{ yaml }` 或 `{ json }`。
210
+
211
+ ### Agent 配置项总览
212
+
213
+ managed_agent 的配置可写在两处,语义不同(**Version 快照优先级高于 Workload 默认**):
214
+
215
+ | 写在哪 | 字段入口 | 性质 |
216
+ | --- | --- | --- |
217
+ | `agents.create({ defaults })` | Workload 级默认 | 可变;作为新版本的起始模板,也是没快照时的兜底。 |
218
+ | `agents.publishVersion({ managedAgentProfileSnapshot })` | Version 级不可变快照 | **session 运行时实际解析的值**;按版本钉死,隔离后续对 defaults 的修改。 |
219
+
220
+ > 想要「版本钉死 + 隔离」的真实 agent 配置就写在 `managedAgentProfileSnapshot`;
221
+ > `defaults` 当作 workload 级默认模板。两层字段基本一致(下表)。
222
+
223
+ #### 画像字段(`defaults` 与 `managedAgentProfileSnapshot` 通用)
224
+
225
+ | 字段 | 类型 | 说明 |
226
+ | --- | --- | --- |
227
+ | `model` | `string` | 模型 id 或别名(见 [模型](#模型))。 |
228
+ | `systemPrompt` | `string` | 系统提示词,≤ 32768 字符。 |
229
+ | `enabledSkills` | `EnabledSkillEntry[]` | 启用的 Rush skills。 |
230
+ | `enabledMcpServers` | `EnabledMcpEntry[]` | 启用的 MCP server,每个可带 `toolFilter` / `extraConfigValues` / `disabled`。 |
231
+ | `configValues` | `Record<string, string>` | 配置 / env 键值(有保留 key 与长度限制)。 |
232
+ | `agentOptions` | `AgentOptions` | 高级运行选项,见下表。 |
233
+
234
+ `defaults` 额外接受 `workerContract`(workload 级默认 worker 契约);
235
+ `managedAgentProfileSnapshot` 仅当 `workerContract.kind === "managed_agent"` 时允许。
236
+
237
+ #### `agentOptions`(仅 managed_agent;**只能收紧 / 限额**)
238
+
239
+ | 字段 | 约束 | 说明 |
240
+ | --- | --- | --- |
241
+ | `maxTurns` | 整数 1–200 | 最大 agentic 轮次。 |
242
+ | `maxThinkingTokens` | 整数 1–60000 | 扩展思考 token 预算。 |
243
+ | `maxBudgetUsd` | 0–50 | 单次运行花费上限(USD)。 |
244
+ | `effort` | `"low"|"medium"|"high"|"max"` | 推理强度。 |
245
+ | `allowedTools` | `string[]`,≤ 64 | 工具白名单;与平台基线**取交集**(只会更窄)。 |
246
+ | `disallowedTools` | `string[]`,≤ 64 | 工具黑名单;叠加平台黑名单,**不能移除**平台守卫工具。支持有界 arg matcher(如 `Bash(rm:*)`),禁止全通配 `(*)` / `(*:*)`。 |
247
+
248
+ 出于跨租户安全,`agentOptions` 故意**不开放** `permissionMode` / `env` / `mcpServers` / `systemPrompt`
249
+ 替换 / `hooks` / `plugins` / 原始 `sdkOptions` 等可能越权或逃逸 sandbox 的字段(见 issue #840)。
250
+
251
+ #### Version 级其他字段(`publishVersion` / `publishRevision`,非画像)
252
+
253
+ | 字段 | 说明 |
254
+ | --- | --- |
255
+ | `workerContract` | `{ kind: "managed_agent" | "self_managed"; name?; version? }`,必填。 |
256
+ | `setDefault` | 是否设为默认版本,默认 `true`。 |
257
+ | `startup` | 启动门禁 `{ requiredGates?: string[]; optionalGates?: string[] }`。 |
258
+ | `runtime` | 运行时环境 `{ profileRef?; environment?; overrides? }`,省略则继承 project 默认。 |
259
+ | `configValues` | version 级配置 / env 键值。 |
260
+
261
+ #### Workload 级其他字段(`create`)
262
+
263
+ | 字段 | 说明 |
264
+ | --- | --- |
265
+ | `ui` | Default-UI 展示提示(`WorkloadManifestUiHint`)。 |
266
+ | `defaults.workerContract` | workload 级默认 worker 契约。 |
183
267
 
184
268
  ### `agenthub.sessions`
185
269
 
186
- | Method | Description |
270
+ | 方法 | 说明 |
271
+ | --- | --- |
272
+ | `create({ projectId, workloadId, revisionId?, configValues?, metadata?, idempotencyKey?, resources?, ... })` | 启动 Session。省略 `revisionId` 时使用 Workload 默认 Revision。`resources` 注入 Model A 只读输入文件(见下)。返回 `{ sessionId, status }`。 |
273
+ | `get(sessionId)` | 读取 Session 快照(`{ session: { id, status, ... } }`)。 |
274
+ | `wait(sessionId, { intervalMs?, timeoutMs?, signal? })` | 轮询到 `status === "ready"`;遇到 `failed` 或超时会抛错。 |
275
+
276
+ Session `status` 取值为 `created`、`provisioning`、`starting`、`ready`、`failed`。
277
+
278
+ ### `agenthub.files`
279
+
280
+ | 方法 | 说明 |
187
281
  | --- | --- |
188
- | `create({ projectId, workloadId, revisionId?, configValues?, metadata?, idempotencyKey?, ... })` | Start a session. Omitting `revisionId` uses the workload's default revision. Returns `{ sessionId, status }`. |
189
- | `get(sessionId)` | Snapshot the session (`{ session: { id, status, ... } }`). |
190
- | `wait(sessionId, { intervalMs?, timeoutMs?, signal? })` | Poll until `status === "ready"`; throws on `failed` or timeout. |
282
+ | `upload({ projectId, file, filename?, contentType? })` | 上传单个文件,返回 `{ ossUrl, url, filename, size, mediaType, mimeType }`。`file` 接受 `Blob` / `File` / `Uint8Array` / `ArrayBuffer`;非具名 `File` 时必须传 `filename`。 |
283
+
284
+ 文件落在 `pilot/attachments/<projectId>/`,与 Session 资源 scope 校验同一 keyspace —— 为某 Project
285
+ 上传的文件无法挂到另一个 Project 的 Session。`url` 是 ~1h 的 presigned GET(仅预览用);
286
+ 要持久引用的是 `ossUrl`。
287
+
288
+ #### Model A 只读输入文件(session resources)
289
+
290
+ 把文件作为 **Session 级只读输入**挂进 sandbox 的 `/workspace/.session/inputs/`(每次
291
+ provision / revival 重新物化),用 `files.upload` + `sessions.create({ resources })`:
292
+
293
+ ```ts
294
+ const up = await agenthub.files.upload({
295
+ projectId,
296
+ file: new Blob([await fs.promises.readFile("spec.md")]),
297
+ filename: "spec.md",
298
+ });
299
+
300
+ // `up` 是 SessionFileResource 的超集,只多一个预览用的 `url`;解构掉它,
301
+ // 剩下的 `meta`(ossUrl/filename/size/mediaType/mimeType)正是一个资源条目。
302
+ const { url, ...meta } = up;
303
+
304
+ const { sessionId } = await agenthub.sessions.create({
305
+ projectId,
306
+ workloadId,
307
+ resources: {
308
+ version: "v1",
309
+ files: [{ ...meta, mountPath: "docs/spec.md" }], // mountPath 可省略 → 用文件名
310
+ },
311
+ });
312
+ // agent 在 /workspace/.session/inputs/docs/spec.md 只读看到该文件
313
+ ```
191
314
 
192
- Session `status` is one of `created`, `provisioning`, `starting`, `ready`,
193
- `failed`.
315
+ 约束:每 Session ≤ 20 个文件;`mountPath` 必须是 `.session/inputs/` 下的相对子路径
316
+ (拒绝绝对路径与 `..`);只读。
194
317
 
195
- ## Runtime templates
318
+ ## Runtime template
196
319
 
197
- A managed-agent revision runs on a **runtime template** (a registered runtime
198
- source). The Control Plane resolves it in this order:
320
+ managed-agent Revision 运行在一个 **runtime template**(已注册的 runtime source)上。
321
+ Control Plane 按以下顺序解析:
199
322
 
200
- 1. revision `runtime.profileRef` (structured) / `spec.runtime.profileRef`
201
- 2. revision `spec.runtimeTemplateRef` (manifest)
202
- 3. workload defaults `spec.defaults.runtimeTemplateRef` (manifest)
323
+ 1. revision `runtime.profileRef`(structured)/ `spec.runtime.profileRef`
324
+ 2. revision `spec.runtimeTemplateRef`(manifest)
325
+ 3. workload defaults `spec.defaults.runtimeTemplateRef`(manifest)
203
326
  4. project `defaultRuntimeTemplateRefName`
204
327
 
205
- If none resolves → `PROJECT_DEFAULT_RUNTIME_MISSING`. If the named template does
206
- not exist in the project (or as a platform-shared template) →
207
- `RUNTIME_TEMPLATE_NOT_FOUND`.
328
+ 如果都解析不到,返回 `PROJECT_DEFAULT_RUNTIME_MISSING`。如果指定模板在当前 Project
329
+ 或 platform-shared templates 中不存在,返回 `RUNTIME_TEMPLATE_NOT_FOUND`。
208
330
 
209
- For the happy path, give the project a default at creation so callers never pick
210
- a template:
331
+ 主路径建议在创建 Project 时设置默认模板,这样调用方发布 Revision 时不需要手选:
211
332
 
212
333
  ```ts
213
334
  await agenthub.projects.create({
@@ -217,21 +338,20 @@ await agenthub.projects.create({
217
338
  });
218
339
  ```
219
340
 
220
- Otherwise select one explicitly per revision with
221
- `runtime: { profileRef: { name: "..." } }`.
341
+ 否则需要在每个 Revision 上显式指定:
342
+ `runtime: { profileRef: { name: "..." } }`。
222
343
 
223
- **Platform-shared templates.** Templates owned by the Platform Default project
224
- (e.g. `pilot-v2-pod-agent`) are shared infrastructure: the lookup falls back to
225
- Platform Default when the name is not found in the caller's project, so any
226
- project's revision may reference them by name. `echo-bot` is a built-in
227
- echo-only template useful for smoke tests — it does **not** run an LLM.
344
+ **Platform-shared templates。** Platform Default project 拥有的模板(例如
345
+ `pilot-v2-pod-agent`)是共享基础设施:当调用方 Project 内找不到同名模板时,解析会回退到
346
+ Platform Default,因此任意 Project 的 Revision 都可以按名称引用它们。`echo-bot`
347
+ 是内置 echo-only 模板,适合 smoke test;它**不会**运行 LLM。
228
348
 
229
- ## Models
349
+ ## 模型
230
350
 
231
- `model` accepts a full id (`claude-opus-4-7`, `claude-sonnet-4-6`,
232
- `claude-haiku-4-5`) or a legacy alias that maps to one:
351
+ `model` 接受完整 id(`claude-opus-4-7`、`claude-sonnet-4-6`、`claude-haiku-4-5`),
352
+ 也接受会映射到完整 id 的历史别名:
233
353
 
234
- | Alias | Resolves to |
354
+ | Alias | 解析为 |
235
355
  | --- | --- |
236
356
  | `opus` | `claude-opus-4-7` |
237
357
  | `sonnet` | `claude-sonnet-4-6` |
@@ -239,15 +359,14 @@ echo-only template useful for smoke tests — it does **not** run an LLM.
239
359
 
240
360
  ## Dry runs
241
361
 
242
- `workloads.create`, `publishRevision`, and the `apply*` methods accept
243
- `{ dryRun: true }`. A dry run validates and resolves the request without
244
- persisting, returning `mode: "dry_run"` and a `would_create` / `would_update`
245
- status. Use it to verify a runtime template resolves before publishing for real.
362
+ `workloads.create`、`publishRevision` 和 `apply*` 方法都接受 `{ dryRun: true }`。
363
+ dry run 会校验并解析请求,但不持久化;返回 `mode: "dry_run"` 和
364
+ `would_create` / `would_update` 状态;Revision 已存在且内容一致时可能返回
365
+ `existing`。正式发布前可以用它确认 runtime template 能正确解析。
246
366
 
247
- ## Errors
367
+ ## 错误
248
368
 
249
- All API failures throw a typed error carrying `status`, `code`, and
250
- `requestId`:
369
+ 所有 API 请求失败都会抛出类型化错误,错误对象带 `status`、`code` 和 `requestId`:
251
370
 
252
371
  | Class | HTTP |
253
372
  | --- | --- |
@@ -255,7 +374,7 @@ All API failures throw a typed error carrying `status`, `code`, and
255
374
  | `PilotPlatformForbiddenError` | 403 |
256
375
  | `PilotPlatformNotFoundError` | 404 |
257
376
  | `PilotPlatformServerError` | 5xx |
258
- | `PilotPlatformApiError` | base class for the above |
377
+ | `PilotPlatformApiError` | 上述错误的基类 |
259
378
 
260
379
  ```ts
261
380
  import { PilotPlatformNotFoundError } from "@kanyun-ai-infra/agenthub";