@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.
Files changed (2) hide show
  1. package/README.md +242 -17
  2. package/package.json +12 -15
package/README.md CHANGED
@@ -1,24 +1,54 @@
1
1
  # @kanyun-ai-infra/agenthub
2
2
 
3
- Typed SDK for the Pilot v2 Control Plane API.
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 pilot = new PilotPlatformClient({
9
- controlPlaneUrl: "https://pilot-control-plane.example.com",
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
- const project = await pilot.projects.create({
14
- slug: "acme-project",
15
- displayName: "Acme Project",
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
- await pilot.workloads.create({
47
+ // 2. Workload — a runnable agent/app in the project
48
+ await agenthub.workloads.create({
19
49
  projectId: project.id,
20
- slug: "acme-agent",
21
- displayName: "Acme Agent",
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
- const revision = await pilot.workloads.publishRevision({
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: "acme-agent",
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
- const session = await pilot.sessions.create({
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 pilot.sessions.wait(session.sessionId);
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
- This package talks directly to `apps/control-plane`. The legacy
45
- `@kanyun-ai-infra/pilot` package remains available for the portal/BFF
46
- `agents` and `runs` workflows.
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.0",
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
- "dist",
18
- "README.md"
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
+ }