@sema-agent/client-core 0.93.1 → 0.95.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 +554 -0
- package/README.md +89 -55
- package/dist/adapt/arms.js +13 -11
- package/dist/adapt/panelTasks.js +4 -10
- package/dist/adapt/toolCards.js +2 -2
- package/dist/adapt/wireShapes.js +3 -8
- package/dist/adapter/activeRunSelfHeal.d.ts +8 -3
- package/dist/adapter/activeRunSelfHeal.js +20 -12
- package/dist/adapter/downstream/eventToSdkMessage.js +24 -17
- package/dist/adapter/downstream/terminalToSdkResult.js +13 -6
- package/dist/adapter/runStream.js +2 -1
- package/dist/adapter/types.d.ts +7 -0
- package/dist/adapter/types.js +15 -0
- package/dist/agentSession/backgroundView.js +5 -1
- package/dist/agentSession/engineAgentRegistryRead.js +2 -1
- package/dist/agentSession/engineSessionBackgroundStop.js +5 -3
- package/dist/agentsWireCaps.d.ts +17 -0
- package/dist/agentsWireCaps.js +111 -1
- package/dist/approvalDecidedByCapability.d.ts +0 -1
- package/dist/approvalDecidedByCapability.js +2 -7
- package/dist/approvalReachWire.d.ts +18 -0
- package/dist/approvalReachWire.js +58 -0
- package/dist/approvalsStreamLiveCapability.d.ts +0 -1
- package/dist/approvalsStreamLiveCapability.js +15 -14
- package/dist/atMostOnce.d.ts +8 -0
- package/dist/atMostOnce.js +36 -0
- package/dist/attachmentSeatCapability.d.ts +0 -1
- package/dist/attachmentSeatCapability.js +0 -3
- package/dist/attachmentsWireCaps.js +11 -6
- package/dist/bashExitReading.d.ts +10 -0
- package/dist/bashExitReading.js +12 -0
- package/dist/callerCwdCapability.d.ts +15 -0
- package/dist/callerCwdCapability.js +42 -0
- package/dist/centerWiringCapability.d.ts +1 -3
- package/dist/centerWiringCapability.js +18 -21
- package/dist/classifierStatus.js +4 -4
- package/dist/cloudConfigWireCaps.js +43 -21
- package/dist/compensations.js +1 -1
- package/dist/controlRouter.js +3 -10
- package/dist/coreValuePorts.d.ts +64 -1
- package/dist/coreValuePorts.js +30 -0
- package/dist/cycleOrder.d.ts +15 -0
- package/dist/cycleOrder.js +45 -0
- package/dist/decideFailureNote.js +4 -1
- package/dist/decideReceipt.d.ts +2 -1
- package/dist/decideReceipt.js +41 -13
- package/dist/declared/supportFloorDeclared.d.ts +1 -0
- package/dist/declared/supportFloorDeclared.js +5 -0
- package/dist/detachWire.d.ts +1 -4
- package/dist/detachWire.js +1 -1
- package/dist/deviceExecutorManagementCapability.d.ts +0 -1
- package/dist/deviceExecutorManagementCapability.js +36 -40
- package/dist/deviceFlowPolling.d.ts +5 -0
- package/dist/deviceFlowPolling.js +28 -0
- package/dist/deviceRebind.d.ts +88 -0
- package/dist/deviceRebind.js +242 -0
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +963 -30
- package/dist/engineAgentAbsence.d.ts +2 -2
- package/dist/engineAgentPanelStore.d.ts +8 -18
- package/dist/engineAgentPanelStore.js +19 -537
- package/dist/engineCapReader.d.ts +6 -6
- package/dist/engineCapReader.js +30 -43
- package/dist/engineCapsCache.d.ts +7 -2
- package/dist/engineCapsCache.js +64 -26
- package/dist/engineCredentialRequirement.d.ts +9 -0
- package/dist/engineCredentialRequirement.js +23 -0
- package/dist/engineEnvSourcing.d.ts +53 -0
- package/dist/engineEnvSourcing.js +81 -0
- package/dist/engineErrorCodes.d.ts +19 -4
- package/dist/engineErrorCodes.js +39 -21
- package/dist/engineIdentity.js +2 -0
- package/dist/engineNoticeCodes.d.ts +22 -2
- package/dist/engineNoticeCodes.js +73 -6
- package/dist/engineRefusedToolName.d.ts +1 -0
- package/dist/engineRefusedToolName.js +8 -0
- package/dist/engineWireSdk.js +2 -2
- package/dist/executionLaneCapability.d.ts +2 -3
- package/dist/executionLaneCapability.js +28 -28
- package/dist/fileHistoryCaptureCapability.d.ts +0 -1
- package/dist/fileHistoryCaptureCapability.js +13 -12
- package/dist/fileHistoryLegNotice.d.ts +14 -2
- package/dist/fileHistoryLegNotice.js +101 -15
- package/dist/fleet/fleetLedger.d.ts +2 -0
- package/dist/fleet/fleetLedger.js +74 -52
- package/dist/fleet/fleetProjection.d.ts +0 -3
- package/dist/fleet/fleetProjection.js +9 -16
- package/dist/fleetAgentPanelProjection.d.ts +4 -17
- package/dist/fleetAgentPanelProjection.js +7 -197
- package/dist/fleetAgentRowLike.d.ts +16 -0
- package/dist/fleetAgentRowLike.js +1 -0
- package/dist/gateOutcome.d.ts +2 -1
- package/dist/gateOutcome.js +33 -18
- package/dist/gateVocabulary.js +1 -1
- package/dist/generated/engineAskFaceTables.d.ts +3 -0
- package/dist/generated/engineAskFaceTables.js +12 -0
- package/dist/generated/engineFactTables.d.ts +4 -2
- package/dist/generated/engineFactTables.js +13 -0
- package/dist/generated/engineNoticeTables.d.ts +5 -0
- package/dist/generated/engineNoticeTables.js +7 -0
- package/dist/generated/sdkFactTables.d.ts +5 -0
- package/dist/generated/sdkFactTables.js +34 -0
- package/dist/generated/settingsSchemaFns.d.ts +10 -0
- package/dist/generated/settingsSchemaFns.js +22 -0
- package/dist/generated/settingsSchemaTables.d.ts +3 -0
- package/dist/generated/settingsSchemaTables.js +3 -0
- package/dist/headlessPermissionModeWire.d.ts +2 -2
- package/dist/headlessPermissionModeWire.js +11 -21
- package/dist/headlessReconnectWire.js +49 -20
- package/dist/hitl/allowRuleShadow.d.ts +1 -1
- package/dist/hitl/allowRuleShadow.js +49 -8
- package/dist/hitl/approvalCompleteParked.d.ts +1 -0
- package/dist/hitl/approvalCompleteParked.js +14 -0
- package/dist/hitl/approvalEndingCause.d.ts +5 -0
- package/dist/hitl/approvalEndingCause.js +61 -0
- package/dist/hitl/approvalHolds.d.ts +46 -0
- package/dist/hitl/approvalHolds.js +140 -0
- package/dist/hitl/approvalOutcomeNote.js +2 -1
- package/dist/hitl/approvalResolution.js +9 -1
- package/dist/hitl/approvalsFeed.js +23 -6
- package/dist/hitl/askGateWire.d.ts +2 -1
- package/dist/hitl/askGateWire.js +29 -1
- package/dist/hitl/automaticAnswerVerdict.d.ts +8 -2
- package/dist/hitl/automaticAnswerVerdict.js +71 -23
- package/dist/hitl/crashConverged.js +2 -0
- package/dist/hitl/decisionConflict.d.ts +3 -0
- package/dist/hitl/decisionConflict.js +43 -0
- package/dist/hitl/decisionRefusal.d.ts +23 -0
- package/dist/hitl/decisionRefusal.js +88 -0
- package/dist/hitl/frameRouter.d.ts +10 -0
- package/dist/hitl/frameRouter.js +71 -32
- package/dist/hitl/gateLedger.d.ts +8 -0
- package/dist/hitl/gateLedger.js +38 -0
- package/dist/hitl/hitlBridge.d.ts +14 -3
- package/dist/hitl/hitlBridge.js +75 -62
- package/dist/hitl/hitlHostSurface.d.ts +3 -0
- package/dist/hitl/hitlHostSurface.js +17 -15
- package/dist/hitl/livePendingAsk.d.ts +16 -6
- package/dist/hitl/livePendingAsk.js +36 -4
- package/dist/hitl/localAllowRule.js +2 -1
- package/dist/hitl/noAllowCause.d.ts +9 -0
- package/dist/hitl/noAllowCause.js +26 -0
- package/dist/hitl/parkExpiryJudgements.d.ts +19 -0
- package/dist/hitl/parkExpiryJudgements.js +46 -0
- package/dist/hitl/parkResolver.d.ts +3 -7
- package/dist/hitl/parkResolver.js +55 -28
- package/dist/hitl/parkRowBirthWait.js +2 -1
- package/dist/hitl/persistedRulesWire.d.ts +6 -1
- package/dist/hitl/persistedRulesWire.js +16 -4
- package/dist/hitl/planReviewWire.d.ts +2 -3
- package/dist/hitl/planReviewWire.js +86 -39
- package/dist/hitl/replayedApproval.d.ts +8 -0
- package/dist/hitl/replayedApproval.js +125 -10
- package/dist/hitl/resumeRunningCard.d.ts +2 -0
- package/dist/hitl/resumeRunningCard.js +15 -4
- package/dist/hitl/sessionPolicyDeliverable.d.ts +1 -1
- package/dist/hitl/sessionPolicyDeliverable.js +3 -8
- package/dist/hitl/sessionPolicyWire.js +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +50 -5
- package/dist/hitl/toolApprovalWire.js +368 -56
- package/dist/hooksWireCaps.js +38 -6
- package/dist/host.d.ts +5 -0
- package/dist/host.js +3 -1
- package/dist/hostCallbackGuard.d.ts +1 -0
- package/dist/hostCallbackGuard.js +25 -0
- package/dist/humanTurnRead.d.ts +15 -1
- package/dist/humanTurnRead.js +28 -2
- package/dist/index.d.ts +45 -14
- package/dist/index.js +33 -12
- package/dist/interactiveInterrupt.d.ts +8 -0
- package/dist/interactiveInterrupt.js +54 -0
- package/dist/limitsWire.d.ts +5 -1
- package/dist/limitsWire.js +51 -13
- package/dist/liveModelCatalog.d.ts +109 -0
- package/dist/liveModelCatalog.js +344 -18
- package/dist/mcpEngineLeg.d.ts +25 -0
- package/dist/mcpEngineLeg.js +71 -15
- package/dist/mcpPanel.js +2 -1
- package/dist/mcpProbeCapability.d.ts +0 -1
- package/dist/mcpProbeCapability.js +13 -12
- package/dist/mcpReconnect.d.ts +1 -3
- package/dist/mcpReconnect.js +20 -10
- package/dist/memoryComplianceCapability.d.ts +0 -1
- package/dist/memoryComplianceCapability.js +14 -13
- package/dist/memoryOriginCapability.d.ts +0 -1
- package/dist/memoryOriginCapability.js +14 -13
- package/dist/memoryVerbsWire.d.ts +1 -1
- package/dist/memoryVerbsWire.js +4 -0
- package/dist/model/liveCatalogShape.d.ts +14 -0
- package/dist/model/liveCatalogShape.js +71 -0
- package/dist/model/modelSupplyRules.d.ts +1 -0
- package/dist/model/modelSupplyRules.js +30 -9
- package/dist/model/modelsPolicy.d.ts +21 -0
- package/dist/model/modelsPolicy.js +90 -0
- package/dist/modelIdentityResolvability.d.ts +4 -2
- package/dist/modelIdentityResolvability.js +25 -5
- package/dist/modelSwitchFallback.d.ts +69 -0
- package/dist/modelSwitchFallback.js +206 -0
- package/dist/notifications.js +12 -11
- package/dist/outputStyleSeatCapability.d.ts +15 -0
- package/dist/outputStyleSeatCapability.js +42 -0
- package/dist/ownKey.d.ts +7 -0
- package/dist/ownKey.js +58 -0
- package/dist/panelReduce.d.ts +114 -0
- package/dist/panelReduce.js +1135 -0
- package/dist/panelStateHolder.d.ts +17 -0
- package/dist/panelStateHolder.js +201 -0
- package/dist/peerLaneCapability.d.ts +0 -1
- package/dist/peerLaneCapability.js +15 -14
- package/dist/permissionModesCapability.d.ts +0 -1
- package/dist/permissionModesCapability.js +5 -10
- package/dist/permissionRuleIssue.js +1 -1
- package/dist/permissionRulesWriteCapability.d.ts +0 -1
- package/dist/permissionRulesWriteCapability.js +15 -14
- package/dist/permissionsAllowGrantCapability.d.ts +2 -1
- package/dist/permissionsAllowGrantCapability.js +35 -19
- package/dist/permissionsDeclaration.d.ts +16 -1
- package/dist/permissionsDeclaration.js +142 -15
- package/dist/printToolResultFrame.js +2 -10
- package/dist/promptDelivery.js +0 -8
- package/dist/protocolSegment.d.ts +1 -0
- package/dist/protocolSegment.js +13 -1
- package/dist/request/taskRequest.d.ts +11 -3
- package/dist/request/taskRequest.js +13 -1
- package/dist/resultFrameKeys.d.ts +4 -0
- package/dist/resultFrameKeys.js +13 -0
- package/dist/resumeRefusalCopy.d.ts +18 -1
- package/dist/resumeRefusalCopy.js +132 -31
- package/dist/retryStatus.js +6 -4
- package/dist/rewindArchiveCapability.d.ts +2 -1
- package/dist/rewindArchiveCapability.js +28 -15
- package/dist/rewindEngineAction.d.ts +21 -0
- package/dist/rewindEngineAction.js +36 -0
- package/dist/rewindWireCaps.d.ts +2 -1
- package/dist/rewindWireCaps.js +1 -0
- package/dist/{hitl/rosterMountedNames.d.ts → rosterMountedNames.d.ts} +1 -1
- package/dist/runCancelContext.js +2 -1
- package/dist/runTerminal.d.ts +0 -11
- package/dist/runTerminal.js +4 -27
- package/dist/sdkRegistryTransit.d.ts +2 -1
- package/dist/sdkRegistryTransit.js +1 -0
- package/dist/sealedKeyCapability.d.ts +0 -1
- package/dist/sealedKeyCapability.js +19 -20
- package/dist/seatContract.d.ts +85 -28
- package/dist/seatContract.js +512 -148
- package/dist/sessionIdSegment.d.ts +1 -0
- package/dist/sessionIdSegment.js +11 -0
- package/dist/sessionMemoryErase.d.ts +1 -1
- package/dist/sessionMemoryErase.js +6 -1
- package/dist/sessionMemoryStatus.js +3 -2
- package/dist/sessionPolicyCapability.d.ts +0 -1
- package/dist/sessionPolicyCapability.js +14 -13
- package/dist/sessionReadRedactionCapability.d.ts +15 -0
- package/dist/sessionReadRedactionCapability.js +42 -0
- package/dist/sessionSyncFileHistoryCapability.d.ts +0 -1
- package/dist/sessionSyncFileHistoryCapability.js +13 -12
- package/dist/skillToolListsCapability.d.ts +0 -1
- package/dist/skillToolListsCapability.js +13 -12
- package/dist/skillsWireCaps.d.ts +4 -0
- package/dist/skillsWireCaps.js +66 -1
- package/dist/sqlEngineCapability.d.ts +0 -1
- package/dist/sqlEngineCapability.js +21 -21
- package/dist/steerPriorityCapability.d.ts +0 -1
- package/dist/steerPriorityCapability.js +18 -19
- package/dist/storePostureCapability.d.ts +1 -1
- package/dist/storePostureCapability.js +16 -16
- package/dist/streamDrainingLegs.d.ts +6 -0
- package/dist/streamDrainingLegs.js +23 -0
- package/dist/subagent/agentStateDetail.d.ts +1 -0
- package/dist/subagent/agentStateDetail.js +41 -0
- package/dist/subagent/engineCompactWire.d.ts +15 -0
- package/dist/subagent/engineCompactWire.js +82 -45
- package/dist/subagent/engineDelegatedPrompt.js +10 -6
- package/dist/subagent/engineSubagentOutput.d.ts +0 -1
- package/dist/subagent/engineSubagentOutput.js +5 -20
- package/dist/subagent/engineSubagentTail.d.ts +0 -1
- package/dist/subagent/engineSubagentTail.js +7 -32
- package/dist/subagentContentStore.js +3 -3
- package/dist/supportFloor.js +2 -5
- package/dist/taskRequestWords.d.ts +2 -4
- package/dist/taskRequestWords.js +3 -2
- package/dist/terminalStatuses.d.ts +30 -0
- package/dist/terminalStatuses.js +67 -0
- package/dist/toolResult.d.ts +5 -0
- package/dist/toolResult.js +88 -36
- package/dist/types/engineState.d.ts +2 -1
- package/dist/usageAnalytics.d.ts +146 -0
- package/dist/usageAnalytics.js +311 -0
- package/dist/userAttachmentEnvelope.d.ts +22 -1
- package/dist/userAttachmentEnvelope.js +90 -2
- package/dist/userInvokedSkillsCapability.d.ts +0 -1
- package/dist/userInvokedSkillsCapability.js +13 -12
- package/dist/webSearchBackendCapability.d.ts +0 -1
- package/dist/webSearchBackendCapability.js +20 -19
- package/dist/webSearchWireCaps.js +3 -11
- package/dist/wireErrorTriage.d.ts +11 -0
- package/dist/wireErrorTriage.js +35 -0
- package/dist/wireFailureShape.d.ts +10 -0
- package/dist/wireFailureShape.js +72 -5
- package/dist/wireRefusalCopy.d.ts +6 -1
- package/dist/wireRefusalCopy.js +23 -25
- package/dist/wiringInstructionsAttribution.d.ts +10 -0
- package/dist/wiringInstructionsAttribution.js +67 -0
- package/dist/workflowClient.js +19 -2
- package/dist/workflowsJournalCapability.d.ts +0 -1
- package/dist/workflowsJournalCapability.js +13 -12
- package/dist/writeProtectionCapability.d.ts +0 -1
- package/dist/writeProtectionCapability.js +26 -26
- package/docs/INTEGRATION-CLIENTS.md +1733 -52
- package/package.json +5 -5
- package/dist/askSurvivesStandingAnswer.d.ts +0 -13
- package/dist/askSurvivesStandingAnswer.js +0 -53
- package/dist/engineCapsGenerationGuard.d.ts +0 -4
- package/dist/engineCapsGenerationGuard.js +0 -19
- package/dist/hitl/askSurvivesPosture.d.ts +0 -20
- package/dist/hitl/askSurvivesPosture.js +0 -48
- package/dist/panelRunningHistory.d.ts +0 -22
- package/dist/panelRunningHistory.js +0 -82
- package/dist/registryConflict.d.ts +0 -3
- package/dist/registryConflict.js +0 -44
- /package/dist/{hitl/rosterMountedNames.js → rosterMountedNames.js} +0 -0
package/dist/hitl/hitlBridge.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { askParkForeignGateKind } from '../adapter/activeRunSelfHeal.js';
|
|
2
2
|
import { eventSeq } from '../adapter/types.js';
|
|
3
3
|
import { hostLog } from '../host.js';
|
|
4
|
+
import { invokeHostCallbackIsolated } from '../hostCallbackGuard.js';
|
|
4
5
|
import { abortableSleep } from '../abortableSleep.js';
|
|
5
6
|
import { readOwnDataValue } from '../ownKey.js';
|
|
7
|
+
import { THROWN_SLOT_UNREADABLE, readThrownSlot, thrownIsInstanceOf, wireFailureTextsOf } from '../wireFailureShape.js';
|
|
8
|
+
import { decisionConflictOf } from './decisionConflict.js';
|
|
6
9
|
import { suspendedReopenOf } from './suspendedReopen.js';
|
|
7
10
|
export const DEFAULT_DENY_REASON = 'The user rejected this tool use';
|
|
8
11
|
const MAX_DENY_REASON_CHARS = 4096;
|
|
@@ -26,6 +29,14 @@ export const PLAN_REVIEW_MODE_AFTER_WORDS = Object.freeze(['default', 'acceptEdi
|
|
|
26
29
|
export function isPlanReviewModeAfter(v) {
|
|
27
30
|
return v !== undefined && PLAN_REVIEW_MODE_AFTER_WORDS.includes(v);
|
|
28
31
|
}
|
|
32
|
+
export const GATE_FAILURE_CODES = [
|
|
33
|
+
'no_pending',
|
|
34
|
+
'binding_mismatch',
|
|
35
|
+
'wrong_gate',
|
|
36
|
+
'bad_plan_edit',
|
|
37
|
+
'bad_plan_mode',
|
|
38
|
+
'empty_answer',
|
|
39
|
+
];
|
|
29
40
|
export const NO_APPROVAL_CARD_PORT_REASON = 'no approval card port installed (print/non-REPL mode, or host forgot installApprovalCardPort)';
|
|
30
41
|
export const APPROVAL_CARD_PORT_KEY_MISMATCH_REASON = 'no approval card port installed for the default session key, but a non-default sessionKey has one — likely a keyed-install/default-read mismatch (installApprovalCardPortFor vs the zero-arg default-key read), not a missing install';
|
|
31
42
|
export const NO_QUESTION_OVERLAY_REASON = 'no question overlay mounted (print/non-REPL mode)';
|
|
@@ -40,28 +51,46 @@ export class HitlSafetyError extends Error {
|
|
|
40
51
|
this.name = 'HitlSafetyError';
|
|
41
52
|
}
|
|
42
53
|
}
|
|
54
|
+
export function hitlSafetyCodeOf(e) {
|
|
55
|
+
if (!thrownIsInstanceOf(e, HitlSafetyError))
|
|
56
|
+
return undefined;
|
|
57
|
+
const raw = readThrownSlot(e, 'code');
|
|
58
|
+
return typeof raw === 'string' && GATE_FAILURE_CODES.includes(raw) ? raw : undefined;
|
|
59
|
+
}
|
|
43
60
|
const _gateCurrentPendingReadonlyPin = true;
|
|
44
61
|
void _gateCurrentPendingReadonlyPin;
|
|
45
62
|
export function readDecideCurrentPending(e) {
|
|
46
|
-
|
|
63
|
+
if (e === null || e === undefined)
|
|
64
|
+
return undefined;
|
|
65
|
+
const raw = readThrownSlot(e, 'currentPending');
|
|
47
66
|
if (typeof raw !== 'object' || raw === null)
|
|
48
67
|
return undefined;
|
|
49
|
-
const
|
|
50
|
-
|
|
68
|
+
const toolName = readThrownSlot(raw, 'toolName');
|
|
69
|
+
const boundCallId = readThrownSlot(raw, 'boundCallId');
|
|
70
|
+
const boundInputHash = readThrownSlot(raw, 'boundInputHash');
|
|
71
|
+
if (typeof toolName !== 'string' || toolName.length === 0)
|
|
51
72
|
return undefined;
|
|
52
|
-
if (typeof
|
|
73
|
+
if (typeof boundCallId !== 'string' || boundCallId.length === 0)
|
|
53
74
|
return undefined;
|
|
54
75
|
return {
|
|
55
|
-
toolName
|
|
56
|
-
boundCallId
|
|
57
|
-
...(typeof
|
|
58
|
-
? { boundInputHash
|
|
76
|
+
toolName,
|
|
77
|
+
boundCallId,
|
|
78
|
+
...(typeof boundInputHash === 'string' && boundInputHash.length > 0
|
|
79
|
+
? { boundInputHash }
|
|
59
80
|
: {}),
|
|
60
81
|
};
|
|
61
82
|
}
|
|
62
83
|
export function readWireErrorCode(e) {
|
|
63
|
-
const
|
|
64
|
-
return
|
|
84
|
+
const reading = readWireErrorCodeReading(e);
|
|
85
|
+
return reading.state === 'code' ? reading.code : undefined;
|
|
86
|
+
}
|
|
87
|
+
export function readWireErrorCodeReading(e) {
|
|
88
|
+
if (e === null || e === undefined)
|
|
89
|
+
return { state: 'absent' };
|
|
90
|
+
const raw = readThrownSlot(e, 'errorCode');
|
|
91
|
+
if (raw === THROWN_SLOT_UNREADABLE)
|
|
92
|
+
return { state: 'unreadable' };
|
|
93
|
+
return typeof raw === 'string' && raw.length > 0 ? { state: 'code', code: raw } : { state: 'absent' };
|
|
65
94
|
}
|
|
66
95
|
const DECIDE_TRANSPORT_RETRY_BACKOFF_MS = 750;
|
|
67
96
|
const DECIDE_RETRY_BACKOFF_MAX_MS = 5_000;
|
|
@@ -79,10 +108,9 @@ function decideTimeoutRetryBudgetMs() {
|
|
|
79
108
|
function isDecideAttemptTimeout(e, depth = 0) {
|
|
80
109
|
if (depth > 3 || e === null || typeof e !== 'object')
|
|
81
110
|
return false;
|
|
82
|
-
|
|
83
|
-
if (o.name === 'TimeoutError')
|
|
111
|
+
if (readThrownSlot(e, 'name') === 'TimeoutError')
|
|
84
112
|
return true;
|
|
85
|
-
return isDecideAttemptTimeout(
|
|
113
|
+
return isDecideAttemptTimeout(readThrownSlot(e, 'cause'), depth + 1);
|
|
86
114
|
}
|
|
87
115
|
const TRANSIENT_NETWORK_CODES = new Set([
|
|
88
116
|
'ECONNREFUSED', 'ECONNRESET', 'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN',
|
|
@@ -92,18 +120,21 @@ const TRANSIENT_NETWORK_CODES = new Set([
|
|
|
92
120
|
function isTransientDecideTransportFailure(e, depth = 0) {
|
|
93
121
|
if (depth > 3 || e === null || typeof e !== 'object')
|
|
94
122
|
return false;
|
|
95
|
-
if (e
|
|
123
|
+
if (thrownIsInstanceOf(e, HitlSafetyError))
|
|
96
124
|
return false;
|
|
97
|
-
const
|
|
98
|
-
if (typeof
|
|
125
|
+
const status = readThrownSlot(e, 'status');
|
|
126
|
+
if (status === THROWN_SLOT_UNREADABLE || typeof status === 'number')
|
|
99
127
|
return false;
|
|
100
|
-
|
|
128
|
+
const name = readThrownSlot(e, 'name');
|
|
129
|
+
if (name === 'TimeoutError' || name === 'AbortError')
|
|
101
130
|
return true;
|
|
102
|
-
|
|
131
|
+
const code = readThrownSlot(e, 'code');
|
|
132
|
+
if (typeof code === 'string' && TRANSIENT_NETWORK_CODES.has(code))
|
|
103
133
|
return true;
|
|
104
|
-
|
|
134
|
+
const message = readThrownSlot(e, 'message');
|
|
135
|
+
if (typeof message === 'string' && message.toLowerCase().includes('fetch failed'))
|
|
105
136
|
return true;
|
|
106
|
-
return isTransientDecideTransportFailure(
|
|
137
|
+
return isTransientDecideTransportFailure(readThrownSlot(e, 'cause'), depth + 1);
|
|
107
138
|
}
|
|
108
139
|
export class DecideTransportRetryExhaustedError extends Error {
|
|
109
140
|
attempts;
|
|
@@ -148,7 +179,7 @@ class DecideSpan {
|
|
|
148
179
|
}
|
|
149
180
|
catch (e) {
|
|
150
181
|
this.ok = false;
|
|
151
|
-
this.retryExhausted = e
|
|
182
|
+
this.retryExhausted = thrownIsInstanceOf(e, DecideTransportRetryExhaustedError);
|
|
152
183
|
throw e;
|
|
153
184
|
}
|
|
154
185
|
finally {
|
|
@@ -174,32 +205,13 @@ class DecideSpan {
|
|
|
174
205
|
notifyDecideObserver(this.observer, Object.freeze({ ...this.identity, phase: 'end', ok: this.ok, attempts: this.attempts, retryExhausted: this.retryExhausted }));
|
|
175
206
|
}
|
|
176
207
|
}
|
|
177
|
-
function reportObserverFault(phase, what, e) {
|
|
178
|
-
try {
|
|
179
|
-
hostLog('debug', `hitlBridge: onDecideOperation(${phase}) ${what}: ${String(e).slice(0, 160)}`);
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
catch {
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
208
|
function wireOptsOf(opts) {
|
|
187
209
|
if (opts === undefined || opts.operation === undefined)
|
|
188
210
|
return opts;
|
|
189
211
|
return opts.signal !== undefined ? { signal: opts.signal } : undefined;
|
|
190
212
|
}
|
|
191
213
|
function notifyDecideObserver(observer, ev) {
|
|
192
|
-
|
|
193
|
-
const out = observer(ev);
|
|
194
|
-
if (out && typeof out.then === 'function') {
|
|
195
|
-
void Promise.resolve(out).then(undefined, (e) => {
|
|
196
|
-
reportObserverFault(ev.phase, 'rejected', e);
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
catch (e) {
|
|
201
|
-
reportObserverFault(ev.phase, 'threw', e);
|
|
202
|
-
}
|
|
214
|
+
invokeHostCallbackIsolated(`hitlBridge: onDecideOperation(${ev.phase})`, () => observer(ev));
|
|
203
215
|
}
|
|
204
216
|
const ANY_TOOL_FAMILY = () => true;
|
|
205
217
|
export async function findPendingForTask(client, taskId, matches, opts, callId, identityAccepts = (r) => matches(typeof r.toolName === 'string' ? r.toolName : undefined)) {
|
|
@@ -208,7 +220,9 @@ export async function findPendingForTask(client, taskId, matches, opts, callId,
|
|
|
208
220
|
rows = (await client.approvals.list(opts)).pending;
|
|
209
221
|
}
|
|
210
222
|
catch (e) {
|
|
211
|
-
|
|
223
|
+
const t = wireFailureTextsOf(e);
|
|
224
|
+
hostLog('debug', `hitlBridge: approvals.list failed: ${t.log}`);
|
|
225
|
+
return { ok: false, reason: `approvals.list failed: ${t.reason}` };
|
|
212
226
|
}
|
|
213
227
|
const decidable = rows.filter((r) => askParkForeignGateKind(r) === null);
|
|
214
228
|
const identityRow = callId !== undefined
|
|
@@ -327,13 +341,8 @@ export class HitlBridge {
|
|
|
327
341
|
throw new HitlSafetyError(`plan-review "${outcome.decision}" must NOT carry editedPlan`, 'bad_plan_edit');
|
|
328
342
|
}
|
|
329
343
|
const modeAfter = outcome.permissionModeAfter;
|
|
330
|
-
if (modeAfter !== undefined) {
|
|
331
|
-
|
|
332
|
-
throw new HitlSafetyError(`plan-review "${outcome.decision}" must NOT carry permissionModeAfter (it only applies to an approval)`, 'bad_plan_mode');
|
|
333
|
-
}
|
|
334
|
-
if (!isPlanReviewModeAfter(modeAfter)) {
|
|
335
|
-
throw new HitlSafetyError('plan-review permissionModeAfter must be "default" or "acceptEdits"', 'bad_plan_mode');
|
|
336
|
-
}
|
|
344
|
+
if (modeAfter !== undefined && !isPlanReviewModeAfter(modeAfter)) {
|
|
345
|
+
throw new HitlSafetyError('plan-review permissionModeAfter must be "default" or "acceptEdits"', 'bad_plan_mode');
|
|
337
346
|
}
|
|
338
347
|
const req = { decision: outcome.decision };
|
|
339
348
|
if (modeAfter !== undefined && isPlanReviewModeAfter(modeAfter))
|
|
@@ -376,7 +385,7 @@ export class HitlBridge {
|
|
|
376
385
|
return r;
|
|
377
386
|
}
|
|
378
387
|
catch (e) {
|
|
379
|
-
retryExhausted = e
|
|
388
|
+
retryExhausted = thrownIsInstanceOf(e, DecideTransportRetryExhaustedError);
|
|
380
389
|
throw e;
|
|
381
390
|
}
|
|
382
391
|
finally {
|
|
@@ -409,18 +418,21 @@ export class HitlBridge {
|
|
|
409
418
|
return r;
|
|
410
419
|
}
|
|
411
420
|
catch (e) {
|
|
412
|
-
|
|
421
|
+
const binding = bindingMismatchReading(e);
|
|
422
|
+
if (binding === 'mismatch') {
|
|
413
423
|
throw new HitlSafetyError('approval_binding_mismatch — the pending action changed under the human; refetch + re-present', 'binding_mismatch');
|
|
414
424
|
}
|
|
425
|
+
if (binding === 'unreadable')
|
|
426
|
+
throw e;
|
|
415
427
|
if (!isTransientDecideTransportFailure(e) || callerAborted())
|
|
416
428
|
throw e;
|
|
417
429
|
if (isDecideAttemptTimeout(e)) {
|
|
418
430
|
if (attempts >= DECIDE_TIMEOUT_MIN_ATTEMPTS && Date.now() - startedAt >= decideTimeoutRetryBudgetMs()) {
|
|
419
|
-
throw new DecideTransportRetryExhaustedError(attempts,
|
|
431
|
+
throw new DecideTransportRetryExhaustedError(attempts, wireFailureTextsOf(e).reason);
|
|
420
432
|
}
|
|
421
433
|
}
|
|
422
434
|
else if (netRetriesUsed >= 1) {
|
|
423
|
-
throw new DecideTransportRetryExhaustedError(attempts,
|
|
435
|
+
throw new DecideTransportRetryExhaustedError(attempts, wireFailureTextsOf(e).reason);
|
|
424
436
|
}
|
|
425
437
|
else {
|
|
426
438
|
netRetriesUsed++;
|
|
@@ -481,16 +493,17 @@ function marshalAnswer(a) {
|
|
|
481
493
|
entry.note = a.note;
|
|
482
494
|
return entry;
|
|
483
495
|
}
|
|
484
|
-
function
|
|
496
|
+
function bindingMismatchReading(e) {
|
|
485
497
|
if (!e || typeof e !== 'object')
|
|
486
|
-
return
|
|
487
|
-
const
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
498
|
+
return 'not';
|
|
499
|
+
const code = readWireErrorCodeReading(e);
|
|
500
|
+
const name = readThrownSlot(e, 'name');
|
|
501
|
+
const family = (code.state === 'code' && code.code === 'approval_binding_mismatch') || name === 'ApprovalBindingMismatchError';
|
|
502
|
+
if (family)
|
|
503
|
+
return decisionConflictOf(e) !== 'answer_invalid' ? 'mismatch' : 'not';
|
|
504
|
+
if (code.state === 'unreadable')
|
|
505
|
+
return 'unreadable';
|
|
506
|
+
return 'not';
|
|
494
507
|
}
|
|
495
508
|
export function backendDeny(reason) {
|
|
496
509
|
return {
|
|
@@ -23,6 +23,7 @@ export declare function hitlHostSurfaceFor(sessionKey: string): HitlHostSurface
|
|
|
23
23
|
export declare function _resetHitlHostSurfaceForTest(): void;
|
|
24
24
|
export declare function surfaceForCurrentSession(): HitlHostSurface | null;
|
|
25
25
|
export declare const CANCEL_DENY_BUDGET_MS = 2000;
|
|
26
|
+
export declare const INTERRUPT_DENY_REASON = "Interrupted by user";
|
|
26
27
|
export declare const CANCEL_DENY_WARN_TEXT = "could not cancel the pending question \u2014 the session may stay locked; the run may need engine-side recovery";
|
|
27
28
|
export declare const REMEMBER_NOT_APPLIED_WARN_TEXT = "this session-wide allow was not remembered by the worker \u2014 you will be asked again for this tool";
|
|
28
29
|
export declare const EDIT_NOT_FORWARDED_WARN_TEXT = "your edited tool input was NOT forwarded \u2014 the tool is running with the ORIGINAL input you saw before editing";
|
|
@@ -31,6 +32,8 @@ export declare function surfaceEditNotForwarded(): void;
|
|
|
31
32
|
export declare const APPROVAL_PARKING_WARN_TEXT = "This approval is being parked; answer it again on the parked card when it appears.";
|
|
32
33
|
export declare function approvalParkingNoticeText(retryAfterMs?: number): string;
|
|
33
34
|
export declare function surfaceApprovalParking(retryAfterMs?: number): void;
|
|
35
|
+
export declare const COMPACT_NOT_RUNNING_WARN_TEXT = "engine run finished before compaction was applied; nothing was compacted";
|
|
36
|
+
export declare function surfaceCompactNotRunning(sessionKey?: string): void;
|
|
34
37
|
export declare const REPLAYED_APPROVAL_LIST_UNREADABLE_WARN_TEXT: string;
|
|
35
38
|
export declare function surfaceReplayedApprovalListUnreadable(): void;
|
|
36
39
|
export declare const EDIT_REFUSED_ON_BLIND_ASK_WARN_TEXT: string;
|
|
@@ -2,7 +2,7 @@ import { createSessionSlot, DEFAULT_SESSION_KEY } from '../sessionSlot.js';
|
|
|
2
2
|
import { hostLog } from '../host.js';
|
|
3
3
|
import { unrefTimer } from '../unrefTimer.js';
|
|
4
4
|
import { decideFailureNote } from '../decideFailureNote.js';
|
|
5
|
-
import {
|
|
5
|
+
import { decisionRefusalSaysAskGone } from './decisionRefusal.js';
|
|
6
6
|
const hostSurfaceByKey = createSessionSlot();
|
|
7
7
|
const hostSurfaceMissesByKey = new Map();
|
|
8
8
|
export function installHitlHostSurface(surface) {
|
|
@@ -29,22 +29,26 @@ export function _resetHitlHostSurfaceForTest() {
|
|
|
29
29
|
hostSurfaceMissesByKey.clear();
|
|
30
30
|
}
|
|
31
31
|
export function surfaceForCurrentSession() {
|
|
32
|
-
|
|
32
|
+
return surfaceForSession(DEFAULT_SESSION_KEY);
|
|
33
|
+
}
|
|
34
|
+
function surfaceForSession(sessionKey) {
|
|
35
|
+
const hostSurface = hitlHostSurfaceFor(sessionKey);
|
|
33
36
|
if (hostSurface === null) {
|
|
34
|
-
hostSurfaceMissesByKey.set(
|
|
37
|
+
hostSurfaceMissesByKey.set(sessionKey, (hostSurfaceMissesByKey.get(sessionKey) ?? 0) + 1);
|
|
35
38
|
}
|
|
36
39
|
return hostSurface;
|
|
37
40
|
}
|
|
38
41
|
export const CANCEL_DENY_BUDGET_MS = 2000;
|
|
42
|
+
export const INTERRUPT_DENY_REASON = 'Interrupted by user';
|
|
39
43
|
export const CANCEL_DENY_WARN_TEXT = 'could not cancel the pending question — the session may stay locked; the run may need engine-side recovery';
|
|
40
44
|
const CANCEL_DENY_WARN_KEY = 'hitl-cancel-deny-warn';
|
|
41
45
|
const CANCEL_DENY_WARN_TIMEOUT_MS = 10_000;
|
|
42
46
|
function surfaceCancelDenyWarn(text = CANCEL_DENY_WARN_TEXT) {
|
|
43
47
|
surfaceSelfClearingWarn(CANCEL_DENY_WARN_KEY, text, CANCEL_DENY_WARN_TIMEOUT_MS);
|
|
44
48
|
}
|
|
45
|
-
function surfaceSelfClearingWarn(key, text, timeoutMs) {
|
|
49
|
+
function surfaceSelfClearingWarn(key, text, timeoutMs, sessionKey = DEFAULT_SESSION_KEY) {
|
|
46
50
|
try {
|
|
47
|
-
const s =
|
|
51
|
+
const s = surfaceForSession(sessionKey);
|
|
48
52
|
if (!s)
|
|
49
53
|
return;
|
|
50
54
|
s.showNotice({ key, text, color: 'warning', priority: 'immediate', timeoutMs });
|
|
@@ -83,6 +87,12 @@ export function approvalParkingNoticeText(retryAfterMs) {
|
|
|
83
87
|
export function surfaceApprovalParking(retryAfterMs) {
|
|
84
88
|
surfaceSelfClearingWarn(APPROVAL_PARKING_KEY, approvalParkingNoticeText(retryAfterMs), APPROVAL_PARKING_TIMEOUT_MS);
|
|
85
89
|
}
|
|
90
|
+
export const COMPACT_NOT_RUNNING_WARN_TEXT = 'engine run finished before compaction was applied; nothing was compacted';
|
|
91
|
+
const COMPACT_NOT_RUNNING_KEY = 'engine-compact-not-running';
|
|
92
|
+
const COMPACT_NOT_RUNNING_TIMEOUT_MS = 10_000;
|
|
93
|
+
export function surfaceCompactNotRunning(sessionKey = DEFAULT_SESSION_KEY) {
|
|
94
|
+
surfaceSelfClearingWarn(COMPACT_NOT_RUNNING_KEY, COMPACT_NOT_RUNNING_WARN_TEXT, COMPACT_NOT_RUNNING_TIMEOUT_MS, sessionKey);
|
|
95
|
+
}
|
|
86
96
|
export const REPLAYED_APPROVAL_LIST_UNREADABLE_WARN_TEXT = "Could not read the pending-approval list, so an approval request read back from this run's event log was not raised as a question, " +
|
|
87
97
|
'and no decision was sent for it.';
|
|
88
98
|
const REPLAYED_APPROVAL_LIST_UNREADABLE_KEY = 'hitl-replayed-approval-list-unreadable';
|
|
@@ -123,14 +133,6 @@ const RULE_NOT_SENT_REJECTED_TIMEOUT_MS = 10_000;
|
|
|
123
133
|
export function surfaceRuleArmRejected(why) {
|
|
124
134
|
surfaceSelfClearingWarn(RULE_NOT_SENT_REJECTED_KEY, ruleNotSentRejectedText(why), RULE_NOT_SENT_REJECTED_TIMEOUT_MS);
|
|
125
135
|
}
|
|
126
|
-
function isNoPendingError(e) {
|
|
127
|
-
if (e instanceof HitlSafetyError)
|
|
128
|
-
return e.code === 'no_pending';
|
|
129
|
-
if (typeof e !== 'object' || e === null || !('code' in e))
|
|
130
|
-
return false;
|
|
131
|
-
const code = e.code;
|
|
132
|
-
return typeof code === 'string' && code === 'no_pending';
|
|
133
|
-
}
|
|
134
136
|
export function observeCancelByDeny(settle, taskId) {
|
|
135
137
|
let timer;
|
|
136
138
|
const budget = new Promise((_, reject) => {
|
|
@@ -142,8 +144,8 @@ export function observeCancelByDeny(settle, taskId) {
|
|
|
142
144
|
hostLog('debug', `[hitl-cancel-deny] cancel-by-deny settled for run ${taskId} (session unlocked)`);
|
|
143
145
|
})
|
|
144
146
|
.catch((e) => {
|
|
145
|
-
if (
|
|
146
|
-
hostLog('debug', `[hitl-cancel-deny] cancel-by-deny
|
|
147
|
+
if (decisionRefusalSaysAskGone(e)) {
|
|
148
|
+
hostLog('debug', `[hitl-cancel-deny] cancel-by-deny found the question no longer pending for run ${taskId} (benign — settled elsewhere, parked or gone)`);
|
|
147
149
|
return;
|
|
148
150
|
}
|
|
149
151
|
const rowNote = decideFailureNote(e, 'deny');
|
|
@@ -22,16 +22,26 @@ export type LivePendingReading = {
|
|
|
22
22
|
dropped: number;
|
|
23
23
|
};
|
|
24
24
|
export declare function readLivePendingRows(body: unknown): LivePendingReading;
|
|
25
|
-
export
|
|
26
|
-
sessionId
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
export type SuspendedAskFilter = {
|
|
26
|
+
readonly sessionId: string;
|
|
27
|
+
readonly allSessions?: never;
|
|
28
|
+
readonly identityPending?: never;
|
|
29
|
+
} | {
|
|
30
|
+
readonly allSessions: true;
|
|
31
|
+
readonly sessionId?: never;
|
|
32
|
+
readonly identityPending?: never;
|
|
33
|
+
} | {
|
|
34
|
+
readonly identityPending: true;
|
|
35
|
+
readonly sessionId?: never;
|
|
36
|
+
readonly allSessions?: never;
|
|
37
|
+
};
|
|
38
|
+
export declare function suspendedSubagentAsks(snapshot: ApprovalsFeedEmission | null | undefined, filter: SuspendedAskFilter): LivePendingAskView[];
|
|
29
39
|
export interface ApprovalsAwaitingDecisionCount {
|
|
30
40
|
durable: number | null;
|
|
31
41
|
live: number | null;
|
|
32
42
|
suspendedSubagent: number | null;
|
|
33
43
|
}
|
|
34
|
-
export declare function countApprovalsAwaitingDecision(snapshot: ApprovalsFeedEmission | null | undefined, filter
|
|
44
|
+
export declare function countApprovalsAwaitingDecision(snapshot: ApprovalsFeedEmission | null | undefined, filter: SuspendedAskFilter): ApprovalsAwaitingDecisionCount;
|
|
35
45
|
export declare function livePendingRowToApprovalFrame(row: LivePendingAskView): ToolApprovalFrame;
|
|
36
46
|
export declare function surfaceSuspendedAskAndRespond(row: LivePendingAskView, respond: RespondToolApprovalFn, signal?: AbortSignal, lane?: ToolApprovalFrameLaneOpts): Promise<ToolApprovalFrameOutcome>;
|
|
37
47
|
export interface SuspendedAskDelta {
|
|
@@ -45,4 +55,4 @@ export interface SuspendedAskTracker {
|
|
|
45
55
|
requeue(approvalId: string): void;
|
|
46
56
|
noteDecided(approvalId: string): void;
|
|
47
57
|
}
|
|
48
|
-
export declare function createSuspendedAskTracker(filter
|
|
58
|
+
export declare function createSuspendedAskTracker(filter: SuspendedAskFilter): SuspendedAskTracker;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { THROWN_SLOT_UNREADABLE, readThrownSlot } from '../wireFailureShape.js';
|
|
1
2
|
import { isToolApprovalFrame, surfaceToolApprovalFrameAndRespond, } from './toolApprovalWire.js';
|
|
2
3
|
function nonEmptyString(v) {
|
|
3
4
|
return typeof v === 'string' && v !== '';
|
|
@@ -69,20 +70,48 @@ export function readLivePendingRows(body) {
|
|
|
69
70
|
return { kind: 'malformed' };
|
|
70
71
|
return { kind: 'present', rows, dropped };
|
|
71
72
|
}
|
|
72
|
-
|
|
73
|
+
const IDENTITY_PENDING_SCOPE = Object.freeze({ kind: 'identity_pending' });
|
|
74
|
+
function suspendedAskScopeOf(filter) {
|
|
75
|
+
if (typeof filter !== 'object' || filter === null)
|
|
76
|
+
return IDENTITY_PENDING_SCOPE;
|
|
77
|
+
const sessionId = readThrownSlot(filter, 'sessionId', true);
|
|
78
|
+
const allSessions = readThrownSlot(filter, 'allSessions', true);
|
|
79
|
+
const identityPending = readThrownSlot(filter, 'identityPending', true);
|
|
80
|
+
if (sessionId === THROWN_SLOT_UNREADABLE || allSessions === THROWN_SLOT_UNREADABLE || identityPending === THROWN_SLOT_UNREADABLE)
|
|
81
|
+
return IDENTITY_PENDING_SCOPE;
|
|
82
|
+
const sessionOk = typeof sessionId === 'string' && sessionId !== '';
|
|
83
|
+
const allOk = allSessions === true;
|
|
84
|
+
const pendingOk = identityPending === true;
|
|
85
|
+
if ((sessionId !== undefined && !sessionOk) || (allSessions !== undefined && !allOk) || (identityPending !== undefined && !pendingOk))
|
|
86
|
+
return IDENTITY_PENDING_SCOPE;
|
|
87
|
+
if (sessionOk && !allOk && !pendingOk)
|
|
88
|
+
return { kind: 'session', sessionId };
|
|
89
|
+
if (allOk && !sessionOk && !pendingOk)
|
|
90
|
+
return { kind: 'all' };
|
|
91
|
+
return IDENTITY_PENDING_SCOPE;
|
|
92
|
+
}
|
|
93
|
+
function subagentAsksIn(snapshot, scope) {
|
|
94
|
+
if (scope.kind === 'identity_pending')
|
|
95
|
+
return [];
|
|
73
96
|
if (snapshot?.kind === 'unknown')
|
|
74
97
|
return [];
|
|
75
98
|
const rows = snapshot?.livePending;
|
|
76
99
|
if (!Array.isArray(rows))
|
|
77
100
|
return [];
|
|
78
|
-
return rows.filter(r => r.fromSubagent === true && (
|
|
101
|
+
return rows.filter(r => r.fromSubagent === true && (scope.kind === 'all' || r.sessionId === scope.sessionId));
|
|
102
|
+
}
|
|
103
|
+
export function suspendedSubagentAsks(snapshot, filter) {
|
|
104
|
+
return subagentAsksIn(snapshot, suspendedAskScopeOf(filter));
|
|
79
105
|
}
|
|
80
106
|
export function countApprovalsAwaitingDecision(snapshot, filter) {
|
|
107
|
+
const scope = suspendedAskScopeOf(filter);
|
|
108
|
+
if (scope.kind === 'identity_pending')
|
|
109
|
+
return { durable: null, live: null, suspendedSubagent: null };
|
|
81
110
|
if (snapshot === null || snapshot === undefined)
|
|
82
111
|
return { durable: null, live: null, suspendedSubagent: null };
|
|
83
112
|
if (snapshot.kind === 'unknown')
|
|
84
113
|
return { durable: null, live: null, suspendedSubagent: null };
|
|
85
|
-
const bySession = (rows) =>
|
|
114
|
+
const bySession = (rows) => scope.kind === 'session' ? rows.filter(r => r.sessionId === scope.sessionId) : [...rows];
|
|
86
115
|
const durable = (snapshot.pendingDropped ?? 0) > 0 ? null : Array.isArray(snapshot.pending) ? bySession(snapshot.pending).length : null;
|
|
87
116
|
if (!Array.isArray(snapshot.livePending))
|
|
88
117
|
return { durable, live: null, suspendedSubagent: null };
|
|
@@ -113,6 +142,7 @@ export function surfaceSuspendedAskAndRespond(row, respond, signal, lane) {
|
|
|
113
142
|
}
|
|
114
143
|
const TRACKER_UNSEEN_CLAIMS_MAX = 512;
|
|
115
144
|
export function createSuspendedAskTracker(filter) {
|
|
145
|
+
const scope = suspendedAskScopeOf(filter);
|
|
116
146
|
const shown = new Set();
|
|
117
147
|
const shownWithFrame = new Set();
|
|
118
148
|
const claimed = new Map();
|
|
@@ -137,7 +167,9 @@ export function createSuspendedAskTracker(filter) {
|
|
|
137
167
|
ingest(snapshot) {
|
|
138
168
|
if (snapshot?.kind === 'unknown')
|
|
139
169
|
return { appeared: [], gone: [], upgraded: [] };
|
|
140
|
-
|
|
170
|
+
if (scope.kind === 'identity_pending')
|
|
171
|
+
return { appeared: [], gone: [], upgraded: [] };
|
|
172
|
+
const rows = subagentAsksIn(snapshot, scope);
|
|
141
173
|
const present = new Set(rows.map(r => r.approvalId));
|
|
142
174
|
const appeared = [];
|
|
143
175
|
const upgraded = [];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { wireFailureTextsOf } from '../wireFailureShape.js';
|
|
1
2
|
const BASH_TOOL_NAME_FOR_RULES = 'Bash';
|
|
2
3
|
export function parseLocalAllowRule(rule, expectedToolName, deps) {
|
|
3
4
|
if (typeof rule !== 'string' || rule === '') {
|
|
@@ -8,7 +9,7 @@ export function parseLocalAllowRule(rule, expectedToolName, deps) {
|
|
|
8
9
|
value = deps.parseRule(rule);
|
|
9
10
|
}
|
|
10
11
|
catch (e) {
|
|
11
|
-
return { ok: false, error: `rule text did not parse (${
|
|
12
|
+
return { ok: false, error: `rule text did not parse (${wireFailureTextsOf(e).reason})` };
|
|
12
13
|
}
|
|
13
14
|
if (typeof value.toolName !== 'string' || value.toolName === '') {
|
|
14
15
|
return { ok: false, error: 'rule text carries no tool name' };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type NoAllowCause = 'no_allow_rule' | 'ask_rule' | 'budget' | 'other';
|
|
2
|
+
export interface RuleLadderNoAllowFacts {
|
|
3
|
+
readonly allowed?: boolean;
|
|
4
|
+
readonly denied?: boolean;
|
|
5
|
+
readonly askRuleMatched?: boolean;
|
|
6
|
+
readonly budgetExhausted?: boolean;
|
|
7
|
+
readonly noRuleMatched?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function noAllowCauseOf(card: object | null | undefined, ladder: RuleLadderNoAllowFacts | null | undefined): NoAllowCause | undefined;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { automaticAnswerVerdict } from './automaticAnswerVerdict.js';
|
|
2
|
+
function ladderSays(ladder, key) {
|
|
3
|
+
if (typeof ladder !== 'object' || ladder === null)
|
|
4
|
+
return false;
|
|
5
|
+
try {
|
|
6
|
+
const d = Object.getOwnPropertyDescriptor(ladder, key);
|
|
7
|
+
return d !== undefined && 'value' in d && d.value === true;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function noAllowCauseOf(card, ladder) {
|
|
14
|
+
if (ladderSays(ladder, 'allowed') || ladderSays(ladder, 'denied'))
|
|
15
|
+
return undefined;
|
|
16
|
+
if (ladderSays(ladder, 'askRuleMatched'))
|
|
17
|
+
return 'ask_rule';
|
|
18
|
+
if (ladderSays(ladder, 'budgetExhausted'))
|
|
19
|
+
return 'budget';
|
|
20
|
+
const standing = automaticAnswerVerdict(card, 'standing_rule');
|
|
21
|
+
if (standing.kind === 'must_ask' && (standing.askClass === 'ask_rule' || standing.origin === 'ask_rule'))
|
|
22
|
+
return 'ask_rule';
|
|
23
|
+
if (ladderSays(ladder, 'noRuleMatched') && standing.kind === 'may_answer')
|
|
24
|
+
return 'no_allow_rule';
|
|
25
|
+
return 'other';
|
|
26
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type ApprovalCompleteDisposition = 'live-expired-parked' | 'live-expired-retract' | 'settled' | null;
|
|
2
|
+
export declare function classifyApprovalCompleteFrame(frame: unknown): ApprovalCompleteDisposition;
|
|
3
|
+
export type ParkRowDeadlineState = {
|
|
4
|
+
kind: 'none';
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'pending';
|
|
7
|
+
deadlineMs: number;
|
|
8
|
+
remainingMs: number;
|
|
9
|
+
} | {
|
|
10
|
+
kind: 'past';
|
|
11
|
+
deadlineMs: number;
|
|
12
|
+
remainingMs: number;
|
|
13
|
+
};
|
|
14
|
+
export declare function parkRowDeadlineState(row: unknown, nowMs: number): ParkRowDeadlineState;
|
|
15
|
+
export declare function lateDecideRoute(o: {
|
|
16
|
+
windowClosed: boolean;
|
|
17
|
+
durableRowFound: boolean;
|
|
18
|
+
}): 'decide' | 'respond';
|
|
19
|
+
export declare function runReapedByDeadline(client: unknown, taskId: string): Promise<boolean>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { APPROVAL_EXPIRED } from '../engineErrorCodes.js';
|
|
2
|
+
import { approvalCompleteParked } from './approvalCompleteParked.js';
|
|
3
|
+
export function classifyApprovalCompleteFrame(frame) {
|
|
4
|
+
if (typeof frame !== 'object' || frame === null)
|
|
5
|
+
return null;
|
|
6
|
+
const f = frame;
|
|
7
|
+
if (f.type !== 'tool_approval_complete')
|
|
8
|
+
return null;
|
|
9
|
+
const outcome = f.outcome;
|
|
10
|
+
if (outcome === 'allowed' || outcome === 'denied')
|
|
11
|
+
return 'settled';
|
|
12
|
+
if (outcome !== 'expired')
|
|
13
|
+
return null;
|
|
14
|
+
return approvalCompleteParked(frame) ? 'live-expired-parked' : 'live-expired-retract';
|
|
15
|
+
}
|
|
16
|
+
const PARK_DEADLINE_MAX_SANE_MS = 24 * 60 * 60 * 1000;
|
|
17
|
+
export function parkRowDeadlineState(row, nowMs) {
|
|
18
|
+
if (typeof row !== 'object' || row === null)
|
|
19
|
+
return { kind: 'none' };
|
|
20
|
+
const raw = row.deadline;
|
|
21
|
+
if (typeof raw !== 'number' || !Number.isFinite(raw) || raw <= 0)
|
|
22
|
+
return { kind: 'none' };
|
|
23
|
+
const remainingMs = raw - nowMs;
|
|
24
|
+
if (remainingMs > PARK_DEADLINE_MAX_SANE_MS)
|
|
25
|
+
return { kind: 'none' };
|
|
26
|
+
return remainingMs > 0
|
|
27
|
+
? { kind: 'pending', deadlineMs: raw, remainingMs }
|
|
28
|
+
: { kind: 'past', deadlineMs: raw, remainingMs };
|
|
29
|
+
}
|
|
30
|
+
export function lateDecideRoute(o) {
|
|
31
|
+
if (!o.windowClosed)
|
|
32
|
+
return 'respond';
|
|
33
|
+
return o.durableRowFound ? 'decide' : 'respond';
|
|
34
|
+
}
|
|
35
|
+
export async function runReapedByDeadline(client, taskId) {
|
|
36
|
+
try {
|
|
37
|
+
const runs = client?.runs;
|
|
38
|
+
if (typeof runs?.get !== 'function')
|
|
39
|
+
return false;
|
|
40
|
+
const rec = (await runs.get(taskId));
|
|
41
|
+
return rec?.errorCode === APPROVAL_EXPIRED;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { AgentEvent } from '@sema-agent/sdk';
|
|
2
|
-
import { type GateCurrentPending, type HitlFailureStage } from './hitlBridge.js';
|
|
2
|
+
import { type GateCurrentPending, type HitlFailureStage, type HitlSafetyCode } from './hitlBridge.js';
|
|
3
3
|
import { type QuestionAnswer } from '../liveQuestionStore.js';
|
|
4
|
-
import { type FsApprovalOutcome } from './toolApprovalWire.js';
|
|
5
4
|
import type { AskAnsweredOutput, GateLedger } from './gateLedger.js';
|
|
6
5
|
import { type AskGateWireDeps, type GatePark } from './frameRouter.js';
|
|
7
6
|
import { type DecideReceiptView } from '../decideReceipt.js';
|
|
@@ -13,8 +12,7 @@ export interface HopBudget {
|
|
|
13
12
|
}
|
|
14
13
|
export declare function nextHopBudget(prev: HopBudget | undefined, round: HopRound): HopBudget;
|
|
15
14
|
export declare const MAX_TOTAL_PARKS = 64;
|
|
16
|
-
export
|
|
17
|
-
export type GateFailureCode = (typeof GATE_FAILURE_CODES)[number];
|
|
15
|
+
export type GateFailureCode = HitlSafetyCode;
|
|
18
16
|
export type GateOutcome = {
|
|
19
17
|
kind: 'decided';
|
|
20
18
|
gatedCallId?: string | undefined;
|
|
@@ -35,9 +33,7 @@ export type GateOutcome = {
|
|
|
35
33
|
currentPending?: GateCurrentPending | undefined;
|
|
36
34
|
};
|
|
37
35
|
export declare function isAlreadyResolvedGateReason(reason: unknown): boolean;
|
|
38
|
-
export declare function isAlreadyResolvedFailure(
|
|
39
|
-
kind: 'failed';
|
|
40
|
-
}>): boolean;
|
|
36
|
+
export declare function isAlreadyResolvedFailure(failure: unknown): boolean;
|
|
41
37
|
export declare function isGateStandingErrorCode(code: string | null | undefined, retriable?: boolean): boolean;
|
|
42
38
|
export declare function isCodeClassifiedGateFailure(code: string | null | undefined, retriable?: boolean): boolean;
|
|
43
39
|
export declare function toAnsweredOutput(questions: unknown[], answer: QuestionAnswer): AskAnsweredOutput;
|