@sema-agent/client-core 0.77.1 → 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 +13 -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 +0 -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 +6 -498
- 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 +6 -67
- package/dist/subagent/engineTaskHandleWire.js +0 -126
- 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 +30 -1
- package/package.json +1 -1
package/dist/liveInitToolFace.js
CHANGED
|
@@ -1,72 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ⇄ B6 批搬迁(2026-07-27,设计稿 §3 B6 · B2 判给后批的**宿主耦合六件**之一):cli
|
|
3
|
-
* `src/sema/liveInitToolFace.ts` 整搬。B2 当时不搬的理由 = 它 `await import('./engineTarget.js')`
|
|
4
|
-
* 取凭证,而 engineTarget 是 fs 重图;B4 的 §8-2 收编把凭证解析定到了 `resolveWireAuth`
|
|
5
|
-
* (engineWireSdk,零依赖),那条理由随之消失。
|
|
6
|
-
*
|
|
7
|
-
* 🔴 搬迁三处差分(行为一字节不变):
|
|
8
|
-
* ① 凭证:`engineTarget.resolveLiveAuthToken(baseUrl)`(其 token 缺省 = `process.env.SEMA_LIVE_TOKEN`)
|
|
9
|
-
* → `resolveWireAuth(baseUrl, env.SEMA_LIVE_TOKEN)`。两者是同一套 #118 三态,`resolveWireAuth`
|
|
10
|
-
* 的头注自述就是它的收编口。取值面完全一致:三态里只有**真 token 串**与 `'anon'` 是 string,
|
|
11
|
-
* `{mode:'loopback-unauthed'}` 是对象 ⇒ 原文那句 `typeof t === 'string' ? t : undefined` 语义照搬。
|
|
12
|
-
* ② 三个 `await import('./xxxWire.js')` fail-soft 动态 import → **静态 import**(scenarioWire /
|
|
13
|
-
* interactiveToolsWire / webSearchWireCaps 三件 B5 都已在本包内)。原文那三层 try/catch 的
|
|
14
|
-
* 目的是「模块缺席也别挡首帧」,包内它们不可能缺席;**try/catch 仍逐条保留**——它护的另一半是
|
|
15
|
-
* 「函数自己抛」,那半在包内照样成立。
|
|
16
|
-
* ③ `process.env` → 入参 `EnvLike`(签名本来就显式收 env;缺省值不存在,调用方必传)。
|
|
17
|
-
*
|
|
18
|
-
* 🔴 模块级状态:`cached`(baseUrl+scenario+旋钮 键控的一次性探测缓存)。写读口都在本文件;
|
|
19
|
-
* 两份实例只是多探一次(不是静默失效),但仍登记进单实例清单。
|
|
20
|
-
*
|
|
21
|
-
* ── 以下为原文件的领域说明(逐字保留)────────────────────────────────────────────────────────
|
|
22
|
-
*
|
|
23
|
-
* liveInitToolFace — 件1(core [931] 壳半场):headless `-p` live 车道 `system/init` 首帧的
|
|
24
|
-
* `tools` 自报面,从「壳静态工具表」改为「引擎实挂 wire 词表」生成。
|
|
25
|
-
*
|
|
26
|
-
* 根因(core [931]/CC209 裁决):壳自报静态表(TodoWrite 在、TaskCreate 族不在)而引擎 wire 实挂
|
|
27
|
-
* TaskCreate 族(core 1.296+ 默认)且不挂 TodoWrite ⇒ SDK/自动化消费者照自报面配
|
|
28
|
-
* `--disallowedTools TodoWrite` 之类静默无效(fail-open)。core 1.300 已在引擎侧加名单池审计
|
|
29
|
-
* advisory(config.toolpolicy.unmatched_names)兜观测面;这里是壳半场 = 自报按实挂生成。
|
|
30
|
-
*
|
|
31
|
-
* 真源层级(gap-check 2026-07-16 实测读数,server 1.214.0 / core 1.300.0):
|
|
32
|
-
* 1. server 无全量挂载探测面:GET /v1/capabilities 只有能力布尔;
|
|
33
|
-
* GET /v1/capabilities/scenarios/:name 只含【场景附加】工具(default/code →
|
|
34
|
-
* Now/WebFetch/Agent/TaskCreate 族七具),首方 band(Bash/Read/…)由 core prepare-task
|
|
35
|
-
* 另挂、不进该面 ⇒ 整表无法远端取。
|
|
36
|
-
* 2. 故缺省场景用壳已知 wire 词表(下表):观测 tap 记录壳 `-p` live 车道 LLM 请求体
|
|
37
|
-
* tools[].name(REMOTE_EXEC=host 生产姿势)实测定稿,再按壳自己 stamp 的请求旋钮修正
|
|
38
|
-
* (interactiveTools≠false → AskUserQuestion;settings.webSearch 在 → WebSearch)。
|
|
39
|
-
* 3. per-scenario 差异如实标注:非缺省 scenario(--scenario/SEMA_HEADLESS_SCENARIO)的工具面
|
|
40
|
-
* 由部署定义(scan/oa = repo-readonly 面,首方 band 是否在位壳无法确证)⇒ 尽力探场景详情面
|
|
41
|
-
* GET /v1/capabilities/scenarios/:name 报【场景附加】工具 + runner 恒挂段,并经
|
|
42
|
-
* SEMA_DEBUG 如实标注是探测面而非整表;探测失败回退缺省词表(fail-soft,绝不阻塞首帧)。
|
|
43
|
-
* 4. mock/离线车道(无 SEMA_LIVE_BASEURL)返回 null,调用方保持现状静态表 —— 宪法三问的
|
|
44
|
-
* 补偿轴:离线态回退静态表,行为字节不变。
|
|
45
|
-
*
|
|
46
|
-
* 已知局限(如实):词表按 pin 的 server/core 版本定稿,外接旧引擎或无执行底座的 worker
|
|
47
|
-
* (REMOTE_EXEC 缺省的裸 worker 不挂 hands band)会有偏差 —— 但相比旧静态表(TodoWrite 幻影 +
|
|
48
|
-
* TaskCreate 族缺席)已是严格更准的自报;整表探测面等引擎侧补(见 [931] 报告)。
|
|
49
|
-
*/
|
|
50
1
|
import { makeEngineWireClient, resolveWireAuth } from './engineWireSdk.js';
|
|
51
2
|
import { hostLog } from './host.js';
|
|
52
3
|
import { scenarioForPrint } from './scenarioWire.js';
|
|
53
4
|
import { resolveHeadlessInteractiveTools } from './interactiveToolsWire.js';
|
|
54
5
|
import { webSearchFromEnv } from './webSearchWireCaps.js';
|
|
55
|
-
// ── 🔴 退役条款(0.63.0 / L-161 登记;engine ≥7.66.0 有名册,≥7.9.0 才真推)──────────────────
|
|
56
|
-
// 下面三张表(`ENGINE_HANDS_BAND` / `ENGINE_SCENARIO_EXTRAS_DEFAULT` / `ENGINE_RUNNER_FACE`)是
|
|
57
|
-
// **估计值**:2026-07-16 一次 tap 实测按当时 pin 的引擎版本定稿,外接别的引擎、别的场景、别的
|
|
58
|
-
// env 门就会偏(文件头「已知局限」段自己写着这一条)。它们的继任者是引擎**自己说的**那份东西 ——
|
|
59
|
-
// `wiring_manifest.tools` 上的工具名册(本包 `toolRoster.ts`:`projectToolRoster` /
|
|
60
|
-
// `toolRosterNames` / `toolShimFromRoster`),那里有每只工具的身份、轴与面,不用按名字猜。
|
|
61
|
-
//
|
|
62
|
-
// **本批刻意不删表**,因为回落还得留着:名册只在 **effective 半场**(live 帧)铸,而本函数跑在
|
|
63
|
-
// 首帧之前走的是 HTTP 探测面;且只有 ≥7.9.0 的引擎才真推那条帧。⇒ 现役姿势 =
|
|
64
|
-
// **名册在场用名册,缺席才回落这三张表**,装配在宿主(它才拿得到帧流)。
|
|
65
|
-
// 退役条件(满足即删这三张表 + 删掉本段):**名册恒在场**的引擎版本成为支持底线。
|
|
66
|
-
// ⚠️ 删表时连 `runnerFaceForEnv` 的 env 门一起删 —— 那道门也是在补估计值的偏,名册在场时它是
|
|
67
|
-
// 第二份台账(引擎已经按 env 门算过一遍才铸的名册)。
|
|
68
|
-
// ── 壳已知 wire 词表(tap 实测 2026-07-16,server 1.214.0/core 1.300.0,壳 -p 缺省旋钮)──────────
|
|
69
|
-
/** hands band(本地/远程执行底座在位时 prepare-task 挂载;壳自 spawn 恒 REMOTE_EXEC=host ⇒ 在位)。 */
|
|
70
6
|
export const ENGINE_HANDS_BAND = [
|
|
71
7
|
'Bash',
|
|
72
8
|
'Read',
|
|
@@ -81,10 +17,6 @@ export const ENGINE_HANDS_BAND = [
|
|
|
81
17
|
'ExitWorktree',
|
|
82
18
|
'Monitor',
|
|
83
19
|
];
|
|
84
|
-
/** 缺省(code/default)场景附加段 —— 与 GET /v1/capabilities/scenarios/{code,default} 详情面
|
|
85
|
-
* 实测逐字一致(场景工厂 nowTool + assembleFullBodyTools)。
|
|
86
|
-
* ⚠️ TodoWrite 故意不在(core 1.296+ 默认 taskList:true ⇒ TodoWrite 不挂,[931] 本案根因);
|
|
87
|
-
* TaskCreate 族在 —— 这两条就是本修要对齐的实况。 */
|
|
88
20
|
export const ENGINE_SCENARIO_EXTRAS_DEFAULT = [
|
|
89
21
|
'Now',
|
|
90
22
|
'WebFetch',
|
|
@@ -94,10 +26,6 @@ export const ENGINE_SCENARIO_EXTRAS_DEFAULT = [
|
|
|
94
26
|
'TaskUpdate',
|
|
95
27
|
'TaskList',
|
|
96
28
|
];
|
|
97
|
-
/** runner 恒挂段(prepare-task 按请求旋钮挂载、场景无关):壳 `-p` 恒 stamp
|
|
98
|
-
* selfOrchestration→Workflow、attachments.backgroundTasks→TaskOutput/TaskStop/Monitor/
|
|
99
|
-
* SendMessage/AgentTranscript;ReadToolResult/ReportBlocked/ReportFindings/Skill/Cron 族/
|
|
100
|
-
* ScheduleWakeup 为 runner 缺省注入。 */
|
|
101
29
|
export const ENGINE_RUNNER_FACE = [
|
|
102
30
|
'AgentTranscript',
|
|
103
31
|
'CronCreate',
|
|
@@ -111,14 +39,9 @@ export const ENGINE_RUNNER_FACE = [
|
|
|
111
39
|
'Skill',
|
|
112
40
|
'TaskOutput',
|
|
113
41
|
'TaskStop',
|
|
114
|
-
// [1870] L2 半条(0.11.1):deferred-tools 取回工具,runner 恒挂——引擎对模型的真实请求
|
|
115
|
-
// 恒声明它(sema-test repro A2 双向断言实证),此前自报面漏它=显示轨迹失真误导归因。
|
|
116
42
|
'ToolSearch',
|
|
117
43
|
'Workflow',
|
|
118
44
|
];
|
|
119
|
-
/** [1036]/clay 裁:runner 恒挂段按壳已知 env 门过滤——print 宿主前置 SCHEDULER_ENABLED=false
|
|
120
|
-
* (scheduler 族 headless 不挂)/SELF_ORCHESTRATION_ENABLED=false(Workflow 卸)时,自报面
|
|
121
|
-
* 必须跟实挂(此前静态词表在 env 门形态失真=自报 32 实挂 28,消融实测逮到)。 */
|
|
122
45
|
export function runnerFaceForEnv(env) {
|
|
123
46
|
let face = [...ENGINE_RUNNER_FACE];
|
|
124
47
|
if (env.SCHEDULER_ENABLED === 'false') {
|
|
@@ -129,18 +52,10 @@ export function runnerFaceForEnv(env) {
|
|
|
129
52
|
}
|
|
130
53
|
return face;
|
|
131
54
|
}
|
|
132
|
-
// 按 baseUrl+scenario 缓存(多 turn headless 会话只付一次探测;词表车道零 IO 本就便宜,统一缓存简单)。
|
|
133
55
|
let cached = null;
|
|
134
|
-
/** 测试钩子:清缓存。 */
|
|
135
56
|
export function _resetLiveInitToolFaceForTest() {
|
|
136
57
|
cached = null;
|
|
137
58
|
}
|
|
138
|
-
/** 非缺省场景的详情面探测:SDK 0.0.52 scenarioCapabilities(name)(GET /v1/capabilities/scenarios/:name,
|
|
139
|
-
* 同 wire 同 encodeURIComponent)→ { tools(场景附加段), toolset }。fail-soft:任何失败(网络/404/
|
|
140
|
-
* 形状不符/超时)返回 null,调用层回退缺省词表。等价性记账:超时经 client timeoutMs(缺省 2s 同预算,
|
|
141
|
-
* maxRetries=0 单发同原语义);ScenarioDetail 类型面之外仍保留逐字段运行时校验(引擎回什么不轻信)。
|
|
142
|
-
* principal 头:SDK 6.11 起值检查删头(缺席不发;F-011 停发后单机形恒缺席)——原手抄在无 principal
|
|
143
|
-
* 时省略该头;principal-first 宪法姿势,对 requirePrincipal 部署是 fail-open 改善。 */
|
|
144
59
|
export async function probeScenarioTools(baseUrl, scenario, opts) {
|
|
145
60
|
const client = makeEngineWireClient({
|
|
146
61
|
baseUrl,
|
|
@@ -167,21 +82,11 @@ export async function probeScenarioTools(baseUrl, scenario, opts) {
|
|
|
167
82
|
return null;
|
|
168
83
|
}
|
|
169
84
|
}
|
|
170
|
-
/**
|
|
171
|
-
* resolveLiveInitToolFace — live 车道 init 首帧 `tools` 的实挂投影。
|
|
172
|
-
* · 无 SEMA_LIVE_BASEURL ⇒ null(mock/离线车道,调用方维持静态表现状);
|
|
173
|
-
* · 缺省场景 ⇒ hands band + runner 恒挂段 + 旋钮修正(词表车道,零 IO);
|
|
174
|
-
* · 非缺省场景 ⇒ 详情面探测成功用【场景附加 + runner 恒挂】(如实标注:hands band 是否在位
|
|
175
|
-
* 由部署定,不妄报),失败回退缺省词表;
|
|
176
|
-
* · 任何内部错误 fail-soft 返回 null(调用方回退静态表,首帧永不因此缺席)。
|
|
177
|
-
*/
|
|
178
85
|
export async function resolveLiveInitToolFace(argv, env, opts) {
|
|
179
86
|
const baseUrl = env.SEMA_LIVE_BASEURL;
|
|
180
87
|
if (!baseUrl)
|
|
181
88
|
return null;
|
|
182
89
|
try {
|
|
183
|
-
// 场景解析(scenarioWire 同源:flag > SEMA_HEADLESS_SCENARIO;非法 flag 在 seamQueryEngine
|
|
184
|
-
// 已 fail-loud 退出,这里只可能看到合法值或解析失败 → 按缺省处理)。
|
|
185
90
|
let scenario;
|
|
186
91
|
try {
|
|
187
92
|
const sc = scenarioForPrint([...argv], env);
|
|
@@ -189,47 +94,36 @@ export async function resolveLiveInitToolFace(argv, env, opts) {
|
|
|
189
94
|
scenario = sc.scenario;
|
|
190
95
|
}
|
|
191
96
|
catch {
|
|
192
|
-
/* fail-soft → 缺省场景 */
|
|
193
97
|
}
|
|
194
|
-
// 旋钮修正① interactiveTools:壳 `-p` 缺省 stamp false ⇒ AskUserQuestion 不挂;
|
|
195
|
-
// 显式交互意图(--permission-mode plan)/部署旋钮开 ⇒ 引擎缺省挂。
|
|
196
98
|
let askUserQuestion = false;
|
|
197
99
|
try {
|
|
198
100
|
const r = resolveHeadlessInteractiveTools([...argv], env);
|
|
199
101
|
askUserQuestion = r.fields.interactiveTools !== false;
|
|
200
102
|
}
|
|
201
103
|
catch {
|
|
202
|
-
/* fail-soft → 按缺省 stamp false,不报 AskUserQuestion */
|
|
203
104
|
}
|
|
204
|
-
// 旋钮修正② webSearch:壳发 settings.webSearch 时 server 才组 WebSearch 后端
|
|
205
|
-
// (seamQueryEngine `-p` 车道同源 = env 面 webSearchFromEnv)。
|
|
206
105
|
let webSearch = false;
|
|
207
106
|
try {
|
|
208
107
|
webSearch = webSearchFromEnv(env) !== undefined;
|
|
209
108
|
}
|
|
210
109
|
catch {
|
|
211
|
-
/* fail-soft → 不报 WebSearch */
|
|
212
110
|
}
|
|
213
111
|
const knobTools = [
|
|
214
112
|
...(askUserQuestion ? ['AskUserQuestion'] : []),
|
|
215
113
|
...(webSearch ? ['WebSearch'] : []),
|
|
216
114
|
];
|
|
217
|
-
// 缓存键含旋钮(argv/env 同进程内稳定,但键面完备防同进程内旋钮变化的陈旧命中)。
|
|
218
115
|
const key = `${baseUrl}::${scenario ?? ''}::${askUserQuestion ? 'q' : ''}${webSearch ? 'w' : ''}::${env.SCHEDULER_ENABLED === 'false' ? 'ns' : ''}${env.SELF_ORCHESTRATION_ENABLED === 'false' ? 'nw' : ''}`;
|
|
219
116
|
if (cached && cached.key === key)
|
|
220
117
|
return cached.face;
|
|
221
118
|
let names;
|
|
222
119
|
let source = 'wire-vocabulary';
|
|
223
120
|
if (scenario) {
|
|
224
|
-
// 非缺省场景:详情面探测(场景附加段真源)。auth 同 live 车道纪律(#118 三态;
|
|
225
|
-
// loopback-unauthed ⇒ 不出示 bearer —— 对象形不是 string,下面那句照原文过滤掉)。
|
|
226
121
|
let authToken;
|
|
227
122
|
try {
|
|
228
123
|
const t = resolveWireAuth(baseUrl, env.SEMA_LIVE_TOKEN);
|
|
229
124
|
authToken = typeof t === 'string' ? t : undefined;
|
|
230
125
|
}
|
|
231
126
|
catch {
|
|
232
|
-
/* fail-soft → 无 token 探测 */
|
|
233
127
|
}
|
|
234
128
|
const probed = await probeScenarioTools(baseUrl, scenario, {
|
|
235
129
|
...(opts?.fetchImpl ? { fetchImpl: opts.fetchImpl } : {}),
|
|
@@ -238,8 +132,6 @@ export async function resolveLiveInitToolFace(argv, env, opts) {
|
|
|
238
132
|
...(env.SEMA_LIVE_PRINCIPAL ? { principal: env.SEMA_LIVE_PRINCIPAL } : {}),
|
|
239
133
|
});
|
|
240
134
|
if (probed) {
|
|
241
|
-
// 如实标注:场景附加(探测面)+ runner 恒挂段;hands band 只在详情面自证 full-body 时
|
|
242
|
-
// 才报(repo-readonly 等场景不挂首方 band,不妄报)。
|
|
243
135
|
const handsBand = probed.toolset === 'full-body' ? ENGINE_HANDS_BAND : [];
|
|
244
136
|
names = [...new Set([...probed.tools, ...handsBand, ...runnerFaceForEnv(env), ...knobTools])];
|
|
245
137
|
source = 'scenario-probe';
|
|
@@ -262,6 +154,6 @@ export async function resolveLiveInitToolFace(argv, env, opts) {
|
|
|
262
154
|
return face;
|
|
263
155
|
}
|
|
264
156
|
catch {
|
|
265
|
-
return null;
|
|
157
|
+
return null;
|
|
266
158
|
}
|
|
267
159
|
}
|
|
@@ -1,76 +1,24 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/liveModelCatalog.ts 逐字搬入(零依赖;🔴 catalog/refresher 是单实例态 —— 写口 setLiveModelCatalog/installer 与读口 getLiveModelCatalog 必须同实例)。
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* src/sema/liveModelCatalog.ts — the LIVE model-catalog singleton (TEAM-C / clay decision #1 = A).
|
|
6
|
-
*
|
|
7
|
-
* WHY THIS FILE EXISTS
|
|
8
|
-
* --------------------
|
|
9
|
-
* The `/model` picker, the header model line, the /status "Model" row, and the picker's ✔ are all stuck on
|
|
10
|
-
* a STATIC opus[1m] / a STATIC fictional catalog (mock/control/modelOptionsSeam.ts). The live engine actually
|
|
11
|
-
* serves a different fleet — `client.models.list()` returns `{ models, default }` (the REAL catalog), and
|
|
12
|
-
* `done.result.model` echoes the REAL served model (MF-25). This module is the one-shot, process-wide bridge
|
|
13
|
-
* between the LIVE wire read (done once at boot in replEntry's live block) and the SYNCHRONOUS render-time
|
|
14
|
-
* readers (getModelOptions, called inside the picker's React render — it cannot await).
|
|
15
|
-
*
|
|
16
|
-
* SINGLE INSTANCE (build discipline): replEntry.tsx (build-src/src/sema/replEntry.tsx) SETS the catalog and
|
|
17
|
-
* mock/control/modelOptionsSeam.ts (build-src/mock/control/…, the aliased getModelOptions target) READS it.
|
|
18
|
-
* Both resolve this module to ONE staged path (build-src/src/sema/liveModelCatalog.ts), so the singleton is
|
|
19
|
-
* shared — the same single-instance invariant the seam-module fix in scripts/build.sema.mjs guarantees.
|
|
20
|
-
*
|
|
21
|
-
* MOCK PATH UNCHANGED: with SEMA_LIVE_BASEURL unset, no one calls setLiveModelCatalog → the catalog stays
|
|
22
|
-
* null → getModelOptions falls back to the static fleetModels mock and the boot keeps opus[1m]. So the
|
|
23
|
-
* cell-exact mock parity (the /model picker mock rows, the opus[1m] header/status, the /context 20-glyph
|
|
24
|
-
* grid driven by has1mContext('opus[1m]')) is preserved byte-for-byte.
|
|
25
|
-
*/
|
|
26
|
-
/** The neutral wire shape of one model-catalog row (a structural subset of @sema-ai/sdk ModelInfo +
|
|
27
|
-
* mock/control/modelSelect.ts ModelInfo — name/id/provider/reasoning/vision drive the picker badges). */
|
|
28
1
|
export interface LiveModelInfo {
|
|
29
2
|
name: string;
|
|
30
3
|
id?: string;
|
|
31
4
|
provider?: string;
|
|
32
5
|
reasoning?: boolean;
|
|
33
6
|
vision?: boolean;
|
|
34
|
-
/** sdk `ModelInfo.routePairing`(#345,server ≥7.45 恒在场;真开集):这一行的 key↔URL 配对姿态;读法用 {@link routePairingVerdict}。 */
|
|
35
7
|
routePairing?: string;
|
|
36
8
|
[k: string]: unknown;
|
|
37
9
|
}
|
|
38
|
-
/** The `GET /v1/models` envelope: the catalog rows + the deployment default model id (display-only). */
|
|
39
10
|
export interface LiveModelCatalog {
|
|
40
11
|
models: LiveModelInfo[];
|
|
41
|
-
/** The served-by-default model id (models.list().default) — the boot mainLoopModel + the picker default desc. */
|
|
42
12
|
default: string;
|
|
43
13
|
}
|
|
44
|
-
/** Install the live catalog (called once at boot from replEntry's live block). null clears it. */
|
|
45
14
|
export declare function setLiveModelCatalog(next: LiveModelCatalog | null): void;
|
|
46
|
-
/** boot 注册的重取器(与 boot fetch 同参)。k3 案(clay 2026-07-20):/config 改 Model ID 后
|
|
47
|
-
* 同会话 /model 仍显旧目录名——目录只在 boot 拉一次。Hub 保存/面板打开时经此重取。 */
|
|
48
15
|
export declare function setLiveModelCatalogRefresher(fn: (() => Promise<LiveModelCatalog | null>) | null): void;
|
|
49
|
-
/** Re-fetch the live catalog (boot 参数);成功即替换 singleton 并返回 true。mock 路径(无
|
|
50
|
-
* refresher)/拉取失败 → false,现值不动(fail-soft,绝不用 null 清掉可用旧目录)。 */
|
|
51
16
|
export declare function refreshLiveModelCatalog(): Promise<boolean>;
|
|
52
|
-
/** Read the live catalog (null = mock path / live read failed → callers fall back to the static mock). */
|
|
53
17
|
export declare function getLiveModelCatalog(): LiveModelCatalog | null;
|
|
54
|
-
/**
|
|
55
|
-
* 件4/MOD-6(F1 模型面批):id/name 双键归一。目录行有两个可寻址键 —— `name`(池 entry id,
|
|
56
|
-
* /model 面板行的 value、@mention 的 handle)和 `id`(上游 modelId);/v1/models 的 `default`
|
|
57
|
-
* 与 boot 回读可能给 id,面板/appState 用 name ⇒ 单键比对时 id≠name 的行匹配不上,面板追加
|
|
58
|
-
* 合成 "Current model" 重复行、✔ 落错行。归一规则:ref 已是某行 name ⇒ 原样;否则命中某行
|
|
59
|
-
* id ⇒ 归一到该行 name;目录缺失(mock 路径)/未命中 ⇒ 原样返回(mock parity 零影响)。
|
|
60
|
-
*/
|
|
61
18
|
export declare function normalizeLiveModelRef(ref: string): string;
|
|
62
|
-
/** 件4(S2 回显):目录 default 的用户名 —— name(池 entry id)优先,id 兜底;null=无目录
|
|
63
|
-
* (mock 路径,调用方回落 CC 字面护 parity)。 */
|
|
64
19
|
export declare function liveDefaultModelName(): string | null;
|
|
65
|
-
/** {@link routePairingVerdict} 的读数:`ok` / `broken` / `unknown` 三态 + 原样姿态词(缺席 / 非串时无 posture)。 */
|
|
66
20
|
export interface RoutePairingVerdict {
|
|
67
21
|
verdict: 'ok' | 'broken' | 'unknown';
|
|
68
22
|
posture?: string;
|
|
69
23
|
}
|
|
70
|
-
/**
|
|
71
|
-
* CC-06 / B-081(0.71.3):`ModelInfo.routePairing` 的读口 —— 只对 sdk 头注列出的**七词**给 verdict:四个 `ok:*` ⇒ ok
|
|
72
|
-
* (凭据路说得通)/ 两个 `broken:*` ⇒ broken(真请求会被引擎拒:标红,给这只模型配 per-model 凭据或挪到部署根上)/
|
|
73
|
-
* 其余一律 unknown(`unknown` 本身、未知词、缺席、非串、空串)—— 真开集下按前缀猜好坏 = 给一个契约没支持的词发正常 /
|
|
74
|
-
* 故障提示(异源复审实抓);`posture` 原样带给端渲「未知(<词>)」。
|
|
75
|
-
*/
|
|
76
24
|
export declare function routePairingVerdict(v: unknown): RoutePairingVerdict;
|
package/dist/liveModelCatalog.js
CHANGED
|
@@ -1,41 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/liveModelCatalog.ts 逐字搬入(零依赖;🔴 catalog/refresher 是单实例态 —— 写口 setLiveModelCatalog/installer 与读口 getLiveModelCatalog 必须同实例)。
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* src/sema/liveModelCatalog.ts — the LIVE model-catalog singleton (TEAM-C / clay decision #1 = A).
|
|
6
|
-
*
|
|
7
|
-
* WHY THIS FILE EXISTS
|
|
8
|
-
* --------------------
|
|
9
|
-
* The `/model` picker, the header model line, the /status "Model" row, and the picker's ✔ are all stuck on
|
|
10
|
-
* a STATIC opus[1m] / a STATIC fictional catalog (mock/control/modelOptionsSeam.ts). The live engine actually
|
|
11
|
-
* serves a different fleet — `client.models.list()` returns `{ models, default }` (the REAL catalog), and
|
|
12
|
-
* `done.result.model` echoes the REAL served model (MF-25). This module is the one-shot, process-wide bridge
|
|
13
|
-
* between the LIVE wire read (done once at boot in replEntry's live block) and the SYNCHRONOUS render-time
|
|
14
|
-
* readers (getModelOptions, called inside the picker's React render — it cannot await).
|
|
15
|
-
*
|
|
16
|
-
* SINGLE INSTANCE (build discipline): replEntry.tsx (build-src/src/sema/replEntry.tsx) SETS the catalog and
|
|
17
|
-
* mock/control/modelOptionsSeam.ts (build-src/mock/control/…, the aliased getModelOptions target) READS it.
|
|
18
|
-
* Both resolve this module to ONE staged path (build-src/src/sema/liveModelCatalog.ts), so the singleton is
|
|
19
|
-
* shared — the same single-instance invariant the seam-module fix in scripts/build.sema.mjs guarantees.
|
|
20
|
-
*
|
|
21
|
-
* MOCK PATH UNCHANGED: with SEMA_LIVE_BASEURL unset, no one calls setLiveModelCatalog → the catalog stays
|
|
22
|
-
* null → getModelOptions falls back to the static fleetModels mock and the boot keeps opus[1m]. So the
|
|
23
|
-
* cell-exact mock parity (the /model picker mock rows, the opus[1m] header/status, the /context 20-glyph
|
|
24
|
-
* grid driven by has1mContext('opus[1m]')) is preserved byte-for-byte.
|
|
25
|
-
*/
|
|
26
1
|
let catalog = null;
|
|
27
2
|
let refresher = null;
|
|
28
|
-
/** Install the live catalog (called once at boot from replEntry's live block). null clears it. */
|
|
29
3
|
export function setLiveModelCatalog(next) {
|
|
30
4
|
catalog = next;
|
|
31
5
|
}
|
|
32
|
-
/** boot 注册的重取器(与 boot fetch 同参)。k3 案(clay 2026-07-20):/config 改 Model ID 后
|
|
33
|
-
* 同会话 /model 仍显旧目录名——目录只在 boot 拉一次。Hub 保存/面板打开时经此重取。 */
|
|
34
6
|
export function setLiveModelCatalogRefresher(fn) {
|
|
35
7
|
refresher = fn;
|
|
36
8
|
}
|
|
37
|
-
/** Re-fetch the live catalog (boot 参数);成功即替换 singleton 并返回 true。mock 路径(无
|
|
38
|
-
* refresher)/拉取失败 → false,现值不动(fail-soft,绝不用 null 清掉可用旧目录)。 */
|
|
39
9
|
export async function refreshLiveModelCatalog() {
|
|
40
10
|
if (!refresher)
|
|
41
11
|
return false;
|
|
@@ -47,21 +17,12 @@ export async function refreshLiveModelCatalog() {
|
|
|
47
17
|
}
|
|
48
18
|
}
|
|
49
19
|
catch {
|
|
50
|
-
/* fail-soft */
|
|
51
20
|
}
|
|
52
21
|
return false;
|
|
53
22
|
}
|
|
54
|
-
/** Read the live catalog (null = mock path / live read failed → callers fall back to the static mock). */
|
|
55
23
|
export function getLiveModelCatalog() {
|
|
56
24
|
return catalog;
|
|
57
25
|
}
|
|
58
|
-
/**
|
|
59
|
-
* 件4/MOD-6(F1 模型面批):id/name 双键归一。目录行有两个可寻址键 —— `name`(池 entry id,
|
|
60
|
-
* /model 面板行的 value、@mention 的 handle)和 `id`(上游 modelId);/v1/models 的 `default`
|
|
61
|
-
* 与 boot 回读可能给 id,面板/appState 用 name ⇒ 单键比对时 id≠name 的行匹配不上,面板追加
|
|
62
|
-
* 合成 "Current model" 重复行、✔ 落错行。归一规则:ref 已是某行 name ⇒ 原样;否则命中某行
|
|
63
|
-
* id ⇒ 归一到该行 name;目录缺失(mock 路径)/未命中 ⇒ 原样返回(mock parity 零影响)。
|
|
64
|
-
*/
|
|
65
26
|
export function normalizeLiveModelRef(ref) {
|
|
66
27
|
if (!catalog || !ref)
|
|
67
28
|
return ref;
|
|
@@ -70,22 +31,13 @@ export function normalizeLiveModelRef(ref) {
|
|
|
70
31
|
const row = catalog.models.find(m => typeof m.id === 'string' && m.id === ref);
|
|
71
32
|
return row?.name || ref;
|
|
72
33
|
}
|
|
73
|
-
/** 件4(S2 回显):目录 default 的用户名 —— name(池 entry id)优先,id 兜底;null=无目录
|
|
74
|
-
* (mock 路径,调用方回落 CC 字面护 parity)。 */
|
|
75
34
|
export function liveDefaultModelName() {
|
|
76
35
|
if (!catalog?.default)
|
|
77
36
|
return null;
|
|
78
37
|
return normalizeLiveModelRef(catalog.default);
|
|
79
38
|
}
|
|
80
|
-
/** sdk `RoutePairingStatus` 已知七词(9.6.0 `types.d.ts`);头注逐字「switch 认上面七词,再留一条 default 臂当未知」。 */
|
|
81
39
|
const ROUTE_PAIRING_OK = new Set(['ok:per-model', 'ok:paired', 'ok:unpinned', 'ok:keyless']);
|
|
82
40
|
const ROUTE_PAIRING_BROKEN = new Set(['broken:credential_mismatch', 'broken:credential_missing']);
|
|
83
|
-
/**
|
|
84
|
-
* CC-06 / B-081(0.71.3):`ModelInfo.routePairing` 的读口 —— 只对 sdk 头注列出的**七词**给 verdict:四个 `ok:*` ⇒ ok
|
|
85
|
-
* (凭据路说得通)/ 两个 `broken:*` ⇒ broken(真请求会被引擎拒:标红,给这只模型配 per-model 凭据或挪到部署根上)/
|
|
86
|
-
* 其余一律 unknown(`unknown` 本身、未知词、缺席、非串、空串)—— 真开集下按前缀猜好坏 = 给一个契约没支持的词发正常 /
|
|
87
|
-
* 故障提示(异源复审实抓);`posture` 原样带给端渲「未知(<词>)」。
|
|
88
|
-
*/
|
|
89
41
|
export function routePairingVerdict(v) {
|
|
90
42
|
if (typeof v !== 'string' || v.length === 0)
|
|
91
43
|
return { verdict: 'unknown' };
|
|
@@ -1,63 +1,20 @@
|
|
|
1
1
|
import type { AskAnswer } from './hitl/hitlBridge.js';
|
|
2
|
-
/**
|
|
3
|
-
* src/sema/liveQuestionStore.ts — the SIDE-CHANNEL for §4④ live-stream AskUserQuestion (the conversation-seam
|
|
4
|
-
* twin of liveSessionStore.ts).
|
|
5
|
-
*
|
|
6
|
-
* WHY THIS EXISTS
|
|
7
|
-
* ---------------
|
|
8
|
-
* In TOC (two-process) the MODEL runs in the engine; its `AskUserQuestion` tool fires on core's
|
|
9
|
-
* `RunnerDeps.onQuestion` seam and the service (question.ts, 1.61.0) emits a NAMED SSE frame
|
|
10
|
-
* (`event: question` / `event: question_complete`) that INTERLEAVES on the same live token stream as the
|
|
11
|
-
* AgentEvents. That frame is NOT an AgentEvent arm (it is a DISTINCT vocabulary, exactly like elicitation) —
|
|
12
|
-
* so it must be DEMUXED out of the transcript-render pipeline and routed to an interactive DIALOG overlay
|
|
13
|
-
* instead. This tiny, dependency-FREE module is that route: liveClient WRITES the demuxed frame here (on each
|
|
14
|
-
* `question`/`question_complete`) and publishes its `client.questions.respond` binding; the UI overlay
|
|
15
|
-
* (main.tsx / REPL) READS the frames and answers via `respondToQuestion`. Same shape as liveSessionStore /
|
|
16
|
-
* rewindAnchorStore — the overlay stays testable (no @sema-ai/sdk graph) and seamQuery/normalizeToolNames are
|
|
17
|
-
* untouched.
|
|
18
|
-
*
|
|
19
|
-
* 🔴 LIVE-ONLY + SAME-REPLICA (the `steer()`-class of HITL): the service parks the answer promise in-memory,
|
|
20
|
-
* so a respond that lands after the TTL (5 min) / after answer / on another replica → 404. No durable resume
|
|
21
|
-
* anchor — a mid-question disconnect just lets the run proceed with the headless default (the model never
|
|
22
|
-
* hangs). The overlay must therefore treat `respondToQuestion` as best-effort (a 404 = "already released",
|
|
23
|
-
* dismiss the dialog, never retry).
|
|
24
|
-
*
|
|
25
|
-
* 🔴 UNTRUSTED: the `questions` payload is model-authored (service secret-redacted, but still UNTRUSTED for
|
|
26
|
-
* display). The overlay RENDERS it; it must NEVER be re-fed to a model. The answer the overlay sends back is
|
|
27
|
-
* fenced by CORE (`selected ⊆ options`, `note` untrusted-fenced) — the overlay must echo the EXACT option
|
|
28
|
-
* labels the user saw, never fabricate one.
|
|
29
|
-
*/
|
|
30
|
-
/** One option of an AskUserQuestion question (CC AskUserQuestionTool option shape). */
|
|
31
2
|
export interface AskQuestionOption {
|
|
32
|
-
/** EXACT display label — the answer echoes labels verbatim (core fences `selected ⊆ options`). */
|
|
33
3
|
label: string;
|
|
34
4
|
description?: string;
|
|
35
5
|
}
|
|
36
|
-
/** One model-authored question (UNTRUSTED: render-only, never re-fed to a model). */
|
|
37
6
|
export interface AskQuestion {
|
|
38
|
-
/** The question text (the CC dialog keys its answers Record by this). */
|
|
39
7
|
question: string;
|
|
40
|
-
/** Short header — the WIRE answer is keyed by this (see {@link QuestionAnswer}). */
|
|
41
8
|
header: string;
|
|
42
9
|
options: AskQuestionOption[];
|
|
43
10
|
multiSelect: boolean;
|
|
44
11
|
}
|
|
45
|
-
/** A demuxed/synthetic live question frame (legacy 1.61 wire payload `{type,questionId,questions?,outcome?}`;
|
|
46
|
-
* today also synthesized locally by liveHitlAskWire (`hitl-ask:*`) and planReviewWire (`plan-review:*`)).
|
|
47
|
-
* `question` opens the dialog overlay; `question_complete` dismisses a still-open one. */
|
|
48
12
|
export interface QuestionFrame {
|
|
49
13
|
type: 'question' | 'question_complete';
|
|
50
14
|
questionId: string;
|
|
51
|
-
/** Present on `question` frames; may be absent when the service dropped an over-cap payload. */
|
|
52
15
|
questions?: AskQuestion[];
|
|
53
|
-
/** `question_complete` only (legacy wire): why the ask was released (answered/expired/aborted). */
|
|
54
16
|
outcome?: string;
|
|
55
17
|
}
|
|
56
|
-
/** The answer the overlay sends back — keyed by HEADER; `selected` echoes exact option labels
|
|
57
|
-
* (`selected ⊆ options`, core's fence); off-list / free-text input rides `note` (untrusted-fenced).
|
|
58
|
-
* REF-CC-038(2026-08-02):entry 直接是 hitlBridge 的 `AskAnswer`(唯一源),不再各写一份 ——
|
|
59
|
-
* 之前这里是一份内联匿名形的独立声明,只靠注释断言与 hitlBridge 那份「形状相同」,
|
|
60
|
-
* 下游(`askGateWire.ts`)因此要 `as AskAnswer[]` 兜齐两个名不同的等价形状。 */
|
|
61
18
|
export interface QuestionAnswer {
|
|
62
19
|
answers: AskAnswer[];
|
|
63
20
|
}
|
|
@@ -65,62 +22,18 @@ type QuestionFrameHandler = (frame: QuestionFrame) => void;
|
|
|
65
22
|
type RespondFn = (id: string, answer: QuestionAnswer, opts?: {
|
|
66
23
|
signal?: AbortSignal;
|
|
67
24
|
}) => Promise<unknown>;
|
|
68
|
-
/** Register a one-shot local responder for a SYNTHETIC question frame (e.g. `plan-review:<taskId>`).
|
|
69
|
-
* Returns an unregister fn (dialog dismissed without answering ⇒ caller cleans up). */
|
|
70
25
|
export declare function registerLocalQuestionResponder(id: string, fn: RespondFn): () => void;
|
|
71
|
-
/**
|
|
72
|
-
* Unregister a local responder **by id**(A-028.4 复审二轮收紧,2026-08-12)。
|
|
73
|
-
*
|
|
74
|
-
* 为什么需要按 id 注销:`registerLocalQuestionResponder` 的注销钩只回到注册方手里,而重开腿
|
|
75
|
-
* (`planReviewWire.reopenPlanReviewCard`)要退役的是**别的注册方**(arm 臂)登记的 canonical
|
|
76
|
-
* responder —— 只发 `question_complete` 撤帧撤不掉表里的 responder,一个在途的迟到作答仍能经
|
|
77
|
-
* 它投递决断,与新卡的投递构成同一 gate 的双决断面。返回是否真删了一条(调用方留痕用)。
|
|
78
|
-
* 🔴 只删表项,不通知原注册方 —— 原注册方的自愈臂(如 arm 的陈旧武装态分支)按
|
|
79
|
-
* `hasLocalQuestionResponder` 探询真相,不依赖回调。
|
|
80
|
-
*/
|
|
81
26
|
export declare function unregisterLocalQuestionResponder(id: string): boolean;
|
|
82
|
-
/**
|
|
83
|
-
* Is a local responder for this synthetic questionId still bound?([2393] hitl-F3,2026-08-02)
|
|
84
|
-
*
|
|
85
|
-
* 🔴 为什么这是**只读探询**而不是「谁注册谁自己记着就行」:上面那条契约把「对话框被 dismiss 却没
|
|
86
|
-
* 作答」的清理责任交给了 caller,而 caller(planReviewWire)自己那份武装态与这张表是**两个**容器 ——
|
|
87
|
-
* 两个容器各自都可能被单方面改动(`respondToQuestion` 的一次性 delete、别的注册把同 id 顶掉后再
|
|
88
|
-
* 注销),于是「我以为还武装着」和「表里还真有人收答」会漂开。漂开的后果不是多弹一张卡,是
|
|
89
|
-
* **一张都不弹**:去重短路认为卡还在,而实际上没有任何 responder 能收答([paired-mechanisms-must-
|
|
90
|
-
* share-premise])。给出这条探询口,让去重臂能问真相而不是问自己的记忆。
|
|
91
|
-
*
|
|
92
|
-
* 🔴 只回答布尔:responder 函数本身绝不出境(它闭包着 caller 的一次性状态,交出去就有第二个调用者)。
|
|
93
|
-
*/
|
|
94
27
|
export declare function hasLocalQuestionResponder(id: string): boolean;
|
|
95
|
-
/**
|
|
96
|
-
* Publish a demuxed live question frame (called from liveClient's demuxQuestionFrames on each
|
|
97
|
-
* `question`/`question_complete`). Best-effort: a UI handler error is swallowed so a broken overlay can NEVER
|
|
98
|
-
* break the live stream drain (the run must keep flowing; a lost frame just headless-defaults the ask).
|
|
99
|
-
*/
|
|
100
28
|
export declare function publishQuestionFrame(frame: QuestionFrame): void;
|
|
101
|
-
/** W1 keyed variant: publish to ONE session's overlay (multi-session hosts demux by their own key). */
|
|
102
29
|
export declare function publishQuestionFrameFor(sessionKey: string, frame: QuestionFrame): void;
|
|
103
|
-
/** Whether a UI overlay is currently subscribed (liveHitlAskWire gates on this: print/non-REPL mode has no
|
|
104
|
-
* dialog to park on, so the suspended terminal must fall through honestly instead of hanging the stream). */
|
|
105
30
|
export declare function hasQuestionOverlay(): boolean;
|
|
106
|
-
/** W1 keyed variant. */
|
|
107
31
|
export declare function hasQuestionOverlayFor(sessionKey: string): boolean;
|
|
108
|
-
/** Subscribe the UI overlay to live question frames. Returns an unsubscribe. Last writer wins (one overlay). */
|
|
109
32
|
export declare function onQuestionFrame(handler: QuestionFrameHandler): () => void;
|
|
110
|
-
/** W1 keyed variant: one overlay PER sessionKey (last writer wins within a key; keys never clobber
|
|
111
|
-
* each other — the r1 E2 dual-session hazard this registry exists to close). */
|
|
112
33
|
export declare function onQuestionFrameFor(sessionKey: string, handler: QuestionFrameHandler): () => void;
|
|
113
|
-
/** Publish the live client's `questions.respond` binding (called from createLiveConversationClient). `null`
|
|
114
|
-
* clears it (offline/mock → respondToQuestion rejects cleanly). */
|
|
115
34
|
export declare function setQuestionRespond(fn: RespondFn | null): void;
|
|
116
|
-
/**
|
|
117
|
-
* Answer a parked live question (POST /v1/questions/:id/respond via the live client). Rejects when no live
|
|
118
|
-
* client is wired (offline/mock) so the overlay can fall back / dismiss. The 404 (answered/expired/wrong
|
|
119
|
-
* replica) surfaces as a thrown ApiError — the overlay treats it as "already released", never a retry.
|
|
120
|
-
*/
|
|
121
35
|
export declare function respondToQuestion(id: string, answer: QuestionAnswer, opts?: {
|
|
122
36
|
signal?: AbortSignal;
|
|
123
37
|
}): Promise<unknown>;
|
|
124
|
-
/** Test-only reset. */
|
|
125
38
|
export declare function _resetLiveQuestionStore(): void;
|
|
126
39
|
export {};
|
|
@@ -1,62 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ⇄ B1 批搬迁(2026-07-27,多端改造设计稿 §2.4.1-B):cli src/sema/liveQuestionStore.ts 逐字搬入(零依赖;壳侧改 re-export)。
|
|
3
|
-
* 本模块自持 AskUserQuestion 的 wire 词汇(SDK 0.0.44 删掉了 questions 资源导出),搬入后这套
|
|
4
|
-
* 类型随包发布 —— web/桌面端的 HITL 覆盖层与 TUI 共用同一份 QuestionFrame/QuestionAnswer 形。
|
|
5
|
-
*/
|
|
6
1
|
import { createSessionSlot, DEFAULT_SESSION_KEY } from './sessionSlot.js';
|
|
7
|
-
// W1(design/161):frameHandler 槽位改 sessionKey → 注册表;零参 API = DEFAULT_SESSION_KEY
|
|
8
|
-
// 兼容层(cli 装配不动)。respondFn / localResponders 不在 W1 五槽位切口内,维持原样。
|
|
9
2
|
const frameHandlerByKey = createSessionSlot();
|
|
10
3
|
let respondFn = null;
|
|
11
|
-
/** SHELL-LOCAL question responders (plan-review approval cards etc. — synthetic frames whose id does
|
|
12
|
-
* NOT exist engine-side, so POST /v1/questions/:id/respond would 404). Registered per-questionId by
|
|
13
|
-
* the frame's publisher; consumed once (respond removes the entry). Checked BEFORE the live respond. */
|
|
14
4
|
const localResponders = new Map();
|
|
15
|
-
/** Register a one-shot local responder for a SYNTHETIC question frame (e.g. `plan-review:<taskId>`).
|
|
16
|
-
* Returns an unregister fn (dialog dismissed without answering ⇒ caller cleans up). */
|
|
17
5
|
export function registerLocalQuestionResponder(id, fn) {
|
|
18
6
|
localResponders.set(id, fn);
|
|
19
7
|
return () => {
|
|
20
8
|
localResponders.delete(id);
|
|
21
9
|
};
|
|
22
10
|
}
|
|
23
|
-
/**
|
|
24
|
-
* Unregister a local responder **by id**(A-028.4 复审二轮收紧,2026-08-12)。
|
|
25
|
-
*
|
|
26
|
-
* 为什么需要按 id 注销:`registerLocalQuestionResponder` 的注销钩只回到注册方手里,而重开腿
|
|
27
|
-
* (`planReviewWire.reopenPlanReviewCard`)要退役的是**别的注册方**(arm 臂)登记的 canonical
|
|
28
|
-
* responder —— 只发 `question_complete` 撤帧撤不掉表里的 responder,一个在途的迟到作答仍能经
|
|
29
|
-
* 它投递决断,与新卡的投递构成同一 gate 的双决断面。返回是否真删了一条(调用方留痕用)。
|
|
30
|
-
* 🔴 只删表项,不通知原注册方 —— 原注册方的自愈臂(如 arm 的陈旧武装态分支)按
|
|
31
|
-
* `hasLocalQuestionResponder` 探询真相,不依赖回调。
|
|
32
|
-
*/
|
|
33
11
|
export function unregisterLocalQuestionResponder(id) {
|
|
34
12
|
return localResponders.delete(id);
|
|
35
13
|
}
|
|
36
|
-
/**
|
|
37
|
-
* Is a local responder for this synthetic questionId still bound?([2393] hitl-F3,2026-08-02)
|
|
38
|
-
*
|
|
39
|
-
* 🔴 为什么这是**只读探询**而不是「谁注册谁自己记着就行」:上面那条契约把「对话框被 dismiss 却没
|
|
40
|
-
* 作答」的清理责任交给了 caller,而 caller(planReviewWire)自己那份武装态与这张表是**两个**容器 ——
|
|
41
|
-
* 两个容器各自都可能被单方面改动(`respondToQuestion` 的一次性 delete、别的注册把同 id 顶掉后再
|
|
42
|
-
* 注销),于是「我以为还武装着」和「表里还真有人收答」会漂开。漂开的后果不是多弹一张卡,是
|
|
43
|
-
* **一张都不弹**:去重短路认为卡还在,而实际上没有任何 responder 能收答([paired-mechanisms-must-
|
|
44
|
-
* share-premise])。给出这条探询口,让去重臂能问真相而不是问自己的记忆。
|
|
45
|
-
*
|
|
46
|
-
* 🔴 只回答布尔:responder 函数本身绝不出境(它闭包着 caller 的一次性状态,交出去就有第二个调用者)。
|
|
47
|
-
*/
|
|
48
14
|
export function hasLocalQuestionResponder(id) {
|
|
49
15
|
return localResponders.has(id);
|
|
50
16
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Publish a demuxed live question frame (called from liveClient's demuxQuestionFrames on each
|
|
53
|
-
* `question`/`question_complete`). Best-effort: a UI handler error is swallowed so a broken overlay can NEVER
|
|
54
|
-
* break the live stream drain (the run must keep flowing; a lost frame just headless-defaults the ask).
|
|
55
|
-
*/
|
|
56
17
|
export function publishQuestionFrame(frame) {
|
|
57
18
|
publishQuestionFrameFor(DEFAULT_SESSION_KEY, frame);
|
|
58
19
|
}
|
|
59
|
-
/** W1 keyed variant: publish to ONE session's overlay (multi-session hosts demux by their own key). */
|
|
60
20
|
export function publishQuestionFrameFor(sessionKey, frame) {
|
|
61
21
|
const frameHandler = frameHandlerByKey.get(sessionKey);
|
|
62
22
|
if (!frameHandler)
|
|
@@ -65,24 +25,17 @@ export function publishQuestionFrameFor(sessionKey, frame) {
|
|
|
65
25
|
frameHandler(frame);
|
|
66
26
|
}
|
|
67
27
|
catch {
|
|
68
|
-
/* a UI handler throw must never propagate into the AgentEvent drain */
|
|
69
28
|
}
|
|
70
29
|
}
|
|
71
|
-
/** Whether a UI overlay is currently subscribed (liveHitlAskWire gates on this: print/non-REPL mode has no
|
|
72
|
-
* dialog to park on, so the suspended terminal must fall through honestly instead of hanging the stream). */
|
|
73
30
|
export function hasQuestionOverlay() {
|
|
74
31
|
return hasQuestionOverlayFor(DEFAULT_SESSION_KEY);
|
|
75
32
|
}
|
|
76
|
-
/** W1 keyed variant. */
|
|
77
33
|
export function hasQuestionOverlayFor(sessionKey) {
|
|
78
34
|
return frameHandlerByKey.get(sessionKey) !== undefined;
|
|
79
35
|
}
|
|
80
|
-
/** Subscribe the UI overlay to live question frames. Returns an unsubscribe. Last writer wins (one overlay). */
|
|
81
36
|
export function onQuestionFrame(handler) {
|
|
82
37
|
return onQuestionFrameFor(DEFAULT_SESSION_KEY, handler);
|
|
83
38
|
}
|
|
84
|
-
/** W1 keyed variant: one overlay PER sessionKey (last writer wins within a key; keys never clobber
|
|
85
|
-
* each other — the r1 E2 dual-session hazard this registry exists to close). */
|
|
86
39
|
export function onQuestionFrameFor(sessionKey, handler) {
|
|
87
40
|
frameHandlerByKey.set(sessionKey, handler);
|
|
88
41
|
return () => {
|
|
@@ -90,20 +43,13 @@ export function onQuestionFrameFor(sessionKey, handler) {
|
|
|
90
43
|
frameHandlerByKey.set(sessionKey, undefined);
|
|
91
44
|
};
|
|
92
45
|
}
|
|
93
|
-
/** Publish the live client's `questions.respond` binding (called from createLiveConversationClient). `null`
|
|
94
|
-
* clears it (offline/mock → respondToQuestion rejects cleanly). */
|
|
95
46
|
export function setQuestionRespond(fn) {
|
|
96
47
|
respondFn = fn;
|
|
97
48
|
}
|
|
98
|
-
/**
|
|
99
|
-
* Answer a parked live question (POST /v1/questions/:id/respond via the live client). Rejects when no live
|
|
100
|
-
* client is wired (offline/mock) so the overlay can fall back / dismiss. The 404 (answered/expired/wrong
|
|
101
|
-
* replica) surfaces as a thrown ApiError — the overlay treats it as "already released", never a retry.
|
|
102
|
-
*/
|
|
103
49
|
export function respondToQuestion(id, answer, opts) {
|
|
104
50
|
const local = localResponders.get(id);
|
|
105
51
|
if (local) {
|
|
106
|
-
localResponders.delete(id);
|
|
52
|
+
localResponders.delete(id);
|
|
107
53
|
return local(id, answer, opts);
|
|
108
54
|
}
|
|
109
55
|
if (!respondFn) {
|
|
@@ -111,7 +57,6 @@ export function respondToQuestion(id, answer, opts) {
|
|
|
111
57
|
}
|
|
112
58
|
return respondFn(id, answer, opts);
|
|
113
59
|
}
|
|
114
|
-
/** Test-only reset. */
|
|
115
60
|
export function _resetLiveQuestionStore() {
|
|
116
61
|
frameHandlerByKey.clear();
|
|
117
62
|
respondFn = null;
|