@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
package/dist/gateVocabulary.d.ts
CHANGED
|
@@ -94,10 +94,13 @@ export declare function askOriginDetail(origin: unknown, message?: unknown): str
|
|
|
94
94
|
* 结构上到不了消费端。
|
|
95
95
|
* 🔴 形制:`Object.freeze` 的数组,理由同上面两张表。
|
|
96
96
|
*/
|
|
97
|
-
export declare const RULE_STORE_UNREADABLE_KINDS: readonly
|
|
97
|
+
export declare const RULE_STORE_UNREADABLE_KINDS: readonly ["store", "call"];
|
|
98
|
+
/** {@link RULE_STORE_UNREADABLE_KINDS} 的成员型(端的型面改派生,不再手抄两词)。 */
|
|
99
|
+
export type RuleStoreUnreadableKind = (typeof RULE_STORE_UNREADABLE_KINDS)[number];
|
|
98
100
|
/** 这个值是不是 {@link RULE_STORE_UNREADABLE_KINDS} 的成员(core `isRuleStoreUnreadable` 的镜像)。
|
|
99
|
-
* 🔴 **唯一判据口**:窄读器与端都调它,谁都不许再抄一份字面量(B-025 的根因就是手抄)。
|
|
100
|
-
|
|
101
|
+
* 🔴 **唯一判据口**:窄读器与端都调它,谁都不许再抄一份字面量(B-025 的根因就是手抄)。
|
|
102
|
+
* 🔴 0.68.0 / L-245:改成**型守卫** —— 端用它一判就拿到闭集成员型,下一步喂措辞铸点时不必 cast。 */
|
|
103
|
+
export declare function isRuleStoreUnreadableKind(v: unknown): v is RuleStoreUnreadableKind;
|
|
101
104
|
/**
|
|
102
105
|
* 一个 `ruleStoreUnreadable` 词 → 一句人话。**唯一铸点**(三端共用;端零自拼)。
|
|
103
106
|
*
|
|
@@ -105,8 +108,16 @@ export declare function isRuleStoreUnreadableKind(v: unknown): boolean;
|
|
|
105
108
|
* **哪一头**」。`rule_store_unavailable` 那只 ask 上两句都该在,渲一句丢一句就等于把人指去
|
|
106
109
|
* 错的地方 —— 而这正是 core 把这一位单独铸出来的理由。
|
|
107
110
|
* 🔴 **查表用 `Object.hasOwn`**(冻结不移除原型;理由与本文件另两个铸点逐字相同)。
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
+
*
|
|
112
|
+
* ── 🔴 0.68.0 / L-245:入参从 `unknown` 收窄成**闭集成员型** ─────────────────────────────────
|
|
113
|
+
* 修前这里同样留着一句「is **a word newer than this client**」的兜底,而它**结构上走不到**:
|
|
114
|
+
* 唯一到达本铸点的路是卡口的窄读器(`toolApprovalWire` 的 `readRuleStoreUnreadable`),那一层已经
|
|
115
|
+
* 按闭集把表外值判成了缺席;而这一面在上游是**真闭集**(core 在唯一 stamp 点把政策自报值剥掉之后
|
|
116
|
+
* 才盖章)⇒ 一个「比这一端新」的值根本到不了。
|
|
117
|
+
* ⚠️ 与**隔壁那一句**({@link askOriginDetail})的处置刻意相反,而两边都是对的:`AskOrigin` 在 wire
|
|
118
|
+
* 上是**开集**(server 只判非空串,core 加词当天合法的帧就带着它到达)⇒ 那一句兜底**真的会被
|
|
119
|
+
* 走到**,必须留。一套面一条规矩:闭集则收窄 + 编译期围栏,开集则保留兜底。
|
|
120
|
+
* 🔴 渲染路径不许抛,所以 never 分支照样交一句话;只是它现在说的是「这个词不在本端的闭集里」
|
|
121
|
+
* (一句真话),而不再冒充「上游比我新」。
|
|
111
122
|
*/
|
|
112
|
-
export declare function ruleStoreUnreadableDetail(kind:
|
|
123
|
+
export declare function ruleStoreUnreadableDetail(kind: RuleStoreUnreadableKind): string;
|
package/dist/gateVocabulary.js
CHANGED
|
@@ -203,14 +203,19 @@ void _deniedByWordsPin;
|
|
|
203
203
|
* 结构上到不了消费端。
|
|
204
204
|
* 🔴 形制:`Object.freeze` 的数组,理由同上面两张表。
|
|
205
205
|
*/
|
|
206
|
+
// 🔴 0.68.0 / L-245:形制从 `readonly string[]` 改成**字面元组**(理由同 `CLASSIFIER_DENY_CAUSES`:
|
|
207
|
+
// 型面交得出成员字面量,端才能派生型而不是再抄一遍两个词)。
|
|
206
208
|
export const RULE_STORE_UNREADABLE_KINDS = Object.freeze(['store', 'call']);
|
|
207
209
|
const RULE_STORE_UNREADABLE_SET = new Set(RULE_STORE_UNREADABLE_KINDS);
|
|
208
210
|
/** 这个值是不是 {@link RULE_STORE_UNREADABLE_KINDS} 的成员(core `isRuleStoreUnreadable` 的镜像)。
|
|
209
|
-
* 🔴 **唯一判据口**:窄读器与端都调它,谁都不许再抄一份字面量(B-025 的根因就是手抄)。
|
|
211
|
+
* 🔴 **唯一判据口**:窄读器与端都调它,谁都不许再抄一份字面量(B-025 的根因就是手抄)。
|
|
212
|
+
* 🔴 0.68.0 / L-245:改成**型守卫** —— 端用它一判就拿到闭集成员型,下一步喂措辞铸点时不必 cast。 */
|
|
210
213
|
export function isRuleStoreUnreadableKind(v) {
|
|
211
214
|
return typeof v === 'string' && RULE_STORE_UNREADABLE_SET.has(v);
|
|
212
215
|
}
|
|
213
|
-
/** 逐词一句人话。**两句刻意逐字互异** —— 两条不同的下一步(去修部署的规则店 / 去改自己那条规则)。
|
|
216
|
+
/** 逐词一句人话。**两句刻意逐字互异** —— 两条不同的下一步(去修部署的规则店 / 去改自己那条规则)。
|
|
217
|
+
* 🔴 0.68.0 / L-245:表型改 `Record<RuleStoreUnreadableKind, string>` —— core 加第三个机制词那天
|
|
218
|
+
* **这张表少一个键 ⇒ 编译期当场红**,逼人同批补那一句话(修前是 `Record<string,…>`,加词一声不响)。 */
|
|
214
219
|
const RULE_STORE_UNREADABLE_SENTENCES = Object.freeze({
|
|
215
220
|
store: 'your standing deny/ask rules could not be read at all (the rule store did not answer), so this call asks',
|
|
216
221
|
call: 'this command could not be read against your standing deny/ask rules (the engine’s own sentence is on this ask), so it asks',
|
|
@@ -222,16 +227,24 @@ const RULE_STORE_UNREADABLE_SENTENCES = Object.freeze({
|
|
|
222
227
|
* **哪一头**」。`rule_store_unavailable` 那只 ask 上两句都该在,渲一句丢一句就等于把人指去
|
|
223
228
|
* 错的地方 —— 而这正是 core 把这一位单独铸出来的理由。
|
|
224
229
|
* 🔴 **查表用 `Object.hasOwn`**(冻结不移除原型;理由与本文件另两个铸点逐字相同)。
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
230
|
+
*
|
|
231
|
+
* ── 🔴 0.68.0 / L-245:入参从 `unknown` 收窄成**闭集成员型** ─────────────────────────────────
|
|
232
|
+
* 修前这里同样留着一句「is **a word newer than this client**」的兜底,而它**结构上走不到**:
|
|
233
|
+
* 唯一到达本铸点的路是卡口的窄读器(`toolApprovalWire` 的 `readRuleStoreUnreadable`),那一层已经
|
|
234
|
+
* 按闭集把表外值判成了缺席;而这一面在上游是**真闭集**(core 在唯一 stamp 点把政策自报值剥掉之后
|
|
235
|
+
* 才盖章)⇒ 一个「比这一端新」的值根本到不了。
|
|
236
|
+
* ⚠️ 与**隔壁那一句**({@link askOriginDetail})的处置刻意相反,而两边都是对的:`AskOrigin` 在 wire
|
|
237
|
+
* 上是**开集**(server 只判非空串,core 加词当天合法的帧就带着它到达)⇒ 那一句兜底**真的会被
|
|
238
|
+
* 走到**,必须留。一套面一条规矩:闭集则收窄 + 编译期围栏,开集则保留兜底。
|
|
239
|
+
* 🔴 渲染路径不许抛,所以 never 分支照样交一句话;只是它现在说的是「这个词不在本端的闭集里」
|
|
240
|
+
* (一句真话),而不再冒充「上游比我新」。
|
|
228
241
|
*/
|
|
229
242
|
export function ruleStoreUnreadableDetail(kind) {
|
|
230
|
-
const known =
|
|
243
|
+
const known = Object.hasOwn(RULE_STORE_UNREADABLE_SENTENCES, kind)
|
|
231
244
|
? RULE_STORE_UNREADABLE_SENTENCES[kind]
|
|
232
245
|
: undefined;
|
|
233
|
-
if (known
|
|
246
|
+
if (typeof known === 'string')
|
|
234
247
|
return known;
|
|
235
248
|
const word = typeof kind === 'string' && kind.length > 0 ? kind : '(none)';
|
|
236
|
-
return `your standing deny/ask rules could not be applied to this call; the reported reason ${word} is
|
|
249
|
+
return `your standing deny/ask rules could not be applied to this call; the reported reason ${word} is not one of the mechanisms this client's closed set knows, so answer this ask as usual`;
|
|
237
250
|
}
|
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* parkResolver — HITL gate 桥**外环**的 park 决断(REF-CC-032 / SPLIT-12 第三刀,2026-08-02)。
|
|
3
|
-
*
|
|
4
|
-
* 内环(`frameRouter.ts`)带出一个 `GatePark` 之后,这里回答唯一一个问题:**接着读流,还是
|
|
5
|
-
* fail-soft 收场**。三条出路:
|
|
6
|
-
* · 决断成功 ⇒ `reattach`(驱动 attach `runs.events`,`lastEventId` 续传);
|
|
7
|
-
* · 「这个 gate 早就被解决了」(durable re-attach 必然重放已决断的 park)⇒ 同样 `reattach`;
|
|
8
|
-
* · 其余(overlay 缺席 / pending 蒸发 / decide 409/404 / turn 中断 / hop 预算耗尽)⇒ `failsoft`:
|
|
9
|
-
* flush HOLD 的毒化帧 + 原样吐 suspended 终帧(durable 腿无终帧则合成一条可见的 failed)。
|
|
10
|
-
*
|
|
11
|
-
* 🔴 本文件不碰流、不 yield:events 以数组交回驱动。`resolvePark` 的**返回值**就是它的全部对外
|
|
12
|
-
* 效果(台账写入除外,且台账写入全经 `GateLedger` 的动词)—— 于是「禁掉某条真臂」这种变异
|
|
13
|
-
* 在驱动的消费点上必然显形,而不是被本文件自己吞掉。
|
|
14
|
-
*/
|
|
15
1
|
import type { AgentEvent } from '@sema-agent/sdk';
|
|
16
2
|
import { type GateCurrentPending, type HitlFailureStage } from './hitlBridge.js';
|
|
17
3
|
import { type QuestionAnswer } from '../liveQuestionStore.js';
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* parkResolver — HITL gate 桥**外环**的 park 决断(REF-CC-032 / SPLIT-12 第三刀,2026-08-02)。
|
|
3
|
+
*
|
|
4
|
+
* 内环(`frameRouter.ts`)带出一个 `GatePark` 之后,这里回答唯一一个问题:**接着读流,还是
|
|
5
|
+
* fail-soft 收场**。三条出路:
|
|
6
|
+
* · 决断成功 ⇒ `reattach`(驱动 attach `runs.events`,`lastEventId` 续传);
|
|
7
|
+
* · 「这个 gate 早就被解决了」(durable re-attach 必然重放已决断的 park)⇒ 同样 `reattach`;
|
|
8
|
+
* · 其余(overlay 缺席 / pending 蒸发 / decide 409/404 / turn 中断 / hop 预算耗尽)⇒ `failsoft`:
|
|
9
|
+
* flush HOLD 的毒化帧 + 原样吐 suspended 终帧(durable 腿无终帧则合成一条可见的 failed)。
|
|
10
|
+
*
|
|
11
|
+
* 🔴 本文件不碰流、不 yield:events 以数组交回驱动。`resolvePark` 的**返回值**就是它的全部对外
|
|
12
|
+
* 效果(台账写入除外,且台账写入全经 `GateLedger` 的动词)—— 于是「禁掉某条真臂」这种变异
|
|
13
|
+
* 在驱动的消费点上必然显形,而不是被本文件自己吞掉。
|
|
14
|
+
*/
|
|
15
|
+
import { putOwnKey } from '../ownKey.js';
|
|
1
16
|
import { DecideTransportRetryExhaustedError, HitlBridge, HitlSafetyError, findPendingForTask, readDecideCurrentPending, readWireErrorCode, } from './hitlBridge.js';
|
|
2
17
|
import { publishQuestionFrame, registerLocalQuestionResponder, hasQuestionOverlay, } from '../liveQuestionStore.js';
|
|
3
18
|
import { hostLog } from '../host.js';
|
|
@@ -146,16 +161,14 @@ export function toAnsweredOutput(questions, answer) {
|
|
|
146
161
|
for (const entry of answer.answers ?? []) {
|
|
147
162
|
const q = questions.find(qq => qq.header === entry.header);
|
|
148
163
|
const key = typeof q?.question === 'string' ? q.question : entry.header;
|
|
149
|
-
// 🔴 0.
|
|
150
|
-
// `
|
|
151
|
-
// `
|
|
152
|
-
// `
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
};
|
|
156
|
-
put(answers, (entry.selected ?? []).join(', '));
|
|
164
|
+
// 🔴 0.68.0 / L-246 B2:落键走**单源** `putOwnKey`(`src/ownKey.ts`)。修前这里是一只内联的
|
|
165
|
+
// 同形实现,与 `adapter/downstream/terminalToSdkResult.ts` 的那一份各写各的 —— 陷阱与取舍
|
|
166
|
+
// 的完整说明现在只在那个模块的头注里一份。`key` 来自 wire(问题正文 / header),字面等于
|
|
167
|
+
// `"__proto__"` 时裸赋值走的是 `Object.prototype` 上那只 accessor:`answers` 那一格(串值)
|
|
168
|
+
// 整条静默丢失,`annotations` 那一格(对象值)还顺手改了表自己的原型。
|
|
169
|
+
putOwnKey(answers, key, (entry.selected ?? []).join(', '));
|
|
157
170
|
if (entry.note)
|
|
158
|
-
|
|
171
|
+
putOwnKey(annotations, key, { notes: entry.note });
|
|
159
172
|
}
|
|
160
173
|
return {
|
|
161
174
|
type: 'ask-user-question',
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
* 🔴 方向纪律:reason/note 只做归因,绝不参与裁决;缺席 ⇒ 现状字节不变。
|
|
79
79
|
*/
|
|
80
80
|
import { type GateCurrentPending, type HitlFailureStage, type HitlSafetyCode, type HitlClientLike } from './hitlBridge.js';
|
|
81
|
+
import { type RuleStoreUnreadableKind } from '../gateVocabulary.js';
|
|
81
82
|
import { type DecideReceiptView } from '../decideReceipt.js';
|
|
82
83
|
import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, DENIAL_LIMIT_KINDS } from '@sema-agent/sdk';
|
|
83
84
|
import type { RuleSuggestion, ToolApprovalRespondAck, PersistedRuleAnchor as SdkPersistedRuleAnchor, RuleOfferMatch as SdkRuleOfferMatch, RuleOfferBatchMember as SdkRuleOfferBatchMember, RuleOfferUncoveredDetail as SdkRuleOfferUncoveredDetail, RuleOfferUncoveredReason as SdkRuleOfferUncoveredReason, AskOrigin as SdkAskOrigin, RuleOffersAbsence as SdkRuleOffersAbsence, DenialLimitKind as SdkDenialLimitKind, DenialLimitFallback as SdkDenialLimitFallback } from '@sema-agent/sdk';
|
|
@@ -708,7 +709,7 @@ export interface ApprovalCardRequest {
|
|
|
708
709
|
* value is removed at the stamp」)⇒ 表外值到不了消费端,真读到就是坏形,渲一句成因就是编事实。
|
|
709
710
|
* 人话两句走**唯一铸点** `ruleStoreUnreadableDetail`(三端零自拼)。
|
|
710
711
|
*/
|
|
711
|
-
ruleStoreUnreadable?:
|
|
712
|
+
ruleStoreUnreadable?: RuleStoreUnreadableKind;
|
|
712
713
|
}
|
|
713
714
|
/**
|
|
714
715
|
* 🔴 **拆缝口** —— 弹「三选卡」并等人的决断。壳 = vendored CC `PermissionRequest`;
|
|
@@ -1016,6 +1016,7 @@ export function readDenialLimitFallback(v) {
|
|
|
1016
1016
|
* 入参签名(typeshape 门的 unknown-出境棘轮 +1),而它的行为由两条腿的端到端素材覆盖。
|
|
1017
1017
|
*/
|
|
1018
1018
|
function readRuleStoreUnreadable(v) {
|
|
1019
|
+
// 🔴 0.68.0 / L-245:谓词已是**型守卫** ⇒ 这里的 `as string` 退役(一处 cast 少一处)。
|
|
1019
1020
|
return isRuleStoreUnreadableKind(v) ? v : undefined;
|
|
1020
1021
|
}
|
|
1021
1022
|
/**
|
package/dist/ownKey.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
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 declare function putOwnKey<T>(table: Record<string, T>, key: string, value: T): void;
|
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
|
+
}
|
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/toolResult.js
CHANGED
|
@@ -125,6 +125,14 @@ export const STRUCTURED_DETAIL_TYPES = new Set([
|
|
|
125
125
|
// 并已登记在 `dist/core/runner/tool-output-projection.js:67` 的 `CC_DETAIL_TYPES` 里)。
|
|
126
126
|
// 病根与 5.20 / 5.43 两次逐字同族:词漏了不会响,只会让那一类卡**永远退回正则解模型面文本**。
|
|
127
127
|
'list-agents',
|
|
128
|
+
// ── core 7.17.0 跟车一词(0.68.0 提货批;engine-vocab ⑤ 段对 7.17.1 实装物直证,红文逐字:
|
|
129
|
+
// 「core 7.17.1:44 项 / 本包 43 项;漏:artifact」)────────────────────────────────────────
|
|
130
|
+
// `artifact` = Artifact 工具的结构化卡(core `dist/tools/artifact/artifact-tool.js` 的
|
|
131
|
+
// `details: { type: "artifact", action: … }` 铸点,七种 action 各一形 + 三条错误形)。
|
|
132
|
+
// 🔴 **可达性有前提**:只有宿主真接了 artifact 席(`RunnerDeps.artifactHost`)那只工具才挂载 ⇒
|
|
133
|
+
// 没接的部署上零帧差异。补它的理由与历史五次逐字同族:词漏了不会响,只会让那一类卡**永远
|
|
134
|
+
// 退回正则解模型面文本**,而任何一层都不会说话。
|
|
135
|
+
'artifact',
|
|
128
136
|
]);
|
|
129
137
|
// 🔴 同批**删三词**(core 5.10.0 BREAKING「幽灵卡」清仓):`multiedit` / `memory-saved` /
|
|
130
138
|
// `memory-recall` —— 全树零铸点(MultiEdit/批量重放铸的是 `type:"edit"` 带 `edits[]`;core
|