@kanyun-ai-infra/agenthub 1.27.1 → 1.29.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/CHANGELOG.md +170 -0
- package/README.md +69 -5
- package/dist/index.cjs +3758 -3007
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +526 -6
- package/dist/index.d.ts +526 -6
- package/dist/index.js +5177 -4436
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/agenthub-sdk/SKILL.md +144 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,176 @@
|
|
|
2
2
|
|
|
3
3
|
本文件从 1.12.0 开始记录;更早的版本见 git 历史中的 `chore(agenthub-sdk): release X.Y.Z` 提交。
|
|
4
4
|
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
## 1.29.0
|
|
8
|
+
|
|
9
|
+
本版带上 1.28.0 之后合入 main 的公开面变化:凭据录入票据 `credentialEntryTickets`(#6007)、
|
|
10
|
+
统一凭据管理入口 `credentials.revoke`(#6008)、`evals.createRun` 与 `duration` / `usage`
|
|
11
|
+
grader(#5979)、回合耗时与价目成本读面及 `usage-update` 进度帧(#5978),以及候选构建读回的
|
|
12
|
+
随包文档(#5976)。全部为新增或文档,没有行为变化,也没有需要迁移的改动。
|
|
13
|
+
|
|
14
|
+
### 新增(主入口)
|
|
15
|
+
|
|
16
|
+
- `credentials.revoke(credentialRef, { mode?, reason? }, { signal? })`:项目密钥(`sec_*`)、
|
|
17
|
+
vault 凭据(`vcrd_*`)与模型服务(`llmp_*`)的统一管理入口,按引用前缀分发到各类既有归档
|
|
18
|
+
路径。`mode` 取 `"retire"`(退役)或 `"revoke"`(彻底撤销)。
|
|
19
|
+
- `mode: "retire"` 沿用各类既有行为,需要该类型原有的 write scope:`sec_*` 用
|
|
20
|
+
`secrets:write`,`llmp_*` 用 `model-services:write`,`vcrd_*` 的 remote / stdio 用
|
|
21
|
+
`managed-mcps:write`,net / git 用 `vaults:write`。另需项目访问权限,普通 vault 还要求
|
|
22
|
+
actor 所有权(项目默认托管 vault 按项目权限)。scope 之间没有蕴含关系,不能跨类型使用。
|
|
23
|
+
- retire 的效果:模型服务与托管 MCP 保留存量会话的解析;项目密钥、网络凭据与 git token 在
|
|
24
|
+
下次取用时失效。既有归档护栏与阶段引用护栏继续生效。
|
|
25
|
+
- **缺省 `mode` 是 `"revoke"`**,该模式尚未开放:它要求预留的 `vaults:admin`,当前签发的
|
|
26
|
+
平台 token 拿不到这个 scope,缺省调用返回 403 `CREDENTIAL_FORBIDDEN`;授权保留调用方通过
|
|
27
|
+
项目、actor 与类型校验后返回 501 `CREDENTIAL_REVOKE_NOT_ENABLED`,不修改任何凭据
|
|
28
|
+
(服务端尚未开放撤销)。
|
|
29
|
+
- 响应只有 `{ credentialRef, mode }`,不含凭据值。`reason` 是最长 1000 字符的可选请求上下文,
|
|
30
|
+
不持久化。
|
|
31
|
+
- 错误:400 `CREDENTIAL_REF_INVALID` / `CREDENTIAL_REQUEST_INVALID` /
|
|
32
|
+
`CREDENTIAL_TYPE_UNSUPPORTED`(该 vault 凭据类型不支持此操作),404 `CREDENTIAL_NOT_FOUND`
|
|
33
|
+
(不存在与不在权限范围同形),403 `CREDENTIAL_FORBIDDEN`,501
|
|
34
|
+
`CREDENTIAL_REVOKE_NOT_ENABLED`。
|
|
35
|
+
- 既有各资源面的 archive / retire 方法保留,本方法只是统一入口。
|
|
36
|
+
- 新增 `credentialEntryTickets.create/get/revoke`:按目标写 scope 签发短期录入链接、查询状态和撤销。SDK 不提供填值方法。
|
|
37
|
+
- 建票支持 `Idempotency-Key`:pending 恢复同一 URL;异体 409;终态或过期同 key 返回 410,不重发 URL,24 小时内保留无能力 tombstone。
|
|
38
|
+
- 建票结果的 `url` 通过显式属性读取;JSON 与 Node inspect 隐去 URL,票据资源错误只保留安全代码。
|
|
39
|
+
- `evals.createRun({ projectId, agent, suiteRef, strict? })`:手动触发一次 test 槽的 suite run,
|
|
40
|
+
scope **`eval:trigger`**。`POST /api/eval-runs` 以 202 返回 `{ runId }`,只建 run head 并入队;
|
|
41
|
+
`trigger` 固定 `cli`,没有可挂的 pipeline run,因此不产生 gate-visible conclusion,不参与
|
|
42
|
+
槽位晋级判定。`agent` 传 slug;未知 slug 404 `AGENT_NOT_FOUND`、test 槽未部署 400
|
|
43
|
+
`STAGE_NOT_DEPLOYED`、suite 不合法 400 `INVALID_SUITE` / `SUITE_PARSE_ERROR`。`caseIds` 不上
|
|
44
|
+
wire(服务端 400 `CASE_IDS_NOT_SUPPORTED`),一次 run 总是执行整个 suite。
|
|
45
|
+
- suite 可声明两种新 grader 类型(#5979):`duration`(`maxTurnMs` 逐回合,或用 `turn` 收窄
|
|
46
|
+
单轮;`maxTotalMs` 求和;`maxTimeToFirstTokenMs` 逐回合)与 `usage`(`maxInputTokens` /
|
|
47
|
+
`maxOutputTokens` / `maxTotalTokens` / `maxCacheReadInputTokens` /
|
|
48
|
+
`maxCacheWriteInputTokens` / `maxCostUsd`,case 全回合求和)。无终态事件、非 completed 终态、
|
|
49
|
+
`usageSource: "missing"`、或声明了某预算而读数缺席时判 `errored`;`errored` 不计 `failed`,
|
|
50
|
+
不直接挡晋级闸。
|
|
51
|
+
- 回合读面(#5978,均为新增键,旧读方剥掉而不拒收):
|
|
52
|
+
- `usage-update` chunk:仅带 `maxCostUsd` 的回合产出,读数是累计值,只在读数变化时追加一帧
|
|
53
|
+
(长工具调用不刷屏)。SDK 导出 `isUsageUpdateChunk` guard 与 `UsageUpdateChunk` 类型;
|
|
54
|
+
`streamEvents` 直接可读,轮询用 `listEvents({ chunkTypes: ["usage-update"] })`。
|
|
55
|
+
- `TurnUsage.toolDurationMs`:本回合工具执行墙钟时间的并集(并行调用重叠只计一次),恒为
|
|
56
|
+
`durationMs` 的子集;`tool-output-available` / `tool-output-error` chunk 与
|
|
57
|
+
`TurnAssistantToolPart` 同时带逐工具的 `durationMs`。
|
|
58
|
+
- completed 终态的 `usage.pricebookCost`(`amountUsd` / `priceTableVersion` /
|
|
59
|
+
`unpricedModelEstimated`):按派发时冻结的价目表估算,只有带 `maxCostUsd` 的回合有;与
|
|
60
|
+
执行器自报的 `usage.costUsd` 是两个来源,不参与计费。
|
|
61
|
+
|
|
62
|
+
### 随包文档
|
|
63
|
+
|
|
64
|
+
- `SKILL.md`:候选构建读回(#5976)——候选 run 终态后 `getRun(runId, { includeCandidates: true })`
|
|
65
|
+
的 `workloads[].revisionId` 即候选 Revision,可直接作为 `sessions.create` 的 `revisionId`
|
|
66
|
+
钉进会话(不走槽位解析);`credentials.revoke` 与 `credentialEntryTickets` 的用法、scope
|
|
67
|
+
与错误面;`evals.createRun` 的手动触发口径。随包 skill 版本 0.37.0 → 0.39.0(#6007 / #6008
|
|
68
|
+
各自 bump)。
|
|
69
|
+
- `README.md`:`credentials.revoke` 与 `credentialEntryTickets` 小节。
|
|
70
|
+
|
|
71
|
+
### 导出面核对
|
|
72
|
+
|
|
73
|
+
把 npm 上的 `@kanyun-ai-infra/agenthub@1.28.0` 解包后的 `dist/index.d.ts` 与本分支构建产物
|
|
74
|
+
对比,去掉注释后**没有任何删除行**。新增:
|
|
75
|
+
|
|
76
|
+
- 客户端字段:`PilotPlatformClient.credentials`、`PilotPlatformClient.credentialEntryTickets`;
|
|
77
|
+
- 方法:`CredentialsResource.revoke`、`CredentialEntryTicketsResource.create` / `get` /
|
|
78
|
+
`revoke`、`EvalsResource.createRun`;
|
|
79
|
+
- 值导出:`isUsageUpdateChunk`、`CreateEvalRunRequestSchema`、`CreateEvalRunResponseSchema`;
|
|
80
|
+
- 类型:`CredentialRef`、`CredentialRevocationMode`、`CredentialRevocationErrorCode`、
|
|
81
|
+
`RevokeCredentialRequest`、`RevokeCredentialResult`、`CredentialEntryTarget`、
|
|
82
|
+
`CredentialEntryTicketView`、`CreateCredentialEntryTicketRequest`、
|
|
83
|
+
`CreatedCredentialEntryTicket`、`CreateEvalRunRequest`、`CreateEvalRunResponse`、
|
|
84
|
+
`UsageUpdateChunk`;
|
|
85
|
+
- 既有类型新增可选键:`TurnUsage.toolDurationMs` / `TurnUsage.pricebookCost`、工具输出 chunk
|
|
86
|
+
与 `TurnAssistantToolPart` 的 `durationMs`、`usage-update` chunk 的 `observedUsd` /
|
|
87
|
+
`limitUsd` / `priceTableVersion` / `unpricedModelEstimated` / `callCount`。
|
|
88
|
+
|
|
89
|
+
`dist/realtime.d.ts` 无非注释差异。
|
|
90
|
+
|
|
91
|
+
### 迁移说明
|
|
92
|
+
|
|
93
|
+
没有破坏性变化;不用新方法、新入参时行为与 1.28.0 相同。
|
|
94
|
+
|
|
95
|
+
## 1.28.0
|
|
96
|
+
|
|
97
|
+
本版带上 1.27.1 之后合入 main 的公开面变化:`sessions.sendTurn` 的单回合预算 `maxCostUsd`
|
|
98
|
+
(#5946)、`sessions.terminate`、版本与槽位读面报告模型服务名、回合 `usage.durationMs` 的口径说明、
|
|
99
|
+
幂等键 24 小时窗口,以及 `turns.abort` 对已终止会话的 409 说明(#5942)。除下面「行为变化」一条外
|
|
100
|
+
均为新增或文档。
|
|
101
|
+
|
|
102
|
+
### 新增(主入口)
|
|
103
|
+
|
|
104
|
+
- `sessions.terminate(sessionId, { reason?, deadlineAt?, requireNoActiveWork? })`:显式终止会话,
|
|
105
|
+
scope **`sessions:terminate`**(任何预设都不含它,自定义 token 上显式勾选)。
|
|
106
|
+
- 202 返回生命周期迁移结果 `{ ok, sessionId, from, to, transitionId }`;沙箱由平台异步销毁,
|
|
107
|
+
`deadlineAt`(ISO 8601)是等待干净停止的上限,省略用服务端默认。
|
|
108
|
+
- `requireNoActiveWork` 默认 `true`:有回合在跑时**拒绝本次调用**,应答
|
|
109
|
+
422 `INVALID_TRANSITION`(等回合结束重试,或传 `false` 中途终止)。
|
|
110
|
+
- 404 `SESSION_NOT_FOUND`(不存在与不在你的项目范围是同一个 404)。**422 是所有生命周期拒绝的
|
|
111
|
+
状态码,具体看里面的 `code`**:`INVALID_TRANSITION` = active-work 拒绝(有回合在跑)或已
|
|
112
|
+
`terminating` / `reviving`(这两者同码,按自己的意图处理);`ALREADY_TERMINAL` = 行已
|
|
113
|
+
`terminated`(重试时可当已达成、调用未改任何状态)。409 `SESSION_NOT_READY` 是另一件事:
|
|
114
|
+
会话行本身不是 `status = ready`。
|
|
115
|
+
- 终止不是删除:会话行保留,之后 `sendTurn` 会把它复活到新沙箱(202 `revival_in_progress`);
|
|
116
|
+
在 `terminating` 期间发回合也会启动复活,终止 runner 会放弃销毁。
|
|
117
|
+
- `agents.getRevision` / `getRevisionById` / `getVersion`(以及 `agents.get` 内嵌的
|
|
118
|
+
`defaultRevision`)新增可选 **`modelServiceId` / `modelServiceName`**:这个版本会冻结到的模型服务
|
|
119
|
+
(`llmp_*` public id 与显示名;legacy 版本回落到 workload 的 manifest 默认)。版本没声明模型服务
|
|
120
|
+
时两个键都缺省;服务行被硬删时 `modelServiceName` 为 `null`(归档后仍返回名字)。
|
|
121
|
+
- `agents.stages.list` 在**信封层**新增 `stageModelServices`:
|
|
122
|
+
`[{ stage, modelServiceId, modelServiceName }]`,只含声明了模型服务的槽位。返回类型因此变为
|
|
123
|
+
`ListStagesResult`(= `ListStagesResponse & { stageModelServices? }`,原有字段一字不变);旧服务端
|
|
124
|
+
不返回这个键——缺省表示「没报告」,不是「没有模型服务」。放在信封层而不是槽位对象里,是因为
|
|
125
|
+
`StageSlotViewSchema` 是 `.strict()` 且内联在已发布客户端里,槽位对象多键会让旧客户端解析失败。
|
|
126
|
+
- `sessions.sendTurn` 接受 `maxCostUsd`(美元,> 0 且 ≤ 50)与 `requireAuthoritativePrice`
|
|
127
|
+
(#5946):服务端按回合判停。无价目返回 400 `BUDGET_UNPRICED`,会话/镜像不支持预算返回
|
|
128
|
+
409 `BUDGET_UNSUPPORTED_RUNTIME`——两种都是重发时去掉 `maxCostUsd`。
|
|
129
|
+
|
|
130
|
+
### 行为变化(唯一一条,影响面写全)
|
|
131
|
+
|
|
132
|
+
- **嵌套错误信封的码被提升**:`pilotPlatformErrorFromResponse` 是**本 SDK 发出的请求**所有 HTTP
|
|
133
|
+
错误的唯一入口,它现在在顶层没有 `code` / `message` 时读 `body.error.code` /
|
|
134
|
+
`body.error.message`。生效范围是所有**经本 SDK 发送**、且平台回该信封的端点:
|
|
135
|
+
- `sessions.createVoiceTicket` —— 实测例:平台停用实时语音时 `err.code` 从 `REQUEST_FAILED` 变成
|
|
136
|
+
`REALTIME_DISABLED`;
|
|
137
|
+
- `sessions.terminate`(本版新增的面,回 `{ success: false, error: { code, message? } }`);
|
|
138
|
+
- 任何未来经本 SDK 调用、且平台回这个信封形状的路由,自动跟上。
|
|
139
|
+
顶层 `code` / `message` 始终优先(两种形状同时出现时行为不变),`err.body` 里仍是原始 body,
|
|
140
|
+
`err.body.error.code` 照旧可读。**按旧兜底码(`NOT_FOUND` / `REQUEST_FAILED` / `SERVER_ERROR`)
|
|
141
|
+
分支这两类调用的调用方需要改成按真实码分支**;只按 `err.status` 分支的不受影响。
|
|
142
|
+
**不在射程内**:SDK 没有 `sessions.acquire` 方法(`/api/sessions/acquire` 是平台内部路由,SDK 不调用);
|
|
143
|
+
浏览器实时语音入口(`createRealtimeVoiceClient`)走 WebSocket 与自己的错误类型,不抛
|
|
144
|
+
`PilotPlatformApiError`;服务端内部写口与语音合成 handler 不属于本 SDK 的调用面。
|
|
145
|
+
|
|
146
|
+
### 随包文档
|
|
147
|
+
|
|
148
|
+
- `SKILL.md`:`sessions.terminate` 用法与 scope;版本 / 槽位读面的模型服务字段;幂等键的
|
|
149
|
+
**24 小时**回放窗口(窗口内同键同体重放、同键不同体 409;过期后同一个键会再执行一次并新建
|
|
150
|
+
资源,不能当永久去重);`usage.durationMs` / `usage.timeToFirstTokenMs` 的口径(provider 流时长,
|
|
151
|
+
**不是**回合墙钟;墙钟用 `dispatchedAt` → `completedAt`)。随包 skill 版本 0.36.1 → 0.37.0。
|
|
152
|
+
- `README.md`:同上四块的对应小节。
|
|
153
|
+
- `turns.abort` 的 JSDoc 与 SKILL 已由 #5942 写明:对 `terminated` 会话的 409 `SESSION_TERMINATED`
|
|
154
|
+
不可重试,该会话仍可由新的 `sendTurn` 复活。
|
|
155
|
+
|
|
156
|
+
### 导出面核对
|
|
157
|
+
|
|
158
|
+
把 `npm pack @kanyun-ai-infra/agenthub@1.27.1` 解包后的 `dist/index.d.ts` 与本分支构建产物对比,
|
|
159
|
+
去掉注释后的差异:
|
|
160
|
+
- `PlatformRevisionSchema` 与两处内嵌(workload 读面的 `defaultRevision`、`GetPlatformRevisionResponse`)
|
|
161
|
+
新增 `modelServiceId?` / `modelServiceName?`;
|
|
162
|
+
- 新增 `ListStagesResult`、`SessionTerminateLifecyclePhase`、`SessionTerminateRequest`、
|
|
163
|
+
`SessionTerminateRequestInput`、`SessionTerminateResponse`、`SessionTerminateRequestSchema`、
|
|
164
|
+
`SessionTerminateResponseSchema`、`StageSlotModelServiceView`、`StageSlotModelServiceViewSchema`;
|
|
165
|
+
- `SessionsResource` 新增 `terminate`;`WorkloadStagesResource.list` 的返回类型换成
|
|
166
|
+
`ListStagesResult`;
|
|
167
|
+
- `SendTurnInput` 新增 `maxCostUsd?` / `requireAuthoritativePrice?`。
|
|
168
|
+
|
|
169
|
+
没有删除。`dist/realtime.d.ts` 无非注释差异。
|
|
170
|
+
|
|
171
|
+
### 迁移说明
|
|
172
|
+
|
|
173
|
+
除「行为变化」那条错误码提升外没有破坏性变化;不用新方法、新入参时行为与 1.27.1 相同。
|
|
174
|
+
|
|
5
175
|
## 1.27.1
|
|
6
176
|
|
|
7
177
|
只改文档,没有行为变化。
|
package/README.md
CHANGED
|
@@ -156,6 +156,43 @@ Agents 和 runtime templates 都是 **project-scoped**。Version 必须在同一
|
|
|
156
156
|
> 未声明的字段时会被忽略,不会报错;服务端新增字段不需要客户端升级。1.16.0 起
|
|
157
157
|
> `PlatformRevision` 接受可选的 `sequence`(每个 Agent 内从 1 递增的版本序号,号可
|
|
158
158
|
> 不连续);服务端读面返回它之前,该字段为 `undefined`。
|
|
159
|
+
>
|
|
160
|
+
> 1.28.0 起版本读面还带 **`modelServiceId` / `modelServiceName`**:这个版本会冻结到
|
|
161
|
+
> 的模型服务(`llmp_*` id 及显示名,legacy 版本回落到 workload 的 manifest 默认)。
|
|
162
|
+
> 版本没声明模型服务时两个键都缺省;服务行被硬删时 `modelServiceName` 为 `null`
|
|
163
|
+
> (归档后仍显示名字)。`agents.stages.list` 在**信封层**(不在 `stages` 元素内)多给
|
|
164
|
+
> 一个 `stageModelServices: [{ stage, modelServiceId, modelServiceName }]`,只含声明了
|
|
165
|
+
> 模型服务的槽位;旧服务端不给这个键——缺省表示"没报告",不是"没有模型服务"。
|
|
166
|
+
|
|
167
|
+
## 终止会话与自动复活
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
// 显式终止:只翻生命周期到 terminating,沙箱由平台异步销毁(deadlineAt 兜底)。
|
|
171
|
+
const t = await agenthub.sessions.terminate(sessionId, {
|
|
172
|
+
reason: "user_request", // 1–50 字符,默认 "api"
|
|
173
|
+
requireNoActiveWork: true, // 默认 true:有回合在跑时 422 INVALID_TRANSITION(拒绝本次调用)
|
|
174
|
+
});
|
|
175
|
+
// t => { sessionId, from, to: "terminating", transitionId }
|
|
176
|
+
|
|
177
|
+
// 终止不是删除:之后对同一会话 sendTurn 会自动复活到新沙箱。
|
|
178
|
+
const sent = await agenthub.sessions.sendTurn(sessionId, { text: "继续" });
|
|
179
|
+
// sent.kind === "revival_in_progress"(HTTP 202,别重发);用 waitForTurn 等那一轮
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- 需要 scope **`sessions:terminate`**(任何预设都不含它,自定义 token 里显式勾选)。
|
|
183
|
+
- 404 同时表示"不存在"与"不在你的项目范围"。
|
|
184
|
+
- **422 是所有生命周期拒绝的状态码,具体看里面的 `code`**:`INVALID_TRANSITION` 是 active-work
|
|
185
|
+
拒绝(等回合结束重试,或显式传 `false` 中途终止),或会话已在 `terminating` / `reviving`
|
|
186
|
+
——这两者同码,按自己的意图处理;`ALREADY_TERMINAL` 是会话已经 `terminated`(重试时可当已达成,
|
|
187
|
+
本次调用没改任何状态)。409 `SESSION_NOT_READY` 是另一件事:会话行本身不是 `status = ready`。
|
|
188
|
+
- 在 `terminating` 期间 `sendTurn` 会启动 Agent Recovery,终止 runner 发现
|
|
189
|
+
transition id 变了会放弃销毁——**想留在终止态就别在这时发回合**。
|
|
190
|
+
- 带 `idempotencyKey` 的创建方法(`projects.create` / `secrets.create` /
|
|
191
|
+
`modelServices.create` / `managedMcps.create` / `schedules.create` /
|
|
192
|
+
`vaults.credentials.create`)**回放窗口是 24 小时**:窗口内同键同体重放原响应,
|
|
193
|
+
同键不同体 409;窗口过后同一个键会再执行一次并新建资源,幂等键不能当永久去重,
|
|
194
|
+
创建出来的 id 要自己存。
|
|
195
|
+
|
|
159
196
|
|
|
160
197
|
## 记忆(agenthub.memories)
|
|
161
198
|
|
|
@@ -214,7 +251,7 @@ App 里点的"对";`purge(projectId, { subjectKind, subjectId })` 按主体清
|
|
|
214
251
|
|
|
215
252
|
| 字段 | 含义 |
|
|
216
253
|
| --- | --- |
|
|
217
|
-
| `usage` | 模型用量(`inputTokens` / `outputTokens` / `totalTokens` 等)。其中 `costUsd` 是 Claude Code CLI **自报的列表价估算**(`costSource === "claude_code_cli"`),不是账单实付;`failed` / `aborted` 轮次没有 `usage`(T-INV-13)。`completed` 轮次也可能缺省——用量数据没通过校验时字段不落,并在该轮 `anomalies` 里记 `usage_parse_failed
|
|
254
|
+
| `usage` | 模型用量(`inputTokens` / `outputTokens` / `totalTokens` 等)。其中 `costUsd` 是 Claude Code CLI **自报的列表价估算**(`costSource === "claude_code_cli"`),不是账单实付;`failed` / `aborted` 轮次没有 `usage`(T-INV-13)。`completed` 轮次也可能缺省——用量数据没通过校验时字段不落,并在该轮 `anomalies` 里记 `usage_parse_failed`。`usage.durationMs` 是**模型 provider 流**的时长(首字节到最后一个 chunk),不含技能安装、交付、快照采集,**不是回合墙钟**;回合计时用 `dispatchedAt` → `completedAt`。`usage.timeToFirstTokenMs` 是同一时钟上到首个正文 chunk 的时间。 |
|
|
218
255
|
| `traceId` | 这一轮的分布式 trace id(`string \| null`),可拼 Octopus trace-explorer 深链定位整条链路(agenthub → control-worker → agent-worker)。 |
|
|
219
256
|
| `memoryRecall.state` | **只在会话首轮出现**——设计如此,不是版本或故障问题:读服务只给首轮投影这个字段(`session-turns-read-service.ts` 的 `core.turnId === enrichment.firstTurnId` 判据),第 2 轮起 `memoryRecall` 恒为 `undefined`,即便服务端是最新版。值是这一轮的**记忆召回状态**枚举,不是召回内容:`selected`(召回并注入了条目)/ `empty`(功能开着、也查了,本轮无可注入记忆)/ `recall_failed`(召回过程失败)/ `unavailable`(回读时没能解出召回快照)/ `legacy`(会话早于记忆机制,无快照)。目前只对外暴露状态,不含召回内容。 |
|
|
220
257
|
|
|
@@ -307,7 +344,9 @@ await agenthub.sessions.create({
|
|
|
307
344
|
|
|
308
345
|
## 错误
|
|
309
346
|
|
|
310
|
-
API 请求失败都会抛出类型化错误,错误对象带 `status`、`code` 和 `requestId`——但请求被 `AbortSignal` 取消是例外,那条路径抛的是原生 `AbortError
|
|
347
|
+
API 请求失败都会抛出类型化错误,错误对象带 `status`、`code` 和 `requestId`——但请求被 `AbortSignal` 取消是例外,那条路径抛的是原生 `AbortError`,没有这些字段,需要单独判断。
|
|
348
|
+
|
|
349
|
+
`code` 的取法:先看响应顶层的 `code`,没有就读嵌套信封 `{ success: false, error: { code, message? } }` 里的 `body.error.code`(1.28.0 起;更早的版本只读顶层,嵌套信封的端点会给你按状态码兜底的 `NOT_FOUND` / `REQUEST_FAILED` / `SERVER_ERROR`)。原始 body 始终留在 `err.body`。
|
|
311
350
|
|
|
312
351
|
| Class | HTTP |
|
|
313
352
|
| --- | --- |
|
|
@@ -417,7 +456,7 @@ SDK 1.13.0 起提供此行为。旧版 1.11.0 / 1.12.0 / 1.12.1 忽略 `call_end
|
|
|
417
456
|
|
|
418
457
|
通话可能在两处被拒:接入方后端取票时,和浏览器握手时。
|
|
419
458
|
|
|
420
|
-
**取票被拒。** 发票接口的错误体是 `{ success: false, error: { code, message?, scope? } }`。SDK
|
|
459
|
+
**取票被拒。** 发票接口的错误体是 `{ success: false, error: { code, message?, scope? } }`。1.28.0 起 SDK 把**嵌套信封的** `error.code` / `error.message` 提升到 `err.code` / `err.message`(顶层键优先),所以这里 `err.code` 直接就是下表里的码(如 409 `REALTIME_DISABLED`),可读原因在 `err.message`;原始 body 仍整块留在 `err.body`(`err.body.error.code` 同样可读)。1.27.1 及更早只取顶层,`err.code` 是按 HTTP 状态给的通用值(409 `REQUEST_FAILED`、503 `SERVER_ERROR`)——按旧版本写的 `err.body.error.code` 分支在新版本上照样成立。下表注明哪些码带 `message`。
|
|
421
460
|
|
|
422
461
|
```ts
|
|
423
462
|
import { PilotPlatformApiError } from "@kanyun-ai-infra/agenthub";
|
|
@@ -426,8 +465,9 @@ try {
|
|
|
426
465
|
return await client.sessions.createVoiceTicket(sessionId);
|
|
427
466
|
} catch (err) {
|
|
428
467
|
if (err instanceof PilotPlatformApiError) {
|
|
429
|
-
|
|
430
|
-
//
|
|
468
|
+
// err.code 例如 "REALTIME_UPSTREAM_NOT_CONFIGURED"(1.28.0 起;更早版本读 err.body.error.code)
|
|
469
|
+
// err.message 可以直接展示给用户
|
|
470
|
+
// REALTIME_CAPACITY_EXCEEDED 还要看 scope:err.body.error.scope 为 "project" / "global"(见下表)
|
|
431
471
|
}
|
|
432
472
|
throw err;
|
|
433
473
|
}
|
|
@@ -464,3 +504,27 @@ try {
|
|
|
464
504
|
调用方必须实现 `isAudienceAllowed(aud)`,查询本上游接受的托管 MCP ID(重建退场期可能同时接受新旧 ID);必须实现 `claimJti(jti, expiresAtSeconds)`,用跨实例共享的原子写登记 nonce,例如数据库唯一键或 Redis SET NX,直到绝对 Unix 秒时间戳到期。已登记返回 false。存储或回调异常会向上传播,上游应拒绝请求。
|
|
465
505
|
|
|
466
506
|
返回 `ok: true` 后,还需按 `claims.sub` 查本地会话,并核对 `claims.project_id`。actor 字段只用于审计,不能授予权限。缺头、签名/请求绑定失败、过期、未知公钥和重放都返回 `ok: false` 及具体 reason;配置错误抛 TypeError。时钟容差默认 30 秒,允许降低,不允许增加。
|
|
507
|
+
|
|
508
|
+
### 统一凭据管理
|
|
509
|
+
|
|
510
|
+
```ts
|
|
511
|
+
await agenthub.credentials.revoke(credentialRef, { mode: "retire" });
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
接受 `sec_*`、`vcrd_*`、`llmp_*`。需要对应类型的原有 write scope:项目密钥 `secrets:write`、模型服务 `model-services:write`、托管 MCP `managed-mcps:write`、网络 / git 凭据 `vaults:write`;另校验项目权限和普通 vault 的 actor 所有权。返回 `{ credentialRef, mode }`,不含凭据值。retire 沿用各类现有行为:模型服务与托管 MCP 保留存量会话解析;项目密钥、网络凭据与 git token 在下次取用时失效。既有归档和引用护栏继续生效。缺省 `mode` 为 `revoke`,需预留的 `vaults:admin`(当前不可对平台 token 签发),当前签发的平台 token 因缺少该 scope 返回 403 `CREDENTIAL_FORBIDDEN`;501 `CREDENTIAL_REVOKE_NOT_ENABLED` 仅是授权保留调用方通过校验后的语义,不修改凭据。可选 `reason` 只作为请求上下文,不持久化。
|
|
515
|
+
|
|
516
|
+
维护者验收(仅限源码仓库):npm 包不包含探针脚本。release 从 [Pilot 源码中的验收脚本](https://github.com/kanyun-ai-explore/pilot/blob/main/packages/agenthub-sdk/scripts/probe-credential-retire.mjs) 取用,使用隔离 testing 凭据,通过 agentcred 注入 `AGENTHUB_PLATFORM_TOKEN`,在仓库根目录执行:
|
|
517
|
+
|
|
518
|
+
```bash
|
|
519
|
+
node packages/agenthub-sdk/scripts/probe-credential-retire.mjs --url "$B1_TEST_PLANE_URL" --ref "$B1_TEST_SECRET_REF" --mode retire --expect 200
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
该命令会执行既有退场 / 归档动作;只使用专用验收凭据。探针不重试,输出状态、错误码和身份,不输出凭据值。
|
|
523
|
+
|
|
524
|
+
## Credential entry tickets
|
|
525
|
+
|
|
526
|
+
Use `client.credentialEntryTickets.create(projectId, { target, returnUrl, ttlSeconds? }, { idempotencyKey? })` to get a short-lived administrator entry link. `target` is `{secretId}` (independent `env_jit`, `secrets:write`) or `{managedMcpId, field: "accessToken" | "secretValues.<KEY>"}` (`managed-mcps:write`). The callback requires controlled registration for the authenticated subject and tenant. TTL is an integer from 1 to 900 seconds, default 900.
|
|
527
|
+
|
|
528
|
+
Read `result.url` explicitly to hand it to an administrator; JSON serialization and Node inspect hide it. Never log the link or HTTP body. Filling still requires portal CAS login and project management permission; this resource has no fill method. `get(projectId, ticketId)` and `revoke(projectId, ticketId)` return `{ticketId, status, expiresAt}` and require the issuer's current write scope and project access.
|
|
529
|
+
|
|
530
|
+
With an idempotency key, pending retries return the same ID, URL and expiry; different request bytes return 409. Terminal or expired retries return 410 without a URL. The key is retained as a capability-free tombstone for 24 hours from creation; use a new key to issue a new ticket. Package publication is coordinated separately from the workspace API.
|