@sema-agent/client-core 0.56.0 → 0.58.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 +293 -0
- package/README.md +8 -3
- package/dist/adapter/downstream/eventToSdkMessage.js +19 -0
- package/dist/engineErrorCodes.d.ts +59 -0
- package/dist/engineErrorCodes.js +79 -0
- package/dist/hitl/toolApprovalWire.d.ts +151 -91
- package/dist/hitl/toolApprovalWire.js +174 -20
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/resumeRefusalCopy.d.ts +58 -0
- package/dist/resumeRefusalCopy.js +115 -0
- package/dist/subagent/engineSubagentResume.d.ts +82 -6
- package/dist/subagent/engineSubagentResume.js +19 -2
- package/dist/wireErrorTriage.d.ts +73 -0
- package/dist/wireErrorTriage.js +40 -1
- package/docs/INTEGRATION-CLIENTS.md +378 -9
- package/package.json +3 -3
|
@@ -15,15 +15,15 @@
|
|
|
15
15
|
|
|
16
16
|
## §0 版本锚与重扫纪律
|
|
17
17
|
|
|
18
|
-
### 0a. 版本锚(2026-09-
|
|
18
|
+
### 0a. 版本锚(2026-09-06)
|
|
19
19
|
|
|
20
20
|
| 项 | 值 | 真源 |
|
|
21
21
|
|---|---|---|
|
|
22
22
|
| 本包 | `@sema-agent/client-core` **0.55.0**(工作树**未发**;npm 最新 = **0.54.0**。B-003 `waiting_first_token` 那一批进 `CHANGELOG.md` 的 `## 0.55.0(2026-09-05)` 段,冻结账已按两阶段协议插 `pending` 行) | `package.json` `version` |
|
|
23
|
-
| peer:wire 契约 | `@sema-agent/sdk` **>=
|
|
23
|
+
| peer:wire 契约 | `@sema-agent/sdk` **>=8.2.0**(value-level,非 type-only;**0.58.0 抬版**,四条硬理由见 §22a 与 `scripts/run-sdk-floor-test.mjs` 的 `FLOOR` 注;上一次是 0.48.0 的 `>=7.4.0`) | `package.json` `peerDependencies` |
|
|
24
24
|
| peer:会话词汇表 | `@sema-agent/agent-types` **>=0.2.0**(type-only,零运行时) | 同上 |
|
|
25
25
|
| runtime dep | `diff` ^9.0.0(**唯一**一条;portability 门按**等值**钉死) | `package.json` `dependencies` |
|
|
26
|
-
| 公开导出面 | **
|
|
26
|
+
| 公开导出面 | **828** 个运行期符号(+ 41 个测试钩;= 工作树当下的值 = 0.58.0 三件 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.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
|
|
|
@@ -111,7 +111,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
111
111
|
|
|
112
112
|
## §2 公共导出面地图(按域)
|
|
113
113
|
|
|
114
|
-
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**
|
|
114
|
+
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**828** 项)。
|
|
115
115
|
> 本节**不逐名抄**,只给「域 → 承重导出 → 用途 → 实现锚」。承重导出 = 一个端为了让这个域干活
|
|
116
116
|
> **必须**直接调到的那几个符号;其余是它们的类型、变体与辅助位。
|
|
117
117
|
> 单一入口:`import { … } from '@sema-agent/client-core'`(`exports` 只有 `.` 一个;
|
|
@@ -135,18 +135,18 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
135
135
|
`WorkflowsGateUnknownDenial` 四形**不在**基线里,`src/selfOrchestrationDenial.ts` 对基线贡献
|
|
136
136
|
**4** 项运行期导出(三个函数 + `SELF_ORCHESTRATION_RETRY_WITHOUT`)。
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
828 项的内部构成(帮助端估读表大小):**252** 项是 `SCREAMING_SNAKE` 常量数据表/词汇表
|
|
139
139
|
(矩阵、键集、env 名、锚串)而非可调用物;**5** 项是 PascalCase 运行期值
|
|
140
140
|
(`ControlRouter` / `ControlSafetyError` / `HitlBridge` / `HitlSafetyError` / `DecideTransportRetryExhaustedError`);
|
|
141
141
|
**41** 项是 `*For(sessionKey, …)` 的 per-session 变体(§6;其中 `engineNamespaceKeyFor` 是命名巧合 —— 参数是 baseUrl 不是 sessionKey,见域 14)。
|
|
142
142
|
|
|
143
|
-
### 2b. 域图(16 域,逐域计数之和 =
|
|
143
|
+
### 2b. 域图(16 域,逐域计数之和 = 828)
|
|
144
144
|
|
|
145
145
|
| # | 域 | 名数 | 承重导出 | 用途 | 实现锚 |
|
|
146
146
|
|---|---|---|---|---|---|
|
|
147
147
|
| 1 | **适配内核(下行主链)** | 33 | `adapt` · `createWireToCcAdapter` · `runStream` · `eventToSdkMessage` · `terminalToSdkResult` · `turnUsageToModelUsage` · `isRunStreamActive` · `ADAPTER_DIVERGENCES` | 引擎 SSE `AgentEvent` → 端要渲的**双面输出**:transcript(`SDKMessage`)+ chrome(瞬态 `ChromeEvent`)。**本包存在的理由** | `src/adapt.ts`、`src/adapt/{arms,wireShapes,panelTasks}.ts`(经 `adapt.ts` 再导出)、`src/adapter/runStream.ts`、`src/adapter/downstream/*`、`src/adapter/types.ts` |
|
|
148
148
|
| 2 | **seam 公共契约** | 2(其余为 type-only) | `CHROME_ARMS` · `deriveTranscriptId` | 公共词汇 + **id 确定性不变量**(同一条流重放 ⇒ 同一串 id)。`CHROME_ARMS` = 端「我要消费哪些 chrome 臂」的对照清单 | `src/seam.ts` |
|
|
149
|
-
| 3 | **HITL 决断卡链**(§4/§5 主战场) |
|
|
149
|
+
| 3 | **HITL 决断卡链**(§4/§5 主战场) | 141 | `makeHitlCanUseTool` · `HitlBridge` · `findPendingForTask` · `HitlSafetyError` · `bridgeAskUserQuestionGates` · `surfaceToolApprovalFrameAndRespond` / `surfaceFsApprovalAndDecide` · `readToolApprovalRespondAck` · `installApprovalCardPort(For)` · `installHitlHostSurface(For)` · `armPlanReviewApproval` · `reopenPlanReviewCard` · `decidePlanReview` · `startApprovalsFeed` · `pendingRowIsOwnedByThisSession` · `approvalCallKey`/`liveFrameCallKey`/`planReviewQuestionId` · `registerArmedGateFor`/`wasGateArmedFor`/`clearArmedGateFor` · `waitForGateArmed(For)`/`onGateArmed(For)`/`gateArmedWaitMs`(#244 F1 呈现回执事件源) · `planReviewArmedKey(For)`/`notePlanReviewAnswered(For)`/`notePlanReviewAnsweredIfDecisive(For)`(A-024.4 plan 呈现分代) · `toolEndOutputText` · `isAskTool` · `waitForParkRowBirth` · `classifyAskParkRows` / `askParkRowArm` / `classifyAskParkChainFailure` · `readDecisionNoteAudit` / `decisionNoteAuditLine` · `resumeRunningOptions` / `resumeChoiceFromLabels` · `persistedRulesLaneAvailable`/`persistedRulesGovernanceAvailable` · `classifyRulesFailure` · `listAllPersistedRules` · `classifySkippedReason` · `readRulePersistOutcome`(#244 F2:persist-ack 读口与 `readToolApprovalRespondAck` 合成一处) · `parseLocalAllowRule`(durable 腿本地落规则窄化骨架,谓词经 `LocalAllowRuleDeps` 注入) · `readToolApprovalRespondRefusal`(#225 件5,0.42.0:respond 抛错的结构化原文读口 —— 三位各自防御读、各自缺席不铸、**三位皆缺席时整只返 `undefined`**;原样交还零加工,UNTRUSTED-for-display)· `installEditedRuleTextPrechecker` / `hasEditedRuleTextPrechecker` / `precheckEditedRuleText`([5076] 转出口,0.42.0:core 5.57.0 `precheckEditedRuleText` 的**端口注入形** —— 类型面 + 注入口 + 诚实缺席读口。🔴 **不是** value 级 re-export,理由见 §7 缺口 **P-34**;未装 ⇒ 返 `undefined`,绝不编一个 `{ok:true}`)· `surfaceRuleArmNotSent` / `RULE_NOT_SENT_WARN_TEXT` + `surfaceRuleArmRejected` / `RULE_NOT_SENT_REJECTED_WARN_TEXT`(#334,0.43.0:人在卡上按下的「不再询问」被整条丢弃时的诚实告知——**两条刻意分开**:前者=**引擎能力位未确认**(换台引擎/等探测就好),后者=**这次选择没过包内表核/互斥核**(表外文本/坏下标/两臂同场,换引擎也不会变) —— 编辑臂 `respondFreeFormRules` 与批臂 `respondBatchRuleOffers` 两条同形存量共用一条,与 `surfaceRememberNotApplied` 同族纪律:决断照送、只是规则没存,静默丢掉用户明确意图 = 让人以为功能坏了)· `projectCrashConverged`(L-38,0.49.0:`/v1/approvals` additive 键 `crashConverged` 的分桶投影 —— 崩溃收敛的孤儿审批读面,**缺席 ≠ 空数组**、分桶恰一个合取、坏行丢弃并计数,详见 §12;同批把 `ApprovalsResourceLike.list()` 的返回位 additive 放宽成 `ApprovalsListEnvelope`,老形 `{pending}` 仍可赋值)· `readRuleOffers` / `readRuleOfferSupply`(L-103/[C228],0.57.0 additive 导出:「不再询问」候选两代 wire 键的窄读器**公面化** —— 此前只经卡端口出包,不走卡端口架构的宿主只能自己重铸一把,而它承载的是兑付安全判据(原始下标不前移/逐条丢坏/闭集 kind/两代取舍序),详见 §20)· `DecideTransportRetryExhaustedError`(Inkglow-1085 P0a:decide 出站瞬断重试耗尽的 typed 判别 —— HitlBridge 内建单次退避重试,耗尽走重呈臂不判死 turn;端一般只消费行为,不需要 instanceof) | suspended→decide→resume 环。🔴 **D-1 两元组 verbatim 回显**是字节级断言的安全不变量,端**不许重实现它的任何一段**。🔴 键空间边界(web [C1] d3 拦截):`gateIdentity` 四常量两函数只覆盖 HITL questionId/callKey 空间;seat 的 `TOOL_PERMISSION_REQUEST_ID_DOMAINS`(`plan:` 等)是另一键空间,**两者绝不合并**(合并=座位校验器静默拒全部 plan-review 卡) | `src/hitl/hitlBridge.ts`、`toolApprovalWire.ts`、`askGateWire.ts`、`planReviewWire.ts`、`hitlHostSurface.ts`、`gateIdentity.ts`、`armedGateRegistry.ts`、`parkOwnership.ts`、`parkResolver.ts`、`approvalsFeed.ts`、`frameRouter.ts`(**只挑名导出** `toolEndOutputText`/`ENGINE_ABORT_TOOL_RESULT`/`isAskTool`/`HITL_REJECT_MESSAGE`/`HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE`)、`parkRowBirthWait.ts`、`approvalDecisionNoteAudit.ts`、`askParkRowRouting.ts`、`resumeRunningCard.ts`(#265 上收的判定层)、`persistedRulesWire.ts`、`localAllowRule.ts`(#244 F2 规则侧)、`crashConverged.ts`(L-38 崩溃收敛读面) |
|
|
150
150
|
| 4 | **子代 wire + 面板侧信道台账** | 84 | `tailEngineSubagent` · `installSubagentActivitySink` · `installSubagentTailMetaSink`(#280 件2:tail meta 帧发布口,`contentFrames` 判别位载体)· `stopEngineTask` + `classifyTaskStopConflict` · `fetchEngineSubagentReport` · `steerEngineSubagent`(0.32.0 未发布 #280 件A:additive 第三参 `childTaskId` —— 端有行上下文时**应当**传,传了就走「台账优先 / 缺席即诚实缺席 + `noteBgOwnerAbsence` 留痕」的 Q3 口径,与 tail·taskOutput·subagentOutput 三腿同姿势、与孪生 resume 腿共用同一个 `resolveOwnerRunId` 判据;**不传**则逐字维持旧行为=回落在飞 run)· `resumeSettledSubagent` + `resolveSubagentResumeContext` + `resolveOwnerRunId` + `classifySubagentResumeFailure` + `subagentResumeAvailable`(#242 批 2 A-028.7:resume 判定半场上收,与 steer 孪生同居;取址三态 = 台账有行用行值 / 指名了行但台账缺席则**诚实缺席绝不回落在飞 run** / 没指名行才回落。出路文案归端)· `recordSubagentOwnerFromProgress` + `getBgParentRunOwner`(A-028.6:「子代 → 宿主 run」**单表**,宿主 run 必须由持 stream-local 值的调用方显式传入,包内绝不从 `activeEngineRunId()` 推断)· `noteBgOwnerAbsence`(#242 批 3 [4000] Q3=B:tail/taskOutput·taskStop/subagentOutput 三腿台账缺席即诚实缺席**绝不回落在飞 run**,缺席 warn 留痕每 (腿,taskId) 一条)· `clearBgTerminalFacts`(#242 批 3 扫码修:复活=新周期,旧周期终态事实作废——fleetLedger 复活两腿按尾段清账,factsAccepted 方向核不再拿上周期终态当先例)· `auditRetainWithoutWake`([4000] Q5:引擎宣示 `subagentResume` + 本端在付 `retainSubagentSessions` + 端未实现 `wakeSubagent` ⇒ 响亮一条;`CLIENT_VERBS.wakeSubagent` 维持 fail-soft)· `subscribeSubagentContent` · `subscribeEngineAgentPanel` · `publishQuestionFrame` / `respondToQuestion` | 驱动与观测委派子代;经 module 级台账喂活体 agent/task 面板。全部**能力位 gate**(§5b) | `src/subagent/*.ts`、`src/subagentContentStore.ts`、`src/engineAgentPanelStore.ts`、`src/engineInlineTaskStats.ts`、`src/engineToolLabelStore.ts`、`src/liveQuestionStore.ts` |
|
|
151
151
|
| 5 | **fleet 投影** | 46 | `createFleetLedger` · `projectTasks` · `projectWorkflows` · `projectFleetAgentRows` · `readEngineActiveBgTasks` · `FLEET_TASK_VIEW_KEYS` · `escapeDisplayControlChars`(不可见字符可见化,行标签/描述消毒的共享底座)· `wireCycleSeq` / `wireRetiredBy`(0.38.0 提货补投的 #261 §2 两位:代际号 = SendMessage 复活即 +1,**缺席 ≠ 第一代**;`retiredBy` 在场 = 这条终态是对账腿从 durable run 行投影出来的、**不是**发布方亲报 —— 幽灵行与正常收尾唯一的 wire 判据。两位都只在场才落键) | 老 `fleetClient` 那一刀的成品:**帧体归库、连接归端** —— 端持 SSE 连接,库做行投影 + 保留台账 | `src/fleet/fleetProjection.ts`、`src/fleet/fleetLedger.ts`、`src/fleetAgentPanelProjection.ts`、`src/fleetTaskDesc.ts` |
|
|
152
152
|
| 6 | **请求装配(上行唯一构造口)** | 8 | `buildTaskRequest` · `REQUEST_FIELD_MATRIX` · `unregisteredRequestKeys` · `applyLiveRequestDefaults` · `taskNotificationToPrintFrame` | 两条车道(`interactive`/`print`)出站请求的**唯一**构造器;`unregisteredRequestKeys` 是可执行门 —— 端偷带一个未登记键上 wire 就红 | `src/request/taskRequest.ts`、`src/request/printNotification.ts` |
|
|
@@ -158,8 +158,8 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
158
158
|
| 12 | **workflow 与后台工作视图** | 19 | `projectWorkflowRun` · `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`) |
|
|
159
159
|
| 13 | **座位 IPC 契约** | 33 | `LOCAL_SESSIONS_SPEC` · `SEAT_METHOD_NAMES` · `SEAT_EVENT_TYPES` · `isLocalSessionEvent` · `isToolPermissionRequest` · `toolPermissionRequestId` · `SEAT_VALIDATOR_KEY_COVERAGE` | 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 桌面壳里的符号只会零命中,而零命中在这里**既不证真也不证伪**。复核这些断言**不得**拿本仓语料当反证 |
|
|
160
160
|
| 14 | **宿主端口与会话槽** | 26 | `installHost` · `installHostFor` · `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` |
|
|
161
|
-
| 15 | **控制面与传输** |
|
|
162
|
-
| 16 | **引擎词汇表与包自检** |
|
|
161
|
+
| 15 | **控制面与传输** | 83 | `ControlRouter`(+ `ControlSafetyError`)· `makeEngineWireClient` + `resolveWireAuth` · `installEngineWireTarget` · `diagnoseSseIdleTear` / `isSseIdleError` · `attemptActiveRunSelfHeal` + `activeRunBusySignal` + `activeRunSelfHealRow` / `activeRunBusyHeadlessRow` · `kickEngineCapsProbe` / `engineCapTrue` / `invalidateEngineCaps(baseUrl, probe?)`(#307 S25:引擎温切后的 caps 生产失效口 —— kick 自带幂等闸,同 baseUrl 重启后不显式失效就永远读到旧引擎那一版能力位;调用方 = 壳的 respawn/restartEngine。🔴 **推荐两参形**:第二参给替代探测则「推进代际 + 注册新探测」在同一同步块内完成,失效与下一次 kick 之间那个「等待者读到未判」的窗按构造不存在;单参形保留给「只丢缓存、这一刻没有替代探测」的调用方,那种情形下读到未判是诚实结局) · `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) | 上行通道的**监管**半场(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` |
|
|
162
|
+
| 16 | **引擎词汇表与包自检** | 58 | `CONFIG_REFUSAL_CODES` / `isConfigRefusalCode` · `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) | 三端分臂共用的**去字面化** `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` |
|
|
163
163
|
|
|
164
164
|
🔴 **`engineErrorCodes` 的开集纪律**(该文件头注逐字):这些 `ReadonlySet` / 前缀谓词一律是**识别表**,
|
|
165
165
|
回答的是「我认不认得这个码」,**绝不是**「合法码只有这些」。消费点 `switch` **必须留 `default`**,
|
|
@@ -1527,6 +1527,8 @@ CHANGELOG 0.29.0「已知局限」段与相应 JSDoc 都有成文。**别在读
|
|
|
1527
1527
|
|
|
1528
1528
|
| **P-43** | med(治理面)@cli @web @desktop | 🆕 **`hooksForWire()` 只守住了本地执行器四条治理腿里的三条**(0.52.0 L-67④ 补了第三条,第四条**在册未修**):cli 仓那份本地执行器(`utils/hooks/hooksConfigSnapshot.ts` 的 `getHooksFromAllowedSources`,**cli 仓坐标不是本仓坐标**)的第四条腿 = `disableAllHooks` 出现在**非** managed 来源(user/project/local)时按 CC 语义降级成「只跑 managed hooks」。本包今天**只读** `policySettings.disableAllHooks` ⇒ 该形在引擎腿上**不成立**(用户把自己的 hooks 关了,引擎照投照跑)。**为什么不做单边近似**:cli 那条腿读的是**合并后**的标量(四源按 policy→user→project→local 后写覆盖前写),而本包 `SettingsPort` 只有 per-source 读口 —— 拿「任一来源为 true」去近似会在「user 写 `true`、local 写 `false`」这一形上**判反**(cli 那边是**不**限制)。忠实复刻要给 `SettingsPort` 加一个合并读口 = **公面改动**(端要跟车实现),属另一批 | `src/hooksWireCaps.ts`(头注「在册缺口」段);§15b/§15d | 端**不要**假定「用户 settings 里的 `disableAllHooks` 会挡住引擎腿的 hooks」——今天只有 **managed(policySettings)** 那一份挡得住。要它落地按 [C162] 令④ 回 C 板提(正位解在包侧:`SettingsPort` 补合并读口 + 本函数补第四条腿) |
|
|
1529
1529
|
|
|
1530
|
+
| **P-44** | ✅ **已收**(0.58.0,sdk 8.2.0 提货)@cli @web @desktop | ✅ **上游已补齐,本条转已收** —— sdk **8.2.0**(S-134 五锚)把这一族型面缺口一次补完:①`respond` 体 `persistRule` 由单臂 `{rule}` 换成具名**两臂互斥**联合 `PersistRuleSelection`(`{rule, edited?}` ∣ `{batchOfferIndex}`,互斥用 `?: never` 钉在编译期 ⇒ server 那句 `PERSIST_RULE_BATCH_EXCLUSIVE_ERROR` 400 永远打不到线上);②`ToolApprovalFrame` / `ApprovalCard` / `PendingCheckpoint` 三腿同一个 `RuleOffer` 判别联合(含 `match` 四员闭词表、成员 `command`/`directoryRead` 两臂、additive `uncoveredDetail`);③`ToolApprovalRespondAck` 补 `persistedRule` / `persistedRules` / `persistedRuleAnchors` 三位。🔴 **本包侧本来就零 cast、也不需要 cast**(0.57.0 原文,逐字仍成立):本包**不铸 respond 的 wire 体** —— `RespondToolApprovalFn` 是**宿主注入**的函数型,包只把扁平兄弟位(`persistRule: string` / `persistRuleEdited?: true` / `persistRuleBatchOfferIndex?: number`)交给注入面。⇒ 吃这个缺口的一直是**三端的注入面**。本包 0.58.0 这一侧的动作是:归一形 `RuleOffer` 一族改由 sdk 派生、`ToolApprovalRespondAckView` 与 `PersistedRuleAnchor` 两个包内自铸形按各自写下的退役条款回收成 sdk 形的别名、`AHEAD_OF_ANCHOR` 里那条 `ruleOffers` 领先登记到期自红删除(详见 **§22a**)。🔴 **三端还要做的那一半(本条转已收之后的剩余动作)**:注入面那处宽 `cast`(或自铸的 respond 包装形)现在可以删掉,改直接用 sdk 8.2.0 的 `PersistRuleSelection` —— 两臂互斥由编译期钉,`{rule, batchOfferIndex}` 同场会**编译红**(这正是要的);`batchOfferIndex: 0` 逐字进 body(`0` 不被 falsy 吞)。同样别再在端侧自铸同名 `RuleOffer` 形:归一形与它的伴生类型自 0.57.0 起在本包公面上,三张闭词表自 0.58.0 起也在(§22b) | `src/hitl/toolApprovalWire.ts`(两处「候 sdk 补锚」头注已随本批锚到 8.2.0 / 回收)· `scripts/run-approval-frame-keys-test.mjs`(该条 `AHEAD_OF_ANCHOR` 登记已删)· `scripts/run-sdk-floor-test.mjs`(地板 8.2.0) | 端按上一栏「剩余动作」删自己的宽 cast;peer 地板随本包抬到 `>=8.2.0`,提货前先抬依赖 |
|
|
1531
|
+
|
|
1530
1532
|
### 7e. 缺口的共同形状(值得单独说)
|
|
1531
1533
|
|
|
1532
1534
|
**P-1 / P-2 / P-3 / P-4 / P-5 / P-6 / P-7 是同一类**:上游(server / SDK)已经把材料铸到 wire 上了,
|
|
@@ -2867,3 +2869,370 @@ CC 2.1.250 语料**无同形提示行** —— `first token` / `firstToken` / `f
|
|
|
2867
2869
|
`CHROME_ARM_TABLE` 加员)。
|
|
2868
2870
|
**常驻门**:`scripts/run-type-superset-ledger-test.mjs`(两个 `_sema_` 键登记)、
|
|
2869
2871
|
`scripts/run-integration-doc-freshness-test.mjs` ③ §3c(臂表双向对账)。
|
|
2872
|
+
|
|
2873
|
+
---
|
|
2874
|
+
|
|
2875
|
+
## §20 🆕 「不再询问」候选窄读器的公面(0.57.0;L-103 / [C228]、[C233]②)
|
|
2876
|
+
|
|
2877
|
+
### 20a. 修的是哪一形
|
|
2878
|
+
|
|
2879
|
+
两代 wire 键(`ruleOffers`,server ≥7.46.0 / 退役键 `ruleSuggestions`,≤7.45)在 0.56.0 及更早
|
|
2880
|
+
**只经卡端口出包**:归一形 `RuleOffer[]` 唯一的公面落点是 `ApprovalCardRequest.ruleOffers`
|
|
2881
|
+
(活卡帧腿)与 `ApprovalCardRequest.ruleOffersReadOnly`(durable 行腿)。窄读器本身
|
|
2882
|
+
(`readRuleOffers` / `readRuleOfferSupply`)是**模块内私有函数**。
|
|
2883
|
+
|
|
2884
|
+
后果:**不走卡端口架构的宿主**(浏览器端自己拿帧渲,没有 Ink 三选卡)只能在自己那边重铸一遍
|
|
2885
|
+
同一把窄读器。而这把读器承载的不是格式化,是**兑付安全**判据:
|
|
2886
|
+
|
|
2887
|
+
| 判据 | 重铸错了会怎样 |
|
|
2888
|
+
|---|---|
|
|
2889
|
+
| 逐条丢坏、**原始 wire 下标不前移** | 人点的第 k 个与服务端兑的第 k 个指向**两条不同规则** |
|
|
2890
|
+
| `kind` 是闭集判别位 | 不认识的臂被猜成 `single`,渲出一个按下去必被拒的选项 |
|
|
2891
|
+
| 两代取舍序(新键在场即定局 / `null` ≡ 缺席) | 拿旧键素材冒充这次 ask 的候选;或把中转层的 `null` 判成坏形,整段打掉 ≤7.45 引擎的「不再询问」档 |
|
|
2892
|
+
|
|
2893
|
+
0.57.0 把两个口 **additive 推上公面**,语义与字节一字未改。
|
|
2894
|
+
|
|
2895
|
+
### 20b. 端该怎么用(两步)
|
|
2896
|
+
|
|
2897
|
+
1. **手里是一整帧/一整行** ⇒ 调 `readRuleOfferSupply(frame.ruleOffers, frame.ruleSuggestions)`
|
|
2898
|
+
—— 这是三端唯一该调的那个口,两代键的取舍序在它里面。
|
|
2899
|
+
2. **手里只有新键** ⇒ 调 `readRuleOffers(offers)`。
|
|
2900
|
+
|
|
2901
|
+
返回 `RuleOffer[]`(至少一条)或 `undefined`(= 这张卡没有可渲的「不再询问」档)。
|
|
2902
|
+
🔴 **`undefined` 不是空数组**:空数组会被渲成「有这个档、里面一条都没有」,而真相是「没有档」。
|
|
2903
|
+
|
|
2904
|
+
### 20c. 🔴 五条读法(端不许自己重判,也不许自己放宽)
|
|
2905
|
+
|
|
2906
|
+
1. **`offerIndex` 的定义域随腿不同,函数不知道你在哪条腿上**:
|
|
2907
|
+
· **活卡帧腿**(`tool_approval` 帧的 `ruleOffers`)—— server 同步腿是纯前缀截、零逐条丢弃 ⇒
|
|
2908
|
+
它恒等于引擎侧的 offer index,**是**合法选择键,批臂按它回兑
|
|
2909
|
+
(respond 体 `persistRule.batchOfferIndex`);
|
|
2910
|
+
· **durable 行腿**(`/v1/approvals` 行的 `ruleOffers`)—— server 已逐条丢弃并压紧过一次 ⇒
|
|
2911
|
+
行上的下标本就不是引擎的 offer index,而这条腿**根本没有兑付口**(`/decide` 体无规则位)。
|
|
2912
|
+
那一位只是展示/对账座,**禁**当选择键。
|
|
2913
|
+
2. **逐条丢坏,不整只拒**:一条坏 offer 不该让另一条真 offer 消失(与 server 侧同向)。
|
|
2914
|
+
但**留下来的每一条都带原始下标**——压紧下标是本节表里第一行那条失效形。
|
|
2915
|
+
3. **batch 的成员不逐条丢**:合取批是「对全体成员一次说是」,任一成员不合形(含 `kind` 不识)
|
|
2916
|
+
⇒ **整条 batch 丢**(兄弟 offer 不连坐,也**不**整卡丢)。渲一个缺了成员的批 = 人点的与引擎
|
|
2917
|
+
兑的不是同一批规则。⚠️ 这条**不是本包的保守选择,是上游的规范性条款**:core design/382 §2.3
|
|
2918
|
+
逐字 "drops the WHOLE batch offer — never the single member ... and never the whole card"
|
|
2919
|
+
(sdk 8.2.0 `RULE_OFFER_BATCH_MEMBER_KINDS` 顶注同文)—— 端**不许**自行改成丢单个成员。
|
|
2920
|
+
4. **`uncoveredSegments` 是诚实余量披露,不是装饰位**:非「有限非负整数」⇒ 整条 batch 丢。
|
|
2921
|
+
渲一个编出来的 `0` 等于对用户说「兑完这批就全覆盖了」,而那句话没有证据。
|
|
2922
|
+
`0` 本身是**合法读数**。
|
|
2923
|
+
5. **超帽整只降缺席、不截断**:条数 > 8(server 执法帽是 4,包侧刻意留宽)⇒ 整只缺席。
|
|
2924
|
+
截了不留痕会掩盖注入。
|
|
2925
|
+
|
|
2926
|
+
### 20d. 形校验(包侧已做,端不必重做)
|
|
2927
|
+
|
|
2928
|
+
- 一条 `single` offer / 一个 `command` 成员共用三位窄化:`rule` 非空串 ∧ `match` ∈ **闭词表**
|
|
2929
|
+
(⚠️ **0.58.0 起是四员** `exact` / `prefix` / `wildcard` / `subpath`,由 sdk 8.2.0
|
|
2930
|
+
`RULE_OFFER_MATCHES` 单源派生;0.43.0–0.57.0 这里手抄成两员,合法的 `wildcard` 候选被整条丢掉
|
|
2931
|
+
—— B-025,详见 §22)∧ `command` 非空串;成员另加 `segment` 非空串(渲染座,**永不参与裁决**)。
|
|
2932
|
+
- ⚠️ **0.58.0 起 batch 成员是判别联合**(`kind: 'command' | 'directoryRead'`,§22b):
|
|
2933
|
+
`directoryRead` 臂**没有** `match`/`command` 两座,渲之前先读 `kind`。
|
|
2934
|
+
- `rule` / `command` / `segment` 三位都是 **UNTRUSTED-for-display**(原始 post-rewrite 命令字节)——
|
|
2935
|
+
包不消毒(消毒单源在端的展示层),端渲之前照自己那套控制字符/长度纪律处理。
|
|
2936
|
+
- 空数组 / 非数组 / `null` / 全条坏形 / 超帽 ⇒ `undefined`。
|
|
2937
|
+
|
|
2938
|
+
### 20e. 与卡端口的关系(不是二选一,是同一把读器的两个出口)
|
|
2939
|
+
|
|
2940
|
+
已经走卡端口的宿主**什么都不用改**:`ApprovalCardRequest.ruleOffers` /
|
|
2941
|
+
`.ruleOffersReadOnly` 仍是同一把读器的产物,字节零变化。公面出口是给**没有卡端口**的宿主准备的
|
|
2942
|
+
第二个观察面。常驻门 ⑦ 段把两者对同一份素材逐字对账 —— 哪天有人在其中一条腿上就地改窄读,当场红。
|
|
2943
|
+
|
|
2944
|
+
**实现锚**:`src/hitl/toolApprovalWire.ts`(`readRuleOffers` / `readRuleOfferSupply` 两个 `export`;
|
|
2945
|
+
归一形 `RuleOffer` / `RuleOfferMatch` / `RuleOfferBatchMember` 与入参形 `WireRuleOffer` 照旧导出。
|
|
2946
|
+
🆕 0.58.0 起 `RuleOfferMatch` / `RuleOfferBatchMember` / `RuleOfferUncoveredDetail` /
|
|
2947
|
+
`RuleOfferUncoveredReason` 四形**由 sdk 8.2.0 派生**,三张闭词表随之公面再导出,见 §22)。
|
|
2948
|
+
**常驻门**:`scripts/run-rule-offers-reader-test.mjs`(公面在场 + 两代正控 + 下标不前移 +
|
|
2949
|
+
batch 语义 + 坏形处置 + 取舍序 + 与两条卡端口腿的单一铸点对账)。
|
|
2950
|
+
|
|
2951
|
+
---
|
|
2952
|
+
|
|
2953
|
+
## §21 🆕 resume 族「时间性拒绝」二码的判型(0.57.0;L-102,server ≥7.47.0 / ≥7.51.0,SDK 8.1.0)
|
|
2954
|
+
|
|
2955
|
+
### 21a. 修的是哪一形
|
|
2956
|
+
|
|
2957
|
+
`resume.*` 这一族(409 合同拒绝族)今天有九个成员。下面两个是这一族里**唯一带得出「等多久」**
|
|
2958
|
+
(`retryAfterSec`)的两个 —— 这是它们被收成一个闭集的**全部理由**:
|
|
2959
|
+
|
|
2960
|
+
| 码 | 语义 | server 起版 |
|
|
2961
|
+
|---|---|---|
|
|
2962
|
+
| `resume.usage_window_exhausted` | 这一行的账本键上,本部署的**治理窗**满了。什么都没消费、什么都没解钉 ⇒ 同一个 token 带同一个决议在窗放开后**可直兑** | ≥7.47.0 |
|
|
2963
|
+
| `resume.preflight_rejected` | 部署自己的 resume 预检拒了这次(显式拒 / 抛 / 超时 / 读不动,四臂一律 fail-closed)。它是提交前的**最后一档**,所以什么都没被消费 | ≥7.51.0 |
|
|
2964
|
+
|
|
2965
|
+
两码的 409 体 additive 携 `retryAfterSec`(秒,`ceil`,**下限 1**;server 的铸键判据闭集恰是
|
|
2966
|
+
「本码 ∧ 有限正数」,两码之外恒缺席)。SDK 8.1.0 起按这两个具名码铸 `ResumeRetryLaterError`。
|
|
2967
|
+
|
|
2968
|
+
🔴 **本闭集不是「哪些码可以等」的名单**(端最容易读错的一句):族内有**明确的可等反例** ——
|
|
2969
|
+
`resume.row_recycling`(core 铸文逐字 "this clears on its own; send again in a moment",本包既有
|
|
2970
|
+
处置 `row-contended`),它可等,只是 server 给不出秒数,所以它**不在**这个闭集里。
|
|
2971
|
+
⇒ `resumeRetryLaterFromError()` 返回 `null` 只意味着**没命中这两码**,**不意味着「等也没用」**;
|
|
2972
|
+
闭集外的码照旧按既有分类结果处置。把 `null` 读成「不可等」会把一个自清的瞬时争用说成「去重开一个
|
|
2973
|
+
新 agent」——正是本包 0.38.0 收 `row_recycling`/`row_gone` 那批要根治的病换了个方向。
|
|
2974
|
+
|
|
2975
|
+
修前:本包的 resume 失败分类器把两码双双落进开集兜底 `error` ⇒ server 明明给了等待窗,到端只剩
|
|
2976
|
+
一句泛泛失败;而壳侧自己手接了一份判型 —— 判定长在端里,三端各写一遍必然各错一遍。
|
|
2977
|
+
|
|
2978
|
+
### 21b. 端该怎么用(两条路,按你消费哪一层选)
|
|
2979
|
+
|
|
2980
|
+
1. **只要判型**(自己组织重试/文案,或者你消费的不是子代复活腿而是别的 resume 面)⇒
|
|
2981
|
+
`resumeRetryLaterFromError(err)` → `{ code, waitable, retryAfterSec? } | null`。
|
|
2982
|
+
🔴 **命中 ≠ 可等**:处置位是 `waitable`,不是「返回了非 null」。
|
|
2983
|
+
2. **走子代复活腿** ⇒ 照旧读 `resumeSettledSubagent()` 的结局:失败臂新增**两格**
|
|
2984
|
+
`reason: 'retry-later'` / `'refused-preflight'`,并 additive 携 `code?` 与 `retryAfterSec?`。
|
|
2985
|
+
|
|
2986
|
+
**两格怎么分**(判据在包里,端零重判):
|
|
2987
|
+
|
|
2988
|
+
| `reason` | 什么时候 | 端能说什么 |
|
|
2989
|
+
|---|---|---|
|
|
2990
|
+
| `retry-later` | `resume.usage_window_exhausted`(该码本身即证据)**或** `resume.preflight_rejected` **且 server 给了窗** | 「等一会儿(有窗就说等多久)再试」 |
|
|
2991
|
+
| `refused-preflight` | `resume.preflight_rejected` **且没有窗** | 「这一拒发生在提交之前,你的决定没被消费」+ 把「还能不能再赎」交给引擎那行原文。**不许**渲成「稍后重试」,**也不许**渲成终局 |
|
|
2992
|
+
|
|
2993
|
+
### 21c. 🔴 四条读法
|
|
2994
|
+
|
|
2995
|
+
1. **`retryAfterSec` 缺席 ≠ 0**:缺席 = 服务端没给窗(老引擎 / 老 SDK 映射把本码塌进无字段的族
|
|
2996
|
+
基类 / 该腿不发 `Retry-After` 头)。**绝不渲一个编出来的倒计时**。
|
|
2997
|
+
🔴 **缺席时该说什么由 `reason` 决定,不由这一位决定**:`retry-later` 且窗缺席 ⇒ 说「稍后重试」
|
|
2998
|
+
但不给数字;`refused-preflight` ⇒ **不许**说「稍后重试」(见上表)。把两者说成同一句,
|
|
2999
|
+
就是本节要修的病换了个方向。
|
|
3000
|
+
2. **「可以再试」是说给人听的,不是自动重试腿的授权**:resume 是 **AT-MOST-ONCE** 的有副作用动作
|
|
3001
|
+
(叫醒 = 真跑一轮),本包在这一格上照旧**一次都不重试**。端要做自动重试请自己承担幂等论证。
|
|
3002
|
+
3. **`preflight_rejected` 的两条上游臂在客户端分辨不出来**(`retry_later` / `terminal` 的判别位在
|
|
3003
|
+
message 散文里)。本包**不按文案分臂** —— 按文案分支正是上游改一个词就静默空转的形。
|
|
3004
|
+
⇒ 正解是**按正向证据分格**:有窗 ⇒ `retry-later`;没窗 ⇒ `refused-preflight` = **不可判**。
|
|
3005
|
+
证据成立是**直证**(core 7.3.1 `dist/core/runner/runtask.js` 的 `resumePreflight` 拒绝段直读):
|
|
3006
|
+
`terminal` 臂抛的错**一个 detail 都不带**(它走的是单发 `expire` CAS,文末逐字 "the token is not
|
|
3007
|
+
redeemable")⇒ 结构上不可能有 `retryAfterMs` ⇒ server 无从铸 `retryAfterSec`;而 `retry_later` 臂
|
|
3008
|
+
只在部署真给了等待建议时带它。⇒ **有窗是 retry_later 的充分证据,没窗两臂都可能**。
|
|
3009
|
+
🔴 `refused-preflight` **不是**「不可重试」,它是「我不知道还能不能再赎」——两者渲成同一句话
|
|
3010
|
+
就又回到了本条要修的病(一个把终局说成暂时,一个把暂时说成终局)。
|
|
3011
|
+
4. **别把它与 429 的 `usage.window_exhausted` 合并判**:同一本账、**不同门、不同码** —— 那一个是
|
|
3012
|
+
提交面的准入拒,这两个是 resume/decide 腿的**提交前**拒。
|
|
3013
|
+
🔴 **「卡仍 pending、token 仍可兑」只对 `retry-later` 那一格成立**:`resume.usage_window_exhausted`
|
|
3014
|
+
有 core 的不变量背书(什么都没消费、什么都没解钉);而 `refused-preflight` 那一格**不能**这么说 ——
|
|
3015
|
+
`terminal` 臂恰恰已经把行用单发 `expire` CAS 结清了。端在无窗预检拒上只许陈述**这一次拒绝本身**
|
|
3016
|
+
(发生在提交之前、这一拒没有消费你的决定),**不许**顺带承诺卡还在、token 还能兑。
|
|
3017
|
+
|
|
3018
|
+
### 21d. 形校验(包侧已做)
|
|
3019
|
+
|
|
3020
|
+
- 判型是**闭集**的(恰这两个码),**绝不放宽成 `resume.` 前缀判**:放宽会把 `retain_off` /
|
|
3021
|
+
`evicted` / `row_gone` 这些「等也没用」的码一起说成「过会儿再试」——一半用户白等、另一半白重开。
|
|
3022
|
+
上游哪天真在新码上铸 `retryAfterSec`,加成员必须同批带判据。
|
|
3023
|
+
- `retryAfterSec` 的窄读域 = **server 的铸键域**(整数 ∧ ≥1),不更宽也不更窄:`0` / 负数 / 小数 /
|
|
3024
|
+
`NaN` / `Infinity` / 数字串一律**降缺席**(不降 0、不取绝对值)。放行 `0` 就是对消费端说
|
|
3025
|
+
「立刻重试」,而上面第 2 条说了那意味着什么。
|
|
3026
|
+
- **结构读不 `instanceof`**:客户端是宿主注入的,跨 bundle 的同名类是两个类;键位只认 `errorCode`
|
|
3027
|
+
(退役 `code` 槽不做兼容)。null 原型的 plain object(desktop IPC / web 转投的真形)照样命中。
|
|
3028
|
+
- **闭集是 `Object.freeze` 的只读数组,不是 `ReadonlySet`**:后者只在类型面只读,运行期就是普通
|
|
3029
|
+
`Set`,而判定查的是**同一个实例** ⇒ 端一行 `.add('resume.row_gone')` 就能把一条「等也没用」的
|
|
3030
|
+
拒绝翻成带窗的 `retry-later`。端**可以**读它(对表/留痕),**改不动**它(ESM strict 下 `push` /
|
|
3031
|
+
下标赋值直接抛)—— 要加成员请回上游,不是在消费侧撑开闭集。
|
|
3032
|
+
|
|
3033
|
+
### 21e. 🔴 老宿主:穷尽形必须加一条 case
|
|
3034
|
+
|
|
3035
|
+
`SubagentResumeFailureKind` 从八员变**十**员(`retry-later` + `refused-preflight`)。
|
|
3036
|
+
**结构形免动**(读 `reason`/`detail` 的宿主一字不用改),
|
|
3037
|
+
但对该联合做**穷尽 switch**(TS `never` 兜底)的宿主会在提货时编译红 —— 那是设计:一个新的处置
|
|
3038
|
+
落进 `default` 而无人处理,就是把「等一会儿就好」渲成「失败了」。同 §18c 的老宿主纪律。
|
|
3039
|
+
|
|
3040
|
+
### 21f. 上游供给的诚实边界(本版新增的已知局限)
|
|
3041
|
+
|
|
3042
|
+
- **本包不铸 `ResumeRetryLaterError`,也不 `instanceof` 它**:该类是 SDK 8.1.0 的,而本包 peer 地板
|
|
3043
|
+
仍是 `>=7.4.0`。⇒ 挂在 ≤8.0 SDK 上的宿主,这两码走的是无字段的族基类,`retryAfterSec` 在错误对象上
|
|
3044
|
+
**根本不存在** ⇒ 本包如实报缺席。要拿到窗,宿主得把 SDK 抬到 8.1.0(或自己从 409 体里读出来,
|
|
3045
|
+
按同一条窄读域喂进来)。
|
|
3046
|
+
- **本包不替端排重试节拍**:窗只是 server 给的**建议下界**。
|
|
3047
|
+
- **`refused-preflight` 这一格今天在多数部署上结构性不可达**:`resume.preflight_rejected` 要有
|
|
3048
|
+
部署自己的 resume 预检座才发得出来。它是**预置臂**,不是当版可触发的行为面 —— 端接上去是为了
|
|
3049
|
+
「码到货那天不至于只会印一行裸码」,不要据此推断本部署已经在用预检。
|
|
3050
|
+
|
|
3051
|
+
---
|
|
3052
|
+
|
|
3053
|
+
## §22 🆕 sdk 8.2.0 提货 · 规则报价窄读器修根(B-025)· resume 拒绝文案铸点上收(0.58.0)
|
|
3054
|
+
|
|
3055
|
+
本节三件同一批,分三段。**共同的形**都是「上游已经把单源摆出来了,而消费侧还留着一份自己的抄本」。
|
|
3056
|
+
|
|
3057
|
+
### 22a. sdk 8.2.0 提货:peer 地板 `>=7.4.0` → `>=8.2.0`(本版唯一的非 additive 面)
|
|
3058
|
+
|
|
3059
|
+
| 面 | 0.57.0 | 0.58.0 | 端要做什么 |
|
|
3060
|
+
|---|---|---|---|
|
|
3061
|
+
| peer 地板 | `@sema-agent/sdk >=7.4.0` | **`>=8.2.0`** | 提货前先抬自己的 sdk 依赖;装 <8.2.0 会看到 peer 警告,且本包**运行期真的需要** 8.2.0(见下) |
|
|
3062
|
+
| sdk 消费姿势 | 值级 5 个符号 | 值级 **8** 个(新增三张 `as const` 闭词表) | 无(本包内部) |
|
|
3063
|
+
| `RuleOfferMatch` | 本包手抄 `'exact' \| 'prefix'` | **sdk 派生**,四员 | 🔴 对它写穷尽 `switch` 的端**会编译红** —— 那正是要显形的东西(见 22b) |
|
|
3064
|
+
| `RuleOfferBatchMember` | 本包自铸 interface(四座) | **sdk 派生**判别联合 | 🔴 渲成员前先读 `kind`(见 22b) |
|
|
3065
|
+
| `ToolApprovalRespondAckView` | sdk 形的 additive 超集 | **= sdk `ToolApprovalRespondAck` 本身**(别名) | 无(名字保留,读法逐字不变) |
|
|
3066
|
+
| `PersistedRuleAnchor` | 本包自铸(三位 `readonly`) | **sdk 派生**(同三位,跟随 sdk 的可变性声明) | 无(读方源码兼容) |
|
|
3067
|
+
|
|
3068
|
+
🔴 **地板抬升的四条硬理由**(不是顺手跟版本;逐条写在 `scripts/run-sdk-floor-test.mjs` 的 `FLOOR` 注里):
|
|
3069
|
+
① 三张闭词表是**运行期**判据 ⇒ 值级 import,<8.2.0 上这三个名字不存在,整包编译不过;
|
|
3070
|
+
② `RuleOffer` 一族五个类型面(本包归一形由它们派生);
|
|
3071
|
+
③ `ToolApprovalRespondAck` 上的 `persistedRule` / `persistedRules` / `persistedRuleAnchors` 三位
|
|
3072
|
+
(0.43.0 起的包内超集按它自己写下的退役条款回收);
|
|
3073
|
+
④ `AgentEvent` 新增 `approval_revoke` 臂 —— 臂一进 union,下行投影的编译期穷举断言当场红。
|
|
3074
|
+
|
|
3075
|
+
**同批退役的两笔记账**(都是「带退出条件的登记到期自红」,不是清理):
|
|
3076
|
+
- `run-approval-frame-keys-test.mjs` 的 `AHEAD_OF_ANCHOR` 里那条 `ruleOffers` 领先登记 ——
|
|
3077
|
+
sdk 8.2.0 的运行期锚 `TOOL_APPROVAL_FRAME_KEYS` 已含该键(18 项),门先自红一次再删;
|
|
3078
|
+
⚠️ 同表其余 6 条(`requiresRealApproval` / 窗三键 / `inputHasBidi` / `parked`)**仍在**,
|
|
3079
|
+
锚上依旧没有它们 —— 退出条件是**逐条**的,不是整表的。
|
|
3080
|
+
- §7d **P-44 转「已收」**:sdk 8.1.0 那一族型面缺口(respond 体 `persistRule` 单臂、帧/行的
|
|
3081
|
+
`ruleOffers`、ack 三位)在 8.2.0 全部补齐。🔴 **本包侧本来就零 cast**(P-44 原文已写清:本包不铸
|
|
3082
|
+
respond 的 wire 体,吃这个缺口的是三端**注入面**)⇒ 本包这一侧的动作只是把归一形改成派生 +
|
|
3083
|
+
回收超集;**三端注入面**现在可以删掉自己那处宽 `cast`,改用 sdk 8.2.0 的
|
|
3084
|
+
`PersistRuleSelection`(两臂互斥 `{rule, edited?}` ∣ `{batchOfferIndex}`,互斥用 `?: never` 钉在编译期)。
|
|
3085
|
+
|
|
3086
|
+
**`approval_revoke` 的处置(如实记账)**:本包**今天零消费口** —— `isToolApprovalFrame` 只认
|
|
3087
|
+
legacy 的 `tool_approval` / `tool_approval_complete`。新臂与它的兄弟 `approval_request` 同处置:
|
|
3088
|
+
`dropped/unsupported_arm`(**有痕**,经 `reportDroppedFrame` 走宿主 sink),不是静默的
|
|
3089
|
+
`none/not_in_slice`。端**不要**把「撤卡帧没反应」读成「引擎没发」;接那条新卡链是另一批。
|
|
3090
|
+
|
|
3091
|
+
### 22b. B-025 修根:「不再询问」候选窄读器不再手抄上游闭词表
|
|
3092
|
+
|
|
3093
|
+
**病形**(0.43.0 铸、0.57.0 仍在;由 sdk [6464] 两侧源码对读点名,坐标 `toolApprovalWire.ts:1772` / `:209`):
|
|
3094
|
+
|
|
3095
|
+
| 症状 | 0.57.0 实际行为 | 用户看到什么 |
|
|
3096
|
+
|---|---|---|
|
|
3097
|
+
| ① `match` 词表手抄成两员 | 一条合法的 `match:"wildcard"`(或 `"subpath"`)single **整条丢** | 卡上那一格「不再询问」**凭空消失** |
|
|
3098
|
+
| ② batch 成员没有 `directoryRead` 臂 | 一只带 `cd` 段目录只读授权的 batch **整只丢** | 同上,且与该函数自己注释承诺的「逐条丢坏、不整拒」相反 |
|
|
3099
|
+
| ③ 没有 `uncoveredDetail` 座 | design/382 §3.5 的 additive 明细整段读不到 | 「为什么这段还会问」无从渲 |
|
|
3100
|
+
|
|
3101
|
+
**修**=三张闭词表**单源化**到 sdk 8.2.0,本包不再有第二份:
|
|
3102
|
+
|
|
3103
|
+
```ts
|
|
3104
|
+
import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS } from '@sema-agent/client-core'
|
|
3105
|
+
// RULE_OFFER_MATCHES = ['exact', 'prefix', 'wildcard', 'subpath']
|
|
3106
|
+
// RULE_OFFER_BATCH_MEMBER_KINDS = ['command', 'directoryRead']
|
|
3107
|
+
// RULE_OFFER_UNCOVERED_REASONS = ['redirection', 'no_rule_form', 'cap_overflow']
|
|
3108
|
+
```
|
|
3109
|
+
|
|
3110
|
+
🔴 **端拿它们判定,别再手抄字面量** —— 三端与包共用同一份数组对象,词表加员时上游一处改、四处跟。
|
|
3111
|
+
常驻门对 `match` 做**双向全等钉**:表里每个词都必须被读器认下(⊇;手抄的窄表在新词上当场红),
|
|
3112
|
+
构造出来保证在表外的词必须被丢(⊆;读器放宽成「是串就收」时当场红)。
|
|
3113
|
+
|
|
3114
|
+
**batch 成员的新形**(sdk 8.2.0 `RuleOfferBatchMember`,core design/382 §2.3 B3):
|
|
3115
|
+
|
|
3116
|
+
```ts
|
|
3117
|
+
type RuleOfferBatchMember =
|
|
3118
|
+
| { kind: 'command'; rule: string; match: RuleOfferMatch; command: string; segment: string }
|
|
3119
|
+
| { kind: 'directoryRead'; rule: string; directory: string; segment: string }
|
|
3120
|
+
```
|
|
3121
|
+
|
|
3122
|
+
- `directoryRead` = `cd <dir>` 段铸的**目录只读授权**:`rule` 是规范 `Read(//dir/**)` 文本,
|
|
3123
|
+
`directory` 是词法规范绝对目录(渲染座,免二次解析)。本臂**没有** `match`/`command` 两座 ——
|
|
3124
|
+
拿「三元组」窄读器去读它会整只判假,那正是症状②。
|
|
3125
|
+
- 🔴 **成员 `kind` 不识 ⇒ 丢整只 batch,绝不丢单个成员,也绝不丢整卡**(core 的**规范性**降级臂,
|
|
3126
|
+
§20c 第 3 条已引原文)。端不许自行改成成员级容错。
|
|
3127
|
+
- ⚠️ **本包另收一条 pre-B3 兼容臂**:`kind` **缺席**的成员按 `kind:'command'` 归一(server ≥7.46.0
|
|
3128
|
+
到 B3 落地之间铸的成员没有判别位;窄读域只许等于或宽于铸点域)。⇒ **归一形上 `kind` 恒在场**,
|
|
3129
|
+
端拿到的成员永远是判别联合,零分支差异。
|
|
3130
|
+
|
|
3131
|
+
**additive `uncoveredDetail`**(0.58.0 起透传到 `RuleOffer` 的 batch 臂):
|
|
3132
|
+
|
|
3133
|
+
```ts
|
|
3134
|
+
uncoveredDetail?: readonly { segment: string; reason: 'redirection' | 'no_rule_form' | 'cap_overflow' }[]
|
|
3135
|
+
```
|
|
3136
|
+
|
|
3137
|
+
- 🔴 **缺席 ≠ 「没有未覆盖段」**:server 对坏形的座**只丢座不丢批**,老引擎更是压根不铸 ——
|
|
3138
|
+
真源恒是 `uncoveredSegments` 那个 **count**。本包缺席时**不铸空数组**(空数组会被端读成
|
|
3139
|
+
「已确认没有未覆盖段」)。
|
|
3140
|
+
- 行数与 `uncoveredSegments` **不强制相等**(见上一条);坏行**只丢那一行**,坏载体只让**本位**
|
|
3141
|
+
降缺席,**绝不**因为一个 additive 位否决整只 batch。
|
|
3142
|
+
- **行数帽 = 32**,锚在上游铸点域上(server `MAX_UNCOVERED_DETAIL_ROWS`)。⚠️ 未覆盖段数**不受
|
|
3143
|
+
成员帽约束**:一只只有 1 个成员的 batch 可以带 9 条明细(9 个带重定向的段各自 mint 不出规则形)
|
|
3144
|
+
—— 端若自己再设一个更窄的帽,就会把合法明细整座吞掉(本包初稿的 8 正是这么错的,异源对抗复审
|
|
3145
|
+
逮到)。33 行及以上 ⇒ 本位降缺席(与 server 座级预筛同判)。
|
|
3146
|
+
- `segment` 与其余文本座同属 **UNTRUSTED-for-display**。
|
|
3147
|
+
|
|
3148
|
+
**端的迁移动作**(逐条,都很小):
|
|
3149
|
+
1. 对 `RuleOfferMatch` 写穷尽 `switch` 的端:补 `wildcard` / `subpath` 两格(编译红会指给你)。
|
|
3150
|
+
⚠️ 这两格此前在端上是**静默不可达**的(包在读器里就丢掉了),不是「新增的空格子」。
|
|
3151
|
+
2. 渲 batch 成员前先读 `kind`;`directoryRead` 臂渲 `directory`(它没有 `command` 可渲)。
|
|
3152
|
+
3. 想渲「为什么这段还会问」的端:读 `uncoveredDetail`,**缺席就什么都别说**(别渲成 0)。
|
|
3153
|
+
4. 已走卡端口的宿主:`ApprovalCardRequest.ruleOffers` / `.ruleOffersReadOnly` 是同一把读器的产物,
|
|
3154
|
+
新形自动到位;常驻门 ⑨e 段把公面与两条卡腿对同一份新形素材逐字对账。
|
|
3155
|
+
|
|
3156
|
+
### 22c. L-102 下半场:resume 拒绝**文案铸点**上收(壳侧改薄成适配层)
|
|
3157
|
+
|
|
3158
|
+
0.57.0 上收的是**事实读数**(§21 的 `resumeRetryLaterFromError`:命中哪个码 / server 给没给窗 /
|
|
3159
|
+
等一会儿有没有用)。留在壳里的另一半是**人话** —— cli 1.0.x 的 `sema/resumeRefusalCopy.ts`(⚠️ **cli 仓坐标,不是本仓坐标**)自铸了
|
|
3160
|
+
一份判型 + 三句 `·` 分段文案,而 web-client / desktop 要么没有、要么将来会再抄一份。三端各抄一份
|
|
3161
|
+
= 同一次拒绝在三个端上说三句不一样的话,而这三句回答的是**同一个安全问题**:
|
|
3162
|
+
「这次拒绝有没有消费掉我的决定 / 这张卡还能不能再决」。
|
|
3163
|
+
|
|
3164
|
+
**新公面**(`src/resumeRefusalCopy.ts`):
|
|
3165
|
+
|
|
3166
|
+
```ts
|
|
3167
|
+
export const RESUME_REFUSAL_CODES: readonly string[] // 冻结数组,恰两员
|
|
3168
|
+
export interface ResumeRefusalDetail { code: string; retryAfterSec?: number; waitable: boolean }
|
|
3169
|
+
export function resumeRefusalFromError(err: unknown): ResumeRefusalDetail | null
|
|
3170
|
+
export function resumeRefusalContent(detail: ResumeRefusalDetail): string
|
|
3171
|
+
// 同批新增码常量:RESUME_PLACEMENT_MISMATCH(engineErrorCodes.ts)
|
|
3172
|
+
```
|
|
3173
|
+
|
|
3174
|
+
🔴 **两个闭集刻意分家**(端别把它们当同一张表的两个名字):
|
|
3175
|
+
|
|
3176
|
+
| 闭集 | 闭的是什么 | 成员 |
|
|
3177
|
+
|---|---|---|
|
|
3178
|
+
| `RESUME_RETRY_LATER_CODES`(§21,0.57.0) | **server 在哪些码上铸 `retryAfterSec`** ⇒ 答「能不能等」 | `resume.usage_window_exhausted` · `resume.preflight_rejected` |
|
|
3179
|
+
| `RESUME_REFUSAL_CODES`(本节,0.58.0) | **哪些 resume 拒绝有人话可补** ⇒ 答「该对人说什么」 | `resume.placement_mismatch` · `resume.preflight_rejected` |
|
|
3180
|
+
|
|
3181
|
+
两集**交于** `preflight_rejected` 一码、**各有**一个独占成员:
|
|
3182
|
+
- `usage_window_exhausted` 只在前者 —— 它没有专属人话,「你可以等」就是全部信息;
|
|
3183
|
+
- `placement_mismatch` 只在后者 —— server 不给它铸窗,而且**等一会儿对它毫无用处**:出路是
|
|
3184
|
+
「用记录里的那个 root 重来,或干脆不传 `internals.placementRoot` 继承记录值」,是**换参数**
|
|
3185
|
+
不是**等时间**。把它放进时间性闭集 = 让人白等一个永远不会自己好的拒绝。
|
|
3186
|
+
|
|
3187
|
+
🔴 **本口不复制判定**:`preflight_rejected` 的窗与可等性一律**转调** `resumeRetryLaterFromError`,
|
|
3188
|
+
本模块里没有第二个 `retryAfterSec` 窄读器。常驻门用九形入参驱动两口,`waitable` 与 `retryAfterSec`
|
|
3189
|
+
必须**逐字相同**(含「缺席」那一格)。
|
|
3190
|
+
|
|
3191
|
+
**`waitable` 的两种 `false` 落到不同的第三句**(端不必自己再分):
|
|
3192
|
+
|
|
3193
|
+
| 码 | `waitable` | 第三句 |
|
|
3194
|
+
|---|---|---|
|
|
3195
|
+
| `placement_mismatch` | 恒 `false`(等没用) | `Retry with the recorded root, or omit the placement root to inherit it` |
|
|
3196
|
+
| `preflight_rejected` ∧ 无窗 | `false`(**不可判**) | `The engine line above says whether this token can still be redeemed` |
|
|
3197
|
+
| `preflight_rejected` ∧ 有窗 | `true`(正向证据) | `The engine supplied a wait, so this token stays redeemable once the obstacle clears` |
|
|
3198
|
+
|
|
3199
|
+
🔴 第三句由 `waitable` 选,**绝不**由 message 文本选:按上游散文分支正是「上游改一个词、端的判定
|
|
3200
|
+
静默空转」的形。门里把两族原话(terminal / retry_later)都灌进 message 而窗不动,文案必须一字不动。
|
|
3201
|
+
|
|
3202
|
+
⚠️ **`retryAfterSec` 的窄读域比 cli 1.0.x 那份自铸的更窄**(端提货要知道的行为差分):
|
|
3203
|
+
|
|
3204
|
+
| | cli 1.0.x 自铸 | 本口(与 §21 同律) |
|
|
3205
|
+
|---|---|---|
|
|
3206
|
+
| 域 | 有限数 ∧ ≥0 | **整数 ∧ ≥1** |
|
|
3207
|
+
| `0` / 负数 / 小数 | 透传(`0` 会渲成「立刻重试」) | **降缺席**(不渲等待行) |
|
|
3208
|
+
|
|
3209
|
+
server 的铸键逐字是「ms → 秒**向上取整**、**下限 1**」⇒ 真供给里不存在 0 / 负数 / 小数。放行 `0`
|
|
3210
|
+
就是对端说「立刻重试」,而 resume 是 **AT-MOST-ONCE** 的有副作用动作(叫醒 = 真跑一轮)—— 一个 0
|
|
3211
|
+
会把「等一会儿」变成热循环。⇒ 壳提货后这三形上的行为**会变**,这是**修好**不是回归。
|
|
3212
|
+
|
|
3213
|
+
**端该怎么接**(cli 半场 = 1.0.101,本车不改壳):
|
|
3214
|
+
|
|
3215
|
+
1. cli 仓 `sema/resumeRefusalCopy.ts` **改薄成适配层**(或整个删掉,直接从包里 re-export):
|
|
3216
|
+
`RESUME_REFUSAL_CODES` / `resumeRefusalFromError` / `resumeRefusalContent` 三个名字与壳现有的
|
|
3217
|
+
**逐字同名同形**,壳侧的 `ResumeRefusalDetail` 多出一位 `waitable`(additive)。
|
|
3218
|
+
2. cli 仓 `sema/apiErrorSupplement.ts` 的 61-73 行那条**互斥链**改消费包面:`resumeRefusalFromError` 换成
|
|
3219
|
+
包导出的那一个,其余一字不动 —— 段序、互斥序(quota → scenario → resume → device)、
|
|
3220
|
+
`retryAfterHint` 的 `??` 取值口全部照旧。
|
|
3221
|
+
3. 🔴 **等待那一行仍归端渲**:包里的文案**不铸秒数**(写在里面 = 同一个数字上屏两遍);
|
|
3222
|
+
壳继续用 `retryAfterHint(err, quotaDetail?.retryAfterSec ?? resumeRefusal?.retryAfterSec)`。
|
|
3223
|
+
4. 开集兜底一字不动:不认识的码 ⇒ `null` ⇒ 端一个字都不补 ⇒
|
|
3224
|
+
`API Error: <status> <errorCode> · <msg>` 原样上屏。
|
|
3225
|
+
|
|
3226
|
+
**可达性如实登记**(不许把预置说成到货):两码在 server 7.51 当版**结构性不可达**(四条腿都不供
|
|
3227
|
+
`placementRoot`,也没有 `resumePreflight` 座)。本模块与壳那份一样是**预置臂**,不是当版可触发的
|
|
3228
|
+
行为面 —— 收进包是为了「码到货那天三端不至于各说各话」。
|
|
3229
|
+
|
|
3230
|
+
### 22d. 常驻门
|
|
3231
|
+
|
|
3232
|
+
| 门 | 守什么 |
|
|
3233
|
+
|---|---|
|
|
3234
|
+
| `scripts/run-rule-offers-reader-test.mjs` | 段 ⑨ 新增:三张闭词表单源化与再导出逐字相等 · match 词集双向全等钉 · `directoryRead` 臂认回与四座逐字 · pre-B3 成员归一 · 成员 `kind` 不识丢整只(七形)· `uncoveredDetail` 透传/只丢坏行/缺席不铸空 · 卡端口两腿同吃新形 |
|
|
3235
|
+
| `scripts/run-resume-refusal-copy-test.mjs` | 🆕 公面在场 · **两个闭集关系双向钉** · 不复制判定(九形入参两口逐字相同)· `placement_mismatch` 恒无窗恒不可等且带窗也不翻 · 窄读域「整数 ∧ ≥1」· 文案三句由 `waitable` 选而非 message · 负控与坏载体 · 纯函数 |
|
|
3236
|
+
| `scripts/run-approval-frame-keys-test.mjs` | `ruleOffers` 领先登记退役后回到逐元素相等(其余 6 条领先登记仍在) |
|
|
3237
|
+
| `scripts/run-sdk-floor-test.mjs` | 地板 `8.2.0` 与 peer 声明**三位逐位等值**互绑 |
|
|
3238
|
+
| `scripts/run-public-surface-test.mjs` | peer 地板 / README 三处逐字核 + 公面导出基线 **821 → 828** |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/client-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.0",
|
|
4
4
|
"description": "Client-side session runtime shared by every sema human client (TUI / web / desktop): sema wire frames (AgentEvent) -> CC session vocabulary (SDKMessage) with dual-plane output (transcript/chrome), deterministic transcript ids, lane discipline as a type, and the notification/dedup ledgers. Every CC-skin shape is collected here so the wire itself stays neutral. Renamed from @sema-agent/wire-cc-adapter (0.1.x).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@sema-agent/agent-types": ">=0.2.0",
|
|
34
|
-
"@sema-agent/sdk": ">=
|
|
34
|
+
"@sema-agent/sdk": ">=8.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@sema-agent/agent-types": "^0.2.0",
|
|
38
38
|
"@sema-agent/core": "~7.3.0",
|
|
39
|
-
"@sema-agent/sdk": "^
|
|
39
|
+
"@sema-agent/sdk": "^8.2.0",
|
|
40
40
|
"esbuild": "^0.27.4",
|
|
41
41
|
"typescript": "^6.0.2"
|
|
42
42
|
}
|