@sema-agent/client-core 0.77.0 → 0.77.2
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 +23 -1
- package/README.md +5 -4
- package/dist/abortableSleep.d.ts +0 -28
- package/dist/abortableSleep.js +0 -28
- package/dist/adapt/arms.d.ts +0 -46
- package/dist/adapt/arms.js +9 -544
- package/dist/adapt/ids.d.ts +0 -58
- package/dist/adapt/ids.js +0 -63
- package/dist/adapt/instanceLedger.d.ts +0 -25
- package/dist/adapt/instanceLedger.js +0 -20
- package/dist/adapt/panelTasks.d.ts +0 -69
- package/dist/adapt/panelTasks.js +0 -95
- package/dist/adapt/textSegmentAuthority.d.ts +1 -137
- package/dist/adapt/textSegmentAuthority.js +0 -54
- package/dist/adapt/textStream.d.ts +0 -252
- package/dist/adapt/textStream.js +2 -281
- package/dist/adapt/toolCards.d.ts +0 -46
- package/dist/adapt/toolCards.js +0 -23
- package/dist/adapt/turnFlags.d.ts +0 -54
- package/dist/adapt/turnFlags.js +1 -17
- package/dist/adapt/wireShapes.d.ts +0 -92
- package/dist/adapt/wireShapes.js +0 -83
- package/dist/adapt.d.ts +0 -55
- package/dist/adapt.js +1 -120
- package/dist/adapter/activeRunSelfHeal.d.ts +22 -515
- package/dist/adapter/activeRunSelfHeal.js +10 -625
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -305
- package/dist/adapter/downstream/eventToSdkMessage.js +2 -867
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +2 -314
- package/dist/adapter/downstream/terminalToSdkResult.js +13 -560
- package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +0 -95
- package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -31
- package/dist/adapter/runStream.d.ts +0 -206
- package/dist/adapter/runStream.js +6 -596
- package/dist/adapter/types.d.ts +0 -111
- package/dist/adapter/types.js +0 -29
- package/dist/agentSession/backgroundView.d.ts +0 -106
- package/dist/agentSession/backgroundView.js +3 -49
- package/dist/agentSession/contract.d.ts +0 -98
- package/dist/agentSession/contract.js +0 -12
- package/dist/agentsWireCaps.d.ts +0 -72
- package/dist/agentsWireCaps.js +4 -72
- package/dist/approvalsStreamLiveCapability.d.ts +0 -25
- package/dist/approvalsStreamLiveCapability.js +0 -31
- package/dist/argvFlagValue.d.ts +0 -33
- package/dist/argvFlagValue.js +3 -35
- package/dist/attachmentsWireCaps.d.ts +0 -127
- package/dist/attachmentsWireCaps.js +0 -144
- package/dist/autoModeUnavailable.d.ts +0 -120
- package/dist/autoModeUnavailable.js +0 -144
- package/dist/classifierStatus.d.ts +0 -72
- package/dist/classifierStatus.js +0 -167
- package/dist/classifierVerdictWire.d.ts +0 -54
- package/dist/classifierVerdictWire.js +0 -133
- package/dist/clientContextWireCaps.d.ts +0 -37
- package/dist/clientContextWireCaps.js +0 -36
- package/dist/clientSlice.d.ts +0 -63
- package/dist/clientSlice.js +0 -45
- package/dist/cloudConfigWireCaps.d.ts +0 -86
- package/dist/cloudConfigWireCaps.js +2 -65
- package/dist/compensations.d.ts +0 -52
- package/dist/compensations.js +2 -63
- package/dist/controlRouter.d.ts +2 -208
- package/dist/controlRouter.js +1 -129
- package/dist/coreValuePorts.d.ts +0 -84
- package/dist/coreValuePorts.js +0 -29
- package/dist/decideReceipt.d.ts +0 -110
- package/dist/decideReceipt.js +0 -84
- package/dist/detachWire.d.ts +0 -130
- package/dist/detachWire.js +1 -130
- package/dist/deviceExecutorManagementCapability.d.ts +2 -35
- package/dist/deviceExecutorManagementCapability.js +1 -37
- package/dist/diagnostics.d.ts +0 -8
- package/dist/diagnostics.js +0 -8
- package/dist/diff/patch.d.ts +0 -17
- package/dist/diff/patch.js +0 -19
- package/dist/effectiveFacts.d.ts +0 -40
- package/dist/effectiveFacts.js +0 -22
- package/dist/effortWire.d.ts +0 -11
- package/dist/effortWire.js +0 -12
- package/dist/engineAgentPanelStore.d.ts +0 -169
- package/dist/engineAgentPanelStore.js +13 -293
- package/dist/engineCapReader.d.ts +0 -62
- package/dist/engineCapReader.js +1 -43
- package/dist/engineCapsCache.d.ts +0 -177
- package/dist/engineCapsCache.js +0 -199
- package/dist/engineCapsGenerationGuard.d.ts +0 -2
- package/dist/engineCapsGenerationGuard.js +0 -11
- package/dist/engineErrorCodes.d.ts +1 -316
- package/dist/engineErrorCodes.js +0 -427
- package/dist/engineHttpTools.d.ts +0 -29
- package/dist/engineHttpTools.js +0 -29
- package/dist/engineIdentity.d.ts +0 -83
- package/dist/engineIdentity.js +0 -88
- package/dist/engineInlineTaskStats.d.ts +0 -57
- package/dist/engineInlineTaskStats.js +1 -42
- package/dist/engineNoticeCodes.d.ts +0 -190
- package/dist/engineNoticeCodes.js +0 -182
- package/dist/engineSessionParam.d.ts +0 -30
- package/dist/engineSessionParam.js +0 -52
- package/dist/engineToolLabelStore.d.ts +0 -29
- package/dist/engineToolLabelStore.js +0 -31
- package/dist/engineWireSdk.d.ts +0 -90
- package/dist/engineWireSdk.js +0 -74
- package/dist/engineWireTarget.d.ts +0 -14
- package/dist/engineWireTarget.js +0 -39
- package/dist/env/localeGeo.d.ts +0 -12
- package/dist/env/localeGeo.js +2 -77
- package/dist/env/localeTag.d.ts +0 -34
- package/dist/env/localeTag.js +0 -32
- package/dist/env/uiLanguage.d.ts +0 -13
- package/dist/env/uiLanguage.js +0 -25
- package/dist/envFlag.d.ts +0 -37
- package/dist/envFlag.js +0 -40
- package/dist/executionLaneCapability.d.ts +0 -48
- package/dist/executionLaneCapability.js +0 -54
- package/dist/finalVerifyWire.d.ts +0 -67
- package/dist/finalVerifyWire.js +3 -43
- package/dist/fleet/fleetLedger.d.ts +0 -308
- package/dist/fleet/fleetLedger.js +10 -429
- package/dist/fleet/fleetProjection.d.ts +0 -240
- package/dist/fleet/fleetProjection.js +0 -189
- package/dist/fleet/fleetRowAgentType.d.ts +0 -6
- package/dist/fleet/fleetRowAgentType.js +1 -32
- package/dist/fleet/workflowSizeWarning.d.ts +0 -47
- package/dist/fleet/workflowSizeWarning.js +1 -46
- package/dist/fleetAgentPanelProjection.d.ts +0 -48
- package/dist/fleetAgentPanelProjection.js +8 -173
- package/dist/fleetTaskDesc.d.ts +0 -39
- package/dist/fleetTaskDesc.js +0 -69
- package/dist/forkWireCaps.d.ts +0 -23
- package/dist/forkWireCaps.js +1 -24
- package/dist/gateOutcome.d.ts +0 -140
- package/dist/gateOutcome.js +0 -85
- package/dist/gateVocabulary.d.ts +0 -114
- package/dist/gateVocabulary.js +1 -161
- package/dist/goalStopHook.d.ts +0 -127
- package/dist/goalStopHook.js +0 -178
- package/dist/headlessPermissionModeWire.d.ts +0 -76
- package/dist/headlessPermissionModeWire.js +1 -155
- package/dist/headlessReconnectWire.d.ts +0 -84
- package/dist/headlessReconnectWire.js +13 -67
- package/dist/hitl/approvalDecisionNoteAudit.d.ts +0 -49
- package/dist/hitl/approvalDecisionNoteAudit.js +0 -56
- package/dist/hitl/approvalOutcomeNote.d.ts +0 -2
- package/dist/hitl/approvalOutcomeNote.js +0 -20
- package/dist/hitl/approvalResolution.d.ts +0 -113
- package/dist/hitl/approvalResolution.js +0 -66
- package/dist/hitl/approvalsFeed.d.ts +0 -183
- package/dist/hitl/approvalsFeed.js +12 -243
- package/dist/hitl/armedGateRegistry.d.ts +0 -55
- package/dist/hitl/armedGateRegistry.js +0 -146
- package/dist/hitl/askGateWire.d.ts +0 -86
- package/dist/hitl/askGateWire.js +1 -95
- package/dist/hitl/askParkRowRouting.d.ts +0 -123
- package/dist/hitl/askParkRowRouting.js +1 -89
- package/dist/hitl/crashConverged.d.ts +0 -148
- package/dist/hitl/crashConverged.js +0 -214
- package/dist/hitl/editedRuleTextPrecheck.d.ts +0 -109
- package/dist/hitl/editedRuleTextPrecheck.js +0 -71
- package/dist/hitl/frameRouter.d.ts +0 -134
- package/dist/hitl/frameRouter.js +6 -378
- package/dist/hitl/gateIdentity.d.ts +0 -39
- package/dist/hitl/gateIdentity.js +0 -41
- package/dist/hitl/gateLedger.d.ts +0 -267
- package/dist/hitl/gateLedger.js +0 -121
- package/dist/hitl/hitlBridge.d.ts +7 -431
- package/dist/hitl/hitlBridge.js +7 -476
- package/dist/hitl/hitlHostSurface.d.ts +0 -150
- package/dist/hitl/hitlHostSurface.js +0 -169
- package/dist/hitl/livePendingAsk.d.ts +0 -91
- package/dist/hitl/livePendingAsk.js +0 -74
- package/dist/hitl/localAllowRule.d.ts +0 -62
- package/dist/hitl/localAllowRule.js +1 -33
- package/dist/hitl/parkOwnership.d.ts +0 -56
- package/dist/hitl/parkOwnership.js +0 -22
- package/dist/hitl/parkResolver.d.ts +3 -88
- package/dist/hitl/parkResolver.js +8 -349
- package/dist/hitl/parkRowBirthWait.d.ts +2 -26
- package/dist/hitl/parkRowBirthWait.js +3 -93
- package/dist/hitl/persistedRulesWire.d.ts +13 -358
- package/dist/hitl/persistedRulesWire.js +0 -310
- package/dist/hitl/planReviewWire.d.ts +4 -176
- package/dist/hitl/planReviewWire.js +9 -312
- package/dist/hitl/resumeRunningCard.d.ts +0 -105
- package/dist/hitl/resumeRunningCard.js +0 -105
- package/dist/hitl/sessionPolicyWire.d.ts +11 -191
- package/dist/hitl/sessionPolicyWire.js +0 -149
- package/dist/hitl/suspendedReopen.d.ts +3 -24
- package/dist/hitl/suspendedReopen.js +0 -14
- package/dist/hitl/toolApprovalWire.d.ts +5 -1308
- package/dist/hitl/toolApprovalWire.js +5 -945
- package/dist/hooksWireCaps.d.ts +0 -38
- package/dist/hooksWireCaps.js +0 -190
- package/dist/host.d.ts +0 -105
- package/dist/host.js +0 -33
- package/dist/hostEnv.d.ts +0 -14
- package/dist/hostEnv.js +0 -13
- package/dist/imagesWireCaps.d.ts +0 -21
- package/dist/imagesWireCaps.js +0 -22
- package/dist/index.d.ts +0 -134
- package/dist/index.js +0 -476
- package/dist/interactiveHalt.d.ts +5 -153
- package/dist/interactiveHalt.js +0 -111
- package/dist/interactiveToolsWire.d.ts +0 -62
- package/dist/interactiveToolsWire.js +1 -67
- package/dist/leaderConflict.d.ts +0 -59
- package/dist/leaderConflict.js +0 -48
- package/dist/limitsWire.d.ts +0 -125
- package/dist/limitsWire.js +2 -120
- package/dist/liveInitToolFace.d.ts +0 -77
- package/dist/liveInitToolFace.js +1 -109
- package/dist/liveModelCatalog.d.ts +0 -52
- package/dist/liveModelCatalog.js +0 -48
- package/dist/liveQuestionStore.d.ts +0 -87
- package/dist/liveQuestionStore.js +1 -56
- package/dist/mcpLiveness.d.ts +0 -151
- package/dist/mcpLiveness.js +0 -122
- package/dist/mcpPanel.d.ts +0 -104
- package/dist/mcpPanel.js +0 -49
- package/dist/mcpReconnect.d.ts +0 -58
- package/dist/mcpReconnect.js +1 -69
- package/dist/mcpWireCaps.d.ts +0 -55
- package/dist/mcpWireCaps.js +1 -13
- package/dist/memoryComplianceCapability.d.ts +3 -57
- package/dist/memoryComplianceCapability.js +0 -57
- package/dist/memoryEntriesWire.d.ts +6 -198
- package/dist/memoryEntriesWire.js +0 -144
- package/dist/memoryOriginCapability.d.ts +3 -53
- package/dist/memoryOriginCapability.js +0 -50
- package/dist/memorySpecWire.d.ts +0 -116
- package/dist/memorySpecWire.js +0 -150
- package/dist/model/catalog.d.ts +0 -111
- package/dist/model/catalog.js +0 -87
- package/dist/model/catalogLoader.d.ts +0 -114
- package/dist/model/catalogLoader.js +2 -139
- package/dist/model/modelSupplyRules.d.ts +1 -55
- package/dist/model/modelSupplyRules.js +0 -62
- package/dist/model/providerAuth.d.ts +0 -103
- package/dist/model/providerAuth.js +2 -38
- package/dist/model/providerCatalog.d.ts +0 -45
- package/dist/model/providerCatalog.js +0 -37
- package/dist/model/providerPresets.d.ts +0 -33
- package/dist/model/providerPresets.js +2 -91
- package/dist/model/tierVocabulary.d.ts +0 -31
- package/dist/model/tierVocabulary.js +0 -27
- package/dist/modelBudgetRule.d.ts +0 -39
- package/dist/modelBudgetRule.js +0 -39
- package/dist/modelCapabilityProbe.d.ts +0 -175
- package/dist/modelCapabilityProbe.js +0 -147
- package/dist/modelWireCaps.d.ts +0 -13
- package/dist/modelWireCaps.js +0 -13
- package/dist/notifications.d.ts +0 -233
- package/dist/notifications.js +14 -492
- package/dist/oneShotWireCaps.d.ts +0 -34
- package/dist/oneShotWireCaps.js +0 -35
- package/dist/ownKey.d.ts +0 -33
- package/dist/ownKey.js +0 -33
- package/dist/panelRunningHistory.d.ts +0 -28
- package/dist/panelRunningHistory.js +0 -43
- package/dist/peerFrames.d.ts +0 -71
- package/dist/peerFrames.js +0 -168
- package/dist/peerLaneCapability.d.ts +0 -44
- package/dist/peerLaneCapability.js +0 -52
- package/dist/permissionRuleIssue.d.ts +0 -30
- package/dist/permissionRuleIssue.js +0 -78
- package/dist/permissionRulesWriteCapability.d.ts +0 -46
- package/dist/permissionRulesWriteCapability.js +0 -54
- package/dist/permissionWireCaps.d.ts +0 -37
- package/dist/permissionWireCaps.js +0 -37
- package/dist/postureKnob.d.ts +0 -71
- package/dist/postureKnob.js +0 -86
- package/dist/principalWire.d.ts +0 -17
- package/dist/principalWire.js +0 -17
- package/dist/printToolResultFrame.d.ts +0 -100
- package/dist/printToolResultFrame.js +0 -33
- package/dist/promptProfileWireCaps.d.ts +0 -13
- package/dist/promptProfileWireCaps.js +0 -13
- package/dist/readFacePosture.d.ts +0 -43
- package/dist/readFacePosture.js +0 -46
- package/dist/request/printNotification.d.ts +0 -20
- package/dist/request/printNotification.js +0 -55
- package/dist/request/taskRequest.d.ts +0 -249
- package/dist/request/taskRequest.js +10 -496
- package/dist/resumeRefusalCopy.d.ts +0 -136
- package/dist/resumeRefusalCopy.js +1 -117
- package/dist/retainBackgroundWireCaps.d.ts +0 -48
- package/dist/retainBackgroundWireCaps.js +0 -48
- package/dist/retryStatus.d.ts +2 -221
- package/dist/retryStatus.js +0 -107
- package/dist/rewindWireCaps.d.ts +0 -27
- package/dist/rewindWireCaps.js +0 -24
- package/dist/runCancelContext.d.ts +1 -20
- package/dist/runCancelContext.js +0 -34
- package/dist/runTerminal.d.ts +0 -273
- package/dist/runTerminal.js +0 -177
- package/dist/sandboxWire.d.ts +0 -38
- package/dist/sandboxWire.js +0 -82
- package/dist/scenarioWire.d.ts +0 -60
- package/dist/scenarioWire.js +0 -68
- package/dist/scratchpadWireCaps.d.ts +0 -11
- package/dist/scratchpadWireCaps.js +0 -32
- package/dist/sdkWireTransit.d.ts +0 -38
- package/dist/sdkWireTransit.js +0 -30
- package/dist/seam.d.ts +18 -853
- package/dist/seam.js +0 -52
- package/dist/seatContract.d.ts +0 -555
- package/dist/seatContract.js +5 -304
- package/dist/selfOrchestrationDenial.d.ts +0 -189
- package/dist/selfOrchestrationDenial.js +0 -162
- package/dist/selfOrchestrationWireCaps.d.ts +0 -38
- package/dist/selfOrchestrationWireCaps.js +0 -38
- package/dist/sessionMap.d.ts +0 -60
- package/dist/sessionMap.js +0 -37
- package/dist/sessionMemoryStatus.d.ts +11 -114
- package/dist/sessionMemoryStatus.js +0 -112
- package/dist/sessionModelLatch.d.ts +0 -29
- package/dist/sessionModelLatch.js +0 -40
- package/dist/sessionPolicyCapability.d.ts +3 -53
- package/dist/sessionPolicyCapability.js +0 -52
- package/dist/sessionSlot.d.ts +0 -26
- package/dist/sessionSlot.js +0 -17
- package/dist/skillsWireCaps.d.ts +0 -87
- package/dist/skillsWireCaps.js +0 -38
- package/dist/sqlEngineCapability.d.ts +0 -118
- package/dist/sqlEngineCapability.js +0 -134
- package/dist/sseIdleTriage.d.ts +0 -79
- package/dist/sseIdleTriage.js +1 -80
- package/dist/steering.d.ts +0 -54
- package/dist/steering.js +0 -63
- package/dist/subagent/engineCompactWire.d.ts +0 -34
- package/dist/subagent/engineCompactWire.js +4 -134
- package/dist/subagent/engineDelegatedPrompt.d.ts +0 -31
- package/dist/subagent/engineDelegatedPrompt.js +1 -103
- package/dist/subagent/engineRowStopGate.d.ts +0 -20
- package/dist/subagent/engineRowStopGate.js +0 -49
- package/dist/subagent/engineSubagentOutput.d.ts +0 -7
- package/dist/subagent/engineSubagentOutput.js +1 -51
- package/dist/subagent/engineSubagentResume.d.ts +2 -279
- package/dist/subagent/engineSubagentResume.js +2 -129
- package/dist/subagent/engineSubagentSteer.d.ts +0 -26
- package/dist/subagent/engineSubagentSteer.js +0 -63
- package/dist/subagent/engineSubagentTail.d.ts +0 -38
- package/dist/subagent/engineSubagentTail.js +2 -110
- package/dist/subagent/engineTaskHandleWire.d.ts +11 -65
- package/dist/subagent/engineTaskHandleWire.js +20 -131
- package/dist/subagent/subagentOwnerAbsence.d.ts +0 -2
- package/dist/subagent/subagentOwnerAbsence.js +0 -25
- package/dist/subagentContentStore.d.ts +3 -260
- package/dist/subagentContentStore.js +7 -540
- package/dist/systemReminderTag.d.ts +0 -49
- package/dist/systemReminderTag.js +0 -61
- package/dist/toolResult.d.ts +1 -211
- package/dist/toolResult.js +1 -358
- package/dist/toolRoster.d.ts +0 -140
- package/dist/toolRoster.js +0 -66
- package/dist/typePins.d.ts +0 -46
- package/dist/types/engineState.d.ts +0 -71
- package/dist/types/engineState.js +0 -16
- package/dist/ultracodeWireCaps.d.ts +0 -75
- package/dist/ultracodeWireCaps.js +0 -92
- package/dist/unrefTimer.d.ts +0 -27
- package/dist/webSearchBackendCapability.d.ts +0 -72
- package/dist/webSearchBackendCapability.js +0 -79
- package/dist/webSearchWireCaps.d.ts +0 -37
- package/dist/webSearchWireCaps.js +0 -34
- package/dist/websearch/searchProviderPresets.d.ts +0 -81
- package/dist/websearch/searchProviderPresets.js +0 -27
- package/dist/wireErrorTriage.d.ts +4 -160
- package/dist/wireErrorTriage.js +0 -171
- package/dist/wireRefusalCopy.d.ts +0 -28
- package/dist/wireRefusalCopy.js +0 -28
- package/dist/workflow.d.ts +0 -40
- package/dist/workflow.js +0 -52
- package/dist/workflowClient.d.ts +0 -122
- package/dist/workflowClient.js +8 -360
- package/dist/workflowMonitor.d.ts +2 -72
- package/dist/workflowMonitor.js +0 -26
- package/dist/writeProtectionCapability.d.ts +0 -112
- package/dist/writeProtectionCapability.js +0 -109
- package/docs/INTEGRATION-CLIENTS.md +62 -1
- package/package.json +1 -1
package/dist/modelBudgetRule.js
CHANGED
|
@@ -1,41 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/modelBudgetRule.ts 逐字搬入(零依赖,纯规则)。
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* modelBudgetRule.ts — max-output-tokens 中央规则(clay 2026-07-15 拍板,F2 maxTokens 裁决批)。
|
|
6
|
-
*
|
|
7
|
-
* 裁决(逐字):
|
|
8
|
-
* · 上下文窗口:预设/家族表能匹配用匹配值;匹配不上默认 200000(FALLBACK_CONTEXT_WINDOW)。
|
|
9
|
-
* · maxTokens 默认:32000;上下文窗口 ≥500000 → 64000;恒受两道封顶:
|
|
10
|
-
* ① per-model 已知 cap(providerPresets 精确表,inferFamily 第①层命中带 perModelCap);
|
|
11
|
-
* ② 上下文窗口 ÷ 4(向下取整)。
|
|
12
|
-
* · UI 四档(超集):16K / 32K(默认)/ 64K / 128K;档位 > 上下文窗口÷4 的禁用/跳过
|
|
13
|
-
* (例:128K 上下文 → 顶 32K;1M → 全档可用)。
|
|
14
|
-
* · env 显式值恒赢:CLAUDE_CODE_MAX_OUTPUT_TOKENS 映射与显式 MODEL_MAX_TOKENS 既有行为不动
|
|
15
|
-
* (本模块只算默认,不碰覆盖层 —— 见 ccConfigFallback.applyModelEnvFamilyFallback)。
|
|
16
|
-
*
|
|
17
|
-
* CC 对照锚(有意偏离,记忆档 max-tokens-ruling-deviate-cc):CC 2.1.207 per-model 表
|
|
18
|
-
* `max_output_tokens:{default:32000,upper:64000}`(源 13760)+ CLAUDE_CODE_MAX_OUTPUT_TOKENS env
|
|
19
|
-
* 钳制(源 529278),无 UI 档位、无 ÷4 封顶。sema 面对任意三方模型/网关,家族表大数直接当默认会
|
|
20
|
-
* 超供应商 cap(400)或单轮吃穿预算 —— 故默认收敛到 CC 口径 32K/64K,并加 ÷4 与 per-model 封顶;
|
|
21
|
-
* UI 档位是超集便利面。
|
|
22
|
-
*
|
|
23
|
-
* 注意:providerPresets.json 精确表 / modelFamilies.json 家族表的 maxTokens 字段【保留】——
|
|
24
|
-
* 只作 cap 参考(perModelCap / 显示),不再直接当默认 stamp 值。
|
|
25
|
-
*/
|
|
26
|
-
/** 裁决:预设/家族都匹配不上时的上下文窗口默认(=CC 的 200k 口径)。 */
|
|
27
1
|
export const FALLBACK_CONTEXT_WINDOW = 200000;
|
|
28
|
-
/** UI 四档(超集):16K / 32K(默认)/ 64K / 128K。十进制(与 CC 32000/64000 同基)。 */
|
|
29
2
|
export const MAXTOK_TIERS = [16000, 32000, 64000, 128000];
|
|
30
3
|
function normalizeCtx(contextWindow) {
|
|
31
4
|
return typeof contextWindow === 'number' && Number.isFinite(contextWindow) && contextWindow > 0
|
|
32
5
|
? contextWindow
|
|
33
6
|
: FALLBACK_CONTEXT_WINDOW;
|
|
34
7
|
}
|
|
35
|
-
/**
|
|
36
|
-
* 默认 max tokens = min( ctx>=500000 ? 64000 : 32000 , floor(ctx/4) , perModelCap ?? ∞ )。
|
|
37
|
-
* contextWindow 传 null/undefined/非法 = 匹配不上 → 按 200000 算(→ 32000)。
|
|
38
|
-
*/
|
|
39
8
|
export function defaultMaxTokensFor(contextWindow, perModelCap) {
|
|
40
9
|
const ctx = normalizeCtx(contextWindow);
|
|
41
10
|
const base = ctx >= 500000 ? 64000 : 32000;
|
|
@@ -45,18 +14,10 @@ export function defaultMaxTokensFor(contextWindow, perModelCap) {
|
|
|
45
14
|
: Infinity;
|
|
46
15
|
return Math.min(base, quarter, cap);
|
|
47
16
|
}
|
|
48
|
-
/**
|
|
49
|
-
* 该上下文窗口下可用的 UI 档位(> ctx÷4 的禁用/跳过)。可能为空(ctx < 64000,如 32K 上下文
|
|
50
|
-
* 连 16K 档都超 ÷4)—— UI 调用方对空列表降级(提示用 M 自由输入),规则函数不瞎补。
|
|
51
|
-
*/
|
|
52
17
|
export function tierChoicesFor(contextWindow) {
|
|
53
18
|
const ctx = normalizeCtx(contextWindow);
|
|
54
19
|
return MAXTOK_TIERS.filter(t => t <= ctx / 4);
|
|
55
20
|
}
|
|
56
|
-
/**
|
|
57
|
-
* 档位循环:当前值在档内 → 下一档(循环);不在档内(自由输入/家族值)→ 大于当前的最小档,
|
|
58
|
-
* 都不大于则回第一档(与 modelCtxOverride.nextStep 同语义)。无可用档 → null(调用方降级)。
|
|
59
|
-
*/
|
|
60
21
|
export function nextMaxTokTier(current, contextWindow) {
|
|
61
22
|
const tiers = tierChoicesFor(contextWindow);
|
|
62
23
|
if (tiers.length === 0)
|
|
@@ -1,47 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* src/modelCapabilityProbe.ts — 一条 OpenAI-completions 车道的模型**会不会思考、关不关得掉**
|
|
3
|
-
* 的三端公共探测(0.64.0 件①)。
|
|
4
|
-
*
|
|
5
|
-
* -- 它答的是哪一问 ---------------------------------------------------------------------------
|
|
6
|
-
* 一台 vLLM/Qwen 类网关**默认就在思考**,而「关掉」这件事各家拼法不同:有的读顶层
|
|
7
|
-
* `enable_thinking`,有的只认模板参数 `chat_template_kwargs.enable_thinking`,有的要
|
|
8
|
-
* `thinking:{type:"disabled"}`。目录条目上那一格 `compat.thinkingFormat` 就是告诉引擎该用哪种
|
|
9
|
-
* 拼法 —— 而**没有人能靠看一眼型号名答出它是哪一种**。本模块把这一问变成一次可复现的探测:
|
|
10
|
-
* 发一发最小请求看它思不思考,思考就按序把每一种拼法试一遍,记下第一种真关得掉的。
|
|
11
|
-
*
|
|
12
|
-
* -- 🔴 网络那半场不在包里 --------------------------------------------------------------------
|
|
13
|
-
* 本模块**零 fetch、零 URL、零凭证**:调用方注入一只 {@link ProbeSend},自己去做鉴权与传输,
|
|
14
|
-
* 只把「答了多长的正文 / 有没有思考通道 / 什么 finish 位 / 什么状态码」交回来。理由与本包
|
|
15
|
-
* `model/catalogLoader.ts` 的 `CatalogFetchJson` 同一条:三端的凭证轨、代理、超时策略各不相同,
|
|
16
|
-
* 而**判定**是同一份 —— 判定归包,传输归端。凭证因此一个字节都不会经过本包。
|
|
17
|
-
*
|
|
18
|
-
* -- 🔴 方言闭集是**抄件**,不是本包的意见 ---------------------------------------------------
|
|
19
|
-
* 七个词的属主是引擎:`@sema-agent/core` 的 `dist/engine/llm/types.d.ts` 里
|
|
20
|
-
* `OpenAICompletionsCompat.thinkingFormat`(7.10.0 = 七词)。而 core **不是本包消费者的依赖**
|
|
21
|
-
* (既非 peer 也非 runtime dep),`.d.ts` 一旦引用它,装了本包却没装 core 的下游会当场编译不过
|
|
22
|
-
* ⇒ 与 `engineNoticeCodes.ts` / `autoModeUnavailable.ts` 同一条处置:**按真字节镜像,把代价交给
|
|
23
|
-
* 门** —— `run-model-capability-probe-test.mjs` 的 A 段对实装 devDep core 双向等值对账,
|
|
24
|
-
* 上游加一个方言这里当天先红。
|
|
25
|
-
* ⚠️ **settings-schema 那边取不到这张表,别去那儿找**:`ModelEntry.compat` 在 1.10.0 引入、2.0.0 仍是(2026-09-16 核 dist/types.d.ts)
|
|
26
|
-
* **parse-transparent 的 `z.unknown()`**,它的 JSDoc 逐字写着「the SHAPE and the VOCABULARY …
|
|
27
|
-
* are the consuming side's single point — this package deliberately does NOT restate that table」。
|
|
28
|
-
* 那一格刻意不复述词表,所以「从 settings-schema import 闭集」这条路在型面上不存在。
|
|
29
|
-
*
|
|
30
|
-
* -- 🔴 试关序是**公面承诺**,不是实现细节 ---------------------------------------------------
|
|
31
|
-
* 每多试一种拼法就是对那台网关多烧一次真钱与真时延,所以「先试哪一种」必须成文、必须被门钉死
|
|
32
|
-
* ({@link THINKING_DISABLE_PROBE_ORDER})。排序的理由是观测到的真实序列:一台 Qwen 类网关收到
|
|
33
|
-
* **顶层** `enable_thinking:false` 时,思考照旧、而正文变空 —— 换成模板参数才真的关掉。把模板形
|
|
34
|
-
* 排在前面,绝大多数这类网关一发即中。
|
|
35
|
-
* 🔴 **`openai` 不在试关序里**:它的「关」拼法是 `reasoning_effort:<thinkingLevelMap.off>`,而那张
|
|
36
|
-
* 映射表是**条目上的声明**,探针手里没有 ⇒ core 在这一形上什么都不写,发出去等于把 baseline
|
|
37
|
-
* 那一发原样再烧一次。它在本模块里的角色只有一个:关不掉时补一发 `reasoning_effort:"low"`,
|
|
38
|
-
* 看这台网关**收不收**低档旋钮({@link ModelProbeEvidence.lowEffortAccepted})。
|
|
39
|
-
* 🔴 **线上同形的两个词不各占一臂**:`zai` 与 `qwen` 铸出的请求体逐字节相同(顶层
|
|
40
|
-
* `enable_thinking`),`together` 与 `openrouter` 同理(`reasoning:{enabled:false}`)——
|
|
41
|
-
* 再烧一次往返证明不了任何新东西。对照表在 {@link THINKING_FORMAT_WIRE_TWINS};铸出的词取
|
|
42
|
-
* 每对里线上更常见的那一个,而**它们在这条轴上真的可以互换**(不是近似)。
|
|
43
|
-
*/
|
|
44
|
-
/** 一次探测请求的请求体 —— OpenAI-completions 车道的最小子集(方言位逐次至多一个在场)。 */
|
|
45
1
|
export interface OpenAICompletionsProbeBody {
|
|
46
2
|
model: string;
|
|
47
3
|
messages: ReadonlyArray<{
|
|
@@ -50,195 +6,64 @@ export interface OpenAICompletionsProbeBody {
|
|
|
50
6
|
}>;
|
|
51
7
|
max_tokens: number;
|
|
52
8
|
stream: false;
|
|
53
|
-
/** `qwen` / `zai` 的关拼法。 */
|
|
54
9
|
enable_thinking?: boolean;
|
|
55
|
-
/** `qwen-chat-template` 的关拼法(模板渲染参数)。
|
|
56
|
-
* 🔴 **不是 `Record<string, unknown>`**:这只体**只由本包铸**(端拿到它就原样转发),所以这一位
|
|
57
|
-
* 上真正会出现的只有这一个开关 —— 声明成自由记录等于在公面上开一个没有理由的 unknown 出境口
|
|
58
|
-
* (typeshape 棘轮盯的正是这个),而且会让端以为自己可以往里塞别的模板参数。 */
|
|
59
10
|
chat_template_kwargs?: {
|
|
60
11
|
enable_thinking: boolean;
|
|
61
12
|
};
|
|
62
|
-
/** `deepseek` 的关拼法。 */
|
|
63
13
|
thinking?: {
|
|
64
14
|
type: string;
|
|
65
15
|
};
|
|
66
|
-
/** `openrouter` / `together` 的关拼法。 */
|
|
67
16
|
reasoning?: {
|
|
68
17
|
enabled: boolean;
|
|
69
18
|
};
|
|
70
|
-
/** `openai` 车道的档位旋钮(本模块只用它做 low 档探测,**不**当作「关」)。 */
|
|
71
19
|
reasoning_effort?: string;
|
|
72
20
|
}
|
|
73
|
-
/**
|
|
74
|
-
* 一次探测的**回执**(端负责把自己那条 HTTP 应答折成这个形)。
|
|
75
|
-
* 🔴 只要四件事,一件都不要更多:正文、思考通道、finish 位、状态码 —— 端不必、也不该把整只
|
|
76
|
-
* 应答体交进来(那会让本包变成第二个应答解析器,而解析归引擎)。
|
|
77
|
-
*/
|
|
78
21
|
export interface ProbeSendResult {
|
|
79
|
-
/** 模型答的正文(`choices[0].message.content`;没有 ⇒ 空串)。 */
|
|
80
22
|
content: string;
|
|
81
|
-
/** 思考通道(`choices[0].message.reasoning_content`);缺席 = 这台网关没给这一通道。 */
|
|
82
23
|
reasoningContent?: string;
|
|
83
|
-
/** `choices[0].finish_reason` 原样。 */
|
|
84
24
|
finishReason?: string;
|
|
85
|
-
/** HTTP 状态码。**缺席 = 端没报**,不是 200 —— 本模块因此只把「明确 ≥400」判成被拒。 */
|
|
86
25
|
status?: number;
|
|
87
26
|
}
|
|
88
|
-
/**
|
|
89
|
-
* 网络端口:把一只请求体发出去,交回 {@link ProbeSendResult}。
|
|
90
|
-
* 🔴 **抛错是合法回答**(端不必自己吞):本模块把「抛了」与「4xx/5xx」一视同仁地记成
|
|
91
|
-
* `refused`,并按发生在哪一发决定判词(见 {@link probeModelCapability})。
|
|
92
|
-
*/
|
|
93
27
|
export type ProbeSend = (body: OpenAICompletionsProbeBody) => Promise<ProbeSendResult>;
|
|
94
|
-
/** 被探测的目录条目(只要这三格 —— 条目的其余键与本探测无关)。 */
|
|
95
28
|
export interface ModelProbeEntry {
|
|
96
|
-
/** 线上模型 id(进请求体的那一个)。 */
|
|
97
29
|
id: string;
|
|
98
|
-
/** 车道(本模块只服务 `openai-completions`;别的车道由调用方先筛掉)。 */
|
|
99
30
|
api: string;
|
|
100
|
-
/** 端点(本模块**不读它**,只是让调用方的 `send` 闭包不必再查一次条目)。 */
|
|
101
31
|
baseUrl?: string;
|
|
102
32
|
}
|
|
103
|
-
/**
|
|
104
|
-
* 引擎的**思考拼法闭集**(core `OpenAICompletionsCompat.thinkingFormat`,7.10.0 = 七词;
|
|
105
|
-
* 顺序同源)。🔴 这是一份抄件,不是本包的意见 —— 改它必须同 commit 附 core 坐标,且门会先红。
|
|
106
|
-
|
|
107
|
-
* 🔴 形制:`Object.freeze` 的数组,**不是**只在类型面只读的 `readonly T[]` —— 后者一行 `.splice()`
|
|
108
|
-
* 就能改,而公面消费者拿到的正是这个实例(本仓已定谳的病形,同 `RESUME_RETRY_LATER_CODES`)。
|
|
109
|
-
*/
|
|
110
33
|
export declare const THINKING_FORMATS: readonly string[];
|
|
111
|
-
/**
|
|
112
|
-
* 线上**逐字节同形**的方言对(`键` ⇒ 探针实际会试的那一个)。它们在这条轴上可以互换:
|
|
113
|
-
* `zai` 与 `qwen` 都写顶层 `enable_thinking`,`together` 与 `openrouter` 都写 `reasoning.enabled`。
|
|
114
|
-
* ⚠️ 只对**思考开关**这一条轴成立 —— 别把它读成「这两个词处处等价」。
|
|
115
|
-
*/
|
|
116
34
|
export declare const THINKING_FORMAT_WIRE_TWINS: Readonly<Record<string, string>>;
|
|
117
|
-
/**
|
|
118
|
-
* **试关序**(公面承诺,见模块顶注)。四臂覆盖全部四种线上不同形的关拼法;`openai` 刻意不在其中。
|
|
119
|
-
* 🔴 顺序承重:模板形排第一,因为观测到的真实序列是「顶层形关不掉且把正文答空、模板形才真关掉」。
|
|
120
|
-
*/
|
|
121
35
|
export declare const THINKING_DISABLE_PROBE_ORDER: readonly string[];
|
|
122
|
-
/**
|
|
123
|
-
* 一次探测的四个判词。
|
|
124
|
-
* · `no_reasoning` —— 这台网关本来就不思考(一发即知,不再烧往返);
|
|
125
|
-
* · `disabled_via` —— 会思考,而 {@link ModelProbeResult.thinkingFormat} 那一种拼法真关掉了;
|
|
126
|
-
* · `cannot_disable` —— 会思考,四种拼法**逐臂给出正面反证**(每一臂都看见思考还开着)⇒ 关不掉;
|
|
127
|
-
* · `inconclusive` —— **问不出来**(baseline 没有证据力,或**任一**试关臂没有证据力)。
|
|
128
|
-
* 🔴 `cannot_disable` 与 `inconclusive` 的边界是本模块最要紧的一条,而它锚的是**证据力**
|
|
129
|
-
* (见 `forceOf`)而不是「有没有被拒」:一臂超时、或一臂答了一条「零思考 + 正文空」的合法空
|
|
130
|
-
* 回执,那一种拼法都**没被证伪**,唯一诚实的判词是「问不出来」。这一条不是洁癖:
|
|
131
|
-
* `cannot_disable` 是 {@link applyProbeToEntry} **删掉**条目上原有 `thinkingFormat` 的唯一触发,
|
|
132
|
-
* 而那一删是**持久**的。
|
|
133
|
-
*/
|
|
134
36
|
export declare const MODEL_PROBE_VERDICTS: readonly string[];
|
|
135
|
-
/** 一发的**可留痕部分** —— 长度与位,🔴 一个字节的应答正文都不进来(证据要能进日志与工单)。 */
|
|
136
37
|
export interface ModelProbeObservation {
|
|
137
|
-
/** 正文长度(码元数;**原始**长度,不因判据收紧而变 —— 证据面记的是读数)。 */
|
|
138
38
|
contentLen: number;
|
|
139
|
-
/**
|
|
140
|
-
* 正文里有没有**看得见的字**(去掉空白之后仍非空)。
|
|
141
|
-
* 🔴 与 {@link contentLen} 分开两格是刻意的:`{content:' '}` 的 `contentLen` 是 3(真读数),
|
|
142
|
-
* 而它在判据上**一个字都没说** —— 一格当两用会逼着判据去读一个它不该读的量。
|
|
143
|
-
*/
|
|
144
39
|
hasText: boolean;
|
|
145
|
-
/** 思考通道长度;没有该通道 ⇒ `0`。 */
|
|
146
40
|
reasoningLen: number;
|
|
147
|
-
/** 正文里出现了 `<think>` / `<thinking>` 开标签(没有思考通道的网关走这条)。 */
|
|
148
41
|
sawThinkTag: boolean;
|
|
149
|
-
/** `finish_reason` 原样(引擎/网关铸的词,不是用户内容)。 */
|
|
150
42
|
finishReason?: string;
|
|
151
|
-
/** 端报的状态码;缺席 = 端没报。 */
|
|
152
43
|
status?: number;
|
|
153
|
-
/** 这一发被拒了(`send` 抛错,或状态码 ≥400)。 */
|
|
154
44
|
refused: boolean;
|
|
155
45
|
}
|
|
156
|
-
/** 一条试关臂的观测(比 {@link ModelProbeObservation} 多一格:试的是哪一种拼法)。 */
|
|
157
46
|
export interface ModelProbeAttempt extends ModelProbeObservation {
|
|
158
|
-
/** {@link THINKING_DISABLE_PROBE_ORDER} 之一。 */
|
|
159
47
|
format: string;
|
|
160
48
|
}
|
|
161
|
-
/** 一次探测留下的全部证据(零正文)。 */
|
|
162
49
|
export interface ModelProbeEvidence {
|
|
163
|
-
/** 第一发(不带任何方言位)。 */
|
|
164
50
|
baseline: ModelProbeObservation;
|
|
165
|
-
/** 逐臂试关(命中即停,所以这张表长度 ≤ 试关序长度)。 */
|
|
166
51
|
attempts: readonly ModelProbeAttempt[];
|
|
167
|
-
/**
|
|
168
|
-
* 关不掉之后补的那一发:这台网关**收不收** `reasoning_effort:"low"`。
|
|
169
|
-
* 🔴 它说的是「低档旋钮被收下了」,**不是**「思考真的变少了」—— 后者本探针量不到,别那样渲。
|
|
170
|
-
* 缺席 = 没做这一发(没到 `cannot_disable` 那一步)。
|
|
171
|
-
*/
|
|
172
52
|
lowEffortAccepted?: boolean;
|
|
173
53
|
}
|
|
174
|
-
/** 一次探测的结论。 */
|
|
175
54
|
export interface ModelProbeResult {
|
|
176
|
-
/**
|
|
177
|
-
* 这台网关会不会思考。
|
|
178
|
-
* 🔴 **`inconclusive` 且 baseline 都没问出来时,这一格整个缺席** —— 不是 `false`。
|
|
179
|
-
* 把「问不出来」渲成「不会思考」正是本仓已定谳的病形([honest-absence-not-fabricated-zero]);
|
|
180
|
-
* 型面上让它可缺席,消费端就没法不小心把它读成一个读数。
|
|
181
|
-
*/
|
|
182
55
|
reasoning?: boolean;
|
|
183
|
-
/** 真关得掉的那一种拼法;🔴 只在 `disabled_via` 上在场。 */
|
|
184
56
|
thinkingFormat?: string;
|
|
185
|
-
/** {@link MODEL_PROBE_VERDICTS} 之一。 */
|
|
186
57
|
verdict: string;
|
|
187
58
|
evidence: ModelProbeEvidence;
|
|
188
59
|
}
|
|
189
|
-
/**
|
|
190
|
-
* 铸一只探测请求体。
|
|
191
|
-
* @param entry 被探测的条目(只取 `id`)
|
|
192
|
-
* @param format 关拼法;缺席 ⇒ baseline(不带任何方言位)
|
|
193
|
-
* @param opts `reasoningEffort` = low 档探测那一发(与关拼法互斥使用)
|
|
194
|
-
*
|
|
195
|
-
* 🔴 **逐次新对象**:调用方(与门)拿到的每一只都是新的,改一只不会污染下一只。
|
|
196
|
-
* 🔴 拼法逐字同 core `dist/brain/openai.js` 的 `applyThinking` 关分支;表外词 ⇒ 不写任何方言位
|
|
197
|
-
* (**不猜**:一个猜出来的旋钮会让判定去读一台网关根本没被要求过的行为)。
|
|
198
|
-
*/
|
|
199
60
|
export declare function probeRequestBody(entry: ModelProbeEntry, format?: string, opts?: {
|
|
200
61
|
reasoningEffort?: string;
|
|
201
62
|
}): OpenAICompletionsProbeBody;
|
|
202
|
-
/**
|
|
203
|
-
* 探测一个条目:会不会思考、关不关得掉、用哪种拼法关。
|
|
204
|
-
*
|
|
205
|
-
* 步骤(每一步都可能是最后一步 —— 能少烧一次往返就少烧一次):
|
|
206
|
-
* ① baseline:最小请求,不带任何方言位。
|
|
207
|
-
* · **没有证据力**(被拒,或「零思考 + 正文也空」的合法空回执)⇒ `inconclusive`,
|
|
208
|
-
* **结果里没有 `reasoning` 这一格**(问不出来 ≠ 不思考);
|
|
209
|
-
* · **正面证据**「正文非空且零思考」⇒ `no_reasoning`,收工(不再烧任何往返)。
|
|
210
|
-
* ② 按 {@link THINKING_DISABLE_PROBE_ORDER} 逐臂试关,第一个 {@link thinkingIsOff} 成立的
|
|
211
|
-
* 拼法就是答案 ⇒ `disabled_via`,收工。
|
|
212
|
-
* ③ 四臂都没关掉:
|
|
213
|
-
* · **每一臂都给出正面反证**(都看见思考还开着)⇒ `cannot_disable`,并补一发
|
|
214
|
-
* `reasoning_effort:"low"` 记下这台网关收不收低档旋钮(端据此渲「会思考、当前关不掉;
|
|
215
|
-
* 席位将按 low 档运行」);
|
|
216
|
-
* · **任一臂没有证据力**(被拒,或空回执)⇒ `inconclusive` —— 那一种拼法没被证伪,
|
|
217
|
-
* 「问不出来」不是「关不掉」。这一形上 `reasoning` 那一格**在场且为真**(baseline 是
|
|
218
|
-
* 问出来了的),而证据里逐臂留着每一发的长度与状态,端可以据此只重试那一臂。
|
|
219
|
-
*
|
|
220
|
-
* @param entry 被探测的条目
|
|
221
|
-
* @param send 网络端口(端自备鉴权与传输;本包零 fetch)
|
|
222
|
-
*/
|
|
223
63
|
export declare function probeModelCapability(entry: ModelProbeEntry, send: ProbeSend): Promise<ModelProbeResult>;
|
|
224
|
-
/** 一条目录条目上本模块会碰到的两键(其余键本模块一律不认识、也不动)。 */
|
|
225
64
|
type ProbeWritableEntry = {
|
|
226
65
|
reasoning?: boolean;
|
|
227
66
|
compat?: unknown;
|
|
228
67
|
};
|
|
229
|
-
/**
|
|
230
|
-
* 把一次探测的结论落到条目上 —— **纯函数**:入参一个字节不动,返回一只新条目。
|
|
231
|
-
*
|
|
232
|
-
* 只写两键:`reasoning` 与 `compat.thinkingFormat`。条目上别的键(`name` / `tier` / `cost` /
|
|
233
|
-
* `extraBody` / `compat` 里别的位……)逐字原样带过去。
|
|
234
|
-
*
|
|
235
|
-
* 🔴 **`inconclusive` ⇒ 原样退回同一只条目**(连拷贝都不做,`===` 成立):问不出来的时候写什么
|
|
236
|
-
* 都是编。端要渲「这次没探到」就去读 `verdict`。
|
|
237
|
-
* 🔴 **`cannot_disable` ⇒ 把条目上原有的 `thinkingFormat` 删掉**,而不是留着不管。留着的后果是
|
|
238
|
-
* 双重的:引擎会继续发一种**已被实测证伪**的拼法,而目录/卡面会照那一格渲一句「思考已关」的
|
|
239
|
-
* 假话。删的只是那一键 —— `compat` 里别的位一个不动。
|
|
240
|
-
* 🔴 **`compat` 不是对象时不 spread**(wire 上什么都可能来):铸一只只带 `thinkingFormat` 的
|
|
241
|
-
* 干净新 `compat`,而不是把一段字符串摊进对象里。
|
|
242
|
-
*/
|
|
243
68
|
export declare function applyProbeToEntry<T extends ProbeWritableEntry>(entry: T, result: ModelProbeResult): T;
|
|
244
69
|
export {};
|
|
@@ -1,53 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* src/modelCapabilityProbe.ts — 一条 OpenAI-completions 车道的模型**会不会思考、关不关得掉**
|
|
3
|
-
* 的三端公共探测(0.64.0 件①)。
|
|
4
|
-
*
|
|
5
|
-
* -- 它答的是哪一问 ---------------------------------------------------------------------------
|
|
6
|
-
* 一台 vLLM/Qwen 类网关**默认就在思考**,而「关掉」这件事各家拼法不同:有的读顶层
|
|
7
|
-
* `enable_thinking`,有的只认模板参数 `chat_template_kwargs.enable_thinking`,有的要
|
|
8
|
-
* `thinking:{type:"disabled"}`。目录条目上那一格 `compat.thinkingFormat` 就是告诉引擎该用哪种
|
|
9
|
-
* 拼法 —— 而**没有人能靠看一眼型号名答出它是哪一种**。本模块把这一问变成一次可复现的探测:
|
|
10
|
-
* 发一发最小请求看它思不思考,思考就按序把每一种拼法试一遍,记下第一种真关得掉的。
|
|
11
|
-
*
|
|
12
|
-
* -- 🔴 网络那半场不在包里 --------------------------------------------------------------------
|
|
13
|
-
* 本模块**零 fetch、零 URL、零凭证**:调用方注入一只 {@link ProbeSend},自己去做鉴权与传输,
|
|
14
|
-
* 只把「答了多长的正文 / 有没有思考通道 / 什么 finish 位 / 什么状态码」交回来。理由与本包
|
|
15
|
-
* `model/catalogLoader.ts` 的 `CatalogFetchJson` 同一条:三端的凭证轨、代理、超时策略各不相同,
|
|
16
|
-
* 而**判定**是同一份 —— 判定归包,传输归端。凭证因此一个字节都不会经过本包。
|
|
17
|
-
*
|
|
18
|
-
* -- 🔴 方言闭集是**抄件**,不是本包的意见 ---------------------------------------------------
|
|
19
|
-
* 七个词的属主是引擎:`@sema-agent/core` 的 `dist/engine/llm/types.d.ts` 里
|
|
20
|
-
* `OpenAICompletionsCompat.thinkingFormat`(7.10.0 = 七词)。而 core **不是本包消费者的依赖**
|
|
21
|
-
* (既非 peer 也非 runtime dep),`.d.ts` 一旦引用它,装了本包却没装 core 的下游会当场编译不过
|
|
22
|
-
* ⇒ 与 `engineNoticeCodes.ts` / `autoModeUnavailable.ts` 同一条处置:**按真字节镜像,把代价交给
|
|
23
|
-
* 门** —— `run-model-capability-probe-test.mjs` 的 A 段对实装 devDep core 双向等值对账,
|
|
24
|
-
* 上游加一个方言这里当天先红。
|
|
25
|
-
* ⚠️ **settings-schema 那边取不到这张表,别去那儿找**:`ModelEntry.compat` 在 1.10.0 引入、2.0.0 仍是(2026-09-16 核 dist/types.d.ts)
|
|
26
|
-
* **parse-transparent 的 `z.unknown()`**,它的 JSDoc 逐字写着「the SHAPE and the VOCABULARY …
|
|
27
|
-
* are the consuming side's single point — this package deliberately does NOT restate that table」。
|
|
28
|
-
* 那一格刻意不复述词表,所以「从 settings-schema import 闭集」这条路在型面上不存在。
|
|
29
|
-
*
|
|
30
|
-
* -- 🔴 试关序是**公面承诺**,不是实现细节 ---------------------------------------------------
|
|
31
|
-
* 每多试一种拼法就是对那台网关多烧一次真钱与真时延,所以「先试哪一种」必须成文、必须被门钉死
|
|
32
|
-
* ({@link THINKING_DISABLE_PROBE_ORDER})。排序的理由是观测到的真实序列:一台 Qwen 类网关收到
|
|
33
|
-
* **顶层** `enable_thinking:false` 时,思考照旧、而正文变空 —— 换成模板参数才真的关掉。把模板形
|
|
34
|
-
* 排在前面,绝大多数这类网关一发即中。
|
|
35
|
-
* 🔴 **`openai` 不在试关序里**:它的「关」拼法是 `reasoning_effort:<thinkingLevelMap.off>`,而那张
|
|
36
|
-
* 映射表是**条目上的声明**,探针手里没有 ⇒ core 在这一形上什么都不写,发出去等于把 baseline
|
|
37
|
-
* 那一发原样再烧一次。它在本模块里的角色只有一个:关不掉时补一发 `reasoning_effort:"low"`,
|
|
38
|
-
* 看这台网关**收不收**低档旋钮({@link ModelProbeEvidence.lowEffortAccepted})。
|
|
39
|
-
* 🔴 **线上同形的两个词不各占一臂**:`zai` 与 `qwen` 铸出的请求体逐字节相同(顶层
|
|
40
|
-
* `enable_thinking`),`together` 与 `openrouter` 同理(`reasoning:{enabled:false}`)——
|
|
41
|
-
* 再烧一次往返证明不了任何新东西。对照表在 {@link THINKING_FORMAT_WIRE_TWINS};铸出的词取
|
|
42
|
-
* 每对里线上更常见的那一个,而**它们在这条轴上真的可以互换**(不是近似)。
|
|
43
|
-
*/
|
|
44
|
-
/**
|
|
45
|
-
* 引擎的**思考拼法闭集**(core `OpenAICompletionsCompat.thinkingFormat`,7.10.0 = 七词;
|
|
46
|
-
* 顺序同源)。🔴 这是一份抄件,不是本包的意见 —— 改它必须同 commit 附 core 坐标,且门会先红。
|
|
47
|
-
|
|
48
|
-
* 🔴 形制:`Object.freeze` 的数组,**不是**只在类型面只读的 `readonly T[]` —— 后者一行 `.splice()`
|
|
49
|
-
* 就能改,而公面消费者拿到的正是这个实例(本仓已定谳的病形,同 `RESUME_RETRY_LATER_CODES`)。
|
|
50
|
-
*/
|
|
51
1
|
export const THINKING_FORMATS = Object.freeze([
|
|
52
2
|
'openai',
|
|
53
3
|
'openrouter',
|
|
@@ -57,57 +7,24 @@ export const THINKING_FORMATS = Object.freeze([
|
|
|
57
7
|
'qwen',
|
|
58
8
|
'qwen-chat-template',
|
|
59
9
|
]);
|
|
60
|
-
/**
|
|
61
|
-
* 线上**逐字节同形**的方言对(`键` ⇒ 探针实际会试的那一个)。它们在这条轴上可以互换:
|
|
62
|
-
* `zai` 与 `qwen` 都写顶层 `enable_thinking`,`together` 与 `openrouter` 都写 `reasoning.enabled`。
|
|
63
|
-
* ⚠️ 只对**思考开关**这一条轴成立 —— 别把它读成「这两个词处处等价」。
|
|
64
|
-
*/
|
|
65
10
|
export const THINKING_FORMAT_WIRE_TWINS = Object.freeze({
|
|
66
11
|
zai: 'qwen',
|
|
67
12
|
together: 'openrouter',
|
|
68
13
|
});
|
|
69
|
-
/**
|
|
70
|
-
* **试关序**(公面承诺,见模块顶注)。四臂覆盖全部四种线上不同形的关拼法;`openai` 刻意不在其中。
|
|
71
|
-
* 🔴 顺序承重:模板形排第一,因为观测到的真实序列是「顶层形关不掉且把正文答空、模板形才真关掉」。
|
|
72
|
-
*/
|
|
73
14
|
export const THINKING_DISABLE_PROBE_ORDER = Object.freeze([
|
|
74
15
|
'qwen-chat-template',
|
|
75
16
|
'qwen',
|
|
76
17
|
'deepseek',
|
|
77
18
|
'openrouter',
|
|
78
19
|
]);
|
|
79
|
-
/**
|
|
80
|
-
* 一次探测的四个判词。
|
|
81
|
-
* · `no_reasoning` —— 这台网关本来就不思考(一发即知,不再烧往返);
|
|
82
|
-
* · `disabled_via` —— 会思考,而 {@link ModelProbeResult.thinkingFormat} 那一种拼法真关掉了;
|
|
83
|
-
* · `cannot_disable` —— 会思考,四种拼法**逐臂给出正面反证**(每一臂都看见思考还开着)⇒ 关不掉;
|
|
84
|
-
* · `inconclusive` —— **问不出来**(baseline 没有证据力,或**任一**试关臂没有证据力)。
|
|
85
|
-
* 🔴 `cannot_disable` 与 `inconclusive` 的边界是本模块最要紧的一条,而它锚的是**证据力**
|
|
86
|
-
* (见 `forceOf`)而不是「有没有被拒」:一臂超时、或一臂答了一条「零思考 + 正文空」的合法空
|
|
87
|
-
* 回执,那一种拼法都**没被证伪**,唯一诚实的判词是「问不出来」。这一条不是洁癖:
|
|
88
|
-
* `cannot_disable` 是 {@link applyProbeToEntry} **删掉**条目上原有 `thinkingFormat` 的唯一触发,
|
|
89
|
-
* 而那一删是**持久**的。
|
|
90
|
-
*/
|
|
91
20
|
export const MODEL_PROBE_VERDICTS = Object.freeze([
|
|
92
21
|
'no_reasoning',
|
|
93
22
|
'disabled_via',
|
|
94
23
|
'cannot_disable',
|
|
95
24
|
'inconclusive',
|
|
96
25
|
]);
|
|
97
|
-
/** 固定题面 —— 短、无歧义、任何模型都答得出,且答案长度可判。 */
|
|
98
26
|
const PROBE_PROMPT = 'Reply with exactly OK';
|
|
99
|
-
/** 输出上限:够答一句 `OK`,又不至于让一台在思考的网关烧掉一整个预算。 */
|
|
100
27
|
const PROBE_MAX_TOKENS = 64;
|
|
101
|
-
/**
|
|
102
|
-
* 铸一只探测请求体。
|
|
103
|
-
* @param entry 被探测的条目(只取 `id`)
|
|
104
|
-
* @param format 关拼法;缺席 ⇒ baseline(不带任何方言位)
|
|
105
|
-
* @param opts `reasoningEffort` = low 档探测那一发(与关拼法互斥使用)
|
|
106
|
-
*
|
|
107
|
-
* 🔴 **逐次新对象**:调用方(与门)拿到的每一只都是新的,改一只不会污染下一只。
|
|
108
|
-
* 🔴 拼法逐字同 core `dist/brain/openai.js` 的 `applyThinking` 关分支;表外词 ⇒ 不写任何方言位
|
|
109
|
-
* (**不猜**:一个猜出来的旋钮会让判定去读一台网关根本没被要求过的行为)。
|
|
110
|
-
*/
|
|
111
28
|
export function probeRequestBody(entry, format, opts) {
|
|
112
29
|
const body = {
|
|
113
30
|
model: entry.id,
|
|
@@ -137,11 +54,9 @@ export function probeRequestBody(entry, format, opts) {
|
|
|
137
54
|
body.reasoning_effort = opts.reasoningEffort;
|
|
138
55
|
return body;
|
|
139
56
|
}
|
|
140
|
-
/** 正文里有没有思考开标签(没有 `reasoning_content` 通道的网关把思考写在正文里)。 */
|
|
141
57
|
function sawThinkTagIn(content) {
|
|
142
58
|
return content.includes('<think>') || content.includes('<thinking>');
|
|
143
59
|
}
|
|
144
|
-
/** 一发的观测(零正文)。`refused` = 抛错或状态码 ≥400。 */
|
|
145
60
|
function observe(r) {
|
|
146
61
|
const content = typeof r.content === 'string' ? r.content : '';
|
|
147
62
|
const reasoning = typeof r.reasoningContent === 'string' ? r.reasoningContent : '';
|
|
@@ -155,68 +70,31 @@ function observe(r) {
|
|
|
155
70
|
refused: typeof r.status === 'number' && Number.isFinite(r.status) && r.status >= 400,
|
|
156
71
|
};
|
|
157
72
|
}
|
|
158
|
-
/** 被拒的一发(`send` 抛了)——长度位如实为零,`refused` 为真。 */
|
|
159
73
|
function refusedObservation() {
|
|
160
74
|
return { contentLen: 0, hasText: false, reasoningLen: 0, sawThinkTag: false, refused: true };
|
|
161
75
|
}
|
|
162
|
-
/** 发一发,把抛错折成一次被拒的观测(🔴 探针答的是一个判词,不是一次崩)。 */
|
|
163
76
|
async function sendOnce(send, body) {
|
|
164
77
|
try {
|
|
165
78
|
return observe(await send(body));
|
|
166
79
|
}
|
|
167
80
|
catch {
|
|
168
|
-
// 🔴 刻意不留错误对象:它可能带 URL、请求头、乃至凭证片段([credential-error-path-leak]),
|
|
169
|
-
// 而本模块的证据面承诺过「可以整只进日志与工单」。归因靠端自己的传输日志。
|
|
170
81
|
return refusedObservation();
|
|
171
82
|
}
|
|
172
83
|
}
|
|
173
84
|
function forceOf(o) {
|
|
174
85
|
if (o.refused)
|
|
175
86
|
return 'moot';
|
|
176
|
-
// 思考的正面证据一到手就成立 —— 截断与否都不影响(见上面的 ⚠️)。
|
|
177
87
|
if (o.reasoningLen > 0 || o.sawThinkTag)
|
|
178
88
|
return 'on';
|
|
179
|
-
// 🔴 **正文空 / 纯空白 ⇒ moot,不是 off**:观测到的真实序列里,一台 Qwen 网关收到不认识的顶层
|
|
180
|
-
// 旋钮时会把思考留着、正文答空;而「零思考 + 正文空」同样出现在一次被截断的应答上。一个把话
|
|
181
|
-
// 答没了的旋钮不是「关掉了思考」—— 收它进来会让探针假阳,而假阳的代价是条目上落一个错的
|
|
182
|
-
// `thinkingFormat`,此后每一次真对话都发一种这台网关不认的拼法。
|
|
183
89
|
if (!o.hasText)
|
|
184
90
|
return 'moot';
|
|
185
|
-
// 🔴 **被截断 ⇒ moot**:`finish_reason: "length"` 说的是「这一发没答完」。本探针的 `max_tokens`
|
|
186
|
-
// 只有 64,一台在思考的网关很容易先烧完额度再被截掉 —— 那时思考通道可能一个字都没送出来。
|
|
187
|
-
// **按开集读**:只认上游明说的这一个词,别的词(含缺席 —— 端没报)一律不当截断,否则不报
|
|
188
|
-
// finish 位的宿主会永远拿不到 `off`。
|
|
189
91
|
if (o.finishReason === 'length')
|
|
190
92
|
return 'moot';
|
|
191
93
|
return 'off';
|
|
192
94
|
}
|
|
193
|
-
/**
|
|
194
|
-
* 探测一个条目:会不会思考、关不关得掉、用哪种拼法关。
|
|
195
|
-
*
|
|
196
|
-
* 步骤(每一步都可能是最后一步 —— 能少烧一次往返就少烧一次):
|
|
197
|
-
* ① baseline:最小请求,不带任何方言位。
|
|
198
|
-
* · **没有证据力**(被拒,或「零思考 + 正文也空」的合法空回执)⇒ `inconclusive`,
|
|
199
|
-
* **结果里没有 `reasoning` 这一格**(问不出来 ≠ 不思考);
|
|
200
|
-
* · **正面证据**「正文非空且零思考」⇒ `no_reasoning`,收工(不再烧任何往返)。
|
|
201
|
-
* ② 按 {@link THINKING_DISABLE_PROBE_ORDER} 逐臂试关,第一个 {@link thinkingIsOff} 成立的
|
|
202
|
-
* 拼法就是答案 ⇒ `disabled_via`,收工。
|
|
203
|
-
* ③ 四臂都没关掉:
|
|
204
|
-
* · **每一臂都给出正面反证**(都看见思考还开着)⇒ `cannot_disable`,并补一发
|
|
205
|
-
* `reasoning_effort:"low"` 记下这台网关收不收低档旋钮(端据此渲「会思考、当前关不掉;
|
|
206
|
-
* 席位将按 low 档运行」);
|
|
207
|
-
* · **任一臂没有证据力**(被拒,或空回执)⇒ `inconclusive` —— 那一种拼法没被证伪,
|
|
208
|
-
* 「问不出来」不是「关不掉」。这一形上 `reasoning` 那一格**在场且为真**(baseline 是
|
|
209
|
-
* 问出来了的),而证据里逐臂留着每一发的长度与状态,端可以据此只重试那一臂。
|
|
210
|
-
*
|
|
211
|
-
* @param entry 被探测的条目
|
|
212
|
-
* @param send 网络端口(端自备鉴权与传输;本包零 fetch)
|
|
213
|
-
*/
|
|
214
95
|
export async function probeModelCapability(entry, send) {
|
|
215
96
|
const baseline = await sendOnce(send, probeRequestBody(entry));
|
|
216
97
|
const baseForce = forceOf(baseline);
|
|
217
|
-
// 🔴 **`moot` 的 baseline 什么都不写**:被拒、或一条「零思考 + 正文空」的合法回执 —— 后者
|
|
218
|
-
// (`{content:'', finishReason:'length'}`)修前被判 `no_reasoning` 并把 `reasoning:false`
|
|
219
|
-
// 写进条目,等于用一次空回执覆盖一份原本正确的能力声明(异源复审 r1 finding② 的真病)。
|
|
220
98
|
if (baseForce === 'moot') {
|
|
221
99
|
return { verdict: 'inconclusive', evidence: { baseline, attempts: [] } };
|
|
222
100
|
}
|
|
@@ -234,11 +112,6 @@ export async function probeModelCapability(entry, send) {
|
|
|
234
112
|
return { reasoning: true, thinkingFormat: format, verdict: 'disabled_via', evidence: { baseline, attempts } };
|
|
235
113
|
}
|
|
236
114
|
}
|
|
237
|
-
// 🔴 「四种拼法都试过、都关不掉」这句话要成立,四臂就得**逐臂给出正面反证**(每一臂都真的看见
|
|
238
|
-
// 思考还开着)—— 不只是「没被拒」(异源复审 r1 finding① 的两个形):一臂超时,那一种拼法
|
|
239
|
-
// 压根没被证伪;四臂全是空回执,那四发一个字都没证明。这一条不是洁癖:`cannot_disable` 是
|
|
240
|
-
// `applyProbeToEntry` **删掉**条目上原有 `thinkingFormat` 的唯一触发,而那一删是**持久**的
|
|
241
|
-
// —— 让一次偶发的超时或空回执去抹掉一份正确配置,是本探针能犯的最贵的错。
|
|
242
115
|
if (!forces.every((f) => f === 'on')) {
|
|
243
116
|
return { reasoning: true, verdict: 'inconclusive', evidence: { baseline, attempts } };
|
|
244
117
|
}
|
|
@@ -249,20 +122,6 @@ export async function probeModelCapability(entry, send) {
|
|
|
249
122
|
evidence: { baseline, attempts, lowEffortAccepted: !low.refused },
|
|
250
123
|
};
|
|
251
124
|
}
|
|
252
|
-
/**
|
|
253
|
-
* 把一次探测的结论落到条目上 —— **纯函数**:入参一个字节不动,返回一只新条目。
|
|
254
|
-
*
|
|
255
|
-
* 只写两键:`reasoning` 与 `compat.thinkingFormat`。条目上别的键(`name` / `tier` / `cost` /
|
|
256
|
-
* `extraBody` / `compat` 里别的位……)逐字原样带过去。
|
|
257
|
-
*
|
|
258
|
-
* 🔴 **`inconclusive` ⇒ 原样退回同一只条目**(连拷贝都不做,`===` 成立):问不出来的时候写什么
|
|
259
|
-
* 都是编。端要渲「这次没探到」就去读 `verdict`。
|
|
260
|
-
* 🔴 **`cannot_disable` ⇒ 把条目上原有的 `thinkingFormat` 删掉**,而不是留着不管。留着的后果是
|
|
261
|
-
* 双重的:引擎会继续发一种**已被实测证伪**的拼法,而目录/卡面会照那一格渲一句「思考已关」的
|
|
262
|
-
* 假话。删的只是那一键 —— `compat` 里别的位一个不动。
|
|
263
|
-
* 🔴 **`compat` 不是对象时不 spread**(wire 上什么都可能来):铸一只只带 `thinkingFormat` 的
|
|
264
|
-
* 干净新 `compat`,而不是把一段字符串摊进对象里。
|
|
265
|
-
*/
|
|
266
125
|
export function applyProbeToEntry(entry, result) {
|
|
267
126
|
if (result.verdict === 'inconclusive')
|
|
268
127
|
return entry;
|
|
@@ -278,14 +137,8 @@ export function applyProbeToEntry(entry, result) {
|
|
|
278
137
|
if (result.verdict === 'cannot_disable') {
|
|
279
138
|
if (compatIn === undefined)
|
|
280
139
|
return { ...entry, reasoning: true };
|
|
281
|
-
// 🔴 **不用 `rest[k] = v` 裸下标**(异源对抗复审 r1 采纳的真病):`compat` 是从配置/wire 来的,
|
|
282
|
-
// 而 `JSON.parse('{"__proto__":{}}')` 造得出一个**自有** `__proto__` 键 —— 裸下标赋值会命中
|
|
283
|
-
// `Object.prototype` 上的 setter:那一键被静默丢掉,**而新对象的原型被换掉**。
|
|
284
|
-
// `Object.fromEntries` 走 CreateDataProperty,建的是自有属性,两个后果都不会发生
|
|
285
|
-
// (同理,本文件别处的对象展开 `{...}` 也是安全的 —— 出问题的只有下标赋值这一种写法)。
|
|
286
140
|
const rest = Object.fromEntries(Object.entries(compatIn).filter(([k]) => k !== 'thinkingFormat'));
|
|
287
141
|
return { ...entry, reasoning: true, compat: rest };
|
|
288
142
|
}
|
|
289
|
-
// 表外判词(一个比这一端新的词)⇒ 什么都不写,与 `inconclusive` 同一条纪律。
|
|
290
143
|
return entry;
|
|
291
144
|
}
|
package/dist/modelWireCaps.d.ts
CHANGED
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/modelWireCaps.ts 逐字搬入(零依赖)。
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* src/sema/modelWireCaps.ts — PURE per-turn /model projection (CC /model picker parity). seamQuery imports it.
|
|
6
|
-
*
|
|
7
|
-
* The mid-session model lives at `AppState`/`toolUseContext.options.mainLoopModel` (the /model picker writes it,
|
|
8
|
-
* query.ts). sema's engine ALREADY consumes a top-level `body.model` (service resolveTaskModel main.ts:1217 →
|
|
9
|
-
* core `TaskSpec.model`, catalog-gated, body.model wins over @mention wins over default). Without this wire a
|
|
10
|
-
* mid-session /model switch did NOTHING on the live engine (the survey's biggest functional hole). config-class
|
|
11
|
-
* intent → tighten/select only (the service catalog-gates an out-of-roster pick), so it rides the wire directly.
|
|
12
|
-
*/
|
|
13
1
|
export interface ModelField {
|
|
14
2
|
model?: string;
|
|
15
3
|
}
|
|
16
|
-
/** Project the client's selected model → the wire intent. Non-empty string carried verbatim; else no stamp. */
|
|
17
4
|
export declare function modelFromAppState(model: string | undefined): ModelField;
|
package/dist/modelWireCaps.js
CHANGED
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/modelWireCaps.ts 逐字搬入(零依赖)。
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* src/sema/modelWireCaps.ts — PURE per-turn /model projection (CC /model picker parity). seamQuery imports it.
|
|
6
|
-
*
|
|
7
|
-
* The mid-session model lives at `AppState`/`toolUseContext.options.mainLoopModel` (the /model picker writes it,
|
|
8
|
-
* query.ts). sema's engine ALREADY consumes a top-level `body.model` (service resolveTaskModel main.ts:1217 →
|
|
9
|
-
* core `TaskSpec.model`, catalog-gated, body.model wins over @mention wins over default). Without this wire a
|
|
10
|
-
* mid-session /model switch did NOTHING on the live engine (the survey's biggest functional hole). config-class
|
|
11
|
-
* intent → tighten/select only (the service catalog-gates an out-of-roster pick), so it rides the wire directly.
|
|
12
|
-
*/
|
|
13
|
-
/** Project the client's selected model → the wire intent. Non-empty string carried verbatim; else no stamp. */
|
|
14
1
|
export function modelFromAppState(model) {
|
|
15
2
|
return typeof model === 'string' && model.trim().length > 0 ? { model: model.trim() } : {};
|
|
16
3
|
}
|