@sema-agent/client-core 0.64.2 → 0.65.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +154 -0
- package/README.md +11 -3
- package/dist/adapt/arms.js +125 -7
- package/dist/adapt/ids.d.ts +22 -0
- package/dist/adapt/ids.js +29 -0
- package/dist/adapt/panelTasks.d.ts +24 -2
- package/dist/adapt/panelTasks.js +65 -15
- package/dist/adapt/textStream.js +6 -3
- package/dist/adapt.d.ts +1 -1
- package/dist/adapt.js +3 -0
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +0 -10
- package/dist/adapter/downstream/eventToSdkMessage.js +207 -65
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +4 -4
- package/dist/adapter/downstream/terminalToSdkResult.js +43 -12
- package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +23 -2
- package/dist/adapter/downstream/turnUsageToModelUsage.js +7 -1
- package/dist/adapter/runStream.js +43 -2
- package/dist/adapter/types.d.ts +12 -0
- package/dist/autoModeUnavailable.d.ts +39 -83
- package/dist/autoModeUnavailable.js +58 -111
- package/dist/classifierStatus.d.ts +25 -71
- package/dist/classifierStatus.js +110 -105
- package/dist/decideReceipt.d.ts +117 -0
- package/dist/decideReceipt.js +142 -0
- package/dist/engineErrorCodes.d.ts +32 -0
- package/dist/engineErrorCodes.js +42 -0
- package/dist/fleet/fleetProjection.d.ts +24 -1
- package/dist/fleet/fleetProjection.js +26 -1
- package/dist/fleetAgentPanelProjection.js +6 -1
- package/dist/gateVocabulary.d.ts +9 -1
- package/dist/gateVocabulary.js +46 -4
- package/dist/hitl/askGateWire.js +22 -1
- package/dist/hitl/gateLedger.d.ts +24 -0
- package/dist/hitl/gateLedger.js +8 -0
- package/dist/hitl/hitlBridge.js +14 -2
- package/dist/hitl/parkResolver.d.ts +23 -2
- package/dist/hitl/parkResolver.js +34 -6
- package/dist/hitl/toolApprovalWire.d.ts +12 -1
- package/dist/hitl/toolApprovalWire.js +15 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +16 -6
- package/dist/notifications.js +11 -2
- package/dist/runTerminal.d.ts +48 -0
- package/dist/runTerminal.js +59 -0
- package/dist/seam.d.ts +131 -1
- package/dist/seam.js +22 -0
- package/docs/INTEGRATION-CLIENTS.md +680 -63
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* src/autoModeUnavailable.ts — 「这只 ask 是因为**分类器跑不了**才问人」的事实读器 + 唯一措辞铸点
|
|
3
|
-
* (0.63.0 件⑧;core 7.10.0 #616)。
|
|
3
|
+
* (0.63.0 件⑧;core 7.10.0 #616 —— **0.65.0 随 core 7.12.0 收窄,见下方「熔断族退役」段**)。
|
|
4
4
|
*
|
|
5
5
|
* -- 它答的是哪一问 ---------------------------------------------------------------------------
|
|
6
6
|
* auto 模式下,门会就一只 ask 去咨询分类器。分类器**没跑成**时,引擎在这只 ask 上盖一格
|
|
@@ -10,77 +10,64 @@
|
|
|
10
10
|
* 🔴 **缺席 ≠「分类器跑成了」**:绝大多数 ask 根本没咨询过分类器(部署没武装 auto、或这只 ask 走的
|
|
11
11
|
* 是别的门)。缺席只意味着「这只 ask 上没有这条事实」。
|
|
12
12
|
*
|
|
13
|
-
* -- 🔴
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
13
|
+
* -- 🔴 熔断族退役(0.65.0;core 7.12.0 CHANGELOG「Removed (BREAKING)」)--------------------------
|
|
14
|
+
* core 7.12.0 把 `AUTO_MODE_BREAKER_CAUSES` 与 `WiringManifest.autoMode.breaker` 整族删掉,
|
|
15
|
+
* `AUTO_MODE_UNAVAILABLE_CAUSES` 同批收成 `["error","timeout"]`(`dist/core/auto-mode.d.ts:9` 真字节);
|
|
16
|
+
* server 7.70.0([6927])读面同批收窄,`classifierUnavailable.cause` 不再发 `breaker_open`。
|
|
17
|
+
* ⇒ 本模块把 `AUTO_MODE_BREAKER_CAUSES` / `ClassifierBreakerView` / `classifierBreakerOf` 与
|
|
18
|
+
* `breaker_open` 这个词**干净切**(clean-cut,不留别名、不留兼容读):留一个读不到的读器只会让
|
|
19
|
+
* 三端继续为一件上游已经不发的事实写渲染分支,而那正是「校旧物」的门自己要拦的形。
|
|
20
|
+
* 🔴 **`cause` 的开集读一个字节不动**:一台比本端**新**的引擎发一个新成因词时照收(见
|
|
21
|
+
* {@link classifierUnavailableOf});退役掉的只是本端**认得**的那张表里的一个成员 —— 旧引擎真发
|
|
22
|
+
* `breaker_open` 时它照旧过境,只是走 {@link classifierUnavailableDetail} 的兜底句
|
|
23
|
+
* (「这个词比这一端新/旧」那一类),不再冒充一句本端自铸的解释。
|
|
24
|
+
*
|
|
25
|
+
* -- 🔴 判据轴与成因轴不是一张表 --------------------------------------------------------------
|
|
26
|
+
* · {@link AUTO_MODE_UNAVAILABLE_CAUSES}(`error` / `timeout`)—— 「这一轮分类**为什么没跑成**」。
|
|
27
|
+
* 这是 `classifierUnavailable.cause` 的值域(词表属主 = core)。
|
|
28
|
+
* · core `AutoModeVerdict` 的**判据轴**另有一个 `parse_error` 臂 —— 分类器**跑了并且答了**,
|
|
29
|
+
* 只是答在契约之外(`dist/core/auto-mode.d.ts:29-32` 逐字:「The model responded but not in the
|
|
30
|
+
* `<block>…` contract shape. Handled as a BLOCK …」)。它**一个字节都不 stamp** 到
|
|
31
|
+
* `classifierUnavailable` 上,那是**另一句话**。
|
|
32
|
+
* 🔴 本读器因此把 {@link NEVER_STAMPED_CAUSES}(今天 = `{parse_error}`)判**缺席** —— 把一个判据词
|
|
33
|
+
* 读成「没跑成」的成因,就是替引擎编一件它明说没发生的事。0.63.0 起的黑盒判据 G-19 钉的正是这
|
|
34
|
+
* 一条,退役熔断族**没有改动它的行为**(修前这一格由「熔断轴 − 不可用轴」的差集派生,而差集的
|
|
35
|
+
* 右操作数随熔断表一起没了;排除的**理由**从来就不在熔断轴上,现按理由的真出处直写)。
|
|
26
36
|
*
|
|
27
37
|
* -- 为什么是镜像而不是 import ---------------------------------------------------------------
|
|
28
|
-
*
|
|
29
|
-
* 全树零命中),唯一的出处是 `@sema-agent/core` 的 `dist/core/auto-mode.js` / `tool-policy.d.ts
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* `
|
|
38
|
+
* 这张表与 `classifierUnavailable` 的型面在 sdk 8.8.0 与 agent-types 上**都还没有**(亲验:两棵树
|
|
39
|
+
* 全树零命中),唯一的出处是 `@sema-agent/core` 的 `dist/core/auto-mode.js` / `tool-policy.d.ts`。
|
|
40
|
+
* 而 core **不是本包消费者的依赖**(既非 peer 也非 runtime dep),本包的 `.d.ts` 一旦引用它,装了
|
|
41
|
+
* 本包却没装 core 的下游会当场编译不过。⇒ 与 `engineNoticeCodes.ts` / `toolResult.ts` /
|
|
42
|
+
* `retryStatus.ts` 同一条处置:**按真字节镜像,把代价交给门** ——
|
|
33
43
|
* `run-auto-mode-unavailable-test.mjs` 对**实装 devDep core** 的产物逐词双向对账,core 一动这里就先红。
|
|
34
|
-
* 🔴 **候上游导出即换**:sdk
|
|
35
|
-
*
|
|
36
|
-
* -- 0.64.0 件② 加员:**会话轴**的窄读 --------------------------------------------------------
|
|
37
|
-
* {@link classifierBreakerOf} 读的是同一条熔断轴的**另一端**:不是「这一轮为什么没跑成」,而是
|
|
38
|
-
* 「这个**会话**的闩什么时候合上的、因为什么、连着失败了几次」(core 7.10.0 `AutoModeBreakerTrip`,
|
|
39
|
-
* 挂在 `WiringManifest.autoMode.breaker` 上;**server ≥7.69.0 才投**)。
|
|
40
|
-
* 🔴 **它是历史,不是当前闩状态**:core 顶注逐字「a trip names one leg … the ledger carries the most
|
|
41
|
-
* recent one forward per session」—— 同一会话的后一条腿完全可以重新武装。判「分类器现在跑不跑」
|
|
42
|
-
* 的量是那条腿的 `armed`,不是这条记录在不在(判定在 `classifierStatus.ts`)。
|
|
43
|
-
* 🔴 **缺席有四种成因,不可分辨**:从没熔断过 / 账本(有界 FIFO)把它淘汰了 / 这一次是 standalone
|
|
44
|
-
* prepare(账本没接上)/ 老引擎不投。所以缺席只能读成「**没有可用的熔断记录**」——
|
|
45
|
-
* 既不是「没熔断过」,也不是「一定是老引擎」。
|
|
46
|
-
* 它落在本文件是因为
|
|
47
|
-
* {@link AUTO_MODE_BREAKER_CAUSES} 本来就在这里 —— 表与读它的窄读同居,而不是隔一个文件遥指。
|
|
48
|
-
* 🔴 它同时是那一处的**唯一**窄读:`wiring_manifest` 的投影臂与 `classifierStatus.ts` 的状态读器
|
|
49
|
-
* 共用它。本文件是**零 import 的纯叶**,所以投影臂那条内核闭包只多一件叶子(见
|
|
50
|
-
* `run-client-core-portability-test.mjs` 的内核上限记账)。
|
|
51
|
-
* 🔴 **退役条款**:上游若改采 CC 形而把 `breaker` 这一键整只退役(它是 sema 在 CC 之外自己加的
|
|
52
|
-
* 一格),本读器**零改** —— 它的**缺席臂**当天就是正解:读不到就是没有,状态面自然回落到
|
|
53
|
-
* 本轮轴与「可用」。退役一个 additive 键不该逼三端各改一次。
|
|
44
|
+
* 🔴 **候上游导出即换**:sdk 哪天镜像了这张表与那一格,本模块的表应当整只退役改成从 sdk 取。
|
|
54
45
|
*/
|
|
55
46
|
/**
|
|
56
|
-
* 一轮分类**为什么没跑成**(core `AUTO_MODE_UNAVAILABLE_CAUSES
|
|
47
|
+
* 一轮分类**为什么没跑成**(core `AUTO_MODE_UNAVAILABLE_CAUSES`;逐词逐序镜像,core 7.12.0 起两词)。
|
|
57
48
|
* · `error` —— 模型那条腿抛了/被拒(分类时的路由失败也读在这里:派生路由的前置在任何 decide
|
|
58
49
|
* 之前就回落了,所以没有单独的词);
|
|
59
|
-
* · `timeout` ——
|
|
60
|
-
* · `breaker_open` —— 本会话的熔断闩**已经**合上,这一轮被短路,压根没发出去。
|
|
61
|
-
|
|
62
|
-
* 🔴 形制:`Object.freeze` 的数组,**不是**只在类型面只读的 `readonly T[]` —— 后者一行 `.splice()`
|
|
63
|
-
* 就能改,而公面消费者拿到的正是这个实例(本仓已定谳的病形,同 `RESUME_RETRY_LATER_CODES`)。
|
|
64
|
-
*/
|
|
65
|
-
export const AUTO_MODE_UNAVAILABLE_CAUSES = Object.freeze(['error', 'timeout', 'breaker_open']);
|
|
66
|
-
/**
|
|
67
|
-
* **熔断闩为什么合上**(core `AUTO_MODE_BREAKER_CAUSES`;逐词逐序镜像)——**另一条轴**,
|
|
68
|
-
* 与上面那张表刻意不合并(见模块顶注)。`parse_error` 是它的独占成员。
|
|
50
|
+
* · `timeout` —— 往返上限到了。
|
|
69
51
|
|
|
70
52
|
* 🔴 形制:`Object.freeze` 的数组,**不是**只在类型面只读的 `readonly T[]` —— 后者一行 `.splice()`
|
|
71
53
|
* 就能改,而公面消费者拿到的正是这个实例(本仓已定谳的病形,同 `RESUME_RETRY_LATER_CODES`)。
|
|
72
54
|
*/
|
|
73
|
-
export const
|
|
55
|
+
export const AUTO_MODE_UNAVAILABLE_CAUSES = Object.freeze(['error', 'timeout']);
|
|
74
56
|
/**
|
|
75
|
-
*
|
|
76
|
-
* `
|
|
57
|
+
* **判据轴独占、且 core 明说「不 stamp」的成因词**(0.65.0 起是本文件唯一的排除集)——今天恰是
|
|
58
|
+
* `{parse_error}`。
|
|
77
59
|
*
|
|
78
|
-
* 🔴
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
60
|
+
* 🔴 **它的出处是理由,不是另一张表**:core `AutoModeVerdict` 的 `parse_error` 臂逐字说的是
|
|
61
|
+
* 「分类器跑了并且答了,只是答在契约之外,按 BLOCK 处置」——一个**有裁决**的回合,而
|
|
62
|
+
* `classifierUnavailable` 这一格答的是「这一轮**没跑成**」。两句话互斥,所以这个词到达这一格
|
|
63
|
+
* 时只能是坏数据,读它就是替引擎编事实。
|
|
64
|
+
* ⚠️ **形制变更的如实登记**(0.65.0):修前这只集合是 `AUTO_MODE_BREAKER_CAUSES` 减
|
|
65
|
+
* `AUTO_MODE_UNAVAILABLE_CAUSES` 的**差集**。core 7.12.0 删掉熔断表之后那条派生的右操作数不存在
|
|
66
|
+
* 了 —— 而排除的理由从头到尾都不是「它在熔断轴上」,是上面那一条。所以这里按理由的真出处直写
|
|
67
|
+
* 一张单员表,而不是为了保住「派生」的形去挽留一张上游已经删掉的表。core 哪天再给判据轴加一个
|
|
68
|
+
* 「答了但不算数」的臂,加员与它的一句人话同批落在本文件,门会先红。
|
|
82
69
|
*/
|
|
83
|
-
const
|
|
70
|
+
const NEVER_STAMPED_CAUSES = new Set(['parse_error']);
|
|
84
71
|
/**
|
|
85
72
|
* 一只 ask(或一条 durable park 行的 `tool_approval` 载荷)→ 「分类器跑不了」的事实;
|
|
86
73
|
* 没有这条事实 / 形坏 ⇒ `undefined`,绝不抛出。
|
|
@@ -88,7 +75,7 @@ const BREAKER_ONLY = new Set(AUTO_MODE_BREAKER_CAUSES.filter((c) => !AUTO_MODE_U
|
|
|
88
75
|
* 🔴 **两处同一只读器**:`AskRequest.classifierUnavailable` 与
|
|
89
76
|
* `PendingAction.tool_approval.classifierUnavailable`(durable park 行的孪生位)**键路同形**,
|
|
90
77
|
* 所以一只读器吃两处 —— 各写一份就是两份台账各漂各的,本包一贯要根治的形。
|
|
91
|
-
* 🔴 **`cause` 按开集读 +
|
|
78
|
+
* 🔴 **`cause` 按开集读 + 一条有出处的排除**(**0.64.2 订正,行为面**;修前是「unavailable 闭集」):
|
|
92
79
|
* · **非空串即收** —— 词表的属主是 core,而 server 侧除了「非空串」之外**不做词表校验**
|
|
93
80
|
* (engine fixture `approval-card.js:240` 的 `z.string().min(1)`)。在这里抄一份闭集表,只会在
|
|
94
81
|
* core 加词那天把一个**合法**值判没,而丢掉的正是「这次不可用是**新出现的那一类**」这条信息
|
|
@@ -96,8 +83,10 @@ const BREAKER_ONLY = new Set(AUTO_MODE_BREAKER_CAUSES.filter((c) => !AUTO_MODE_U
|
|
|
96
83
|
* 修前那条路是可复现的:一台比本端新的引擎发一个新成因词 ⇒ 卡上那一行**整段消失**,而
|
|
97
84
|
* {@link classifierUnavailableDetail} 早就为这一形备好了兜底句(「a word newer than this client」)
|
|
98
85
|
* —— 那句话在修前**永远不可达**,这本身就是判据写错了的证据。
|
|
99
|
-
*
|
|
100
|
-
*
|
|
86
|
+
* ⚠️ 0.65.0 起 `breaker_open` 也走这一条(core 7.12.0 已删该词)—— **旧引擎的合法帧照旧过境**,
|
|
87
|
+
* 只是本端不再为它自铸一句解释。
|
|
88
|
+
* · **{@link NEVER_STAMPED_CAUSES} 里的词仍判缺席** —— 今天只有 `parse_error`。这不是「表外词一律拒」,
|
|
89
|
+
* 而是一条**有出处的排除**:core 的判据轴逐字说它「跑了并且答了」,读它就是替引擎编一件
|
|
101
90
|
* 它明说没发生的事。0.63.0 起的黑盒判据 G-19 钉的正是这一条,行为**一字未变**。
|
|
102
91
|
* 🔴 **只交 `cause` 一格**:顺手把整只 ask 的别的键带出来会长成第二份 ask 读面。
|
|
103
92
|
* 🔴 **端不许在自己那一侧再补一张闭集表**:未知词的正解是渲兜底句(措辞铸点已经有),不是不渲。
|
|
@@ -111,20 +100,22 @@ export function classifierUnavailableOf(ask) {
|
|
|
111
100
|
const cause = raw.cause;
|
|
112
101
|
if (typeof cause !== 'string' || cause === '')
|
|
113
102
|
return undefined;
|
|
114
|
-
if (
|
|
103
|
+
if (NEVER_STAMPED_CAUSES.has(cause))
|
|
115
104
|
return undefined;
|
|
116
105
|
return { cause };
|
|
117
106
|
}
|
|
118
107
|
/**
|
|
119
|
-
*
|
|
120
|
-
* 🔴 `parse_error`
|
|
108
|
+
* 逐成因一句人话。**三句**刻意逐字互异 —— 对用户是三条不同的下一步。
|
|
109
|
+
* 🔴 `parse_error` 那一句说的是「分类器**跑了、答了**,只是答在契约之外」,与另外两句的
|
|
121
110
|
* 「没跑成」是两回事;它**永远不会**从 {@link classifierUnavailableOf} 出来(那一格按
|
|
122
|
-
*
|
|
111
|
+
* {@link NEVER_STAMPED_CAUSES} 排除),放在这里是给**渲判据面**的消费端用同一个铸点。
|
|
112
|
+
* 🔴 **`breaker_open` 那一句 0.65.0 随熔断族退役**(core 7.12.0 已删该词):旧引擎发来的
|
|
113
|
+
* `breaker_open` 从此走下面的兜底句,原样带上那个词 —— 编一句本端自铸的熔断解释,就是在描述
|
|
114
|
+
* 一个这一代引擎里已经不存在的机制。
|
|
123
115
|
*/
|
|
124
116
|
const CAUSE_SENTENCES = Object.freeze({
|
|
125
117
|
error: 'asked because the auto-mode classifier could not run (it errored)',
|
|
126
118
|
timeout: 'asked because the auto-mode classifier could not run (it timed out)',
|
|
127
|
-
breaker_open: 'asked because the auto-mode classifier is latched off for this session (its breaker tripped), so this round was never sent',
|
|
128
119
|
parse_error: 'the auto-mode classifier answered outside its contract (its reply could not be parsed)',
|
|
129
120
|
});
|
|
130
121
|
/**
|
|
@@ -133,7 +124,7 @@ const CAUSE_SENTENCES = Object.freeze({
|
|
|
133
124
|
* 🔴 **按自有属性查表**(与本包其余措辞铸点同一条纪律):`Object.freeze` 不移除原型,裸下标会让
|
|
134
125
|
* 一个来自 wire 的 `constructor` / `toString` 命中 `Object.prototype` 上的**函数**并被当成一句话。
|
|
135
126
|
* 🔴 表外词 / 坏值 ⇒ 一句**兜底**:仍然告诉用户「这只 ask 是分类器那条腿引出来的」,但**不冒充**
|
|
136
|
-
*
|
|
127
|
+
* 三句里的任何一句(成因读不懂 ≠ 成因是别的什么);原样带上那个词供运维追问上游。
|
|
137
128
|
*/
|
|
138
129
|
export function classifierUnavailableDetail(cause) {
|
|
139
130
|
const known = typeof cause === 'string' && Object.hasOwn(CAUSE_SENTENCES, cause) ? CAUSE_SENTENCES[cause] : undefined;
|
|
@@ -142,47 +133,3 @@ export function classifierUnavailableDetail(cause) {
|
|
|
142
133
|
const word = typeof cause === 'string' && cause.length > 0 ? cause : '(none)';
|
|
143
134
|
return `asked because of the auto-mode classifier; its reported cause ${word} is a word newer than this client`;
|
|
144
135
|
}
|
|
145
|
-
/** JS `Date` 能表示的绝对值上限(±8.64e15 ms);越界的数会让 `toISOString()` 抛 `RangeError`。 */
|
|
146
|
-
const MAX_EPOCH_MS = 8.64e15;
|
|
147
|
-
/**
|
|
148
|
-
* `wiring_manifest.autoMode` → 熔断记录;没有这条事实 / 形坏 ⇒ `undefined`,绝不抛。
|
|
149
|
-
*
|
|
150
|
-
* 🔴 **三键承重、一键可缺**:`openedAtMs` / `lastCause` / `failures` 是那句话的承重物
|
|
151
|
-
* (「什么时候、因为什么、几次」),缺任一 ⇒ **整段缺席**(半句没有出口的话不如不渲);
|
|
152
|
-
* `runId` 不进那句话 ⇒ 缺席只丢它自己。这与本包 `projectMcpSection` 的「必需两座 + 其余可缺」
|
|
153
|
-
* 同一条判据。
|
|
154
|
-
* 🔴 **`lastCause` 开集读**:表外词照收 —— 词的属主在 core,抄一张表在这里只会把 core 加的新词
|
|
155
|
-
* 吞成缺席(与 `WiringManifestMcpEntry.errorCode` 同规)。消费端按具名词写的 `switch` 必须带
|
|
156
|
-
* `default` 臂;本模块的措辞铸点自带兜底句。
|
|
157
|
-
* 🔴 **按自有属性读**:一只来自 wire 的对象可以带原型;`Object.create({openedAtMs:1,…})` 上那些
|
|
158
|
-
* 值不是这条帧带来的事实。
|
|
159
|
-
*/
|
|
160
|
-
export function classifierBreakerOf(autoMode) {
|
|
161
|
-
if (typeof autoMode !== 'object' || autoMode === null || Array.isArray(autoMode))
|
|
162
|
-
return undefined;
|
|
163
|
-
if (!Object.hasOwn(autoMode, 'breaker'))
|
|
164
|
-
return undefined;
|
|
165
|
-
const raw = autoMode.breaker;
|
|
166
|
-
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
167
|
-
return undefined;
|
|
168
|
-
const r = raw;
|
|
169
|
-
const openedAtMs = Object.hasOwn(r, 'openedAtMs') ? r.openedAtMs : undefined;
|
|
170
|
-
if (typeof openedAtMs !== 'number' || !Number.isFinite(openedAtMs))
|
|
171
|
-
return undefined;
|
|
172
|
-
// 🔴 见模块顶注:越界的数会让渲染路径当场抛 `RangeError`;负数不是一个「闩合上了」的读数。
|
|
173
|
-
if (openedAtMs < 0 || openedAtMs > MAX_EPOCH_MS)
|
|
174
|
-
return undefined;
|
|
175
|
-
const lastCause = Object.hasOwn(r, 'lastCause') ? r.lastCause : undefined;
|
|
176
|
-
if (typeof lastCause !== 'string' || lastCause.length === 0)
|
|
177
|
-
return undefined;
|
|
178
|
-
const failures = Object.hasOwn(r, 'failures') ? r.failures : undefined;
|
|
179
|
-
if (typeof failures !== 'number' || !Number.isInteger(failures) || failures < 1)
|
|
180
|
-
return undefined;
|
|
181
|
-
const runId = Object.hasOwn(r, 'runId') ? r.runId : undefined;
|
|
182
|
-
return {
|
|
183
|
-
openedAtMs,
|
|
184
|
-
lastCause,
|
|
185
|
-
failures,
|
|
186
|
-
...(typeof runId === 'string' && runId.length > 0 ? { runId } : {}),
|
|
187
|
-
};
|
|
188
|
-
}
|
|
@@ -1,63 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* 分类器的三态(0.65.0:熔断族退役,`breaker_open` 随之删除;同批 `armed` 与 `available` 拆成
|
|
3
|
+
* 两个词)。**「没武装」仍然不在里面** —— 那一问由 `wiring_manifest.autoMode.reason` 那一格
|
|
4
|
+
* 自己回答(六词闭集),在这里再答一遍会长出第二份台账。
|
|
5
|
+
*
|
|
6
|
+
* 🔴 **0.65.0 / B-071:`armed` 与 `available` 拆成两个词**(此前只有后者,`armed===true` 直接
|
|
7
|
+
* 判 `available`)。core 的 `WiringManifest.autoMode` 顶注把这两件事**明确分开**了:
|
|
8
|
+
* · `armed` ⇔ `reason === "armed"` —— 「**这条腿**铸出了分类器 decider」
|
|
9
|
+
* (逐字 `the classifier decider was minted for this leg`),一个**装配期**事实;
|
|
10
|
+
* · 而 `The classifier's availability is a per-CALL fact`(逐字;下一句还写明「an
|
|
11
|
+
* unavailable round is a deny that says so, and the next round is classified afresh」)。
|
|
12
|
+
* ⇒ 拿 `armed` 去回答「可用吗」= 用装配期读数回答每次调用的问题。武装了的分类器完全可能在
|
|
13
|
+
* 某一轮跑不了(那一轮是一条 deny),下一轮又好了 —— 这正是 core 说「没有会话级 breaker 面」
|
|
14
|
+
* 的理由(0.65.0 起它连那一格也一并删了)。措辞面跟着分两句:「武装了」与「这一次真的跑了」
|
|
15
|
+
* 对用户是两条不同的下一步。
|
|
16
|
+
*
|
|
17
|
+
* 词序 = 判据强度递增的反向读法:`armed`(装配期)→ `available`(本轮肯定事实)→ 坏消息。
|
|
4
18
|
*
|
|
5
|
-
* -- 它答的是哪一问(与卡面那一问**不是同一问**)----------------------------------------------
|
|
6
|
-
* `autoModeUnavailable.ts` 答的是**卡面**那一问:「这一刻**为什么在问我**」——一次性的、就这只 ask。
|
|
7
|
-
* 本模块答的是**状态面**那一问:「这个**会话**上,auto 分类器现在是什么状态」——诊断行、模型设置页、
|
|
8
|
-
* 权限卡的状态栏读的是它。两问的下一步不同,所以句子也不同(门里有一条反向钉守着两张面的句子零重合)。
|
|
9
|
-
*
|
|
10
|
-
* -- 两处窄读,一只读器 ----------------------------------------------------------------------
|
|
11
|
-
* · **会话轴**:`wiring_manifest.autoMode.breaker`(core `AutoModeBreakerTrip`;server ≥7.69.0 才投)
|
|
12
|
-
* —— 「这个会话的闩**已经**合上了,是什么时候、因为什么、连着失败了几次」。
|
|
13
|
-
* · **本轮轴**:一只 ask 上的 `classifierUnavailable.cause` —— 复用 0.63.0 已有的
|
|
14
|
-
* {@link classifierUnavailableOf},**不重铸**。
|
|
15
|
-
* `classifierBreakerOf` 是会话轴那一处的**唯一**窄读:`wiring_manifest` 的投影臂与本模块的
|
|
16
|
-
* 状态读器共用它。各写一份就是两份台账各漂各的(本包一贯要根治的形)。
|
|
17
|
-
* 🔴 **它的物理位置在 `autoModeUnavailable.ts` 而不是这里**,理由是**门**:`wiring_manifest` 的
|
|
18
|
-
* 投影臂在**内核闭包**里,而那道闭包的棘轮判据逐字是「新进来的这一件自己有没有 import ——
|
|
19
|
-
* 有,就说明它不是叶子,那种 +1 正是本棘轮要拦的东西」。本模块有值级 import(它复用本轮轴的
|
|
20
|
-
* 读器,刻意不另铸第二只),所以**本模块自己不该进内核**;而那只窄读是零 import 的纯判据,
|
|
21
|
-
* 放进已经在闭包里的那张**熔断轴表**的同一个文件里,内核只多一件叶子。归属上也更顺:
|
|
22
|
-
* `AUTO_MODE_BREAKER_CAUSES` 本来就在那里,窄读读的正是那条轴。
|
|
23
|
-
*
|
|
24
|
-
* -- 🔴 「有熔断记录」与 `armed`/`reason` 之间**没有**互证关系,别去补一条 ---------------------
|
|
25
|
-
* 直觉会想写「有 breaker ⇒ reason 应当是 `latch_open`」。那条互证是**错的**,而且会把真读数整段判没:
|
|
26
|
-
* core 的 arm 词表头注逐字写着 —— 闩合上之后,**被闩住的那条腿不再把 auto 意图传给后续腿**,于是
|
|
27
|
-
* 后续腿的 arm 判读走的是 `no_intent`;`latch_open` 那个词留在词表里只是为了让「中途重读」的消费者
|
|
28
|
-
* 在闭集上完备,而**今天没有任何东西铸它**。所以一份 `{armed:false, reason:"no_intent", breaker:{…}}`
|
|
29
|
-
* 是**最常见**的合法形,不是矛盾。
|
|
30
|
-
*
|
|
31
|
-
* -- 🔴 优先序承重:本轮事实 > 这条腿的 `armed` > 历史熔断记录 -------------------------------
|
|
32
|
-
* 判据锚在**真正决定「分类器现在跑不跑」的量**上,而那个量是**这条腿的 `armed`**,不是账本里有没有
|
|
33
|
-
* 一条旧记录:
|
|
34
|
-
* · **本轮事实最先**(`classifierUnavailable`)—— 它说的是眼前这一只 ask,最具体也最新;
|
|
35
|
-
* · **其次是 `armed`** —— core 顶注逐字:「A decider is minted per run (its latch is a RUN fact),
|
|
36
|
-
* so a trip names one leg; the ledger below carries the most recent one forward per session」。
|
|
37
|
-
* ⇒ 同一会话的**后一条腿**完全可以重新武装(新 decider 的闩由构造关着),而账本仍把那次旧 trip
|
|
38
|
-
* 带着。`armed === true` 时判 `breaker_open`,就是把一个**正在放行**的分类器显示成已经关掉了
|
|
39
|
-
* (异源对抗复审 r2 抓出的真病);
|
|
40
|
-
* · **最后才是历史记录** —— 没武装、而账本里有一条 trip,那条 trip 就是「为什么没武装」的最好解释。
|
|
41
|
-
* 🔴 **历史记录不因为被压下去就丢掉**:任何一态上 {@link ClassifierStatusView.breaker} 都照带,
|
|
42
|
-
* 端可以在「在跑」那一行后面补一句「这个会话上曾经熔断过」——那是**两条不同的下一步**,所以
|
|
43
|
-
* 措辞铸点为它单出一句。
|
|
44
|
-
*
|
|
45
|
-
* -- 🔴 时刻一律 UTC ISO,不猜用户时区 --------------------------------------------------------
|
|
46
|
-
* 时区是宿主的事(它知道用户的 locale,本包不知道)。一个猜错的本地时刻比一个明确的 UTC 时刻更难
|
|
47
|
-
* 排查 —— 运维拿着它去对引擎日志,而引擎日志也是 UTC。
|
|
48
|
-
* 🔴 `openedAtMs` 是 **wire 来的数**:一个 `1e20` 会让 `toISOString()` 当场抛 `RangeError`,那是
|
|
49
|
-
* **整屏崩**不是一行渲不出([render-path-must-not-throw])。窄读因此按 Date 的真实值域收。
|
|
50
|
-
*
|
|
51
|
-
* -- 退役条款 ---------------------------------------------------------------------------------
|
|
52
|
-
* 上游若改采 CC 形而把 `breaker` 这一键退役(它今天是 sema 在 CC 之外自己加的一格),本模块**零改**:
|
|
53
|
-
* {@link classifierBreakerOf} 的**缺席臂**当天就是正解 —— 读不到就是没有,状态面自然回落到本轮轴
|
|
54
|
-
* 与 `available`。这条设计是刻意的:退役一个 additive 键不该逼三端各改一次。
|
|
55
|
-
*/
|
|
56
|
-
import { type ClassifierBreakerView } from './autoModeUnavailable.js';
|
|
57
|
-
/**
|
|
58
|
-
* 分类器的三态。**刻意只有三个** —— 「没武装」不是分类器的健康状态,那一问由
|
|
59
|
-
* `wiring_manifest.autoMode.reason` 那一格自己回答(六词闭集),在这里再答一遍会长出第二份台账。
|
|
60
|
-
|
|
61
19
|
* 🔴 形制:`Object.freeze` 的数组,**不是**只在类型面只读的 `readonly T[]`(同
|
|
62
20
|
* `AUTO_MODE_UNAVAILABLE_CAUSES` 的理由)。
|
|
63
21
|
*/
|
|
@@ -66,9 +24,7 @@ export declare const CLASSIFIER_STATUS_STATES: readonly string[];
|
|
|
66
24
|
export interface ClassifierStatusView {
|
|
67
25
|
/** {@link CLASSIFIER_STATUS_STATES} 之一。 */
|
|
68
26
|
state: string;
|
|
69
|
-
/** `
|
|
70
|
-
breaker?: ClassifierBreakerView;
|
|
71
|
-
/** `unavailable_this_round` 上在场:本轮没跑成的成因(`AUTO_MODE_UNAVAILABLE_CAUSES` 之一)。 */
|
|
27
|
+
/** `unavailable_this_round` 上在场:本轮没跑成的成因(**开集**:词表属主在 core)。 */
|
|
72
28
|
cause?: string;
|
|
73
29
|
}
|
|
74
30
|
/**
|
|
@@ -77,14 +33,13 @@ export interface ClassifierStatusView {
|
|
|
77
33
|
* @param autoMode `wiring_manifest` 的 `autoMode` 段(投影后的或原始的都吃;本函数自己窄读)
|
|
78
34
|
* @param ask 可选:**本轮**那只 ask(或 durable park 行的 `tool_approval` 载荷)
|
|
79
35
|
*
|
|
80
|
-
* 优先序(承重,理由见模块顶注):**本轮事实 > 这条腿的 `armed
|
|
81
|
-
*
|
|
82
|
-
*
|
|
36
|
+
* 优先序(承重,理由见模块顶注):**本轮事实(否定 + 肯定)> 这条腿的 `armed`**——先看 `ask` 上的
|
|
37
|
+
* 本轮不可用事实,再看 `ask` 上那条「分类器真的跑过」的肯定事实,最后才看这条腿武没武装。
|
|
38
|
+
* `ask` 带本轮事实时,`autoMode` 段缺席也照样答得出(两条本轮臂都不依赖那一段)。
|
|
83
39
|
*
|
|
84
40
|
* 🔴 **`undefined` 是一个诚实的答案,不是一个坏路径**:
|
|
85
41
|
* · `autoMode` 段缺席(老 mint / 外部 derive)⇒ 这一端**没有**分类器的健康读数;
|
|
86
|
-
* ·
|
|
87
|
-
* 它的健康无从谈起。
|
|
42
|
+
* · 段在、但没武装,而且没有本轮事实 ⇒ 分类器**压根没参与**这条腿,它的健康无从谈起。
|
|
88
43
|
* 两种情形都**绝不**折成 `available`(那是把「没报」渲成「一切正常」)。
|
|
89
44
|
* ⚠️ 「没武装」本身仍是一条要渲的事实 —— 但它的出处是 `autoMode.reason`,不是本读器。
|
|
90
45
|
*/
|
|
@@ -92,10 +47,9 @@ export declare function classifierStatusOf(autoMode: unknown, ask?: unknown): Cl
|
|
|
92
47
|
/**
|
|
93
48
|
* 一次状态读数 → 一句人话。**唯一措辞铸点**(三端共用;端零自拼)。
|
|
94
49
|
*
|
|
95
|
-
* 三句逐字互异,且与 `classifierUnavailableDetail`
|
|
96
|
-
* 🔴
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* 复核**那只记录(走同一只窄读),读不出就走「没被告知何时因何」那一句,绝不半渲一个假读数。
|
|
50
|
+
* 三句逐字互异,且与 `classifierUnavailableDetail` 的三句**零重合**(两张面答两个问题)。
|
|
51
|
+
* 🔴 **表外态不抛**:型面挡不住 wire,也挡不住一份从持久态恢复回来的视图 —— 一个
|
|
52
|
+
* `{state:'breaker_open'}`(0.65.0 退役掉的那个词,可能来自旧持久态)必须渲出一句诚实的话,
|
|
53
|
+
* 而不是把整屏带崩,也不冒充三句里的任何一句。
|
|
100
54
|
*/
|
|
101
55
|
export declare function classifierStatusDetail(view: ClassifierStatusView): string;
|