@sema-agent/client-core 0.74.5 → 0.75.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 +23 -0
- package/README.md +3 -2
- package/dist/adapt/arms.js +31 -0
- package/dist/adapter/downstream/eventToSdkMessage.js +40 -11
- package/dist/deviceExecutorManagementCapability.d.ts +1 -1
- package/dist/deviceExecutorManagementCapability.js +1 -1
- package/dist/engineAgentPanelStore.d.ts +6 -1
- package/dist/engineAgentPanelStore.js +75 -18
- package/dist/fleetAgentPanelProjection.js +41 -14
- package/dist/panelRunningHistory.d.ts +22 -2
- package/dist/panelRunningHistory.js +65 -3
- package/dist/seam.d.ts +16 -1
- package/dist/seam.js +5 -0
- package/docs/INTEGRATION-CLIENTS.md +56 -4
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -49,6 +49,29 @@
|
|
|
49
49
|
> 挡住 ⇒ 本批把它机械化——④a0 对 `pending` 行**要求段头已是日期形**(`(未发布)` 直接红),阶段一
|
|
50
50
|
> commit 漏转在发布前就红,不再靠人记。
|
|
51
51
|
|
|
52
|
+
## 0.75.0(2026-09-20)
|
|
53
|
+
|
|
54
|
+
> 主题:**压缩的非 compacted 结局上 chrome 面**(CC-89;此前三端都看不见压缩失败)+ **peer sdk 地板 `>=9.8.1`**(CC-81)+ **短命子代的最终用量不再丢**(0.74.5 首见即终态零事件的代价面,外部复验读数)。**minor**:① 新内部臂 `compaction_outcome` 进 `INTERNAL_SDK_ARM_TYPES` —— 自建 print / stream-json 出口的端**必须**先给它表态(吞或转),否则它会顺着兜底透传成越界帧;② peer 地板抬升。型面 additive(`ChromeEvent` +1 臂 `CompactionOutcomeChromeEvent`;值导出零增)。接入面 §74。
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- **chrome 臂 `compaction_outcome`(CC-89)**:引擎的 `compaction_outcome` 帧(一次压缩**没有**以 compacted 收尾:被任务终态抢先而作废、熔断开着而失败等)此前在投影口落 `not_in_slice`,包内与三端零消费者 —— 压缩失败对用户不可见。现在:投影口出内部臂 `{type:'compaction_outcome', outcome, trigger?, reason?, …identity}`,适配层出 `ChromeEvent{kind:'compaction_outcome', laneProof, outcome, trigger?, reason?, eventId?}`,转录面零行(CC 转录里只有成功压缩的 `compact_boundary`,不替它编消息)。`outcome` / `trigger` 是引擎开集原词,逐字不折;`trigger` / `reason` 非空串才在场;`outcome` 缺席 / 非串 / 空串 ⇒ malformed。lane 如实:`parentToolCallId` 在场 ⇒ `laneProof.lane === 'subagent'`;只能靠 `sourceTaskId` / `bgAgentId` 归因的帧不发(没有诚实的 lane 可挂,不落到主会话名下;KNOWN-LIMITS KL-22)。臂表 `required:false`。
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- **短命子代的最终用量不再被「首见即终态零事件」吞掉(0.74.5 CC-86 的代价面;外部复验 W2 读数)**:子代在面板两拍之间起步并结束、从没投影过 running 时,通知车道的 `end` 已递达(消费端建了行、状态 ended),终态 `fleet-row` 却被当成历史行零事件 ⇒ 行在、`totalTokens` / `toolUses` 两位空。「首见」的判据从「本进程没发布过 running」改成「消费端没有这一行」= 没发布过 running **也没递达过 end**:历史叶加第二本账(漏斗里任何 lane 的当代 `end` 递达后记 ended{周期身份},有界 4096)。结过的行再来终态帧:同代 / 判不出代际 ⇒ 恰一条 `fleet-row` 交最终用量、**不再第二次 `end`**;可证更新的一代(结过之后复活又结束)⇒ 照发 `fleet-row` + `end`。反序(终态 `fleet-row` 先到、`end` 后到)⇒ 终态行先缓住(有界 4096),`end` 到漏斗时**先于一切身份归一**放出(放出的行帧登记的钥匙 / 所有权,后面的 `end` 归一必须看到)、按代际 peek 后再放(`end` 可证更旧 ⇒ 缓行留着;可证更新 ⇒ 作废;同代 / 判不出 ⇒ 放);复活为 running 作废缓行;真历史行永远等不到 `end`,不上屏。结过的行再来的终态帧按**方向**判:可证更旧 ⇒ 整帧丢(不倒写用量、不第二次 `end`);ended 账单调写、`end` 的陈旧判据同时参考行帧水位与 ended 账(短命子代常没有行帧水位)。0.74.5 的两格「零事件」改口为「零 `end`、至多一条 `fleet-row`」。
|
|
63
|
+
- `compacted.freedTokens` 负值 / 非有限在本包按缺席(不夹到 0):注释此前写「夹 ≥ 0」与代码不符,改注释不改代码 —— 缺席比编一个 0 诚实(外部复验读数)。
|
|
64
|
+
|
|
65
|
+
### Changed
|
|
66
|
+
|
|
67
|
+
- **peer `@sema-agent/sdk` 地板 `>=9.7.1` → `>=9.8.1`(CC-81)**:9.8.x 给 `Capabilities.deviceExecutor` 的对象臂声明了 `management?: boolean`(本包 0.74.2 起的读器此前按结构读),包现在对 9.8.1 编译,消费端实装全在 9.8.1 ⇒ 9.7.1 失去物料见证。读器运行时行为零变化(入参仍按不可信结构防御读);device 读器门 +7 格把 sdk 声明形(可选键 / false 臂 / `management` 可选布尔;readonly / `| undefined` 算兼容形)钉住,声明删除 / 行注释伪证 / string 退化 / 改必填 各一枚负控;读器本身仍按不可信结构读,关联只在门。
|
|
68
|
+
- 两只测试钩(`__resetEngineAgentPanelIdentityForTests` / `__resetPanelRunningHistoryForTests`)的注释逐表列出清什么、不清什么,并写明连续场景中途别调(外部验收方的请求)。
|
|
69
|
+
|
|
70
|
+
### Guards
|
|
71
|
+
|
|
72
|
+
- panel-cycle 门 +19 格(S1v / S1w / S1x / S1y / S1z 族:两序 / 真历史行 / 复活新一代 / 前代 end 不放当代缓行 / 前代迟到帧不作废缓行;S1α–S1δ 族:异源对抗复审第三轮四条 [high] 反例 —— 缓行放出后重新归一 / 迟到前代终态帧整帧丢 / ended 账不倒写 / 前代 end 不取走当代缓行)、pure 门与身份归一门两格改口;singleton +2 high(ended 账 / 缓行表,上限 116 → 118)。
|
|
73
|
+
- 新门 `scripts/run-compaction-outcome-projection-test.mjs` 18 格(投影口 10 / 适配层 8;异源对抗复审 R1 [medium] 采修 —— 投影器不浅拷帧:展开会擦掉原型链上的身份键、还执行无关的可枚举 getter,与兄弟臂同律逐键读);device 读器门 +7(T1–T7);sdk 地板门 FLOOR 9.8.1,负控锚同批。新门 A3 改成同序列有 / 无结局帧的转录面逐字对拍(异源对抗复审 R2 [medium]:只排除同名 type 的行守不住「零新增转录行」)。
|
|
74
|
+
|
|
52
75
|
## 0.74.5(2026-09-19)
|
|
53
76
|
|
|
54
77
|
> 主题:**core 7.24.0 提货**(CC-85 `compacted.freedTokens?`)+ **首见即终态的行零事件**(CC-86;cli L-415 幽灵完成行)+ **`isNewEngineAgentPanelCycle` 上公面**(CC-87)。**patch**:型面 additive(+2 常量 +2 函数,公面 1061 → 1065;`compact_metadata._sema_freed_tokens?` 超集键;零 wire 新键 —— `freedTokens` 由 core 7.24.0 铸;peer 不动)。接入面 §73。
|
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Renamed from **`@sema-agent/wire-cc-adapter`** (0.1.x, deprecated — see *Migra
|
|
|
35
35
|
|
|
36
36
|
## Scope
|
|
37
37
|
|
|
38
|
-
**Version:** 0.
|
|
38
|
+
**Version:** 0.75.0
|
|
39
39
|
|
|
40
40
|
- **Today** — the adapter seam, the whole `adapt()` pipeline (all 14 A-layer arms plus the
|
|
41
41
|
B/D/E tool-card layers), the notification/caps/model families, the adapter kernel (stream driver
|
|
@@ -67,7 +67,7 @@ Renamed from **`@sema-agent/wire-cc-adapter`** (0.1.x, deprecated — see *Migra
|
|
|
67
67
|
against — the tables live upstream precisely so this package does not keep a second copy that can
|
|
68
68
|
fall behind. The browser bundle really bundles the SDK through (the portability guard would
|
|
69
69
|
exit 3 rather than quietly mark it external).
|
|
70
|
-
- The declared floor is `>=9.
|
|
70
|
+
- The declared floor is `>=9.8.1` (raised from `>=9.7.1` in 0.75.0: `Capabilities.deviceExecutor.management` is typed from 9.8.x on, the package now compiles against 9.8.1, and no consumer ships 9.7.x any more, so the older floor lost its witness; before that raised from `>=9.6.0` in 0.74.0: `Capabilities.approvalsStreamLive` / `.executionLane`, `LivePendingRow.frame`, the `live_*` approval-stream events and `gates[].toolCallId` are typed from 9.7.x on, and no consumer ships 9.6.0 any more, so the older floor lost its witness; before that raised from `>=9.4.0` in 0.71.0: the `tool_disclosure` / `tool_progress` frames and `ToolApprovalFrame.readRootCandidate` are typed there; earlier: raised from `>=8.8.0` in 0.69.0: the `reasoning_end` frame and `McpStatusPanel.lastLegMcp` are typed from 9.4.0 on), and it is *witnessed*: the guard checks that an actually
|
|
71
71
|
installed SDK at that line still exports every value-level symbol this package imports and still
|
|
72
72
|
declares `TaskStats.costMicroUsd` (the key `costOrNull` reads). A floor nobody ever ran is a
|
|
73
73
|
promise, not a contract.
|
|
@@ -317,6 +317,7 @@ public-surface guard checks that last one).
|
|
|
317
317
|
| `scripts/run-run-cancel-context-test.mjs` | The run record's `cancelContext` side-note (engine ≥7.87.3) read structurally, and the cause of a `turn_aborted{engine_error}` classified from machine-readable evidence only: `cancelled` (code `cancelled`, with the cancel-time context when present) / `engine_error` (any other failure code, passed through verbatim) / `run_still_live` (the record is not terminal — a dropped stream is a client-side fact, not the run's cause) / `unknown` (never guessed). An absent `cancelContext` reads as *not reported*, never as "not cancelled"; `elapsedMs` is never folded to 0. |
|
|
318
318
|
| `scripts/run-suspended-reopen-projection-test.mjs` | The durable `suspended` event's `reopened` key read as three distinct states — `reopened` (with the engine's code, verbatim), `not_reopened` (an explicit `null`), `unstated` (key absent or unreadable) — and carried on the HITL bridge's active gate (`currentGateReopen()`), re-read on every `suspended` and cleared with the gate. |
|
|
319
319
|
| `scripts/run-panel-identity-normalization-test.mjs` | One background subagent has two ids on the wire — the fleet row id tail and the `task_progress` task id (its transcript id). Every panel event goes through one funnel that rewrites the `tick` / `end` task id onto the fleet row's id once a `fleet-row` has registered the key (`transcriptId` first, `parentToolCallId` as the fallback), carrying the original as `wireTaskId` and marking `taskIdOrigin`; an unbound tick whose row has not arrived yet waits one beat (bounded) and is released verbatim on the next tick / `end`, when the buffer is full, or after `MAX_HELD_WIRE_TICK_BEATS` other fleet-row / end / sweep events (a `sweep` itself leaves it alone: there is no row to settle yet); a normalized `end` that carries no cycle identity borrows the registering row's, so a late close of a revived task is recognized as stale; the key table is an LRU (a task that keeps ticking is never evicted by newer registrations); the residency mark migrates with the id and both keys are cleared on settle — except that a stale (previous-cycle) terminal never clears the revived row's mark — so the notification lane can clear it. Once a tick has been delivered verbatim under its UUID, that UUID is the subagent's key: later fleet rows and fleet-side ends are rewritten onto it (the tail kept in `wireTaskId`), so a consumer sees one row in every arrival order; a late tick from a previous cycle is dropped rather than folded into the revived row. |
|
|
320
|
+
| `scripts/run-compaction-outcome-projection-test.mjs` | The `compaction_outcome` frame (a compaction that did **not** end as compacted: mooted by the task ending, failed, …) projected to an internal arm and then to the additive `compaction_outcome` chrome event — `outcome` required and verbatim (open set), `trigger` / `reason` present only when the engine sent a non-empty string, malformed frames dropped, zero transcript rows, the lane told honestly (`parentToolCallId` ⇒ subagent lane; a frame attributable only by `sourceTaskId` / `bgAgentId` is not surfaced on the main lane). |
|
|
320
321
|
| `scripts/run-approval-card-retract-test.mjs` | The approval card's **decision-free retraction** and the in-stream frame leg's **outcome hand-back**: a host that must withdraw a card that no longer has a decision channel (session switch, engine switch, a tracker reporting the ask gone) answers `{ kind: 'retracted' }` and the package sends nothing on any of the three legs (in-stream frame, suspended ask, durable park), reporting `decision: 'unresolved'` with a `retracted` flag; `aborted` / `failed` / `deny` keep their meaning (a real deny is still posted), and `onToolApprovalOutcome` hands every in-stream outcome back to the host exactly once, tolerating a throwing or rejecting callback Also the single source for the host-side approval-outcome note (`approvalOutcomeNoteOf`): `settled` is whether the decision was delivered, `retracted` is an independent key present only when the card was retracted, and `detail` is the retraction / edit-refused sentence or the refusal code and message — never a fabricated sentence. |
|
|
321
322
|
| `scripts/run-panel-cycle-identity-test.mjs` | The **cycle identity** on agent-panel events and the fleet ledger's **departure read-out**: a background agent may be revived under the same id, so `fleet-row` and `end` events now carry the wire's own `cycleSeq` / `startedAt` when present (absent means the row has no notion of generations, never "generation one"), `isStaleEngineAgentPanelEnd` is the single rule for ignoring a late `end` from a previous cycle (only when both sides carry a comparable identity; absence never drops a real terminal), a changed `cycleSeq` is a new cycle for usage stickiness and buffer coalescing, the notification lane carries `cycleSeq` only when the wire really sent `seq`, and `task_remove` frames reach the host through `onTaskRemoved` with `removeReason` / `cycleSeq` verbatim, a stale previous-generation removal leaving the newer row in place |
|
|
322
323
|
| `scripts/run-workflow-size-warning-test.mjs` | The **workflow size warning** verdict shared by every host footer / panel: a three-state result (`warn` / `ok` / `unknown`) read off the optional fleet view keys, where an unknown size is never reported as a normal one (absent `totalCount` / `tokens` without positive over-cap evidence is `unknown`, naming the missing keys), positive evidence on either axis wins regardless of absent keys, the per-agent denominator uses the engine's started count only when it is not below done+failed (a smaller value is a stale reading), otherwise falls back to the done+failed lower bound only when both keys are present — and a lower-bound denominator only yields an upper bound of the projection, which can prove *within cap* (`ok`, flagged) but never *over cap* (`unknown`, with the upper bound exposed) — and the prior is used only when the engine itself reports zero started agents; cap precedence env > explicit guideline > default, prototype keys never act as a guideline, the env reader is pure and does not fall through to the second name on a bad first value; caps, guideline table, env names and the three copy variants are single-sourced |
|
package/dist/adapt/arms.js
CHANGED
|
@@ -557,6 +557,35 @@ const contextUsageArm = function* (m) {
|
|
|
557
557
|
...(typeof m.eventId === 'string' && m.eventId.length > 0 ? { eventId: m.eventId } : {}),
|
|
558
558
|
});
|
|
559
559
|
};
|
|
560
|
+
/**
|
|
561
|
+
* CC-89(0.75.0):`compaction_outcome` 内部臂 → chrome `compaction_outcome`。每帧一条;转录面零行。
|
|
562
|
+
* 🔴 lane 如实:`parentToolCallId` 非空串 ⇒ subagent;只有 `sourceTaskId` / `bgAgentId`(或父键空串)的帧没有诚实的 lane 可挂 ⇒ 不发,
|
|
563
|
+
* 绝不落到主会话名下。`outcome` 非空串才发(非投影口喂进来的坏帧兜底)。
|
|
564
|
+
*/
|
|
565
|
+
const compactionOutcomeArm = function* (m) {
|
|
566
|
+
const str = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
|
|
567
|
+
const outcome = str(m.outcome);
|
|
568
|
+
if (outcome === undefined)
|
|
569
|
+
return;
|
|
570
|
+
let laneProof = MAIN;
|
|
571
|
+
if (isSubFlowSegmentEnd(m)) {
|
|
572
|
+
const parent = str(m.parentToolCallId);
|
|
573
|
+
if (parent === undefined)
|
|
574
|
+
return;
|
|
575
|
+
laneProof = { lane: 'subagent', parentToolCallId: parent };
|
|
576
|
+
}
|
|
577
|
+
const trigger = str(m.trigger);
|
|
578
|
+
const reason = str(m.reason);
|
|
579
|
+
const eventId = str(m.eventId);
|
|
580
|
+
yield chrome({
|
|
581
|
+
kind: 'compaction_outcome',
|
|
582
|
+
laneProof,
|
|
583
|
+
outcome,
|
|
584
|
+
...(trigger !== undefined ? { trigger } : {}),
|
|
585
|
+
...(reason !== undefined ? { reason } : {}),
|
|
586
|
+
...(eventId !== undefined ? { eventId } : {}),
|
|
587
|
+
});
|
|
588
|
+
};
|
|
560
589
|
const textSegmentEndArm = function* (m, { text }) {
|
|
561
590
|
// 🔴 断闸按「**键在不在**」判,不按「是不是串」判(异源对抗复审第三轮 [medium] 采纳)。
|
|
562
591
|
// 投影层已对坏 lane 位整帧 fail-closed;这一道是给**非投影口**喂进来的帧(宿主自建管线 /
|
|
@@ -1269,6 +1298,8 @@ export const ARMS = new Map([
|
|
|
1269
1298
|
['tool_progress', toolProgressArm],
|
|
1270
1299
|
['tool_roster_delta', toolRosterDeltaArm],
|
|
1271
1300
|
['context_usage', contextUsageArm],
|
|
1301
|
+
// CC-89(0.75.0):压缩的非 compacted 结局(additive;不接 = 压缩失败对用户不可见)。
|
|
1302
|
+
['compaction_outcome', compactionOutcomeArm],
|
|
1272
1303
|
['wiring_manifest', wiringManifestArm],
|
|
1273
1304
|
// B-078 / L-208(0.65.0):design/172 流内审批两帧 —— 修前它们在投影层就 `dropped`,
|
|
1274
1305
|
// 壳自己另接一份 ⇒ desktop/web 拿不到卡集与撤卡(归层违例)。
|
|
@@ -44,6 +44,8 @@ export const INTERNAL_SDK_ARM_TYPES = new Set([
|
|
|
44
44
|
'tool_progress',
|
|
45
45
|
'tool_roster_delta',
|
|
46
46
|
'context_usage',
|
|
47
|
+
// CC-89(0.75.0):压缩的非 compacted 结局 → 中性内部臂(print 车道同律:吞或转,裸透传 = 越界帧)。
|
|
48
|
+
'compaction_outcome',
|
|
47
49
|
'workflow_complete',
|
|
48
50
|
'tool_end_result',
|
|
49
51
|
'retry_status',
|
|
@@ -338,8 +340,8 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
338
340
|
// sdk 补上该位的当天,`run-compaction-boundary-projection-test.mjs` F10 行当场红逼复核。
|
|
339
341
|
case 'compacted': {
|
|
340
342
|
const raw = ev;
|
|
341
|
-
// 0.74.5 CC-85(core 7.24.0 #946)
|
|
342
|
-
// 缺席 = 没测出来 ⇒ 键不落(渲「未知」不是 0)
|
|
343
|
+
// 0.74.5 CC-85(core 7.24.0 #946):引擎自己测的结构性差值(core 侧夹 ≥ 0);旧的 tokensBefore / tokensAfter **不是可相减的一对**。
|
|
344
|
+
// 缺席 = 没测出来 ⇒ 键不落(渲「未知」不是 0);在场才带超集键。**负值 / 非有限在本包同样按缺席**(不夹到 0 —— 缺席比编一个 0 诚实;test 0.74.5 复验读数)。
|
|
343
345
|
const freedTokens = typeof raw.freedTokens === 'number' && Number.isFinite(raw.freedTokens) && raw.freedTokens >= 0 ? raw.freedTokens : undefined;
|
|
344
346
|
const attachedFiles = raw.attachedFiles;
|
|
345
347
|
const seg = raw.preserved_segment;
|
|
@@ -826,8 +828,8 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
826
828
|
case 'failed':
|
|
827
829
|
return nothing('terminal_delegated');
|
|
828
830
|
// ── 已入 SDK union、本切片**有意**不投影的臂(REF-CC-060:进 switch 才受穷举保护)────────
|
|
829
|
-
// `meta`:流首帧的 taskId/sessionId 一等信号 ——
|
|
830
|
-
//
|
|
831
|
+
// `meta`:流首帧的 taskId/sessionId 一等信号 —— 本切片无可渲染内容(runStream 只按 `eventSeq` 去重)。
|
|
832
|
+
// ⚠️ 活性普查(2026-09-19)更正:传输层**不**替宿主消费它;需要 sessionId / taskId 的端(desktop / web-client)各自直读本帧。
|
|
831
833
|
case 'meta':
|
|
832
834
|
// `file_link` / `prompt_assembled` / `model_usage` / `context_usage` / `config_assembled`:
|
|
833
835
|
// 引擎的可观测/审计面帧,本切片(CC transcript 投影)无对位渲染物;
|
|
@@ -840,12 +842,8 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
840
842
|
case 'config_assembled':
|
|
841
843
|
// `needs_review`:plan-review park 的**事件**形;壳消费的是 done{status:'needs_review'} 终帧
|
|
842
844
|
// (runStream 的 plan_review_park chrome 臂),事件形在本切片重复且更早,故不投影。
|
|
845
|
+
// ⚠️ 活性普查(2026-09-19):web-client 仍直读事件形;本切片不投的理由不变(终帧是权威),但「没人消费」这句不成立。
|
|
843
846
|
case 'needs_review':
|
|
844
|
-
// `compaction_outcome`(sdk 4.0.1 新臂,[2373]A-2 三腿同源):压缩**非 compacted 结局**报告
|
|
845
|
-
// (mooted/failed 等)。CC transcript 无对位物(compact_boundary 只对成功压缩,由 `compacted`
|
|
846
|
-
// 臂投)——本切片不投影。⚠️ 「压缩失败让用户看见」是 chrome/HUD 面的活,今天两端都还没接
|
|
847
|
-
// (adapt 臂表同样无此臂),缺口记 0.13.0 候选,不许由本切片顺手编一个假 transcript 形。
|
|
848
|
-
case 'compaction_outcome':
|
|
849
847
|
// ── sdk 6.9.0 提货批(2026-08-08)新入 union 的四条臂 ─────────────────────────────────────
|
|
850
848
|
// `tool_approval` / `tool_approval_complete`:HITL 审批帧。**#185a 起它们是 `AgentEvent` 的臂**
|
|
851
849
|
// (此前只是 named SSE frame),但本切片不是它们的消费口 —— 它们由
|
|
@@ -918,6 +916,10 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
918
916
|
// 由哪些段组成、哪一段大」,fleet/HUD 面要渲;三个标量走 finite 门(非有限即缺席,永不 null)。
|
|
919
917
|
case 'context_usage':
|
|
920
918
|
return contextUsageProjection(ev, ctx);
|
|
919
|
+
// CC-89(0.75.0):`compaction_outcome` 从 not_in_slice 组里拿出来 —— 压缩的**非 compacted 结局**(被终态抢先 / 失败等)此前
|
|
920
|
+
// 没有任何一端看得见。转录里没有对位物(`compact_boundary` 只对成功压缩)⇒ 走内部臂 → chrome 臂,不编消息。
|
|
921
|
+
case 'compaction_outcome':
|
|
922
|
+
return compactionOutcomeProjection(ev, ctx);
|
|
921
923
|
case 'tool_progress':
|
|
922
924
|
return toolProgressProjection(ev, ctx);
|
|
923
925
|
default:
|
|
@@ -1294,6 +1296,8 @@ function projectLspSection(raw) {
|
|
|
1294
1296
|
return undefined;
|
|
1295
1297
|
return { mounted: o.mounted, ...(typeof o.lane === 'string' && o.lane.length > 0 ? { lane: o.lane } : {}) };
|
|
1296
1298
|
}
|
|
1299
|
+
/** 内部臂的唯一铸出口(内部臂不在 CC 的 SDKMessage 联合里,出境只此一处铸;新臂走这里,不再各写一处铸链)。 */
|
|
1300
|
+
const internalArmExit = (body) => body;
|
|
1297
1301
|
function contextUsageProjection(ev, ctx) {
|
|
1298
1302
|
const { identity, bad } = identityOrMalformed(ev, 'context_usage');
|
|
1299
1303
|
if (bad !== null)
|
|
@@ -1319,14 +1323,39 @@ function contextUsageProjection(ev, ctx) {
|
|
|
1319
1323
|
}
|
|
1320
1324
|
if (usedTokens === undefined && windowTokens === undefined && compactAtTokens === undefined && sections === undefined)
|
|
1321
1325
|
return nothing('empty_payload');
|
|
1322
|
-
return projected(stamp(ctx, armBody({
|
|
1326
|
+
return projected(internalArmExit(stamp(ctx, armBody({
|
|
1323
1327
|
type: 'context_usage',
|
|
1324
1328
|
...(usedTokens !== undefined ? { usedTokens } : {}),
|
|
1325
1329
|
...(windowTokens !== undefined ? { windowTokens } : {}),
|
|
1326
1330
|
...(compactAtTokens !== undefined ? { compactAtTokens } : {}),
|
|
1327
1331
|
...(sections !== undefined ? { sections } : {}),
|
|
1328
1332
|
...identity,
|
|
1329
|
-
})));
|
|
1333
|
+
}))));
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* CC-89(0.75.0):`outcome` 是主事实,非空串必在(否则 malformed —— 不投一条没有结局的结局帧),原词逐字(引擎开集,不按成员过滤);
|
|
1337
|
+
* `trigger` / `reason` 非空串才在场,缺席 / 坏形 ⇒ 键不在场(不编 'auto'、不编空串;主事实不因旁键丢)。
|
|
1338
|
+
*/
|
|
1339
|
+
function compactionOutcomeProjection(frame, ctx) {
|
|
1340
|
+
// 🔴 不浅拷(异源复审 R1 [medium]):展开会擦掉原型链上的身份键(进程内对象把子代帧洗成主会话)、还会执行无关的可枚举 getter;
|
|
1341
|
+
// 与兄弟臂同律 —— 就在同一份记录上逐键各读一次。
|
|
1342
|
+
const ev = frame;
|
|
1343
|
+
const { identity, bad } = identityOrMalformed(ev, 'compaction_outcome');
|
|
1344
|
+
if (bad !== null)
|
|
1345
|
+
return bad;
|
|
1346
|
+
const str = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
|
|
1347
|
+
const outcome = str(ev.outcome);
|
|
1348
|
+
if (outcome === undefined)
|
|
1349
|
+
return dropped('malformed', 'compaction_outcome');
|
|
1350
|
+
const trigger = str(ev.trigger);
|
|
1351
|
+
const reason = str(ev.reason);
|
|
1352
|
+
return projected(internalArmExit(stamp(ctx, armBody({
|
|
1353
|
+
type: 'compaction_outcome',
|
|
1354
|
+
outcome,
|
|
1355
|
+
...(trigger !== undefined ? { trigger } : {}),
|
|
1356
|
+
...(reason !== undefined ? { reason } : {}),
|
|
1357
|
+
...identity,
|
|
1358
|
+
}))));
|
|
1330
1359
|
}
|
|
1331
1360
|
function engineNoticeProjection(ev, ctx) {
|
|
1332
1361
|
const code = typeof ev.code === 'string' && ev.code.length > 0 ? ev.code : undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* deviceExecutorManagementCapability — `GET /v1/capabilities.deviceExecutor.management`(server ≥7.88.0;契约附录 B.1
|
|
3
3
|
* `deviceExecutor` 行 + §14)的三端共用读面(0.74.2;与 sql / writeProtection / webSearch.backend / executionLane /
|
|
4
|
-
* approvalsStreamLive 五只兄弟同一套四态词汇)。sdk
|
|
4
|
+
* approvalsStreamLive 五只兄弟同一套四态词汇)。sdk 9.7.1 对该位无型 ⇒ 按契约结构读;9.8.x 起声明 `management?: boolean`(0.75.0 CC-81 对表:读器不改,门钉声明形)。
|
|
5
5
|
*
|
|
6
6
|
* ── 这一位答的是哪一个问题 ────────────────────────────────────────────────────────────────
|
|
7
7
|
* 「`/v1/devices/*` 的管理动词在这台 server 上在不在」(present-iff:与该族 501 判据逐字同源)。它挂在 `deviceExecutor`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* deviceExecutorManagementCapability — `GET /v1/capabilities.deviceExecutor.management`(server ≥7.88.0;契约附录 B.1
|
|
3
3
|
* `deviceExecutor` 行 + §14)的三端共用读面(0.74.2;与 sql / writeProtection / webSearch.backend / executionLane /
|
|
4
|
-
* approvalsStreamLive 五只兄弟同一套四态词汇)。sdk
|
|
4
|
+
* approvalsStreamLive 五只兄弟同一套四态词汇)。sdk 9.7.1 对该位无型 ⇒ 按契约结构读;9.8.x 起声明 `management?: boolean`(0.75.0 CC-81 对表:读器不改,门钉声明形)。
|
|
5
5
|
*
|
|
6
6
|
* ── 这一位答的是哪一个问题 ────────────────────────────────────────────────────────────────
|
|
7
7
|
* 「`/v1/devices/*` 的管理动词在这台 server 上在不在」(present-iff:与该族 501 判据逐字同源)。它挂在 `deviceExecutor`
|
|
@@ -209,7 +209,12 @@ export declare function resolveEnginePanelTaskId(wireTaskId: string, parentToolC
|
|
|
209
209
|
* `cycle`(0.74.4):调用方(通知车道)带得出这条终态的周期时传进来 —— 尾段归某把 UUID 所有而通知比所有权旧 ⇒ 不清那把 UUID 的常驻标。
|
|
210
210
|
*/
|
|
211
211
|
export declare function clearEnginePanelTaskResidentByWire(wireTaskId: string, cycle?: EngineAgentPanelCycleIdentity): void;
|
|
212
|
-
/**
|
|
212
|
+
/**
|
|
213
|
+
* 测试钩。逐表清单(每加一张表同批更新这里):① 转录钥匙表(UUID → 行尾段)② 父调用钥匙表(parentToolCallId → 行尾段)
|
|
214
|
+
* ③ 缓着的未绑卡 tick ④ 每行最近一次行帧的周期水位 ⑤ 「先发布的键」集合(UUID)⑥ 同上按父调用记的那一份 ⑦ 反向所有权表(行尾段 → UUID)。
|
|
215
|
+
* 🔴 不清:订阅者 / 回放缓冲、常驻标、running 历史(那一本由 `__resetPanelRunningHistoryForTests` 清)。
|
|
216
|
+
* 🔴 连续场景(同一只子代跨多步的用例)**中途别调**:清掉 ④–⑦ 之后,陈旧判据与「先发布的键为准」都会从零开始,前后两半不再是同一段历史。
|
|
217
|
+
*/
|
|
213
218
|
export declare function __resetEngineAgentPanelIdentityForTests(): void;
|
|
214
219
|
/** 宿主的唯一发布口(三条 lane 都经这里):先归一身份,再进主通道(订阅者 / 缓冲)。 */
|
|
215
220
|
export declare function publishEngineAgentPanelEvent(ev: EngineAgentPanelEvent): void;
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* Buffering: ticks published before the panel mounts are buffered (bounded) and replayed to the first
|
|
23
23
|
* subscriber, so early frames in a fast turn aren't lost to mount timing.
|
|
24
24
|
*/
|
|
25
|
-
import { retirePanelRowRunning } from './panelRunningHistory.js';
|
|
25
|
+
import { retirePanelRowRunning, notePanelRowEnded, panelRowEndedIdentity, peekHeldNewbornTerminalRow, takeHeldNewbornTerminalRow, dropHeldNewbornTerminalRow } from './panelRunningHistory.js';
|
|
26
26
|
const _panelToolUsesLanePins = [true, true];
|
|
27
27
|
void _panelToolUsesLanePins;
|
|
28
28
|
/**
|
|
@@ -331,7 +331,12 @@ export function clearEnginePanelTaskResidentByWire(wireTaskId, cycle) {
|
|
|
331
331
|
return;
|
|
332
332
|
residentTaskIds.delete(id.taskId);
|
|
333
333
|
}
|
|
334
|
-
/**
|
|
334
|
+
/**
|
|
335
|
+
* 测试钩。逐表清单(每加一张表同批更新这里):① 转录钥匙表(UUID → 行尾段)② 父调用钥匙表(parentToolCallId → 行尾段)
|
|
336
|
+
* ③ 缓着的未绑卡 tick ④ 每行最近一次行帧的周期水位 ⑤ 「先发布的键」集合(UUID)⑥ 同上按父调用记的那一份 ⑦ 反向所有权表(行尾段 → UUID)。
|
|
337
|
+
* 🔴 不清:订阅者 / 回放缓冲、常驻标、running 历史(那一本由 `__resetPanelRunningHistoryForTests` 清)。
|
|
338
|
+
* 🔴 连续场景(同一只子代跨多步的用例)**中途别调**:清掉 ④–⑦ 之后,陈旧判据与「先发布的键为准」都会从零开始,前后两半不再是同一段历史。
|
|
339
|
+
*/
|
|
335
340
|
export function __resetEngineAgentPanelIdentityForTests() {
|
|
336
341
|
fleetIdByTranscriptId.clear();
|
|
337
342
|
fleetIdByParentToolCallId.clear();
|
|
@@ -341,6 +346,35 @@ export function __resetEngineAgentPanelIdentityForTests() {
|
|
|
341
346
|
publishedWireByParent.clear();
|
|
342
347
|
wireIdByFleetId.clear();
|
|
343
348
|
}
|
|
349
|
+
/**
|
|
350
|
+
* 0.75.0 W2:一条 end 递达之前,先把投影缓着的「首见即终态」行放出来(它带这一行唯一的一份最终用量),经漏斗原路发布(身份归一照走);
|
|
351
|
+
* 递达之后记「本进程结过这一行」—— 投影据此把之后到的终态行当成短命子代的收尾(照发用量)而不是历史行。两步都只对当代 end(陈旧判据与销 running 历史同一只)。
|
|
352
|
+
*/
|
|
353
|
+
function releaseHeldNewbornTerminal(taskId, endCycle) {
|
|
354
|
+
// 先 peek 比周期再决定(异源复审 R3 [high]:先 take 会让前代 end 把当代唯一的缓行取走丢掉):
|
|
355
|
+
// end 可证比缓行**旧** ⇒ 缓行留着(等当代的 end);end 可证比缓行**新** ⇒ 缓行作废(前代用量不盖当代行);同代 / 判不出 ⇒ 放出。
|
|
356
|
+
const held = peekHeldNewbornTerminalRow(taskId);
|
|
357
|
+
if (held === undefined || held.kind !== 'fleet-row')
|
|
358
|
+
return;
|
|
359
|
+
const heldCycle = { ...(held.cycleSeq !== undefined ? { cycleSeq: held.cycleSeq } : {}), ...(held.startedAt !== undefined ? { startedAt: held.startedAt } : {}) };
|
|
360
|
+
if (isStaleEngineAgentPanelEnd(endCycle, heldCycle))
|
|
361
|
+
return;
|
|
362
|
+
if (isStaleEngineAgentPanelEnd(heldCycle, endCycle)) {
|
|
363
|
+
dropHeldNewbornTerminalRow(taskId);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
takeHeldNewbornTerminalRow(taskId);
|
|
367
|
+
publishEngineAgentPanelEvent(held);
|
|
368
|
+
}
|
|
369
|
+
/** 结算(end 已递达):running 历史销、ended 账单调写(可证比已结周期旧的 end 不倒写)。 */
|
|
370
|
+
function settleRowHistory(taskId, cycle) {
|
|
371
|
+
retirePanelRowRunning(taskId);
|
|
372
|
+
notePanelRowEnded(taskId, cycle, isStaleEngineAgentPanelEnd(cycle, panelRowEndedIdentity(taskId)));
|
|
373
|
+
}
|
|
374
|
+
/** end 的陈旧判据同时参考行帧水位与 ended 账(短命子代常常没有行帧水位 —— 异源复审 R3 [high])。 */
|
|
375
|
+
function endOlderThanKnown(end, taskId, rowCycle) {
|
|
376
|
+
return isStaleEngineAgentPanelEnd(end, rowCycle) || isStaleEngineAgentPanelEnd(end, panelRowEndedIdentity(taskId));
|
|
377
|
+
}
|
|
344
378
|
/** 宿主的唯一发布口(三条 lane 都经这里):先归一身份,再进主通道(订阅者 / 缓冲)。 */
|
|
345
379
|
export function publishEngineAgentPanelEvent(ev) {
|
|
346
380
|
// 行帧先登记、先放自己匹配的 tick,再给别的缓着的 tick 记拍(异源复审 R2 [high]:先记拍会让第 16 拍那条正好是自己行帧的 tick 过期);
|
|
@@ -422,33 +456,54 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
422
456
|
return;
|
|
423
457
|
}
|
|
424
458
|
case 'end': {
|
|
459
|
+
// 0.75.0 W2:缓着的「首见即终态」行**先于一切归一**放出(异源复审 R3 [high]:放出的行帧会登记钥匙 / 所有权,之后的 end 归一必须看到它,
|
|
460
|
+
// 否则同一子代长成 UUID 行 + 尾段行两行)。三把可能的键:尾段本身 / UUID 经钥匙解析到的尾段 / 这把 UUID 名下的尾段。
|
|
461
|
+
releaseHeldNewbornTerminal(ev.taskId, ev);
|
|
462
|
+
{
|
|
463
|
+
const pre = resolveEnginePanelTaskId(ev.taskId);
|
|
464
|
+
if (pre.origin === 'fleet-row' && pre.taskId !== ev.taskId) {
|
|
465
|
+
releaseHeldNewbornTerminal(pre.taskId, {
|
|
466
|
+
...(ev.cycleSeq !== undefined ? { cycleSeq: ev.cycleSeq } : pre.cycleSeq !== undefined ? { cycleSeq: pre.cycleSeq } : {}),
|
|
467
|
+
...(ev.startedAt !== undefined ? { startedAt: ev.startedAt } : pre.startedAt !== undefined ? { startedAt: pre.startedAt } : {}),
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
for (const [fleetId, o] of wireIdByFleetId)
|
|
471
|
+
if (o.wireId === ev.taskId && !o.retired)
|
|
472
|
+
releaseHeldNewbornTerminal(fleetId, ev);
|
|
473
|
+
}
|
|
425
474
|
// 先发布的键为准(CC-83):尾段已被改写成 UUID 的子代,fleet 侧(投影 / 通知)的 end{尾段} 也改写成 UUID
|
|
426
475
|
const wireOwner = wireOwnerOf(ev.taskId, ev);
|
|
427
476
|
if (wireOwner !== undefined) {
|
|
428
477
|
const ownerRec = wireIdByFleetId.get(ev.taskId);
|
|
478
|
+
const staleA = endOlderThanKnown(ev, ev.taskId, ownerRec) || isStaleEngineAgentPanelEnd(ev, panelRowEndedIdentity(wireOwner));
|
|
429
479
|
deliverEngineAgentPanelEvent({ ...ev, taskId: wireOwner, wireTaskId: ev.taskId, taskIdOrigin: 'wire' });
|
|
430
480
|
// 前代迟到的 end(比所有权登记时的周期旧)只过境让消费端判陈旧,不退役当代所有权(异源复审 R3)、不销当代 running 历史
|
|
431
|
-
if (!
|
|
481
|
+
if (!staleA) {
|
|
432
482
|
retireWire(wireOwner);
|
|
433
|
-
|
|
434
|
-
|
|
483
|
+
settleRowHistory(ev.taskId, ev);
|
|
484
|
+
settleRowHistory(wireOwner, ev);
|
|
435
485
|
}
|
|
436
486
|
return;
|
|
437
487
|
}
|
|
438
488
|
if (publishedWireIds.has(ev.taskId)) {
|
|
439
489
|
// 这把 UUID 是先发布的键 ⇒ 它的 end 落在它自己的行上(不归一;一把已发布的键永远不改写)
|
|
440
490
|
flushHeld(ev.taskId);
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
retirePanelRowRunning(ev.taskId);
|
|
444
|
-
// 这把 UUID 名下的尾段(反向所有权 / 转录别名)在投影里以尾段记的 running 历史一起销(复审 R3 [medium]),各自带周期守卫
|
|
491
|
+
// 这把 UUID 名下的尾段(反向所有权 / 转录别名)在投影里以尾段记账(复审 R3 [medium]),各自带周期守卫:先放缓着的终态行,end 之后再销
|
|
492
|
+
const ownedFleetIds = [];
|
|
445
493
|
for (const [fleetId, o] of wireIdByFleetId) {
|
|
446
|
-
if (o.wireId === ev.taskId && !
|
|
447
|
-
|
|
494
|
+
if (o.wireId === ev.taskId && !endOlderThanKnown(ev, fleetId, o))
|
|
495
|
+
ownedFleetIds.push(fleetId);
|
|
448
496
|
}
|
|
449
497
|
const alias = fleetIdByTranscriptId.get(ev.taskId);
|
|
450
|
-
if (alias !== undefined && !
|
|
451
|
-
|
|
498
|
+
if (alias !== undefined && !endOlderThanKnown(ev, alias.fleetId, alias) && !ownedFleetIds.includes(alias.fleetId))
|
|
499
|
+
ownedFleetIds.push(alias.fleetId);
|
|
500
|
+
deliverEngineAgentPanelEvent(ev);
|
|
501
|
+
retireWire(ev.taskId);
|
|
502
|
+
// UUID 自己的 ended 账也带守卫(end(U,2) 之后的 end(U,1) 不倒写)
|
|
503
|
+
if (!isStaleEngineAgentPanelEnd(ev, panelRowEndedIdentity(ev.taskId)))
|
|
504
|
+
settleRowHistory(ev.taskId, ev);
|
|
505
|
+
for (const fleetId of ownedFleetIds)
|
|
506
|
+
settleRowHistory(fleetId, ev);
|
|
452
507
|
return;
|
|
453
508
|
}
|
|
454
509
|
const id = resolveEnginePanelTaskId(ev.taskId);
|
|
@@ -461,8 +516,7 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
461
516
|
...(ev.cycleSeq !== undefined ? { cycleSeq: ev.cycleSeq } : id.cycleSeq !== undefined ? { cycleSeq: id.cycleSeq } : {}),
|
|
462
517
|
...(ev.startedAt !== undefined ? { startedAt: ev.startedAt } : id.startedAt !== undefined ? { startedAt: id.startedAt } : {}),
|
|
463
518
|
};
|
|
464
|
-
|
|
465
|
-
retirePanelRowRunning(id.taskId);
|
|
519
|
+
const staleC = endOlderThanKnown(effectiveEnd, id.taskId, latestCycleByFleetId.get(id.taskId));
|
|
466
520
|
deliverEngineAgentPanelEvent({
|
|
467
521
|
...ev,
|
|
468
522
|
taskId: id.taskId,
|
|
@@ -472,14 +526,17 @@ export function publishEngineAgentPanelEvent(ev) {
|
|
|
472
526
|
...(ev.cycleSeq === undefined && id.cycleSeq !== undefined ? { cycleSeq: id.cycleSeq } : {}),
|
|
473
527
|
...(ev.startedAt === undefined && id.startedAt !== undefined ? { startedAt: id.startedAt } : {}),
|
|
474
528
|
});
|
|
529
|
+
if (!staleC)
|
|
530
|
+
settleRowHistory(id.taskId, effectiveEnd);
|
|
475
531
|
return;
|
|
476
532
|
}
|
|
477
533
|
flushHeld(ev.taskId); // 缓着的 tick 先落行,终态才有行可结
|
|
534
|
+
// 通知车道 / fleet 投影铸的 end(尾段键):只对当代(前代迟到的 end 带旧 seq / cycleSeq ⇒ 不擦历史、不放缓着的行)
|
|
535
|
+
const staleD = endOlderThanKnown(ev, ev.taskId, latestCycleByFleetId.get(ev.taskId));
|
|
478
536
|
deliverEngineAgentPanelEvent(ev);
|
|
479
537
|
retireWire(ev.taskId); // 这把 UUID 若是先发布的键,所有权退役(容量满时先让位)
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
retirePanelRowRunning(ev.taskId);
|
|
538
|
+
if (!staleD)
|
|
539
|
+
settleRowHistory(ev.taskId, ev);
|
|
483
540
|
return;
|
|
484
541
|
}
|
|
485
542
|
default:
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
* 就地维护第二份;该函数出过等价性事故,0.1.1 修,见 `workflow.ts` 头注)。
|
|
49
49
|
*/
|
|
50
50
|
import { isStaleEngineAgentPanelEnd, publishEngineAgentPanelAbsence, publishEngineAgentPanelEvent } from './engineAgentPanelStore.js';
|
|
51
|
-
import { __resetPanelRunningHistoryForTests, notePanelRowRunning,
|
|
51
|
+
import { __resetPanelRunningHistoryForTests, notePanelRowRunning, panelRowUnknownToConsumer, panelRowEndedIdentity, holdNewbornTerminalRow, dropHeldNewbornTerminalRow } from './panelRunningHistory.js';
|
|
52
52
|
import { rowIdTail } from './workflow.js';
|
|
53
53
|
import { TERMINAL_FLEET_TASK_STATUSES } from './fleet/fleetProjection.js';
|
|
54
54
|
import { DEFAULT_SESSION_KEY } from './sessionSlot.js';
|
|
@@ -188,9 +188,34 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
|
|
|
188
188
|
// (交最终用量)再发 end ⇒ 宿主为本会话从没跑过的任务建行随即 settle = 面板幽灵完成行(reattach / resume 后引擎
|
|
189
189
|
// fleet 列表里的历史终态行全部上屏)。本会话内起步又结束、面板从没见过 running 的后台任务由通知车道的 end 收尸;
|
|
190
190
|
// 复活(prev 已 settled 且这一帧周期更新)不在此列,照发。
|
|
191
|
-
|
|
191
|
+
// 0.75.0 W2:「首见」= 消费端没有这一行(没发布过 running **也没递达过 end**);通知 end 先到的短命子代 ⇒ 终态行照发(交最终用量,不再第二次 end)。
|
|
192
|
+
const newbornTerminal = prev === undefined && panelRowUnknownToConsumer(taskId);
|
|
192
193
|
const settledThisCycle = prev?.settled === true && !rowNewerCycle;
|
|
193
|
-
|
|
194
|
+
// 结过的行(本进程递达过 end)再来终态帧:同代或判不出代际 = 短命子代的最终用量到了 ⇒ 只发 fleet-row、不再第二次 end;
|
|
195
|
+
// 可证更新的一代 = 结过之后复活又结束 ⇒ 照发 fleet-row + end。
|
|
196
|
+
const endedRec = prev === undefined ? panelRowEndedIdentity(taskId) : undefined;
|
|
197
|
+
const frameCycle = { ...(cycleSeq !== undefined ? { cycleSeq } : {}), ...(startedAt !== undefined ? { startedAt } : {}) };
|
|
198
|
+
// 方向判(异源复审 R3 [high]:只判「不等」会把迟到的前代终态当成新一代 ⇒ 倒写用量 + 第二次 end):
|
|
199
|
+
// 帧可证比已结周期**旧** ⇒ 整帧丢(不进台账,不发);可证**新** ⇒ 复活又结束,fleet-row + end;同代 / 判不出 ⇒ 只补用量。
|
|
200
|
+
if (endedRec !== undefined && isStaleEngineAgentPanelEnd(frameCycle, endedRec))
|
|
201
|
+
continue;
|
|
202
|
+
const endedSameCycle = endedRec !== undefined && !isStaleEngineAgentPanelEnd(endedRec, frameCycle);
|
|
203
|
+
if (newbornTerminal) {
|
|
204
|
+
// 反序保护:end 也许下一拍才到 ⇒ 终态行(带用量)缓在历史叶里,end 到漏斗时先放它再放 end;真历史行永远等不到 end,缓着直到被挤掉。
|
|
205
|
+
holdNewbornTerminalRow(taskId, {
|
|
206
|
+
kind: 'fleet-row',
|
|
207
|
+
taskId,
|
|
208
|
+
...(row.name ? { name: row.name } : {}),
|
|
209
|
+
...(row.description ? { description: row.description } : {}),
|
|
210
|
+
...(knownTokens !== undefined ? { totalTokens: knownTokens } : {}),
|
|
211
|
+
...(toolUses !== undefined ? { toolUses } : {}),
|
|
212
|
+
...(transcriptId !== undefined ? { transcriptId } : {}),
|
|
213
|
+
...(parentToolCallId !== undefined ? { parentToolCallId } : {}),
|
|
214
|
+
...(knownStartedAt !== undefined ? { startedAt: knownStartedAt } : {}),
|
|
215
|
+
...(knownCycleSeq !== undefined ? { cycleSeq: knownCycleSeq } : {}),
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
else if (!settledThisCycle) {
|
|
194
219
|
// 终态行也把最后一拍的累计工具数/转录锚带上:详情页在行翻终态后仍要显示真计数与
|
|
195
220
|
// 委派 prompt,而终态帧常常是这一行**唯一**带全 usage 的一帧(bg lane 只在活动边界发行帧)。
|
|
196
221
|
if (
|
|
@@ -216,17 +241,18 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
|
|
|
216
241
|
...(knownCycleSeq !== undefined ? { cycleSeq: knownCycleSeq } : {}),
|
|
217
242
|
});
|
|
218
243
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
244
|
+
if (!endedSameCycle)
|
|
245
|
+
publishEngineAgentPanelEvent({
|
|
246
|
+
kind: 'end',
|
|
247
|
+
taskId,
|
|
248
|
+
// L-215② 族扫(0.65.0):与 `notifications.enqueueBgChildNotification` 的 `isError` 位
|
|
249
|
+
// **同一个病形**(内联两词 ⇒ core [6908] 的 `blocked` 漏成「成功」)。两处一次改齐,
|
|
250
|
+
// 读同一个单铸谓词;只修当格 = 下一次加词又漏一处。
|
|
251
|
+
isError: isTerminalNotSuccess(status),
|
|
252
|
+
// 0.74.0:这条终态属于哪个周期(在场才带)—— 消费端据此挡掉上一周期迟到的 end。
|
|
253
|
+
...(knownCycleSeq !== undefined ? { cycleSeq: knownCycleSeq } : {}),
|
|
254
|
+
...(knownStartedAt !== undefined ? { startedAt: knownStartedAt } : {}),
|
|
255
|
+
});
|
|
230
256
|
}
|
|
231
257
|
seenMap.set(taskId, {
|
|
232
258
|
status,
|
|
@@ -261,6 +287,7 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
|
|
|
261
287
|
(cycleSeq !== undefined && prev.cycleSeq !== cycleSeq) ||
|
|
262
288
|
(currentToolKey !== undefined && prev.currentToolKey !== currentToolKey)) {
|
|
263
289
|
notePanelRowRunning(taskId); // CC-86:真发布了这一行在跑才记历史(未变的陈旧快照零事件也零记账,复审 R3)
|
|
290
|
+
dropHeldNewbornTerminalRow(taskId); // 复活为 running ⇒ 缓着的旧终态行作废(用量以新一代为准)
|
|
264
291
|
publishEngineAgentPanelEvent({
|
|
265
292
|
kind: 'fleet-row',
|
|
266
293
|
taskId,
|
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
export declare function notePanelRowRunning(taskId: string): void;
|
|
2
2
|
/** 结掉了(任何 lane 的 end 递达):历史不再需要。 */
|
|
3
3
|
export declare function retirePanelRowRunning(taskId: string): void;
|
|
4
|
-
/**
|
|
5
|
-
export
|
|
4
|
+
/** 结过的行 → 那条 end 的周期身份(两键都可缺席 = 判不出代际);投影据此分「同代的最终用量到了」与「结过之后复活的新一代」。 */
|
|
5
|
+
export interface PanelRowEndedIdentity {
|
|
6
|
+
cycleSeq?: number;
|
|
7
|
+
startedAt?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 单调写(异源复审 R3 [high]:旧 end 后到不许把已结周期倒写回前代):`older(cycle, existing)` 由调用方(漏斗)用陈旧判据算 ——
|
|
11
|
+
* 可证更旧 ⇒ 不写;同代 / 判不出 ⇒ 与已有记录合并(保留已知的另一半身份);可证更新 ⇒ 调用方传 older=false,本函数整只替换已知键。
|
|
12
|
+
*/
|
|
13
|
+
export declare function notePanelRowEnded(taskId: string, cycle: PanelRowEndedIdentity, older: boolean): void;
|
|
14
|
+
/** 本进程递达过这一行的 end ⇒ 那条 end 的周期身份;没有 ⇒ undefined。 */
|
|
15
|
+
export declare function panelRowEndedIdentity(taskId: string): PanelRowEndedIdentity | undefined;
|
|
16
|
+
/** 首见即终态且**确知**消费端没有这一行(running 表没溢出、不在 running 表、也没递达过 end)⇒ 历史行。 */
|
|
17
|
+
export declare function panelRowUnknownToConsumer(taskId: string): boolean;
|
|
18
|
+
export declare function holdNewbornTerminalRow(taskId: string, ev: object): void;
|
|
19
|
+
export declare function peekHeldNewbornTerminalRow<T extends object>(taskId: string): T | undefined;
|
|
20
|
+
export declare function takeHeldNewbornTerminalRow<T extends object>(taskId: string): T | undefined;
|
|
21
|
+
export declare function dropHeldNewbornTerminalRow(taskId: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* 测试钩。清四样:① 「发布过 running 且还没结」的行 id 集合 ② 溢出标(溢出后读口一律答保守)③ 「递达过 end」的行 id 集合 ④ 缓着的首见终态行。
|
|
24
|
+
* 🔴 连续场景中途别调:清掉之后,「首见即终态」的判定会把此前见过 running / 结过的行当成从没见过。
|
|
25
|
+
*/
|
|
6
26
|
export declare function __resetPanelRunningHistoryForTests(): void;
|
|
7
27
|
/** 测试 / 诊断读面。 */
|
|
8
28
|
export declare function __panelRunningHistorySize(): number;
|
|
@@ -24,13 +24,75 @@ export function notePanelRowRunning(taskId) {
|
|
|
24
24
|
export function retirePanelRowRunning(taskId) {
|
|
25
25
|
ids.delete(taskId);
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
/**
|
|
28
|
+
* 0.75.0 W2(test 0.74.5 复验读数):「没发布过 running」不等于「消费端没有这一行」—— 短命子代在两拍之间起步并结束时,通知车道的 end
|
|
29
|
+
* 已经递达(消费端建了行、状态 ended),终态 fleet-row 再被零事件吞掉 = 那一行的最终用量丢了(它是唯一带全 usage 的一帧)。
|
|
30
|
+
* ⇒ 第二本账:本进程**递达过 end** 的行 id(任何 lane;只记当代 —— 与销 running 历史同一个陈旧判据)。有界 FIFO 4096;被挤掉的 id 之后
|
|
31
|
+
* 若再来终态行会被当历史行(用量丢),这是有界的代价,不是压制永久关掉。
|
|
32
|
+
*/
|
|
33
|
+
const MAX_ENDED = 4096;
|
|
34
|
+
const endedIds = new Map();
|
|
35
|
+
/**
|
|
36
|
+
* 单调写(异源复审 R3 [high]:旧 end 后到不许把已结周期倒写回前代):`older(cycle, existing)` 由调用方(漏斗)用陈旧判据算 ——
|
|
37
|
+
* 可证更旧 ⇒ 不写;同代 / 判不出 ⇒ 与已有记录合并(保留已知的另一半身份);可证更新 ⇒ 调用方传 older=false,本函数整只替换已知键。
|
|
38
|
+
*/
|
|
39
|
+
export function notePanelRowEnded(taskId, cycle, older) {
|
|
40
|
+
const existing = endedIds.get(taskId);
|
|
41
|
+
if (existing !== undefined && older)
|
|
42
|
+
return;
|
|
43
|
+
endedIds.delete(taskId);
|
|
44
|
+
endedIds.set(taskId, { ...(existing ?? {}), ...(cycle.cycleSeq !== undefined ? { cycleSeq: cycle.cycleSeq } : {}), ...(cycle.startedAt !== undefined ? { startedAt: cycle.startedAt } : {}) });
|
|
45
|
+
if (endedIds.size > MAX_ENDED) {
|
|
46
|
+
const oldest = endedIds.keys().next().value;
|
|
47
|
+
if (oldest !== undefined)
|
|
48
|
+
endedIds.delete(oldest);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** 本进程递达过这一行的 end ⇒ 那条 end 的周期身份;没有 ⇒ undefined。 */
|
|
52
|
+
export function panelRowEndedIdentity(taskId) {
|
|
53
|
+
return endedIds.get(taskId);
|
|
30
54
|
}
|
|
55
|
+
/** 首见即终态且**确知**消费端没有这一行(running 表没溢出、不在 running 表、也没递达过 end)⇒ 历史行。 */
|
|
56
|
+
export function panelRowUnknownToConsumer(taskId) {
|
|
57
|
+
return !overflowed && !ids.has(taskId) && !endedIds.has(taskId);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 反序(终态 fleet-row 先到、通知 end 后到):终态行先缓住(投影把它当历史行零事件),end 到漏斗时先放行再放 end —— 用量不丢、也不为真历史行建行。
|
|
61
|
+
* 有界 FIFO 4096(与两本 id 账同量级;挤掉 = 那一行的用量丢,触发条件 = 同一进程里 4096 条首见终态行都还没等到 end);任何后到的行帧把缓着的作废。
|
|
62
|
+
*/
|
|
63
|
+
const MAX_HELD = 4096;
|
|
64
|
+
const heldNewborn = new Map();
|
|
65
|
+
export function holdNewbornTerminalRow(taskId, ev) {
|
|
66
|
+
heldNewborn.delete(taskId);
|
|
67
|
+
heldNewborn.set(taskId, ev);
|
|
68
|
+
if (heldNewborn.size > MAX_HELD) {
|
|
69
|
+
const oldest = heldNewborn.keys().next().value;
|
|
70
|
+
if (oldest !== undefined)
|
|
71
|
+
heldNewborn.delete(oldest);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export function peekHeldNewbornTerminalRow(taskId) {
|
|
75
|
+
return heldNewborn.get(taskId);
|
|
76
|
+
}
|
|
77
|
+
export function takeHeldNewbornTerminalRow(taskId) {
|
|
78
|
+
const ev = heldNewborn.get(taskId);
|
|
79
|
+
if (ev === undefined)
|
|
80
|
+
return undefined;
|
|
81
|
+
heldNewborn.delete(taskId);
|
|
82
|
+
return ev;
|
|
83
|
+
}
|
|
84
|
+
export function dropHeldNewbornTerminalRow(taskId) {
|
|
85
|
+
heldNewborn.delete(taskId);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 测试钩。清四样:① 「发布过 running 且还没结」的行 id 集合 ② 溢出标(溢出后读口一律答保守)③ 「递达过 end」的行 id 集合 ④ 缓着的首见终态行。
|
|
89
|
+
* 🔴 连续场景中途别调:清掉之后,「首见即终态」的判定会把此前见过 running / 结过的行当成从没见过。
|
|
90
|
+
*/
|
|
31
91
|
export function __resetPanelRunningHistoryForTests() {
|
|
32
92
|
ids.clear();
|
|
33
93
|
overflowed = false;
|
|
94
|
+
endedIds.clear();
|
|
95
|
+
heldNewborn.clear();
|
|
34
96
|
}
|
|
35
97
|
/** 测试 / 诊断读面。 */
|
|
36
98
|
export function __panelRunningHistorySize() {
|
package/dist/seam.d.ts
CHANGED
|
@@ -534,7 +534,7 @@ export type ChromeEvent = {
|
|
|
534
534
|
* ⚠️ **只有 live 腿有本帧**(server 7.69.0 亲读:durable/bg 腿把它喂给 rewind 锚而不入账本)
|
|
535
535
|
* ⇒ replay/resume 上映射表是空的;那时正解是**不画分割线**,不是回退成「画在最后一条」。
|
|
536
536
|
*/
|
|
537
|
-
| MessageCommittedChromeEvent | EngineNoticeChromeEvent | TextSegmentEndChromeEvent | ThinkingSegmentEndChromeEvent | ToolDisclosureChromeEvent | ToolProgressChromeEvent | ToolRosterDeltaChromeEvent | ContextUsageChromeEvent | WiringManifestChromeEvent | ResultTextDivergedChromeEvent
|
|
537
|
+
| MessageCommittedChromeEvent | EngineNoticeChromeEvent | TextSegmentEndChromeEvent | ThinkingSegmentEndChromeEvent | ToolDisclosureChromeEvent | ToolProgressChromeEvent | ToolRosterDeltaChromeEvent | ContextUsageChromeEvent | CompactionOutcomeChromeEvent | WiringManifestChromeEvent | ResultTextDivergedChromeEvent
|
|
538
538
|
/**
|
|
539
539
|
* B-078 / L-208(0.65.0):design/172 流内审批协议的**两条帧**。修前它们在标准管线上落
|
|
540
540
|
* `dropped('unsupported_arm')`,壳自己另接一份 ⇒ 只走包管线的宿主(desktop/web)拿不到
|
|
@@ -794,6 +794,21 @@ export interface ContextUsageChromeEvent {
|
|
|
794
794
|
sections?: readonly ContextUsageSectionView[];
|
|
795
795
|
eventId?: string;
|
|
796
796
|
}
|
|
797
|
+
/**
|
|
798
|
+
* CC-89(0.75.0;sdk `compaction_outcome`):一次压缩的**非 compacted 结局**(例:被任务终态抢先而作废、熔断开着而失败)。
|
|
799
|
+
* 成功压缩不走本臂 —— 那条的权威仍是转录里的 `compact_boundary`。
|
|
800
|
+
* 🔴 `outcome` / `trigger` 是引擎**开集**原词(已知 `trigger`:`auto` / `manual` / `forced`),按成员渲染时必须带 default 臂,认不得的词照原词显示,别丢帧;
|
|
801
|
+
* 🔴 本臂**不是终态**:任务还在跑,别据它收 spinner / 判 run 结束;`reason` 是引擎说明文本(上游已脱敏),渲前仍按宿主自己的不可信文本纪律处理。
|
|
802
|
+
* `laneProof.lane === 'subagent'` = 这是某只子代的压缩结局,别渲成主会话的。缺席键 = 引擎没说,不是空值。
|
|
803
|
+
*/
|
|
804
|
+
export interface CompactionOutcomeChromeEvent {
|
|
805
|
+
kind: 'compaction_outcome';
|
|
806
|
+
laneProof: LaneProof;
|
|
807
|
+
outcome: string;
|
|
808
|
+
trigger?: string;
|
|
809
|
+
reason?: string;
|
|
810
|
+
eventId?: string;
|
|
811
|
+
}
|
|
797
812
|
export interface ToolDisclosureChromeEvent {
|
|
798
813
|
kind: 'tool_disclosure';
|
|
799
814
|
laneProof: LaneProof;
|
package/dist/seam.js
CHANGED
|
@@ -88,6 +88,11 @@ const CHROME_ARM_TABLE = {
|
|
|
88
88
|
duty: 'CC-08(0.71.0):每个压缩边界一条,按**最后一条**取当前值;`usedTokens > compactAtTokens` 是引擎的 shouldCompact 谓词,别重算;`windowTokens` 是 autocompact 窗,' +
|
|
89
89
|
'别渲成模型上下文大小;🔴 `sections[].tokens` 与 `usedTokens` 不同坐标系,**禁相减**、禁拿一段比 `compactAtTokens`;`sections` 整键缺席 = 没装配出段 IR,不是各段为零。',
|
|
90
90
|
},
|
|
91
|
+
compaction_outcome: {
|
|
92
|
+
required: false,
|
|
93
|
+
duty: 'CC-89(0.75.0):一次压缩的非 compacted 结局(作废 / 失败等),给用户一条可见提示。`outcome` / `trigger` 是引擎开集原词,按成员渲染必带 default 臂、认不得照原词显示;' +
|
|
94
|
+
'🔴 不是终态 —— 任务还在跑,别据它收 spinner;`laneProof.lane` 为 subagent = 子代的压缩结局,别渲成主会话的;成功压缩不走本臂(权威是转录的 compact_boundary)。不接 = 压缩失败对用户不可见。',
|
|
95
|
+
},
|
|
91
96
|
tool_disclosure: {
|
|
92
97
|
required: false,
|
|
93
98
|
duty: 'CC-08(0.71.0):这条腿的工具名字占位普查。`deferred` / `activated` 都是**全量快照,整只替换**(不做增量合并);' +
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
|
|
20
20
|
| 项 | 值 | 真源 |
|
|
21
21
|
|---|---|---|
|
|
22
|
-
| 本包 | `@sema-agent/client-core` **0.
|
|
23
|
-
| peer:wire 契约 | `@sema-agent/sdk` **>=9.
|
|
22
|
+
| 本包 | `@sema-agent/client-core` **0.75.0**(本批发布版 = **minor**:压缩的非 compacted 结局上 chrome 面 `compaction_outcome`(新内部臂 —— 自建 print 出口的端先表态)+ peer sdk 地板 `>=9.8.1`;型面 additive(ChromeEvent +1 臂)、公面 1065、零 wire 新键;§74。上一版 0.74.5 = **patch**:core 7.24.0 提货 `_sema_freed_tokens?` + 首见即终态的行零事件(幽灵完成行)+ `isNewEngineAgentPanelCycle` / `approvalOutcomeNoteOf` 上公面;型面 additive、公面 1065、peer 不动;§73。上一版 0.74.4 = **patch**:面板键「先发布的键为准」(tick 归不了一的三序不再两行)+ 前代 UUID 迟到 tick 丢弃 + `readRunCancelContext` 下钻收紧;型面 additive、公面 1061、peer 不动;§72。上一版 0.74.3 = **patch**:面板子代身份归一(tick / end 的 UUID 归到 fleet 尾段,宿主零改)+ run 记录 `cancelContext` 读口与成因四词 + workflow 行 `errorCode` + reopen 第二臂两件;型面纯 additive、公面 1061、peer 不动;§71。上一版 0.74.2 = **patch**:`capabilities.deviceExecutor.management` 四态读口(缺席 ≠ false;`deviceExecutor: false` = 车道缺席;管理动词可用性三态归包);公面 1052;§70。上一版 0.74.1 = **patch**:审批卡无决断收口 + 结局回交;§69。上一版 0.74.0 = **minor**:peer sdk 地板 >=9.7.1 + covers 过境 + 面板周期身份 + 离场读口;§68。上一版 0.73.5 = **patch**:workflow 规模告警判定上收进包(`evaluateWorkflowSize` 三态:未知的规模不当作规模正常;分母口径与帽优先级单源;env 读口纯函数);型面纯 additive、公面 1044、peer 不动;§67。上一版 0.73.4 = **patch**:终帧 `permission_denials` 第三键 ⇐ 同一条流 `tool_start` 入参按 `toolCallId` join(三道闸;join 不上留 sema 载体;🔴 更正 0.73.2「自动升级收口」一句)+ 审批 feed push 侧取件失败的欠账退避重试;型面纯 additive、公面 1033、peer 不动;§66。上一版 0.73.3 = **patch**:CC-61 sdk 9.7.1 提货 + `capabilities.approvalsStreamLive` 四态读口(缺席 = 判不出;`livePendingNeedsReconcile` 只在引擎明说会推时才让对账节拍降兜底)+ CC-60 五条模型面文案锚包侧半场(cursorSemantics 机读位 / result 行注记 / bash 首行两变体与良性槽 / 通知 seed 并集 / parked 臂);型面纯 additive、公面 1032、peer 不动;§65。上一版 0.73.2 = **patch**:CC-59 悬挂 ask 全卡 —— `livePending[].frame`(server ≥7.87.0)两道闸窄读进视图,在场即走流内帧腿同一条路(入参可见、改写可转发),缺席保持盲卡;CC-34 收口(引擎半场随 7.87.0 到货,判据交黑盒);型面纯 additive、公面 1026、peer 不动;§64。上一版 0.73.1 = **patch**:CC-57 `decidePlanReview` outcome 尾句按「决断有没有生效」四态选(单铸点 `planReviewOutcomeTail`;此前本地拒发仍让模型汇报已拒绝)+ CC-56 cancel 的 409 按机器码分家(`cancelConflictFromError` 三形 / 新安全码 `cancel_run_not_running`)与提交面 429 用量窗读口 + 人话;型面纯 additive、公面 1026、peer 不动;§63。上一版 0.73.0 = **minor,型面 BREAKING**:fleet 视图八个数值键改可选 —— CC-52 `FleetTaskView.elapsedMs` / `tokens` / `queuedCount` 与 `FleetWorkflowView.doneCount` / `totalCount` / `failedCount` / `tokens` / `elapsedMs` 不再 `?? 0`(有键 = 真值含真 0,缺键 = 不知道;逐键缺席语义见 §62b)+ 台账补偿链无基数不铸;公面导出名零增减 1019、零 wire 变化、peer 不动;§62。上一版 0.72.14 = **patch**:悬挂的流内 ask 拉半场 —— CC-55 `startApprovalsFeed` 快照加 `livePending` 段并进变化摘要(键缺席 = 未报,不铸空)+ 视图 / 去重账 / 与流内帧腿同链的决断口(入参不可见上卡明说、改写不转发)+ 宿主闸对账节拍 + 待决计数读口(不知道 = null);型面纯 additive、公面 1019、peer 不动;§61。上一版 0.72.13 = **patch**:server 7.86.0 提货 —— CC-46 plan_review `permissionModeAfter` 发口(三选卡双闸:宿主声明只读起步 ∧ 引擎 ≥7.86.0;400 field_conflict 两种处置)+ CC-54 `capabilities.executionLane` 四态读面(键缺席 ≠ 不是本机车道;`toolsRunHere` 判据归包)+ CC-53 detach 版本闸三态;型面 additive(另撤回 0.72.12 的主通道 `absent` 臂,改独立缺席订阅口)、公面 1011、peer 不动;§60;**预告 0.73.0 BREAKING**:fleet 视图数值键改可选。上一版 0.72.12 = **patch**:「缺席被折成正向终态」按类清剿 —— CC-50 M1 头条(fleet 行缺席改发 `absent` 不再铸 `end{isError:false}`)+ 六站一次改齐(缺席 ⇒ `unknown`)+ 结果边界 fail-closed 取舍 + `_sema_outcome` + `Outcome unknown:` 行 + CC-51 M6(default 臂不再谎报 running)+ 普查门 + DS-06;型面 additive、公面 993、peer 不动;行为面三处真变化见 CHANGELOG 取舍段;§59。上一版 0.72.11 = **patch**:core 7.23.0 提货 —— CC-49 通告码 66 → 67 `config.write_protection_unresolved`(operator;兄弟码 `target_view_absent` = 没有视图,这枚 = 有视图解析不出)+ `permission_denials` 自动升级腿通电(`gates[].toolCallId` ⇒ `tool_use_id`;CC-34 引擎半场);型面零变化、公面 989、peer 不动、devDep core ~7.23.0;§58。上一版 0.72.10 = **patch**:CC-41 leader run 终局 `needs_human` + `result.conflict` 三形读面(none 缺席不可分 / unreadable 在场读不懂 / conflict;`salvaged[]` 原样给落盘口;措辞单源不提重试);型面纯 additive、公面 989、peer 不动;§57。上一版 0.72.9 = **patch**:server 7.85.0 提货 —— CC-30 会话内 MCP re-dial 消费口(`reconnectMcpServer` 三态 / unsupported 恒五键 / 交易文案单源)+ CC-39② memory-status `autoConsolidationArmed` 三态 + CC-45 resume 补充句渲保留秒数;型面纯 additive、公面 985、peer 不动;§56。上一版 0.72.8 = **patch**:清账三票 —— `memory:"off"` 请求键(CC-39③,server 7.84.0 S-405)+ `runStream` 第二条中性臂 `Model output error:`(CC-43)+ 注入件撞活 run 自动 steer 零卡(CC-44);型面纯 additive、公面 977、peer 不动;§55。上一版 0.72.7 = **patch**:core 7.22.0 提货 —— 通告码 66 `mcp.server_redialed` + 读器 `readMcpServerRedialed` + `wiring_manifest.readDeny` 第九段 `_sema_readDeny`(缺席 = 没有内置行判这条腿);型面纯 additive、公面 971、peer 不动、devDep core ~7.22.0;§54。上一版 0.72.6 = **patch**:cli L-379 包侧半场 —— `steerFollowIntent` steer 后续听意图三态(tail / after-decision / after-wake)+ `activeRunSelfHealRow` 续听声明第五参;型面纯 additive、公面 969、peer 不动;§53。上一版 0.72.5 = **patch**:server 7.82.1 提货 —— `capabilities.webSearch.backend` 部署默认 WebSearch 后端四态读面(键缺席 = 老引擎判不了 ≠ `none`);型面纯 additive、公面 968、peer 不动;§52。上一版 0.72.4 = **patch**:core 7.21.x 三件经 server 7.82.0 提货 —— `wiring_manifest.autoConsolidation` 第八段 `_sema_autoConsolidation`(缺席 = indeterminate 不折 false);型面纯 additive、公面 962、peer 不动;§51。上一版 0.72.3 = **patch**:core #863 记忆单系统半场 ① —— `projectAgentsForWire` 投影 `agents[].memory`(user|project|local 三词同映射引擎平面 agent:<type>);型面纯 additive、公面 962、零 wire 新键、peer 不动;§50。上一版 0.72.2 = **patch**:workflow 视图两票 —— `LiveWorkflowController.resolution()` 六态(snapshot() 的 null 三义拆开)+ `noteOwnWorkflowRun` own 台账同拍登记;型面纯 additive、公面 961、零 wire 键、peer 不动;§49。上一版 0.72.1 = **patch**:server 7.80.1 提货 —— 409 `conflict.resume_context_unavailable` 结构读数(`staleAfterSec` / `runId`;sdk 9.6.0 尚未带键,经 sdk 今天恒缺席)+ `SkillSpec.baseDir`(只在本机车道带);型面纯 additive、公面 960、peer 不动;§48。上一版 0.72.0 = **minor**:型面 BREAKING —— 39 个零消费导出退出公面(CC-32 退役批,[7419] §45 预告 / cli [7422] 同意 / web-client·desktop 过节拍沉默 = 同意;名单见 §47a S-1);运行期零 BREAKING、公面 956、peer 不动、devDep core ~7.20.1;随批:已退役名账 `removed` + export-liveness 门 G 段 + 冻结账门 ⑧c;§47。上一版 0.71.4 = **patch**:core 7.20.1 提货 —— `ENGINE_NOTICE_CODES` 65 + `wiring_manifest.writeProtection` 第七段 `_sema_writeProtection`;型面纯 additive、公面 995、peer 不动、devDep core `~7.20.1`;§46。上一版 0.71.3 = **patch**:门体系清账批 —— CC-24 export-liveness 门 + 39 个导出退役预告(0.72.0 删,表态制)/ CC-26 `as unknown as` 铸链棘轮 / CC-25 冻结账门 ⑧ 段 / CC-06 B-081 包侧半场(终帧 `_sema_effective_reasoning` / `_sema_effective_memory_scopes` + resume reopen 族 + `routePairingVerdict`);型面纯 additive、公面 986 → 995、peer 不动;§45。上一版 0.71.2 = **patch**:接入方验收两票归包 —— CC-28 B-132 decide 拒体三句去内部车道词 / CC-29 B-133 committedUuids 唯一性(重复 ⇒ 形 f);零型面变化、公面 986、peer 不动;§44。上一版 0.71.1 = **patch**:接入档打回修正 —— CC-27 `ApprovalCardRequest.readRootCandidate?` 帧→卡透传位 + 新导出型 `ReadRootCandidateView`;型面纯 additive、公面 986 不变、peer 不动;§43。上一版 0.71.0 = **minor**:型面 BREAKING 六件 —— peer sdk 地板 >=9.6.0 + agent-types >=0.3.0 / `SkillsListingTruncatedFactsView` 删 `requestedBudgetBytes?`·`laneClamped?` / `WiringManifestMcpEntry` → `WiringManifestMcpEntryView` / `MAX_AGENT_SKILLS` 删 / `decide.workflow_host_not_parked` 退役;运行期零 BREAKING。内容:core 7.20.0 提货(闭集 +5 六十四码)/ 🔴 CC-16 `text_segment_end.committedUuids[]` / CC-08 全五件(tool_disclosure / tool_progress 两 chrome 臂、wiring_manifest tools·hooks·lsp 进切片、tool_roster_delta 接上、context_usage 进切片、`readRootCandidate` 镜像)/ CC-19 `mcpEngineLegPresence` 归包 / CC-20 not_parked clean-cut;公面 986;§42 / 42y 八条)|
|
|
23
|
+
| peer:wire 契约 | `@sema-agent/sdk` **>=9.8.1**(value-level,非 type-only;**0.75.0 抬版**:9.8.x 声明 `Capabilities.deviceExecutor.management?`,9.7.1 失去物料见证;**0.74.0 曾抬到 >=9.7.1**:9.7.x 追平的六处型面是本包 0.73.3 起的编译基线,且 9.6.0 失去物料见证;**0.71.0 曾抬到 >=9.6.0**:`tool_disclosure` / `tool_progress` 两帧型与 `ToolApprovalFrame.readRootCandidate` 自 9.6.0 起;0.69.0 曾抬到 >=9.4.0(`reasoning_end` / `lastLegMcp`),0.60.0 抬到 >=8.4.0;地板由 `scripts/run-sdk-floor-test.mjs` 的 `FLOOR` 与 public-surface 门 C-CC-3「不低于见证到的最低实装版」双钉)| `package.json` `peerDependencies` |
|
|
24
24
|
| peer:会话词汇表 | `@sema-agent/agent-types` **>=0.3.0**(type-only,零运行时;0.71.0 抬版:devDep 与 peer 同步,type-superset 门 ④ 撞名预警对着 0.3.0 的 .d.ts 求值) | 同上 |
|
|
25
25
|
| runtime dep | `diff` ^9.0.0(**唯一**一条;portability 门按**等值**钉死) | `package.json` `dependencies` |
|
|
26
26
|
| 公开导出面 | **1065** 个运行期符号(+ 51 个测试钩;= 0.74.5 的值:相对 0.74.4 +4 —— `isNewEngineAgentPanelCycle`(CC-87,域 4)+ `approvalOutcomeNoteOf` 与两句固定文案常量(CC-88,域 3);1061 = 0.74.3 / 0.74.4 的值:相对 0.74.2 +9 —— CC-70 / CC-71 / CC-72 / CC-73 八件 + CC-80 `lastFlagValue`,见 §2b 域 3 / 4 / 10 / 15;1052 = 0.74.2 的值:相对 0.74.1 +6 —— CC-69 六件,见 §2b 域 9;1046 = 0.74.1 的值:相对 0.74.0 +1 —— `RETRACTED_CARD_DECISION_KIND`,见 §2b 域 3;1045 = 0.74.0 的值:相对 0.73.5 +1 —— `isStaleEngineAgentPanelEnd`,见 §2b 域 4;1044 = 0.73.5 的值:相对 0.73.4 +11 —— CC-58 规模告警十一件,名单见 §2b 域 12;1033 = 0.73.4 的值:相对 0.73.3 +1 —— `TOOL_INPUT_JOIN_MAX_CALLS`,见 §2b 域 1;1032 = 0.73.3 的值:相对 0.73.2 +6 —— CC-61 六件,名单见 §2b 域 9;1026 = 0.73.2 的值(导出名零增减);= 0.73.1 的值:相对 0.73.0 +7 —— CC-56 六件 / CC-57 一件,名单见 §2b 域 3 / 15;1019 = 0.73.0 的值(导出名零增减,BREAKING 在类型面);= 0.72.14 的值:相对 0.72.13 +8 —— CC-55 八件,名单见 §2b 域 3;1011 = 0.72.13 的值:相对 0.72.12 +18 —— CC-46 八件 / CC-54 六件 / CC-53 两件 / CC-50 缺席口两件,名单见 §2b 域 3 / 4 / 9 / 10;993 = 0.72.12 的值(测试钩 45):相对 0.72.11 +4 —— CC-50 `OUTCOME_UNKNOWN_ROW_PREFIX` / `isOutcomeUnknownRowText` / `TASK_NOTIFICATION_TERMINAL_STATUSES` / `isTaskNotificationTerminalStatus`;989 = 0.72.10 的值:相对 0.72.9 +4 —— CC-41 `LEADER_RUN_STATUSES` / `LEADER_REJ_HEAD_DISPLAY_MAX` / `projectLeaderConflict` / `leaderConflictDetail`;985 = 0.72.9 的值:相对 0.72.8 +8 —— CC-30 `MCP_RECONNECT_OUTCOMES` / `MCP_RECONNECT_TRANSACTION_NOTICE` / `projectMcpReconnectResult` / `classifyMcpReconnectFailure` / `reconnectMcpServer` / `projectMcpReconnectCapability` / `mcpReconnectOutcomeDetail`、CC-39② `readAutoConsolidationArmed`;977 = 0.72.8 的值:相对 0.72.7 +6 —— CC-39③ `MEMORY_OFF` / `memoryOffDeclarationField` / `memoryOffDeclared`、CC-43 `MODEL_OUTPUT_ERROR_PREFIX` / `isModelOutputErrorText` / `isModelOutputErrorRowText`;971 = 0.72.7 的值:相对 0.72.6 +2 —— CC-42 core 7.22.0 提货 `MCP_REDIAL_OUTCOMES` / `readMcpServerRedialed`;969 = 0.72.6 的值:相对 0.72.5 +1 —— CC-40 `steerFollowIntent`;968 = 0.72.5 的值:相对 0.72.4 +6 —— CC-31 server 7.82.1 提货 `capabilities.webSearch.backend` 四态读面:`WEB_SEARCH_BACKEND_NONE` / `projectWebSearchBackendCapability` / `observedWebSearchBackend` / `noteEngineCapsForWebSearchBackend` / `forgetWebSearchBackendReading` / `webSearchBackendDoctorDetail`;962 = 0.72.3 的值:相对 0.72.2 +1 —— CC-39① `AGENT_MEMORY_WORDS`;0.72.2 相对 0.72.1 +1 —— CC-37 `noteOwnWorkflowRun`;0.72.1 相对 0.72.0 +4 —— CC-33 server 7.80.1 提货:`RESUME_CONTEXT_UNAVAILABLE` / `resumeContextUnavailableFromError` / `resumeContextUnavailableContent` / `skillBaseDirOf`;0.72.0 相对 0.71.4 −39 —— CC-32 退役批删 export-liveness 登记 retire 的 39 个零消费导出(23 常量 + 16 函数,名单见 §47);995 = 0.71.3 的值:相对 0.71.2 +9 —— CC-06 `readEffectiveReasoning` / `readEffectiveMemoryScopes` / `resumeReopenFromError` / `resumeReopenContent` / `routePairingVerdict` 五函数 + `RESUME_REOPEN_CODES` / `RESUME_ENV_FAILED` / `RESUME_TOOL_UNAVAILABLE` / `RESUME_TOOL_CONTRACT_MISMATCH` 四常量;986 = 0.71.0 的值:相对 0.70.2 −`MAX_AGENT_SKILLS` −`DECIDE_WORKFLOW_HOST_NOT_PARKED` +`projectToolRosterDelta` +`mcpEngineLegPresence`;986 = 0.70.0 的值:相对 0.69.2 **一件 additive(`readSkillsListingTruncated`,§39)、零删除**;985 = 0.69.2 的值:相对 0.69.1 **三件 additive、零删除**(CC-13 `isSubFlowSegmentEnd` / `SEGMENT_END_IDENTITY_KEYS` / `droppedWhySentence`,§38);982 = 0.69.0 未发布版的值(原排 0.68.3,因 peer 地板抬升改 minor)= 相对 0.68.2 **十七件 additive、零删除**:`fetchMcpPanel`(CC-03 补件,§36e)+ `readWorkflowResumeAdmissionIncomplete`(CC-05 core 7.18.0 #755)+ `installCoreValuePorts`/`hasCoreValuePorts`/`hasCoreValuePort`/`coreValuePortMisses`/`CORE_VALUE_PORT_NAMES` + 十读口(CC-07 core 值级端口,§36d);0.68.2 相对 0.68.1 十三件 additive:`SEMA_SEGMENT_ID_KEY`(CC-01 段身份键,§35f)/ `projectMcpPanel`+`mcpPanelLastLegDetail`+`projectMcpSection`(CC-03 `/mcp` 面板读视图,§35g)/ `resolveTextSegmentAuthority`/`createTextSegmentLedger`(L-318 `text_end` 权威段替换的判决单源 + print 形段账,详见 §35b/§35c)/ `memoryCaptureDeclarationField`/`MEMORY_CAPTURE_OFF`(L-316 会话级隐私声明的字面唯一铸点,§35d)/ `engineUrl`/`probeHealth`(L-61 件④ SDK 纯工具面原样转口,§35d)/ `AgentClient`/`isApprovalRequestFrameV1`/`isApprovalRevokeFrameV1`(L-61 存量清零:SDK **wire 面**原样转口,§35e)。`0.68.1`/`0.68.0` 是 **952**,那批是相对 0.67.2 **二十件 additive、🔴 两件删除(BREAKING)**:additive = `TERMINAL_CAUSE_KINDS`/`isTerminalCauseKind`/`RUN_TERMINAL_NOT_SUCCESS_STATUSES`/`RUN_TERMINAL_STATUSES`(L-247 终态词两表分源,详见 §33b)/ `SEMA_SUBAGENT_USAGE_PARTIAL_KEY`/`subagentUsageIsPartial`(L-244 子代下界位自有名,§33g)/ `ASK_UNRESOLVABLE_CAUSES`/`readAskUnresolvable`/`DURABLE_MANDATE_SOURCES`/`readDurableGateUnavailable`(core 7.17.0 #709 ①② 两只通告事实窄读器,§33c)/ `WORKFLOW_PARK_TRUTH_UNREADABLE`/`WORKFLOW_PARK_NOT_PENDING`/`WORKFLOW_PARK_BINDING_BROKEN`/`WORKFLOW_PARK_REQUIRES_RUN_STORE`(四个单码常量 🔧 0.72.0 退役)/`WORKFLOW_PARK_REFUSAL_CODES`/`isWorkflowParkRefusalCode`/`readWorkflowParks`(core 7.17.0 #652 park 真相四码 + parks 三键读器,§33d)/ `ENGINE_STOP_REASONS`/`engineStopReasonToCc`(L-246 A13 停止原词映射下沉,§33g)/ `readCancelRequested`(L-230 读面,§33f);🔴 **删除两件** `TERMINAL_NOT_SUCCESS_STATUSES`/`TERMINAL_STATUSES`(随 L-247 两表分源更名成 `RUN_TERMINAL_*`,clean-cut **不留别名** —— 留一个别名等于让端可以继续按合起来的那张表读,分源就白做了,详见 §33b)。`0.67.0` 是 **934**,那批是相对 0.66.0 **七件 additive、🔴 两件删除**:additive = `CLASSIFIER_DENY_CAUSES`/`isClassifierDenyCause`/`classifierDenyCauseOf`/`classifierDenyCauseDetail`(core 7.14.0 退役 `classifierUnavailable` 之后的**拒绝面**继任读器与措辞,详见 §32b)/ `RULE_STORE_UNREADABLE_KINDS`/`isRuleStoreUnreadableKind`/`ruleStoreUnreadableDetail`(core 7.14.0 #688 C3 的规则店机制位三件,详见 §32d);🔴 **删除两件** `classifierUnavailableOf`/`classifierUnavailableDetail`(随 core 7.14.0 的 Retired keys 表整族退役,clean-cut 不留别名,详见 §32b;同批删的还有**型** `ClassifierUnavailableView`、卡位与帧位 `classifierUnavailable`、以及一条恒真的型面钉 `_askOriginWordsPin`)。`0.66.0` 是 **929**,那批是一件 additive、零删除:`readRunCostFacts`(终局成本事实的唯一读器:`costBreakdown` / `nested` 窄读 + 对账三段与两个判别位,终帧超集键与 chrome 对账臂共用它;详见 §31c);已发的 **0.65.x 十一件 additive、两件删除**:additive = `DECIDE_WORKFLOW_HOST_UNKNOWN`/`DECIDE_WORKFLOW_HOST_NOT_PARKED`/`DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED`/`DECIDE_WORKFLOW_LANE_CODES`/`readDecideReceipt`/`decideAcceptedNotResolved`/`decideRefusalFromError`(B-070 `/decide` 回执读面与三码人话,详见 §30h)/ `TERMINAL_NOT_SUCCESS_STATUSES`/`isTerminalNotSuccess`/`TERMINAL_STATUSES`/`isTerminalStatus`(L-215② 终局词汇单铸谓词,详见 §30j);🔴 **删除两件** `AUTO_MODE_BREAKER_CAUSES`/`classifierBreakerOf`(熔断族随 core 7.12.0 的 Removed(BREAKING) 整只退役,clean-cut 不留别名,详见 §30k②;同批删的还有**型** `ClassifierBreakerView` 与 `ClassifierStatusView.breaker` 一位)。`0.64.2` 是 **919**,那批是一件 additive、零删除:`readDenialLimitFallback`(限额回落卡的窄读器上公面,壳侧同判据副本退役,详见 §29③);`0.64.0` 是 **918**,那批是件①+件② 十三件 additive、零删除:`CLASSIFIER_STATUS_STATES`/`classifierBreakerOf`/`classifierStatusOf`/`classifierStatusDetail`(分类器状态面,详见 §28②)/ `THINKING_FORMATS`/`THINKING_FORMAT_WIRE_TWINS`/`THINKING_DISABLE_PROBE_ORDER`/`MODEL_PROBE_VERDICTS`/`PROBE_PROMPT`/`PROBE_MAX_TOKENS`(两个探针常量 🔧 0.72.0 退役)/`probeRequestBody`/`probeModelCapability`/`applyProbeToEntry`(模型思考能力探测,详见 §28①);`0.63.0` 是 **905**,那批是八件 additive、零删除:`projectServerGateKnobs`/`postureKnobSourceOf`/`postureSourceIsOperatorPinned`/`postureKnobDetail`/`POSTURE_SOURCE_WORDS`(S-178 三根 posture 旋钮读数,详见 §27b)/ `PERSISTED_RULE_BEHAVIORS`/`PERSISTED_RULE_BEHAVIOR_UNKNOWN`/`persistedRuleBehaviorOf`/`persistedRuleBehaviorLabel`/`revokeTargetFromPersistedRule`(三态规则身份,§27c)/ `engineIdentityOf`/`engineIdentityVerdict`/`engineIdentityChanged`/`engineIdentityChangedBy`/`ENGINE_IDENTITY_ANCHORS`(S-179 代际锚,§27d)/ `GATE_DENIED_BY_WORDS`/`gateDeniedByDetail`/`ASK_ORIGIN_WORDS`/`askOriginDetail`(门词汇 +2,§27e)/ `PERMISSION_RULE_ISSUE_CODES`/`RETIRED_PERMISSION_RULE_ISSUE_CODES`/`permissionRuleIssueDetail`(规则 lint 码表,§27f)/ `projectToolRoster`/`toolRosterNames`/`toolShimFromRoster`/`applyToolRosterDelta`(L-161 工具名册,§27g)/ `ENGINE_NOTICE_CODES`/`ENGINE_NOTICE_AUDIENCE`/`noticeAudienceOf`/`engineNoticeInCatalog`/`MCP_INJECTION_DROP_REASONS`/`readMcpInjectionDrop`(L-167 通告码册,§27h)/ `AUTO_MODE_UNAVAILABLE_CAUSES`/`AUTO_MODE_BREAKER_CAUSES`/`classifierUnavailableOf`/`classifierUnavailableDetail`(件⑧ 分类器不可用事实,§27h2);`0.62.0` 是 **869**,那批是五件 additive、**零删除**:`capForDisplay`(呈前消毒 + 封长的共用铸点,详见 §26⑦)/ `SEAT_SEND_MESSAGE_KEY_ORIGINS`(座位载荷逐键出身表,详见 §26③)/ `configureSubagentContentStore`+`subagentContentStoreConfig`+`SUBAGENT_CONTENT_STORE_DEFAULTS`(子代内容账本字节预算,测试钩 `__resetSubagentContentStoreConfigForTests` +1,详见 §26②);`0.61.0` 是 **864**,那批是三件 additive、**零删除**:`projectReadFacePosture`/`readFacePostureDetail`/`readFaceDisagreement`(S-167 READ 容纳面 operator 读器,详见 §25);`0.60.0` 是 **861**,那批是二十五件 additive、**零删除**:`readRunTerminal`/`runTerminalCode`/`runTerminalGateKind`/`runTerminalGateToolName`/`isReviewPark`/`REVIEW_PARK_GATE_KINDS` 六件终局因由读器 + `gateOutcomeOf`/`isDeniedGate`/`gateDeniedBy`/`gateApprover`/`isApprovalWindowExpiredGate`/`isDenialLimitAutoDeniedGate`/`isParkSlaExpiredGate`/`isHumanSettledGate` 八件门记录读器 + `projectWriteProtectionCapability`/`noteEngineCapsForWriteProtection`/`observedWriteProtection`/`forgetWriteProtectionReading`/`writeProtectionDoctorDetail`/`projectWriteProtectionPosture`/`writeProtectionPostureDetail` 七件写保护读面(测试钩 `__resetWriteProtectionReadingsForTests` +1)+ `readWireErrorCode` + 真机边界①的两件 `isGateParkedToolEnd`/`GATE_PARKED_ERROR_CODE` + 异源复审逼出的 `engineCapsGeneration`;`0.59.0` 是 **836**,那批是八件 additive:`RULE_OFFERS_ABSENCE_REASONS`/`DENIAL_LIMIT_KINDS` 两张闭词表再导出 + `engineCapValue` 能力位四态通用读口 + `projectSqlEngineCapability`/`observedSqlEngine`/`noteEngineCapsForSqlEngine`/`forgetSqlEngineReading`/`sqlEngineDoctorDetail` 五件 SQL 姿态读面(测试钩 `__resetSqlEngineReadingsForTests` +1);`0.58.0` 是 **828**,那批是三件 additive:`RULE_OFFER_MATCHES`/`RULE_OFFER_BATCH_MEMBER_KINDS`/`RULE_OFFER_UNCOVERED_REASONS` 三张闭词表再导出 + `RESUME_REFUSAL_CODES`/`RESUME_PLACEMENT_MISMATCH`/`resumeRefusalFromError`/`resumeRefusalContent` 四件文案铸点;`0.57.0` 是 **821**;`0.56.0`/`0.55.0` 是 **815**;已发 `0.54.0`(design/385 十件 additive 含 `AUTHORITY_ENVELOPE_TAGS` 🔧 0.72.0 退役);`0.52.0` 是 **805**(L-69⑨ 两件);`0.51.0` 是 **803**;`0.50.0` 是 **800**(S-81 五件);`0.49.0` 是 **795**;`0.48.0` 是 **794**;npm `0.47.0` 是 **790**,`0.46.0` 是 **787**,`0.44.0` 是 **783**,`0.43.1`/`0.43.0` 是 **776**,`0.42.0` 是 **771**,`0.41.0` 是 **767**,`0.39.0` 是 **766**,`0.38.0` 是 **764**;`0.37.0` 是 **753**,见 `CHANGELOG.md`) | `scripts/public-export-baseline.json` 的 `count` / `testHookCount` —— **别手抄进别处,以该文件为准** |
|
|
@@ -246,7 +246,7 @@ type EventProjection =
|
|
|
246
246
|
`meta`(流首帧身份信号,SDK/传输层自消费)· `file_link` / `prompt_assembled` / `model_usage` /
|
|
247
247
|
`config_assembled`(引擎可观测/审计面,CC transcript 无对位物;context_usage 自 0.71.0 CC-08 ③ 起**进切片**为 chrome 臂,不再在本表,见 §42)·
|
|
248
248
|
`needs_review`(壳消费的是 `done{status:'needs_review'}` 终帧,事件形重复且更早)·
|
|
249
|
-
|
|
249
|
+
(compaction_outcome 自 0.75.0 CC-89 起**进切片**为 chrome 臂,不再在本表,见 §74)·
|
|
250
250
|
`tool_approval` / `tool_approval_complete`(**不是丢帧**:它们走
|
|
251
251
|
`hitl/toolApprovalWire.isToolApprovalFrame` + `hitl/frameRouter` 那条审批卡链;在这里投一条 transcript 行
|
|
252
252
|
只会让同一只 ask 出现两次)· **`error`**(见下,单列)。
|
|
@@ -1487,7 +1487,7 @@ CHANGELOG 0.29.0「已知局限」段与相应 JSDoc 都有成文。**别在读
|
|
|
1487
1487
|
| **P-3** | med | `approval_request`(design/172 流内审批开卡帧)在本包**零消费口** ⇒ `dropped('unsupported_arm')`(有痕、没人接) | `src/adapter/downstream/eventToSdkMessage.ts` 的 `case 'approval_request'` | 存量路径今天仍能决断(legacy `tool_approval` 腿在,同一只 ask 出两帧,顺序钉死「先 legacy、后 `approval_request`」)。🔴 **但降级路径不保证**(逐字):legacy respond 是 **live-only + same-replica**(错副本 404),重连时 pending 卡靠 `approval_request` preamble 对账 —— 「收到 legacy 帧后断线、按 `Last-Event-ID` 重连只再看到 `approval_request`」以及**非粘性多副本部署**这两条路上,今天只能等窗口到期 → park/deny。**多副本 worker 上这是已知缺口不是环境问题** |
|
|
1488
1488
|
| **P-4** | med | **`approval_revoke` 在 SDK union 里连成员都没有**(SDK 顶注:known asymmetry,`Registering it is an open item for the next batch`)⇒ 本包不可能有 case ⇒ 运行期落 `dropped('unknown_arm')`;审批链也看不见它(`isToolApprovalFrame` 只认两帧)。全仓 `grep -rn "revoke"` = **0** | `src/adapter/downstream/eventToSdkMessage.ts` 的 `default` 臂;`src/hitl/toolApprovalWire.ts` 的 `isToolApprovalFrame` | 🔴 **引擎撤卡时本包不会替你撤那张卡** —— 被撤的 ask 会一直留在屏上,直到它自己的 5 分钟 TTL / deny 路径触发。要 revoke 语义的端只能自己接 raw named-SSE 腿并撤自己的卡(`unknown_arm` 的 drop 至少留了一行痕) |
|
|
1489
1489
|
| **P-5** | 真缺口(未定级) | **durable 重放腿上,一条被重放的 `question` 今天不会再打开覆盖层** —— 覆盖层的入口是 `liveQuestionStore` 的 **live demux 写口**,不是投影函数。交互 REPL 无损,「断线后按 `Last-Event-ID` 续读」场景下是真缺口。补它属**行为面**改动(先要答「重放一条已过 5min TTL 的问题该不该弹窗」),按宪法三问单独走 | `src/adapter/downstream/eventToSdkMessage.ts` 的 `question`/`question_complete`/`elicitation`/`elicitation_complete` 臂(缺口逐字记在该处);`src/liveQuestionStore.ts` 头注(`LIVE-ONLY + SAME-REPLICA … No durable resume anchor`) | `respondToQuestion` 当 best-effort 用(404 = 「已经放掉了」,dismiss,**绝不重试**);重连后的恢复走 **409 自愈树 + 自己的 `/v1/approvals` 列举**,**不要**指望重放的 `question` 帧能弹出覆盖层 |
|
|
1490
|
-
| **P-6** | low |
|
|
1490
|
+
| **P-6** | ~~low~~ ✅ 0.75.0 已闭 | ~~`compaction_outcome` 在本切片 `not_in_slice`,压缩失败对用户不可见~~ —— 0.75.0(CC-89)起投为内部臂 + chrome 臂 `compaction_outcome`,转录面仍零行(不编 transcript 形),见 §74 | `src/adapter/downstream/eventToSdkMessage.ts` `compactionOutcomeProjection` / `src/adapt/arms.ts` `compactionOutcomeArm` | 端接 chrome 臂后压缩失败可见;不接 = 同旧 |
|
|
1491
1491
|
| **P-32** | 在册局限(0.36.0 两 wire 键过境后的**辖域**,非缺陷) @cli @web @desktop | **两键各只有一条腿,别按「两面能对上」写码**。① **`requiresRealApproval`**(#283)与 🆕 **`inputHasBidi`**(#341,0.43.0)**同族**:两位都只在**活卡帧**腿(`ToolApprovalFrame` → `ApprovalCardRequest`);**耐久腿零 stamp** —— sdk 7.1.0 / **server 7.46.0 fixture 重验**的`PendingCheckpoint` / `riskDescriptor` 都没有这两位(server 那份在**卡内**:`risk.requiresRealApproval` 是**恒在布尔**、`inputHasBidi` 是卡上的在场位,都不是行上的键),包侧刻意不猜载体名。🔴 **「帧上没有」与「卡上是 false」是两条不同的陈述,别互相推导**(server `ApprovalCardSchema` 顶注逐字)。② **`checkpointId`**(#285 件2):只在 **409 `conflict.session_active_run` 体 + 其 SSE done 帧**的 `pendingGate`;另外三条 park 读面(`/v1/assistant/inbox`、`GET /v1/approvals`、`/v1/approvals/stream`)**都没有**这一格(后两条要给 checkpoint 表反范式一列 = SQL 面双库门,属另一批) | `src/hitl/toolApprovalWire.ts`(帧腿 stamp / durable 腿刻意零 stamp,两处 JSDoc 逐条写明理由)· `src/adapter/runStream.ts`(`ActiveRunPendingGate.checkpointId` + `pendingGateIsProvablyDifferent`)· 行为钉:`run-durable-card-display-keys-test.mjs` ⑨ 段(四种最像的载体名摆在行上,卡入参一个都不许长出来)· `run-selfheal-reopen-test.mjs` G1/G1b | ① **`requiresRealApproval` 在场 ⇒ 一切自动放行让位**(记住的规则 / `allow_session` / bypass 姿态),**缺席绝不读成 `false`**(缺席 = 不是安全类 ask **或** 老 server,两者同形不猜);durable 卡上今天**恒缺席**,别据此认为「durable 门都不是安全类」。② **`checkpointId` 只做两件事**:落日志/排障关联,以及经 `pendingGateIsProvablyDifferent(prev, next)` 做**单向**判断「id 变了 ⇒ 不是刚才那一行」。🔴 **`false` 是「证不出」不是「同一道门」**,🔴 **绝不**当跨调用去重键(server 选行是**无序 `LIMIT 1`**、同 session 可并存多条 pending 行 ⇒ 同一情形连续两次 409 可能报不同 id;也可能 id 不变而 `activeTaskId` 已换),🔴 **绝不**拿它去 join durable 队列行(必然落空,且落空与 legacy 行同形)。缺席是**三成因合流**(legacy 行 / 值没过 server 信任边界校验 / 整只材料读取失败),读作「不知道这道门叫什么」 |
|
|
1492
1492
|
|
|
1493
1493
|
### 7b. 决断链缺口
|
|
@@ -9254,3 +9254,55 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
|
|
|
9254
9254
|
3. peer 不动;core <7.24.0 ⇒ `_sema_freed_tokens` 缺席。
|
|
9255
9255
|
|
|
9256
9256
|
**包侧缺口:** ① CC-74 mcpProbe 候 server S-481;② CC-81 sdk 9.8.0 换钉 + K-04 `FleetWorkflowRow.errorCode?`(sdk 9.9.0,窗 10-03)随下一 minor;③ RH-2 第二步候排序;④ CC-36 候 core #874;其余同 §72。
|
|
9257
|
+
|
|
9258
|
+
## §74 🆕 0.75.0 压缩的非 compacted 结局上 chrome 面(CC-89)+ peer sdk 地板 >=9.8.1(CC-81);minor
|
|
9259
|
+
|
|
9260
|
+
> **minor**:① 新内部臂 `compaction_outcome` 进 `INTERNAL_SDK_ARM_TYPES`(自建 print / stream-json 出口的端必须先表态);② peer `@sema-agent/sdk` 地板 `>=9.7.1` → `>=9.8.1`。型面 additive(`ChromeEvent` +1 臂;值导出零增,公面计数不动);零 wire 新键(帧由引擎铸,sdk ≥4.0.1 已有型)。
|
|
9261
|
+
|
|
9262
|
+
### 74a. 处置表
|
|
9263
|
+
|
|
9264
|
+
| # | 面 | 本包做了什么 | 端要做什么 |
|
|
9265
|
+
|---|---|---|---|
|
|
9266
|
+
| S-0 🔴 **peer** | `@sema-agent/sdk` 地板 `>=9.7.1` → `>=9.8.1` | 四处同批抬齐 | 换钉 `^0.75.0` 的端把自己的 sdk 钉抬到 ≥9.8.1;<9.8.1 装本版只收 peer 警告,不改行为 |
|
|
9267
|
+
| S-1 🔴 | 内部臂 `compaction_outcome`(转录流里的新 `type`) | **added** 进 `INTERNAL_SDK_ARM_TYPES` | 🔴 自建 print / stream-json 出口的端:换钉**之前**给它加处置(吞,或转成自己面上的合法帧)。出口若是「逐型手列 + 末尾兜底原样透传」的形,不加 = 越界帧落到 stdout。建议把兜底前那一步改成按 `INTERNAL_SDK_ARM_TYPES.has(type)` 默认吞 —— 以后包每加一条内部臂都不再漏 |
|
|
9268
|
+
| S-2 | chrome 臂 `compaction_outcome` | **added**(`required:false`;`ChromeEvent` 联合 +1 成员) | 🔴 **编译迁移**:chrome 消费者若是穷举 switch(`default` 里 `never` 断言)或 `Record<ChromeArmKind, …>` 完整映射,换钉即编译红 —— 必须新增 `compaction_outcome` 分支(显式忽略或渲染都行);`required:false` 只说消费义务可选,不解除 TypeScript 穷举。运行期开集容忍的消费者(`default` 放行)零改。渲的话:一条可见提示(HUD / 通知行),`outcome` 原词带 default 臂;不渲 = 压缩失败继续对用户不可见 |
|
|
9269
|
+
| S-3 | `Capabilities.deviceExecutor.management` | 读器零行为变化;门钉 sdk 声明形 | 零改 |
|
|
9270
|
+
| S-4 🔴 | 面板:短命子代的最终用量(0.74.5 首见即终态零事件的代价面) | **fixed**:结过的行再来终态帧 ⇒ 恰一条 `fleet-row` 交用量、不再第二次 `end`;反序先缓后放 | 零改;消费端对已 ended 的行收到 `fleet-row` 要**更新用量、不改状态、不重开行**(cli 现行即如此) |
|
|
9271
|
+
|
|
9272
|
+
### 74b. 缺席语义(逐键)
|
|
9273
|
+
|
|
9274
|
+
- `outcome`:必在,引擎**开集**原词(见过的:`mooted` / `failed`);按成员渲染必须带 default 臂,认不得的词照原词显示,别丢帧、别折成「失败」。
|
|
9275
|
+
- `trigger` 缺席 = 引擎没说(不是 `auto`);已知 `auto` / `manual` / `forced`,同为开集。
|
|
9276
|
+
- `reason` 缺席 = 没有说明文本(不编句);在场时是引擎说明文本(上游已脱敏),渲前仍按宿主自己的不可信文本纪律处理。
|
|
9277
|
+
- `eventId` 缺席 = 这条腿没带幂等键;重放去重只能在带键时做。
|
|
9278
|
+
- `laneProof.lane === 'subagent'` = 某只子代的压缩结局,别渲成主会话的。只能靠 `sourceTaskId` / `bgAgentId` 归因的帧**本包不发**(KL-22)。
|
|
9279
|
+
- 🔴 本臂**不是终态**:任务还在跑,别据它收 spinner / 判 run 结束。成功压缩不走本臂(权威 = 转录的 `compact_boundary`)。
|
|
9280
|
+
- 面板行结过之后再收到的 `fleet-row`:用量到了(同代)或新一代(随后必跟 `end`);缺席 `end` = 同代,不是行重开。判不出代际(帧与结过的记录都不带周期键)按同代处理 —— 真字节里子代行恒带周期键、通知 `end` 带 seq,判不出只在 root 形行上发生(KL-25)。
|
|
9281
|
+
- 补注(§73 的 `_sema_freed_tokens` 同理):判缺席一律 `=== undefined`。wire 帧上缺席是整键省略,进程内对象上可能是键在、值 `undefined` —— `in` / `hasOwnProperty` 在两面读数相反;`0` 是真值不是缺席。
|
|
9282
|
+
|
|
9283
|
+
### 74c. 黑盒判据骨架
|
|
9284
|
+
|
|
9285
|
+
- **G1(CC-89 交互面)**:手动压缩撞任务收尾(引擎出 `compaction_outcome{outcome:"mooted"}`)⇒ 宿主收到恰一条 chrome `compaction_outcome`,`outcome` 逐字;转录面零新增行。
|
|
9286
|
+
- **G2(CC-89 print 面)**:同一场景在 stream-json 出口 ⇒ stdout 零条 `type:"compaction_outcome"` 行(端已表态);0.74.5 基线:帧在投影口即 `not_in_slice`,两面都零。
|
|
9287
|
+
- **G3(CC-89 lane)**:子代内压缩失败(帧带**非空串** `parentToolCallId`)⇒ chrome 的 `laneProof.lane === "subagent"`,主会话 HUD 不出「主会话压缩失败」;父键空串 ⇒ 判子流但构不成 lane ⇒ 不发。
|
|
9288
|
+
- **G4(CC-81)**:端装 sdk 9.8.1 + 本版 ⇒ 零 peer 警告;`deviceManagementVerbsAvailable` 四态读数与 0.74.5 逐位同。
|
|
9289
|
+
- **G5(W2)**:子代在两拍之间起步并结束(从没投影过 running)⇒ 面板那一行 `state:ended` 且 `totalTokens` / `toolUses` 在场(0.74.5 红基线:两位空);`end` 恰一次。
|
|
9290
|
+
|
|
9291
|
+
### 74z. 逐键处置表
|
|
9292
|
+
|
|
9293
|
+
| # | 键 / 面 | 处置 | 坐标 / 理由 |
|
|
9294
|
+
|---|---|---|---|
|
|
9295
|
+
| 1 | `compaction_outcome.outcome` | **consumed**(原词) | `src/adapter/downstream/eventToSdkMessage.ts` `compactionOutcomeProjection` → `src/adapt/arms.ts` `compactionOutcomeArm` |
|
|
9296
|
+
| 2 | `compaction_outcome.trigger` / `.reason` | **consumed**(非空串才在场) | 同上 |
|
|
9297
|
+
| 3 | `compaction_outcome.eventId` / `.parentToolCallId` | **consumed**(幂等键 / lane 证明) | 同上 |
|
|
9298
|
+
| 4 | 只带 `sourceTaskId` / `bgAgentId` 的帧 | **declined**(不发 chrome) | `LaneProof` 没有后台子代的诚实形;KL-22 |
|
|
9299
|
+
| 6 | 面板短命子代最终用量 | **fixed** | `src/panelRunningHistory.ts`(ended 账 + 缓行)/ `src/fleetAgentPanelProjection.ts` 终态分支 / `src/engineAgentPanelStore.ts` 漏斗 end 四路径 |
|
|
9300
|
+
| 5 | `Capabilities.deviceExecutor.management` | **consumed**(0.74.2 起;读器仍按不可信结构读,本版由门 T1–T7 钉 sdk 声明形,读器与声明的关联只在门) | `src/deviceExecutorManagementCapability.ts` |
|
|
9301
|
+
|
|
9302
|
+
### 74y. 🔴 三端升级必读(固定段式,[C295])
|
|
9303
|
+
|
|
9304
|
+
1. 换钉 `^0.75.0` **之前**:自建 print / stream-json 出口给内部臂 `compaction_outcome` 加处置(S-1);同时把 sdk 钉抬到 ≥9.8.1。
|
|
9305
|
+
2. 交互面:穷举型 chrome 消费者(`never` 断言 / 完整映射)换钉后**必须**补 `compaction_outcome` 分支才能编译(显式忽略即可);要渲就带 default 臂渲 `outcome` 原词、subagent lane 不渲进主会话。不渲 = 与 0.74.5 同(压缩失败不可见),不属行为丢失。
|
|
9306
|
+
3. 面板:结过的行再收到 `fleet-row` = 用量到了,更新用量、不改状态、不重开行(cli 现行即如此);其余零变化:转录面零新增行;device 读器四态读数不变。
|
|
9307
|
+
|
|
9308
|
+
**包侧缺口:** ① CC-74 mcpProbe 候 server S-481;② K-04 `FleetWorkflowRow.errorCode?` 候 sdk 9.9.0(窗 10-03);③ RH-2 第二步候排序;④ CC-36 候 core #874;⑤ 后台子代的压缩结局无 lane 可挂(KL-22);其余同 §73。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/client-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.75.0",
|
|
4
4
|
"description": "Client-side session runtime shared by every sema human client (TUI / web / desktop): sema wire frames (AgentEvent) -> CC session vocabulary (SDKMessage) with dual-plane output (transcript/chrome), deterministic transcript ids, lane discipline as a type, and the notification/dedup ledgers. Every CC-skin shape is collected here so the wire itself stays neutral. Renamed from @sema-agent/wire-cc-adapter (0.1.x).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@sema-agent/agent-types": ">=0.3.0",
|
|
34
|
-
"@sema-agent/sdk": ">=9.
|
|
34
|
+
"@sema-agent/sdk": ">=9.8.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@sema-agent/agent-types": "^0.3.0",
|
|
38
38
|
"@sema-agent/core": "~7.23.0",
|
|
39
|
-
"@sema-agent/sdk": "^9.
|
|
39
|
+
"@sema-agent/sdk": "^9.8.1",
|
|
40
40
|
"@sema-agent/settings-schema": "^2.0.0",
|
|
41
41
|
"esbuild": "^0.27.4",
|
|
42
42
|
"typescript": "^6.0.2"
|