@sema-agent/client-core 0.80.1 → 0.81.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -49,6 +49,23 @@
49
49
  > 挡住 ⇒ 本批把它机械化——④a0 对 `pending` 行**要求段头已是日期形**(`(未发布)` 直接红),阶段一
50
50
  > commit 漏转在发布前就红,不再靠人记。
51
51
 
52
+ ## 0.81.0(2026-09-22)
53
+
54
+ ### 🔴 BREAKING 预告(本版不删,0.82.0 删)
55
+ - **CC 形消息上的非 SDK 面键将在 0.82.0 退役**(CC-131 / C-R85):本版起本包发出的 `user` / `assistant` / `result` / `system` 消息只承诺 `@sema-agent/agent-types` 同臂声明的键与 `_sema_` 前缀的超集键;23 个此前挂在这些消息上的键(`toolUseResult`、`result.degraded` / `errorCode` / `model`、错误子型上的 `result.result`、`system.isMeta` / `timestamp` / `writtenPaths` / `attachedFiles`、`assistant.isApiErrorMessage`、task_notification 的 `stoppedBy` / `resumable` / `partial` / `exitCode` / `diagnostics` / `lines` / `result` / `injected` / `seq` / `source` / `recentSteps` / `editedFiles` / `task_type`)与 `system` 的 `memory_saved` 整个子型本版照旧铸出,但已登记到期日 0.82.0;逐键终态(改 `_sema_` 前缀 / 改读 SDK 面同义位 / 删)在 §90 处置表与 0.82.0 发车帖公布。按这些键读的端请在 0.82.0 前改读。
56
+
57
+ ### Fixed
58
+ - **`/rewind` 的「对话 + 代码一起回退」自 core 6.0.0 起被引擎拒**(CC-145,P1):`rewindSpecForMode('both')` 仍发已退役的 `rewindFiles:true`(引擎 typed 拒 `rewind.rewind_files_retired`),现改发真名 `restoreFiles:true`(core `TaskSpec.restoreFiles`);`projectRewind` 的每轮 capture 戳整只删(core 6.0.0 起文件历史按首触追踪恒开,那一戳只换来每轮一条弃用披露);`projectRewind` 第二参 `captureEnabled` 删签名(端同批摘掉供值链;留一个什么都不做的开关是另一种谎)。射程:code-only 与 conversation-only 两臂不变。
59
+
60
+ ### Added
61
+ - **user 工具结果记录带 SDK 面键 `tool_use_result`**(CC-131 / C-R85):agent-types `SDKUserMessage` 声明的拼法;与过渡键 `toolUseResult` 同引用、同缺席同在场(单铸点);直接把记录当 SDK 消息吐给外部消费方的端从此按声明读得到结构化工具输出。本包不出映射器:终态一张脸(SDK 面),端的内部转录面由端自己的入口适配器映回。
62
+ - **CC 形消息键普查门**(DS-19 硬门):本包每一处铸 CC 形消息的顶层键 ⇔ agent-types 同臂**同子型**成员表(按 `subtype` 分表,AST 现场见证)∪ `_sema_*` ∪ 带到期日的过渡表;顶层键按语法逐层解析(类型断言、`Partial<Pick<…>>` 收窄、计算名都洗不掉键;参数 / `let` / 可重绑函数 / 成员访问展开判不了即 exit 9);`subtype` 判别位取值沿 const 别名与函数返回追到根,`as` 断言与声明返回型不背书;构建期红,零常驻豁免。
63
+
64
+ ## 0.80.2(2026-09-22)
65
+
66
+ ### Fixed
67
+ - **`conflict.resume_context_unavailable` 的 `staleAfterSec` / `runId` 在真 SDK 上读不到**(CC-137):sdk 11.1.0 起把错误体上的非具名键收进 `APIError.extra`,这一码映射成的 `ConflictError` 没有具名位 ⇒ 顶层没有,而读口只读顶层 ⇒ 真调用链上文案第三句永远不带保留秒数与 runId,只有壳自造的普通对象才读得到。现在体源结构位统一 **顶层有效值优先、`extra` 兜底**(单铸读口;`resumeRetryLaterFromError` 的 `retryAfterSec`、`scenarioDenyFromError` 的 `allowlist`、429 用量窗的 `retryAfterSec` 因 sdk 子类本有具名位,行为不变、只多了 extra 兜底);头源 `retryAfterMs`(sdk 从 `Retry-After` 算)只读具名位,体里的同名字段不当窗。窄读域不变。射程:只影响经 sdk `APIError` 抛出的错误;直接喂普通对象的端行为不变。
68
+
52
69
  ## 0.80.1(2026-09-22)
53
70
 
54
71
  ### Changed
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.80.1
38
+ **Version:** 0.81.0
39
39
 
40
40
  - **Today** — the adapter seam, the whole `adapt()` pipeline (all 14 A-layer arms plus the
41
41
  B/D/E tool-card layers), the notification/caps/model families, the adapter kernel (stream driver
@@ -414,6 +414,7 @@ guard still cross-checks the table by name).
414
414
  | `scripts/run-sdk-registry-transit-test.mjs` | The package's cloud control-plane surface (`sdkRegistryTransit`), which lives behind its own `./registry` subpath entry point rather than on the root barrel, and this guard holds both halves of that decision. Upstream publishes the same surface behind a subpath of its own, because the subject differs: the engine-wire surface speaks for one engine's service credential, this one for a person's rotating token, and their refresh and error semantics were deliberately never merged. Keeping it behind a second entry point means a client that never touches the control plane neither resolves nor type-checks it. Every value re-export is therefore read from the file the subpath entry actually resolves to, and must be the **same reference** as upstream's own (the control-plane client class, the three config reads, the health probe, the feedback call, the auth-path constant, the content-address helper, and the two typed error classes a host recognises with `instanceof`); every type re-export is compared with the emitted declaration file in both directions; the gate's list and the source file's export lists are likewise compared both ways; and the root entry is checked to carry none of these names, with the root barrel's own source checked to reference the entry file nowhere — a name leaking onto the root would put the cost of this surface back on clients that never asked for it. The subpath is then verified end to end: the installed SDK must really publish its own `./registry` entry and declare every transited name inside it, and this package's own `exports` must point that subpath at exactly the files the gate just judged. Portability is two checks rather than one, done with a parser rather than a text search: the upstream subpath's emitted JavaScript, walked recursively, must contain neither a `node:` specifier (static, side-effect, dynamic, `require` and re-export forms all exercised) nor a Node **global** — because the same package's third entry point is a Node-only surface that imports nothing at all and reaches for the `Buffer` global, so a specifier check alone would pass it as isomorphic, while a byte-level search of it reports two `node:` hits that live entirely inside a documentation example. A text scanner that merely strips comments first gets both directions wrong on ordinary JavaScript — a regular-expression literal containing a slash pair swallows the rest of its line, and the word in a string reads as a reference — so both scanners run off the syntax tree and are checked against fixtures for each failure direction as well as against that real material — including a dynamic import written with a template literal, which a check that accepts only quoted strings misses entirely, and a dynamic import whose target cannot be determined statically, which is refused rather than read as no edge at all. Zero-processing is likewise enforced with a syntax-tree allowlist rather than a keyword search: every top-level statement must be a named re-export carrying that one specifier, so an import followed by an in-place edit of the upstream prototype is refused with a file and line — that shape leaves the name lists untouched and even keeps the same-reference check green, since both sides are then the one object that was damaged. The last section measures, rather than merely notes, one declaration-level gap: two of the upstream subpath's declaration files reference a package the SDK lists only among its own dev dependencies. Moving such a check to a scratch directory is not isolation, because package resolution walks the ancestor directories, so the gate builds a sandbox served by a restricted compiler host and proves the isolation both ways — a decoy copy of the missing package placed one level above the sandbox must silence the errors for an unrestricted host and must not silence them for the restricted one. Then it installs this package into that same sandbox as a real consumer would, and pins the two readings that justify the entry-point split: a consumer that imports only from the root sees no unresolved-module errors at all, while a consumer that imports the subpath sees exactly the two, reported honestly rather than swallowed by this layer. The day upstream ships those declarations, that section turns red and the note comes out with it. The separation itself rests on the root closure being computed correctly, so the portability guard that computes it was extended in the same change: a template-literal dynamic import is followed like any other edge, and an edge whose target cannot be resolved statically is refused on every one of the four graphs — without that, a single line in a third file already reachable from the root would put this surface back into the root runtime while every guard stayed green. |
415
415
  | `scripts/run-rule-removal-consequence-test.mjs` | The one sentence a rule-removal confirmation surface shows for what removing the rule will actually do: one line per behaviour the rule could have been enforcing, plus a neutral line for when that behaviour cannot be read back, so a caller that hits an out-of-set or missing value never falls back to a specific claim it cannot support. The guard compares the actual output against frozen text rather than merely checking that some string came back, so a dropped word or a swapped clause is caught the day it lands, and the four sentences are pinned pairwise distinct. The line for a rule that was denying something is pinned to say the removal widens what can run rather than echoing the wording used for a rule that asks again — the two are opposite directions, and sharing a sentence between them would tell the person confirming the removal the opposite of what is about to happen. The neutral line is checked from the other side for the same reason: it must not contain a word that belongs to only one of the three behaviours, because that would answer on behalf of a state the caller was unable to determine. The lookup that turns a raw stored or transmitted value into one of the three behaviours reads by strict equality only, proven with a fully trapped proxy and a counting getter to show it never touches a property on whatever it is handed, so a value with a legitimate-looking word sitting on its prototype chain is rejected exactly like any other out-of-set value rather than being unwrapped. A closing self-check mutates one character out of each frozen sentence and asserts the exact-match comparison actually fails on it, so the guard cannot pass by checking only that a string of some kind came back |
416
416
  | `scripts/run-mcp-engine-leg-test.mjs` | The two legs behind one row on the MCP detail card. In a two-process setup the servers are hosted by the **engine**, while the Status cell on the card reports **this client's own** connection to them, and the two are independent truths: this client failing to connect does not mean the server's tools are unavailable, and the engine leg on the same screen may be saying it completed an exchange moments ago. Two mints share the work. The first reads one server's liveness off the engine leg as six readings, and its load-bearing distinctions are three. **No roster that could be read end to end** (`null`, `undefined`, anything that is not an array, a length that is not a non-negative integer, a length beyond the scan bound, or rows that could not be read at all with nothing matched) is **not** the same as an **empty** roster, which is the engine leg's positive statement that it declared no servers; the same narrower that feeds this reader answers `undefined` when a non-empty section yields no readable row, so *I could not read it* never turns into *I know it is zero*, and a roster that was not read to the end never produces *this server is not on it*. **Could not be read is not the same as absent**: absence means only that the row carries no liveness key of its own, while a record that is present but unintelligible — a cell that is not an object, a word that is not a non-empty string, or a read that fails outright — is reported as unreadable and is decided before the observation beside it, since a record that may well have said the opposite is no evidence of reachability. **An ambiguous name is answered as ambiguous**: when a roster that was read end to end matches a name more than once, the reader reports the match count instead of picking one, because the upstream contract for the sibling MCP face states that names are not guaranteed unique, and picking optimistically would contradict the worst-fact-first verdict shown on the same screen. When a row's identity could not be read at all the reader makes **no claim about that name whatsoever**, not even a count, since the row it could not read may well be a second one carrying the same name — a row that is plainly not a row, such as a hole in a sparse array, is a different matter and leaves the roster complete. The observed word is passed through **verbatim as an open set**, so a fourth word one day arrives at consumers untouched. The second mint is the one sentence that goes under Status, and it appears **only** when this client's own connection really did fail — the other Status values already tell the truth, and a sentence on top of them would only muddy the verbatim health vocabulary. **The liveness observation outranks the tool roster, and having heard from the engine includes hearing that it could not tell, and hearing something unreadable**: a word meaning *looked and could not tell*, a word this version does not recognise, and a record that arrived but could not be read each get their own sentence rather than falling back to the roster, because falling back would say this client holds nothing at all while the diagnostics page shows that very record. A value that is not a reading at all is a different case and does fall back, since nothing then establishes that the engine sent anything. Only when liveness genuinely cannot speak does the roster get a turn, and the roster itself has four answers — tools were listed, nothing was said, the engine reported zero, and the count could not be read — because **unreadable, absent and zero are three different facts**. No sentence claims that nothing at all has been seen about the server, because on two of the readings that reach the roster the engine has plainly listed it; the sentence for a silent roster states only what this client holds. The nine sentences are pairwise distinct, each one names the engine leg, and **none of them renders the liveness word itself**. Membership of the word list is decided by the one shared predicate rather than a second copy, and the branch over the known words is pinned so that a new word upstream fails the build instead of silently taking the *not recognised* sentence. Neither mint ever throws, whatever a host hands it: every value is taken through one reader that accepts **own properties only** — an inherited key is not a wire fact, and one on a shared prototype could otherwise manufacture an engine observation or suppress a real one — reads each key exactly once, and keeps a read that fails apart from a value that is absent. The roster is walked by index rather than through the array's own `find`, the array test is guarded because it can throw on its own, and a length that overstates itself would otherwise spin forever |
