@sema-agent/client-core 0.72.8 → 0.72.9
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 +15 -0
- package/README.md +2 -1
- package/dist/adapter/activeRunSelfHeal.js +15 -0
- package/dist/adapter/runStream.js +7 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/mcpReconnect.d.ts +131 -0
- package/dist/mcpReconnect.js +235 -0
- package/dist/resumeRefusalCopy.d.ts +2 -2
- package/dist/resumeRefusalCopy.js +10 -4
- package/dist/sessionMemoryStatus.d.ts +15 -1
- package/dist/sessionMemoryStatus.js +18 -0
- package/docs/INTEGRATION-CLIENTS.md +42 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -49,6 +49,21 @@
|
|
|
49
49
|
> 挡住 ⇒ 本批把它机械化——④a0 对 `pending` 行**要求段头已是日期形**(`(未发布)` 直接红),阶段一
|
|
50
50
|
> commit 漏转在发布前就红,不再靠人记。
|
|
51
51
|
|
|
52
|
+
## 0.72.9(2026-09-18)
|
|
53
|
+
|
|
54
|
+
> 主题:**server 7.85.0 提货批**(发车帖 [7522] @client-core;CC-30 会话内 MCP re-dial 消费口 / CC-39② memory-status `autoConsolidationArmed` 读数)+ **CC-45 resume 补充句渲保留秒数**(cli L-383 / test [7516] N-G10)+ **CC-47 / CC-48**(test 0.72.8 验收 sema-internal#56 / #57)。**patch**:型面纯 additive(+2 常量 +6 函数,公面 977 → 985;`MemoryStatusFacts` 加一可选键;零 wire 新键 —— 端点 / 能力位 / 新键由 server 7.85.0 铸,本包只读;peer 不动)。接入面 §56。
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- **`src/mcpReconnect.ts`(CC-30;server ≥7.85.0 S-381 / core 7.22.0 #857;契约 §G.7c)**:`reconnectMcpServer(client, sessionId, server, { signal? })` 消费口(**永不抛**;duck-typed 注入 `sessions.mcpReconnect`,sdk 9.6.0 未声明;本地体门 `server` 非空 ≤190 不发注定 400 的请求;🔴 `signal` 已 abort ⇒ 动词零调用直接 `failed`(破坏性动词不在用户说停之后再发,不依赖壳传输看不看 signal);回声 `sessionId` / `server` 与请求逐字相等否则 `failed`)⇒ `McpReconnectVerdict`(`ok` / `invalid` / `not_running` / `unsupported{capability|route}` / `not_found` / `failed`,按 `errorCode` 分诊、无码不猜);`projectMcpReconnectResult(body)` 按 `outcome` 三词(`MCP_RECONNECT_OUTCOMES`)分形:🔴 `unsupported` **恒五键**(`prefix` / `toolCount` / `added` / `removed` 不编 `0` / `[]`),`accepted` / `refused` 四座必填缺一整只畸形;🔴 名册按 `toolNames` **在场性**(缺席 = 名册原样不动;`[]` = 工具被撤走);`status` 八键 `errorCode` **开集**透传(core 十词 server 不枚举,消费端 switch 必带 default),`error` / `serverInfo` / `reason` UNTRUSTED 消毒封长,`transportClosed` 在场即 true;`listingIncomplete` 原样。`projectMcpReconnectCapability(caps)` 能力位三态(`available` / `unavailable` / `not_reported` = 老 server 判不了);`mcpReconnectOutcomeDetail(view)` 措辞单源(`refused` 按 `toolNames` 在场性分三句:缺席 = 连接未动工具未撤 / `[]` = 工具撤走 / 非空 = 如实报名册);**`MCP_RECONNECT_TRANSACTION_NOTICE`** = 契约 🔴 必进 UI 的那句(健康 server 上重连 = 一次交易,不是刷新:旧连接先关、失败则工具撤走)。🔴 「在场但坏形 ≠ 缺席」:`toolNames` / `listingIncomplete` 在契约上缺席各是一条正面指令(名册别动 / 名册走完了),在场但读不懂 ⇒ 整只畸形,不折成缺席;`listingIncomplete.pages` 必填;`status.name` 是身份键不封长;`unsupported` 的 `reason` 可缺席(判别键是 `outcome`);501 按 `capability.*` / `feature.*` 前缀族分诊(server 本路由真发两道 501)。⚠️ `McpReconnectVerdict.kind:'unsupported'`(面 / 部署不存在)与 `result.outcome:'unsupported'`(这条 run 未声明 MCP)是**两个词两件事**,端别并成一句。门 `run-mcp-reconnect-test.mjs` 51 格(红先绿后;两路异源复审四条真修:分诊器在 catch 里读 Proxy 属性抛穿「永不抛」—— 登 `docs/DISEASE-SHAPES.md` DS-05 / refused 无条件说撤工具 / 坏形折缺席 / 501 第二码漏诊);singleton +1;typeshape `unknownExport` 349 → 354(负控锚同批);portability index 闭包 167。
|
|
59
|
+
- **memory-status `autoConsolidationArmed: boolean`(CC-39②;server 7.85.0 S-403;core #863 W1 唯一读法组)**:`MemoryStatusFacts = SessionMemoryStatus & { autoConsolidationArmed?: boolean }`,`readSessionMemoryStatus` 逐键条件拷贝(非布尔 / 老 server 缺席 ⇒ 键不在场,不铸 false);读器 **`readAutoConsolidationArmed(facts)`** ⇒ `armed` / `unarmed` / `indeterminate`(🔴 缺席 = 老 server <7.85.0 判不了,不折 unarmed;与 manifest `autoConsolidation` 段「缺席 = indeterminate」同律)。memory-status 门 G2c 段 +8 格(红先绿后)。
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- **`resumeContextUnavailableContent` 第三句带保留秒数**(CC-45;cli L-383 / test [7516] N-G10 / sema-internal#54):`staleAfterSec` 在场 ⇒ 第三句尾加「(本部署的会话保留时长为 N 秒)」(N 原数,读口已窄读为整数 ≥1);缺席 ⇒ 逐字同 0.72.1。0.72.1 曾把秒数留给端「单独渲」而端没渲 ⇒ 补充句永无保留秒数;归层改为**有数必渲、无数不编**。resume-refusal 门 ⑧ 段改钉五格(在场恰一次原数 / 缺席零数字 / runId 缺席时同样带数 / 缺席两形逐字节 = 0.72.1 基线串 / 措辞铸点自复核 `0` · 非整数 · 巨数不渲)。
|
|
64
|
+
- **注入形 steer 失败按 `delivery` 分句 + 已中止不 steer**(CC-47;test 0.72.8 验收 sema-internal#56):`running-steer-failed` 注入形不再落默认「NOT delivered … could not put a decision on screen」句 —— `unknown`(5xx / 断连,可能已注入)说「可能已送达、未重试(steer 不可安全重发)、请观察」并带上游真因;`rejected` 说引擎拒收、未重试、模型未收到;`deps.signal` 已 abort ⇒ 注入形不发那枪不可撤回的 steer(零动作 `not-parked`)。reopen 门 ③z +4 格。
|
|
65
|
+
- **`isModelOutputErrorText` 按位置认锚**(CC-48;test #57):真实 provider HTTP 400 的错误体引用了锚句(`offending text: "tool call argument(s) …"`)曾被子串命中改标为模型输出错误 ⇒ 锚**只认消息开头**(`trimStart` 后 `startsWith`;core 铸点两句都出现时用 ` | ` 连、第一句仍在开头);引用形 / 加前缀形 / `<上游错误> | <引用锚句>` 形一律不命中,仍 `API Error:`。identity-copy 门 G1c +5 格。
|
|
66
|
+
|
|
52
67
|
## 0.72.8(2026-09-18)
|
|
53
68
|
|
|
54
69
|
> 主题:**清账三票**(CC-39③ server 7.84.0 S-405 `memory:"off"` 请求键 / CC-43 cli L-372 ③ `Model output error:` 中性臂 / CC-44 cli L-380 注入件撞活 run 自动 steer 零卡)。**patch**:型面纯 additive(+2 常量 +4 函数,公面 971 → 977;`ActiveRunSelfHealDeps.submissionOrigin?` 可选席;零 wire 新键 —— `memory` 键由 server 7.84.0 铸,本包只发;peer 不动)。接入面 §55。
|
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.72.
|
|
38
|
+
**Version:** 0.72.9
|
|
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
|
|
@@ -311,6 +311,7 @@ public-surface guard checks that last one).
|
|
|
311
311
|
| `scripts/run-export-liveness-test.mjs` | Every runtime export in the public baseline must be **alive**: referenced by some gate, or explicitly registered in `scripts/export-liveness.json` as `contract` (consumed by a client with no gate yet), `internal` (an internal helper amplified onto the public surface by `export *`), `candidate` (with ticket + retire-by) or `retire` (dead; retire-by version). Registration is accounting, not exemption: a row for a name a gate already references is stale and must go, a row for a name no longer exported is red, `retire`/`candidate` rows go red the moment `package.json` reaches their retire-by version, and the row count only ratchets down. When the sibling client trees are on disk the consumption evidence is checked by name — a `contract` row's claimed consumers must equal the real set, and a `retire` name must not be imported by any client. Names that have already left the surface are kept in a per-version `removed` ledger: they must never reappear in the baseline or the registry, and the ledger's versions must not run ahead of the changelog. |
|
|
312
312
|
| `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). |
|
|
313
313
|
| `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") |
|
|
314
|
+
| `scripts/run-mcp-reconnect-test.mjs` | The in-session MCP re-dial verb (`POST /v1/sessions/:id/mcp/reconnect`, engine ≥7.85.0), consumed. The single discriminant is `outcome` and all three answers are HTTP 200, so the reader branches on the word and never on the status; the `unsupported` answer carries exactly five keys and the reader refuses to invent a zero or an empty list for the four fields the engine did not produce, while `accepted` / `refused` treat those four as required and go malformed when one is missing. The tool roster follows the **presence** of `toolNames` (absent = untouched, empty = withdrawn), the connection record passes `errorCode` through as an open set, and every remote-authored string is sanitised and bounded before display. Failures are classified by `errorCode` alone, a missing code is reported as unknown rather than guessed, the verb never throws, and the request-side guard (non-empty name, ≤190 chars) stops a call that the contract would reject anyway. The capability bit reads absent as "cannot tell" rather than "unavailable", and the one sentence the contract insists every UI carries — that re-dialing is a transaction, not a refresh — is minted here once |
|
|
314
315
|
| `scripts/run-core-value-ports-test.mjs` | The port-injection seam for ten **engine value-level** facilities (autonomous-loop prompt assembly, permission-rule loosening, tool-policy composition, protocol/retired-name/grammar lookups, rule compilation, the discussion workflow name). This package cannot re-export them (the engine barrel drags Node built-ins into the browser bundle), so it declares the ports and honest-absence readers; a Node host installs the engine's own functions verbatim. The guard pins: every reader returns `undefined` when nothing is installed (never a fabricated empty array or default policy), arguments and results pass through by reference, engine errors propagate unchanged, partial installs read partially, restore functions unwind to the previous bag, and the module source has zero engine imports |
|
|
315
316
|
| `scripts/run-read-face-posture-projection-test.mjs` | The operator-face `readFace: ReadFacePosture` reader (server >=7.65.0). Three ways of "can't say" are pinned to three different, literal sentences, and none of them may read as "nothing is pinned" — that statement belongs to exactly one case, `face: null`, which is a positive fact reported by the engine, not an absence: not having read an operator response yet, having read one from an engine too old to report the key, and the engine actually saying nothing is pinned are three different next steps for an operator and must not collapse into each other. `source` is read as an open set (the server's closed four words plus an escape hatch) rather than narrowed to an enum, so a new word added upstream is not silently turned into a bad reading. The free-text `note` is sanitized and length-capped before it is ever rendered. A companion pure function flags disagreement between this face and the tenant-facing `capabilities.readFace` — silent only when the two actually agree, honest-absent when either side cannot be read at all, never asserting agreement as a fact. The gate's last leg reads the installed SDK's own `openapi.yaml` directly rather than restating the schema in prose, so the package's leniency cannot quietly drift from the real contract |
|
|
316
317
|
| `scripts/run-display-cap-order-test.mjs` | The order in which untrusted text is sanitised and length-capped, across every mint point that puts an engine- or database-supplied string on a screen. The sanitiser rewrites each invisible character as a six-character escape, so capping the **raw** string first and escaping afterwards hands the screen six times the width that was budgeted — a forty-character allowance becomes two hundred and forty. The guard does not hardcode that allowance, because each mint point wraps its field in different fixed prose and the prose moves: it anchors on the deciding quantity instead, feeding one benign and one control-character input of the same length through the same mint and requiring the second not to come out longer. That criterion is immune to wording changes and stays sensitive to the expansion, and it is `<=` rather than `==` on purpose — a correct escape-then-cap backs the cut off a partially-consumed escape token, so the control-character line is legitimately the shorter of the two, and demanding equality would score that avoidance as a regression. Each mint is bracketed by two positive controls (the input really reaches the screen; the cap really engages) and the expansion predicate is shown to turn red against a deliberately cap-then-escape reference, so an all-green run cannot mean the guard simply measured nothing. The shared mint point is checked directly for the two avoidances it owes — never splitting an escape token in half, which would leave something on screen that looks like the beginning of a complete answer, and never splitting a legal surrogate pair, which would manufacture the very lone surrogate the sanitiser exists to catch |
|
|
@@ -965,6 +965,10 @@ async function runningChoiceArm(taskId, status, busy, statusFromWire, runs, deps
|
|
|
965
965
|
let offerDelivered = false;
|
|
966
966
|
if (injected) {
|
|
967
967
|
// CC-44:系统件不问人 —— canSteer 已在上面证过(动词在场 ∧ 有正文)。cancel 永不自动打(反钉纪律不变)。
|
|
968
|
+
// 🔴 CC-47(test 0.72.8 验收 #56 ②):用户已按 Esc(`deps.signal` 已 abort)⇒ **不发**这枪不可撤回的 steer,零动作现状行
|
|
969
|
+
// 收口 —— 用户说停之后系统件还往 run 里注入 = 「UI 显示已停、后台还在动」那一形。
|
|
970
|
+
if (probeCallerAborted())
|
|
971
|
+
return notParked;
|
|
968
972
|
choice = 'steer';
|
|
969
973
|
}
|
|
970
974
|
else if (typeof offer === 'function') {
|
|
@@ -1143,6 +1147,17 @@ export function activeRunSelfHealRow(outcome, signal, copy, origin, follow) {
|
|
|
1143
1147
|
*/
|
|
1144
1148
|
function injectedSubmissionRow(outcome, following = false) {
|
|
1145
1149
|
const handle = 'taskId' in outcome && outcome.taskId ? ` (run ${outcome.taskId})` : '';
|
|
1150
|
+
// 0.72.9 CC-47(test 0.72.8 验收 #56):steer 失败**按 delivery 分句**,不落默认 not-delivered 句 —— 那句说「could not put a
|
|
1151
|
+
// decision on screen」与真因不符,且对 `unknown`(5xx / 断连,可能已注入)断言「未送达、模型不知道」是替引擎编一句安全声明;
|
|
1152
|
+
// 用户据此手动补发 = 重复注入。与用户形同一条律:明确拒收才说没送到;送达未知只说「未知、未重试、请观察」。
|
|
1153
|
+
if (outcome.kind === 'running-steer-failed') {
|
|
1154
|
+
return outcome.delivery === 'unknown'
|
|
1155
|
+
? `A system notification was handed to the run that is already working${handle}, but the engine did not confirm delivery ` +
|
|
1156
|
+
`(${outcome.detail}) — that run may or may not have received it; sema did not retry (a steer cannot be re-sent safely). ` +
|
|
1157
|
+
`Watch that run for what it does next.`
|
|
1158
|
+
: `A system notification was NOT delivered: the engine refused it for the run that is already working${handle} ` +
|
|
1159
|
+
`(${outcome.detail}); sema did not retry. The model was not told about it.`;
|
|
1160
|
+
}
|
|
1146
1161
|
switch (selfHealSubmissionDisposition(outcome)) {
|
|
1147
1162
|
case 'held-for-decision':
|
|
1148
1163
|
return (`A system notification could not be delivered while an earlier turn${handle} is waiting on a ` +
|
|
@@ -185,8 +185,13 @@ export const MODEL_OUTPUT_ERROR_PREFIX = 'Model output error';
|
|
|
185
185
|
* 行回落 `API Error:`(开集兜底,不误报)。两句锚 = 同一铸点的两个分支(参数非 JSON / 无工具名),brain 用 ` | ` 连。
|
|
186
186
|
*/
|
|
187
187
|
export function isModelOutputErrorText(text) {
|
|
188
|
-
|
|
189
|
-
|
|
188
|
+
// 🔴 0.72.9 CC-48(test 0.72.8 验收 #57):**按位置**认锚,不按子串 —— 真实 provider HTTP 400 的错误体会引用这句
|
|
189
|
+
// (`offending text: "tool call argument(s) not valid JSON …"`),子串命中就把 API 侧拒请求说成模型输出坏了。
|
|
190
|
+
// core 的铸点把这两句放在 errorMessage **开头**(两句都出现时 brain 用 " | " 连,第一句仍在开头)⇒ **只认消息开头**;
|
|
191
|
+
// 引用形、加前缀形、`<上游错误> | <引用锚句>` 形(异源复审第二轮抓出:任意段首也是子串匹配的变体)一律不命中。
|
|
192
|
+
const anchors = ['tool call argument(s) not valid JSON', 'tool call(s) arrived with no tool name and cannot be executed'];
|
|
193
|
+
const t = text.trimStart();
|
|
194
|
+
return anchors.some((a) => t.startsWith(a));
|
|
190
195
|
}
|
|
191
196
|
/** 这一行是不是「模型输出问题」行(渲染面 / 归约面的谓词;与铸点同源,端别自抄前缀字面)。与 {@link isGovernanceStopRowText} 互斥。 */
|
|
192
197
|
export function isModelOutputErrorRowText(text) {
|
package/dist/index.d.ts
CHANGED
|
@@ -155,6 +155,7 @@ export * from './engineCapsCache.js';
|
|
|
155
155
|
export * from './sqlEngineCapability.js';
|
|
156
156
|
export * from './writeProtectionCapability.js';
|
|
157
157
|
export * from './webSearchBackendCapability.js';
|
|
158
|
+
export * from './mcpReconnect.js';
|
|
158
159
|
export * from './runTerminal.js';
|
|
159
160
|
export * from './readFacePosture.js';
|
|
160
161
|
export * from './mcpPanel.js';
|
package/dist/index.js
CHANGED
|
@@ -187,6 +187,9 @@ export * from './writeProtectionCapability.js';
|
|
|
187
187
|
// S-382(0.72.5;server ≥7.82.1,sdk 尚未声明):`Capabilities.webSearch.backend` 的四态窄读器 ——
|
|
188
188
|
// 部署默认 WebSearch 后端(`none` = 正面事实 / 键缺席 = 老引擎判不了,两者处置相反)。与上两只同构同纪律。
|
|
189
189
|
export * from './webSearchBackendCapability.js';
|
|
190
|
+
// S-381 / core 7.22.0 #857(0.72.9 CC-30;server ≥7.85.0,sdk 尚未声明):会话内 MCP re-dial 的消费口 —— 200 三态按 outcome 分形读、
|
|
191
|
+
// unsupported 恒五键、名册按 toolNames 在场性、失败按 errorCode 分诊、「重连 = 一次交易」措辞单源;能力位 mcpReconnect 三态读。
|
|
192
|
+
export * from './mcpReconnect.js';
|
|
190
193
|
// 0.60.0(engine ≥7.64.0 / sdk 8.4.0):终局因由与门记录两只**判定归包**的读器。
|
|
191
194
|
export * from './runTerminal.js';
|
|
192
195
|
// 0.61.0(engine ≥7.65.0 / sdk 8.5.0 / S-167):READ 容纳面档位 + 来源的 operator 面窄读器
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mcpReconnect — 会话内 MCP re-dial 的**三端共用消费口**(0.72.9 CC-30;server ≥7.85.0 S-381 / core 7.22.0 #857;
|
|
3
|
+
* 契约 §G.7c / 附录 B.1 `mcpReconnect`;sdk 9.6.0 尚未声明端点与体,读口 duck-typed 注入,与 `sessionMemoryStatus` 同款)。
|
|
4
|
+
*
|
|
5
|
+
* ── 这一口答的是哪件事 ────────────────────────────────────────────────────────────────────
|
|
6
|
+
* 传输断了的 stdio MCP server 在不结束任务的前提下**重拨一台具名 server**:`POST /v1/sessions/:id/mcp/reconnect { server }`。
|
|
7
|
+
* 壳只有「重连这台」按钮与结果渲染;判定(三态分臂 / 名册在场性 / 失败分诊 / 交易文案)三端各写一遍必各错一遍 ⇒ 归包。
|
|
8
|
+
*
|
|
9
|
+
* ── 🔴 五条契约读法(§G.7c 逐字)──────────────────────────────────────────────────────────
|
|
10
|
+
* ① `outcome` 是**唯一判别键**,三态全部走 200:`accepted`(core reconnected)/ `refused`(core refused **或** not_declared,
|
|
11
|
+
* wire 上刻意不可区分,子理由骑 `reason`)/ `unsupported`(server 自己的词:这条 run 一台 MCP 都没声明;不是 409、不是 refused)。
|
|
12
|
+
* ② `unsupported` **恒五键**(taskId / sessionId / server / outcome / reason):那条臂没有 core 结果,`prefix` / `toolCount` / `added` /
|
|
13
|
+
* `removed` 编成 `0` / `[]` = 替 core 说一句它没说过的话 ⇒ 本读器**按 outcome 分支再读**;accepted / refused 四座缺一 ⇒ 整只畸形。
|
|
14
|
+
* ③ **名册按 `toolNames` 的在场性**:在场非空 = 对该 `prefix` 域断言的名册(**超集**:core 挂载前还滤一道);在场 `[]` = 拨号失败、
|
|
15
|
+
* 这台的工具被撤走(空数组是一句话);整键缺席 = 这条臂从未碰过连接,挂载名册原样不动。真挂上了什么读 `wiring_manifest.tools`。
|
|
16
|
+
* ④ **下一步动作读 `status.errorCode` / `httpStatus`,不解析 `reason`**:`errorCode` 是 core 十词闭集但 server 不枚举 ⇒ 本读器按**开集**
|
|
17
|
+
* 透传(消费端 switch 必带 default);`delivered` 三词 / `transportClosed` 在场即 true(缺席 = 没观察到关闭,**不是**还活着);
|
|
18
|
+
* `error` / `serverInfo` / `reason` 是远端自由文本 —— UNTRUSTED-for-display,呈前消毒封长。
|
|
19
|
+
* ⑤ **交易,不是刷新**(core 原话,契约 🔴 必进 UI):旧连接在拨新号**之前**就被关 ⇒ 一次失败的重拨花掉一条能用的连接。
|
|
20
|
+
* 壳不许只写「重连」—— 措辞单源 {@link MCP_RECONNECT_TRANSACTION_NOTICE}。
|
|
21
|
+
*
|
|
22
|
+
* ── 失败分诊按 `errorCode` 不按 status(与 `classifyMemoryStatusFailure` 同律)────────────────
|
|
23
|
+
* 422 `steering.invalid_content` ⇒ invalid · 409 `steering.not_running` ⇒ not_running(parked / 终态 / 他副本 / 无活流四臂一码)·
|
|
24
|
+
* 501 `capability.run_store_required` ⇒ unsupported/capability · 404 `not_found.route` ⇒ unsupported/route(老 server 无此路由)·
|
|
25
|
+
* 404 `not_found.session` ⇒ not_found(未知 / 非属主同码同串)· 无码 ⇒ failed(**不猜**)。
|
|
26
|
+
*/
|
|
27
|
+
/** `outcome` 三词(契约 §G.7c;`unsupported` 是 server 的词,core 没有它)。 */
|
|
28
|
+
export declare const MCP_RECONNECT_OUTCOMES: readonly string[];
|
|
29
|
+
/**
|
|
30
|
+
* 「重连 = 一次交易」的**唯一措辞铸点**(三端共用;契约 🔴 这句必须进 UI,壳不许只写「重连」)。
|
|
31
|
+
* 零内部车道词;只说用户能据以决策的事实:旧连接先关、失败则工具撤走、直到再拨成功。
|
|
32
|
+
*/
|
|
33
|
+
export declare const MCP_RECONNECT_TRANSACTION_NOTICE: string;
|
|
34
|
+
/** `status`(这一次拨号的新连接时记录)的八键投影;`errorCode` 开集透传。UNTRUSTED 座已消毒封长。 */
|
|
35
|
+
export interface McpReconnectStatusView {
|
|
36
|
+
name: string;
|
|
37
|
+
status: string;
|
|
38
|
+
errorCode?: string;
|
|
39
|
+
httpStatus?: number;
|
|
40
|
+
delivered?: string;
|
|
41
|
+
serverInfo?: {
|
|
42
|
+
name: string;
|
|
43
|
+
version: string;
|
|
44
|
+
};
|
|
45
|
+
error?: string;
|
|
46
|
+
/** 在场即 `true`(core 永不写 false);缺席 = 没观察到关闭,**不是**「还活着」。 */
|
|
47
|
+
transportClosed?: true;
|
|
48
|
+
}
|
|
49
|
+
/** `listingIncomplete`:这次 `tools/list` 没走完 ⇒ 名册不许当全集(缺的一条是未证明缺席,不是被撤走)。 */
|
|
50
|
+
export interface McpReconnectListingIncompleteView {
|
|
51
|
+
reason: string;
|
|
52
|
+
/** 这次 `tools/list` 走到第几页(server 无条件投;非整数 ⇒ 整只畸形)。 */
|
|
53
|
+
pages: number;
|
|
54
|
+
budgetMs?: number;
|
|
55
|
+
error?: string;
|
|
56
|
+
}
|
|
57
|
+
/** 200 体的读视图 —— **按 `outcome` 分形**(`unsupported` 五键 / 其余四座必填)。 */
|
|
58
|
+
export type McpReconnectResultView = {
|
|
59
|
+
outcome: 'unsupported';
|
|
60
|
+
taskId: string;
|
|
61
|
+
sessionId: string;
|
|
62
|
+
server: string;
|
|
63
|
+
reason?: string;
|
|
64
|
+
} | {
|
|
65
|
+
outcome: 'accepted' | 'refused';
|
|
66
|
+
taskId: string;
|
|
67
|
+
sessionId: string;
|
|
68
|
+
server: string;
|
|
69
|
+
prefix: string;
|
|
70
|
+
toolCount: number;
|
|
71
|
+
/** 带命名空间的工具名(相对「一刻之前它挂载了什么」;失败的拨号移除它原有的全部)。**不是**通告 `mcp.server_redialed` 的计数。 */
|
|
72
|
+
added: string[];
|
|
73
|
+
removed: string[];
|
|
74
|
+
/** present-iff 这次结果对自己的 `prefix` 域做了名册断言(见文件头 ③);缺席 ⇒ 名册原样不动。 */
|
|
75
|
+
toolNames?: string[];
|
|
76
|
+
reason?: string;
|
|
77
|
+
status?: McpReconnectStatusView;
|
|
78
|
+
listingIncomplete?: McpReconnectListingIncompleteView;
|
|
79
|
+
};
|
|
80
|
+
/** 消费口的判决。`ok` 之外五档各是一条不同的下一步;`failed` 原错误带出(端要能看到真因)。 */
|
|
81
|
+
export type McpReconnectVerdict = {
|
|
82
|
+
readonly kind: 'ok';
|
|
83
|
+
readonly result: McpReconnectResultView;
|
|
84
|
+
} | {
|
|
85
|
+
readonly kind: 'invalid';
|
|
86
|
+
} | {
|
|
87
|
+
readonly kind: 'not_running';
|
|
88
|
+
} | {
|
|
89
|
+
readonly kind: 'unsupported';
|
|
90
|
+
readonly reason: 'capability' | 'route' | 'feature';
|
|
91
|
+
} | {
|
|
92
|
+
readonly kind: 'not_found';
|
|
93
|
+
} | {
|
|
94
|
+
readonly kind: 'failed';
|
|
95
|
+
readonly error: unknown;
|
|
96
|
+
};
|
|
97
|
+
/** 宿主注入的读口切片(duck-typed;sdk 9.6.0 没有本方法,壳用自己的传输层接 `POST /v1/sessions/:id/mcp/reconnect`)。 */
|
|
98
|
+
export interface McpReconnectClientLike {
|
|
99
|
+
sessions: {
|
|
100
|
+
mcpReconnect?: (sessionId: string, body: {
|
|
101
|
+
server: string;
|
|
102
|
+
}, opts?: {
|
|
103
|
+
signal?: AbortSignal;
|
|
104
|
+
}) => Promise<unknown>;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 200 体 → 读视图;**畸形一律 `undefined`**(不编、不猜)。按 `outcome` 分形读键(文件头 ①②③④)。
|
|
109
|
+
*/
|
|
110
|
+
export declare function projectMcpReconnectResult(body: unknown): McpReconnectResultView | undefined;
|
|
111
|
+
/** 抛出物 → 判决(按 `errorCode`;与 `classifyMemoryStatusFailure` 同律:无码不猜)。 */
|
|
112
|
+
export declare function classifyMcpReconnectFailure(e: unknown): McpReconnectVerdict;
|
|
113
|
+
/**
|
|
114
|
+
* 「重连这台 MCP」的消费口:**永不抛**。本地先按契约把体门(`server` 非空 ≤ 190)判掉,不发一条注定 400 的请求;
|
|
115
|
+
* 回体经 {@link projectMcpReconnectResult} 投影;**回声身份**(`sessionId` / `server`)与请求逐字相等,否则 `failed`(宁缺席不串台,
|
|
116
|
+
* 与 `readSessionMemoryStatus` 同律)。注入口没有方法 ⇒ `unsupported/route`(壳没接线 = 面不存在)。
|
|
117
|
+
*/
|
|
118
|
+
export declare function reconnectMcpServer(client: McpReconnectClientLike, sessionId: string, server: string, opts?: {
|
|
119
|
+
signal?: AbortSignal;
|
|
120
|
+
}): Promise<McpReconnectVerdict>;
|
|
121
|
+
/**
|
|
122
|
+
* 能力位 `GET /v1/capabilities.mcpReconnect`(设施依赖 = runStore ∧ sessionStorage.ownerOf)的三态读:
|
|
123
|
+
* `available` / `unavailable` / `not_reported`(键缺席 = 老 server <7.85.0 **判不了**,不折 unavailable);坏形 ⇒ `undefined`。
|
|
124
|
+
* 纯投影(caps 体由宿主交,本包不另开 tee:这一位只在按钮亮不亮时读一次)。
|
|
125
|
+
*/
|
|
126
|
+
export declare function projectMcpReconnectCapability(caps: unknown): 'available' | 'unavailable' | 'not_reported' | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* 三态 → 一句结果(**唯一措辞铸点**;三端共用;零内部车道词)。`accepted` 带工具计数;`refused` 说清工具已撤走(交易的代价)并带 reason;
|
|
129
|
+
* `unsupported` 说清是这条 run 的装配(未声明 MCP),不是 refused。
|
|
130
|
+
*/
|
|
131
|
+
export declare function mcpReconnectOutcomeDetail(view: McpReconnectResultView): string;
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mcpReconnect — 会话内 MCP re-dial 的**三端共用消费口**(0.72.9 CC-30;server ≥7.85.0 S-381 / core 7.22.0 #857;
|
|
3
|
+
* 契约 §G.7c / 附录 B.1 `mcpReconnect`;sdk 9.6.0 尚未声明端点与体,读口 duck-typed 注入,与 `sessionMemoryStatus` 同款)。
|
|
4
|
+
*
|
|
5
|
+
* ── 这一口答的是哪件事 ────────────────────────────────────────────────────────────────────
|
|
6
|
+
* 传输断了的 stdio MCP server 在不结束任务的前提下**重拨一台具名 server**:`POST /v1/sessions/:id/mcp/reconnect { server }`。
|
|
7
|
+
* 壳只有「重连这台」按钮与结果渲染;判定(三态分臂 / 名册在场性 / 失败分诊 / 交易文案)三端各写一遍必各错一遍 ⇒ 归包。
|
|
8
|
+
*
|
|
9
|
+
* ── 🔴 五条契约读法(§G.7c 逐字)──────────────────────────────────────────────────────────
|
|
10
|
+
* ① `outcome` 是**唯一判别键**,三态全部走 200:`accepted`(core reconnected)/ `refused`(core refused **或** not_declared,
|
|
11
|
+
* wire 上刻意不可区分,子理由骑 `reason`)/ `unsupported`(server 自己的词:这条 run 一台 MCP 都没声明;不是 409、不是 refused)。
|
|
12
|
+
* ② `unsupported` **恒五键**(taskId / sessionId / server / outcome / reason):那条臂没有 core 结果,`prefix` / `toolCount` / `added` /
|
|
13
|
+
* `removed` 编成 `0` / `[]` = 替 core 说一句它没说过的话 ⇒ 本读器**按 outcome 分支再读**;accepted / refused 四座缺一 ⇒ 整只畸形。
|
|
14
|
+
* ③ **名册按 `toolNames` 的在场性**:在场非空 = 对该 `prefix` 域断言的名册(**超集**:core 挂载前还滤一道);在场 `[]` = 拨号失败、
|
|
15
|
+
* 这台的工具被撤走(空数组是一句话);整键缺席 = 这条臂从未碰过连接,挂载名册原样不动。真挂上了什么读 `wiring_manifest.tools`。
|
|
16
|
+
* ④ **下一步动作读 `status.errorCode` / `httpStatus`,不解析 `reason`**:`errorCode` 是 core 十词闭集但 server 不枚举 ⇒ 本读器按**开集**
|
|
17
|
+
* 透传(消费端 switch 必带 default);`delivered` 三词 / `transportClosed` 在场即 true(缺席 = 没观察到关闭,**不是**还活着);
|
|
18
|
+
* `error` / `serverInfo` / `reason` 是远端自由文本 —— UNTRUSTED-for-display,呈前消毒封长。
|
|
19
|
+
* ⑤ **交易,不是刷新**(core 原话,契约 🔴 必进 UI):旧连接在拨新号**之前**就被关 ⇒ 一次失败的重拨花掉一条能用的连接。
|
|
20
|
+
* 壳不许只写「重连」—— 措辞单源 {@link MCP_RECONNECT_TRANSACTION_NOTICE}。
|
|
21
|
+
*
|
|
22
|
+
* ── 失败分诊按 `errorCode` 不按 status(与 `classifyMemoryStatusFailure` 同律)────────────────
|
|
23
|
+
* 422 `steering.invalid_content` ⇒ invalid · 409 `steering.not_running` ⇒ not_running(parked / 终态 / 他副本 / 无活流四臂一码)·
|
|
24
|
+
* 501 `capability.run_store_required` ⇒ unsupported/capability · 404 `not_found.route` ⇒ unsupported/route(老 server 无此路由)·
|
|
25
|
+
* 404 `not_found.session` ⇒ not_found(未知 / 非属主同码同串)· 无码 ⇒ failed(**不猜**)。
|
|
26
|
+
*/
|
|
27
|
+
import { capForDisplay } from './fleetTaskDesc.js';
|
|
28
|
+
/** `outcome` 三词(契约 §G.7c;`unsupported` 是 server 的词,core 没有它)。 */
|
|
29
|
+
export const MCP_RECONNECT_OUTCOMES = Object.freeze(['accepted', 'refused', 'unsupported']);
|
|
30
|
+
/**
|
|
31
|
+
* 「重连 = 一次交易」的**唯一措辞铸点**(三端共用;契约 🔴 这句必须进 UI,壳不许只写「重连」)。
|
|
32
|
+
* 零内部车道词;只说用户能据以决策的事实:旧连接先关、失败则工具撤走、直到再拨成功。
|
|
33
|
+
*/
|
|
34
|
+
export const MCP_RECONNECT_TRANSACTION_NOTICE = 'Reconnecting closes the current connection before dialing again. On a healthy server this is a transaction, ' +
|
|
35
|
+
'not a refresh: a failed re-dial leaves the server down and withdraws its tools from the model until a later re-dial succeeds.';
|
|
36
|
+
const RECONNECT_TEXT_MAX = 200;
|
|
37
|
+
const RECONNECT_WORD_MAX = 40;
|
|
38
|
+
/** 契约 §G.7c:`server` 非空且 ≤ 190 字符(逐字进 core 运维通告 `detail.server`)。 */
|
|
39
|
+
const SERVER_NAME_MAX = 190;
|
|
40
|
+
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
41
|
+
const nonEmpty = (v) => typeof v === 'string' && v.length > 0;
|
|
42
|
+
const stringList = (v) => Array.isArray(v) && v.every((t) => typeof t === 'string') ? [...v] : undefined;
|
|
43
|
+
function projectStatus(raw) {
|
|
44
|
+
if (!isRecord(raw) || !nonEmpty(raw.name) || !nonEmpty(raw.status))
|
|
45
|
+
return undefined;
|
|
46
|
+
// `name` 是**身份键**(core `statuses[name]` 的键,与顶层 `server` 同一事实),不是远端自由文本 ⇒ 原样,不封长(opus 替补复审 [low]);
|
|
47
|
+
// 消毒封长只给 serverInfo / error 两座远端文本。
|
|
48
|
+
const view = { name: raw.name, status: raw.status };
|
|
49
|
+
if (nonEmpty(raw.errorCode))
|
|
50
|
+
view.errorCode = raw.errorCode;
|
|
51
|
+
if (typeof raw.httpStatus === 'number' && Number.isInteger(raw.httpStatus))
|
|
52
|
+
view.httpStatus = raw.httpStatus;
|
|
53
|
+
if (nonEmpty(raw.delivered))
|
|
54
|
+
view.delivered = raw.delivered;
|
|
55
|
+
const si = raw.serverInfo;
|
|
56
|
+
if (isRecord(si) && typeof si.name === 'string' && typeof si.version === 'string') {
|
|
57
|
+
view.serverInfo = { name: capForDisplay(si.name, RECONNECT_WORD_MAX), version: capForDisplay(si.version, RECONNECT_WORD_MAX) };
|
|
58
|
+
}
|
|
59
|
+
if (typeof raw.error === 'string')
|
|
60
|
+
view.error = capForDisplay(raw.error, RECONNECT_TEXT_MAX);
|
|
61
|
+
if (raw.transportClosed === true)
|
|
62
|
+
view.transportClosed = true;
|
|
63
|
+
return view;
|
|
64
|
+
}
|
|
65
|
+
function projectListingIncomplete(raw) {
|
|
66
|
+
// `reason` / `pages` 必填(server 侧无条件投 pages):缺一 = 读不懂这一格,由调用方判整只畸形(在场但坏形 ≠ 缺席)。
|
|
67
|
+
if (!isRecord(raw) || !nonEmpty(raw.reason))
|
|
68
|
+
return undefined;
|
|
69
|
+
if (typeof raw.pages !== 'number' || !Number.isInteger(raw.pages) || raw.pages < 0)
|
|
70
|
+
return undefined;
|
|
71
|
+
const view = { reason: raw.reason, pages: raw.pages };
|
|
72
|
+
if (typeof raw.budgetMs === 'number' && Number.isFinite(raw.budgetMs))
|
|
73
|
+
view.budgetMs = raw.budgetMs;
|
|
74
|
+
if (typeof raw.error === 'string')
|
|
75
|
+
view.error = capForDisplay(raw.error, RECONNECT_TEXT_MAX);
|
|
76
|
+
return view;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 200 体 → 读视图;**畸形一律 `undefined`**(不编、不猜)。按 `outcome` 分形读键(文件头 ①②③④)。
|
|
80
|
+
*/
|
|
81
|
+
export function projectMcpReconnectResult(body) {
|
|
82
|
+
if (!isRecord(body))
|
|
83
|
+
return undefined;
|
|
84
|
+
if (!nonEmpty(body.taskId) || !nonEmpty(body.sessionId) || !nonEmpty(body.server))
|
|
85
|
+
return undefined;
|
|
86
|
+
const outcome = body.outcome;
|
|
87
|
+
if (typeof outcome !== 'string' || !MCP_RECONNECT_OUTCOMES.includes(outcome))
|
|
88
|
+
return undefined;
|
|
89
|
+
const base = { taskId: body.taskId, sessionId: body.sessionId, server: body.server };
|
|
90
|
+
if (outcome === 'unsupported') {
|
|
91
|
+
// 恒五键:其余键真出现了也不过境。`reason` 是人读文本(server 侧可为空)—— `outcome` 才是唯一判别键,
|
|
92
|
+
// 一句人读文本不许把判别键整只报废(opus 替补复审 [low]):缺席 / 空串 ⇒ 视图无 reason 键。
|
|
93
|
+
const u = { outcome: 'unsupported', ...base };
|
|
94
|
+
if (nonEmpty(body.reason))
|
|
95
|
+
u.reason = capForDisplay(body.reason, RECONNECT_TEXT_MAX);
|
|
96
|
+
return u;
|
|
97
|
+
}
|
|
98
|
+
// accepted / refused:四座必填(core 型上必填,server 原样投),缺一整只畸形。
|
|
99
|
+
const added = stringList(body.added);
|
|
100
|
+
const removed = stringList(body.removed);
|
|
101
|
+
if (!nonEmpty(body.prefix) || typeof body.toolCount !== 'number' || !Number.isInteger(body.toolCount) || body.toolCount < 0)
|
|
102
|
+
return undefined;
|
|
103
|
+
if (added === undefined || removed === undefined)
|
|
104
|
+
return undefined;
|
|
105
|
+
const view = {
|
|
106
|
+
outcome: outcome,
|
|
107
|
+
...base,
|
|
108
|
+
prefix: body.prefix,
|
|
109
|
+
toolCount: body.toolCount,
|
|
110
|
+
added,
|
|
111
|
+
removed,
|
|
112
|
+
};
|
|
113
|
+
// 🔴 「在场但坏形」≠「缺席」(opus 替补复审 [medium]×2):`toolNames` 缺席 = 名册别动、`listingIncomplete` 缺席 = 名册走完了,
|
|
114
|
+
// 两者在契约上都是**正面指令**;把读不懂的那一格折成缺席 = 替 server 下一条它没下的指令 ⇒ 在场但坏形一律整只畸形。
|
|
115
|
+
if ('toolNames' in body && body.toolNames !== undefined) {
|
|
116
|
+
const toolNames = stringList(body.toolNames);
|
|
117
|
+
if (toolNames === undefined)
|
|
118
|
+
return undefined;
|
|
119
|
+
view.toolNames = toolNames;
|
|
120
|
+
}
|
|
121
|
+
if (nonEmpty(body.reason))
|
|
122
|
+
view.reason = capForDisplay(body.reason, RECONNECT_TEXT_MAX);
|
|
123
|
+
const status = projectStatus(body.status);
|
|
124
|
+
if (status !== undefined)
|
|
125
|
+
view.status = status;
|
|
126
|
+
if ('listingIncomplete' in body && body.listingIncomplete !== undefined) {
|
|
127
|
+
const li = projectListingIncomplete(body.listingIncomplete);
|
|
128
|
+
if (li === undefined)
|
|
129
|
+
return undefined;
|
|
130
|
+
view.listingIncomplete = li;
|
|
131
|
+
}
|
|
132
|
+
return view;
|
|
133
|
+
}
|
|
134
|
+
/** 抛出物 → 判决(按 `errorCode`;与 `classifyMemoryStatusFailure` 同律:无码不猜)。 */
|
|
135
|
+
export function classifyMcpReconnectFailure(e) {
|
|
136
|
+
// 🔴 读 `errorCode` 本身包在 try 里(异源对抗复审 [medium]):拒因可以是 Proxy / 带抛 getter 的对象,读一个属性就抛 ⇒
|
|
137
|
+
// 分诊器抛穿「永不抛」。读不出 = 判不出码 ⇒ failed,原拒因原样带出。
|
|
138
|
+
let code;
|
|
139
|
+
try {
|
|
140
|
+
code = typeof e === 'object' && e !== null ? e.errorCode : undefined;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return { kind: 'failed', error: e };
|
|
144
|
+
}
|
|
145
|
+
if (code === 'steering.invalid_content')
|
|
146
|
+
return { kind: 'invalid' };
|
|
147
|
+
if (code === 'steering.not_running')
|
|
148
|
+
return { kind: 'not_running' };
|
|
149
|
+
// 501 两码并列(附录 B.1:缺 sessionStorage.ownerOf ⇒ `capability.session_ownership_required`,缺 run 账面 ⇒ `capability.run_store_required`)
|
|
150
|
+
// ⇒ 前缀族开集(opus 替补复审 [medium]);`feature.*` = 面在但开关关着,与 capability 分列(与 memory-status 分诊同律)。
|
|
151
|
+
if (typeof code === 'string' && code.startsWith('capability.'))
|
|
152
|
+
return { kind: 'unsupported', reason: 'capability' };
|
|
153
|
+
if (typeof code === 'string' && code.startsWith('feature.'))
|
|
154
|
+
return { kind: 'unsupported', reason: 'feature' };
|
|
155
|
+
if (code === 'not_found.route')
|
|
156
|
+
return { kind: 'unsupported', reason: 'route' };
|
|
157
|
+
if (code === 'not_found.session')
|
|
158
|
+
return { kind: 'not_found' };
|
|
159
|
+
return { kind: 'failed', error: e };
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* 「重连这台 MCP」的消费口:**永不抛**。本地先按契约把体门(`server` 非空 ≤ 190)判掉,不发一条注定 400 的请求;
|
|
163
|
+
* 回体经 {@link projectMcpReconnectResult} 投影;**回声身份**(`sessionId` / `server`)与请求逐字相等,否则 `failed`(宁缺席不串台,
|
|
164
|
+
* 与 `readSessionMemoryStatus` 同律)。注入口没有方法 ⇒ `unsupported/route`(壳没接线 = 面不存在)。
|
|
165
|
+
*/
|
|
166
|
+
export async function reconnectMcpServer(client, sessionId, server, opts) {
|
|
167
|
+
if (!nonEmpty(sessionId))
|
|
168
|
+
return { kind: 'invalid' };
|
|
169
|
+
if (!nonEmpty(server) || server.length > SERVER_NAME_MAX)
|
|
170
|
+
return { kind: 'invalid' };
|
|
171
|
+
try {
|
|
172
|
+
const verb = client?.sessions?.mcpReconnect;
|
|
173
|
+
if (typeof verb !== 'function')
|
|
174
|
+
return { kind: 'unsupported', reason: 'route' };
|
|
175
|
+
// 🔴 本地取消闸(异源复审第二轮 [medium]):signal 只转交给注入口不够 —— 壳的传输若忽略它,用户已撤销的操作仍会关掉一条
|
|
176
|
+
// 健康连接并重拨(失败则工具撤走)。破坏性动词在「用户说停」之后一发都不许出。
|
|
177
|
+
if (opts?.signal?.aborted === true) {
|
|
178
|
+
return { kind: 'failed', error: opts.signal.reason ?? new Error('mcpReconnect: aborted before the verb was called') };
|
|
179
|
+
}
|
|
180
|
+
// 方法形调用保接收者(真 SDK 资源方法体走 this.t.request)。
|
|
181
|
+
const raw = await client.sessions.mcpReconnect(sessionId, { server }, opts?.signal ? { signal: opts.signal } : undefined);
|
|
182
|
+
const view = projectMcpReconnectResult(raw);
|
|
183
|
+
if (view === undefined)
|
|
184
|
+
return { kind: 'failed', error: new Error('mcpReconnect: malformed body') };
|
|
185
|
+
if (view.sessionId !== sessionId || view.server !== server)
|
|
186
|
+
return { kind: 'failed', error: new Error('mcpReconnect: response identity mismatch') };
|
|
187
|
+
return { kind: 'ok', result: view };
|
|
188
|
+
}
|
|
189
|
+
catch (e) {
|
|
190
|
+
return classifyMcpReconnectFailure(e);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* 能力位 `GET /v1/capabilities.mcpReconnect`(设施依赖 = runStore ∧ sessionStorage.ownerOf)的三态读:
|
|
195
|
+
* `available` / `unavailable` / `not_reported`(键缺席 = 老 server <7.85.0 **判不了**,不折 unavailable);坏形 ⇒ `undefined`。
|
|
196
|
+
* 纯投影(caps 体由宿主交,本包不另开 tee:这一位只在按钮亮不亮时读一次)。
|
|
197
|
+
*/
|
|
198
|
+
export function projectMcpReconnectCapability(caps) {
|
|
199
|
+
if (!isRecord(caps))
|
|
200
|
+
return undefined;
|
|
201
|
+
if (!('mcpReconnect' in caps) || caps.mcpReconnect === undefined)
|
|
202
|
+
return 'not_reported';
|
|
203
|
+
if (caps.mcpReconnect === true)
|
|
204
|
+
return 'available';
|
|
205
|
+
if (caps.mcpReconnect === false)
|
|
206
|
+
return 'unavailable';
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* 三态 → 一句结果(**唯一措辞铸点**;三端共用;零内部车道词)。`accepted` 带工具计数;`refused` 说清工具已撤走(交易的代价)并带 reason;
|
|
211
|
+
* `unsupported` 说清是这条 run 的装配(未声明 MCP),不是 refused。
|
|
212
|
+
*/
|
|
213
|
+
export function mcpReconnectOutcomeDetail(view) {
|
|
214
|
+
const name = capForDisplay(view.server, RECONNECT_WORD_MAX);
|
|
215
|
+
switch (view.outcome) {
|
|
216
|
+
case 'accepted':
|
|
217
|
+
return `MCP server ${name} was re-dialed: ${view.toolCount} tool${view.toolCount === 1 ? '' : 's'} mounted (${view.added.length} added, ${view.removed.length} removed)`;
|
|
218
|
+
case 'refused': {
|
|
219
|
+
// 🔴 名册按 toolNames 在场性分三句(异源对抗复审 [medium]:此前无条件说「工具已撤走」,把未知名 / 重拨在飞 / 已撤销这些
|
|
220
|
+
// **没碰连接**的拒绝也说成撤了工具,误导用户再来一次破坏性重拨):
|
|
221
|
+
// 缺席 = 这条臂从未碰过连接,名册未动;[] = 拨号失败,工具撤走;非空 = 拒了但对该 prefix 域做了名册断言,如实报数。
|
|
222
|
+
const why = view.reason !== undefined ? ` — ${view.reason}` : '';
|
|
223
|
+
if (view.toolNames === undefined) {
|
|
224
|
+
return `MCP server ${name} was NOT re-dialed; its connection and tools were left untouched${why}`;
|
|
225
|
+
}
|
|
226
|
+
if (view.toolNames.length === 0) {
|
|
227
|
+
return `MCP server ${name} was NOT re-dialed and its tools were withdrawn from the model until a later re-dial succeeds${why}`;
|
|
228
|
+
}
|
|
229
|
+
return `MCP server ${name} was NOT re-dialed; the engine reports ${view.toolNames.length} tool${view.toolNames.length === 1 ? '' : 's'} for it after this attempt${why}`;
|
|
230
|
+
}
|
|
231
|
+
case 'unsupported':
|
|
232
|
+
return (`This run declared no MCP servers, so there is nothing to re-dial (${name} is not part of this run)` +
|
|
233
|
+
(view.reason !== undefined ? ` — ${view.reason}` : ''));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
@@ -153,7 +153,7 @@ export declare function resumeContextUnavailableFromError(err: unknown): ResumeC
|
|
|
153
153
|
* 🔴 **只凭码不推断原因**(异源对抗复审实抓):server 在「上下文被回收」与「上下文读取失败(如存储故障)」两种情况下
|
|
154
154
|
* 都返回本码,wire 上没有判别位 ⇒ 第一句只说「当前没有可用的上下文来继续它」,不说「等得太久 / 已被回收」。
|
|
155
155
|
* 🔴 **调大保留时长救不回这一次**(上下文已删就是删了),它只能避免以后再发生 ⇒ 第三句按 `runId` 在场与否给恢复指引,
|
|
156
|
-
*
|
|
157
|
-
*
|
|
156
|
+
* 保留时长只作预防句。零内部车道词;{@link ResumeContextUnavailableDetail.staleAfterSec} 在场时第三句**带原数**
|
|
157
|
+
* (0.72.9 CC-45:此前留给端渲而端没渲 ⇒ 有数必渲),缺席就不渲、不编。
|
|
158
158
|
*/
|
|
159
159
|
export declare function resumeContextUnavailableContent(d: ResumeContextUnavailableDetail): string;
|
|
@@ -185,13 +185,19 @@ export function resumeContextUnavailableFromError(err) {
|
|
|
185
185
|
* 🔴 **只凭码不推断原因**(异源对抗复审实抓):server 在「上下文被回收」与「上下文读取失败(如存储故障)」两种情况下
|
|
186
186
|
* 都返回本码,wire 上没有判别位 ⇒ 第一句只说「当前没有可用的上下文来继续它」,不说「等得太久 / 已被回收」。
|
|
187
187
|
* 🔴 **调大保留时长救不回这一次**(上下文已删就是删了),它只能避免以后再发生 ⇒ 第三句按 `runId` 在场与否给恢复指引,
|
|
188
|
-
*
|
|
189
|
-
*
|
|
188
|
+
* 保留时长只作预防句。零内部车道词;{@link ResumeContextUnavailableDetail.staleAfterSec} 在场时第三句**带原数**
|
|
189
|
+
* (0.72.9 CC-45:此前留给端渲而端没渲 ⇒ 有数必渲),缺席就不渲、不编。
|
|
190
190
|
*/
|
|
191
191
|
export function resumeContextUnavailableContent(d) {
|
|
192
|
-
|
|
192
|
+
// 0.72.9 CC-45(cli L-383 / test [7516] N-G10):**有数必渲、无数不编**。0.72.1 曾把秒数留给端「单独渲」而端没渲 ⇒ 补充句永无
|
|
193
|
+
// 保留秒数;归层改为本句直接带原数(整数秒,读口已窄读),缺席时本句逐字同 0.72.1。
|
|
194
|
+
// 🔴 措辞铸点是最后一关(opus 替补复审 [low]):公面函数入参可被手工构造,`0` / 非整数 / 巨数与读口同一判据(整数 ∧ ≥1)才渲,
|
|
195
|
+
// 否则不渲 —— 绝不渲「0 秒」这种看起来像答案的空壳。
|
|
196
|
+
const sec = d.staleAfterSec;
|
|
197
|
+
const retention = typeof sec === 'number' && Number.isSafeInteger(sec) && sec >= 1 ? `(本部署的会话保留时长为 ${sec} 秒)` : '';
|
|
198
|
+
const third = (d.runId !== undefined
|
|
193
199
|
? '错误里带了这条运行的 id,请用它自己恢复这条运行再决;调大会话保留时长只能避免以后再发生,救不回这一次'
|
|
194
|
-
: '错误里没有带运行 id,请回到运行列表找到这条运行自己恢复它再决;调大会话保留时长只能避免以后再发生,救不回这一次';
|
|
200
|
+
: '错误里没有带运行 id,请回到运行列表找到这条运行自己恢复它再决;调大会话保留时长只能避免以后再发生,救不回这一次') + retention;
|
|
195
201
|
return [
|
|
196
202
|
'这个批准无处投递:发起这次运行的会话当前没有可用的上下文来继续它',
|
|
197
203
|
'什么都没有被决定,你的决定没有被消费,这张卡仍在等待',
|
|
@@ -29,12 +29,20 @@ export interface MemoryStatusClientLike {
|
|
|
29
29
|
} & SessionMemoryStatus>;
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* 读数体 = sdk 五键 + server 7.85.0 S-403 新键 `autoConsolidationArmed`(0.72.9 CC-39②;core #863 W1 唯一读法
|
|
34
|
+
* `autoRunOnRecommendationEffective` 组,与 manifest `autoConsolidation` 段在场性同源)。sdk 9.6.0 尚未声明 ⇒ 本包按结构读;
|
|
35
|
+
* 缺席 = 老 server(<7.85.0)**判不了**,不折 false —— 读法见 {@link readAutoConsolidationArmed}。
|
|
36
|
+
*/
|
|
37
|
+
export type MemoryStatusFacts = SessionMemoryStatus & {
|
|
38
|
+
readonly autoConsolidationArmed?: boolean;
|
|
39
|
+
};
|
|
32
40
|
export type MemoryStatusVerdict =
|
|
33
41
|
/** 200:读到了。`facts` 的**每一键**都按 wire 原样(合形才在场),缺席语义见 {@link readCaptureOptOut} 等。 */
|
|
34
42
|
{
|
|
35
43
|
readonly kind: 'ok';
|
|
36
44
|
readonly sessionId: string;
|
|
37
|
-
readonly facts:
|
|
45
|
+
readonly facts: MemoryStatusFacts;
|
|
38
46
|
}
|
|
39
47
|
/** 本部署**没有这个面** —— 端应当**别提供这个入口**(不是报错,是诚实的能力缺席)。 */
|
|
40
48
|
| {
|
|
@@ -136,3 +144,9 @@ export declare function readLastCapture(s: SessionMemoryStatus): LastCaptureRead
|
|
|
136
144
|
export declare function readSessionMemoryStatus(client: MemoryStatusClientLike, sessionId: string, opts?: {
|
|
137
145
|
signal?: AbortSignal;
|
|
138
146
|
}): Promise<MemoryStatusVerdict>;
|
|
147
|
+
/**
|
|
148
|
+
* 「这台部署的记忆自动整理武装了没有」:`armed` / `unarmed` / `indeterminate`。
|
|
149
|
+
* 🔴 缺席 = 老 server(<7.85.0)**判不了**,不折 `unarmed`;坏形同样 `indeterminate`(不抛)。三个词对运维是三条不同的下一步
|
|
150
|
+
* (与 manifest `autoConsolidation` 段「缺席 = indeterminate」同律;server 用 core 唯一读法组这一位,端别按席自判)。
|
|
151
|
+
*/
|
|
152
|
+
export declare function readAutoConsolidationArmed(facts: MemoryStatusFacts | null | undefined): 'armed' | 'unarmed' | 'indeterminate';
|
|
@@ -172,6 +172,8 @@ export async function readSessionMemoryStatus(client, sessionId, opts) {
|
|
|
172
172
|
? { optOutSource: o.optOutSource }
|
|
173
173
|
: {}),
|
|
174
174
|
...(typeof o.lastCaptureAt === 'number' ? { lastCaptureAt: o.lastCaptureAt } : {}),
|
|
175
|
+
// 0.72.9 CC-39②(server 7.85.0 S-403):布尔恒在场;非布尔 / 老 server 缺席 ⇒ 键不在场(不铸 false)。
|
|
176
|
+
...(typeof o.autoConsolidationArmed === 'boolean' ? { autoConsolidationArmed: o.autoConsolidationArmed } : {}),
|
|
175
177
|
},
|
|
176
178
|
};
|
|
177
179
|
}
|
|
@@ -179,3 +181,19 @@ export async function readSessionMemoryStatus(client, sessionId, opts) {
|
|
|
179
181
|
return classifyMemoryStatusFailure(e);
|
|
180
182
|
}
|
|
181
183
|
}
|
|
184
|
+
// ── ④ autoConsolidationArmed 三态(0.72.9 CC-39②)──────────────────────────────────────────
|
|
185
|
+
/**
|
|
186
|
+
* 「这台部署的记忆自动整理武装了没有」:`armed` / `unarmed` / `indeterminate`。
|
|
187
|
+
* 🔴 缺席 = 老 server(<7.85.0)**判不了**,不折 `unarmed`;坏形同样 `indeterminate`(不抛)。三个词对运维是三条不同的下一步
|
|
188
|
+
* (与 manifest `autoConsolidation` 段「缺席 = indeterminate」同律;server 用 core 唯一读法组这一位,端别按席自判)。
|
|
189
|
+
*/
|
|
190
|
+
export function readAutoConsolidationArmed(facts) {
|
|
191
|
+
if (typeof facts !== 'object' || facts === null)
|
|
192
|
+
return 'indeterminate';
|
|
193
|
+
const v = facts.autoConsolidationArmed;
|
|
194
|
+
if (v === true)
|
|
195
|
+
return 'armed';
|
|
196
|
+
if (v === false)
|
|
197
|
+
return 'unarmed';
|
|
198
|
+
return 'indeterminate';
|
|
199
|
+
}
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
|
|
20
20
|
| 项 | 值 | 真源 |
|
|
21
21
|
|---|---|---|
|
|
22
|
-
| 本包 | `@sema-agent/client-core` **0.72.
|
|
22
|
+
| 本包 | `@sema-agent/client-core` **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` **>=9.6.0**(value-level,非 type-only;**0.71.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
|
+
| 公开导出面 | **985** 个运行期符号(+ 45 个测试钩;= 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
|
|
|
@@ -121,7 +121,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
121
121
|
|
|
122
122
|
## §2 公共导出面地图(按域)
|
|
123
123
|
|
|
124
|
-
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**
|
|
124
|
+
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**985** 项)。
|
|
125
125
|
> 本节**不逐名抄**,只给「域 → 承重导出 → 用途 → 实现锚」。承重导出 = 一个端为了让这个域干活
|
|
126
126
|
> **必须**直接调到的那几个符号;其余是它们的类型、变体与辅助位。
|
|
127
127
|
> 单一入口:`import { … } from '@sema-agent/client-core'`(`exports` 只有 `.` 一个;
|
|
@@ -145,12 +145,12 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
145
145
|
`WorkflowsGateUnknownDenial` 四形**不在**基线里,`src/selfOrchestrationDenial.ts` 对基线贡献
|
|
146
146
|
**4** 项运行期导出(三个函数 + `SELF_ORCHESTRATION_RETRY_WITHOUT`)。
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
985 项的内部构成(帮助端估读表大小;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):**286** 项是 `SCREAMING_SNAKE` 常量数据表/词汇表
|
|
149
149
|
(矩阵、键集、env 名、锚串)而非可调用物;**6** 项是 PascalCase 运行期值
|
|
150
150
|
(`ControlRouter` / `ControlSafetyError` / `HitlBridge` / `HitlSafetyError` / `DecideTransportRetryExhaustedError`);
|
|
151
151
|
**37** 项是 `*For(sessionKey, …)` 的 per-session 变体(0.72.0 −4:`clearArmedGateFor` / `onGateArmedFor` / `registerArmedGateFromQuestionIdFor` / `notePlanReviewAnsweredIfDecisiveFor` 退出公面)(§6;其中 `engineNamespaceKeyFor` 是命名巧合 —— 参数是 baseUrl 不是 sessionKey,见域 14)。
|
|
152
152
|
|
|
153
|
-
### 2b. 域图(16 域,逐域计数之和 =
|
|
153
|
+
### 2b. 域图(16 域,逐域计数之和 = 985)
|
|
154
154
|
|
|
155
155
|
| # | 域 | 名数 | 承重导出 | 用途 | 实现锚 |
|
|
156
156
|
|---|---|---|---|---|---|
|
|
@@ -168,7 +168,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
168
168
|
| 12 | **workflow 与后台工作视图** | 21 | `projectWorkflowRun` · `readWorkflowResumeAdmissionIncomplete`(0.68.3 CC-05:core 7.18.0 `resumeAdmissionIncomplete` 在场 = 不是 resume 基,与 `readWorkflowParks` 同一条投影义务)· `createLiveWorkflowSource` · `ensureWorkflowActivityLedger` · `readWorkflowActivityLedger` · `stopWorkflowActivityLedger` · `resetWorkflowActivityLedgers` · `createBackgroundView` · `projectBackgroundView` · `recordWorkflowAgentTaskId` · `agentDisplayStatus` | 活过一个 turn 的长任务读面:workflow run + 跨 session 后台任务归一表(`assistant.tasks` 与 fleet SSE **两源独立降级**) | `src/workflow.ts`、`src/workflowClient.ts`、`src/workflowMonitor.ts`、`src/agentSession/backgroundView.ts`(+ 纯类型 `src/agentSession/contract.ts`) |
|
|
169
169
|
| 13 | **座位 IPC 契约** | 34 | `LOCAL_SESSIONS_SPEC` · `SEAT_METHOD_NAMES` · `SEAT_EVENT_TYPES` · `isLocalSessionEvent` · `isToolPermissionRequest` · `toolPermissionRequestId` · `SEAT_VALIDATOR_KEY_COVERAGE` · `SEAT_SEND_MESSAGE_KEY_ORIGINS`(0.62.0:座位载荷**逐键出身**登记 —— 每个位要么写明转投哪个引擎请求位、要么写明为什么不上 wire;常驻门对**装在盘上的** sdk 型面逐名核,详见 §26③)| desktop↔web 座位 IPC 契约的**单一真源**(此前两边各一份、名字零重合 ⇒ 编译器永远不会告诉你它们漂了)。🔴 加 verb 忘了加 `LOCAL_SESSIONS_SPEC` **不报错**:preload 不注册 channel、渲染端读到 `undefined` | `src/seatContract.ts`(**零 import**,纯类型 + 常量 + 纯谓词)。🔴 **证据等级标注(0.42.0,test [5087] 的「语料**种类**缺口」/ cli [5088] 认领件)**:该文件里所有以「CC 如何如何」为形的断言(`212 methods` / `854-channel census` / 方法名逐字保留 / `fQe` 逐字段对照 / 一切 `.vite/build/index.chunk-*.js` 坐标)**证据等级 = 桌面 unpack,本地语料库不可复验** —— 本仓手边可复验的参照语料**只覆盖终端 CLI 形态**的静态产物,拿它去 grep 桌面壳里的符号只会零命中,而零命中在这里**既不证真也不证伪**。复核这些断言**不得**拿本仓语料当反证 |
|
|
170
170
|
| 14 | **宿主端口与会话槽** | 41 | `installHost` · `installHostFor` · `installCoreValuePorts` + 十读口 + 三存在性口(0.69.0 CC-07:core 值级面端口注入,Node 宿主装配根装、浏览器 lane 恒缺席)· `hostPortMisses(For)` · `DEFAULT_SESSION_KEY` · `hostEnv` · `unrefTimer` · `parseLocaleTag` / `pickUiLanguage`(#244 F4 族D A-028.20:locale tag 手术单源 + UI 语言判定;与 `resolveRegionHint` 双出口成文 —— 语言偏好域 en/zh ≠ 地址可达域 cn/intl/unknown,`zh-Hant` 前者 zh 后者 intl 是设计)· `engineNamespaceKeyFor` / `mergeSessionMapRecord` / `mergeEngineEntry`(A-028.12:会话 id 映射单一键形 + merge 判定;存储经 `SessionMapStorePort` 归端 —— cli 文件锁/原子写,web localStorage)| 进程/端级装配层(settings/fs/queue/timers/session/log/probe),与 per-turn 的 `AdapterContext` **分层**。头注的判定规则:**这个能力每 turn 都会变吗?** 会 ⇒ `ctx`;不会 ⇒ `installHost` | `src/host.ts`、`src/hostEnv.ts`、`src/sessionSlot.ts`、`src/unrefTimer.ts`、`src/env/{localeGeo,localeTag,uiLanguage}.ts`、`src/sessionMap.ts` |
|
|
171
|
-
| 15 | **控制面与传输** |
|
|
171
|
+
| 15 | **控制面与传输** | 139 | `reconnectMcpServer` / `projectMcpReconnectResult` / `classifyMcpReconnectFailure` / `projectMcpReconnectCapability` / `mcpReconnectOutcomeDetail` + `MCP_RECONNECT_OUTCOMES` / `MCP_RECONNECT_TRANSACTION_NOTICE`(0.72.9 CC-30:会话内 MCP re-dial 消费口,outcome 三态 / unsupported 恒五键 / 名册按 toolNames 在场性;§56)· `readAutoConsolidationArmed`(0.72.9 CC-39②:memory-status `autoConsolidationArmed` 三态,缺席 = 老 server 判不了;§56)· `steerFollowIntent`(0.72.6 CC-40:steer 后续听意图三态 tail / after-decision / after-wake,按 `SteerReceipt.delivery` 判;§53)· `projectWebSearchBackendCapability` / `observedWebSearchBackend` / `noteEngineCapsForWebSearchBackend` / `forgetWebSearchBackendReading` / `webSearchBackendDoctorDetail` + `WEB_SEARCH_BACKEND_NONE`(0.72.5 CC-31:`capabilities.webSearch.backend` 四态读面 —— 键缺席 = 老引擎判不了 ≠ `none` = 引擎明说没有默认后端;与 `sqlEngineCapability` / `writeProtectionCapability` 同构;§52)· `resumeContextUnavailableFromError` / `resumeContextUnavailableContent`(0.72.1 CC-33:409 `conflict.resume_context_unavailable` 读数 `{ code, staleAfterSec?, runId? }` + 三句人话;§48)· `mcpEngineLegPresence`(0.71.0 CC-19:引擎侧 MCP 在场三值,只从面板视图求;§42)· `ControlRouter`(+ `ControlSafetyError`)· `fetchMcpPanel`(0.69.0:经 sdk `sessions.mcp` 取体 + 投视图,不裸 fetch)· `projectMcpPanel` + `mcpPanelLastLegDetail`(0.68.2 CC-03:`GET /v1/sessions/:id/mcp` 面板体防御读视图 + `lastLegMcp` 一行措辞铸点;缺席 = 键不铸、读不懂 = `lastLegMcpUnreadable`、禁与 `servers[]` 对账)· `makeEngineWireClient` + `resolveWireAuth` · `installEngineWireTarget` · `diagnoseSseIdleTear` / `isSseIdleError` · `attemptActiveRunSelfHeal` + `activeRunBusySignal` + `activeRunSelfHealRow` / `activeRunBusyHeadlessRow` · `kickEngineCapsProbe` / `engineCapTrue` / `invalidateEngineCaps(baseUrl, probe?)`(#307 S25:引擎温切后的 caps 生产失效口 —— kick 自带幂等闸,同 baseUrl 重启后不显式失效就永远读到旧引擎那一版能力位;调用方 = 壳的 respawn/restartEngine。🔴 **推荐两参形**:第二参给替代探测则「推进代际 + 注册新探测」在同一同步块内完成,失效与下一次 kick 之间那个「等待者读到未判」的窗按构造不存在;单参形保留给「只丢缓存、这一刻没有替代探测」的调用方,那种情形下读到未判是诚实结局) · `engineCapValue`(S-131,0.59.0:能力位的**四态**通用读口 `unobserved`/`not_reported`/`null`/`value` —— 既有三口把四种「读不出」全折成 fail-closed 一档,对**放行**问题是对的、对**读面/诊断**问题是错的:`null`(引擎明确说没有,正面事实)会与「老引擎不报」「还没探到」在屏上同形。`value` 位刻意不做形校验,形归各能力位自己的窄读器,详见 §23b)· `projectSqlEngineCapability` / `observedSqlEngine` / `noteEngineCapsForSqlEngine` / `forgetSqlEngineReading` / `sqlEngineDoctorDetail`(S-131,0.59.0:`Capabilities.sql`(server ≥7.60.0)的四态读面**从壳侧上收** —— 归层债,0.58.0 时它长在壳里正是因为包侧没有嵌套对象读口。🔴 **导出名与壳侧那份逐字同名 = drift-lock**;`txnMode: null` 是铸点域内的合法值不是畸形;换代失效口清成未观测而不是留旧值,详见 §23b)· `mapBrainStatusToRetry` · `waitForClaimRelease` + `CLAIM_RELEASED_STATES` / `CLAIM_HELD_STATES` · `atMostOnceFailureClass` / `readSteerDelivery` · `clearRunningChoiceOffer`(Inkglow-1085 P0b①:「Do nothing」登记的清口 —— 端的「重新打开操作菜单」入口;登记在场时 attemptActiveRunSelfHeal 不整卡重弹,not-parked 结局带 `alreadyOffered: true` 判别位,端据此降级渲一行)· `INTERACTIVE_WAY_OUT`(默认出路串单源)· `engineSessionParamFor`(design/285 批 0:`?session=` 派生的 **per-key** 形 —— `hostSessionFor(sessionKey)?.currentSessionId()` + [1501] 空串归一;零参 `engineSessionParam()` = 默认槽兼容层,取值链逐字等价)· `normalizeWirePrincipal`(A-028.10:principal 在场性 trim 原语 —— 全空白=缺席不发头,engineWireTarget 两臂/makeEngineWireClient/壳 livePrincipal 同尺)· `readSessionMemoryStatus` / `classifyMemoryStatusFailure` / `readCaptureOptOut` / `readLastCapture`(S-53 会话记忆姿态读面,0.48.0:失败分诊**码优先**——两个 404 分道 `not_found.session` / `not_found.route`,无码 404 不猜落 failed;五键逐键缺席语义两个合读器,`lastCapture` 三态的判别材料是 `committedCount` 不是本键;IO 归宿主注入 `MemoryStatusClientLike`,详见 §11) · `classifyTurnWireError` / `isWireTransportError` / `isPreStreamDrainingReject` / `isResumeAtRejection` / `drainingRetryDelayMs` / `scenarioDenyFromError` + `WIRE_NETWORK_ERROR_PATTERN`(A-028.11/.13:turn 错误分型判定半场,人话文案与渲染归端)· `resumeRetryLaterFromError`(L-102,0.57.0:resume 族**时间性拒绝**二码的判型半场 —— 这一族里唯一**带得出「等多久」**(`retryAfterSec`)的两个码。🔴 闭集**不是**「哪些码可以等」的名单:同族 `resume.row_recycling` 同样可等(窗口自清)只是没有秒数 ⇒ 本读口返回 `null` 只意味着没命中这两码,详见 §21) · `projectWriteProtectionCapability` / `observedWriteProtection` / `noteEngineCapsForWriteProtection` / `forgetWriteProtectionReading` / `writeProtectionDoctorDetail` / `projectWriteProtectionPosture` / `writeProtectionPostureDetail`(S-138,0.60.0:`Capabilities.writeProtection` (engine ≥7.63.0)的**四态**读面 + operator 面行表 —— 与上面 S-131 那一格**同构同纪律**。🔴 三位刻意不合成一个布尔;`not_reported` **不是**「这台部署没有写保护表」(座位缺席恰是缺省表在岗);逐行 name/kind 走**最小披露**只上 operator 面,详见 §24e)· `projectReadFacePosture` / `readFacePostureDetail` / `readFaceDisagreement`(S-167,0.61.0:operator 面 `diagnostics.wiring.readFace`(engine ≥7.65.0)的窄读器 —— 与上面S-138 那一格**同构同纪律**。🔴 三句「答不出来」逐字互异且没有一句等于「没有 READ 档」;`source` 按开集读;与租户面 `capabilities.readFace` 刻意不合流,只带一个纯比较函数,详见 §25)| 上行通道的**监管**半场(submit / steer / kill / 队列命令定序)+ 传输构造、caps 探测、SSE 断流分诊、**409 active-run 自愈** | `src/controlRouter.ts`、`steering.ts`、`sseIdleTriage.ts`、`retryStatus.ts`、`diagnostics.ts`、`engineWireSdk.ts`、`engineWireTarget.ts`、`src/principalWire.ts`、`src/wireErrorTriage.ts`、`engineSessionParam.ts`、`engineCapsCache.ts`、`liveInitToolFace.ts`、`adapter/activeRunSelfHeal.ts`、`src/sessionMemoryStatus.ts`、`src/writeProtectionCapability.ts`、`src/webSearchBackendCapability.ts`、`src/mcpReconnect.ts`、`src/readFacePosture.ts` |
|
|
172
172
|
| 16 | **引擎词汇表与包自检** | 93 | `MCP_REDIAL_OUTCOMES` / `readMcpServerRedialed`(0.72.7 CC-42:通告 `mcp.server_redialed` 事实读器,outcome 三词闭集、added/removed 计数;§54)· `RESUME_CONTEXT_UNAVAILABLE`(0.72.1 CC-33;不进两个 resume 闭集:不可等、也不是换参数)· `RESUME_REOPEN_CODES` / `RESUME_ENV_FAILED` / `RESUME_TOOL_UNAVAILABLE` / `RESUME_TOOL_CONTRACT_MISMATCH` · `resumeReopenFromError` / `resumeReopenContent`(0.71.3 CC-06:resume reopen 族三码闭集 + 读口 + 三句,§45)· `readSkillsListingTruncated`(0.70.0 CC-04:`skills.listing_truncated` 事实读器,§39)· `CONFIG_REFUSAL_CODES` / `isConfigRefusalCode` · `DECIDE_WORKFLOW_LANE_CODES`(+ 三个具名码;`/decide` workflow 车道,三条出路刻意不合并,详见 §30h)· `STOP_CONFLICT_CODES` · `isInterruptedToolEndCode` · `isRewindFamilyCode` · `CLIENT_VERBS` · `compensationSplitViolations` · `DELEGATION_CAP_CODES` / `isDelegationCapCode` / `DELEGATION_CONCURRENCY_CAP` / `DELEGATION_SESSION_CAP`(0.38.0 #318 件④:core 5.48.0 design/323 委派席位到限**两码,处置不对称禁合并** —— 并发帽=**可等**(兄弟结束即有位)/ 会话累计帽=**等也没用**(这条会话的配额用尽))· `CONFIG_DELEGATION_ENTRY_CAPS`(同批入 `CONFIG_REFUSAL_CODES` 识别表)· `delegationCapDispositionOf` / `MCP_SERVER_REVOKED`(0.39.0 载体到货消费件:core 5.50.0 补 `{ error: code, code }` 孪生拼法后两码真上 `tool_end.errorCode`,0.38.0「先立词不落消费分支」的已知局限自此解除;处置轴 `wait-for-slot` / `reuse-existing-or-await-reap` 机器可读(累计帽=retained-window 帐,行回收配额即回,处置=SendMessage 复用,**非**「换会话/永久耗尽」——0.38.0 段该句系勘误),未知 `delegation.*` 码 ⇒ `undefined`;`mcp.server_revoked` = 操作员 mid-session 吊销 server 后的工具面本地闸(被吊销的 server **名**今天不过 wire 境:detail.server 是进程内位,抬升腿只 lift code——归因渲染候 core 补 typed detail,已点名);载体门 = engine-vocab G3 腿锚 core dist 铸点)· `CAPABILITY_SELF_ORCHESTRATION_REQUIRED`(S-81,server 7.57.0:提交面的 selfOrchestration 准入拒绝码。🔴 **复用码** —— 与其它 `capability.*` 501 同体形而处置不同,消费点必须按**恰等**判、绝不放宽成前缀判;判型与「去键重发一次」归 `src/selfOrchestrationDenial.ts`,详见 §13) · `GATE_PARKED_ERROR_CODE`(0.60.0:「门把这次调用 park 了」的机读码单源 —— `frameRouter` 的连坐/中断判据与 `gateOutcome.isGateParkedToolEnd` 读同一个常量;真机黑盒直证 park 短路帧上**没有 `gate`**,这个码是那一形唯一的信号,详见 §24c)| 三端分臂共用的**去字面化** `errorCode` 词表(病根正是三端各抄一份字面);编译期 verb 闭合门;搬迁补偿登记表 | `src/engineErrorCodes.ts`(计数以 `scripts/public-export-baseline.json` 为准,别手抄;A-028.11/.13 补 `DRAINING_ERROR_CODE`/`SCENARIO_NOT_ALLOWED_ERROR_CODE`/`RESUME_AT_ERROR_CODE_PREFIX`;#318 件④ 补 `delegation.*` 族四位 + `config.delegation_entry_caps`;0.39.0 补三新码消费件三位);S-81 补 `capability.self_orchestration_required` 一位;L-102 补 `resume.*` 时间性拒绝二码 + 闭集 `RESUME_RETRY_LATER_CODES` 三位)、`src/classifierVerdictWire.ts`、`src/compensations.ts`、`src/clientSlice.ts`;**0.67.0 补锚**(这三件的导出一直计在本域,而本表此前没有它们的锚行 —— 如实补上,不是搬家):`src/gateVocabulary.ts`(`GATE_DENIED_BY_WORDS`/`gateDeniedByDetail`/`ASK_ORIGIN_WORDS`/`askOriginDetail` + 🆕 `RULE_STORE_UNREADABLE_KINDS`/`isRuleStoreUnreadableKind`/`ruleStoreUnreadableDetail`,详见 §32d)、`src/autoModeUnavailable.ts`(`AUTO_MODE_UNAVAILABLE_CAUSES` + 🆕 `CLASSIFIER_DENY_CAUSES`/`isClassifierDenyCause`/`classifierDenyCauseOf`/`classifierDenyCauseDetail`;🔴 同批**删**`classifierUnavailableOf`/`classifierUnavailableDetail`,详见 §32b)、`src/classifierStatus.ts`(`CLASSIFIER_STATUS_STATES`/`classifierStatusOf`/`classifierStatusDetail`)|
|
|
173
173
|
|
|
174
174
|
🔴 **`engineErrorCodes` 的开集纪律**(该文件头注逐字):这些 `ReadonlySet` / 前缀谓词一律是**识别表**,
|
|
@@ -8522,3 +8522,39 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
|
|
|
8522
8522
|
3. peer sdk >=9.6.0 / agent-types >=0.3.0 不动;server <7.84.0 对 `memory:"off"` 回 400(端如实渲)。
|
|
8523
8523
|
|
|
8524
8524
|
**包侧缺口:** ① CC-41 leader `needs_human` + `result.conflict` 渲染面(0.72.9);② CC-30 MCP 会话内重连消费口(core #857 已到;候 server S-381);③ CC-34 `permission_denials` 自动升级验证(候 core #897 + server 透传);④ CC-39②(memory-status `consolidation?` 切片判定;候 server S-403);⑤ CC-36 托管 MCP 活性三态读口(候 core #874);⑥ `staleAfterSec` / `runId` 经 sdk 到端(候 sdk 出键);⑦ `Capabilities.webSearch` / `TaskRequestBody.memory` / `WiringManifest.readDeny` 经 sdk 声明(候 sdk 出键);⑧ `agents.listing_truncated` detail 读器候消费场景(by-design);⑨ `ClassifierSeat.defaulted?` 候 sdk 出键(by-design);⑩ §NNz「declined 键真零命中」机读第二刀(候形式化)。
|
|
8525
|
+
|
|
8526
|
+
## §56 🆕 0.72.9 server 7.85.0 提货(CC-30 MCP re-dial 消费口 / CC-39② `autoConsolidationArmed`)+ CC-45 resume 补充句渲秒数;patch
|
|
8527
|
+
|
|
8528
|
+
> **patch**:型面纯 additive(+2 常量 +6 函数,公面 977 → 985;`MemoryStatusFacts` 加一可选键;零 wire 新键 —— 端点 / 能力位 / 新键由 server 7.85.0 [7522] 铸,本包只读;peer 不动;sdk 9.6.0 未声明 `mcpReconnect` 端点与体、`SessionMemoryStatus.autoConsolidationArmed`,本包按结构读 / duck-typed 注入)。三票来源:server [7522] ④ @client-core(CC-30 席位到位)/ [7522] ① memory-status 新键(CC-39②)/ cli [7519] L-383(CC-45)。
|
|
8529
|
+
|
|
8530
|
+
### 56a. 处置表
|
|
8531
|
+
|
|
8532
|
+
| # | 面 | 本包做了什么 | 端要做什么 |
|
|
8533
|
+
|---|---|---|---|
|
|
8534
|
+
| S-1 | **`POST /v1/sessions/:id/mcp/reconnect { server }`**(server ≥7.85.0;契约 §G.7c;200 三态 `accepted` / `refused` / `unsupported`;422 / 409 / 501 / 404) | **consumed**:`reconnectMcpServer(client, sessionId, server, { signal? })` 永不抛 ⇒ `McpReconnectVerdict` 六档(`signal` 已 abort ⇒ 动词零调用 `failed`);`projectMcpReconnectResult` 按 `outcome` 分形(`unsupported` 恒五键不编 0 / [];四座必填缺一畸形;`toolNames` 在场性;`status.errorCode` 开集;UNTRUSTED 消毒封长);`classifyMcpReconnectFailure` 按码分诊;`mcpReconnectOutcomeDetail` 三句单源;`MCP_RECONNECT_TRANSACTION_NOTICE` | 壳用自己的传输层接 `sessions.mcpReconnect(sessionId, { server }, { signal })` 注入(sdk 未声明);`/mcp` 面板「Reconnect」按钮:🔴 文案**必须**带 `MCP_RECONNECT_TRANSACTION_NOTICE`(健康 server 上重连 = 一次交易),不许只写「重连」;结果渲 `mcpReconnectOutcomeDetail`;`toolNames` 在场才整域替换本地名册,缺席不动;下一步按 `status.errorCode` / `httpStatus`(401 / 403 = 重新授权),不解析 `reason`;`not_running` ⇒ 告知没有活跃 run;`unsupported/route` ⇒ 老 server 不渲按钮;⚠️ 判决 `kind:'unsupported'`(面 / 部署不存在)与结果 `outcome:'unsupported'`(这条 run 未声明 MCP)是两个词两件事,别并成一句 |
|
|
8535
|
+
| S-2 | **`GET /v1/capabilities.mcpReconnect: boolean`**(设施依赖;缺席 = 老 server) | **consumed**:`projectMcpReconnectCapability(caps)` ⇒ `available` / `unavailable` / `not_reported` / 坏形 undefined | 按钮亮 iff `available`;`not_reported` 与 `unavailable` **不同句**(判不了 ≠ 不可用) |
|
|
8536
|
+
| S-3 | **`GET /v1/sessions/:id/memory-status.autoConsolidationArmed: boolean`**(server 7.85.0 S-403;恒在场;与 manifest `autoConsolidation` 段在场性同源) | **consumed**:`MemoryStatusFacts.autoConsolidationArmed?` 逐键条件拷贝;`readAutoConsolidationArmed(facts)` ⇒ `armed` / `unarmed` / `indeterminate` | `/status` 记忆段 / `/doctor` 记忆行渲三态;🔴 `indeterminate`(老 server)不渲「未武装」;与 chrome `wiring_manifest.autoConsolidation`(§51)是同一事实的两个读口,同屏不许互相矛盾 —— 都缺席一律 indeterminate |
|
|
8537
|
+
| S-5 | 注入件自动 steer 失败(CC-47;test 0.72.8 验收 sema-internal#56) | **changed**:`running-steer-failed` 注入形按 `delivery` 分句(`unknown` = 可能已送达、未重试、请观察 + 上游真因;`rejected` = 引擎拒收、未重试、模型未收到);`deps.signal` 已 abort ⇒ 注入形不发 steer(`not-parked`) | 零接线;注入行照旧走 `activeRunSelfHealRow(…, 'injected')`;Esc 后不会再有系统件注入进 run |
|
|
8538
|
+
| S-6 | `Model output error:` 锚(CC-48;test #57) | **changed**:锚**只认消息开头**(`trimStart` 后 `startsWith`)不按子串;引用锚句的 provider 400、`<上游错误> \| <引用锚句>` 形仍 `API Error:` | 零接线;`retagModelOutputErrorRow` 直通不变 |
|
|
8539
|
+
| S-4 | resume 决断 409 `conflict.resume_context_unavailable` 的补充句(cli L-383 / test [7516] N-G10) | **changed**:`resumeContextUnavailableContent` 第三句在 `staleAfterSec` 在场时带「(本部署的会话保留时长为 N 秒)」,缺席逐字同 0.72.1 | 🔧 **§48y ① 勘误**:那条「秒数由端按 staleAfterSec 单独渲」作废 —— 端**不再**自渲秒数,直接渲本包这句;`resumeContextUnavailableFromError` 读口不变 |
|
|
8540
|
+
|
|
8541
|
+
### 56z. 逐键处置表
|
|
8542
|
+
|
|
8543
|
+
| # | 键 / 面 | 处置 | 坐标 / 理由 |
|
|
8544
|
+
|---|---|---|---|
|
|
8545
|
+
| 1 | reconnect 200 体 `taskId` / `sessionId` / `server` / `outcome` / `reason?` / `prefix` / `toolCount` / `added` / `removed` / `toolNames` / `status`(八键;`name` 是身份键不封长)/ `listingIncomplete`(`reason` + `pages` 必填) | **consumed(按 outcome 分形;在场但坏形 ≠ 缺席 ⇒ 整只畸形)** | `src/mcpReconnect.ts` `#projectMcpReconnectResult`;门 `run-mcp-reconnect-test.mjs` S1 十七格 |
|
|
8546
|
+
| 2 | 422 `steering.invalid_content` / 409 `steering.not_running` / 501 `capability.*`(本路由真发两码:`run_store_required` / `session_ownership_required`,前缀族开集)/ 501 `feature.*` / 404 `not_found.route` / 404 `not_found.session` | **consumed(分诊)** | `#classifyMcpReconnectFailure`(分诊器自身永不抛:属性读取包 try);S2 九格 |
|
|
8547
|
+
| 3 | `capabilities.mcpReconnect` | **consumed(三态)** | `#projectMcpReconnectCapability`;S4;sdk 未声明 ⇒ 台账门在 sdk 出键当天红逼登记 |
|
|
8548
|
+
| 4 | `memory-status.autoConsolidationArmed` | **consumed** | `src/sessionMemoryStatus.ts` `#readAutoConsolidationArmed`;memory-status 门 G2c 八格 |
|
|
8549
|
+
| 5 | 409 体 `staleAfterSec`(既有键) | **consumed(渲;铸点自复核整数 ≥1)** | `src/resumeRefusalCopy.ts` `#resumeContextUnavailableContent`;resume-refusal 门 ⑧ 五格(含缺席两形逐字节基线串) |
|
|
8550
|
+
| 7 | `running-steer-failed.delivery` × 注入形 / `deps.signal.aborted` | **consumed(分句 / 闸)** | `src/adapter/activeRunSelfHeal.ts` `#injectedSubmissionRow` / `#runningChoiceArm`;reopen 门 ③z8–③z11 |
|
|
8551
|
+
| 8 | `done.result.errorMessage` 引用锚句(provider 400) | **declined(不改身份)** | `src/adapter/runStream.ts` `#isModelOutputErrorText` 只认消息开头;identity-copy 门 G1c 五格 |
|
|
8552
|
+
| 6 | reconnect 体 `axes` / `dropped` / `warnings` | **declined** | 契约 §G.7c 第 4 条:server 有意不投(工具面事实归 ask 卡与 manifest;诊断归 onError) |
|
|
8553
|
+
|
|
8554
|
+
### 56y. 🔴 三端升级必读(固定段式,[C295])
|
|
8555
|
+
|
|
8556
|
+
1. 换钉 `^0.72.9`:`/mcp` 面板接 `reconnectMcpServer` + `projectMcpReconnectCapability`(按钮亮 iff available),文案带 `MCP_RECONNECT_TRANSACTION_NOTICE`;记忆面读 `readAutoConsolidationArmed`(indeterminate 不渲未武装);resume 决断补充句直接渲包句(端不再自渲秒数,§48y ① 勘误)。
|
|
8557
|
+
2. 不接线的端零变化:reconnect 是新消费口;`autoConsolidationArmed` 只在 facts 上多一个可选键;补充句只在 `staleAfterSec` 在场时多一段。
|
|
8558
|
+
3. peer sdk >=9.6.0 / agent-types >=0.3.0 不动;server <7.85.0 上端点 404 `not_found.route` ⇒ `unsupported/route`、能力位 `not_reported`、新键缺席 ⇒ `indeterminate`。
|
|
8559
|
+
|
|
8560
|
+
**包侧缺口:** ① CC-41 leader `needs_human` + `result.conflict` 渲染面(0.72.10);② CC-46 `plan_review` 体 `permissionModeAfter` 发口(候 server 7.86.0 S-433 + sdk 型面);③ CC-34 `permission_denials` 自动升级验证(候 core #897 + server 透传);④ CC-36 托管 MCP 活性三态读口(候 core #874);⑤ `staleAfterSec` / `runId` 经 sdk 到端(候 sdk 出键);⑥ `Capabilities.webSearch` / `mcpReconnect` / `TaskRequestBody.memory` / `WiringManifest.readDeny` / `SessionMemoryStatus.autoConsolidationArmed` / reconnect 端点与体 经 sdk 声明(候 sdk 出键);⑦ `agents.listing_truncated` detail 读器候消费场景(by-design);⑧ `ClassifierSeat.defaulted?` 候 sdk 出键(by-design);⑨ §NNz「declined 键真零命中」机读第二刀(候形式化)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/client-core",
|
|
3
|
-
"version": "0.72.
|
|
3
|
+
"version": "0.72.9",
|
|
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",
|