@sema-agent/client-core 0.63.2 → 0.64.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 +90 -0
- package/README.md +4 -2
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +10 -0
- package/dist/adapter/downstream/eventToSdkMessage.js +15 -1
- package/dist/autoModeUnavailable.d.ts +47 -0
- package/dist/autoModeUnavailable.js +63 -0
- package/dist/classifierStatus.d.ts +99 -0
- package/dist/classifierStatus.js +179 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +10 -0
- package/dist/modelCapabilityProbe.d.ts +248 -0
- package/dist/modelCapabilityProbe.js +291 -0
- package/docs/INTEGRATION-CLIENTS.md +317 -10
- package/package.json +2 -1
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
| peer:wire 契约 | `@sema-agent/sdk` **>=8.4.0**(value-level,非 type-only;**0.60.0 抬版**,四条硬理由见 §24a 与 `scripts/run-sdk-floor-test.mjs` 的 `FLOOR` 注;上一次是 0.59.0 的 `>=8.3.0`)。🔴 支持窗同批收到 **engine ≥7.64.0**:sdk 8.4.0 与 7.63.0 及以前的 wire **不同窗** | `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
|
+
| 公开导出面 | **918** 个运行期符号(+ 44 个测试钩;= 工作树当下的值 = **0.64.0 件①+件② 十三件 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`/`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.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`(**918** 项)。
|
|
115
115
|
> 本节**不逐名抄**,只给「域 → 承重导出 → 用途 → 实现锚」。承重导出 = 一个端为了让这个域干活
|
|
116
116
|
> **必须**直接调到的那几个符号;其余是它们的类型、变体与辅助位。
|
|
117
117
|
> 单一入口:`import { … } from '@sema-agent/client-core'`(`exports` 只有 `.` 一个;
|
|
@@ -135,12 +135,12 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
135
135
|
`WorkflowsGateUnknownDenial` 四形**不在**基线里,`src/selfOrchestrationDenial.ts` 对基线贡献
|
|
136
136
|
**4** 项运行期导出(三个函数 + `SELF_ORCHESTRATION_RETRY_WITHOUT`)。
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
918 项的内部构成(帮助端估读表大小):**278** 项是 `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 域,逐域计数之和 = 918)
|
|
144
144
|
|
|
145
145
|
| # | 域 | 名数 | 承重导出 | 用途 | 实现锚 |
|
|
146
146
|
|---|---|---|---|---|---|
|
|
@@ -152,9 +152,9 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
152
152
|
| 6 | **请求装配(上行唯一构造口)** | 8 | `buildTaskRequest` · `REQUEST_FIELD_MATRIX` · `unregisteredRequestKeys` · `applyLiveRequestDefaults` · `taskNotificationToPrintFrame` | 两条车道(`interactive`/`print`)出站请求的**唯一**构造器;`unregisteredRequestKeys` 是可执行门 —— 端偷带一个未登记键上 wire 就红 | `src/request/taskRequest.ts`、`src/request/printNotification.ts` |
|
|
153
153
|
| 7 | **通知与 outstanding 台账** | 51 | `installNotificationQueuePort` · `normalizeTaskNotification` · `taskNotificationDedupKeyFromWire` · `registerOutstandingBgTask` / `registerOutstandingWorkflowRun` · `notificationQueuePortMisses` · `subscribeOutstandingWorkflows` · `outstandingDeliverableWorkflowCount` | `task_notification` 归一 + 去重 + 投递进宿主命令队列的**一把闸**;`outstandingDeliverableWorkflowCount()` 是 headless `-p` 的**退出门** · `classifyPeerNotification` / `renderPeerFrameTranscriptText` / `parsePeerFrameText` / `peerFrameDisplayName` + 三张闭集表(design/385,0.54.0:同一条 `task_notification` 车道上三条**引擎注入帧**的类型化投影 —— 判别位=载体在场而非 summary 文本,详见 §17) | `src/notifications.ts`(11 个 module 台账) |
|
|
154
154
|
| 8 | **工具结果卡** | 25 | `structuredToToolUseResult` · `readAsyncLaunchedAgentReceipt` · `wireOutputToBody` · `parseModelFacingBash` · `getPatchFromContents` · `toolEndResultToUserFrame` · `flattenToolOutput` | 铸端要渲的 `tool_result` 卡体,含客户端 diff hunk(唯一 runtime dep 的用处) | `src/toolResult.ts`、`src/printToolResultFrame.ts`、`src/diff/patch.ts` |
|
|
155
|
-
| 9 | **能力/旋钮 wire 门族** |
|
|
155
|
+
| 9 | **能力/旋钮 wire 门族** | 96 | `projectAgentsForWire` / `awaitTaskAgentsWire` · `hooksForWire` · `mcpConfigsToSpecs` · `ultracodeForRequest` · `resolveWebSearch` + `buildWebSearchEnv` · `attachmentsForRequest` · `projectEffectiveBody` · `classifySelfOrchestrationRefusal` / `stripSelfOrchestrationIntent` / `projectWorkflowsGate` / `SELF_ORCHESTRATION_RETRY_WITHOUT`(S-81,server 7.57.0:上面两条 stamp 腿的**背面** —— 半配置多租户形态下 server 把带 `selfOrchestration` / `settings.ultracode` 的提交 501 拒掉,判型/去键/caps 闸三处都是判定不是文案,详见 §13) · `engineCapsGeneration`(0.60.0,异源对抗复审 [medium] 逼出:caps 探测的**当代号**读口 —— 代际闸在 probe **返回之后**才跑,而宿主的读面 tee 是在 probe **内部**落地的 ⇒ 一次慢的旧探测能把上一台引擎的读数写回来。宿主在**起探测那一刻**抓号、tee 时交回 `{generation}`,陈旧那一发整只丢掉;不传 = 逐字节同行为,详见 §24e)| 逐功能的「引擎有没有这个能力 + 这个字段怎么上 wire」投影器,由 `buildTaskRequest` 组装。🔴 `hooksForWire()` 是 **fail-closed**:无 `SettingsPort` ⇒ 返回 `undefined`(信任门,不是取值) | 17 个 `src/*WireCaps.ts` + `src/scratchpadWireCaps.ts`、`src/hooksWireCaps.ts`、`src/goalStopHook.ts`、`src/websearch/searchProviderPresets.ts`、`src/selfOrchestrationDenial.ts`(S-81 拒绝判定层) |
|
|
156
156
|
| 10 | **headless / 部署旋钮 wire** | 61 | `parseSandboxArgv` / `sandboxRequestFields` · `parseLimitsArgv` / `limitsForPrint` · `resolveHeadlessFinalVerify` · `resolveHeadlessPermissionMode` · `resolveHeadlessInteractiveTools` · `armDetachCancel` + `detachCancelArm` + `isDetachArmed` · `withHeadlessR1Reconnect` | `-p`/headless 车道的 env+argv 旋钮。🔴 `detachWire` 是**拆**的补偿:判定与 cancel-arm 台账在库,信号路径的裸 fetch 留宿主(`detachCancelArm()` 是取件口) | `src/sandboxWire.ts`、`scenarioWire.ts`、`finalVerifyWire.ts`、`limitsWire.ts`、`interactiveToolsWire.ts`、`headlessPermissionModeWire.ts`、`headlessReconnectWire.ts`、`detachWire.ts` |
|
|
157
|
-
| 11 | **模型目录与预算** |
|
|
157
|
+
| 11 | **模型目录与预算** | 76 | `resolveModelCatalog` · `loadCatalogWithSources` · `PROVIDER_PRESETS` / `MODEL_FAMILIES` · `defaultMaxTokensFor` · `getLiveModelCatalog` / `setLiveModelCatalogRefresher` · `providerAuthMethods` / `beginDeviceCodeAuth` · `providerCatalogRows` / `providerCatalogRowDetail` / `providerPresetById`(#244 F4 族D A-028.17:46 家表的规范折表层 —— 全表不重排、诚实缺席「model id typed in」,cli 目录/web 向导同一份折表)· `TIER_ORDER` / `CC_TIER_ALIASES` / `isTier` / `resolveTierBinding`(A-028.18:档位词表+校验+fail-open 降档派生单源;settings 存储归宿主)· `resolveEntryVision` / `computeDeleteBlockers` / `computeDeleteWarnings`(0.38.0 #318 件③ 上收:Model Hub 供给面的三端公共判定 —— vision 生效值+来源三态、删除断链核(拒删+指路)、删除降级后果(照删但必说)。**零 IO**,读盘那半场留各端;`doc === null` 的两义在调用方分流) | 三层 provider 目录解析(线上 URL → 包内预设 → 用户覆盖)+ per-model `maxTokens` 封顶。线上腿需注入 `CatalogFetchJson`,缺席 ⇒ 整条不启用(`online.reason='no-fetch-port'`);缓存落盘经 `CatalogCachePort` | `src/model/{catalog,catalogLoader,providerAuth,providerPresets,providerCatalog,tierVocabulary}.ts`、`src/liveModelCatalog.ts`、`src/modelBudgetRule.ts`、`src/sessionModelLatch.ts`、`src/effortWire.ts` |
|
|
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 契约** | 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 桌面壳里的符号只会零命中,而零命中在这里**既不证真也不证伪**。复核这些断言**不得**拿本仓语料当反证 |
|
|
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` |
|
|
@@ -4774,10 +4774,20 @@ core 双向对账)。**候上游导出即整只退役改成从 sdk 取**。
|
|
|
4774
4774
|
- **G-19**:让分类器**答了但答在契约之外**(parse_error)—— 卡上**不出现**「分类器跑不了」那一族的
|
|
4775
4775
|
任何一句(引擎在这一形上根本不盖那一格);而**不武装** auto 模式跑同样的调用 —— 卡上同样没有那一行
|
|
4776
4776
|
(缺席 ≠「分类器跑成了」)。
|
|
4777
|
-
- **G-20**(0.63.1 订正判据口径:park 落在**腿**上不落在 run
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4777
|
+
- **G-20**(0.63.1 订正判据口径:park 落在**腿**上不落在 run 上;🆕 **0.64.0 再订正:显示词是
|
|
4778
|
+
二次派生的,别去 agent 行上找它**)——让一条 workflow **agent 腿**停在审批门上,判据是**两条**:
|
|
4779
|
+
① 投影产物那一行的 `agent.state` **逐字是 `parked`**;② 把那一行喂进显示态派生
|
|
4780
|
+
`agentDisplayStatus(agent, false)`(第二参 = run 是否还活跃;这里刻意传 `false`)得到的**也**逐字是
|
|
4781
|
+
`parked` —— 不是 `running`,也不是 `interrupted`(那条腿 park 之后整只 run 就收在 `failed`,所以
|
|
4782
|
+
「run 不活跃 ⇒ interrupted」那条老臂会抢答,②的第二参传 `false` 就是为了把那条老臂放到台面上)。
|
|
4783
|
+
批掉那张卡之后两条判据**都不再**是 `parked`。反向:随便造一个这一端没见过的状态词,②仍渲成在跑
|
|
4784
|
+
(开集兜底没被改宽)。
|
|
4785
|
+
🔴 **订正的理由(test [6783] G-1/G-2 提的,亲核属实)**:原文写的是「监视器里那一行的状态词逐字是
|
|
4786
|
+
`parked`」,而**投影产物的 agent 行上压根没有 `displayStatus` 这一格** —— `displayStatus` 是
|
|
4787
|
+
service detail **入参**上的键,投影把它折进 `state` 之后就不再出现在产物上;显示词由
|
|
4788
|
+
`agentDisplayStatus(agent, workflowActive)` **二次派生**。按原文字面去读 `row.displayStatus` 的 test
|
|
4789
|
+
永远读到 `undefined`,于是这条判据要么恒红要么被写成别的东西。机读锚:
|
|
4790
|
+
`scripts/run-client-core-pure-test.mjs` G-20 段新增一格,逐字断言那一行**没有** `displayStatus`。
|
|
4781
4791
|
|
|
4782
4792
|
---
|
|
4783
4793
|
|
|
@@ -4798,3 +4808,300 @@ core 双向对账)。**候上游导出即整只退役改成从 sdk 取**。
|
|
|
4798
4808
|
| `scripts/run-integration-doc-freshness-test.mjs` | 本节新增坐标在盘 + 入库;§0a/§2/§2b 计数与基线等值;🆕 **①c**(0.63.1):签名块里的**表长数字** ⟷ 源码那张表的真实成员数(TS AST 取 `Object.freeze([...])` 的元素个数)。档里一律写阿拉伯数字 —— 中文数词读不出来的门等于没有门,抽取器读不出即判工具红 |
|
|
4799
4809
|
|
|
4800
4810
|
---
|
|
4811
|
+
|
|
4812
|
+
## §28 🆕 0.64.0 内容批(模型思考能力探测 · 分类器状态面 · `DecisionReason` uplift 锚 · G-20 判据订正 · 落库前提门)
|
|
4813
|
+
|
|
4814
|
+
### 28a. 本节速览
|
|
4815
|
+
|
|
4816
|
+
| # | 件 | 面 | 破坏性 | 端要做什么 |
|
|
4817
|
+
|---|---|---|---|---|
|
|
4818
|
+
| ① | 模型思考能力探测(`src/modelCapabilityProbe.ts`) | 新 9 导出 | 无 | 模型目录页/向导加一个「探测」动作;**网络那半场端自己实现**并作为 `send` 注入 |
|
|
4819
|
+
| ② | auto 分类器状态面(`src/classifierStatus.ts` + `src/autoModeUnavailable.ts` 加员) | 新 4 导出 + wire additive 一键 | 无 | 诊断行 / 模型设置页 / 权限卡状态栏改接铸点;`breaker` 缺席 = 老引擎 |
|
|
4820
|
+
| ③ | `DecisionReason` +`read_only` 的 uplift 锚 | **零导出** | 无 | **端无事可做**;上游镜像到货时本包先红,那时才有铸点 |
|
|
4821
|
+
| ④ | §27j 的 G-20 判据口径订正 | 文档 + 机读锚 | 无 | test 侧改判据;端零改 |
|
|
4822
|
+
| ⑤ | devDep 抬 `@sema-agent/settings-schema ^1.10.0` + 落库前提门 | 门 | 无 | **端无事可做**(devDep,不进 peer、不出包) |
|
|
4823
|
+
|
|
4824
|
+
🔴 **本批本包侧全部 additive、零删除**:`peerDependencies` 一字未动(仍 `@sema-agent/sdk >=8.8.0` /
|
|
4825
|
+
`@sema-agent/agent-types >=0.2.0`)。唯一的 wire 加员是 `_sema_autoMode` 段上的可选一键 `breaker`,
|
|
4826
|
+
缺席即老引擎,老端一个字节都不受影响。
|
|
4827
|
+
|
|
4828
|
+
---
|
|
4829
|
+
|
|
4830
|
+
### 28b. ① 模型「会不会思考、关不关得掉」的探测
|
|
4831
|
+
|
|
4832
|
+
**它答的是哪一问**:一台 vLLM/Qwen 类网关**默认就在思考**,而「关掉」各家拼法不同 —— 有的读顶层
|
|
4833
|
+
`enable_thinking`,有的只认模板参数 `chat_template_kwargs.enable_thinking`,有的要
|
|
4834
|
+
`thinking:{type:"disabled"}`。目录条目上 `compat.thinkingFormat` 那一格就是告诉引擎该用哪一种,
|
|
4835
|
+
而**没有人能靠看一眼型号名答出它是哪一种**。⇒ 把这一问变成一次可复现的探测。
|
|
4836
|
+
|
|
4837
|
+
**签名**
|
|
4838
|
+
|
|
4839
|
+
```ts
|
|
4840
|
+
THINKING_FORMATS: readonly string[] // 7 词,引擎闭集的镜像,顺序同源
|
|
4841
|
+
THINKING_DISABLE_PROBE_ORDER: readonly string[] // 4 词,试关序(公面承诺)
|
|
4842
|
+
MODEL_PROBE_VERDICTS: readonly string[] // 4 词
|
|
4843
|
+
THINKING_FORMAT_WIRE_TWINS: Readonly<Record<string, string>>
|
|
4844
|
+
PROBE_PROMPT: string
|
|
4845
|
+
PROBE_MAX_TOKENS: number
|
|
4846
|
+
|
|
4847
|
+
probeRequestBody(entry: ModelProbeEntry, format?: string, opts?: { reasoningEffort?: string })
|
|
4848
|
+
: OpenAICompletionsProbeBody
|
|
4849
|
+
probeModelCapability(entry: ModelProbeEntry, send: ProbeSend): Promise<ModelProbeResult>
|
|
4850
|
+
applyProbeToEntry<T extends { reasoning?: boolean; compat?: unknown }>(entry: T, result: ModelProbeResult): T
|
|
4851
|
+
```
|
|
4852
|
+
|
|
4853
|
+
**输入形(端要实现的那一只)**
|
|
4854
|
+
|
|
4855
|
+
```ts
|
|
4856
|
+
type ProbeSend = (body: OpenAICompletionsProbeBody) => Promise<{
|
|
4857
|
+
content: string // choices[0].message.content;没有 ⇒ 空串
|
|
4858
|
+
reasoningContent?: string // choices[0].message.reasoning_content;缺席 = 这台网关没给这一通道
|
|
4859
|
+
finishReason?: string // choices[0].finish_reason 原样
|
|
4860
|
+
status?: number // HTTP 状态码;缺席 = 端没报(不是 200)
|
|
4861
|
+
}>
|
|
4862
|
+
```
|
|
4863
|
+
|
|
4864
|
+
🔴 **包内零网络**:鉴权、代理、超时、重试全在端手里;本包零 `fetch`、零 URL、零凭证键(门有源码级
|
|
4865
|
+
反向钉)。**抛错是合法回答** —— 端不必自己吞,本包按它发生在哪一发决定判词。
|
|
4866
|
+
|
|
4867
|
+
**步骤与判词**
|
|
4868
|
+
|
|
4869
|
+
1. baseline:最小请求(题面 `PROBE_PROMPT`,`max_tokens` = `PROBE_MAX_TOKENS`),不带任何方言位。
|
|
4870
|
+
· **没有证据力** —— 被拒(抛错 / 状态码 ≥400),**或**一条「零思考 + 正文也空」的合法回执
|
|
4871
|
+
(`{content:'', finishReason:'length', status:200}`,被截断 / 网关吞了正文)⇒ `inconclusive`,
|
|
4872
|
+
**结果里压根没有 `reasoning` 这一格**;
|
|
4873
|
+
· **正面证据**「正文非空且零思考」⇒ `no_reasoning`,**收工**(一次往返都不多烧)。
|
|
4874
|
+
2. 会思考 ⇒ 按 `THINKING_DISABLE_PROBE_ORDER` 逐臂试关,第一个**「零思考 且 正文非空」**的拼法
|
|
4875
|
+
即答案 ⇒ `disabled_via`,收工。
|
|
4876
|
+
3. 四臂都没关掉:**每一臂都给出正面反证**(逐臂都看见思考还开着)⇒ `cannot_disable`,并补一发
|
|
4877
|
+
`reasoning_effort:"low"` 记下这台网关**收不收**低档旋钮(`evidence.lowEffortAccepted`);
|
|
4878
|
+
🔴 **任一臂没有证据力**(被拒,**或**空回执)⇒ `inconclusive` —— 那一种拼法**没被证伪**,
|
|
4879
|
+
而 `cannot_disable` 是**删掉**条目上原有 `thinkingFormat` 的唯一触发,让一次偶发的超时或空回执
|
|
4880
|
+
去抹掉一份正确配置是本探针能犯的最贵的错。证据里逐臂留着每一发的长度与状态,端可以据此
|
|
4881
|
+
只重试那一臂。
|
|
4882
|
+
|
|
4883
|
+
🔴 **贯穿三步的一条**:「**没看见思考**」不等于「**思考关掉了**」。每一发都先判**证据力**三态
|
|
4884
|
+
(`off` 正面看见关掉了 / `on` 正面看见还开着 / `moot` 什么都没证明),判词只建在正面证据上 ——
|
|
4885
|
+
把一条空回执读成任何一边,都会让一次偶发的网关抖动去覆盖一份正确的持久配置。
|
|
4886
|
+
`moot` 有**四个同形**(两轮异源复审各抓出一个,逐个补进来的):被拒(抛错 / 4xx)/ 正文空 /
|
|
4887
|
+
正文**纯空白**(只差一个空格就能骗过「长度 > 0」)/ 这一发**被截断了**(`finish_reason: "length"`
|
|
4888
|
+
—— 本探针的 `max_tokens` 只有 64,一台在思考的网关很容易先烧完额度再被截掉,那时思考通道可能一个字
|
|
4889
|
+
都没送出来)。⚠️ 截断只否掉 `off` 那一边:一发**已经吐出思考**的截断回执照旧是 `on`。
|
|
4890
|
+
`evidence` 因此把**原始** `contentLen` 与判据用的 `hasText` 分成两格 —— 一格当两用会逼着判据去读一个
|
|
4891
|
+
它不该读的量。
|
|
4892
|
+
|
|
4893
|
+
**缺席语义(逐条,别读成更弱的话)**
|
|
4894
|
+
|
|
4895
|
+
| 形 | 语义 | 🔴 不许渲成 |
|
|
4896
|
+
|---|---|---|
|
|
4897
|
+
| `verdict === 'inconclusive'` 且 `reasoning` 这一格**不在** | baseline 没有证据力(被拒,**或**空回执) | 「这个模型不会思考」 |
|
|
4898
|
+
| `verdict === 'inconclusive'` 且 `reasoning === true` | 会思考,但**关不关得掉问不出来**(baseline 有证据力,而**至少一臂**被拒或空回执) | 「关不掉」 |
|
|
4899
|
+
| `verdict === 'cannot_disable'`,`thinkingFormat` **缺席** | 四种拼法**逐臂给出正面反证**、都关不掉 | 挑一个词写上去 |
|
|
4900
|
+
| `evidence.lowEffortAccepted === true` | 低档旋钮**被收下了** | 「思考真的变少了」(本探针量不到) |
|
|
4901
|
+
| `evidence.lowEffortAccepted` 缺席 | **没做**这一发(没走到 `cannot_disable`) | `false` |
|
|
4902
|
+
|
|
4903
|
+
**`applyProbeToEntry` 的三条纪律**
|
|
4904
|
+
|
|
4905
|
+
- 只写 `reasoning` 与 `compat.thinkingFormat` 两键,条目上别的键(`name`/`tier`/`cost`/`extraBody`/
|
|
4906
|
+
`compat` 里别的位)逐字原样带过去;**入参一个字节不动**(纯函数)。
|
|
4907
|
+
- 🔴 `inconclusive` ⇒ **原样退回同一只条目**(`===` 成立),一个键都不写。
|
|
4908
|
+
- 🔴 `cannot_disable` ⇒ 把条目上原有的 `thinkingFormat` **删掉**。留着的后果是双重的:引擎会继续发
|
|
4909
|
+
一种**已被实测证伪**的拼法,而目录/卡面照那一格渲一句「思考已关」的假话。
|
|
4910
|
+
|
|
4911
|
+
**🔴 试关序是公面承诺,不是实现细节**:每多试一种拼法就是对那台网关多烧一次真钱与真时延。
|
|
4912
|
+
模板形排第一,是因为观测到的真实序列是「顶层形关不掉、且把正文答空」;`openai` 不占一臂(它的关
|
|
4913
|
+
拼法要一份探针没有的 `thinkingLevelMap.off`,发出去等于把 baseline 那一发原样再烧一次);
|
|
4914
|
+
`zai`≡`qwen`、`together`≡`openrouter` 在这条轴上**请求体逐字节相同**,不各占一臂
|
|
4915
|
+
(对照表 `THINKING_FORMAT_WIRE_TWINS`)。
|
|
4916
|
+
|
|
4917
|
+
**⚠️ 方言闭集的真源是引擎,不是 settings-schema**:`ModelEntry.compat` 在 settings-schema 1.10.0 上是
|
|
4918
|
+
**parse-transparent 的 `z.unknown()`**,其 JSDoc 逐字声明它刻意不复述词表(「the SHAPE and the
|
|
4919
|
+
VOCABULARY … are the consuming side's single point」)。真源是 core 的
|
|
4920
|
+
`OpenAICompletionsCompat.thinkingFormat`,本包按真字节镜像 + 常驻门双向对账。
|
|
4921
|
+
|
|
4922
|
+
---
|
|
4923
|
+
|
|
4924
|
+
### 28c. ② auto 分类器的**状态面**(与审批卡那一问分家)
|
|
4925
|
+
|
|
4926
|
+
**两问不是同一问**:审批卡答「这一刻**为什么在问我**」(一次性的、就这只 ask,0.63.0 件⑧ 已有);
|
|
4927
|
+
诊断行 / 模型设置页 / 权限卡状态栏答「这个**会话**上分类器现在是什么状态」。两问的下一步不同,
|
|
4928
|
+
所以句子分家 —— 门里有一条反向钉守着两张面的句子**零重合**。
|
|
4929
|
+
|
|
4930
|
+
**签名**
|
|
4931
|
+
|
|
4932
|
+
```ts
|
|
4933
|
+
CLASSIFIER_STATUS_STATES: readonly string[] // 3 词:available / breaker_open / unavailable_this_round
|
|
4934
|
+
|
|
4935
|
+
classifierBreakerOf(autoMode: unknown): ClassifierBreakerView | undefined
|
|
4936
|
+
classifierStatusOf(autoMode: unknown, ask?: unknown): ClassifierStatusView | undefined
|
|
4937
|
+
classifierStatusDetail(view: ClassifierStatusView): string
|
|
4938
|
+
|
|
4939
|
+
interface ClassifierBreakerView { openedAtMs: number; lastCause: string; failures: number; runId?: string }
|
|
4940
|
+
interface ClassifierStatusView { state: string; breaker?: ClassifierBreakerView; cause?: string }
|
|
4941
|
+
```
|
|
4942
|
+
|
|
4943
|
+
**wire 加员**:`WiringManifestAutoMode` 上 additive 一键 `breaker`(core 7.10.0 `AutoModeBreakerTrip`
|
|
4944
|
+
的四键;**server ≥7.69.0 才投**),随 `_sema_autoMode` 段过帧。
|
|
4945
|
+
|
|
4946
|
+
**输入形**:`autoMode` 吃 `wiring_manifest` 的 `autoMode` 段(投影后的或原始的都吃,本函数自己窄读);
|
|
4947
|
+
`ask` 吃一只 ask 或 durable park 行的 `tool_approval` 载荷(与 `classifierUnavailableOf` 同一只读器)。
|
|
4948
|
+
|
|
4949
|
+
**缺席语义**
|
|
4950
|
+
|
|
4951
|
+
| 形 | 语义 | 🔴 不许渲成 |
|
|
4952
|
+
|---|---|---|
|
|
4953
|
+
| `breaker` 键**不在场** | **没有可用的熔断记录** —— 四种成因不可分辨:①这个会话从没熔断过 ②账本(有界 FIFO)把它淘汰了 ③这一次是 standalone prepare(账本压根没接上)④server <7.69.0 不投这一段 | 「没熔断过」;也**别**读成「一定是老引擎」 |
|
|
4954
|
+
| `classifierStatusOf(...) === undefined` | 这一端说不出分类器的健康状况(段缺席;或没武装、且既无本轮事实也无历史记录) | `available` |
|
|
4955
|
+
| `runId` 缺席 | 引擎没报是哪条腿合的闩 | 编一个 |
|
|
4956
|
+
| 熔断记录三键(`openedAtMs`/`lastCause`/`failures`)缺任一 | **整段**判缺席(半句没有出口的话不如不渲) | 半句 |
|
|
4957
|
+
|
|
4958
|
+
**四条承重(照抄进端的复审清单)**
|
|
4959
|
+
|
|
4960
|
+
- 🔴 **熔断记录与 `armed`/`reason` 之间零互证**:闩合上之后被闩住的那条腿**不再把 auto 意图传给后续
|
|
4961
|
+
腿**,于是后续腿读作 `no_intent` 而**不是** `latch_open` —— `{armed:false, reason:"no_intent",
|
|
4962
|
+
breaker:{…}}` 是**最常见**的合法形。补一条「有 breaker 就该 latch_open」的互证会把真读数整段判没。
|
|
4963
|
+
- 🔴 **优先序:本轮事实 > 这条腿的 `armed` > 历史熔断记录**。判据锚在**真正决定「分类器现在跑不跑」
|
|
4964
|
+
的量**上,而那个量是**这条腿的 `armed`**,不是账本里有没有一条旧记录 —— core 顶注逐字:
|
|
4965
|
+
「A decider is minted per run (its latch is a RUN fact) … the ledger below carries the most recent one
|
|
4966
|
+
forward per session」⇒ 同一会话的**后一条腿完全可以重新武装**(新 decider 的闩由构造关着),而账本
|
|
4967
|
+
仍把那次旧 trip 带着。`armed === true` 时判 `breaker_open`,就是把一个**正在放行**的分类器显示成
|
|
4968
|
+
已经关掉了。
|
|
4969
|
+
- 🔴 **历史记录不因为被压下去就丢掉**:任何一态上 `view.breaker` 都照带。`available` 因此有**两句**
|
|
4970
|
+
措辞 —— 「在跑」与「在跑、但这个会话上**曾经**熔断过」是两条不同的下一步(后者要去看那次失败为什么
|
|
4971
|
+
发生,它随时可能再来一次)。
|
|
4972
|
+
- 🔴 **别渲「不新开会话就恢复不了」**:闩是**一条腿**的事实,后一条腿会铸一只新的、闩关着的
|
|
4973
|
+
decider ⇒ 那句话是编的。本包的两句熔断措辞都只说真的发生过的事(什么时候、因为什么、连着几次)。
|
|
4974
|
+
- 🔴 **`lastCause` 开集读**:词的属主在 core;端按具名词写的 `switch` **必须带 `default`**,
|
|
4975
|
+
或者直接用 `classifierStatusDetail()`(它自带兜底句,原样带上那个词供运维追问上游)。
|
|
4976
|
+
- 🔴 **时刻是 UTC ISO**:时区是宿主的事。端要本地化就拿 `view.breaker.openedAtMs` **自己**格式化,
|
|
4977
|
+
别去改那句话 —— 而 `openedAtMs` 已由窄读收进 `Date` 的真实值域(一个 wire 上的 `1e20` 会让
|
|
4978
|
+
`toISOString()` 当场 `RangeError`,那是整屏崩不是一行渲不出)。
|
|
4979
|
+
|
|
4980
|
+
---
|
|
4981
|
+
|
|
4982
|
+
### 28d. ③ `DecisionReason` +`read_only`:**候 sdk**(本批零导出)
|
|
4983
|
+
|
|
4984
|
+
`gateVocabulary.ts` 今天承载的是 `DeniedBy`(谁拒的)与 `AskOrigin`(谁问的)两张表。
|
|
4985
|
+
`DecisionReason`(**为什么这么判**)是**第三个**语义面,本包一张表都还没有。
|
|
4986
|
+
|
|
4987
|
+
0.64.0 亲验的事实(别只信版本号):
|
|
4988
|
+
|
|
4989
|
+
- 实装 **sdk 8.8.0** 全树**零** `DecisionReason` —— 那个联合上游至今没镜像给 sdk;
|
|
4990
|
+
- 实装 **core 7.10.0** 的 `DECISION_REASONS` 是**九词**(rule / mode / hook / safety / classifier /
|
|
4991
|
+
persisted_rule / sandbox / org_rule / org_unavailable),**没有** `read_only`;npm 上
|
|
4992
|
+
`@sema-agent/core` 的 latest 就是 7.10.0。
|
|
4993
|
+
|
|
4994
|
+
⇒ 本批**不自铸**那张表(下游自铸的联合在上游镜像出来的那天就是第二个会漂的源,与
|
|
4995
|
+
`permissionRuleIssue.ts` 的「候上游导出即换」同款处置),改为在
|
|
4996
|
+
`scripts/run-gate-vocabulary-test.mjs` 的 D 段**两端各断言一次缺席**:sdk 那端(镜像到货时红)与
|
|
4997
|
+
devDep core 那端(提货批抬版时先红)。**红的那一刻 = 该铸一句「allowed: read-only shell command」
|
|
4998
|
+
并给三端一个铸点的施工令**,不是删锚的理由。
|
|
4999
|
+
|
|
5000
|
+
🔴 **端本批无事可做**:在那句话有铸点之前,端**别自拼**一句 —— 那正是这条锚要避免的第二个源。
|
|
5001
|
+
|
|
5002
|
+
---
|
|
5003
|
+
|
|
5004
|
+
### 28e. ④⑤ 判据订正与依赖
|
|
5005
|
+
|
|
5006
|
+
- **④ §27j 的 G-20**:判据口径已按 test [6783] G-1/G-2 订正(见 §27j 该条)。要点:
|
|
5007
|
+
`displayStatus` **不在** `projectWorkflowRun` 的 agent 行上,显示词由
|
|
5008
|
+
`agentDisplayStatus(agent, workflowActive)` **二次派生**。机读锚在
|
|
5009
|
+
`scripts/run-client-core-pure-test.mjs` 的 G-20 段。**端零改**。
|
|
5010
|
+
- **⑤ devDep `@sema-agent/settings-schema ^1.10.0`**:**不进 peer**(本包运行期与 `.d.ts` 都不引用它),
|
|
5011
|
+
**不出包**。它买的是一条跨包前提门 —— `applyProbeToEntry` 的产物要经 `ModelEntry` 的 zod 解析落库,
|
|
5012
|
+
而那一格哪天从 parse-transparent 改成窄类型,探针写的 `thinkingFormat` 会在落库那一刻被**静默剥掉**
|
|
5013
|
+
(三端看不到任何错误,长得就像「探测没跑」)。门里真跑一次那只解析器拿真产物对照,并用两个
|
|
5014
|
+
「必须被拒」的形证明它不是一台「什么都收」的解析器。**端无事可做。**
|
|
5015
|
+
|
|
5016
|
+
---
|
|
5017
|
+
|
|
5018
|
+
### 28f. 🔴 三端换装清单(逐件坐标)
|
|
5019
|
+
|
|
5020
|
+
| 件 | 壳(cli) | web-client | desktop |
|
|
5021
|
+
|---|---|---|---|
|
|
5022
|
+
| ① 探针 | 模型目录页/新增模型向导加一个「探测思考能力」动作:端实现 `send`(读自己那条凭证轨,**绝不**把 key 交进本包)→ `probeModelCapability(entry, send)` → 拿 `verdict` 渲结果 → 用户确认后 `applyProbeToEntry(entry, result)` 落库。`doctor` 的模型段可复用同一只结论渲一行。🔴 `inconclusive` 那一格**必须**渲成「这次没探到」而不是「不会思考」;`cannot_disable` 渲「会思考、当前关不掉;这个席位将按 low 档运行」(clay 裁),并读 `evidence.lowEffortAccepted` 决定那半句说不说得下去 | 模型设置页同左;`send` 走浏览器 `fetch`(注意 CORS 与代理由部署决定,失败照 `inconclusive` 渲) | 同 web-client;`send` 走主进程那条腿,渲染进程只拿结论 |
|
|
5023
|
+
| ② 状态面 | `doctor` 的 Permissions 段加**一行** `classifierStatusDetail(classifierStatusOf(autoMode, ask))`;`undefined` ⇒ **整行不渲**(不是渲「正常」)。权限卡的状态栏同一只铸点。🔴 `_sema_autoMode.breaker` 缺席 = 老引擎,别渲「没熔断过」 | 模型设置页/权限卡同左 | 同左 |
|
|
5024
|
+
| ③ uplift 锚 | 无 | 无 | 无 |
|
|
5025
|
+
| ④ G-20 订正 | 无(test 侧改判据) | 无 | 无 |
|
|
5026
|
+
| ⑤ 落库前提门 | 无 | 无 | 无 |
|
|
5027
|
+
|
|
5028
|
+
**共同的两条**(三端逐条对照):
|
|
5029
|
+
|
|
5030
|
+
1. 🔴 **`send` 是端的责任面**:凭证、代理、超时、并发上限、以及「探测要不要征得用户同意」都在端。
|
|
5031
|
+
本包只保证**判定与序列**,不保证任何一台网关的行为。
|
|
5032
|
+
2. 🔴 **别在端上再写一份判定**:`thinkingIsOff` 那三条(零思考 / 正文非空 / 没被拒)、三态优先序、
|
|
5033
|
+
缺席语义,端一条都不要自己复述 —— 复述一份就是第二个会漂的源,而这正是本包存在的理由。
|
|
5034
|
+
|
|
5035
|
+
---
|
|
5036
|
+
|
|
5037
|
+
### 28g. 黑盒判据(test 视角;以 `send` 桩序列可复现,不引用内部实现)
|
|
5038
|
+
|
|
5039
|
+
> 🔴 **G-21…G-27 全部零网络可复现**:喂一只按剧本作答的 `send` 桩,数它被调用了几次、每次的请求体
|
|
5040
|
+
> 带的是哪一种拼法。这一节刻意做成这样,正是为了让 test 不必对着一台真网关花钱。
|
|
5041
|
+
|
|
5042
|
+
- **G-21**:桩第一发就答「只有正文、没有思考通道」—— 结论是「不会思考」,而桩**总共只被调用一次**
|
|
5043
|
+
(多烧任何一次往返都是缺陷:那是真钱)。
|
|
5044
|
+
- **G-21b**(🔴 异源复审逼出来的,**三个同形各跑一遍**):桩第一发分别答 ①**空正文**
|
|
5045
|
+
②**纯空白正文**(一个空格)③**被截断**的正文(`finish_reason: "length"`),都是零思考、HTTP 200
|
|
5046
|
+
的合法回执 —— 三次的结论都是**「没探出来」**而不是「不会思考」,结论里**根本没有「会不会思考」
|
|
5047
|
+
这一格**;把它落到一个原本声明了「会思考」的条目上,那一格**一个字节都没变**。
|
|
5048
|
+
反向:同一构造换成一条答完了的非空正文,结论立刻变回「不会思考」。
|
|
5049
|
+
- **G-22**:桩对**带模板参数 `chat_template_kwargs.enable_thinking=false`** 的那一发答干净正文,对
|
|
5050
|
+
别的一律答「还在思考、正文空」—— 结论点名的拼法是模板形,而桩**恰被调用两次**,且**顶层
|
|
5051
|
+
`enable_thinking` 一次都没出现在线上**。
|
|
5052
|
+
- **G-23**:反过来,桩**只**认顶层 `enable_thinking=false` —— 结论点名顶层形,桩恰被调用三次,
|
|
5053
|
+
调用序逐格是「baseline → 模板形 → 顶层形」(颠倒这个序 = 对每台这类网关多烧一次往返)。
|
|
5054
|
+
- **G-24**:桩对**每一发**都答「还在思考」—— 结论是「会思考、关不掉」,**不带任何拼法**;桩此后
|
|
5055
|
+
**还多被调用一次**,那一发带的是 `reasoning_effort:"low"`。桩对那一发答 4xx 时,结论仍是
|
|
5056
|
+
「关不掉」,但「低档收不收」那一格是**否**。
|
|
5057
|
+
- **G-24b**(🔴 混合形,异源复审逼出来的):桩只让**其中一发**试关超时、其余照答「还在思考」——
|
|
5058
|
+
结论是**「没探出来」**而不是「关不掉」(那一种拼法压根没被证伪);把同一只条目落笔之后,
|
|
5059
|
+
条目上**原有的拼法一个字节都没变**。反向:同一构造把那一发换成正常作答,结论立刻变回「关不掉」。
|
|
5060
|
+
- **G-24d**(🔴 同族第二形):桩让**四发试关全部**答空正文、零思考、HTTP 200 —— 结论同样是
|
|
5061
|
+
**「没探出来」**(那四发一个字都没证明「思考还开着」),条目上原有的拼法照旧一个字节都没变。
|
|
5062
|
+
- **G-24e**(🔴 同族第三形):把**其中一发**试关换成纯空白正文、或换成被截断的正文 —— 那一发
|
|
5063
|
+
**不算「关掉了」**(不许据它铸拼法),整只结论是「没探出来」,而条目上原有的拼法一个字节都没变。
|
|
5064
|
+
- **G-24c**:给条目的 compat 里塞一个名为 `__proto__` 的**自有**键(`JSON.parse` 造得出),再落一次
|
|
5065
|
+
「关不掉」的结论 —— 铸出来的 compat **原型没被换掉**、那一键仍是自有属性、该删的那一键真的删了。
|
|
5066
|
+
- **G-25**:桩第一发就抛错(或答 401)—— 结论是「没探出来」,桩**不再被调用**,而且结论里**根本
|
|
5067
|
+
没有「会不会思考」这一格**(不是「不会思考」)。把它落到条目上时,**条目一个键都不变**。
|
|
5068
|
+
- **G-26**:桩第一发答「在思考」,此后**每一发都抛错** —— 结论仍是「没探出来」(不是「关不掉」),
|
|
5069
|
+
而「会不会思考」这一格**在场且为真**。
|
|
5070
|
+
- **G-27**:在答案与思考通道里各埋一串独一无二的文本 —— 把整只结论序列化之后,那串文本**一个字节
|
|
5071
|
+
都不出现**(它要能整只进日志与工单)。
|
|
5072
|
+
- **G-28**:让一条会话的 auto 分类器**熔断**(连续失败到闩合上),而后续这条腿**没有重新武装**——
|
|
5073
|
+
诊断行上那一句同时报出**成因、连续失败次数与合闩时刻**;把次数换一个数重放,**那句话里的数字
|
|
5074
|
+
跟着变**(不是碰巧命中时刻串里的某个数字)。
|
|
5075
|
+
- **G-28b**(🔴 异源复审 r2 逼出来的):同一条会话上让后一条腿**重新武装**(auto 又跑起来了),
|
|
5076
|
+
而那条旧熔断记录仍在 —— 诊断行说的是**「在跑」**,不是「已关闭」;同一行里**仍带得出**那段历史
|
|
5077
|
+
(曾经熔断过、什么时候、因为什么、连着几次)。🔴 两句里**都不许**出现「不新开会话就恢复不了」
|
|
5078
|
+
这类话 —— 那条腿已经在放行了。
|
|
5079
|
+
- **G-29**:对一台**不投熔断记录**的 worker(<7.69.0,或这个会话本来就没熔断过)做同样的事 ——
|
|
5080
|
+
诊断行上**不出现**任何关于熔断的话(不是渲成「没熔断过」,也不是渲成「一定是老引擎」)。
|
|
5081
|
+
而同一台机器上让分类器**这一轮**超时:诊断行改说**「这一轮没跑成」**(它是一条真事实,照渲),
|
|
5082
|
+
且与卡上那句「这一刻为什么问我」**逐字不同**(两张面答两个问题)。
|
|
5083
|
+
- **G-30**:把 auto 完全**不武装**跑一轮 —— 状态那一行**不出现**(不是渲成「分类器正常」);
|
|
5084
|
+
「没武装」这件事仍由既有的 arm 那一格自己回答。
|
|
5085
|
+
- **G-31**:构造一条熔断记录,把合闩时刻写成一个**荒谬的大数**(或把次数写成 `0`、成因写成空串)
|
|
5086
|
+
—— **整个界面不崩**(渲染路径不许抛),而那条坏记录**一个字节都不上屏**:这条腿要是没武装,
|
|
5087
|
+
诊断行整行不出现;要是武装着,诊断行就只说**「在跑」**那一句、**不带**任何历史片段。
|
|
5088
|
+
🔴 判据是「坏记录零呈现 + 不崩」,**不是**「整行消失」—— 后者只在没武装那一支成立。
|
|
5089
|
+
同样把 `breaker` 直接写成 `null` 或一个字符串,结果一样。
|
|
5090
|
+
- **G-32**:构造一条**这一端没见过的**熔断成因词 —— 那一行**仍出现**,句子里**原样带着那个词**,
|
|
5091
|
+
且与三句已知成因的话**逐字不同**。
|
|
5092
|
+
|
|
5093
|
+
---
|
|
5094
|
+
|
|
5095
|
+
### 28h. 常驻门
|
|
5096
|
+
|
|
5097
|
+
| 门 | 守什么 |
|
|
5098
|
+
|---|---|
|
|
5099
|
+
| 🆕 `scripts/run-model-capability-probe-test.mjs` | ① 七词方言表对实装 core 双向等值 / 试关序按 `send` 桩调用序列逐格钉死 / 每方言一格正控 + 「顶层关不掉、模板形才关得掉」的真实序列格 / 「正文空」不算关掉了 / `inconclusive` 结果里没有 `reasoning` 这一格且落笔原样退回同一只条目 / `cannot_disable` 删掉被证伪的拼法 / 证据零正文 / 包内零 fetch 零 URL 零凭证键;🆕 **I 段**(件⑤)真跑一次 settings-schema 的 `ModelEntry` 解析拿真产物对照 + 两个「必须被拒」的正控 + 夹具自证 |
|
|
5100
|
+
| 🆕 `scripts/run-classifier-status-test.mjs` | ② 熔断记录四键对实装 core 的 `AutoModeBreakerTrip` 逐键对账 + 挂点真字节 / 三键承重一键可缺、`lastCause` 开集读、`openedAtMs` 按 `Date` 值域收 / 投影臂与状态读器共用同一只窄读(逐键相等)、坏记录只丢自己、缺席不铸 `null` / 熔断记录与 `armed`·`reason` 零互证 / 三态优先序 + 没武装与段缺席都判 `undefined` / 三句逐字互异且与卡面四句零重合 / 归层反向钉(窄读住在零 import 的叶子里,状态面刻意留在内核闭包外) |
|
|
5101
|
+
| `scripts/run-gate-vocabulary-test.mjs` | 🆕 **D 段**(件③)`DecisionReason`+`read_only` 的 uplift 锚:sdk 端与 devDep core 端**各断言一次缺席**;红了 = 该铸第三张措辞表,不是删锚 |
|
|
5102
|
+
| `scripts/run-client-core-pure-test.mjs` | 🆕 G-20 段加一格(件④):逐字断言投影产物的 agent 行**没有** `displayStatus` |
|
|
5103
|
+
| `scripts/run-client-core-portability-test.mjs` | 内核闭包上限 9 → **10**(件② 的零 import 叶,逐件记账);index 闭包上限 155 → **157**(件①② 各一件) |
|
|
5104
|
+
| `scripts/run-public-surface-test.mjs` | 公面导出基线 **905 → 918** |
|
|
5105
|
+
| `scripts/run-integration-doc-freshness-test.mjs` | 本节新增坐标在盘 + 入库;§0a/§2/§2b 计数与基线等值;①c 表长登记 +4 |
|
|
5106
|
+
|
|
5107
|
+
---
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/client-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.64.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",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"@sema-agent/agent-types": "^0.2.0",
|
|
38
38
|
"@sema-agent/core": "~7.10.0",
|
|
39
39
|
"@sema-agent/sdk": "^8.8.0",
|
|
40
|
+
"@sema-agent/settings-schema": "^1.10.0",
|
|
40
41
|
"esbuild": "^0.27.4",
|
|
41
42
|
"typescript": "^6.0.2"
|
|
42
43
|
}
|