@sema-agent/client-core 0.73.5 → 0.74.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 +33 -0
- package/README.md +4 -2
- package/dist/engineAgentPanelStore.d.ts +29 -0
- package/dist/engineAgentPanelStore.js +31 -1
- package/dist/fleet/fleetLedger.d.ts +20 -0
- package/dist/fleet/fleetLedger.js +103 -10
- package/dist/fleetAgentPanelProjection.d.ts +2 -0
- package/dist/fleetAgentPanelProjection.js +42 -7
- package/dist/hitl/frameRouter.d.ts +6 -1
- package/dist/hitl/frameRouter.js +17 -1
- package/dist/hitl/parkResolver.js +10 -2
- package/dist/hitl/toolApprovalWire.d.ts +29 -1
- package/dist/hitl/toolApprovalWire.js +17 -1
- package/dist/notifications.js +3 -0
- package/dist/subagentContentStore.d.ts +2 -0
- package/docs/INTEGRATION-CLIENTS.md +97 -8
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -49,6 +49,39 @@
|
|
|
49
49
|
> 挡住 ⇒ 本批把它机械化——④a0 对 `pending` 行**要求段头已是日期形**(`(未发布)` 直接红),阶段一
|
|
50
50
|
> commit 漏转在发布前就红,不再靠人记。
|
|
51
51
|
|
|
52
|
+
## 0.74.1(2026-09-19)
|
|
53
|
+
|
|
54
|
+
> 主题:**审批卡的无决断收口**(CC-67)+ **流内帧腿的结局回交**(CC-68)+ headless 处置成文。**patch**:型面纯 additive(+1 常量,公面 1045 → 1046;`ApprovalCardDecision` +1 联合成员;`ToolApprovalFrameOutcome` / `FsApprovalOutcome` 各 +1;`AskGateWireDeps` +1 可选回调;零 wire 新键;peer 不动)。
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- **卡口结局 `{ kind: 'retracted' }`(CC-67)**:宿主把一张**已经没有决断口**的卡撤掉(换会话 / 换引擎 / 跟踪器报 gone)时用它。包见到它**一个字节都不发**:流内帧腿 respond 零次、悬挂 ask 的盲卡 / 全卡同路、durable-park 腿 decide 零次;结局 `decision: 'unresolved'` + `retracted: true`(`FsApprovalOutcome` 为 `kind: 'retracted'`),不计 decided,ask 在引擎上照旧挂着。此前撤卡三形(`aborted` / `failed` / `deny`)在决断链上都落 deny 并真 POST —— 撤一张卡等于替用户 POST 一次他没做过的拒绝,悬挂的子代 ask 会被误拒。🔴 `aborted` 语义**不动**(用户放弃 = 拒,照旧 deny 真 POST);新值不复用老词。常量单源 `RETRACTED_CARD_DECISION_KIND`;park 解析器对 durable 腿的撤卡按 fail-soft 收口并写明真因(run 照旧 parked,别处仍可决)。
|
|
59
|
+
- **`AskGateWireDeps.onToolApprovalOutcome?(frame, outcome)`(CC-68)**:路由把流内帧腿每次决断的结局交回宿主(恰一次;撤卡也回交),宿主据此直接判「这一发落没落定」,孤儿认领回收不必再靠间接判据。缺席零变化;回调抛错 / async reject 被吞。
|
|
60
|
+
- 门:新 `scripts/run-approval-card-retract-test.mjs`(16 格);变异反证六枚逐格见红。
|
|
61
|
+
|
|
62
|
+
## 0.74.0(2026-09-19)
|
|
63
|
+
|
|
64
|
+
> 主题:**peer sdk 地板抬到 `>=9.7.1`** + **审批卡 `readRootCandidate.covers: "exact"` 过境**(CC-64)+ **面板事件周期身份**(CC-66)+ **fleet 行离场读口**(CC-65)+ 三版缺口行更正。**minor**:peer 地板抬升是非 additive 变化(<9.7.1 的宿主装本版会收到 peer 警告);型面本身纯 additive(+1 函数,公面 1044 → 1045;`ReadRootCandidateView` / `EngineAgentPanelEvent` 两臂 / `FleetAgentRowLike` / `FleetLedgerHooks` / `BgTerminalFacts` 各加可选位;零 wire 新键)。
|
|
65
|
+
|
|
66
|
+
### Changed(🔴 peer)
|
|
67
|
+
|
|
68
|
+
- **peer `@sema-agent/sdk` 地板 `>=9.6.0` → `>=9.7.1`**(peerDependencies / lockfile / README 地板句 / `run-sdk-floor-test.mjs` 的 `FLOOR` 四处同批抬齐;devDep 自 0.73.3 起已是 `^9.7.1`)。理由:sdk 9.7.x 追平的六处型面(`Capabilities.approvalsStreamLive` / `.executionLane`、`LivePendingRow.frame`、`live_*` 审批流事件、`gates[].toolCallId`)是本包 0.73.3 起的编译基线;消费端实装已全部在 9.7.1,`>=9.6.0` 这条线没有任何物料证明跑过(public-surface 门 C-CC-3 当场红)。承诺的下线必须有见证,所以抬到有见证的那条。
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
|
|
72
|
+
- **`readRootCandidate.covers: "exact"` 被本包剥掉**(CC-64;core ≥7.22.0 / server ≥7.85.0;core 7.23.0 起它真的到得了卡)。在场 = `dir` 这一串**不是目录**,是命令点名的那条路径本身(`cat ~/.gitconfig` 的 `~/.gitconfig`);上游契约的硬话是「消费端必须逐字添加这一串」—— 展成目录模式授不到任何东西、卡还在。本包的窄读此前只铸 `dir` / `clearsThisAsk` 两键形,于是端在结构上分不出两种出路,只能一律按目录渲。现在:`ReadRootCandidateView` +`covers?: 'exact'`,在场逐字上卡;**缺席 = 目录出路,卡上的形逐字节同旧**;出闭集(别的词 / 空串 / 非字符串 / 键在场而值 undefined)⇒ **整只座不过境**,不是摘掉坏成员其余照发(两种读法在人那一侧是相反的动作)。
|
|
73
|
+
- **更正 0.73.3 / 0.73.4 / 0.73.5 三版接入档缺口行的一句话**:「缺席上报附 `removeReason`(候壳透传)」写反了。宿主一直把 fleet 原始帧原样交给账本,`task_remove` 帧上的 `removeReason` / `cycleSeq` 逐字到得了本包;丢键的是本包。本版补读口(下)。
|
|
74
|
+
|
|
75
|
+
### Added
|
|
76
|
+
|
|
77
|
+
- **面板事件的周期身份(CC-66)**。后台 agent 同一个 `taskId` 可以复活;`EngineAgentPanelEvent` 的 `end` 臂此前只有 `taskId` / `isError` / `report`,上一周期迟到的 `end` 会把复活后的新一轮结掉(壳因此不敢把状态翻回 running)。现在 `fleet-row` 臂 +`cycleSeq?`,`end` 臂 +`cycleSeq?` / `startedAt?`:fleet 行车道在 wire 给了的时候带(`cycleSeq` = 引擎的 stop-cycle 计数,与后台通知的 `seq` 同域同轴;`startedAt` = launch 锚),通知车道在通知真带 `seq` 时带 `cycleSeq`;**流内 close 臂没有这个概念,恒缺席**。🔴 缺席 = 这一行没有代际概念(同步委派子代 / workflow agent / 顶层 run / 老引擎),**不是第一代**,绝不补 1。
|
|
78
|
+
- 判据单源 `isStaleEngineAgentPanelEnd(end, current)`:两边都有 `cycleSeq` ⇒ 只比它(小 = 陈旧);否则两边都有 `startedAt` ⇒ 比它;任一边判不出 ⇒ **不陈旧**(现行为;不因缺席丢一条真终态)。陈旧的 `end` 消费端忽略(不 settle、不写 report、不摘所有权);终报异步回写同理按发起时记下的周期核。
|
|
79
|
+
- `cycleSeq` 变了 = 新周期:投影侧用量粘性不跨周期继承(与 launch 锚变了同一处置);事件缓冲的逐键合并也以它为屏障。`FleetAgentRowLike` +`cycleSeq?`(把 `FleetTaskView` 原样交进来即得)。
|
|
80
|
+
- 🔴 **前代迟到帧在包内就挡住**(异源对抗复审两轮):投影台账上已是更新的一代、这一帧却是更早的一代 ⇒ 整只跳过(不发 `fleet-row` 去改写消费端记的身份、不发 `end`、不动台账)—— 判定与 `isStaleEngineAgentPanelEnd` **同一条规则**(cycleSeq 优先、startedAt 回退,只带 startedAt 的前代帧同样挡住);settle 去重按周期(已 settle 的是上一代、来的是可证更新的一代 ⇒ 照发);周期身份推进本身算变化(用量等键全不变、首帧就是终态,也先发 `fleet-row` 让端记下身份再发 `end`);账本的通知退休腿与留存池更新对「通知 `seq` 早于行 / 留存条目 `cycleSeq`」的前代通知一律不改写,也不入终局事实台账;行退场后账本仍按 task 记**周期水位**(有界),零命中的前代通知同样挡住;终局事实台账带 `cycleSeq`(通知报了才记),洗绿保护只在同周期内生效 —— 第 1 代 failed 在账、第 2 代 completed 到是新事实不是洗绿。身份的沿用与用量的沿用分开:同周期重复的终态帧不抹掉记住的 `startedAt` / `cycleSeq`。
|
|
81
|
+
- **fleet 行离场读口(CC-65)**:`FleetLedgerHooks` +`onTaskRemoved(removal)`,`FleetTaskRemoval = { id, removeReason?, cycleSeq?, stale?, unknownRow? }`。`removeReason`(开集原词;今天只有 `orphaned`)与 `cycleSeq`(被退那一代)在场才带。退的是**前一代**而账本里这一行已是更新的一代 ⇒ 前代迟到帧:**不删行**,读口照报并标 `stale`;账本本来就没这一行(晚连接者)⇒ 照报并标 `unknownRow`。回调抛错被吞(含 async 回调的 reject)。🔴 离场**不是终局证据**(契约附录 H):读口只陈述离场,本包不据它 settle;不装读口 ⇒ 行为逐字同旧。
|
|
82
|
+
- 门:新 `scripts/run-panel-cycle-identity-test.mjs`(57 格);`run-client-core-pure-test.mjs` +CC-64a–d。变异反证三 + 二十一枚逐格见红。
|
|
83
|
+
- `BgTerminalFacts` +`cycleSeq?`(additive)。
|
|
84
|
+
|
|
52
85
|
## 0.73.5(2026-09-19)
|
|
53
86
|
|
|
54
87
|
> 主题:**workflow 规模告警判定上收进包**(CC-58)+ plan review 陈旧重开卡作答的 outcome 措辞。**patch**:型面纯 additive(+8 常量 +3 函数,公面 1033 → 1044);零 wire 新键;peer 不动。
|
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.74.1
|
|
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.6.0`
|
|
70
|
+
- The declared floor is `>=9.7.1` (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.
|
|
@@ -313,6 +313,8 @@ public-surface guard checks that last one).
|
|
|
313
313
|
| `scripts/run-tool-disclosure-progress-projection-test.mjs` | The two wire arms sdk 9.6.0 adds — `tool_disclosure` (name-only tool census: open-set `policy`, `thresholdPercent` absent ≠ default, `deferred`/`activated` full snapshots) and `tool_progress` (one frame, two beats: Bash ticks carry an output tail with `totalLines`/`totalBytes` that come and go together; other tools carry only `elapsedSeconds`) — project to neutral internal arms plus chrome arms. Required keys missing ⇒ `malformed`; bad optional keys drop only themselves; the sub-flow three-key gate keeps child frames off the leader lane; both arms are `required: false` in the arm table with duties stated (the output tail is untrusted raw and must never be fed back to the model). |
|
|
314
314
|
| `scripts/run-mcp-panel-projection-test.mjs` | The `GET /v1/sessions/:id/mcp` panel reader (`projectMcpPanel`; server >=7.77.0 adds the optional `lastLegMcp` key) and the single wording mint for its "last leg" line. Absence of `lastLegMcp` is one literal sentence that never blames the engine version (a new session, a leg outside the retention window, a leg without a manifest and an older engine all look the same on the wire); a key that is present but unreadable is a different sentence plus a `lastLegMcpUnreadable: true` mark, never folded into absence. The `mcp[]` roster goes through the same reader as the live `wiring_manifest` third section, so a replayed roster and a live one have one shape. The two faces of the panel (`servers[]` and the last-leg roster) may legitimately differ, so the view carries no agreement flag and none of the five sentences mentions `servers`. Required keys are pinned to the SDK `openapi.yaml` component bytes **0.69.0:** `fetchMcpPanel` fetches the panel through the SDK client's own `sessions.mcp` call (same transport and auth as every other read) and projects it; transport failure, an unreadable body and an empty session id all come back as `undefined`, never as a fabricated empty panel 0.71.0 adds section K: `mcpEngineLegPresence(view)` — the engine-side MCP presence tri-state read only off the panel view (`unknown` when the view could not be read, never rendered as "no MCP configured") |
|
|
315
315
|
| `scripts/run-absence-fold-census-test.mjs` | A package-wide census of the "absence folded into a positive outcome" defect shape, so that fixing the six sites this release does not merely move the shape somewhere else. The defect is defined by position, not syntax: a fallback position (the unconditional tail return, the `default:` arm, the literal minted when there is nothing to pass on, the value returned from an error path) may only say `unknown` or stay absent, never a positive word. Detection walks the syntax tree of every source file, so comments, strings and multi-line spellings cannot hide or fake a hit, and covers five forms: the right arm of `??` / `||`, the else arm of a ternary, the first return of an explicit `default:`, a `catch` block or `.catch(() => …)` arrow returning a healthy value, and a function whose last statement returns a positive word after other returns. Every remaining hit must be registered with a written reason, an unregistered hit fails the gate naming the file and line, the registered count must equal the real count so a cleared site cannot leave a spare allowance behind, and the gate proves its own teeth behind a fence (a failed self-proof refuses to report any count): each form injected into an in-memory copy must add exactly one hit, two correct spellings are pinned as non-hits, and samples inside comments or strings do not count. It also pins the headline site: the fleet panel projection no longer mints an `end` with `isError: false` on absence |
|
|
316
|
+
| `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 |
|
|
317
|
+
| `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 |
|
|
316
318
|
| `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 |
|
|
317
319
|
| `scripts/run-approvals-stream-live-capability-test.mjs` | The engine's live-approval-push self-description (`capabilities.approvalsStreamLive`, engine ≥7.87.1), read the same four-state way as its four sibling capability readers: an absent key is reported as not reported (never folded into `false`), the value must be a strict boolean, and the one decision the feed consumer needs — whether it must keep pulling suspended asks itself — is answered by `livePendingNeedsReconcile`, which only says no when the engine explicitly says it pushes. |
|
|
318
320
|
| `scripts/run-model-facing-anchors-test.mjs` | Five places where model-facing engine text is parsed back into card slots: the task-output cursor semantics machine-readable key wins over the spool marker text (and its absence is never read as `full`), the `--- result (…) ---` line accepts a parenthesised note, the bash header accepts the engine's exit-note and image variants and carries the note into the same benign-exit slot the structured path uses, the notification seed scan treats both producers' terminal words as terminal, and the parked background-task phrase is recognised. |
|
|
@@ -94,10 +94,24 @@ export type EngineAgentPanelEvent = {
|
|
|
94
94
|
* 渲出 1h+ 假时长。消费端拿到即覆盖行的 startTime;缺席 ⇒ 老引擎,维持现状。
|
|
95
95
|
*/
|
|
96
96
|
startedAt?: number;
|
|
97
|
+
/**
|
|
98
|
+
* 0.74.0 —— 这一行的**代际号**(引擎的 stop-cycle 计数;fleet 行帧 `cycleSeq` 与后台通知 `seq` 同域同轴:
|
|
99
|
+
* 首次派发 = 1,每次复活 +1)。消费端把它记在行上,用 {@link isStaleEngineAgentPanelEnd} 判 `end` 是不是上一周期迟到的。
|
|
100
|
+
* 🔴 缺席 = 这一行**没有代际概念**(同步委派子代 / workflow agent / 顶层 run / 老引擎),**不是第一代**。
|
|
101
|
+
*/
|
|
102
|
+
cycleSeq?: number;
|
|
97
103
|
} | {
|
|
98
104
|
kind: 'end';
|
|
99
105
|
taskId: string;
|
|
100
106
|
isError: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* 0.74.0 —— 这条终态属于**哪一个周期**。同一个 taskId 可以复活;没有周期身份时,上一周期迟到的 `end` 会把
|
|
109
|
+
* 复活后的新一轮结掉。fleet 行车道与通知车道在 wire 给了的时候带;**流内 close 臂没有这个概念,恒缺席**。
|
|
110
|
+
* 读法单源:{@link isStaleEngineAgentPanelEnd}。缺席 ⇒ 判不出 ⇒ 按现行为 settle(不因缺席丢一条真终态)。
|
|
111
|
+
*/
|
|
112
|
+
cycleSeq?: number;
|
|
113
|
+
/** 0.74.0 —— 同上,launch 锚(epoch ms);只有 fleet 行车道带得出。 */
|
|
114
|
+
startedAt?: number;
|
|
101
115
|
/** The subagent's FINAL REPORT — the delegating Task/Agent card's `tool_end.output` text (only the
|
|
102
116
|
* explicit close arm carries it; the defensive sweeps settle without one). The consumer persists it
|
|
103
117
|
* on the row (task.result) + appends it to a live-viewed transcript (拍1 查看态 seed). */
|
|
@@ -117,6 +131,21 @@ export declare function markEnginePanelTaskResident(taskId: string): void;
|
|
|
117
131
|
export declare function clearEnginePanelTaskResident(taskId: string): void;
|
|
118
132
|
export declare function isEnginePanelTaskResident(taskId: string): boolean;
|
|
119
133
|
type Listener = (ev: EngineAgentPanelEvent) => void;
|
|
134
|
+
/** 周期身份的一格(`end` 事件上的,或消费端记在行上的当前周期)。 */
|
|
135
|
+
export interface EngineAgentPanelCycleIdentity {
|
|
136
|
+
readonly cycleSeq?: number;
|
|
137
|
+
readonly startedAt?: number;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* 0.74.0 —— 这条 `end` 是不是**上一周期迟到的**(单源判据,三端共用)。`current` = 消费端记在行上的当前周期
|
|
141
|
+
* (取自最近一条 `fleet-row` 的 `cycleSeq` / `startedAt`)。
|
|
142
|
+
* · 两边都有 `cycleSeq` ⇒ **只**比它:`end` 更小 ⇒ 陈旧;
|
|
143
|
+
* · 否则两边都有 `startedAt` ⇒ `end` 更早 ⇒ 陈旧;
|
|
144
|
+
* · 任一边判不出(流内 close 臂的 `end` / 没有代际概念的行 / 老引擎 / 坏形)⇒ **不陈旧** —— 按现行为 settle。
|
|
145
|
+
* 方向是宁可照旧也不因为缺席丢掉一条真终态。
|
|
146
|
+
* 陈旧的 `end`:忽略(不 settle、不写 report、不摘所有权)。
|
|
147
|
+
*/
|
|
148
|
+
export declare function isStaleEngineAgentPanelEnd(end: EngineAgentPanelCycleIdentity | null | undefined, current: EngineAgentPanelCycleIdentity | null | undefined): boolean;
|
|
120
149
|
export declare function publishEngineAgentPanelEvent(ev: EngineAgentPanelEvent): void;
|
|
121
150
|
/** Single consumer (the panel hook). Replays any buffered events, returns an unsubscribe. */
|
|
122
151
|
export declare function subscribeEngineAgentPanel(fn: Listener): () => void;
|
|
@@ -52,12 +52,42 @@ export function isEnginePanelTaskResident(taskId) {
|
|
|
52
52
|
const MAX_BUFFER = 200;
|
|
53
53
|
let listener = null;
|
|
54
54
|
const buffer = [];
|
|
55
|
-
/** 两条 fleet-row
|
|
55
|
+
/** 两条 fleet-row 都带同一种周期身份(launch 锚 / 代际号)且不相等 ⇒ 新周期(任一条没带 = 这一帧没说,不算变化)。 */
|
|
56
56
|
function launchAnchorChanged(prev, next) {
|
|
57
57
|
if (prev.kind !== 'fleet-row' || next.kind !== 'fleet-row')
|
|
58
58
|
return false;
|
|
59
|
+
if (prev.cycleSeq !== undefined && next.cycleSeq !== undefined && prev.cycleSeq !== next.cycleSeq)
|
|
60
|
+
return true;
|
|
59
61
|
return prev.startedAt !== undefined && next.startedAt !== undefined && prev.startedAt !== next.startedAt;
|
|
60
62
|
}
|
|
63
|
+
function cycleSeqOf(v) {
|
|
64
|
+
const n = v?.cycleSeq;
|
|
65
|
+
return typeof n === 'number' && Number.isInteger(n) && n >= 1 ? n : undefined;
|
|
66
|
+
}
|
|
67
|
+
function startedAtOf(v) {
|
|
68
|
+
const n = v?.startedAt;
|
|
69
|
+
return typeof n === 'number' && Number.isFinite(n) && n > 0 ? n : undefined;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 0.74.0 —— 这条 `end` 是不是**上一周期迟到的**(单源判据,三端共用)。`current` = 消费端记在行上的当前周期
|
|
73
|
+
* (取自最近一条 `fleet-row` 的 `cycleSeq` / `startedAt`)。
|
|
74
|
+
* · 两边都有 `cycleSeq` ⇒ **只**比它:`end` 更小 ⇒ 陈旧;
|
|
75
|
+
* · 否则两边都有 `startedAt` ⇒ `end` 更早 ⇒ 陈旧;
|
|
76
|
+
* · 任一边判不出(流内 close 臂的 `end` / 没有代际概念的行 / 老引擎 / 坏形)⇒ **不陈旧** —— 按现行为 settle。
|
|
77
|
+
* 方向是宁可照旧也不因为缺席丢掉一条真终态。
|
|
78
|
+
* 陈旧的 `end`:忽略(不 settle、不写 report、不摘所有权)。
|
|
79
|
+
*/
|
|
80
|
+
export function isStaleEngineAgentPanelEnd(end, current) {
|
|
81
|
+
const ec = cycleSeqOf(end);
|
|
82
|
+
const cc = cycleSeqOf(current);
|
|
83
|
+
if (ec !== undefined && cc !== undefined)
|
|
84
|
+
return ec < cc;
|
|
85
|
+
const es = startedAtOf(end);
|
|
86
|
+
const cs = startedAtOf(current);
|
|
87
|
+
if (es !== undefined && cs !== undefined)
|
|
88
|
+
return es < cs;
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
61
91
|
export function publishEngineAgentPanelEvent(ev) {
|
|
62
92
|
// 同 taskId 的任何主通道事实(tick / fleet-row = 行在场;end = 真终态)都让**缓冲里**那条缺席过期 —— 迟订阅的消费者
|
|
63
93
|
// 不许先恢复了行、再被一条旧缺席标成 unknown(已递达订阅者的缺席由订阅者按契约在这些事件上撤标)。
|
|
@@ -265,7 +265,27 @@ export type HookNoticeFrame = Extract<FleetFrame, {
|
|
|
265
265
|
* 开集只在本包加臂时扩,端按未知词兜底(`default` 当 `absent_parent` 一档处理最安全)。
|
|
266
266
|
*/
|
|
267
267
|
export type BgNotificationAcceptEvidence = 'server_fail_closed' | 'own_root' | 'session_anchor_untrusted' | 'own_parent' | 'absent_parent';
|
|
268
|
+
/**
|
|
269
|
+
* 0.74.0 —— 一条 fleet 行**离场**(`task_remove` 帧)的读口载荷。
|
|
270
|
+
* 🔴 离场**不是终局证据**:`task_remove` 在任何形态下都只说「这一行离场了」,结算的属主在 durable 侧;
|
|
271
|
+
* 要终局去读 run 面,本包不据它 settle。`removeReason`(开集原词;今天只有 `orphaned`)与 `cycleSeq`
|
|
272
|
+
* (被退那一代的代际号)**在场才带**,缺席不编。
|
|
273
|
+
*/
|
|
274
|
+
export interface FleetTaskRemoval {
|
|
275
|
+
readonly id: string;
|
|
276
|
+
readonly removeReason?: string;
|
|
277
|
+
readonly cycleSeq?: number;
|
|
278
|
+
/** 只在这条退场帧退的是**前一代**、而账本里这一行已经是更新的一代时在场:前代迟到帧,**行没有被删**。 */
|
|
279
|
+
readonly stale?: true;
|
|
280
|
+
/** 只在账本里本来就没有这一行时在场(晚连接者收到的退场帧;端可以直接忽略)。 */
|
|
281
|
+
readonly unknownRow?: true;
|
|
282
|
+
}
|
|
268
283
|
export interface FleetLedgerHooks {
|
|
284
|
+
/**
|
|
285
|
+
* 0.74.0 —— `task_remove` 帧的读口(见 {@link FleetTaskRemoval})。不给 = 行为逐字同旧(只删行)。
|
|
286
|
+
* 回调抛错被吞(fail-soft):宿主的渲染 bug 不许打断账本。
|
|
287
|
+
*/
|
|
288
|
+
onTaskRemoved?(removal: FleetTaskRemoval): void;
|
|
269
289
|
/**
|
|
270
290
|
* hook_notice 帧的**写 store** 半场(判定在 `classifyHookNoticeFrame`,本台账只做分发)。
|
|
271
291
|
* 返回值忽略;不给 = 该帧被静默丢弃(端没有承载面时的正确行为)。
|
|
@@ -8,7 +8,7 @@ import { clearBgTerminalFacts, getBgTerminalFacts, isOwnEngineRun, recordBgParen
|
|
|
8
8
|
import { rowIdTail } from '../workflow.js';
|
|
9
9
|
import { recordEngineTranscriptId } from '../subagent/engineDelegatedPrompt.js';
|
|
10
10
|
import { DEFAULT_SESSION_KEY } from '../sessionSlot.js';
|
|
11
|
-
import { TERMINAL_FLEET_TASK_STATUSES, projectTasks, projectWorkflows, wireParentId, } from './fleetProjection.js';
|
|
11
|
+
import { TERMINAL_FLEET_TASK_STATUSES, projectTasks, projectWorkflows, wireCycleSeq, wireParentId, } from './fleetProjection.js';
|
|
12
12
|
/** 终态行留存宽限窗(187 的 agents 页把完成会话留在列表;窗过即净,防长会话堆行)。 */
|
|
13
13
|
export const TERMINAL_RETAIN_MS = 60_000;
|
|
14
14
|
/** REF-CC-044(fleet2-06):per-sessionKey 注册表(W1 同款 `Map<sessionKey, T>` 形)。 */
|
|
@@ -126,6 +126,26 @@ export function createFleetLedger(hooks = {}, opts = {}) {
|
|
|
126
126
|
* settle 过 —— 在飞读面(`bgView.read`)对带标且未过窗的条目**继续按在飞计**(E4-7 解耦,
|
|
127
127
|
* 见 `EngineActiveBgTask.retiredByNotification` 顶注);行帧路径写入的条目从不带标。 */
|
|
128
128
|
const retained = new Map();
|
|
129
|
+
/**
|
|
130
|
+
* 0.74.0(异源对抗复审 R3)—— 每个 task 见过的最高代际(按行 id 尾段);**行退场后仍留**(有界 LRU):零命中的
|
|
131
|
+
* 前代通知(行已退场、留存已过窗)没有别的判据可挡,靠它挡在事实台账之外。
|
|
132
|
+
*/
|
|
133
|
+
const cycleWatermark = new Map();
|
|
134
|
+
const CYCLE_WATERMARK_MAX = 512;
|
|
135
|
+
function raiseCycleWatermark(tail, gen) {
|
|
136
|
+
if (gen === undefined || tail.length === 0)
|
|
137
|
+
return;
|
|
138
|
+
const prior = cycleWatermark.get(tail);
|
|
139
|
+
if (prior !== undefined && prior >= gen)
|
|
140
|
+
return;
|
|
141
|
+
cycleWatermark.delete(tail);
|
|
142
|
+
if (cycleWatermark.size >= CYCLE_WATERMARK_MAX) {
|
|
143
|
+
const oldest = cycleWatermark.keys().next().value;
|
|
144
|
+
if (oldest !== undefined)
|
|
145
|
+
cycleWatermark.delete(oldest);
|
|
146
|
+
}
|
|
147
|
+
cycleWatermark.set(tail, gen);
|
|
148
|
+
}
|
|
129
149
|
/** REF-CC-051(fleet2-13):畸形帧/通知早退计数(与同文件的策略性丢弃 debug 行对称留痕)。 */
|
|
130
150
|
let droppedMalformed = 0;
|
|
131
151
|
/** [2393] notif-F12:另两条丢弃路径的计数(未知帧型 / 隔离优先丢弃)。 */
|
|
@@ -290,6 +310,7 @@ export function createFleetLedger(hooks = {}, opts = {}) {
|
|
|
290
310
|
// REF-CC-039(fleet2-01):同一个字段只有一个铸点 —— 本地接收时刻,不是 `frame.ts`。
|
|
291
311
|
const receivedAtMs = nowFn();
|
|
292
312
|
taskMap.set(row.id, row); // POST-MERGE FULL row → replace by id
|
|
313
|
+
raiseCycleWatermark(rowIdTail(row.id), wireCycleSeq(row)); // 0.74.0:周期水位(退场后仍留)
|
|
293
314
|
rowMeta.set(row.id, { receivedAtMs });
|
|
294
315
|
debug(`[fleet-row] id=${row.id} parent=${row.parentId ?? '-'} agentType=${row.agentType ?? '-'}` +
|
|
295
316
|
` agentName=${row.agentName ?? '-'} name=${row.name ?? '-'} status=${row.status ?? '-'}` +
|
|
@@ -355,10 +376,42 @@ export function createFleetLedger(hooks = {}, opts = {}) {
|
|
|
355
376
|
}
|
|
356
377
|
break;
|
|
357
378
|
}
|
|
358
|
-
case 'task_remove':
|
|
359
|
-
|
|
360
|
-
|
|
379
|
+
case 'task_remove': {
|
|
380
|
+
// 0.74.0:退场帧带**被退那一代**的代际号。行已经是更新的一代(两边都报了且帧上更小)⇒ 这是前代迟到帧,
|
|
381
|
+
// 删了就把复活后的行抹掉 ⇒ 不删。任一边没报 ⇒ 判不出 ⇒ 现行为(删)。
|
|
382
|
+
const fr = frame;
|
|
383
|
+
const removedGen = typeof fr.cycleSeq === 'number' && Number.isInteger(fr.cycleSeq) && fr.cycleSeq >= 1 ? fr.cycleSeq : undefined;
|
|
384
|
+
const held = taskMap.get(frame.id);
|
|
385
|
+
const heldGen = held !== undefined ? wireCycleSeq(held) : undefined;
|
|
386
|
+
const stale = removedGen !== undefined && heldGen !== undefined && removedGen < heldGen;
|
|
387
|
+
if (!stale) {
|
|
388
|
+
taskMap.delete(frame.id);
|
|
389
|
+
rowMeta.delete(frame.id);
|
|
390
|
+
}
|
|
391
|
+
if (hooks.onTaskRemoved !== undefined) {
|
|
392
|
+
const reason = typeof fr.removeReason === 'string' && fr.removeReason.length > 0 ? fr.removeReason : undefined;
|
|
393
|
+
try {
|
|
394
|
+
const out = hooks.onTaskRemoved({
|
|
395
|
+
id: frame.id,
|
|
396
|
+
...(reason !== undefined ? { removeReason: reason } : {}),
|
|
397
|
+
...(removedGen !== undefined ? { cycleSeq: removedGen } : {}),
|
|
398
|
+
...(stale ? { stale: true } : {}),
|
|
399
|
+
...(held === undefined ? { unknownRow: true } : {}),
|
|
400
|
+
});
|
|
401
|
+
// 宿主给的可能是 async 回调:reject 同样要接住(与 onBgNotificationAccepted 同款),否则是 unhandledRejection。
|
|
402
|
+
if (out && typeof out.then === 'function') {
|
|
403
|
+
void Promise.resolve(out).catch((e) => {
|
|
404
|
+
hostLog('debug', `[fleet-frame] onTaskRemoved hook rejected: ${String(e).slice(0, 160)}`);
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
catch (e) {
|
|
409
|
+
// 宿主读口的异常不许拆帧消费循环(与 onBgNotificationAccepted 同款);留痕走 hostLog(端的 debug 汇集面)。
|
|
410
|
+
hostLog('debug', `[fleet-frame] onTaskRemoved hook threw: ${String(e).slice(0, 160)}`);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
361
413
|
break;
|
|
414
|
+
}
|
|
362
415
|
case 'workflow':
|
|
363
416
|
if (frame.row?.id) {
|
|
364
417
|
wfMap.set(frame.row.id, frame.row);
|
|
@@ -551,10 +604,29 @@ export function createFleetLedger(hooks = {}, opts = {}) {
|
|
|
551
604
|
const writtenIds = new Set();
|
|
552
605
|
let applied = false;
|
|
553
606
|
let washBlocked = false;
|
|
607
|
+
/** 0.74.0:通知的 seq 早于行 / 留存条目的代际 ⇒ 前代通知;挡在状态面之外,也不入事实台账(与洗绿同一档)。 */
|
|
608
|
+
let staleBlocked = false;
|
|
609
|
+
const notifSeq = typeof n.seq === 'number' && Number.isInteger(n.seq) && n.seq >= 1 ? n.seq : undefined;
|
|
610
|
+
// 零命中路径(行已退场、留存已过窗)的前代判据 = 本 task 的周期水位;通知本身也抬水位(它是同一条轴上的读数)。
|
|
611
|
+
{
|
|
612
|
+
const mark = cycleWatermark.get(n.taskId);
|
|
613
|
+
if (notifSeq !== undefined && mark !== undefined && notifSeq < mark) {
|
|
614
|
+
staleBlocked = true;
|
|
615
|
+
debug(`[fleet-frame] bg_notification stale-cycle ignored(watermark=${mark} notif-seq=${notifSeq})`);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
554
618
|
for (const id of rowIds) {
|
|
555
619
|
const known = taskMap.get(id);
|
|
556
620
|
if (!known)
|
|
557
621
|
continue;
|
|
622
|
+
// 0.74.0(异源对抗复审 R1):通知带的是**前一代**的 seq、而 live 行已是更新的一代 ⇒ 前代迟到通知,不退休这一行
|
|
623
|
+
// (退休会把行上的 cycleSeq 借给终态,消费端据此把仍在跑的新一轮结掉)。任一边没报 ⇒ 判不出 ⇒ 现行为。
|
|
624
|
+
const heldGen = wireCycleSeq(known);
|
|
625
|
+
if (notifSeq !== undefined && heldGen !== undefined && notifSeq < heldGen) {
|
|
626
|
+
staleBlocked = true;
|
|
627
|
+
debug(`[fleet-frame] bg_notification stale-cycle ignored(row=${id} row-cycle=${heldGen} notif-seq=${notifSeq})`);
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
558
630
|
const rowStatus = known.status ?? '';
|
|
559
631
|
if (TERMINAL_FLEET_TASK_STATUSES.has(rowStatus)) {
|
|
560
632
|
// 行车道已 settle 本行(终态行帧在先):retained 已由 case 'task' 写入行帧真值。
|
|
@@ -615,6 +687,13 @@ export function createFleetLedger(hooks = {}, opts = {}) {
|
|
|
615
687
|
continue;
|
|
616
688
|
if (id !== n.taskId && rowIdTail(id) !== n.taskId)
|
|
617
689
|
continue;
|
|
690
|
+
// 0.74.0(异源对抗复审 R2):留存池这条独立成路的更新同样按周期判 —— 否则被 live 路挡掉的前代通知从这里改写新一代的结局。
|
|
691
|
+
const retainedGen = wireCycleSeq(entry.row);
|
|
692
|
+
if (notifSeq !== undefined && retainedGen !== undefined && notifSeq < retainedGen) {
|
|
693
|
+
staleBlocked = true;
|
|
694
|
+
debug(`[fleet-frame] bg_notification stale-cycle ignored(retained=${id} row-cycle=${retainedGen} notif-seq=${notifSeq})`);
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
618
697
|
const prior = entry.row.status ?? '';
|
|
619
698
|
if (prior === n.status) {
|
|
620
699
|
applied = true; // 幂等重投(G5):同值不动、**不续窗**(回声风暴不得无限延长读面在飞窗)
|
|
@@ -638,15 +717,29 @@ export function createFleetLedger(hooks = {}, opts = {}) {
|
|
|
638
717
|
// completed 而面板渲 failed = 同一帧两写分叉,REF-CC-040 腿三的反面)。零命中且零拦截
|
|
639
718
|
// (行帧车道整条丢失、留存已过窗)⇒ 按既有事实台账自身做同方向核(killed/failed 在账,
|
|
640
719
|
// completed 回声不得洗绿它)。
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
720
|
+
// 0.74.0:事实台账带周期 —— 洗绿保护只在**同周期**内生效(第 1 代 failed 在账、第 2 代 completed 是新事实不是洗绿);
|
|
721
|
+
// 在账的周期比来的通知新 ⇒ 前代回声,不记。
|
|
722
|
+
const factsAccepted = !staleBlocked &&
|
|
723
|
+
(applied ||
|
|
724
|
+
(!washBlocked &&
|
|
725
|
+
(() => {
|
|
726
|
+
const prior = getBgTerminalFacts(n.taskId);
|
|
727
|
+
if (prior === undefined)
|
|
728
|
+
return true;
|
|
729
|
+
if (notifSeq !== undefined && prior.cycleSeq !== undefined) {
|
|
730
|
+
if (notifSeq < prior.cycleSeq)
|
|
731
|
+
return false;
|
|
732
|
+
if (notifSeq > prior.cycleSeq)
|
|
733
|
+
return true;
|
|
734
|
+
}
|
|
735
|
+
return !isWashGreen(prior.status, n.status);
|
|
736
|
+
})()));
|
|
737
|
+
if (factsAccepted)
|
|
738
|
+
raiseCycleWatermark(n.taskId, notifSeq);
|
|
647
739
|
if (factsAccepted) {
|
|
648
740
|
recordBgTerminalFacts(n.taskId, {
|
|
649
741
|
status: n.status,
|
|
742
|
+
...(notifSeq !== undefined ? { cycleSeq: notifSeq } : {}),
|
|
650
743
|
...(typeof n.summary === 'string' ? { summary: n.summary } : {}),
|
|
651
744
|
// 🔴 SDK 0.0.117 把 `recentSteps` 的三键 declare 成**必填** string,但那是**声称**不是保证:
|
|
652
745
|
// 帧从 wire 上来,脏项(null / 缺键 / 非串)在类型面之外仍可能到达,而 BgTerminalFacts
|
|
@@ -36,6 +36,8 @@ export interface FleetAgentRowLike {
|
|
|
36
36
|
/** server 1.250 起行带的 launch 真锚(epoch ms)。R4(clay 五报 07-31):此前投影载荷丢弃它,
|
|
37
37
|
* 详情页 elapsed 只能锚「壳建行时刻」——遗留行上渲出 1h+ 的假时长。缺席=老引擎,消费端保持现状。 */
|
|
38
38
|
startedAt?: number;
|
|
39
|
+
/** 0.74.0 —— 行的代际号(fleet 视图 `FleetTaskView.cycleSeq` 原样交)。缺席 = 这一行没有代际概念,不是第一代。 */
|
|
40
|
+
cycleSeq?: number;
|
|
39
41
|
}
|
|
40
42
|
/** 行从投影集消失多久之后上报 `absent`(0.72.12 起不再 settle;重连空窗 / snapshot 清表远小于此)。名字沿用(公面导出)。 */
|
|
41
43
|
export declare const ABSENT_SETTLE_MS = 30000;
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
* run 发布器双生行的形)——REF-CC-042:与同包 `workflow.rowIdTail` 同一个函数(import,不再
|
|
48
48
|
* 就地维护第二份;该函数出过等价性事故,0.1.1 修,见 `workflow.ts` 头注)。
|
|
49
49
|
*/
|
|
50
|
-
import { publishEngineAgentPanelAbsence, publishEngineAgentPanelEvent } from './engineAgentPanelStore.js';
|
|
50
|
+
import { isStaleEngineAgentPanelEnd, publishEngineAgentPanelAbsence, publishEngineAgentPanelEvent } from './engineAgentPanelStore.js';
|
|
51
51
|
import { rowIdTail } from './workflow.js';
|
|
52
52
|
import { TERMINAL_FLEET_TASK_STATUSES } from './fleet/fleetProjection.js';
|
|
53
53
|
import { DEFAULT_SESSION_KEY } from './sessionSlot.js';
|
|
@@ -142,26 +142,53 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
|
|
|
142
142
|
const toolUses = typeof row.toolUses === 'number' ? row.toolUses : undefined;
|
|
143
143
|
const transcriptId = row.transcriptId || undefined;
|
|
144
144
|
const startedAt = typeof row.startedAt === 'number' && row.startedAt > 0 ? row.startedAt : undefined;
|
|
145
|
+
// 0.74.0:代际号(正整数才算;坏形 / 缺席 ⇒ undefined,绝不补 1)。
|
|
146
|
+
const cycleSeq = typeof row.cycleSeq === 'number' && Number.isInteger(row.cycleSeq) && row.cycleSeq >= 1 ? row.cycleSeq : undefined;
|
|
145
147
|
const currentTool = currentToolKeyOf(row.currentTool) !== undefined ? row.currentTool : undefined;
|
|
146
148
|
const currentToolKey = currentToolKeyOf(row.currentTool);
|
|
147
149
|
const prev = seenMap.get(taskId);
|
|
150
|
+
// 0.74.0(异源对抗复审 R1):行上已是更新的一代,这一帧却是更早的一代 ⇒ 前代迟到帧。整只跳过:不发 fleet-row
|
|
151
|
+
// (它会把消费端记的周期身份改写回旧代,让随后的 end{旧代} 过陈旧判据)、不发 end、不动台账(否则台账被标
|
|
152
|
+
// settled,新一代的真终态就被去重吞掉)。在场已记 ⇒ 不会因此误报缺席。
|
|
153
|
+
// 判据与消费端同一条(`isStaleEngineAgentPanelEnd`:cycleSeq 优先,startedAt 回退)—— 只比 cycleSeq 会让只带
|
|
154
|
+
// startedAt 的前代帧漏网(异源对抗复审 R2)。
|
|
155
|
+
const rowIdentity = { ...(cycleSeq !== undefined ? { cycleSeq } : {}), ...(startedAt !== undefined ? { startedAt } : {}) };
|
|
156
|
+
const prevIdentity = prev !== undefined
|
|
157
|
+
? { ...(prev.cycleSeq !== undefined ? { cycleSeq: prev.cycleSeq } : {}), ...(prev.startedAt !== undefined ? { startedAt: prev.startedAt } : {}) }
|
|
158
|
+
: undefined;
|
|
159
|
+
if (prev !== undefined && isStaleEngineAgentPanelEnd(rowIdentity, prevIdentity))
|
|
160
|
+
continue;
|
|
161
|
+
/** 这一帧的周期身份**可证明**比台账上的新(同一条规则反向)。 */
|
|
162
|
+
const rowNewerCycle = prev !== undefined && isStaleEngineAgentPanelEnd(prevIdentity, rowIdentity);
|
|
148
163
|
// 🔴 粘性只在**同一周期**内成立:上一条已 settle(同 id 复活 = 新周期)或 launch 锚换了 ⇒ 不继承上一周期的用量
|
|
149
164
|
// (否则新周期首帧没报 tokens 时会把上一周期的数当成当前读数发布;异源对抗复审)。
|
|
150
165
|
const sameCycle = prev !== undefined &&
|
|
151
166
|
!prev.settled &&
|
|
152
|
-
(startedAt === undefined || prev.startedAt === undefined || prev.startedAt === startedAt)
|
|
167
|
+
(startedAt === undefined || prev.startedAt === undefined || prev.startedAt === startedAt) &&
|
|
168
|
+
// 0.74.0:代际号变了同样是新周期(两条都报了才比;任一条没报 = 这一帧没说)
|
|
169
|
+
(cycleSeq === undefined || prev.cycleSeq === undefined || prev.cycleSeq === cycleSeq);
|
|
153
170
|
const knownTokens = tokens !== undefined ? tokens : sameCycle ? prev?.tokens : undefined;
|
|
154
171
|
// 本周期已知的 launch 锚:帧上给了用帧上的,没给则同周期沿用。🔴 它随**每一条** fleet-row 发布(不只是变化那一帧)——
|
|
155
172
|
// 事件缓冲靠它判「这两条部分帧是不是同一周期」;缺锚的部分帧会让跨周期合并绕过屏障(异源对抗复审 [high])。
|
|
156
|
-
|
|
173
|
+
// 🔴 身份的沿用与用量的沿用是两回事(异源对抗复审 R3):用量只在**活着的同周期**内粘(`sameCycle` 要求
|
|
174
|
+
// !prev.settled);身份只要这一帧**不可证更新**就沿用 —— 同周期重复的终态帧若把记住的 startedAt / cycleSeq
|
|
175
|
+
// 抹掉,下一代只带另一半身份时就判不出「更新」,被 settled 吞掉。
|
|
176
|
+
const carryIdentity = prev !== undefined && !rowNewerCycle;
|
|
177
|
+
const knownStartedAt = startedAt !== undefined ? startedAt : carryIdentity ? prev.startedAt : undefined;
|
|
178
|
+
const knownCycleSeq = cycleSeq !== undefined ? cycleSeq : carryIdentity ? prev.cycleSeq : undefined;
|
|
157
179
|
if (TERMINAL_FLEET_TASK_STATUSES.has(status)) {
|
|
158
|
-
// ② 终态一次性 settle(幂等台账;消费端 settle 也幂等)。
|
|
159
|
-
|
|
180
|
+
// ② 终态一次性 settle(幂等台账;消费端 settle 也幂等)。0.74.0:去重按**周期** —— 已 settle 的是上一代、这一帧是
|
|
181
|
+
// 更新的一代(中间没见到 running 帧)⇒ 新周期的终态照发,不被上一代的 settled 吞掉。
|
|
182
|
+
const settledThisCycle = prev?.settled === true && !rowNewerCycle;
|
|
183
|
+
if (!settledThisCycle) {
|
|
160
184
|
// 终态行也把最后一拍的累计工具数/转录锚带上:详情页在行翻终态后仍要显示真计数与
|
|
161
185
|
// 委派 prompt,而终态帧常常是这一行**唯一**带全 usage 的一帧(bg lane 只在活动边界发行帧)。
|
|
162
186
|
if (
|
|
163
|
-
//
|
|
164
|
-
|
|
187
|
+
// 0.74.0:周期身份本身推进(或首帧就带身份)也是变化 —— 消费端要先记下身份才能对 end 判陈旧。
|
|
188
|
+
rowNewerCycle ||
|
|
189
|
+
(cycleSeq !== undefined && prev?.cycleSeq !== cycleSeq) || // 含首帧(prev 缺席)就带身份的终态
|
|
190
|
+
// 最终用量也算(终态帧常是唯一带全 usage 的一帧;消费端不更新非 running 行 ⇒ 必须赶在 end 之前发)
|
|
191
|
+
(tokens !== undefined && prev?.tokens !== tokens) ||
|
|
165
192
|
(toolUses !== undefined && prev?.toolUses !== toolUses) ||
|
|
166
193
|
(transcriptId !== undefined && prev?.transcriptId !== transcriptId) ||
|
|
167
194
|
(startedAt !== undefined && prev?.startedAt !== startedAt)) {
|
|
@@ -174,6 +201,7 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
|
|
|
174
201
|
...(toolUses !== undefined ? { toolUses } : {}),
|
|
175
202
|
...(transcriptId !== undefined ? { transcriptId } : {}),
|
|
176
203
|
...(knownStartedAt !== undefined ? { startedAt: knownStartedAt } : {}),
|
|
204
|
+
...(knownCycleSeq !== undefined ? { cycleSeq: knownCycleSeq } : {}),
|
|
177
205
|
});
|
|
178
206
|
}
|
|
179
207
|
publishEngineAgentPanelEvent({
|
|
@@ -183,6 +211,9 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
|
|
|
183
211
|
// **同一个病形**(内联两词 ⇒ core [6908] 的 `blocked` 漏成「成功」)。两处一次改齐,
|
|
184
212
|
// 读同一个单铸谓词;只修当格 = 下一次加词又漏一处。
|
|
185
213
|
isError: isTerminalNotSuccess(status),
|
|
214
|
+
// 0.74.0:这条终态属于哪个周期(在场才带)—— 消费端据此挡掉上一周期迟到的 end。
|
|
215
|
+
...(knownCycleSeq !== undefined ? { cycleSeq: knownCycleSeq } : {}),
|
|
216
|
+
...(knownStartedAt !== undefined ? { startedAt: knownStartedAt } : {}),
|
|
186
217
|
});
|
|
187
218
|
}
|
|
188
219
|
seenMap.set(taskId, {
|
|
@@ -191,6 +222,7 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
|
|
|
191
222
|
toolUses: toolUses !== undefined ? toolUses : prev?.toolUses,
|
|
192
223
|
transcriptId: transcriptId !== undefined ? transcriptId : prev?.transcriptId,
|
|
193
224
|
startedAt: knownStartedAt,
|
|
225
|
+
cycleSeq: knownCycleSeq,
|
|
194
226
|
currentToolKey: currentToolKey !== undefined ? currentToolKey : prev?.currentToolKey,
|
|
195
227
|
lastSeenAt: nowMs,
|
|
196
228
|
settled: true,
|
|
@@ -212,6 +244,7 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
|
|
|
212
244
|
(toolUses !== undefined && prev.toolUses !== toolUses) ||
|
|
213
245
|
(transcriptId !== undefined && prev.transcriptId !== transcriptId) ||
|
|
214
246
|
(startedAt !== undefined && prev.startedAt !== startedAt) ||
|
|
247
|
+
(cycleSeq !== undefined && prev.cycleSeq !== cycleSeq) ||
|
|
215
248
|
(currentToolKey !== undefined && prev.currentToolKey !== currentToolKey)) {
|
|
216
249
|
publishEngineAgentPanelEvent({
|
|
217
250
|
kind: 'fleet-row',
|
|
@@ -223,6 +256,7 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
|
|
|
223
256
|
...(toolUses !== undefined ? { toolUses } : {}),
|
|
224
257
|
...(transcriptId !== undefined ? { transcriptId } : {}),
|
|
225
258
|
...(knownStartedAt !== undefined ? { startedAt: knownStartedAt } : {}),
|
|
259
|
+
...(knownCycleSeq !== undefined ? { cycleSeq: knownCycleSeq } : {}),
|
|
226
260
|
...(currentTool !== undefined ? { currentTool } : {}),
|
|
227
261
|
});
|
|
228
262
|
}
|
|
@@ -233,6 +267,7 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
|
|
|
233
267
|
toolUses: toolUses !== undefined ? toolUses : prev?.toolUses,
|
|
234
268
|
transcriptId: transcriptId !== undefined ? transcriptId : prev?.transcriptId,
|
|
235
269
|
startedAt: knownStartedAt,
|
|
270
|
+
cycleSeq: knownCycleSeq,
|
|
236
271
|
currentToolKey: currentToolKey !== undefined ? currentToolKey : prev?.currentToolKey,
|
|
237
272
|
lastSeenAt: nowMs,
|
|
238
273
|
settled: false,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import type { AgentEvent } from '@sema-agent/sdk';
|
|
18
18
|
import type { HitlClientLike } from './hitlBridge.js';
|
|
19
|
-
import { type RespondToolApprovalFn, type ToolApprovalFrameLaneOpts } from './toolApprovalWire.js';
|
|
19
|
+
import { type RespondToolApprovalFn, type ToolApprovalFrame, type ToolApprovalFrameLaneOpts, type ToolApprovalFrameOutcome } from './toolApprovalWire.js';
|
|
20
20
|
import type { GateLedger } from './gateLedger.js';
|
|
21
21
|
/**
|
|
22
22
|
* CC `utils/messages.ts` 的 `REJECT_MESSAGE` **逐字**(B7 搬迁差分 2)。deny 后重放 tool_end 的
|
|
@@ -96,6 +96,11 @@ export interface AskGateWireDeps {
|
|
|
96
96
|
* 按下的「不再询问」会被整条丢弃(决断照送 + 一条 `surfaceRuleArmNotSent` 通知)—— 逐位语义见
|
|
97
97
|
* 各自的 JSDoc 与 `docs/INTEGRATION-CLIENTS.md` §5b。 */
|
|
98
98
|
approvalLane?: ToolApprovalFrameLaneOpts;
|
|
99
|
+
/**
|
|
100
|
+
* 0.74.1(CC-68)—— 流内帧腿的**结局回交**:每次 `tool_approval` 帧经卡口决断后调一次(帧 + {@link ToolApprovalFrameOutcome}),
|
|
101
|
+
* 宿主据此直接判「这一发落没落定」(孤儿认领回收不必再靠间接判据)。缺席零变化;抛错 / reject 被吞。
|
|
102
|
+
*/
|
|
103
|
+
onToolApprovalOutcome?: (frame: ToolApprovalFrame, outcome: ToolApprovalFrameOutcome) => void | Promise<void>;
|
|
99
104
|
}
|
|
100
105
|
/** 两族 gate:AskUserQuestion 走问答 overlay(原路);其余(fs 写三件 / Bash / 一等
|
|
101
106
|
* `kind==='tool_approval'`)走 CC 三选卡。 */
|
package/dist/hitl/frameRouter.js
CHANGED
|
@@ -543,7 +543,23 @@ async function routeToolApprovalFrame(ev, ctx) {
|
|
|
543
543
|
const gatedCallId = !fromSubagent ? led.lastPendingFsCall() : undefined;
|
|
544
544
|
// FIX①(2026-08-07):产物是 `{decision, ack?}` —— ack 上的 `rememberApplied`/`updatedInputForwarded`
|
|
545
545
|
// 由 toolApprovalWire 就地收敛成宿主通知(本路由只认决断词,不重复解释 ack)。
|
|
546
|
-
const
|
|
546
|
+
const outcome = await surfaceToolApprovalFrameAndRespond(ev, deps.respondToolApproval, argsOfGatedStart(led, gatedCallId), ctx.signal, deps.approvalLane);
|
|
547
|
+
const { decision } = outcome;
|
|
548
|
+
// 0.74.1(CC-68):结局交回宿主(fail-soft:宿主的回调 bug 不许拆流)。
|
|
549
|
+
if (deps.onToolApprovalOutcome !== undefined) {
|
|
550
|
+
try {
|
|
551
|
+
const out = deps.onToolApprovalOutcome(ev, outcome);
|
|
552
|
+
if (out && typeof out.then === 'function') {
|
|
553
|
+
void Promise.resolve(out).catch((e) => {
|
|
554
|
+
hostLog('debug', `liveHitlAskWire: onToolApprovalOutcome rejected: ${String(e).slice(0, 160)}`);
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
catch (e) {
|
|
559
|
+
// 宿主回调的异常不许拆帧路由;留痕走 hostLog。
|
|
560
|
+
hostLog('debug', `liveHitlAskWire: onToolApprovalOutcome threw: ${String(e).slice(0, 160)}`);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
547
563
|
if (decision === 'deny' && !fromSubagent) {
|
|
548
564
|
// 该 call 的报错收口帧 stamp REJECT 文案(vendored `User rejected <op> to <path>` 卡)。
|
|
549
565
|
if (gatedCallId !== undefined)
|
|
@@ -424,7 +424,7 @@ export async function resolvePark(park, ctx) {
|
|
|
424
424
|
else {
|
|
425
425
|
const closing = await surfaceParkGate(park, ctx, park.gatedCallId, witness);
|
|
426
426
|
outcome =
|
|
427
|
-
closing.kind === 'decided' || closing.kind === 'aborted'
|
|
427
|
+
closing.kind === 'decided' || closing.kind === 'aborted' || closing.kind === 'retracted'
|
|
428
428
|
? closing
|
|
429
429
|
: { kind: 'failed', stage: 'orchestration', reason: `${stalledReason}; closing re-read: ${closing.reason}` };
|
|
430
430
|
}
|
|
@@ -490,6 +490,7 @@ export async function resolvePark(park, ctx) {
|
|
|
490
490
|
if (rescan !== undefined &&
|
|
491
491
|
(rescan.kind === 'decided' ||
|
|
492
492
|
rescan.kind === 'aborted' ||
|
|
493
|
+
rescan.kind === 'retracted' || // 0.74.1(CC-67):宿主撤卡也是「人那一侧有了处置」,采信,不再重探
|
|
493
494
|
(rescan.kind === 'failed' && rescan.retryExhausted === true))) {
|
|
494
495
|
// L-80:**不在这里**复位同因计数 —— 复位只在驱动侧观察到 host 进展帧时发生(#357 的闸曾被这一行
|
|
495
496
|
// 每轮绕空:坐标失配序下每轮都「找到新行→决成功→引擎原样重放」,计数永远回不到 2)。
|
|
@@ -557,7 +558,14 @@ export async function resolvePark(park, ctx) {
|
|
|
557
558
|
}
|
|
558
559
|
if (outcome.kind !== 'decided') {
|
|
559
560
|
hostLog('debug', `liveHitlAskWire: gate not decided (${outcome.kind}${'reason' in outcome ? `: ${outcome.reason}` : ''}) — fail-soft to suspended terminal`);
|
|
560
|
-
|
|
561
|
+
// 0.74.1(CC-67):宿主撤卡(无决断收口)⇒ 零 decide,run 照旧 parked;这一轮按 fail-soft 收口并把真因写进去
|
|
562
|
+
// (不是用户中断、不是 decide 失败 —— 是这张卡在这个宿主上已经没有决断口了)。
|
|
563
|
+
const failedReason = outcome.kind === 'failed'
|
|
564
|
+
? outcome.reason
|
|
565
|
+
: outcome.kind === 'retracted'
|
|
566
|
+
? 'the approval card was retracted by the host without a decision (nothing was sent; the run stays parked and remains decidable elsewhere)'
|
|
567
|
+
: undefined;
|
|
568
|
+
return { kind: 'failsoft', events: failsoftEvents(park, ctx, outcome.kind === 'aborted', failedReason) };
|
|
561
569
|
}
|
|
562
570
|
// decide 成功:丢弃该 call 的毒化 HOLD(续流重放会带 isError:false 的解答帧收口卡片),
|
|
563
571
|
// 并记下真实答案供该解答帧 stamp `structured`(否则卡片渲成结果不可用)。
|
|
@@ -118,6 +118,11 @@ export type FsApprovalOutcome =
|
|
|
118
118
|
kind: 'aborted';
|
|
119
119
|
gatedCallId?: string | undefined;
|
|
120
120
|
}
|
|
121
|
+
/** 0.74.1(CC-67):宿主撤卡,零 decide;见 {@link ApprovalCardDecision} 的 retracted 臂。 */
|
|
122
|
+
| {
|
|
123
|
+
kind: 'retracted';
|
|
124
|
+
gatedCallId?: string | undefined;
|
|
125
|
+
}
|
|
121
126
|
/** `retryExhausted`(Inkglow-1085 P0a,0.37.0):decide 出站在**瞬断类**失败上重试一次仍未送达
|
|
122
127
|
* (两发都没拿到引擎的语义答复)—— 在场即真。消费方(parkResolver)据此走**重呈臂**(re-attach
|
|
123
128
|
* 重放 park ⇒ 同一张卡重新交给用户),不合成 `hitl_unanswered` 判死 turn。缺席 = 语义类失败
|
|
@@ -445,7 +450,19 @@ export type ApprovalCardDecision = ApprovalCardAllowDecision | ApprovalCardDenyD
|
|
|
445
450
|
} | {
|
|
446
451
|
kind: 'failed';
|
|
447
452
|
reason: string;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* 0.74.1(CC-67)—— **无决断收口**:宿主把一张**已经没有决断口**的卡撤掉(换会话 / 换引擎 / 跟踪器报 gone),
|
|
456
|
+
* 包见到它**一个字节都不发**(流内帧腿不 respond、durable-park 腿不 decide),不计 decided。
|
|
457
|
+
* 🔴 不复用 `aborted`:那是「用户放弃 = 拒」(照旧 deny 真 POST);撤卡 = 替用户 POST 一次他没做过的拒绝,
|
|
458
|
+
* 悬挂的子代 ask 会被误拒。`reason` 只留痕,不上 wire。
|
|
459
|
+
*/
|
|
460
|
+
| {
|
|
461
|
+
kind: typeof RETRACTED_CARD_DECISION_KIND;
|
|
462
|
+
reason?: string;
|
|
448
463
|
};
|
|
464
|
+
/** 卡口「无决断收口」结局值(单源;见 {@link ApprovalCardDecision})。 */
|
|
465
|
+
export declare const RETRACTED_CARD_DECISION_KIND: "retracted";
|
|
449
466
|
/** 卡口的入参 —— cli `surfaceApprovalCard` 的 `req` 逐字。 */
|
|
450
467
|
export interface ApprovalCardRequest {
|
|
451
468
|
toolName: string;
|
|
@@ -1107,11 +1124,17 @@ export interface ToolApprovalFrame {
|
|
|
1107
1124
|
}
|
|
1108
1125
|
/**
|
|
1109
1126
|
* 根外读 ask 附的「把 `dir` 加为本会话读目录」候选(core 7.19.0 #803;sdk 9.6.0 帧键第 30 员)。
|
|
1110
|
-
* 穷举表恰一臂:`clearsThisAsk` 域 = {true}。`dir` 原样(不截、不归一)
|
|
1127
|
+
* 穷举表恰一臂:`clearsThisAsk` 域 = {true}。`dir` 原样(不截、不归一);声明之外的成员不过境。
|
|
1111
1128
|
*/
|
|
1112
1129
|
export interface ReadRootCandidateView {
|
|
1113
1130
|
dir: string;
|
|
1114
1131
|
clearsThisAsk: true;
|
|
1132
|
+
/**
|
|
1133
|
+
* 0.73.6 —— `"exact"`(core ≥7.22.0 / server ≥7.85.0):**`dir` 这一串不是目录**,是命令点名的那条路径本身
|
|
1134
|
+
* (`cat ~/.gitconfig` 的 `~/.gitconfig`)。消费端必须**逐字添加这一串**;展成目录模式(`<dir>/**`)授不到任何东西、
|
|
1135
|
+
* 卡还在。渲染按它分支:在场那格不要说成「授权这个目录」。**缺席 = 目录出路,逐字节同旧;只读在场,永不读缺席。**
|
|
1136
|
+
*/
|
|
1137
|
+
covers?: 'exact';
|
|
1115
1138
|
}
|
|
1116
1139
|
/** {@link ToolApprovalFrame.delegation} 的形(命名形,不用内联匿名 —— typeshape 门 B4 棘轮口径)。 */
|
|
1117
1140
|
export interface ToolApprovalDelegation {
|
|
@@ -1294,6 +1317,11 @@ export interface ToolApprovalFrameOutcome {
|
|
|
1294
1317
|
* 这只 ask 在引擎上仍然挂着。端应重新出卡(跟踪器 `requeue`)。缺席 = 没发生这件事。
|
|
1295
1318
|
*/
|
|
1296
1319
|
editRefused?: true;
|
|
1320
|
+
/**
|
|
1321
|
+
* 0.74.1(CC-67):宿主用 `{ kind: 'retracted' }` 撤了这张卡 ⇒ 包侧**一个字节都没发**,`decision` 为 `'unresolved'`,
|
|
1322
|
+
* 这只 ask 在引擎上仍然挂着。与 `editRefused` 同款:附加诊断位,不是新的决断态;缺席 = 没发生这件事。
|
|
1323
|
+
*/
|
|
1324
|
+
retracted?: true;
|
|
1297
1325
|
}
|
|
1298
1326
|
/**
|
|
1299
1327
|
* #225 件5:respond 抛错的**结构化原文**(不是新的决断态,见
|
|
@@ -178,6 +178,8 @@ export { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED
|
|
|
178
178
|
* 透传纪律逐字同规)。再导出是给端的 `switch` 一份可数的表 —— 端仍必须带 `default` 臂。
|
|
179
179
|
*/
|
|
180
180
|
export { RULE_OFFERS_ABSENCE_REASONS, DENIAL_LIMIT_KINDS };
|
|
181
|
+
/** 卡口「无决断收口」结局值(单源;见 {@link ApprovalCardDecision})。 */
|
|
182
|
+
export const RETRACTED_CARD_DECISION_KIND = 'retracted';
|
|
181
183
|
// W1(design/161):sessionKey → 注册表;零参 API = DEFAULT_SESSION_KEY 兼容层(cli 装配不动)。
|
|
182
184
|
const cardPortByKey = createSessionSlot();
|
|
183
185
|
const cardPortMissesByKey = new Map();
|
|
@@ -419,6 +421,10 @@ parkGatedCallId) {
|
|
|
419
421
|
switch (card.kind) {
|
|
420
422
|
case 'failed':
|
|
421
423
|
return { kind: 'failed', stage: 'card', gatedCallId, reason: card.reason };
|
|
424
|
+
case 'retracted':
|
|
425
|
+
// 0.74.1(CC-67):撤卡不是决断 —— 零 decide,引擎那头的 ask 照旧挂着(由它的 TTL / 别的决断口结算)。
|
|
426
|
+
hostLog('debug', `liveHitlAskWire: approval card retracted without a decision for ${gatedCallId ?? '(no call)'} — nothing sent`);
|
|
427
|
+
return { kind: 'retracted', gatedCallId };
|
|
422
428
|
case 'aborted':
|
|
423
429
|
// turn 被中断(Esc/Ctrl+C):把挂着的 ask 用一次 **TOOL 级 deny** 结算掉(server
|
|
424
430
|
// `ASSISTANT-WIRE-CONTRACT.md` §4a;0.42.0 撤稿 —— 原文写的是「cancel-by-deny(contract/04
|
|
@@ -522,13 +528,17 @@ parkGatedCallId) {
|
|
|
522
528
|
}
|
|
523
529
|
}
|
|
524
530
|
}
|
|
525
|
-
/** 帧上 `readRootCandidate` 的窄读(模块内部,不出公面):在场且形对 ⇒
|
|
531
|
+
/** 帧上 `readRootCandidate` 的窄读(模块内部,不出公面):在场且形对 ⇒ 新铸两键形(`covers: "exact"` 在场时三键);缺席 / 坏形 ⇒ undefined(键不置)。 */
|
|
526
532
|
function readReadRootCandidate(v) {
|
|
527
533
|
if (typeof v !== 'object' || v === null)
|
|
528
534
|
return undefined;
|
|
529
535
|
const o = v;
|
|
530
536
|
if (typeof o.dir !== 'string' || o.dir.length === 0 || o.clearsThisAsk !== true)
|
|
531
537
|
return undefined;
|
|
538
|
+
// `covers` 域 = {缺席, "exact"}。出闭集(含键在场而值 undefined)⇒ **整只座不过境**,不是「摘掉坏成员、其余照发」:
|
|
539
|
+
// 两种读法在人那一侧是相反的动作(逐字添加 vs 加目录),发一半会让人按错的那一种回授。与上游同一处置。
|
|
540
|
+
if ('covers' in o)
|
|
541
|
+
return o.covers === 'exact' ? { dir: o.dir, clearsThisAsk: true, covers: 'exact' } : undefined;
|
|
532
542
|
return { dir: o.dir, clearsThisAsk: true };
|
|
533
543
|
}
|
|
534
544
|
/**
|
|
@@ -1483,6 +1493,12 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
1483
1493
|
surfaceEditRefusedOnBlindAsk();
|
|
1484
1494
|
return { decision: 'unresolved', editRefused: true };
|
|
1485
1495
|
}
|
|
1496
|
+
// 0.74.1(CC-67):宿主撤卡(无决断收口)⇒ **什么都不发**。这张卡已经没有决断口(换会话 / 换引擎 / 跟踪器报 gone),
|
|
1497
|
+
// 替用户 POST 一次 deny 会把悬挂的子代 ask 误拒。结局如实标 `retracted`,ask 在引擎上照旧挂着。
|
|
1498
|
+
if (card.kind === RETRACTED_CARD_DECISION_KIND) {
|
|
1499
|
+
hostLog('debug', `liveToolApprovalWire: ${frame.approvalId} card retracted without a decision${card.reason ? ` (${card.reason})` : ''} — nothing sent`);
|
|
1500
|
+
return { decision: 'unresolved', retracted: true };
|
|
1501
|
+
}
|
|
1486
1502
|
const decision = card.kind === 'allow' ? (card.allowSession ? 'allow_session' : 'allow') : 'deny';
|
|
1487
1503
|
if (card.kind === 'failed') {
|
|
1488
1504
|
hostLog('debug', `liveToolApprovalWire: approval card unavailable (${card.reason}) — fail-closed deny for ${frame.approvalId}`);
|
package/dist/notifications.js
CHANGED
|
@@ -931,6 +931,9 @@ export function enqueueBgChildNotification(n) {
|
|
|
931
931
|
// 后台 run 在面板上被 settle 成**成功**。🔴 `suspended`/`needs_review` 仍不在表里
|
|
932
932
|
// (那两词是「等一次人的决定」,判成终局会把一条正等着你的 run 在面板上判死)。
|
|
933
933
|
isError: isTerminalNotSuccess(n.status),
|
|
934
|
+
// 0.74.0:周期身份 —— **wire 真给了 seq 才带**。上面的 `cycle` 是去重键用的归一值(缺席归一成首周期),
|
|
935
|
+
// 那是键不是事实;把它上屏等于对一条没报代际的通知声称「这是第一代」。
|
|
936
|
+
...(typeof n.seq === 'number' && Number.isInteger(n.seq) && n.seq >= BG_FIRST_SEQ ? { cycleSeq: n.seq } : {}),
|
|
934
937
|
});
|
|
935
938
|
}
|
|
936
939
|
catch {
|
|
@@ -260,6 +260,8 @@ export declare function settleSubagentContent(taskId: string): void;
|
|
|
260
260
|
export declare function clearSubagentContent(taskId: string): void;
|
|
261
261
|
export interface BgTerminalFacts {
|
|
262
262
|
status: string;
|
|
263
|
+
/** 0.74.0 —— 这份终局属于哪个周期(通知带 `seq` 时记;缺席 = 通知没报)。洗绿保护只在同周期内生效。 */
|
|
264
|
+
cycleSeq?: number;
|
|
263
265
|
summary?: string;
|
|
264
266
|
recentSteps?: Array<{
|
|
265
267
|
tool?: string;
|
|
@@ -19,11 +19,11 @@
|
|
|
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.74.1**(本批发布版 = **patch**:审批卡无决断收口 `retracted`(三腿零发送)+ 流内帧腿结局回交 `onToolApprovalOutcome` + headless 不装 feed 成文;公面 1046;§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.7.1**(value-level,非 type-only;**0.74.0 抬版**: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
|
+
| 公开导出面 | **1046** 个运行期符号(+ 49 个测试钩;= 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` —— **别手抄进别处,以该文件为准** |
|
|
27
27
|
| 常驻门 | 以 `scripts/gates-manifest.json` 的 `suites` 长度为准(**本档不抄这个数**) | `scripts/gates-manifest.json`;`npm test` 的名单等值门与它逐名对账 |
|
|
28
28
|
| 沿革档 | 0.29.0 起建 `CHANGELOG.md`;更早批次记账在 `src/index.ts` 文件头 + `docs/REFACTOR-LEDGER.md` | — |
|
|
29
29
|
|
|
@@ -123,7 +123,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
123
123
|
|
|
124
124
|
> 📦 **随包 / 不随包**:npm 包只带 `dist` / `README` / `CHANGELOG` / 本档 / `LICENSE`。本档各处提到的 `docs/type-superset.json`、`scripts/*.json`、`scripts/run-*-test.mjs` 都是**仓内登记物与门,不随包发出** —— 装包的消费者找不到它们是预期;`_sema_` 超集键的**随包契约**就是本档各 §NNz 逐键处置表(键名 / 值域 / 缺席语义逐条在表里)。
|
|
125
125
|
>
|
|
126
|
-
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**
|
|
126
|
+
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**1046** 项)。
|
|
127
127
|
> 本节**不逐名抄**,只给「域 → 承重导出 → 用途 → 实现锚」。承重导出 = 一个端为了让这个域干活
|
|
128
128
|
> **必须**直接调到的那几个符号;其余是它们的类型、变体与辅助位。
|
|
129
129
|
> 单一入口:`import { … } from '@sema-agent/client-core'`(`exports` 只有 `.` 一个;
|
|
@@ -147,19 +147,19 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
147
147
|
`WorkflowsGateUnknownDenial` 四形**不在**基线里,`src/selfOrchestrationDenial.ts` 对基线贡献
|
|
148
148
|
**4** 项运行期导出(三个函数 + `SELF_ORCHESTRATION_RETRY_WITHOUT`)。
|
|
149
149
|
|
|
150
|
-
|
|
150
|
+
1046 项的内部构成(帮助端估读表大小;0.74.1 +1 常量(CC-67);0.74.0 +1 函数(CC-66);0.73.5 +8 常量 +3 函数(CC-58);0.73.4 +1 常量(CC-34);0.73.3 +6 函数(CC-61;测试钩 +1);0.73.1 +2 常量 +5 函数(CC-56 / CC-57;测试钩 +1);0.72.14 +1 常量 +7 函数(CC-55);0.72.13 +4 常量 +14 函数(CC-46 / CC-54 / CC-53 / CC-50 缺席口);0.72.12 +2 常量 +2 函数(CC-50);0.72.10 +2 常量 +2 函数(CC-41);0.72.9 +2 常量 +6 函数(CC-30 / CC-39②);0.72.8 +2 常量 +4 函数(CC-39③ / CC-43);0.72.7 +1 常量 +1 函数(CC-42);0.72.6 +1 函数(CC-40);0.72.5 +1 常量 +5 函数(CC-31);0.72.3 +1 常量(CC-39①);0.72.2 +1 函数(CC-37);0.72.1 +1 常量 +3 函数(CC-33);0.72.0 −23 常量 −16 函数(CC-32 退役批);0.71.3 +4 常量 +5 函数(CC-06);0.71.0 −2 常量 `MAX_AGENT_SKILLS` / `DECIDE_WORKFLOW_HOST_NOT_PARKED` +2 函数 `projectToolRosterDelta` / `mcpEngineLegPresence`;0.70.0 起 +1 函数;0.69.2 起 +3:常量 1 / 函数 2):**307** 项是 `SCREAMING_SNAKE` 常量数据表/词汇表
|
|
151
151
|
(矩阵、键集、env 名、锚串)而非可调用物;**6** 项是 PascalCase 运行期值
|
|
152
152
|
(`ControlRouter` / `ControlSafetyError` / `HitlBridge` / `HitlSafetyError` / `DecideTransportRetryExhaustedError`);
|
|
153
153
|
**37** 项是 `*For(sessionKey, …)` 的 per-session 变体(0.72.0 −4:`clearArmedGateFor` / `onGateArmedFor` / `registerArmedGateFromQuestionIdFor` / `notePlanReviewAnsweredIfDecisiveFor` 退出公面)(§6;其中 `engineNamespaceKeyFor` 是命名巧合 —— 参数是 baseUrl 不是 sessionKey,见域 14)。
|
|
154
154
|
|
|
155
|
-
### 2b. 域图(16 域,逐域计数之和 =
|
|
155
|
+
### 2b. 域图(16 域,逐域计数之和 = 1046)
|
|
156
156
|
|
|
157
157
|
| # | 域 | 名数 | 承重导出 | 用途 | 实现锚 |
|
|
158
158
|
|---|---|---|---|---|---|
|
|
159
159
|
| 1 | **适配内核(下行主链)** | 63 | `TOOL_INPUT_JOIN_MAX_CALLS`(0.73.4 CC-34:终帧拒绝清单第三键的本流快照上限;§66)· `OUTCOME_UNKNOWN_ROW_PREFIX` / `isOutcomeUnknownRowText`(0.72.12 CC-50:第三条中性终局行「结局不知道」,读结果帧 `_sema_outcome`;§59)· `MODEL_OUTPUT_ERROR_PREFIX` / `isModelOutputErrorText` / `isModelOutputErrorRowText`(0.72.8 CC-43:runStream 第二条中性臂 —— core malformed tool-call 一族的行身份;§55)· `readEffectiveReasoning` · `readEffectiveMemoryScopes`(0.71.3 CC-06:终帧 `_sema_effective_reasoning` / `_sema_effective_memory_scopes` 的窄读器,§45)· `isSubFlowSegmentEnd` · `SEGMENT_END_IDENTITY_KEYS` · `droppedWhySentence`(0.69.2 CC-13:三件出公面,§38)· `adapt` · `createWireToCcAdapter` · `runStream` · `eventToSdkMessage` · `terminalToSdkResult` · `SEMA_SEGMENT_ID_KEY`(0.68.2 CC-01:committed assistant 文本行顶层段身份键的唯一字面量出处,壳只读)· `projectMcpSection`(0.68.2 CC-03:`wiring_manifest.mcp[]` 与 `/mcp` 面板 `lastLegMcp.mcp[]` 共用的同一只条目读器)· `readRunCostFacts`(0.66.0:终局成本事实的**唯一读器** —— `TaskStats.costBreakdown` / `nested` 逐键窄读 + 对账三段(own/nested/compaction)与两个「没定价」判别位;终帧的两个超集键与 chrome 臂 `run_cost_reconciled` **共用它**,两面不会各算各的,详见 §31c)· `TERMINAL_CAUSE_KINDS`/`isTerminalCauseKind`(0.68.0 / L-247:**core 终局因由**闭集,四词 `completed|failed|blocked|paused`)· `RUN_TERMINAL_NOT_SUCCESS_STATUSES`/`isTerminalNotSuccess`/`RUN_TERMINAL_STATUSES`/`isTerminalStatus`(L-215② 终局词汇的**单铸谓词**,0.68.0 随 L-247 **两表分源**更名 —— `killed` 属 server run 行状态面、`paused` 属 core 因由面,合成一张会让两边加词时都读不出该改哪儿;`blocked` 是 agent 自报终态,`suspended`/`needs_review` 刻意不在表里,详见 §33b / §30j)· `SEMA_SUBAGENT_USAGE_PARTIAL_KEY`/`subagentUsageIsPartial`(0.68.0 / L-244:子代用量下界位的**自有名**与唯一判据,与终帧 `_sema_usage_lower_bound` 分名,详见 §33g) · `turnUsageToModelUsage` · `isRunStreamActive` · `ADAPTER_DIVERGENCES` · `readRunTerminal` / `runTerminalCode` / `runTerminalGateKind` / `runTerminalGateToolName` / `isReviewPark` / `REVIEW_PARK_GATE_KINDS`(0.60.0 / engine ≥7.64.0:一次 run **怎么结束的**唯一读器 —— 终局从八个平面键换成一条带标因由 `terminal`,四臂 + `unknown` 防御臂 + `plane` 两代字节标;🔴 不认识的终态词绝不折成成功、本包不提供「因由→五词 status」的兼容投影,详见 §24b)| 引擎 SSE `AgentEvent` → 端要渲的**双面输出**:transcript(`SDKMessage`)+ chrome(瞬态 `ChromeEvent`)。**本包存在的理由** | `src/adapt.ts`、`src/adapt/{arms,wireShapes,panelTasks}.ts`(经 `adapt.ts` 再导出)、`src/adapter/runStream.ts`、`src/adapter/downstream/*`、`src/adapter/types.ts`、`src/runTerminal.ts` |
|
|
160
160
|
| 2 | **seam 公共契约** | 2(其余为 type-only) | `CHROME_ARMS` · `deriveTranscriptId` | 公共词汇 + **id 确定性不变量**(同一条流重放 ⇒ 同一串 id)。`CHROME_ARMS` = 端「我要消费哪些 chrome 臂」的对照清单 | `src/seam.ts` |
|
|
161
|
-
| 3 | **HITL 决断卡链**(§4/§5 主战场) |
|
|
162
|
-
| 4 | **子代 wire + 面板侧信道台账** |
|
|
161
|
+
| 3 | **HITL 决断卡链**(§4/§5 主战场) | 178 | `RETRACTED_CARD_DECISION_KIND`(0.74.1 CC-67:卡口无决断收口;§69)· `planReviewOutcomeTail`(0.73.1 CC-57:outcome 尾句六态单铸点;投递口闩;§63)· `readLivePendingRows` / `suspendedSubagentAsks` / `countApprovalsAwaitingDecision` / `createSuspendedAskTracker` / `livePendingRowToApprovalFrame` / `surfaceSuspendedAskAndRespond` / `surfaceEditRefusedOnBlindAsk` + `EDIT_REFUSED_ON_BLIND_ASK_WARN_TEXT`(0.72.14 CC-55:悬挂的流内 ask 读面 / 视图 / 去重账 / 决断口;§61)· `planReviewCardOptions` / `planReviewChoiceFromAnswer` / `versionSupportsPlanReviewModeAfter` / `isPlanReviewModeAfter` + `PLAN_REVIEW_APPROVE_AUTO_LABEL` / `PLAN_REVIEW_APPROVE_MANUAL_LABEL` / `PLAN_REVIEW_MODE_AFTER_WORDS` / `PLAN_REVIEW_MODE_AFTER_MIN_ENGINE`(0.72.13 CC-46:plan_review 批准后模式 `permissionModeAfter` 发口与三选卡双闸;§60)· `makeHitlCanUseTool` · `HitlBridge` · `findPendingForTask` · `readDecideReceipt`/`decideAcceptedNotResolved`/`decideRefusalFromError`(B-070:`/decide` 200 = **投递受理**不是「门已解决」;`executionOutcome` 缺席 = 未知,详见 §30h) · `HitlSafetyError` · `bridgeAskUserQuestionGates` · `surfaceToolApprovalFrameAndRespond` / `surfaceFsApprovalAndDecide` · `readToolApprovalRespondAck` · `installApprovalCardPort(For)` · `installHitlHostSurface(For)` · `armPlanReviewApproval` · `reopenPlanReviewCard` · `decidePlanReview` · `startApprovalsFeed` · `pendingRowIsOwnedByThisSession` · `approvalCallKey`/`liveFrameCallKey`/`planReviewQuestionId` · `registerArmedGateFor`/`wasGateArmedFor` · `waitForGateArmed(For)`/`onGateArmed`/`gateArmedWaitMs`(#244 F1 呈现回执事件源) · `planReviewArmedKey(For)`/`notePlanReviewAnswered(For)`/`notePlanReviewAnsweredIfDecisive`(A-024.4 plan 呈现分代) · `toolEndOutputText` · `isAskTool` · `waitForParkRowBirth` · `classifyAskParkRows` / `askParkRowArm` / `classifyAskParkChainFailure` · `readDecisionNoteAudit` / `decisionNoteAuditLine` · `resumeRunningOptions` / `resumeChoiceFromLabels` · `persistedRulesLaneAvailable`/`persistedRulesGovernanceAvailable` · `classifyRulesFailure` · `listAllPersistedRules` · `classifySkippedReason` · `readRulePersistOutcome`(#244 F2:persist-ack 读口与 `readToolApprovalRespondAck` 合成一处) · `parseLocalAllowRule`(durable 腿本地落规则窄化骨架,谓词经 `LocalAllowRuleDeps` 注入) · `readToolApprovalRespondRefusal`(#225 件5,0.42.0:respond 抛错的结构化原文读口 —— 三位各自防御读、各自缺席不铸、**三位皆缺席时整只返 `undefined`**;原样交还零加工,UNTRUSTED-for-display)· `installEditedRuleTextPrechecker` / `hasEditedRuleTextPrechecker` / `precheckEditedRuleText`([5076] 转出口,0.42.0:core 5.57.0 `precheckEditedRuleText` 的**端口注入形** —— 类型面 + 注入口 + 诚实缺席读口。🔴 **不是** value 级 re-export,理由见 §7 缺口 **P-34**;未装 ⇒ 返 `undefined`,绝不编一个 `{ok:true}`)· `surfaceRuleArmNotSent` / `RULE_NOT_SENT_WARN_TEXT` + `surfaceRuleArmRejected` / `RULE_NOT_SENT_REJECTED_WARN_TEXT`(#334,0.43.0:人在卡上按下的「不再询问」被整条丢弃时的诚实告知——**两条刻意分开**:前者=**引擎能力位未确认**(换台引擎/等探测就好),后者=**这次选择没过包内表核/互斥核**(表外文本/坏下标/两臂同场,换引擎也不会变) —— 编辑臂 `respondFreeFormRules` 与批臂 `respondBatchRuleOffers` 两条同形存量共用一条,与 `surfaceRememberNotApplied` 同族纪律:决断照送、只是规则没存,静默丢掉用户明确意图 = 让人以为功能坏了)· `projectCrashConverged`(L-38,0.49.0:`/v1/approvals` additive 键 `crashConverged` 的分桶投影 —— 崩溃收敛的孤儿审批读面,**缺席 ≠ 空数组**、分桶恰一个合取、坏行丢弃并计数,详见 §12;同批把 `ApprovalsResourceLike.list()` 的返回位 additive 放宽成 `ApprovalsListEnvelope`,老形 `{pending}` 仍可赋值)· `readRuleOffers` / `readRuleOfferSupply`(L-103/[C228],0.57.0 additive 导出:「不再询问」候选两代 wire 键的窄读器**公面化** —— 此前只经卡端口出包,不走卡端口架构的宿主只能自己重铸一把,而它承载的是兑付安全判据(原始下标不前移/逐条丢坏/闭集 kind/两代取舍序),详见 §20)· `RULE_OFFERS_ABSENCE_REASONS` / `DENIAL_LIMIT_KINDS`(0.59.0 / sdk 8.3.0 提货:`ruleOffersAbsence` 三词与 `denialLimitFallback.limit` 二词的**运行期**闭词表再导出 —— 与 0.58.0 那三张同一条纪律:端拿它做判定别再手抄字面量。⚠️ **本包自己不拿这两张表做窄读判定**(两处都按开集透传,词表属主是 core、server 已按闭集拒过),再导出只是给端的 `switch` 一份可数的表,端仍必须带 `default` 臂,详见 §23a)· `DecideTransportRetryExhaustedError`(Inkglow-1085 P0a:decide 出站瞬断重试耗尽的 typed 判别 —— HitlBridge 内建单次退避重试,耗尽走重呈臂不判死 turn;端一般只消费行为,不需要 instanceof) · `gateOutcomeOf` / `isDeniedGate` / `gateDeniedBy` / `gateApprover` / `isApprovalWindowExpiredGate` / `isDenialLimitAutoDeniedGate` / `isParkSlaExpiredGate` / `isHumanSettledGate`(0.60.0 / engine ≥7.64.0:`tool_end.gate` 整条门记录的窄读器 + 判定谓词 —— 取代退役的四个正交词 `settledBy`/`resolution`/`autoDenied`/`approver`。🔴 **判定归包**:「是不是审批窗自己走完的拒绝」旧形上是端各自拼的两键合取,而三条窗词现在分得开、合并读回去等于把刚修好的判别力扔掉;⚠️ 公面型一律带 `View` 后缀 —— 本文件的 `GateOutcome`(决断腿结局)与 sdk 的 `GateOutcome`(引擎门记录)**同名不同义**,详见 §24c)· `isGateParkedToolEnd`(「这次调用没在这里结算」的**第二形**谓词:gate 缺席 + `errorCode:"gate.parked"`;端判这件事必须与 `isApprovalWindowExpiredGate` **两形合读**) · `readWireErrorCode`(B-037 候包件②:decide/取件失败上引擎 wire 机器码的单源读口,结构视图读不 `instanceof`;与本包铸的 `code` 是两个命名空间,详见 §24g)| suspended→decide→resume 环。🔴 **D-1 两元组 verbatim 回显**是字节级断言的安全不变量,端**不许重实现它的任何一段**。🔴 键空间边界(web [C1] d3 拦截):`gateIdentity` 四常量两函数只覆盖 HITL questionId/callKey 空间;seat 的 `TOOL_PERMISSION_REQUEST_ID_DOMAINS`(`plan:` 等)是另一键空间,**两者绝不合并**(合并=座位校验器静默拒全部 plan-review 卡) | `src/hitl/hitlBridge.ts`、`toolApprovalWire.ts`、`askGateWire.ts`、`planReviewWire.ts`、`hitlHostSurface.ts`、`gateIdentity.ts`、`armedGateRegistry.ts`、`parkOwnership.ts`、`parkResolver.ts`、`approvalsFeed.ts`、`frameRouter.ts`(**只挑名导出** `toolEndOutputText`/`ENGINE_ABORT_TOOL_RESULT`/`isAskTool`/`HITL_REJECT_MESSAGE`/`HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE`)、`parkRowBirthWait.ts`、`approvalDecisionNoteAudit.ts`、`askParkRowRouting.ts`、`resumeRunningCard.ts`(#265 上收的判定层)、`persistedRulesWire.ts`、`localAllowRule.ts`(#244 F2 规则侧)、`crashConverged.ts`(L-38 崩溃收敛读面)、`src/gateOutcome.ts` |
|
|
162
|
+
| 4 | **子代 wire + 面板侧信道台账** | 89 | `isStaleEngineAgentPanelEnd`(0.74.0 CC-66:面板 end 的周期身份判据;§68)· `subscribeEngineAgentPanelAbsence` / `publishEngineAgentPanelAbsence`(0.72.13:fleet 行缺席上报的**独立订阅口** —— 不上主通道,老消费者结构上收不到;§60 S-5)· `tailEngineSubagent` · `installSubagentActivitySink` · `installSubagentTailMetaSink`(#280 件2:tail meta 帧发布口,`contentFrames` 判别位载体)· `stopEngineTask` + `classifyTaskStopConflict` · `fetchEngineSubagentReport` · `steerEngineSubagent`(0.32.0 未发布 #280 件A:additive 第三参 `childTaskId` —— 端有行上下文时**应当**传,传了就走「台账优先 / 缺席即诚实缺席 + `noteBgOwnerAbsence` 留痕」的 Q3 口径,与 tail·taskOutput·subagentOutput 三腿同姿势、与孪生 resume 腿共用同一个 `resolveOwnerRunId` 判据;**不传**则逐字维持旧行为=回落在飞 run)· `resumeSettledSubagent` + `resolveSubagentResumeContext` + `resolveOwnerRunId` + `classifySubagentResumeFailure` + `subagentResumeAvailable`(#242 批 2 A-028.7:resume 判定半场上收,与 steer 孪生同居;取址三态 = 台账有行用行值 / 指名了行但台账缺席则**诚实缺席绝不回落在飞 run** / 没指名行才回落。出路文案归端)· `recordSubagentOwnerFromProgress` + `getBgParentRunOwner`(A-028.6:「子代 → 宿主 run」**单表**,宿主 run 必须由持 stream-local 值的调用方显式传入,包内绝不从 `activeEngineRunId()` 推断)· `noteBgOwnerAbsence`(#242 批 3 [4000] Q3=B:tail/taskOutput·taskStop/subagentOutput 三腿台账缺席即诚实缺席**绝不回落在飞 run**,缺席 warn 留痕每 (腿,taskId) 一条)· `clearBgTerminalFacts`(#242 批 3 扫码修:复活=新周期,旧周期终态事实作废——fleetLedger 复活两腿按尾段清账,factsAccepted 方向核不再拿上周期终态当先例)· `auditRetainWithoutWake`([4000] Q5:引擎宣示 `subagentResume` + 本端在付 `retainSubagentSessions` + 端未实现 `wakeSubagent` ⇒ 响亮一条;`CLIENT_VERBS.wakeSubagent` 维持 fail-soft)· `subscribeSubagentContent` · `subscribeEngineAgentPanel` · `publishQuestionFrame` / `respondToQuestion` · `configureSubagentContentStore` / `subagentContentStoreConfig` / `SUBAGENT_CONTENT_STORE_DEFAULTS`(0.62.0:子代内容账本的**字节预算** —— 此前只有条数帽而单条无上限,一条 base64 工具结果就能让一个子代槽吃到十几 MB;越限从最早的内容开始丢并留一条可渲染的 `truncated` 记录,总帽淘汰整条最久未用的账本。配置面 fail-loud,详见 §26②)| 驱动与观测委派子代;经 module 级台账喂活体 agent/task 面板。全部**能力位 gate**(§5b) | `src/subagent/*.ts`、`src/subagentContentStore.ts`、`src/engineAgentPanelStore.ts`、`src/engineInlineTaskStats.ts`、`src/engineToolLabelStore.ts`、`src/liveQuestionStore.ts` |
|
|
163
163
|
| 5 | **fleet 投影** | 38 | `createFleetLedger` · `projectTasks` · `projectWorkflows` · `projectFleetAgentRows` · `readEngineActiveBgTasks` · `FLEET_TASK_VIEW_KEYS` · `escapeDisplayControlChars`(不可见字符可见化,行标签/描述消毒的共享底座)· `capForDisplay`(0.62.0:呈前**消毒 + 封长**的共用铸点 —— 先转义、后按转义结果封长,截点避开半截转义 token 与合法代理对;本包该族四处此前各写一份、其中三份顺序是反的,详见 §26⑦)· `wireCycleSeq`(0.38.0 提货补投的 #261 §2 两位之一,另一位 `wireRetiredBy` 🔧 0.72.0 退出公面:代际号 = SendMessage 复活即 +1,**缺席 ≠ 第一代**;`retiredBy` 在场 = 这条终态是对账腿从 durable run 行投影出来的、**不是**发布方亲报 —— 幽灵行与正常收尾唯一的 wire 判据。两位都只在场才落键) | 老 `fleetClient` 那一刀的成品:**帧体归库、连接归端** —— 端持 SSE 连接,库做行投影 + 保留台账 | `src/fleet/fleetProjection.ts`、`src/fleet/fleetLedger.ts`、`src/fleetAgentPanelProjection.ts`、`src/fleetTaskDesc.ts` |
|
|
164
164
|
| 6 | **请求装配(上行唯一构造口)** | 13 | `MEMORY_OFF` / `memoryOffDeclarationField` / `memoryOffDeclared`(0.72.8 CC-39③:`memory:"off"` 请求级整面关的意图位片段;§55)· `buildTaskRequest` · `REQUEST_FIELD_MATRIX` · `unregisteredRequestKeys` · `applyLiveRequestDefaults` · `taskNotificationToPrintFrame` | 两条车道(`interactive`/`print`)出站请求的**唯一**构造器;`unregisteredRequestKeys` 是可执行门 —— 端偷带一个未登记键上 wire 就红 | `src/request/taskRequest.ts`、`src/request/printNotification.ts` |
|
|
165
165
|
| 7 | **通知与 outstanding 台账** | 52 | `noteOwnWorkflowRun`(0.72.2 CC-37:own 台账显式登记口,adapter workflow lane 门在 own-run 正向证明下同拍调;§49)· `installNotificationQueuePort` · `normalizeTaskNotification` · `taskNotificationDedupKeyFromWire` · `registerOutstandingBgTask` / `registerOutstandingWorkflowRun` · `notificationQueuePortMisses` · `subscribeOutstandingWorkflows` · `outstandingDeliverableWorkflowCount` | `task_notification` 归一 + 去重 + 投递进宿主命令队列的**一把闸**;`outstandingDeliverableWorkflowCount()` 是 headless `-p` 的**退出门** · `classifyPeerNotification` / `renderPeerFrameTranscriptText` / `parsePeerFrameText` / `peerFrameDisplayName` + 三张闭集表(design/385,0.54.0:同一条 `task_notification` 车道上三条**引擎注入帧**的类型化投影 —— 判别位=载体在场而非 summary 文本,详见 §17) | `src/notifications.ts`(11 个 module 台账) |
|
|
@@ -8982,3 +8982,92 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
|
|
|
8982
8982
|
|
|
8983
8983
|
**包侧缺口:** ⓪ CC-36 托管 MCP 活性三态读口(候 core #874);① 409 体 `pendingGate` 无门身份 id ⇒ 本包分不出「刚答过的那道门的陈旧回声」与「同 task 的新一道门」,重开判据按身份收紧候 server 出键;② 告警轴 `axis` 只供遥测,三档文案不分轴(与 CC 同);其余同 §66。
|
|
8984
8984
|
|
|
8985
|
+
## §68 🆕 0.74.0 peer sdk 地板 >=9.7.1 + 读根候选 `covers: "exact"` 过境(CC-64)+ 面板周期身份(CC-66)+ 离场读口(CC-65);minor
|
|
8986
|
+
|
|
8987
|
+
> **minor**(peer 地板抬升 = 非 additive):型面本身纯 additive(+1 函数,公面 1044 → 1045;`ReadRootCandidateView` +`covers?`;`EngineAgentPanelEvent` `fleet-row` 臂 +`cycleSeq?`、`end` 臂 +`cycleSeq?` / `startedAt?`;`FleetAgentRowLike` +`cycleSeq?`;`FleetLedgerHooks` +`onTaskRemoved?`;零 wire 新键)。🔴 **更正 §65 / §66 / §67 缺口行**:「缺席上报附 `removeReason`(候壳透传)」不实 —— 宿主的透传一直在,丢键的是本包的 `task_remove` 臂;本版补读口。票来源:cli 1.0.122 提货批直讯三件(CC-64 / CC-65 / CC-66)。
|
|
8988
|
+
|
|
8989
|
+
### 68a. 处置表
|
|
8990
|
+
|
|
8991
|
+
| # | 面 | 本包做了什么 | 端要做什么 |
|
|
8992
|
+
|---|---|---|---|
|
|
8993
|
+
| S-0 🔴 **peer** | `@sema-agent/sdk` 地板 `>=9.6.0` → `>=9.7.1` | 四处同批抬齐 | 换钉 `^0.74.0` 的端把自己的 sdk 钉抬到 ≥9.7.1(cli 1.0.122 已在);<9.7.1 装本版只收 peer 警告,不改行为 |
|
|
8994
|
+
| S-1 | 审批卡 `readRootCandidate.covers`(server ≥7.85.0;core 7.23.0 起真到卡) | **fixed**:在场(`"exact"`)逐字上卡;此前被窄读剥掉 | 🔴 渲染与回授都按它分支:在场 ⇒ 这一串是**路径本身**,回授时**逐字添加**(不展 `<dir>/**`、不劝加父目录),文案不要说「授权这个目录」;缺席 ⇒ 目录出路,现行为逐字不变。**只读在场,永不读缺席** |
|
|
8995
|
+
| S-2 | 面板 `fleet-row.cycleSeq?` / `end.cycleSeq?` / `end.startedAt?` | **新增**(在场才带;流内 close 臂恒缺席) | 行上记最近一条 `fleet-row` 的 `cycleSeq` / `startedAt`;收到 `end` 先 `isStaleEngineAgentPanelEnd(end, row)`,陈旧 ⇒ 忽略(不 settle / 不写 report / 不摘所有权);复活后可以把状态翻回 running 了。终报异步回写:发起时记下周期,回来时同判。把 `FleetTaskView` 原样交给 `projectFleetAgentRows`(它已带 `cycleSeq`) |
|
|
8996
|
+
| S-3 | 账本 `task_remove` 离场读口 `hooks.onTaskRemoved` | **新增**(`removeReason` / `cycleSeq` 在场才带;`stale` / `unknownRow` 标) | 要渲「离场原因」的端装读口;🔴 离场不是终局:渲「离场」不清行、不结算(契约附录 H);`stale` 行没被删,别在端上删 |
|
|
8997
|
+
|
|
8998
|
+
### 68b. 缺席语义(逐键)
|
|
8999
|
+
|
|
9000
|
+
- `covers` 缺席 = 目录出路(老引擎,或这条 ask 的候选本来就是目录)。**不是**「未知」—— 上游承诺缺席即目录。出闭集 ⇒ 整个 `readRootCandidate` 键不在卡上。
|
|
9001
|
+
- `end.cycleSeq` / `end.startedAt` 缺席 = 这条终态没有周期身份(流内 close 臂 / 没有代际概念的行 / 老引擎)⇒ `isStaleEngineAgentPanelEnd` 恒 `false` ⇒ 按现行为 settle。**不是第一代**。
|
|
9002
|
+
- `fleet-row.cycleSeq` 缺席 = 这一行没有代际概念(同步委派子代 / workflow agent / 顶层 run)或老引擎;不补 1。同周期内粘性:后一帧没报,沿用本周期已知值;周期变了(`cycleSeq` 或 `startedAt` 变)不继承。**前代迟到帧**(台账已是更新一代、帧是更早一代;判定与 `isStaleEngineAgentPanelEnd` 同一条规则,含只带 `startedAt` 的帧)在包内整只跳过,端根本收不到;端侧的 `isStaleEngineAgentPanelEnd` 是第二道(流内 close 臂 / 通知车道 / 缓冲重放等包内挡不住的来源)。周期身份推进本身算变化:连续两代终态即使别的键全不变,也先发 `fleet-row{新代}` 再发 `end{新代}`。
|
|
9003
|
+
- `FleetTaskRemoval.removeReason` 缺席 = 常规清场(server 没说原因);`cycleSeq` 缺席 = 退场帧没带代际 ⇒ 判不出新旧 ⇒ 照删(现行为)。
|
|
9004
|
+
|
|
9005
|
+
### 68c. 黑盒判据骨架
|
|
9006
|
+
|
|
9007
|
+
- **G1**:真引擎 ≥7.23.0,根外读单文件(`cat <根外文件>`)⇒ 卡请求 `readRootCandidate` 三键,`covers === 'exact'`,`dir` === 命令点名的路径。修前(≤0.73.5):两键,无 `covers`。
|
|
9008
|
+
- **G2(负控)**:根外读目录形 ⇒ 两键形,与 0.73.5 逐字节同。
|
|
9009
|
+
- **G3**:夹具帧 `covers: 'dir'` ⇒ 卡上无 `readRootCandidate` 键。
|
|
9010
|
+
- **G4(周期)**:同 id 行 `cycleSeq: 1` 终态 → `cycleSeq: 2` running ⇒ 两条事件:`end{cycleSeq:1}`、`fleet-row{cycleSeq:2}`;`isStaleEngineAgentPanelEnd({cycleSeq:1}, {cycleSeq:2}) === true`。修前:`end` 无身份,判据函数不存在。
|
|
9011
|
+
- **G5(通知车道)**:`enqueueBgChildNotification({seq: 2, status: 'completed'})` ⇒ `end.cycleSeq === 2`;不带 `seq` ⇒ 无 `cycleSeq`。
|
|
9012
|
+
- **G7(前代迟到)**:同 id 行 `cycleSeq: 2` running 后收 `cycleSeq: 1` 的终态行 ⇒ 零事件;行 `{cycleSeq: 2, startedAt: 200}` 后收只带 `startedAt: 100` 的终态行 ⇒ 同样零事件;账本 live 行 `cycleSeq: 2` 收 `bg_notification{seq: 1}` ⇒ 不退休;第 2 代终态行 + `seq: 1` 的 failed 通知 + 同代退场 ⇒ 留存池仍 completed;行退场后重放 `seq: 1` 失败通知(零行命中)⇒ 不入事实台账,随后 `seq: 2` 的完成照记(事实台账带周期,洗绿只在同周期内)。修前:发 `fleet-row{1}` + `end{1}` 并把台账标 settled;通知把行退休并借用第 2 代身份;留存池被前代通知改写。
|
|
9013
|
+
- **G6(离场)**:账本行 `cycleSeq: 2` 在场时收 `task_remove{cycleSeq: 1}` ⇒ 行仍在、读口报 `stale: true`;`task_remove{cycleSeq: 2, removeReason: 'orphaned'}` ⇒ 行删、读口带原词。修前:任何 `task_remove` 都删行、无读口。
|
|
9014
|
+
|
|
9015
|
+
### 68z. 逐键处置表
|
|
9016
|
+
|
|
9017
|
+
| # | 键 / 面 | 处置 | 坐标 / 理由 |
|
|
9018
|
+
|---|---|---|---|
|
|
9019
|
+
| 1 | `tool_approval.readRootCandidate.covers` | **consumed(闭集单词,在场逐字)** | `src/hitl/toolApprovalWire.ts` `#ReadRootCandidateView` |
|
|
9020
|
+
| 2 | `FleetTaskRow.cycleSeq`(行帧) | **consumed(面板周期身份;此前只进 fleet 视图)** | `src/fleetAgentPanelProjection.ts`;`src/engineAgentPanelStore.ts` `#isStaleEngineAgentPanelEnd` |
|
|
9021
|
+
| 3 | `bg_notification.seq` | **consumed(通知车道 end 的周期身份;去重键此前已用)** | `src/notifications.ts` `#enqueueBgChildNotification` |
|
|
9022
|
+
| 4 | `task_remove.removeReason` / `.cycleSeq` | **consumed(读口;前代迟到帧不删行)** | `src/fleet/fleetLedger.ts` `task_remove` 臂 + `#FleetTaskRemoval` |
|
|
9023
|
+
| 5 | `bg_notification.seq` ↔ 行 `cycleSeq`(同轴) | **consumed(前代通知不退休 / 不改写留存池 / 不入事实台账;退场后按周期水位挡)** | 同文件 `#applyBgNotification`;`BgTerminalFacts.cycleSeq?` |
|
|
9024
|
+
|
|
9025
|
+
### 68y. 🔴 三端升级必读(固定段式,[C295])
|
|
9026
|
+
|
|
9027
|
+
1. 换钉 `^0.74.0` **同时**把 sdk 钉抬到 ≥9.7.1;审批卡的 add-dir 出路按 `readRootCandidate.covers` 分两支 —— `"exact"` ⇒ 逐字添加那条路径;缺席 ⇒ 目录出路同旧。
|
|
9028
|
+
2. 面板:行上记 `cycleSeq` / `startedAt`,`end` 先过 `isStaleEngineAgentPanelEnd`;复活后状态可翻回 running。不接线的端:`end` 多两个可选位,现行为不变。
|
|
9029
|
+
3. 账本离场读口可选;不装零变化。peer agent-types >=0.3.0 不动。
|
|
9030
|
+
|
|
9031
|
+
**包侧缺口:** ⓪ CC-67 无决断撤卡口 + CC-68 流内帧腿 outcome 回交(窗 09-22);① CC-69 `capabilities.deviceExecutor.management` 四态读口(server 7.88.0;窗 09-23);② headless(`-p` / SDK-stdio)无卡口 ⇒ 不装审批 feed,悬挂 ask 只进 doctor 面(成文候 CC-67 同批);③ CC-36 托管 MCP 活性三态读口(候 core #874);其余同 §67。
|
|
9032
|
+
|
|
9033
|
+
## §69 🆕 0.74.1 审批卡无决断收口(CC-67)+ 流内帧腿结局回交(CC-68)+ headless 成文;patch
|
|
9034
|
+
|
|
9035
|
+
> **patch**:型面纯 additive(+1 常量,公面 1045 → 1046;`ApprovalCardDecision` +`retracted` 臂;`ToolApprovalFrameOutcome` +`retracted?`;`FsApprovalOutcome` +`retracted` 臂;`AskGateWireDeps` +`onToolApprovalOutcome?`;零 wire 新键;peer 不动)。票来源:cli L-397 装配直讯两件。
|
|
9036
|
+
|
|
9037
|
+
### 69a. 处置表
|
|
9038
|
+
|
|
9039
|
+
| # | 面 | 本包做了什么 | 端要做什么 |
|
|
9040
|
+
|---|---|---|---|
|
|
9041
|
+
| S-1 | 卡口结局 `{ kind: 'retracted', reason? }` | **新增**:三条腿都零发送,结局 `unresolved` + `retracted` | 撤一张已无决断口的卡(换会话 / 换引擎 / tracker `gone`)时回它,**别**回 `aborted`(那仍是拒);`reason` 只留痕 |
|
|
9042
|
+
| S-2 | `onToolApprovalOutcome(frame, outcome)` | **新增**(可选;每次流内帧腿决断后恰一次) | 装上后直接按 `outcome.decision` / `retracted` / `editRefused` 判落没落定;`noteSurfacedByStream` 的孤儿认领据此回收 |
|
|
9043
|
+
| S-3 | headless(`-p` / SDK-stdio) | **成文**:无卡口 ⇒ **不装审批 feed**(挂上去只会白取件,并把一张按不下去的卡记成出过卡);悬挂 ask 只进 doctor / 提示面 | headless 车道不调 `startApprovalsFeed`;要展示悬挂数读 `livePendingNeedsReconcile` 与 feed 摘要之外的 doctor 面 |
|
|
9044
|
+
|
|
9045
|
+
### 69b. 缺席语义(逐键)
|
|
9046
|
+
|
|
9047
|
+
- `ToolApprovalFrameOutcome.retracted` 缺席 = 没发生撤卡(与 `editRefused` 同款附加位)。`decision: 'unresolved'` 本身仍只说「respond 没送达」。
|
|
9048
|
+
- `FsApprovalOutcome.kind === 'retracted'` 时 `gatedCallId` 与别的臂同一缺席纪律。
|
|
9049
|
+
- `onToolApprovalOutcome` 缺席 = 宿主不消费结局,路由行为逐字同旧。
|
|
9050
|
+
|
|
9051
|
+
### 69c. 黑盒判据骨架
|
|
9052
|
+
|
|
9053
|
+
- **G1**:假卡口回 `retracted` ⇒ 流内帧腿 `respond` 零次、`outcome.retracted === true`;修前:`respond(id, 'deny')` 一次。
|
|
9054
|
+
- **G2**:同一卡口回 `aborted` ⇒ 仍 deny 一次(语义不动;负控)。
|
|
9055
|
+
- **G3**:悬挂 ask(盲卡 / 全卡)撤卡 ⇒ 零 respond;durable-park 腿撤卡 ⇒ `decide` 零次、`kind: 'retracted'`。
|
|
9056
|
+
- **G4**:`routeFrame` 带 `onToolApprovalOutcome` ⇒ 每帧恰一次回交;回调抛错不拆流。
|
|
9057
|
+
|
|
9058
|
+
### 69z. 逐键处置表
|
|
9059
|
+
|
|
9060
|
+
| # | 键 / 面 | 处置 | 坐标 / 理由 |
|
|
9061
|
+
|---|---|---|---|
|
|
9062
|
+
| 1 | 卡口结局闭集 | **additive +retracted** | `src/hitl/toolApprovalWire.ts` `#ApprovalCardDecision` / `#RETRACTED_CARD_DECISION_KIND` |
|
|
9063
|
+
| 2 | 流内帧腿 / 悬挂 ask / durable-park 三腿 | **consumed(零发送臂)** | 同文件 `#surfaceToolApprovalFrameAndRespond` / `#surfaceFsApprovalAndDecide`;`src/hitl/parkResolver.ts` fail-soft 真因 |
|
|
9064
|
+
| 3 | 路由结局回交 | **additive** | `src/hitl/frameRouter.ts` `#AskGateWireDeps.onToolApprovalOutcome` |
|
|
9065
|
+
|
|
9066
|
+
### 69y. 🔴 三端升级必读(固定段式,[C295])
|
|
9067
|
+
|
|
9068
|
+
1. 换钉 `^0.74.1`:撤卡路径改回 `{ kind: 'retracted' }`;`aborted` 只留给用户真放弃。
|
|
9069
|
+
2. 装 `onToolApprovalOutcome` 后,孤儿认领回收改读结局;不装零变化。
|
|
9070
|
+
3. headless 不装审批 feed。peer 不动。
|
|
9071
|
+
|
|
9072
|
+
**包侧缺口:** ⓪ CC-69 `capabilities.deviceExecutor.management` 四态读口(窗 09-23);① CC-70 面板子代身份归一(窗 09-23);② CC-71 run 记录 `cancelContext` 读口 + 三分成因判定(窗 09-24);③ CC-36 候 core #874;其余同 §68。
|
|
9073
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/client-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.74.1",
|
|
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,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@sema-agent/agent-types": ">=0.3.0",
|
|
34
|
-
"@sema-agent/sdk": ">=9.
|
|
34
|
+
"@sema-agent/sdk": ">=9.7.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@sema-agent/agent-types": "^0.3.0",
|