@sema-agent/client-core 0.69.2 → 0.70.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/CHANGELOG.md +26 -2
- package/README.md +1 -1
- package/dist/adapt/arms.js +2 -1
- package/dist/adapt/textStream.js +44 -1
- package/dist/cloudConfigWireCaps.js +1 -3
- package/dist/engineNoticeCodes.d.ts +31 -1
- package/dist/engineNoticeCodes.js +52 -1
- package/dist/seam.d.ts +1 -0
- package/dist/skillsWireCaps.d.ts +23 -17
- package/dist/skillsWireCaps.js +19 -17
- package/docs/INTEGRATION-CLIENTS.md +73 -11
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -49,9 +49,33 @@
|
|
|
49
49
|
> 挡住 ⇒ 本批把它机械化——④a0 对 `pending` 行**要求段头已是日期形**(`(未发布)` 直接红),阶段一
|
|
50
50
|
> commit 漏转在发布前就红,不再靠人记。
|
|
51
51
|
|
|
52
|
-
## 0.
|
|
52
|
+
## 0.70.1(2026-09-16)
|
|
53
53
|
|
|
54
|
-
>
|
|
54
|
+
> 主题:**CC-17 推理/文本面安全修复** —— `handOffOnly` 形(段跨包侧边界 ∧ 已提交前缀自身过期)同步两本补差账 + 清未提交尾段。接入面 §40。
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- 🔴 **CC-17 `handOffOnly` 形不再漏账**(接入方两形回执,整链实测复现)。段跨过包侧边界(工具卡 / 消息划界)且已提交前缀自身也过期时,`replaceAnswerSegment` 旧码只发三键信号就返回,两本补差账一行不动:
|
|
59
|
+
- **形一(卡后有增量)**:`answerSegment` 里那截**原始未脱敏**尾段照常被 `takeAnswerSegment` 提交上屏落盘 —— 它属于一个已作废的段,宿主换的是**另一条**消息,没人会来清它。
|
|
60
|
+
- **形二(卡后零增量)**:`lastCommittedAnswerText` 回退到上一条消息的原始正文,`result` 臂第④臂据此把尾段当「屏上缺的后缀」再吐一遍(终帧未脱敏时连字节都残留)。
|
|
61
|
+
修后:前缀落在哪本账就把哪本的 `livePrefix` 换成 `content`(`endsWith` 守卫,与非跨界形逐字同律),`answer` 同步,并清掉本段还没交出去的那一截(含它押在活体缓冲里的部分;上一段的 `carry` 原样留)。**仍然一个字节都不新交**,不铸任何消息。
|
|
62
|
+
🔴 **收窄(实测逼出)**:两本账是**按消息**记的,而 `livePrefix` 可能跨**多条**消息(多个工具卡 ⇒ 段身份覆盖多行)。那一形下宿主自己也换不了(归属歧义,端按「证明不了就不动手」整发放弃),包若照样清账清尾段,补差基线会回退到中间那条,`result` 反而从第⑤臂(只报分岔)掉进第④臂(补吐一整段)。⇒ 账对不上就退回既有行为:只发信号、一个字节不动;多行那一形的正解是把整段归属交全(`text_segment_end.committedUuids[]`,排下一版),不是包单方面清。
|
|
63
|
+
`run-text-segment-authority-test` Y 段九格 + D14b 按更强判据改口(旧格钉的「与 0.68.0 基线逐字相同」正是这个病);232 → 247;变异三发(去收窄 / 不清尾段 / 不同步账)各红。
|
|
64
|
+
|
|
65
|
+
## 0.70.0(2026-09-16)
|
|
66
|
+
|
|
67
|
+
> 主题:**CC-04 技能帽退役改预算式**(server 7.78.1 + core 7.19.0 同窗:`SKILL_CAPS` 三键退役、零条数丢弃、清单裁切整只归引擎 + `readSkillsListingTruncated` 读器)+ 通告码 +3 + CC-15 形 (a) 透传 `committedUuids: []`。接入面 §39。
|
|
68
|
+
> **minor**:型面 BREAKING 仅 `SKILL_CAPS.items` / `.name` / `.description` 三键退役(读它们的端与本版同窗退役:cli 1.0.116);运行期零 BREAKING(server 7.78.1 对任意条数 / 任意长名与描述都受理)。0.69.2 段里写的「0.69.3」读作本版。
|
|
69
|
+
|
|
70
|
+
### Changed
|
|
71
|
+
|
|
72
|
+
- 🔴 **CC-04 `SKILL_CAPS` 只剩 `content`(1MB 引擎加载门)**:`items: 10` / `name: 64` / `description: 1024` 三键退役 —— server 7.78.1 `validateUserSkills`(直读 dist)已无条数帽、无 name / description 长度帽(7.78.0 及以前仍有);core 7.19.0 的 `<skills>` 清单按字节预算自己裁描述 / 退成 name-only 并发 `skills.listing_truncated` 通告。`skillCommandsToSpecs` / `cloudSkillsToSpecs` **不再在第 10 条断开**(此前静默丢弃,零留痕),`toCappedSpec` 不再预截 name / description(在一道已不存在的门下面静默切字节 = `content` 曾在 32768 上得过的同一个病)。`agents[].skills` 轴零删键(C-R43 ①)。engine-vocab G2-a / pure C-B1 改钉「只剩 content」。
|
|
73
|
+
|
|
74
|
+
### Added
|
|
75
|
+
|
|
76
|
+
- **`readSkillsListingTruncated(notice)` + `SkillsListingTruncatedFactsView`**(CC-04 预算式半场的留痕读口):`skills.listing_truncated` 通告 `detail` 逐格(`budgetBytes` / `total` / `kept` / `nameOnly[]` / `dropped[]` 必填;`requestedBudgetBytes?` / `descMaxChars?` / `sessionId?` 可选;派生 `laneClamped?` = requested 在场且 ≠ budget,缺席不折 false);不成形 ⇒ `undefined` 绝不抛;`kept` 照带不重算;名单冻结。宿主渲运维面 / 折叠行读它,不自己数「发了几条上了几条」。码册门 G 段 25 格。公面 985 → 986。
|
|
77
|
+
- **`ENGINE_NOTICE_CODES` 镜像 +3 = 五十九码**(core 7.19.0;顺序同源):`classifier.role_defaulted` / `classifier.contract_broken`(紧跟 `classifier.fallback`)/ `skills.listing_truncated`(`<skills>` 披露块超字节预算 ⇒ `detail.nameOnly[]` 只列名或 `detail.dropped[]` 不列;Skill 工具仍服务全部技能),受众均 operator;`engineNoticeInCatalog` / `noticeAudienceOf` 自动覆盖,`ENGINE_NOTICE_AUDIENCE` +3。devDep `@sema-agent/core` `~7.18.0` → `~7.19.0`(零值级直连;码册门 / engine-vocab 门对账基线随之)。
|
|
78
|
+
- **CC-15 形 (a) 透传 `committedUuids: []`**(cli 0.69.2 接入回执):`thinking_segment_end` 在「全部还押在缓冲里」那形现带 **在场但空** 的 `committedUuids: []` = 本包判定「本段零已提交行」的正面事实;整键缺席只留给零经手形 (f)。修前 (a) 形不铸键,宿主分不出「零已提交行」与「包说不出」,只能自己数窗口里过境的行(会把上一段迟交行 / durable 行数进去 = 假披露)。additive;`committedUuid` 兼容位不变(仍缺席)。TSA Ta6 / Tf3 / X2c / X5b。
|
|
55
79
|
|
|
56
80
|
## 0.69.2(2026-09-16)
|
|
57
81
|
|
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Renamed from **`@sema-agent/wire-cc-adapter`** (0.1.x, deprecated — see *Migra
|
|
|
35
35
|
|
|
36
36
|
## Scope
|
|
37
37
|
|
|
38
|
-
**Version:** 0.
|
|
38
|
+
**Version:** 0.70.1
|
|
39
39
|
|
|
40
40
|
- **Today** — the adapter seam, the whole `adapt()` pipeline (all 14 A-layer arms plus the
|
|
41
41
|
B/D/E tool-card layers), the notification/caps/model families, the adapter kernel (stream driver
|
package/dist/adapt/arms.js
CHANGED
|
@@ -500,7 +500,8 @@ const thinkingSegmentEndArm = function* (m, { text }) {
|
|
|
500
500
|
...(r.committedPrefixDiverged ? { committedPrefixDiverged: true } : {}),
|
|
501
501
|
...(r.committedPrefixLen > 0 ? { committedPrefixLen: r.committedPrefixLen } : {}),
|
|
502
502
|
...(r.committedUuid !== undefined ? { committedUuid: r.committedUuid } : {}),
|
|
503
|
-
|
|
503
|
+
// CC-15:`[]` 也透传(形 (a) 的正面事实「零已提交行」);只有 `undefined`(形 (f) 零经手)才不铸键。
|
|
504
|
+
...(r.committedUuids !== undefined ? { committedUuids: r.committedUuids } : {}),
|
|
504
505
|
...(typeof m.eventId === 'string' && m.eventId.length > 0 ? { eventId: m.eventId } : {}),
|
|
505
506
|
});
|
|
506
507
|
};
|
package/dist/adapt/textStream.js
CHANGED
|
@@ -367,6 +367,46 @@ export function createTextStream(ctx, idOf) {
|
|
|
367
367
|
*/
|
|
368
368
|
const handOffOnly = committedPrefixDiverged && previousSegmentCommitted.length > 0;
|
|
369
369
|
if (handOffOnly) {
|
|
370
|
+
// ── CC-17(0.70.1,cli 接入回执两形;整链实测复现)────────────────────────────────────
|
|
371
|
+
// 🔴 「只发信号」曾被写成「两本账一行都不动」,那是**漏账**不是克制:权威全文这一刻已经
|
|
372
|
+
// 交给宿主去换了,包却还按「屏上只有那截原始前缀」继续算,于是
|
|
373
|
+
// 形一(卡后有增量):`answerSegment` 里那截**原始未脱敏**尾段照常被 `takeAnswerSegment`
|
|
374
|
+
// 提交上屏落盘 —— 它属于一个已经作废的段,宿主换的是**另一条**消息,没人会来清它;
|
|
375
|
+
// 形二(卡后零增量):`lastCommittedAnswerText` 回退到上一条消息的原始正文,`result` 臂
|
|
376
|
+
// 的第④臂据此把尾段当「屏上缺的后缀」再吐一遍(终帧未脱敏时连字节都残留)。
|
|
377
|
+
// ⇒ 同步两本补差账(前缀落在哪本就换哪本,`endsWith` 守卫不匹配就不动,与非跨界形逐字同律)
|
|
378
|
+
// + 清掉本段还没交出去的那一截。**仍然一个字节都不新交**(不铸任何消息):那些字节在别的
|
|
379
|
+
// 消息里,宿主按三键换;本分支改的只是「包自己以为屏上有什么」。
|
|
380
|
+
// 🔴 旧注释(异源复审轮五 finding②)说「清未提交尾段会让 `lastCommittedAnswerText` 回退 ⇒
|
|
381
|
+
// 第④臂补吐一整段」—— 那个后果的**前提正是账没同步**;上面一行同步之后前提消失。这句话
|
|
382
|
+
// 不是推理,是判据:`run-text-segment-authority-test.mjs` 的 Y4 就跑那条时序。
|
|
383
|
+
// 🔴 **只在「宿主确定会把某一整条换成 `content`」时才认账**(收窄,实测逼出):这两本账是
|
|
384
|
+
// **按消息**记的,而 `livePrefix` 可能跨了**多条**消息(两个工具卡 ⇒ 段身份覆盖多行)。
|
|
385
|
+
// 那一形下宿主自己也换不了(段身份对上多行 = 归属歧义,端按「证明不了就不动手」整发放弃),
|
|
386
|
+
// 包若照样清账清尾段,`lastCommittedAnswerText` 会回退到中间那条,`result` 臂反而从第⑤臂
|
|
387
|
+
// (只报分岔)掉进第④臂(补吐一整段)—— 那正是轮五 finding② 抓到的**新增重复转录路径**,
|
|
388
|
+
// 实测确认过(D35/D36 两格钉的就是它)。⇒ 对不上就退回 0.68.0 行为:只发信号,一个字节不动。
|
|
389
|
+
// 多行跨界那一形的正解是把整段归属交全(`committedUuids[]`,CC-16),不是包单方面清。
|
|
390
|
+
const syncedBook = committedText.length > 0 && committedText.endsWith(livePrefix) ? 'current'
|
|
391
|
+
: previousCommittedText.endsWith(livePrefix) ? 'previous'
|
|
392
|
+
: null;
|
|
393
|
+
if (syncedBook === 'current') {
|
|
394
|
+
committedText = committedText.slice(0, committedText.length - livePrefix.length) + content;
|
|
395
|
+
}
|
|
396
|
+
else if (syncedBook === 'previous') {
|
|
397
|
+
previousCommittedText =
|
|
398
|
+
previousCommittedText.slice(0, previousCommittedText.length - livePrefix.length) + content;
|
|
399
|
+
}
|
|
400
|
+
if (syncedBook !== null && answer.endsWith(liveSegment)) {
|
|
401
|
+
answer = answer.slice(0, answer.length - liveSegment.length) + content;
|
|
402
|
+
}
|
|
403
|
+
if (syncedBook !== null) {
|
|
404
|
+
// 活体面:本段还押着没吐的那一截也作废(`textPending` 是段缓冲的后缀,前面那截 `carry`
|
|
405
|
+
// 属于上一段,与本次替换无关 ⇒ 原样留)。
|
|
406
|
+
const staleTailLen = Math.min(textPending.length, prevSegment.length);
|
|
407
|
+
textPending = textPending.slice(0, textPending.length - staleTailLen);
|
|
408
|
+
answerSegment = '';
|
|
409
|
+
}
|
|
370
410
|
segmentCommitted = '';
|
|
371
411
|
previousSegmentCommitted = '';
|
|
372
412
|
idleFlushUsedInSegment = false;
|
|
@@ -472,7 +512,10 @@ export function createTextStream(ctx, idOf) {
|
|
|
472
512
|
thinkingPending = content.startsWith(emitted) ? content.slice(emitted.length) : '';
|
|
473
513
|
thinking = content;
|
|
474
514
|
thinkingSettled = content.length > 0;
|
|
475
|
-
|
|
515
|
+
// CC-15(0.69.3,cli 接入回执):形 (a) 透传 `committedUuids: []` —— **在场但空** = 本包判定「本段零已提交行」
|
|
516
|
+
// 的正面事实;整键缺席只留给形 (f)(本包零经手,说不出)。壳靠这条才能不自己数窗口里过境的行
|
|
517
|
+
// (那会把上一段迟交行 / durable 行数进去 = 假披露)。
|
|
518
|
+
return { diverged, committedPrefixLen: 0, committedPrefixDiverged: false, committedUuids: [] };
|
|
476
519
|
}
|
|
477
520
|
// (b) 有已提交行(一条或跨卡多条):已提交那截撤不回。
|
|
478
521
|
const committedPrefixDiverged = !content.startsWith(prefix);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MCP_CAPS } from './mcpWireCaps.js';
|
|
2
|
-
import {
|
|
2
|
+
import { toCappedSpec } from './skillsWireCaps.js';
|
|
3
3
|
const asRec = (v) => (typeof v === 'object' && v !== null && !Array.isArray(v) ? v : undefined);
|
|
4
4
|
const asArr = (v) => (Array.isArray(v) ? v : []);
|
|
5
5
|
const asStr = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
|
|
@@ -129,8 +129,6 @@ export function cloudSkillsToSpecs(manifestSkills, resolveBody) {
|
|
|
129
129
|
const specs = [];
|
|
130
130
|
const seen = new Set();
|
|
131
131
|
for (const raw of asArr(manifestSkills)) {
|
|
132
|
-
if (specs.length >= SKILL_CAPS.items)
|
|
133
|
-
break;
|
|
134
132
|
const s = asRec(raw);
|
|
135
133
|
if (!s || s.enabled === false)
|
|
136
134
|
continue;
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
/** 一条通告是**说给谁听**的。两值,刻意不设第三值(见模块顶注)。 */
|
|
55
55
|
export type NoticeAudience = 'user' | 'operator';
|
|
56
56
|
/**
|
|
57
|
-
* 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES`,**7.
|
|
57
|
+
* 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES`,**7.19.0 = 五十九码**(7.17.x 五十二 + 7.18.0 #748 两枚 writeFace + #742 两枚 classifier + 7.19.0 三枚:`classifier.role_defaulted` / `classifier.contract_broken` / `skills.listing_truncated`,均 operator);顺序同源)。
|
|
58
58
|
* 🔴 这是一份**抄件**,不是本包的意见 —— 改它必须同 commit 附 core 坐标,且门会先红。
|
|
59
59
|
* ⚠️ `EngineNotice.code` 的型面在上游**故意留 `string`**(宿主把自己的通告转发进同一个水槽是
|
|
60
60
|
* 被支持的形),所以本表是**判据**不是型 —— 别拿它去窄化那个字段。
|
|
@@ -200,3 +200,33 @@ export interface DurableGateUnavailableFactsView {
|
|
|
200
200
|
* 「这一格是 false」对用户的下一步不同(前者是「引擎没说」,后者是「没有人会答你这条 ask」)。
|
|
201
201
|
*/
|
|
202
202
|
export declare function readDurableGateUnavailable(notice: unknown): DurableGateUnavailableFactsView | undefined;
|
|
203
|
+
/** `skills.listing_truncated` 通告 `detail` 上的事实(core `skill-listing-budget.js` 铸点逐格)。 */
|
|
204
|
+
export interface SkillsListingTruncatedFactsView {
|
|
205
|
+
/** 清单实际拿到的字节预算(交付车道结构性 clamp 之后)。 */
|
|
206
|
+
budgetBytes: number;
|
|
207
|
+
/** 部署声明的比例**要**的预算(clamp 之前);只在 clamp 真绑住时与 `budgetBytes` 不同。读不出 ⇒ 键不铸。 */
|
|
208
|
+
requestedBudgetBytes?: number;
|
|
209
|
+
/** 每条描述的字符帽(含省略号)。读不出 ⇒ 键不铸。 */
|
|
210
|
+
descMaxChars?: number;
|
|
211
|
+
/** 这一帧清单上的技能总数(初始清单 = 全名册;drift 帧 = 新宣告的那一批)。 */
|
|
212
|
+
total: number;
|
|
213
|
+
/** 带完整描述上了清单的条数(= total − nameOnly − dropped;引擎铸点算好,本包照带不重算)。 */
|
|
214
|
+
kept: number;
|
|
215
|
+
/** 只列名的技能名(按引擎顺序)。 */
|
|
216
|
+
nameOnly: readonly string[];
|
|
217
|
+
/** 整条没进清单的技能名(病态形;Skill 工具仍服务它们)。 */
|
|
218
|
+
dropped: readonly string[];
|
|
219
|
+
/** 🔴 清单是被**交付车道的结构性 clamp** 缩短的(而不是部署自己的比例):`requestedBudgetBytes` 在场且 ≠ `budgetBytes`。
|
|
220
|
+
* 两者都读得出才铸;缺席 = 分不出(不折 `false`)。运维面据此分「调 fraction 有用」与「调了也没用」。 */
|
|
221
|
+
laneClamped?: boolean;
|
|
222
|
+
/** 投给哪个会话。读不出 ⇒ 键不铸(operator 通告不要求会话)。 */
|
|
223
|
+
sessionId?: string;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* `skills.listing_truncated` 通告 → 事实;不成形 ⇒ `undefined`,绝不抛出。
|
|
227
|
+
*
|
|
228
|
+
* 🔴 必填 = `budgetBytes` / `total` / `kept` / `nameOnly` / `dropped`(引擎铸点恒带的五格);任一读不出 ⇒ 整只缺席。
|
|
229
|
+
* 🔴 `nameOnly` / `dropped` 里混进非串 ⇒ 整只缺席(名单是渲染键,半张坏名单比没有更坏)。
|
|
230
|
+
* 🔴 `kept` 照带不重算:引擎已在铸点算过;本包再算一遍 = 第二份公式,上游改口那天两边各走各的。
|
|
231
|
+
*/
|
|
232
|
+
export declare function readSkillsListingTruncated(notice: unknown): SkillsListingTruncatedFactsView | undefined;
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
* 出现在本包源码或产物里 => 当场红。
|
|
53
53
|
*/
|
|
54
54
|
/**
|
|
55
|
-
* 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES`,**7.
|
|
55
|
+
* 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES`,**7.19.0 = 五十九码**(7.17.x 五十二 + 7.18.0 #748 两枚 writeFace + #742 两枚 classifier + 7.19.0 三枚:`classifier.role_defaulted` / `classifier.contract_broken` / `skills.listing_truncated`,均 operator);顺序同源)。
|
|
56
56
|
* 🔴 这是一份**抄件**,不是本包的意见 —— 改它必须同 commit 附 core 坐标,且门会先红。
|
|
57
57
|
* ⚠️ `EngineNotice.code` 的型面在上游**故意留 `string`**(宿主把自己的通告转发进同一个水槽是
|
|
58
58
|
* 被支持的形),所以本表是**判据**不是型 —— 别拿它去窄化那个字段。
|
|
@@ -88,6 +88,9 @@ export const ENGINE_NOTICE_CODES = Object.freeze([
|
|
|
88
88
|
'classifier.denial_limit',
|
|
89
89
|
// core 7.18.0 #742(CC-05):分类器席坏配置 ⇒ 主模型代判的一条运维通告;元组 @22。
|
|
90
90
|
'classifier.fallback',
|
|
91
|
+
// core 7.19.0(CC-04 core 半场):分类器席角色缺省 / 契约破裂两枚运维通告;顺序同源(紧跟 fallback)。
|
|
92
|
+
'classifier.role_defaulted',
|
|
93
|
+
'classifier.contract_broken',
|
|
91
94
|
'checkpoint.execution_outcome_unrecorded',
|
|
92
95
|
'delegation.transcript_integrity',
|
|
93
96
|
'delegation.ask_unresolvable',
|
|
@@ -122,6 +125,9 @@ export const ENGINE_NOTICE_CODES = Object.freeze([
|
|
|
122
125
|
'task.interrupt_unconsumed',
|
|
123
126
|
'memory.capture_opted_out',
|
|
124
127
|
'memory.capture_optout_unpersisted',
|
|
128
|
+
// core 7.19.0(CC-04 core 半场):`<skills>` 披露块超字节预算 ⇒ 至少一条只列名(`detail.nameOnly[]`)或整条不列
|
|
129
|
+
// (`detail.dropped[]`);Skill 工具仍服务全部技能。运维面事(调 skillListingBudgetFraction / skillListingMaxDescChars / 少声明)。
|
|
130
|
+
'skills.listing_truncated',
|
|
125
131
|
'tool_result.offload_put_failed',
|
|
126
132
|
]);
|
|
127
133
|
const CATALOG = new Set(ENGINE_NOTICE_CODES);
|
|
@@ -162,6 +168,8 @@ export const ENGINE_NOTICE_AUDIENCE = Object.freeze({
|
|
|
162
168
|
'peer.idle_subscription': 'user',
|
|
163
169
|
'classifier.denial_limit': 'user',
|
|
164
170
|
'classifier.fallback': 'operator',
|
|
171
|
+
'classifier.role_defaulted': 'operator',
|
|
172
|
+
'classifier.contract_broken': 'operator',
|
|
165
173
|
'checkpoint.execution_outcome_unrecorded': 'operator',
|
|
166
174
|
'delegation.transcript_integrity': 'operator',
|
|
167
175
|
'delegation.ask_unresolvable': 'user',
|
|
@@ -196,6 +204,7 @@ export const ENGINE_NOTICE_AUDIENCE = Object.freeze({
|
|
|
196
204
|
'task.interrupt_unconsumed': 'user',
|
|
197
205
|
'memory.capture_opted_out': 'user',
|
|
198
206
|
'memory.capture_optout_unpersisted': 'user',
|
|
207
|
+
'skills.listing_truncated': 'operator',
|
|
199
208
|
'tool_result.offload_put_failed': 'operator',
|
|
200
209
|
});
|
|
201
210
|
/**
|
|
@@ -369,3 +378,45 @@ export function readDurableGateUnavailable(notice) {
|
|
|
369
378
|
...(typeof o.liveQuestionFace === 'boolean' ? { liveQuestionFace: o.liveQuestionFace } : {}),
|
|
370
379
|
};
|
|
371
380
|
}
|
|
381
|
+
const nonNegInt = (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 ? v : undefined;
|
|
382
|
+
const nameList = (v) => Array.isArray(v) && v.every((x) => typeof x === 'string' && x.length > 0) ? Object.freeze([...v]) : undefined;
|
|
383
|
+
/**
|
|
384
|
+
* `skills.listing_truncated` 通告 → 事实;不成形 ⇒ `undefined`,绝不抛出。
|
|
385
|
+
*
|
|
386
|
+
* 🔴 必填 = `budgetBytes` / `total` / `kept` / `nameOnly` / `dropped`(引擎铸点恒带的五格);任一读不出 ⇒ 整只缺席。
|
|
387
|
+
* 🔴 `nameOnly` / `dropped` 里混进非串 ⇒ 整只缺席(名单是渲染键,半张坏名单比没有更坏)。
|
|
388
|
+
* 🔴 `kept` 照带不重算:引擎已在铸点算过;本包再算一遍 = 第二份公式,上游改口那天两边各走各的。
|
|
389
|
+
*/
|
|
390
|
+
export function readSkillsListingTruncated(notice) {
|
|
391
|
+
if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
|
|
392
|
+
return undefined;
|
|
393
|
+
const n = notice;
|
|
394
|
+
if (n.code !== 'skills.listing_truncated')
|
|
395
|
+
return undefined;
|
|
396
|
+
const d = n.detail;
|
|
397
|
+
if (typeof d !== 'object' || d === null || Array.isArray(d))
|
|
398
|
+
return undefined;
|
|
399
|
+
const o = d;
|
|
400
|
+
const budgetBytes = nonNegInt(o.budgetBytes);
|
|
401
|
+
const total = nonNegInt(o.total);
|
|
402
|
+
const kept = nonNegInt(o.kept);
|
|
403
|
+
const nameOnly = nameList(o.nameOnly);
|
|
404
|
+
const dropped = nameList(o.dropped);
|
|
405
|
+
if (budgetBytes === undefined || total === undefined || kept === undefined || nameOnly === undefined || dropped === undefined) {
|
|
406
|
+
return undefined;
|
|
407
|
+
}
|
|
408
|
+
const requestedBudgetBytes = nonNegInt(o.requestedBudgetBytes);
|
|
409
|
+
const descMaxChars = nonNegInt(o.descMaxChars);
|
|
410
|
+
const sessionId = typeof o.sessionId === 'string' && o.sessionId.length > 0 ? o.sessionId : undefined;
|
|
411
|
+
return {
|
|
412
|
+
budgetBytes,
|
|
413
|
+
...(requestedBudgetBytes !== undefined ? { requestedBudgetBytes } : {}),
|
|
414
|
+
...(descMaxChars !== undefined ? { descMaxChars } : {}),
|
|
415
|
+
total,
|
|
416
|
+
kept,
|
|
417
|
+
nameOnly,
|
|
418
|
+
dropped,
|
|
419
|
+
...(requestedBudgetBytes !== undefined ? { laneClamped: requestedBudgetBytes !== budgetBytes } : {}),
|
|
420
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
421
|
+
};
|
|
422
|
+
}
|
package/dist/seam.d.ts
CHANGED
|
@@ -750,6 +750,7 @@ export interface ThinkingSegmentEndChromeEvent {
|
|
|
750
750
|
* 有父链 / 压缩段依赖的转录**清空优于删**,保行身份、父链与压缩元数据;安全目标 = 未脱敏字节零留盘;整段换,不切片);
|
|
751
751
|
* 缺席(`committedPrefixDiverged` 缺席)⇒ 这些行照旧,本包只换了还押着的后段(或零字节)。
|
|
752
752
|
*/
|
|
753
|
+
/** CC-11 段内全部已提交思考行 uuid(按序);CC-15(0.69.3):形 (a) 为 `[]`(在场但空 = 本包判定本段零已提交行),形 (f) 零经手才整键缺席。 */
|
|
753
754
|
committedUuids?: readonly string[];
|
|
754
755
|
/** core 铸的事件身份(uuidv7 形);wire 未必带 ⇒ 缺席时本键不在场。 */
|
|
755
756
|
eventId?: string;
|
package/dist/skillsWireCaps.d.ts
CHANGED
|
@@ -8,9 +8,13 @@
|
|
|
8
8
|
* loader graph (loadSkillsDir / loadPluginCommands pull analytics/signals/fs). It imports ONLY the `SkillSpec`
|
|
9
9
|
* type (erased at build), so a test can esbuild-bundle THIS file alone — no runtime side effects.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* 0.70.0(CC-04,server 7.78.1 + core 7.19.0):the ONLY remaining cap is `content` ≤1MB (the engine's skill load
|
|
12
|
+
* door — over it is rejected outright, so we truncate HERE to keep that field well-formed by construction).
|
|
13
|
+
* The item-count cap (10), the name-length cap (64) and the description-length cap (1024) are RETIRED: server
|
|
14
|
+
* 7.78.1 `validateUserSkills` no longer rejects on any of them, and the engine's `<skills>` listing (core 7.19.0)
|
|
15
|
+
* fits descriptions to a byte budget itself and ANNOUNCES it (`skills.listing_truncated`, see
|
|
16
|
+
* `readSkillsListingTruncated`). Pre-truncating below a door that no longer exists would be a silent cut nobody
|
|
17
|
+
* could see — the exact disease the `content` cap once had at 32768.
|
|
14
18
|
*
|
|
15
19
|
* 🔴 措辞收窄(2026-08-08 对抗复审命中):原文写「make the live request well-formed by construction」——
|
|
16
20
|
* 那是**过头的承诺**,本模块只管每个字段的**逐字段**帽,管不到整请求。server 那边 10 项 × 1MB 与
|
|
@@ -20,11 +24,15 @@
|
|
|
20
24
|
*/
|
|
21
25
|
import type { SkillSpec } from '@sema-agent/sdk';
|
|
22
26
|
/**
|
|
23
|
-
*
|
|
27
|
+
* Caps for `TaskRequest.skills` — 0.70.0 起只剩 `content`(违反 = 400 / 引擎整拒)。
|
|
24
28
|
*
|
|
25
|
-
* 🔴
|
|
26
|
-
*
|
|
27
|
-
*
|
|
29
|
+
* 🔴 **0.70.0 退役三键 `items` / `name` / `description`**(CC-04;C-R41 / C-R43 ①):server 7.78.1 的
|
|
30
|
+
* `validateUserSkills` 直读 dist 已无条数帽、无 name / description 长度帽(7.78.0 及以前仍有);引擎侧
|
|
31
|
+
* (core 7.19.0)`<skills>` 清单按字节预算自己裁描述 / 退成 name-only,并发 `skills.listing_truncated`
|
|
32
|
+
* 通告。本包再按 10 / 64 / 1024 预截 = 在一道已不存在的门下面静默切字节,链上没有任何一层会响。
|
|
33
|
+
* 读这三键的消费端(cli `skillsWireOverflow`)与本版同窗退役。
|
|
34
|
+
*
|
|
35
|
+
* 🔴 对照坐标(取证方式 = 直读 shipped 产物,不信任何注释):
|
|
28
36
|
* · `content` —— server `MAX_SKILL_CONTENT_CHARS = 1_048_576`(`dist/http/server.js`),它自己的
|
|
29
37
|
* 头注点名这是 core `SKILL_CONTENT_MAX_CHARS` 的同值孪生(core `dist/core/runner/synthetic-tools.js`
|
|
30
38
|
* 的 `SKILL_CONTENT_MAX_CHARS = 1024 * 1024`);core 1.293 起技能正文**零截断、超 1MB 整拒**。
|
|
@@ -36,15 +44,11 @@ import type { SkillSpec } from '@sema-agent/sdk';
|
|
|
36
44
|
* 反漂移腿:`scripts/run-engine-vocab-floor-test.mjs` 的 G2-a 段拿本键对**实装 @sema-agent/core**
|
|
37
45
|
* 的 `SKILL_CONTENT_MAX_CHARS` 逐值对账(devDep 钉在本仓,不靠兄弟树物料)——上游改门,那边先红。
|
|
38
46
|
*
|
|
39
|
-
* ⚠️ 留给上游的一处**上游内部张力**(如实记录,本层不代偿)
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* 即本次修的这个病。真要治,治在 server 的两帽一致性上。
|
|
47
|
+
* ⚠️ 留给上游的一处**上游内部张力**(如实记录,本层不代偿):技能条数已无帽,N 条 × 1MB 对上 server
|
|
48
|
+
* 自己的整体 body 帽 8MB(`MAX_BODY`)—— 极端组合会整请求 400/413。这是 server 的事,壳侧不做「按剩余
|
|
49
|
+
* 预算偷偷多截一点」的补偿:那正好会把一个**响亮的 400** 换回一次**静默截断**。
|
|
43
50
|
*/
|
|
44
51
|
export declare const SKILL_CAPS: {
|
|
45
|
-
readonly items: 10;
|
|
46
|
-
readonly name: 64;
|
|
47
|
-
readonly description: 1024;
|
|
48
52
|
readonly content: 1048576;
|
|
49
53
|
};
|
|
50
54
|
/** The minimal shape of a loaded skill `Command` this projection reads (a structural subset of CC's Command,
|
|
@@ -61,12 +65,14 @@ export interface SkillCmdLike {
|
|
|
61
65
|
/** the skill's own directory (`createSkillCommand` baseDir → command.skillRoot); SKILL.md lives at root/SKILL.md. */
|
|
62
66
|
skillRoot?: string;
|
|
63
67
|
}
|
|
64
|
-
/** Build one
|
|
68
|
+
/** Build one `SkillSpec`, or null when there is no usable name/body. description folds in `whenToUse`
|
|
65
69
|
* (CC's progressive-disclosure metadata is name+description+whenToUse) so the engine's Skill tool can select
|
|
66
|
-
* it.
|
|
70
|
+
* it. 0.70.0: only `content` is capped (engine load door); name / description go through untouched — the
|
|
71
|
+
* engine's listing budget fits the description and announces when it had to (`skills.listing_truncated`). */
|
|
67
72
|
export declare function toCappedSpec(name: string, description: string, whenToUse: string, body: string): SkillSpec | null;
|
|
68
73
|
/**
|
|
69
|
-
* PURE projection: loaded skill commands → `SkillSpec[]` (capped, deduped by name
|
|
74
|
+
* PURE projection: loaded skill commands → `SkillSpec[]` (content-capped, deduped by name; 0.70.0: NO item cap —
|
|
75
|
+
* every eligible skill goes on the wire, the engine budgets the listing). `resolveBody`
|
|
70
76
|
* supplies each command's raw SKILL.md body (null ⇒ skip); injecting it keeps this function IO-free and
|
|
71
77
|
* unit-testable. Only MODEL-INVOCABLE prompt skills are sent — UI-only / `disableModelInvocation` commands
|
|
72
78
|
* are excluded (engine injection feeds the model's Skill tool, not the slash menu).
|
package/dist/skillsWireCaps.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Caps for `TaskRequest.skills` — 0.70.0 起只剩 `content`(违反 = 400 / 引擎整拒)。
|
|
3
3
|
*
|
|
4
|
-
* 🔴
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* 🔴 **0.70.0 退役三键 `items` / `name` / `description`**(CC-04;C-R41 / C-R43 ①):server 7.78.1 的
|
|
5
|
+
* `validateUserSkills` 直读 dist 已无条数帽、无 name / description 长度帽(7.78.0 及以前仍有);引擎侧
|
|
6
|
+
* (core 7.19.0)`<skills>` 清单按字节预算自己裁描述 / 退成 name-only,并发 `skills.listing_truncated`
|
|
7
|
+
* 通告。本包再按 10 / 64 / 1024 预截 = 在一道已不存在的门下面静默切字节,链上没有任何一层会响。
|
|
8
|
+
* 读这三键的消费端(cli `skillsWireOverflow`)与本版同窗退役。
|
|
9
|
+
*
|
|
10
|
+
* 🔴 对照坐标(取证方式 = 直读 shipped 产物,不信任何注释):
|
|
7
11
|
* · `content` —— server `MAX_SKILL_CONTENT_CHARS = 1_048_576`(`dist/http/server.js`),它自己的
|
|
8
12
|
* 头注点名这是 core `SKILL_CONTENT_MAX_CHARS` 的同值孪生(core `dist/core/runner/synthetic-tools.js`
|
|
9
13
|
* 的 `SKILL_CONTENT_MAX_CHARS = 1024 * 1024`);core 1.293 起技能正文**零截断、超 1MB 整拒**。
|
|
@@ -15,28 +19,28 @@
|
|
|
15
19
|
* 反漂移腿:`scripts/run-engine-vocab-floor-test.mjs` 的 G2-a 段拿本键对**实装 @sema-agent/core**
|
|
16
20
|
* 的 `SKILL_CONTENT_MAX_CHARS` 逐值对账(devDep 钉在本仓,不靠兄弟树物料)——上游改门,那边先红。
|
|
17
21
|
*
|
|
18
|
-
* ⚠️ 留给上游的一处**上游内部张力**(如实记录,本层不代偿)
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* 即本次修的这个病。真要治,治在 server 的两帽一致性上。
|
|
22
|
+
* ⚠️ 留给上游的一处**上游内部张力**(如实记录,本层不代偿):技能条数已无帽,N 条 × 1MB 对上 server
|
|
23
|
+
* 自己的整体 body 帽 8MB(`MAX_BODY`)—— 极端组合会整请求 400/413。这是 server 的事,壳侧不做「按剩余
|
|
24
|
+
* 预算偷偷多截一点」的补偿:那正好会把一个**响亮的 400** 换回一次**静默截断**。
|
|
22
25
|
*/
|
|
23
|
-
export const SKILL_CAPS = {
|
|
24
|
-
/** Build one
|
|
26
|
+
export const SKILL_CAPS = { content: 1_048_576 };
|
|
27
|
+
/** Build one `SkillSpec`, or null when there is no usable name/body. description folds in `whenToUse`
|
|
25
28
|
* (CC's progressive-disclosure metadata is name+description+whenToUse) so the engine's Skill tool can select
|
|
26
|
-
* it.
|
|
29
|
+
* it. 0.70.0: only `content` is capped (engine load door); name / description go through untouched — the
|
|
30
|
+
* engine's listing budget fits the description and announces when it had to (`skills.listing_truncated`). */
|
|
27
31
|
export function toCappedSpec(name, description, whenToUse, body) {
|
|
28
|
-
const n = name.trim()
|
|
32
|
+
const n = name.trim();
|
|
29
33
|
const c = body.trim().slice(0, SKILL_CAPS.content);
|
|
30
34
|
if (!n || !c)
|
|
31
35
|
return null;
|
|
32
36
|
const desc = [description.trim(), whenToUse.trim()]
|
|
33
37
|
.filter((s) => s.length > 0)
|
|
34
|
-
.join(' — ')
|
|
35
|
-
.slice(0, SKILL_CAPS.description);
|
|
38
|
+
.join(' — ');
|
|
36
39
|
return { name: n, description: desc, content: c };
|
|
37
40
|
}
|
|
38
41
|
/**
|
|
39
|
-
* PURE projection: loaded skill commands → `SkillSpec[]` (capped, deduped by name
|
|
42
|
+
* PURE projection: loaded skill commands → `SkillSpec[]` (content-capped, deduped by name; 0.70.0: NO item cap —
|
|
43
|
+
* every eligible skill goes on the wire, the engine budgets the listing). `resolveBody`
|
|
40
44
|
* supplies each command's raw SKILL.md body (null ⇒ skip); injecting it keeps this function IO-free and
|
|
41
45
|
* unit-testable. Only MODEL-INVOCABLE prompt skills are sent — UI-only / `disableModelInvocation` commands
|
|
42
46
|
* are excluded (engine injection feeds the model's Skill tool, not the slash menu).
|
|
@@ -45,8 +49,6 @@ export function skillCommandsToSpecs(cmds, resolveBody) {
|
|
|
45
49
|
const specs = [];
|
|
46
50
|
const seen = new Set();
|
|
47
51
|
for (const cmd of cmds) {
|
|
48
|
-
if (specs.length >= SKILL_CAPS.items)
|
|
49
|
-
break;
|
|
50
52
|
if (cmd.type !== 'prompt' || cmd.disableModelInvocation)
|
|
51
53
|
continue;
|
|
52
54
|
const body = resolveBody(cmd);
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
|
|
20
20
|
| 项 | 值 | 真源 |
|
|
21
21
|
|---|---|---|
|
|
22
|
-
| 本包 | `@sema-agent/client-core` **0.
|
|
22
|
+
| 本包 | `@sema-agent/client-core` **0.70.1**(本批发布版 = patch,零型面变化:🔴 CC-17 `handOffOnly` 形(段跨包侧边界 ∧ 已提交前缀自身过期)同步两本补差账 + 清未提交尾段 —— 修前形一卡后原始未脱敏尾段照常上屏落盘、形二 `result` 臂把它当缺的后缀补吐;账对不上(前缀跨多条消息)则退回既有行为;§40 / 40y 两条)|
|
|
23
23
|
| peer:wire 契约 | `@sema-agent/sdk` **>=8.4.0**(value-level,非 type-only;**0.60.0 抬版**,四条硬理由见 §24a 与 `scripts/run-sdk-floor-test.mjs` 的 `FLOOR` 注;上一次是 0.59.0 的 `>=8.3.0`)。🔴 支持窗同批收到 **engine ≥7.64.0**:sdk 8.4.0 与 7.63.0 及以前的 wire **不同窗** | `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
|
+
| 公开导出面 | **986** 个运行期符号(+ 44 个测试钩;= 0.70.0 未发布版的值:相对 0.69.2 **一件 additive(`readSkillsListingTruncated`,§39)、零删除**;985 = 0.69.2 的值:相对 0.69.1 **三件 additive、零删除**(CC-13 `isSubFlowSegmentEnd` / `SEGMENT_END_IDENTITY_KEYS` / `droppedWhySentence`,§38);982 = 0.69.0 未发布版的值(原排 0.68.3,因 peer 地板抬升改 minor)= 相对 0.68.2 **十七件 additive、零删除**:`fetchMcpPanel`(CC-03 补件,§36e)+ `readWorkflowResumeAdmissionIncomplete`(CC-05 core 7.18.0 #755)+ `installCoreValuePorts`/`hasCoreValuePorts`/`hasCoreValuePort`/`coreValuePortMisses`/`CORE_VALUE_PORT_NAMES` + 十读口(CC-07 core 值级端口,§36d);0.68.2 相对 0.68.1 十三件 additive:`SEMA_SEGMENT_ID_KEY`(CC-01 段身份键,§35f)/ `projectMcpPanel`+`mcpPanelLastLegDetail`+`projectMcpSection`(CC-03 `/mcp` 面板读视图,§35g)/ `resolveTextSegmentAuthority`/`createTextSegmentLedger`(L-318 `text_end` 权威段替换的判决单源 + print 形段账,详见 §35b/§35c)/ `memoryCaptureDeclarationField`/`MEMORY_CAPTURE_OFF`(L-316 会话级隐私声明的字面唯一铸点,§35d)/ `engineUrl`/`probeHealth`(L-61 件④ SDK 纯工具面原样转口,§35d)/ `AgentClient`/`isApprovalRequestFrameV1`/`isApprovalRevokeFrameV1`(L-61 存量清零:SDK **wire 面**原样转口,§35e)。`0.68.1`/`0.68.0` 是 **952**,那批是相对 0.67.2 **二十件 additive、🔴 两件删除(BREAKING)**:additive = `TERMINAL_CAUSE_KINDS`/`isTerminalCauseKind`/`RUN_TERMINAL_NOT_SUCCESS_STATUSES`/`RUN_TERMINAL_STATUSES`(L-247 终态词两表分源,详见 §33b)/ `SEMA_SUBAGENT_USAGE_PARTIAL_KEY`/`subagentUsageIsPartial`(L-244 子代下界位自有名,§33g)/ `ASK_UNRESOLVABLE_CAUSES`/`readAskUnresolvable`/`DURABLE_MANDATE_SOURCES`/`readDurableGateUnavailable`(core 7.17.0 #709 ①② 两只通告事实窄读器,§33c)/ `WORKFLOW_PARK_TRUTH_UNREADABLE`/`WORKFLOW_PARK_NOT_PENDING`/`WORKFLOW_PARK_BINDING_BROKEN`/`WORKFLOW_PARK_REQUIRES_RUN_STORE`/`WORKFLOW_PARK_REFUSAL_CODES`/`isWorkflowParkRefusalCode`/`readWorkflowParks`(core 7.17.0 #652 park 真相四码 + parks 三键读器,§33d)/ `ENGINE_STOP_REASONS`/`engineStopReasonToCc`(L-246 A13 停止原词映射下沉,§33g)/ `readCancelRequested`(L-230 读面,§33f);🔴 **删除两件** `TERMINAL_NOT_SUCCESS_STATUSES`/`TERMINAL_STATUSES`(随 L-247 两表分源更名成 `RUN_TERMINAL_*`,clean-cut **不留别名** —— 留一个别名等于让端可以继续按合起来的那张表读,分源就白做了,详见 §33b)。`0.67.0` 是 **934**,那批是相对 0.66.0 **七件 additive、🔴 两件删除**:additive = `CLASSIFIER_DENY_CAUSES`/`isClassifierDenyCause`/`classifierDenyCauseOf`/`classifierDenyCauseDetail`(core 7.14.0 退役 `classifierUnavailable` 之后的**拒绝面**继任读器与措辞,详见 §32b)/ `RULE_STORE_UNREADABLE_KINDS`/`isRuleStoreUnreadableKind`/`ruleStoreUnreadableDetail`(core 7.14.0 #688 C3 的规则店机制位三件,详见 §32d);🔴 **删除两件** `classifierUnavailableOf`/`classifierUnavailableDetail`(随 core 7.14.0 的 Retired keys 表整族退役,clean-cut 不留别名,详见 §32b;同批删的还有**型** `ClassifierUnavailableView`、卡位与帧位 `classifierUnavailable`、以及一条恒真的型面钉 `_askOriginWordsPin`)。`0.66.0` 是 **929**,那批是一件 additive、零删除:`readRunCostFacts`(终局成本事实的唯一读器:`costBreakdown` / `nested` 窄读 + 对账三段与两个判别位,终帧超集键与 chrome 对账臂共用它;详见 §31c);已发的 **0.65.x 十一件 additive、两件删除**:additive = `DECIDE_WORKFLOW_HOST_UNKNOWN`/`DECIDE_WORKFLOW_HOST_NOT_PARKED`/`DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED`/`DECIDE_WORKFLOW_LANE_CODES`/`readDecideReceipt`/`decideAcceptedNotResolved`/`decideRefusalFromError`(B-070 `/decide` 回执读面与三码人话,详见 §30h)/ `TERMINAL_NOT_SUCCESS_STATUSES`/`isTerminalNotSuccess`/`TERMINAL_STATUSES`/`isTerminalStatus`(L-215② 终局词汇单铸谓词,详见 §30j);🔴 **删除两件** `AUTO_MODE_BREAKER_CAUSES`/`classifierBreakerOf`(熔断族随 core 7.12.0 的 Removed(BREAKING) 整只退役,clean-cut 不留别名,详见 §30k②;同批删的还有**型** `ClassifierBreakerView` 与 `ClassifierStatusView.breaker` 一位)。`0.64.2` 是 **919**,那批是一件 additive、零删除:`readDenialLimitFallback`(限额回落卡的窄读器上公面,壳侧同判据副本退役,详见 §29③);`0.64.0` 是 **918**,那批是件①+件② 十三件 additive、零删除:`CLASSIFIER_STATUS_STATES`/`classifierBreakerOf`/`classifierStatusOf`/`classifierStatusDetail`(分类器状态面,详见 §28②)/ `THINKING_FORMATS`/`THINKING_FORMAT_WIRE_TWINS`/`THINKING_DISABLE_PROBE_ORDER`/`MODEL_PROBE_VERDICTS`/`PROBE_PROMPT`/`PROBE_MAX_TOKENS`/`probeRequestBody`/`probeModelCapability`/`applyProbeToEntry`(模型思考能力探测,详见 §28①);`0.63.0` 是 **905**,那批是八件 additive、零删除:`projectServerGateKnobs`/`postureKnobSourceOf`/`postureSourceIsOperatorPinned`/`postureKnobDetail`/`POSTURE_SOURCE_WORDS`(S-178 三根 posture 旋钮读数,详见 §27b)/ `PERSISTED_RULE_BEHAVIORS`/`PERSISTED_RULE_BEHAVIOR_UNKNOWN`/`persistedRuleBehaviorOf`/`persistedRuleBehaviorLabel`/`revokeTargetFromPersistedRule`(三态规则身份,§27c)/ `engineIdentityOf`/`engineIdentityVerdict`/`engineIdentityChanged`/`engineIdentityChangedBy`/`ENGINE_IDENTITY_ANCHORS`(S-179 代际锚,§27d)/ `GATE_DENIED_BY_WORDS`/`gateDeniedByDetail`/`ASK_ORIGIN_WORDS`/`askOriginDetail`(门词汇 +2,§27e)/ `PERMISSION_RULE_ISSUE_CODES`/`RETIRED_PERMISSION_RULE_ISSUE_CODES`/`permissionRuleIssueDetail`(规则 lint 码表,§27f)/ `projectToolRoster`/`toolRosterNames`/`toolShimFromRoster`/`applyToolRosterDelta`(L-161 工具名册,§27g)/ `ENGINE_NOTICE_CODES`/`ENGINE_NOTICE_AUDIENCE`/`noticeAudienceOf`/`engineNoticeInCatalog`/`MCP_INJECTION_DROP_REASONS`/`readMcpInjectionDrop`(L-167 通告码册,§27h)/ `AUTO_MODE_UNAVAILABLE_CAUSES`/`AUTO_MODE_BREAKER_CAUSES`/`classifierUnavailableOf`/`classifierUnavailableDetail`(件⑧ 分类器不可用事实,§27h2);`0.62.0` 是 **869**,那批是五件 additive、**零删除**:`capForDisplay`(呈前消毒 + 封长的共用铸点,详见 §26⑦)/ `SEAT_SEND_MESSAGE_KEY_ORIGINS`(座位载荷逐键出身表,详见 §26③)/ `configureSubagentContentStore`+`subagentContentStoreConfig`+`SUBAGENT_CONTENT_STORE_DEFAULTS`(子代内容账本字节预算,测试钩 `__resetSubagentContentStoreConfigForTests` +1,详见 §26②);`0.61.0` 是 **864**,那批是三件 additive、**零删除**:`projectReadFacePosture`/`readFacePostureDetail`/`readFaceDisagreement`(S-167 READ 容纳面 operator 读器,详见 §25);`0.60.0` 是 **861**,那批是二十五件 additive、**零删除**:`readRunTerminal`/`runTerminalCode`/`runTerminalGateKind`/`runTerminalGateToolName`/`isReviewPark`/`REVIEW_PARK_GATE_KINDS` 六件终局因由读器 + `gateOutcomeOf`/`isDeniedGate`/`gateDeniedBy`/`gateApprover`/`isApprovalWindowExpiredGate`/`isDenialLimitAutoDeniedGate`/`isParkSlaExpiredGate`/`isHumanSettledGate` 八件门记录读器 + `projectWriteProtectionCapability`/`noteEngineCapsForWriteProtection`/`observedWriteProtection`/`forgetWriteProtectionReading`/`writeProtectionDoctorDetail`/`projectWriteProtectionPosture`/`writeProtectionPostureDetail` 七件写保护读面(测试钩 `__resetWriteProtectionReadingsForTests` +1)+ `readWireErrorCode` + 真机边界①的两件 `isGateParkedToolEnd`/`GATE_PARKED_ERROR_CODE` + 异源复审逼出的 `engineCapsGeneration`;`0.59.0` 是 **836**,那批是八件 additive:`RULE_OFFERS_ABSENCE_REASONS`/`DENIAL_LIMIT_KINDS` 两张闭词表再导出 + `engineCapValue` 能力位四态通用读口 + `projectSqlEngineCapability`/`observedSqlEngine`/`noteEngineCapsForSqlEngine`/`forgetSqlEngineReading`/`sqlEngineDoctorDetail` 五件 SQL 姿态读面(测试钩 `__resetSqlEngineReadingsForTests` +1);`0.58.0` 是 **828**,那批是三件 additive:`RULE_OFFER_MATCHES`/`RULE_OFFER_BATCH_MEMBER_KINDS`/`RULE_OFFER_UNCOVERED_REASONS` 三张闭词表再导出 + `RESUME_REFUSAL_CODES`/`RESUME_PLACEMENT_MISMATCH`/`resumeRefusalFromError`/`resumeRefusalContent` 四件文案铸点;`0.57.0` 是 **821**;`0.56.0`/`0.55.0` 是 **815**;已发 `0.54.0`(design/385 十件 additive 含 `AUTHORITY_ENVELOPE_TAGS`);`0.52.0` 是 **805**(L-69⑨ 两件);`0.51.0` 是 **803**;`0.50.0` 是 **800**(S-81 五件);`0.49.0` 是 **795**;`0.48.0` 是 **794**;npm `0.47.0` 是 **790**,`0.46.0` 是 **787**,`0.44.0` 是 **783**,`0.43.1`/`0.43.0` 是 **776**,`0.42.0` 是 **771**,`0.41.0` 是 **767**,`0.39.0` 是 **766**,`0.38.0` 是 **764**;`0.37.0` 是 **753**,见 `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
|
|
|
@@ -111,7 +111,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
111
111
|
|
|
112
112
|
## §2 公共导出面地图(按域)
|
|
113
113
|
|
|
114
|
-
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**
|
|
114
|
+
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**986** 项)。
|
|
115
115
|
> 本节**不逐名抄**,只给「域 → 承重导出 → 用途 → 实现锚」。承重导出 = 一个端为了让这个域干活
|
|
116
116
|
> **必须**直接调到的那几个符号;其余是它们的类型、变体与辅助位。
|
|
117
117
|
> 单一入口:`import { … } from '@sema-agent/client-core'`(`exports` 只有 `.` 一个;
|
|
@@ -135,7 +135,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
135
135
|
`WorkflowsGateUnknownDenial` 四形**不在**基线里,`src/selfOrchestrationDenial.ts` 对基线贡献
|
|
136
136
|
**4** 项运行期导出(三个函数 + `SELF_ORCHESTRATION_RETRY_WITHOUT`)。
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
986 项的内部构成(帮助端估读表大小;0.70.0 起 +1 函数;0.69.2 起 +3:常量 1 / 函数 2):**299** 项是 `SCREAMING_SNAKE` 常量数据表/词汇表
|
|
139
139
|
(矩阵、键集、env 名、锚串)而非可调用物;**6** 项是 PascalCase 运行期值
|
|
140
140
|
(`ControlRouter` / `ControlSafetyError` / `HitlBridge` / `HitlSafetyError` / `DecideTransportRetryExhaustedError`);
|
|
141
141
|
**41** 项是 `*For(sessionKey, …)` 的 per-session 变体(§6;其中 `engineNamespaceKeyFor` 是命名巧合 —— 参数是 baseUrl 不是 sessionKey,见域 14)。
|
|
@@ -159,7 +159,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
159
159
|
| 13 | **座位 IPC 契约** | 34 | `LOCAL_SESSIONS_SPEC` · `SEAT_METHOD_NAMES` · `SEAT_EVENT_TYPES` · `isLocalSessionEvent` · `isToolPermissionRequest` · `toolPermissionRequestId` · `SEAT_VALIDATOR_KEY_COVERAGE` · `SEAT_SEND_MESSAGE_KEY_ORIGINS`(0.62.0:座位载荷**逐键出身**登记 —— 每个位要么写明转投哪个引擎请求位、要么写明为什么不上 wire;常驻门对**装在盘上的** sdk 型面逐名核,详见 §26③)| desktop↔web 座位 IPC 契约的**单一真源**(此前两边各一份、名字零重合 ⇒ 编译器永远不会告诉你它们漂了)。🔴 加 verb 忘了加 `LOCAL_SESSIONS_SPEC` **不报错**:preload 不注册 channel、渲染端读到 `undefined` | `src/seatContract.ts`(**零 import**,纯类型 + 常量 + 纯谓词)。🔴 **证据等级标注(0.42.0,test [5087] 的「语料**种类**缺口」/ cli [5088] 认领件)**:该文件里所有以「CC 如何如何」为形的断言(`212 methods` / `854-channel census` / 方法名逐字保留 / `fQe` 逐字段对照 / 一切 `.vite/build/index.chunk-*.js` 坐标)**证据等级 = 桌面 unpack,本地语料库不可复验** —— 本仓手边可复验的参照语料**只覆盖终端 CLI 形态**的静态产物,拿它去 grep 桌面壳里的符号只会零命中,而零命中在这里**既不证真也不证伪**。复核这些断言**不得**拿本仓语料当反证 |
|
|
160
160
|
| 14 | **宿主端口与会话槽** | 41 | `installHost` · `installHostFor` · `installCoreValuePorts` + 十读口 + 三存在性口(0.69.0 CC-07:core 值级面端口注入,Node 宿主装配根装、浏览器 lane 恒缺席)· `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` |
|
|
161
161
|
| 15 | **控制面与传输** | 122 | `ControlRouter`(+ `ControlSafetyError`)· `fetchMcpPanel`(0.69.0:经 sdk `sessions.mcp` 取体 + 投视图,不裸 fetch)· `projectMcpPanel` + `mcpPanelLastLegDetail`(0.68.2 CC-03:`GET /v1/sessions/:id/mcp` 面板体防御读视图 + `lastLegMcp` 一行措辞铸点;缺席 = 键不铸、读不懂 = `lastLegMcpUnreadable`、禁与 `servers[]` 对账)· `makeEngineWireClient` + `resolveWireAuth` · `installEngineWireTarget` · `diagnoseSseIdleTear` / `isSseIdleError` · `attemptActiveRunSelfHeal` + `activeRunBusySignal` + `activeRunSelfHealRow` / `activeRunBusyHeadlessRow` · `kickEngineCapsProbe` / `engineCapTrue` / `invalidateEngineCaps(baseUrl, probe?)`(#307 S25:引擎温切后的 caps 生产失效口 —— kick 自带幂等闸,同 baseUrl 重启后不显式失效就永远读到旧引擎那一版能力位;调用方 = 壳的 respawn/restartEngine。🔴 **推荐两参形**:第二参给替代探测则「推进代际 + 注册新探测」在同一同步块内完成,失效与下一次 kick 之间那个「等待者读到未判」的窗按构造不存在;单参形保留给「只丢缓存、这一刻没有替代探测」的调用方,那种情形下读到未判是诚实结局) · `engineCapValue`(S-131,0.59.0:能力位的**四态**通用读口 `unobserved`/`not_reported`/`null`/`value` —— 既有三口把四种「读不出」全折成 fail-closed 一档,对**放行**问题是对的、对**读面/诊断**问题是错的:`null`(引擎明确说没有,正面事实)会与「老引擎不报」「还没探到」在屏上同形。`value` 位刻意不做形校验,形归各能力位自己的窄读器,详见 §23b)· `projectSqlEngineCapability` / `observedSqlEngine` / `noteEngineCapsForSqlEngine` / `forgetSqlEngineReading` / `sqlEngineDoctorDetail`(S-131,0.59.0:`Capabilities.sql`(server ≥7.60.0)的四态读面**从壳侧上收** —— 归层债,0.58.0 时它长在壳里正是因为包侧没有嵌套对象读口。🔴 **导出名与壳侧那份逐字同名 = drift-lock**;`txnMode: null` 是铸点域内的合法值不是畸形;换代失效口清成未观测而不是留旧值,详见 §23b)· `mapBrainStatusToRetry` · `waitForClaimRelease` + `CLAIM_RELEASED_STATES` / `CLAIM_HELD_STATES` · `atMostOnceFailureClass` / `readSteerDelivery` · `clearRunningChoiceOffer`(Inkglow-1085 P0b①:「Do nothing」登记的清口 —— 端的「重新打开操作菜单」入口;登记在场时 attemptActiveRunSelfHeal 不整卡重弹,not-parked 结局带 `alreadyOffered: true` 判别位,端据此降级渲一行)· `INTERACTIVE_WAY_OUT`(默认出路串单源)· `engineSessionParamFor`(design/285 批 0:`?session=` 派生的 **per-key** 形 —— `hostSessionFor(sessionKey)?.currentSessionId()` + [1501] 空串归一;零参 `engineSessionParam()` = 默认槽兼容层,取值链逐字等价)· `normalizeWirePrincipal`(A-028.10:principal 在场性 trim 原语 —— 全空白=缺席不发头,engineWireTarget 两臂/makeEngineWireClient/壳 livePrincipal 同尺)· `readSessionMemoryStatus` / `classifyMemoryStatusFailure` / `readCaptureOptOut` / `readLastCapture`(S-53 会话记忆姿态读面,0.48.0:失败分诊**码优先**——两个 404 分道 `not_found.session` / `not_found.route`,无码 404 不猜落 failed;五键逐键缺席语义两个合读器,`lastCapture` 三态的判别材料是 `committedCount` 不是本键;IO 归宿主注入 `MemoryStatusClientLike`,详见 §11) · `classifyTurnWireError` / `isWireTransportError` / `isPreStreamDrainingReject` / `isResumeAtRejection` / `drainingRetryDelayMs` / `scenarioDenyFromError` + `WIRE_NETWORK_ERROR_PATTERN`(A-028.11/.13:turn 错误分型判定半场,人话文案与渲染归端)· `resumeRetryLaterFromError`(L-102,0.57.0:resume 族**时间性拒绝**二码的判型半场 —— 这一族里唯一**带得出「等多久」**(`retryAfterSec`)的两个码。🔴 闭集**不是**「哪些码可以等」的名单:同族 `resume.row_recycling` 同样可等(窗口自清)只是没有秒数 ⇒ 本读口返回 `null` 只意味着没命中这两码,详见 §21) · `projectWriteProtectionCapability` / `observedWriteProtection` / `noteEngineCapsForWriteProtection` / `forgetWriteProtectionReading` / `writeProtectionDoctorDetail` / `projectWriteProtectionPosture` / `writeProtectionPostureDetail`(S-138,0.60.0:`Capabilities.writeProtection` (engine ≥7.63.0)的**四态**读面 + operator 面行表 —— 与上面 S-131 那一格**同构同纪律**。🔴 三位刻意不合成一个布尔;`not_reported` **不是**「这台部署没有写保护表」(座位缺席恰是缺省表在岗);逐行 name/kind 走**最小披露**只上 operator 面,详见 §24e)· `projectReadFacePosture` / `readFacePostureDetail` / `readFaceDisagreement`(S-167,0.61.0:operator 面 `diagnostics.wiring.readFace`(engine ≥7.65.0)的窄读器 —— 与上面S-138 那一格**同构同纪律**。🔴 三句「答不出来」逐字互异且没有一句等于「没有 READ 档」;`source` 按开集读;与租户面 `capabilities.readFace` 刻意不合流,只带一个纯比较函数,详见 §25)| 上行通道的**监管**半场(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`、`src/sessionMemoryStatus.ts`、`src/writeProtectionCapability.ts`、`src/readFacePosture.ts` |
|
|
162
|
-
| 16 | **引擎词汇表与包自检** |
|
|
162
|
+
| 16 | **引擎词汇表与包自检** | 91 | `readSkillsListingTruncated`(0.70.0 CC-04:`skills.listing_truncated` 事实读器,§39)· `CONFIG_REFUSAL_CODES` / `isConfigRefusalCode` · `DECIDE_WORKFLOW_LANE_CODES`(+ 三个具名码;`/decide` workflow 车道,三条出路刻意不合并,详见 §30h)· `STOP_CONFLICT_CODES` · `isInterruptedToolEndCode` · `isRewindFamilyCode` · `CLIENT_VERBS` · `compensationSplitViolations` · `DELEGATION_CAP_CODES` / `isDelegationCapCode` / `DELEGATION_CONCURRENCY_CAP` / `DELEGATION_SESSION_CAP`(0.38.0 #318 件④:core 5.48.0 design/323 委派席位到限**两码,处置不对称禁合并** —— 并发帽=**可等**(兄弟结束即有位)/ 会话累计帽=**等也没用**(这条会话的配额用尽))· `CONFIG_DELEGATION_ENTRY_CAPS`(同批入 `CONFIG_REFUSAL_CODES` 识别表)· `delegationCapDispositionOf` / `MCP_SERVER_REVOKED`(0.39.0 载体到货消费件:core 5.50.0 补 `{ error: code, code }` 孪生拼法后两码真上 `tool_end.errorCode`,0.38.0「先立词不落消费分支」的已知局限自此解除;处置轴 `wait-for-slot` / `reuse-existing-or-await-reap` 机器可读(累计帽=retained-window 帐,行回收配额即回,处置=SendMessage 复用,**非**「换会话/永久耗尽」——0.38.0 段该句系勘误),未知 `delegation.*` 码 ⇒ `undefined`;`mcp.server_revoked` = 操作员 mid-session 吊销 server 后的工具面本地闸(被吊销的 server **名**今天不过 wire 境:detail.server 是进程内位,抬升腿只 lift code——归因渲染候 core 补 typed detail,已点名);载体门 = engine-vocab G3 腿锚 core dist 铸点)· `CAPABILITY_SELF_ORCHESTRATION_REQUIRED`(S-81,server 7.57.0:提交面的 selfOrchestration 准入拒绝码。🔴 **复用码** —— 与其它 `capability.*` 501 同体形而处置不同,消费点必须按**恰等**判、绝不放宽成前缀判;判型与「去键重发一次」归 `src/selfOrchestrationDenial.ts`,详见 §13) · `GATE_PARKED_ERROR_CODE`(0.60.0:「门把这次调用 park 了」的机读码单源 —— `frameRouter` 的连坐/中断判据与 `gateOutcome.isGateParkedToolEnd` 读同一个常量;真机黑盒直证 park 短路帧上**没有 `gate`**,这个码是那一形唯一的信号,详见 §24c)| 三端分臂共用的**去字面化** `errorCode` 词表(病根正是三端各抄一份字面);编译期 verb 闭合门;搬迁补偿登记表 | `src/engineErrorCodes.ts`(计数以 `scripts/public-export-baseline.json` 为准,别手抄;A-028.11/.13 补 `DRAINING_ERROR_CODE`/`SCENARIO_NOT_ALLOWED_ERROR_CODE`/`RESUME_AT_ERROR_CODE_PREFIX`;#318 件④ 补 `delegation.*` 族四位 + `config.delegation_entry_caps`;0.39.0 补三新码消费件三位);S-81 补 `capability.self_orchestration_required` 一位;L-102 补 `resume.*` 时间性拒绝二码 + 闭集 `RESUME_RETRY_LATER_CODES` 三位)、`src/classifierVerdictWire.ts`、`src/compensations.ts`、`src/clientSlice.ts`;**0.67.0 补锚**(这三件的导出一直计在本域,而本表此前没有它们的锚行 —— 如实补上,不是搬家):`src/gateVocabulary.ts`(`GATE_DENIED_BY_WORDS`/`gateDeniedByDetail`/`ASK_ORIGIN_WORDS`/`askOriginDetail` + 🆕 `RULE_STORE_UNREADABLE_KINDS`/`isRuleStoreUnreadableKind`/`ruleStoreUnreadableDetail`,详见 §32d)、`src/autoModeUnavailable.ts`(`AUTO_MODE_UNAVAILABLE_CAUSES` + 🆕 `CLASSIFIER_DENY_CAUSES`/`isClassifierDenyCause`/`classifierDenyCauseOf`/`classifierDenyCauseDetail`;🔴 同批**删**`classifierUnavailableOf`/`classifierUnavailableDetail`,详见 §32b)、`src/classifierStatus.ts`(`CLASSIFIER_STATUS_STATES`/`classifierStatusOf`/`classifierStatusDetail`)|
|
|
163
163
|
|
|
164
164
|
🔴 **`engineErrorCodes` 的开集纪律**(该文件头注逐字):这些 `ReadonlySet` / 前缀谓词一律是**识别表**,
|
|
165
165
|
回答的是「我认不认得这个码」,**绝不是**「合法码只有这些」。消费点 `switch` **必须留 `default`**,
|
|
@@ -4621,7 +4621,7 @@ an argument」。audience 答另一问:这条事实**说给谁听**。
|
|
|
4621
4621
|
**签名**
|
|
4622
4622
|
|
|
4623
4623
|
```ts
|
|
4624
|
-
ENGINE_NOTICE_CODES: readonly string[] //
|
|
4624
|
+
ENGINE_NOTICE_CODES: readonly string[] // 59 码,顺序同源(core 7.19.0 +3;0.70.0)
|
|
4625
4625
|
ENGINE_NOTICE_AUDIENCE: Readonly<Record<string, 'user' | 'operator'>>
|
|
4626
4626
|
noticeAudienceOf(code: unknown): 'user' | 'operator'
|
|
4627
4627
|
engineNoticeInCatalog(code: unknown): boolean
|
|
@@ -7736,6 +7736,8 @@ import { AgentClient, isApprovalRequestFrameV1, type AgentEvent } from '@sema-ag
|
|
|
7736
7736
|
|
|
7737
7737
|
**语义一句话**:一个身份覆盖「上一次段收口 → 本次段收口」之间过境的**全部** committed assistant 文本行。流开场一个初值;idle-flush 提交的半段与终态提交的同段**共享**一个身份(归属正要这个);`text_segment_end` 帧带的是轮换**前**的那个(与它盖过的行同值);臂处理完之后轮换;思考→回答边界**不**轮换;子流(带 `parentToolCallId`)的段边界不轮换。
|
|
7738
7738
|
|
|
7739
|
+
🔧 **0.70.0 订正(cli 1.0.116 归层清账真机实撞,一句打回)**:与 `text_segment_end.segmentId` 同值的**只有段边界之前**提交的行(idle-flush 半段、或收口前已提交的整段)。**常态段**(`text_end` 先到、定稿行在边界**之后**才提交)的定稿行按包语义属于**下一**窗口 —— 它提交时正文已经是权威文本(缓冲在臂里换过),端**不用也不该**拿它对账;拿它去认「这一段交出去的那一行」会锚错行。上面「idle-flush 提交的半段与终态提交的同段共享一个身份」只对**两者都在边界前提交**那一形成立。
|
|
7740
|
+
|
|
7739
7741
|
**形**:派生自窗口首帧锚 + 窗口序号(`idOf(anchor, 'segment<n>')`)⇒ **同流重放同身份**(与行 `uuid` 同一条确定性纪律);锚缺席那一形(durable 整条消息先于任何增量到达)退到 `ctx.uuid()` 并**缓存一次**。
|
|
7740
7742
|
|
|
7741
7743
|
**铸点唯一** = `adapt()` 的出口(`TextStream.stampSegmentIdentity`):durable 整条消息(`assistant` 臂)与流式分段(M1 提交口)两条腿都从那里过。🔴 **只盖尾块是 `text` 的 assistant 行**:思考块、只带 `tool_use` 的行、chrome 事件一个字节不动;就地盖不复制(台账/宿主持有的引用仍是同一条)。
|
|
@@ -7926,7 +7928,7 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
|
|
|
7926
7928
|
|
|
7927
7929
|
| 件 | 一句话 | 端要做什么 |
|
|
7928
7930
|
|---|---|---|
|
|
7929
|
-
| S-1 🔴 **已知边界** |
|
|
7931
|
+
| S-1 🔴 **已知边界**(0.70.0 改口:test [7335] B-125 实证 cli **两条车道**都经 `runStream`,「交互车道 `adapt()` 不经去重不受影响」是包视角的车道假设)| **凡经 `runStream` 的消费端(cli 交互 + `-p` 皆是;只有直喂 `adapt()` 的自建管线不在内)在 server <7.78.1 上收不到 `reasoning_end`**:server 7.77.0 给它的 SSE `id:` 复用该段首枚 `reasoning_delta` 的 id,`runStream` 的 durable seq 去重把它当重放丢;0.69.1 起**丢了必留痕**(`ctx.onDroppedFrame({ type:'reasoning_end', why:'duplicate_seq' })`)。**交互车道 `adapt()` 不经这只去重**,`thinking_segment_end` 照到 | 装 `onDroppedFrame` 的端把 `duplicate_seq` 当运维面留痕渲(不是用户面);`-p` 端在 server <7.78.1 上**如实披露**「推理面权威段不到」,不许壳侧绕过去重(去重律是契约) |
|
|
7930
7932
|
| S-2 🔴 **安全面** | **段末帧子流断闸改按身份三键**(CC-10):`text_end` / `reasoning_end` 内部臂新带 `sourceTaskId?` / `bgAgentId?`(与 `parentToolCallId` 同律原样透传),两臂任一在场即断;只带 `sourceTaskId` 的子代段末帧不再被当 leader 投上来 | 自建管线的端(print 车道 / 座位层)断子流按**三键**判,别只看 `parentToolCallId` |
|
|
7931
7933
|
| S-3 🔴 **安全面** | **跨工具卡的推理段归属交全**(CC-11):`thinking_segment_end` 新带 `committedUuids[]`(段内全部已提交思考行,按序;`committedUuid` = 末条兼容位);`committedPrefixLen` = 全部之和;新增 (b1) 形(前缀对得上 ⇒ 只换还押着的后段) | **宿主义务改口**:`committedPrefixDiverged` ⇒ `committedUuids` 首行就地换成 `content`,其余行**删除或清空其推理正文**(宿主按自身转录结构选;不再只换 `committedUuid` 那一条);缺席 ⇒ 行照旧 |
|
|
7932
7934
|
| S-4 | **park 两新键进 `WorkflowRunState`**(CC-12):`parks?` / `resumeAdmissionIncomplete?`(additive,由两读器铸) | 渲 resume 候选 / park 行的端改读视图上这两位;cli 的「到货锚」可翻 consumed |
|
|
@@ -7953,7 +7955,7 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
|
|
|
7953
7955
|
|
|
7954
7956
|
**包侧缺口:** ① CC-04 技能帽退役随 7.78.1 进 0.69.2;② server <7.78.1 上 `-p` 链收不到 `reasoning_end`(归口 server,本版只留痕);③ 其余同 §36 包侧缺口。
|
|
7955
7957
|
|
|
7956
|
-
## §38 🆕 0.69.2 收尾批(CC-14 思考段账按行所属引擎段 / CC-13 壳抄包两件出公面;CC-04 改随 core 7.19.0 + server 7.78.1 进 0.
|
|
7958
|
+
## §38 🆕 0.69.2 收尾批(CC-14 思考段账按行所属引擎段 / CC-13 壳抄包两件出公面;CC-04 改随 core 7.19.0 + server 7.78.1 进 0.70.0)
|
|
7957
7959
|
|
|
7958
7960
|
|
|
7959
7961
|
### 38a. 本节速览
|
|
@@ -7963,7 +7965,7 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
|
|
|
7963
7965
|
| S-1 🔴 **安全面** | **CC-14 `thinking_segment_end` 段账按「行所属的引擎段」记**:帧序 `thinking(A) → reasoning_end(A′) → tool_use → thinking(B) → text_delta → reasoning_end(B′)` 下,修前第一段定稿后迟交的 A′ 行被登进第二段 `committedUuids` 首项 ⇒ 宿主按 §37y ① 义务把 A′ 换成 B′、把 B 清空,上一段定稿丢失而披露仍说成功。修后定稿块提交时不登下一段账;定稿块押着时下一段推理增量直接叠上(无提交边界)⇒ 先按自己的段提交、新块另起,两段推理绝不同行 | 自拼推理面并按 `committedUuids` 改写转录的端:提货即除;cli 1.0.115 的壳侧自卫(记上一段权威文本命中即剔除)按本版到货退役。渲染层零动作 |
|
|
7964
7966
|
| S-2 | **CC-13 ① 子流三键判定出公面**:`isSubFlowSegmentEnd(frame)` + `SEGMENT_END_IDENTITY_KEYS`(`adapter/types.ts`;此前 `adapt/arms.ts` 私有) | 自建管线的端(print 车道 / 座位层)把自铸的三键判定改调本判定后删掉 |
|
|
7965
7967
|
| S-3 | **CC-13 ② 丢帧判词出公面**:`droppedWhySentence(why)` 导出;`ctx.onDroppedFrame` 载荷新带 `sentence?`(additive) | 自渲运维面的端删手抄判词表,读 `info.sentence ?? droppedWhySentence(info.why)` |
|
|
7966
|
-
| S-4 | CC-04 `SKILL_CAPS.items` 退役改预算式(读 core 7.19.0 `skills.listing_truncated` 通告)+ `ENGINE_NOTICE_CODES` 镜像 +3 | **不在本版**:改随 core 7.19.0 + server 7.78.1 进 **0.
|
|
7968
|
+
| S-4 | CC-04 `SKILL_CAPS.items` 退役改预算式(读 core 7.19.0 `skills.listing_truncated` 通告)+ `ENGINE_NOTICE_CODES` 镜像 +3 | **不在本版**:改随 core 7.19.0 + server 7.78.1 进 **0.70.0**(§39;本段原写 0.69.3,因型面变化改 minor) |
|
|
7967
7969
|
|
|
7968
7970
|
### 38z. 逐键处置表(0.69.2)
|
|
7969
7971
|
|
|
@@ -7974,7 +7976,7 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
|
|
|
7974
7976
|
| 3 | `isSubFlowSegmentEnd` / `SEGMENT_END_IDENTITY_KEYS` | **consumed(出公面)** | `src/adapter/types.ts`;`src/adapt/arms.ts` 与 `src/adapter/downstream/eventToSdkMessage.ts` 的 `#segmentEndProjection` 同源读;门 TSA W1–W3 |
|
|
7975
7977
|
| 4 | `droppedWhySentence` / `DroppedFrameInfo.sentence?` | **consumed(出公面,additive)** | `src/adapter/runStream.ts`;`src/adapter/types.ts`;门 TSA W4–W6 |
|
|
7976
7978
|
| 5 | `committedUuid` 兼容位语义 | **consumed(明写)** | = 段内**末条**(0.69.0 单行时代的钥匙);首行 = `committedUuids[0]`。端以 `committedUuids[0]` 为首行、仅在列表缺席时回落 `committedUuid` |
|
|
7977
|
-
| 6 | CC-04(`SKILL_CAPS.items` 退役 / `skills.listing_truncated` / 通告码 +3) | **不在本版(0.69.3)** | 候 core 7.19.0 / server 7.78.1 发布;[7315] 预发布判据已表态认领 [7316] |
|
|
7979
|
+
| 6 | CC-04(`SKILL_CAPS.items` 退役 / `skills.listing_truncated` / 通告码 +3) | **不在本版(0.70.0,原写 0.69.3)** | 候 core 7.19.0 / server 7.78.1 发布;[7315] 预发布判据已表态认领 [7316] |
|
|
7978
7980
|
|
|
7979
7981
|
### 38y. 🔴 三端升级必读(固定段式,[C295];本批**三条**)
|
|
7980
7982
|
|
|
@@ -7982,4 +7984,64 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
|
|
|
7982
7984
|
2. **自建管线的端断子流改调 `isSubFlowSegmentEnd`**(或读 `SEGMENT_END_IDENTITY_KEYS`),删自铸的三键判定;判定语义与 §37y ② 逐字相同(按键在不在)。
|
|
7983
7985
|
3. **`onDroppedFrame` 载荷新带 `sentence?`**:自渲运维面的端删手抄判词表;宿主自构造的载荷可缺席 ⇒ 读方 `info.sentence ?? droppedWhySentence(info.why)`。`committedUuid` 兼容位 = 段内末条,首行取 `committedUuids[0]`(38z #5)。
|
|
7984
7986
|
|
|
7985
|
-
**包侧缺口:** ① CC-04 技能帽退役随 core 7.19.0 / server 7.78.1 进 0.
|
|
7987
|
+
**包侧缺口:** ① CC-04 技能帽退役随 core 7.19.0 / server 7.78.1 进 0.70.0(38a S-4;§39);② 其余同 §37 包侧缺口。
|
|
7988
|
+
|
|
7989
|
+
## §39 🆕 0.70.0 提货批(server 7.78.1 + core 7.19.0:CC-04 技能帽退役改预算式 / 通告码 +3 / CC-15 形 (a) 透传 `committedUuids: []`)
|
|
7990
|
+
|
|
7991
|
+
### 39a. 本节速览
|
|
7992
|
+
|
|
7993
|
+
| 件 | 一句话 | 端要做什么 |
|
|
7994
|
+
|---|---|---|
|
|
7995
|
+
| S-1 🔴 **型面 BREAKING(唯一)** | **CC-04 `SKILL_CAPS` 只剩 `content`**:`items` / `name` / `description` 三键退役。server 7.78.1 `validateUserSkills` 直读 dist 已无条数帽、无长度帽(7.78.0 及以前仍有);core 7.19.0 `<skills>` 清单按字节预算自己裁描述 / 退 name-only 并发 `skills.listing_truncated`。`skillCommandsToSpecs` / `cloudSkillsToSpecs` 不再在第 10 条断开(此前静默丢弃零留痕);`toCappedSpec` 不再预截 name / description | 读 `SKILL_CAPS.items/.name/.description` 的端**删**(cli `skillsWireOverflow` 与本版同窗退役);别在端里复刻一个条数帽或长度帽 —— 那是在一道已不存在的门下面静默切字节 |
|
|
7996
|
+
| S-2 | **`readSkillsListingTruncated(notice)`**:清单裁切的唯一留痕读口(五必填 / 三可选 / 派生 `laneClamped?`) | 运维面 / 折叠行读它渲「N 条只列名、M 条没上清单、是车道 clamp 还是部署比例」;不自己数「发了几条上了几条」,不对 `message` 做等值匹配 |
|
|
7997
|
+
| S-3 | `ENGINE_NOTICE_CODES` +3 = 五十九码(`classifier.role_defaulted` / `classifier.contract_broken` / `skills.listing_truncated`,operator);devDep core `~7.19.0` | 开集透传照旧;渲运维面的端按受众表分流 |
|
|
7998
|
+
| S-4 | **CC-15** `thinking_segment_end` 形 (a) 透传 `committedUuids: []`(在场但空 = 本包判定本段零已提交行);形 (f) 零经手仍整键缺席;`committedUuid` 兼容位不变 | 读法改口:`Array.isArray(committedUuids)` 在场即以它为准(`[]` = 零行,不再数窗口里过境的行);整键缺席才是「包说不出」 |
|
|
7999
|
+
| S-5 | `skillListingBudgetFraction` / `skillListingMaxDescChars` 两旋钮 | **本包零动作**:它们是 server `task-settings`(部署面)键,不在 `TaskRequest` 装配矩阵上;端不透传 |
|
|
8000
|
+
|
|
8001
|
+
### 39z. 逐键处置表(0.70.0)
|
|
8002
|
+
|
|
8003
|
+
| # | 键 / 面 | 处置 | 坐标 / 理由 |
|
|
8004
|
+
|---|---|---|---|
|
|
8005
|
+
| 1 | `SKILL_CAPS.items` / `.name` / `.description` | **retired(型面 BREAKING)** | `src/skillsWireCaps.ts` 的 `#SKILL_CAPS`;两处 `>= items` 断开删(`src/cloudConfigWireCaps.ts` 的 `#cloudSkillsToSpecs` 同律);门 engine-vocab G2-a / pure C-B1 + 「零条数帽」「name/description 不预截」两格 |
|
|
8006
|
+
| 2 | `SKILL_CAPS.content` | **consumed(不变)** | 引擎加载门 1MB,超出整拒;G2-a 对实装 core `SKILL_CONTENT_MAX_CHARS` 等值 |
|
|
8007
|
+
| 3 | `skills.listing_truncated` 通告 detail 八格 | **consumed(事实读器)** | `src/engineNoticeCodes.ts` 的 `#readSkillsListingTruncated`;门 engine-notice-catalog G1–G7(25 格) |
|
|
8008
|
+
| 4 | `ENGINE_NOTICE_CODES` +3 | **consumed** | `src/engineNoticeCodes.ts`;码册门 A 双向等值(实装 core 7.19.0) |
|
|
8009
|
+
| 5 | `skillListingBudgetFraction` / `skillListingMaxDescChars` | **n/a(server task-settings 部署面键,非 TaskRequest)** | server 7.78.1 `dist/task-settings.d.ts`;端零透传 |
|
|
8010
|
+
| 6 | `agents[].skills` 轴 | **不动(C-R43 ①)** | `projectAgentsForWire` 零删键;server 只退了 `MAX_AGENT_SKILLS` 条数帽 |
|
|
8011
|
+
| 7 | 形 (a) `committedUuids: []` | **consumed(CC-15)** | `src/adapt/textStream.ts` 的 `#replaceThinkingSegment` 形 (a);`src/adapt/arms.ts` 臂对空数组照铸键;门 TSA Ta6 / Tf3 / X2c / X5b / Te9 |
|
|
8012
|
+
| 8 | `RECOMMENDED_SENSITIVE_*` / `AUTO_MODE_PARSE_FAILURES` / `ReadRootGrantCandidate`(core 7.19.0) | **n/a / 候 sdk** | 本包零消费;`readRootCandidate` 候 sdk 出键随下一提货批([7326]) |
|
|
8013
|
+
|
|
8014
|
+
### 39y. 🔴 三端升级必读(固定段式,[C295];本批**三条**)
|
|
8015
|
+
|
|
8016
|
+
1. 🔴 **技能条数帽 / 长度帽在端里一律删**:`SKILL_CAPS` 只剩 `content`;凡自己复刻「≤10 条」「name ≤64」「description ≤1024」或以 `SKILL_CAPS.items` 算「溢出了几条」的端(cli `skillsWireOverflow`)与本版同窗退役 —— server 7.78.1 全受理,引擎清单自己裁并通告。
|
|
8017
|
+
2. **清单裁切只从 `skills.listing_truncated` 读**:`readSkillsListingTruncated(notice)` 给八格事实 + `laneClamped?`;运维面据此分「调 `skillListingBudgetFraction` 有用(部署比例)」与「调了也没用(车道 clamp)」;别自己数条数。
|
|
8018
|
+
3. **CC-15 读法改口**:`thinking_segment_end.committedUuids` 在场即以它为准(`[]` = 本段零已提交行),整键缺席才是「包说不出」;为形 (a) 自建的过境行计数臂删。
|
|
8019
|
+
|
|
8020
|
+
**到期复核(0.70.0 发后当拍记)**:① core 7.20.0 预告([7334] ③a)删 `skills.listing_truncated.detail.requestedBudgetBytes`(8 KiB 天花板退役后请求预算即实际预算)⇒ `readSkillsListingTruncated` 该键可选、`laneClamped` 只在它在场时派生,到货零改即缺席;随 7.20.0 提货批把 `laneClamped` 派生位整只删。② §37y ③ 「交互车道 `adapt()` 不经去重不受影响」是包视角的车道假设:cli 交互车道实际也经 `runStream`(durable-seq 去重在那里),server 7.77.0 的 `reasoning_end` id 复用在交互车道**同样**把权威段当重放丢(test [7335] B-125 实证);包侧去重律不变、零改,根因修在 server 7.78.1(唯一 id)。**已知边界改口**:凡经 `runStream` 的车道(cli 两车道皆是)在 server <7.78.1 上都收不到 `reasoning_end`。
|
|
8021
|
+
|
|
8022
|
+
**包侧缺口:** ① `readRootCandidate` 候 sdk 出键;② CC-08 三段(`tool_progress` / `tool_disclosure` / `wiring_manifest`)顺延 0.71;③ `laneClamped` 派生位随 core 7.20.0 删;④ 其余同 §38 包侧缺口。
|
|
8023
|
+
|
|
8024
|
+
## §40 🆕 0.70.1 安全修复(CC-17:`handOffOnly` 形同步两本补差账 + 清未提交尾段)
|
|
8025
|
+
|
|
8026
|
+
### 40a. 本节速览
|
|
8027
|
+
|
|
8028
|
+
| 件 | 一句话 | 端要做什么 |
|
|
8029
|
+
|---|---|---|
|
|
8030
|
+
| S-1 🔴 **安全面** | **`handOffOnly` 形不再漏账**:段跨包侧边界(工具卡 / 消息划界)∧ 已提交前缀自身过期时,旧码只发三键信号、两本补差账一行不动 ⇒ 形一 卡后**原始未脱敏**尾段照常上屏落盘;形二 `result` 臂第④臂把它当「屏上缺的后缀」补吐一遍。修后账同步 + 清未交尾段,仍一个字节不新交 | **零动作**(端义务不变:按三键把那一行换成 `content`)。为这两形自建的壳侧补偿可退役;「归属证明不了就不动手」的闸留着当反钉 |
|
|
8031
|
+
| S-2 | **收窄:账对不上就不动**(`livePrefix` 跨多条消息 ⇒ 宿主自己也换不了)| 多行跨界那一形**照旧**是既有行为(原始行在场);它的正解是整段归属交全(`committedUuids[]`,排下一版),端在那之前对多行段保持「整发放弃」是对的 |
|
|
8032
|
+
|
|
8033
|
+
### 40z. 逐键处置表(0.70.1)
|
|
8034
|
+
|
|
8035
|
+
| # | 键 / 面 | 处置 | 坐标 / 理由 |
|
|
8036
|
+
|---|---|---|---|
|
|
8037
|
+
| 1 | `handOffOnly` 分支的两本补差账(`committedText` / `previousCommittedText`) | **consumed(修复)** | `src/adapt/textStream.ts` 的 `#replaceAnswerSegment`;`endsWith` 守卫按前缀落在哪本换哪本 |
|
|
8038
|
+
| 2 | 本段未提交尾段(`answerSegment` + 其 `textPending` 那截) | **consumed(修复)** | 账同步成功才清;`carry`(上一段的)原样留 |
|
|
8039
|
+
| 3 | 多行跨界形(`livePrefix` 跨多条消息) | **declined(退回既有行为)** | 清了会把补差基线搞回退 ⇒ `result` 从第⑤臂掉进第④臂补吐;正解是 `committedUuids[]`(下一版) |
|
|
8040
|
+
| 4 | 三键信号(`diverged` / `committedPrefixLen` / `committedPrefixDiverged`) | **不变** | 本批只改「包自己以为屏上有什么」,信号面逐字未动 |
|
|
8041
|
+
|
|
8042
|
+
### 40y. 🔴 三端升级必读(固定段式,[C295];本批**两条**)
|
|
8043
|
+
|
|
8044
|
+
1. 🔴 **端义务不变**,但包不再交那截未脱敏尾段:为这两形自建的壳侧补偿(记住原始尾段再比对、或整发放弃后手工清)**可退役**;通用的「归属证明不了就不动手」闸留着。
|
|
8045
|
+
2. **多行跨界段仍按老规矩**:一个 `segmentId` 对上多行时端照旧整发放弃(包这一版不单方面清);整段归属交全在下一版(`text_segment_end.committedUuids[]`)。
|
|
8046
|
+
|
|
8047
|
+
**包侧缺口:** ① 多行跨界形候 `committedUuids[]`(下一版);② 其余同 §39 包侧缺口。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/client-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.70.1",
|
|
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. 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": "~7.
|
|
38
|
+
"@sema-agent/core": "~7.19.0",
|
|
39
39
|
"@sema-agent/sdk": "^9.4.0",
|
|
40
40
|
"@sema-agent/settings-schema": "^2.0.0",
|
|
41
41
|
"esbuild": "^0.27.4",
|