417
+ | `scripts/run-cc-message-key-census-test.mjs` | The one rule behind CC-shaped messages this package emits: every top-level key on a `user` / `assistant` / `result` / `system` message must be a member the CC SDK mirror (`@sema-agent/agent-types`) declares for that same arm, or one of this package's `_sema_`-prefixed additive keys, or a row in a dated transition table that goes red the day its retire version arrives. Mint sites are found syntactically (identifier, quoted and computed `type` names alike) and their key sets are resolved syntactically too — inline literals, both branches of a conditional, the nullish-coalescing and logical or/and operators, `const` initializers and every `return` of a helper — so a type assertion, a `Partial<Pick<…>>` narrowing or a computed name cannot launder a key past the check, while a spread the tool cannot follow (a parameter, a `let`, a member access) fails the tool, never the product. Arms that carry a `subtype` discriminator are checked against that subtype's own member set, so a key declared only for another subtype does not pass on the strength of the arm-wide union. The runtime section drives the real adapter pipeline and pins the tool-result record's SDK-spelled `tool_use_result` (the transitional camelCase twin rides along by reference until 0.82.0). |
417
418
 
418
419
  Each suite carries a floor that only moves up — a refactor that stops executing a group of
419
420
  assertions is a failure, not a quieter pass. Guards anchor on the **installed artefact's content**
