@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,122 +1,28 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ⇄ B7 批搬迁(2026-07-27,设计稿 §3 B7):cli `src/seam/adapter/upstream/hitlBridge.ts`(491 行)
|
|
3
|
-
* **整条进包**。这是 HITL 的心脏 —— suspended ↔ canUseTool 的编组层。
|
|
4
|
-
*
|
|
5
|
-
* 🔴 **D-1 两元组是安全不变量,原样搬,一个字节不改**(设计稿 §3 B7 原文):
|
|
6
|
-
* `bindingOf()`(下方 §1 末)把人**看见的那一行** `PendingCheckpoint` 上的
|
|
7
|
-
* `boundCallId` + `boundInputHash` **逐字回显**进 `approvals.decide(...)` —— 绝不本地重算
|
|
8
|
-
* (重算出来的假不匹配会 fail-close 掉一个合法审批);409 `approval_binding_mismatch`
|
|
9
|
-
* 是**安全信号**,抛 `HitlSafetyError('binding_mismatch')`,**绝不自动重试**。
|
|
10
|
-
* 这两段代码在 `scripts/run-client-core-pure-test.mjs` 的 B7 段有**字节级**断言
|
|
11
|
-
* (常量字面量比对 + 壳树在场时的双向比对),改一个字符就红。
|
|
12
|
-
*
|
|
13
|
-
* ── 搬迁差分(只有三处,全在类型/依赖面,零运行时语义变化)────────────────────────────────
|
|
14
|
-
* 1. `eventSeq` 从 `../types.js` → `../adapter/types.js`(B3 已搬入本包,同一份实现)。
|
|
15
|
-
* 2. CC 的 `PermissionDecision` / `PermissionDenyDecision` / `CanUseToolFn` 三个类型住在壳的
|
|
16
|
-
* `src/types/permissions.ts` + `src/hooks/useCanUseTool.tsx`(它们拖 `ToolType` /
|
|
17
|
-
* `ToolUseContext` / `AssistantMessage` 整张 CC 内部类型图,不属于 wire 词汇表)。
|
|
18
|
-
* 本包改用**结构切片 + 泛型**:`HitlPermissionDecisionLike`(本桥真正读的三个键)与
|
|
19
|
-
* `HitlCanUseToolFn<D>`(CC 回调的形状,tool/context/message 三个位对本桥是不透明的)。
|
|
20
|
-
* 壳侧 shim 用自己的 `PermissionDecision` 实例化泛型 ⇒ 壳侧调用点类型一字节不变。
|
|
21
|
-
* 🔴 这是**类型面**的收窄,不是行为面:运行时只读 `.behavior` / `.message` / `.updatedInput`
|
|
22
|
-
* 三个键(原文就只读这三个)。
|
|
23
|
-
* 3. `backendDeny` 的返回形状(`decisionReason:{type:'asyncAgent',reason}`)是 CC 的
|
|
24
|
-
* `PermissionDenyDecision` 逐字形,本包按字面量声明(壳侧 shim 断言可赋值)。
|
|
25
|
-
*
|
|
26
|
-
* ── 以下为原文件的领域说明(逐字保留)────────────────────────────────────────────────────────
|
|
27
|
-
*
|
|
28
|
-
* src/seam/adapter/upstream/hitlBridge.ts — the UPSTREAM control bridge (tasks.json T23; NEW file, no CC-logic edit).
|
|
29
|
-
*
|
|
30
|
-
* This is the human-in-the-loop (HITL) heart of the seam: the place where CC's synchronous `canUseTool`
|
|
31
|
-
* callback (useCanUseTool.tsx:27 — the spine the contract must reproduce) meets the `@sema-ai/sdk`
|
|
32
|
-
* suspended → decide → resume loop (contract/04 §2/§4/§6, contract/08 IH-4/IH-5/IH-10). CC's loop calls
|
|
33
|
-
* `canUseTool(tool, input, …)` before any guarded tool runs and BLOCKS on the returned `PermissionDecision`;
|
|
34
|
-
* the contract turns that blocking callback into a DURABLE pause (a `suspended` event carrying a
|
|
35
|
-
* `CheckpointGate`) plus a `decide` verb. This module is the marshalling layer between the two worlds.
|
|
36
|
-
*
|
|
37
|
-
* What it does (the three contract laws this file pins):
|
|
38
|
-
*
|
|
39
|
-
* 1. **suspended ↔ canUseTool with the D-1 TOCTOU guard** (contract/04 §2.2, §D-1; 08 IH-4).
|
|
40
|
-
* When CC asks "may I run THIS tool?", the bridge finds the matching `PendingCheckpoint` the human SAW
|
|
41
|
-
* (joined by `toolCallId` → `boundCallId`), reads its `boundCallId` + `boundInputHash` two-tuple, and
|
|
42
|
-
* echoes them back into `approvals.decide(...)` VERBATIM. The hash is a server-minted opaque sha256 over
|
|
43
|
-
* the pending args at mint time — the bridge NEVER recomputes it (a false mismatch would fail-close a
|
|
44
|
-
* legitimate approval, approvals.ts:33). `updatedInput` (approve-with-edit, design/37 last-wins) is
|
|
45
|
-
* applied AFTER the binding check and does NOT change the binding — the hash still binds the ORIGINAL
|
|
46
|
-
* input the human reviewed. A 409 `approval_binding_mismatch` is a SAFETY signal: re-present to the
|
|
47
|
-
* human, NEVER auto-retry (contract/04 §9.1 fail-closed law).
|
|
48
|
-
*
|
|
49
|
-
* 2. **AskUserQuestion answer marshalling** (contract/04 §4.1; 08 CS-16/IH-4). The same suspended → decide
|
|
50
|
-
* loop, but the gate's `toolName` is `"AskUserQuestion"` and the answer rides `ApprovalDecision.answer`
|
|
51
|
-
* as the worker-validated wire shape `{ answers: [{ header, selected, note? }] }` — `header` MATCHES the
|
|
52
|
-
* question's header, `selected` is an ARRAY (multi-select → multiple entries), `note` is optional free
|
|
53
|
-
* text. The SDK types `answer` as `unknown`, so this is hand-marshalled (catalog mock-fill); the
|
|
54
|
-
* transport is sdk-covered. The D-1 binding still binds (AskUserQuestion is still a checkpoint).
|
|
55
|
-
*
|
|
56
|
-
* 3. **plan_review** (contract/04 §3; 08 CS-17/IH-6). CC's plan mode ends a planning turn with a markdown
|
|
57
|
-
* plan; the human approves/edits/rejects the PLAN itself (no bound tool action). This resolves on a
|
|
58
|
-
* DISTINCT wire — `assistant.planReview(taskId, { decision, editedPlan?, reason? })` — NOT `decide` and
|
|
59
|
-
* NOT `resume`. `editedPlan` is REQUIRED iff `decision === "edit"` and FORBIDDEN otherwise (→ 400). A
|
|
60
|
-
* non-`plan_review` gate routed here would 409 `gate_not_plan_review`; the bridge guards the gate kind
|
|
61
|
-
* before it calls.
|
|
62
|
-
*
|
|
63
|
-
* Provider- and presentation-agnostic (contract/04 laws 2-3; 08 invariants): every verb stays at
|
|
64
|
-
* `ApprovalDecision` / `PlanReviewRequest` / `CheckpointGate` altitude. No Anthropic `effort`/`fast_mode`
|
|
65
|
-
* vocabulary, no claude.ai permission-rule destinations, no widget/glyph/keybinding crosses this seam. The
|
|
66
|
-
* backend supplies the SIGNAL; the shell owns the chrome.
|
|
67
|
-
*/
|
|
68
1
|
import type { AgentEvent, ApprovalDecision, ApprovalStaleError, PendingCheckpoint, CheckpointGate, PlanReviewRequest, AssistantTaskStatus } from '@sema-agent/sdk';
|
|
69
2
|
import type { ApprovalsListEnvelope } from './crashConverged.js';
|
|
70
3
|
import { type SuspendedReopenReading } from './suspendedReopen.js';
|
|
71
|
-
/** durable `/decide` 腿的既有缺省拒因(不带归因时逐字不变 —— 0.27.0 及之前的 wire 字节)。 */
|
|
72
4
|
export declare const DEFAULT_DENY_REASON = "The user rejected this tool use";
|
|
73
|
-
/**
|
|
74
|
-
* 归因原文 → 可上 wire 的形。缺席/非串/纯空白 ⇒ `undefined`(调用方自定回落:deny 腿落
|
|
75
|
-
* {@link DEFAULT_DENY_REASON},plan-review 腿键不落);超上限 ⇒ 截到上限并 debug 留痕。
|
|
76
|
-
* 🔴 截断**边界安全**:切点落在代理对中间会产出孤高代理 —— server 长度检查放行,但 UTF-8
|
|
77
|
-
* 落库/入签时末尾退化成 U+FFFD,两侧字节不一致还会毒化签名对账。末码元是高代理就再退一位。
|
|
78
|
-
* 🔴 只做归因,不参与裁决:任何返回值都不改变这次决断本身。
|
|
79
|
-
*/
|
|
80
5
|
export declare function denyReasonForWire(reason: string | undefined, tag: string): string | undefined;
|
|
81
|
-
/** CC `PermissionDecision` 的结构切片 —— 本桥运行时真正读的三个键。 */
|
|
82
6
|
export interface HitlPermissionDecisionLike {
|
|
83
7
|
behavior: 'allow' | 'ask' | 'deny';
|
|
84
|
-
/** deny 臂的人话理由(CC `PermissionDenyDecision.message`),approve 臂缺席。 */
|
|
85
8
|
message?: string;
|
|
86
|
-
/** approve-with-edit(design/37 last-wins);在**绑定校验之后**生效,绑定仍绑原始 input。 */
|
|
87
9
|
updatedInput?: unknown;
|
|
88
10
|
}
|
|
89
|
-
/**
|
|
90
|
-
* CC `CanUseToolFn` 的结构形(`useCanUseTool.tsx:28`)。tool / toolUseContext / assistantMessage
|
|
91
|
-
* 三个位对本桥是**不透明**的(只读 `tool.name`),所以按最小形声明 —— 壳侧那个更窄的真类型
|
|
92
|
-
* 可赋值到这里(函数参数双变),`makeHitlCanUseTool` 的返回值也就能直接当 `CanUseToolFn` 用。
|
|
93
|
-
*/
|
|
94
11
|
export type HitlCanUseToolFn<D extends HitlPermissionDecisionLike = HitlPermissionDecisionLike> = (tool: {
|
|
95
12
|
name: string;
|
|
96
13
|
}, input: Record<string, unknown>, toolUseContext: never, assistantMessage: never, toolUseID: string, forceDecision?: D) => Promise<D>;
|
|
97
14
|
export interface ApprovalsResourceLike {
|
|
98
|
-
/** GET /v1/approvals — the rich decide-ready queue (approvals.ts:45). NEVER carries a capability token.
|
|
99
|
-
* SDK ≥0.1.0([1908] 信封归一):wire 信封原样 `{ pending }`。
|
|
100
|
-
* 🔴 L-38(server 7.55.0):回体是 {@link ApprovalsListEnvelope} —— `pending` 之外还可能带
|
|
101
|
-
* additive 的 `livePending` / `crashConverged`(按 deps 在场才发)。**放宽是 additive**:
|
|
102
|
-
* 老 mock 的 `{ pending }` 仍然可赋值,本文件与 `approvalsFeed.ts` 的 `.pending` 消费点
|
|
103
|
-
* 一个字节不动。`crashConverged` 的读法见 `hitl/crashConverged.ts` 的 `projectCrashConverged`
|
|
104
|
-
* —— 🔴 它是**上一条命的残留**读面,与本桥这条 D-1 取件路**互不相干**,别在这里顺手消费它。 */
|
|
105
15
|
list(opts?: {
|
|
106
16
|
signal?: AbortSignal;
|
|
107
17
|
}): Promise<ApprovalsListEnvelope>;
|
|
108
|
-
/** POST /v1/approvals/:sessionId/decide — resolve THAT checkpoint; the resumed run continues its stream
|
|
109
|
-
* (approvals.ts:52). NOT a submit → no retry (a decide must never double-act). */
|
|
110
18
|
decide(sessionId: string, decision: ApprovalDecision, opts?: {
|
|
111
19
|
signal?: AbortSignal;
|
|
112
20
|
}): Promise<unknown>;
|
|
113
21
|
}
|
|
114
22
|
export interface AssistantResourceLike {
|
|
115
|
-
/** POST /v1/assistant/tasks/:id/plan_review — the 3-state plan gate (assistant.ts:87). */
|
|
116
23
|
planReview(taskId: string, req: PlanReviewRequest, opts?: {
|
|
117
24
|
signal?: AbortSignal;
|
|
118
25
|
}): Promise<AssistantTaskStatus>;
|
|
119
|
-
/** POST /v1/assistant/tasks/:id/resume — continue a resource_limit slice, NO body (assistant.ts:75). */
|
|
120
26
|
resume(taskId: string, opts?: {
|
|
121
27
|
signal?: AbortSignal;
|
|
122
28
|
}): Promise<AssistantTaskStatus>;
|
|
@@ -125,339 +31,61 @@ export interface HitlClientLike {
|
|
|
125
31
|
approvals: ApprovalsResourceLike;
|
|
126
32
|
assistant: AssistantResourceLike;
|
|
127
33
|
}
|
|
128
|
-
/** The marshalled AskUserQuestion answer body — the worker-validated wire shape (contract/04 §4.1). */
|
|
129
34
|
export interface AskAnswer {
|
|
130
|
-
/** MATCHES the question's `header`. */
|
|
131
35
|
header: string;
|
|
132
|
-
/** ARRAY — multi-select yields multiple entries; single-select is a one-element array. */
|
|
133
36
|
selected: string[];
|
|
134
|
-
/** Optional operator free-text note. */
|
|
135
37
|
note?: string;
|
|
136
38
|
}
|
|
137
|
-
/** A plan-review outcome the shell collected (contract/04 §3.1). `editedPlan` REQUIRED iff decision==="edit". */
|
|
138
39
|
export interface PlanReviewOutcome {
|
|
139
40
|
decision: 'approve' | 'edit' | 'reject';
|
|
140
41
|
editedPlan?: string;
|
|
141
42
|
reason?: string;
|
|
142
|
-
/**
|
|
143
|
-
* 0.72.13 CC-46(engine ≥7.86.0;契约 §4c):批准之后这条任务继续用的 permission mode。**只配 `approve`**;
|
|
144
|
-
* 缺席 = 键不落(老壳姿势,引擎按 `default`)。🔴 适用面读不到 wire:只有**提交这条任务的那一方**知道它是不是
|
|
145
|
-
* `permissionMode:"plan"` 只读起步的 —— 不是只读起步的任务送这一位会吃 400 `request.field_conflict`,那次批准整个送不出去。
|
|
146
|
-
*/
|
|
147
43
|
permissionModeAfter?: PlanReviewModeAfter;
|
|
148
44
|
}
|
|
149
|
-
/** 契约 §4c `permissionModeAfter` 的闭集两词(`acceptEdits` = 工作目录内的写不再逐次征询;`default` = 每次写照常征询)。 */
|
|
150
45
|
export declare const PLAN_REVIEW_MODE_AFTER_WORDS: readonly ["default", "acceptEdits"];
|
|
151
46
|
export type PlanReviewModeAfter = (typeof PLAN_REVIEW_MODE_AFTER_WORDS)[number];
|
|
152
|
-
/** 这个值是不是闭集里的词(词表外 —— 含 `plan` / `bypassPermissions` / `auto` —— 引擎 400:一次批准不许顺带关掉征询面)。 */
|
|
153
47
|
export declare function isPlanReviewModeAfter(v: string | undefined): v is PlanReviewModeAfter;
|
|
154
|
-
/**
|
|
155
|
-
* {@link HitlSafetyError.code} 的闭集(0.60.0 抽名,**成员一个没动**)。
|
|
156
|
-
*
|
|
157
|
-
* 🔴 抽名的理由是**消费面**:决断腿的失败结局要把「本地安全停」与「引擎的 wire 拒绝」结构分开
|
|
158
|
-
* (`FsApprovalOutcome.safetyCode` / `GateOutcome.code`),而那两处此前只能各自把这五个词再抄一遍
|
|
159
|
-
* ——抄一份就是给自己立第二个判官(B-025 的病形)。加员仍必须**同批**改齐
|
|
160
|
-
* `parkResolver.GATE_FAILURE_CODES` 白名单(见下方原注)。
|
|
161
|
-
*/
|
|
162
48
|
export type HitlSafetyCode = 'binding_mismatch' | 'no_pending' | 'wrong_gate' | 'bad_plan_edit' | 'bad_plan_mode' | 'empty_answer';
|
|
163
|
-
/**
|
|
164
|
-
* 一次决断链失败**停在哪一段**(0.60.0;异源对抗复审 [medium] 采纳,B-037 候包件 ② 的完整兑现)。
|
|
165
|
-
*
|
|
166
|
-
* ── 病 ──────────────────────────────────────────────────────────────────────────────────────
|
|
167
|
-
* 两条决断腿(fs / ask)的 `failed` 结局把 typed 错**拍平成一个 `reason` 串**,于是四类完全不同的
|
|
168
|
-
* 失败在消费点**同形**:「取件那一拍没有可决行」「卡口没装」「引擎语义拒绝」「出站瞬断耗尽」——
|
|
169
|
-
* 分流只能去正则匹配那句拍平文案(里面嵌的是 `String(e)`,上游改一个词就静默空转)。而这四类的
|
|
170
|
-
* 出路完全不同:重探 / 装口 / 重呈或换参数 / 重呈不判死。
|
|
171
|
-
*
|
|
172
|
-
* ── 词与判据 ────────────────────────────────────────────────────────────────────────────────
|
|
173
|
-
* · `fetch` —— 取件腿没给出可决行,或读面自己炸了(**一个字节都没送出去**);
|
|
174
|
-
* · `input` —— 行上没有可呈现的载荷(工具入参 / 问句),卡渲不出来(同样没送出去);
|
|
175
|
-
* · `card` —— 卡口那一段失败(没装卡口 / 卡口自己报失败 / 没有问答 overlay);
|
|
176
|
-
* · `decide` —— 决断**已经发出去了**(引擎语义拒绝,或出站瞬断耗尽);
|
|
177
|
-
* · `orchestration` —— 上面四段都不是:编排层在若干轮重挂之后收口(轮数/park 数硬上限、连续零进展)。
|
|
178
|
-
* 🔴 **只有 `decide` 代表「引擎那一头知道这次决断」** —— 安全停的第一问就是它,前三段一个字节都没送出。
|
|
179
|
-
* 🔴 **必填**:一个可选的阶段位等于又留了一格「读不出就猜」,而这一位存在的全部理由就是消灭那一格。
|
|
180
|
-
*/
|
|
181
49
|
export type HitlFailureStage = 'fetch' | 'input' | 'card' | 'decide' | 'orchestration';
|
|
182
|
-
/** A safety stop: a contract law was about to be violated (e.g. a binding mismatch, a wrong-gate route).
|
|
183
|
-
* The caller MUST re-present to the human or surface the error — NEVER silently retry or auto-decide
|
|
184
|
-
* (contract/04 §9.1 fail-closed law). */
|
|
185
50
|
export declare class HitlSafetyError extends Error {
|
|
186
|
-
/** A stable code the shell can branch on (REF-CC-036,2026-08-02:闭集联合,不再是开集 string —
|
|
187
|
-
* 与同族兄弟 `controlRouter.ts` 的 `ControlSafetyError.code` 同形)。 */
|
|
188
|
-
/** 🔴 闭集(FIX② 2026-08-07 加 `empty_answer`,第 5 员)。加员必须**同批**改齐
|
|
189
|
-
* `parkResolver.GATE_FAILURE_CODES` 白名单 —— 那道白名单把不认得的码降成 `undefined`,
|
|
190
|
-
* 一边加一边不改另一边 = 新码在消费端被静默吞掉(比不加还坏:本地拦住了,判词却丢了)。 */
|
|
191
51
|
readonly code: HitlSafetyCode;
|
|
192
|
-
constructor(message: string,
|
|
193
|
-
/** A stable code the shell can branch on (REF-CC-036,2026-08-02:闭集联合,不再是开集 string —
|
|
194
|
-
* 与同族兄弟 `controlRouter.ts` 的 `ControlSafetyError.code` 同形)。 */
|
|
195
|
-
/** 🔴 闭集(FIX② 2026-08-07 加 `empty_answer`,第 5 员)。加员必须**同批**改齐
|
|
196
|
-
* `parkResolver.GATE_FAILURE_CODES` 白名单 —— 那道白名单把不认得的码降成 `undefined`,
|
|
197
|
-
* 一边加一边不改另一边 = 新码在消费端被静默吞掉(比不加还坏:本地拦住了,判词却丢了)。 */
|
|
198
|
-
code: HitlSafetyCode);
|
|
52
|
+
constructor(message: string, code: HitlSafetyCode);
|
|
199
53
|
}
|
|
200
|
-
/**
|
|
201
|
-
* decide 409 `approval_stale` 拒体上的 **additive 指路键** `currentPending` —— 本会话**当前**那条
|
|
202
|
-
* pending 的三件 D-1 坐标(#363,0.47.0;server S-02 ≥7.52)。
|
|
203
|
-
*
|
|
204
|
-
* ── 它是什么、不是什么 ────────────────────────────────────────────────────────────────────
|
|
205
|
-
* 是:「你手上那条已经不是当前的了,**当前**这条长这样」——壳拿它**一跳重定位**再 decide,
|
|
206
|
-
* 免去整队重拉(`GET /v1/approvals`)。
|
|
207
|
-
* 不是:放行凭据 / CAS 输入 / resume 凭证。server 自己的 fail-open 登记原话逐字:
|
|
208
|
-
* 「纯指路/便利面,**不参与任何门/CAS/resume 判定**」。⇒ 缺席的代价 = 退回它到货前的行为
|
|
209
|
-
* (重拉列表自行重定位),所以本包对它一律**宽读、诚实缺席**,绝不 fail-closed。
|
|
210
|
-
* 🔴 **恒不含 `checkpointToken`**(server 侧 resume 凭证不外发纪律)——本形也刻意没有那一位:
|
|
211
|
-
* 多一个位就是给一个「凭证能过境」的错觉。
|
|
212
|
-
*
|
|
213
|
-
* ── 自铸形已退役,本名现在是上游形的**别名**(0.48.0)──────────────────────────────────
|
|
214
|
-
* 0.47.0 这里是一个**自铸 interface** + 一段记账:`@sema-agent/sdk` 7.3.0 起已有逐字同形的
|
|
215
|
-
* `ApprovalStaleCurrentPending`,但当时本包 peer 地板是 `>=7.2.0`,那一版上这个名字不存在 ⇒
|
|
216
|
-
* `import type` 会让装 7.2.0 的端当场编不过。记账段同批写死了退役条件:「peer 地板抬到 `>=7.3.0`
|
|
217
|
-
* 的那一批,把本形改成 `import type` 的别名并删掉这段记账」。
|
|
218
|
-
* 本批(0.48.0)peer 地板抬到 **`>=7.4.0`**(四件新投影都吃 7.4.0 的类型面)⇒ 条件满足,兑现。
|
|
219
|
-
* 🔴 **别名而不是删名**:`GateCurrentPending` 是 `FsApprovalOutcome` / `GateOutcome` 两条腿的**已发布
|
|
220
|
-
* 导出名**,删它是 BREAKING。别名让上游形成为**唯一真源**(上游改一个位,本包的两条腿当天跟着
|
|
221
|
-
* 动,不再有第二份可能漂的声明),而本名继续对已接入的端有效。
|
|
222
|
-
* 🔴 **同名不同源的风险随之消失**:0.47.0 刻意取了个**不同名**(免得地板线下出现一个与上游同名却
|
|
223
|
-
* 不同源的形,[same-name-different-meaning-crosses-layers]);现在两者是同一个形,那条顾虑不再
|
|
224
|
-
* 适用 —— 但名字**不回改**成上游名,理由见上一条(已发布导出名)。
|
|
225
|
-
*
|
|
226
|
-
* 🔴 **为什么绕道 `ApprovalStaleError['currentPending']` 而不是直接 `import type
|
|
227
|
-
* { ApprovalStaleCurrentPending }`(上游缺口,本批亲验实证)**:那个名字在 sdk 7.4.0 里**声明了
|
|
228
|
-
* 但没有从包入口导出** —— `dist/types.d.ts:2359` 有 `export interface ApprovalStaleCurrentPending`,
|
|
229
|
-
* 而 `dist/index.d.ts` 的 re-export 名单里**没有它**(同文件只导出了 `ApprovalStaleError`),
|
|
230
|
-
* 且包 `exports` 映射只开 `.` / `./registry` 两个子路径,深引 `@sema-agent/sdk/dist/types.js`
|
|
231
|
-
* 这条路根本不通。⇒ 按名 import 是**编译错**,不是风格选择。
|
|
232
|
-
* 绕道取的是**同一个声明**(`currentPending?: ApprovalStaleCurrentPending | undefined`,
|
|
233
|
-
* `NonNullable` 剥掉可选位),所以单源化的目的一字不打折:上游改那个形,本包当天跟着动。
|
|
234
|
-
* 📋 **上游候件(已登记,不在本批修)**:请 sdk 把 `ApprovalStaleCurrentPending` 加进 `index.d.ts`
|
|
235
|
-
* 的 `export type {…}` 名单(纯 additive,零行为)。到货后本别名可改回按名 import,
|
|
236
|
-
* **但那是等价重构、不是修复** —— 今天这条路已经拿到上游形本身,不存在第二份可能漂的声明。
|
|
237
|
-
*/
|
|
238
54
|
export type GateCurrentPending = Readonly<NonNullable<ApprovalStaleError['currentPending']>>;
|
|
239
|
-
/**
|
|
240
|
-
* 从一次 decide 失败(任意抛出物)里读出 {@link GateCurrentPending} —— 读不出即 `undefined`。
|
|
241
|
-
*
|
|
242
|
-
* 🔴 **结构视图读,不 `instanceof`**(两条理由,都是承重的):
|
|
243
|
-
* ① **供给面**:本包的 decide 出站走的是宿主注入的 `HitlClientLike`(见该型)。抛出来的到底是不是
|
|
244
|
-
* SDK 的 `ApprovalStaleError` 由**宿主**决定 —— web/desktop 完全可以注入自己的传输层。拿
|
|
245
|
-
* `instanceof` 当闸,等于让「宿主用的是哪一份 SDK 实例」决定一个纯读值的位在不在
|
|
246
|
-
* (跨 realm / 双实例 = `HitlSafetyError` 判型契约踩过的同一个坑,见 §4e)。
|
|
247
|
-
* ② **类型面**(0.48.0 就地订正):0.47.0 这条写的是「`ApprovalStaleError.currentPending` 只在
|
|
248
|
-
* sdk ≥7.3.0 上声明,而本包地板是 7.2.0」——**地板已抬到 `>=7.4.0`,那半条不再成立**。
|
|
249
|
-
* 但本条的**结论不变**,因为承重的从来是 ① 那半:即使类型面现在够得着,抛出来的对象仍由宿主
|
|
250
|
-
* 的传输层决定,`instanceof` 依旧是错的判据。⇒ 保留宽读,只订正理由。
|
|
251
|
-
* 🔴 **判据锚在「值本身合不合形」,不锚它骑在哪个类/哪个 errorCode 上**
|
|
252
|
-
* ([anchor-on-the-deciding-quantity]):真正决定「壳能不能一跳重定位」的量,是**这个三元组的
|
|
253
|
-
* 两件必填位在不在且是非空串** —— 而不是错误的类名。宽读在这里是**方向安全**的:本位不参与
|
|
254
|
-
* 任何裁决(见 {@link GateCurrentPending} 顶注),多读到一次的代价 = 多一条指路;漏读的代价 =
|
|
255
|
-
* 退回整队重拉。
|
|
256
|
-
* 🔴 **两件必填位缺一即整只不铸**:半个三元组重定位不了(`decide` 要的是 boundCallId 本体),
|
|
257
|
-
* 铸一个残形只会让消费点以为「有指路」。`boundInputHash` 是**行上有才带**的可选位,缺席照铸。
|
|
258
|
-
*/
|
|
259
55
|
export declare function readDecideCurrentPending(e: unknown): GateCurrentPending | undefined;
|
|
260
|
-
/**
|
|
261
|
-
* 从一次 decide / 取件失败(任意抛出物)里读出**引擎的机器码** —— 读不出即 `undefined`。
|
|
262
|
-
*
|
|
263
|
-
* 🔴 **为什么这一位非透出不可**(0.60.0;上游候包件 ②,与 0.47.0 补 `currentPending` **同形**):
|
|
264
|
-
* 本包把 typed 错**拍平成 `reason` 串**交给消费点(`FsApprovalOutcome.failed.reason`),于是
|
|
265
|
-
* 「只读 outcome 形」的消费者(壳的重开链、迟到决断代理)对机读码**全盲** —— 要分辨
|
|
266
|
-
* `resume.preflight_rejected` / `approval_stale` / 传输类失败,只能去正则匹配那句拍平文案,
|
|
267
|
-
* 而那句文案里嵌的是 `String(e)`(上游一改措辞就静默空转)。上游为此在壳里绕了一整圈
|
|
268
|
-
* (把 client 套进代理、站在拍平**之前**读)——那圈本该由这一位省掉。
|
|
269
|
-
* 🔴 **结构视图读,不 `instanceof`**:理由与 {@link readDecideCurrentPending} 逐字同一条 ——
|
|
270
|
-
* 抛出来的是不是 SDK 的错误类由**宿主注入的传输层**决定(跨 realm / 双实例)。
|
|
271
|
-
* 🔴 **键位只认 `errorCode`**([2055] 死键纪律,退役的 `code` 槽不做兼容);非空串才算数,
|
|
272
|
-
* 其余一律诚实缺席。
|
|
273
|
-
* 🔴 **只搬运不解释**:本读口不判任何码属于哪一族(词表属主在 server/core,开集)——消费点分支
|
|
274
|
-
* 已知码、永远带 `default`。
|
|
275
|
-
* 🔴 **绝不把它当凭证面**:`errorCode` 是机器码,不是错误正文;错误正文(可能含凭据/内部路径)
|
|
276
|
-
* 照旧**不**经本位外流。
|
|
277
|
-
*/
|
|
278
56
|
export declare function readWireErrorCode(e: unknown): string | undefined;
|
|
279
|
-
/** 测试钩:把超时类重试总窗调小(传 undefined 还原缺省)。 */
|
|
280
57
|
export declare function __setDecideTimeoutRetryBudgetForTests(ms?: number): void;
|
|
281
|
-
/**
|
|
282
|
-
* decide 出站在瞬断类失败上重试一次**仍未送达**(两发都没拿到引擎的语义答复)。
|
|
283
|
-
*
|
|
284
|
-
* 🔴 判别位契约:消费方(`toolApprovalWire` 的 catch 臂 / `parkResolver.surfaceGateAndDecide`)
|
|
285
|
-
* 据 `instanceof` 在 outcome 上 stamp `retryExhausted: true`,parkResolver 对该位走**重呈臂**
|
|
286
|
-
* (re-attach ⇒ durable 流重放 park ⇒ 同一张卡重新交给用户),不再合成 `hitl_unanswered` 把 turn
|
|
287
|
-
* 判死 —— run 仍 parked、pending 行仍可决,判死是三条出路里唯一不可逆的那条。
|
|
288
|
-
* 🔴 message 刻意避开 `isAlreadyResolvedGateReason` 的词表(no pending checkpoint / resolved /
|
|
289
|
-
* already / not found):被那把兜底尺误判成「已解决」会走成静默 reattach,判别位就白铸了 ——
|
|
290
|
-
* pure 门(hitl-gate-honesty F6-d)有常驻负控钉着这一条。
|
|
291
|
-
*/
|
|
292
58
|
export declare class DecideTransportRetryExhaustedError extends Error {
|
|
293
|
-
/** 实际发出的次数(网络断类 = 2:首发 + 单次重试;超时类 = 总窗内发出的全部)。 */
|
|
294
59
|
readonly attempts: number;
|
|
295
|
-
constructor(
|
|
296
|
-
/** 实际发出的次数(网络断类 = 2:首发 + 单次重试;超时类 = 总窗内发出的全部)。 */
|
|
297
|
-
attempts: number, lastFailureText: string);
|
|
60
|
+
constructor(attempts: number, lastFailureText: string);
|
|
298
61
|
}
|
|
299
|
-
/** The active gate the downstream stream most recently suspended on (null when running). */
|
|
300
62
|
export interface ActiveGate {
|
|
301
63
|
gate: CheckpointGate;
|
|
302
|
-
/** The durable seq of the `suspended` event, for rewind/dedup correlation (types.ts:48 eventSeq). */
|
|
303
64
|
seq?: string | undefined;
|
|
304
|
-
/** 0.74.3 CC-73:这条挂起是不是一次 reopen(`suspended.reopened` 三态,见 {@link suspendedReopenOf});每条 suspended 重读,不粘上一条。 */
|
|
305
65
|
reopened: SuspendedReopenReading;
|
|
306
66
|
}
|
|
307
|
-
/** Outcome of {@link findPendingForTask}. */
|
|
308
67
|
export type FindPendingOutcome = {
|
|
309
68
|
ok: true;
|
|
310
69
|
pending: PendingCheckpoint;
|
|
311
70
|
gatedCallId: string | undefined;
|
|
312
|
-
}
|
|
313
|
-
/** `code`:结构化判别位(REF-CC-033)。'no_pending'=良性缺席(park 重放常见);缺席=真失败(list 抛)。 */
|
|
314
|
-
| {
|
|
71
|
+
} | {
|
|
315
72
|
ok: false;
|
|
316
73
|
reason: string;
|
|
317
74
|
code?: 'no_pending';
|
|
318
75
|
};
|
|
319
|
-
/**
|
|
320
|
-
* The single source for "which `PendingCheckpoint` row is the human about to decide on", used by the two
|
|
321
|
-
* decision wires (`toolApprovalWire.surfaceFsApprovalAndDecide` / `askGateWire.surfaceGateAndDecide`)
|
|
322
|
-
* BEFORE they know which specific call/question they're presenting — that is the FIRST fetch, the one
|
|
323
|
-
* that decides what gets rendered on the card/overlay.
|
|
324
|
-
*
|
|
325
|
-
* REF-CC-029(2026-08-02,消 hitl2-08/hitl2-01 双病根):this used to be three near-identical copies
|
|
326
|
-
* (this file's own `HitlBridge.findPending` plus one each in `toolApprovalWire.ts` / `askGateWire.ts`),
|
|
327
|
-
* and only `HitlBridge.findPending`'s copy had a `?? pending[0]` last-resort fallback (REF-CC-022) that
|
|
328
|
-
* could resolve a DIFFERENT session's or a background subagent lane's pending row once this taskId's own
|
|
329
|
-
* rows were gone — they all share the same `/v1/approvals` queue. Single-sourcing this lookup here means
|
|
330
|
-
* that divergence can't recur, and passing the resolved row straight into `decideTool`/`answerQuestion`'s
|
|
331
|
-
* `preResolvedPending` param closes the TOCTOU window between "the row the human saw" (this fetch) and
|
|
332
|
-
* "the row decide resolves" (previously a SECOND independent fetch inside the bridge).
|
|
333
|
-
*
|
|
334
|
-
* Match by `taskId` + a caller-supplied predicate over the row's `toolName` (the tool family this wire
|
|
335
|
-
* cares about, e.g. fs-write vs AskUserQuestion) first; fall back to ANY row for this `taskId` (a gate
|
|
336
|
-
* whose toolName the predicate doesn't recognize, but which still belongs to this run). Never `pending[0]`
|
|
337
|
-
* — a typed failure when nothing for this taskId is queued.
|
|
338
|
-
*
|
|
339
|
-
* F4947-1(2026-08-22,0.41.0):`callId` 是**更强的身份腿**,在场时先于上面两条跑。它来自
|
|
340
|
-
* `HitlBridge.decideTool`/`answerQuestion` 的 `toolUseID`(CC 的 tool_use id)—— 那两处此前走的是
|
|
341
|
-
* 本类里一个**同名私有** `findPending`,REF-CC-029 的收编没覆盖到它、P-30 的门种闸也没加到它,
|
|
342
|
-
* 于是真实生产入口(`makeHitlCanUseTool` → `decideTool`,从不传 `preResolvedPending`)一直在一条
|
|
343
|
-
* **没有闸**的复刻上跑(test 线 P0-KPI 复现)。收口方式是把私有件删掉改调本函数,而不是给它补第二
|
|
344
|
-
* 份过滤 —— 复刻正是这条缺陷的成因。身份腿同样只在**过完门种闸的行**里找:一个 `plan_review` 行
|
|
345
|
-
* 哪怕 callId 逐字命中也不该被工具审批 decide 掉(server 那边照样 409 `gate_not_tool_approval`)。
|
|
346
|
-
*
|
|
347
|
-
* P-30(2026-08-14):both legs only consider rows whose `gateKind` belongs to the ask/approval family
|
|
348
|
-
* ({@link askParkForeignGateKind} — the same single-source guard `classifyAskParkRows` uses). Without it
|
|
349
|
-
* the ANY-row fallback would hand a `plan_review`/`resource_limit` row to the tool-approval wire — an
|
|
350
|
-
* empty-toolName card whose decide then 409s (`gate_not_tool_approval`). A foreign-kind row is filtered
|
|
351
|
-
* out, not a rejection of the whole queue: a genuine approval row for the same task still resolves.
|
|
352
|
-
* Rows with no `gateKind` (pre-`gate_kind` history) keep the old behaviour — no stronger signal exists.
|
|
353
|
-
*/
|
|
354
76
|
export declare function findPendingForTask(client: HitlClientLike, taskId: string, matches: (toolName: string | undefined) => boolean, opts?: {
|
|
355
77
|
signal?: AbortSignal;
|
|
356
|
-
},
|
|
357
|
-
/**
|
|
358
|
-
* F4947-1:调用方手上的**更强身份** —— CC 的 `toolUseID`(`HitlBridge`),或这张 park 的
|
|
359
|
-
* wire 身份(server ≥7.41.0,两条决断腿)。在场 ⇒ 先在**本 taskId** 的行里按
|
|
360
|
-
* `boundCallId`/`toolCallId` 逐字命中(仍在门种闸之内);不命中再走下面两条 taskId 腿。
|
|
361
|
-
*
|
|
362
|
-
* 🔴 **刻意不 fail-closed**(异源复审二审 finding① 的部分驳回,理由成文):身份在场而队列里
|
|
363
|
-
* 没有那一行时**照旧回落**,不铸「身份不匹配」的硬拒。两条理由:
|
|
364
|
-
* · 回落的失效面 = 与本参数出现之前**逐字节相同**(那时压根没有身份腿);fail-closed 的失效面
|
|
365
|
-
* = **每一次审批都决断不了**(用户点了 Yes 也过不去)。代价严重不对称;
|
|
366
|
-
* · 这个 join(checkpoint 的 `pendingAction.toolCallId` ↔ `/v1/approvals` 富行的
|
|
367
|
-
* `toolCallId`/`boundCallId`)本仓**没有对真 server 的实证**,只有上游帖面的口径。拿一个
|
|
368
|
-
* 没实证的键去关整条 HITL 的门,是把「可能对不上」赌成「一定对得上」。
|
|
369
|
-
* 跨 run 那一半的风险由上面的 taskId 约束关掉;「决断落在同 task 的另一行」这一格与本参数出现
|
|
370
|
-
* 之前同形,且下游 `dropHeldForDecidedPark` 对这一格自带保守判(身份对不上 ⇒ 一帧都不摘)。
|
|
371
|
-
*/
|
|
372
|
-
callId?: string,
|
|
373
|
-
/**
|
|
374
|
-
* 身份腿的**族闸**(整行可读)。缺省 = 退回 `matches(toolName)`。
|
|
375
|
-
*
|
|
376
|
-
* 🔴 为什么必须能读**整行**而不是只读 toolName(五审 finding①):工具审批族有**两条腿** ——
|
|
377
|
-
* 一等 `kind === 'tool_approval'`(放行**任意** toolName)与 fs 写 / shell 名字腿。而 wire 模块
|
|
378
|
-
* 传下来的 `matches` 只有名字腿那半(它服务的是「同族第一行」那条 leg 2)。拿它当身份闸,一个
|
|
379
|
-
* **合法的 kind-only 行**即使 taskId+callId 逐字命中也会被判出局 ⇒ 回落挑了同 task 的另一行,
|
|
380
|
-
* 卡面与决断全落在别的审批上、真 gate 继续 suspended。⇒ 调用方按自己那条腿的**完整**族判据
|
|
381
|
-
* 供给本闸(fs 腿 = `isToolApprovalGate({kind: row.gateKind, toolName})`,ask 腿 = `isAskTool`)。
|
|
382
|
-
*/
|
|
383
|
-
identityAccepts?: (row: PendingCheckpoint) => boolean): Promise<FindPendingOutcome>;
|
|
384
|
-
/**
|
|
385
|
-
* The bridge state. One per run/session. The shell feeds it `suspended` events (observe) and the human's
|
|
386
|
-
* outcome (decide / answer / planReview); it owns the `approvals.list()` join + the verbatim binding echo.
|
|
387
|
-
*/
|
|
78
|
+
}, callId?: string, identityAccepts?: (row: PendingCheckpoint) => boolean): Promise<FindPendingOutcome>;
|
|
388
79
|
export declare class HitlBridge {
|
|
389
80
|
private readonly client;
|
|
390
|
-
/** The suspended run's taskId — the handle plan_review/resume address (RunReceipt.taskId). */
|
|
391
81
|
private readonly taskId;
|
|
392
82
|
private active;
|
|
393
|
-
constructor(client: HitlClientLike,
|
|
394
|
-
/** The suspended run's taskId — the handle plan_review/resume address (RunReceipt.taskId). */
|
|
395
|
-
taskId: string);
|
|
396
|
-
/** Observe a downstream event; latch the gate on `suspended`, clear it on a resuming/terminal arm. */
|
|
83
|
+
constructor(client: HitlClientLike, taskId: string);
|
|
397
84
|
observe(ev: AgentEvent): void;
|
|
398
|
-
/** The gate currently awaiting a human, if any. The shell branches on `gate.kind` to pick the chrome. */
|
|
399
85
|
currentGate(): CheckpointGate | null;
|
|
400
|
-
/**
|
|
401
|
-
* 0.74.3 CC-73:当前挂起是不是一次 reopen(`suspended.reopened` 三态);没挂起 ⇒ `null`。
|
|
402
|
-
* 消费方据此把「真 reopen 成功、重试会重放」那半句说出来:`reopened` 在场码 ⇒ 卡仍 pending、决定没被消费、可再决;
|
|
403
|
-
* `not_reopened` / `unstated` ⇒ 普通挂起,一个字都不多说。
|
|
404
|
-
*/
|
|
405
86
|
currentGateReopen(): SuspendedReopenReading | null;
|
|
406
|
-
/**
|
|
407
|
-
* Fetch the `PendingCheckpoint` this decide/answer is about to resolve, for the callers that do NOT
|
|
408
|
-
* already have one in hand (see `decideTool`/`answerQuestion`'s `preResolvedPending` param — the wire
|
|
409
|
-
* modules that surface a card/overlay BEFORE deciding fetch the row themselves and pass it straight
|
|
410
|
-
* through, closing the TOCTOU window between "the row the human saw" and "the row decide resolves",
|
|
411
|
-
* REF-CC-029/hitl2-08).
|
|
412
|
-
*
|
|
413
|
-
* 🔴 F4947-1(2026-08-22,0.41.0):本方法**没有自己的查找逻辑** —— 它是 {@link findPendingForTask}
|
|
414
|
-
* 的一层出参映射,一个字节的行过滤都不在这里。上一版是一个与那个单源导出**撞名**的私有复刻
|
|
415
|
-
* (`findPending`),REF-CC-029 的三合一没覆盖到它、P-30 的门种闸也只加在导出那一份上,于是
|
|
416
|
-
* `makeHitlCanUseTool` → `decideTool`(真实用户点 Yes/No 那条路,从不传 `preResolvedPending`)
|
|
417
|
-
* 一直在没有闸的老复刻上跑:同 task 停着 `plan_review` 行时,它被当成「这个 run 的 pending」
|
|
418
|
-
* 交给工具审批 decide(空 toolName 卡 / 409 `gate_not_tool_approval`)。
|
|
419
|
-
* 名字也一并换掉:撞名正是「看起来只有一份实现」的成因。
|
|
420
|
-
*
|
|
421
|
-
* 谓词传 {@link ANY_TOOL_FAMILY}:桥这一层对工具族**没有意见**(人刚刚决断的是哪张门就是哪张),
|
|
422
|
-
* 与旧私有件的 taskId 兜底逐字同语义;身份腿(`toolUseID`)由单源函数的 `callId` 参数承接。
|
|
423
|
-
*/
|
|
424
87
|
private pendingForDecide;
|
|
425
|
-
/**
|
|
426
|
-
* Build the D-1 binding off the pending row the human SAW. Echo VERBATIM — NEVER recompute the hash
|
|
427
|
-
* (contract/04 §2.2). `checkpointToken` is DELIBERATELY never set (deprecated legacy path;
|
|
428
|
-
* compliant clients send ONLY the two-tuple, approvals.ts:23-27).
|
|
429
|
-
*
|
|
430
|
-
* pre-D-1 的 `{}` 回落臂已删(2026-08-03,#117 提货 / [2356]#2):server 5.x 的 decide 三键必填、
|
|
431
|
-
* 缺键 400,「发一个注定 400 的请求」不如在本地响亮失败——pending 行缺绑定键只可能来自
|
|
432
|
-
* 不再支持的旧 worker 或坏数据,fail-loud 带坐标好过静默烧一轮 HTTP。
|
|
433
|
-
*/
|
|
434
88
|
private bindingOf;
|
|
435
|
-
/**
|
|
436
|
-
* Resolve a `human` / `irreversible_ask` permission gate (contract/04 §2, §6.2; 08 IH-4/IH-10).
|
|
437
|
-
*
|
|
438
|
-
* - `approve` → `{decision:"approve", boundCallId, boundInputHash}`; `updatedInput` rides along for
|
|
439
|
-
* approve-with-edit (applied AFTER the binding check — the hash still binds the ORIGINAL input).
|
|
440
|
-
* - `deny` → `{decision:"deny", reason}`.
|
|
441
|
-
*
|
|
442
|
-
* 🔴 **§2.4「DENY-abort」撤稿(0.42.0;server [4833] 明请,契约成文 `4631a0f` 随 7.39 出)**。
|
|
443
|
-
* 本段原文写的是:「CANCEL a suspended run by DENYING, never by `runs.cancel` (**which 409s on a
|
|
444
|
-
* suspended run** — contract/04 §2.4); the deny-and-abort `interrupt:true` EFFECT is *the run ends
|
|
445
|
-
* after the deny*」。**三句话里有两句已被上游证伪,逐条**:
|
|
446
|
-
* · **「deny 用来 cancel 一条 run」** —— `ASSISTANT-WIRE-CONTRACT.md` §4a 逐字反过来说:
|
|
447
|
-
* **DENY is a TOOL-level answer, NEVER a run kill**;客户端不得把用户的拒绝译成 cancel。
|
|
448
|
-
* 两个动词的 wire 判别式是 `cancelled`(真取消)vs `gate.batch_halted`(裸拒的兄弟结算)。
|
|
449
|
-
* · **「`runs.cancel` 对 suspended run 回 409」** —— 自 server [868] 起**就地取消**:
|
|
450
|
-
* `runs.js` 的 cancel 腿对 SUSPENDED/needs_review 先结算 pending checkpoint(CAS expire)再
|
|
451
|
-
* 终态化,`cancelSuspended` 有实体,409 只剩 `conflict.approval_settled` 一条
|
|
452
|
-
* (本仓 `docs/fresh-scan-client-core-2026-08-08.md` B型-5 已按真字节证伪,当时未跟修注释)。
|
|
453
|
-
* · **仍然成立的那一句**:deny 之后 run 是否结束由**后端编排**决定,不是 wire 上的旗标
|
|
454
|
-
* (裸拒 ⇒ `gate.batch_halted` + `haltedOnUserRejection`;带留言拒 ⇒ run 续跑)。
|
|
455
|
-
* ⇒ 本方法的**行为一字未改**(它本来走的就是 §4a 说的那条 TOOL 级 decide 通路);改的是这段
|
|
456
|
-
* 引用错权威、并把一条早已失效的 409 断言当理由的散文。
|
|
457
|
-
*
|
|
458
|
-
* The resumed run continues its SAME durable stream. A binding mismatch (409) is re-raised as a
|
|
459
|
-
* `HitlSafetyError('binding_mismatch')` — the caller re-presents, NEVER auto-retries.
|
|
460
|
-
*/
|
|
461
89
|
decideTool(outcome: {
|
|
462
90
|
decision: 'approve';
|
|
463
91
|
updatedInput?: unknown;
|
|
@@ -467,75 +95,25 @@ export declare class HitlBridge {
|
|
|
467
95
|
reason?: string | undefined;
|
|
468
96
|
}, toolUseID?: string, opts?: {
|
|
469
97
|
signal?: AbortSignal;
|
|
470
|
-
},
|
|
471
|
-
/** REF-CC-029(2026-08-02):the pending row the caller ALREADY fetched (via `findPendingForTask`,
|
|
472
|
-
* below) to render the card/overlay the human just decided on. When supplied, this method skips
|
|
473
|
-
* its own `approvals.list()` — closing the TOCTOU window between "the row the human saw" and "the
|
|
474
|
-
* row decide resolves" (two independent fetches could otherwise land on different rows if the
|
|
475
|
-
* first one got resolved/expired in between, hitl2-01/hitl2-08). Omit only when the caller has no
|
|
476
|
-
* such row in hand(缺省回落 `pendingForDecide` — 见其头注,那是单源 `findPendingForTask` 的一层出参映射). */
|
|
477
|
-
preResolvedPending?: PendingCheckpoint): Promise<unknown>;
|
|
478
|
-
/**
|
|
479
|
-
* Answer an `AskUserQuestion` gate (contract/04 §4; 08 CS-16). Same suspended → decide loop as a
|
|
480
|
-
* permission gate, but the answer rides `ApprovalDecision.answer` as the worker-validated
|
|
481
|
-
* `{ answers: [{ header, selected, note? }] }` shape. The D-1 binding STILL binds (it is still a
|
|
482
|
-
* checkpoint). Each answer's `header` MUST match a question header (the worker 400s on mismatch).
|
|
483
|
-
*
|
|
484
|
-
* 🔴 FIX②(2026-08-07)—— **本地 fail-loud**:此前本方法对 `answers: []` 与「某条 `selected: []`」
|
|
485
|
-
* 零校验,一条注定 400 的请求照样出门。这不是「多一次往返」而已 ——
|
|
486
|
-
* · 用户面只看到「作答失败」,而失败的原因(空作答)在壳侧一个字都没说;
|
|
487
|
-
* · `ToolPermissionDecision.answer` 的头注自己写着「a silently emptied answer is the user's
|
|
488
|
-
* choice being thrown away without anyone noticing」—— 那条纪律此前只写在类型注释里,
|
|
489
|
-
* 没有任何一层真的执行它;
|
|
490
|
-
* · `{answers:[]}` 在 wire 上另有确切含义(question 域 **deny** 的 NO_HUMAN 形),把它当成一次
|
|
491
|
-
* approve 发出去 = 拿 deny 的载荷冒充 approve。
|
|
492
|
-
* 三形一律抛 `HitlSafetyError('empty_answer')`,一次 decide 都不发:空 `answers[]` /
|
|
493
|
-
* 任一条 `selected[]` 为空 / 任一条 `header` 为空串。
|
|
494
|
-
*/
|
|
98
|
+
}, preResolvedPending?: PendingCheckpoint): Promise<unknown>;
|
|
495
99
|
answerQuestion(answers: AskAnswer[], toolUseID?: string, opts?: {
|
|
496
100
|
signal?: AbortSignal;
|
|
497
|
-
},
|
|
498
|
-
/** REF-CC-029(2026-08-02):see `decideTool`'s same-named param — the pending row the caller already
|
|
499
|
-
* fetched via `findPendingForTask`. */
|
|
500
|
-
preResolvedPending?: PendingCheckpoint): Promise<unknown>;
|
|
501
|
-
/**
|
|
502
|
-
* Resolve a plan-mode gate (contract/04 §3; 08 IH-6). Routed to `assistant.planReview`, NOT `decide`/
|
|
503
|
-
* `resume`. Also guards the `editedPlan` invariant (REQUIRED iff `decision==="edit"`, FORBIDDEN
|
|
504
|
-
* otherwise → 400) so the bad call never leaves the shell — that check is unconditional (no
|
|
505
|
-
* `observe()` dependency). The gate-kind guard below is host-optional (see its own comment); the
|
|
506
|
-
* server's 409 `gate_not_plan_review` is the real backstop either way.
|
|
507
|
-
*/
|
|
101
|
+
}, preResolvedPending?: PendingCheckpoint): Promise<unknown>;
|
|
508
102
|
reviewPlan(outcome: PlanReviewOutcome, opts?: {
|
|
509
103
|
signal?: AbortSignal;
|
|
510
104
|
}): Promise<AssistantTaskStatus>;
|
|
511
|
-
/**
|
|
512
|
-
* Continue a `resource_limit` slice pause (contract/04 §6.1; 08 IH-9). Bodyless `assistant.resume` — NOT
|
|
513
|
-
* `decide`. A `human`/`irreversible_ask` gate routed here would 409 `gate_not_resumable` (a "continue"
|
|
514
|
-
* must NEVER bypass a human approval). REF-CC-028(2026-08-02,评注现势):the local guard below is
|
|
515
|
-
* host-optional — it only fires when the host drives `observe(ev)` (neither production call site does
|
|
516
|
-
* today, see `reviewPlan`'s comment); the server's 409 is the fail-closed backstop that actually holds
|
|
517
|
-
* this invariant.
|
|
518
|
-
*/
|
|
519
105
|
resumeResourceLimit(opts?: {
|
|
520
106
|
signal?: AbortSignal;
|
|
521
107
|
}): Promise<AssistantTaskStatus>;
|
|
522
108
|
private decideRaw;
|
|
523
109
|
}
|
|
524
|
-
/** The shell's presentation hook: surface a gate, resolve to a CC `PermissionDecision`. */
|
|
525
110
|
export type GatePrompt<D extends HitlPermissionDecisionLike = HitlPermissionDecisionLike> = (ctx: {
|
|
526
111
|
toolName: string;
|
|
527
112
|
input: Record<string, unknown>;
|
|
528
113
|
toolUseID: string;
|
|
529
114
|
gate: CheckpointGate | null;
|
|
530
115
|
}) => Promise<D>;
|
|
531
|
-
/**
|
|
532
|
-
* Build a `CanUseToolFn` backed by the bridge. CC's loop calls it before any guarded tool; it surfaces the
|
|
533
|
-
* gate via `prompt`, routes the human's decision to `approvals.decide` (binding echoed verbatim), and
|
|
534
|
-
* returns the same `PermissionDecision` to unblock the loop. A `forceDecision` (CC's pre-resolved path)
|
|
535
|
-
* short-circuits the prompt but STILL drives the decide verb so the backend resolves the checkpoint.
|
|
536
|
-
*/
|
|
537
116
|
export declare function makeHitlCanUseTool<D extends HitlPermissionDecisionLike = HitlPermissionDecisionLike>(bridge: HitlBridge, prompt: GatePrompt<D>): HitlCanUseToolFn<D>;
|
|
538
|
-
/** CC `PermissionDenyDecision` 的逐字形(`decisionReason` 的 `asyncAgent` 臂)。 */
|
|
539
117
|
export interface HitlBackendDenyDecision {
|
|
540
118
|
behavior: 'deny';
|
|
541
119
|
message: string;
|
|
@@ -544,6 +122,4 @@ export interface HitlBackendDenyDecision {
|
|
|
544
122
|
reason: string;
|
|
545
123
|
};
|
|
546
124
|
}
|
|
547
|
-
/** Build a CC deny `PermissionDecision` from a backend-driven denial (e.g. an SLA / policy auto-deny).
|
|
548
|
-
* The decisionReason is `asyncAgent` — the denial originated upstream, not from a local rule/mode. */
|
|
549
125
|
export declare function backendDeny(reason: string): HitlBackendDenyDecision;
|