@sema-agent/client-core 0.35.0 → 0.37.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 +241 -0
- package/README.md +1 -1
- package/dist/adapt/arms.js +3 -0
- package/dist/adapter/activeRunSelfHeal.d.ts +35 -2
- package/dist/adapter/activeRunSelfHeal.js +157 -4
- package/dist/adapter/downstream/eventToSdkMessage.js +5 -0
- package/dist/adapter/runStream.d.ts +63 -1
- package/dist/adapter/runStream.js +38 -0
- package/dist/engineCapsCache.d.ts +48 -2
- package/dist/engineCapsCache.js +157 -11
- package/dist/fleet/fleetProjection.d.ts +9 -1
- package/dist/fleet/fleetProjection.js +13 -3
- package/dist/fleetTaskDesc.d.ts +5 -1
- package/dist/fleetTaskDesc.js +39 -2
- package/dist/hitl/armedGateRegistry.js +11 -3
- package/dist/hitl/hitlBridge.d.ts +20 -0
- package/dist/hitl/hitlBridge.js +156 -12
- package/dist/hitl/parkResolver.d.ts +1 -0
- package/dist/hitl/parkResolver.js +22 -2
- package/dist/hitl/toolApprovalWire.d.ts +88 -7
- package/dist/hitl/toolApprovalWire.js +50 -6
- package/dist/request/taskRequest.js +11 -11
- package/dist/retryStatus.d.ts +38 -3
- package/dist/retryStatus.js +15 -5
- package/dist/toolResult.d.ts +8 -0
- package/dist/toolResult.js +15 -0
- package/docs/INTEGRATION-CLIENTS.md +20 -19
- package/package.json +2 -2
package/dist/retryStatus.d.ts
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* recovered → null → 覆盖层摘掉(重试**成功**,不是错误 —— 见下)
|
|
10
10
|
* gave_up → error+terminal → '✻ <detail>'(重试用尽的终态;与 recovered 反向。**打 terminal 位**,
|
|
11
11
|
* 渲染面据此不得再接「· Retrying in Ns」——已经没有下一次了)
|
|
12
|
-
* 绝不捏造 attempt 计数——只用引擎真给的 phase / detail / retryInSec / retryInMs / attempt /
|
|
12
|
+
* 绝不捏造 attempt 计数——只用引擎真给的 phase / detail / retryInSec / retryInMs / attempt /
|
|
13
|
+
* maxRetries / errClass(core 5.43.0 起七键)。
|
|
13
14
|
*
|
|
14
15
|
* 🔴 员数与字段补全(2026-08-08,#3004 跟修批)。此前本文件只列 4 相 + 3 字段,而引擎侧
|
|
15
16
|
* (core `BrainStatusPhase` / `BrainStatus`,dist/core/types.d.ts)是 **6 相 + 6 字段**,server 两腿的
|
|
@@ -30,11 +31,15 @@ export type RetryStatus =
|
|
|
30
31
|
deadline: number;
|
|
31
32
|
attempt?: number;
|
|
32
33
|
maxRetries?: number;
|
|
34
|
+
/** 见 {@link BrainStatusPayload.errClass}(引擎给了才在场;本层只透传,措辞是壳半场)。 */
|
|
35
|
+
errClass?: BrainRetryErrClass | (string & {});
|
|
33
36
|
} | {
|
|
34
37
|
kind: 'error';
|
|
35
38
|
deadline: number;
|
|
36
39
|
attempt?: number;
|
|
37
40
|
maxRetries?: number;
|
|
41
|
+
/** 见 {@link BrainStatusPayload.errClass}(引擎给了才在场;本层只透传,措辞是壳半场)。 */
|
|
42
|
+
errClass?: BrainRetryErrClass | (string & {});
|
|
38
43
|
/**
|
|
39
44
|
* 🔴 **终态位**(2026-08-08 对抗复审命中):`true` ⇔ 引擎**不会再重试了**(`gave_up` 相)。
|
|
40
45
|
* 缺席 = 仍在重试循环里(retrying / rate_limited / circuit_open)。
|
|
@@ -65,7 +70,23 @@ export type RetryStatus =
|
|
|
65
70
|
*/
|
|
66
71
|
export declare const BRAIN_STATUS_PHASES: readonly ["rate_limited", "retrying", "reconnecting", "circuit_open", "recovered", "gave_up"];
|
|
67
72
|
export type BrainStatusPhase = (typeof BRAIN_STATUS_PHASES)[number];
|
|
68
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* core `BrainRetryErrClass`(5.43.0)的**类型面镜像** —— 一次重试等待的**原因分桶**,
|
|
75
|
+
* provider 中立(绝不是 HTTP 状态码 / syscall code / provider 分类法;那些不许过这条通道):
|
|
76
|
+
* · `connect_refused` 目标本身给了确定否定(该地址没人 accept / 名字无地址)—— 短梯队服务的那一类;
|
|
77
|
+
* · `transport` 其余传输层失败(connect 超时 / reset / 流中断 / 流停滞)—— 全梯队;
|
|
78
|
+
* · `rate_limit` provider 要求放慢;
|
|
79
|
+
* · `server` provider 自报自己这边出错;
|
|
80
|
+
* · `http` 状态谓词判终态、但 provider 自己的显式重试裁定说重试;
|
|
81
|
+
* · `output_cap` 根本不是连接失败:provider 报上下文超限后按更低 output cap 重发(无退避)。
|
|
82
|
+
*
|
|
83
|
+
* 🔴 **刻意没有运行期值镜像**(与 {@link BRAIN_STATUS_PHASES} 不同):本包对 errClass **零分支**
|
|
84
|
+
* (纯透传),少一个成员没有任何行为后果 —— 开集读会把不认得的桶原样带过去。而 phase 是有 switch
|
|
85
|
+
* 分支的,少一相会落 default 臂被渲成错话,所以那张表才需要运行期镜像 + engine-vocab 等值门。
|
|
86
|
+
* 判据锚在「真正决定结果的量」上:决定结果的是有没有分支,不是有没有一张表。
|
|
87
|
+
*/
|
|
88
|
+
export type BrainRetryErrClass = 'connect_refused' | 'transport' | 'rate_limit' | 'server' | 'http' | 'output_cap';
|
|
89
|
+
/** wire 上 `status` 臂的载荷(= core `BrainStatus`;server 两腿白名单原样转发这 7 键)。 */
|
|
69
90
|
export interface BrainStatusPayload {
|
|
70
91
|
/** 闭集 + `(string & {})`:未知相仍可携带(开集读),不必先改类型再解析。 */
|
|
71
92
|
phase: BrainStatusPhase | (string & {});
|
|
@@ -79,13 +100,27 @@ export interface BrainStatusPayload {
|
|
|
79
100
|
attempt?: number;
|
|
80
101
|
/** 引擎这一轮的重试上限。与 `attempt` 一起才能渲「2/5」。 */
|
|
81
102
|
maxRetries?: number;
|
|
103
|
+
/**
|
|
104
|
+
* core 5.43.0(#307 双扫 S44,2026-08-19;ADDITIVE)——**这次等待的原因分桶**
|
|
105
|
+
* (core `BrainRetryErrClass`,provider 中立闭集)。与 `phase`(引擎正在**做什么**)互补:
|
|
106
|
+
* 本键说的是**为什么**。只在**重试等待帧**上在场且引擎分得出类;`recovered`/`gave_up` 两个终态帧
|
|
107
|
+
* 与 `circuit_open`(本地快失败,不是观测到的失败)上刻意缺席。
|
|
108
|
+
*
|
|
109
|
+
* 🔴 **闭集 + `(string & {})`,读时按开集处理**,与 `phase` 同款纪律:一个部署可以在自己的通道上
|
|
110
|
+
* 冒出别的桶,认得的照走、认不得的原样带过去 —— 绝不因为「不认得」就把这次等待的原因抹成缺席
|
|
111
|
+
* (那是把引擎真给的量在本层剥掉,#3004 那批修的正是这一类)。
|
|
112
|
+
* 缺席 = 引擎没分类,**不得**被渲成某个默认桶。
|
|
113
|
+
*
|
|
114
|
+
* 分工:本包只负责让这个事实到得了壳(投影/透传保真),措辞与是否上屏是壳半场。
|
|
115
|
+
*/
|
|
116
|
+
errClass?: BrainRetryErrClass | (string & {});
|
|
82
117
|
}
|
|
83
118
|
/**
|
|
84
119
|
* 上面那个 interface 的**运行期键镜像**(照 `TOOL_APPROVAL_FRAME_KEYS_MIRROR` 先例):
|
|
85
120
|
* engine-vocab 门 G2-c 拿它与 core `BrainStatus` 的键集逐元素比 ⇒ 引擎 additive 增键当天红。
|
|
86
121
|
* 下面两个类型钉保证镜像与 interface 之间不可能漂移(少键/多键都是编译错)。
|
|
87
122
|
*/
|
|
88
|
-
export declare const BRAIN_STATUS_PAYLOAD_KEYS: readonly ["phase", "detail", "retryInSec", "retryInMs", "attempt", "maxRetries"];
|
|
123
|
+
export declare const BRAIN_STATUS_PAYLOAD_KEYS: readonly ["phase", "detail", "retryInSec", "retryInMs", "attempt", "maxRetries", "errClass"];
|
|
89
124
|
/**
|
|
90
125
|
* BrainStatus 载荷 → spinner 行状态。
|
|
91
126
|
*
|
package/dist/retryStatus.js
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* recovered → null → 覆盖层摘掉(重试**成功**,不是错误 —— 见下)
|
|
10
10
|
* gave_up → error+terminal → '✻ <detail>'(重试用尽的终态;与 recovered 反向。**打 terminal 位**,
|
|
11
11
|
* 渲染面据此不得再接「· Retrying in Ns」——已经没有下一次了)
|
|
12
|
-
* 绝不捏造 attempt 计数——只用引擎真给的 phase / detail / retryInSec / retryInMs / attempt /
|
|
12
|
+
* 绝不捏造 attempt 计数——只用引擎真给的 phase / detail / retryInSec / retryInMs / attempt /
|
|
13
|
+
* maxRetries / errClass(core 5.43.0 起七键)。
|
|
13
14
|
*
|
|
14
15
|
* 🔴 员数与字段补全(2026-08-08,#3004 跟修批)。此前本文件只列 4 相 + 3 字段,而引擎侧
|
|
15
16
|
* (core `BrainStatusPhase` / `BrainStatus`,dist/core/types.d.ts)是 **6 相 + 6 字段**,server 两腿的
|
|
@@ -46,6 +47,8 @@ export const BRAIN_STATUS_PAYLOAD_KEYS = [
|
|
|
46
47
|
'retryInMs',
|
|
47
48
|
'attempt',
|
|
48
49
|
'maxRetries',
|
|
50
|
+
// core 5.43.0 跟车一键(#307 双扫 S44,2026-08-19):engine-vocab G2-c 对实装 core 逐键对账。
|
|
51
|
+
'errClass',
|
|
49
52
|
];
|
|
50
53
|
const _brainStatusKeyPin = [true, true];
|
|
51
54
|
void _brainStatusKeyPin;
|
|
@@ -64,19 +67,26 @@ export function mapBrainStatusToRetry(p, nowMs) {
|
|
|
64
67
|
...(typeof p.attempt === 'number' ? { attempt: p.attempt } : {}),
|
|
65
68
|
...(typeof p.maxRetries === 'number' ? { maxRetries: p.maxRetries } : {}),
|
|
66
69
|
};
|
|
70
|
+
/**
|
|
71
|
+
* 原因桶(#307 S44):引擎真给的**非空串**才落位。缺席 / 空串 / 非串 ⇒ 键不 stamp
|
|
72
|
+
* ——「不知道为什么等」渲成缺席,绝不折成某个默认桶。开集:不认得的桶原样带过去
|
|
73
|
+
* (本层零分支,认不得也没有可落错的臂)。
|
|
74
|
+
*/
|
|
75
|
+
const cause = typeof p.errClass === 'string' && p.errClass.length > 0 ? { errClass: p.errClass } : {};
|
|
67
76
|
switch (p.phase) {
|
|
68
77
|
// 🔴 引擎直报「恢复」:摘行。绝不落 error 臂 —— 那是把成功渲成失败。
|
|
69
78
|
case 'recovered':
|
|
70
79
|
return null;
|
|
71
80
|
case 'reconnecting':
|
|
72
|
-
return { kind: 'stalled', deadline, ...counts };
|
|
81
|
+
return { kind: 'stalled', deadline, ...counts, ...cause };
|
|
73
82
|
case 'rate_limited':
|
|
74
|
-
return { kind: 'error', deadline, ...counts, error: { formatted: '', rateLimits: {} } };
|
|
83
|
+
return { kind: 'error', deadline, ...counts, ...cause, error: { formatted: '', rateLimits: {} } };
|
|
75
84
|
case 'circuit_open':
|
|
76
85
|
return {
|
|
77
86
|
kind: 'error',
|
|
78
87
|
deadline,
|
|
79
88
|
...counts,
|
|
89
|
+
...cause,
|
|
80
90
|
error: { formatted: p.detail ?? 'Service temporarily unavailable', isNetworkDown: true },
|
|
81
91
|
};
|
|
82
92
|
// 重试用尽:仍是错误行(与 recovered 反向,绝不许一起归成「结束了 ⇒ 清行」),但**打终态位** ——
|
|
@@ -84,9 +94,9 @@ export function mapBrainStatusToRetry(p, nowMs) {
|
|
|
84
94
|
// retrying'),既没有计数也没有 retryIn*,所以「不会再重试了」这件事**只能**由本位表达;
|
|
85
95
|
// 靠 attempt===maxRetries 去推是错的(供给方根本不发那两位)。
|
|
86
96
|
case 'gave_up':
|
|
87
|
-
return { kind: 'error', deadline, terminal: true, ...counts, error: { formatted: p.detail ?? '' } };
|
|
97
|
+
return { kind: 'error', deadline, terminal: true, ...counts, ...cause, error: { formatted: p.detail ?? '' } };
|
|
88
98
|
case 'retrying':
|
|
89
99
|
default:
|
|
90
|
-
return { kind: 'error', deadline, ...counts, error: { formatted: '' } };
|
|
100
|
+
return { kind: 'error', deadline, ...counts, ...cause, error: { formatted: '' } };
|
|
91
101
|
}
|
|
92
102
|
}
|
package/dist/toolResult.d.ts
CHANGED
|
@@ -8,6 +8,14 @@ import { type ModelFallbackReason } from './engineErrorCodes.js';
|
|
|
8
8
|
* 反过来,一个 `{type:'something-else'}` 或裸对象**不算** structured 在场 —— 宁可回落到正则,
|
|
9
9
|
* 也不许把「有个对象」当成「引擎发了结构化」(判据锚在决定结果的量上:决定的是「该不该信正则」)。
|
|
10
10
|
* ⚠️ 与设计稿的口径差:任务书写「29 项」,[1840] 清单逐条数是 **30 项**(见交接报告「设计稿错漏」)。
|
|
11
|
+
*
|
|
12
|
+
* 🔴 **本表是 core `CC_DETAIL_TYPES` 的镜像,不是本包自铸的词表**(core
|
|
13
|
+
* `dist/core/runner/tool-output-projection.js`)。等值由 `scripts/run-engine-vocab-floor-test.mjs` ⑤ 段
|
|
14
|
+
* 对**实装 core** 双向钉(漏一词 / 多一词都红),对账物 = 本仓 devDep `@sema-agent/core`。
|
|
15
|
+
* ⇒ **core 提货窗必须跟车对表**:每次抬 devDep core 版本,先跑 engine-vocab 门看这张表红不红,
|
|
16
|
+
* 红了按 core 那一版的铸点逐词补/删,别改门去迁就表。历史上两次恒绿(5.10 前停 devDep 5.1、
|
|
17
|
+
* 5.43 前停 devDep 5.20)的病根都不在表本身,在**对账物没跟着抬** —— 表漏一词的实际后果是
|
|
18
|
+
* 那一类卡永远退回正则解模型面文本,而任何一层都不会响。
|
|
11
19
|
*/
|
|
12
20
|
export declare const STRUCTURED_DETAIL_TYPES: ReadonlySet<string>;
|
|
13
21
|
/** structured 在场判别:顶层 `type` ∈ 白名单 ⇒ 返回该 type,否则 undefined(= 不在场)。 */
|
package/dist/toolResult.js
CHANGED
|
@@ -39,6 +39,14 @@ import { asModelFallbackReason } from './engineErrorCodes.js';
|
|
|
39
39
|
* 反过来,一个 `{type:'something-else'}` 或裸对象**不算** structured 在场 —— 宁可回落到正则,
|
|
40
40
|
* 也不许把「有个对象」当成「引擎发了结构化」(判据锚在决定结果的量上:决定的是「该不该信正则」)。
|
|
41
41
|
* ⚠️ 与设计稿的口径差:任务书写「29 项」,[1840] 清单逐条数是 **30 项**(见交接报告「设计稿错漏」)。
|
|
42
|
+
*
|
|
43
|
+
* 🔴 **本表是 core `CC_DETAIL_TYPES` 的镜像,不是本包自铸的词表**(core
|
|
44
|
+
* `dist/core/runner/tool-output-projection.js`)。等值由 `scripts/run-engine-vocab-floor-test.mjs` ⑤ 段
|
|
45
|
+
* 对**实装 core** 双向钉(漏一词 / 多一词都红),对账物 = 本仓 devDep `@sema-agent/core`。
|
|
46
|
+
* ⇒ **core 提货窗必须跟车对表**:每次抬 devDep core 版本,先跑 engine-vocab 门看这张表红不红,
|
|
47
|
+
* 红了按 core 那一版的铸点逐词补/删,别改门去迁就表。历史上两次恒绿(5.10 前停 devDep 5.1、
|
|
48
|
+
* 5.43 前停 devDep 5.20)的病根都不在表本身,在**对账物没跟着抬** —— 表漏一词的实际后果是
|
|
49
|
+
* 那一类卡永远退回正则解模型面文本,而任何一层都不会响。
|
|
42
50
|
*/
|
|
43
51
|
export const STRUCTURED_DETAIL_TYPES = new Set([
|
|
44
52
|
'edit',
|
|
@@ -102,6 +110,13 @@ export const STRUCTURED_DETAIL_TYPES = new Set([
|
|
|
102
110
|
// `path_not_in_root`/`readonly_out_of_root` 同族(参数拒绝的结构化错误卡)。
|
|
103
111
|
'ask-question',
|
|
104
112
|
'bash_invalid_timeout',
|
|
113
|
+
// ── core 5.43.0 跟车一词(#307 双扫 S43,2026-08-19;engine-vocab 等值门对 5.43+ 实装物直证)──
|
|
114
|
+
// `read_path_denied` = fs 安全层拒读的结构化错误卡(core `dist/tools/fs/safety.js` 的
|
|
115
|
+
// `return { type: "read_path_denied", … }` 铸点),与 `path_not_in_root`(shell 面)/
|
|
116
|
+
// `readonly_out_of_root`(fs 写面)/ `bash_invalid_timeout`(参数面)同属「拒绝理由结构化」一族。
|
|
117
|
+
// 病根仍是对账物代际差:门锚本仓 devDep core,devDep 停 5.20.0 时该词还没铸 ⇒ 门恒绿。
|
|
118
|
+
// 修 = devDep 升 ^5.43.0(门当场翻红显出漂移)+ 补词,与 A-004.5 那批同一条路。
|
|
119
|
+
'read_path_denied',
|
|
105
120
|
]);
|
|
106
121
|
// 🔴 同批**删三词**(core 5.10.0 BREAKING「幽灵卡」清仓):`multiedit` / `memory-saved` /
|
|
107
122
|
// `memory-recall` —— 全树零铸点(MultiEdit/批量重放铸的是 `type:"edit"` 带 `edits[]`;core
|
|
@@ -15,22 +15,22 @@
|
|
|
15
15
|
|
|
16
16
|
## §0 版本锚与重扫纪律
|
|
17
17
|
|
|
18
|
-
### 0a. 版本锚(2026-08-
|
|
18
|
+
### 0a. 版本锚(2026-08-19)
|
|
19
19
|
|
|
20
20
|
| 项 | 值 | 真源 |
|
|
21
21
|
|---|---|---|
|
|
22
|
-
| 本包 | `@sema-agent/client-core` **0.
|
|
23
|
-
| peer:wire 契约 | `@sema-agent/sdk` **>=
|
|
22
|
+
| 本包 | `@sema-agent/client-core` **0.37.0** | `package.json` `version` |
|
|
23
|
+
| peer:wire 契约 | `@sema-agent/sdk` **>=7.1.0**(value-level,非 type-only) | `package.json` `peerDependencies` |
|
|
24
24
|
| peer:会话词汇表 | `@sema-agent/agent-types` **>=0.2.0**(type-only,零运行时) | 同上 |
|
|
25
25
|
| runtime dep | `diff` ^9.0.0(**唯一**一条;portability 门按**等值**钉死) | `package.json` `dependencies` |
|
|
26
|
-
| 公开导出面 | **
|
|
26
|
+
| 公开导出面 | **753** 个运行期符号(+ 39 个测试钩;= npm `0.37.0` 的值;`0.36.0` 是 **749**,见 `CHANGELOG.md`) | `scripts/public-export-baseline.json` 的 `count` / `testHookCount` —— **别手抄进别处,以该文件为准** |
|
|
27
27
|
| 常驻门 | 以 `scripts/gates-manifest.json` 的 `suites` 长度为准(**本档不抄这个数**) | `scripts/gates-manifest.json`;`npm test` 的名单等值门与它逐名对账 |
|
|
28
28
|
| 沿革档 | 0.29.0 起建 `CHANGELOG.md`;更早批次记账在 `src/index.ts` 文件头 + `docs/REFACTOR-LEDGER.md` | — |
|
|
29
29
|
|
|
30
|
-
⚠️
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
⚠️ 0.37.0 已于 2026-08-19 发布,本表与 npm 最新版重新对齐(工作树 = npm)。装旧版(≤0.36.0)的
|
|
31
|
+
端注意:0.37.0 新增的四个 additive 导出(`invalidateEngineCaps` 两参形、`escapeDisplayControlChars`、
|
|
32
|
+
`DecideTransportRetryExhaustedError`、`clearRunningChoiceOffer`)在旧版上按名 import 会**在 ESM
|
|
33
|
+
实例化当场炸**(具名导出不存在)—— 提货前先抬依赖。旧版对表以 `CHANGELOG.md` 对应版本段为准。
|
|
34
34
|
|
|
35
35
|
🔴 **本表里仍然手抄的数字都有门看着**(#252,2026-08-14):`scripts/run-integration-doc-freshness-test.mjs`
|
|
36
36
|
① 段把 638 / 32 / §2b 十六域名数之和 / 191 / 4 / 33 逐个对 `public-export-baseline.json` 算出来的值,
|
|
@@ -99,7 +99,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
99
99
|
|
|
100
100
|
## §2 公共导出面地图(按域)
|
|
101
101
|
|
|
102
|
-
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**
|
|
102
|
+
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**753** 项)。
|
|
103
103
|
> 本节**不逐名抄**,只给「域 → 承重导出 → 用途 → 实现锚」。承重导出 = 一个端为了让这个域干活
|
|
104
104
|
> **必须**直接调到的那几个符号;其余是它们的类型、变体与辅助位。
|
|
105
105
|
> 单一入口:`import { … } from '@sema-agent/client-core'`(`exports` 只有 `.` 一个;
|
|
@@ -109,7 +109,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
109
109
|
|
|
110
110
|
`public-export-baseline.json` 由 **`dist/index.js` 的运行期导出**生成(生成口径自述见
|
|
111
111
|
`scripts/run-client-core-typeshape-test.mjs`,双向精确集合门在 `scripts/run-public-surface-test.mjs`)。
|
|
112
|
-
实测:
|
|
112
|
+
实测:753 项 **100% 是运行期导出,零 type-only**。
|
|
113
113
|
|
|
114
114
|
**推论(端必须知道)**:
|
|
115
115
|
- barrel 导出的**类型**面比 707 大得多,且**不被这道门看守** —— `AdapterContext` / `SeamEvent` /
|
|
@@ -118,20 +118,20 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
118
118
|
端依赖这些类型是合法的,但**不要**拿基线 diff 当"类型面没变"的证据。
|
|
119
119
|
- `src/agentSession/contract.ts` 对基线贡献 **0** 项(纯类型模块,`export *` 在 dist 里是空转发)。
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
(矩阵、键集、env 名、锚串)而非可调用物;**
|
|
123
|
-
(`ControlRouter` / `ControlSafetyError` / `HitlBridge` / `HitlSafetyError`);
|
|
121
|
+
753 项的内部构成(帮助端估读表大小):**221** 项是 `SCREAMING_SNAKE` 常量数据表/词汇表
|
|
122
|
+
(矩阵、键集、env 名、锚串)而非可调用物;**5** 项是 PascalCase 运行期值
|
|
123
|
+
(`ControlRouter` / `ControlSafetyError` / `HitlBridge` / `HitlSafetyError` / `DecideTransportRetryExhaustedError`);
|
|
124
124
|
**39** 项是 `*For(sessionKey, …)` 的 per-session 变体(§6;其中 `engineNamespaceKeyFor` 是命名巧合 —— 参数是 baseUrl 不是 sessionKey,见域 14)。
|
|
125
125
|
|
|
126
|
-
### 2b. 域图(16 域,逐域计数之和 =
|
|
126
|
+
### 2b. 域图(16 域,逐域计数之和 = 753)
|
|
127
127
|
|
|
128
128
|
| # | 域 | 名数 | 承重导出 | 用途 | 实现锚 |
|
|
129
129
|
|---|---|---|---|---|---|
|
|
130
130
|
| 1 | **适配内核(下行主链)** | 33 | `adapt` · `createWireToCcAdapter` · `runStream` · `eventToSdkMessage` · `terminalToSdkResult` · `turnUsageToModelUsage` · `isRunStreamActive` · `ADAPTER_DIVERGENCES` | 引擎 SSE `AgentEvent` → 端要渲的**双面输出**:transcript(`SDKMessage`)+ chrome(瞬态 `ChromeEvent`)。**本包存在的理由** | `src/adapt.ts`、`src/adapt/{arms,wireShapes,panelTasks}.ts`(经 `adapt.ts` 再导出)、`src/adapter/runStream.ts`、`src/adapter/downstream/*`、`src/adapter/types.ts` |
|
|
131
131
|
| 2 | **seam 公共契约** | 2(其余为 type-only) | `CHROME_ARMS` · `deriveTranscriptId` | 公共词汇 + **id 确定性不变量**(同一条流重放 ⇒ 同一串 id)。`CHROME_ARMS` = 端「我要消费哪些 chrome 臂」的对照清单 | `src/seam.ts` |
|
|
132
|
-
| 3 | **HITL 决断卡链**(§4/§5 主战场) |
|
|
132
|
+
| 3 | **HITL 决断卡链**(§4/§5 主战场) | 120 | `makeHitlCanUseTool` · `HitlBridge` · `findPendingForTask` · `HitlSafetyError` · `bridgeAskUserQuestionGates` · `surfaceToolApprovalFrameAndRespond` / `surfaceFsApprovalAndDecide` · `readToolApprovalRespondAck` · `installApprovalCardPort(For)` · `installHitlHostSurface(For)` · `armPlanReviewApproval` · `reopenPlanReviewCard` · `decidePlanReview` · `startApprovalsFeed` · `pendingRowIsOwnedByThisSession` · `approvalCallKey`/`liveFrameCallKey`/`planReviewQuestionId` · `registerArmedGateFor`/`wasGateArmedFor`/`clearArmedGateFor` · `waitForGateArmed(For)`/`onGateArmed(For)`/`gateArmedWaitMs`(#244 F1 呈现回执事件源) · `planReviewArmedKey(For)`/`notePlanReviewAnswered(For)`/`notePlanReviewAnsweredIfDecisive(For)`(A-024.4 plan 呈现分代) · `toolEndOutputText` · `isAskTool` · `waitForParkRowBirth` · `classifyAskParkRows` / `askParkRowArm` / `classifyAskParkChainFailure` · `readDecisionNoteAudit` / `decisionNoteAuditLine` · `resumeRunningOptions` / `resumeChoiceFromLabels` · `persistedRulesLaneAvailable`/`persistedRulesGovernanceAvailable` · `classifyRulesFailure` · `listAllPersistedRules` · `classifySkippedReason` · `readRulePersistOutcome`(#244 F2:persist-ack 读口与 `readToolApprovalRespondAck` 合成一处) · `parseLocalAllowRule`(durable 腿本地落规则窄化骨架,谓词经 `LocalAllowRuleDeps` 注入) · `DecideTransportRetryExhaustedError`(Inkglow-1085 P0a:decide 出站瞬断重试耗尽的 typed 判别 —— HitlBridge 内建单次退避重试,耗尽走重呈臂不判死 turn;端一般只消费行为,不需要 instanceof) | suspended→decide→resume 环。🔴 **D-1 两元组 verbatim 回显**是字节级断言的安全不变量,端**不许重实现它的任何一段**。🔴 键空间边界(web [C1] d3 拦截):`gateIdentity` 四常量两函数只覆盖 HITL questionId/callKey 空间;seat 的 `TOOL_PERMISSION_REQUEST_ID_DOMAINS`(`plan:` 等)是另一键空间,**两者绝不合并**(合并=座位校验器静默拒全部 plan-review 卡) | `src/hitl/hitlBridge.ts`、`toolApprovalWire.ts`、`askGateWire.ts`、`planReviewWire.ts`、`hitlHostSurface.ts`、`gateIdentity.ts`、`armedGateRegistry.ts`、`parkOwnership.ts`、`parkResolver.ts`、`approvalsFeed.ts`、`frameRouter.ts`(**只挑名导出** `toolEndOutputText`/`ENGINE_ABORT_TOOL_RESULT`/`isAskTool`/`HITL_REJECT_MESSAGE`)、`parkRowBirthWait.ts`、`approvalDecisionNoteAudit.ts`、`askParkRowRouting.ts`、`resumeRunningCard.ts`(#265 上收的判定层)、`persistedRulesWire.ts`、`localAllowRule.ts`(#244 F2 规则侧) |
|
|
133
133
|
| 4 | **子代 wire + 面板侧信道台账** | 82 | `tailEngineSubagent` · `installSubagentActivitySink` · `installSubagentTailMetaSink`(#280 件2:tail meta 帧发布口,`contentFrames` 判别位载体)· `stopEngineTask` + `classifyTaskStopConflict` · `fetchEngineSubagentReport` · `steerEngineSubagent`(0.32.0 未发布 #280 件A:additive 第三参 `childTaskId` —— 端有行上下文时**应当**传,传了就走「台账优先 / 缺席即诚实缺席 + `noteBgOwnerAbsence` 留痕」的 Q3 口径,与 tail·taskOutput·subagentOutput 三腿同姿势、与孪生 resume 腿共用同一个 `resolveOwnerRunId` 判据;**不传**则逐字维持旧行为=回落在飞 run)· `resumeSettledSubagent` + `resolveSubagentResumeContext` + `resolveOwnerRunId` + `classifySubagentResumeFailure` + `subagentResumeAvailable`(#242 批 2 A-028.7:resume 判定半场上收,与 steer 孪生同居;取址三态 = 台账有行用行值 / 指名了行但台账缺席则**诚实缺席绝不回落在飞 run** / 没指名行才回落。出路文案归端)· `recordSubagentOwnerFromProgress` + `getBgParentRunOwner`(A-028.6:「子代 → 宿主 run」**单表**,宿主 run 必须由持 stream-local 值的调用方显式传入,包内绝不从 `activeEngineRunId()` 推断)· `noteBgOwnerAbsence`(#242 批 3 [4000] Q3=B:tail/taskOutput·taskStop/subagentOutput 三腿台账缺席即诚实缺席**绝不回落在飞 run**,缺席 warn 留痕每 (腿,taskId) 一条)· `clearBgTerminalFacts`(#242 批 3 扫码修:复活=新周期,旧周期终态事实作废——fleetLedger 复活两腿按尾段清账,factsAccepted 方向核不再拿上周期终态当先例)· `auditRetainWithoutWake`([4000] Q5:引擎宣示 `subagentResume` + 本端在付 `retainSubagentSessions` + 端未实现 `wakeSubagent` ⇒ 响亮一条;`CLIENT_VERBS.wakeSubagent` 维持 fail-soft)· `subscribeSubagentContent` · `subscribeEngineAgentPanel` · `publishQuestionFrame` / `respondToQuestion` | 驱动与观测委派子代;经 module 级台账喂活体 agent/task 面板。全部**能力位 gate**(§5b) | `src/subagent/*.ts`、`src/subagentContentStore.ts`、`src/engineAgentPanelStore.ts`、`src/engineInlineTaskStats.ts`、`src/engineToolLabelStore.ts`、`src/liveQuestionStore.ts` |
|
|
134
|
-
| 5 | **fleet 投影** |
|
|
134
|
+
| 5 | **fleet 投影** | 44 | `createFleetLedger` · `projectTasks` · `projectWorkflows` · `projectFleetAgentRows` · `readEngineActiveBgTasks` · `FLEET_TASK_VIEW_KEYS` · `escapeDisplayControlChars`(不可见字符可见化,行标签/描述消毒的共享底座) | 老 `fleetClient` 那一刀的成品:**帧体归库、连接归端** —— 端持 SSE 连接,库做行投影 + 保留台账 | `src/fleet/fleetProjection.ts`、`src/fleet/fleetLedger.ts`、`src/fleetAgentPanelProjection.ts`、`src/fleetTaskDesc.ts` |
|
|
135
135
|
| 6 | **请求装配(上行唯一构造口)** | 8 | `buildTaskRequest` · `REQUEST_FIELD_MATRIX` · `unregisteredRequestKeys` · `applyLiveRequestDefaults` · `taskNotificationToPrintFrame` | 两条车道(`interactive`/`print`)出站请求的**唯一**构造器;`unregisteredRequestKeys` 是可执行门 —— 端偷带一个未登记键上 wire 就红 | `src/request/taskRequest.ts`、`src/request/printNotification.ts` |
|
|
136
136
|
| 7 | **通知与 outstanding 台账** | 37 | `installNotificationQueuePort` · `normalizeTaskNotification` · `taskNotificationDedupKeyFromWire` · `registerOutstandingBgTask` / `registerOutstandingWorkflowRun` · `notificationQueuePortMisses` · `subscribeOutstandingWorkflows` · `outstandingDeliverableWorkflowCount` | `task_notification` 归一 + 去重 + 投递进宿主命令队列的**一把闸**;`outstandingDeliverableWorkflowCount()` 是 headless `-p` 的**退出门** | `src/notifications.ts`(11 个 module 台账) |
|
|
137
137
|
| 8 | **工具结果卡** | 25 | `structuredToToolUseResult` · `readAsyncLaunchedAgentReceipt` · `wireOutputToBody` · `parseModelFacingBash` · `getPatchFromContents` · `toolEndResultToUserFrame` · `flattenToolOutput` | 铸端要渲的 `tool_result` 卡体,含客户端 diff hunk(唯一 runtime dep 的用处) | `src/toolResult.ts`、`src/printToolResultFrame.ts`、`src/diff/patch.ts` |
|
|
@@ -141,7 +141,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
141
141
|
| 12 | **workflow 与后台工作视图** | 19 | `projectWorkflowRun` · `createLiveWorkflowSource` · `ensureWorkflowActivityLedger` · `readWorkflowActivityLedger` · `stopWorkflowActivityLedger` · `resetWorkflowActivityLedgers` · `createBackgroundView` · `projectBackgroundView` · `recordWorkflowAgentTaskId` · `agentDisplayStatus` | 活过一个 turn 的长任务读面:workflow run + 跨 session 后台任务归一表(`assistant.tasks` 与 fleet SSE **两源独立降级**) | `src/workflow.ts`、`src/workflowClient.ts`、`src/workflowMonitor.ts`、`src/agentSession/backgroundView.ts`(+ 纯类型 `src/agentSession/contract.ts`) |
|
|
142
142
|
| 13 | **座位 IPC 契约** | 33 | `LOCAL_SESSIONS_SPEC` · `SEAT_METHOD_NAMES` · `SEAT_EVENT_TYPES` · `isLocalSessionEvent` · `isToolPermissionRequest` · `toolPermissionRequestId` · `SEAT_VALIDATOR_KEY_COVERAGE` | desktop↔web 座位 IPC 契约的**单一真源**(此前两边各一份、名字零重合 ⇒ 编译器永远不会告诉你它们漂了)。🔴 加 verb 忘了加 `LOCAL_SESSIONS_SPEC` **不报错**:preload 不注册 channel、渲染端读到 `undefined` | `src/seatContract.ts`(**零 import**,纯类型 + 常量 + 纯谓词) |
|
|
143
143
|
| 14 | **宿主端口与会话槽** | 26 | `installHost` · `installHostFor` · `hostPortMisses(For)` · `DEFAULT_SESSION_KEY` · `hostEnv` · `unrefTimer` · `parseLocaleTag` / `pickUiLanguage`(#244 F4 族D A-028.20:locale tag 手术单源 + UI 语言判定;与 `resolveRegionHint` 双出口成文 —— 语言偏好域 en/zh ≠ 地址可达域 cn/intl/unknown,`zh-Hant` 前者 zh 后者 intl 是设计)· `engineNamespaceKeyFor` / `mergeSessionMapRecord` / `mergeEngineEntry`(A-028.12:会话 id 映射单一键形 + merge 判定;存储经 `SessionMapStorePort` 归端 —— cli 文件锁/原子写,web localStorage)| 进程/端级装配层(settings/fs/queue/timers/session/log/probe),与 per-turn 的 `AdapterContext` **分层**。头注的判定规则:**这个能力每 turn 都会变吗?** 会 ⇒ `ctx`;不会 ⇒ `installHost` | `src/host.ts`、`src/hostEnv.ts`、`src/sessionSlot.ts`、`src/unrefTimer.ts`、`src/env/{localeGeo,localeTag,uiLanguage}.ts`、`src/sessionMap.ts` |
|
|
144
|
-
| 15 | **控制面与传输** |
|
|
144
|
+
| 15 | **控制面与传输** | 72 | `ControlRouter`(+ `ControlSafetyError`)· `makeEngineWireClient` + `resolveWireAuth` · `installEngineWireTarget` · `diagnoseSseIdleTear` / `isSseIdleError` · `attemptActiveRunSelfHeal` + `activeRunBusySignal` + `activeRunSelfHealRow` / `activeRunBusyHeadlessRow` · `kickEngineCapsProbe` / `engineCapTrue` / `invalidateEngineCaps(baseUrl, probe?)`(#307 S25:引擎温切后的 caps 生产失效口 —— kick 自带幂等闸,同 baseUrl 重启后不显式失效就永远读到旧引擎那一版能力位;调用方 = 壳的 respawn/restartEngine。🔴 **推荐两参形**:第二参给替代探测则「推进代际 + 注册新探测」在同一同步块内完成,失效与下一次 kick 之间那个「等待者读到未判」的窗按构造不存在;单参形保留给「只丢缓存、这一刻没有替代探测」的调用方,那种情形下读到未判是诚实结局) · `mapBrainStatusToRetry` · `waitForClaimRelease` + `CLAIM_RELEASED_STATES` / `CLAIM_HELD_STATES` · `atMostOnceFailureClass` / `readSteerDelivery` · `clearRunningChoiceOffer`(Inkglow-1085 P0b①:「Do nothing」登记的清口 —— 端的「重新打开操作菜单」入口;登记在场时 attemptActiveRunSelfHeal 不整卡重弹,not-parked 结局带 `alreadyOffered: true` 判别位,端据此降级渲一行)· `INTERACTIVE_WAY_OUT`(默认出路串单源)· `normalizeWirePrincipal`(A-028.10:principal 在场性 trim 原语 —— 全空白=缺席不发头,engineWireTarget 两臂/makeEngineWireClient/壳 livePrincipal 同尺)· `classifyTurnWireError` / `isWireTransportError` / `isPreStreamDrainingReject` / `isResumeAtRejection` / `drainingRetryDelayMs` / `scenarioDenyFromError` + `WIRE_NETWORK_ERROR_PATTERN`(A-028.11/.13:turn 错误分型判定半场,人话文案与渲染归端) | 上行通道的**监管**半场(submit / steer / kill / 队列命令定序)+ 传输构造、caps 探测、SSE 断流分诊、**409 active-run 自愈** | `src/controlRouter.ts`、`steering.ts`、`sseIdleTriage.ts`、`retryStatus.ts`、`diagnostics.ts`、`engineWireSdk.ts`、`engineWireTarget.ts`、`src/principalWire.ts`、`src/wireErrorTriage.ts`、`engineSessionParam.ts`、`engineCapsCache.ts`、`liveInitToolFace.ts`、`adapter/activeRunSelfHeal.ts` |
|
|
145
145
|
| 16 | **引擎词汇表与包自检** | 41 | `CONFIG_REFUSAL_CODES` / `isConfigRefusalCode` · `STOP_CONFLICT_CODES` · `isInterruptedToolEndCode` · `isRewindFamilyCode` · `CLIENT_VERBS` · `compensationSplitViolations` | 三端分臂共用的**去字面化** `errorCode` 词表(病根正是三端各抄一份字面);编译期 verb 闭合门;搬迁补偿登记表 | `src/engineErrorCodes.ts`(34 项;A-028.11/.13 补 `DRAINING_ERROR_CODE`/`SCENARIO_NOT_ALLOWED_ERROR_CODE`/`RESUME_AT_ERROR_CODE_PREFIX`)、`src/classifierVerdictWire.ts`、`src/compensations.ts`、`src/clientSlice.ts` |
|
|
146
146
|
|
|
147
147
|
🔴 **`engineErrorCodes` 的开集纪律**(该文件头注逐字):这些 `ReadonlySet` / 前缀谓词一律是**识别表**,
|
|
@@ -369,7 +369,7 @@ durable park 腿走 `HitlBridge.decideTool(outcome, toolUseID, opts, preResolved
|
|
|
369
369
|
| **D-1 两元组 verbatim 回显** | `boundCallId` + `boundInputHash` 逐字回显进 `decide`,**绝不本地重算 hash**(`bindingOf`)。409 ⇒ `HitlSafetyError('binding_mismatch')`,调用方**重新呈现,绝不自动重试**(一次 decide 绝不双act)。pure 门 B7 段对这两段做**字节级**断言,改一个字符就红 |
|
|
370
370
|
| `reason` 上限 | `MAX_DENY_REASON_CHARS = 4096`;超限 server **413 `reason_too_large`**,丢的不是归因而是**整次决断**(413 ⇒ 决断没送达 ⇒ run 留 suspended)。包内 `denyReasonForWire(reason, tag)` 截断 + 留痕 |
|
|
371
371
|
| 缺省拒因 | `DEFAULT_DENY_REASON = 'The user rejected this tool use'`(不带归因时逐字不变) |
|
|
372
|
-
| **cancel
|
|
372
|
+
| **cancel vs deny(两动词,按意图选)** | 🔴 **按「你要停的是哪一样」选,不是按 run 的状态选**。`deny`(本节两条决断腿)= 否掉**这一道门**:决断送达后 run **继续**,模型拿到一条拒绝继续跑 —— 这是「不许它做这件事」。`runs.cancel` = 终结**整条 run**:server [868] 起对 `suspended` / `needs_review` 的 run **就地取消**(把待决 checkpoint 结清 + 行终态化,ack 带 `errorCode:"cancelled"`),这是「别跑了」。⚠️ **本行 0.36.0 前的原文是失真的**(SDK 7.1.0 已标 stale):它写的是「取消 suspended run 必须用 deny,绝不 `runs.cancel`(对 suspended run 会 409)」—— 照那句做会把「停」实现成「放它接着跑」(deny 只关掉一道门,run 照跑)。`cancel` 的 409 **今天只剩 lost CAS race**(待决门被并发决掉/过期 ⇒ 重读再试),**不再**是「suspended 一律 409」。判据锚 = 装机 SDK `dist/resources/runs.d.ts` 的 `cancel` JSDoc(常驻门 ⑦ 段对账,上游改说法当天红) |
|
|
373
373
|
| 空作答 fail-loud | `answerQuestion` 三形一律抛 `HitlSafetyError('empty_answer')`、**一次 decide 都不发**:空 `answers[]` / 任一条 `selected[]` 为空 / 任一条 `header` 为空串。理由:`{answers:[]}` 在 wire 上另有确切含义(question 域 deny 的 NO_HUMAN 形),当 approve 发出去 = **拿 deny 的载荷冒充 approve** |
|
|
374
374
|
| **回执** | ⚠️ `decideTool` / `answerQuestion` 的返回型是 **`Promise<unknown>`** —— 本包**不结构化读** durable `/decide` 的响应体,**没有** 4a 那样的 ack 消费层。见 §7b 缺口 **P-7**(不是 P-6:P-6 是 `compaction_outcome`) |
|
|
375
375
|
| TOCTOU | 调用方若已经用 `findPendingForTask` 取过 pending 行(呈卡用的那一行),**必须**经 `preResolvedPending` 传进来 —— 否则本方法自己再 `approvals.list()` 一次,两次独立取数可能落在**不同的行**上(「人看到的行」≠「decide 解析的行」) |
|
|
@@ -700,6 +700,7 @@ CHANGELOG 0.29.0「已知局限」段与相应 JSDoc 都有成文。**别在读
|
|
|
700
700
|
| **P-4** | med | **`approval_revoke` 在 SDK union 里连成员都没有**(SDK 顶注:known asymmetry,`Registering it is an open item for the next batch`)⇒ 本包不可能有 case ⇒ 运行期落 `dropped('unknown_arm')`;审批链也看不见它(`isToolApprovalFrame` 只认两帧)。全仓 `grep -rn "revoke"` = **0** | `src/adapter/downstream/eventToSdkMessage.ts` 的 `default` 臂;`src/hitl/toolApprovalWire.ts` 的 `isToolApprovalFrame` | 🔴 **引擎撤卡时本包不会替你撤那张卡** —— 被撤的 ask 会一直留在屏上,直到它自己的 5 分钟 TTL / deny 路径触发。要 revoke 语义的端只能自己接 raw named-SSE 腿并撤自己的卡(`unknown_arm` 的 drop 至少留了一行痕) |
|
|
701
701
|
| **P-5** | 真缺口(未定级) | **durable 重放腿上,一条被重放的 `question` 今天不会再打开覆盖层** —— 覆盖层的入口是 `liveQuestionStore` 的 **live demux 写口**,不是投影函数。交互 REPL 无损,「断线后按 `Last-Event-ID` 续读」场景下是真缺口。补它属**行为面**改动(先要答「重放一条已过 5min TTL 的问题该不该弹窗」),按宪法三问单独走 | `src/adapter/downstream/eventToSdkMessage.ts` 的 `question`/`question_complete`/`elicitation`/`elicitation_complete` 臂(缺口逐字记在该处);`src/liveQuestionStore.ts` 头注(`LIVE-ONLY + SAME-REPLICA … No durable resume anchor`) | `respondToQuestion` 当 best-effort 用(404 = 「已经放掉了」,dismiss,**绝不重试**);重连后的恢复走 **409 自愈树 + 自己的 `/v1/approvals` 列举**,**不要**指望重放的 `question` 帧能弹出覆盖层 |
|
|
702
702
|
| **P-6** | low | `compaction_outcome`(压缩**非成功结局**:mooted/failed)在本切片 `not_in_slice`;「压缩失败让用户看见」是 chrome/HUD 面的活,**今天两端都还没接**(adapt 臂表同样无此臂) | `src/adapter/downstream/eventToSdkMessage.ts` 的 `case 'compaction_outcome'` | 压缩失败对用户**不可见**。🔴 **不许**由投影切片顺手编一个假 transcript 形来假装接上了 |
|
|
703
|
+
| **P-32** | 在册局限(0.36.0 两 wire 键过境后的**辖域**,非缺陷) @cli @web @desktop | **两键各只有一条腿,别按「两面能对上」写码**。① **`requiresRealApproval`**(#283):只在**活卡帧**腿(`ToolApprovalFrame` → `ApprovalCardRequest`);**耐久腿零 stamp** —— sdk 7.1.0 的 `PendingCheckpoint` / `riskDescriptor` 都没有这一位(server 那份在**卡内** `risk` 子树,不是行上的键),包侧刻意不猜载体名。② **`checkpointId`**(#285 件2):只在 **409 `conflict.session_active_run` 体 + 其 SSE done 帧**的 `pendingGate`;另外三条 park 读面(`/v1/assistant/inbox`、`GET /v1/approvals`、`/v1/approvals/stream`)**都没有**这一格(后两条要给 checkpoint 表反范式一列 = SQL 面双库门,属另一批) | `src/hitl/toolApprovalWire.ts`(帧腿 stamp / durable 腿刻意零 stamp,两处 JSDoc 逐条写明理由)· `src/adapter/runStream.ts`(`ActiveRunPendingGate.checkpointId` + `pendingGateIsProvablyDifferent`)· 行为钉:`run-durable-card-display-keys-test.mjs` ⑨ 段(四种最像的载体名摆在行上,卡入参一个都不许长出来)· `run-selfheal-reopen-test.mjs` G1/G1b | ① **`requiresRealApproval` 在场 ⇒ 一切自动放行让位**(记住的规则 / `allow_session` / bypass 姿态),**缺席绝不读成 `false`**(缺席 = 不是安全类 ask **或** 老 server,两者同形不猜);durable 卡上今天**恒缺席**,别据此认为「durable 门都不是安全类」。② **`checkpointId` 只做两件事**:落日志/排障关联,以及经 `pendingGateIsProvablyDifferent(prev, next)` 做**单向**判断「id 变了 ⇒ 不是刚才那一行」。🔴 **`false` 是「证不出」不是「同一道门」**,🔴 **绝不**当跨调用去重键(server 选行是**无序 `LIMIT 1`**、同 session 可并存多条 pending 行 ⇒ 同一情形连续两次 409 可能报不同 id;也可能 id 不变而 `activeTaskId` 已换),🔴 **绝不**拿它去 join durable 队列行(必然落空,且落空与 legacy 行同形)。缺席是**三成因合流**(legacy 行 / 值没过 server 信任边界校验 / 整只材料读取失败),读作「不知道这道门叫什么」 |
|
|
703
704
|
|
|
704
705
|
### 7b. 决断链缺口
|
|
705
706
|
|
|
@@ -843,7 +844,7 @@ reason 里写明「枚举器盲区形」。已知两形:
|
|
|
843
844
|
- [ ] 接审批帧腿时**填 `AskGateWireDeps.approvalLane`**(缺席 = `note` 恒不发,fail-closed 且不报错)
|
|
844
845
|
- [ ] ack 五位按 §4a 三列表消费:**缺席一律当未知**,`rememberApplied === false` 与 `updatedInputForwarded === false` 必须响亮告知
|
|
845
846
|
- [ ] durable 腿:`decideTool` 前把**呈卡用的那一行** pending 经 `preResolvedPending` 传进去(TOCTOU)
|
|
846
|
-
- [ ] durable
|
|
847
|
+
- [ ] durable 腿:**按意图**选动词 —— 否掉这一道门用 **deny**(run 继续),终结整条 run 用 **`runs.cancel`**(server [868] 起对 suspended/needs_review 就地取消;409 只剩 CAS race)。⚠️ 0.36.0 修:原行写的「取消 suspended 必须用 deny、绝不 cancel」已被 SDK 7.1.0 标 stale,详见 §4 「cancel vs deny」行
|
|
847
848
|
- [ ] `HitlSafetyError` 按 **`.code` 结构化判型**,`instanceof` 只作加强(跨 realm / 双实例)
|
|
848
849
|
- [ ] `ReopenCardVerdict.presented`:要用这个位就自己在呈现层实现回执;不实现就**缺席**(缺席不降级),**别填 `false` 当占位**
|
|
849
850
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/client-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"description": "Client-side session runtime shared by every sema human client (TUI / web / desktop): sema wire frames (AgentEvent) -> CC session vocabulary (SDKMessage) with dual-plane output (transcript/chrome), deterministic transcript ids, lane discipline as a type, and the notification/dedup ledgers. Every CC-skin shape is collected here so the wire itself stays neutral. Blackboard [1832] design axioms; [1651]/[1652]/[1653] signed seam design. Renamed from @sema-agent/wire-cc-adapter (0.1.x).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@sema-agent/agent-types": "^0.2.0",
|
|
38
|
-
"@sema-agent/core": "^5.
|
|
38
|
+
"@sema-agent/core": "^5.43.0",
|
|
39
39
|
"@sema-agent/sdk": "^7.1.0",
|
|
40
40
|
"esbuild": "^0.27.4",
|
|
41
41
|
"typescript": "^6.0.2"
|