@sema-agent/client-core 0.67.2 → 0.68.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 +310 -0
- package/README.md +65 -1
- package/dist/adapt/arms.js +67 -9
- package/dist/adapt/textStream.d.ts +102 -1
- package/dist/adapt/textStream.js +169 -6
- package/dist/adapt/turnFlags.d.ts +14 -0
- package/dist/adapt/turnFlags.js +4 -1
- package/dist/adapt.js +4 -1
- package/dist/adapter/activeRunSelfHeal.d.ts +53 -6
- package/dist/adapter/activeRunSelfHeal.js +79 -8
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +18 -1
- package/dist/adapter/downstream/eventToSdkMessage.js +50 -9
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +29 -0
- package/dist/adapter/downstream/terminalToSdkResult.js +46 -15
- package/dist/adapter/runStream.d.ts +22 -2
- package/dist/adapter/runStream.js +139 -38
- package/dist/adapter/types.d.ts +4 -1
- package/dist/autoModeUnavailable.d.ts +17 -9
- package/dist/autoModeUnavailable.js +26 -8
- package/dist/classifierStatus.d.ts +32 -4
- package/dist/classifierStatus.js +5 -3
- package/dist/controlRouter.d.ts +16 -0
- package/dist/controlRouter.js +6 -0
- package/dist/engineErrorCodes.d.ts +52 -0
- package/dist/engineErrorCodes.js +117 -0
- package/dist/engineNoticeCodes.d.ts +95 -1
- package/dist/engineNoticeCodes.js +124 -1
- package/dist/gateVocabulary.d.ts +18 -7
- package/dist/gateVocabulary.js +21 -8
- package/dist/hitl/parkResolver.d.ts +0 -14
- package/dist/hitl/parkResolver.js +22 -9
- package/dist/hitl/toolApprovalWire.d.ts +2 -1
- package/dist/hitl/toolApprovalWire.js +1 -0
- package/dist/ownKey.d.ts +34 -0
- package/dist/ownKey.js +36 -0
- package/dist/request/taskRequest.d.ts +6 -6
- package/dist/request/taskRequest.js +45 -0
- package/dist/retryStatus.d.ts +13 -2
- package/dist/retryStatus.js +4 -1
- package/dist/runTerminal.d.ts +87 -14
- package/dist/runTerminal.js +89 -15
- package/dist/seam.d.ts +78 -8
- package/dist/seam.js +16 -2
- package/dist/toolResult.js +8 -0
- package/dist/toolRoster.d.ts +34 -2
- package/dist/toolRoster.js +16 -2
- package/dist/workflowClient.d.ts +22 -0
- package/dist/workflowClient.js +37 -0
- package/docs/INTEGRATION-CLIENTS.md +633 -9
- package/package.json +2 -2
package/dist/ownKey.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/ownKey.ts — 「拿 **wire 给的串**当对象键」时的**唯一落键姿势**(0.68.0 / L-246 B2 单源化)。
|
|
3
|
+
*
|
|
4
|
+
* ── 病形(0.67.1 在 `terminalToSdkResult.ts` 上定谳,同批在 `hitl/parkResolver.ts` 上又长了一份)──
|
|
5
|
+
* `Object.prototype.__proto__` 是一个 **accessor**:在一只普通对象上写 `o["__proto__"] = v` 走的是
|
|
6
|
+
* 那只 setter ——
|
|
7
|
+
* · **不产生自有属性** ⇒ 那一行在 `Object.keys` / `JSON.stringify` 里**整条消失**,连行数都少一;
|
|
8
|
+
* · `v` 是对象时还**顺手改了 `o` 的原型**。
|
|
9
|
+
* 而这几张表的键全都来自 wire(taskId / modelId / core 开集的 costBreakdown 键名 / 一条问题正文),
|
|
10
|
+
* 没有任何一条保证它们不等于这个字面。⇒ 落键一律走 `defineProperty`。
|
|
11
|
+
*
|
|
12
|
+
* ── 为什么要单源(本文件存在的理由)────────────────────────────────────────────────────────
|
|
13
|
+
* 修前同一条处置有**两份实现**(`terminalToSdkResult.ts` 的 `putOwn` 与 `parkResolver.ts` 里那只
|
|
14
|
+
* 内联 `put`),而且两份都带着各自的一段说明。两份同形实现的代价不是重复几行,是**下一次只修一处**:
|
|
15
|
+
* 这条落键姿势将来若要再收紧(例如连 `constructor` 一类也要拦),漏掉的那一份会静默地把老病留住。
|
|
16
|
+
* 本仓「同形存量」纪律的直接落点。
|
|
17
|
+
*
|
|
18
|
+
* 🔴 **不改成 null 原型对象交付**:端拿到的仍是一只正常对象(`hasOwnProperty` / `toString` 都在),
|
|
19
|
+
* 本模块只管「落键」这一步,不改交付形 —— 换原型会在宿主侧造出一类新的 `TypeError`。
|
|
20
|
+
* 描述符与普通赋值**逐位相同**(`writable` / `enumerable` / `configurable` 三真),所以除了
|
|
21
|
+
* `__proto__` 这一个字面,其余每一个键的行为一个字节都没变。
|
|
22
|
+
*
|
|
23
|
+
* 🔴 **零 import**(纯叶):它进 runStream 内核闭包与 index 闭包两条传递闭包,自己一条 import 都没有
|
|
24
|
+
* ⇒ 不可能把任何东西拖进去(portability 门真正守的三件 —— 零 Node 内建 / 零 react·ink /
|
|
25
|
+
* 外部包等值集 —— 一件都不动)。
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* 把 `value` 落在 `table[key]` 上,**保证产生一个自有属性**(`key` 可以是任何 wire 串,含 `__proto__`)。
|
|
29
|
+
*
|
|
30
|
+
* @param table 目标表(交付形不变:仍是一只普通对象)
|
|
31
|
+
* @param key 来自 wire 的键串
|
|
32
|
+
* @param value 要落的值
|
|
33
|
+
*/
|
|
34
|
+
export function putOwnKey(table, key, value) {
|
|
35
|
+
Object.defineProperty(table, key, { value, enumerable: true, writable: true, configurable: true });
|
|
36
|
+
}
|
|
@@ -90,6 +90,12 @@ export interface TaskRequestInput {
|
|
|
90
90
|
interactiveTools?: false;
|
|
91
91
|
/** 一次性提交声明(`true|undefined` 型:opt-out=不传,绝不发 false——wire 上与缺席同义,发小的那个)。 */
|
|
92
92
|
oneShot?: true;
|
|
93
|
+
/**
|
|
94
|
+
* 「本会话永远不进长期记忆」的**声明形**([7226] ⑤;server §12.4)。
|
|
95
|
+
* 🔴 型面就写成 `'off'`:上游是**单成员闭集**(没有 `"on"`),给它一个宽串型等于邀请调用方发
|
|
96
|
+
* 一个 400 回来。JS 调用方(本包是发出去的 npm 公开面)绕过型面时由构造器再判一次值。
|
|
97
|
+
*/
|
|
98
|
+
memoryCapture?: 'off';
|
|
93
99
|
/** rewind 三件(E18);端自己判空。 */
|
|
94
100
|
rewind?: Record<string, unknown>;
|
|
95
101
|
/** 仓库坐标串(scan/code-review 场景;今日唯一供给方 web 的 Repository 输入=url/`owner/name` 串。
|
|
@@ -112,12 +118,6 @@ export interface TaskRequestInput {
|
|
|
112
118
|
outputStyle?: string;
|
|
113
119
|
};
|
|
114
120
|
}
|
|
115
|
-
/**
|
|
116
|
-
* 合一后的请求构造器 —— **按车道出两形**,字段集差异全部由 `REQUEST_FIELD_MATRIX` 决定。
|
|
117
|
-
*
|
|
118
|
-
* 🔴 行为纪律:本函数**不做任何统一**。print 没有 `ultracode` 就是没有(表里 `gap:true` 记着账),
|
|
119
|
-
* 补齐要另立项 —— 在这里顺手加一行,就是把「合一」偷换成「行为改动」。
|
|
120
|
-
*/
|
|
121
121
|
export declare function buildTaskRequest(input: TaskRequestInput, lane: RequestLane): TaskRequestLike;
|
|
122
122
|
/** `applyLiveRequestDefaults` 的宿主输入(端解析好的值,同样零取值方式)。 */
|
|
123
123
|
export interface LiveDefaultsInput {
|
|
@@ -42,6 +42,15 @@ export const REQUEST_FIELD_MATRIX = [
|
|
|
42
42
|
{ field: 'debate', lanes: ['interactive', 'print'], live: true, why: 'council 的 debate 变体开关(server 读 `=== true`)' },
|
|
43
43
|
{ field: 'rounds', lanes: ['interactive', 'print'], live: true, why: 'debate 轮数(server clamp [1,3],非有限数被 server 归 undefined——本层原样透传不预 clamp)' },
|
|
44
44
|
{ field: 'lenses', lanes: ['interactive', 'print'], live: true, why: 'code-review 镜头集(passthrough 同 repo;形状由 server 场景定义,本层不闭集)' },
|
|
45
|
+
// ── memoryCapture([7226] 包侧缺口 ⑤,0.68.1)──────────────────────────────────────────────
|
|
46
|
+
// 🔴 **单成员闭集**:server 契约 §12.4 逐字「`memoryCapture?: "off"`。单成员闭集(**没有**
|
|
47
|
+
// `"on"`)」—— 所以本层只在值**恰是** `'off'` 时 stamp;`'on'` / 坏拼写一律不上 wire
|
|
48
|
+
// (坏拼写 server 判 400 `request.field_invalid`,本层不预铸第二判官,但也不替它买路)。
|
|
49
|
+
// 🔴 与**中途翻转 verb** `POST /v1/runs/:id/memory/capture-optout`(§12.5,能力位
|
|
50
|
+
// `runMemoryCaptureOptOut`)是**同一条一次性单向记录的两个口**,不是两个轴:verb 管这一条
|
|
51
|
+
// 在飞的 run,本键管「本会话的下一次新提交」。非 live 的 verb(parked / 终态 / 他副本)回
|
|
52
|
+
// 409 `steering.not_running` 并**指路本键** —— 端没有本键就接不住那条指路。
|
|
53
|
+
{ field: 'memoryCapture', lanes: ['interactive', 'print'], live: true, why: '本会话永远不进长期记忆的**声明形**(server §12.4 body 键,单成员闭集 "off");两条车道都是提交面 ⇒ 都能声明。与 memoryWrite:false 不是一个轴(那是「本 run 只读平面」)。⚠️ parked 续跑腿结构性拿不到声明(决策/续跑端点从持久 body 重建 spec),那是引擎侧事实,不是本层的漏' },
|
|
45
54
|
// ── print 独有(§8-5 认定的**有理由**的差异)──────────────────────────────────────────────
|
|
46
55
|
{ field: 'finalVerification', lanes: ['print'], live: true, why: 'P1-1 终验:无人值守车道才需要引擎自证;交互 REPL 由人当场看结果。#106 裁 B(让位+告知)后交互面默认关' },
|
|
47
56
|
{ field: 'limits', lanes: ['print'], live: true, why: 'P2-3-b:`-p` 的预算护栏(--max-* flag 族),交互 REPL 由人随时 Esc' },
|
|
@@ -390,8 +399,40 @@ const resolvedSnapshotForWire = (resolved) => {
|
|
|
390
399
|
* 🔴 行为纪律:本函数**不做任何统一**。print 没有 `ultracode` 就是没有(表里 `gap:true` 记着账),
|
|
391
400
|
* 补齐要另立项 —— 在这里顺手加一行,就是把「合一」偷换成「行为改动」。
|
|
392
401
|
*/
|
|
402
|
+
/**
|
|
403
|
+
* ⑤ 的**响亮拒**([7226] 包侧缺口 ⑤;异源对抗复审轮五 finding① 采纳)。
|
|
404
|
+
*
|
|
405
|
+
* 🔴 修前这里是「不是 `'off'` 就整键不 stamp」——**静默删键**,而删掉的恰是一条**隐私声明**:
|
|
406
|
+
* 一个把 `/memory-capture off` 打成 `OFF` 的会话,请求照发、引擎照常采集,**没有任何人会知道**。
|
|
407
|
+
* 🔴 上游把这条写死了(装机 core `dist/core/memory.d.ts` 的 `capture?: "off"` 头注**逐字**):
|
|
408
|
+
* 「Any other value — `"on"`, `"OFF"`, booleans, garbage — is REFUSED loudly
|
|
409
|
+
* (`config.memory_capture_spelling`), never read as either state (**a privacy request must not be
|
|
410
|
+
* dropped by a typo**, and capture must not be switched off by one either)」;server 契约 §12.4
|
|
411
|
+
* 同样写明坏拼写 400 `request.field_invalid`,并点名「把一条隐私请求按打字错误静默丢掉恰是**禁的方向**」。
|
|
412
|
+
* ⇒ 提前删键 = 把上游那道响亮门**绕过去**,方向正好反了。
|
|
413
|
+
* 🔴 与本文件 `resolvedSnapshotForWire` 对畸形权限快照的处置**同一条纪律**(那里也是抛,理由逐字
|
|
414
|
+
* 是「降空 = 让请求带着被剥掉的权限面发出去」)——两处都是**声明方向**的位:丢了没人看得见。
|
|
415
|
+
* ⚠️ `undefined` / `null` = **合法缺席**(端没有这个入口 / 没有声明),照旧不 stamp,不拒。
|
|
416
|
+
* ⚠️ **不分车道、不受 live 门**:拒绝不是「stamp 一个键」,不改请求形状;而一条打错字的隐私声明
|
|
417
|
+
* 在哪条车道上都不该被默默放行。
|
|
418
|
+
* (本包是发出去的 npm 公开面:JS 调用方与版本偏斜的宿主都到得了这里,型面拦不住。)
|
|
419
|
+
*/
|
|
420
|
+
const refuseBadMemoryCapture = (v) => {
|
|
421
|
+
if (v === undefined || v === null)
|
|
422
|
+
return;
|
|
423
|
+
if (v === 'off')
|
|
424
|
+
return;
|
|
425
|
+
throw new TypeError('buildTaskRequest: memoryCapture 只接受字面量 `\'off\'` 或缺席(undefined/null)—— ' +
|
|
426
|
+
`收到 ${shapeTag(v)}。这一位是**会话级隐私声明**(「本会话永远不进长期记忆」),` +
|
|
427
|
+
'上游是**单成员闭集**(没有 `"on"`)且对坏拼写**响亮拒**(core `config.memory_capture_spelling` / ' +
|
|
428
|
+
'server 400 `request.field_invalid`)。本层若把坏值静默删键,请求会照发、引擎会照常采集,' +
|
|
429
|
+
'而声明人不会知道自己的 opt-out 丢了 —— 把一条隐私请求按打字错误静默丢掉是**禁的方向**。' +
|
|
430
|
+
'错误文本只报形状,不回显值。');
|
|
431
|
+
};
|
|
393
432
|
export function buildTaskRequest(input, lane) {
|
|
394
433
|
const live = input.live;
|
|
434
|
+
// ⑤ 响亮拒排在最前面:一条打错字的隐私声明绝不许被后面任何一条「不 stamp」路径吞掉。
|
|
435
|
+
refuseBadMemoryCapture(input.memoryCapture);
|
|
395
436
|
/** stamp 门:字段在本车道的表里 ∧(非 live-gated ∨ 本次是 live 车道)∧ 值非空。 */
|
|
396
437
|
const on = (field, value) => {
|
|
397
438
|
if (value === undefined || value === null)
|
|
@@ -469,6 +510,10 @@ export function buildTaskRequest(input, lane) {
|
|
|
469
510
|
? { interactiveTools: false }
|
|
470
511
|
: {}),
|
|
471
512
|
...(on('oneShot', input.oneShot) && input.oneShot === true ? { oneShot: true } : {}),
|
|
513
|
+
// ⑤ 单成员闭集:值**恰是** `'off'` 才 stamp。表外拼写在上面已经**响亮拒**(见 `refuseBadMemoryCapture`)。
|
|
514
|
+
...(on('memoryCapture', input.memoryCapture) && input.memoryCapture === 'off'
|
|
515
|
+
? { memoryCapture: 'off' }
|
|
516
|
+
: {}),
|
|
472
517
|
...(Object.keys(settingsOut).length > 0 ? { settings: settingsOut } : {}),
|
|
473
518
|
};
|
|
474
519
|
return out;
|
package/dist/retryStatus.d.ts
CHANGED
|
@@ -48,6 +48,16 @@ export type RetryStatus =
|
|
|
48
48
|
elapsedMs?: number;
|
|
49
49
|
/** 见 {@link BrainStatusPayload.timeoutMs}(引擎给了才在场;缺席禁渲成 0)。 */
|
|
50
50
|
timeoutMs?: number;
|
|
51
|
+
/**
|
|
52
|
+
* 🔴 0.68.0(L-246)—— 引擎给的**中性人话提示**(`BrainStatus.detail`;server 已脱敏 + 限 300 字)。
|
|
53
|
+
*
|
|
54
|
+
* 修前这一位只在两条 `error` 臂上被读(`circuit_open` / `gave_up` 各拿它当 `error.formatted`),
|
|
55
|
+
* `stalled` 臂**整只丢掉**它 —— 于是「为什么还在等」这句唯一由引擎产出的解释,恰恰在**最长的
|
|
56
|
+
* 那一段等待**上看不见,端只好自己按 `errClass` 拼一句泛泛的话(而那正是措辞该由产生者单铸的
|
|
57
|
+
* 反例)。⇒ 原样透传,**一个字不改写、不截断**(显示封顶归端,它才知道自己的行宽)。
|
|
58
|
+
* 🔴 缺席 ⇒ 键不铸(空串同理):一格空白的解释比没有解释更坏。
|
|
59
|
+
*/
|
|
60
|
+
detail?: string;
|
|
51
61
|
} | {
|
|
52
62
|
kind: 'error';
|
|
53
63
|
deadline: number;
|
|
@@ -163,7 +173,8 @@ export type BrainStatusPhase = (typeof BRAIN_STATUS_PHASES)[number];
|
|
|
163
173
|
* core `BrainRetryErrClass`(5.43.0)的**类型面镜像** —— 一次重试等待的**原因分桶**,
|
|
164
174
|
* provider 中立(绝不是 HTTP 状态码 / syscall code / provider 分类法;那些不许过这条通道):
|
|
165
175
|
* · `connect_refused` 目标本身给了确定否定(该地址没人 accept / 名字无地址)—— 短梯队服务的那一类;
|
|
166
|
-
* · `transport` 其余传输层失败(connect 超时 / reset / 流中断
|
|
176
|
+
* · `transport` 其余传输层失败(connect 超时 / reset / 流中断)—— 全梯队;
|
|
177
|
+
* · `stall` 连上了、也没断,但**不出字节**(流停滞)—— 与 `transport` 分家的理由见下;
|
|
167
178
|
* · `rate_limit` provider 要求放慢;
|
|
168
179
|
* · `server` provider 自报自己这边出错;
|
|
169
180
|
* · `http` 状态谓词判终态、但 provider 自己的显式重试裁定说重试;
|
|
@@ -174,7 +185,7 @@ export type BrainStatusPhase = (typeof BRAIN_STATUS_PHASES)[number];
|
|
|
174
185
|
* 分支的,少一相会落 default 臂被渲成错话,所以那张表才需要运行期镜像 + engine-vocab 等值门。
|
|
175
186
|
* 判据锚在「真正决定结果的量」上:决定结果的是有没有分支,不是有没有一张表。
|
|
176
187
|
*/
|
|
177
|
-
export type BrainRetryErrClass = 'connect_refused' | 'transport' | 'rate_limit' | 'server' | 'http' | 'output_cap';
|
|
188
|
+
export type BrainRetryErrClass = 'connect_refused' | 'transport' | 'stall' | 'rate_limit' | 'server' | 'http' | 'output_cap';
|
|
178
189
|
/** wire 上 `status` 臂的载荷(= core `BrainStatus`;server 两腿白名单原样转发这 **11** 键(7.3.0 起含 `elapsedMs`/`timeoutMs`)——
|
|
179
190
|
* 真源 = server 7.58.0 `dist/trace/project.js` 的 `brainStatusEventData`,逐条条件拷贝)。 */
|
|
180
191
|
export interface BrainStatusPayload {
|
package/dist/retryStatus.js
CHANGED
|
@@ -128,13 +128,16 @@ export function mapBrainStatusToRetry(p, nowMs) {
|
|
|
128
128
|
...(elapsedMs !== undefined ? { elapsedMs } : {}),
|
|
129
129
|
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
130
130
|
};
|
|
131
|
+
// 🔴 0.68.0(L-246):引擎那句中性提示。**只进 `stalled` 臂** —— 两条 error 臂上它已经是
|
|
132
|
+
// `error.formatted` 的来源,同一句话在同一只读数上出现两次会让端不知道该渲哪一份。
|
|
133
|
+
const stalledDetail = typeof p.detail === 'string' && p.detail.length > 0 ? { detail: p.detail } : {};
|
|
131
134
|
const extra = { ...counts, ...cause, ...producerTiming, ...failureStatus, ...waitProgress };
|
|
132
135
|
switch (p.phase) {
|
|
133
136
|
// 🔴 引擎直报「恢复」:摘行。绝不落 error 臂 —— 那是把成功渲成失败。
|
|
134
137
|
case 'recovered':
|
|
135
138
|
return null;
|
|
136
139
|
case 'reconnecting':
|
|
137
|
-
return { kind: 'stalled', deadline, ...extra };
|
|
140
|
+
return { kind: 'stalled', deadline, ...extra, ...stalledDetail };
|
|
138
141
|
case 'rate_limited':
|
|
139
142
|
return { kind: 'error', deadline, ...extra, error: { formatted: '', rateLimits: {} } };
|
|
140
143
|
case 'circuit_open':
|
package/dist/runTerminal.d.ts
CHANGED
|
@@ -193,25 +193,93 @@ export declare function runTerminalCode(read: RunTerminalRead | null): string |
|
|
|
193
193
|
*/
|
|
194
194
|
export declare function isReviewPark(read: RunTerminalRead | null): boolean;
|
|
195
195
|
/**
|
|
196
|
-
*
|
|
197
|
-
*
|
|
196
|
+
* ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
197
|
+
* 0.68.0 🔴 BREAKING —— 终态词**两表分源**(L-247;core [7067] @cli 行顺答)
|
|
198
|
+
* ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
199
|
+
* 修前本模块只有一张 `TERMINAL_STATUSES = ['completed','failed','killed','blocked']`,把**两个不同
|
|
200
|
+
* 属主**的词表合成了一张:
|
|
201
|
+
* · `completed` / `failed` / `blocked` 属 **core 的终局因由闭集**(`TerminalCause["kind"]`,
|
|
202
|
+
* `terminal-cause.ts`;core 那边第四员是 `paused`);
|
|
203
|
+
* · `killed` 属 **server 的 run 行状态面**(core 的因由集里**根本没有这个词** —— core [7067] 逐字:
|
|
204
|
+
* 「`killed` 不是 core 词 —— 壳手抄四词里的 `killed` 来自 server run status 面」)。
|
|
205
|
+
* 合成一张的后果是两边加员时都读不出该改哪儿:core 加第五个因由(闭集加员会在 wire 清单的
|
|
206
|
+
* `closedSetMembers` 上具名)与 server 加一个行状态词,在一张表上长得一模一样,于是消费方要么
|
|
207
|
+
* 把新词折进已知词(不安全侧,B-079① 同形),要么两边都漏。
|
|
208
|
+
*
|
|
209
|
+
* ⇒ 两张表**按属主分开**,各自带自己的对账物:
|
|
210
|
+
* · {@link TERMINAL_CAUSE_KINDS} —— core 闭集的镜像,门对**实装 devDep core** 双向对账;
|
|
211
|
+
* · {@link RUN_TERMINAL_STATUSES} —— server run 行状态面的终态词,门对 sdk 真字节钉 + 反向钉
|
|
212
|
+
* 「`killed` 不在 core 因由集里」。
|
|
213
|
+
*
|
|
214
|
+
* 🔴 **为什么是镜像而不是 `export … from '@sema-agent/core'`**(与 `engineNoticeCodes.ts` /
|
|
215
|
+
* `autoModeUnavailable.ts` / `toolResult.ts` 三处逐字同一条理由,再加两条本表独有的):
|
|
216
|
+
* ① `@sema-agent/core` 既不是本包的 peer 也不是 runtime dep —— 本包的 `.d.ts` 一旦引用它,
|
|
217
|
+
* 装了本包却没装 core 的下游当场编译不过;`portability` 门的 `EXPECTED_PACKAGES_INDEX` 是
|
|
218
|
+
* **等值门**(闭包外部包恒等于 `{diff, @sema-agent/sdk}`)且 ③ 段拿 esbuild
|
|
219
|
+
* `--platform=browser` 真打一次包,一条值级边会把整台引擎焊进 web/desktop 的产物;
|
|
220
|
+
* ② core **没有导出**任何名为「终局因由闭集」的元组:它只导出 `TERMINAL_CAUSE_IS_REPLAYABLE`
|
|
221
|
+
* (一张 `Record<kind, boolean>` 的处置表)与谓词 `isTerminalCauseKind`,而且这两件**都不在
|
|
222
|
+
* core 的 barrel 上**(`dist/index.d.ts` 只 re-export 了**类型** `TerminalCause`)⇒
|
|
223
|
+
* 「直接 re-export 那个闭集」在今天的上游字节上不存在可 re-export 的符号。
|
|
224
|
+
* ⇒ 镜像 + 机器对账(本仓对「不自抄」的既定机制):这张表是一份**抄件**不是意见,
|
|
225
|
+
* `scripts/run-terminal-word-source-test.mjs` 拿 core 那张处置表的**键集**逐词双向钉,
|
|
226
|
+
* core 一动这里就先红。
|
|
227
|
+
*/
|
|
228
|
+
/**
|
|
229
|
+
* **core 终局因由**的 kind 闭集(core `TerminalCause["kind"]` 逐词镜像;顺序同源 =
|
|
230
|
+
* `dist/core/terminal-cause.js` 的 `TERMINAL_CAUSE_IS_REPLAYABLE` 键序)。
|
|
231
|
+
*
|
|
232
|
+
* 四员各答「这条 run 为什么结束」:
|
|
233
|
+
* · `completed` —— 跑完了(用户干净 halt 也算,见 `TaskResult.haltedByUser`);
|
|
234
|
+
* · `failed` —— 限额 / provider 失败 / abort / 产出不合法……;
|
|
235
|
+
* · `blocked` —— **agent 自报**走不下去(`report_blocked`)。上游逐字:它是 TERMINAL 的,
|
|
236
|
+
* 「the leg is over and it waits for nobody」;
|
|
237
|
+
* · `paused` —— 一次耐久暂停提交了 checkpoint,**run 可以被恢复**。🔴 它在因由面上是一个
|
|
238
|
+
* 合法的 kind,但它**不是**「run 结束了」——所以它**不在** {@link RUN_TERMINAL_STATUSES} 里。
|
|
239
|
+
* 这正是两张表必须分源的最硬那一格:同一个词在两张面上答的是两个问题。
|
|
240
|
+
*
|
|
241
|
+
* 🔴 **集外词的读法**:core 加第五个因由词时,wire 清单的 `closedSetMembers` 必须列、发车帖必须
|
|
242
|
+
* 具名(core [7067] 逐字规矩)。消费方按闭集读 —— **集外词整键缺席,绝不折成已知词**。
|
|
243
|
+
* 🔴 形制:`Object.freeze` 的**字面元组**(`as const`),不是 `readonly string[]` —— 后者在类型面
|
|
244
|
+
* 交不出成员字面量,端就只能自己再抄一遍四个词(L-247 的病根)。冻结是为了让公面消费者
|
|
245
|
+
* `.push()` 改不动判定源(同 `RESUME_RETRY_LATER_CODES` 的已定谳病形)。
|
|
246
|
+
*/
|
|
247
|
+
export declare const TERMINAL_CAUSE_KINDS: readonly ["completed", "failed", "blocked", "paused"];
|
|
248
|
+
/** {@link TERMINAL_CAUSE_KINDS} 的成员型(端的型面改**派生**,不再手抄词)。 */
|
|
249
|
+
export type TerminalCauseKind = (typeof TERMINAL_CAUSE_KINDS)[number];
|
|
250
|
+
/**
|
|
251
|
+
* 一个词是不是 core 的终局**因由** kind({@link TERMINAL_CAUSE_KINDS} 的成员)。
|
|
252
|
+
*
|
|
253
|
+
* 🔴 **它不答「这条 run 结束了没有」** —— `paused` 是合法成员而 run 还能被恢复。要那一问请读
|
|
254
|
+
* {@link isTerminalStatus}(server 行状态面)或 {@link readRunTerminal} 的因由臂。
|
|
255
|
+
* 🔴 非串 / 空串 / 集外词 ⇒ `false` = 「这不是本端认得的因由词」,**不是**「成功」。
|
|
256
|
+
*/
|
|
257
|
+
export declare function isTerminalCauseKind(kind: unknown): kind is TerminalCauseKind;
|
|
258
|
+
/**
|
|
259
|
+
* **server run 行状态面**的「非成功终局」词(闭集;0.65.0 新铸,L-215② / core [6908];
|
|
260
|
+
* 0.68.0 随 L-247 更名 `TERMINAL_NOT_SUCCESS_STATUSES` → 本名,理由见本段顶注的分源说明)——
|
|
261
|
+
* 「这条 run **不会再自己动了**,而且它没有成功」。
|
|
198
262
|
*
|
|
199
263
|
* 🔴 三员各有出处,且 **`blocked` 与 `suspended`/`needs_review` 的分界是本表存在的全部理由**
|
|
200
264
|
* (core [6908] 定谳):
|
|
201
265
|
* · `failed` —— 引擎自报失败;
|
|
202
|
-
* · `killed` ——
|
|
266
|
+
* · `killed` —— 外力终止。🔴 **这一员是本表与 {@link TERMINAL_CAUSE_KINDS} 的分水岭**:
|
|
267
|
+
* core 的因由闭集里没有它,它是 server run 行状态面自己的词(sdk `FleetTaskStatus` /
|
|
268
|
+
* `SessionNotifyStatus` 上都在,`RunStatus` 上今天还没有 —— 见 §33 的登记);
|
|
203
269
|
* · `blocked` —— **agent 自报的终态**:它自己判定这条 run 走不下去了(core `terminal.blocked`
|
|
204
270
|
* 的 `reason` 是它的说明)。🔴 它**不是「等人」** —— 这正是修前被漏掉的那一格;
|
|
205
271
|
* · 🔴 **`suspended` / `needs_review` 刻意不在表里**:那两个词是**等一次人的决定**,run 还活着、
|
|
206
272
|
* 决定给了就继续跑。把它们读成「非成功终局」会把一条**正等着你**的 run 在面板上判死,
|
|
207
273
|
* 而用户从此不知道有一张卡在等他 —— 与本表要修的方向相反的同一类错。
|
|
208
274
|
*
|
|
209
|
-
* 🔴 形制:`Object.freeze`
|
|
210
|
-
*
|
|
275
|
+
* 🔴 形制:`Object.freeze` 的**字面元组**,不是 `ReadonlySet`(同 `RESUME_RETRY_LATER_CODES` 的
|
|
276
|
+
* 已定谳病形:`ReadonlySet` 只在类型面只读,而判定查的就是公面上这同一个实例)。
|
|
211
277
|
*/
|
|
212
|
-
export declare const
|
|
278
|
+
export declare const RUN_TERMINAL_NOT_SUCCESS_STATUSES: readonly ["failed", "killed", "blocked"];
|
|
279
|
+
/** {@link RUN_TERMINAL_NOT_SUCCESS_STATUSES} 的成员型(端的型面改派生,不再手抄三词)。 */
|
|
280
|
+
export type RunTerminalNotSuccessStatus = (typeof RUN_TERMINAL_NOT_SUCCESS_STATUSES)[number];
|
|
213
281
|
/**
|
|
214
|
-
* 一个状态词是不是**非成功终局**({@link
|
|
282
|
+
* 一个状态词是不是**非成功终局**({@link RUN_TERMINAL_NOT_SUCCESS_STATUSES} 的成员)。
|
|
215
283
|
*
|
|
216
284
|
* **单铸谓词**(L-215②):本包的通知链(面板 settle 的 `isError` 位)与三端各自的后台白名单
|
|
217
285
|
* 读的必须是**同一个判据** —— 修前包里是一处内联的 `status === 'failed' || status === 'killed'`,
|
|
@@ -224,19 +292,24 @@ export declare const TERMINAL_NOT_SUCCESS_STATUSES: readonly string[];
|
|
|
224
292
|
* 已定谳的事故形。
|
|
225
293
|
* 🔴 非串 / 空串 ⇒ `false`(同上:是「答不出」,不是「成功」)。
|
|
226
294
|
*/
|
|
227
|
-
export declare function isTerminalNotSuccess(status: unknown):
|
|
295
|
+
export declare function isTerminalNotSuccess(status: unknown): status is RunTerminalNotSuccessStatus;
|
|
228
296
|
/**
|
|
229
|
-
*
|
|
230
|
-
* 的三员。答的是「这条 run
|
|
231
|
-
*
|
|
297
|
+
* **server run 行状态面**的终局状态词(闭集;0.65.0 新铸,0.68.0 随 L-247 更名 `TERMINAL_STATUSES`
|
|
298
|
+
* → 本名)—— 成功那一员加上 {@link RUN_TERMINAL_NOT_SUCCESS_STATUSES} 的三员。答的是「这条 run
|
|
299
|
+
* 还会不会自己动」,与上一张表答的「它成没成功」是**两个问题**,所以两张表分开、后者由前者派生
|
|
300
|
+
* (加员只有一处要改)。
|
|
232
301
|
*
|
|
233
302
|
* 🔴 同样**不含** `suspended` / `needs_review`:那两个词是「等一次人的决定」——run 没有结束。
|
|
303
|
+
* 🔴 也**不含** core 因由面的 `paused`:那是另一张表的词,而且它在语义上恰好与本表相反
|
|
304
|
+
* ({@link TERMINAL_CAUSE_KINDS} 顶注)。
|
|
234
305
|
*/
|
|
235
|
-
export declare const
|
|
306
|
+
export declare const RUN_TERMINAL_STATUSES: readonly ["completed", "failed", "killed", "blocked"];
|
|
307
|
+
/** {@link RUN_TERMINAL_STATUSES} 的成员型(端的型面改派生,不再手抄四词 —— L-247 的修形)。 */
|
|
308
|
+
export type RunTerminalStatus = (typeof RUN_TERMINAL_STATUSES)[number];
|
|
236
309
|
/**
|
|
237
|
-
* 一个状态词是不是**终局**({@link
|
|
310
|
+
* 一个状态词是不是**终局**({@link RUN_TERMINAL_STATUSES} 的成员)。
|
|
238
311
|
*
|
|
239
312
|
* 用在「这条通知/这条行是不是可以收摊了」这一问上(通知去重的 seed 扫描、后台行 settle 门)。
|
|
240
313
|
* 🔴 表外词 ⇒ `false` = 「本端认不出这是个终局」,**不是**「它还在跑」;要判「在跑」请读正向证据。
|
|
241
314
|
*/
|
|
242
|
-
export declare function isTerminalStatus(status: unknown):
|
|
315
|
+
export declare function isTerminalStatus(status: unknown): status is RunTerminalStatus;
|
package/dist/runTerminal.js
CHANGED
|
@@ -188,29 +188,100 @@ export function isReviewPark(read) {
|
|
|
188
188
|
return read !== null && read.kind === 'paused' && read.flatStatus === FLAT_REVIEW_STATUS;
|
|
189
189
|
}
|
|
190
190
|
/**
|
|
191
|
-
*
|
|
192
|
-
*
|
|
191
|
+
* ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
192
|
+
* 0.68.0 🔴 BREAKING —— 终态词**两表分源**(L-247;core [7067] @cli 行顺答)
|
|
193
|
+
* ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
194
|
+
* 修前本模块只有一张 `TERMINAL_STATUSES = ['completed','failed','killed','blocked']`,把**两个不同
|
|
195
|
+
* 属主**的词表合成了一张:
|
|
196
|
+
* · `completed` / `failed` / `blocked` 属 **core 的终局因由闭集**(`TerminalCause["kind"]`,
|
|
197
|
+
* `terminal-cause.ts`;core 那边第四员是 `paused`);
|
|
198
|
+
* · `killed` 属 **server 的 run 行状态面**(core 的因由集里**根本没有这个词** —— core [7067] 逐字:
|
|
199
|
+
* 「`killed` 不是 core 词 —— 壳手抄四词里的 `killed` 来自 server run status 面」)。
|
|
200
|
+
* 合成一张的后果是两边加员时都读不出该改哪儿:core 加第五个因由(闭集加员会在 wire 清单的
|
|
201
|
+
* `closedSetMembers` 上具名)与 server 加一个行状态词,在一张表上长得一模一样,于是消费方要么
|
|
202
|
+
* 把新词折进已知词(不安全侧,B-079① 同形),要么两边都漏。
|
|
203
|
+
*
|
|
204
|
+
* ⇒ 两张表**按属主分开**,各自带自己的对账物:
|
|
205
|
+
* · {@link TERMINAL_CAUSE_KINDS} —— core 闭集的镜像,门对**实装 devDep core** 双向对账;
|
|
206
|
+
* · {@link RUN_TERMINAL_STATUSES} —— server run 行状态面的终态词,门对 sdk 真字节钉 + 反向钉
|
|
207
|
+
* 「`killed` 不在 core 因由集里」。
|
|
208
|
+
*
|
|
209
|
+
* 🔴 **为什么是镜像而不是 `export … from '@sema-agent/core'`**(与 `engineNoticeCodes.ts` /
|
|
210
|
+
* `autoModeUnavailable.ts` / `toolResult.ts` 三处逐字同一条理由,再加两条本表独有的):
|
|
211
|
+
* ① `@sema-agent/core` 既不是本包的 peer 也不是 runtime dep —— 本包的 `.d.ts` 一旦引用它,
|
|
212
|
+
* 装了本包却没装 core 的下游当场编译不过;`portability` 门的 `EXPECTED_PACKAGES_INDEX` 是
|
|
213
|
+
* **等值门**(闭包外部包恒等于 `{diff, @sema-agent/sdk}`)且 ③ 段拿 esbuild
|
|
214
|
+
* `--platform=browser` 真打一次包,一条值级边会把整台引擎焊进 web/desktop 的产物;
|
|
215
|
+
* ② core **没有导出**任何名为「终局因由闭集」的元组:它只导出 `TERMINAL_CAUSE_IS_REPLAYABLE`
|
|
216
|
+
* (一张 `Record<kind, boolean>` 的处置表)与谓词 `isTerminalCauseKind`,而且这两件**都不在
|
|
217
|
+
* core 的 barrel 上**(`dist/index.d.ts` 只 re-export 了**类型** `TerminalCause`)⇒
|
|
218
|
+
* 「直接 re-export 那个闭集」在今天的上游字节上不存在可 re-export 的符号。
|
|
219
|
+
* ⇒ 镜像 + 机器对账(本仓对「不自抄」的既定机制):这张表是一份**抄件**不是意见,
|
|
220
|
+
* `scripts/run-terminal-word-source-test.mjs` 拿 core 那张处置表的**键集**逐词双向钉,
|
|
221
|
+
* core 一动这里就先红。
|
|
222
|
+
*/
|
|
223
|
+
/**
|
|
224
|
+
* **core 终局因由**的 kind 闭集(core `TerminalCause["kind"]` 逐词镜像;顺序同源 =
|
|
225
|
+
* `dist/core/terminal-cause.js` 的 `TERMINAL_CAUSE_IS_REPLAYABLE` 键序)。
|
|
226
|
+
*
|
|
227
|
+
* 四员各答「这条 run 为什么结束」:
|
|
228
|
+
* · `completed` —— 跑完了(用户干净 halt 也算,见 `TaskResult.haltedByUser`);
|
|
229
|
+
* · `failed` —— 限额 / provider 失败 / abort / 产出不合法……;
|
|
230
|
+
* · `blocked` —— **agent 自报**走不下去(`report_blocked`)。上游逐字:它是 TERMINAL 的,
|
|
231
|
+
* 「the leg is over and it waits for nobody」;
|
|
232
|
+
* · `paused` —— 一次耐久暂停提交了 checkpoint,**run 可以被恢复**。🔴 它在因由面上是一个
|
|
233
|
+
* 合法的 kind,但它**不是**「run 结束了」——所以它**不在** {@link RUN_TERMINAL_STATUSES} 里。
|
|
234
|
+
* 这正是两张表必须分源的最硬那一格:同一个词在两张面上答的是两个问题。
|
|
235
|
+
*
|
|
236
|
+
* 🔴 **集外词的读法**:core 加第五个因由词时,wire 清单的 `closedSetMembers` 必须列、发车帖必须
|
|
237
|
+
* 具名(core [7067] 逐字规矩)。消费方按闭集读 —— **集外词整键缺席,绝不折成已知词**。
|
|
238
|
+
* 🔴 形制:`Object.freeze` 的**字面元组**(`as const`),不是 `readonly string[]` —— 后者在类型面
|
|
239
|
+
* 交不出成员字面量,端就只能自己再抄一遍四个词(L-247 的病根)。冻结是为了让公面消费者
|
|
240
|
+
* `.push()` 改不动判定源(同 `RESUME_RETRY_LATER_CODES` 的已定谳病形)。
|
|
241
|
+
*/
|
|
242
|
+
export const TERMINAL_CAUSE_KINDS = Object.freeze([
|
|
243
|
+
'completed',
|
|
244
|
+
'failed',
|
|
245
|
+
'blocked',
|
|
246
|
+
'paused',
|
|
247
|
+
]);
|
|
248
|
+
/**
|
|
249
|
+
* 一个词是不是 core 的终局**因由** kind({@link TERMINAL_CAUSE_KINDS} 的成员)。
|
|
250
|
+
*
|
|
251
|
+
* 🔴 **它不答「这条 run 结束了没有」** —— `paused` 是合法成员而 run 还能被恢复。要那一问请读
|
|
252
|
+
* {@link isTerminalStatus}(server 行状态面)或 {@link readRunTerminal} 的因由臂。
|
|
253
|
+
* 🔴 非串 / 空串 / 集外词 ⇒ `false` = 「这不是本端认得的因由词」,**不是**「成功」。
|
|
254
|
+
*/
|
|
255
|
+
export function isTerminalCauseKind(kind) {
|
|
256
|
+
return typeof kind === 'string' && TERMINAL_CAUSE_KINDS.includes(kind);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* **server run 行状态面**的「非成功终局」词(闭集;0.65.0 新铸,L-215② / core [6908];
|
|
260
|
+
* 0.68.0 随 L-247 更名 `TERMINAL_NOT_SUCCESS_STATUSES` → 本名,理由见本段顶注的分源说明)——
|
|
261
|
+
* 「这条 run **不会再自己动了**,而且它没有成功」。
|
|
193
262
|
*
|
|
194
263
|
* 🔴 三员各有出处,且 **`blocked` 与 `suspended`/`needs_review` 的分界是本表存在的全部理由**
|
|
195
264
|
* (core [6908] 定谳):
|
|
196
265
|
* · `failed` —— 引擎自报失败;
|
|
197
|
-
* · `killed` ——
|
|
266
|
+
* · `killed` —— 外力终止。🔴 **这一员是本表与 {@link TERMINAL_CAUSE_KINDS} 的分水岭**:
|
|
267
|
+
* core 的因由闭集里没有它,它是 server run 行状态面自己的词(sdk `FleetTaskStatus` /
|
|
268
|
+
* `SessionNotifyStatus` 上都在,`RunStatus` 上今天还没有 —— 见 §33 的登记);
|
|
198
269
|
* · `blocked` —— **agent 自报的终态**:它自己判定这条 run 走不下去了(core `terminal.blocked`
|
|
199
270
|
* 的 `reason` 是它的说明)。🔴 它**不是「等人」** —— 这正是修前被漏掉的那一格;
|
|
200
271
|
* · 🔴 **`suspended` / `needs_review` 刻意不在表里**:那两个词是**等一次人的决定**,run 还活着、
|
|
201
272
|
* 决定给了就继续跑。把它们读成「非成功终局」会把一条**正等着你**的 run 在面板上判死,
|
|
202
273
|
* 而用户从此不知道有一张卡在等他 —— 与本表要修的方向相反的同一类错。
|
|
203
274
|
*
|
|
204
|
-
* 🔴 形制:`Object.freeze`
|
|
205
|
-
*
|
|
275
|
+
* 🔴 形制:`Object.freeze` 的**字面元组**,不是 `ReadonlySet`(同 `RESUME_RETRY_LATER_CODES` 的
|
|
276
|
+
* 已定谳病形:`ReadonlySet` 只在类型面只读,而判定查的就是公面上这同一个实例)。
|
|
206
277
|
*/
|
|
207
|
-
export const
|
|
278
|
+
export const RUN_TERMINAL_NOT_SUCCESS_STATUSES = Object.freeze([
|
|
208
279
|
'failed',
|
|
209
280
|
'killed',
|
|
210
281
|
'blocked',
|
|
211
282
|
]);
|
|
212
283
|
/**
|
|
213
|
-
* 一个状态词是不是**非成功终局**({@link
|
|
284
|
+
* 一个状态词是不是**非成功终局**({@link RUN_TERMINAL_NOT_SUCCESS_STATUSES} 的成员)。
|
|
214
285
|
*
|
|
215
286
|
* **单铸谓词**(L-215②):本包的通知链(面板 settle 的 `isError` 位)与三端各自的后台白名单
|
|
216
287
|
* 读的必须是**同一个判据** —— 修前包里是一处内联的 `status === 'failed' || status === 'killed'`,
|
|
@@ -224,25 +295,28 @@ export const TERMINAL_NOT_SUCCESS_STATUSES = Object.freeze([
|
|
|
224
295
|
* 🔴 非串 / 空串 ⇒ `false`(同上:是「答不出」,不是「成功」)。
|
|
225
296
|
*/
|
|
226
297
|
export function isTerminalNotSuccess(status) {
|
|
227
|
-
return typeof status === 'string' &&
|
|
298
|
+
return typeof status === 'string' && RUN_TERMINAL_NOT_SUCCESS_STATUSES.includes(status);
|
|
228
299
|
}
|
|
229
300
|
/**
|
|
230
|
-
*
|
|
231
|
-
* 的三员。答的是「这条 run
|
|
232
|
-
*
|
|
301
|
+
* **server run 行状态面**的终局状态词(闭集;0.65.0 新铸,0.68.0 随 L-247 更名 `TERMINAL_STATUSES`
|
|
302
|
+
* → 本名)—— 成功那一员加上 {@link RUN_TERMINAL_NOT_SUCCESS_STATUSES} 的三员。答的是「这条 run
|
|
303
|
+
* 还会不会自己动」,与上一张表答的「它成没成功」是**两个问题**,所以两张表分开、后者由前者派生
|
|
304
|
+
* (加员只有一处要改)。
|
|
233
305
|
*
|
|
234
306
|
* 🔴 同样**不含** `suspended` / `needs_review`:那两个词是「等一次人的决定」——run 没有结束。
|
|
307
|
+
* 🔴 也**不含** core 因由面的 `paused`:那是另一张表的词,而且它在语义上恰好与本表相反
|
|
308
|
+
* ({@link TERMINAL_CAUSE_KINDS} 顶注)。
|
|
235
309
|
*/
|
|
236
|
-
export const
|
|
310
|
+
export const RUN_TERMINAL_STATUSES = Object.freeze([
|
|
237
311
|
'completed',
|
|
238
|
-
...
|
|
312
|
+
...RUN_TERMINAL_NOT_SUCCESS_STATUSES,
|
|
239
313
|
]);
|
|
240
314
|
/**
|
|
241
|
-
* 一个状态词是不是**终局**({@link
|
|
315
|
+
* 一个状态词是不是**终局**({@link RUN_TERMINAL_STATUSES} 的成员)。
|
|
242
316
|
*
|
|
243
317
|
* 用在「这条通知/这条行是不是可以收摊了」这一问上(通知去重的 seed 扫描、后台行 settle 门)。
|
|
244
318
|
* 🔴 表外词 ⇒ `false` = 「本端认不出这是个终局」,**不是**「它还在跑」;要判「在跑」请读正向证据。
|
|
245
319
|
*/
|
|
246
320
|
export function isTerminalStatus(status) {
|
|
247
|
-
return typeof status === 'string' &&
|
|
321
|
+
return typeof status === 'string' && RUN_TERMINAL_STATUSES.includes(status);
|
|
248
322
|
}
|
package/dist/seam.d.ts
CHANGED
|
@@ -600,11 +600,53 @@ export interface WiringManifestChromeEvent {
|
|
|
600
600
|
* text content block。CC 对位:CC 在 provider 的 `content_block_stop` 上把每个写完的块当作一条
|
|
601
601
|
* 独立 assistant 消息 —— 块结束**就是**分段信号,本臂把同一个边界搬到了 wire 上。
|
|
602
602
|
*
|
|
603
|
-
* 🔴 **宿主消费义务**(
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
607
|
-
*
|
|
603
|
+
* 🔴 **宿主消费义务**(② ③ ④ 可选、fail-soft;① 自 0.68.1 起是**安全面义务**,不实现 = 未脱敏
|
|
604
|
+
* 字节留在那个宿主的本地转录里):
|
|
605
|
+
* ① 🔴 **它是信号 + 权威内容**(0.68.1 改口;server ≥7.75.3)。`content` = 那一段的**权威全文**,
|
|
606
|
+
* 并且与活体增量的拼接**可以不相等** —— server 7.75.3 起它与 `result`/账本走**同一只脱敏器**,
|
|
607
|
+
* 而 `text_delta` 仍逐字(跨 chunk 的凭据无法就地判)。修前这里写的是「与增量拼接逐字节相等…
|
|
608
|
+
* 别拿它再渲一行」,那句话在 7.75.3 起**不再成立**;按它不渲 = 屏上与转录里留的是**未脱敏**
|
|
609
|
+
* 的那一份。
|
|
610
|
+
* · **`diverged` 在场**(never false,缺席 = 逐字节相同)⇒ 你按增量拼出来的那一段是**过期**的:
|
|
611
|
+
* 必须用 `content` **重渲该段**,并以它为该段的 committed 文本,**不许保留增量拼文**。
|
|
612
|
+
* · 🔴 **`committedPrefixDiverged` 在场**(never false)⇒ 这一段此前已经 committed 上屏的那一截
|
|
613
|
+
* **自己**就是过期的(凭据落在它里面),而它**撤不回**(那条 transcript 消息早已交给你)。
|
|
614
|
+
* 这一形下本包**一个字节都不再交**给 transcript 平面 —— 该段唯一算数的那一份就是本帧的
|
|
615
|
+
* `content`:宿主必须把 `committedPrefixLen` 指的那一截(见下)换成 `content`。
|
|
616
|
+
* 🔴 **不实现这一条 = 这一段在你的转录里只剩未脱敏的那半截**(而且缺了后半段)。
|
|
617
|
+
* 它**缺席**时(含压根没有已提交前缀)本包交的是**尾段** —— 前缀 + 尾段拼起来逐字节 =
|
|
618
|
+
* `content`,宿主**什么都不用丢**,照常把新到的 transcript 消息接在后面。
|
|
619
|
+
* · **`committedPrefixLen` 在场**(never 0)= 这一段已经 committed 上屏的**长度**,是上一条的
|
|
620
|
+
* **定位量**,照抄这一行就对:
|
|
621
|
+
* `已committed正文.slice(0, 已committed正文.length - committedPrefixLen) + content`。
|
|
622
|
+
* 🔴 **单位 = JS 字符串长度(UTF-16 代码单元),不是 UTF-8 字节** —— 按 UTF-8 字节去截会在
|
|
623
|
+
* 任何非 ASCII 正文上截错位置(实测 `sk-…` + `中文`×30 + 换行:UTF-16 长度 82 / UTF-8 字节 202,
|
|
624
|
+
* 按 202 截会把凭据**原样留在屏上**还附带乱码)。
|
|
625
|
+
* 🔴 **也不是「几条消息」** —— 本包在 idle-flush 那一形下会把「上一段的定稿 + 这一段的
|
|
626
|
+
* 半截」合并进**同一条** assistant 消息(分段行为零改动的代价),按**消息**去丢会把已经
|
|
627
|
+
* 定稿的上一段一起删掉,而本包不会再补发它。
|
|
628
|
+
* 🔴 它按**增量拼文**计长,**不是** `content` 上的偏移量 —— 前缀自己也可能被脱敏改过字节,
|
|
629
|
+
* 拿它去切 `content` 在 `committedPrefixDiverged` 那一形上会切出半截乱码。
|
|
630
|
+
* ⚠️ 🔴 **一条总不变量 + 一条如实留白**:
|
|
631
|
+
* **不变量** —— 本包只在「整段都在自己手里(**同一条** committed 消息内)」时改自己交的字节;
|
|
632
|
+
* 段一旦跨过包侧边界(工具卡 / 消息划界),就**只发这三个键、不动任何既有行为**:转录逐条、
|
|
633
|
+
* 终帧补差走向都与 0.68.0 **逐字相同**(常驻门按「补差臂走向」这个真正决定结果的量对照)。
|
|
634
|
+
* **留白** —— 因此跨消息那几形里,`committedPrefixLen` 指的那一截可能落在别条消息里、甚至
|
|
635
|
+
* 中间**夹着一张工具卡**,而终帧补差的基线也不会跟着换(它本来就不跟,与本批无关)。
|
|
636
|
+
* 两者的根因是同一个:**包按自己的边界切 committed 消息,引擎按 content block 切段**。
|
|
637
|
+
* 根治 = 「每个引擎段各自一条 committed 消息」(= CC 在 `content_block_stop` 上的原生做法),
|
|
638
|
+
* 那是**分段行为改动**、与撤 idle-flush 启发式同一件事,按宪法三问单独走;本批不做,
|
|
639
|
+
* 把边界如实写在这里而不是假装没有。
|
|
640
|
+
* · 三键**都缺席**(= 最常见的那一形)⇒ 一切照旧:`content` 只是**定界**信号,这些字节已经
|
|
641
|
+
* 以 `stream_delta` 流过、并由 transcript 平面给出 committed 形,**拿它再渲一行 = 同一段
|
|
642
|
+
* 文字上屏两遍**。
|
|
643
|
+
* ⚠️ 分工:`diverged` 那一条只有**自己拼 delta 上屏**的宿主要做(只渲 transcript 平面的宿主
|
|
644
|
+
* 自动正确 —— 本包已经把权威全文换进段缓冲);而 `committedPrefixDiverged` 那一条
|
|
645
|
+
* **所有宿主都要做**(包在那一形上交不出东西,只有你能修)。
|
|
646
|
+
* ⚠️ 🔴 **迟到的段边界**(引擎在工具执行之后才报这一段的边界 —— openai 车道的实测时序)同样
|
|
647
|
+
* 会带着这三个键到达:那一段的正文可能已经落在**上一条** assistant 消息里,`committedPrefixLen`
|
|
648
|
+
* 指的就是那一条。宿主按同一条规矩处置(丢掉 + 用 `content` 重渲),不要因为「这一段看起来
|
|
649
|
+
* 已经结束很久了」就跳过。
|
|
608
650
|
* ② **诚实缺席,不可反推**(core 臂注逐字):只有会报块结束的 Brain 才发它 —— 三个一方 brain 都发,
|
|
609
651
|
* 自定义 brain 可能整条流一帧都没有。⇒ 缺席 = 「**没报**」,**永远不等于**「这一段没结束」。
|
|
610
652
|
* 消费方按**每条流**判「这条流带不带边界帧」,只在整条流一帧都没有时才回落自己的启发式;
|
|
@@ -618,14 +660,42 @@ export interface WiringManifestChromeEvent {
|
|
|
618
660
|
* 要消费子流边界的宿主读 SDKMessage 平面的 `text_end` 内部臂,那一层原样带 `parentToolCallId`。
|
|
619
661
|
*
|
|
620
662
|
* ⚠️ **UNTRUSTED、仅展示**:`content` 是模型输出,契约与活体增量同 —— 渲染,绝不回喂模型。
|
|
621
|
-
* 📋 如实留白:本包的 `takeAnswerSegmentOnIdle`
|
|
622
|
-
* 的状态化策略,属行为面改动,按宪法三问单独走)
|
|
663
|
+
* 📋 如实留白:本包的 `takeAnswerSegmentOnIdle` 启发式**仍未撤**(撤它要按 ② 做一条 per-stream
|
|
664
|
+
* 的状态化策略,属行为面改动,按宪法三问单独走)。0.68.1 的权威段替换是**兼容**它的 ——
|
|
665
|
+
* 「半段已被 idle-flush 提交」那一形由 `committedPrefixLen` / `committedPrefixDiverged` 如实
|
|
666
|
+
* 交代,不是把启发式悄悄换掉了。
|
|
623
667
|
*/
|
|
624
668
|
export interface TextSegmentEndChromeEvent {
|
|
625
669
|
kind: 'text_segment_end';
|
|
626
670
|
laneProof: LaneProof;
|
|
627
|
-
/**
|
|
671
|
+
/**
|
|
672
|
+
* 该段的**权威全文**(server ≥7.75.3 起经脱敏器;**可以**与活体增量的拼接**不相等**)。
|
|
673
|
+
* 🔴 读法全在上面义务 ①:`diverged` 缺席时它只是对账/定界量(别拿它再渲一行);在场时它是
|
|
674
|
+
* 该段唯一算数的那一份。
|
|
675
|
+
*/
|
|
628
676
|
content: string;
|
|
677
|
+
/**
|
|
678
|
+
* **活体面**那份过期了(never false —— 缺席 = 与增量拼接逐字节相同)。
|
|
679
|
+
* 在场 ⇒ 按 {@link TextSegmentEndChromeEvent.content} 重渲该段,别保留增量拼文。
|
|
680
|
+
*/
|
|
681
|
+
diverged?: true;
|
|
682
|
+
/**
|
|
683
|
+
* **转录面**已经 committed 的那一截**自己**也过期了(never false)。
|
|
684
|
+
* 🔴 在场 ⇒ 本包**一个字节都不再交**给转录面(撤不回的那截拼不出 `content`,再补一条就是同一段话
|
|
685
|
+
* 上屏两遍)⇒ 该段唯一算数的那一份就是 {@link TextSegmentEndChromeEvent.content},宿主把
|
|
686
|
+
* {@link TextSegmentEndChromeEvent.committedPrefixLen} 指的那一截换成它;
|
|
687
|
+
* 缺席 ⇒ 本包交的是**尾段**,前缀 + 尾段 = `content`,什么都不用丢。
|
|
688
|
+
*/
|
|
689
|
+
committedPrefixDiverged?: true;
|
|
690
|
+
/**
|
|
691
|
+
* 这一段已经 committed 上屏的**长度**(never 0)——「要换的是哪一段」的定位量:
|
|
692
|
+
* `已committed正文.slice(0, 已committed正文.length - committedPrefixLen) + content`。
|
|
693
|
+
* 🔴 **单位 = JS 字符串长度(UTF-16 代码单元),不是 UTF-8 字节**(按字节截会在非 ASCII 正文上
|
|
694
|
+
* 截错位置,凭据会原样留在屏上);🔴 **也不是「几条消息」**(本包会把上一段的定稿与这一段的
|
|
695
|
+
* 半截合并进同一条消息);
|
|
696
|
+
* 🔴 按**增量拼文**计长,不是 `content` 上的偏移量(见义务 ①)。
|
|
697
|
+
*/
|
|
698
|
+
committedPrefixLen?: number;
|
|
629
699
|
/** core 铸的事件身份(uuidv7 形);wire 未必带 ⇒ 缺席时本键不在场。 */
|
|
630
700
|
eventId?: string;
|
|
631
701
|
}
|
package/dist/seam.js
CHANGED
|
@@ -110,8 +110,22 @@ const CHROME_ARM_TABLE = {
|
|
|
110
110
|
'(撤帧可能整帧丢失)③已 DECIDED 的兄弟不在 askIds 里;真撤到本地卡时给一行归因(reason 消毒后呈现),零命中不要多说那一行',
|
|
111
111
|
},
|
|
112
112
|
text_segment_end: {
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
// 🔴 0.68.1 / L-310:`false` → `true`。改的理由不是「这一面更重要了」,是**后果类目变了**:
|
|
114
|
+
// 本表的 `false` 语义逐字是「不接 = 这条披露看不见,不属『已发生的行为丢失』」,而 server
|
|
115
|
+
// 7.75.3 起不接的后果是**未脱敏字节留在本地转录里**(b2 那一形上,那条明文消息**已经渲过**
|
|
116
|
+
// ⇒ 就是「已发生的行为」)。留 `false` = 把一条安全面义务标成可选,正是本仓点名要治的
|
|
117
|
+
// 「假 affordance / 悄悄的谎」。⚠️ 这一位翻面会让按本表自检覆盖率的端**当场显形**——那正是目的。
|
|
118
|
+
required: true,
|
|
119
|
+
duty: '🔴 引擎明报的 assistant 散文段边界 + **该段权威全文**(#323/core #447;server ≥7.75.3 起 content 经脱敏器、' +
|
|
120
|
+
'text_delta 仍逐字 ⇒ 两者**可以不相等**)。①`diverged` 在场(never false)⇒ 你按增量拼出来的那一段是过期的,' +
|
|
121
|
+
'必须用 content **重渲该段**并以它为该段 committed 文本,不许保留增量拼文;②`committedPrefixDiverged` 在场' +
|
|
122
|
+
'(never false)⇒ 这一段此前已 committed 上屏的正文**也**过期了,🔴 本包在这一形上**一个字节都不再交**' +
|
|
123
|
+
'(撤不回的那截拼不出 content)⇒ 把 committedPrefixLen 指的那一截换成 content,这一条**所有宿主都要做**;' +
|
|
124
|
+
'缺席 ⇒ 本包交的是尾段,前缀+尾段=content,什么都不用丢;③`committedPrefixLen`(never 0)= 定位量,' +
|
|
125
|
+
'🔴 **单位 = JS 字符串长度(UTF-16 代码单元),不是 UTF-8 字节、也不是几条消息**' +
|
|
126
|
+
'(按 UTF-8 字节截会在非 ASCII 正文上截错位置把凭据留在屏上;按消息丢会连合并在同一条消息里的上一段定稿一起删掉),' +
|
|
127
|
+
'照抄 `已committed正文.slice(0, 长度 - committedPrefixLen) + content`;按**增量拼文**计长、不是 content 上的偏移;④三键全缺席 ⇒ 照旧只当对账/定界,拿 content 再渲一行 = 同一段上屏两遍。' +
|
|
128
|
+
'🔴 缺席只表示「没报」,绝不等于「段没结束」——要退回自家启发式必须按整条流判、不按单帧判',
|
|
115
129
|
},
|
|
116
130
|
};
|
|
117
131
|
/**
|