@sema-agent/client-core 0.77.1 → 0.77.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -1
- package/README.md +5 -4
- package/dist/abortableSleep.d.ts +0 -28
- package/dist/abortableSleep.js +0 -28
- package/dist/adapt/arms.d.ts +0 -46
- package/dist/adapt/arms.js +9 -544
- package/dist/adapt/ids.d.ts +0 -58
- package/dist/adapt/ids.js +0 -63
- package/dist/adapt/instanceLedger.d.ts +0 -25
- package/dist/adapt/instanceLedger.js +0 -20
- package/dist/adapt/panelTasks.d.ts +0 -69
- package/dist/adapt/panelTasks.js +0 -95
- package/dist/adapt/textSegmentAuthority.d.ts +1 -137
- package/dist/adapt/textSegmentAuthority.js +0 -54
- package/dist/adapt/textStream.d.ts +0 -252
- package/dist/adapt/textStream.js +2 -281
- package/dist/adapt/toolCards.d.ts +0 -46
- package/dist/adapt/toolCards.js +0 -23
- package/dist/adapt/turnFlags.d.ts +0 -54
- package/dist/adapt/turnFlags.js +1 -17
- package/dist/adapt/wireShapes.d.ts +0 -92
- package/dist/adapt/wireShapes.js +0 -83
- package/dist/adapt.d.ts +0 -55
- package/dist/adapt.js +1 -120
- package/dist/adapter/activeRunSelfHeal.d.ts +22 -515
- package/dist/adapter/activeRunSelfHeal.js +10 -625
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -305
- package/dist/adapter/downstream/eventToSdkMessage.js +2 -867
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +2 -314
- package/dist/adapter/downstream/terminalToSdkResult.js +13 -560
- package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +0 -95
- package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -31
- package/dist/adapter/runStream.d.ts +0 -206
- package/dist/adapter/runStream.js +6 -596
- package/dist/adapter/types.d.ts +0 -111
- package/dist/adapter/types.js +0 -29
- package/dist/agentSession/backgroundView.d.ts +0 -106
- package/dist/agentSession/backgroundView.js +3 -49
- package/dist/agentSession/contract.d.ts +0 -98
- package/dist/agentSession/contract.js +0 -12
- package/dist/agentsWireCaps.d.ts +0 -72
- package/dist/agentsWireCaps.js +4 -72
- package/dist/approvalsStreamLiveCapability.d.ts +0 -25
- package/dist/approvalsStreamLiveCapability.js +0 -31
- package/dist/argvFlagValue.d.ts +0 -33
- package/dist/argvFlagValue.js +3 -35
- package/dist/attachmentsWireCaps.d.ts +0 -127
- package/dist/attachmentsWireCaps.js +0 -144
- package/dist/autoModeUnavailable.d.ts +0 -120
- package/dist/autoModeUnavailable.js +0 -144
- package/dist/classifierStatus.d.ts +0 -72
- package/dist/classifierStatus.js +0 -167
- package/dist/classifierVerdictWire.d.ts +0 -54
- package/dist/classifierVerdictWire.js +0 -133
- package/dist/clientContextWireCaps.d.ts +0 -37
- package/dist/clientContextWireCaps.js +0 -36
- package/dist/clientSlice.d.ts +0 -63
- package/dist/clientSlice.js +0 -45
- package/dist/cloudConfigWireCaps.d.ts +0 -86
- package/dist/cloudConfigWireCaps.js +2 -65
- package/dist/compensations.d.ts +0 -52
- package/dist/compensations.js +2 -63
- package/dist/controlRouter.d.ts +2 -208
- package/dist/controlRouter.js +1 -129
- package/dist/coreValuePorts.d.ts +0 -84
- package/dist/coreValuePorts.js +0 -29
- package/dist/decideReceipt.d.ts +0 -110
- package/dist/decideReceipt.js +0 -84
- package/dist/detachWire.d.ts +0 -130
- package/dist/detachWire.js +1 -130
- package/dist/deviceExecutorManagementCapability.d.ts +2 -35
- package/dist/deviceExecutorManagementCapability.js +1 -37
- package/dist/diagnostics.d.ts +0 -8
- package/dist/diagnostics.js +0 -8
- package/dist/diff/patch.d.ts +0 -17
- package/dist/diff/patch.js +0 -19
- package/dist/effectiveFacts.d.ts +0 -40
- package/dist/effectiveFacts.js +0 -22
- package/dist/effortWire.d.ts +0 -11
- package/dist/effortWire.js +0 -12
- package/dist/engineAgentPanelStore.d.ts +0 -169
- package/dist/engineAgentPanelStore.js +13 -293
- package/dist/engineCapReader.d.ts +0 -62
- package/dist/engineCapReader.js +1 -43
- package/dist/engineCapsCache.d.ts +0 -177
- package/dist/engineCapsCache.js +0 -199
- package/dist/engineCapsGenerationGuard.d.ts +0 -2
- package/dist/engineCapsGenerationGuard.js +0 -11
- package/dist/engineErrorCodes.d.ts +1 -316
- package/dist/engineErrorCodes.js +0 -427
- package/dist/engineHttpTools.d.ts +0 -29
- package/dist/engineHttpTools.js +0 -29
- package/dist/engineIdentity.d.ts +0 -83
- package/dist/engineIdentity.js +0 -88
- package/dist/engineInlineTaskStats.d.ts +0 -57
- package/dist/engineInlineTaskStats.js +1 -42
- package/dist/engineNoticeCodes.d.ts +0 -190
- package/dist/engineNoticeCodes.js +0 -182
- package/dist/engineSessionParam.d.ts +0 -30
- package/dist/engineSessionParam.js +0 -52
- package/dist/engineToolLabelStore.d.ts +0 -29
- package/dist/engineToolLabelStore.js +0 -31
- package/dist/engineWireSdk.d.ts +0 -90
- package/dist/engineWireSdk.js +0 -74
- package/dist/engineWireTarget.d.ts +0 -14
- package/dist/engineWireTarget.js +0 -39
- package/dist/env/localeGeo.d.ts +0 -12
- package/dist/env/localeGeo.js +2 -77
- package/dist/env/localeTag.d.ts +0 -34
- package/dist/env/localeTag.js +0 -32
- package/dist/env/uiLanguage.d.ts +0 -13
- package/dist/env/uiLanguage.js +0 -25
- package/dist/envFlag.d.ts +0 -37
- package/dist/envFlag.js +0 -40
- package/dist/executionLaneCapability.d.ts +0 -48
- package/dist/executionLaneCapability.js +0 -54
- package/dist/finalVerifyWire.d.ts +0 -67
- package/dist/finalVerifyWire.js +3 -43
- package/dist/fleet/fleetLedger.d.ts +0 -308
- package/dist/fleet/fleetLedger.js +10 -429
- package/dist/fleet/fleetProjection.d.ts +0 -240
- package/dist/fleet/fleetProjection.js +0 -189
- package/dist/fleet/fleetRowAgentType.d.ts +0 -6
- package/dist/fleet/fleetRowAgentType.js +1 -32
- package/dist/fleet/workflowSizeWarning.d.ts +0 -47
- package/dist/fleet/workflowSizeWarning.js +1 -46
- package/dist/fleetAgentPanelProjection.d.ts +0 -48
- package/dist/fleetAgentPanelProjection.js +8 -173
- package/dist/fleetTaskDesc.d.ts +0 -39
- package/dist/fleetTaskDesc.js +0 -69
- package/dist/forkWireCaps.d.ts +0 -23
- package/dist/forkWireCaps.js +1 -24
- package/dist/gateOutcome.d.ts +0 -140
- package/dist/gateOutcome.js +0 -85
- package/dist/gateVocabulary.d.ts +0 -114
- package/dist/gateVocabulary.js +1 -161
- package/dist/goalStopHook.d.ts +0 -127
- package/dist/goalStopHook.js +0 -178
- package/dist/headlessPermissionModeWire.d.ts +0 -76
- package/dist/headlessPermissionModeWire.js +1 -155
- package/dist/headlessReconnectWire.d.ts +0 -84
- package/dist/headlessReconnectWire.js +13 -67
- package/dist/hitl/approvalDecisionNoteAudit.d.ts +0 -49
- package/dist/hitl/approvalDecisionNoteAudit.js +0 -56
- package/dist/hitl/approvalOutcomeNote.d.ts +0 -2
- package/dist/hitl/approvalOutcomeNote.js +0 -20
- package/dist/hitl/approvalResolution.d.ts +0 -113
- package/dist/hitl/approvalResolution.js +0 -66
- package/dist/hitl/approvalsFeed.d.ts +0 -183
- package/dist/hitl/approvalsFeed.js +12 -243
- package/dist/hitl/armedGateRegistry.d.ts +0 -55
- package/dist/hitl/armedGateRegistry.js +0 -146
- package/dist/hitl/askGateWire.d.ts +0 -86
- package/dist/hitl/askGateWire.js +1 -95
- package/dist/hitl/askParkRowRouting.d.ts +0 -123
- package/dist/hitl/askParkRowRouting.js +1 -89
- package/dist/hitl/crashConverged.d.ts +0 -148
- package/dist/hitl/crashConverged.js +0 -214
- package/dist/hitl/editedRuleTextPrecheck.d.ts +0 -109
- package/dist/hitl/editedRuleTextPrecheck.js +0 -71
- package/dist/hitl/frameRouter.d.ts +0 -134
- package/dist/hitl/frameRouter.js +6 -378
- package/dist/hitl/gateIdentity.d.ts +0 -39
- package/dist/hitl/gateIdentity.js +0 -41
- package/dist/hitl/gateLedger.d.ts +0 -267
- package/dist/hitl/gateLedger.js +0 -121
- package/dist/hitl/hitlBridge.d.ts +7 -431
- package/dist/hitl/hitlBridge.js +7 -476
- package/dist/hitl/hitlHostSurface.d.ts +0 -150
- package/dist/hitl/hitlHostSurface.js +0 -169
- package/dist/hitl/livePendingAsk.d.ts +0 -91
- package/dist/hitl/livePendingAsk.js +0 -74
- package/dist/hitl/localAllowRule.d.ts +0 -62
- package/dist/hitl/localAllowRule.js +1 -33
- package/dist/hitl/parkOwnership.d.ts +0 -56
- package/dist/hitl/parkOwnership.js +0 -22
- package/dist/hitl/parkResolver.d.ts +3 -88
- package/dist/hitl/parkResolver.js +8 -349
- package/dist/hitl/parkRowBirthWait.d.ts +2 -26
- package/dist/hitl/parkRowBirthWait.js +3 -93
- package/dist/hitl/persistedRulesWire.d.ts +13 -358
- package/dist/hitl/persistedRulesWire.js +0 -310
- package/dist/hitl/planReviewWire.d.ts +4 -176
- package/dist/hitl/planReviewWire.js +9 -312
- package/dist/hitl/resumeRunningCard.d.ts +0 -105
- package/dist/hitl/resumeRunningCard.js +0 -105
- package/dist/hitl/sessionPolicyWire.d.ts +11 -191
- package/dist/hitl/sessionPolicyWire.js +0 -149
- package/dist/hitl/suspendedReopen.d.ts +3 -24
- package/dist/hitl/suspendedReopen.js +0 -14
- package/dist/hitl/toolApprovalWire.d.ts +5 -1308
- package/dist/hitl/toolApprovalWire.js +5 -945
- package/dist/hooksWireCaps.d.ts +0 -38
- package/dist/hooksWireCaps.js +0 -190
- package/dist/host.d.ts +0 -105
- package/dist/host.js +0 -33
- package/dist/hostEnv.d.ts +0 -14
- package/dist/hostEnv.js +0 -13
- package/dist/imagesWireCaps.d.ts +0 -21
- package/dist/imagesWireCaps.js +0 -22
- package/dist/index.d.ts +0 -134
- package/dist/index.js +0 -476
- package/dist/interactiveHalt.d.ts +5 -153
- package/dist/interactiveHalt.js +0 -111
- package/dist/interactiveToolsWire.d.ts +0 -62
- package/dist/interactiveToolsWire.js +1 -67
- package/dist/leaderConflict.d.ts +0 -59
- package/dist/leaderConflict.js +0 -48
- package/dist/limitsWire.d.ts +0 -125
- package/dist/limitsWire.js +2 -120
- package/dist/liveInitToolFace.d.ts +0 -77
- package/dist/liveInitToolFace.js +1 -109
- package/dist/liveModelCatalog.d.ts +0 -52
- package/dist/liveModelCatalog.js +0 -48
- package/dist/liveQuestionStore.d.ts +0 -87
- package/dist/liveQuestionStore.js +1 -56
- package/dist/mcpLiveness.d.ts +0 -151
- package/dist/mcpLiveness.js +0 -122
- package/dist/mcpPanel.d.ts +0 -104
- package/dist/mcpPanel.js +0 -49
- package/dist/mcpReconnect.d.ts +0 -58
- package/dist/mcpReconnect.js +0 -69
- package/dist/mcpWireCaps.d.ts +0 -55
- package/dist/mcpWireCaps.js +1 -13
- package/dist/memoryComplianceCapability.d.ts +3 -57
- package/dist/memoryComplianceCapability.js +0 -57
- package/dist/memoryEntriesWire.d.ts +6 -198
- package/dist/memoryEntriesWire.js +0 -144
- package/dist/memoryOriginCapability.d.ts +3 -53
- package/dist/memoryOriginCapability.js +0 -50
- package/dist/memorySpecWire.d.ts +0 -116
- package/dist/memorySpecWire.js +0 -150
- package/dist/model/catalog.d.ts +0 -111
- package/dist/model/catalog.js +0 -87
- package/dist/model/catalogLoader.d.ts +0 -114
- package/dist/model/catalogLoader.js +2 -139
- package/dist/model/modelSupplyRules.d.ts +1 -55
- package/dist/model/modelSupplyRules.js +0 -62
- package/dist/model/providerAuth.d.ts +0 -103
- package/dist/model/providerAuth.js +2 -38
- package/dist/model/providerCatalog.d.ts +0 -45
- package/dist/model/providerCatalog.js +0 -37
- package/dist/model/providerPresets.d.ts +0 -33
- package/dist/model/providerPresets.js +2 -91
- package/dist/model/tierVocabulary.d.ts +0 -31
- package/dist/model/tierVocabulary.js +0 -27
- package/dist/modelBudgetRule.d.ts +0 -39
- package/dist/modelBudgetRule.js +0 -39
- package/dist/modelCapabilityProbe.d.ts +0 -175
- package/dist/modelCapabilityProbe.js +0 -147
- package/dist/modelWireCaps.d.ts +0 -13
- package/dist/modelWireCaps.js +0 -13
- package/dist/notifications.d.ts +0 -233
- package/dist/notifications.js +14 -492
- package/dist/oneShotWireCaps.d.ts +0 -34
- package/dist/oneShotWireCaps.js +0 -35
- package/dist/ownKey.d.ts +0 -33
- package/dist/ownKey.js +0 -33
- package/dist/panelRunningHistory.d.ts +0 -28
- package/dist/panelRunningHistory.js +0 -43
- package/dist/peerFrames.d.ts +0 -71
- package/dist/peerFrames.js +0 -168
- package/dist/peerLaneCapability.d.ts +0 -44
- package/dist/peerLaneCapability.js +0 -52
- package/dist/permissionRuleIssue.d.ts +0 -30
- package/dist/permissionRuleIssue.js +0 -78
- package/dist/permissionRulesWriteCapability.d.ts +0 -46
- package/dist/permissionRulesWriteCapability.js +0 -54
- package/dist/permissionWireCaps.d.ts +0 -37
- package/dist/permissionWireCaps.js +0 -37
- package/dist/postureKnob.d.ts +0 -71
- package/dist/postureKnob.js +0 -86
- package/dist/principalWire.d.ts +0 -17
- package/dist/principalWire.js +0 -17
- package/dist/printToolResultFrame.d.ts +0 -100
- package/dist/printToolResultFrame.js +0 -33
- package/dist/promptProfileWireCaps.d.ts +0 -13
- package/dist/promptProfileWireCaps.js +0 -13
- package/dist/readFacePosture.d.ts +0 -43
- package/dist/readFacePosture.js +0 -46
- package/dist/request/printNotification.d.ts +0 -20
- package/dist/request/printNotification.js +0 -55
- package/dist/request/taskRequest.d.ts +0 -249
- package/dist/request/taskRequest.js +6 -498
- package/dist/resumeRefusalCopy.d.ts +0 -136
- package/dist/resumeRefusalCopy.js +1 -117
- package/dist/retainBackgroundWireCaps.d.ts +0 -48
- package/dist/retainBackgroundWireCaps.js +0 -48
- package/dist/retryStatus.d.ts +2 -221
- package/dist/retryStatus.js +0 -107
- package/dist/rewindWireCaps.d.ts +0 -27
- package/dist/rewindWireCaps.js +0 -24
- package/dist/runCancelContext.d.ts +1 -20
- package/dist/runCancelContext.js +0 -34
- package/dist/runTerminal.d.ts +0 -273
- package/dist/runTerminal.js +0 -177
- package/dist/sandboxWire.d.ts +0 -38
- package/dist/sandboxWire.js +0 -82
- package/dist/scenarioWire.d.ts +0 -60
- package/dist/scenarioWire.js +0 -68
- package/dist/scratchpadWireCaps.d.ts +0 -11
- package/dist/scratchpadWireCaps.js +0 -32
- package/dist/sdkWireTransit.d.ts +0 -38
- package/dist/sdkWireTransit.js +0 -30
- package/dist/seam.d.ts +18 -853
- package/dist/seam.js +0 -52
- package/dist/seatContract.d.ts +0 -555
- package/dist/seatContract.js +5 -304
- package/dist/selfOrchestrationDenial.d.ts +0 -189
- package/dist/selfOrchestrationDenial.js +0 -162
- package/dist/selfOrchestrationWireCaps.d.ts +0 -38
- package/dist/selfOrchestrationWireCaps.js +0 -38
- package/dist/sessionMap.d.ts +0 -60
- package/dist/sessionMap.js +0 -37
- package/dist/sessionMemoryStatus.d.ts +11 -114
- package/dist/sessionMemoryStatus.js +0 -112
- package/dist/sessionModelLatch.d.ts +0 -29
- package/dist/sessionModelLatch.js +0 -40
- package/dist/sessionPolicyCapability.d.ts +3 -53
- package/dist/sessionPolicyCapability.js +0 -52
- package/dist/sessionSlot.d.ts +0 -26
- package/dist/sessionSlot.js +0 -17
- package/dist/skillsWireCaps.d.ts +0 -87
- package/dist/skillsWireCaps.js +0 -38
- package/dist/sqlEngineCapability.d.ts +0 -118
- package/dist/sqlEngineCapability.js +0 -134
- package/dist/sseIdleTriage.d.ts +0 -79
- package/dist/sseIdleTriage.js +1 -80
- package/dist/steering.d.ts +0 -54
- package/dist/steering.js +0 -63
- package/dist/subagent/engineCompactWire.d.ts +0 -34
- package/dist/subagent/engineCompactWire.js +4 -134
- package/dist/subagent/engineDelegatedPrompt.d.ts +0 -31
- package/dist/subagent/engineDelegatedPrompt.js +1 -103
- package/dist/subagent/engineRowStopGate.d.ts +0 -20
- package/dist/subagent/engineRowStopGate.js +0 -49
- package/dist/subagent/engineSubagentOutput.d.ts +0 -7
- package/dist/subagent/engineSubagentOutput.js +1 -51
- package/dist/subagent/engineSubagentResume.d.ts +2 -279
- package/dist/subagent/engineSubagentResume.js +2 -129
- package/dist/subagent/engineSubagentSteer.d.ts +0 -26
- package/dist/subagent/engineSubagentSteer.js +0 -63
- package/dist/subagent/engineSubagentTail.d.ts +0 -38
- package/dist/subagent/engineSubagentTail.js +2 -110
- package/dist/subagent/engineTaskHandleWire.d.ts +6 -67
- package/dist/subagent/engineTaskHandleWire.js +0 -126
- package/dist/subagent/subagentOwnerAbsence.d.ts +0 -2
- package/dist/subagent/subagentOwnerAbsence.js +0 -25
- package/dist/subagentContentStore.d.ts +3 -260
- package/dist/subagentContentStore.js +7 -540
- package/dist/systemReminderTag.d.ts +0 -49
- package/dist/systemReminderTag.js +0 -61
- package/dist/toolResult.d.ts +1 -211
- package/dist/toolResult.js +1 -358
- package/dist/toolRoster.d.ts +0 -140
- package/dist/toolRoster.js +0 -66
- package/dist/typePins.d.ts +0 -46
- package/dist/types/engineState.d.ts +0 -71
- package/dist/types/engineState.js +0 -16
- package/dist/ultracodeWireCaps.d.ts +0 -75
- package/dist/ultracodeWireCaps.js +0 -92
- package/dist/unrefTimer.d.ts +0 -27
- package/dist/webSearchBackendCapability.d.ts +0 -72
- package/dist/webSearchBackendCapability.js +0 -79
- package/dist/webSearchWireCaps.d.ts +0 -37
- package/dist/webSearchWireCaps.js +0 -34
- package/dist/websearch/searchProviderPresets.d.ts +0 -81
- package/dist/websearch/searchProviderPresets.js +0 -27
- package/dist/wireErrorTriage.d.ts +4 -160
- package/dist/wireErrorTriage.js +0 -171
- package/dist/wireRefusalCopy.d.ts +0 -28
- package/dist/wireRefusalCopy.js +0 -28
- package/dist/workflow.d.ts +0 -40
- package/dist/workflow.js +0 -52
- package/dist/workflowClient.d.ts +0 -122
- package/dist/workflowClient.js +8 -360
- package/dist/workflowMonitor.d.ts +2 -72
- package/dist/workflowMonitor.js +0 -26
- package/dist/writeProtectionCapability.d.ts +0 -112
- package/dist/writeProtectionCapability.js +0 -109
- package/docs/INTEGRATION-CLIENTS.md +30 -1
- package/package.json +1 -1
package/dist/adapt/textStream.js
CHANGED
|
@@ -1,60 +1,12 @@
|
|
|
1
1
|
import { chrome, mainLane, transcript, messageIdentityOf } from './ids.js';
|
|
2
2
|
import { estimateCjkTokens, FLUSH_INTERVAL_MS } from './wireShapes.js';
|
|
3
|
-
// L-318:六形判决单源(两条车道同吃;落账各归各层,见 textSegmentAuthority.ts 头注)。
|
|
4
3
|
import { resolveTextSegmentAuthority } from './textSegmentAuthority.js';
|
|
5
|
-
/**
|
|
6
|
-
* **段身份键**(CC-01,0.68.2)—— 打在 committed assistant **文本**转录行**顶层**的 `_sema_` 超集键。
|
|
7
|
-
*
|
|
8
|
-
* ── 为什么有它(归层修,不是新功能)──────────────────────────────────────────────────────────
|
|
9
|
-
* `text_segment_end` 到达时若已提交前缀自己也过期(`committedPrefixDiverged`),宿主要在**自己持有的**
|
|
10
|
-
* 转录里找出「这一段交出去的那一行」把它换掉。按字节相等去找会被**同后缀的独立行**冒充(实撞过);
|
|
11
|
-
* 按 uuid 找只证明「是这一行」,不证明「是这一段的」。⇒ 归属要两把钥匙:行身份(`uuid`)∧ **段身份**。
|
|
12
|
-
* 段身份此前由壳在自己的过境口铸(先壳后包);段的边界(开场 / 收口 / 轮换)本来就只有本模块知道,
|
|
13
|
-
* 铸点归这里,壳只读。
|
|
14
|
-
*
|
|
15
|
-
* ── 语义(一句话)────────────────────────────────────────────────────────────────────────────
|
|
16
|
-
* **一个身份覆盖「上一次段收口 → 本次段收口」之间过境的全部 committed 文本行**:流开场一个初值;
|
|
17
|
-
* idle-flush 提交的半段与终态提交的同段共享一个身份(归属正要这个);`text_segment_end` 臂处理完之后
|
|
18
|
-
* 轮换(帧上带的是轮换**前**的那一个,与它盖过的行同值);思考→回答边界**不**轮换;子流(带
|
|
19
|
-
* `parentToolCallId`)的段边界不轮换(它们不产 leader 事件,见臂头注)。
|
|
20
|
-
*
|
|
21
|
-
* ── 铸法与形 ──────────────────────────────────────────────────────────────────────────────
|
|
22
|
-
* 派生自本窗口的**第一帧**锚 + 窗口序号(`idOf(anchor, 'segment<n>')`)⇒ **同流重放同身份**
|
|
23
|
-
* (与 committed 行的 uuid 同一条确定性纪律;宿主的双跑对拍门靠它)。🔴 它是**转录格式**上的键,
|
|
24
|
-
* 不是 wire 键:只出现在宿主落盘的转录行上,不进 provider 请求(顶层自铸键不外溢,与
|
|
25
|
-
* `_sema_degraded` 同律)。🔴 **只盖尾块是 `text` 的 assistant 行**:只带 `tool_use` 的行永远不可能是
|
|
26
|
-
* 替换目标,盖了只是往转录里加噪;思考块同理。缺席 = 「这条不属于任何引擎段」,不是「属于某个未知段」。
|
|
27
|
-
* 🔴 **只加不减**:非本形消息一个字节不动。
|
|
28
|
-
*/
|
|
29
4
|
export const SEMA_SEGMENT_ID_KEY = '_sema_segment_id';
|
|
30
|
-
/**
|
|
31
|
-
* 件 A(#323 症状①)判据 (b) 的句末字符集 —— 中英文各一套,**闭集**(开集匹配会把「代码里的点」
|
|
32
|
-
* 之外的一切标点都当句末,等于没收紧)。换行单独在 {@link endsAtSentenceBoundary} 里判(段末)。
|
|
33
|
-
*/
|
|
34
5
|
const SENTENCE_END_CHARS = new Set(['。', '!', '?', '…', '.', '!', '?']);
|
|
35
|
-
/**
|
|
36
|
-
* 句末标点**之后**还可以合法跟着的收尾符(闭集):引号 / 括号 / markdown 强调与行内代码标记。
|
|
37
|
-
* 🔴 有它的理由(异源复审 finding 采纳):真句末很常见地**不以句末标点结尾** ——
|
|
38
|
-
* `他说:“完成了。”` 的末字符是右引号、`**Done.**` 的末字符是 `*`。不剥这一层,判据 (b) 会把
|
|
39
|
-
* 这些**真句末**永久判否(每一拍 idle 都返回 false),等于对带引号/强调的回复整条腿失效。
|
|
40
|
-
* 🔴 只剥**收尾**符,不做括号配对分析:未闭合的行内代码 `` `a.b `` 末字符是 `b`,本来就判否;
|
|
41
|
-
* 而 `` `a.b` `` 剥掉反引号后是 `b`,同样判否 —— 代码跨度里的点不会被误当句末。
|
|
42
|
-
*/
|
|
43
6
|
const SENTENCE_CLOSING_CHARS = new Set([
|
|
44
7
|
'"', "'", '”', '’', '』', '」', '》', '〉', '】', '〕', ')', ')', ']', ']', '}', '}', '*', '_', '~', '`',
|
|
45
8
|
]);
|
|
46
|
-
/** 收尾符最多剥这么多层 —— 剥的是收尾符,不是「一直回溯到找得着句号为止」。 */
|
|
47
9
|
const MAX_TRAILING_CLOSERS = 8;
|
|
48
|
-
/**
|
|
49
|
-
* 段尾是不是句末/段末边界(件 A 判据 (b))。
|
|
50
|
-
* 行末空格/制表符先剥掉再看最后一个字符 —— 流式 delta 常把 `". "` 拆成两拍,不剥就恒判否。
|
|
51
|
-
* 然后剥一层 {@link SENTENCE_CLOSING_CHARS} 收尾符,最后一次性判「换行(段末)∪ 句末标点」。
|
|
52
|
-
*
|
|
53
|
-
* 🔴 **换行判在剥尾之后**(异源复审第四轮 finding 采纳):换行检查若只做在剥尾**之前**,
|
|
54
|
-
* `Done.\n**`、整块围栏代码块(```` ```\nx\n``` ````)、`“完成了\n”` 这些**剥掉收尾符才露出换行**
|
|
55
|
-
* 的形会全部判否 —— 恰好是「已经写完一段」最常见的三种收尾,判否等于把它们永久押到工具边界/
|
|
56
|
-
* turn 收口。换行本身不在收尾符集里,所以「先剥后判」对「换行就在最外层」那些形是恒等的。
|
|
57
|
-
*/
|
|
58
10
|
function endsAtSentenceBoundary(s) {
|
|
59
11
|
let t = s.replace(/[ \t]+$/u, '');
|
|
60
12
|
if (t.length === 0)
|
|
@@ -69,101 +21,30 @@ function endsAtSentenceBoundary(s) {
|
|
|
69
21
|
return last === '\n' || last === '\r' || SENTENCE_END_CHARS.has(last);
|
|
70
22
|
}
|
|
71
23
|
export function createTextStream(ctx, idOf) {
|
|
72
|
-
// ── turn 级状态(cli generator 局部变量的等价;矩阵 §1.1 逐行对位)──────────────────────────
|
|
73
24
|
let answer = '';
|
|
74
25
|
let answerSegment = '';
|
|
75
26
|
let thinking = '';
|
|
76
27
|
let emittedAssistantText = false;
|
|
77
|
-
/** **当前这条 assistant 消息**已提交上屏的正文(补差判据的输入;与 `answer` 刻意分家,见接口注)。 */
|
|
78
28
|
let committedText = '';
|
|
79
|
-
/** 上一条**真有正文**的 assistant 消息在屏上的那段(见 lastCommittedAnswerText 头注)。 */
|
|
80
29
|
let previousCommittedText = '';
|
|
81
|
-
/**
|
|
82
|
-
* CC-16(0.71.0):**本段身份窗口里已提交的文本行**(正文 + 本包铸的 uuid,按序)—— 与思考面的
|
|
83
|
-
* `committedThinking`(CC-11)同律。写于 `emitAnswerSegment` 铸行那一拍;`replaceAnswerSegment` 用过即清;
|
|
84
|
-
* 窗口轮换(`rotateSegmentIdentity`)整只清。修前 `text_segment_end` 只带 `segmentId`,持有转录的端要自己跟踪
|
|
85
|
-
* 「本窗口过境了哪几条盖着该 id 的行」,窗口内 ≥2 条(两个工具卡)时端整发放弃 = 未脱敏字节留盘;包在铸行处
|
|
86
|
-
* 确知每一条,交全就不用端猜。常态段的定稿行在轮换**之后**才提交 ⇒ 天然属下一窗口、不在本列。
|
|
87
|
-
*/
|
|
88
30
|
let committedTextRows = [];
|
|
89
|
-
/** 消息序号(`beginAssistantMessage` 递增):行账按消息分组重建两本补差账用。 */
|
|
90
31
|
let messageSerial = 0;
|
|
91
32
|
let textPending = '';
|
|
92
33
|
let thinkingPending = '';
|
|
93
34
|
let textBlockOpen = false;
|
|
94
35
|
let thinkingBlockOpen = false;
|
|
95
36
|
let lastFlushAt = 0;
|
|
96
|
-
/**
|
|
97
|
-
* 件 A 判据 (a):**本段已经用掉 idle 的那一刀**。写于 `takeAnswerSegmentOnIdle` 真提交那一拍,
|
|
98
|
-
* 复位于 `takeAnswerSegment`(= 正常边界到达 ⇒ 重开新段)——**空段的正常边界也复位**:
|
|
99
|
-
* 「工具帧来过」本身就是重开新段的事实,与那一拍有没有散文可提交无关。
|
|
100
|
-
*/
|
|
101
37
|
let idleFlushUsedInSegment = false;
|
|
102
|
-
/**
|
|
103
|
-
* L-310:**当前引擎段**里已经 committed 上屏的那一截(idle-flush 的刀)。
|
|
104
|
-
*
|
|
105
|
-
* 🔴 与 `committedText` 刻意分家(两个量、两件事,别合并):`committedText` 记的是「**这条
|
|
106
|
-
* assistant 消息**屏上已经有了哪些字」(跨段累加,补差判据的输入);这一个记的是「**这一段**
|
|
107
|
-
* 有多少字节已经撤不回了」——它是权威段替换唯一能算出「尾段该换成什么」的量。
|
|
108
|
-
* 写于 `emitAnswerSegment`(提交本体,**只计当前段那一截**,不含 {@link segmentSealed});
|
|
109
|
-
* 归零于三处**段到此为止**的事实发生地:正常边界(`takeAnswerSegment`)、权威替换
|
|
110
|
-
* (`replaceAnswerSegment`)、新消息划界(`beginAssistantMessage`)。
|
|
111
|
-
* idle 入口**不**归零 —— 那正是「段还没完、只是先上屏半截」这件事本身。
|
|
112
|
-
*/
|
|
113
38
|
let segmentCommitted = '';
|
|
114
|
-
/**
|
|
115
|
-
* 🔴 **上一个包侧边界带走的那一截**(L-310 / 异源复审 finding①,0.68.1)。
|
|
116
|
-
*
|
|
117
|
-
* 存在的理由是一条**上游实测的时序**:openai 车道的 `text_end` 是在 `finalize()` 里 push 的
|
|
118
|
-
* (装机 core `dist/brain/openai.js` 的 `finalize` 真字节),而 `toolcall_end` 会先触发
|
|
119
|
-
* `executor.maybeAdmit`(`dist/engine/loop/agent-loop.js`)⇒ **工具卡先到、段边界后到**。
|
|
120
|
-
* 那一拍包侧的工具卡臂已经 `takeAnswerSegment()` 把卡前散文提交进**上一条** assistant 消息,
|
|
121
|
-
* 于是 `segmentCommitted` 与 `answerSegment` 双双为空 —— 若据此判「本包没经手过这一段」,
|
|
122
|
-
* 一段**未脱敏**的正文就会静静留在转录里、且三个分歧键一个都不发(宿主连纠正的机会都没有)。
|
|
123
|
-
* ⇒ 边界带走那一截时把它记在这里,迟到的 `text_end` 据它**算分歧、发信号**;
|
|
124
|
-
* 但**不铸任何消息**(那些字节在上一条消息里,在这里补一条只会落到工具卡**之后**)。
|
|
125
|
-
* 与 `previousCommittedText` 是同一条思路的两个量,刻意分开:那一个是「上一条消息的全部正文」
|
|
126
|
-
* (终答补差用),这一个是「上一个包侧边界带走的**本段**那一截」(分歧判据用)。
|
|
127
|
-
*/
|
|
128
39
|
let previousSegmentCommitted = '';
|
|
129
|
-
/**
|
|
130
|
-
* 🔴 **已由引擎明报收尾、但还没提交的段正文**(L-310 / 异源复审 finding②,0.68.1)。
|
|
131
|
-
*
|
|
132
|
-
* 病形(复审实抓):`delta(A) → text_end(A) → delta(B) → text_end(B)` 中间没有工具卡也没有
|
|
133
|
-
* idle 提交时,若替换只是把 `content` 写回 `answerSegment`,B 的 delta 会**接着往同一个缓冲里加**,
|
|
134
|
-
* 然后被 `contentB` 整段覆盖 —— **A 段的正文凭空消失**,而且 B 那一帧还会误报 `diverged`。
|
|
135
|
-
* 这条时序在 anthropic 车道是**常态**(装机 core `dist/brain/anthropic.js` 在
|
|
136
|
-
* `content_block_stop` 上逐块 push `text_end`,一条消息可以有多个 text 块)。
|
|
137
|
-
* ⇒ 替换把定稿正文移进本缓冲(「封存」),`answerSegment` 清空给下一段用;段提交本体交的是
|
|
138
|
-
* `segmentSealed + answerSegment`。分段行为**零改动**(整 turn 仍只提交一条 assistant 文本
|
|
139
|
-
* 消息,除非有工具卡/idle 边界)—— 撤 idle-flush 启发式仍是另一批的事。
|
|
140
|
-
*/
|
|
141
40
|
let segmentSealed = '';
|
|
142
|
-
/** T29 攒批节拍:宿主策略优先(桌面/web 可传 16ms 对齐 CC 桌面端),缺席=207 CLI 口径 100ms。 */
|
|
143
41
|
const flushEveryMs = typeof ctx.coalesceIntervalMs === 'number' && ctx.coalesceIntervalMs >= 0
|
|
144
42
|
? ctx.coalesceIntervalMs
|
|
145
43
|
: FLUSH_INTERVAL_MS;
|
|
146
|
-
/** committed 消息的 id 锚 —— 该段/该思考块的**第一帧**(重放确定性:同流同 id)。 */
|
|
147
44
|
let segmentAnchor = null;
|
|
148
45
|
let thinkingAnchor = null;
|
|
149
|
-
/**
|
|
150
|
-
* CC-02:**当前窗口里最近一次整块提交的思考行**(正文 + 本包铸的 uuid)—— `reasoning_end` 迟到时
|
|
151
|
-
* (`text_delta` 先触发了思考→回答边界的提交)唯一能拿来算分歧、指认行的对照物。
|
|
152
|
-
* 写于 `takeThinking` 提交那一拍;清于 `replaceThinkingSegment` 用过之后、以及下一块思考开始
|
|
153
|
-
* (`feedThinking` 首条)—— 上一块的提交不是这一块的对照物。
|
|
154
|
-
*/
|
|
155
46
|
let committedThinking = [];
|
|
156
|
-
/**
|
|
157
|
-
* CC-14(0.69.2):活体思考块已被 `reasoning_end` **定稿**(形 (a) 整块换 / 形 (b1) 尾段换)但还没提交。
|
|
158
|
-
* 段账按「行所属的引擎段」记,不按「提交时间落在哪一段」:定稿块迟交(tool_use / 下一段 text_delta 才提交)时
|
|
159
|
-
* **不**登进下一段的 `committedThinking` —— 修前登进去,宿主按义务把上一段定稿行换成下一段权威、其余行清空,
|
|
160
|
-
* 上一段定稿内容丢失而披露仍说成功(cli 1.0.115 合并树对抗复审实抓)。
|
|
161
|
-
*/
|
|
162
47
|
let thinkingSettled = false;
|
|
163
|
-
/**
|
|
164
|
-
* 段身份窗口(见 {@link SEMA_SEGMENT_ID_KEY} 头注):窗口的第一帧锚 + 序号 + 派生结果缓存。
|
|
165
|
-
* 🔴 缓存不是优化:锚缺席那一形派生落到 `ctx.uuid()`,不缓存的话同一窗口两次读会得到两个身份。
|
|
166
|
-
*/
|
|
167
48
|
let segmentWindowAnchor = null;
|
|
168
49
|
let segmentWindowSerial = 0;
|
|
169
50
|
let segmentIdCache = null;
|
|
@@ -172,44 +53,33 @@ export function createTextStream(ctx, idOf) {
|
|
|
172
53
|
segmentIdCache = idOf(segmentWindowAnchor ?? {}, `segment${segmentWindowSerial}`);
|
|
173
54
|
return segmentIdCache;
|
|
174
55
|
};
|
|
175
|
-
/** 提交累积的思考块(cli takeThinking:committed 形 + 关活体块 + 收活动行)。 */
|
|
176
56
|
function* takeThinking() {
|
|
177
57
|
if (thinking.length === 0)
|
|
178
58
|
return;
|
|
179
59
|
const anchor = thinkingAnchor ?? {};
|
|
180
60
|
const msg = {
|
|
181
61
|
type: 'assistant',
|
|
182
|
-
// L-215③:上游投影器铸在 durable 内容帧上的两个身份位在这里**接力**,不是重铸
|
|
183
|
-
// (本构造点是重建 `{role,content}` 的,不接就原地丢掉;见 `ids.ts` 的 messageIdentityOf)。
|
|
184
62
|
message: { role: 'assistant', content: [{ type: 'thinking', thinking }], ...messageIdentityOf(anchor, ctx) },
|
|
185
63
|
uuid: idOf(anchor, 'thinking'),
|
|
186
64
|
session_id: ctx.sessionId,
|
|
187
65
|
parent_tool_use_id: null,
|
|
188
66
|
};
|
|
189
|
-
// CC-11(0.69.1):**按序累积**,不覆盖 —— 一段推理可以跨工具卡(openai 车道 finalize 时序),每一块提交都是
|
|
190
|
-
// 这一段的一部分;`reasoning_end` 到达时把它们全部交出去(`committedUuids`),宿主才有整段的归属。
|
|
191
|
-
// CC-14:定稿块属上一段,不登本段账(它的权威已经在正文里)。
|
|
192
67
|
if (!thinkingSettled)
|
|
193
68
|
committedThinking.push({ text: thinking, uuid: msg.uuid });
|
|
194
69
|
thinkingSettled = false;
|
|
195
70
|
thinking = '';
|
|
196
71
|
thinkingAnchor = null;
|
|
197
72
|
thinkingBlockOpen = false;
|
|
198
|
-
// P2d:活体 "∴ Thinking…" 行在 committed 块落地的**同一刻**收掉(先收行再上消息,cli 同序)
|
|
199
73
|
yield chrome({ kind: 'thinking_activity', laneProof: mainLane(), active: false });
|
|
200
74
|
yield transcript(msg, ctx.now());
|
|
201
75
|
}
|
|
202
|
-
/** 段提交的**唯一本体**(两个入口 `takeAnswerSegment` / `takeAnswerSegmentOnIdle` 共用;
|
|
203
|
-
* 两个入口的差别只在准入判据,提交出来的消息一个字节都不分叉)。 */
|
|
204
76
|
function* emitAnswerSegment() {
|
|
205
|
-
// L-310:提交的是「已封存的定稿段 + 还在攒的当前段」。分段行为零改动 —— 封存只换字节,不切消息。
|
|
206
77
|
const body = segmentSealed + answerSegment;
|
|
207
78
|
if (body.length === 0)
|
|
208
79
|
return;
|
|
209
80
|
const anchor = segmentAnchor ?? {};
|
|
210
81
|
const msg = {
|
|
211
82
|
type: 'assistant',
|
|
212
|
-
// L-215③:同 takeThinking —— 身份位接力(帧优先、ctx 兜底;两位都读不出就一个都不铸)。
|
|
213
83
|
message: { role: 'assistant', content: [{ type: 'text', text: body }], ...messageIdentityOf(anchor, ctx) },
|
|
214
84
|
uuid: idOf(anchor, 'text'),
|
|
215
85
|
session_id: ctx.sessionId,
|
|
@@ -217,14 +87,7 @@ export function createTextStream(ctx, idOf) {
|
|
|
217
87
|
};
|
|
218
88
|
const committedTextBeforeRow = committedText;
|
|
219
89
|
committedText += body;
|
|
220
|
-
// L-310:🔴 **只有当前段那一截**算进「本段已提交前缀」—— 已封存的定稿段属于**上一个**引擎段,
|
|
221
|
-
// 把它算进来会让下一帧 `text_end` 拿一个跨段的前缀去比 `content`,当场误报前缀分歧。
|
|
222
90
|
segmentCommitted += answerSegment;
|
|
223
|
-
// CC-16:本窗口行账 —— 与上一行的前缀账**同律**:只有携带本窗口字节(`answerSegment` 那截)的行才登记;
|
|
224
|
-
// 正文全是已封存定稿段(`segmentSealed`)的行属**上一个**引擎段,登进来会让下一帧 `text_end` 把它当
|
|
225
|
-
// 本窗口的已提交行去换 —— 那是思考面 CC-14 的同形病(定稿迟交行误登下一段账)。
|
|
226
|
-
// `sealedPrefix` = 该行里属上一段的定稿那截(封存只换字节不切消息 ⇒ 混合行);端写回时必须保住它。
|
|
227
|
-
// `msgTextBefore` = 该行提交前所属消息已有的正文(窗口之外独立提交的定稿前缀也在里面),写回后按消息重建账本用。
|
|
228
91
|
if (answerSegment.length > 0)
|
|
229
92
|
committedTextRows.push({ text: body, uuid: msg.uuid, sealedPrefix: segmentSealed, msgSerial: messageSerial, msgTextBefore: committedTextBeforeRow });
|
|
230
93
|
segmentSealed = '';
|
|
@@ -234,21 +97,13 @@ export function createTextStream(ctx, idOf) {
|
|
|
234
97
|
textBlockOpen = false;
|
|
235
98
|
yield transcript(msg, ctx.now());
|
|
236
99
|
}
|
|
237
|
-
/** 提交累积的文本段(cli takeAnswerSegment:#27 段序铁律——工具卡前/turn 末各 flush 一次)。
|
|
238
|
-
* 🔴 **正常边界**入口:除了复位件 A 的 idle 配额,行为与拆分前逐字一致(零改动面)。 */
|
|
239
100
|
function* takeAnswerSegment() {
|
|
240
101
|
idleFlushUsedInSegment = false;
|
|
241
102
|
yield* emitAnswerSegment();
|
|
242
|
-
// L-310:正常边界带走了当前段的那一截 ⇒ 本段前缀账归零(下一段的替换不许把上一段的字节
|
|
243
|
-
// 算成自己的前缀),但**记进** `previousSegmentCommitted` —— 这是包侧边界,不是引擎段边界:
|
|
244
|
-
// openai 车道的 `text_end` 会在这之后才到,那一拍还得拿它算分歧(见 replaceAnswerSegment)。
|
|
245
103
|
previousSegmentCommitted += segmentCommitted;
|
|
246
104
|
segmentCommitted = '';
|
|
247
105
|
}
|
|
248
|
-
/** 件 A:IDLE-FLUSH 专用入口(准入 = 每段一刀 + 句末/段末边界;两条都过才提交)。 */
|
|
249
106
|
function* takeAnswerSegmentOnIdle() {
|
|
250
|
-
// L-310:准入判的是**提交本体真要交的那份**(封存段 + 当前段),不是只看当前段 ——
|
|
251
|
-
// 否则「定稿段已封存、当前段还空着」那一拍会被判成没东西可交,把已定稿的正文继续押着。
|
|
252
107
|
const body = segmentSealed + answerSegment;
|
|
253
108
|
if (body.length === 0)
|
|
254
109
|
return;
|
|
@@ -259,7 +114,6 @@ export function createTextStream(ctx, idOf) {
|
|
|
259
114
|
idleFlushUsedInSegment = true;
|
|
260
115
|
yield* emitAnswerSegment();
|
|
261
116
|
}
|
|
262
|
-
/** 合并后的活体增量下泄(cli drainLive:思考先于文本 = 持久臂序)。 */
|
|
263
117
|
function* drainLive() {
|
|
264
118
|
if (thinkingPending.length > 0) {
|
|
265
119
|
const opening = !thinkingBlockOpen;
|
|
@@ -277,9 +131,6 @@ export function createTextStream(ctx, idOf) {
|
|
|
277
131
|
if (textPending.length > 0) {
|
|
278
132
|
const opening = !textBlockOpen;
|
|
279
133
|
textBlockOpen = true;
|
|
280
|
-
// B3:cli 的 `SEMA_STREAM_PROBE` 文件探针换成 ctx.probe 口(体检 #5 同款用途:Ink 挂载后
|
|
281
|
-
// console 被吞,harness 只能靠这条证明「引擎是**逐 token 增量**到的」而不是整块一次性 dump)。
|
|
282
|
-
// 载荷格式与 cli 逐字同形,只把 Date.now() 换成 ctx.now()(注入时钟纪律)。
|
|
283
134
|
ctx.probe?.('stream', `${ctx.now()} text_flush len=${textPending.length}`);
|
|
284
135
|
yield chrome({
|
|
285
136
|
kind: 'stream_delta',
|
|
@@ -294,12 +145,10 @@ export function createTextStream(ctx, idOf) {
|
|
|
294
145
|
}
|
|
295
146
|
return {
|
|
296
147
|
*feedText(delta, frame) {
|
|
297
|
-
// MOD-1 思考→回答边界:回答一起头就把思考块 committed 上屏(它推理的内容之前)。
|
|
298
148
|
if (thinking.length > 0 || thinkingPending.length > 0) {
|
|
299
149
|
yield* drainLive();
|
|
300
150
|
yield* takeThinking();
|
|
301
151
|
}
|
|
302
|
-
// L-310:已封存的定稿段也算「这条消息已经开了头」⇒ 锚不重置(同流重放同 id)。
|
|
303
152
|
if (answerSegment.length === 0 && segmentSealed.length === 0)
|
|
304
153
|
segmentAnchor = frame;
|
|
305
154
|
if (segmentWindowAnchor === null)
|
|
@@ -311,8 +160,6 @@ export function createTextStream(ctx, idOf) {
|
|
|
311
160
|
*feedThinking(delta, frame) {
|
|
312
161
|
if (segmentWindowAnchor === null)
|
|
313
162
|
segmentWindowAnchor = frame;
|
|
314
|
-
// CC-14:定稿块还押着、下一段增量直接叠上来(中间无提交边界)⇒ 先按它自己的段提交,新块另起;
|
|
315
|
-
// 两段推理绝不同行(同行 = 下一段 end 的归属会把上一段定稿一并换掉)。
|
|
316
163
|
if (thinkingSettled) {
|
|
317
164
|
if (thinking.length > 0) {
|
|
318
165
|
yield* drainLive();
|
|
@@ -324,10 +171,6 @@ export function createTextStream(ctx, idOf) {
|
|
|
324
171
|
}
|
|
325
172
|
if (thinking.length === 0) {
|
|
326
173
|
thinkingAnchor = frame;
|
|
327
|
-
// CC-11:新一块开始**不**清对照物(修前这里清了 —— 跨工具卡的推理段只剩末条归属,cli 接入回执 ② 实抓);
|
|
328
|
-
// 对照物只在 `reasoning_end` 用过之后清(段界由引擎说了算),turn 结束整只丢,天然有界。
|
|
329
|
-
// P2d:elapsed 锚在**首条** leader 推理增量(token 累计由 stream_delta.estimatedTokens
|
|
330
|
-
// 承载,宿主自加;>30s 无增量的 stall 提示同样由宿主按增量时间戳判)。
|
|
331
174
|
yield chrome({ kind: 'thinking_activity', laneProof: mainLane(), active: true });
|
|
332
175
|
}
|
|
333
176
|
thinking += delta;
|
|
@@ -339,28 +182,7 @@ export function createTextStream(ctx, idOf) {
|
|
|
339
182
|
takeAnswerSegmentOnIdle,
|
|
340
183
|
replaceAnswerSegment: (content, anchor) => {
|
|
341
184
|
const prevSegment = answerSegment;
|
|
342
|
-
/**
|
|
343
|
-
* 本段**已经撤不回**的那一截 = 包侧边界带走的(可能跨了工具卡 / 消息划界,见
|
|
344
|
-
* {@link previousSegmentCommitted})+ 本消息内 idle-flush 掉的。
|
|
345
|
-
* 🔴 **两本账必须相加,不是二选一**(异源对抗复审轮二 finding① 实抓):修前只在「当前缓冲
|
|
346
|
-
* 全空」时才去读前一本,于是 `delta(含凭据) → 工具卡 → 同段后续 delta → text_end` 这条
|
|
347
|
-
* **openai 车道真实交错**(brain 持续累加文本直到 `finalize`,而 streamingToolExecution
|
|
348
|
-
* 允许工具先执行)上,卡前那截明文**不算进前缀** ⇒ 两个前缀键双双缺席、旧明文消息留存,
|
|
349
|
-
* 而权威全文又被完整提交一次(同一段话上屏两遍 + 明文没人清)。实测复现过。
|
|
350
|
-
*/
|
|
351
185
|
const livePrefix = previousSegmentCommitted + segmentCommitted;
|
|
352
|
-
/**
|
|
353
|
-
* 🔴 **判决单源**(L-318,0.68.2):六形判据整只让位给 `adapt/textSegmentAuthority.ts` 的
|
|
354
|
-
* {@link resolveTextSegmentAuthority} —— 与 `-p` 形车道(宿主的 CC stdout 投影器)吃的是
|
|
355
|
-
* **同一只**。修前这里是本包这一份,壳里另有逐形对照的第二份(cli 1.0.114 B-122 热修),
|
|
356
|
-
* 上游改口时两边各走各的。判据语义**逐字未变**:
|
|
357
|
-
* · 形 (f)「本层一个字节都没经手」⇒ `form: 'untouched'`,三位全报否;
|
|
358
|
-
* · `diverged` = 缝出来的那一段 ≠ 权威全文;
|
|
359
|
-
* · `committedPrefixLen` = 已撤不回那一截的 UTF-16 长度;
|
|
360
|
-
* · `committedPrefixDiverged` 锚 `content.startsWith(前缀)`(不锚「有没有 flush 过」)。
|
|
361
|
-
* **落账仍归本模块**:下面的 handOffOnly / 活体尾巴重算 / 封存 / 补差账同步,一行未动
|
|
362
|
-
* (两条车道的账本形状不同,理由见 textSegmentAuthority.ts 头注「判决与落账刻意分家」)。
|
|
363
|
-
*/
|
|
364
186
|
const verdict = resolveTextSegmentAuthority(content, {
|
|
365
187
|
committedPrefix: livePrefix,
|
|
366
188
|
openSegment: prevSegment,
|
|
@@ -372,17 +194,11 @@ export function createTextStream(ctx, idOf) {
|
|
|
372
194
|
const diverged = verdict.diverged;
|
|
373
195
|
const committedPrefixLen = verdict.committedPrefixLen;
|
|
374
196
|
const committedPrefixDiverged = verdict.committedPrefixDiverged;
|
|
375
|
-
// CC-16:本窗口已提交行的归属一次交全(用过即清;轮换也清)。`[]` 是正面事实,不是缺席。
|
|
376
197
|
const rowsAll = committedTextRows;
|
|
377
198
|
committedTextRows = [];
|
|
378
|
-
// B-133 / CC-29(0.71.2):行 uuid 由 wire 帧 uuid 派生,只有上游帧 uuid 重复才会让两条行同 uuid;端按 uuid 找行,
|
|
379
|
-
// 重复 = 归属**说不出** ⇒ 整键缺席(形 f),且不交 committedRows、不清尾巴不同步账(退回零经手行为)。
|
|
380
|
-
// 不去重、不取首:任一种都是替上游把「两条行一个身份」这件事湮灭掉。
|
|
381
199
|
const uuidsUnique = new Set(rowsAll.map((r) => r.uuid)).size === rowsAll.length;
|
|
382
200
|
const rows = uuidsUnique ? rowsAll : [];
|
|
383
201
|
const rowUuids = rows.map((r) => r.uuid);
|
|
384
|
-
// 只有「已提交前缀自己也过期」这一形端才有东西要写回:首行 = 前段定稿前缀 + content(混合行的上一段正文保住),
|
|
385
|
-
// 其余行清空(它们的字节全在 content 里)。b1 形已提交行本来就对,不给;形 (a) 零行,不给。
|
|
386
202
|
const committedRowsOut = committedPrefixDiverged && rows.length > 0
|
|
387
203
|
? rows.map((r, i) => ({ uuid: r.uuid, text: i === 0 ? r.sealedPrefix + content : r.sealedPrefix }))
|
|
388
204
|
: undefined;
|
|
@@ -393,54 +209,12 @@ export function createTextStream(ctx, idOf) {
|
|
|
393
209
|
...(committedRowsOut !== undefined ? { committedRows: committedRowsOut } : {}),
|
|
394
210
|
}
|
|
395
211
|
: {};
|
|
396
|
-
/**
|
|
397
|
-
* 🔴 **段跨过包侧边界、而且已提交那截自己也过期** ⇒ 本模块**一个字节都不动**(只发信号)。
|
|
398
|
-
*
|
|
399
|
-
* 理由是**不许把一条既有行为改坏**(异源对抗复审轮五 finding② 实抓,基线对照确认):这一形下
|
|
400
|
-
* 那一截的字节在**别的** assistant 消息里,而本模块能动的只有当前这条 —— 清掉未提交尾段会让
|
|
401
|
-
* `lastCommittedAnswerText` 回退到上一条,`result` 臂据它落第④臂**补吐一整段**;而 e4cd371
|
|
402
|
-
* 基线上同一条时序只是提交那截尾段 + 落第⑤臂报一行分岔(不补吐)。⇒ 清空在这里是**新增**的
|
|
403
|
-
* 重复转录路径,不是「更安全」。
|
|
404
|
-
* ⇒ 分界线一句话:**整段都在自己手里(同一条消息内)时才改自己交的字节;段一旦跨过包侧边界,
|
|
405
|
-
* 就只发信号、不动任何既有行为**。宿主照三个键把那截过期前缀换掉,其余与 0.68.0 逐字相同。
|
|
406
|
-
*/
|
|
407
212
|
const handOffOnly = committedPrefixDiverged && previousSegmentCommitted.length > 0;
|
|
408
213
|
if (handOffOnly) {
|
|
409
|
-
// ── CC-17(0.70.1,cli 接入回执两形;整链实测复现)────────────────────────────────────
|
|
410
|
-
// 🔴 「只发信号」曾被写成「两本账一行都不动」,那是**漏账**不是克制:权威全文这一刻已经
|
|
411
|
-
// 交给宿主去换了,包却还按「屏上只有那截原始前缀」继续算,于是
|
|
412
|
-
// 形一(卡后有增量):`answerSegment` 里那截**原始未脱敏**尾段照常被 `takeAnswerSegment`
|
|
413
|
-
// 提交上屏落盘 —— 它属于一个已经作废的段,宿主换的是**另一条**消息,没人会来清它;
|
|
414
|
-
// 形二(卡后零增量):`lastCommittedAnswerText` 回退到上一条消息的原始正文,`result` 臂
|
|
415
|
-
// 的第④臂据此把尾段当「屏上缺的后缀」再吐一遍(终帧未脱敏时连字节都残留)。
|
|
416
|
-
// ⇒ 同步两本补差账(前缀落在哪本就换哪本,`endsWith` 守卫不匹配就不动,与非跨界形逐字同律)
|
|
417
|
-
// + 清掉本段还没交出去的那一截。**仍然一个字节都不新交**(不铸任何消息):那些字节在别的
|
|
418
|
-
// 消息里,宿主按三键换;本分支改的只是「包自己以为屏上有什么」。
|
|
419
|
-
// 🔴 旧注释(异源复审轮五 finding②)说「清未提交尾段会让 `lastCommittedAnswerText` 回退 ⇒
|
|
420
|
-
// 第④臂补吐一整段」—— 那个后果的**前提正是账没同步**;上面一行同步之后前提消失。这句话
|
|
421
|
-
// 不是推理,是判据:`run-text-segment-authority-test.mjs` 的 Y4 就跑那条时序。
|
|
422
|
-
// 🔴 **只在「宿主确定会把某一整条换成 `content`」时才认账**(收窄,实测逼出):这两本账是
|
|
423
|
-
// **按消息**记的,而 `livePrefix` 可能跨了**多条**消息(两个工具卡 ⇒ 段身份覆盖多行)。
|
|
424
|
-
// 那一形下宿主自己也换不了(段身份对上多行 = 归属歧义,端按「证明不了就不动手」整发放弃),
|
|
425
|
-
// 包若照样清账清尾段,`lastCommittedAnswerText` 会回退到中间那条,`result` 臂反而从第⑤臂
|
|
426
|
-
// (只报分岔)掉进第④臂(补吐一整段)—— 那正是轮五 finding② 抓到的**新增重复转录路径**,
|
|
427
|
-
// 实测确认过(D35/D36 两格钉的就是它)。⇒ 对不上就退回 0.68.0 行为:只发信号,一个字节不动。
|
|
428
|
-
// 多行跨界那一形的正解是把整段归属交全(`committedUuids[]`,CC-16),不是包单方面清。
|
|
429
|
-
// 🔴 CC-16 `committedRows` 起(异源对抗复审第 2 轮 finding①):多行跨界的归属**已经交全**、端按行写回
|
|
430
|
-
// (首行 = 前缀 + content、其余行空)⇒ 上面那句「对不上就一个字节不动」的前提消失 —— 再把本段
|
|
431
|
-
// 原始尾巴提交成又一条,就是重复正文 + 未脱敏残留。所以 `syncedBook === null` 而 `committedRows`
|
|
432
|
-
// 已交出时,两本账按**端写回后的屏**同步(最后一行 = 当前消息那本,首行 = 上一条真有正文的那本),
|
|
433
|
-
// 尾巴照清;`result` 臂拿到的 `lastCommittedAnswerText` 就是权威全文,落第③格不补吐(Z9 钉)。
|
|
434
|
-
// 🔴 第 4 轮 finding①:`committedRows` 在场时**一律**按消息分组重建(行归属确定,零启发式);`endsWith` 快捷分支只在
|
|
435
|
-
// 零行(没有行归属可用)时回退 —— 重复正文(两条消息都是「Intro. 」)会让 endsWith 误命中、跳过重建,消息二那本账没清 ⇒ 终帧再补一次。
|
|
436
214
|
let booksSynced = false;
|
|
437
215
|
if (!uuidsUnique) {
|
|
438
|
-
// B-133 / CC-29:重复 uuid ⇒ 归属说不出 ⇒ **一个字节不动**:既不进分组重建,也不走 endsWith 回退(复审实抓:回退会把
|
|
439
|
-
// previousCommittedText 同步成从未提交的权威全文,再把尾段清掉 —— 端按缺席契约零写回,尾段就此消失)。
|
|
440
216
|
}
|
|
441
217
|
else if (committedRowsOut !== undefined) {
|
|
442
|
-
// 按**消息**重建(第 3 轮 finding②):一条消息的正文 = 窗口之外已独立提交的那截(`msgTextBefore`)+ 该消息里
|
|
443
|
-
// 各行写回后的正文;只按首行写回正文重建会丢掉独立提交的定稿前缀,终帧再落第⑤臂误报分岔。
|
|
444
218
|
const groups = new Map();
|
|
445
219
|
rows.forEach((r, i) => {
|
|
446
220
|
const g = groups.get(r.msgSerial) ?? { before: r.msgTextBefore, parts: [] };
|
|
@@ -458,8 +232,7 @@ export function createTextStream(ctx, idOf) {
|
|
|
458
232
|
if (txt.length > 0)
|
|
459
233
|
lastNonEmpty = txt;
|
|
460
234
|
}
|
|
461
|
-
|
|
462
|
-
if (!currentTouched && committedText.length > 0) { /* 保持 */ }
|
|
235
|
+
if (!currentTouched && committedText.length > 0) { }
|
|
463
236
|
if (committedText.length === 0 && lastNonEmpty.length > 0)
|
|
464
237
|
previousCommittedText = lastNonEmpty;
|
|
465
238
|
booksSynced = true;
|
|
@@ -481,8 +254,6 @@ export function createTextStream(ctx, idOf) {
|
|
|
481
254
|
answer = answer.slice(0, answer.length - liveSegment.length) + content;
|
|
482
255
|
}
|
|
483
256
|
if (booksSynced) {
|
|
484
|
-
// 活体面:本段还押着没吐的那一截也作废(`textPending` 是段缓冲的后缀,前面那截 `carry`
|
|
485
|
-
// 属于上一段,与本次替换无关 ⇒ 原样留)。
|
|
486
257
|
const staleTailLen = Math.min(textPending.length, prevSegment.length);
|
|
487
258
|
textPending = textPending.slice(0, textPending.length - staleTailLen);
|
|
488
259
|
answerSegment = '';
|
|
@@ -492,74 +263,37 @@ export function createTextStream(ctx, idOf) {
|
|
|
492
263
|
idleFlushUsedInSegment = false;
|
|
493
264
|
return { diverged, committedPrefixLen, committedPrefixDiverged, ...attribution };
|
|
494
265
|
}
|
|
495
|
-
// ── ① 活体面:已泄出去的那一截撤不回 ⇒ 尾巴按替换后的段重算(判据见接口注「活体面」段)──
|
|
496
|
-
// `textPending` 是段缓冲的**后缀**;工具卡边界只提交不 drain,所以它也可能还押着**上一段**
|
|
497
|
-
// 的尾巴(那一截与本次替换无关,原样留着)。
|
|
498
266
|
const segTailLen = Math.min(textPending.length, prevSegment.length);
|
|
499
267
|
const carry = textPending.slice(0, textPending.length - segTailLen);
|
|
500
268
|
const emittedForSegment = livePrefix + prevSegment.slice(0, prevSegment.length - segTailLen);
|
|
501
269
|
textPending = content.startsWith(emittedForSegment)
|
|
502
270
|
? carry + content.slice(emittedForSegment.length)
|
|
503
271
|
: carry;
|
|
504
|
-
// ── ② 转录面:**封存**这一段的定稿正文,`answerSegment` 清空给下一段用 ──────────────────
|
|
505
|
-
// 🔴 清空是轮一 finding② 的修复本体:不清空的话,下一段的 delta 会接着往同一个缓冲里加,
|
|
506
|
-
// 然后被下一帧的 `content` 整段覆盖 —— 上一段的正文凭空消失(anthropic 车道逐块发
|
|
507
|
-
// `text_end`,这条时序是常态)。封存**不切消息**:段提交本体交的是 `sealed + segment`。
|
|
508
|
-
// 🔴 `committedPrefixDiverged` 那一形**一个字节都不交**(统一规则,见接口注):已提交的
|
|
509
|
-
// 那截撤不回,而切片拼不出 `content` —— 再补一条就是同一段话上屏两遍;该段唯一算数的
|
|
510
|
-
// 那一份在帧上,由宿主按 `committedPrefixLen` 指的那一截换掉(单位见回执头注)。
|
|
511
272
|
if (committedPrefixDiverged) {
|
|
512
|
-
// 🔴 **同步终答补差账 —— 但只在「整截都在当前这条消息里」那一形**(轮三 finding② 采纳,
|
|
513
|
-
// 轮四 finding①② 收窄)。这一形下本包不交正文,而屏上那一段在宿主照契约换过之后**就是**
|
|
514
|
-
// `content`;补差账若还留着旧的那一份,`result` 臂会把权威全文当成「屏上缺的后缀」
|
|
515
|
-
// 再渲一遍(第④臂),正好违反三处文案承诺的「不再交正文」。
|
|
516
|
-
//
|
|
517
|
-
// 🔴 **为什么只同步这一形**(轮四两条 finding 的根因,记明免得下一棒又去「补全」它):
|
|
518
|
-
// 段跨过包侧边界(工具卡 / 消息划界)时,这一截的字节落在**别的** assistant 消息里,而
|
|
519
|
-
// `committedText` / `previousCommittedText` 是**按消息**记的两本账 —— 把 `content` 往当前
|
|
520
|
-
// 这本账上写,就等于把上一条消息的正文算进当前这条:轮四实测 ① 迟到边界那一形会让随后
|
|
521
|
-
// 正常的 B 段被误报 `result_text_diverged`、甚至把该补的后缀压掉;② 同段跨两张卡时
|
|
522
|
-
// `previousCommittedText` 只留得下最后一条,守卫直接不成立、同步静默跳过。
|
|
523
|
-
// ⇒ 跨消息那几形**不碰账**。代价如实认领:那里的补差基线与「宿主换过之后的屏」对不齐,
|
|
524
|
-
// `result` 可能落第④臂补一截或落第⑤臂报一行 `result_text_diverged` —— 而这两者
|
|
525
|
-
// **都是本批之前就有的行为**(主树 0.68.0 上同一条时序实测同形:卡后有散文时
|
|
526
|
-
// `lastCommittedAnswerText` 取的就是卡**之后**那一条,终帧却是整条消息的全文)。
|
|
527
|
-
// 根因是「包按自己的边界切消息、引擎按 content block 切段」这两套边界对不齐,根治 =
|
|
528
|
-
// 「每个引擎段各自一条 committed 消息」(= CC 原生做法),那是分段行为改动,单独走。
|
|
529
273
|
if (committedText.endsWith(livePrefix)) {
|
|
530
274
|
committedText = committedText.slice(0, committedText.length - livePrefix.length) + content;
|
|
531
275
|
}
|
|
532
276
|
}
|
|
533
277
|
else {
|
|
534
|
-
// L-318:尾段切片也走判决那一份(`content.slice(committedPrefixLen)` 逐字等价),
|
|
535
|
-
// 免得「怎么切」这件事在两条车道上各留一个算式。
|
|
536
278
|
segmentSealed += verdict.tail;
|
|
537
279
|
}
|
|
538
280
|
answerSegment = '';
|
|
539
|
-
// ── ③ `answer`(D8 调试行的长度读位)跟着换尾 —— 只在尾巴真对得上时换 ──────────────────
|
|
540
|
-
// `appendAnswer`(durable 整条腿)会往同一个累加器里加字,那一形下本段已经不是它的后缀;
|
|
541
|
-
// 猜着改一个诊断计数器比让它原样更坏,所以对不上就不动(它只喂 `answerLen=` 那一行)。
|
|
542
281
|
if (answer.endsWith(liveSegment)) {
|
|
543
282
|
answer = answer.slice(0, answer.length - liveSegment.length) + content;
|
|
544
283
|
}
|
|
545
|
-
// 段锚缺席(整段已被 idle 提交光、或整段零 delta)才用本帧兜底 —— 在场**不覆盖**,
|
|
546
|
-
// 否则同一条流重放两次会拿到两个不同的 committed 消息 id(replay-id 不变量)。
|
|
547
284
|
if (segmentAnchor === null && anchor !== undefined)
|
|
548
285
|
segmentAnchor = anchor;
|
|
549
|
-
// ── ④ 段账收口:这一段由引擎明说已经写完 ⇒ 两本前缀账都归零、idle 配额重开 ──────────────
|
|
550
286
|
segmentCommitted = '';
|
|
551
287
|
previousSegmentCommitted = '';
|
|
552
288
|
idleFlushUsedInSegment = false;
|
|
553
289
|
return { diverged, committedPrefixLen, committedPrefixDiverged, ...attribution };
|
|
554
290
|
},
|
|
555
291
|
hasPendingContent: () => thinking.length > 0 ||
|
|
556
|
-
// L-310:已封存的定稿段同样是「有已生成未提交的内容」(不算进来会让它一直押到 turn 收口)。
|
|
557
292
|
segmentSealed.length > 0 ||
|
|
558
293
|
answerSegment.length > 0 ||
|
|
559
294
|
thinkingPending.length > 0 ||
|
|
560
295
|
textPending.length > 0,
|
|
561
296
|
*maybeFlushOnBeat(nowMs) {
|
|
562
|
-
// COALESCER 节拍:一个间隔至多一次 flush(同步 SSE 突发先攒着,过闸再一次泄干)。
|
|
563
297
|
if ((textPending.length > 0 || thinkingPending.length > 0) && nowMs - lastFlushAt >= flushEveryMs) {
|
|
564
298
|
yield* drainLive();
|
|
565
299
|
lastFlushAt = nowMs;
|
|
@@ -574,33 +308,25 @@ export function createTextStream(ctx, idOf) {
|
|
|
574
308
|
committedText += committed;
|
|
575
309
|
},
|
|
576
310
|
replaceThinkingSegment: (content) => {
|
|
577
|
-
// CC-11:段 = 段内**全部**已提交思考行(按序)+ 还押着的缓冲。分歧按整段拼文比;归属一次交出全部 uuid。
|
|
578
311
|
const rows = committedThinking;
|
|
579
312
|
committedThinking = [];
|
|
580
313
|
const prefix = rows.map((r) => r.text).join('');
|
|
581
314
|
const uuids = rows.map((r) => r.uuid);
|
|
582
315
|
const last = uuids.length > 0 ? uuids[uuids.length - 1] : undefined;
|
|
583
|
-
// (f) 本包没经手过这一段(durable 整块臂铸过 transcript 行 / 宿主只喂 end)。
|
|
584
316
|
if (prefix.length === 0 && thinking.length === 0) {
|
|
585
317
|
return { diverged: false, committedPrefixLen: 0, committedPrefixDiverged: false };
|
|
586
318
|
}
|
|
587
319
|
const live = prefix + thinking;
|
|
588
320
|
const diverged = live !== content;
|
|
589
321
|
if (prefix.length === 0) {
|
|
590
|
-
// (a) 全部还押在缓冲里:整块换,活体尾巴按已泄前缀重算。
|
|
591
322
|
const emitted = thinking.slice(0, thinking.length - thinkingPending.length);
|
|
592
323
|
thinkingPending = content.startsWith(emitted) ? content.slice(emitted.length) : '';
|
|
593
324
|
thinking = content;
|
|
594
325
|
thinkingSettled = content.length > 0;
|
|
595
|
-
// CC-15(0.69.3,cli 接入回执):形 (a) 透传 `committedUuids: []` —— **在场但空** = 本包判定「本段零已提交行」
|
|
596
|
-
// 的正面事实;整键缺席只留给形 (f)(本包零经手,说不出)。壳靠这条才能不自己数窗口里过境的行
|
|
597
|
-
// (那会把上一段迟交行 / durable 行数进去 = 假披露)。
|
|
598
326
|
return { diverged, committedPrefixLen: 0, committedPrefixDiverged: false, committedUuids: [] };
|
|
599
327
|
}
|
|
600
|
-
// (b) 有已提交行(一条或跨卡多条):已提交那截撤不回。
|
|
601
328
|
const committedPrefixDiverged = !content.startsWith(prefix);
|
|
602
329
|
if (!committedPrefixDiverged) {
|
|
603
|
-
// (b1) 已提交前缀逐字对得上 ⇒ 只换还押着的尾段(跨卡后段);`thinking` 为空时零字节可换,只报归属。
|
|
604
330
|
if (thinking.length > 0) {
|
|
605
331
|
const tail = content.slice(prefix.length);
|
|
606
332
|
const emitted = thinking.slice(0, thinking.length - thinkingPending.length);
|
|
@@ -610,7 +336,6 @@ export function createTextStream(ctx, idOf) {
|
|
|
610
336
|
}
|
|
611
337
|
return { diverged, committedPrefixLen: prefix.length, committedPrefixDiverged: false, ...(last !== undefined ? { committedUuid: last } : {}), committedUuids: uuids };
|
|
612
338
|
}
|
|
613
|
-
// (b2) 已提交那截自己也过期 ⇒ 一个字节都不再交(还押着的尾段清掉,别让它落成第二份),整段归宿主换。
|
|
614
339
|
thinking = '';
|
|
615
340
|
thinkingPending = '';
|
|
616
341
|
thinkingAnchor = null;
|
|
@@ -619,7 +344,7 @@ export function createTextStream(ctx, idOf) {
|
|
|
619
344
|
},
|
|
620
345
|
segmentId: segmentIdNow,
|
|
621
346
|
rotateSegmentIdentity: (anchor) => {
|
|
622
|
-
committedTextRows = [];
|
|
347
|
+
committedTextRows = [];
|
|
623
348
|
segmentWindowSerial += 1;
|
|
624
349
|
segmentWindowAnchor = anchor;
|
|
625
350
|
segmentIdCache = null;
|
|
@@ -627,8 +352,6 @@ export function createTextStream(ctx, idOf) {
|
|
|
627
352
|
stampSegmentIdentity: (out) => {
|
|
628
353
|
if (out.plane !== 'transcript')
|
|
629
354
|
return out;
|
|
630
|
-
// ⚠️ 局部名刻意不叫 `msg`/`content`:message-branching 门把 `msg.message` 读成「错误文案」,
|
|
631
|
-
// 并按名字把污染扩到整个文件 —— 同名的 `content.startsWith` 会被误判成按文案分支。
|
|
632
355
|
const row = out.message;
|
|
633
356
|
if (row.type !== 'assistant')
|
|
634
357
|
return out;
|
|
@@ -646,8 +369,6 @@ export function createTextStream(ctx, idOf) {
|
|
|
646
369
|
if (committedText.length > 0)
|
|
647
370
|
previousCommittedText = committedText;
|
|
648
371
|
committedText = '';
|
|
649
|
-
// L-310:新消息开始 = 旧段的已提交前缀与**新**段无关 ⇒ 本段账归零;同 takeAnswerSegment,
|
|
650
|
-
// 归零前记进 `previousSegmentCommitted`(迟到的 `text_end` 还要拿它算分歧)。
|
|
651
372
|
previousSegmentCommitted += segmentCommitted;
|
|
652
373
|
segmentCommitted = '';
|
|
653
374
|
},
|
|
@@ -1,30 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* adapt/toolCards.ts — M2 **工具卡台账**(A 族拆分 REF-CC-SPLIT-03;矩阵 §1.2 三行状态)。
|
|
3
|
-
*
|
|
4
|
-
* 收编 `pending`(开卡表)/ `assistantResponseId`(S1 per-RESPONSE id)/ `lastLiveTodos`
|
|
5
|
-
* (TodoWrite 划删线 diff 的 oldTodos)三行状态 + C4 mintResponseId / C10 buildToolResult /
|
|
6
|
-
* C11 sweepOpenCards 三个闭包 + `PendingToolUse` 形本身。
|
|
7
|
-
*
|
|
8
|
-
* 🔴 拆分硬约束(SPLIT-03,复审结论 2 采纳形):**S1 复位在 `close()` 内部、第一个 `yield`
|
|
9
|
-
* 之前**。理由是生成器语义 —— yield 之后的语句只有消费者再要下一个值时才跑,消费者早退
|
|
10
|
-
* (`it.return()` / break)时永不执行。把复位留在调用方,调用方就还能写出「yield 后复位」的形;
|
|
11
|
-
* 收进被调方之后,这条时序由**一处**保证。原 `tool_end_result` 臂 :1054-1056(delete → 复位 →
|
|
12
|
-
* yield)与 sweep :743-747 是同一个三步,现在是同一段代码。
|
|
13
|
-
*
|
|
14
|
-
* 🔴 同批把 assistant 臂 reject/cancel(:970)与 error(:990)两条路径的复位**前移到各自 yield 之前**
|
|
15
|
-
* —— 矩阵 §2.2 的定性:那两处是**形不一致的技术债、不是缺陷**(`assistantResponseId` 是 L1
|
|
16
|
-
* turn 级,两行之后紧跟 `break`,早退时生成器已死、再无读者 ⇒ 零可观测后果),所以前移是
|
|
17
|
-
* **纯一致性改动、零行为差**。反钉见矩阵 §2.2:前移不影响 mint —— 影响窗口只有
|
|
18
|
-
* 「复位语句与原复位点(yield 之后)」之间那几行,窗口内无 mint 点;三条支随即退出本臂,
|
|
19
|
-
* 后续帧的 mint 走各自臂的常规路径,与拆分前同(对抗复审校准:break 退出的是臂不是 turn)。
|
|
20
|
-
*
|
|
21
|
-
* 🔴 `pending` 是唯一跨 M2→M3 的数据面(矩阵 §1.2 注):面板族只读两个字段(`name` 判
|
|
22
|
-
* SUBAGENT_TOOL_NAMES / `rawInput` T50 双形读)。所以对外给的是 `OpenCardView` **只读视图**,
|
|
23
|
-
* 不交 Map 本体 —— 交出去 M3 就能 `delete`,而「一张开卡一条 tool_result」是本模块的不变量。
|
|
24
|
-
*/
|
|
25
1
|
import type { AdapterContext, AdapterOutput } from '../seam.js';
|
|
26
2
|
import { type Frame, type IdOf } from './ids.js';
|
|
27
|
-
/** 一张开着的卡(assistant tool_use 臂开、tool_end_result 臂关)。 */
|
|
28
3
|
export interface PendingToolUse {
|
|
29
4
|
id: string;
|
|
30
5
|
name: string;
|
|
@@ -32,18 +7,6 @@ export interface PendingToolUse {
|
|
|
32
7
|
eventId?: string;
|
|
33
8
|
parentToolCallId?: string;
|
|
34
9
|
}
|
|
35
|
-
/**
|
|
36
|
-
* `tool_end_result` 帧上**与关卡有关的那几位**(原 `buildToolResult` 的内联入参形,具名化)。
|
|
37
|
-
*
|
|
38
|
-
* 🔴 本形**不是** `tool_end_result` 臂的镜像,是它的**关卡切片** —— 只收「铸这张 tool_result 卡真正
|
|
39
|
-
* 要读的位」。臂上另有若干**开集观察位**按设计**不进本形**:`errorCode`(core 5.9.0 W3)、
|
|
40
|
-
* `gate`(整条门记录,engine ≥7.64.0 / sdk 8.4.0 —— 取代退役的四个正交词)、`delivered`
|
|
41
|
-
* (MCP 投递判词,core ≥7.6.0)、`gatedCallId`(core ≥5.55.0)。它们由
|
|
42
|
-
* `eventToSdkMessage` 的 `case 'tool_end'` 臂原样上臂、由**宿主/桥**直接从臂上读(壳 upstreamBridge、
|
|
43
|
-
* print 车道 {@link import('../printToolResultFrame.js').ToolEndResultArmLike}),卡台账一位都不消费。
|
|
44
|
-
* 往本形加一个没有落点的键 = 一句「关卡会用到它」的假话(声明与产物对不上,且没有任何门会响);
|
|
45
|
-
* 真要让转录卡带上结算归属,那是一件**新的呈现设计**(需定 `_sema_` 超集键 + 台账登记),不是透传。
|
|
46
|
-
*/
|
|
47
10
|
export interface ToolEndPayload {
|
|
48
11
|
output?: unknown;
|
|
49
12
|
structured?: unknown;
|
|
@@ -52,25 +15,16 @@ export interface ToolEndPayload {
|
|
|
52
15
|
eventId?: string | undefined;
|
|
53
16
|
parentToolCallId?: string | undefined;
|
|
54
17
|
}
|
|
55
|
-
/** 交给面板族(M3)的**只读**视图 —— 不含任何写口。 */
|
|
56
18
|
export interface OpenCardView {
|
|
57
|
-
/** 这张卡此刻还开着吗(#6 live vs inert 的判位)。 */
|
|
58
19
|
has(id: string): boolean;
|
|
59
|
-
/** 读卡(面板族只用 `name` 与 `rawInput` 两个字段)。 */
|
|
60
20
|
peek(id: string): PendingToolUse | undefined;
|
|
61
|
-
/** 按**开卡顺序**遍历(FIFO 猜父臂依赖这个顺序)。 */
|
|
62
21
|
entries(): Iterable<readonly [string, PendingToolUse]>;
|
|
63
22
|
}
|
|
64
23
|
export interface ToolCardLedger extends OpenCardView {
|
|
65
|
-
/** 开卡(assistant tool_use 臂)。 */
|
|
66
24
|
open(p: PendingToolUse): void;
|
|
67
|
-
/** 关一张卡:出栈 + S1 复位 + 铸 tool_result(三步都在第一个 yield 之前完成前两步)。 */
|
|
68
25
|
close(p: PendingToolUse, end?: ToolEndPayload): Generator<AdapterOutput>;
|
|
69
|
-
/** 关掉所有还开着的卡(流被截断 / 无 result 收尾;abort 路径**不做**)。 */
|
|
70
26
|
sweep(): Generator<AdapterOutput>;
|
|
71
|
-
/** S1:per-RESPONSE 铸 id(同一个 model response 内的多张卡共用)。 */
|
|
72
27
|
mintResponseId(frame: Frame): string;
|
|
73
|
-
/** S1:一个结果关闭该 model response(reject/cancel/error 三支的显式复位口)。 */
|
|
74
28
|
resetResponseId(): void;
|
|
75
29
|
}
|
|
76
30
|
export declare function createToolCardLedger(ctx: AdapterContext, idOf: IdOf): ToolCardLedger;
|