@sema-agent/client-core 0.67.2 → 0.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +173 -0
- package/README.md +64 -1
- package/dist/adapt/arms.js +27 -2
- package/dist/adapt/turnFlags.d.ts +14 -0
- package/dist/adapt/turnFlags.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 +33 -2
- 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/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/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/toolResult.js +8 -0
- package/dist/workflowClient.d.ts +22 -0
- package/dist/workflowClient.js +37 -0
- package/docs/INTEGRATION-CLIENTS.md +367 -9
- package/package.json +2 -2
|
@@ -61,6 +61,9 @@
|
|
|
61
61
|
* 🔴 形制:`Object.freeze` 的数组,**不是**只在类型面只读的 `readonly T[]` —— 后者一行 `.splice()`
|
|
62
62
|
* 就能改,而公面消费者拿到的正是这个实例(本仓已定谳的病形,同 `RESUME_RETRY_LATER_CODES`)。
|
|
63
63
|
*/
|
|
64
|
+
// 🔴 0.68.0 / L-245:形制从 `readonly string[]` 改成**字面元组**(`as const`)—— 型面交得出成员
|
|
65
|
+
// 字面量,端的型面才能**派生**而不是再抄一遍两个词(与 `runTerminal.ts` 的两表分源同一条medicine)。
|
|
66
|
+
// 冻结的理由一字未改(公面消费者拿到的正是这个实例)。
|
|
64
67
|
export const CLASSIFIER_DENY_CAUSES = Object.freeze(['unavailable', 'parse_error']);
|
|
65
68
|
/** {@link CLASSIFIER_DENY_CAUSES} 的运行期成员判据(判据用它,别在端上再抄一张表)。 */
|
|
66
69
|
const DENY_CAUSE_SET = new Set(CLASSIFIER_DENY_CAUSES);
|
|
@@ -103,6 +106,8 @@ export function classifierDenyCauseOf(gate) {
|
|
|
103
106
|
const dd = d;
|
|
104
107
|
if (dd.kind !== 'denied')
|
|
105
108
|
return undefined;
|
|
109
|
+
// 🔴 0.68.0 / L-245:出参改**闭集成员型**(谓词已是型守卫)—— 读器闭集进、闭集出,措辞铸点
|
|
110
|
+
// 那一层的入参因此也能收窄,那条「结构不可达的兜底」于是变成编译期就闭的事(见下面那段)。
|
|
106
111
|
return isClassifierDenyCause(dd.cause) ? dd.cause : undefined;
|
|
107
112
|
}
|
|
108
113
|
/**
|
|
@@ -142,6 +147,11 @@ export const AUTO_MODE_UNAVAILABLE_CAUSES = Object.freeze(['error', 'timeout']);
|
|
|
142
147
|
* 重试解决不了,要去看那一轮的裁决散文 / 调分类器。
|
|
143
148
|
* 🔴 两句**不许合并**:合并等于把「稍后重试」与「别重试」渲成同一句。
|
|
144
149
|
*/
|
|
150
|
+
// 🔴 0.68.0 / L-245:表型从 `Record<string, string>` 改成 **`Record<ClassifierDenyCause, string>`**。
|
|
151
|
+
// 这一改就是本件真正的「never 分支断言」:core 哪天加第三个词,元组长一员 ⇒ 成员型多一员 ⇒
|
|
152
|
+
// **这张表少一个键** ⇒ **编译期当场红**,逼人同批补那一句话。修前是 `Record<string,…>`,加词那天
|
|
153
|
+
// 这里一声不响,靠的是运行期那句「a word newer than this client」的兜底 —— 而那句兜底**结构上
|
|
154
|
+
// 走不到**(读器在上一层就按闭集把表外词判成缺席),所以它既拦不住漂移、也从来没说过话。
|
|
145
155
|
const DENY_CAUSE_SENTENCES = Object.freeze({
|
|
146
156
|
unavailable: 'denied because the auto-mode classifier could not run this round (the call may be retried later)',
|
|
147
157
|
parse_error: 'denied because the auto-mode classifier answered outside its contract (its reply could not be parsed, so the call was blocked)',
|
|
@@ -151,18 +161,26 @@ const DENY_CAUSE_SENTENCES = Object.freeze({
|
|
|
151
161
|
*
|
|
152
162
|
* 🔴 **按自有属性查表**(与本包其余措辞铸点同一条纪律):`Object.freeze` 不移除原型,裸下标会让
|
|
153
163
|
* 一个来自 wire 的 `constructor` / `toString` 命中 `Object.prototype` 上的**函数**并被当成一句话。
|
|
154
|
-
* 🔴
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
164
|
+
* ── 🔴 0.68.0 / L-245:入参从 `unknown` 收窄成**闭集成员型** ─────────────────────────────────
|
|
165
|
+
* 修前这里留着一句「its reported cause X **is a word newer than this client**」的兜底,而它
|
|
166
|
+
* **结构上走不到**:唯一到达本铸点的路是 {@link classifierDenyCauseOf},那一层已经按闭集把表外词
|
|
167
|
+
* 判成了缺席(理由见该函数:出闭集的 cause 在 core 那边是**记录缺陷**,server 整条不上帧 ⇒ 一个
|
|
168
|
+
* 表外词根本到不了消费端)。一条走不到的兜底有两重坏处:① 它假装这一面是开集,于是没人给这张表
|
|
169
|
+
* 配编译期围栏,core 加词那天这里一声不响;② 它说的那句话是**假的** —— 真有一个「比这一端新」的词
|
|
170
|
+
* 时,它压根不会到这里。
|
|
171
|
+
* ⇒ 入参收窄(表外词现在是**编译期**错误)+ 表型 `Record<ClassifierDenyCause, string>`(加词当天
|
|
172
|
+
* 缺键红)。剩下的运行期兜底只服务一种情形:调用方 cast 绕过型面、或从旧持久态恢复出一个非成员值
|
|
173
|
+
* —— 那时它说的是「这个词不在本端的闭集里」(一句真话),而**不再**冒充「上游比我新」。
|
|
174
|
+
* 🔴 渲染路径**不许抛**(本仓已定谳的病形),所以 never 分支照样交一句话,不 throw。
|
|
159
175
|
*/
|
|
160
176
|
export function classifierDenyCauseDetail(cause) {
|
|
161
|
-
|
|
177
|
+
// 🔴 **按自有属性查表**(与本包其余措辞铸点同一条纪律):`Object.freeze` 不移除原型,一个被
|
|
178
|
+
// cast 进来的 `constructor` / `toString` 会命中 `Object.prototype` 上的**函数**并被当成一句话。
|
|
179
|
+
const known = Object.hasOwn(DENY_CAUSE_SENTENCES, cause)
|
|
162
180
|
? DENY_CAUSE_SENTENCES[cause]
|
|
163
181
|
: undefined;
|
|
164
|
-
if (known
|
|
182
|
+
if (typeof known === 'string')
|
|
165
183
|
return known;
|
|
166
184
|
const word = typeof cause === 'string' && cause.length > 0 ? cause : '(none)';
|
|
167
|
-
return `denied by the auto-mode classifier lane; its reported cause ${word} is
|
|
185
|
+
return `denied by the auto-mode classifier lane; its reported cause ${word} is not one of the causes this client's closed set knows`;
|
|
168
186
|
}
|
|
@@ -20,6 +20,32 @@
|
|
|
20
20
|
* `AUTO_MODE_UNAVAILABLE_CAUSES` 的理由)。
|
|
21
21
|
*/
|
|
22
22
|
export declare const CLASSIFIER_STATUS_STATES: readonly string[];
|
|
23
|
+
/**
|
|
24
|
+
* 「本轮那一次观测」的**窄型面**(0.68.0 / L-245 B6)。
|
|
25
|
+
*
|
|
26
|
+
* ── 为什么这个型要有名字 ────────────────────────────────────────────────────────────────────
|
|
27
|
+
* 修前第二参是裸 `unknown`,而端手里常常只有**两格裸串**(`disposition.kind` / `disposition.cause`)——
|
|
28
|
+
* 于是壳把它们**铸回一个假门记录** `{gate:{disposition:{kind,cause}}}` 再喂进来(cli
|
|
29
|
+
* `classifierRoundObservation.ts` 的那一处)。那是一条「为了过读器而伪造上游形状」的路:伪造出来的
|
|
30
|
+
* 那层 `gate` 在 wire 上根本不存在,读者会以为端手里有一整只门记录,而下一次读器换键路时端还得
|
|
31
|
+
* 跟着改自己的伪造件。
|
|
32
|
+
* ⇒ 给它一个名字,并把**三条合法入形**写进型面:
|
|
33
|
+
* · `{ disposition }` —— 端手里只有处置那一格时**直接给这一格**(不必再铸一层 `gate`);
|
|
34
|
+
* · `{ gate }` —— 整只 `tool_end` 帧 / 一条耐久 park 行(键路 `gate.disposition`);
|
|
35
|
+
* · `{ origin }` —— 「分类器真的跑过」那条**肯定事实**的载体。
|
|
36
|
+
* 🔴 索引签名是**故意**的:整只 wire 帧(键远不止这三个)照样喂得进来,端零改造;而 `unknown`
|
|
37
|
+
* 类型的变量从此喂不进来 —— 那正是「端先自己判一下手里是什么」的那一步,也是伪造件消失的地方。
|
|
38
|
+
*/
|
|
39
|
+
export interface ClassifierRoundObservation {
|
|
40
|
+
/** 门记录上的处置(`{kind:'denied', cause}`)。端手里只有这一格时直接给它。 */
|
|
41
|
+
readonly disposition?: unknown;
|
|
42
|
+
/** 整只帧 / 耐久行上的门记录(键路 `gate.disposition`)。 */
|
|
43
|
+
readonly gate?: unknown;
|
|
44
|
+
/** 这只 ask 的出身词(`askOriginOf` 读它;`CLASSIFIER_RAN_ORIGINS` 的成员 = 分类器真跑过)。 */
|
|
45
|
+
readonly origin?: unknown;
|
|
46
|
+
/** 整只 wire 帧上的其余键(读器一个都不读;留索引签名是为了端零改造)。 */
|
|
47
|
+
readonly [extra: string]: unknown;
|
|
48
|
+
}
|
|
23
49
|
/** 一次状态读数。 */
|
|
24
50
|
export interface ClassifierStatusView {
|
|
25
51
|
/** {@link CLASSIFIER_STATUS_STATES} 之一。 */
|
|
@@ -31,9 +57,11 @@ export interface ClassifierStatusView {
|
|
|
31
57
|
* 「这个会话上,auto 分类器现在是什么状态」——三态,或 `undefined`(**说不出来**)。
|
|
32
58
|
*
|
|
33
59
|
* @param autoMode `wiring_manifest` 的 `autoMode` 段(投影后的或原始的都吃;本函数自己窄读)
|
|
34
|
-
* @param ask 可选:**本轮那一次观测**
|
|
35
|
-
* 载荷 / 一只带 `gate` 的 `tool_end`
|
|
36
|
-
*
|
|
60
|
+
* @param ask 可选:**本轮那一次观测**({@link ClassifierRoundObservation};0.68.0 / L-245 起
|
|
61
|
+
* 有名字)—— 一只 ask / 一条 durable park 行的 `tool_approval` 载荷 / 一只带 `gate` 的 `tool_end`
|
|
62
|
+
* 帧 / 一条门记录本体 / **只有 `{disposition}` 那一格**。键路同形,同一把读器吃(0.67.0:否定事实
|
|
63
|
+
* 的载体从 ask 上的 `classifierUnavailable` 改成门记录上的 `disposition.cause`)。
|
|
64
|
+
* 🔴 端**不必**为了过这只读器去铸一个假门记录:手里只有两格裸串时,直接交 `{disposition:{kind,cause}}`。
|
|
37
65
|
*
|
|
38
66
|
* 优先序(承重,理由见模块顶注):**本轮事实(否定 + 肯定)> 这条腿的 `armed`**——先看观测座上的
|
|
39
67
|
* 本轮不可用事实,再看那条「分类器真的跑过」的肯定事实,最后才看这条腿武没武装。
|
|
@@ -45,7 +73,7 @@ export interface ClassifierStatusView {
|
|
|
45
73
|
* 两种情形都**绝不**折成 `available`(那是把「没报」渲成「一切正常」)。
|
|
46
74
|
* ⚠️ 「没武装」本身仍是一条要渲的事实 —— 但它的出处是 `autoMode.reason`,不是本读器。
|
|
47
75
|
*/
|
|
48
|
-
export declare function classifierStatusOf(autoMode: unknown, ask?:
|
|
76
|
+
export declare function classifierStatusOf(autoMode: unknown, ask?: ClassifierRoundObservation): ClassifierStatusView | undefined;
|
|
49
77
|
/**
|
|
50
78
|
* 一次状态读数 → 一句人话。**唯一措辞铸点**(三端共用;端零自拼)。
|
|
51
79
|
*
|
package/dist/classifierStatus.js
CHANGED
|
@@ -135,9 +135,11 @@ const NOT_A_ROUND_FAILURE = new Set(['parse_error']);
|
|
|
135
135
|
* 「这个会话上,auto 分类器现在是什么状态」——三态,或 `undefined`(**说不出来**)。
|
|
136
136
|
*
|
|
137
137
|
* @param autoMode `wiring_manifest` 的 `autoMode` 段(投影后的或原始的都吃;本函数自己窄读)
|
|
138
|
-
* @param ask 可选:**本轮那一次观测**
|
|
139
|
-
* 载荷 / 一只带 `gate` 的 `tool_end`
|
|
140
|
-
*
|
|
138
|
+
* @param ask 可选:**本轮那一次观测**({@link ClassifierRoundObservation};0.68.0 / L-245 起
|
|
139
|
+
* 有名字)—— 一只 ask / 一条 durable park 行的 `tool_approval` 载荷 / 一只带 `gate` 的 `tool_end`
|
|
140
|
+
* 帧 / 一条门记录本体 / **只有 `{disposition}` 那一格**。键路同形,同一把读器吃(0.67.0:否定事实
|
|
141
|
+
* 的载体从 ask 上的 `classifierUnavailable` 改成门记录上的 `disposition.cause`)。
|
|
142
|
+
* 🔴 端**不必**为了过这只读器去铸一个假门记录:手里只有两格裸串时,直接交 `{disposition:{kind,cause}}`。
|
|
141
143
|
*
|
|
142
144
|
* 优先序(承重,理由见模块顶注):**本轮事实(否定 + 肯定)> 这条腿的 `armed`**——先看观测座上的
|
|
143
145
|
* 本轮不可用事实,再看那条「分类器真的跑过」的肯定事实,最后才看这条腿武没武装。
|
|
@@ -283,6 +283,37 @@ export declare const DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED = "decide.workflow_rem
|
|
|
283
283
|
* 🔴 加成员必须**同批**补那一句人话 + 判据,不许靠 `decide.` 前缀放宽(前缀下住着三种处置)。
|
|
284
284
|
*/
|
|
285
285
|
export declare const DECIDE_WORKFLOW_LANE_CODES: readonly string[];
|
|
286
|
+
/** 这条 workflow 的 park 真相**读不出来**(店抛了 / 超时 / 记录不在 / 记录还在跑)。
|
|
287
|
+
* `detail.reason` 开集(`checkpoint_store_threw` / `store_threw` / `record_missing` /
|
|
288
|
+
* `record_not_terminal`…;词表属主在 core)⇒ 读得出即原样带,读不懂**不折**已知词。 */
|
|
289
|
+
export declare const WORKFLOW_PARK_TRUTH_UNREADABLE = "workflow.park_truth_unreadable";
|
|
290
|
+
/** 记录说这一序号 park 着,而 checkpoint 店说那只审批**已决 / 已过期 / 被回收**。
|
|
291
|
+
* `detail.status` 三词(`absent` / `expired` / `resolved`)+ `detail.ordinal`;
|
|
292
|
+
* `detail.checkpointId` **可缺席**(店里没 id)—— 缺席 ≠ 「没有 checkpoint」。 */
|
|
293
|
+
export declare const WORKFLOW_PARK_NOT_PENDING = "workflow.park_not_pending";
|
|
294
|
+
/** 记录里的 park **绑不回**它的 checkpoint(记录自相矛盾)。`detail.ordinal` 在场。 */
|
|
295
|
+
export declare const WORKFLOW_PARK_BINDING_BROKEN = "workflow.park_binding_broken";
|
|
296
|
+
/** 这条 workflow 的子代会 park,而部署**没有 run 店**(或没有 checkpoint 店)⇒ 没有耐久行可供
|
|
297
|
+
* 宿主按它路由那只停着的审批。`detail` 恒空对象(这是**配置**问题,不是某一条 run 的事实)。 */
|
|
298
|
+
export declare const WORKFLOW_PARK_REQUIRES_RUN_STORE = "workflow.park_requires_run_store";
|
|
299
|
+
/**
|
|
300
|
+
* workflow **park 真相**拒绝码的闭集(四员;core 7.17.0 `workflow.ts:602` 码集)。
|
|
301
|
+
*
|
|
302
|
+
* 🔴 闭的是「**这四个码是 park 真相这一族独有的**」,不是「`workflow.*` 一共有几个码」——
|
|
303
|
+
* 后者仍是开集(`workflow.governance_key_stripped` / `workflow.agent_option_ignored` 是通告码,
|
|
304
|
+
* `workflow.journal_incompatible` 是另一族拒绝码,各有各的既有处置)。
|
|
305
|
+
* 🔴 **绝不靠 `workflow.park_` 前缀放宽**:前缀是个命名巧合,不是契约;上游哪天加第五个码,
|
|
306
|
+
* 该在这里显形并被人处置,而不是被一条前缀判据无声吞进来。
|
|
307
|
+
* 🔴 形制:`Object.freeze` 的数组(同 {@link DECIDE_WORKFLOW_LANE_CODES})。
|
|
308
|
+
*/
|
|
309
|
+
export declare const WORKFLOW_PARK_REFUSAL_CODES: readonly string[];
|
|
310
|
+
/**
|
|
311
|
+
* 这个码是不是 workflow park 真相族的拒绝码({@link WORKFLOW_PARK_REFUSAL_CODES} 的成员)。
|
|
312
|
+
*
|
|
313
|
+
* 🔴 表外码 ⇒ `false` = 「本端认不出它属于这一族」,**不是**「这次 resume 没问题」。
|
|
314
|
+
* 🔴 非串 / 空串 ⇒ `false`;认**原始值**(消毒只进文案,不进判据)。
|
|
315
|
+
*/
|
|
316
|
+
export declare function isWorkflowParkRefusalCode(code: unknown): boolean;
|
|
286
317
|
/**
|
|
287
318
|
* server 温切 drain 门的 pre-stream 拒收码(503 + `errorCode:"draining"`;server 侧
|
|
288
319
|
* `error:"draining"` 是冻结契约,SDK toApiError 盖成 `errorCode`)。此前壳/包注释各持裸字面。
|
|
@@ -314,3 +345,24 @@ export type ModelFallbackReason = 'inherit_no_tier_binding';
|
|
|
314
345
|
export declare const MODEL_FALLBACK_INHERIT_NO_TIER_BINDING: ModelFallbackReason;
|
|
315
346
|
/** wire 上的 `modelFallback` 窄化:是闭集成员才认,别的一律当缺席(不认得的原因 ≠ 编一个)。 */
|
|
316
347
|
export declare function asModelFallbackReason(v: unknown): ModelFallbackReason | undefined;
|
|
348
|
+
/**
|
|
349
|
+
* 引擎 turn 停止原词的**识别表**(五词;core `StopReason` 归一化后的值集)。
|
|
350
|
+
*
|
|
351
|
+
* 🔴 **它是识别表不是闭集判据**:`turn_end.stopReason` 在 sdk 型面上是开放 `string`(上游刻意让
|
|
352
|
+
* 引擎的 union 保持私有)⇒ 引擎比这一端新时真的会送一个第六个词过来。本表回答的是
|
|
353
|
+
* 「我认不认得这个词」,**绝不是**「合法的词只有这五个」。
|
|
354
|
+
*/
|
|
355
|
+
export declare const ENGINE_STOP_REASONS: readonly string[];
|
|
356
|
+
/**
|
|
357
|
+
* 引擎停止原词 → CC `stop_reason` 的**唯一映射口**。**三态**,刻意不合并:
|
|
358
|
+
* · `string` —— 映到了一个 CC 词;
|
|
359
|
+
* · `null` —— 映到了**诚实缺席**(`error` / `aborted`:CC 没有对应词,不编一个);
|
|
360
|
+
* · `undefined` —— **这个词本端不认识**(表外词 / 非串 / 空串)⇒ 调用方按「不映射」走原路。
|
|
361
|
+
*
|
|
362
|
+
* 🔴 `null` 与 `undefined` 必须分开:前者是「我认得这个词,而它的正确渲法就是没有词」,后者是
|
|
363
|
+
* 「我不认得这个词」。合成一个值 ⇒ 引擎加第六个词那天,它会被渲成一次「这一轮没有 stop_reason」
|
|
364
|
+
* 的**肯定事实**,而真相是这一端读不懂 —— 本仓反复在修的那条「把不知道渲成事实」的病。
|
|
365
|
+
* 🔴 **按自有属性查表**(`Object.freeze` 不移除原型):一个来自 wire 的 `constructor` / `toString`
|
|
366
|
+
* 会命中 `Object.prototype` 上的**函数**并被当成一个 CC 词交出去。
|
|
367
|
+
*/
|
|
368
|
+
export declare function engineStopReasonToCc(stopReason: unknown): string | null | undefined;
|
package/dist/engineErrorCodes.js
CHANGED
|
@@ -380,6 +380,57 @@ export const DECIDE_WORKFLOW_LANE_CODES = Object.freeze([
|
|
|
380
380
|
DECIDE_WORKFLOW_HOST_NOT_PARKED,
|
|
381
381
|
DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED,
|
|
382
382
|
]);
|
|
383
|
+
// ══ 0.68.0 提货批(core 7.17.0 #652;server [7084] D 段)—— workflow **park 真相**四拒码 ══════
|
|
384
|
+
//
|
|
385
|
+
// 背景一句话:workflow run 记录从 7.17.0 起带 `parks[]`(准入输入),而「一条 run 的 park 到底是
|
|
386
|
+
// 什么状态」是 **resume 的前提**。读不出 / 对不上 / 不在 pending / 压根没有 run 店 —— 四种情形此前
|
|
387
|
+
// 混在 `workflow.journal_incompatible` 的「journal entry missing」那一臂里,一个码说四件事,于是
|
|
388
|
+
// 消费端只能渲一句「日志不兼容」,而四条出路完全不同。core 7.17.0 把它们拆成四个码(那条旧臂同批
|
|
389
|
+
// 退役),`workflow.ts:602` 是码集的铸点。
|
|
390
|
+
//
|
|
391
|
+
// 🔴 **它们不是 `SCRIPT_ERROR_CODES` 的成员**(core 顶注逐字:host runtime 类)—— 别拿脚本错误那
|
|
392
|
+
// 张表去判它们,也别把它们塞进那张表。
|
|
393
|
+
// 🔴 **本包不抄 core 的句子**(单铸律,同 `engineNoticeCodes.ts` 顶注):只给码、闭集与每个码的
|
|
394
|
+
// `detail` 键位读法,人话用引擎给的那一句。
|
|
395
|
+
/** 这条 workflow 的 park 真相**读不出来**(店抛了 / 超时 / 记录不在 / 记录还在跑)。
|
|
396
|
+
* `detail.reason` 开集(`checkpoint_store_threw` / `store_threw` / `record_missing` /
|
|
397
|
+
* `record_not_terminal`…;词表属主在 core)⇒ 读得出即原样带,读不懂**不折**已知词。 */
|
|
398
|
+
export const WORKFLOW_PARK_TRUTH_UNREADABLE = 'workflow.park_truth_unreadable';
|
|
399
|
+
/** 记录说这一序号 park 着,而 checkpoint 店说那只审批**已决 / 已过期 / 被回收**。
|
|
400
|
+
* `detail.status` 三词(`absent` / `expired` / `resolved`)+ `detail.ordinal`;
|
|
401
|
+
* `detail.checkpointId` **可缺席**(店里没 id)—— 缺席 ≠ 「没有 checkpoint」。 */
|
|
402
|
+
export const WORKFLOW_PARK_NOT_PENDING = 'workflow.park_not_pending';
|
|
403
|
+
/** 记录里的 park **绑不回**它的 checkpoint(记录自相矛盾)。`detail.ordinal` 在场。 */
|
|
404
|
+
export const WORKFLOW_PARK_BINDING_BROKEN = 'workflow.park_binding_broken';
|
|
405
|
+
/** 这条 workflow 的子代会 park,而部署**没有 run 店**(或没有 checkpoint 店)⇒ 没有耐久行可供
|
|
406
|
+
* 宿主按它路由那只停着的审批。`detail` 恒空对象(这是**配置**问题,不是某一条 run 的事实)。 */
|
|
407
|
+
export const WORKFLOW_PARK_REQUIRES_RUN_STORE = 'workflow.park_requires_run_store';
|
|
408
|
+
/**
|
|
409
|
+
* workflow **park 真相**拒绝码的闭集(四员;core 7.17.0 `workflow.ts:602` 码集)。
|
|
410
|
+
*
|
|
411
|
+
* 🔴 闭的是「**这四个码是 park 真相这一族独有的**」,不是「`workflow.*` 一共有几个码」——
|
|
412
|
+
* 后者仍是开集(`workflow.governance_key_stripped` / `workflow.agent_option_ignored` 是通告码,
|
|
413
|
+
* `workflow.journal_incompatible` 是另一族拒绝码,各有各的既有处置)。
|
|
414
|
+
* 🔴 **绝不靠 `workflow.park_` 前缀放宽**:前缀是个命名巧合,不是契约;上游哪天加第五个码,
|
|
415
|
+
* 该在这里显形并被人处置,而不是被一条前缀判据无声吞进来。
|
|
416
|
+
* 🔴 形制:`Object.freeze` 的数组(同 {@link DECIDE_WORKFLOW_LANE_CODES})。
|
|
417
|
+
*/
|
|
418
|
+
export const WORKFLOW_PARK_REFUSAL_CODES = Object.freeze([
|
|
419
|
+
WORKFLOW_PARK_TRUTH_UNREADABLE,
|
|
420
|
+
WORKFLOW_PARK_NOT_PENDING,
|
|
421
|
+
WORKFLOW_PARK_BINDING_BROKEN,
|
|
422
|
+
WORKFLOW_PARK_REQUIRES_RUN_STORE,
|
|
423
|
+
]);
|
|
424
|
+
const WORKFLOW_PARK_REFUSAL_CODE_SET = new Set(WORKFLOW_PARK_REFUSAL_CODES);
|
|
425
|
+
/**
|
|
426
|
+
* 这个码是不是 workflow park 真相族的拒绝码({@link WORKFLOW_PARK_REFUSAL_CODES} 的成员)。
|
|
427
|
+
*
|
|
428
|
+
* 🔴 表外码 ⇒ `false` = 「本端认不出它属于这一族」,**不是**「这次 resume 没问题」。
|
|
429
|
+
* 🔴 非串 / 空串 ⇒ `false`;认**原始值**(消毒只进文案,不进判据)。
|
|
430
|
+
*/
|
|
431
|
+
export function isWorkflowParkRefusalCode(code) {
|
|
432
|
+
return typeof code === 'string' && WORKFLOW_PARK_REFUSAL_CODE_SET.has(code);
|
|
433
|
+
}
|
|
383
434
|
// ── drain / 场景执法族(A-028.11/.13 单源化,#244 族E,2026-08-15)────────────────────────────
|
|
384
435
|
/**
|
|
385
436
|
* server 温切 drain 门的 pre-stream 拒收码(503 + `errorCode:"draining"`;server 侧
|
|
@@ -405,3 +456,69 @@ export const MODEL_FALLBACK_INHERIT_NO_TIER_BINDING = 'inherit_no_tier_binding';
|
|
|
405
456
|
export function asModelFallbackReason(v) {
|
|
406
457
|
return v === MODEL_FALLBACK_INHERIT_NO_TIER_BINDING ? MODEL_FALLBACK_INHERIT_NO_TIER_BINDING : undefined;
|
|
407
458
|
}
|
|
459
|
+
// ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
460
|
+
// 0.68.0(L-246 A13)—— 引擎的 **turn 停止原词** → CC `stop_reason`(**唯一映射铸点**)
|
|
461
|
+
// ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
462
|
+
//
|
|
463
|
+
// ── 为什么它下沉到包里 ────────────────────────────────────────────────────────────────────────
|
|
464
|
+
// 这张表此前住在壳里(cli `printStreamJsonContract.ts` 的 `ENGINE_STOP_REASON_TO_CC`),而它是一张
|
|
465
|
+
// **CC 皮肤词汇表** —— 本包的立意逐字是「Every CC-skin shape is collected here so the wire itself
|
|
466
|
+
// stays neutral」。住在壳里的后果是三端各铸一份:web / desktop 要渲同一个 `stop_reason` 时只能
|
|
467
|
+
// 自己再抄一遍五个词,而下一次 core 归一化词表变动时,漏掉的那一份会把**这一轮为什么停**渲错 ——
|
|
468
|
+
// 而那恰恰是出错/被截断那一刻最需要读对的一格。
|
|
469
|
+
//
|
|
470
|
+
// ── 左右两列的出处 ────────────────────────────────────────────────────────────────────────────
|
|
471
|
+
// 左列 = `turn_end.stopReason`(core `StopReason` 归一化后的五词;core `task-event.d.ts` 逐字:
|
|
472
|
+
// 「Typed `string` (not the internal `StopReason`) to keep the engine's union private, but the
|
|
473
|
+
// value set is exactly those five tokens」)—— 本包的 `turn_usage._sema_stop_reason` 原词透传它。
|
|
474
|
+
// 右列 = CC stdout 契约上的 `stop_reason`。
|
|
475
|
+
/**
|
|
476
|
+
* 引擎 turn 停止原词的**识别表**(五词;core `StopReason` 归一化后的值集)。
|
|
477
|
+
*
|
|
478
|
+
* 🔴 **它是识别表不是闭集判据**:`turn_end.stopReason` 在 sdk 型面上是开放 `string`(上游刻意让
|
|
479
|
+
* 引擎的 union 保持私有)⇒ 引擎比这一端新时真的会送一个第六个词过来。本表回答的是
|
|
480
|
+
* 「我认不认得这个词」,**绝不是**「合法的词只有这五个」。
|
|
481
|
+
*/
|
|
482
|
+
export const ENGINE_STOP_REASONS = Object.freeze([
|
|
483
|
+
'stop',
|
|
484
|
+
'length',
|
|
485
|
+
'toolUse',
|
|
486
|
+
'error',
|
|
487
|
+
'aborted',
|
|
488
|
+
]);
|
|
489
|
+
/**
|
|
490
|
+
* 五词 → CC `stop_reason`。`null` **不是**「没映射」,是**映射到诚实缺席**。
|
|
491
|
+
*
|
|
492
|
+
* 🔴 两条纪律(逐字自壳侧原表搬入,一个字节没改语义):
|
|
493
|
+
* · `error` / `aborted` 在 CC 的词表里**没有对应词**,而既有结算规则对出错的一轮本来就留 `null`
|
|
494
|
+
* (schema 可空)⇒ 这里同样**不编一个词出来**;
|
|
495
|
+
* · **表外词一律不映射**(见 {@link engineStopReasonToCc}):引擎长出第六个词时既不猜也不改既有
|
|
496
|
+
* 结算,让它按修前那条路走完 —— 猜一个 CC 词会让消费者据此判错这一轮的结局。
|
|
497
|
+
*/
|
|
498
|
+
const ENGINE_STOP_REASON_TO_CC = Object.freeze({
|
|
499
|
+
stop: 'end_turn',
|
|
500
|
+
length: 'max_tokens',
|
|
501
|
+
toolUse: 'tool_use',
|
|
502
|
+
error: null,
|
|
503
|
+
aborted: null,
|
|
504
|
+
});
|
|
505
|
+
/**
|
|
506
|
+
* 引擎停止原词 → CC `stop_reason` 的**唯一映射口**。**三态**,刻意不合并:
|
|
507
|
+
* · `string` —— 映到了一个 CC 词;
|
|
508
|
+
* · `null` —— 映到了**诚实缺席**(`error` / `aborted`:CC 没有对应词,不编一个);
|
|
509
|
+
* · `undefined` —— **这个词本端不认识**(表外词 / 非串 / 空串)⇒ 调用方按「不映射」走原路。
|
|
510
|
+
*
|
|
511
|
+
* 🔴 `null` 与 `undefined` 必须分开:前者是「我认得这个词,而它的正确渲法就是没有词」,后者是
|
|
512
|
+
* 「我不认得这个词」。合成一个值 ⇒ 引擎加第六个词那天,它会被渲成一次「这一轮没有 stop_reason」
|
|
513
|
+
* 的**肯定事实**,而真相是这一端读不懂 —— 本仓反复在修的那条「把不知道渲成事实」的病。
|
|
514
|
+
* 🔴 **按自有属性查表**(`Object.freeze` 不移除原型):一个来自 wire 的 `constructor` / `toString`
|
|
515
|
+
* 会命中 `Object.prototype` 上的**函数**并被当成一个 CC 词交出去。
|
|
516
|
+
*/
|
|
517
|
+
export function engineStopReasonToCc(stopReason) {
|
|
518
|
+
if (typeof stopReason !== 'string' || stopReason.length === 0)
|
|
519
|
+
return undefined;
|
|
520
|
+
if (!Object.hasOwn(ENGINE_STOP_REASON_TO_CC, stopReason))
|
|
521
|
+
return undefined;
|
|
522
|
+
const row = ENGINE_STOP_REASON_TO_CC[stopReason];
|
|
523
|
+
return typeof row === 'string' || row === null ? row : undefined;
|
|
524
|
+
}
|
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
* · **core 7.10.0 +2**:`delegation.ask_unresolvable`(audience **user** —— 委派链上那只 ask 判不出
|
|
23
23
|
* 归属、没有人可问,这件事的收件人是发起这次委派的**用户**)/ `config.read_face_swapped`
|
|
24
24
|
* (audience **operator** —— READ 容纳面被换过档,是部署事实)。四十八码 ⇒ **五十码**。
|
|
25
|
+
* · **core 7.17.0 +1**(0.68.0 提货批,同样由本门 A1 段当天红抓出:「上游 52 / 本包 51」):
|
|
26
|
+
* `config.artifact_host_invalid`(audience **operator** —— 宿主接了 artifact 席但它的
|
|
27
|
+
* `capabilities()` 声明不过席上的不变量、或 `onMount` 抛了 ⇒ 那只工具没挂上。上游逐字:
|
|
28
|
+
* 「an absent seat is silent; a broken one must not look the same」)。五十一码 ⇒ **五十二码**。
|
|
25
29
|
* · **core ≤7.16.0 +1**(0.67.0 提货批,由本门的 A1 段当天红抓出 —— 不是人眼发现的):
|
|
26
30
|
* `task.interrupt_unconsumed`(audience **user**;位置在 `task.late_approval` 与
|
|
27
31
|
* `memory.capture_opted_out` 之间,`governance-codes.js:146` / `NOTICE_AUDIENCE_TABLE:165` 真字节)。
|
|
@@ -50,7 +54,7 @@
|
|
|
50
54
|
/** 一条通告是**说给谁听**的。两值,刻意不设第三值(见模块顶注)。 */
|
|
51
55
|
export type NoticeAudience = 'user' | 'operator';
|
|
52
56
|
/**
|
|
53
|
-
* 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES
|
|
57
|
+
* 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES`,**7.17.x = 五十二码**;顺序同源)。
|
|
54
58
|
* 🔴 这是一份**抄件**,不是本包的意见 —— 改它必须同 commit 附 core 坐标,且门会先红。
|
|
55
59
|
* ⚠️ `EngineNotice.code` 的型面在上游**故意留 `string`**(宿主把自己的通告转发进同一个水槽是
|
|
56
60
|
* 被支持的形),所以本表是**判据**不是型 —— 别拿它去窄化那个字段。
|
|
@@ -106,3 +110,93 @@ export interface McpInjectionDropFactsView {
|
|
|
106
110
|
* (要渲一句话时,用引擎给的 `message`,见模块顶注的单铸律。)
|
|
107
111
|
*/
|
|
108
112
|
export declare function readMcpInjectionDrop(notice: unknown): McpInjectionDropFactsView | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* `delegation.ask_unresolvable` 的三个成因(core `ASK_UNRESOLVABLE_CAUSES` 逐词镜像,
|
|
115
|
+
* `dist/core/ask-unresolvable-notice.d.ts:31`)。
|
|
116
|
+
*
|
|
117
|
+
* 🔴 **0.68.0 BREAKING(core #709 ②)**:这一位**取代**了 7.16.0 及以前那条通告 `detail` 上的
|
|
118
|
+
* `settlementKind`(core `gate-exit.ts` 的一处铸点;`settlementKind` 在 7.17.x 的 core 与 sdk
|
|
119
|
+
* 真字节上**零命中**,本包按 clean-cut 不留双读,登记在 `run-retired-vocabulary-census-test.mjs`)。
|
|
120
|
+
* 两者不是改名:`settlementKind` 只说得出「结算是怎么落的」,而 in-fold 拒绝那一臂**根本没有
|
|
121
|
+
* 结算**骑在帧上(`mandate_unreconstructible`)—— 旧位在那一形上恒缺席。
|
|
122
|
+
*
|
|
123
|
+
* 三词各答「为什么这只 ask 判不出来」(上游逐字):
|
|
124
|
+
* · `approver_unavailable` —— 被问到的审批席(本 run 自己的,或委派子代身上那张冻结的祖先席)
|
|
125
|
+
* 对路由问题答了 `unavailable`,而其后**没有**耐久 park 接下这次调用;
|
|
126
|
+
* · `no_approver_wired` —— 这条 run 根本没接审批席(或问答面),或者席位就是拒绝姿态串
|
|
127
|
+
* (headless 自动拒);
|
|
128
|
+
* · `mandate_unreconstructible` —— 继承来的耐久审批 mandate 绑住了这只 ask,而**这条腿没有 park
|
|
129
|
+
* 设施**去兑现它,于是委派子代就地拒绝(in-fold 拒,帧上不带 settlement)。
|
|
130
|
+
*
|
|
131
|
+
* 🔴 形制:`Object.freeze` 的数组(同 `MCP_INJECTION_DROP_REASONS` 的已定谳病形)。
|
|
132
|
+
*/
|
|
133
|
+
export declare const ASK_UNRESOLVABLE_CAUSES: readonly string[];
|
|
134
|
+
/** `delegation.ask_unresolvable` 通告 `detail` 上的事实(引擎在拒绝出口知道的那几件)。 */
|
|
135
|
+
export interface AskUnresolvableFactsView {
|
|
136
|
+
/** 这条通告投给哪个会话。**必填** —— user audience 的通告没有会话就无处投递(上游在铸点抛)。 */
|
|
137
|
+
sessionId: string;
|
|
138
|
+
/** 这只 ask 是为哪个工具问的(引擎的 message 里逐字引了它)。 */
|
|
139
|
+
toolName: string;
|
|
140
|
+
/** 被拒的那次调用 id —— 与带着同一次拒绝的 `tool_end` 帧对得上的关联键。 */
|
|
141
|
+
toolCallId: string;
|
|
142
|
+
/** 三词之一({@link ASK_UNRESOLVABLE_CAUSES})。 */
|
|
143
|
+
cause: string;
|
|
144
|
+
/**
|
|
145
|
+
* 这条 run 上**有没有**武装过耐久审批 park 车道。
|
|
146
|
+
* `true` = park 有过它那一次机会而没接下(它拒了或失败了);`false` = 压根没有 park 车道(常见形)。
|
|
147
|
+
* 🔴 **读不出 ⇒ 键不铸**(不折 `false`):「没有 park 车道」与「不知道有没有」的下一步不同 ——
|
|
148
|
+
* 前者该去接一个 checkpoint 店,后者该去问引擎为什么没说。
|
|
149
|
+
*/
|
|
150
|
+
parkLaneExisted?: boolean;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* `delegation.ask_unresolvable` 通告 → 事实;不成形 ⇒ `undefined`,绝不抛出。
|
|
154
|
+
*
|
|
155
|
+
* 🔴 `cause` **按闭集读**:它是消费端分支的键(三条恢复路不同 —— 接一个耐久店 / 接一个审批席 /
|
|
156
|
+
* 别在无 park 设施的腿上继承 mandate)。读不懂的词 ⇒ **整只缺席**,而不是交一个分不了支的串。
|
|
157
|
+
*/
|
|
158
|
+
export declare function readAskUnresolvable(notice: unknown): AskUnresolvableFactsView | undefined;
|
|
159
|
+
/**
|
|
160
|
+
* 一条腿上的耐久审批 **mandate 从哪儿来**(core `DURABLE_MANDATE_SOURCES` 逐词镜像,
|
|
161
|
+
* `dist/core/tool-policy.d.ts:1403`)。两词的**恢复动作不同**,这正是上游把它铸上通告的理由:
|
|
162
|
+
* · `force_durable_gate` —— per-principal 的控制面权利,与席位无关 ⇒ 要么给这套部署接一个
|
|
163
|
+
* checkpoint 店,要么撤掉这批 principal 的这项权利;
|
|
164
|
+
* · `durable_approval` —— 任务自己的 opt-in 且**没有**活审批席 ⇒ 给任务一个活席位,或者不要
|
|
165
|
+
* 再传 `durableApproval`。
|
|
166
|
+
*
|
|
167
|
+
* 🔴 形制同上(冻结数组)。
|
|
168
|
+
*/
|
|
169
|
+
export declare const DURABLE_MANDATE_SOURCES: readonly string[];
|
|
170
|
+
/** `config.durable_gate_unavailable` 通告 `detail` 上的事实。 */
|
|
171
|
+
export interface DurableGateUnavailableFactsView {
|
|
172
|
+
/** 这条通告投给哪个会话(user audience ⇒ 必填)。 */
|
|
173
|
+
sessionId: string;
|
|
174
|
+
/** 哪一条 run。 */
|
|
175
|
+
runId: string;
|
|
176
|
+
/** 这条腿服务的 principal;上游只在有值时铸 ⇒ 读不出即缺席。 */
|
|
177
|
+
principal?: string;
|
|
178
|
+
/**
|
|
179
|
+
* **哪一个 mandate 没被兑现**({@link DURABLE_MANDATE_SOURCES} 之一)。
|
|
180
|
+
* 🔴 读不懂的词 ⇒ **整只缺席**(它是恢复动作的分支键;猜错会把人指去撤一项他根本没开的权利)。
|
|
181
|
+
*/
|
|
182
|
+
source: string;
|
|
183
|
+
/**
|
|
184
|
+
* **为什么没有 park 设施**:上游今天两词 `no_deployment_store`(这套部署一个店都没接)/
|
|
185
|
+
* `task_store_disabled`(`TaskSpec.checkpointStore: "disabled"`,这一次 run 自己关掉的)。
|
|
186
|
+
* 🔴 **开集透传**:core 今天**不导出**这两个词的闭集(它在铸点是一个三元表达式,
|
|
187
|
+
* `prepare-wiring-manifest.js:90`)⇒ 抄一份就是本包自铸词表,加员那天还是本包先错。
|
|
188
|
+
* 非空串即原样带回,词表属主在 core;要分支的消费端自己按已知词判,别拿它当穷举。
|
|
189
|
+
*/
|
|
190
|
+
cause: string;
|
|
191
|
+
/** 这条腿的权限 ask **会不会**由一个活席位当场答(`false` ⇒ fail-closed 拒)。读不出 ⇒ 键不铸。 */
|
|
192
|
+
liveApprover?: boolean;
|
|
193
|
+
/** `AskUserQuestion` **会不会**由一个活问答面当场答。读不出 ⇒ 键不铸。 */
|
|
194
|
+
liveQuestionFace?: boolean;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* `config.durable_gate_unavailable` 通告 → 事实;不成形 ⇒ `undefined`,绝不抛出。
|
|
198
|
+
*
|
|
199
|
+
* 🔴 **两个布尔位缺席不折 `false`**:core 在铸点把它们写成必填,但「这一格读不出」与
|
|
200
|
+
* 「这一格是 false」对用户的下一步不同(前者是「引擎没说」,后者是「没有人会答你这条 ask」)。
|
|
201
|
+
*/
|
|
202
|
+
export declare function readDurableGateUnavailable(notice: unknown): DurableGateUnavailableFactsView | undefined;
|
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
* · **core 7.10.0 +2**:`delegation.ask_unresolvable`(audience **user** —— 委派链上那只 ask 判不出
|
|
23
23
|
* 归属、没有人可问,这件事的收件人是发起这次委派的**用户**)/ `config.read_face_swapped`
|
|
24
24
|
* (audience **operator** —— READ 容纳面被换过档,是部署事实)。四十八码 ⇒ **五十码**。
|
|
25
|
+
* · **core 7.17.0 +1**(0.68.0 提货批,同样由本门 A1 段当天红抓出:「上游 52 / 本包 51」):
|
|
26
|
+
* `config.artifact_host_invalid`(audience **operator** —— 宿主接了 artifact 席但它的
|
|
27
|
+
* `capabilities()` 声明不过席上的不变量、或 `onMount` 抛了 ⇒ 那只工具没挂上。上游逐字:
|
|
28
|
+
* 「an absent seat is silent; a broken one must not look the same」)。五十一码 ⇒ **五十二码**。
|
|
25
29
|
* · **core ≤7.16.0 +1**(0.67.0 提货批,由本门的 A1 段当天红抓出 —— 不是人眼发现的):
|
|
26
30
|
* `task.interrupt_unconsumed`(audience **user**;位置在 `task.late_approval` 与
|
|
27
31
|
* `memory.capture_opted_out` 之间,`governance-codes.js:146` / `NOTICE_AUDIENCE_TABLE:165` 真字节)。
|
|
@@ -48,7 +52,7 @@
|
|
|
48
52
|
* 出现在本包源码或产物里 => 当场红。
|
|
49
53
|
*/
|
|
50
54
|
/**
|
|
51
|
-
* 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES
|
|
55
|
+
* 引擎**成文码册**的逐字镜像(core `ENGINE_NOTICE_CODES`,**7.17.x = 五十二码**;顺序同源)。
|
|
52
56
|
* 🔴 这是一份**抄件**,不是本包的意见 —— 改它必须同 commit 附 core 坐标,且门会先红。
|
|
53
57
|
* ⚠️ `EngineNotice.code` 的型面在上游**故意留 `string`**(宿主把自己的通告转发进同一个水槽是
|
|
54
58
|
* 被支持的形),所以本表是**判据**不是型 —— 别拿它去窄化那个字段。
|
|
@@ -66,6 +70,9 @@ export const ENGINE_NOTICE_CODES = Object.freeze([
|
|
|
66
70
|
'config.tool_model_gate_removed',
|
|
67
71
|
'config.tool_model_gate_unknown_class',
|
|
68
72
|
'config.tool_model_gate_env_invalid',
|
|
73
|
+
// 0.68.0 提货批(core 7.17.0 加员;位置 = `governance-codes.js:108` 真字节,在
|
|
74
|
+
// `config.tool_model_gate_env_invalid` 与 `config.tool_card_undeclared` 之间)。
|
|
75
|
+
'config.artifact_host_invalid',
|
|
69
76
|
'config.tool_card_undeclared',
|
|
70
77
|
'config.tool_face_undeclared',
|
|
71
78
|
'config.tool_face_invalid',
|
|
@@ -133,6 +140,8 @@ export const ENGINE_NOTICE_AUDIENCE = Object.freeze({
|
|
|
133
140
|
'config.tool_model_gate_removed': 'operator',
|
|
134
141
|
'config.tool_model_gate_unknown_class': 'operator',
|
|
135
142
|
'config.tool_model_gate_env_invalid': 'operator',
|
|
143
|
+
// 0.68.0 提货批:`NOTICE_AUDIENCE_TABLE:181` 真字节 —— 一条「宿主把 artifact 席接坏了」的部署事实。
|
|
144
|
+
'config.artifact_host_invalid': 'operator',
|
|
136
145
|
'config.tool_card_undeclared': 'operator',
|
|
137
146
|
'config.tool_face_undeclared': 'operator',
|
|
138
147
|
'config.tool_face_invalid': 'operator',
|
|
@@ -235,3 +244,117 @@ export function readMcpInjectionDrop(notice) {
|
|
|
235
244
|
const field = typeof o.field === 'string' && o.field.length > 0 ? o.field : undefined;
|
|
236
245
|
return { sessionId, server, reason, ...(field !== undefined ? { field } : {}) };
|
|
237
246
|
}
|
|
247
|
+
// ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
248
|
+
// 0.68.0 提货批(core 7.17.0 #709 ①②)—— 两条通告的**事实窄读器**
|
|
249
|
+
// ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
250
|
+
// 与 {@link readMcpInjectionDrop} 同一套规矩(单铸律不变:本模块只给码册、闭集与**事实**,
|
|
251
|
+
// 一句措辞都不抄 —— 转录用引擎给的 `message`):
|
|
252
|
+
// · **只认自己那一个码**(读器按码分家);
|
|
253
|
+
// · 必填格缺一 ⇒ **整只缺席**(读点判缺席而不抛:读点抛只会把一条读不懂的通告升级成一次崩);
|
|
254
|
+
// · **分支用的键按闭集读**(读不懂的词不许被当成一个能拿去分支的原因);**非分支键开集透传**。
|
|
255
|
+
/**
|
|
256
|
+
* `delegation.ask_unresolvable` 的三个成因(core `ASK_UNRESOLVABLE_CAUSES` 逐词镜像,
|
|
257
|
+
* `dist/core/ask-unresolvable-notice.d.ts:31`)。
|
|
258
|
+
*
|
|
259
|
+
* 🔴 **0.68.0 BREAKING(core #709 ②)**:这一位**取代**了 7.16.0 及以前那条通告 `detail` 上的
|
|
260
|
+
* `settlementKind`(core `gate-exit.ts` 的一处铸点;`settlementKind` 在 7.17.x 的 core 与 sdk
|
|
261
|
+
* 真字节上**零命中**,本包按 clean-cut 不留双读,登记在 `run-retired-vocabulary-census-test.mjs`)。
|
|
262
|
+
* 两者不是改名:`settlementKind` 只说得出「结算是怎么落的」,而 in-fold 拒绝那一臂**根本没有
|
|
263
|
+
* 结算**骑在帧上(`mandate_unreconstructible`)—— 旧位在那一形上恒缺席。
|
|
264
|
+
*
|
|
265
|
+
* 三词各答「为什么这只 ask 判不出来」(上游逐字):
|
|
266
|
+
* · `approver_unavailable` —— 被问到的审批席(本 run 自己的,或委派子代身上那张冻结的祖先席)
|
|
267
|
+
* 对路由问题答了 `unavailable`,而其后**没有**耐久 park 接下这次调用;
|
|
268
|
+
* · `no_approver_wired` —— 这条 run 根本没接审批席(或问答面),或者席位就是拒绝姿态串
|
|
269
|
+
* (headless 自动拒);
|
|
270
|
+
* · `mandate_unreconstructible` —— 继承来的耐久审批 mandate 绑住了这只 ask,而**这条腿没有 park
|
|
271
|
+
* 设施**去兑现它,于是委派子代就地拒绝(in-fold 拒,帧上不带 settlement)。
|
|
272
|
+
*
|
|
273
|
+
* 🔴 形制:`Object.freeze` 的数组(同 `MCP_INJECTION_DROP_REASONS` 的已定谳病形)。
|
|
274
|
+
*/
|
|
275
|
+
export const ASK_UNRESOLVABLE_CAUSES = Object.freeze([
|
|
276
|
+
'approver_unavailable',
|
|
277
|
+
'no_approver_wired',
|
|
278
|
+
'mandate_unreconstructible',
|
|
279
|
+
]);
|
|
280
|
+
const ASK_UNRESOLVABLE_CAUSE_SET = new Set(ASK_UNRESOLVABLE_CAUSES);
|
|
281
|
+
/**
|
|
282
|
+
* `delegation.ask_unresolvable` 通告 → 事实;不成形 ⇒ `undefined`,绝不抛出。
|
|
283
|
+
*
|
|
284
|
+
* 🔴 `cause` **按闭集读**:它是消费端分支的键(三条恢复路不同 —— 接一个耐久店 / 接一个审批席 /
|
|
285
|
+
* 别在无 park 设施的腿上继承 mandate)。读不懂的词 ⇒ **整只缺席**,而不是交一个分不了支的串。
|
|
286
|
+
*/
|
|
287
|
+
export function readAskUnresolvable(notice) {
|
|
288
|
+
if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
|
|
289
|
+
return undefined;
|
|
290
|
+
const n = notice;
|
|
291
|
+
if (n.code !== 'delegation.ask_unresolvable')
|
|
292
|
+
return undefined;
|
|
293
|
+
const d = n.detail;
|
|
294
|
+
if (typeof d !== 'object' || d === null || Array.isArray(d))
|
|
295
|
+
return undefined;
|
|
296
|
+
const o = d;
|
|
297
|
+
const sessionId = typeof o.sessionId === 'string' && o.sessionId.length > 0 ? o.sessionId : undefined;
|
|
298
|
+
const toolName = typeof o.toolName === 'string' && o.toolName.length > 0 ? o.toolName : undefined;
|
|
299
|
+
const toolCallId = typeof o.toolCallId === 'string' && o.toolCallId.length > 0 ? o.toolCallId : undefined;
|
|
300
|
+
const cause = typeof o.cause === 'string' && ASK_UNRESOLVABLE_CAUSE_SET.has(o.cause) ? o.cause : undefined;
|
|
301
|
+
if (sessionId === undefined || toolName === undefined || toolCallId === undefined || cause === undefined) {
|
|
302
|
+
return undefined;
|
|
303
|
+
}
|
|
304
|
+
return {
|
|
305
|
+
sessionId,
|
|
306
|
+
toolName,
|
|
307
|
+
toolCallId,
|
|
308
|
+
cause,
|
|
309
|
+
...(typeof o.parkLaneExisted === 'boolean' ? { parkLaneExisted: o.parkLaneExisted } : {}),
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* 一条腿上的耐久审批 **mandate 从哪儿来**(core `DURABLE_MANDATE_SOURCES` 逐词镜像,
|
|
314
|
+
* `dist/core/tool-policy.d.ts:1403`)。两词的**恢复动作不同**,这正是上游把它铸上通告的理由:
|
|
315
|
+
* · `force_durable_gate` —— per-principal 的控制面权利,与席位无关 ⇒ 要么给这套部署接一个
|
|
316
|
+
* checkpoint 店,要么撤掉这批 principal 的这项权利;
|
|
317
|
+
* · `durable_approval` —— 任务自己的 opt-in 且**没有**活审批席 ⇒ 给任务一个活席位,或者不要
|
|
318
|
+
* 再传 `durableApproval`。
|
|
319
|
+
*
|
|
320
|
+
* 🔴 形制同上(冻结数组)。
|
|
321
|
+
*/
|
|
322
|
+
export const DURABLE_MANDATE_SOURCES = Object.freeze([
|
|
323
|
+
'force_durable_gate',
|
|
324
|
+
'durable_approval',
|
|
325
|
+
]);
|
|
326
|
+
const DURABLE_MANDATE_SOURCE_SET = new Set(DURABLE_MANDATE_SOURCES);
|
|
327
|
+
/**
|
|
328
|
+
* `config.durable_gate_unavailable` 通告 → 事实;不成形 ⇒ `undefined`,绝不抛出。
|
|
329
|
+
*
|
|
330
|
+
* 🔴 **两个布尔位缺席不折 `false`**:core 在铸点把它们写成必填,但「这一格读不出」与
|
|
331
|
+
* 「这一格是 false」对用户的下一步不同(前者是「引擎没说」,后者是「没有人会答你这条 ask」)。
|
|
332
|
+
*/
|
|
333
|
+
export function readDurableGateUnavailable(notice) {
|
|
334
|
+
if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
|
|
335
|
+
return undefined;
|
|
336
|
+
const n = notice;
|
|
337
|
+
if (n.code !== 'config.durable_gate_unavailable')
|
|
338
|
+
return undefined;
|
|
339
|
+
const d = n.detail;
|
|
340
|
+
if (typeof d !== 'object' || d === null || Array.isArray(d))
|
|
341
|
+
return undefined;
|
|
342
|
+
const o = d;
|
|
343
|
+
const sessionId = typeof o.sessionId === 'string' && o.sessionId.length > 0 ? o.sessionId : undefined;
|
|
344
|
+
const runId = typeof o.runId === 'string' && o.runId.length > 0 ? o.runId : undefined;
|
|
345
|
+
const source = typeof o.source === 'string' && DURABLE_MANDATE_SOURCE_SET.has(o.source) ? o.source : undefined;
|
|
346
|
+
const cause = typeof o.cause === 'string' && o.cause.length > 0 ? o.cause : undefined;
|
|
347
|
+
if (sessionId === undefined || runId === undefined || source === undefined || cause === undefined) {
|
|
348
|
+
return undefined;
|
|
349
|
+
}
|
|
350
|
+
const principal = typeof o.principal === 'string' && o.principal.length > 0 ? o.principal : undefined;
|
|
351
|
+
return {
|
|
352
|
+
sessionId,
|
|
353
|
+
runId,
|
|
354
|
+
...(principal !== undefined ? { principal } : {}),
|
|
355
|
+
source,
|
|
356
|
+
cause,
|
|
357
|
+
...(typeof o.liveApprover === 'boolean' ? { liveApprover: o.liveApprover } : {}),
|
|
358
|
+
...(typeof o.liveQuestionFace === 'boolean' ? { liveQuestionFace: o.liveQuestionFace } : {}),
|
|
359
|
+
};
|
|
360
|
+
}
|