@sema-agent/sdk 19.0.0 → 20.0.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 +56 -0
- package/dist/errors.d.ts +4 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +4 -1
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +15 -15
- package/dist/events.d.ts.map +1 -1
- package/dist/idempotency.d.ts +11 -0
- package/dist/idempotency.d.ts.map +1 -1
- package/dist/idempotency.js +11 -0
- package/dist/idempotency.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/fleet.d.ts +7 -0
- package/dist/resources/fleet.d.ts.map +1 -1
- package/dist/resources/fleet.js.map +1 -1
- package/dist/resources/leader.d.ts +9 -0
- package/dist/resources/leader.d.ts.map +1 -1
- package/dist/resources/leader.js +9 -0
- package/dist/resources/leader.js.map +1 -1
- package/dist/resources/runs.d.ts +16 -0
- package/dist/resources/runs.d.ts.map +1 -1
- package/dist/resources/runs.js +22 -0
- package/dist/resources/runs.js.map +1 -1
- package/dist/resources/session-sync.d.ts +14 -5
- package/dist/resources/session-sync.d.ts.map +1 -1
- package/dist/resources/session-sync.js +3 -2
- package/dist/resources/session-sync.js.map +1 -1
- package/dist/resources/sessions.d.ts +33 -2
- package/dist/resources/sessions.d.ts.map +1 -1
- package/dist/resources/sessions.js +29 -1
- package/dist/resources/sessions.js.map +1 -1
- package/dist/resources/tasks.d.ts +10 -2
- package/dist/resources/tasks.d.ts.map +1 -1
- package/dist/resources/tasks.js +8 -0
- package/dist/resources/tasks.js.map +1 -1
- package/dist/sync.d.ts +23 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +43 -0
- package/dist/sync.js.map +1 -1
- package/dist/types.d.ts +156 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/openapi.yaml +370 -20
- package/package.json +1 -1
package/dist/types.d.ts
CHANGED
|
@@ -244,11 +244,13 @@ export interface TaskRequest {
|
|
|
244
244
|
/** [2400] TR-16 — CALLER-MINTED task id (**uuidv7**), the DURABLE second tier of idempotency on
|
|
245
245
|
* `POST /v1/runs` (server `src/http/routes/runs.ts:196-217`).
|
|
246
246
|
*
|
|
247
|
-
* Why it exists next to `Idempotency-Key`: that header's cache is IN-MEMORY and PER-POD, so a dispatch
|
|
247
|
+
* Why it exists next to `Idempotency-Key`: on server ≤7.124.x that header's cache is IN-MEMORY and PER-POD, so a dispatch
|
|
248
248
|
* gateway that re-routes a retry to ANOTHER instance after a network error would start a SECOND run. This
|
|
249
249
|
* replay reads the DURABLE run store, so it survives the re-route AND a restart — it is the prerequisite for
|
|
250
250
|
* gateway failover. A hit replays the original receipt (202 `{taskId, sessionId, status}`); nothing re-runs,
|
|
251
|
-
* nothing re-bills.
|
|
251
|
+
* nothing re-bills. 🔴 server ≥7.125.0: `Idempotency-Key` is ALSO a unique key on the run row (contract §0.7) — two keys to ONE row; sent together they
|
|
252
|
+
* must point at the same row, and a key that points at a row this `taskId` does not name is 409 `conflict.run_exists`
|
|
253
|
+
* (sentence `a run already exists for this submission's taskId or Idempotency-Key`; the code is unchanged, nothing about the row is echoed).
|
|
252
254
|
* 🔴 Shape-gated: a non-uuidv7 value is a 400 `request.id_invalid` (the caller cannot inject an arbitrary PK
|
|
253
255
|
* shape — it is the same alphabet the server mints). Owner-gated replay: a taskId owned by ANOTHER principal
|
|
254
256
|
* answers 409 `conflict.run_exists`, never that tenant's run (no cross-tenant id oracle).
|
|
@@ -537,7 +539,9 @@ export interface TaskRequest {
|
|
|
537
539
|
* eventId→entryId 映射、`resumeAnchorStore.resolve` 折算。**必须配 `sessionId`**(要分叉的会话;session 由 auth 派生,
|
|
538
540
|
* body 不带);**不能与 durable resume 同用**(resume 路径会先剥掉 resumeAt 再 re-resolve)。anchor 未知 → 4xx;已知但
|
|
539
541
|
* 被 compact 掉 → 同步 4xx / 异步 run-result `resume_at.not_found`。worker 无 anchor store(`resumeAnchorStore`+
|
|
540
|
-
* `getLeafId`)→ 501,与 `capabilities.resumeAt` 同对一对(能力说 yes ⟺ 路由 resolve)。
|
|
542
|
+
* `getLeafId`)→ 501,与 `capabilities.resumeAt` 同对一对(能力说 yes ⟺ 路由 resolve)。
|
|
543
|
+
* server ≥7.125.0:**用户提示词**的手柄也可以直接取自历史读面 —— `GET /v1/sessions/:id` 的用户消息行上的 `taskId`(见 {@link SessionUserMessageRow};present-iff,
|
|
544
|
+
* 行上有就一定解得出),重载之后无需再有 live `eventId` 在手。 */
|
|
541
545
|
resumeAt?: string;
|
|
542
546
|
/** 🔴 D1 补型(2026-07-29;形自 server `src/http/wire-types.ts` 亲读)—— [833] 排他 rewind(core 1.292
|
|
543
547
|
* `TaskSpec.resumeAtMode`):限定 {@link resumeAt} 的落点。`"at"`(缺席时的默认,零回归)把目标消息**留在**
|
|
@@ -1114,6 +1118,19 @@ export interface SealedKeyCapability {
|
|
|
1114
1118
|
/** 32 字节 X25519 公钥的**标准** base64(44 字符)。公钥,可记日志。 */
|
|
1115
1119
|
publicKey: string;
|
|
1116
1120
|
}
|
|
1121
|
+
/**
|
|
1122
|
+
* `GET /v1/capabilities` 的 `workspaceSync` 段(server ≥7.125.0,契约附录 B.1 / B.1a)—— **恰两键**,与 server `src/workspace-space.ts` 的 `WorkspaceSyncCapability` 逐键同
|
|
1123
|
+
* (测试源码腿 / dist 腿对拍;成员闭集登记在契约 B.1a:两键都是「恒在场」成员,随整个对象在场)。
|
|
1124
|
+
*/
|
|
1125
|
+
export interface WorkspaceSyncCapability {
|
|
1126
|
+
/** 运维旋钮 `WORKSPACE_PERSIST` 的有效值,**两词闭集**,🔴 **缺省 `"off"`**(持久化是 opt-in):
|
|
1127
|
+
* · `"space"` —— 运维显式开了:工作区按会话住客跨轮保留;
|
|
1128
|
+
* · `"off"` —— 快照存储在、但**没开**(缺省,或运维显式关):每轮新建工作区。🔴 **与整个对象缺席不同义**(缺席 = 这台部署根本没有这项设施)。
|
|
1129
|
+
* 壳 / 中心只在 `"space"` 时渲「工作文件跨轮保留」。 */
|
|
1130
|
+
persist: "space" | "off";
|
|
1131
|
+
/** 每个空间(会话住客)保留的快照份数(运维旋钮 `WORKSPACE_SNAPSHOT_KEEP`,整数 `[1, 50]`,缺省 3);超出的旧快照在每次存成功之后删。 */
|
|
1132
|
+
keep: number;
|
|
1133
|
+
}
|
|
1117
1134
|
/**
|
|
1118
1135
|
* S-173(K-24;server ≥7.104.0)—— 一条**停在门上**的 run 在 `GET /v1/runs/:id` 行上的 `status` 词,也是同步提交撞 park 时
|
|
1119
1136
|
* 200 体上的回执词。server 从 `RUN_STATUS_CLASS` 判 `"parked"` 的那几个词**派生**(`plugins/store-contracts.ts` 的
|
|
@@ -1157,6 +1174,12 @@ export interface SyncParkReceipt {
|
|
|
1157
1174
|
* ```
|
|
1158
1175
|
* 🔴 判代用 `r.terminal === undefined`,**别用** `"terminal" in r`:`terminal` 在型上是必填,`in` 的假支会被收成 `never`
|
|
1159
1176
|
* (那一支里 `r.status` 编译不过)。
|
|
1177
|
+
*
|
|
1178
|
+
* 🔴 **20.0.0:`tasks.submit` 返回 {@link SyncSubmitOutcome}(本型 ∪ {@link RunReplayRecord})**。server ≥7.125.0 起,同一把 `Idempotency-Key` 已经建过一条 run 行
|
|
1179
|
+
* (换了进程 / 副本 / 重启,或原请求已落定;SDK 自动键的断线重发正会撞上)时,200 **不是**上面任何一代的首答 —— 它是 `GET /v1/runs/:id` 的读面 + `replay: true`
|
|
1180
|
+
* (`result` 是**嵌套**的 {@link TaskResult},**没有**顶层 `terminal` / `stats`,没有 `wiringManifest` / `notice`)。所以本型**只描述首答**(含上面三代),重放体是联合的另一臂;
|
|
1181
|
+
* 判别位 `r.replay`:`true` ⇒ 重放体,缺席 ⇒ 本型。窄化之后,上面「三代通用读法」原样适用。
|
|
1182
|
+
* 同进程里同键的**并发**请求被合流到的那一份不是重放:与首答逐字节同体、没有 `replay` 键。
|
|
1160
1183
|
*/
|
|
1161
1184
|
export interface SyncSubmitResult extends TaskResult {
|
|
1162
1185
|
/** 回执词 / ≤7.63 平面词(见上):≥7.104 只在 park 时在场(park 两词);7.64–7.103 只在 park 体上;≤7.63 恒在(平面终局词)。 */
|
|
@@ -1522,7 +1545,8 @@ export interface ModelsResponse {
|
|
|
1522
1545
|
export interface UsageInfo {
|
|
1523
1546
|
/** 是否配置了成本配额窗口(false ⇒ 仅有单任务上限,无窗口用量账本)。 */
|
|
1524
1547
|
enabled: boolean;
|
|
1525
|
-
/**
|
|
1548
|
+
/** 配额窗口秒数(如 86400=日窗)。server ≥7.125.0 起窗在每种部署上都是时钟对齐桶(桶号 = `floor(now / windowSec)`,日窗在 UTC 零点滚),
|
|
1549
|
+
* 不再有「从首笔花费起算」的单副本形;窗什么时候滚读 {@link UsageInfo.windowResetsAt}。 */
|
|
1526
1550
|
windowSec?: number;
|
|
1527
1551
|
/** 当前窗口已用(micro-USD,1e-6 美元)。 */
|
|
1528
1552
|
usedMicroUsd?: number;
|
|
@@ -1538,6 +1562,12 @@ export interface UsageInfo {
|
|
|
1538
1562
|
overLimit?: boolean;
|
|
1539
1563
|
/** 超限时建议的重试等待秒数。 */
|
|
1540
1564
|
retryAfterSec?: number;
|
|
1565
|
+
/** server ≥7.125.0(additive)—— **当代配额窗的窗末**(ISO 8601,date-time 串):时钟对齐桶滚到下一只桶、`usedMicroUsd` 从零重计的那一刻。
|
|
1566
|
+
* `enabled: true` 的体**恒带**(零花费、限额为 0 的关断态也在场 —— 窗长仍是配置事实);`enabled: false` 的体**没有**它。
|
|
1567
|
+
* 🔴 **缺席读法**:`enabled: true` 而本键缺席 = 老 server(< 7.125.0),**不是**「窗不滚」,更不是「永不重置」;不要从 `windowSec` 自己推窗末(窗是对齐桶,不是从你的首笔花费起算)。
|
|
1568
|
+
* 越顶的 429 `limit.cost_quota_exceeded` 体带同一个值(经 {@link import("./errors.js").APIError.extra}〔`err.extra.windowResetsAt`〕到达),`retryAfterSec` 与 `Retry-After` 头照旧、与它同一次读钟。
|
|
1569
|
+
* 不加能力位(能力位 `usage` 不变),消费端按键在场判。 */
|
|
1570
|
+
windowResetsAt?: string;
|
|
1541
1571
|
/** 单任务成本硬上限(USD;与窗口配额独立,总在)。 */
|
|
1542
1572
|
maxTaskCostUsd?: number;
|
|
1543
1573
|
/** 单任务 token 硬上限(与窗口配额独立,总在)。 */
|
|
@@ -2270,7 +2300,73 @@ export interface RunRecord {
|
|
|
2270
2300
|
* 续跑认领会把旗清零(撞上 suspend 的取消不许在恢复之后再杀一遍)。⇒ **别**把 `cancelRequested` 翻回 `false` 读成「取消完成」—— 等终态 `status` + `errorCode:"cancelled"`。
|
|
2271
2301
|
* `POST /v1/runs/:id/cancel` 的受理体带同一个键({@link CancelAck.cancelRequested},同一个谓词)。< 7.73.0 缺席。 */
|
|
2272
2302
|
cancelRequested?: boolean;
|
|
2303
|
+
/** 🔴 server ≥7.125.0(additive;契约 §0.7)—— **提交幂等重放体的判别位**:只在 `POST /v1/tasks` 的 200 重放体与 `POST /v1/tasks/stream` 的 `done.result` 重放体上在场(值恒 `true`,见 {@link RunReplayRecord}),
|
|
2304
|
+
* `GET /v1/runs/:id` 与 `GET /v1/runs?idempotencyKey=` 上**缺席**(那是读面本身),从不发 `false`。按 `replay === true` 分流;结果读 `result`(嵌套的 {@link TaskResult})。 */
|
|
2305
|
+
replay?: true;
|
|
2306
|
+
}
|
|
2307
|
+
/**
|
|
2308
|
+
* **提交幂等的重放体**(server ≥7.125.0;契约 §0.7)= {@link RunRecord}(`GET /v1/runs/:id` 的读面,同一只投影口)+ `replay: true`。
|
|
2309
|
+
*
|
|
2310
|
+
* 同一把 `Idempotency-Key` 已经建过一条 run 行(换了进程 / 副本 / 重启,或原请求已落定)时,同步提交 `POST /v1/tasks` 不再「当新提交再跑一遍」、
|
|
2311
|
+
* 也**不**回首答的形:200 回这一份体;`POST /v1/tasks/stream` 开流同首答(`x-task-id` 头 + `meta` 帧),终帧 `done { result: <同一份体>, replay: true }`。
|
|
2312
|
+
*
|
|
2313
|
+
* 🔴 **它不是 {@link TaskResult}**:首答是引擎结果(`terminal` / `stats` 在顶层,`result` 是字符串),重放时手里只有行 ⇒ 体是行读面:`result` 是**嵌套**的 {@link TaskResult}(或在 run 还没有结果时缺席),
|
|
2314
|
+
* **没有**顶层 `terminal` / `stats`,也**没有** `wiringManifest`(起手接线回执是首帧的活捕获、不落行)与 `notice`。判别位 `replay === true`(两形不会同时匹配)。
|
|
2315
|
+
* 在飞合流(同进程里同键的并发请求)到的那一份不是重放:与首答逐字节同体、**没有** `replay` 键。
|
|
2316
|
+
*
|
|
2317
|
+
* 流式腿的一个窄形:这条腿**已开流之后**才发现命中(建行那一刻撞上另一副本先落的行)时,已发出的 `x-task-id` 头 / `meta` 帧带的是本腿现铸、没建成的那枚 id —— 终帧重放体里的 `taskId` 才是命中的那条 run 的真 id,以终帧为准。
|
|
2318
|
+
*
|
|
2319
|
+
* 只有**建得出行**的提交才有行可放:要有 run 店,且 `POST /v1/tasks` / `/v1/tasks/stream` 带 `sessionId`(`POST /v1/runs` 恒建行);没有行的提交落定之后同键重试会再跑一遍。
|
|
2320
|
+
* 重放体读不到(属主不符 / 键指向别的行)⇒ 409 `conflict.run_exists`({@link import("./errors.js").ConflictError},体里不回显那一行的任何标识)。
|
|
2321
|
+
*/
|
|
2322
|
+
export interface RunReplayRecord extends RunRecord {
|
|
2323
|
+
replay: true;
|
|
2324
|
+
}
|
|
2325
|
+
/**
|
|
2326
|
+
* **提交在 SSE 已开流之后被拒**时的 `done.result`(`POST /v1/tasks/stream`)—— 状态行已经发出,拒绝只能编码成终帧的三键 `{ status: "failed", errorCode, errorMessage }`
|
|
2327
|
+
* (码与句取自 JSON 拒绝体本会带的那一对;server `routes/tasks.ts`)。两个生产者:
|
|
2328
|
+
* · **server ≥7.125.0** —— 同键重放只在建行那一刻才被发现(另一副本先落了行),而那条行调用方读不到 / 指向别的 run ⇒ `errorCode: "conflict.run_exists"`(契约 §0.7;该帧同时带 `replay: true`);
|
|
2329
|
+
* · device 放置拒(placement 错误体的码与句;此前在型面上没有这一臂)。
|
|
2330
|
+
* 不是引擎结果(没有 `taskId` / `stats`),也不是 {@link ActiveRunConflictDoneResult}(那一臂码恒为 `conflict.session_active_run` 且必带 `activeTaskId`)。
|
|
2331
|
+
* **按 `errorCode` 分支,句子只给人看。** `replay` 在 `result` 上恒缺席(帧上的 `replay: true` 是另一回事)。
|
|
2332
|
+
*/
|
|
2333
|
+
export interface SubmitRefusalDoneResult {
|
|
2334
|
+
status: "failed";
|
|
2335
|
+
/** 开集串:`conflict.run_exists`(server ≥7.125.0)或 device 放置拒的码。 */
|
|
2336
|
+
errorCode: string;
|
|
2337
|
+
errorMessage: string;
|
|
2273
2338
|
}
|
|
2339
|
+
/** 判别位 `replay` 的「非重放」一半:联合里每一条非重放臂都带它,于是 `r.replay === true` 能把联合窄到 {@link RunReplayRecord}(各臂接口本身不声明 `replay`——它们镜像 wire 键,wire 上这些形没有这个键)。 */
|
|
2340
|
+
type NotReplay = {
|
|
2341
|
+
replay?: undefined;
|
|
2342
|
+
};
|
|
2343
|
+
/**
|
|
2344
|
+
* `POST /v1/tasks`(同步腿)200 体的**可判别联合**(20.0.0;server ≥7.125.0 起重放体可达):
|
|
2345
|
+
* · 首答 {@link SyncSubmitResult} —— 引擎结果(`terminal` / `stats` 在顶层);**没有** `replay` 键;
|
|
2346
|
+
* · 幂等重放 {@link RunReplayRecord} —— 同键已建过 run 行时的读面 + `replay: true`(结果在嵌套的 `result`,**没有**顶层 `terminal` / `stats`)。
|
|
2347
|
+
* 判别位 = `r.replay`:`true` ⇒ 重放体,`undefined` ⇒ 首答。先分流再读引擎字段:
|
|
2348
|
+
* ```ts
|
|
2349
|
+
* const r = await client.tasks.submit(req);
|
|
2350
|
+
* if (r.replay === true) readRow(r.status, r.result); // 行读面:状态 / 嵌套结果 / errorCode …
|
|
2351
|
+
* else render(r.terminal); // 首答:引擎结果
|
|
2352
|
+
* ```
|
|
2353
|
+
*/
|
|
2354
|
+
export type SyncSubmitOutcome = (SyncSubmitResult & NotReplay) | RunReplayRecord;
|
|
2355
|
+
/**
|
|
2356
|
+
* 流式提交(`POST /v1/tasks/stream`)终帧 `done.result` 的**可判别联合**(20.0.0;`AgentEvent` 的 `done` 臂读它)——spec `Event_done.result` 的 `oneOf` 同表:
|
|
2357
|
+
* · {@link TaskResult} —— 正常终态(引擎结果);
|
|
2358
|
+
* · {@link ActiveRunConflictDoneResult} —— 会话已有活跃 run 的拒绝信封(`conflict.session_active_run`,必带 `activeTaskId`);
|
|
2359
|
+
* · {@link LegacyPlaneTaskResult} —— 只在 durable 账本回放腿上、跨 7.64.0 升级过的部署:升级前落盘的旧平面形;
|
|
2360
|
+
* · {@link RunReplayRecord} —— server ≥7.125.0 同键重放(该 run 已落行):读面 + `replay: true`;
|
|
2361
|
+
* · {@link SubmitRefusalDoneResult} —— 开流后才被拒的 `{status:"failed", errorCode, errorMessage}`。
|
|
2362
|
+
* **窄化顺序**(五臂靠不同的键分家):`r.replay === true` ⇒ 重放体;`"stats" in r` ⇒ 引擎结果(再按 `"terminal" in r` 分现行因由形与旧平面形);`"activeTaskId" in r` ⇒ 会话占用冲突;其余 ⇒ 拒绝三键。
|
|
2363
|
+
* ⚠️ 帧上的 `replay: true` 与 `result.replay` 不是一回事:同进程在飞合流到的那一份,帧上也带 `replay: true`,但 `result` 是首答 {@link TaskResult} 逐字(无 `result.replay`)。
|
|
2364
|
+
* 🔴 **在飞合流的拒绝(server ≥7.125.0 起与首发同形)**:同进程在飞合流的跟随方,若**首请求被拒**(会话占用 409 / `conflict.run_exists` / device 放置拒 / 同步腿零工作拒),`done.result` 与首发那一帧是**同一只投影**
|
|
2365
|
+
* (会话占用 ⇒ 冲突臂,其余 ⇒ 拒绝三键),帧上带 `replay: true`、`result` 上没有 —— 都在上面五臂里,按 `errorCode` 判、`errorMessage` 读句子即可。
|
|
2366
|
+
* **≤7.124.x** 的跟随方拿到的是首请求的 **JSON 拒绝体原样**(键是 `error` / `errorCode` / …,**没有** `status` / `errorMessage`),不在五臂的形里:带 `activeTaskId` 的会落进冲突臂的窄化却读不到 `errorMessage`。
|
|
2367
|
+
* 老 server 的读法:拒绝类终帧一律先按 `errorCode` 判,`errorMessage` 缺席时回落读 `error` —— 这条回落分支只为 ≤7.124.x,支持底线抬过 7.124.x 之后可删。
|
|
2368
|
+
*/
|
|
2369
|
+
export type DoneFrameResult = (TaskResult & NotReplay) | (ActiveRunConflictDoneResult & NotReplay) | (LegacyPlaneTaskResult & NotReplay) | RunReplayRecord | (SubmitRefusalDoneResult & NotReplay);
|
|
2274
2370
|
/** Run list item (`GET /v1/tasks` items) — the live cheap `runSummary` shape (service Drift 1).
|
|
2275
2371
|
* NOTE wire names: `id` (not taskId), `startedAt` (not createdAt), `costMicroUsd` (micro-USD); no sessionId. */
|
|
2276
2372
|
export interface TaskSummary {
|
|
@@ -4215,7 +4311,11 @@ export interface Capabilities {
|
|
|
4215
4311
|
* 🔴 **7.116.0 的位值变化**:`A2A_SERVE_ENABLED=true` 而**没有 durable run store** 的部署(`DB_BACKEND=memory`、多租户裸起)上,本位由 `true` 变 `false`
|
|
4216
4312
|
* —— 那里它广告的两条路由本来就恒拒(7.115.x:卡照发 200,`message/send` / `tasks/get` 恒答 JSON-RPC `-32004`);现在卡与 RPC 都 404,起服日志一行 warn
|
|
4217
4313
|
* `a2a_serve_not_served`(`reason` 点名成因)。对端 orchestrator 对这种部署拉卡由 200 变 404(与旋钮关同一形)。出路:`DB_BACKEND=mysql|pg|local`,或关掉 `A2A_SERVE_ENABLED`。
|
|
4218
|
-
* 旧注「server 刻意不把 runStore 折进本位」**作废**(位与路由门现读同一只事实,「位说有而端点恒拒」结构上不可能)。
|
|
4314
|
+
* 旧注「server 刻意不把 runStore 折进本位」**作废**(位与路由门现读同一只事实,「位说有而端点恒拒」结构上不可能)。
|
|
4315
|
+
*
|
|
4316
|
+
* **server ≥7.125.0(契约 §0.7,提交幂等)**:A2A `message/send` 与 HTTP 提交面共用同一个幂等作用域(资源族 `run`;键由消息的 `messageId`、内容、`contextId` 与 skill id 派生,再按调用方身份加盐)——
|
|
4317
|
+
* 重投命中既有 run ⇒ **立即**回那条 task 的协议对象(不进 `blocking` 等待);命中的行调用方读不到、或它指向另一条 run ⇒ JSON-RPC **`-32602`**(Invalid params),
|
|
4318
|
+
* 与 HTTP 面的 409 `conflict.run_exists` 是同一个拒绝(协议渲染归 A2A 腿,体里不回显那一行的任何标识)。本包不含 A2A 协议客户端,此条只是文档。 */
|
|
4219
4319
|
a2aServe?: boolean;
|
|
4220
4320
|
/** 后台 agent **名册读面** `GET /v1/agents/roster` 的位(server `routes/capabilities.ts:640` =
|
|
4221
4321
|
* `Boolean(deps.backgroundAgentStore)`;#A1)。谓词**逐字**是那条路由的 501 门 ⇒「说 yes ⟺ 路由真能用」
|
|
@@ -4378,6 +4478,17 @@ export interface Capabilities {
|
|
|
4378
4478
|
* 🔴 **每台宿主一份**:保管店在 `<数据根>/sealed-key/`;多副本不共享这个目录时各副本答的公钥不同,对着 A 副本公钥封的密文在
|
|
4379
4479
|
* B 副本上是 `stale_ciphertext`(逐模型响亮失败)。出路 = 共享保管目录,或走中心形。 */
|
|
4380
4480
|
sealedKey?: SealedKeyCapability;
|
|
4481
|
+
/** **工作区跨轮保留**(server ≥7.125.0;铸点 `routes/capabilities.ts` 的能力对象成员 `workspaceSync`,值 = 能力事实 `workspaceSpace` 的见证 `{ persist, keep }`;契约附录 B.1 / B.1a)——
|
|
4482
|
+
* k8s 车道的 `/workspace` 按**会话住客**(会话化身;会话删掉后同一 id 重新登记 = 新空间、从空目录开始)存进对象存储:每条 run 结束把工作区快照进 `<前缀>/<化身>/space/`(这条车道独占的子前缀;停驻挂起快照在它外面、从不被删旧)、
|
|
4483
|
+
* 移动 `space/latest` 指针、只留最近 {@link WorkspaceSyncCapability.keep} 份;下一条 run 开始(连上沙箱时)按 `latest` 恢复;本副本读不到会话住客 ⇒ 该 run 既不恢复也不保存(运维行),不按会话 id 兜底。
|
|
4484
|
+
* 🔴 **缺省 `off`**(持久化是 opt-in):壳 / 中心只在 `persist:"space"` 时渲「工作文件跨轮保留」。
|
|
4485
|
+
* 🔴 **present-iff**(能力面三个逐键例外之一,与 {@link sealedKey} / {@link centerWiring} 同册,契约附录 B.1):设施 = **k8s 车道 ∧ 快照存储**(`MINIO_ENDPOINT` / `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY` 三键齐)。
|
|
4486
|
+
* 缺席是**键不在**,不是 `false` / `null` / `{}`(判 `caps.workspaceSync !== undefined`);缺席有**两种含义、同一个动作**:① 老 server(< 7.125.0,不认识这一位);② 这台部署不是 k8s 车道,或 k8s 车道没配快照存储
|
|
4487
|
+
* (起服一行 `workspace_persist_unavailable` 点名缺键)—— 同一体的 `version` 能分。不论哪种:**别**承诺「上一轮的文件还在」,每条 run 的工作区按空目录对待。
|
|
4488
|
+
* `persist:"off"` = 存储在、但没开(缺省,或运维显式关;能力在、今天不保留),**与缺席不同义**。
|
|
4489
|
+
* 只盖 `/workspace`(进程 / 内存态不跨轮)。**失败是响亮的**:读 `latest` 或提交标记失败、`latest` 指向的快照对象不在、或恢复中途失败 ⇒ 该 run 连沙箱失败(不静默给空目录,残缺目录不给工具用也不会被快照回去);
|
|
4490
|
+
* run 末快照失败 ⇒ 舰队终态 `task` 帧带残局键 `workspaceSnapshot: "failed"`({@link import("./resources/fleet.js").FleetTaskRow.workspaceSnapshot}),下一条 run 恢复的是**上一份** `latest`。 */
|
|
4491
|
+
workspaceSync?: WorkspaceSyncCapability;
|
|
4381
4492
|
/** **会话后台任务两口的在场位**(server ≥7.102.0 / S-745 / core 7.32.0 #1107;铸点 `routes/capabilities.ts:308` =
|
|
4382
4493
|
* `{ listFace: sessionBackgroundFacesAvailable(deps), exitFaces: sessionBackgroundFacesAvailable(deps) }`,与两口的 501
|
|
4383
4494
|
* **同一只谓词**:会话属主面 `sessionStorage.ownerOf` 在场 ⇒「说 yes 但 501」结构上不可能;缺它 ⇒ 两位显式 `false`、
|
|
@@ -4853,6 +4964,11 @@ export interface SessionRecord {
|
|
|
4853
4964
|
provider: string;
|
|
4854
4965
|
modelId: string;
|
|
4855
4966
|
} | null;
|
|
4967
|
+
/** The engine's message rows (opaque to the SDK — typed `unknown`; the shapes are the engine's, not this package's).
|
|
4968
|
+
* 🔴 **server ≥7.125.0 (the one key the server itself adds, 契约 §20)**: a `role: "user"` row may carry the rewind handle `taskId` — see {@link SessionUserMessageRow}
|
|
4969
|
+
* (the `taskId` of the run that submitted that prompt; hand it to `resumeAt` to rewind to just before it). It is on **every** way of fetching the rows (whole read / `tail` /
|
|
4970
|
+
* `before` / `blobCap` / `?message=N`), and is **present-iff** the anchor store holds exactly one row for that user entry owned by the reader — an absent key is NOT an error
|
|
4971
|
+
* (see the type for the four absences). assistant / toolResult / other-role rows never carry it. */
|
|
4856
4972
|
messages: unknown[];
|
|
4857
4973
|
/** Present ONLY on a windowed read (`tail`/`before`) against server ≥1.162. */
|
|
4858
4974
|
window?: SessionWindow;
|
|
@@ -4883,6 +4999,22 @@ export interface SessionRecord {
|
|
|
4883
4999
|
}>;
|
|
4884
5000
|
[k: string]: unknown;
|
|
4885
5001
|
}
|
|
5002
|
+
/** 🔴 **server ≥7.125.0**(契约 §20)—— `SessionRecord.messages` 里 `role: "user"` 一行的**服务铸键**(这是服务端在引擎消息形之上添的**唯一一键**;`messages` 其余形状属引擎、本包不替它声明)。
|
|
5003
|
+
* 用法:`session.messages` 的元素是 `unknown`;读用户行的回退手柄时先按 `role === "user"` 窄到本型(本包不替引擎的消息联合起名)。
|
|
5004
|
+
* `taskId`(串)= 回退时交给 {@link TaskRequest.resumeAt} 的那个手柄(该条提示词所在 run 的 `taskId`)。端侧回退 = 既有 `POST /v1/runs`(或 `/v1/tasks`)
|
|
5005
|
+
* `{ sessionId, resumeAt: <taskId> }`,零新动词;同一枚手柄出现在 `GET /v1/sessions/:id` 的**所有**取法上(整读 / `tail` / `before` / `blobCap` / `?message=N`)。
|
|
5006
|
+
* 🔴 **present-iff**:锚店(`resume_anchor`)里**恰好一行** `entry_id` = 这条用户条目、`owner` = 读者(读这张视图的已验身份;无身份 = 无属主)——
|
|
5007
|
+
* 与 `resumeAt` 的解析**同一只谓词**,所以行上出现的手柄读者拿去回退一定解得出。**缺席**有四种,都不是错误、都不许读成「这条不能回退」以外的别的意思:
|
|
5008
|
+
* ① 更老的条目(锚是后来才开始写的,不做一次性回填);② 锚是别人的(混属主会话);③ 同一条目被两行锚点名(不挑);④ 非流式 `POST /v1/tasks` 提交的提示词**没有锚**
|
|
5009
|
+
* (今天只有耐久腿写用户消息锚:`POST /v1/runs`、`POST /v1/tasks/stream`、续跑腿;拿那条 run 的 `taskId` 去 `resumeAt` 也是 404 `resume_at.unknown_event`,与本键缺席同一事实)。
|
|
5010
|
+
* 同一条 run 里后来的用户消息(steer)会把这条 run 的锚挪到最后提交的那一条上(锚按 `taskId` 键入)⇒ 手柄出现在那一条上。
|
|
5011
|
+
* 值是服务铸的标识符,逐字(不脱敏);老 server(≤7.124.x)的用户行没有这个键。assistant / toolResult / 其余角色行**没有**这个键。 */
|
|
5012
|
+
export interface SessionUserMessageRow {
|
|
5013
|
+
role: "user";
|
|
5014
|
+
/** 回退手柄(见本型顶注的四种缺席)。 */
|
|
5015
|
+
taskId?: string;
|
|
5016
|
+
[k: string]: unknown;
|
|
5017
|
+
}
|
|
4886
5018
|
/** The `window` companion of a windowed session read: `messages` is the slice
|
|
4887
5019
|
* `[offset, offset+messages.length)` of `total`. `offset` is stable within one `floorEntryId`
|
|
4888
5020
|
* generation — compaction swaps the generation (floorEntryId changes) ⇒ re-pull from scratch. */
|
|
@@ -4897,6 +5029,8 @@ export interface SessionMessageEnvelope {
|
|
|
4897
5029
|
sessionId: string;
|
|
4898
5030
|
floorEntryId?: string | null;
|
|
4899
5031
|
index: number;
|
|
5032
|
+
/** The one message at `index`, verbatim (opaque `unknown`). Server ≥7.125.0: a `role: "user"` message carries the same present-iff rewind handle `taskId` as on the
|
|
5033
|
+
* whole-record read — see {@link SessionUserMessageRow}. */
|
|
4900
5034
|
message: unknown;
|
|
4901
5035
|
[k: string]: unknown;
|
|
4902
5036
|
}
|
|
@@ -4930,8 +5064,16 @@ export interface SessionSummary {
|
|
|
4930
5064
|
/** 🔴 facade 审计(2026-07-24,批次②-11):server security.ts:12-24 权威 `SessionListItem`(handleSessionList
|
|
4931
5065
|
* 直接透传给 sendJson,零裁剪;类型自述"Mirrors SessionSummary shape so the wire response is unchanged")
|
|
4932
5066
|
* 真实带这个字段——会话自动摘要(session-titler.ts,首次提交后台起一次廉价模型调用生成,IS NULL 门控幂等,
|
|
4933
|
-
* SESSION_AUTO_TITLE 默认开)。null = 未生成(自动摘要关闭 / 该 session 首次提交后台任务还没跑完)。
|
|
5067
|
+
* SESSION_AUTO_TITLE 默认开)。null = 未生成(自动摘要关闭 / 该 session 首次提交后台任务还没跑完)。
|
|
5068
|
+
* 🔴 **server ≥7.125.0 起这一列有两个写者、一条律**(契约 §20):用户经 {@link import("./resources/sessions.js").SessionsResource.patch} **无条件**写
|
|
5069
|
+
* (串 = 改名;`null` = 清回自动标题,列回 NULL);自动标题器**只填 NULL**(每次提交按列读一次,是 NULL 才起名)。所以读法是「用户写的串,否则自动标题器的,否则 `null`」——
|
|
5070
|
+
* 把它当「恒为自动标题」读的消费方要改读法;用户写过串的会话自动标题器永不覆盖,用户清掉之后下一次提交由自动标题器照常再填。≤7.124.x 只有自动标题器写它。 */
|
|
4934
5071
|
title: string | null;
|
|
5072
|
+
/** 🔴 **server ≥7.125.0**(契约 §20)—— 用户置顶位(`PATCH /v1/sessions/:id` 写,{@link import("./resources/sessions.js").SessionsResource.patch})。
|
|
5073
|
+
* 在 ≥7.125.0 上**恒在场**(不是 present-iff:置顶是会话的状态,不是能力),缺省 `false`;没有会话元数据的老形枚举面(内存 run 店聚合)也恒答 `false`(那里也没有可写口)。
|
|
5074
|
+
* **缺席 = 老 server(≤7.124.x)**——按「没有置顶」读,别读成错误。排序不变(仍按 `lastActivityAt` 新近序),置顶段由端侧按本位分组;
|
|
5075
|
+
* 改名 / 置顶**不动** `lastActivityAt`;服务重启后置顶位仍在(两种后端同读数)。 */
|
|
5076
|
+
pinned?: boolean;
|
|
4935
5077
|
/** server ≥7.91.0(additive,老 server 缺席):会话活动词,由最近 run 的状态经 server 与 peer 目录**同一张**映射表派生
|
|
4936
5078
|
* (running → `active`;suspended / needs_review → `blocked`;无非终态 run → `idle`)。壳的会话列表 / peer 行 tempo 同源。 */
|
|
4937
5079
|
tempo?: "active" | "idle" | "blocked";
|
|
@@ -5336,6 +5478,14 @@ export interface SessionManifest {
|
|
|
5336
5478
|
fileHistory?: FileHistoryExport | null;
|
|
5337
5479
|
policy: SessionRulesRecord[];
|
|
5338
5480
|
anchors: SyncAnchor[];
|
|
5481
|
+
/** 🔴 **server ≥7.125.0**(契约 §20)—— 会话行的标题,经**列表行同一只投影**读(与 {@link SessionSummary.title} 同一个值:用户写的串,否则自动标题器的)。
|
|
5482
|
+
* `null` = 没有标题;**把它推给目的端的 PUSH(`sessions.sync.import` Phase A 的 `title`)会把目的端清回自动标题**——与 `sessions.patch({ title: null })` 同一条律。
|
|
5483
|
+
* **present-iff 这只会话是列表面上的一行**:普通会话恒在,子代转录(placed)会话两键都缺席;**缺席 = 老 server(≤7.124.x)或子代转录会话**,按「不带」读。
|
|
5484
|
+
* 不在 `basis` / `payloadVerified` 的判据里(那两键只说对话日志)。
|
|
5485
|
+
* 编排 verb({@link import("./sync.js").pushSessionBundle} / {@link import("./sync.js").importSessionBundle})不走 Phase A 体,而是日志搬完之后经 `sessions.patch` 把这两位镜像到目的端(结果面 `rowBits`)。 */
|
|
5486
|
+
title?: string | null;
|
|
5487
|
+
/** 🔴 **server ≥7.125.0**(契约 §20)—— 会话行的置顶位(同 {@link SessionSummary.pinned};present-iff 与 {@link title} 同一条)。 */
|
|
5488
|
+
pinned?: boolean;
|
|
5339
5489
|
}
|
|
5340
5490
|
/** The portable state of ONE session, ready to replay into another backend (mirrors session-sync.ts SessionBundle:193).
|
|
5341
5491
|
* Blobs are deliberately NOT inlined — each snapshot carries only its `manifest`; the bytes stream through the
|