@kanyun-ai-infra/agenthub 0.1.0 → 0.1.1
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 +242 -17
- package/package.json +12 -15
package/README.md
CHANGED
|
@@ -1,24 +1,54 @@
|
|
|
1
1
|
# @kanyun-ai-infra/agenthub
|
|
2
2
|
|
|
3
|
-
Typed
|
|
3
|
+
Typed TypeScript client for the **agenthub Control Plane API**.
|
|
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.
|
|
8
|
+
|
|
9
|
+
Two surfaces are involved:
|
|
10
|
+
|
|
11
|
+
| Surface | URL | Audience |
|
|
12
|
+
| --- | --- | --- |
|
|
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**. |
|
|
15
|
+
|
|
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.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm add @kanyun-ai-infra/agenthub
|
|
24
|
+
# or: npm i @kanyun-ai-infra/agenthub
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Requires Node 18+ (uses the global `fetch`).
|
|
28
|
+
|
|
29
|
+
## Quickstart
|
|
4
30
|
|
|
5
31
|
```ts
|
|
6
32
|
import { PilotPlatformClient } from "@kanyun-ai-infra/agenthub";
|
|
7
33
|
|
|
8
|
-
const
|
|
9
|
-
controlPlaneUrl: "https://
|
|
10
|
-
token: process.env.PILOT_TOKEN,
|
|
34
|
+
const agenthub = new PilotPlatformClient({
|
|
35
|
+
controlPlaneUrl: "https://agenthub-plane.zhenguanyu.com",
|
|
36
|
+
token: process.env.PILOT_TOKEN, // platform-api token from the admin portal
|
|
11
37
|
});
|
|
12
38
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
39
|
+
// 1. Project — the tenant/root grouping. The default runtime template lets
|
|
40
|
+
// callers publish revisions without picking one each time (see below).
|
|
41
|
+
const project = await agenthub.projects.create({
|
|
42
|
+
slug: "acme",
|
|
43
|
+
displayName: "Acme",
|
|
44
|
+
defaultRuntimeTemplateRefName: "pilot-v2-pod-agent",
|
|
16
45
|
});
|
|
17
46
|
|
|
18
|
-
|
|
47
|
+
// 2. Workload — a runnable agent/app in the project
|
|
48
|
+
await agenthub.workloads.create({
|
|
19
49
|
projectId: project.id,
|
|
20
|
-
slug: "
|
|
21
|
-
displayName: "
|
|
50
|
+
slug: "support-bot",
|
|
51
|
+
displayName: "Support Bot",
|
|
22
52
|
kind: "managed_agent",
|
|
23
53
|
defaults: {
|
|
24
54
|
model: "claude-opus-4-7",
|
|
@@ -26,21 +56,216 @@ await pilot.workloads.create({
|
|
|
26
56
|
},
|
|
27
57
|
});
|
|
28
58
|
|
|
29
|
-
|
|
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({
|
|
30
62
|
projectId: project.id,
|
|
31
|
-
workloadSlug: "
|
|
63
|
+
workloadSlug: "support-bot",
|
|
32
64
|
version: "v1",
|
|
33
65
|
workerContract: { kind: "managed_agent" },
|
|
66
|
+
setDefault: true,
|
|
67
|
+
managedAgentProfileSnapshot: {
|
|
68
|
+
model: "claude-opus-4-7",
|
|
69
|
+
systemPrompt: "You are the Acme support agent.",
|
|
70
|
+
},
|
|
34
71
|
});
|
|
35
72
|
|
|
36
|
-
|
|
73
|
+
// 4. Session — a runtime allocation against the default (or a specific) revision
|
|
74
|
+
const session = await agenthub.sessions.create({
|
|
37
75
|
projectId: project.id,
|
|
38
76
|
workloadId: revision.workloadId,
|
|
39
77
|
});
|
|
40
78
|
|
|
41
|
-
await
|
|
79
|
+
const ready = await agenthub.sessions.wait(session.sessionId); // resolves when status === "ready"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Client configuration
|
|
83
|
+
|
|
84
|
+
`new PilotPlatformClient(config)`
|
|
85
|
+
|
|
86
|
+
| Option | Required | Description |
|
|
87
|
+
| --- | --- | --- |
|
|
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). |
|
|
95
|
+
|
|
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.
|
|
99
|
+
|
|
100
|
+
### Getting a token
|
|
101
|
+
|
|
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
|
+
|
|
108
|
+
## Core model
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
Project → Workload → Revision → Session
|
|
112
|
+
```
|
|
113
|
+
|
|
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.
|
|
121
|
+
|
|
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).
|
|
125
|
+
|
|
126
|
+
## API reference
|
|
127
|
+
|
|
128
|
+
### `agenthub.projects`
|
|
129
|
+
|
|
130
|
+
| Method | Description |
|
|
131
|
+
| --- | --- |
|
|
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. |
|
|
135
|
+
|
|
136
|
+
### `agenthub.workloads`
|
|
137
|
+
|
|
138
|
+
| Method | Description |
|
|
139
|
+
| --- | --- |
|
|
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. |
|
|
144
|
+
|
|
145
|
+
`req` for `create`:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
{
|
|
149
|
+
projectId: string;
|
|
150
|
+
slug: string;
|
|
151
|
+
displayName: string;
|
|
152
|
+
kind: "managed_agent" | "self_managed";
|
|
153
|
+
defaults?: {
|
|
154
|
+
model?: string;
|
|
155
|
+
systemPrompt?: string;
|
|
156
|
+
workerContract?: { name?: string; version?: string };
|
|
157
|
+
configValues?: Record<string, string>;
|
|
158
|
+
enabledSkills?: EnabledSkill[];
|
|
159
|
+
enabledMcpServers?: EnabledMcpServer[];
|
|
160
|
+
};
|
|
161
|
+
ui?: { /* Default-UI hints */ };
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
`req` for `publishRevision`:
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
{
|
|
169
|
+
projectId: string;
|
|
170
|
+
workloadSlug: string;
|
|
171
|
+
version: string;
|
|
172
|
+
workerContract: { kind: "managed_agent" | "self_managed"; name?: string; version?: string };
|
|
173
|
+
runtime?: { profileRef?: { name: string }; environment?: ...; overrides?: ... };
|
|
174
|
+
setDefault?: boolean;
|
|
175
|
+
startup?: { requiredGates?: string[]; optionalGates?: string[] };
|
|
176
|
+
configValues?: Record<string, string>;
|
|
177
|
+
managedAgentProfileSnapshot?: { model?: string; systemPrompt?: string; enabledSkills?: ...; enabledMcpServers?: ... };
|
|
178
|
+
}
|
|
42
179
|
```
|
|
43
180
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
181
|
+
`manifest` (for the `apply*` methods) accepts a manifest object, `{ yaml }`, or
|
|
182
|
+
`{ json }`.
|
|
183
|
+
|
|
184
|
+
### `agenthub.sessions`
|
|
185
|
+
|
|
186
|
+
| Method | Description |
|
|
187
|
+
| --- | --- |
|
|
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. |
|
|
191
|
+
|
|
192
|
+
Session `status` is one of `created`, `provisioning`, `starting`, `ready`,
|
|
193
|
+
`failed`.
|
|
194
|
+
|
|
195
|
+
## Runtime templates
|
|
196
|
+
|
|
197
|
+
A managed-agent revision runs on a **runtime template** (a registered runtime
|
|
198
|
+
source). The Control Plane resolves it in this order:
|
|
199
|
+
|
|
200
|
+
1. revision `runtime.profileRef` (structured) / `spec.runtime.profileRef`
|
|
201
|
+
2. revision `spec.runtimeTemplateRef` (manifest)
|
|
202
|
+
3. workload defaults `spec.defaults.runtimeTemplateRef` (manifest)
|
|
203
|
+
4. project `defaultRuntimeTemplateRefName`
|
|
204
|
+
|
|
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`.
|
|
208
|
+
|
|
209
|
+
For the happy path, give the project a default at creation so callers never pick
|
|
210
|
+
a template:
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
await agenthub.projects.create({
|
|
214
|
+
slug: "acme",
|
|
215
|
+
displayName: "Acme",
|
|
216
|
+
defaultRuntimeTemplateRefName: "pilot-v2-pod-agent",
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Otherwise select one explicitly per revision with
|
|
221
|
+
`runtime: { profileRef: { name: "..." } }`.
|
|
222
|
+
|
|
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.
|
|
228
|
+
|
|
229
|
+
## Models
|
|
230
|
+
|
|
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:
|
|
233
|
+
|
|
234
|
+
| Alias | Resolves to |
|
|
235
|
+
| --- | --- |
|
|
236
|
+
| `opus` | `claude-opus-4-7` |
|
|
237
|
+
| `sonnet` | `claude-sonnet-4-6` |
|
|
238
|
+
| `haiku` | `claude-haiku-4-5` |
|
|
239
|
+
|
|
240
|
+
## Dry runs
|
|
241
|
+
|
|
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.
|
|
246
|
+
|
|
247
|
+
## Errors
|
|
248
|
+
|
|
249
|
+
All API failures throw a typed error carrying `status`, `code`, and
|
|
250
|
+
`requestId`:
|
|
251
|
+
|
|
252
|
+
| Class | HTTP |
|
|
253
|
+
| --- | --- |
|
|
254
|
+
| `PilotPlatformUnauthenticatedError` | 401 |
|
|
255
|
+
| `PilotPlatformForbiddenError` | 403 |
|
|
256
|
+
| `PilotPlatformNotFoundError` | 404 |
|
|
257
|
+
| `PilotPlatformServerError` | 5xx |
|
|
258
|
+
| `PilotPlatformApiError` | base class for the above |
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
import { PilotPlatformNotFoundError } from "@kanyun-ai-infra/agenthub";
|
|
262
|
+
|
|
263
|
+
try {
|
|
264
|
+
await agenthub.sessions.get(sessionId);
|
|
265
|
+
} catch (err) {
|
|
266
|
+
if (err instanceof PilotPlatformNotFoundError) {
|
|
267
|
+
// err.status === 404, err.code === "SESSION_NOT_FOUND"
|
|
268
|
+
}
|
|
269
|
+
throw err;
|
|
270
|
+
}
|
|
271
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kanyun-ai-infra/agenthub",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Typed TypeScript client for the Pilot v2 Control Plane API",
|
|
6
6
|
"exports": {
|
|
@@ -13,28 +13,25 @@
|
|
|
13
13
|
"main": "./dist/index.cjs",
|
|
14
14
|
"module": "./dist/index.js",
|
|
15
15
|
"types": "./dist/index.d.ts",
|
|
16
|
-
"files": [
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
16
|
+
"files": ["dist", "README.md"],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"check": "tsc --noEmit",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:coverage": "vitest run --coverage",
|
|
22
|
+
"dev": "tsup --watch"
|
|
23
|
+
},
|
|
20
24
|
"dependencies": {
|
|
21
25
|
"zod": "^3.24.0"
|
|
22
26
|
},
|
|
23
27
|
"devDependencies": {
|
|
28
|
+
"@pilot/contracts": "workspace:*",
|
|
24
29
|
"@vitest/coverage-v8": "^4.1.0",
|
|
25
30
|
"tsup": "^8.4.0",
|
|
26
31
|
"typescript": "^5.9.3",
|
|
27
|
-
"vitest": "^4.0.17"
|
|
28
|
-
"@pilot/contracts": "0.0.1"
|
|
32
|
+
"vitest": "^4.0.17"
|
|
29
33
|
},
|
|
30
34
|
"publishConfig": {
|
|
31
35
|
"access": "public"
|
|
32
|
-
},
|
|
33
|
-
"scripts": {
|
|
34
|
-
"build": "tsup",
|
|
35
|
-
"check": "tsc --noEmit",
|
|
36
|
-
"test": "vitest run",
|
|
37
|
-
"test:coverage": "vitest run --coverage",
|
|
38
|
-
"dev": "tsup --watch"
|
|
39
36
|
}
|
|
40
|
-
}
|
|
37
|
+
}
|