@sema-agent/client-core 0.16.1 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/adapter/downstream/eventToSdkMessage.js +60 -20
- package/dist/adapter/downstream/terminalToSdkResult.js +16 -16
- package/dist/adapter/runStream.js +4 -3
- package/dist/engineErrorCodes.d.ts +119 -0
- package/dist/engineErrorCodes.js +147 -0
- package/dist/finalVerifyWire.d.ts +28 -23
- package/dist/finalVerifyWire.js +27 -11
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -0
- package/dist/interactiveToolsWire.d.ts +10 -0
- package/dist/interactiveToolsWire.js +10 -0
- package/dist/limitsWire.d.ts +28 -11
- package/dist/limitsWire.js +27 -29
- package/dist/subagent/engineTaskHandleWire.d.ts +8 -0
- package/dist/subagent/engineTaskHandleWire.js +10 -13
- package/dist/toolResult.d.ts +86 -0
- package/dist/toolResult.js +91 -3
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Renamed from **`@sema-agent/wire-cc-adapter`** (0.1.x, deprecated — see *Migra
|
|
|
23
23
|
|
|
24
24
|
## Scope
|
|
25
25
|
|
|
26
|
-
**Version:** 0.
|
|
26
|
+
**Version:** 0.17.0
|
|
27
27
|
|
|
28
28
|
- **Today** — the adapter seam, the whole `adapt()` pipeline (all 14 A-layer arms plus the
|
|
29
29
|
B/D/E tool-card layers), the notification/caps/model families, the adapter kernel (stream driver
|
|
@@ -53,7 +53,7 @@ Renamed from **`@sema-agent/wire-cc-adapter`** (0.1.x, deprecated — see *Migra
|
|
|
53
53
|
`SseIdleError`, `probeHealth`, `APIError` and `TaskStopConflictError` are imported as values in
|
|
54
54
|
five modules, and the browser bundle really bundles the SDK through (the portability guard would
|
|
55
55
|
exit 3 rather than quietly mark it external).
|
|
56
|
-
- The declared floor is `>=
|
|
56
|
+
- The declared floor is `>=6.2.0`, and it is *witnessed*: the guard checks that an actually
|
|
57
57
|
installed SDK at that line still exports every value-level symbol this package imports and still
|
|
58
58
|
declares `TaskStats.costMicroUsd` (the key `costOrNull` reads). A floor nobody ever ran is a
|
|
59
59
|
promise, not a contract.
|
|
@@ -220,6 +220,7 @@ public-surface guard checks that last one).
|
|
|
220
220
|
| `scripts/run-print-bash-iserror-test.mjs` | The print lane's Bash `is_error` authority (structured over regex) |
|
|
221
221
|
| `scripts/run-sdk-floor-test.mjs` | The SDK version floor — and, more to the point, that the *installed* type declarations still carry the keys this package reads |
|
|
222
222
|
| `scripts/run-engine-vocab-floor-test.mjs` | Engine-mirrored vocabularies (structured card whitelist, self-reported tool face, control verbs, recogniser sets) against the *installed* `@sema-agent/core` |
|
|
223
|
+
| `scripts/run-limits-env-failloud-test.mjs` | `SEMA_HEADLESS_*` env-lane limits reject invalid values as loudly as the flag lane (no silent "no budget" runs) |
|
|
223
224
|
| `scripts/run-streamjson-timing-honesty-test.mjs` | Stream timing & terminal honesty ([2084]): held errored fs-write results release on model progress; a wall-clock stop maps to `error_during_execution` with a truthful salvage note; the synthetic API-error assistant row carries the `<synthetic>` in-message sentinel. Also ([2489], core 5.8.0): the run-limit `errorCode` -> CC subtype map is pinned code by code (`limits.max_{cost,turns,tokens,walltime}_exceeded`), token/wall-clock stops keep the text the engine already produced, and the `failed` event arm shares the one mapping point. The 5.7 dual-vocabulary legs retired with server 6.0.0 (which bundles core 5.8.0); four **retirement negative controls** stand in their place — the retired `status:'timeout'` and the retired codes must fall to the honest fallback subtype and must never drop back to an empty success, so putting any of them back turns the gate red |
|
|
224
225
|
| `scripts/run-background-view-test.mjs` | `createBackgroundView` lifecycle: polling/notify pairing, per-source degrade (`501 → not-configured` vs `unavailable`), the capabilities `scheduler` probe, and dispose really aborting the in-flight fleet snapshot (pure projection lives in the pure suite's W-A segment) |
|
|
225
226
|
| `scripts/run-fleet-view-keys-test.mjs` | The fleet projection views, **both directions**: `FleetTaskView`/`FleetWorkflowView` ⇄ their key lists (compile-pinned) ⇄ what a maximal/minimal row really projects, plus a wire-key coverage ledger (every `FleetTaskRow` key is either projected or carries a written reason why not) and a drift ledger against the shell's render contract. A one-directional assignability check is blind to optional keys — which is how `startedAt` was silently dropped |
|
|
@@ -63,27 +63,27 @@ function assertNeverArm(_ev) {
|
|
|
63
63
|
* 旧写法 `if (msg)` 在新返回型上恒真(对象永远 truthy),所以这是**必须点名**的一类改动。
|
|
64
64
|
*/
|
|
65
65
|
export function eventToSdkMessage(ev, ctx) {
|
|
66
|
-
// service 1.75 — `workflow_complete`: an out-of-band background-workflow completion push, ridden onto
|
|
67
|
-
// the session's next stream open (BEFORE the run's own events). Projects to a NEUTRAL internal arm;
|
|
68
|
-
// the upstream bridge turns it into CC's `<task-notification>` injection.
|
|
69
|
-
// 🔴 REF-CC-060(xlate-06)真码核对:P1 镜头按注释判「五条 raw 臂里四条已入 union」,逐字核
|
|
70
|
-
// `@sema-agent/sdk` 3.0.0 的 `AgentEvent` 后**部分证伪** —— task_notification / diagnostics /
|
|
71
|
-
// steering_injected / workspace_changed 四条确已入 union(已搬进下方 switch 成为正式 case),
|
|
72
|
-
// 而 `workflow_complete` **至今不在 union 里**(与那几条注释自称的相反)。故本臂是**唯一**
|
|
73
|
-
// 保留的 raw 预分派臂,`raw` 变量也随之收窄到这一条。到期复核:每次 SDK major 提货时重查
|
|
74
|
-
// (判据 = SDK d.ts 里出现 `type: "workflow_complete"`),入 union 当天搬进 switch。
|
|
75
|
-
const raw = ev;
|
|
76
|
-
if (raw.type === 'workflow_complete') {
|
|
77
|
-
if (typeof raw.runId !== 'string')
|
|
78
|
-
return dropped('malformed', 'workflow_complete');
|
|
79
|
-
return projected(stamp(ctx, armBody({
|
|
80
|
-
type: 'workflow_complete',
|
|
81
|
-
runId: raw.runId,
|
|
82
|
-
status: raw.status === 'failed' ? 'failed' : 'completed',
|
|
83
|
-
summary: typeof raw.summary === 'string' ? raw.summary : '',
|
|
84
|
-
})));
|
|
85
|
-
}
|
|
86
66
|
switch (ev.type) {
|
|
67
|
+
// service 1.75 — `workflow_complete`: an out-of-band background-workflow completion push, ridden onto
|
|
68
|
+
// the session's next stream open (BEFORE the run's own events). Projects to a NEUTRAL internal arm;
|
|
69
|
+
// the upstream bridge turns it into CC's `<task-notification>` injection.
|
|
70
|
+
// 🔴 **到期复核已兑现(sdk 6.2.0 提货批,2026-08-04)**:本臂此前是 switch 之前的**唯一** raw
|
|
71
|
+
// 预分派臂,理由写着「`workflow_complete` 至今不在 union 里……入 union 当天搬进 switch」。
|
|
72
|
+
// sdk 6.2.0 的 TR-7 批把它连同 question/elicitation 族一并加进了 `AgentEvent` union
|
|
73
|
+
// (判据 = `dist/events.d.ts` 出现 `type: "workflow_complete"`),故按原定计划搬进来 ——
|
|
74
|
+
// raw 预分派臂与 `raw` 变量一并退役,本函数从此**每一条臂都受 B5 编译期穷举保护**。
|
|
75
|
+
// 语义不变:至少一次投递(两条腿同开可能双发),消费方按 `runId` 去重(notifications 台账干这件事)。
|
|
76
|
+
case 'workflow_complete': {
|
|
77
|
+
if (typeof ev.runId !== 'string' || ev.runId.length === 0) {
|
|
78
|
+
return dropped('malformed', 'workflow_complete');
|
|
79
|
+
}
|
|
80
|
+
return projected(stamp(ctx, armBody({
|
|
81
|
+
type: 'workflow_complete',
|
|
82
|
+
runId: ev.runId,
|
|
83
|
+
status: ev.status === 'failed' ? 'failed' : 'completed',
|
|
84
|
+
summary: typeof ev.summary === 'string' ? ev.summary : '',
|
|
85
|
+
})));
|
|
86
|
+
}
|
|
87
87
|
// CS-1 §2.2 — turn-aggregated answer text (durable). Drop raw block array.
|
|
88
88
|
case 'text':
|
|
89
89
|
return projected(assistantArm(ctx, [{ type: 'text', text: ev.text }]));
|
|
@@ -148,11 +148,23 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
148
148
|
// AgentToolResult.details on the wire; not yet in the SDK tool_end arm — raw defensive read).
|
|
149
149
|
// Rides the neutral arm so the bridge can render the REAL rich card (diff / stdout panels).
|
|
150
150
|
const structured = ev.structured;
|
|
151
|
+
// core 5.10.0 — 被**中断**的 call 的合成 `tool_end` 终于带机器码(`interrupted_never_started` /
|
|
152
|
+
// `interrupted_outcome_unknown`,来自持久化的 `details.errorKind`)。此前这一帧只有
|
|
153
|
+
// `isError:true` 而无正文、无码 ⇒ 从帧渲染工具输出的消费者看到空结果,还只能去正则匹配散文
|
|
154
|
+
// 才知道是哪一种中断。`output`/`label` 本臂本来就透传,缺的是这个**判别位**。
|
|
155
|
+
// 🔴 开集 + 防御读:`tool_end.errorCode` 不在 sdk 6.2.0 的 tool_end 臂类型里(SDK 面尚未跟上
|
|
156
|
+
// core 5.10.0),故按 unknown 读;两员之外的未来码**照样原样透传**,窄化只做「是不是串」,
|
|
157
|
+
// 绝不按识别表过滤(过滤 = 替引擎决定哪些原因配得上被看见)。判别用
|
|
158
|
+
// `engineErrorCodes.isInterruptedToolEndCode`,不要在消费点重新写字面比较。
|
|
159
|
+
const toolEndErrorCode = ev.errorCode;
|
|
151
160
|
return projected(stamp(ctx, armBody({
|
|
152
161
|
type: 'tool_end_result',
|
|
153
162
|
toolCallId: ev.toolCallId,
|
|
154
163
|
toolName: ev.toolName,
|
|
155
164
|
isError: ev.isError,
|
|
165
|
+
...(typeof toolEndErrorCode === 'string' && toolEndErrorCode.length > 0
|
|
166
|
+
? { errorCode: toolEndErrorCode }
|
|
167
|
+
: {}),
|
|
156
168
|
// P0-2([1725] 清单A)— `tool_end.label` 同 tool_start 待遇(server trace/project.js:61 白名单
|
|
157
169
|
// 本体产出)。此臂是壳内部侧信道(不进 transcript),所以这里带着无 provider 风险;
|
|
158
170
|
// tool_start 先到时 bridge 已登记过,这条是补位(只有 tool_end 带 label 的场景)。
|
|
@@ -329,7 +341,35 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
329
341
|
return nothing('usage_only');
|
|
330
342
|
// §2.9 — suspended 的 HITL 登记是 run driver 的活(hitlBridge.observe),本层不投影。
|
|
331
343
|
case 'suspended':
|
|
344
|
+
// ── sdk 6.2.0 TR-7 新入 union 的 HITL 带外族(2026-08-04 提货批)────────────────────────
|
|
345
|
+
// `question` / `question_complete`(AskUserQuestion 的开问/收尾)与 `elicitation` /
|
|
346
|
+
// `elicitation_complete`(入站 MCP server 向用户要输入)是**对话框覆盖层**的词汇,不是
|
|
347
|
+
// transcript 的。它们此前只走 live 腿的 SSE `event:` 名分派(`liveQuestionStore.ts` 的 demux
|
|
348
|
+
// 口),6.2.0 把 durable 腿的重放形也纳入了 union —— 于是它们第一次**流经本函数**。
|
|
349
|
+
// 🔴 处置理由与 `suspended` 同族、也与本包既有分工一致:HITL 的挂起/应答由
|
|
350
|
+
// `hitl/hitlBridge.ts` 的 `observe()` 与 `liveQuestionStore` 负责,本切片(CC transcript
|
|
351
|
+
// 投影)对它们**没有对位渲染物** —— 硬投一个 transcript 形就是替覆盖层编一条假消息。
|
|
352
|
+
// 所以走 `hitl_out_of_slice`(可分辨的三态之一),不是 `dropped`(那是「我看不懂」)。
|
|
353
|
+
// 🔴 记档给下一棒(诚实缺席,不是无事发生):durable 重放腿上,一条被重放的 `question` 今天
|
|
354
|
+
// **不会**再打开覆盖层 —— 覆盖层的入口是 liveQuestionStore 的 live demux 写口,而不是本函数。
|
|
355
|
+
// 这在交互 REPL 上无损(live 腿原路不变),在「断线后按 Last-Event-ID 续读」的场景下是一个
|
|
356
|
+
// 真缺口。补它属**行为面**改动(要先答「重放一条已经过期 5min TTL 的问题该不该弹窗」),
|
|
357
|
+
// 按宪法三问单独走,不在本提货批里顺手加 —— 但缺口写在这里,不留白。
|
|
358
|
+
case 'question':
|
|
359
|
+
case 'question_complete':
|
|
360
|
+
case 'elicitation':
|
|
361
|
+
case 'elicitation_complete':
|
|
332
362
|
return nothing('hitl_out_of_slice');
|
|
363
|
+
// ── sdk 6.2.0 CB-1/TR-6 `error` 臂(2026-08-04 提货批)──────────────────────────────────
|
|
364
|
+
// 🔴 **名字骗人,别当终态**:这是流的 15 分钟帽帧(server `sse-log.ts`),帧自己就说
|
|
365
|
+
// 「run 仍然活着」。终态臂只有 `done` / `failed`。把它渲成终态 = 把一条还在跑的任务判死。
|
|
366
|
+
// 正确处置 = 按 `Last-Event-ID` 重连续读,而那件事 SDK 的 `runs.events` 车道内部就做了
|
|
367
|
+
// (本包侧的坐标 = `headlessReconnectWire.ts` 的 STREAM_MAX_DURATION 段)。
|
|
368
|
+
// ⇒ 本切片无对位渲染物,也**绝不终止**调用方的循环(返回 none,不是 terminal)。
|
|
369
|
+
// 🔴 `errorCode` 开集(已知 `STREAM_MAX_DURATION`):未知码同样按「可重连的流控信号」降级,
|
|
370
|
+
// 不要按成员判死 —— 词表见 `engineErrorCodes.ts`。
|
|
371
|
+
case 'error':
|
|
372
|
+
return nothing('not_in_slice');
|
|
333
373
|
// CS-10 / CS-11 — terminals are projected by terminalToSdkResult.
|
|
334
374
|
case 'done':
|
|
335
375
|
case 'failed':
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { stamp } from '../types.js';
|
|
2
2
|
import { toCcModelUsage } from './turnUsageToModelUsage.js';
|
|
3
|
+
// G1 去字面化(2026-08-04):到限/结构化输出/rewind 三族的码字面收编进单一真源,本文件只 import。
|
|
4
|
+
// 开集纪律不变——下面三个集合仍是**识别表**,`subtypeForErrorCode` 的 default 臂才是开集的兑现处。
|
|
5
|
+
import { LIMITS_MAX_COST_EXCEEDED, LIMITS_MAX_TOKENS_EXCEEDED, LIMITS_MAX_TURNS_EXCEEDED, LIMITS_MAX_WALLTIME_EXCEEDED, OUTPUT_INVALID, isRewindFamilyCode, } from '../../engineErrorCodes.js';
|
|
3
6
|
/**
|
|
4
7
|
* Flatten TaskStats → the CC NonNullableUsage placeholder.
|
|
5
8
|
* 🔴 REF-CC-055(xlate-01):`failedToSdkResult` 此前手抄了一份「五键全零」的字面量,那不是
|
|
@@ -133,22 +136,20 @@ function degradedOf(r) {
|
|
|
133
136
|
// 退役批(server 6.0.0 捆 core 5.8.0 发车,2026-08-04):三个集合里的 5.7 旧码成员
|
|
134
137
|
// (`budget.exceeded`/`budget.precall`/`limit.max_turns`)已删,只留新码。放成集合而不是就地 `||`
|
|
135
138
|
// 链的原因不变:词表变动集中在一处可数,不必满文件找 `===` 比较。
|
|
139
|
+
// G1 去字面化(2026-08-04):**码的字面**已收编进 `engineErrorCodes.ts`(单一真源),这里留的是
|
|
140
|
+
// 「哪些码映射到哪个 CC subtype」的**映射事实** —— 那是本文件的职责,不是词表的。
|
|
136
141
|
/** 成本到限 → CC `error_max_budget_usd`(唯一一个 CC 有专词的预算轴)。 */
|
|
137
|
-
const COST_EXCEEDED_CODES = new Set([
|
|
138
|
-
'limits.max_cost_exceeded',
|
|
139
|
-
]);
|
|
142
|
+
const COST_EXCEEDED_CODES = new Set([LIMITS_MAX_COST_EXCEEDED]);
|
|
140
143
|
/** 轮数到限 → CC `error_max_turns`。 */
|
|
141
|
-
const TURNS_EXCEEDED_CODES = new Set([
|
|
142
|
-
'limits.max_turns_exceeded',
|
|
143
|
-
]);
|
|
144
|
+
const TURNS_EXCEEDED_CODES = new Set([LIMITS_MAX_TURNS_EXCEEDED]);
|
|
144
145
|
/**
|
|
145
146
|
* 「截断」族到限码:CC 4 词表里**没有**对应词(token 账不是美元账、墙钟停不是轮数耗尽),
|
|
146
147
|
* 所以 subtype 落诚实兜底词,真实语义靠 errorCode 透传;且这两种停因都可能已产出正文
|
|
147
148
|
* ([2489] 对 max_tokens 明记 result 带正文;墙钟停是既有的写出窗 salvage 语义)⇒ 共用 salvage 腿。
|
|
148
149
|
*/
|
|
149
150
|
const CUTOFF_EXCEEDED_CODES = new Set([
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
LIMITS_MAX_TOKENS_EXCEEDED,
|
|
152
|
+
LIMITS_MAX_WALLTIME_EXCEEDED,
|
|
152
153
|
]);
|
|
153
154
|
/**
|
|
154
155
|
* 🔴 **errorCode → CC subtype 的唯一映射点**。收编前这段 `||`/三元链在 done{failed} 与
|
|
@@ -165,8 +166,11 @@ function subtypeForErrorCode(code) {
|
|
|
165
166
|
return 'error_max_turns';
|
|
166
167
|
// assemble-result.js:58 该 code 的语义字面就是 CC 这词:「did not produce a valid structured
|
|
167
168
|
// output within the retry limit」。
|
|
168
|
-
if (code ===
|
|
169
|
+
if (code === OUTPUT_INVALID)
|
|
169
170
|
return 'error_max_structured_output_retries';
|
|
171
|
+
// 🔴 开集兑现处:未知/未来码(core 5.10.0 的 `config.*` 拒绝族、`usage.window_exhausted`、
|
|
172
|
+
// `env.lifetime_expired` 都落这里)一律诚实兜底词 —— CC 四词表里没有它们的对位词,真实语义
|
|
173
|
+
// 靠上面 `errorCode` 原样透传辨认。绝不为了「有个更像的词」把它们塞进任何一个已知 subtype。
|
|
170
174
|
return 'error_during_execution';
|
|
171
175
|
}
|
|
172
176
|
/**
|
|
@@ -293,7 +297,7 @@ export function doneToSdkResult(ev, ctx) {
|
|
|
293
297
|
return errorResult(ctx, {
|
|
294
298
|
...errorBase,
|
|
295
299
|
subtype: failedSubtype,
|
|
296
|
-
...cutoffParts(r, rr.errorMessage, rr.errorCode ===
|
|
300
|
+
...cutoffParts(r, rr.errorMessage, rr.errorCode === LIMITS_MAX_TOKENS_EXCEEDED
|
|
297
301
|
? 'run exhausted its token budget'
|
|
298
302
|
: 'run hit its wall-clock limit', rr.errorCode),
|
|
299
303
|
});
|
|
@@ -305,9 +309,7 @@ export function doneToSdkResult(ev, ctx) {
|
|
|
305
309
|
// rewind_snapshot.unresolvable 骑在 done{status:"failed"} 帧的 errorCode 上,非 `failed` 帧)——
|
|
306
310
|
// 与 failedToSdkResult 的同款 append 对齐,message 后附 code 便于对账。
|
|
307
311
|
errors: [
|
|
308
|
-
|
|
309
|
-
(rr.errorCode.startsWith('resume_at.') || rr.errorCode.startsWith('rewind_snapshot.')) &&
|
|
310
|
-
rr.errorMessage
|
|
312
|
+
isRewindFamilyCode(rr.errorCode) && rr.errorMessage
|
|
311
313
|
? `${rr.errorMessage} (${rr.errorCode})`
|
|
312
314
|
: (rr.errorMessage ?? 'run failed'),
|
|
313
315
|
],
|
|
@@ -437,9 +439,7 @@ export function failedToSdkResult(ev, ctx) {
|
|
|
437
439
|
// resume_at.before_root_unsupported / rewind_snapshot.unresolvable)透传给用户 —— 这些是
|
|
438
440
|
// 用户可自解的操作性错误(选错目标/回退过根/快照缺失),code 附在 message 后便于对账。
|
|
439
441
|
errors: [
|
|
440
|
-
|
|
441
|
-
(ev.errorCode.startsWith('resume_at.') || ev.errorCode.startsWith('rewind_snapshot.')) &&
|
|
442
|
-
ev.errorMessage
|
|
442
|
+
isRewindFamilyCode(ev.errorCode) && ev.errorMessage
|
|
443
443
|
? `${ev.errorMessage} (${ev.errorCode})`
|
|
444
444
|
: (ev.errorMessage ?? ev.errorCode ?? 'run failed'),
|
|
445
445
|
],
|
|
@@ -2,13 +2,14 @@ import { eventSeq, } from './types.js';
|
|
|
2
2
|
import { eventToSdkMessage, turnEndUsage } from './downstream/eventToSdkMessage.js';
|
|
3
3
|
import { terminalToSdkResult } from './downstream/terminalToSdkResult.js';
|
|
4
4
|
import { publishSubagentContentEvent } from '../subagentContentStore.js';
|
|
5
|
-
/** 本文件发的 chrome 事件全在 leader lane(子代内容在上面就被 divert 走了)。 */
|
|
6
|
-
const MAIN = { lane: 'main' };
|
|
7
5
|
/**
|
|
8
6
|
* 409 session-busy 拒绝的 **canonical errorCode**([2377]C-1,server main `049ff2c`,随 5.0.0 发)。
|
|
9
7
|
* 引擎把它 stamp 在 `done{status:'failed'}` / `failed` 终帧上,壳据此**结构判读**,不再读人话。
|
|
8
|
+
* G1 去字面化(2026-08-04):字面收编进 `engineErrorCodes.ts` 单一真源,本文件只 import。
|
|
10
9
|
*/
|
|
11
|
-
|
|
10
|
+
import { ACTIVE_RUN_BUSY_ERROR_CODE } from '../engineErrorCodes.js';
|
|
11
|
+
/** 本文件发的 chrome 事件全在 leader lane(子代内容在上面就被 divert 走了)。 */
|
|
12
|
+
const MAIN = { lane: 'main' };
|
|
12
13
|
/**
|
|
13
14
|
* 判别一个**原始 AgentEvent** 是不是 409 active-run 拒收终帧;非 busy ⇒ null。
|
|
14
15
|
* 判据=结构两腿(canonical `errorCode` 优先 → `activeTaskId` 在场);人话文案腿已随 #117 提货
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/engineErrorCodes.ts — **引擎 wire 码词表的单一真源**(G1 去字面化,2026-08-04,
|
|
3
|
+
* core 5.10.0 / sdk 6.2.0 消费半场)。
|
|
4
|
+
*
|
|
5
|
+
* ── 为什么要有这个文件 ────────────────────────────────────────────────────────────────────────
|
|
6
|
+
* 引擎的 `errorCode` 是**机器码**(结构位),壳的四条判别链都吃它:终帧 subtype 映射
|
|
7
|
+
* (`adapter/downstream/terminalToSdkResult.ts`)、409 busy 判别(`adapter/runStream.ts`)、
|
|
8
|
+
* `stop.*` 五形分类(`subagent/engineTaskHandleWire.ts`)、限额面文案(`limitsWire.ts`)。
|
|
9
|
+
* 收编前这些码以**裸字面量**散在五个文件、二十余处:core 每次词表迁移(5.8.0 的 `budget.*` →
|
|
10
|
+
* `limits.*`、5.10.0 的 `config.*` 第四波)都要满仓 grep `===` 比较,漏一处的后果不是报错而是
|
|
11
|
+
* **判别链静默走错臂** —— 这正是 [dep-bump-follow-on-checklist] 那类跟车事故的载体。
|
|
12
|
+
*
|
|
13
|
+
* ── 🔴 开集纪律(本文件最重要的一条)──────────────────────────────────────────────────────────
|
|
14
|
+
* **wire 的 `errorCode` 是开集**:引擎完全可能比本包新一版,发一个这里没有的码。所以:
|
|
15
|
+
* · 本文件的 `ReadonlySet` / 前缀谓词一律是**识别表**(recognition table),回答的是
|
|
16
|
+
* 「我认不认得这个码」,**绝不是**「合法码只有这些」;
|
|
17
|
+
* · 消费点的 `switch` 必须留 `default`、`if` 必须留 else 臂,未知码一律**原样透传**
|
|
18
|
+
* + 落诚实兜底臂,绝不塌进任何一个已知形(塌进去 = 替 server 编了一个它没说的原因);
|
|
19
|
+
* · 唯一的**闭集**是 {@link ModelFallbackReason} —— 它是 core 亲自声明的闭集单成员
|
|
20
|
+
* ([2577] 定谳),加成员 = BREAKING 清单行,所以它写成 string literal union 而不是 `string`。
|
|
21
|
+
* 这条例外**只此一处**,别照抄到别的码上。
|
|
22
|
+
*
|
|
23
|
+
* ── 命名与来源 ────────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
* 每一族下方注出它的 core 版本与出处帖号;码的字面**永远以引擎为准**,本文件只是镜子。
|
|
25
|
+
* 词表变动集中在一处可数(与 `terminalToSdkResult.ts` 那三个集合原本的立意同),提货批 diff 里
|
|
26
|
+
* 一眼能看出「这一版引擎加了哪几个词」。
|
|
27
|
+
*/
|
|
28
|
+
/** token 预算到限。`result` 可能带已产出正文([2489] 明记)。 */
|
|
29
|
+
export declare const LIMITS_MAX_TOKENS_EXCEEDED = "limits.max_tokens_exceeded";
|
|
30
|
+
/** 成本预算到限(唯一一个 CC 有专门 subtype 的预算轴)。 */
|
|
31
|
+
export declare const LIMITS_MAX_COST_EXCEEDED = "limits.max_cost_exceeded";
|
|
32
|
+
/** 轮数预算到限。 */
|
|
33
|
+
export declare const LIMITS_MAX_TURNS_EXCEEDED = "limits.max_turns_exceeded";
|
|
34
|
+
/** 墙钟预算到限(5.8.0 起是**响亮终局** `status:'failed'`;`status:'timeout'` 该终态词整体退役)。 */
|
|
35
|
+
export declare const LIMITS_MAX_WALLTIME_EXCEEDED = "limits.max_walltime_exceeded";
|
|
36
|
+
/** 部署级 token 治理窗耗尽。**唯一携带可执行等待量的停因**,与 `retryAfterMs` 配对到货。
|
|
37
|
+
* 5.10.0 起:治理窗与环境寿命同一轮边界到期时,**窗赢**(此前 env-first 报告把它丢了)。 */
|
|
38
|
+
export declare const USAGE_WINDOW_EXHAUSTED = "usage.window_exhausted";
|
|
39
|
+
/** 环境寿命到期(平台侧)。与上一条同轮到期时**让位**给它。 */
|
|
40
|
+
export declare const ENV_LIFETIME_EXPIRED = "env.lifetime_expired";
|
|
41
|
+
/** `TaskRequest.limits` 各门(runTeamDiscussion 累计额 / workflow 治理 TRUSTED 半 /
|
|
42
|
+
* `resourceSuspend` 四键)拒绝不可求值的值。 */
|
|
43
|
+
export declare const CONFIG_LIMIT_INVALID = "config.limit_invalid";
|
|
44
|
+
/** `StrategyStore.find(scope, query, limit)` 的 limit 非「非负整数或 Infinity」。 */
|
|
45
|
+
export declare const CONFIG_STRATEGY_FIND_LIMIT_INVALID = "config.strategy_find_limit_invalid";
|
|
46
|
+
/** `StrategyStore.prune` / `InMemoryStrategyStore` 构造的容量上限非非负整数(含点名拒 `Infinity`
|
|
47
|
+
* —— 容量帽可以放宽,不可以关掉)。 */
|
|
48
|
+
export declare const CONFIG_STRATEGY_MAX_SIZE_INVALID = "config.strategy_max_size_invalid";
|
|
49
|
+
/** 未知的 limits 键(5.8.0 起:同时发新旧两代键会在这里当场失败,所以写面只发单一新形)。 */
|
|
50
|
+
export declare const CONFIG_LIMIT_UNKNOWN_KEY = "config.limit_unknown_key";
|
|
51
|
+
/**
|
|
52
|
+
* 已知的配置拒绝码(**识别表,非白名单**)。判「这是不是一条配置拒绝」请用
|
|
53
|
+
* {@link isConfigRefusalCode} —— 它按 `config.` 前缀判,未来新成员自动落进来。
|
|
54
|
+
*/
|
|
55
|
+
export declare const CONFIG_REFUSAL_CODES: ReadonlySet<string>;
|
|
56
|
+
/** `config.` 前缀谓词 —— **开集**判别:5.10.0 之后每一波「不许静默折叠」都会往这一族加词,
|
|
57
|
+
* 按前缀判的消费点不必跟车,按成员判的必须跟车。缺席/空串 ⇒ false。 */
|
|
58
|
+
export declare function isConfigRefusalCode(code: string | undefined): boolean;
|
|
59
|
+
/** 该 call 从未真正开始执行(可安全重发)。 */
|
|
60
|
+
export declare const TOOL_END_INTERRUPTED_NEVER_STARTED = "interrupted_never_started";
|
|
61
|
+
/** 该 call 的结局未知(持有它的进程死了 —— 副作用可能已经发生,**不可**当作没跑过)。 */
|
|
62
|
+
export declare const TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN = "interrupted_outcome_unknown";
|
|
63
|
+
/**
|
|
64
|
+
* 中断码识别表(**开集**:`tool_end.errorCode` 整体是开集,未来可能有第三种中断成因)。
|
|
65
|
+
* 🔴 两员**语义不对称**,别合并处置:`never_started` 可以重发,`outcome_unknown` 不可以。
|
|
66
|
+
*/
|
|
67
|
+
export declare const TOOL_END_INTERRUPTED_CODES: ReadonlySet<string>;
|
|
68
|
+
/** 这条 `tool_end` 是不是「中断留下的合成收口帧」。未知码 ⇒ false(开集:不认得就不认得,
|
|
69
|
+
* 绝不猜)。 */
|
|
70
|
+
export declare function isInterruptedToolEndCode(code: string | undefined): boolean;
|
|
71
|
+
/** 409 session-busy 的 canonical 码([2377]C-1,server main `049ff2c`,随 5.0.0 发)。 */
|
|
72
|
+
export declare const ACTIVE_RUN_BUSY_ERROR_CODE = "conflict.session_active_run";
|
|
73
|
+
/** 仲裁店不可达 ⇒ **真相未知**(core 1.397 三分的第三形;塌进 `not_landed` 是诚实缺陷)。 */
|
|
74
|
+
export declare const STOP_PARK_ARBITER_UNREACHABLE = "stop.park_arbiter_unreachable";
|
|
75
|
+
/** park 的 resume 赢了这场竞争。 */
|
|
76
|
+
export declare const STOP_PARK_RESUME_WON = "stop.park_resume_won";
|
|
77
|
+
/** kill 没落地。 */
|
|
78
|
+
export declare const STOP_NOT_LANDED = "stop.not_landed";
|
|
79
|
+
/** 该任务不在本副本。 */
|
|
80
|
+
export declare const STOP_NOT_LOCAL = "stop.not_local";
|
|
81
|
+
/** 该任务已 park。 */
|
|
82
|
+
export declare const STOP_PARKED = "stop.parked";
|
|
83
|
+
/**
|
|
84
|
+
* 兜底**字面认码**用的已知集(typed 错误缺席时才走这条回落腿)。
|
|
85
|
+
* 🔴 **顺序即语义**:长码优先 —— `stop.parked` 是 `stop.park_resume_won` 的前缀,顺序反了
|
|
86
|
+
* `detail.includes()` 会让短码抢走长码的命中。数组(有序)不是 Set(无序),这是判据的一部分。
|
|
87
|
+
*/
|
|
88
|
+
export declare const STOP_CONFLICT_CODES: readonly ["stop.park_arbiter_unreachable", "stop.park_resume_won", "stop.not_landed", "stop.not_local", "stop.parked"];
|
|
89
|
+
/** `outputSchema` 任务在重试上限内没能产出合法结构化输出(语义字面就是 CC 那个 subtype 的话)。 */
|
|
90
|
+
export declare const OUTPUT_INVALID = "output.invalid";
|
|
91
|
+
/**
|
|
92
|
+
* 用户**可自解**的操作性错误的码前缀(选错回退目标 / 回退过根 / 快照缺失)。
|
|
93
|
+
* 消费点把 code 附在 message 后便于对账 —— 这一族是「你的操作有问题」,不是「引擎坏了」。
|
|
94
|
+
* 前缀形(不是成员形)= 开集:这一族里每加一个新码,判别自动跟上。
|
|
95
|
+
*/
|
|
96
|
+
export declare const REWIND_ERROR_CODE_PREFIXES: readonly ["resume_at.", "rewind_snapshot."];
|
|
97
|
+
/** 该码是否属 rewind/resume 可自解族。缺席 ⇒ false。 */
|
|
98
|
+
export declare function isRewindFamilyCode(code: string | undefined): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* 15 分钟流帽(server `src/http/sse-log.ts`)。
|
|
101
|
+
* 🔴 **到达 ≠ run 死了** —— 帧自己就说「run 仍然活着」。正确处置 = 按 `Last-Event-ID` 重连续读
|
|
102
|
+
* (`runs.events` 车道由 SDK 内部自动做)。把它当终态渲染会把一条还在跑的任务在 UI 上判死。
|
|
103
|
+
* `errorCode` 整体开集:未知码按「可重连的流控信号」通用降级,不要按成员判死。
|
|
104
|
+
*/
|
|
105
|
+
export declare const STREAM_MAX_DURATION = "STREAM_MAX_DURATION";
|
|
106
|
+
/**
|
|
107
|
+
* 🔴 **本文件唯一的闭集**([2577] core 亲自定谳:"closed set, single member today")。
|
|
108
|
+
* 语义 = 请求的模型词**没绑上**(没有 roster / 不在 roster 上),子代跑在继承来的默认模型上。
|
|
109
|
+
* 这**不是错误**:回落行为本身没变,只是现在说出来了。缺席 = 正常绑定,或压根没请求过模型词。
|
|
110
|
+
*
|
|
111
|
+
* 🔴 **加成员 = BREAKING 清单行** —— 所以此处写 string literal union 而不是 `string`:
|
|
112
|
+
* 消费端可以安全地按闭集分臂,而下一次 core 加成员时本包的类型面会**当场编译红**,
|
|
113
|
+
* 逼提货批显式处理,而不是让一个没人认得的原因静默落进 default 臂。
|
|
114
|
+
*/
|
|
115
|
+
export type ModelFallbackReason = 'inherit_no_tier_binding';
|
|
116
|
+
/** {@link ModelFallbackReason} 的唯一成员(今天)。 */
|
|
117
|
+
export declare const MODEL_FALLBACK_INHERIT_NO_TIER_BINDING: ModelFallbackReason;
|
|
118
|
+
/** wire 上的 `modelFallback` 窄化:是闭集成员才认,别的一律当缺席(不认得的原因 ≠ 编一个)。 */
|
|
119
|
+
export declare function asModelFallbackReason(v: unknown): ModelFallbackReason | undefined;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/engineErrorCodes.ts — **引擎 wire 码词表的单一真源**(G1 去字面化,2026-08-04,
|
|
3
|
+
* core 5.10.0 / sdk 6.2.0 消费半场)。
|
|
4
|
+
*
|
|
5
|
+
* ── 为什么要有这个文件 ────────────────────────────────────────────────────────────────────────
|
|
6
|
+
* 引擎的 `errorCode` 是**机器码**(结构位),壳的四条判别链都吃它:终帧 subtype 映射
|
|
7
|
+
* (`adapter/downstream/terminalToSdkResult.ts`)、409 busy 判别(`adapter/runStream.ts`)、
|
|
8
|
+
* `stop.*` 五形分类(`subagent/engineTaskHandleWire.ts`)、限额面文案(`limitsWire.ts`)。
|
|
9
|
+
* 收编前这些码以**裸字面量**散在五个文件、二十余处:core 每次词表迁移(5.8.0 的 `budget.*` →
|
|
10
|
+
* `limits.*`、5.10.0 的 `config.*` 第四波)都要满仓 grep `===` 比较,漏一处的后果不是报错而是
|
|
11
|
+
* **判别链静默走错臂** —— 这正是 [dep-bump-follow-on-checklist] 那类跟车事故的载体。
|
|
12
|
+
*
|
|
13
|
+
* ── 🔴 开集纪律(本文件最重要的一条)──────────────────────────────────────────────────────────
|
|
14
|
+
* **wire 的 `errorCode` 是开集**:引擎完全可能比本包新一版,发一个这里没有的码。所以:
|
|
15
|
+
* · 本文件的 `ReadonlySet` / 前缀谓词一律是**识别表**(recognition table),回答的是
|
|
16
|
+
* 「我认不认得这个码」,**绝不是**「合法码只有这些」;
|
|
17
|
+
* · 消费点的 `switch` 必须留 `default`、`if` 必须留 else 臂,未知码一律**原样透传**
|
|
18
|
+
* + 落诚实兜底臂,绝不塌进任何一个已知形(塌进去 = 替 server 编了一个它没说的原因);
|
|
19
|
+
* · 唯一的**闭集**是 {@link ModelFallbackReason} —— 它是 core 亲自声明的闭集单成员
|
|
20
|
+
* ([2577] 定谳),加成员 = BREAKING 清单行,所以它写成 string literal union 而不是 `string`。
|
|
21
|
+
* 这条例外**只此一处**,别照抄到别的码上。
|
|
22
|
+
*
|
|
23
|
+
* ── 命名与来源 ────────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
* 每一族下方注出它的 core 版本与出处帖号;码的字面**永远以引擎为准**,本文件只是镜子。
|
|
25
|
+
* 词表变动集中在一处可数(与 `terminalToSdkResult.ts` 那三个集合原本的立意同),提货批 diff 里
|
|
26
|
+
* 一眼能看出「这一版引擎加了哪几个词」。
|
|
27
|
+
*/
|
|
28
|
+
// ── 限额到限族(core 5.8.0 [2489] 词表迁移;5.7 的 `budget.*` / `limit.*` 已随退役批删净)────
|
|
29
|
+
/** token 预算到限。`result` 可能带已产出正文([2489] 明记)。 */
|
|
30
|
+
export const LIMITS_MAX_TOKENS_EXCEEDED = 'limits.max_tokens_exceeded';
|
|
31
|
+
/** 成本预算到限(唯一一个 CC 有专门 subtype 的预算轴)。 */
|
|
32
|
+
export const LIMITS_MAX_COST_EXCEEDED = 'limits.max_cost_exceeded';
|
|
33
|
+
/** 轮数预算到限。 */
|
|
34
|
+
export const LIMITS_MAX_TURNS_EXCEEDED = 'limits.max_turns_exceeded';
|
|
35
|
+
/** 墙钟预算到限(5.8.0 起是**响亮终局** `status:'failed'`;`status:'timeout'` 该终态词整体退役)。 */
|
|
36
|
+
export const LIMITS_MAX_WALLTIME_EXCEEDED = 'limits.max_walltime_exceeded';
|
|
37
|
+
// ── 停钟族(core 5.10.0「三时钟序」:usage_window > env_lifetime > stall)─────────────────────
|
|
38
|
+
/** 部署级 token 治理窗耗尽。**唯一携带可执行等待量的停因**,与 `retryAfterMs` 配对到货。
|
|
39
|
+
* 5.10.0 起:治理窗与环境寿命同一轮边界到期时,**窗赢**(此前 env-first 报告把它丢了)。 */
|
|
40
|
+
export const USAGE_WINDOW_EXHAUSTED = 'usage.window_exhausted';
|
|
41
|
+
/** 环境寿命到期(平台侧)。与上一条同轮到期时**让位**给它。 */
|
|
42
|
+
export const ENV_LIFETIME_EXPIRED = 'env.lifetime_expired';
|
|
43
|
+
// ── 配置拒绝族(core 5.10.0「不许静默折叠」第四波)────────────────────────────────────────────
|
|
44
|
+
// 语义:引擎拿到一个**无法求值**的旋钮值(NaN / 负数 / 分数 / 该轴不许的 Infinity)时**响亮拒**,
|
|
45
|
+
// 而不是折成 0 / 静默停用那道闸。这一族全部是「配置错了」,不是「跑失败了」—— CC 的四词 subtype
|
|
46
|
+
// 里没有对位词,故一律落诚实兜底 `error_during_execution`,真实语义靠码本身透传。
|
|
47
|
+
/** `TaskRequest.limits` 各门(runTeamDiscussion 累计额 / workflow 治理 TRUSTED 半 /
|
|
48
|
+
* `resourceSuspend` 四键)拒绝不可求值的值。 */
|
|
49
|
+
export const CONFIG_LIMIT_INVALID = 'config.limit_invalid';
|
|
50
|
+
/** `StrategyStore.find(scope, query, limit)` 的 limit 非「非负整数或 Infinity」。 */
|
|
51
|
+
export const CONFIG_STRATEGY_FIND_LIMIT_INVALID = 'config.strategy_find_limit_invalid';
|
|
52
|
+
/** `StrategyStore.prune` / `InMemoryStrategyStore` 构造的容量上限非非负整数(含点名拒 `Infinity`
|
|
53
|
+
* —— 容量帽可以放宽,不可以关掉)。 */
|
|
54
|
+
export const CONFIG_STRATEGY_MAX_SIZE_INVALID = 'config.strategy_max_size_invalid';
|
|
55
|
+
/** 未知的 limits 键(5.8.0 起:同时发新旧两代键会在这里当场失败,所以写面只发单一新形)。 */
|
|
56
|
+
export const CONFIG_LIMIT_UNKNOWN_KEY = 'config.limit_unknown_key';
|
|
57
|
+
/**
|
|
58
|
+
* 已知的配置拒绝码(**识别表,非白名单**)。判「这是不是一条配置拒绝」请用
|
|
59
|
+
* {@link isConfigRefusalCode} —— 它按 `config.` 前缀判,未来新成员自动落进来。
|
|
60
|
+
*/
|
|
61
|
+
export const CONFIG_REFUSAL_CODES = new Set([
|
|
62
|
+
CONFIG_LIMIT_INVALID,
|
|
63
|
+
CONFIG_STRATEGY_FIND_LIMIT_INVALID,
|
|
64
|
+
CONFIG_STRATEGY_MAX_SIZE_INVALID,
|
|
65
|
+
CONFIG_LIMIT_UNKNOWN_KEY,
|
|
66
|
+
]);
|
|
67
|
+
/** `config.` 前缀谓词 —— **开集**判别:5.10.0 之后每一波「不许静默折叠」都会往这一族加词,
|
|
68
|
+
* 按前缀判的消费点不必跟车,按成员判的必须跟车。缺席/空串 ⇒ false。 */
|
|
69
|
+
export function isConfigRefusalCode(code) {
|
|
70
|
+
return typeof code === 'string' && code.startsWith('config.');
|
|
71
|
+
}
|
|
72
|
+
// ── 中断族(core 5.10.0:被中断的 tool call 的合成 `tool_end` 终于带正文)──────────────────────
|
|
73
|
+
// 5.10.0 之前两条 reconcile 腿只把 `[INTERRUPTED]` 解释写进 transcript,事件流上只有
|
|
74
|
+
// `isError:true` 而无正文 ⇒ 从帧渲染工具输出的消费者看到的是**空结果**,一次调用的两个面互相矛盾。
|
|
75
|
+
// 现在帧上带 `output`(与所有 live 工具结果同一投影)+ `errorCode`(下面两员,来自持久化的
|
|
76
|
+
// `details.errorKind`)+ `label`,消费者**按码判别**而不是去正则匹配散文。
|
|
77
|
+
/** 该 call 从未真正开始执行(可安全重发)。 */
|
|
78
|
+
export const TOOL_END_INTERRUPTED_NEVER_STARTED = 'interrupted_never_started';
|
|
79
|
+
/** 该 call 的结局未知(持有它的进程死了 —— 副作用可能已经发生,**不可**当作没跑过)。 */
|
|
80
|
+
export const TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN = 'interrupted_outcome_unknown';
|
|
81
|
+
/**
|
|
82
|
+
* 中断码识别表(**开集**:`tool_end.errorCode` 整体是开集,未来可能有第三种中断成因)。
|
|
83
|
+
* 🔴 两员**语义不对称**,别合并处置:`never_started` 可以重发,`outcome_unknown` 不可以。
|
|
84
|
+
*/
|
|
85
|
+
export const TOOL_END_INTERRUPTED_CODES = new Set([
|
|
86
|
+
TOOL_END_INTERRUPTED_NEVER_STARTED,
|
|
87
|
+
TOOL_END_INTERRUPTED_OUTCOME_UNKNOWN,
|
|
88
|
+
]);
|
|
89
|
+
/** 这条 `tool_end` 是不是「中断留下的合成收口帧」。未知码 ⇒ false(开集:不认得就不认得,
|
|
90
|
+
* 绝不猜)。 */
|
|
91
|
+
export function isInterruptedToolEndCode(code) {
|
|
92
|
+
return typeof code === 'string' && TOOL_END_INTERRUPTED_CODES.has(code);
|
|
93
|
+
}
|
|
94
|
+
// ── 会话冲突族 ────────────────────────────────────────────────────────────────────────────────
|
|
95
|
+
/** 409 session-busy 的 canonical 码([2377]C-1,server main `049ff2c`,随 5.0.0 发)。 */
|
|
96
|
+
export const ACTIVE_RUN_BUSY_ERROR_CODE = 'conflict.session_active_run';
|
|
97
|
+
// ── `runs.taskStop` 409 冲突族([1833] G13;SDK `TaskStopConflictError.errorCode` 判别)────────
|
|
98
|
+
/** 仲裁店不可达 ⇒ **真相未知**(core 1.397 三分的第三形;塌进 `not_landed` 是诚实缺陷)。 */
|
|
99
|
+
export const STOP_PARK_ARBITER_UNREACHABLE = 'stop.park_arbiter_unreachable';
|
|
100
|
+
/** park 的 resume 赢了这场竞争。 */
|
|
101
|
+
export const STOP_PARK_RESUME_WON = 'stop.park_resume_won';
|
|
102
|
+
/** kill 没落地。 */
|
|
103
|
+
export const STOP_NOT_LANDED = 'stop.not_landed';
|
|
104
|
+
/** 该任务不在本副本。 */
|
|
105
|
+
export const STOP_NOT_LOCAL = 'stop.not_local';
|
|
106
|
+
/** 该任务已 park。 */
|
|
107
|
+
export const STOP_PARKED = 'stop.parked';
|
|
108
|
+
/**
|
|
109
|
+
* 兜底**字面认码**用的已知集(typed 错误缺席时才走这条回落腿)。
|
|
110
|
+
* 🔴 **顺序即语义**:长码优先 —— `stop.parked` 是 `stop.park_resume_won` 的前缀,顺序反了
|
|
111
|
+
* `detail.includes()` 会让短码抢走长码的命中。数组(有序)不是 Set(无序),这是判据的一部分。
|
|
112
|
+
*/
|
|
113
|
+
export const STOP_CONFLICT_CODES = [
|
|
114
|
+
STOP_PARK_ARBITER_UNREACHABLE,
|
|
115
|
+
STOP_PARK_RESUME_WON,
|
|
116
|
+
STOP_NOT_LANDED,
|
|
117
|
+
STOP_NOT_LOCAL,
|
|
118
|
+
STOP_PARKED,
|
|
119
|
+
];
|
|
120
|
+
// ── 结构化输出族 ──────────────────────────────────────────────────────────────────────────────
|
|
121
|
+
/** `outputSchema` 任务在重试上限内没能产出合法结构化输出(语义字面就是 CC 那个 subtype 的话)。 */
|
|
122
|
+
export const OUTPUT_INVALID = 'output.invalid';
|
|
123
|
+
// ── rewind / resume 族(core 1.292 [833])────────────────────────────────────────────────────
|
|
124
|
+
/**
|
|
125
|
+
* 用户**可自解**的操作性错误的码前缀(选错回退目标 / 回退过根 / 快照缺失)。
|
|
126
|
+
* 消费点把 code 附在 message 后便于对账 —— 这一族是「你的操作有问题」,不是「引擎坏了」。
|
|
127
|
+
* 前缀形(不是成员形)= 开集:这一族里每加一个新码,判别自动跟上。
|
|
128
|
+
*/
|
|
129
|
+
export const REWIND_ERROR_CODE_PREFIXES = ['resume_at.', 'rewind_snapshot.'];
|
|
130
|
+
/** 该码是否属 rewind/resume 可自解族。缺席 ⇒ false。 */
|
|
131
|
+
export function isRewindFamilyCode(code) {
|
|
132
|
+
return typeof code === 'string' && REWIND_ERROR_CODE_PREFIXES.some((p) => code.startsWith(p));
|
|
133
|
+
}
|
|
134
|
+
// ── 流控族(SDK 6.2.0 CB-1/TR-6 的 `error` 臂)───────────────────────────────────────────────
|
|
135
|
+
/**
|
|
136
|
+
* 15 分钟流帽(server `src/http/sse-log.ts`)。
|
|
137
|
+
* 🔴 **到达 ≠ run 死了** —— 帧自己就说「run 仍然活着」。正确处置 = 按 `Last-Event-ID` 重连续读
|
|
138
|
+
* (`runs.events` 车道由 SDK 内部自动做)。把它当终态渲染会把一条还在跑的任务在 UI 上判死。
|
|
139
|
+
* `errorCode` 整体开集:未知码按「可重连的流控信号」通用降级,不要按成员判死。
|
|
140
|
+
*/
|
|
141
|
+
export const STREAM_MAX_DURATION = 'STREAM_MAX_DURATION';
|
|
142
|
+
/** {@link ModelFallbackReason} 的唯一成员(今天)。 */
|
|
143
|
+
export const MODEL_FALLBACK_INHERIT_NO_TIER_BINDING = 'inherit_no_tier_binding';
|
|
144
|
+
/** wire 上的 `modelFallback` 窄化:是闭集成员才认,别的一律当缺席(不认得的原因 ≠ 编一个)。 */
|
|
145
|
+
export function asModelFallbackReason(v) {
|
|
146
|
+
return v === MODEL_FALLBACK_INHERIT_NO_TIER_BINDING ? MODEL_FALLBACK_INHERIT_NO_TIER_BINDING : undefined;
|
|
147
|
+
}
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* src/sema/finalVerifyWire.ts — headless `-p` finalVerification wire
|
|
3
|
-
*
|
|
2
|
+
* src/sema/finalVerifyWire.ts — headless `-p` finalVerification wire(TB2.0 反馈批 A · P1-1 建,
|
|
3
|
+
* 2026-07-15 DEFAULT ON;**clay 裁定 2026-08-04 翻面 DEFAULT OFF**,[2561]→[2562]/[2563] 案)。
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* 为什么默认关(裁定理由,按案情留档):机制是 TB 应试期为「模型自吹已完成」建的遗产;core 面
|
|
6
|
+
* 本就 opt-in([2562]:默认开是本消费层的选择,消费层持有重估义务);实锤=git-multibranch 一题
|
|
7
|
+
* 已构建出会通过验收的正确终态,终验注入后模型用自造哨兵串把正确产出覆盖坏(reward 1→0),注入
|
|
8
|
+
* 文案的两条护栏无代码强制力。配套的时间预算感知已被 design/164 拆除——**时间失明是设计内**,
|
|
9
|
+
* clay 同案否决了 core 的两个补偿选项(walltime 回 approach-notice / 注入带预算快照),不接。
|
|
10
|
+
* 引擎能力保留(core stop-gate 机制原样),要终验的场景显式开。
|
|
9
11
|
*
|
|
10
|
-
* PRECEDENCE(off
|
|
11
|
-
* a) `--no-final-verify` flag → off(
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* settings.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* d) 都没有 → true(TB 默认态吃满终验闸杠杆)。
|
|
12
|
+
* PRECEDENCE(off 优先;显式 on 才可能 stamp;否则默认 false):
|
|
13
|
+
* a) `--no-final-verify` flag → off(显式关,恒赢)。
|
|
14
|
+
* b) `SEMA_HEADLESS_FINAL_VERIFY` env OFF 拼写(envFlagOff,REF-CC-141 dup-02 单源)→ off。
|
|
15
|
+
* c) 显式 on:`--final-verify` flag / env ON 拼写(envFlagOn)——此时若用户配置了 Stop hook
|
|
16
|
+
* (settings hooks.Stop,经 hooksForWire 投影)仍**让位**(#106 裁 B:引擎 finalVerification
|
|
17
|
+
* 分支在 Stop hook 查询之前 return(runtask.js:1430-1443),开着会把用户 Stop hook 延迟至多
|
|
18
|
+
* 2 turn)+ stderr 告知;无 Stop hook → on。
|
|
19
|
+
* d) 都没有 → false(默认关,静默,无告知——没开过的
|
|
20
|
+
* 东西无从让位,让位告知仅在显式 on 被 Stop hook 压下时出现)。
|
|
20
21
|
*
|
|
21
22
|
* LIVE-GATE:与 scenarioWire 同款——调用点(seamQueryEngine.ask)以 SEMA_LIVE_BASEURL 为门,
|
|
22
23
|
* mock/pty fixture 车道永不 stamp 该字段(离线投影字节等价)。
|
|
@@ -39,6 +40,12 @@ export declare const HEADLESS_FINAL_VERIFY_ENV = "SEMA_HEADLESS_FINAL_VERIFY";
|
|
|
39
40
|
* never flags,scenarioWire 同款纪律)。Boolean flag,无值形态,重复无害。
|
|
40
41
|
*/
|
|
41
42
|
export declare function parseNoFinalVerifyArgv(argv: string[]): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Parse the explicit opt-in `--final-verify` out of an argv slice(同 `--no-final-verify` 的扫描
|
|
45
|
+
* 纪律:bare `--` 后是 positionals)。默认关时代的唯一 flag 开口;`--no-final-verify` 恒赢它
|
|
46
|
+
* (off 优先纪律)。壳侧 commander 需在 0.17.x 提货时注册本 flag(提货单点名)。
|
|
47
|
+
*/
|
|
48
|
+
export declare function parseFinalVerifyArgv(argv: string[]): boolean;
|
|
42
49
|
/**
|
|
43
50
|
* The settings-lane off-switch:`SEMA_HEADLESS_FINAL_VERIFY` 设成 {@link envFlagOff} 拼写集
|
|
44
51
|
* (REF-CC-141 dup-02 单源:`0`/`false`/`no`/`off`/`none`,大小写不敏感)disables the stamp。
|
|
@@ -58,17 +65,15 @@ export declare function headlessFinalVerifyDisabledByEnv(env?: EnvLike): boolean
|
|
|
58
65
|
*/
|
|
59
66
|
export declare function hasUserStopHook(wireHooks: WireHooksConfig | undefined): boolean;
|
|
60
67
|
/**
|
|
61
|
-
* Resolve the finalVerification stamp for a headless `-p` submit
|
|
62
|
-
* `--
|
|
68
|
+
* Resolve the finalVerification stamp for a headless `-p` submit:**默认 false**(clay 裁定
|
|
69
|
+
* 2026-08-04,头注案情);仅显式 `--final-verify` / env ON 拼写才可能 on,且 Stop hook 仍让位。
|
|
63
70
|
* 调用点必须 live-gate(SEMA_LIVE_BASEURL)——mock/offline 形状不变。
|
|
64
71
|
*/
|
|
65
72
|
export declare function resolveHeadlessFinalVerify(argv: string[], env?: EnvLike, wireHooks?: WireHooksConfig): boolean;
|
|
66
73
|
/**
|
|
67
|
-
* #106 裁 B(clay 2026-07-26)
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* 失去了终验)。方向注记:finalVerification 后续默认关(CC Stop hook 机制同,不叠超集)——
|
|
71
|
-
* 见记忆 final-verification-direction;届时本函数的默认臂翻转,detail 形不动。
|
|
74
|
+
* #106 裁 B(clay 2026-07-26)让位+告知维持,但默认臂已按 2026-08-04 裁定翻转(头注案情):
|
|
75
|
+
* 默认 off 且**无 offReason**(静默——没开过的东西无从让位,告知只在显式 on 被 Stop hook
|
|
76
|
+
* 压下时出现);flag/env 显式关同样不聒噪。detail 形不动(offReason 词表原样)。
|
|
72
77
|
*/
|
|
73
78
|
export declare function resolveHeadlessFinalVerifyDetail(argv: string[], env?: EnvLike, wireHooks?: WireHooksConfig): {
|
|
74
79
|
on: boolean;
|