@sema-agent/client-core 0.77.1 → 0.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -1
- package/README.md +6 -5
- 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 +3 -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 +23 -371
- package/dist/hitl/persistedRulesWire.js +62 -329
- 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 +1 -249
- package/dist/request/taskRequest.js +20 -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 +78 -5
- package/package.json +3 -3
|
@@ -1,53 +1,20 @@
|
|
|
1
1
|
import { stamp, snapshotSegmentIdentity, } from '../types.js';
|
|
2
2
|
import { turnUsageToModelUsage } from './turnUsageToModelUsage.js';
|
|
3
|
-
// 0.60.0(engine ≥7.64.0 / sdk 8.4.0):`tool_end.gate` 的三端共用窄读器(判定归包,端不许自拼)。
|
|
4
3
|
import { gateOutcomeOf } from '../../gateOutcome.js';
|
|
5
|
-
// CC-08(0.71.0):名册与名册增量的窄读器归 toolRoster.ts(0.63.0 起在),本层只接线。
|
|
6
4
|
import { projectToolRoster, projectToolRosterDelta } from '../../toolRoster.js';
|
|
7
5
|
import { readMcpLiveness } from '../../mcpLiveness.js';
|
|
8
6
|
import { SEGMENT_END_IDENTITY_KEYS } from '../types.js';
|
|
9
|
-
// 0.65.0(core 7.12.0 CHANGELOG「Removed (BREAKING)」`WiringManifest.autoMode.breaker`):
|
|
10
|
-
// 熔断族整只退役 ⇒ 本臂此前对 `autoMode.breaker` 的窄读(`classifierBreakerOf`)与它的型位一并
|
|
11
|
-
// 删除(clean-cut,不留兼容读)。`autoMode` 段剩下的两位 `armed` / `reason` 一个字节不动。
|
|
12
|
-
// #51: `stamp<T extends { uuid?: string; session_id?: string }>` — passing an
|
|
13
|
-
// arm-body object literal straight to `stamp` triggers a TS quirk: the
|
|
14
|
-
// literal gets excess-property-checked against the CONSTRAINT (which only
|
|
15
|
-
// knows uuid/session_id) before T is fully inferred, so every other field
|
|
16
|
-
// (`type`, `taskId`, …) reads as "unknown property". Routing the literal
|
|
17
|
-
// through this identity helper first breaks that early check without
|
|
18
|
-
// touching runtime behavior (pure pass-through; `stamp` still assigns
|
|
19
|
-
// uuid/session_id exactly as before).
|
|
20
7
|
function armBody(body) {
|
|
21
8
|
return body;
|
|
22
9
|
}
|
|
23
|
-
/**
|
|
24
|
-
* `suggestions` 批的防御性上界(REF-CC-061 / xlate-07,A3 魔数命名)。UI 面的界,不是模型面 ——
|
|
25
|
-
* 这条臂的文本**绝不回喂模型**(见 `case 'suggestions'` 头注)。
|
|
26
|
-
* 命名的意义不只是可读:裸字面量对域词表门是隐形的,而这两个数决定「用户少看见几条建议」。
|
|
27
|
-
*/
|
|
28
10
|
const SUGGESTION_BATCH_CAP = 8;
|
|
29
|
-
/** 单条建议的字符上界;超出截断并留可见痕迹(尾部 `…`)。 */
|
|
30
11
|
const SUGGESTION_CHARS_CAP = 200;
|
|
31
|
-
/**
|
|
32
|
-
* 本适配器铸出的**内部臂** `type` 全集(A-004.4 上游半场,2026-08-08)——「内部臂」= 桥面
|
|
33
|
-
* (bridge-facing)消息,**不是** CC SDK stdout 联合体里的帧形(那些是 assistant/stream_event/
|
|
34
|
-
* system 等真帧)。消费方(壳 REPL 桥、`-p` print 出口、web/desktop 座位层)对内部臂只有两种
|
|
35
|
-
* 合法处置:**吞**(不外泄)或**转成真 CC 帧**;顺着兜底裸透传到 stdout/wire = 病族⑥投影缺口
|
|
36
|
-
* (cli A-004.11/12 实翻:human_input/diagnostics/workspace_changed 曾漏进 `-p` stream-json)。
|
|
37
|
-
*
|
|
38
|
-
* 这张表是**唯一权威源**:消费方的吞/转名单必须对账本表(全覆盖,禁手抄子集——A-004.4 的病形
|
|
39
|
-
* 就是壳手抄了 4 词的子集);本包 pure 门有源码对账腿(armBody 铸点抽取 ≡ 本表),加臂不登记
|
|
40
|
-
* 即红。`turn_usage` 的铸点在 runStream.ts(usage 聚合腿),不在本文件的 switch 里,同属本表。
|
|
41
|
-
*/
|
|
42
12
|
export const INTERNAL_SDK_ARM_TYPES = new Set([
|
|
43
|
-
// CC-08(0.71.0,sdk 9.6.0):两条新帧 → 中性内部臂(print 车道按 text_end 同律吞/转;裸透传 = 越界帧)。
|
|
44
13
|
'tool_disclosure',
|
|
45
14
|
'tool_progress',
|
|
46
15
|
'tool_roster_delta',
|
|
47
16
|
'context_usage',
|
|
48
|
-
// CC-89(0.75.0):压缩的非 compacted 结局 → 中性内部臂(print 车道同律:吞或转,裸透传 = 越界帧)。
|
|
49
17
|
'compaction_outcome',
|
|
50
|
-
// CC-91(0.76.0):这一次 prepare 的提示词装配清单 → 中性内部臂(print 车道同律:吞或转,裸透传 = 越界帧)。
|
|
51
18
|
'prompt_assembled',
|
|
52
19
|
'workflow_complete',
|
|
53
20
|
'tool_end_result',
|
|
@@ -60,57 +27,19 @@ export const INTERNAL_SDK_ARM_TYPES = new Set([
|
|
|
60
27
|
'prompt_suggestions',
|
|
61
28
|
'human_input',
|
|
62
29
|
'turn_usage',
|
|
63
|
-
// #310 / #318 件①:引擎结构化通告的会话面(raw 预分派铸点,见 eventToSdkMessage 顶部)。
|
|
64
30
|
'engine_notice',
|
|
65
|
-
// #323 / core #447:assistant 流式**散文段边界**(sdk 9.4.0 起进 union,`case 'text_end'`;见 `textEndProjection` 头注)。
|
|
66
31
|
'text_end',
|
|
67
|
-
// CC-02(0.68.3;server ≥7.77.0 S-310 / sdk ≥9.4.0 `SegmentEndFields`):**推理段边界** + 权威全文,
|
|
68
|
-
// `text_end` 的孪生(形逐字同,空段判据归 server)。消费口 = `adapt/arms.ts` 的 `thinkingSegmentEndArm`。
|
|
69
|
-
// ⚠️ 三端:print 车道对内部臂「要么吞、要么转成真 CC 帧」—— 本臂在 CC stdout 帧全集零同位帧,壳按 `text_end` 同律接。
|
|
70
32
|
'reasoning_end',
|
|
71
|
-
// L-70 / L-108②③(core #524 + core 147③,server ≥7.58.0):`wiring_manifest` 帧上**两个新段**的
|
|
72
|
-
// 超集投影(`_sema_modelGate` / `_sema_autoMode`)。整份 manifest 的其余段仍不在本切片里 ——
|
|
73
|
-
// 射程写在 `case 'wiring_manifest'` 头注,别读成「manifest 接上了」。
|
|
74
33
|
'wiring_manifest',
|
|
75
|
-
// B-078 / L-208(0.65.0;design/172 流内审批协议):呈卡 / 撕卡两帧的内部臂。
|
|
76
|
-
// 载荷是**信封原样**(不窄化到 v1,不摘键重铸)——理由见两个 `case` 的头注。
|
|
77
34
|
'approval_request',
|
|
78
35
|
'approval_revoke',
|
|
79
|
-
// B-072 ④(0.65.0):`message_committed` 会话条目落账帧 —— 从「本切片不投影」改为中性内部臂
|
|
80
|
-
// (chrome 记账,绝不铸 transcript 行)。理由见 `case 'message_committed'` 头注:它是
|
|
81
|
-
// `compacted.preserved_segment` 的**唯一**解析腿。
|
|
82
36
|
'message_committed',
|
|
83
37
|
]);
|
|
84
|
-
/**
|
|
85
|
-
* Wrap neutral content blocks in the CC `assistant` message envelope.
|
|
86
|
-
*
|
|
87
|
-
* ── L-215③(0.65.0):`message` 上补两个**身份**键 ─────────────────────────────────────────
|
|
88
|
-
* 此前交给渲染端的是**裸** `{role, content}` —— CC 的 `SDKAssistantMessage.message` 上那四个键
|
|
89
|
-
* (`id` / `model` / `usage` / `stop_reason`)一个都没有,于是宿主十几处消费面只能各自**估算**。
|
|
90
|
-
* 本批补**两个**,另外两个**刻意不补**,理由逐条如下(不是遗漏,别下一棒又来补一遍):
|
|
91
|
-
*
|
|
92
|
-
* · **`id` ⇐ wire 的 `eventId`**(core 铸的 uuidv7,§E2)。取它而不是现铸,是因为它**确定性**:
|
|
93
|
-
* 同一条消息在 live 与 durable replay 两条腿上必须同 id,否则宿主的去重与 R8 rewind 会把一次
|
|
94
|
-
* 重放当成一条新消息。wire 没给 ⇒ **键不铸**(诚实缺席),绝不塞一个随机 v4 冒充身份。
|
|
95
|
-
* ⚠️ 与信封自己的 `uuid` 是**两个**身份位:后者是本地渲染键(`stamp` 现铸),前者是引擎身份。
|
|
96
|
-
* · **`model` ⇐ `ctx.model`**(宿主开流时钉的那一个,契约见 {@link EmitContext.model})。
|
|
97
|
-
* 缺席 ⇒ 键不铸,**绝不猜**。
|
|
98
|
-
* · 🔴 **`usage` 不铸,理由是帧序**:wire 上 `text`/`text_end` 这些内容臂**先**到、
|
|
99
|
-
* `turn_end.usage` **后**到 —— 臂发出的那一刻,引擎还没说这一轮花了多少。在这里铸一个数只能是
|
|
100
|
-
* **估算**,而估算正是本件要根治的东西(cli 1.0.107 的壳侧回落补丁就是它的症状)。
|
|
101
|
-
* 真值走 `turn_usage` 臂的 `_sema_last_assistant_usage` 超集键(见 runStream 的 turn_end 折叠点)。
|
|
102
|
-
* ⚠️ 也**不**采「turn_end 到达时补发一条 assistant 更新」的形:CC 的消息面没有这种形,
|
|
103
|
-
* 合成一条会让宿主的转录出现一条引擎从没发过的消息。
|
|
104
|
-
* · 🔴 **`stop_reason` 同理不铸**:`turn_end.stopReason` 与 usage 同帧,同一条帧序结论;
|
|
105
|
-
* 它走 `turn_usage` 臂的 `_sema_stop_reason`。
|
|
106
|
-
*/
|
|
107
38
|
function assistantArm(ctx, content, eventId) {
|
|
108
39
|
const id = typeof eventId === 'string' && eventId.length > 0 ? eventId : undefined;
|
|
109
40
|
const model = typeof ctx.model === 'string' && ctx.model.length > 0 ? ctx.model : undefined;
|
|
110
41
|
return stamp(ctx, armBody({
|
|
111
42
|
type: 'assistant',
|
|
112
|
-
// `message` is coreSchemas APIAssistantMessagePlaceholder = z.unknown(): we
|
|
113
|
-
// hand the renderer a neutral { role, content } it can read, not the raw wire.
|
|
114
43
|
message: {
|
|
115
44
|
role: 'assistant',
|
|
116
45
|
content,
|
|
@@ -120,12 +49,9 @@ function assistantArm(ctx, content, eventId) {
|
|
|
120
49
|
parent_tool_use_id: null,
|
|
121
50
|
}));
|
|
122
51
|
}
|
|
123
|
-
/** Wrap a neutral delta in the CC `stream_event` (partial assistant) envelope. */
|
|
124
52
|
function streamEventArm(ctx, event) {
|
|
125
53
|
return stamp(ctx, armBody({
|
|
126
54
|
type: 'stream_event',
|
|
127
|
-
// `event` is RawMessageStreamEventPlaceholder = z.unknown(): a neutral
|
|
128
|
-
// fragment descriptor, NOT a `content_block_delta` wire frame.
|
|
129
55
|
event,
|
|
130
56
|
parent_tool_use_id: null,
|
|
131
57
|
}));
|
|
@@ -133,62 +59,15 @@ function streamEventArm(ctx, event) {
|
|
|
133
59
|
const projected = (message) => ({ kind: 'message', message });
|
|
134
60
|
const nothing = (why) => ({ kind: 'none', why });
|
|
135
61
|
const dropped = (why, type) => ({ kind: 'dropped', why, type });
|
|
136
|
-
/**
|
|
137
|
-
* B5 穷举卫兵:union 加成员必须在**编译期**打红这个 switch,而不是让新臂在用户面静默丢帧。
|
|
138
|
-
* 运行期仍会走到这里 —— wire 是 JSON,引擎完全可能比本包的类型新一版(那正是 `unknown_arm`)。
|
|
139
|
-
*/
|
|
140
62
|
function assertNeverArm(_ev) {
|
|
141
|
-
/* 类型面穷举断言;运行期由调用点返回 typed dropped */
|
|
142
63
|
}
|
|
143
|
-
/**
|
|
144
|
-
* Project one durable/live `AgentEvent` into a typed {@link EventProjection}.
|
|
145
|
-
*
|
|
146
|
-
* `tool_end` projects to a NEUTRAL internal `tool_end_result` arm (NOT a CC
|
|
147
|
-
* SDKMessage the renderer reads) carrying the §E1 wire `output` so the bridge can
|
|
148
|
-
* close the open card with the real body.
|
|
149
|
-
*
|
|
150
|
-
* Terminal `done`/`failed` are delegated to `terminalToSdkResult`.
|
|
151
|
-
*
|
|
152
|
-
* 🔴 BREAKING(REF-CC-058,0.13.0):返回型由 `SDKMessage | null` 改为三态 Result。
|
|
153
|
-
* 迁移判据一句话:`const p = eventToSdkMessage(ev, ctx); if (p.kind === 'message') …` ——
|
|
154
|
-
* 旧写法 `if (msg)` 在新返回型上恒真(对象永远 truthy),所以这是**必须点名**的一类改动。
|
|
155
|
-
*/
|
|
156
64
|
export function eventToSdkMessage(ev, ctx) {
|
|
157
|
-
// ── `text_end` raw 预分派(#323 / core #447,core ≥5.63 / server ≥7.50;契约见 textEndProjection)──
|
|
158
|
-
//
|
|
159
|
-
// 🔴 **为什么是 raw 预分派而不是一条 `case`**(与 `engine_notice` 当年逐字同因):本臂**还没进
|
|
160
|
-
// 已发布 SDK 的 `AgentEvent` union`** —— 亲验 npm `@sema-agent/sdk@7.2.0`(latest,本批当日
|
|
161
|
-
// `npm view @sema-agent/sdk dist-tags` 直读)的真 tarball:`dist/` 全树零 `text_end`。
|
|
162
|
-
// 在这样的 union 上写 `case 'text_end'` 是编译错(`ev.type` 上没有这个字面量)。
|
|
163
|
-
// 🔴 **这不是「按源码将就接」**(接入文档宪法):消费契约取自 **core 5.63.0 的已发布 `dist/core/
|
|
164
|
-
// types.d.ts`**(`TaskEvent` 的 `{type:'text_end'; content: string} & TaskEventIdentity` 臂,
|
|
165
|
-
// 带完整语义头注)与 **server 7.50.0 的已发布 dist**(`http/routes/tasks.js` 的 live SSE 与
|
|
166
|
-
// durable 两处投影 + `fleet/subagent-tail-bus.js` 的 tail 投影,三腿都在发),不是抄 sdk src。
|
|
167
|
-
// 🔴 **到期复核(自退休,不靠人记)**:预分派用 `(ev as {type?:unknown})` 形读判别键,**不收窄** `ev`
|
|
168
|
-
// ⇒ 臂一进 union,switch 的 `default` 仍看得见它,B5 穷举断言 `assertNeverArm` **编译期真红**,
|
|
169
|
-
// 逼下一棒把它搬进 switch。搬进去时行为一字不改(下面的投影函数原样复用)。
|
|
170
|
-
// 🔴 **到期复核已兑现(sdk 9.4.0 提货,0.68.3 CC-02)**:`text_end` 进了 union(与 `reasoning_end` 共用
|
|
171
|
-
// `SegmentEndFields`),按原定计划搬进 switch;`textEndProjection` 原样复用,行为一字不改。
|
|
172
65
|
switch (ev.type) {
|
|
173
66
|
case 'text_end':
|
|
174
67
|
return textEndProjection(ev, ctx);
|
|
175
|
-
/**
|
|
176
|
-
* CC-02(0.68.3):`reasoning_end` —— `text_end` 的推理面孪生(server ≥7.77.0 自铸,core 不发;sdk 9.4.0
|
|
177
|
-
* 两枚帧一份形 `SegmentEndFields`)。处置逐条同 `text_end`:中性内部臂、绝不铸 transcript 行、绝不
|
|
178
|
-
* `not_in_slice`、`content` 非串/lane 位坏 ⇒ malformed、空串 ⇒ empty_payload、身份两键原样透传。
|
|
179
|
-
* 差别只在消费口:`adapt/arms.ts` 的 `thinkingSegmentEndArm` 做**思考块**的整段替换 + chrome
|
|
180
|
-
* `thinking_segment_end`(两形,见 `TextStream.replaceThinkingSegment`)。
|
|
181
|
-
*/
|
|
182
68
|
case 'reasoning_end':
|
|
183
69
|
return segmentEndProjection(ev, ctx, 'reasoning_end');
|
|
184
|
-
/**
|
|
185
|
-
* L-315(候 0.68.4):`tool_roster_delta` —— 名册增量。本包今天不投 `wiring_manifest.tools`(切片只投
|
|
186
|
-
* 三段),名册增量没有可挂的基线 ⇒ **有痕 dropped**,与 0.65.0 前的 `approval_request` 同形(不静默、
|
|
187
|
-
* 不 not_in_slice);接上 `tools` 段的那一批把它一起接。
|
|
188
|
-
*/
|
|
189
70
|
case 'tool_roster_delta': {
|
|
190
|
-
// CC-08 ①(0.71.0):L-315 收口 —— 名册增量接上(此前有痕 dropped)。`delta` 读不出 ⇒ malformed(server 判不出形整帧不发,
|
|
191
|
-
// 本层读不出就是坏帧);三键身份原样透传。宿主按 `fromDigest` 与手上名册比对(applyToolRosterDelta),包不持名册。
|
|
192
71
|
const raw = ev;
|
|
193
72
|
const delta = projectToolRosterDelta(raw.delta);
|
|
194
73
|
if (delta === undefined)
|
|
@@ -198,39 +77,8 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
198
77
|
return bad;
|
|
199
78
|
return projected(stamp(ctx, armBody({ type: 'tool_roster_delta', delta, ...identity })));
|
|
200
79
|
}
|
|
201
|
-
// ── `human_input`(core 5.14.0 design/171 / server 7.4.0 SSE,[3017]/[3020])────────────
|
|
202
|
-
// 🔴 **到期复核已兑现(sdk 6.9.0 提货,2026-08-08)**:本臂此前是 switch **之前**的一条 raw
|
|
203
|
-
// 预分派(理由 = 它还没进 SDK 6.3.0 的 `AgentEvent` union,`case 'human_input'` 在 `ev.type`
|
|
204
|
-
// 上是编译错),头注写着「在 union 里的那天就把它搬进 switch」。sdk 6.9.0 的 events.d.ts
|
|
205
|
-
// 已声明该臂 ⇒ 按原定计划搬进来。这不是可选的整理:预分派用的是 `(ev as {type?:unknown})`
|
|
206
|
-
// 形,**不收窄** `ev`,所以臂一进 union,switch 的 `default` 就还看得见它 ⇒ B5 穷举断言
|
|
207
|
-
// (assertNeverArm)编译期真红。搬进来后本函数重回「每一条臂都受编译期穷举保护」。
|
|
208
|
-
// 处置不变:server 侧对本帧的投影明写「**本帧不带正文**(core 的臂里就没有 text 字段),所以
|
|
209
|
-
// 没有内容脱敏面」。因此它是**生命周期账本帧**,不是转录物 —— 投成中性内部臂交给 chrome 面
|
|
210
|
-
// 记账,绝不铸 transcript 行(铸一行就是替引擎编一条它没说过的话)。
|
|
211
|
-
// `humanInputProjection` 仍按 raw 记录读(逐键防御 + 白名单),不改口径:wire 是 JSON,引擎可能
|
|
212
|
-
// 比本包类型新一版,类型收窄不构成「字段一定合法」的保证。
|
|
213
80
|
case 'human_input':
|
|
214
81
|
return humanInputProjection(ev, ctx);
|
|
215
|
-
/**
|
|
216
|
-
* B-072 ④(0.65.0;core message-identity Phase 1 / server ≥7.69.0 live 腿真发)——
|
|
217
|
-
* 一条**可渲染消息**的会话树条目已落账。此前它落在 `not_in_slice`,理由写着「本切片无对位
|
|
218
|
-
* 渲染物」;那句话对**转录行**成立,对**定位**不成立:
|
|
219
|
-
* · core 的 `compacted.preserved_segment.firstKeptEntryId` 是一个 **entryId**,
|
|
220
|
-
* · core 同一段逐字说消费方**用本帧**自建 `entryId → message` 映射来解析它,
|
|
221
|
-
* ⇒ 只投 `preserved_segment` 而把本帧丢掉,等于把一个**解析不了的锚**交给端。
|
|
222
|
-
*
|
|
223
|
-
* 处置与同族 `human_input` 逐条相同:**中性内部臂**(不是 transcript 行 —— 本帧不带正文,
|
|
224
|
-
* 铸一行就是替引擎编一条它没说过的话),由 `adapt` 的臂转成 chrome 记账事件。
|
|
225
|
-
*
|
|
226
|
-
* 🔴 **两个必填位任一读不出 ⇒ `malformed` 留痕**,绝不铸半个账本行:一个空 `entryId` 落进端的
|
|
227
|
-
* 映射表会静默匹配掉一条真消息(比没有这一帧更坏)。`role` 按**开集**读(core 今天三词,
|
|
228
|
-
* 上游加第四词照过);`toolCallId` 只在 `role==='toolResult'` 腿上有,缺席不铸。
|
|
229
|
-
* ⚠️ **投递腿只有 live**(server 7.69.0 亲读):durable/bg 腿把本帧喂给了 rewind 锚而**不**入
|
|
230
|
-
* 账本 ⇒ 端在 replay/resume 上看不到它。这是上游的投递事实,不是本包的剥离 —— 端据此
|
|
231
|
-
* 建的映射表在 resume 腿上会是空的,`_sema_preserved_segment` 那一格因此要按「解析不出
|
|
232
|
-
* 就不画分割线」处理,不许回退成「画在最后一条」。
|
|
233
|
-
*/
|
|
234
82
|
case 'message_committed': {
|
|
235
83
|
const entryId = typeof ev.entryId === 'string' && ev.entryId.length > 0 ? ev.entryId : undefined;
|
|
236
84
|
const role = typeof ev.role === 'string' && ev.role.length > 0 ? ev.role : undefined;
|
|
@@ -242,64 +90,38 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
242
90
|
entryId,
|
|
243
91
|
role,
|
|
244
92
|
...(toolCallId !== undefined ? { toolCallId } : {}),
|
|
245
|
-
// §E2 身份:durable 重放同一条账本帧必须落成同一笔(同 human_input 的 eventId 纪律)。
|
|
246
93
|
...(typeof ev.eventId === 'string' && ev.eventId.length > 0 ? { eventId: ev.eventId } : {}),
|
|
247
94
|
...(typeof ev.parentToolCallId === 'string' && ev.parentToolCallId.length > 0
|
|
248
95
|
? { parentToolCallId: ev.parentToolCallId }
|
|
249
96
|
: {}),
|
|
250
97
|
})));
|
|
251
98
|
}
|
|
252
|
-
// service 1.75 — `workflow_complete`: an out-of-band background-workflow completion push, ridden onto
|
|
253
|
-
// the session's next stream open (BEFORE the run's own events). Projects to a NEUTRAL internal arm;
|
|
254
|
-
// the upstream bridge turns it into CC's `<task-notification>` injection.
|
|
255
|
-
// 🔴 **到期复核已兑现(sdk 6.2.0 提货批,2026-08-04)**:本臂此前是 switch 之前的**唯一** raw
|
|
256
|
-
// 预分派臂,理由写着「`workflow_complete` 至今不在 union 里……入 union 当天搬进 switch」。
|
|
257
|
-
// sdk 6.2.0 的 TR-7 批把它连同 question/elicitation 族一并加进了 `AgentEvent` union
|
|
258
|
-
// (判据 = `dist/events.d.ts` 出现 `type: "workflow_complete"`),故按原定计划搬进来 ——
|
|
259
|
-
// raw 预分派臂与 `raw` 变量一并退役,本函数从此**每一条臂都受 B5 编译期穷举保护**。
|
|
260
|
-
// 语义不变:至少一次投递(两条腿同开可能双发),消费方按 `runId` 去重(notifications 台账干这件事)。
|
|
261
99
|
case 'workflow_complete': {
|
|
262
100
|
if (typeof ev.runId !== 'string' || ev.runId.length === 0) {
|
|
263
101
|
return dropped('malformed', 'workflow_complete');
|
|
264
102
|
}
|
|
265
|
-
// A-004.9(病族⑤ default-arm-lie,2026-08-08):status 的**合同**是闭集 'completed'|'failed'
|
|
266
|
-
// (server workflow-completion-inbox.d.ts `status: "completed" | "failed"` 直证;sdk events.d.ts
|
|
267
|
-
// 宽成 string 只是类型面松),但 wire 是 JSON 开集——此前 `=== 'failed' ? failed : completed`
|
|
268
|
-
// 把任何第三词(上游未来加终态/坏帧垃圾值)**谎成 completed**。诚实形=与本臂 runId 缺失同款
|
|
269
|
-
// malformed 处置(dropped 留痕):第三词到达=上游换了合同,提货跟车该在这里翻红显形,而
|
|
270
|
-
// server 的 WorkflowStatus poll floor 对被丢的完成推送有结构性兜底(inbox 头注明写)。
|
|
271
103
|
if (ev.status !== 'completed' && ev.status !== 'failed') {
|
|
272
104
|
return dropped('malformed', 'workflow_complete');
|
|
273
105
|
}
|
|
274
106
|
return projected(stamp(ctx, armBody({
|
|
275
107
|
type: 'workflow_complete',
|
|
276
108
|
runId: ev.runId,
|
|
277
|
-
// 卫后二值闭集,三元只在 known 词间选路(TS 不从 string 否定收窄字面量,故保留三元形)。
|
|
278
109
|
status: ev.status === 'failed' ? 'failed' : 'completed',
|
|
279
110
|
summary: typeof ev.summary === 'string' ? ev.summary : '',
|
|
280
111
|
})));
|
|
281
112
|
}
|
|
282
|
-
// CS-1 §2.2 — turn-aggregated answer text (durable). Drop raw block array.
|
|
283
113
|
case 'text':
|
|
284
114
|
return projected(assistantArm(ctx, [{ type: 'text', text: ev.text }], ev.eventId));
|
|
285
|
-
// CS-3 §2.1 — turn-aggregated thinking (durable). Distinct collapsible block.
|
|
286
115
|
case 'reasoning':
|
|
287
116
|
return projected(assistantArm(ctx, [{ type: 'thinking', thinking: ev.text }], ev.eventId));
|
|
288
|
-
// CS-2 §2.4 — per-token answer fragment (live only). Typewriter append.
|
|
289
117
|
case 'text_delta':
|
|
290
118
|
return projected(streamEventArm(ctx, { type: 'text_delta', delta: ev.delta }));
|
|
291
|
-
// CS-4 §2.3 — per-token thinking fragment (live only). Drop signature_delta.
|
|
292
|
-
// §E2 identity (service 1.78 unblanked parentToolCallId on the wire, blackboard dogfood #2): thread it
|
|
293
|
-
// so the bridge can EXCLUDE a sub-flow's reasoning (orchestration/subagent) from the LEADER's spinner
|
|
294
|
-
// counter + thinking preview — the "134k tokens" overcount root cause (upstreamBridge TODO #9).
|
|
295
119
|
case 'reasoning_delta':
|
|
296
120
|
return projected(streamEventArm(ctx, {
|
|
297
121
|
type: 'thinking_delta',
|
|
298
122
|
delta: ev.delta,
|
|
299
123
|
...(ev.parentToolCallId !== undefined ? { parentToolCallId: ev.parentToolCallId } : {}),
|
|
300
124
|
}));
|
|
301
|
-
// CS-5 §2.5 — action-card open. args is `unknown`: render generically.
|
|
302
|
-
// §E2 — thread the wire eventId (+ parentToolCallId) so the bridge stamps it (SB-2).
|
|
303
125
|
case 'tool_start':
|
|
304
126
|
return projected(assistantArm(ctx, [
|
|
305
127
|
{
|
|
@@ -307,8 +129,6 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
307
129
|
id: ev.toolCallId,
|
|
308
130
|
name: ev.toolName,
|
|
309
131
|
input: ev.args,
|
|
310
|
-
// P0-2 — core 展示名(见 NeutralBlock.label 的完整对照记录)。防御读:SDK 0.0.103 已定型
|
|
311
|
-
// `label?: string`,但旧引擎/旧 server 缺席 ⇒ 键不出现,形状与修前逐字相同。
|
|
312
132
|
...(typeof ev.label === 'string' && ev.label.length > 0 ? { label: ev.label } : {}),
|
|
313
133
|
...(ev.eventId !== undefined ? { eventId: ev.eventId } : {}),
|
|
314
134
|
...(ev.parentToolCallId !== undefined
|
|
@@ -316,35 +136,8 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
316
136
|
: {}),
|
|
317
137
|
},
|
|
318
138
|
], ev.eventId));
|
|
319
|
-
// CS-8 §2.8 — compaction divider. tokensBefore ⇐ pre_tokens. core 1.219
|
|
320
|
-
// (attachWorkingFiles default ON): `attachedFiles:[{path,chars,truncated}]` rides through raw so
|
|
321
|
-
// the bridge can project the CC post-compact "Read {path}" attachment rows (blackboard ask ②).
|
|
322
|
-
//
|
|
323
|
-
// 🔴 **B-072 ①(0.65.0):`trigger` 由三词折叠改为开集透传**。修前这一格逐字是
|
|
324
|
-
// `ev.trigger === 'manual' ? 'manual' : 'auto'` —— 一张**闭集折叠表**,于是 core 5.16.0 起
|
|
325
|
-
// 真发的第三个值 `forced`(prompt-too-long 恢复腿 / trim-pressure 腿:压缩**不是可选的**)
|
|
326
|
-
// 到了包边界被改写成 `auto`。core 的臂注逐字点名这件事:wire 现在带的是**钩子层看见的
|
|
327
|
-
// 那个值**(`the SAME value the hooks saw instead of flattening it to "auto"`)——
|
|
328
|
-
// 上游刚刚停止做的折叠,包在下游又做了一遍,这正是 B-025 家族的形。
|
|
329
|
-
// ⚠️ **不是破坏性变更**:core 同一句写明 `Additive value space — a consumer switching on
|
|
330
|
-
// auto/manual keeps its exact old behavior`,CC 消费者按 `!== 'manual'` 分支的行为逐字不变。
|
|
331
|
-
// 缺席 / 空串 / 非串仍回落 `'auto'`(sdk 臂注逐字「缺席或未知值一律按 auto 渲染」)——
|
|
332
|
-
// 回落的是**读不出来**那一档,不是「读出来了但不认识」那一档。
|
|
333
|
-
// 🔴 **两个超集键**(`_sema_` 前缀,CC 同名键语义零改;缺席一律不铸):
|
|
334
|
-
// · `_sema_preserved_segment` ⇐ core `preserved_segment`(CC `SDKCompactBoundary` parity 位)
|
|
335
|
-
// —— 保留尾段的起点 entryId,端拿它把压缩分割线画在**那条消息之前**并重新接上尾段。
|
|
336
|
-
// 解析腿 = 本文件同批新投的 `message_committed` 臂(core 亲口:消费方用它自建
|
|
337
|
-
// `entryId → message` 映射)。半个锚不铸:载体在而 id 读不出 ⇒ 整键不出现。
|
|
338
|
-
// · `_sema_clamped_ratio` ⇐ core `clampedRatio`(design/145 §3)—— 这次压缩的摘要**输入**
|
|
339
|
-
// 被钳掉了多大比例。core 逐字 `bounded loss, disclosed either way` ⇒ 它是**披露**位,
|
|
340
|
-
// 真 0(「一点没钳」)是一条事实,**不是**缺席;缺席(旧引擎 / 没发生钳)则键不铸。
|
|
341
|
-
// 记账:server 7.69.0 `trace/project.js` 白名单真发这一键,而 sdk 8.8.0 的 `compacted`
|
|
342
|
-
// 臂上**还没有座位** ⇒ 这里是防御 raw 读(同 `label` / `model` 的既有姿势)。退役条件 =
|
|
343
|
-
// sdk 补上该位的当天,`run-compaction-boundary-projection-test.mjs` F10 行当场红逼复核。
|
|
344
139
|
case 'compacted': {
|
|
345
140
|
const raw = ev;
|
|
346
|
-
// 0.74.5 CC-85(core 7.24.0 #946):引擎自己测的结构性差值(core 侧夹 ≥ 0);旧的 tokensBefore / tokensAfter **不是可相减的一对**。
|
|
347
|
-
// 缺席 = 没测出来 ⇒ 键不落(渲「未知」不是 0);在场才带超集键。**负值 / 非有限在本包同样按缺席**(不夹到 0 —— 缺席比编一个 0 诚实;test 0.74.5 复验读数)。
|
|
348
141
|
const freedTokens = typeof raw.freedTokens === 'number' && Number.isFinite(raw.freedTokens) && raw.freedTokens >= 0 ? raw.freedTokens : undefined;
|
|
349
142
|
const attachedFiles = raw.attachedFiles;
|
|
350
143
|
const seg = raw.preserved_segment;
|
|
@@ -356,10 +149,6 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
356
149
|
type: 'system',
|
|
357
150
|
subtype: 'compact_boundary',
|
|
358
151
|
compact_metadata: {
|
|
359
|
-
// 开集透传:读得出的词原样过境;读不出(缺席/空串/非串)才回落 CC 的 'auto'。
|
|
360
|
-
// 🔴 **不写 `as 'auto' | 'manual'`**(修前那条 cast 现在会变成谎言):这一格的运行期值
|
|
361
|
-
// 域已经是开集,断言成两个字面量 = 型面对下一棒撒谎([cast-lies-need-a-gate-not-a-rule])。
|
|
362
|
-
// 留 `string` 即可 —— 本臂体最终仍走 `as unknown as SDKMessage`,没有任何约束要求它窄。
|
|
363
152
|
trigger: typeof ev.trigger === 'string' && ev.trigger.length > 0 ? ev.trigger : 'auto',
|
|
364
153
|
pre_tokens: ev.tokensBefore ?? 0,
|
|
365
154
|
...(typeof firstKeptEntryId === 'string' && firstKeptEntryId.length > 0
|
|
@@ -373,66 +162,12 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
373
162
|
...(Array.isArray(attachedFiles) && attachedFiles.length > 0 ? { attachedFiles } : {}),
|
|
374
163
|
})));
|
|
375
164
|
}
|
|
376
|
-
// CS-6 §2.6 — tool_end now carries the §E1 model-facing `output` (the action-card
|
|
377
|
-
// BODY) + isError + the §E2 eventId. Emit a NEUTRAL internal arm the bridge correlates
|
|
378
|
-
// to the open card by `toolCallId`; `output`/`truncated` ride through as-is (UNTRUSTED,
|
|
379
|
-
// observability-only). `output === undefined` ⇒ the tool produced no body → the bridge
|
|
380
|
-
// falls back to the mock synthesizer (events.d.ts:79). Not a renderable CC SDKMessage —
|
|
381
|
-
// a side-channel arm `sdkMessagesToCcEvents` reads; CC's own renderer never sees it.
|
|
382
165
|
case 'tool_end': {
|
|
383
|
-
// design/64 [363] — `structured` is the engine's opt-in CC-shaped details field (core 1.199+
|
|
384
|
-
// AgentToolResult.details on the wire; not yet in the SDK tool_end arm — raw defensive read).
|
|
385
|
-
// Rides the neutral arm so the bridge can render the REAL rich card (diff / stdout panels).
|
|
386
166
|
const structured = ev.structured;
|
|
387
|
-
// core 5.10.0 — 被**中断**的 call 的合成 `tool_end` 终于带机器码(`interrupted_never_started` /
|
|
388
|
-
// `interrupted_outcome_unknown`,来自持久化的 `details.errorKind`)。此前这一帧只有
|
|
389
|
-
// `isError:true` 而无正文、无码 ⇒ 从帧渲染工具输出的消费者看到空结果,还只能去正则匹配散文
|
|
390
|
-
// 才知道是哪一种中断。`output`/`label` 本臂本来就透传,缺的是这个**判别位**。
|
|
391
|
-
// 🔴 开集 + 防御读:`tool_end.errorCode` 不在 sdk 6.2.0 的 tool_end 臂类型里(SDK 面尚未跟上
|
|
392
|
-
// core 5.10.0),故按 unknown 读;两员之外的未来码**照样原样透传**,窄化只做「是不是串」,
|
|
393
|
-
// 绝不按识别表过滤(过滤 = 替引擎决定哪些原因配得上被看见)。判别用
|
|
394
|
-
// `engineErrorCodes.isInterruptedToolEndCode`,不要在消费点重新写字面比较。
|
|
395
167
|
const toolEndErrorCode = ev.errorCode;
|
|
396
|
-
// ── 0.60.0(engine ≥7.64.0 / sdk 8.4.0):四个正交词 → 一条门记录 `tool_end.gate` ──────────
|
|
397
|
-
// 退役的 `settledBy` / `resolution` / `autoDenied` / `approver` **四键全删,无 alias**(上游
|
|
398
|
-
// 类型面 BREAKING)。继任者是一条记录:`disposition`(放行 / 被哪一**层**拒)+ `settlement?`
|
|
399
|
-
// (这次消费掉的等待怎么结束的)+ `origin?`(谁问的),后两位**同在同缺**。
|
|
400
|
-
// 🔴 **窄读单源在包里**(`gateOutcome.gateOutcomeOf`),本臂只负责把成形的那只**原样上臂** ——
|
|
401
|
-
// 此前四个词各自在这里做一次 `typeof === 'string'` 窄化,而端还要再自拼一个两键合取才能
|
|
402
|
-
// 回答「这次是不是审批窗自己走完的」。判定归包之后端调谓词,不再自拼(见 gateOutcome.ts)。
|
|
403
|
-
// 🔴 **不成形就不铸键**(绝不折成 null / 空对象):缺席在上游是**四种不可分辨的成因**
|
|
404
|
-
// (门没看见这次调用 / 延后重发 / reconcile 捡回的孤儿 / 记录过不了引擎的筛而 server
|
|
405
|
-
// 整条不投),一律退回 `isError` + 文案 —— 铸一个空壳会让端把「不知道」读成「放行过」。
|
|
406
|
-
// 🔴 **UNTRUSTED-for-display**:`settlement.who.approver` 与 `settlement.note` 是部署侧审批
|
|
407
|
-
// 通道自报/拒批人自写的自由文本(转录不是认证),只渲染,绝不回喂模型/工具入参,更不许
|
|
408
|
-
// 当鉴权判据。
|
|
409
168
|
const toolEndGate = gateOutcomeOf(ev);
|
|
410
|
-
// ── core ≥7.6.0(S6-B):这次 **MCP** 失败**到没到那台服务器** ─────────────────────────────
|
|
411
|
-
// 🔴 与 {@link errorCode} **合读**才有意义:同一个 `connection_closed`,`no` 可以直接重试
|
|
412
|
-
// (什么都没发出去)、`unknown` 必须先去查(请求可能已经执行了)。带写副作用的工具在
|
|
413
|
-
// `unknown` 上必须先核实再重试 —— 这条判别力单看码拿不到,所以这一位非透传不可。
|
|
414
|
-
// 🔴 **不在本层收窄成三词**:词表属主是引擎(与 `settledBy` 那一代的开集纪律逐字同规),
|
|
415
|
-
// 抄一份会把新词吞成缺席。非空串即原样透传。
|
|
416
|
-
// 🔴 **缺席不带语义**:每一次执行成功的调用、每一次非 MCP 失败都不带它。
|
|
417
169
|
const toolEndDelivered = ev.delivered;
|
|
418
|
-
// ── core ≥5.55.0(#333):耐久 park 正扣着**哪一个** tool call 的 id ────────────────────────
|
|
419
|
-
// 引擎从已提交 checkpoint 的 pendingAction 直读(**禁由工具自报**)。只挂在 park 污染帧上;
|
|
420
|
-
// tool-less park(resource_limit / plan_review / task_done)**整键缺席**,契约逐字
|
|
421
|
-
// "ABSENT, never guessed" —— 缺席不铸键、也不猜。
|
|
422
170
|
const toolEndGatedCallId = ev.gatedCallId;
|
|
423
|
-
// ── #324 半场(0.40.0):连坐 abort 机读位 `_sema_collateral_abort`([4907] 裁定)──
|
|
424
|
-
// 出处**不是引擎**,是本包自己的 HITL 桥:`gateLedger.flushHeld` 对「出身 = collateral」的
|
|
425
|
-
// 扣留帧 stamp(见 `SEMA_COLLATERAL_ABORT_KEY` 头注)。桥在本臂**上游**(宿主先用
|
|
426
|
-
// `bridgeAskUserQuestionGates` 包住事件流,再喂 `eventToSdkMessage`),所以这一位到本臂时
|
|
427
|
-
// 已经在帧上了。
|
|
428
|
-
// 🔴 不转发 = 本臂白名单把它整段剥掉 ⇒ 宿主无论怎么写都读不到一条**本包自己刚打上去**的事实,
|
|
429
|
-
// 正是上面那段头注点名的 [1947] `toolCallId` / [2942] `governanceForced` / #263 两键
|
|
430
|
-
// 同款病形的下一例。缺席不铸键(严格 `true` 才铸,别的值一律当没有 —— 机读位是二值的,
|
|
431
|
-
// 「在场但不是 true」没有语义,折成在场会让消费端把一个坏形当成肯定)。
|
|
432
|
-
// 🔴 **只上内部臂,不进转录卡**:本臂是壳内部侧信道(见文件头注),转录 `tool_result` block
|
|
433
|
-
// 会随 `/compact` 直发 provider —— 往 block 上加自铸键正是 0.5.0 `label` 那个真缺口的形状
|
|
434
|
-
// (provider 400)。要让这一位进呈现面,归宿主在臂上读(壳 upstreamBridge 的 tee 就是
|
|
435
|
-
// `errorCode` 指路行同款既有位),不是往卡体里塞。
|
|
436
171
|
const collateralAbort = ev._sema_collateral_abort;
|
|
437
172
|
return projected(stamp(ctx, armBody({
|
|
438
173
|
type: 'tool_end_result',
|
|
@@ -442,24 +177,17 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
442
177
|
...(typeof toolEndErrorCode === 'string' && toolEndErrorCode.length > 0
|
|
443
178
|
? { errorCode: toolEndErrorCode }
|
|
444
179
|
: {}),
|
|
445
|
-
// P0-2([1725] 清单A)— `tool_end.label` 同 tool_start 待遇(server trace/project.js:61 白名单
|
|
446
|
-
// 本体产出)。此臂是壳内部侧信道(不进 transcript),所以这里带着无 provider 风险;
|
|
447
|
-
// tool_start 先到时 bridge 已登记过,这条是补位(只有 tool_end 带 label 的场景)。
|
|
448
180
|
...(typeof ev.label === 'string' && ev.label.length > 0 ? { label: ev.label } : {}),
|
|
449
181
|
...(ev.output !== undefined ? { output: ev.output } : {}),
|
|
450
182
|
...(structured !== undefined ? { structured } : {}),
|
|
451
183
|
...(ev.truncated !== undefined ? { truncated: ev.truncated } : {}),
|
|
452
|
-
// 0.60.0:整条门记录(不成形不铸键;顶部大段头注是判据本体)。
|
|
453
184
|
...(toolEndGate !== undefined ? { gate: toolEndGate } : {}),
|
|
454
|
-
// S6-B:MCP 投递判词(开集、缺席不铸、在场原样)。
|
|
455
185
|
...(typeof toolEndDelivered === 'string' && toolEndDelivered.length > 0
|
|
456
186
|
? { delivered: toolEndDelivered }
|
|
457
187
|
: {}),
|
|
458
|
-
// #333:耐久 park 正扣着哪个 call(缺席不铸,绝不猜)。
|
|
459
188
|
...(typeof toolEndGatedCallId === 'string' && toolEndGatedCallId.length > 0
|
|
460
189
|
? { gatedCallId: toolEndGatedCallId }
|
|
461
190
|
: {}),
|
|
462
|
-
// #324:连坐 abort 机读位(严格 true 才上臂;见上方头注)。
|
|
463
191
|
...(collateralAbort === true ? { _sema_collateral_abort: true } : {}),
|
|
464
192
|
...(ev.eventId !== undefined ? { eventId: ev.eventId } : {}),
|
|
465
193
|
...(ev.parentToolCallId !== undefined
|
|
@@ -467,42 +195,7 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
467
195
|
: {}),
|
|
468
196
|
})));
|
|
469
197
|
}
|
|
470
|
-
// §E3/§E10 — BrainStatus liveness. Phases: rate_limited/retrying/reconnecting/circuit_open +
|
|
471
|
-
// (core 5.x) recovered/gave_up — the two TERMINAL phases; `recovered` means the retry SUCCEEDED,
|
|
472
|
-
// so the overlay must be TORN DOWN, not rendered as an error (see retryStatus.ts). Project to a
|
|
473
|
-
// NEUTRAL internal `retry_status` arm forwarding the provider-neutral fields verbatim —
|
|
474
|
-
// NOT a renderable CC SDKMessage. The upstream bridge (sema layer) maps phase→SpinnerRetryStatus +
|
|
475
|
-
// publishes to the sema retry-status store the spinner override reads (187's per-agent
|
|
476
|
-
// `afa(agentId).retryStatus` app-state analog, ui-modules/0157_036_ui_Klo.js:31). The seam stays a
|
|
477
|
-
// dumb forwarder: the provider-neutral→UI-shape mapping is the renderer layer's job (retryStatusStore).
|
|
478
198
|
case 'status': {
|
|
479
|
-
// 🔴 开集 + 防御读(#3004 跟修批 2026-08-08,与上面 `tool_end.errorCode` 同族姿势):core
|
|
480
|
-
// `BrainStatus` 自 5.x 起还带 attempt / maxRetries / retryInMs 三键,server 两腿的
|
|
481
|
-
// `brainStatusEventData`(dist/trace/project.js)照发,而 SDK 的 `status` 臂类型只声明
|
|
482
|
-
// phase/detail/retryInSec(SDK 面尚未跟上 core)。类型面缺席不等于 wire 上缺席 —— 按
|
|
483
|
-
// unknown 读、按 number 窄化后原样透传,否则引擎真发的量在这一层就被剥掉了。
|
|
484
|
-
// 键集真源 = retryStatus.ts 的 `BRAIN_STATUS_PAYLOAD_KEYS`(engine-vocab G2-c 对账)。
|
|
485
|
-
// #307 S44(2026-08-19):core 5.43.0 又加了 `errClass`(这次等待的**原因分桶**,
|
|
486
|
-
// provider 中立闭集)—— SDK 的 `status` 臂类型同样还没跟,同款 unknown 读 + 串窄化透传。
|
|
487
|
-
// 🔴 **四键的 cast 已退(0.48.0)**:上面那段说的「SDK 的 `status` 臂类型只声明
|
|
488
|
-
// phase/detail/retryInSec」在 sdk 7.4.0 上**不再成立** —— 该臂现已声明 **7 键**
|
|
489
|
-
// (phase/detail/retryInSec/retryInMs/attempt/maxRetries/errClass,`dist/events.d.ts` 直读)。
|
|
490
|
-
// peer 地板同批抬到 >=7.4.0 ⇒ attempt/maxRetries/retryInMs/errClass 四位改类型面直读。
|
|
491
|
-
// 退役的是 **cast**,不是运行期窄化:`num()` / 非空串门全部保留(wire 是 JSON,旧 server
|
|
492
|
-
// 仍可能发别的形;类型声明是上游承诺,不是本层前提)。
|
|
493
|
-
// 🔴 **两位仍走结构视图读**(0.48.0 新增,**同形第三、第四例**):core 7.0.x #506 ㋑ 起
|
|
494
|
-
// `BrainStatus` 还带 `retryAtMs`(产生者铸的墙钟截止点)与 `errorStatus`(刚失败那次尝试的
|
|
495
|
-
// HTTP 状态),server ≥7.53 的 `brainStatusEventData` **两键全发**(7.54.0 dist 真字节直证),
|
|
496
|
-
// 而 **sdk 7.4.0 的 `status` 臂尚未声明这两位** —— 与 `model`(#363)/`requiresRealApproval`
|
|
497
|
-
// (#283)/`ruleOffers`(#334)同形:server 已真发、SDK 锚未跟。照那几例的先例**先追 server
|
|
498
|
-
// 不等 SDK**,类型面缺席不等于 wire 上缺席。
|
|
499
|
-
// 📋 **退役条件**:sdk 把这两位补进 `status` 臂声明的那一批,把它们并进上面的类型面直读、
|
|
500
|
-
// 删掉本段的 `st2` 结构视图(与本批刚兑现的四键退役逐字同一条路)。
|
|
501
|
-
// 🔴 **0.55.0 又添两位,同一条退役路**(core 7.3.0 #530 / server ≥7.58 `brainStatusEventData`
|
|
502
|
-
// 放行):`elapsedMs`(第一个 token 已被等了多久)与 `timeoutMs`(这次等待的天花板)。
|
|
503
|
-
// 它们只在新相 `waiting_first_token` 上在场,而那一相**除了 phase 就只有这两位带信息** ——
|
|
504
|
-
// 本层剥掉 = 新相到了下游只剩一个空壳,屏上渲不出「等了多久」。sdk 的 `status` 臂同样尚未
|
|
505
|
-
// 声明这两位 ⇒ 与上面两位同款结构视图读,退役条件同(sdk 补声明的那一批一起并进类型面直读)。
|
|
506
199
|
const st2 = ev;
|
|
507
200
|
const num = (v) => typeof v === 'number' && Number.isFinite(v) ? v : undefined;
|
|
508
201
|
const attempt = num(ev.attempt);
|
|
@@ -512,7 +205,6 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
512
205
|
const errorStatus = num(st2.errorStatus);
|
|
513
206
|
const elapsedMs = num(st2.elapsedMs);
|
|
514
207
|
const timeoutMs = num(st2.timeoutMs);
|
|
515
|
-
// 非空串才透传(空串既不是桶也不是「不知道」,只会在下游被渲成一个空的原因)。
|
|
516
208
|
const errClass = typeof ev.errClass === 'string' && ev.errClass.length > 0 ? ev.errClass : undefined;
|
|
517
209
|
return projected(stamp(ctx, armBody({
|
|
518
210
|
type: 'retry_status',
|
|
@@ -523,110 +215,21 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
523
215
|
...(attempt !== undefined ? { attempt } : {}),
|
|
524
216
|
...(maxRetries !== undefined ? { maxRetries } : {}),
|
|
525
217
|
...(errClass !== undefined ? { errClass } : {}),
|
|
526
|
-
// ── 0.48.0 跟车两位(core 7.0.x #506 ㋑ / server ≥7.53 两腿全发)────────────────────
|
|
527
|
-
// 🔴 **这一处是族扫的第二个坐标,不是第一个**:本批的病形(上游真发、闭形白名单剥掉)在
|
|
528
|
-
// `status` 这条腿上有**两层**白名单 —— 本层(wire → 内部 retry_status 臂)与
|
|
529
|
-
// `adapt/arms.ts` 的 `retryStatusArm`(内部臂 → RetryStatus)。只修其中一层,键仍到不了
|
|
530
|
-
// 宿主([same-shape-residue-constitution]:只修当格 = 违宪)。两层同批修,门 G4 驱的是
|
|
531
|
-
// **全链**(adapt 入口 → chrome 事件),所以漏任一层它都红。
|
|
532
218
|
...(retryAtMs !== undefined ? { retryAtMs } : {}),
|
|
533
219
|
...(errorStatus !== undefined ? { errorStatus } : {}),
|
|
534
|
-
// ── 0.55.0 跟车两位(core 7.3.0 #530 / server ≥7.58 放行)──────────────────────────
|
|
535
|
-
// 族扫同址:本条腿的**两层白名单**(本层 + `adapt/arms.ts` 的 `retryStatusArm`)本批同改,
|
|
536
|
-
// 与上面 0.48.0 那两位逐字同一个理由;漏任一层,新相 `waiting_first_token` 的秒数就到不了壳。
|
|
537
220
|
...(elapsedMs !== undefined ? { elapsedMs } : {}),
|
|
538
221
|
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
539
|
-
// 🔴 §E2 lane 身份必须透传(2026-08-08 对抗复审二轮复审命中的**跨 lane 状态破坏**)。
|
|
540
|
-
// `status` 臂本来就是 `& EventIdentity`(SDK events.d.ts),server 两腿共用的
|
|
541
|
-
// `brainStatusEventData` 也经 `identityFields` 发 eventId/parentToolCallId —— 而本层此前
|
|
542
|
-
// 把两键都剥掉了。后果:`arms.ts` 的 `retryStatusArm` 首行那条子代断闸
|
|
543
|
-
// (`if (typeof m.parentToolCallId === 'string') return`,#47 矩阵 #5)在 wire 路径上**恒不命中**,
|
|
544
|
-
// 子代的 status 一直骑着主 spinner。旧代际下这只是显示噪声;`recovered` 相落地后它升级成
|
|
545
|
-
// 真状态破坏:**子代**的 recovered 会去 `takeRetryOverlay()` 消费掉**宿主**仍在重试的覆盖层,
|
|
546
|
-
// 向用户谎报「宿主已恢复」,而宿主随后真正的 recovered 反被判成「没有覆盖层」而沉默。
|
|
547
|
-
// 两键防御读(旧 server 缺席 ⇒ 键不 stamp,形状不变)。
|
|
548
222
|
...(typeof ev.eventId === 'string' ? { eventId: ev.eventId } : {}),
|
|
549
223
|
...(typeof ev.parentToolCallId === 'string' ? { parentToolCallId: ev.parentToolCallId } : {}),
|
|
550
224
|
})));
|
|
551
225
|
}
|
|
552
|
-
// MF-10 (design/99, events.d.ts task_progress) — a SUBAGENT PROGRESS TICK: the delegated sub-run's
|
|
553
|
-
// CUMULATIVE usage at each turn boundary (LIVE/EPHEMERAL, never persisted/replayed). Project to a
|
|
554
|
-
// NEUTRAL internal `task_progress` arm — NOT a renderable CC SDKMessage. The upstream bridge binds it
|
|
555
|
-
// to the open Task/Agent tool_use card and synthesizes CC-native `progress` messages so CC's own
|
|
556
|
-
// Task-card rollup (tool uses / tokens climbing) animates for an ENGINE-side subagent exactly like a
|
|
557
|
-
// local AgentTool one. Fields are read DEFENSIVELY: the service wire whitelist may omit `name` —
|
|
558
|
-
// mirror what actually rides the wire, not the richer core-side arm.
|
|
559
|
-
// 🔴 **就地订正**(#363,0.47.0,真字节实证):本句原文写的是「the service wire whitelist
|
|
560
|
-
// (server.ts:1334-1342) strips `status` + EventIdentity」—— 那是**错的**,而且方向正好相反:
|
|
561
|
-
// server 7.52.1 的 `taskProgressEventData` **发** `status`,`identityFields` 也**发**
|
|
562
|
-
// `eventId` + `parentToolCallId`(见下面的族扫账)。剥掉它们的是**本层**,不是 service。
|
|
563
|
-
// 这句错话正是「两边代码看着都对」的一部分:它把本层自己的白名单说成了上游的缺席。
|
|
564
|
-
//
|
|
565
|
-
// ── 🔴 本臂白名单的**族扫账**(#363,0.47.0;真源 = server 7.52.1 `trace/project.js` 的
|
|
566
|
-
// `taskProgressEventData` + `identityFields` 真字节,不是推断)────────────────────────────
|
|
567
|
-
// server 投影**发** 13 键:taskId · seq · taskType · parentTaskId · name · model · status ·
|
|
568
|
-
// usage · currentAction · workflowRunId · workflowAgentLabel · eventId · parentToolCallId。
|
|
569
|
-
// 本臂**转** 8 键:taskId · name · usage · model · currentAction · workflowRunId ·
|
|
570
|
-
// workflowAgentLabel · parentToolCallId。
|
|
571
|
-
// ⇒ **仍被本层剥掉的 5 键**(逐条登记,刻意不静默多透 —— 每一位都要有消费方与语义才配上臂):
|
|
572
|
-
// · `taskType` / `status` / `parentTaskId` —— 早已在册的 §7 缺口 **P-1**(lane 归属今天改用
|
|
573
|
-
// id 形状 / `workflowRunId` 启发式判,见 `src/adapt/arms.ts`);
|
|
574
|
-
// · `seq` —— core #258 的 stop-cycle 代际号(复活即 +1)。fleet 面已有同轴的
|
|
575
|
-
// `wireCycleSeq`(0.38.0),tick 这条腿今天**没有**消费方。
|
|
576
|
-
// ⚠️ **就地订正(0.48.0)**:本条 0.47.0 的原文写着「SDK 7.3.0 的 `task_progress` 臂连声明
|
|
577
|
-
// 都没有」—— sdk **7.4.0 已声明** `seq?: number`(与 `model` 同批补上,JSDoc 逐字点名
|
|
578
|
-
// core 5.36.0 #258 两铸点)。⇒ **剥它的理由换了一条,但仍然剥**:剥的判据从来不是「SDK 没
|
|
579
|
-
// 声明」(那只是当时顺带成立的第二个事实),而是本白名单的准入条件 ——「说得出谁读它、读来
|
|
580
|
-
// 干什么」。今天这条腿的答案仍是零消费方 ⇒ 照旧不透,P-1 族账不动。声明到货**不是**透传的
|
|
581
|
-
// 理由,否则这张白名单会随上游类型面自动变宽,准入条件形同虚设。
|
|
582
|
-
// · `eventId` —— EventIdentity 的另一半。`status` 臂 2026-08-08 已因跨 lane 状态破坏补齐两键,
|
|
583
|
-
// 本臂只补了 `parentToolCallId`(lane 判据要它),`eventId` 至今无消费方。
|
|
584
|
-
// 上面三档的共同纪律:要透哪一位,先说得出**谁读它、读来干什么**,并同批更新 §3d 的键级剥离账。
|
|
585
226
|
case 'task_progress': {
|
|
586
227
|
if (typeof ev.taskId !== 'string')
|
|
587
228
|
return dropped('malformed', 'task_progress');
|
|
588
|
-
// core 1.262.0 [558]B / service 1.154.0 [579] — `currentAction`: the child's most recent tool
|
|
589
|
-
// intent as ONE human line ("Bash npm test"), derived from the child's tool_start (tool name +
|
|
590
|
-
// argument head) and service-redacted. SDK ≥0.0.108 已定型(events.d.ts task_progress 臂),
|
|
591
|
-
// cast 已退;runtime 门保留(旧 server 缺席 ⇒ 键不 stamp)。
|
|
592
229
|
const currentAction = ev.currentAction;
|
|
593
|
-
// W1 段1([1616]/[1617]②,frame-lane-matrix #2)— core 1.401 起前台 workflow 子代 tick 带
|
|
594
|
-
// `workflowRunId`/`workflowAgentLabel`(lane 归属自描述位)。此前这层 spread 白名单把两键剥掉,
|
|
595
|
-
// bridge 想判 lane 也判不了(「送到了但没人读」的精确坐标其实是「没转」)。additive 透传,
|
|
596
|
-
// 防御读(旧 core/server 缺席 ⇒ 形状不变)。注意 server 侧 project.ts 投影白名单在 1.272.0
|
|
597
|
-
// 仍剥这两键(server a76bd77 才修,[1619])——真 wire 于 1.273+ 才带,此处先备好通路。
|
|
598
230
|
const workflowRunId = ev.workflowRunId;
|
|
599
231
|
const workflowAgentLabel = ev.workflowAgentLabel;
|
|
600
|
-
// #363(0.47.0,提货批取证定谳)— `model`:这条 tick 所属子 run 的**模型 id**。
|
|
601
|
-
// 🔴 上游真字节(不是推断):server 7.52.1 `dist/trace/project.js` 的
|
|
602
|
-
// `taskProgressEventData` 白名单里逐字有
|
|
603
|
-
// `...(typeof ev.model === "string" && ev.model.length > 0 ? { model: ev.model } : {})`,
|
|
604
|
-
// 三条腿(bg runs.ts / resume append / 同步 live SSE)共用它;core 铸点 = `prepared.model.id`。
|
|
605
|
-
// cli 侧 live 采帧同批实证过一条真帧带 `"model":"deepseek-v4-flash"`。
|
|
606
|
-
// 🔴 病形与 `workflowRunId` **同形第二例**([1616]/[1617]②):这层白名单是闭形的,于是一条
|
|
607
|
-
// **已经在 wire 上**的事实到不了宿主,而两边代码看着都对(「送到了但没人读」的精确坐标
|
|
608
|
-
// 其实是「没转」)。additive 透传,旧 server 缺席 ⇒ 键不 stamp,形状逐字节不变。
|
|
609
|
-
// 🔴 **cast 已退(0.48.0,退役条件兑现)**:0.47.0 这一行是 `const model: unknown =
|
|
610
|
-
// (ev as { model?: unknown }).model`,理由 = sdk 7.3.0 的 `task_progress` 臂尚未声明这一位
|
|
611
|
-
// (与 `requiresRealApproval` #283 / `ruleOffers` #334 同形:**server 已真发、SDK 锚未跟**),
|
|
612
|
-
// 头注同批写死了退役条件「SDK 补上当天这处 cast 可整条删掉」。sdk **7.4.0 已声明**
|
|
613
|
-
// `model?: string`(`dist/events.d.ts` task_progress 臂,JSDoc 逐字点名 server ≥7.53 /
|
|
614
|
-
// core 7.0.1 两处无条件铸点)+ 本包 peer 地板同批抬到 `>=7.4.0` ⇒ 按条款兑现,改类型面直读。
|
|
615
|
-
// 退役的是 **cast**,不是运行期判:`typeof` 门保留(旧 server 缺席 ⇒ 键不 stamp;
|
|
616
|
-
// wire 是 JSON,类型声明是上游承诺不是本层前提)。
|
|
617
|
-
// 🔴 条件 spread 与 server 投影**同形同条件**:`string` 且非空才带。空串既不是模型 id 也不是
|
|
618
|
-
// 「不知道」,透下去只会在面板上渲成一个空模型名([honest-absence-not-fabricated-zero])。
|
|
619
232
|
const model = ev.model;
|
|
620
|
-
// 🔴 B-074(0.65.0)—— `status`:这一格是**行的终态信号**,而修前这张白名单里没有它,于是
|
|
621
|
-
// core 明写会发的那一拍(`ONE final tick fires at the sub-run's settle with the terminal
|
|
622
|
-
// face`)到了宿主手上与一次普通 running 拍**逐字节同形** ⇒ 面板行只能等防御 sweep 或一条
|
|
623
|
-
// 通知帧来收尸(core 那句话的下半段正是「so a uuid-lane consumer sees the row finish
|
|
624
|
-
// instead of a bare removal after the last running beat」)。与 `model` / `workflowRunId`
|
|
625
|
-
// 是**同一病形的第 N 例**:事实已经在 wire 上,而包边界这一格空转。
|
|
626
|
-
// server `taskProgressEventData` 白名单逐字 `...(ev.status !== undefined ? { status: ev.status } : {})`。
|
|
627
|
-
// **开集读**:core 今天三词、sdk 已标 `| (string & {})`;词表属主在 core,包只透传不裁决
|
|
628
|
-
// (谁是终态由 adapt 层按 core 明写的两个词判,见 `arms.ts` 的 `TERMINAL_TICK_STATUSES`)。
|
|
629
|
-
// 空串/非串不铸 —— 与本臂其余条件 spread 同一判据(空串既不是词也不是「不知道」)。
|
|
630
233
|
const status = ev.status;
|
|
631
234
|
return projected(stamp(ctx, armBody({
|
|
632
235
|
type: 'task_progress',
|
|
@@ -649,58 +252,17 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
649
252
|
: {}),
|
|
650
253
|
})));
|
|
651
254
|
}
|
|
652
|
-
// ── REF-CC-060(xlate-06):以下四臂**已在 SDK union 里**,从 switch 之前的手搓 raw 预分派
|
|
653
|
-
// 搬进来成为正式 case。搬之前它们永远到不了 switch,`ev.type` 的穷举性对它们失效 ——
|
|
654
|
-
// 也就是说 union 给这四臂新增/改名任何位,编译期一声不响。防御读(`typeof`/`Array.isArray`)
|
|
655
|
-
// 一条不减:wire 是 JSON,类型不在运行期存在(M0/M1)。
|
|
656
|
-
//
|
|
657
|
-
// core 1.204 G2b — `task_notification` (background-bash/workflow completion, TaskNotificationPayload
|
|
658
|
-
// rides on `notification`). Projects to a NEUTRAL internal arm: the REPL bridge drops it (the ENGINE
|
|
659
|
-
// already steer-injects the model-facing XML), the print-mode `ask` converts it to CC's
|
|
660
|
-
// `system/task_notification` SDK frame.
|
|
661
|
-
/**
|
|
662
|
-
* `wiring_manifest` —— 引擎的**接线自述**(leg / ask / question / parkLane / … 指纹)。
|
|
663
|
-
*
|
|
664
|
-
* 🔴 **本臂只投两段,不是整份 manifest**(射程写在这里,免得下一个人读成「manifest 接上了」)。
|
|
665
|
-
* 整份 manifest 是 operator / 诊断面的读物,CC transcript 无对位物 —— 此前本臂与两条 HITL 帧
|
|
666
|
-
* 并列走 `nothing('not_in_slice')`,那句话对**其余每一段**今天仍然成立。改的只是:`modelGate`
|
|
667
|
-
* 与 `autoMode` 这两段是**终端用户面**的事实(「这一 run 你少了哪些工具」/「auto 到底武没武装」),
|
|
668
|
-
* 它们没有第二条到达消费端的路,留在 not_in_slice 里就是静默蒸发。
|
|
669
|
-
*
|
|
670
|
-
* 🔴 **帧是 FLAT 的,没有 `manifest` 包层**(SDK `events.d.ts` 的 wiring_manifest 臂逐字:
|
|
671
|
-
* server 把 core `TaskEvent` 的 `ev.manifest` 过白名单 builder 后 **spread 进帧**,三条腿
|
|
672
|
-
* (live SSE / durable 账本行 / resume 重放)同源)⇒ 读 `ev.modelGate` / `ev.autoMode`,
|
|
673
|
-
* **不是** `ev.manifest.modelGate`。6.7.0 契约声明过的那层 `manifest:{...}` 嵌套 wire 上从未有过。
|
|
674
|
-
*
|
|
675
|
-
* 🔴 **两段各自独立**:一段畸形不牵连另一段;两段都不成形 ⇒ 仍回 `none/not_in_slice`,
|
|
676
|
-
* **不铸空臂** —— 每条腿都会来一帧 wiring_manifest,为它们各铸一条什么都不说的内部臂只会让
|
|
677
|
-
* 消费端每 run 多收一条噪声,还把「本 run 真有门卸」这件事稀释掉。
|
|
678
|
-
*
|
|
679
|
-
* 🔴 **超集键走 `_sema_` 前缀**:`modelGate`/`autoMode` 今天**不在**已发布 SDK 的 `AgentEvent`
|
|
680
|
-
* wiring_manifest 臂里(sdk 8.1.0 `dist/events.d.ts` 全树零命中,亲验)。本包不许自铸 SDK 同名
|
|
681
|
-
* 形去冒充上游词汇;等 SDK 声明该臂后再谈改名(那是 BREAKING,另立)。
|
|
682
|
-
*/
|
|
683
255
|
case 'wiring_manifest': {
|
|
684
|
-
// 🔴 `as unknown as Record<…>` 不是图省事:sdk 8.1.0 的 wiring_manifest 臂**没有**这两段
|
|
685
|
-
// (亲验全树零命中),所以 `ev` 在这里被窄成一个不含它们的具名形 —— 直接读会是编译期
|
|
686
|
-
// 「属性不存在」。这行 cast 就是「上游类型还没到货」这件事的**可见落点**;SDK 声明该臂
|
|
687
|
-
// 之后把它删掉,编译器会立刻指出所有该跟着改的地方。
|
|
688
256
|
const raw = ev;
|
|
689
257
|
const body = wiringManifestSupersetBody(raw);
|
|
690
258
|
if (body === undefined)
|
|
691
259
|
return nothing('not_in_slice');
|
|
692
|
-
// `eventId` 与别的臂同律带上(core 铸的事件身份;wire 未必带 ⇒ 缺席时键不在场)。
|
|
693
|
-
// 🔴 主会话收货门 A1c 抓出的死臂:适配层 `wiringManifestArm` 读 `m.eventId`,而本层原来没投它,
|
|
694
|
-
// 那句透传永远是空 —— 消费端拿不到幂等键,durable 重放只能退到内容去重。
|
|
695
|
-
// 三键身份同函数透传 + 坏值不买路(异源对抗复审第 1 轮 finding②:修前只留 eventId,臂看不见 sourceTaskId / bgAgentId,
|
|
696
|
-
// 子代的接线快照(0.71.0 起含 tools 名册)会上 leader 面、被端当作名册重同步基线)。
|
|
697
260
|
const { identity, bad } = identityOrMalformed(raw, 'wiring_manifest');
|
|
698
261
|
if (bad !== null)
|
|
699
262
|
return bad;
|
|
700
263
|
return projected(stamp(ctx, armBody({ type: 'wiring_manifest', ...body, ...identity })));
|
|
701
264
|
}
|
|
702
265
|
case 'task_notification': {
|
|
703
|
-
// 载荷两形:嵌在 `notification` 里(server 早期形)或直接摊在帧上(今天的 union 形)。
|
|
704
266
|
const nested = ev.notification;
|
|
705
267
|
const n = (nested ?? ev);
|
|
706
268
|
if (typeof n.task_id !== 'string')
|
|
@@ -710,17 +272,7 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
710
272
|
notification: n,
|
|
711
273
|
})));
|
|
712
274
|
}
|
|
713
|
-
// core 1.220 design/121 — engine LSP `diagnostics` frame ({files:[{uri,diagnostics}], isNew}, service
|
|
714
|
-
// §E1 redacted, TOC host lane default ON). Projects to a NEUTRAL internal arm; the REPL bridge maps it
|
|
715
|
-
// into the CC `diagnostics` attachment row (DiagnosticsDisplay renders it, zero new UI).
|
|
716
|
-
// parentToolCallId rides through so the bridge can keep a sub-flow's diagnostics off the leader transcript.
|
|
717
275
|
case 'diagnostics': {
|
|
718
|
-
// ADAPTER-F6(2026-08-02 全窗复审):两种「files 不可渲染」此前塌成同一个 `malformed` ——
|
|
719
|
-
// · **非数组** = 必填位畸形,引擎发了我们读不动 ⇒ dropped/malformed(留痕该吼);
|
|
720
|
-
// · **空数组** = LSP 语义上完全正常的「这一轮没有诊断 / 诊断已清空」⇒ 那是**空批**,
|
|
721
|
-
// 不是坏帧。判它 malformed 会在每条这样的帧上打一行「It renders NOWHERE」的告警,
|
|
722
|
-
// 把引擎的正常行为诬告成故障 —— 而 `empty_payload` 单列一档的理由(见该词头注)
|
|
723
|
-
// 恰恰就是这件事,只是当初只对 suggestions 用了。同一判据两处不一致,在此收平。
|
|
724
276
|
if (!Array.isArray(ev.files))
|
|
725
277
|
return dropped('malformed', 'diagnostics');
|
|
726
278
|
if (ev.files.length === 0)
|
|
@@ -732,13 +284,6 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
732
284
|
...(typeof ev.parentToolCallId === 'string' ? { parentToolCallId: ev.parentToolCallId } : {}),
|
|
733
285
|
})));
|
|
734
286
|
}
|
|
735
|
-
// core 1.251 design/133 ([479] ask-1) + 1.253 G1 ([482]/[487]②) — `steering_injected`: the engine
|
|
736
|
-
// echoed a SYSTEM steering injection ({source, preview:first-220-chars}, echo-only — the model-facing
|
|
737
|
-
// message is server-side). Sources are an OPEN SET (deadline_nudge/finalize + todo_reminder/
|
|
738
|
-
// task_reminder/changed_files/plan_mode + background_tasks/tools_delta today; core may extend).
|
|
739
|
-
// Projects to a NEUTRAL internal arm the REPL bridge maps into renderable attachments
|
|
740
|
-
// (steeringAttachments.ts). parentToolCallId rides through so a sub-flow's echo stays off the leader
|
|
741
|
-
// transcript (same rule as diagnostics).
|
|
742
287
|
case 'steering_injected': {
|
|
743
288
|
if (typeof ev.source !== 'string' || ev.source.length === 0)
|
|
744
289
|
return dropped('malformed', 'steering_injected');
|
|
@@ -749,11 +294,6 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
749
294
|
...(typeof ev.parentToolCallId === 'string' ? { parentToolCallId: ev.parentToolCallId } : {}),
|
|
750
295
|
})));
|
|
751
296
|
}
|
|
752
|
-
// core design/99 §E13([1559]二/[1564]4 提货)— `workspace_changed`: the engine moved its logical
|
|
753
|
-
// cwd (bash `cd` / EnterWorktree), frame carries the NEW cwd (RAW form). Display-only echo — the
|
|
754
|
-
// engine already runs against the new cwd. NOT persistent state: resets to the session root across
|
|
755
|
-
// suspend/resume(core 口径,勿当持久态渲染);projects to a NEUTRAL arm the REPL bridge maps into
|
|
756
|
-
// a dim transcript row.
|
|
757
297
|
case 'workspace_changed': {
|
|
758
298
|
if (typeof ev.cwd !== 'string' || ev.cwd.length === 0)
|
|
759
299
|
return dropped('malformed', 'workspace_changed');
|
|
@@ -763,18 +303,6 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
763
303
|
...(typeof ev.parentToolCallId === 'string' ? { parentToolCallId: ev.parentToolCallId } : {}),
|
|
764
304
|
})));
|
|
765
305
|
}
|
|
766
|
-
// P0-1([1725] 清单A)— E12 `suggestions`:run 跑完(status:"completed")后 core 一次 LLM pass 产的
|
|
767
|
-
// 「下一步可问什么」建议**批**。此前这个臂掉进 `default: return null` ⇒ 全链死信。
|
|
768
|
-
// 🔴 语义(别按 CC 的单条模型套):CC 的 `prompt_suggestion` 是**每轮一条** `suggestion: string`;
|
|
769
|
-
// 引擎这条是**完成后一批** `string[]`(events.d.ts:132-135)——按批渲染/按批投影。
|
|
770
|
-
// 🔴 UNTRUSTED 模型文本(service 已 redact)、仅 UI、**绝不回喂模型** —— 所以投成 NEUTRAL 内部臂
|
|
771
|
-
// (不是可渲染的 CC SDKMessage):TUI 由 upstreamBridge 推给 chips store,print 由 seamQueryEngine
|
|
772
|
-
// 折成 CC 原生 `prompt_suggestion` 帧(coreSchemas.ts:1905 契约既有)。
|
|
773
|
-
// 🔴 产出面实测(2026-07-26,钉版 server 1.277.1 / core 1.416 直连):**只有 durable
|
|
774
|
-
// `/v1/runs` 腿产**(server runs.js:300-303 `spec.suggestNextPrompts && done && completed`);
|
|
775
|
-
// `/v1/tasks/stream` 带 `suggestNextPrompts:true` 也一帧不发(已真跑证伪)。壳的交互 turn 走
|
|
776
|
-
// tasks/stream ⇒ 这条通路今天只在 durable 车道(runs.create + runs.events:Ctrl+B/`/background`/
|
|
777
|
-
// ControlRouter)活。防御性上界:批量截 8 条、单条截 200 字(UI 面,不是模型面)。
|
|
778
306
|
case 'suggestions': {
|
|
779
307
|
const filtered = (Array.isArray(ev.suggestions) ? ev.suggestions : []).filter((s) => typeof s === 'string' && s.trim().length > 0);
|
|
780
308
|
const list = filtered
|
|
@@ -785,175 +313,62 @@ export function eventToSdkMessage(ev, ctx) {
|
|
|
785
313
|
return projected(stamp(ctx, armBody({
|
|
786
314
|
type: 'prompt_suggestions',
|
|
787
315
|
suggestions: list,
|
|
788
|
-
// 🔴 REF-CC-061(xlate-07,H2 无声上限零容忍):**单条**截断本来就是诚实的(尾部 `…` 是
|
|
789
|
-
// 可见痕迹),**批量**截断此前不是 —— 引擎给 12 条时第 9-12 条无声蒸发,臂上没有任何位
|
|
790
|
-
// 说出「还有更多」。additive 位,与本文件 tool_end 臂的 `truncated` 同款姿势;渲不渲是
|
|
791
|
-
// 渲染面的决定,数据面必须先说出来。
|
|
792
316
|
...(filtered.length > list.length ? { truncatedCount: filtered.length - list.length } : {}),
|
|
793
317
|
})));
|
|
794
318
|
}
|
|
795
|
-
// §2.7 — turn_end is usage-only(usage 由 `turnEndUsage` 单独出口,run driver 折叠)。
|
|
796
319
|
case 'turn_end':
|
|
797
320
|
return nothing('usage_only');
|
|
798
|
-
// §2.9 — suspended 的 HITL 登记是 run driver 的活(hitlBridge.observe),本层不投影。
|
|
799
321
|
case 'suspended':
|
|
800
|
-
// ── sdk 6.2.0 TR-7 新入 union 的 HITL 带外族(2026-08-04 提货批)────────────────────────
|
|
801
|
-
// `question` / `question_complete`(AskUserQuestion 的开问/收尾)与 `elicitation` /
|
|
802
|
-
// `elicitation_complete`(入站 MCP server 向用户要输入)是**对话框覆盖层**的词汇,不是
|
|
803
|
-
// transcript 的。它们此前只走 live 腿的 SSE `event:` 名分派(`liveQuestionStore.ts` 的 demux
|
|
804
|
-
// 口),6.2.0 把 durable 腿的重放形也纳入了 union —— 于是它们第一次**流经本函数**。
|
|
805
|
-
// 🔴 处置理由与 `suspended` 同族、也与本包既有分工一致:HITL 的挂起/应答由
|
|
806
|
-
// `hitl/hitlBridge.ts` 的 `observe()` 与 `liveQuestionStore` 负责,本切片(CC transcript
|
|
807
|
-
// 投影)对它们**没有对位渲染物** —— 硬投一个 transcript 形就是替覆盖层编一条假消息。
|
|
808
|
-
// 所以走 `hitl_out_of_slice`(可分辨的三态之一),不是 `dropped`(那是「我看不懂」)。
|
|
809
|
-
// 🔴 记档给下一棒(诚实缺席,不是无事发生):durable 重放腿上,一条被重放的 `question` 今天
|
|
810
|
-
// **不会**再打开覆盖层 —— 覆盖层的入口是 liveQuestionStore 的 live demux 写口,而不是本函数。
|
|
811
|
-
// 这在交互 REPL 上无损(live 腿原路不变),在「断线后按 Last-Event-ID 续读」的场景下是一个
|
|
812
|
-
// 真缺口。补它属**行为面**改动(要先答「重放一条已经过期 5min TTL 的问题该不该弹窗」),
|
|
813
|
-
// 按宪法三问单独走,不在本提货批里顺手加 —— 但缺口写在这里,不留白。
|
|
814
322
|
case 'question':
|
|
815
323
|
case 'question_complete':
|
|
816
324
|
case 'elicitation':
|
|
817
325
|
case 'elicitation_complete':
|
|
818
326
|
return nothing('hitl_out_of_slice');
|
|
819
|
-
// ── sdk 6.2.0 CB-1/TR-6 `error` 臂(2026-08-04 提货批)──────────────────────────────────
|
|
820
|
-
// 🔴 **名字骗人,别当终态**:这是流的 15 分钟帽帧(server `sse-log.ts`),帧自己就说
|
|
821
|
-
// 「run 仍然活着」。终态臂只有 `done` / `failed`。把它渲成终态 = 把一条还在跑的任务判死。
|
|
822
|
-
// 正确处置 = 按 `Last-Event-ID` 重连续读,而那件事 SDK 的 `runs.events` 车道内部就做了
|
|
823
|
-
// (本包侧的坐标 = `headlessReconnectWire.ts` 的 STREAM_MAX_DURATION 段)。
|
|
824
|
-
// ⇒ 本切片无对位渲染物,也**绝不终止**调用方的循环(返回 none,不是 terminal)。
|
|
825
|
-
// 🔴 `errorCode` 开集(已知 `STREAM_MAX_DURATION`):未知码同样按「可重连的流控信号」降级,
|
|
826
|
-
// 不要按成员判死 —— 词表见 `engineErrorCodes.ts`。
|
|
827
327
|
case 'error':
|
|
828
328
|
return nothing('not_in_slice');
|
|
829
|
-
// CS-10 / CS-11 — terminals are projected by terminalToSdkResult.
|
|
830
329
|
case 'done':
|
|
831
330
|
case 'failed':
|
|
832
331
|
return nothing('terminal_delegated');
|
|
833
|
-
// ── 已入 SDK union、本切片**有意**不投影的臂(REF-CC-060:进 switch 才受穷举保护)────────
|
|
834
|
-
// `meta`:流首帧的 taskId/sessionId 一等信号 —— 本切片无可渲染内容(runStream 只按 `eventSeq` 去重)。
|
|
835
|
-
// ⚠️ 活性普查(2026-09-19)更正:传输层**不**替宿主消费它;需要 sessionId / taskId 的端(desktop / web-client)各自直读本帧。
|
|
836
332
|
case 'meta':
|
|
837
|
-
// `file_link` / `model_usage` / `config_assembled`:
|
|
838
|
-
// 引擎的可观测/审计面帧,本切片(CC transcript 投影)无对位渲染物;
|
|
839
|
-
// 消费它们的是 fleet/审计面而不是会话转录。
|
|
840
|
-
// ⚠️ `message_committed` **已在 0.65.0 搬出本档**(B-072 ④):它不是「没有对位物」——
|
|
841
|
-
// 它是 `compacted.preserved_segment` 的唯一解析腿。新臂见本文件 `case 'message_committed'`。
|
|
842
|
-
// ⚠️ `context_usage` 自 0.71.0 CC-08 ③、`compaction_outcome` 自 0.75.0 CC-89、`prompt_assembled` 自
|
|
843
|
-
// 0.76.0 CC-91 起各自**进切片**为内部臂 → chrome 臂,不再在本组(见各自的 case)。
|
|
844
333
|
case 'file_link':
|
|
845
334
|
case 'model_usage':
|
|
846
335
|
case 'config_assembled':
|
|
847
|
-
// `needs_review`:plan-review park 的**事件**形;壳消费的是 done{status:'needs_review'} 终帧
|
|
848
|
-
// (runStream 的 plan_review_park chrome 臂),事件形在本切片重复且更早,故不投影。
|
|
849
|
-
// ⚠️ 活性普查(2026-09-19):web-client 仍直读事件形;本切片不投的理由不变(终帧是权威),但「没人消费」这句不成立。
|
|
850
336
|
case 'needs_review':
|
|
851
|
-
// ── sdk 6.9.0 提货批(2026-08-08)新入 union 的四条臂 ─────────────────────────────────────
|
|
852
|
-
// `tool_approval` / `tool_approval_complete`:HITL 审批帧。**#185a 起它们是 `AgentEvent` 的臂**
|
|
853
|
-
// (此前只是 named SSE frame),但本切片不是它们的消费口 —— 它们由
|
|
854
|
-
// `hitl/toolApprovalWire.isToolApprovalFrame` + `hitl/frameRouter` 走审批卡那条链。在这里投一
|
|
855
|
-
// 条 transcript 行只会让同一只 ask 出现两次;`nothing('not_in_slice')` 是如实陈述,不是丢帧。
|
|
856
|
-
// ⚠️ 它们**必须**出现在这个 switch 里(而不是靠 default 兜):进 switch 才受 B5 编译期穷举
|
|
857
|
-
// 保护,才能在下一次 union 变形时把「谁不投影」这件事重新摆到人眼前。
|
|
858
337
|
case 'tool_approval':
|
|
859
338
|
case 'tool_approval_complete':
|
|
860
339
|
return nothing('not_in_slice');
|
|
861
|
-
/**
|
|
862
|
-
* `approval_request`(design/172 流内审批协议,server ≥7.3.0、7.5.0 起默认开)。
|
|
863
|
-
*
|
|
864
|
-
* 🔴 **0.65.0(B-078 / L-208)起真接上了**:本臂此前是 `dropped('unsupported_arm')` —— 有痕,
|
|
865
|
-
* 但**包内零消费口**,于是壳(cli)在自己的 `approvalStreamWire.ts` 里单独接了一份,而
|
|
866
|
-
* desktop / web 只走包管线 ⇒ 它们开流 preamble 恢复不了 pending 卡集。同一条 wire 上的同一
|
|
867
|
-
* 件事,一个端有、两个端没有,正是归层要根治的形。现改投 chrome 臂
|
|
868
|
-
* ({@link import('../../seam.js').ApprovalRequestChromeEvent}),消费义务写在那只接口的头注里。
|
|
869
|
-
* 🔴 **与 `tool_approval` / `tool_approval_complete` 仍不同源**(上面那两条走
|
|
870
|
-
* `isToolApprovalFrame` + `hitl/frameRouter` 的审批卡链,本臂走 chrome 平面):开关打开时同一
|
|
871
|
-
* 只 ask 出两帧、顺序钉死「先 legacy、后本帧」、两帧同带 `approvalId` ⇒ **去重是宿主的动作**
|
|
872
|
-
* (它才有卡集状态),库不在这一层替它做。
|
|
873
|
-
* 🔴 载荷**不窄化到 v1**(sdk events.d.ts:961-968 的理由逐字搬在 `approvalFrameProjection` 头注)。
|
|
874
|
-
*/
|
|
875
340
|
case 'approval_request': {
|
|
876
341
|
const body = approvalFrameBody(ev);
|
|
877
342
|
if (body === undefined)
|
|
878
343
|
return dropped('malformed', 'approval_request');
|
|
879
344
|
return projected(stamp(ctx, armBody({ type: 'approval_request', ...body })));
|
|
880
345
|
}
|
|
881
|
-
/**
|
|
882
|
-
* `approval_revoke`(design/172 撤卡帧;[5924]/S-58,server ≥7.55.0 起也进 durable 账本重放)。
|
|
883
|
-
*
|
|
884
|
-
* 🔴 **与 `approval_request` 同源同处置**(载荷同是 `ApprovalFrameEnvelope` 信封),所以并在它
|
|
885
|
-
* 旁边 —— 它是同一条流内审批协议的**撤销**半场。0.65.0(B-078 / L-208)同批接上:此前
|
|
886
|
-
* `dropped('unsupported_arm')` ⇒ 只走包管线的宿主在撤销之后**本地卡不清**,用户对着一张
|
|
887
|
-
* 已经决断不了的卡按 Yes。现改投 chrome 臂
|
|
888
|
-
* ({@link import('../../seam.js').ApprovalRevokeChromeEvent}),三条消费纪律(按 `taskId` 归属 /
|
|
889
|
-
* 账本重放只渲时间线 / 已 DECIDED 的兄弟不在 `askIds` 里)写在那只接口的头注里。
|
|
890
|
-
*/
|
|
891
346
|
case 'approval_revoke': {
|
|
892
347
|
const body = approvalFrameBody(ev);
|
|
893
348
|
if (body === undefined)
|
|
894
349
|
return dropped('malformed', 'approval_revoke');
|
|
895
350
|
return projected(stamp(ctx, armBody({ type: 'approval_revoke', ...body })));
|
|
896
351
|
}
|
|
897
|
-
// ── `engine_notice`(#310 / #318 件①,server ≥7.36,契约 = ASSISTANT-WIRE-CONTRACT 附录 D)────
|
|
898
|
-
// 🔴 **到期复核已兑现(sdk 7.4.0 提货,0.48.0)** —— 与 `human_input`(sdk 6.9.0)逐字同一条路。
|
|
899
|
-
// 本臂此前是 switch **之前**的一条 raw 预分派,理由 = 它还没进已发布 SDK 的 `AgentEvent`
|
|
900
|
-
// union(亲验 7.2.0 真 tarball `dist/` 全树零 `engine_notice`)。sdk **7.4.0 已声明该臂**
|
|
901
|
-
// (`dist/events.d.ts`:`{type:"engine_notice"; code; message; detail; sessionId; ts}`,
|
|
902
|
-
// 五键**全必填**、无 `& EventIdentity`)⇒ 按原定的自退休条款搬进 switch。
|
|
903
|
-
// 这不是可选的整理:预分派用的是 `(ev as {type?:unknown})` 形、**不收窄** `ev`,所以臂一进
|
|
904
|
-
// union,`default` 就还看得见它 ⇒ B5 穷举断言 `assertNeverArm` **编译期真红**(本批实翻:
|
|
905
|
-
// devDep 抬到 7.4.0 的当拍 `tsc` 就是这一条错)。搬进来后本函数重回「每一条臂都受编译期
|
|
906
|
-
// 穷举保护」,行为**一字不改**(下面的投影函数原样复用,连入参的 raw 视图形都不动)。
|
|
907
|
-
// 🔴 **投影仍走 raw `Record` 视图,不改吃 SDK 收窄形**(刻意,不是省事):SDK 的臂声明把五键
|
|
908
|
-
// 记成**全必填**,而本层对每一键都做诚实缺席处理(`code` 空 ⇒ malformed;`message`/`detail`
|
|
909
|
-
// 坏 ⇒ 降级不丢帧;`sessionId`/`ts` 非法 ⇒ 不 stamp),这些分支在收窄形上会被类型面判成
|
|
910
|
-
// 死码而**静默失效** —— wire 是 JSON,必填是 server 的承诺不是本层的前提
|
|
911
|
-
// ([jsdoc-untrusted-verify-implementation])。且 `eventId` / `id`(→ `eventSeq`)两个重放
|
|
912
|
-
// 身份键**根本不在** SDK 臂声明里(SDK 从 SSE `id:` stamp),收窄形上读它们是编译错。
|
|
913
352
|
case 'engine_notice':
|
|
914
353
|
return engineNoticeProjection(ev, ctx);
|
|
915
|
-
// CC-08(0.71.0,sdk 9.6.0 换钉):两条新帧。投影仍走 raw `Record` 视图(理由同 engine_notice:
|
|
916
|
-
// wire 是 JSON,必填是 server 的承诺不是本层的前提;缺席/坏值逐键诚实处理)。
|
|
917
354
|
case 'tool_disclosure':
|
|
918
355
|
return toolDisclosureProjection(ev, ctx);
|
|
919
|
-
// CC-08 ③(0.71.0):`context_usage` 从 not_in_slice 组里拿出来 —— sections(core 7.18.0 #790)是「这条腿的系统提示词
|
|
920
|
-
// 由哪些段组成、哪一段大」,fleet/HUD 面要渲;三个标量走 finite 门(非有限即缺席,永不 null)。
|
|
921
356
|
case 'context_usage':
|
|
922
357
|
return contextUsageProjection(ev, ctx);
|
|
923
|
-
// CC-89(0.75.0):`compaction_outcome` 从 not_in_slice 组里拿出来 —— 压缩的**非 compacted 结局**(被终态抢先 / 失败等)此前
|
|
924
|
-
// 没有任何一端看得见。转录里没有对位物(`compact_boundary` 只对成功压缩)⇒ 走内部臂 → chrome 臂,不编消息。
|
|
925
358
|
case 'compaction_outcome':
|
|
926
359
|
return compactionOutcomeProjection(ev, ctx);
|
|
927
|
-
// CC-91(0.76.0):`prompt_assembled` 从 not_in_slice 组里拿出来 —— 这一次 prepare 的**提示词装配清单**
|
|
928
|
-
// (每段多大、挂了哪些工具)是 /context 类面板的唯一引擎侧真值来源;此前三端只能按本地镜像自己估。
|
|
929
|
-
// 转录里没有对位物(它是 ids/digests/counts 的观测面,不是一条消息)⇒ 走内部臂 → chrome 臂,不编消息。
|
|
930
360
|
case 'prompt_assembled':
|
|
931
361
|
return promptAssembledProjection(ev, ctx);
|
|
932
362
|
case 'tool_progress':
|
|
933
363
|
return toolProgressProjection(ev, ctx);
|
|
934
364
|
default:
|
|
935
|
-
// B5 穷举:SDK union 加成员必须在**编译期**打红这一行(而不是让新臂在用户面静默丢帧)。
|
|
936
365
|
assertNeverArm(ev);
|
|
937
|
-
// 运行期:wire 是 JSON,引擎完全可能比本包的类型新一版 —— 如实报 dropped,由 run driver
|
|
938
|
-
// 上报(REF-CC-057:此处此前写着 `log+skip` 而全函数零 log,那句承诺在码里根本不存在)。
|
|
939
366
|
return dropped('unknown_arm', String(ev.type ?? 'unknown'));
|
|
940
367
|
}
|
|
941
368
|
}
|
|
942
|
-
/**
|
|
943
|
-
* 身份四键(`eventId` + 三个子流键)的**一次性快照**:每键**只读一次**,读取抛错 ⇒ 整份不可信。
|
|
944
|
-
*
|
|
945
|
-
* 🔴 为什么是快照而不是就地多读(异源对抗复审第三轮 [medium],实测可复现):wire 是 JSON,但**进程内**的帧
|
|
946
|
-
* (宿主自建管线 / 重放存量转录 / 测试替身)可以带 accessor。同一个键读两次拿到两个值时,「形门读一次、
|
|
947
|
-
* 抄写再读一次、lane 判定又读一次」会让同一帧在不同读点上归属**不同 lane** —— 一条子代帧能被洗成主会话的
|
|
948
|
-
* 组成信息。读一次、全程用同一份,是这条歧义唯一的关门方式;抛错的 getter 同样在这里被关住(此前会从投影口逸出)。
|
|
949
|
-
* ⚠️ 仍按 `ev[k]` 读(**走原型链**:进程内对象的身份键常长在原型上),只是每键只读一次。
|
|
950
|
-
*/
|
|
951
369
|
function identitySnapshot(ev) {
|
|
952
|
-
// 0.76.1:单源 —— 与 adapt 侧各臂共用同一只快照助手(见 adapter/types.ts 的 snapshotSegmentIdentity 头注)。
|
|
953
370
|
return snapshotSegmentIdentity(ev);
|
|
954
371
|
}
|
|
955
|
-
/** CC-08:三键身份(sdk `EventIdentity`)—— 在场非串 ⇒ 坏值不买路;在场(含空串)⇒ 原样透传;`eventId` 非空才带。
|
|
956
|
-
* 🔴 判据与抄写都取 {@link identitySnapshot} 的**同一份**读数(每键只读一次)。 */
|
|
957
372
|
function identityOrMalformed(ev, arm) {
|
|
958
373
|
const snap = identitySnapshot(ev);
|
|
959
374
|
if (snap === null)
|
|
@@ -964,27 +379,17 @@ function identityOrMalformed(ev, arm) {
|
|
|
964
379
|
}
|
|
965
380
|
const identity = {};
|
|
966
381
|
for (const k of ['eventId', ...SEGMENT_END_IDENTITY_KEYS]) {
|
|
967
|
-
// 🔴 三键**空串也透**:子流律是「键在场 = 子代帧」(`isSubFlowSegmentEnd` / `text_end` 投影同律),按 length>0 才抄会把
|
|
968
|
-
// `sourceTaskId: ''` 的子代帧洗成主流(异源对抗复审第 1 轮 finding③);`eventId` 是幂等键,仍要非空。
|
|
969
382
|
if (typeof snap[k] === 'string' && (k === 'eventId' ? snap[k].length > 0 : true))
|
|
970
383
|
identity[k] = snap[k];
|
|
971
384
|
}
|
|
972
385
|
return { identity, bad: null };
|
|
973
386
|
}
|
|
974
|
-
/** 非空串数组窄读:非数组 ⇒ undefined(调用方判 malformed);数组里的非串 / 空串按 server 律**逐个滤掉**。 */
|
|
975
387
|
function nameList(v) {
|
|
976
388
|
if (!Array.isArray(v))
|
|
977
389
|
return undefined;
|
|
978
390
|
return v.filter((x) => typeof x === 'string' && x.length > 0);
|
|
979
391
|
}
|
|
980
392
|
const nonNegInt = (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 ? v : undefined;
|
|
981
|
-
/**
|
|
982
|
-
* `tool_disclosure` → 中性内部臂(CC-08,0.71.0;core design/393 S3 第二缝,sdk 9.6.0)。
|
|
983
|
-
* 这条腿的工具**名字占位普查**:`policy` 开集三词(core 加一档要能穿过 default 臂)/ `thresholdPercent?`
|
|
984
|
-
* (🔴 缺席 = `always`/`never` 两档下根本没查过阈值,**不是**默认百分比;坏值 ⇒ 键不铸不丢帧)/
|
|
985
|
-
* `deferred[]` / `activated[]`(全量快照,整只替换;数组里的非串空串逐个滤 = server 律同形)。
|
|
986
|
-
* 🔴 三只必需位缺一 ⇒ `malformed`:半张普查表会被读成「只有这些被延迟」。
|
|
987
|
-
*/
|
|
988
393
|
function toolDisclosureProjection(ev, ctx) {
|
|
989
394
|
const policy = ev.policy;
|
|
990
395
|
if (typeof policy !== 'string' || policy.length === 0)
|
|
@@ -1010,12 +415,6 @@ function toolDisclosureProjection(ev, ctx) {
|
|
|
1010
415
|
...identity,
|
|
1011
416
|
})));
|
|
1012
417
|
}
|
|
1013
|
-
/**
|
|
1014
|
-
* `tool_progress` → 中性内部臂(CC-08,0.71.0;DV-741,clay C-R50 裁「一帧两拍」入 divergence 册,本包按裁定形投)。
|
|
1015
|
-
* `toolCallId` / `toolName` 必在(接不回自己 `tool_start` 的 tick 挂不上卡 ⇒ `malformed`);
|
|
1016
|
-
* `elapsedTimeSeconds?`(🔴 缺席不是 0);`output?` 在场 = 尾巴窗口(UNTRUSTED RAW,与 `tool_end.output` 同类,
|
|
1017
|
-
* 绝不回喂模型)+ `totalLines?` / `totalBytes?`;`output` 缺席 ⇒ 后两键**一起**不铸(server 律:三者按 output 在场判)。
|
|
1018
|
-
*/
|
|
1019
418
|
function toolProgressProjection(ev, ctx) {
|
|
1020
419
|
const toolCallId = ev.toolCallId;
|
|
1021
420
|
const toolName = ev.toolName;
|
|
@@ -1041,87 +440,18 @@ function toolProgressProjection(ev, ctx) {
|
|
|
1041
440
|
...identity,
|
|
1042
441
|
})));
|
|
1043
442
|
}
|
|
1044
|
-
/**
|
|
1045
|
-
* `text_end` → 中性内部**段边界**臂(#323 / core #447)。
|
|
1046
|
-
*
|
|
1047
|
-
* ── 这是什么 ────────────────────────────────────────────────────────────────────────────────
|
|
1048
|
-
* 「assistant 的这一段散文写完了」—— 模型关掉了那个 text content block,而它的字节刚刚以
|
|
1049
|
-
* `text_delta` 流过。core 的臂注逐字:`content` = **该段的权威全文**(取自 brain 自己的累加),
|
|
1050
|
-
* 消费方**据它提交这一段**,而不是信自己的 delta 缝合。
|
|
1051
|
-
*
|
|
1052
|
-
* 🔴 **「与 delta 拼接逐字节相等」这句自 server 7.75.3 起不再成立**(L-310,0.68.1 订正;此前本注
|
|
1053
|
-
* 照抄 core 臂注的那半句):`text_end.content` 与 `result`/账本走**同一只脱敏器**,而 `text_delta`
|
|
1054
|
-
* 仍逐字(跨 chunk 的凭据无法就地判,流式脱敏是独立设计件)⇒ 含凭据形的段上两者**字节不同**。
|
|
1055
|
-
* server `ASSISTANT-WIRE-CONTRACT` §5.1 live 面逐字要求消费端「在 `text_end` 到达时以它**整段
|
|
1056
|
-
* 替换**已攒的 delta,而不是只当段界信号」。
|
|
1057
|
-
*
|
|
1058
|
-
* 🔴 **它的存在意义 = 让消费方撤掉 idle-flush 启发式**(core 臂注点名的那件事)。本包的
|
|
1059
|
-
* `adapt/textStream.ts` 至今用「静默 1.5s + 句末/段末边界 + 每段一刀」猜段边界(#323 症状① 的止血
|
|
1060
|
-
* 件,`takeAnswerSegmentOnIdle`);那是猜,这是引擎明说。CC 对位:CC 的 agent 流在 provider 的
|
|
1061
|
-
* `content_block_stop` 上把每个写完的 content block 当作一条独立 assistant 消息发出去 —— 块结束
|
|
1062
|
-
* **就是**分段信号,单进程消费方从 provider 流上原生读到它;本臂是同一个边界被搬到 TaskEvent wire 上。
|
|
1063
|
-
*
|
|
1064
|
-
* ── 为什么投**内部臂**,而不是 transcript 行、也不是 `not_in_slice` ─────────────────────────
|
|
1065
|
-
* · **绝不铸 transcript 行**:`content` 是**已经流过**的那一段的全文(durable 腿的 `text` 臂才是
|
|
1066
|
-
* 「这一段的唯一载体」)。在 live 腿把它再铸成一条 assistant 消息 = 同一段文字上屏两遍。
|
|
1067
|
-
* · **绝不 `not_in_slice`**:那一档走 `kind:'none'`,是**静默**的。本帧带着消费方真正需要的判别
|
|
1068
|
-
* 信号(段边界 + 权威全文),静默丢 = 把一个真实能力缺口做成 fail-open,正是本文件对
|
|
1069
|
-
* `approval_request` 那段头注点名的病形。⇒ 投中性内部臂,宿主(壳 REPL 桥 / web / desktop 座位层)
|
|
1070
|
-
* 在臂上读它、决定何时提交段。
|
|
1071
|
-
* · **包内接线**(0.68.1 / L-310 起):`adapt/arms.ts` 的 `textSegmentEndArm` 拿这条内部臂调
|
|
1072
|
-
* `adapt/textStream.ts` 的 `replaceAnswerSegment(content, frame)` —— **整段替换**段缓冲与活体尾巴,
|
|
1073
|
-
* 再把 `diverged` / `committedPrefixDiverged` / `committedPrefixLen` 三个 never-false 键挂到
|
|
1074
|
-
* chrome `text_segment_end` 上交给宿主。
|
|
1075
|
-
* · 📋 **仍然留白的那一件**:让 `textStream` 真的**撤掉** idle-flush 启发式。core 臂注明写这是
|
|
1076
|
-
* 「诚实缺席」的位(只有会报块结束的 brain 才发它,自定义 brain 可能整条流一帧都没有),所以
|
|
1077
|
-
* 消费方必须按**每条流**判「这条流带不带边界帧」再决定退不退启发式 —— 那是一条带状态的策略,
|
|
1078
|
-
* 属行为面改动,按宪法三问单独走。权威替换**兼容**启发式(半段已被 flush 那一形由两个前缀键
|
|
1079
|
-
* 如实交代),不是它的继任。
|
|
1080
|
-
*
|
|
1081
|
-
* ── 畸形与空段(fail-closed 方向 + 对位 core 的「空段无帧」)────────────────────────────────
|
|
1082
|
-
* · `content` **非串** ⇒ `malformed`:承重位读不动(wire 是 JSON,SDK 只 JSON.parse 不校型)。
|
|
1083
|
-
* · `content` **空串** ⇒ `empty_payload`(不是 malformed,也不是丢帧):core 臂注逐字「只为**有
|
|
1084
|
-
* 字节**的段发帧;空 text block 静默关闭 —— 一个没有段的边界会渲出幻影行」。所以空串要么是
|
|
1085
|
-
* 降级中继、要么是未来的契约变形,两种都**不该**让消费方去提交一个空段。与 `diagnostics` 的
|
|
1086
|
-
* `files: []`(ADAPTER-F6)同一档:我们投影这条臂,只是这一帧没有可提交的段。
|
|
1087
|
-
* · `eventId` / `parentToolCallId`(`TaskEventIdentity`,server 两腿都 stamp)按既有姿势透传 ——
|
|
1088
|
-
* 🔴 `parentToolCallId` 尤其不能剥:子流(子代 / 编排)的段边界绝不能去提交 **leader** 的段
|
|
1089
|
-
* (与本文件 `reasoning_delta` / `status` 两臂同一条 lane 身份纪律,#9 与跨 lane 状态破坏案)。
|
|
1090
|
-
*
|
|
1091
|
-
* ⚠️ **UNTRUSTED、仅展示**:`content` 是模型输出,契约与 `text_delta` 同 —— 渲染,绝不回喂模型。
|
|
1092
|
-
*/
|
|
1093
443
|
function textEndProjection(ev, ctx) {
|
|
1094
444
|
return segmentEndProjection(ev, ctx, 'text_end');
|
|
1095
445
|
}
|
|
1096
|
-
/**
|
|
1097
|
-
* 段末帧(`text_end` / `reasoning_end`)的**共用投影**(sdk 9.4.0 `SegmentEndFields` 单源 ⇒ 本侧也只写一份;
|
|
1098
|
-
* 判据与留痕见 {@link textEndProjection} 头注,两枚帧逐字同)。`arm` 只决定内部臂名与留痕里的帧名。
|
|
1099
|
-
*/
|
|
1100
446
|
function segmentEndProjection(ev, ctx, arm) {
|
|
1101
447
|
const content = ev.content;
|
|
1102
448
|
if (typeof content !== 'string')
|
|
1103
449
|
return dropped('malformed', arm);
|
|
1104
|
-
// 🔴 **lane 身份位坏了就整帧 fail-closed**(异源对抗复审第三轮 [medium] 采纳;与本文件
|
|
1105
|
-
// `applyBgNotification` 对 `parentTaskId` 的 B3-DIRTY 处置逐字同族):`parentToolCallId` 是
|
|
1106
|
-
// **子流断闸的锚**。键在场却不是串时,若按「不是串就当没有」处理,这条**子代**的段边界会被
|
|
1107
|
-
// 擦掉 lane 标记、当成 **leader** 的段边界上到宿主面 —— 宿主据它去提交/对账宿主自己的那一段,
|
|
1108
|
-
// 正是本臂头注点名要防的跨 lane 状态破坏,而且是 fail-**open** 方向。
|
|
1109
|
-
// 三态与 B3-DIRTY 同:键缺席/`undefined` ⇒ 本来就是 leader 帧(照旧);键在场却非串(含 `null`,
|
|
1110
|
-
// wire schema 只允许缺席或 string)⇒ `malformed` 丢弃并留痕,坏值不许买路。
|
|
1111
|
-
// CC-10(0.69.1;cli 接入回执 ① 实抓的 fail-open):子流身份是**三键**(sdk `EventIdentity`:`parentToolCallId` /
|
|
1112
|
-
// `sourceTaskId` / `bgAgentId`),core 顶注逐字「stamped ONLY on the content events of a task running AS A SUB-AGENT」——
|
|
1113
|
-
// 只带 `sourceTaskId`(无 `parentToolCallId`)是合法的子代帧形。修前只透 `parentToolCallId`,臂只按它断闸 ⇒ 那一形的
|
|
1114
|
-
// 子代段末帧被当 leader 投上来,端据它换 leader 的思考/文本行 = 子代推理覆盖 leader 推理面。⇒ 三键**原样穿上内部臂**,
|
|
1115
|
-
// 任一键在场却非串 ⇒ 整帧 malformed(与 `parentToolCallId` 同一条 B3-DIRTY 律:坏值不许买路)。
|
|
1116
|
-
// 0.76.1(外部验收方对 0.76.0 的 F2):此前在同一个表达式里把每只身份键读了两次 ⇒ 「每键恰读一次」在这两条臂上不成立
|
|
1117
|
-
// (方向 fail-closed:值随读变的合法子代帧被判 malformed)。改走与其余七条内部臂同一只 identityOrMalformed(一次性快照:
|
|
1118
|
-
// 在场非串 ⇒ malformed;在场含空串 ⇒ 原样;`eventId` 非空才带)。
|
|
1119
450
|
const { identity, bad } = identityOrMalformed(ev, arm);
|
|
1120
451
|
if (bad !== null)
|
|
1121
452
|
return bad;
|
|
1122
453
|
if (content.length === 0)
|
|
1123
454
|
return nothing('empty_payload');
|
|
1124
|
-
// 两处字面量铸点(不是一处参数化):内部臂词表门按 `armBody({ type: '<字面量>'` 抽铸点,参数化会让两臂在账上「多登记」。
|
|
1125
455
|
return arm === 'text_end'
|
|
1126
456
|
? projected(stamp(ctx, armBody({ type: 'text_end', content, ...identity })))
|
|
1127
457
|
: projected(stamp(ctx, armBody({ type: 'reasoning_end', content, ...identity })));
|
|
@@ -1146,30 +476,15 @@ export function projectMcpSection(raw) {
|
|
|
1146
476
|
...(typeof r.source === 'string' && r.source.length > 0 ? { source: r.source } : {}),
|
|
1147
477
|
...(typeof r.errorCode === 'string' && r.errorCode.length > 0 ? { errorCode: r.errorCode } : {}),
|
|
1148
478
|
...(typeof r.toolCount === 'number' && Number.isFinite(r.toolCount) ? { toolCount: r.toolCount } : {}),
|
|
1149
|
-
// S6-B(0.60.0):两位与既有五位同律 —— 逐键挑、开集读、缺席不铸。
|
|
1150
479
|
...(typeof r.delivered === 'string' && r.delivered.length > 0 ? { delivered: r.delivered } : {}),
|
|
1151
480
|
...(typeof r.httpStatus === 'number' && Number.isFinite(r.httpStatus) ? { httpStatus: r.httpStatus } : {}),
|
|
1152
|
-
// CC-36(0.76.1):第六位活性格 —— 判据不在这里写第二遍,全在 readMcpLiveness 那一只铸点里
|
|
1153
|
-
// (三向读数:缺席不铸 / 在场读不出立 never-false 位 / 读得出铸那次观察)。
|
|
1154
481
|
...((cell) => cell.kind === 'observation' ? { liveness: cell.liveness } : cell.kind === 'unreadable' ? { livenessUnreadable: true } : {})(readMcpLiveness(r)),
|
|
1155
482
|
});
|
|
1156
483
|
}
|
|
1157
|
-
// 🔴 见顶注:`raw.length === 0` 是**正面事实**(照铸 `[]`);非空却零行幸存 = 读不出来 ⇒ 段缺席。
|
|
1158
484
|
if (raw.length > 0 && rows.length === 0)
|
|
1159
485
|
return undefined;
|
|
1160
486
|
return rows;
|
|
1161
487
|
}
|
|
1162
|
-
/**
|
|
1163
|
-
* `wiring_manifest.modelGate` 的形校验(core #524 / server S-86,server ≥7.58.0)。
|
|
1164
|
-
*
|
|
1165
|
-
* 语义(core 逐字):**仅本 run 真有门卸时在场**;缺席 = 没卸,**不是**「不知道」也不是
|
|
1166
|
-
* 「老引擎」—— 所以消费端拿不到本段时唯一合法的行为是**什么都不渲**,绝不许渲一句
|
|
1167
|
-
* 「没有工具被卸掉」(那是把「没报」说成「报了个零」)。
|
|
1168
|
-
*
|
|
1169
|
-
* 三键**全有才收**(与 server 侧同判据)。理由是这一段的用户价值是**一句完整的话**:
|
|
1170
|
-
* 「(class)门卸掉了(removed…),恢复用(restore)」—— 少任何一件都只能渲出半句没有出口的话。
|
|
1171
|
-
* 缺件 ⇒ 整段不收:不折 `''`、不折空数组、不编默认恢复办法。
|
|
1172
|
-
*/
|
|
1173
488
|
function projectModelGateSection(raw) {
|
|
1174
489
|
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
1175
490
|
return undefined;
|
|
@@ -1181,28 +496,10 @@ function projectModelGateSection(raw) {
|
|
|
1181
496
|
: undefined;
|
|
1182
497
|
if (cls === undefined || restore === undefined || removed === undefined)
|
|
1183
498
|
return undefined;
|
|
1184
|
-
// 🔴 空数组**不收**:`removed: []` 说的是「卸了零件工具」,与「没卸」在屏面上不可区分,
|
|
1185
|
-
// 而 core 的契约是「有门卸才铸段」⇒ 空数组是坏值,不是一个真读数。
|
|
1186
499
|
if (removed.length === 0)
|
|
1187
500
|
return undefined;
|
|
1188
501
|
return { class: cls, removed, restore };
|
|
1189
502
|
}
|
|
1190
|
-
/**
|
|
1191
|
-
* `wiring_manifest.autoMode` 的形校验(core 147③,server ≥7.58.0)。
|
|
1192
|
-
*
|
|
1193
|
-
* 语义(server 发车帖逐字):**effective 腿恒在**;缺席 = 老 mint / 外部 derive,**不许折成
|
|
1194
|
-
* `armed:false`**(那是把「没报」渲成「没武装」)。`reason` 是 **core 六词逐字透传**,
|
|
1195
|
-
* 🔴 **不映射** `/v1/capabilities.permissionModeAuto.reason` 的六词 —— 两套词表**同名不同义**
|
|
1196
|
-
* (`settings_denied` 在 capabilities 那边折 `no_intent` 不折 `denied`),归一会造出一个假读数。
|
|
1197
|
-
*
|
|
1198
|
-
* server 侧另有一条**互证**判据:`armed === (reason === 'armed')`,不满足整段不投。本层照抄它,
|
|
1199
|
-
* 理由不是「重复上游」而是**非投影口**(宿主自建管线 / 重放存量转录)喂进来的帧不过 server ——
|
|
1200
|
-
* 一个 `{armed:true, reason:'settings_denied'}` 会让消费端同时读到「武装了」和「被拒了」。
|
|
1201
|
-
*
|
|
1202
|
-
* 🔴 **`breaker` 一位 0.65.0 退役**(core 7.12.0 删 `WiringManifest.autoMode.breaker`):本臂不再
|
|
1203
|
-
* 读它、不再投它。老引擎的帧上若仍带这个键,它落在本函数的**未读键**里被丢弃 —— 与本层对
|
|
1204
|
-
* 一切未声明键的处置逐字相同(投影是白名单,不是透传)。
|
|
1205
|
-
*/
|
|
1206
503
|
function projectAutoModeSection(raw) {
|
|
1207
504
|
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
1208
505
|
return undefined;
|
|
@@ -1213,41 +510,15 @@ function projectAutoModeSection(raw) {
|
|
|
1213
510
|
return undefined;
|
|
1214
511
|
if (armed !== (reason === 'armed'))
|
|
1215
512
|
return undefined;
|
|
1216
|
-
// ── 0.67.0(core 7.14.0):`deniedSource` 补位 ───────────────────────────────────────────────
|
|
1217
|
-
// 见 {@link WiringManifestAutoMode.deniedSource}。本层**只在 `reason === "denied"` 上收** ——
|
|
1218
|
-
// core 的段内规矩是它只站在 `denied` 旁边,而这一条与上面那条 `armed === (reason === 'armed')`
|
|
1219
|
-
// 互证判据**同族**:非投影口(宿主自建管线 / 重放存量转录)喂进来的帧不过 server,一个
|
|
1220
|
-
// `{reason:'armed', deniedSource:'org'}` 会让消费端同时读到「武装了」和「被 org 关掉了」。
|
|
1221
|
-
// ⚠️ 与 `errorCode`/`origin` 的「不校配对」不同裁,理由也是上游自己给的:那些是**跨系统的
|
|
1222
|
-
// 不变量**(server 已按它铸),而本条是**同一条帧上的段内自洽**(gateOutcome.ts 顶注点名的
|
|
1223
|
-
// 那条反向先例,逐字就是本函数)。
|
|
1224
|
-
// 🔴 开集读 + 缺席不铸键(绝不折成空串/默认来源)。
|
|
1225
513
|
const deniedSource = reason === 'denied' && typeof a.deniedSource === 'string' && a.deniedSource.length > 0
|
|
1226
514
|
? a.deniedSource
|
|
1227
515
|
: undefined;
|
|
1228
516
|
return { armed, reason, ...(deniedSource !== undefined ? { deniedSource } : {}) };
|
|
1229
517
|
}
|
|
1230
|
-
/**
|
|
1231
|
-
* `wiring_manifest` 帧 → 两个超集键的**纯投影**(公面导出;三端共用,壳侧绝不自抄一份形校验)。
|
|
1232
|
-
*
|
|
1233
|
-
* 返回 `undefined` = 这一帧两段都不在场 / 都不成形 ⇒ 调用方**不铸臂**(见 case 头注)。
|
|
1234
|
-
* 🔴 帧是 FLAT 的:读 `ev.modelGate` / `ev.autoMode`,**不读** `ev.manifest.*`。
|
|
1235
|
-
*
|
|
1236
|
-
* 🔴 **刻意不导出**(typeshape 棘轮「unknown 出境只降」逼出来的正解,不是绕过门):本函数的入参是
|
|
1237
|
-
* 一个**未校验的 wire 帧**,唯一诚实的声明形就是 `Record<string, unknown>` —— 把它推上公面等于在
|
|
1238
|
-
* 包的公面上开一个无类型边界,而那正是那道棘轮存在的理由。三端要消费这两段,走的是**已定型**的
|
|
1239
|
-
* chrome 臂 {@link WiringManifestChromeEvent}(判别键 + 两个具名 interface),不是这个原始投影口;
|
|
1240
|
-
* 两个具名形({@link WiringManifestModelGate} / {@link WiringManifestAutoMode})照常导出。
|
|
1241
|
-
* 若将来真有宿主要自建管线直调本函数,正解是**先给帧定一个具名 interface** 再导出,不是抬棘轮。
|
|
1242
|
-
*/
|
|
1243
518
|
function wiringManifestSupersetBody(ev) {
|
|
1244
519
|
const modelGate = projectModelGateSection(ev.modelGate);
|
|
1245
520
|
const autoMode = projectAutoModeSection(ev.autoMode);
|
|
1246
|
-
// S-124(0.59.0):第三段。🔴 判「三段都不在场」用的是 `mcp === undefined`(**不是** `.length`)——
|
|
1247
|
-
// 空数组是一句正面事实(「这条腿一台都没申报」),拿它当「没有这一段」会让 `mcp: []` 的帧连同
|
|
1248
|
-
// 另两段一起落回 `not_in_slice`,而那正是 core 顶注点名要防的读法。
|
|
1249
521
|
const mcp = projectMcpSection(ev.mcp);
|
|
1250
|
-
// CC-08 ①(0.71.0):第四/五/六段进切片 —— tools(L-315;读器归 toolRoster.ts)/ hooks[] / lsp{mounted, lane?}。
|
|
1251
522
|
const tools = projectToolRoster(ev);
|
|
1252
523
|
const hooks = projectHooksSection(ev.hooks);
|
|
1253
524
|
const lsp = projectLspSection(ev.lsp);
|
|
@@ -1268,7 +539,6 @@ function wiringManifestSupersetBody(ev) {
|
|
|
1268
539
|
...(readDeny !== undefined ? { _sema_readDeny: readDeny } : {}),
|
|
1269
540
|
};
|
|
1270
541
|
}
|
|
1271
|
-
/** 🔴 缺席 = 没编译出判官(第三态),**不折 `spelling-only`**;`targetView` 不在二词 / 非对象 ⇒ 段缺席;多余成员不过境。 */
|
|
1272
542
|
function projectWriteProtectionSection(raw) {
|
|
1273
543
|
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
1274
544
|
return undefined;
|
|
@@ -1277,8 +547,6 @@ function projectWriteProtectionSection(raw) {
|
|
|
1277
547
|
return undefined;
|
|
1278
548
|
return { targetView: v };
|
|
1279
549
|
}
|
|
1280
|
-
/** 🔴 缺席 = 未武装 **或** 本连接不是 operator 面 **或** 老 server(<7.82.0)—— 三者 wire 上不可分,一律读作 indeterminate,**不折 false**;
|
|
1281
|
-
* `onRecommendation` 不是严格 `true` / 非对象 ⇒ 段缺席;多余成员不过境。 */
|
|
1282
550
|
function projectAutoConsolidationSection(raw) {
|
|
1283
551
|
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
1284
552
|
return undefined;
|
|
@@ -1286,9 +554,6 @@ function projectAutoConsolidationSection(raw) {
|
|
|
1286
554
|
return undefined;
|
|
1287
555
|
return { onRecommendation: true };
|
|
1288
556
|
}
|
|
1289
|
-
/** 🔴 缺席 = **没有内置行判这条腿**(出厂 OFF 的未配置部署 / 老 server <7.22.0 承载版)—— **不是**「没有读被 deny 判」:部署与任务级
|
|
1290
|
-
* `readDenyPatterns` 是另一套来源,刻意不上报。空数组铸点**永不发出**(「关」与「开到什么都不判」是一件事)⇒ 判畸形段缺席;
|
|
1291
|
-
* 成员非非空串 / 非对象 ⇒ 段缺席(其余段照投);多余成员不过境;数组是新拷贝。 */
|
|
1292
557
|
function projectReadDenySection(raw) {
|
|
1293
558
|
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
1294
559
|
return undefined;
|
|
@@ -1321,7 +586,6 @@ function projectLspSection(raw) {
|
|
|
1321
586
|
return undefined;
|
|
1322
587
|
return { mounted: o.mounted, ...(typeof o.lane === 'string' && o.lane.length > 0 ? { lane: o.lane } : {}) };
|
|
1323
588
|
}
|
|
1324
|
-
/** 内部臂的唯一铸出口(内部臂不在 CC 的 SDKMessage 联合里,出境只此一处铸;新臂走这里,不再各写一处铸链)。 */
|
|
1325
589
|
const internalArmExit = (body) => body;
|
|
1326
590
|
function contextUsageProjection(ev, ctx) {
|
|
1327
591
|
const { identity, bad } = identityOrMalformed(ev, 'context_usage');
|
|
@@ -1340,11 +604,11 @@ function contextUsageProjection(ev, ctx) {
|
|
|
1340
604
|
const o = r;
|
|
1341
605
|
const tokens = fin(o.tokens);
|
|
1342
606
|
if (typeof o.id !== 'string' || o.id.length === 0 || tokens === undefined)
|
|
1343
|
-
continue;
|
|
607
|
+
continue;
|
|
1344
608
|
rows.push({ id: o.id, tokens, ...(typeof o.kind === 'string' && o.kind.length > 0 ? { kind: o.kind } : {}) });
|
|
1345
609
|
}
|
|
1346
610
|
if (rows.length > 0)
|
|
1347
|
-
sections = rows;
|
|
611
|
+
sections = rows;
|
|
1348
612
|
}
|
|
1349
613
|
if (usedTokens === undefined && windowTokens === undefined && compactAtTokens === undefined && sections === undefined)
|
|
1350
614
|
return nothing('empty_payload');
|
|
@@ -1357,13 +621,7 @@ function contextUsageProjection(ev, ctx) {
|
|
|
1357
621
|
...identity,
|
|
1358
622
|
}))));
|
|
1359
623
|
}
|
|
1360
|
-
/**
|
|
1361
|
-
* CC-89(0.75.0):`outcome` 是主事实,非空串必在(否则 malformed —— 不投一条没有结局的结局帧),原词逐字(引擎开集,不按成员过滤);
|
|
1362
|
-
* `trigger` / `reason` 非空串才在场,缺席 / 坏形 ⇒ 键不在场(不编 'auto'、不编空串;主事实不因旁键丢)。
|
|
1363
|
-
*/
|
|
1364
624
|
function compactionOutcomeProjection(frame, ctx) {
|
|
1365
|
-
// 🔴 不浅拷(异源复审 R1 [medium]):展开会擦掉原型链上的身份键(进程内对象把子代帧洗成主会话)、还会执行无关的可枚举 getter;
|
|
1366
|
-
// 与兄弟臂同律 —— 就在同一份记录上逐键各读一次。
|
|
1367
625
|
const ev = frame;
|
|
1368
626
|
const { identity, bad } = identityOrMalformed(ev, 'compaction_outcome');
|
|
1369
627
|
if (bad !== null)
|
|
@@ -1382,23 +640,7 @@ function compactionOutcomeProjection(frame, ctx) {
|
|
|
1382
640
|
...identity,
|
|
1383
641
|
}))));
|
|
1384
642
|
}
|
|
1385
|
-
/**
|
|
1386
|
-
* CC-91(0.76.0):`prompt_assembled`(一次 prepare 的提示词装配清单)→ 中性内部臂。
|
|
1387
|
-
*
|
|
1388
|
-
* 逐键诚实:`totalChars` 有限非负才在场(缺席 ≠ 0);`blocks` / `sections` / `tools` 三面**逐行**挑
|
|
1389
|
-
* (`id` / `wireName` 非空串 ∧ `chars` 有限非负),坏行逐条丢、全丢光或非数组 ⇒ 该键缺席。
|
|
1390
|
-
* 🔴 于是键缺席是**三支合流**(上游整键缺席 / 空数组 / 逐行滤完只剩空),本层分不出是哪一支 ⇒ 对外只能说
|
|
1391
|
-
* 「本事件没有可读的这一面」,**不许**把它写成一句关于引擎的诊断(如「这条腿没装配出段 IR」)。不铸 `[]`:
|
|
1392
|
-
* 空数组会被读成「装配出来是空的」,那是另一件事。
|
|
1393
|
-
* 🔴 一条组成面的键都读不出 ⇒ `malformed`:core 把 `blocks` / `totalChars` 声明为必填,两件全丢的帧是坏 producer,
|
|
1394
|
-
* 投一份空清单会让消费端把「读不出」渲成「提示词是空的」。
|
|
1395
|
-
* 🔴 帧上的 `constitution`(谁拥有宪法层)**刻意不过境**:本包与三端今天没有任何消费场景,而每一个上了公面的键都是
|
|
1396
|
-
* 一条要长期兑现的契约 —— additive 键晚加不破坏、早加却删不掉。哪天有端点名要它,再按表态制加(本层零改动成本)。
|
|
1397
|
-
* 🔴 **零 `tokens` 铸点**(见 {@link PromptManifestSectionView} 头注):真字节里没有这一位。
|
|
1398
|
-
*/
|
|
1399
643
|
function promptAssembledProjection(frame, ctx) {
|
|
1400
|
-
// 🔴 不浅拷(与 compaction_outcome 同律):展开会擦掉原型链上的身份键(进程内对象把子代帧洗成主会话)、
|
|
1401
|
-
// 还会执行无关的可枚举 getter;就在同一份记录上逐键各读一次。
|
|
1402
644
|
const ev = frame;
|
|
1403
645
|
const { identity, bad } = identityOrMalformed(ev, 'prompt_assembled');
|
|
1404
646
|
if (bad !== null)
|
|
@@ -1478,77 +720,22 @@ function engineNoticeProjection(ev, ctx) {
|
|
|
1478
720
|
return projected(stamp(ctx, armBody({
|
|
1479
721
|
type: 'engine_notice',
|
|
1480
722
|
code,
|
|
1481
|
-
/** 🔴 fallback 展示位,**不是匹配键**(见本函数顶注 ①)。 */
|
|
1482
723
|
message: typeof ev.message === 'string' ? ev.message : '',
|
|
1483
|
-
/** 🔴 原样透传(禁挑键):`detail` 逐码不同且是**开集**,白名单挑键 = 新码的事实在本层静默蒸发。 */
|
|
1484
724
|
detail,
|
|
1485
725
|
...(sessionId !== undefined ? { sessionId } : {}),
|
|
1486
726
|
...(ts !== undefined ? { ts } : {}),
|
|
1487
|
-
// ── 重放身份:两个键、**两个不同的命名空间**,谁都不许顶替谁 ──────────────────────────
|
|
1488
|
-
// durable 腿按 `Last-Event-ID` 续读会重放同一条通告 ⇒ 消费端必须能幂等。可用的身份有两层:
|
|
1489
|
-
// · `eventId` —— core 铸的稳定事件身份(uuidv7 形)。wire 今天未必带。
|
|
1490
|
-
// · `eventSeq` —— **SDK 从 SSE `id:` 字段 stamp 上来的 durable 序号**(= `task_event.seq`,
|
|
1491
|
-
// 见 sdk `dist/sse.js` 的 `ev.id = frame.id`;本包的规范访问口就是 `adapter/types.eventSeq`)。
|
|
1492
|
-
// 它对「同一条账本行」是稳定的,重放会带同一个值。
|
|
1493
|
-
// 🔴 对抗复审 [medium] 采纳(2026-08-21):首版只带 `eventId`,于是 body 不带它时本臂
|
|
1494
|
-
// 给消费端留的唯一去重口是 `code+ts` —— 而 `ts` 是**server 观察时刻(ms)**,同一毫秒里同码
|
|
1495
|
-
// 的两条不同通告会被折成一条(真事实丢失),跨重连的同一条又可能因为观察时刻不同而重复。
|
|
1496
|
-
// 明明有一个稳定序号在手却不带,是本层自己把可靠性降级了。
|
|
1497
|
-
// 🔴 **绝不合并成一个键**([same-name-different-meaning-crosses-layers]):`eventId` 是引擎铸的
|
|
1498
|
-
// 全局身份,`eventSeq` 是 per-task 的单调序号 —— 塞进同一个字段名会让消费端拿两种语义当一种用。
|
|
1499
727
|
...(typeof ev.eventId === 'string' && ev.eventId.length > 0 ? { eventId: ev.eventId } : {}),
|
|
1500
728
|
...(typeof ev.id === 'string' && ev.id.length > 0 ? { eventSeq: ev.id } : {}),
|
|
1501
729
|
})));
|
|
1502
730
|
}
|
|
1503
|
-
/**
|
|
1504
|
-
* `approval_request` / `approval_revoke` 的**信封级成形判**(B-078 / L-208,0.65.0;design/172)——
|
|
1505
|
-
* 两条 `case` 共用这一只(判据单源),而 `type` 字面量留在各自的 `case` 里:
|
|
1506
|
-
* 内部臂词表的常驻对账门(pure 门 A-004.4)按 `armBody({ type: '<字面量>'` 抽取铸点 ——
|
|
1507
|
-
* 把字面量藏进参数会让那道门对这两条臂整个失明。
|
|
1508
|
-
*
|
|
1509
|
-
* ── 🔴 载荷是**信封原样**,本层一个键都不摘 ─────────────────────────────────────────────────
|
|
1510
|
-
* sdk 把这两条臂的载荷声明成 `ApprovalFrameEnvelope`(`type` + `schemaVersion: number` + 开集键),
|
|
1511
|
-
* **刻意不是** v1 帧型 —— 理由 sdk events.d.ts:961-968 逐字:SSE 解析腿只做
|
|
1512
|
-
* `JSON.parse(...) as AgentEvent`、**不跑**谓词,臂若窄化到 v1,一条 `schemaVersion: 2` 的合法帧会
|
|
1513
|
-
* 被类型系统当成 v1 端上来,消费端于是去取 `card.risk.requiresRealApproval` —— 而未知版本的卡
|
|
1514
|
-
* 根本不保证有这些键。
|
|
1515
|
-
* ⇒ 本层只做**信封级**成形判(是不是一只对象 / `schemaVersion` 是不是有限数),把**整只帧**交下去;
|
|
1516
|
-
* 窄化(`isApprovalRequestFrameV1` / `isApprovalRevokeFrameV1`)是**宿主**的动作,契约写在
|
|
1517
|
-
* `seam.ts` 的两个臂头注里。在这里挑键重铸 = 在包里立第二份卡形台账,而那正是上游这条设计要防的。
|
|
1518
|
-
*
|
|
1519
|
-
* ── 成形判不过 ⇒ 调用方报 `dropped('malformed')`,**不是** `none` ─────────────────────────────
|
|
1520
|
-
* 与 `engine_notice` 同规:静默的 `none` 会让「协议帧坏了」这件事在用户面上什么痕迹都不留,而这
|
|
1521
|
-
* 两帧带的是**用户可见的决策内容/状态迁移**。`dropped` 经 `reportDroppedFrame` 走宿主 sink + 留痕。
|
|
1522
|
-
*
|
|
1523
|
-
* 🔴 **不在本层做去重/归属过滤**:`approvalId` 去重、按 `taskId` 归属、开流 preamble 对账,三件都
|
|
1524
|
-
* 需要宿主的**卡集状态**(库这一层没有,也不该有)—— 契约逐条写在 `seam.ts` 的臂注里。
|
|
1525
|
-
*/
|
|
1526
731
|
function approvalFrameBody(ev) {
|
|
1527
|
-
// 🔴 判据锚在**真正决定宿主能不能窄化**的那一个量:`schemaVersion`。它不是有限数 ⇒ 这一帧连
|
|
1528
|
-
// 信封都不成立(宿主的两条腿——v1 窄化与通用卡兜底——都需要它来分流),如实报 malformed。
|
|
1529
732
|
const schemaVersion = typeof ev.schemaVersion === 'number' && Number.isFinite(ev.schemaVersion)
|
|
1530
733
|
? ev.schemaVersion
|
|
1531
734
|
: undefined;
|
|
1532
735
|
if (schemaVersion === undefined)
|
|
1533
736
|
return undefined;
|
|
1534
|
-
// 🔴 帧**原样**(含 `type` 回声与全部开集键)。宿主拿它去跑 sdk 的窄化谓词。
|
|
1535
737
|
return { frame: ev, schemaVersion };
|
|
1536
738
|
}
|
|
1537
|
-
/**
|
|
1538
|
-
* `human_input` → 中性内部账本臂(见 `eventToSdkMessage` 顶部的 raw 预分派注释)。
|
|
1539
|
-
*
|
|
1540
|
-
* 白名单逐键挑(禁 spread),与 server 侧 `humanInputEventData` 的投影面同源:
|
|
1541
|
-
* · `inputId` / `sessionSeq` / `carrier` / `source` / `delivery` / `entryId` = 引擎铸的标识与枚举
|
|
1542
|
-
* 值,非用户内容 ⇒ verbatim;
|
|
1543
|
-
* · `issuer` / `actor.id` / `actor.issuer` = 宿主从入口凭据派生的**身份串**(自由文本形)——
|
|
1544
|
-
* server 已 redact 过再上帧,本层只透传,不再二次加工(壳侧 UNTRUSTED-for-display);
|
|
1545
|
-
* · `actor.hostAsserted` = 消费端**唯一**能判「这个署名可信吗」的位(core 的 `[from …]` 渲染靠它
|
|
1546
|
-
* 决定加不加 `(unverified)`)—— 剥掉它比剥掉 id 更坏:剩下一个看不出真假的名字。
|
|
1547
|
-
* · `principal` = **刻意不投影**(与 ToolApprovalFrame 的 principal 同裁:帧本就经 owner-scoped
|
|
1548
|
-
* 流投递,租户身份不必由帧自述)。
|
|
1549
|
-
* `carrier` 缺席 ⇒ `malformed`:一条既没有载体也没有正文的账本行,渲出去只是一行「有人输入了什么」
|
|
1550
|
-
* 的噪声,而 dropped 至少会留痕。
|
|
1551
|
-
*/
|
|
1552
739
|
function humanInputProjection(ev, ctx) {
|
|
1553
740
|
const str = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
|
|
1554
741
|
const carrier = str(ev.carrier);
|
|
@@ -1574,73 +761,21 @@ function humanInputProjection(ev, ctx) {
|
|
|
1574
761
|
...(str(ev.issuer) !== undefined ? { issuer: str(ev.issuer) } : {}),
|
|
1575
762
|
...(actor !== undefined && Object.keys(actor).length > 0 ? { actor } : {}),
|
|
1576
763
|
...(str(ev.entryId) !== undefined ? { entryId: str(ev.entryId) } : {}),
|
|
1577
|
-
// 🔴 `eventId` 必须带到底(对抗复审二轮):durable 腿按 `Last-Event-ID` 续读会**重放**同一条
|
|
1578
|
-
// 账本帧,而本地行 id 是现铸的 —— 审计/时间线消费者若没有引擎铸的稳定键,一次人工注入会被
|
|
1579
|
-
// 记成多次。`inputId`/`entryId` 在公开形上都是可选的,`eventId` 是那个恒在的身份位。
|
|
1580
764
|
...(str(ev.eventId) !== undefined ? { eventId: str(ev.eventId) } : {}),
|
|
1581
765
|
...(str(ev.parentToolCallId) !== undefined ? { parentToolCallId: str(ev.parentToolCallId) } : {}),
|
|
1582
766
|
})));
|
|
1583
767
|
}
|
|
1584
|
-
/**
|
|
1585
|
-
* CS-7 §2.7 — turn_end usage → CC `ModelUsage` (pinned name mapping;
|
|
1586
|
-
* costMicroUsd/1e6 → costUSD). Surfaced separately because the slice has no
|
|
1587
|
-
* standalone usage SDKMessage arm; the run driver folds it into the footer /
|
|
1588
|
-
* terminal rollup.
|
|
1589
|
-
*
|
|
1590
|
-
* ── 🔴 0.68.0 BREAKING(core 7.17.0 #711;异源对抗复审轮三实抓的**第五处**)──────────────────
|
|
1591
|
-
* 返回 `undefined` 的含义从「`usage` 这一格缺席」收窄成 **「这一轮的账不知道」**,两种入形都答它:
|
|
1592
|
-
* ① `ev.usage` 整个缺席 —— #711 之后这**不再是一条合法形**(契约违约;`runStream` 那一层另有
|
|
1593
|
-
* 响亮留痕,本读器只如实答「不知道」);
|
|
1594
|
-
* ② `usageMissing: true` **且六格全是 0** —— 那正是 core 的**占位**
|
|
1595
|
-
* (`rs.turn.turnUsage ?? {六个 0}`,`run-harness-handlers.js:289-293`)。
|
|
1596
|
-
* 🔴 为什么必须改:#711 之前,「这一轮没量出账」这件事在 wire 上的形是**不发 usage** ⇒ 本函数答
|
|
1597
|
-
* `undefined`;#711 之后同一件事的形变成六个 0,而本函数是**公面导出** —— 不改的话,同一个真实
|
|
1598
|
-
* 情形在引擎升级前后由同一个公开读器给出两个相反的答案(「不知道」变成「这一轮恰好花了 0」),
|
|
1599
|
-
* 而调用方**一个字都没改**。收窄之后跨引擎升级的答案**逐字不变**。
|
|
1600
|
-
* 🔴 **非零照交**:`usageMissing` 并不保证六格是零(core 在同一轮里可能已攒到真数字而另一次调用
|
|
1601
|
-
* 报了缺账 ⇒ 判别位与真数字同帧并存)。占位恒为全零,所以**任何一格非零**都说明这一轮真的量到过
|
|
1602
|
-
* ⇒ 照交镜像(那些数字是**下界**,而「是不是下界」由帧上的 `usageMissing` / 终帧的
|
|
1603
|
-
* `_sema_usage_lower_bound` 回答,不由本函数回答)。
|
|
1604
|
-
* ⚠️ 要**原样**的 wire 镜像(不做任何判断)请直接调 {@link turnUsageToModelUsage} —— 那一只是
|
|
1605
|
-
* 纯映射,本函数是**带缺席语义的读器**,两者刻意分开。
|
|
1606
|
-
*/
|
|
1607
768
|
export function turnEndUsage(ev) {
|
|
1608
|
-
// 🔴 **成形判据不是 `!raw`**(异源复审轮四同族):wire 是 JSON、SSE 解析原样透传 ⇒ `usage: null` /
|
|
1609
|
-
// `usage: 7` 这类形真到得了这里。`null` 会让映射在读字段时抛;标量更坏 —— 它会被映射成一份
|
|
1610
|
-
// **看起来已测量**的全零账(`toCcModelUsage(7)` 逐格读不出、逐格折 0)。坏形与缺席同义:
|
|
1611
|
-
// **这一轮的账不知道**。
|
|
1612
769
|
const rawValue = ev.usage;
|
|
1613
770
|
if (typeof rawValue !== 'object' || rawValue === null || Array.isArray(rawValue))
|
|
1614
771
|
return undefined;
|
|
1615
772
|
const raw = rawValue;
|
|
1616
773
|
const unknown = ev.usageMissing === true;
|
|
1617
|
-
// 占位判据 = **六格全零**(不是「有 usageMissing 就算占位」)。逐格按值判,非有限值当 0 看待
|
|
1618
|
-
// (那一格本来就读不出,它不构成「量到过」的证据)。
|
|
1619
774
|
const placeholder = unknown &&
|
|
1620
775
|
[raw.inputTokens, raw.totalInputTokens, raw.outputTokens, raw.cacheReadTokens, raw.cacheWriteTokens, raw.costMicroUsd]
|
|
1621
776
|
.every((v) => !(typeof v === 'number' && Number.isFinite(v) && v !== 0));
|
|
1622
777
|
return placeholder ? undefined : turnUsageToModelUsage(raw);
|
|
1623
778
|
}
|
|
1624
|
-
/**
|
|
1625
|
-
* Defensive open-set read of a `suspended` gate kind for the run driver's HITL
|
|
1626
|
-
* branch — known kinds plus a generic fallback (contract 02 §2.9 / §3: never
|
|
1627
|
-
* crash on an unknown kind). Kept here so the §6 mapping lives in one file.
|
|
1628
|
-
*
|
|
1629
|
-
* ⚠️ DEAD CODE — 不是「HITL 分支漏接」(2026-07-26 全树核查,task #81 顺带件):
|
|
1630
|
-
* · 全树(src/ + mock/ + build/ + 测试)**零调用点**,adapter facade(src/seam/adapter/index.ts)
|
|
1631
|
-
* 也没把它再导出去 —— 没有任何一处「本该调它却没调」。
|
|
1632
|
-
* · 它想服务的那条 HITL 分支**已经接好了**,只是没走这个函数(REF-CC-063:此处原为四个行号锚,
|
|
1633
|
-
* 今天全部已腐,改符号锚):
|
|
1634
|
-
* - `suspended` 事件臂 → `hitl/hitlBridge.ts` 的 `HitlBridge.observe()` 就地做了**同款**防御
|
|
1635
|
-
* 回落(`ev.gate ? ev.gate : { kind: 'human' }`),而且 latch 的是整个 CheckpointGate 对象,
|
|
1636
|
-
* 壳侧 `currentGate()` 自己 branch `gate.kind`;
|
|
1637
|
-
* - `done{status:'suspended', checkpointGate}` 终帧 → `liveHitlAskWire.ts` 的 ask 合成口 /
|
|
1638
|
-
* `terminalToSdkResult.ts` 的 park 臂各自读 `checkpointGate.kind` **和** `.toolName`。
|
|
1639
|
-
* · 关键:每个真实消费方都同时需要 `toolName`(挑 Ask overlay vs fs 写门三选卡),而本函数只吐
|
|
1640
|
-
* 一个 kind 字符串 —— 签名比任何真实需求都窄,接进去反而要再读一次 gate。
|
|
1641
|
-
* 结论 = 可删的死码(留档不擅删,按 task #81 口径只标记);真要收,连同 `CheckpointGate` 的
|
|
1642
|
-
* type-only import 一起摘。
|
|
1643
|
-
*/
|
|
1644
779
|
export function gateKind(gate) {
|
|
1645
780
|
return gate?.kind ?? 'human';
|
|
1646
781
|
}
|