@@ -3,6 +3,9 @@ import { degradedToolResultBody, detectEngineBgShellReceipt, reportFindingsToolU
3
3
  import { chrome, mainLane, transcript } from './ids.js';
4
4
  import { flattenWireOutput } from './wireShapes.js';
5
5
  import { isCcToolDenialKind } from '../gateVocabulary.js';
6
+ function toolUseResultParts(v) {
7
+ return v !== undefined ? { tool_use_result: v, toolUseResult: v } : {};
8
+ }
6
9
  export function createToolCardLedger(ctx, idOf) {
7
10
  const pending = new Map();
8
11
  let assistantResponseId = null;
@@ -49,7 +52,7 @@ export function createToolCardLedger(ctx, idOf) {
49
52
  uuid: eventId ?? deriveTranscriptId({ toolCallId: p.id }, ctx),
50
53
  session_id: ctx.sessionId,
51
54
  ...(parentToolCallId !== undefined ? { parent_tool_use_id: parentToolCallId } : {}),
52
- toolUseResult: rich !== null ? rich.toolUseResult : (body.toolUseResult ?? body.content),
55
+ ...toolUseResultParts(rich !== null ? rich.toolUseResult : (body.toolUseResult ?? body.content)),
53
56
  ...(body.degraded !== undefined ? { _sema_degraded: body.degraded } : {}),
54
57
  ...(isCcToolDenialKind(end?.denialKind) ? { _sema_denial_kind: end.denialKind } : {}),
55
58
  }, ctx.now());
package/dist/adapt.d.ts CHANGED
@@ -14,7 +14,7 @@ export declare const ADAPTER_COVERAGE: {
14
14
  readonly b5: readonly ["B 层 structuredToToolUseResult 14 case(ask-user-question/bash/edit/create/update/text/grep/glob/notebook-edit/cron-create/cron-delete/cron-list/agent/task-output)+ workflow-run 登记副作用", "D 层 wireOutputToBody 3 臂(bash / taskoutput / 泛化);structured 白名单在场时 T11+T14 正则退位,缺席保回落", "E 层 4 臂:#117a bg Bash 回执 + #158 Monitor 回执(同臂按工具名分,registration.source 判别;判定在库→chrome bgshell_register)· TodoWrite oldTodos 富卡 · ReportFindings 按名认领 · Remember→memory_saved 系统消息", "tool_end_result → user tool_result 正常路径(卡本体);result 与 turn 末两处开卡兜底关闭(abort 不兜底,cli 同)", "task/task-list structured → chrome task_ledger_sync{source:\"structured\"}(判定归一在库、落盘留宿主)", "T7 诚实缺席(§8-4:不搬 mock 合成器,改 degraded 标记)· T20 diff hunks 进包(src/diff/patch.ts)"];
15
15
  readonly todo: readonly ["T13 的 **D 层** 半场(taskoutput block content)未随 structured 退位:退位会改 block content 形状(cli 那里是裸对象 = 件1 隐患),属行为面改动,无真实需求驱动 ⇒ 见 DIVERGENCE-8", "macrotask 让渡(cli 在提交前让出宏任务给 Ink;宿主渲染策略,不进库)"];
16
16
  };
17
- export declare const ADAPTER_DIVERGENCES: readonly [string, string, string, string, string, string, string, string, string];
17
+ export declare const ADAPTER_DIVERGENCES: readonly [string, string, string, string, string, string, string, string, string, string];
18
18
  export interface WireToCcAdapterWithLedger extends WireToCcAdapter {
19
19
  exportLedger(): AdapterLedgerState & Record<string, unknown>;
20
20
  importLedger(state: Partial<AdapterLedgerState> | Record<string, unknown>): number;
package/dist/adapt.js CHANGED
@@ -103,6 +103,9 @@ export const ADAPTER_DIVERGENCES = [
103
103
  '那一步会改 block content 形状(cli 在这里是裸对象,件1 隐患),无真实需求驱动,如实留白。',
104
104
  'DIVERGENCE-9(B5):`tool_result` 消息的 uuid —— cli 在缺 `eventId` 时铸随机 v4,本包派生 ' +
105
105
  '`wtc_<toolUseId>`(DIVERGENCE-2 同族:同流重放 ⇒ 同 id 序列,[1653])。守卫按别名结构比,不比字面。',
106
+ 'DIVERGENCE-10(0.81.0,C-R85 / CC-131 过渡 B):`tool_result` 消息上本包同时铸 SDK 面键 `tool_use_result` 与 ' +
107
+ 'CC 内部转录面驼峰 `toolUseResult`(同引用);壳自有实现只铸驼峰。守卫在两键同在场且同引用时按驼峰比、' +
108
+ '略过 snake 键(两侧对称,壳换钉 0.81.0 后两侧同形仍等);0.82.0 删驼峰后本条自然零触发 ⇒ 自退役。',
106
109
  ];
107
110
  class WireToCcAdapterImpl {
108
111
  ledger = createAdapterInstanceLedger();
@@ -205,6 +205,12 @@ function effectiveFactParts(rec) {
205
205
  ...(scopes !== undefined ? { _sema_effective_memory_scopes: scopes } : {}),
206
206
  };
207
207
  }
208
+ function reemitEffectiveFacts(f) {
209
+ return {
210
+ ...(f?._sema_effective_reasoning !== undefined ? { _sema_effective_reasoning: f._sema_effective_reasoning } : {}),
211
+ ...(f?._sema_effective_memory_scopes !== undefined ? { _sema_effective_memory_scopes: f._sema_effective_memory_scopes } : {}),
212
+ };
213
+ }
208
214
  function costFactParts(stats, observed) {
209
215
  const facts = readRunCostFacts(stats, observed);
210
216
  const lowerBound = usageLowerBoundOf(stats, observed);
@@ -398,7 +404,7 @@ function errorResult(ctx, parts) {
398
404
  modelUsage: modelUsageFor(parts.stats, parts.model),
399
405
  ...permissionDenialParts(parts.stats, parts.observed),
400
406
  ...costFactParts(parts.stats, parts.observed),
401
- ...(parts.facts ?? {}),
407
+ ...reemitEffectiveFacts(parts.facts),
402
408
  ...nestedUsageByTaskParts(parts.stats, parts.observed?.nestedUsageByTask),
403
409
  errors: [...parts.errors],
404
410
  ...(parts.errorCode !== undefined && parts.errorCode.length > 0 ? { errorCode: parts.errorCode } : {}),
@@ -29,7 +29,7 @@ export function taskNotificationToPrintFrame(n, identity = {}) {
29
29
  const f = normalizeTaskNotification(n);
30
30
  if (f === null)
31
31
  return null;
32
- const structured = (key) => Array.isArray(n[key]) && n[key].length > 0 ? { [key]: n[key] } : {};
32
+ const nonEmptyList = (v) => Array.isArray(v) && v.length > 0;
33
33
  return {
34
34
  type: 'system',
35
35
  subtype: 'task_notification',
@@ -46,8 +46,8 @@ export function taskNotificationToPrintFrame(n, identity = {}) {
46
46
  ...(f.diagnostics !== undefined ? { diagnostics: f.diagnostics } : {}),
47
47
  ...(f.result !== undefined ? { result: f.result } : {}),
48
48
  ...(f.lines !== undefined ? { lines: f.lines } : {}),
49
- ...structured('recentSteps'),
50
- ...structured('editedFiles'),
49
+ ...(nonEmptyList(n.recentSteps) ? { recentSteps: n.recentSteps } : {}),
50
+ ...(nonEmptyList(n.editedFiles) ? { editedFiles: n.editedFiles } : {}),
51
51
  ...(f.taskType !== undefined ? { task_type: f.taskType } : {}),
52
52
  ...(f.externalSource !== undefined ? { source: f.externalSource } : {}),
53
53
  ...(typeof n.seq === 'number' || typeof n.seq === 'string' ? { seq: n.seq } : {}),
@@ -39,7 +39,7 @@ export const REQUEST_FIELD_MATRIX = [
39
39
  { field: 'reasoningEffort', lanes: ['interactive', 'print', 'utility'], live: false, why: '思考档位(sdk `TaskRequest.reasoningEffort` 七词闭集;上游对表外词 400 响亮拒 ⇒ 本层不预铸第二判官)。档位是请求级的位、与车道无关:交互面 = `/effort` 拨盘,无人值守面 = 档位旗。🔴 端交的必须是**档位词**:「思考 token 数」今天没有上游对位(见 `UPSTREAM_ABSENT_REQUEST_INTENTS` 的 `maxThinkingTokens`),别把一个数字折成档位词发出去', whyUtilityLane: '有座:side-channel 该用显式低档(省钱省时);与 model 同一条理由 —— 本车道上这两位都由壳显式给,不跟用户会话的拨盘走' },
40
40
  { field: 'model', lanes: ['interactive', 'print', 'utility'], live: false, why: '模型选择(sdk `TaskRequest.model`;交互面 = `/model` 中途换模型的拨盘,无人值守面 = 模型旗 / 部署缺省那一路,side-channel 面 = 壳显式挑的那一只)。三条车道都有来源、都是提交面。🔴 0.79.0 改口:修前「print 的模型走另一条路」这句理由被用户面实测证伪 —— 无人值守车道传了模型名却整键不上请求体,于是同一个坏名字在交互态被引擎 400 点名、在无人值守态却安静换成部署缺省并在首帧回显一个没生效的名字。一个**选择**类声明被静默丢掉,后果与收紧类声明被静默丢掉同形(端不读回执就以为生效)—— 与 `excludeTools` 补 print 座同律。本层原样透传、不预判模型名(名字的合法性归引擎,本层不铸第二判官)', whyUtilityLane: '有座:side-channel 显式挑便宜的那只模型(不跟用户会话的 `/model` 拨盘走)' },
41
41
  { field: 'images', lanes: ['interactive'], live: false, why: '贴图提交是交互动作,`-p` 的 stdin 没有图片块', whyUtilityLane: '无座:贴图是交互动作,side-channel 的提交体里没有图片块' },
42
- { field: 'resumeAt/resumeAtMode/rewindFiles/rewindFilesTo', lanes: ['interactive'], live: false, why: 'E18 `/rewind` 是交互命令;四键同生同灭(resumeAtMode 是 both/conversation 两臂恒带的排他截语义位)', whyUtilityLane: '无座:回退是交互命令,而 side-channel 是一次性的独立会话,没有可回退的历史' },
42
+ { field: 'resumeAt/resumeAtMode/restoreFiles/rewindFiles/rewindFilesTo', lanes: ['interactive'], live: false, why: 'E18 `/rewind` 是交互命令;五键同生同灭(CC-145:core 6.0.0 起 both 臂发 restoreFiles,退役键 rewindFiles 只为旧读者留座不再铸;resumeAtMode 是 both/conversation 两臂恒带的排他截语义位)', whyUtilityLane: '无座:回退是交互命令,而 side-channel 是一次性的独立会话,没有可回退的历史' },
43
43
  { field: 'clientContext', lanes: ['interactive'], live: false, why: 'IANA 时区 + 可选邮箱 → core 本地化 `# Environment` 的 today;print 同样跑在用户机器上,缺席让引擎误标 (UTC)', gap: true, whyUtilityLane: '无座:本地化 today 的用途在用户会话的环境段,而 side-channel 的系统提示由壳整段给出 —— 这一列我判不准要不要(与本行 `gap` 同一条待办:要补先单独立项)' },
44
44
  { field: 'scratchpadDir', lanes: ['interactive'], live: true, why: '[816]③ per-session 暂存目录;print 也有 session,缺席让 `-p` 的工具写不进 exemptDir', gap: true, whyUtilityLane: '无座:per-session 暂存目录是给**工具**写的,零工具面上没人写' },
45
45
  ];
@@ -125,7 +125,7 @@ const INPUT_KEY_ROUTES = {
125
125
  memoryCapture: row('memoryCapture'),
126
126
  memory: row('memory'),
127
127
  approverPosture: row('approverPosture'),
128
- rewind: row('resumeAt/resumeAtMode/rewindFiles/rewindFilesTo'),
128
+ rewind: row('resumeAt/resumeAtMode/restoreFiles/rewindFiles/rewindFilesTo'),
129
129
  repo: row('repo'),
130
130
  council: row('council'),
131
131
  debate: row('debate'),
@@ -589,7 +589,7 @@ export function assembleTaskRequest(input, lane) {
589
589
  const rewindIn = i.rewind;
590
590
  if (present(rewindIn) && (typeof rewindIn !== 'object' || Array.isArray(rewindIn))) {
591
591
  throw new TypeError(`buildTaskRequest: rewind 只接受对象或缺席(undefined/null)—— 收到 ${coarseShape(rewindIn)}。` +
592
- '它是四个具名请求键(resumeAt / resumeAtMode / rewindFiles / rewindFilesTo)的合写位,不是任意展开口。错误文本只报形状,不回显值。');
592
+ '它是五个具名请求键(resumeAt / resumeAtMode / restoreFiles / rewindFiles / rewindFilesTo)的合写位,不是任意展开口。错误文本只报形状,不回显值。');
593
593
  }
594
594
  const rewindObj = present(rewindIn) ? rewindIn : {};
595
595
  const rewindWire = {};
@@ -1,3 +1,4 @@
1
+ import { readErrorNumber, readErrorString } from './wireFailureShape.js';
1
2
  import { RESUME_CONTEXT_UNAVAILABLE, RESUME_PLACEMENT_MISMATCH, RESUME_PREFLIGHT_REJECTED, RESUME_REOPEN_CODES, RESUME_ENV_FAILED, RESUME_TOOL_UNAVAILABLE, } from './engineErrorCodes.js';
2
3
  import { resumeRetryLaterFromError } from './wireErrorTriage.js';
3
4
  export const RESUME_REFUSAL_CODES = Object.freeze([
@@ -67,9 +68,10 @@ export function resumeContextUnavailableFromError(err) {
67
68
  const e = err;
68
69
  if (e.errorCode !== RESUME_CONTEXT_UNAVAILABLE)
69
70
  return null;
70
- const sec = e.staleAfterSec;
71
- const staleSec = typeof sec === 'number' && Number.isInteger(sec) && sec >= 1 ? sec : undefined;
72
- const runId = typeof e.runId === 'string' && e.runId.length > 0 ? e.runId : undefined;
71
+ const sec = readErrorNumber(err, 'staleAfterSec');
72
+ const staleSec = sec !== undefined && Number.isInteger(sec) && sec >= 1 ? sec : undefined;
73
+ const rid = readErrorString(err, 'runId');
74
+ const runId = rid !== undefined && rid.length > 0 ? rid : undefined;
73
75
  return {
74
76
  code: RESUME_CONTEXT_UNAVAILABLE,
75
77
  ...(staleSec !== undefined ? { staleAfterSec: staleSec } : {}),
@@ -1,9 +1,10 @@
1
1
  export interface SeamRewindSpec {
2
2
  resumeAt?: string;
3
3
  resumeAtMode?: 'at' | 'before';
4
+ restoreFiles?: boolean;
4
5
  rewindFiles?: boolean;
5
6
  rewindFilesTo?: string;
6
7
  }
7
8
  export type RewindMode = 'both' | 'conversation' | 'code';
8
9
  export declare function rewindSpecForMode(mode: RewindMode, targetEntryId: string): SeamRewindSpec;
9
- export declare function projectRewind(pending: SeamRewindSpec | undefined, captureEnabled: boolean): SeamRewindSpec;
10
+ export declare function projectRewind(pending: SeamRewindSpec | undefined): SeamRewindSpec;
@@ -1,17 +1,15 @@
1
1
  export function rewindSpecForMode(mode, targetEntryId) {
2
2
  switch (mode) {
3
3
  case 'both':
4
- return { resumeAt: targetEntryId, resumeAtMode: 'before', rewindFiles: true };
4
+ return { resumeAt: targetEntryId, resumeAtMode: 'before', restoreFiles: true };
5
5
  case 'conversation':
6
6
  return { resumeAt: targetEntryId, resumeAtMode: 'before' };
7
7
  case 'code':
8
8
  return { rewindFilesTo: targetEntryId };
9
9
  }
10
10
  }
11
- export function projectRewind(pending, captureEnabled) {
11
+ export function projectRewind(pending) {
12
12
  if (pending)
13
13
  return { ...pending };
14
- if (captureEnabled)
15
- return { rewindFiles: true };
16
14
  return {};
17
15
  }
@@ -1,3 +1,4 @@
1
+ import { readErrorNumber, readErrorStringList } from './wireFailureShape.js';
1
2
  import { DRAINING_ERROR_CODE, RESUME_AT_ERROR_CODE_PREFIX, RESUME_RETRY_LATER_CODES, RESUME_USAGE_WINDOW_EXHAUSTED, SCENARIO_NOT_ALLOWED_ERROR_CODE, } from './engineErrorCodes.js';
2
3
  export const WIRE_NETWORK_ERROR_PATTERN = /fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|EHOSTUNREACH|ENETUNREACH|EPIPE|socket hang up|UND_ERR|terminated|other side closed/i;
3
4
  function wireErrorDetail(err) {
@@ -63,9 +64,7 @@ export function scenarioDenyFromError(err) {
63
64
  const e = err;
64
65
  if (e.status !== 400 || e.errorCode !== SCENARIO_NOT_ALLOWED_ERROR_CODE)
65
66
  return null;
66
- const allowlist = Array.isArray(e.allowlist)
67
- ? e.allowlist.filter((x) => typeof x === 'string' && x.length > 0)
68
- : [];
67
+ const allowlist = (readErrorStringList(err, 'allowlist') ?? []).filter((x) => x.length > 0);
69
68
  return { allowlist };
70
69
  }
71
70
  export function resumeRetryLaterFromError(err) {
@@ -75,7 +74,7 @@ export function resumeRetryLaterFromError(err) {
75
74
  const code = e.errorCode;
76
75
  if (typeof code !== 'string' || !RESUME_RETRY_LATER_CODES.includes(code))
77
76
  return null;
78
- const sec = e.retryAfterSec;
77
+ const sec = readErrorNumber(err, 'retryAfterSec');
79
78
  const windowSec = typeof sec === 'number' && Number.isInteger(sec) && sec >= 1 ? sec : undefined;
80
79
  return {
81
80
  code,
@@ -5,4 +5,7 @@ export interface WireFailureShape {
5
5
  committed?: 'no' | 'unknown' | 'unreadable';
6
6
  message: string;
7
7
  }
8
+ export declare function readErrorNumber(o: object, key: string): number | undefined;
9
+ export declare function readErrorString(o: object, key: string): string | undefined;
10
+ export declare function readErrorStringList(o: object, key: string): readonly string[] | undefined;
8
11
  export declare function wireFailureShapeOf(e: unknown): WireFailureShape;
@@ -6,6 +6,47 @@ function readGuarded(o, key) {
6
6
  return undefined;
7
7
  }
8
8
  }
9
+ function readErrorSlot(obj, key, accept) {
10
+ const o = obj;
11
+ let top;
12
+ try {
13
+ top = o[key];
14
+ }
15
+ catch {
16
+ top = undefined;
17
+ }
18
+ if (accept(top))
19
+ return top;
20
+ let extra;
21
+ try {
22
+ extra = o['extra'];
23
+ }
24
+ catch {
25
+ extra = undefined;
26
+ }
27
+ if (typeof extra !== 'object' || extra === null || Array.isArray(extra))
28
+ return undefined;
29
+ let fromExtra;
30
+ try {
31
+ fromExtra = Object.hasOwn(extra, key) ? extra[key] : undefined;
32
+ }
33
+ catch {
34
+ fromExtra = undefined;
35
+ }
36
+ return accept(fromExtra) ? fromExtra : undefined;
37
+ }
38
+ export function readErrorNumber(o, key) {
39
+ const v = readErrorSlot(o, key, (x) => typeof x === 'number');
40
+ return typeof v === 'number' ? v : undefined;
41
+ }
42
+ export function readErrorString(o, key) {
43
+ const v = readErrorSlot(o, key, (x) => typeof x === 'string');
44
+ return typeof v === 'string' ? v : undefined;
45
+ }
46
+ export function readErrorStringList(o, key) {
47
+ const v = readErrorSlot(o, key, (x) => Array.isArray(x));
48
+ return Array.isArray(v) ? v.filter((x) => typeof x === 'string') : undefined;
49
+ }
9
50
  export function wireFailureShapeOf(e) {
10
51
  const o = e ?? {};
11
52
  const status = readGuarded(o, 'status');
@@ -1,3 +1,4 @@
1
+ import { readErrorNumber } from './wireFailureShape.js';
1
2
  import { USAGE_WINDOW_EXHAUSTED } from './engineErrorCodes.js';
2
3
  export const CONFLICT_APPROVAL_SETTLED = 'conflict.approval_settled';
3
4
  export const CONFLICT_RUN_NOT_RUNNING = 'conflict.run_not_running';
@@ -52,11 +53,13 @@ export function usageWindowExhaustedFromError(err) {
52
53
  const is429 = rawStatus === 429 || (rawStatus === undefined && (o.name === 'UsageWindowExhaustedError' || o.name === 'RateLimitedError'));
53
54
  if (!is429)
54
55
  return null;
55
- const sec = nonNegativeFinite(o.retryAfterSec)
56
- ? Math.ceil(o.retryAfterSec)
57
- : nonNegativeFinite(o.retryAfterMs)
58
- ? Math.ceil(o.retryAfterMs / 1000)
59
- : undefined;
56
+ const rawSec = readErrorNumber(o, 'retryAfterSec');
57
+ const sec = nonNegativeFinite(rawSec)
58
+ ? Math.ceil(rawSec)
59
+ : (() => {
60
+ const rawMs = o.retryAfterMs;
61
+ return nonNegativeFinite(rawMs) ? Math.ceil(rawMs / 1000) : undefined;
62
+ })();
60
63
  return { code: USAGE_WINDOW_EXHAUSTED, ...(sec !== undefined ? { retryAfterSec: sec } : {}) };
61
64
  }
62
65
  catch {
@@ -19,7 +19,7 @@
19
19
 
20
20
  | 项 | 值 | 真源 |
21
21
  |---|---|---|
22
- | 本包 | `@sema-agent/client-core` **0.80.1**(本批发布版 = **patch**:去键重发判据句按「铸」计(CC-143;§87「带键的体恰一次」作废 → 被铸恰一次,POST 几次随传输层)+ 接入文档段落自带射程限定词自 §88 起向前执法 + 模型预设表 deepseek 项改闭集真名 deepseek-flash(CC-144,C-R82 ①)+ 门里 git 兜底自陈探针(CC-142);零 wire 键、零投影臂、根公面 1195;§88。上一版 0.80.0 = **minor**:🔴 peer sdk 地板 >=11.2.1 → >=11.3.0 + 策略拒的归因上 wire(CC-133:发送面 deny+policy 带 settledBy / 读侧 policy_refused 十三词入 CC 规则桶 / 三错误码读口 / 直连门去键重发恰一次)+ 删除规则后果句归包(CC-132)+ /mcp 详情卡两腿分说归包(CC-134:六档读口 + 九句铸点,同批改口八处说满的话)+ 🔴 终帧旧拼法 `structuredOutput` 按 0.79.1 的宣告删除(只剩 CC 形 `structured_output`);根公面 1195;§87。上一版 0.79.1 = **patch**:终帧结构化产出同帧铸 CC 形 `structured_output`(旧拼法 `structuredOutput` 过渡一版,0.80.0 删;CC-130)+ 写审批 `argsOmitted` 退化卡在无受护写入部署形上重新解得出路径(CC-129)+ 云控制面十值二型经本包第二个入口 `@sema-agent/client-core/registry` 原样转口(根入口零变;CC-128 ①);根公面 1184;§86。上一版 0.79.0 = **minor**:server 7.93.0 过境批 —— peer sdk 地板 >=11.2.1 + 写口回执第六臂 unverified 与 503 体 committed 分臂(CC-124)+ 无 run 可读的 MCP 状态面(CC-74)+ 审批卡 mandated 位(CC-110)+ 请求装配第三车道 utility 与 approverPosture / maxTokens / outputRetries 三键 + print 车道 model 座(CC-116 / 118 / 123)+ 拒因两面分铸与四个机读位(CC-125)+ 模型轮边界划消息界(CC-126)+ 委派结果人类面读口按来源声明体内定位(CC-127)+ sdk 转口三件(CC-128)+ 通告码 memory.project_scope_absent(CC-122);公面 1184;§85。上一版 0.78.2 = **patch**:门的棘轮登记数字单真源 —— 五只门十一格棘轮 + 218 条沿革账搬进 scripts/registry.json、门只读不抄、负控改篡改登记物、下调通道 RATCHET-SLACK、新门 run-registry-test(CC-79 第一期)+ 两格存量松量收掉 + submit-wiring-manifest 门补 count===1 边界格;src 零改动,dist 逐字节同 0.78.1;公面 1154;§84。上一版 0.78.1 = **patch**:两辆并行车收货 + 三张跟进票 —— displayBody 人类面读口 + 围栏解析头尾配对收紧(CC-113)/ MCP 两处「没报」措辞分句(CC-115)/ 记忆治理面五动词调用口(CC-97 b)/ 非流式提交回执接线回执读口 readSubmitWiringManifest(CC-121)/ 三份失败判官抛出物读取收口(CC-119);公面 1154;§83。上一版 0.78.0 = **minor**:peer sdk 地板 >=9.8.1 → >=11.0.1(CC-106)+ 单步写口 200 体按 stillLive 判别联合改读、第五臂 revoked、三型取自 sdk、RulesFacade.write 必填、PersistedRuleLiveness 转口(CC-103)+ DeniedBy 第十词 read_boundary 专句(CC-106 ④)+ excludeAllTools 车道行;型面 BREAKING 三处、行为面同 0.77.2;公面 1143;§82。上一版 0.77.2 = **patch**:出包面结构卫生 —— 构建期 removeComments,dist js / d.ts 零注释(新门 run-dist-comments-test.mjs + 卫生门词表 32 条 + 文档向前执法;CC-100)+ gateDeniedByDetail 表外词兜底句改「本版不认识这个层名」(CC-111 ①);行为 / 型面逐字节同 0.77.1;公面 1143;§81。上一版 0.77.1 = **patch**:外部验收三件回填 —— 读器族边界残留 projectMcpReconnectCapability 只认自有键(CC-107)/ rewind 四子键恰读一次(CC-108)/ 子代输出合并按回体 output.type · retrieval_status 定处置(CC-109,server ≥7.92.0 cursorSemantics 缺席面);型面 additive 一处;公面 1143;§80。上一版 0.77.0 = **minor**:请求装配逐键去向回执 + print 车道补座 + 表外键响亮拒(CC-101,四条行为 BREAKING)/ 会话策略写端口(CC-105)/ 持久规则单步写面(CC-103)/ workflow 子代面板行代际三向恢复(CC-104,零改码)/ 能力位读器族口径整族改齐 + 外部验收 F-A / F-B 处置 + 合并树异源复审两轮处置;公面 1143;§79。上一版 0.76.2 = **patch**:制品卫生 —— 清 dist 重 build 去掉两只已撤出源码的编译产物 + dist ⇄ src 对账门;零源码 / 零型面 / 零行为改动;公面 1122;§78。上一版 0.76.1 = **patch**:能力位读器工厂(CC-75)/ MCP 活性观察读口(CC-36)/ `capabilities.peerLane` · `permissionRulesWrite` 四态读口(CC-102)/ 记忆治理面两只读口 + 三只条目面回体读口(CC-97 a)/ 主车道证明逐次新建(CC-99)+ 修 0.76.0 的 F1 / F2(身份四键一次性快照只修了投影口一侧);公面 1122;§77。上一版 0.76.0 = **minor**:六票一批 —— `prompt_assembled` 投影臂 / 审批 feed 三态(**型面 BREAKING**)/ `ApprovalResolution` 单源联合 / 记忆 spec 读口 / 终态词表上游钉 / `tasks_expand` 退役(**型面 BREAKING**),外加身份四键一次性快照(跨全部内部臂);公面 1081;§76。上一版 0.75.1 = **patch**:面板短命子代反序缓行放不出的残洞(外部复验 D1)+ 同代 running 帧三向定形(B4)+ #969 提货 `spawnName` 透传与 `agentType` 改读诚实来源(CC-95);§75。上一版 0.75.0 = **minor**:压缩的非 compacted 结局上 chrome 面 `compaction_outcome`(新内部臂 —— 自建 print 出口的端先表态)+ peer sdk 地板 `>=9.8.1`;型面 additive(ChromeEvent +1 臂)、公面 1065、零 wire 新键;§74。上一版 0.74.5 = **patch**:core 7.24.0 提货 `_sema_freed_tokens?` + 首见即终态的行零事件(幽灵完成行)+ `isNewEngineAgentPanelCycle` / `approvalOutcomeNoteOf` 上公面;型面 additive、公面 1065、peer 不动;§73。上一版 0.74.4 = **patch**:面板键「先发布的键为准」(tick 归不了一的三序不再两行)+ 前代 UUID 迟到 tick 丢弃 + `readRunCancelContext` 下钻收紧;型面 additive、公面 1061、peer 不动;§72。上一版 0.74.3 = **patch**:面板子代身份归一(tick / end 的 UUID 归到 fleet 尾段,宿主零改)+ run 记录 `cancelContext` 读口与成因四词 + workflow 行 `errorCode` + reopen 第二臂两件;型面纯 additive、公面 1061、peer 不动;§71。上一版 0.74.2 = **patch**:`capabilities.deviceExecutor.management` 四态读口(缺席 ≠ false;`deviceExecutor: false` = 车道缺席;管理动词可用性三态归包);公面 1052;§70。上一版 0.74.1 = **patch**:审批卡无决断收口 + 结局回交;§69。上一版 0.74.0 = **minor**:peer sdk 地板 >=9.7.1 + covers 过境 + 面板周期身份 + 离场读口;§68。上一版 0.73.5 = **patch**:workflow 规模告警判定上收进包(`evaluateWorkflowSize` 三态:未知的规模不当作规模正常;分母口径与帽优先级单源;env 读口纯函数);型面纯 additive、公面 1044、peer 不动;§67。上一版 0.73.4 = **patch**:终帧 `permission_denials` 第三键 ⇐ 同一条流 `tool_start` 入参按 `toolCallId` join(三道闸;join 不上留 sema 载体;🔴 更正 0.73.2「自动升级收口」一句)+ 审批 feed push 侧取件失败的欠账退避重试;型面纯 additive、公面 1033、peer 不动;§66。上一版 0.73.3 = **patch**:CC-61 sdk 9.7.1 提货 + `capabilities.approvalsStreamLive` 四态读口(缺席 = 判不出;`livePendingNeedsReconcile` 只在引擎明说会推时才让对账节拍降兜底)+ CC-60 五条模型面文案锚包侧半场(cursorSemantics 机读位 / result 行注记 / bash 首行两变体与良性槽 / 通知 seed 并集 / parked 臂);型面纯 additive、公面 1032、peer 不动;§65。上一版 0.73.2 = **patch**:CC-59 悬挂 ask 全卡 —— `livePending[].frame`(server ≥7.87.0)两道闸窄读进视图,在场即走流内帧腿同一条路(入参可见、改写可转发),缺席保持盲卡;CC-34 收口(引擎半场随 7.87.0 到货,判据交黑盒);型面纯 additive、公面 1026、peer 不动;§64。上一版 0.73.1 = **patch**:CC-57 `decidePlanReview` outcome 尾句按「决断有没有生效」四态选(单铸点 `planReviewOutcomeTail`;此前本地拒发仍让模型汇报已拒绝)+ CC-56 cancel 的 409 按机器码分家(`cancelConflictFromError` 三形 / 新安全码 `cancel_run_not_running`)与提交面 429 用量窗读口 + 人话;型面纯 additive、公面 1026、peer 不动;§63。上一版 0.73.0 = **minor,型面 BREAKING**:fleet 视图八个数值键改可选 —— CC-52 `FleetTaskView.elapsedMs` / `tokens` / `queuedCount` 与 `FleetWorkflowView.doneCount` / `totalCount` / `failedCount` / `tokens` / `elapsedMs` 不再 `?? 0`(有键 = 真值含真 0,缺键 = 不知道;逐键缺席语义见 §62b)+ 台账补偿链无基数不铸;公面导出名零增减 1019、零 wire 变化、peer 不动;§62。上一版 0.72.14 = **patch**:悬挂的流内 ask 拉半场 —— CC-55 `startApprovalsFeed` 快照加 `livePending` 段并进变化摘要(键缺席 = 未报,不铸空)+ 视图 / 去重账 / 与流内帧腿同链的决断口(入参不可见上卡明说、改写不转发)+ 宿主闸对账节拍 + 待决计数读口(不知道 = null);型面纯 additive、公面 1019、peer 不动;§61。上一版 0.72.13 = **patch**:server 7.86.0 提货 —— CC-46 plan_review `permissionModeAfter` 发口(三选卡双闸:宿主声明只读起步 ∧ 引擎 ≥7.86.0;400 field_conflict 两种处置)+ CC-54 `capabilities.executionLane` 四态读面(键缺席 ≠ 不是本机车道;`toolsRunHere` 判据归包)+ CC-53 detach 版本闸三态;型面 additive(另撤回 0.72.12 的主通道 `absent` 臂,改独立缺席订阅口)、公面 1011、peer 不动;§60;**预告 0.73.0 BREAKING**:fleet 视图数值键改可选。上一版 0.72.12 = **patch**:「缺席被折成正向终态」按类清剿 —— CC-50 M1 头条(fleet 行缺席改发 `absent` 不再铸 `end{isError:false}`)+ 六站一次改齐(缺席 ⇒ `unknown`)+ 结果边界 fail-closed 取舍 + `_sema_outcome` + `Outcome unknown:` 行 + CC-51 M6(default 臂不再谎报 running)+ 普查门 + DS-06;型面 additive、公面 993、peer 不动;行为面三处真变化见 CHANGELOG 取舍段;§59。上一版 0.72.11 = **patch**:core 7.23.0 提货 —— CC-49 通告码 66 → 67 `config.write_protection_unresolved`(operator;兄弟码 `target_view_absent` = 没有视图,这枚 = 有视图解析不出)+ `permission_denials` 自动升级腿通电(`gates[].toolCallId` ⇒ `tool_use_id`;CC-34 引擎半场);型面零变化、公面 989、peer 不动、devDep core ~7.23.0;§58。上一版 0.72.10 = **patch**:CC-41 leader run 终局 `needs_human` + `result.conflict` 三形读面(none 缺席不可分 / unreadable 在场读不懂 / conflict;`salvaged[]` 原样给落盘口;措辞单源不提重试);型面纯 additive、公面 989、peer 不动;§57。上一版 0.72.9 = **patch**:server 7.85.0 提货 —— CC-30 会话内 MCP re-dial 消费口(`reconnectMcpServer` 三态 / unsupported 恒五键 / 交易文案单源)+ CC-39② memory-status `autoConsolidationArmed` 三态 + CC-45 resume 补充句渲保留秒数;型面纯 additive、公面 985、peer 不动;§56。上一版 0.72.8 = **patch**:清账三票 —— `memory:"off"` 请求键(CC-39③,server 7.84.0 S-405)+ `runStream` 第二条中性臂 `Model output error:`(CC-43)+ 注入件撞活 run 自动 steer 零卡(CC-44);型面纯 additive、公面 977、peer 不动;§55。上一版 0.72.7 = **patch**:core 7.22.0 提货 —— 通告码 66 `mcp.server_redialed` + 读器 `readMcpServerRedialed` + `wiring_manifest.readDeny` 第九段 `_sema_readDeny`(缺席 = 没有内置行判这条腿);型面纯 additive、公面 971、peer 不动、devDep core ~7.22.0;§54。上一版 0.72.6 = **patch**:cli L-379 包侧半场 —— `steerFollowIntent` steer 后续听意图三态(tail / after-decision / after-wake)+ `activeRunSelfHealRow` 续听声明第五参;型面纯 additive、公面 969、peer 不动;§53。上一版 0.72.5 = **patch**:server 7.82.1 提货 —— `capabilities.webSearch.backend` 部署默认 WebSearch 后端四态读面(键缺席 = 老引擎判不了 ≠ `none`);型面纯 additive、公面 968、peer 不动;§52。上一版 0.72.4 = **patch**:core 7.21.x 三件经 server 7.82.0 提货 —— `wiring_manifest.autoConsolidation` 第八段 `_sema_autoConsolidation`(缺席 = indeterminate 不折 false);型面纯 additive、公面 962、peer 不动;§51。上一版 0.72.3 = **patch**:core #863 记忆单系统半场 ① —— `projectAgentsForWire` 投影 `agents[].memory`(user|project|local 三词同映射引擎平面 agent:<type>);型面纯 additive、公面 962、零 wire 新键、peer 不动;§50。上一版 0.72.2 = **patch**:workflow 视图两票 —— `LiveWorkflowController.resolution()` 六态(snapshot() 的 null 三义拆开)+ `noteOwnWorkflowRun` own 台账同拍登记;型面纯 additive、公面 961、零 wire 键、peer 不动;§49。上一版 0.72.1 = **patch**:server 7.80.1 提货 —— 409 `conflict.resume_context_unavailable` 结构读数(`staleAfterSec` / `runId`;sdk 9.6.0 尚未带键,经 sdk 今天恒缺席)+ `SkillSpec.baseDir`(只在本机车道带);型面纯 additive、公面 960、peer 不动;§48。上一版 0.72.0 = **minor**:型面 BREAKING —— 39 个零消费导出退出公面(CC-32 退役批,[7419] §45 预告 / cli [7422] 同意 / web-client·desktop 过节拍沉默 = 同意;名单见 §47a S-1);运行期零 BREAKING、公面 956、peer 不动、devDep core ~7.20.1;随批:已退役名账 `removed` + export-liveness 门 G 段 + 冻结账门 ⑧c;§47。上一版 0.71.4 = **patch**:core 7.20.1 提货 —— `ENGINE_NOTICE_CODES` 65 + `wiring_manifest.writeProtection` 第七段 `_sema_writeProtection`;型面纯 additive、公面 995、peer 不动、devDep core `~7.20.1`;§46。上一版 0.71.3 = **patch**:门体系清账批 —— CC-24 export-liveness 门 + 39 个导出退役预告(0.72.0 删,表态制)/ CC-26 `as unknown as` 铸链棘轮 / CC-25 冻结账门 ⑧ 段 / CC-06 B-081 包侧半场(终帧 `_sema_effective_reasoning` / `_sema_effective_memory_scopes` + resume reopen 族 + `routePairingVerdict`);型面纯 additive、公面 986 → 995、peer 不动;§45。上一版 0.71.2 = **patch**:接入方验收两票归包 —— CC-28 B-132 decide 拒体三句去内部车道词 / CC-29 B-133 committedUuids 唯一性(重复 ⇒ 形 f);零型面变化、公面 986、peer 不动;§44。上一版 0.71.1 = **patch**:接入档打回修正 —— CC-27 `ApprovalCardRequest.readRootCandidate?` 帧→卡透传位 + 新导出型 `ReadRootCandidateView`;型面纯 additive、公面 986 不变、peer 不动;§43。上一版 0.71.0 = **minor**:型面 BREAKING 六件 —— peer sdk 地板 >=9.6.0 + agent-types >=0.3.0 / `SkillsListingTruncatedFactsView` 删 `requestedBudgetBytes?`·`laneClamped?` / `WiringManifestMcpEntry` → `WiringManifestMcpEntryView` / `MAX_AGENT_SKILLS` 删 / `decide.workflow_host_not_parked` 退役;运行期零 BREAKING。内容:core 7.20.0 提货(闭集 +5 六十四码)/ 🔴 CC-16 `text_segment_end.committedUuids[]` / CC-08 全五件(tool_disclosure / tool_progress 两 chrome 臂、wiring_manifest tools·hooks·lsp 进切片、tool_roster_delta 接上、context_usage 进切片、`readRootCandidate` 镜像)/ CC-19 `mcpEngineLegPresence` 归包 / CC-20 not_parked clean-cut;公面 986;§42 / 42y 八条)|
22
+ | 本包 | `@sema-agent/client-core` **0.81.0**(本批发布版 = **minor**:CC 形消息一张脸(C-R85 / CC-131):user 工具结果记录加 SDK 面键 `tool_use_result`(与过渡键 `toolUseResult` 同引用,0.82.0 删驼峰)+ DS-19 普查门升硬门(键集按语法解析、按 type/subtype 分表;23 键 + 1 子型过渡表 retireBy 0.82.0,零常驻豁免)+ CC-145 `/rewind` both 臂改发 `restoreFiles:true`、`projectRewind(pending)` 单参;零 wire 键、零投影臂、根公面 1195;§90。上一版 0.80.2 = **patch**:`conflict.resume_context_unavailable` 的 `staleAfterSec` / `runId` 在真 SDK 上读不到(CC-137:sdk 11.1.0 起 `APIError` 把体上非具名键收进 `extra`,这一码映射成 `ConflictError` 无具名位,读口只读顶层 ⇒ 真调用链恒缺席)⇒ 体源结构位改「顶层有效值优先、`extra` 兜底」三只类型化读口单铸,有具名子类位的三处(`retryAfterSec` × 2 / `allowlist`)行为不变只多兜底,头源 `retryAfterMs` 只读具名位;零 wire 键、零投影臂、根公面 1195;§89。上一版 0.80.1 = **patch**:去键重发判据句按「铸」计(CC-143;§87「带键的体恰一次」作废 → 被铸恰一次,POST 几次随传输层)+ 接入文档段落自带射程限定词自 §88 起向前执法 + 模型预设表 deepseek 项改闭集真名 deepseek-flash(CC-144,C-R82 ①)+ 门里 git 兜底自陈探针(CC-142);零 wire 键、零投影臂、根公面 1195;§88。上一版 0.80.0 = **minor**:🔴 peer sdk 地板 >=11.2.1 → >=11.3.0 + 策略拒的归因上 wire(CC-133:发送面 deny+policy 带 settledBy / 读侧 policy_refused 十三词入 CC 规则桶 / 三错误码读口 / 直连门去键重发恰一次)+ 删除规则后果句归包(CC-132)+ /mcp 详情卡两腿分说归包(CC-134:六档读口 + 九句铸点,同批改口八处说满的话)+ 🔴 终帧旧拼法 `structuredOutput` 按 0.79.1 的宣告删除(只剩 CC 形 `structured_output`);根公面 1195;§87。上一版 0.79.1 = **patch**:终帧结构化产出同帧铸 CC 形 `structured_output`(旧拼法 `structuredOutput` 过渡一版,0.80.0 删;CC-130)+ 写审批 `argsOmitted` 退化卡在无受护写入部署形上重新解得出路径(CC-129)+ 云控制面十值二型经本包第二个入口 `@sema-agent/client-core/registry` 原样转口(根入口零变;CC-128 ①);根公面 1184;§86。上一版 0.79.0 = **minor**:server 7.93.0 过境批 —— peer sdk 地板 >=11.2.1 + 写口回执第六臂 unverified 与 503 体 committed 分臂(CC-124)+ 无 run 可读的 MCP 状态面(CC-74)+ 审批卡 mandated 位(CC-110)+ 请求装配第三车道 utility 与 approverPosture / maxTokens / outputRetries 三键 + print 车道 model 座(CC-116 / 118 / 123)+ 拒因两面分铸与四个机读位(CC-125)+ 模型轮边界划消息界(CC-126)+ 委派结果人类面读口按来源声明体内定位(CC-127)+ sdk 转口三件(CC-128)+ 通告码 memory.project_scope_absent(CC-122);公面 1184;§85。上一版 0.78.2 = **patch**:门的棘轮登记数字单真源 —— 五只门十一格棘轮 + 218 条沿革账搬进 scripts/registry.json、门只读不抄、负控改篡改登记物、下调通道 RATCHET-SLACK、新门 run-registry-test(CC-79 第一期)+ 两格存量松量收掉 + submit-wiring-manifest 门补 count===1 边界格;src 零改动,dist 逐字节同 0.78.1;公面 1154;§84。上一版 0.78.1 = **patch**:两辆并行车收货 + 三张跟进票 —— displayBody 人类面读口 + 围栏解析头尾配对收紧(CC-113)/ MCP 两处「没报」措辞分句(CC-115)/ 记忆治理面五动词调用口(CC-97 b)/ 非流式提交回执接线回执读口 readSubmitWiringManifest(CC-121)/ 三份失败判官抛出物读取收口(CC-119);公面 1154;§83。上一版 0.78.0 = **minor**:peer sdk 地板 >=9.8.1 → >=11.0.1(CC-106)+ 单步写口 200 体按 stillLive 判别联合改读、第五臂 revoked、三型取自 sdk、RulesFacade.write 必填、PersistedRuleLiveness 转口(CC-103)+ DeniedBy 第十词 read_boundary 专句(CC-106 ④)+ excludeAllTools 车道行;型面 BREAKING 三处、行为面同 0.77.2;公面 1143;§82。上一版 0.77.2 = **patch**:出包面结构卫生 —— 构建期 removeComments,dist js / d.ts 零注释(新门 run-dist-comments-test.mjs + 卫生门词表 32 条 + 文档向前执法;CC-100)+ gateDeniedByDetail 表外词兜底句改「本版不认识这个层名」(CC-111 ①);行为 / 型面逐字节同 0.77.1;公面 1143;§81。上一版 0.77.1 = **patch**:外部验收三件回填 —— 读器族边界残留 projectMcpReconnectCapability 只认自有键(CC-107)/ rewind 四子键恰读一次(CC-108)/ 子代输出合并按回体 output.type · retrieval_status 定处置(CC-109,server ≥7.92.0 cursorSemantics 缺席面);型面 additive 一处;公面 1143;§80。上一版 0.77.0 = **minor**:请求装配逐键去向回执 + print 车道补座 + 表外键响亮拒(CC-101,四条行为 BREAKING)/ 会话策略写端口(CC-105)/ 持久规则单步写面(CC-103)/ workflow 子代面板行代际三向恢复(CC-104,零改码)/ 能力位读器族口径整族改齐 + 外部验收 F-A / F-B 处置 + 合并树异源复审两轮处置;公面 1143;§79。上一版 0.76.2 = **patch**:制品卫生 —— 清 dist 重 build 去掉两只已撤出源码的编译产物 + dist ⇄ src 对账门;零源码 / 零型面 / 零行为改动;公面 1122;§78。上一版 0.76.1 = **patch**:能力位读器工厂(CC-75)/ MCP 活性观察读口(CC-36)/ `capabilities.peerLane` · `permissionRulesWrite` 四态读口(CC-102)/ 记忆治理面两只读口 + 三只条目面回体读口(CC-97 a)/ 主车道证明逐次新建(CC-99)+ 修 0.76.0 的 F1 / F2(身份四键一次性快照只修了投影口一侧);公面 1122;§77。上一版 0.76.0 = **minor**:六票一批 —— `prompt_assembled` 投影臂 / 审批 feed 三态(**型面 BREAKING**)/ `ApprovalResolution` 单源联合 / 记忆 spec 读口 / 终态词表上游钉 / `tasks_expand` 退役(**型面 BREAKING**),外加身份四键一次性快照(跨全部内部臂);公面 1081;§76。上一版 0.75.1 = **patch**:面板短命子代反序缓行放不出的残洞(外部复验 D1)+ 同代 running 帧三向定形(B4)+ #969 提货 `spawnName` 透传与 `agentType` 改读诚实来源(CC-95);§75。上一版 0.75.0 = **minor**:压缩的非 compacted 结局上 chrome 面 `compaction_outcome`(新内部臂 —— 自建 print 出口的端先表态)+ peer sdk 地板 `>=9.8.1`;型面 additive(ChromeEvent +1 臂)、公面 1065、零 wire 新键;§74。上一版 0.74.5 = **patch**:core 7.24.0 提货 `_sema_freed_tokens?` + 首见即终态的行零事件(幽灵完成行)+ `isNewEngineAgentPanelCycle` / `approvalOutcomeNoteOf` 上公面;型面 additive、公面 1065、peer 不动;§73。上一版 0.74.4 = **patch**:面板键「先发布的键为准」(tick 归不了一的三序不再两行)+ 前代 UUID 迟到 tick 丢弃 + `readRunCancelContext` 下钻收紧;型面 additive、公面 1061、peer 不动;§72。上一版 0.74.3 = **patch**:面板子代身份归一(tick / end 的 UUID 归到 fleet 尾段,宿主零改)+ run 记录 `cancelContext` 读口与成因四词 + workflow 行 `errorCode` + reopen 第二臂两件;型面纯 additive、公面 1061、peer 不动;§71。上一版 0.74.2 = **patch**:`capabilities.deviceExecutor.management` 四态读口(缺席 ≠ false;`deviceExecutor: false` = 车道缺席;管理动词可用性三态归包);公面 1052;§70。上一版 0.74.1 = **patch**:审批卡无决断收口 + 结局回交;§69。上一版 0.74.0 = **minor**:peer sdk 地板 >=9.7.1 + covers 过境 + 面板周期身份 + 离场读口;§68。上一版 0.73.5 = **patch**:workflow 规模告警判定上收进包(`evaluateWorkflowSize` 三态:未知的规模不当作规模正常;分母口径与帽优先级单源;env 读口纯函数);型面纯 additive、公面 1044、peer 不动;§67。上一版 0.73.4 = **patch**:终帧 `permission_denials` 第三键 ⇐ 同一条流 `tool_start` 入参按 `toolCallId` join(三道闸;join 不上留 sema 载体;🔴 更正 0.73.2「自动升级收口」一句)+ 审批 feed push 侧取件失败的欠账退避重试;型面纯 additive、公面 1033、peer 不动;§66。上一版 0.73.3 = **patch**:CC-61 sdk 9.7.1 提货 + `capabilities.approvalsStreamLive` 四态读口(缺席 = 判不出;`livePendingNeedsReconcile` 只在引擎明说会推时才让对账节拍降兜底)+ CC-60 五条模型面文案锚包侧半场(cursorSemantics 机读位 / result 行注记 / bash 首行两变体与良性槽 / 通知 seed 并集 / parked 臂);型面纯 additive、公面 1032、peer 不动;§65。上一版 0.73.2 = **patch**:CC-59 悬挂 ask 全卡 —— `livePending[].frame`(server ≥7.87.0)两道闸窄读进视图,在场即走流内帧腿同一条路(入参可见、改写可转发),缺席保持盲卡;CC-34 收口(引擎半场随 7.87.0 到货,判据交黑盒);型面纯 additive、公面 1026、peer 不动;§64。上一版 0.73.1 = **patch**:CC-57 `decidePlanReview` outcome 尾句按「决断有没有生效」四态选(单铸点 `planReviewOutcomeTail`;此前本地拒发仍让模型汇报已拒绝)+ CC-56 cancel 的 409 按机器码分家(`cancelConflictFromError` 三形 / 新安全码 `cancel_run_not_running`)与提交面 429 用量窗读口 + 人话;型面纯 additive、公面 1026、peer 不动;§63。上一版 0.73.0 = **minor,型面 BREAKING**:fleet 视图八个数值键改可选 —— CC-52 `FleetTaskView.elapsedMs` / `tokens` / `queuedCount` 与 `FleetWorkflowView.doneCount` / `totalCount` / `failedCount` / `tokens` / `elapsedMs` 不再 `?? 0`(有键 = 真值含真 0,缺键 = 不知道;逐键缺席语义见 §62b)+ 台账补偿链无基数不铸;公面导出名零增减 1019、零 wire 变化、peer 不动;§62。上一版 0.72.14 = **patch**:悬挂的流内 ask 拉半场 —— CC-55 `startApprovalsFeed` 快照加 `livePending` 段并进变化摘要(键缺席 = 未报,不铸空)+ 视图 / 去重账 / 与流内帧腿同链的决断口(入参不可见上卡明说、改写不转发)+ 宿主闸对账节拍 + 待决计数读口(不知道 = null);型面纯 additive、公面 1019、peer 不动;§61。上一版 0.72.13 = **patch**:server 7.86.0 提货 —— CC-46 plan_review `permissionModeAfter` 发口(三选卡双闸:宿主声明只读起步 ∧ 引擎 ≥7.86.0;400 field_conflict 两种处置)+ CC-54 `capabilities.executionLane` 四态读面(键缺席 ≠ 不是本机车道;`toolsRunHere` 判据归包)+ CC-53 detach 版本闸三态;型面 additive(另撤回 0.72.12 的主通道 `absent` 臂,改独立缺席订阅口)、公面 1011、peer 不动;§60;**预告 0.73.0 BREAKING**:fleet 视图数值键改可选。上一版 0.72.12 = **patch**:「缺席被折成正向终态」按类清剿 —— CC-50 M1 头条(fleet 行缺席改发 `absent` 不再铸 `end{isError:false}`)+ 六站一次改齐(缺席 ⇒ `unknown`)+ 结果边界 fail-closed 取舍 + `_sema_outcome` + `Outcome unknown:` 行 + CC-51 M6(default 臂不再谎报 running)+ 普查门 + DS-06;型面 additive、公面 993、peer 不动;行为面三处真变化见 CHANGELOG 取舍段;§59。上一版 0.72.11 = **patch**:core 7.23.0 提货 —— CC-49 通告码 66 → 67 `config.write_protection_unresolved`(operator;兄弟码 `target_view_absent` = 没有视图,这枚 = 有视图解析不出)+ `permission_denials` 自动升级腿通电(`gates[].toolCallId` ⇒ `tool_use_id`;CC-34 引擎半场);型面零变化、公面 989、peer 不动、devDep core ~7.23.0;§58。上一版 0.72.10 = **patch**:CC-41 leader run 终局 `needs_human` + `result.conflict` 三形读面(none 缺席不可分 / unreadable 在场读不懂 / conflict;`salvaged[]` 原样给落盘口;措辞单源不提重试);型面纯 additive、公面 989、peer 不动;§57。上一版 0.72.9 = **patch**:server 7.85.0 提货 —— CC-30 会话内 MCP re-dial 消费口(`reconnectMcpServer` 三态 / unsupported 恒五键 / 交易文案单源)+ CC-39② memory-status `autoConsolidationArmed` 三态 + CC-45 resume 补充句渲保留秒数;型面纯 additive、公面 985、peer 不动;§56。上一版 0.72.8 = **patch**:清账三票 —— `memory:"off"` 请求键(CC-39③,server 7.84.0 S-405)+ `runStream` 第二条中性臂 `Model output error:`(CC-43)+ 注入件撞活 run 自动 steer 零卡(CC-44);型面纯 additive、公面 977、peer 不动;§55。上一版 0.72.7 = **patch**:core 7.22.0 提货 —— 通告码 66 `mcp.server_redialed` + 读器 `readMcpServerRedialed` + `wiring_manifest.readDeny` 第九段 `_sema_readDeny`(缺席 = 没有内置行判这条腿);型面纯 additive、公面 971、peer 不动、devDep core ~7.22.0;§54。上一版 0.72.6 = **patch**:cli L-379 包侧半场 —— `steerFollowIntent` steer 后续听意图三态(tail / after-decision / after-wake)+ `activeRunSelfHealRow` 续听声明第五参;型面纯 additive、公面 969、peer 不动;§53。上一版 0.72.5 = **patch**:server 7.82.1 提货 —— `capabilities.webSearch.backend` 部署默认 WebSearch 后端四态读面(键缺席 = 老引擎判不了 ≠ `none`);型面纯 additive、公面 968、peer 不动;§52。上一版 0.72.4 = **patch**:core 7.21.x 三件经 server 7.82.0 提货 —— `wiring_manifest.autoConsolidation` 第八段 `_sema_autoConsolidation`(缺席 = indeterminate 不折 false);型面纯 additive、公面 962、peer 不动;§51。上一版 0.72.3 = **patch**:core #863 记忆单系统半场 ① —— `projectAgentsForWire` 投影 `agents[].memory`(user|project|local 三词同映射引擎平面 agent:<type>);型面纯 additive、公面 962、零 wire 新键、peer 不动;§50。上一版 0.72.2 = **patch**:workflow 视图两票 —— `LiveWorkflowController.resolution()` 六态(snapshot() 的 null 三义拆开)+ `noteOwnWorkflowRun` own 台账同拍登记;型面纯 additive、公面 961、零 wire 键、peer 不动;§49。上一版 0.72.1 = **patch**:server 7.80.1 提货 —— 409 `conflict.resume_context_unavailable` 结构读数(`staleAfterSec` / `runId`;sdk 9.6.0 尚未带键,经 sdk 今天恒缺席)+ `SkillSpec.baseDir`(只在本机车道带);型面纯 additive、公面 960、peer 不动;§48。上一版 0.72.0 = **minor**:型面 BREAKING —— 39 个零消费导出退出公面(CC-32 退役批,[7419] §45 预告 / cli [7422] 同意 / web-client·desktop 过节拍沉默 = 同意;名单见 §47a S-1);运行期零 BREAKING、公面 956、peer 不动、devDep core ~7.20.1;随批:已退役名账 `removed` + export-liveness 门 G 段 + 冻结账门 ⑧c;§47。上一版 0.71.4 = **patch**:core 7.20.1 提货 —— `ENGINE_NOTICE_CODES` 65 + `wiring_manifest.writeProtection` 第七段 `_sema_writeProtection`;型面纯 additive、公面 995、peer 不动、devDep core `~7.20.1`;§46。上一版 0.71.3 = **patch**:门体系清账批 —— CC-24 export-liveness 门 + 39 个导出退役预告(0.72.0 删,表态制)/ CC-26 `as unknown as` 铸链棘轮 / CC-25 冻结账门 ⑧ 段 / CC-06 B-081 包侧半场(终帧 `_sema_effective_reasoning` / `_sema_effective_memory_scopes` + resume reopen 族 + `routePairingVerdict`);型面纯 additive、公面 986 → 995、peer 不动;§45。上一版 0.71.2 = **patch**:接入方验收两票归包 —— CC-28 B-132 decide 拒体三句去内部车道词 / CC-29 B-133 committedUuids 唯一性(重复 ⇒ 形 f);零型面变化、公面 986、peer 不动;§44。上一版 0.71.1 = **patch**:接入档打回修正 —— CC-27 `ApprovalCardRequest.readRootCandidate?` 帧→卡透传位 + 新导出型 `ReadRootCandidateView`;型面纯 additive、公面 986 不变、peer 不动;§43。上一版 0.71.0 = **minor**:型面 BREAKING 六件 —— peer sdk 地板 >=9.6.0 + agent-types >=0.3.0 / `SkillsListingTruncatedFactsView` 删 `requestedBudgetBytes?`·`laneClamped?` / `WiringManifestMcpEntry` → `WiringManifestMcpEntryView` / `MAX_AGENT_SKILLS` 删 / `decide.workflow_host_not_parked` 退役;运行期零 BREAKING。内容:core 7.20.0 提货(闭集 +5 六十四码)/ 🔴 CC-16 `text_segment_end.committedUuids[]` / CC-08 全五件(tool_disclosure / tool_progress 两 chrome 臂、wiring_manifest tools·hooks·lsp 进切片、tool_roster_delta 接上、context_usage 进切片、`readRootCandidate` 镜像)/ CC-19 `mcpEngineLegPresence` 归包 / CC-20 not_parked clean-cut;公面 986;§42 / 42y 八条)|
23
23
  | peer:wire 契约 | `@sema-agent/sdk` **>=11.2.1**(value-level,非 type-only;**0.79.0 抬版**:11.2.x 声明 `capabilities.mcpProbe`、`mcpCapabilities` / `probeMcp` + `McpProbeFace`、写回执第三支 `stillLive: "unknown"`,11.2.1 再补 `TaskRequest.approverPosture` 与审批帧键 `mandated`(型面 + 运行期键锚),本包按 11.2.1 编译,11.0.1 失去物料见证;**0.78.0 曾抬到 >=11.0.1**:11.x 声明 `DeniedBy` 第十词 `read_boundary`、`rules.write` 200 体按 `stillLive` 判别联合、`RemovalLiveness` / `RuleWriteRequest` / `RuleWriteResult` / `RuleWriteBehavior` 包根导出、`TaskRequest.excludeAllTools`,本包按 11.0.1 编译,9.8.1 失去物料见证;**0.75.0 曾抬到 >=9.8.1**:9.8.x 声明 `Capabilities.deviceExecutor.management?`,9.7.1 失去物料见证;**0.74.0 曾抬到 >=9.7.1**:9.7.x 追平的六处型面是本包 0.73.3 起的编译基线,且 9.6.0 失去物料见证;**0.71.0 曾抬到 >=9.6.0**:`tool_disclosure` / `tool_progress` 两帧型与 `ToolApprovalFrame.readRootCandidate` 自 9.6.0 起;0.69.0 曾抬到 >=9.4.0(`reasoning_end` / `lastLegMcp`),0.60.0 抬到 >=8.4.0;地板由 `scripts/run-sdk-floor-test.mjs` 的 `FLOOR` 与 public-surface 门 C-CC-3「不低于见证到的最低实装版」双钉)| `package.json` `peerDependencies` |
24
24
  | peer:会话词汇表 | `@sema-agent/agent-types` **>=0.3.0**(type-only,零运行时;0.71.0 抬版:devDep 与 peer 同步,type-superset 门 ④ 撞名预警对着 0.3.0 的 .d.ts 求值) | 同上 |
25
25
  | runtime dep | `diff` ^9.0.0(**唯一**一条;portability 门按**等值**钉死) | `package.json` `dependencies` |
@@ -9599,7 +9599,76 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
9599
9599
 
9600
9600
  **包侧缺口:** ① 出包面注释存量(别仓名 / 票号 / 帖号 / 过程词)与卫生门判据太窄(CC-100)—— 方案候拍板(dist 去注释 vs 手清),0.77.2 · ② `DeniedBy` 第十词 `read_boundary` / `teamName` / `stillLive` 三词随 sdk 10 型面在 0.78.0 吸收(CC-106)· ③ `capabilities.mcpProbe` 候 core 7.26.0 #951 → server 7.93.0(CC-74)。
9601
9601
 
9602
- ## §88 🆕 0.80.1(未发布)判据措辞按「铸」计 + 段落自带射程限定词 + 预设表闭集真名(patch;根公面不动;零 wire 键、零投影臂)
9602
+ ## §90 🆕 0.81.0 CC 形消息一张脸:user 工具结果记录加 SDK 面键 `tool_use_result` + CC 形消息键普查硬门(23 键 + 1 子型过渡表,0.82.0 到期)(minor;根公面不动;零 wire 键、零投影臂)
9603
+
9604
+ > **minor**(行为面 additive 一键 + 制度面一门;peer sdk 地板 `>=11.3.0` 不动;根公面运行期导出 **1195 → 1195**)。裁定 **C-R85**(主板 [7980]):本包发出的 CC 形消息**只留 SDK 面**(`@sema-agent/agent-types` 为唯一真源),**不出映射器**;0.81.0 两键同引用过渡、0.82.0 删非 SDK 面键;DS-19 普查门升硬门、零常驻豁免。
9605
+ > 🔴 **射程限定词(本节按 0.81.0 的读法;若与发车帖不一致以发车帖为准)**:本段每条判据句旁的括号写明它在什么条件下不成立。
9606
+
9607
+ ### 90a. 处置表
9608
+
9609
+ | # | 面 | 本包做了什么 | 端要做什么 |
9610
+ |---|---|---|---|
9611
+ | S-1 | `type:'user'` 工具结果记录 `tool_use_result`(CC-131) | **added(SDK 面,权威)**:值 = sidecar typed 输出(富卡 safeParse 过)或正文回落,与 `toolUseResult` **同引用**、同缺席同在场;单铸点 | 直接把记录当 SDK 消息吐给外部的端(stream-json 出口)改读 `tool_use_result`;cli 类端走自己的入口适配器把 snake 映回内部驼峰(cli `remote/sdkMessageAdapter.ts:205`),出口铸点改读 snake(过渡期两键都在) |
9612
+ | S-2 | `toolUseResult`(过渡键) | **deprecated → 0.82.0 删**:本版照铸(同引用);过渡表 retireBy 0.82.0,到期门红 | 0.82.0 前改读 S-1 |
9613
+ | S-3 | 22 个非 SDK 面键 + 1 个非 SDK 面子型(见 90b 表) | **registered → 0.82.0 到期**:本版一个字节不改;逐键终态处置由 C-R83 双开车与消费方同窗定(候 [79xx] 处置帖) | 按这些键读的端(cli `isMeta` 77 处 / `exitCode` 144 处等)在处置帖到货后 0.82.0 前改读 |
9614
+ | S-5 | `rewindSpecForMode('both')` / `projectRewind`(CC-145,P1 B-148) | **fixed**:both 臂改发 `restoreFiles:true`(core ≥6.0.0 真名;退役键 `rewindFiles` 整键不再铸);capture 戳整只删,`projectRewind(pending)` **第二参删签名**(无 pending ⇒ `{}`) | 端把 `projectRewind(_, captureEnabled)` 的第二参与供值链一并摘掉(cli `seamRewindCapture` / `fileCheckpointingEnabled`);`rewindArm.ts` 只调 `rewindSpecForMode` 零改;端若自己钉了「每轮 `rewindFiles:true`」的判据作废(见 90y ③ ㉓) |
9615
+ | S-4 | CC 形消息键普查门(`run-cc-message-key-census-test.mjs`) | **added(制度)**:静态 AST 找站(标识符 / 引号名 / 计算名三形都认)+ 顶层键**按语法逐层解析**(字面量 / 条件 / `??` / const / 函数 return;类型断言洗不掉键;参数 / `let` / 成员访问展开一律判不了);成员表按 (`type`, `subtype`) **分表** AST 见证(子型间不串键;判别位取值语法优先、退到声明型字面量并集);过渡表带 retireBy;判不了的站 exit 9 | 零改;端若有「CC 形消息体上的非 `_sema_` 键」同形自铸点,同一把尺可复用 |
9616
+
9617
+ ### 90b. 缺席语义(逐键)+ 23 键 + 1 子型过渡表
9618
+
9619
+ - **`tool_use_result` 缺席** = 这张卡没有结构化输出也没有正文回落(与 `toolUseResult` 缺席同义,两键同缺席);**绝不**铸值为 `undefined` 的键。
9620
+ - **过渡表(23 键 + 1 子型,全部 retireBy 0.82.0;本版照铸,读法不变)**:`user.toolUseResult`(→ S-1);`result.degraded`(用户记录上同义键已叫 `_sema_degraded`,终态候定改前缀);`result.errorCode`(错误信封机器码,CC 结果错误臂无此位);`result.model`(MF-25 served model,CC 结果臂无 `model`;与 CC-141 真位同批定);`result.result`**只在四个 `error_*` 子型上**(错误信封带出的 salvaged 正文;CC 只在 `success` 子型声明 `result`;按子型分表后显形,终态候定改 `_sema_salvaged_result`);`system.attachedFiles`(compact_boundary 附带文件,CC 无);`system.writtenPaths` / `system.timestamp` / `system.isMeta`(`memory_saved` 子型整只不在 agent-types;`isMeta` 的 SDK 面同义位 = `isSynthetic`);`assistant.isApiErrorMessage`(SDK 面同义位候核 `assistant.error`);`task_notification` 十三键 `stoppedBy` / `resumable` / `partial` / `exitCode` / `diagnostics` / `lines` / `result` / `injected` / `seq` / `source` / `recentSteps` / `editedFiles` / `task_type`(残局归因族 + 结构位,CC `SDKTaskNotificationMessage` 无;`recentSteps` / `editedFiles` 修前经计算键展开藏在索引签名后、`task_type` 修前被同臂并集放行(CC 只在 `task_started` / `task_progress` 子型声明它),门按子型分表后显形);**过渡子型** `system/memory_saved`(整只子型不在 agent-types;门按子型分表后子型值本身也受约束,登过渡子型表同样 0.82.0 到期)。(车道射程:只覆盖本包源码里的 18 处铸点;端自己往记录上追加的键不在本表。)
9621
+
9622
+ ### 90c. 黑盒判据骨架
9623
+
9624
+ - **U-G1**(本版证明):真管线 `createWireToCcAdapter().adapt` 喂 `assistant{tool_use}` → `tool_end_result{structured}` ⇒ user 记录 `Object.hasOwn(msg,'tool_use_result') === true` ∧ `msg.tool_use_result === msg.toolUseResult`(同引用);`tool_end_result` 无 structured 无正文 ⇒ 两键同缺席。0.80.2 上前半 FAIL(红基线)。
9625
+ - **U-G2**(本版证明):agent-types `messages.d.ts` 的 `SDKUserMessage` / `SDKUserMessageReplay` 成员表含 `tool_use_result`、不含 `toolUseResult`(AST 见证;CC 改名当天红)。
9626
+ - **W-G1**(本版证明;时间射程:0.80.2 及以前 FAIL):`rewindSpecForMode('both','e1')` 逐字节 = `{ resumeAt:'e1', resumeAtMode:'before', restoreFiles:true }` ∧ `'rewindFiles' in …` 为假;`projectRewind(undefined)` 键数 0 且函数长度 1;`code` / `conversation` 两臂与 0.80.2 逐字相同。三模式映射:both = `{resumeAt, resumeAtMode:'before', restoreFiles:true}` / conversation = `{resumeAt, resumeAtMode:'before'}` / code = `{rewindFilesTo}`。
9627
+ - **U-G3**(回归约束):除 S-1 外,本版 user / assistant / result / system 消息的键集与 0.80.2 逐字相同(过渡表 23 键照铸)。
9628
+ - **K-G1**(制度门判据):在本包 src 任一 CC 形消息铸点加一个非 `_sema_`、不在同臂成员表、不在过渡表的键 ⇒ `run-cc-message-key-census-test` C1 红;把过渡表任一行 retireBy 改成 ≤ 当前版本 ⇒ C3 红。
9629
+ - **K-G2**(分表判据):在 `subtype:'task_notification'` 铸点加一个只在 `task_started` 子型声明的键(如 `task_type` 之外的 `description`)⇒ C1 红(同臂并集不放行);把该铸点的 `subtype` 改成参数值、同时留着子型专属键 ⇒ exit 9(子型判不了不给判词)。
9630
+ - **K-G3**(语法解析判据):在任一铸点把一个非法键藏进 `...({ bogus: 1 } as Record<string, unknown>)` / `...v`(`v` 为 `Partial<Pick<…>>` 收窄的 const)/ `[k]: 1`(`k` 为 const 串)⇒ 仍 C1 红;藏进参数 / `let` 变量 / 成员访问的展开 ⇒ exit 9;可重绑的 `let` 函数调用展开、经 `as` 断言收窄的 const 别名或函数返回当 `subtype` 判别位、子型判不了却带限子型的过渡键、同名遮蔽 `undefined` 的参数展开 —— 四形同样 exit 9(判别位取值沿 const 别名与函数 return 追到根,断言与声明返回型不背书;参数的声明型是信任边界,见 KNOWN-LIMITS KL-35)。
9631
+
9632
+ ### 90y. 🔴 三端升级必读(固定段式,[C295])+ 成文改口
9633
+
9634
+ 1. **换钉 `^0.81.0` 之前**:零前置(peer 地板不动);cli 类端把本包记录接进既有入口适配器、出口铸点改读 `tool_use_result`。
9635
+ 2. **逐面**:S-1 新键只加不改;23 键 + 1 子型过渡表本版**不改任何字节**,但 0.82.0 到期 —— 请对照 90b 列自己的读点,等处置帖。
9636
+ 3. **成文改口(旧判据眼作废 → 新判据眼)**:㉑ §87 S-3「读侧零改动即受益」的射程限定:只对本包铸的 `--print` 帧成立(`_sema_denial_kind` 铸在 `eventToSdkMessage` / `printToolResultFrame` 两处),**壳自己持久化的 Message 信封不在本包射程**(生产者半场在壳,壳侧另有票);㉒ 「本包 `type:'user'` 记录 = SDKMessage」作废 → 0.81.0 它同时带 SDK 面键与过渡键,0.82.0 起只是 SDK 面。㉓ 「both 回退 = `resumeAt` + `rewindFiles:true`」与「capture 开着时每轮 stamp `rewindFiles:true`」两句作废(core 6.0.0 起前者是 `restoreFiles`、后者无请求可发)。
9637
+
9638
+ **包侧缺口:** ① 23 键 + 1 子型终态处置未定(候 C-R83 双开车 + 消费方同窗;0.82.0 到期硬约束;处置帖**逐键**标「删 / 改 `_sema_` / 映到 SDK 面同义位」三态之一,不给汇总 —— cli 有 UI 读面,要求逐键);② `memory_saved` 整个 system 子型不在 agent-types(终态可能是整型改 `_sema_` 或退役);③ `result.model` 终态与 CC-141(served model 真位,候 core #1029)同批定。
9639
+
9640
+ ## §89 🆕 0.80.2 四处错误读口改「extra 优先、顶层兜底」(patch;零 wire 键、零投影臂;根公面不动)
9641
+
9642
+ > **patch**:零 wire 键、零投影臂、根公面运行期导出 **1195 → 1195**。一件行为修复(CC-137,DS-23 ① 同形):`conflict.resume_context_unavailable` 映射成的 `ConflictError` 没有具名位,`staleAfterSec` / `runId` 只在 `APIError.extra`(sdk 11.1.0 起体上非具名键都收进那里),而读口只读顶层 ⇒ 真调用链上恒缺席。现在体源结构位**顶层有效值优先、`extra` 兜底**,单铸读口;有具名子类位的三处(`retryAfterSec` × 2 / `allowlist`)行为不变只多兜底;头源 `retryAfterMs` 只读具名位。窄读域与缺席语义一字不变。
9643
+ > 🔴 **射程限定词(本节按 0.80.2 的读法;若与发车帖不一致以发车帖为准)**:本段每条判据句旁的括号写明它在什么条件下不成立。
9644
+
9645
+ ### 89a. 处置表
9646
+
9647
+ | # | 面 | 本包做了什么 | 端要做什么 |
9648
+ |---|---|---|---|
9649
+ | S-1 | `resumeContextUnavailableFromError(err).staleAfterSec` / `.runId`(CC-137) | **fixed**:真 SDK 形(`ConflictError`,结构位只在 `err.extra`)读得出;顶层是那个类型的有效值时取顶层,否则落 `extra`;`extra` 取值器抛 / 非普通对象 ⇒ 当缺席 | 零改;此前靠自造对象绕过的端可以删掉那层搬运 |
9650
+ | S-2 | `resumeRetryLaterFromError(err).retryAfterSec` / `waitable`(CC-137) | **unchanged + 兜底**:`ResumeRetryLaterError` 本有具名 `retryAfterSec`(sdk 从体算好),0.80.1 就读得到;本版只加 `extra` 兜底(未映射到子类时) | 零改 |
9651
+ | S-3 | `scenarioDenyFromError(err).allowlist`(CC-137) | **unchanged + 兜底**:`ScenarioNotAllowedError` 本有具名 `allowlist`;本版只加 `extra` 兜底 | 零改 |
9652
+ | S-4 | 429 用量窗读口 `retryAfterSec` / `retryAfterMs`(CC-137) | **unchanged + 兜底**:`retryAfterSec` 具名位本有(只加 extra 兜底);`retryAfterMs` 是头源具名位,只读具名位、体字段不当窗;体秒有效时**不碰**头毫秒(惰性短路与 0.80.1 一致:一个抛出的 `retryAfterMs` 取值器不会把整只拒绝吞成 null) | 零改 |
9653
+
9654
+ ### 89b. 缺席语义(逐键)
9655
+
9656
+ - 四处窄读域不变(整数 ∧ ≥1 / 非空串 / 字符串数组 / 非负有限);顶层是那个类型的值即取顶层(哪怕是 0,窄读再判),不是那个类型(缺席 / `null` / 串)才落 `extra`;`extra` 里的坏值同样降**缺席**不降 0(车道射程:仅 sdk `APIError` 形;普通对象照旧只读顶层,顶层缺席才看 `extra`)。
9657
+
9658
+ ### 89c. 黑盒判据骨架
9659
+
9660
+ - **O-G10**(本版证明;时间射程:0.80.1 及以前前半 FAIL):sdk 映射器 `toApiError(409, { errorCode:'conflict.resume_context_unavailable', staleAfterSec:120, runId:'run-1' })` 的产物(`ConflictError`,顶层无位)⇒ 读数带 `staleAfterSec:120` 与 `runId:'run-1'`;同形自造 `{ …, get extra(){…} }` 亦同。`resumeRetryLaterFromError` / `scenarioDenyFromError` / 429 读口在结构位**只在** `extra` 的自造形上同样读得出(未映射到子类的兜底路)。
9661
+ - **O-G11**(回归约束):顶层与 `extra` 都有时取顶层(`staleAfterSec` 顶层 5 / extra 120 ⇒ 5;顶层 `null` ⇒ 120);头源:`toApiError(503, { errorCode:'draining', retryAfterMs:0 }, 15000)` ⇒ 退避 15000(体字段不盖头部窗),无头 + 体 0 ⇒ 走默认梯;同内容放顶层(普通对象)四处读数与 0.80.1 逐字相同。
9662
+
9663
+ ### 89y. 🔴 三端升级必读(固定段式,[C295])+ 成文改口
9664
+
9665
+ 1. **换钉 `^0.80.2` 之前**:零前置;peer sdk 地板 `>=11.3.0` 不动。
9666
+ 2. **逐面**:四处读口的消费端零改;若端曾为绕过此病自己从 `err.extra` 搬运过这些位,可退役那层搬运。
9667
+ 3. **成文改口(旧判据眼作废 → 新判据眼)**:⑲ §84 那句「`staleAfterSec` / `runId` sdk 今天没搬上来 ⇒ 缺席,出键当天自动填满」作废(11.1.0 起搬在 `extra` 里、这一码映射成 `ConflictError` 无具名位,读口今起会读);⑳ 本段第一稿的「四处读口在真 SDK 上恒缺席 / extra 优先」作废(发前订正):三处有具名子类位本就读得到,规则是顶层有效值优先、extra 兜底。
9668
+
9669
+ **包侧缺口:** ① 读抛出物结构位的口约 12 处,本版改四处(逐口对 sdk 具名位:基类 `status` / `errorCode` / `retriable` / `message` + 子类 `retryAfterMs` / `retryAfterSec` / `allowlist` / `runId`),其余读的是具名位或非错误对象,未动;② 429 读口 `retryAfterSec`(体,秒)优先于 `retryAfterMs`(头)是 0.73.1 起的既有序,头 15s + 体 0 ⇒ 0 秒提示,本版未动(同一个量两源相左时该信谁候上游一句话)。
9670
+
9671
+ ## §88 🆕 0.80.1 判据措辞按「铸」计 + 段落自带射程限定词 + 预设表闭集真名(patch;根公面不动;零 wire 键、零投影臂)
9603
9672
 
9604
9673
  > **patch**:零 wire 键、零投影臂、根公面运行期导出 **1195 → 1195**;本段是三件**文档 / 数据表**改动 —— ① 去键重发判据句改按「铸」计(CC-143);② 段落自带**射程限定词**的形式定下并自本段起向前执法(CC-143);③ 模型预设表 `deepseek` 项改上游闭集真名(CC-144,候本批落地)。
9605
9674
  > 🔴 **射程限定词(本节按 0.80.1 的读法;若与发车帖不一致以发车帖为准)**:本段每条判据句旁的括号写明它在什么条件下不成立 —— **时间射程**(按哪一版的读法)或**车道射程**(只覆盖哪条腿)。读者据此知道一句话「只对一半」的那一半在哪,不必去别处找权威读法。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/client-core",
3
- "version": "0.80.1",
3
+ "version": "0.81.0",
4
4
  "description": "Client-side session runtime shared by every sema human client (TUI / web / desktop): sema wire frames (AgentEvent) -> CC session vocabulary (SDKMessage) with dual-plane output (transcript/chrome), deterministic transcript ids, lane discipline as a type, and the notification/dedup ledgers. Every CC-skin shape is collected here so the wire itself stays neutral. Renamed from @sema-agent/wire-cc-adapter (0.1.x).",
5
5
  "license": "MIT",
6
6
  "type": "module",