@sema-agent/client-core 0.97.0 → 0.98.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 +429 -0
- package/README.md +74 -36
- package/dist/adapt/arms.d.ts +1 -0
- package/dist/adapt/arms.js +128 -34
- package/dist/adapt/ids.d.ts +12 -1
- package/dist/adapt/ids.js +59 -8
- package/dist/adapt/instanceLedger.d.ts +50 -0
- package/dist/adapt/instanceLedger.js +147 -0
- package/dist/adapt/textStream.d.ts +1 -0
- package/dist/adapt/textStream.js +24 -7
- package/dist/adapt/toolCards.d.ts +27 -5
- package/dist/adapt/toolCards.js +39 -6
- package/dist/adapt/wireShapes.js +6 -2
- package/dist/adapt.d.ts +2 -0
- package/dist/adapt.js +8 -3
- package/dist/adapter/activeRunSelfHeal.d.ts +5 -0
- package/dist/adapter/activeRunSelfHeal.js +51 -28
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -5
- package/dist/adapter/downstream/eventToSdkMessage.js +27 -34
- package/dist/adapter/downstream/terminalToSdkResult.js +11 -4
- package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +5 -2
- package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -0
- package/dist/adapter/runStream.js +29 -13
- package/dist/adapter/types.d.ts +4 -4
- package/dist/agentSession/backgroundView.js +2 -1
- package/dist/agentSession/engineAgentRegistryRead.d.ts +2 -2
- package/dist/agentSession/engineAgentRegistryRead.js +12 -13
- package/dist/agentsWireCaps.d.ts +8 -6
- package/dist/agentsWireCaps.js +177 -162
- package/dist/approvalDecidedByCapability.d.ts +0 -4
- package/dist/approvalDecidedByCapability.js +0 -6
- package/dist/approvalsStreamLiveCapability.d.ts +0 -4
- package/dist/approvalsStreamLiveCapability.js +0 -6
- package/dist/assistantInbox.d.ts +34 -0
- package/dist/assistantInbox.js +118 -0
- package/dist/centerWiringCapability.js +9 -1
- package/dist/clientSlice.d.ts +0 -9
- package/dist/clientSlice.js +0 -3
- package/dist/cloudConfigWireCaps.d.ts +4 -2
- package/dist/cloudConfigWireCaps.js +81 -61
- package/dist/compensations.js +1 -1
- package/dist/connectorStatus.d.ts +21 -0
- package/dist/connectorStatus.js +112 -0
- package/dist/controlRouter.d.ts +14 -1
- package/dist/controlRouter.js +68 -17
- package/dist/coreValuePorts.d.ts +3 -3
- package/dist/decideReceipt.d.ts +2 -2
- package/dist/decideReceipt.js +5 -2
- package/dist/declared/supportFloorDeclared.js +3 -3
- package/dist/deviceExecutorManagementCapability.d.ts +0 -4
- package/dist/deviceExecutorManagementCapability.js +0 -6
- package/dist/deviceRebind.d.ts +49 -1
- package/dist/deviceRebind.js +221 -3
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +250 -76
- package/dist/engineAgentAbsence.d.ts +1 -1
- package/dist/engineAgentPanelStore.d.ts +5 -4
- package/dist/engineAgentPanelStore.js +3 -12
- package/dist/engineCapReader.d.ts +0 -4
- package/dist/engineCapReader.js +1 -5
- package/dist/engineCapsCache.d.ts +4 -0
- package/dist/engineCapsCache.js +17 -12
- package/dist/engineClosedSets.d.ts +1 -0
- package/dist/engineClosedSets.js +4 -1
- package/dist/engineErrorCodes.d.ts +9 -2
- package/dist/engineErrorCodes.js +9 -1
- package/dist/engineIdentity.d.ts +1 -0
- package/dist/engineIdentity.js +8 -0
- package/dist/engineRowRef.d.ts +28 -0
- package/dist/engineRowRef.js +111 -0
- package/dist/engineSessionMessages.d.ts +67 -0
- package/dist/engineSessionMessages.js +364 -0
- package/dist/engineToolDirectory.d.ts +18 -0
- package/dist/engineToolDirectory.js +85 -0
- package/dist/engineUrl.d.ts +18 -0
- package/dist/engineUrl.js +52 -0
- package/dist/env/uiLanguage.d.ts +9 -0
- package/dist/env/uiLanguage.js +35 -0
- package/dist/eventLeg.d.ts +92 -0
- package/dist/eventLeg.js +285 -0
- package/dist/executionLaneCapability.d.ts +0 -4
- package/dist/executionLaneCapability.js +3 -16
- package/dist/fileHistoryCaptureCapability.d.ts +0 -4
- package/dist/fileHistoryCaptureCapability.js +5 -7
- package/dist/fleet/fleetLedger.d.ts +0 -3
- package/dist/fleet/fleetLedger.js +21 -36
- package/dist/fleet/fleetProjection.d.ts +2 -2
- package/dist/fleet/fleetProjection.js +10 -8
- package/dist/frameBinding.d.ts +5 -0
- package/dist/frameBinding.js +23 -0
- package/dist/gateFailureCodes.d.ts +2 -0
- package/dist/gateFailureCodes.js +15 -0
- package/dist/gateOutcome.d.ts +3 -1
- package/dist/gateOutcome.js +25 -6
- package/dist/gateVocabulary.d.ts +5 -0
- package/dist/gateVocabulary.js +64 -2
- package/dist/generated/engineAskFaceTables.js +2 -2
- package/dist/generated/engineFactTables.d.ts +6 -3
- package/dist/generated/engineFactTables.js +22 -4
- package/dist/generated/engineNoticeTables.js +9 -0
- package/dist/generated/toolNameTables.d.ts +1 -0
- package/dist/generated/toolNameTables.js +1 -0
- package/dist/hitl/allowRuleShadow.d.ts +6 -1
- package/dist/hitl/allowRuleShadow.js +21 -17
- package/dist/hitl/approvalCardReading.d.ts +15 -0
- package/dist/hitl/approvalCardReading.js +154 -0
- package/dist/hitl/approvalCardReasons.d.ts +13 -0
- package/dist/hitl/approvalCardReasons.js +120 -0
- package/dist/hitl/approvalHolds.d.ts +47 -15
- package/dist/hitl/approvalHolds.js +134 -28
- package/dist/hitl/approvalResolution.d.ts +51 -26
- package/dist/hitl/approvalResolution.js +86 -122
- package/dist/hitl/approvalsFeed.js +6 -18
- package/dist/hitl/askClassPair.d.ts +2 -0
- package/dist/hitl/askClassPair.js +1 -0
- package/dist/hitl/askGateWire.d.ts +20 -2
- package/dist/hitl/askGateWire.js +49 -1
- package/dist/hitl/askParkRowRouting.d.ts +5 -0
- package/dist/hitl/askParkRowRouting.js +32 -1
- package/dist/hitl/askSettlementLine.d.ts +18 -0
- package/dist/hitl/askSettlementLine.js +79 -0
- package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
- package/dist/hitl/automaticAnswerVerdict.js +21 -5
- package/dist/hitl/crashConverged.d.ts +11 -20
- package/dist/hitl/crashConverged.js +56 -0
- package/dist/hitl/crashConvergedNotice.d.ts +3 -1
- package/dist/hitl/crashConvergedNotice.js +48 -11
- package/dist/hitl/decisionConflict.js +3 -10
- package/dist/hitl/decisionRefusal.d.ts +40 -1
- package/dist/hitl/decisionRefusal.js +199 -42
- package/dist/hitl/frameRouter.d.ts +5 -2
- package/dist/hitl/frameRouter.js +20 -16
- package/dist/hitl/gateLedger.d.ts +2 -0
- package/dist/hitl/gateLedger.js +50 -13
- package/dist/hitl/hitlBridge.d.ts +1 -2
- package/dist/hitl/hitlBridge.js +10 -7
- package/dist/hitl/livePendingAsk.d.ts +3 -3
- package/dist/hitl/livePendingAsk.js +7 -18
- package/dist/hitl/parkResolver.d.ts +2 -24
- package/dist/hitl/parkResolver.js +61 -97
- package/dist/hitl/persistedRulesWire.d.ts +24 -0
- package/dist/hitl/persistedRulesWire.js +122 -2
- package/dist/hitl/planReviewWire.d.ts +26 -13
- package/dist/hitl/planReviewWire.js +112 -78
- package/dist/hitl/refusedToolNameProse.d.ts +0 -1
- package/dist/hitl/refusedToolNameProse.js +0 -3
- package/dist/hitl/replayedApproval.d.ts +4 -3
- package/dist/hitl/replayedApproval.js +7 -4
- package/dist/hitl/sessionPolicyDeliverable.js +2 -4
- package/dist/hitl/sessionPolicyWire.d.ts +32 -20
- package/dist/hitl/sessionPolicyWire.js +162 -52
- package/dist/hitl/standingRows.d.ts +20 -2
- package/dist/hitl/standingRows.js +69 -8
- package/dist/hitl/toolApprovalWire.d.ts +87 -152
- package/dist/hitl/toolApprovalWire.js +591 -380
- package/dist/hookMatcherVerdict.d.ts +6 -1
- package/dist/hookMatcherVerdict.js +14 -7
- package/dist/hooksWireCaps.d.ts +2 -2
- package/dist/hooksWireCaps.js +59 -55
- package/dist/i18n/messages.en.d.ts +121 -0
- package/dist/i18n/messages.en.js +119 -0
- package/dist/i18n/messages.zh.d.ts +3 -0
- package/dist/i18n/messages.zh.js +120 -0
- package/dist/i18n/translate.d.ts +25 -0
- package/dist/i18n/translate.js +127 -0
- package/dist/index.d.ts +53 -18
- package/dist/index.js +38 -10
- package/dist/inheritEnvCapability.d.ts +31 -0
- package/dist/inheritEnvCapability.js +104 -0
- package/dist/liveModelCatalog.d.ts +1 -2
- package/dist/liveModelCatalog.js +2 -6
- package/dist/liveQuestionStore.d.ts +2 -21
- package/dist/mcpLiveness.d.ts +2 -1
- package/dist/mcpProbeWire.d.ts +6 -1
- package/dist/mcpProbeWire.js +1 -1
- package/dist/mcpWireCaps.d.ts +13 -2
- package/dist/mcpWireCaps.js +48 -0
- package/dist/memoryEntriesWire.d.ts +4 -9
- package/dist/model/modelSupplyRules.d.ts +0 -2
- package/dist/model/modelSupplyRules.js +3 -12
- package/dist/model/modelsPolicy.d.ts +0 -5
- package/dist/model/modelsPolicy.js +6 -36
- package/dist/model/subagentModelWord.d.ts +31 -0
- package/dist/model/subagentModelWord.js +261 -0
- package/dist/notifications.d.ts +6 -0
- package/dist/notifications.js +71 -23
- package/dist/outputStyleSeatCapability.d.ts +0 -3
- package/dist/outputStyleSeatCapability.js +0 -3
- package/dist/ownKey.d.ts +15 -0
- package/dist/ownKey.js +60 -3
- package/dist/panelReduce.d.ts +15 -9
- package/dist/panelReduce.js +680 -549
- package/dist/panelStateHolder.d.ts +3 -7
- package/dist/panelStateHolder.js +14 -130
- package/dist/peerLaneCapability.d.ts +0 -4
- package/dist/peerLaneCapability.js +0 -6
- package/dist/permissionRulesWriteCapability.d.ts +0 -4
- package/dist/permissionRulesWriteCapability.js +0 -6
- package/dist/permissionWireCaps.d.ts +2 -2
- package/dist/permissionWireCaps.js +2 -0
- package/dist/permissionsAllowGrantCapability.d.ts +0 -4
- package/dist/permissionsAllowGrantCapability.js +0 -6
- package/dist/permissionsDeclaration.d.ts +0 -11
- package/dist/permissionsDeclaration.js +60 -53
- package/dist/pluginHooksWire.d.ts +1 -1
- package/dist/pluginHooksWire.js +3 -6
- package/dist/preemptWire.d.ts +44 -0
- package/dist/preemptWire.js +83 -0
- package/dist/printToolResultFrame.js +15 -4
- package/dist/replayBody.d.ts +3 -0
- package/dist/replayBody.js +14 -0
- package/dist/request/taskRequest.d.ts +0 -1
- package/dist/request/taskRequest.js +0 -3
- package/dist/resumeRefusalCopy.d.ts +2 -1
- package/dist/resumeRefusalCopy.js +38 -2
- package/dist/retryStatus.d.ts +8 -0
- package/dist/retryStatus.js +106 -1
- package/dist/rewindArchiveCapability.d.ts +0 -4
- package/dist/rewindArchiveCapability.js +2 -10
- package/dist/rewindArchiveReading.d.ts +0 -1
- package/dist/rewindArchiveReading.js +0 -3
- package/dist/runCancelContext.d.ts +2 -1
- package/dist/runCancelContext.js +4 -2
- package/dist/runReattachPolicy.d.ts +31 -0
- package/dist/runReattachPolicy.js +46 -0
- package/dist/runTerminal.d.ts +3 -6
- package/dist/runTerminal.js +8 -9
- package/dist/sandboxWire.d.ts +3 -1
- package/dist/sandboxWire.js +76 -27
- package/dist/scenarioWire.js +1 -1
- package/dist/seam.d.ts +24 -2
- package/dist/seam.js +15 -3
- package/dist/seatContract.d.ts +53 -10
- package/dist/seatContract.js +132 -81
- package/dist/sessionPolicyCapability.d.ts +0 -4
- package/dist/sessionPolicyCapability.js +0 -6
- package/dist/sessionSyncFileHistoryCapability.d.ts +0 -3
- package/dist/sessionSyncFileHistoryCapability.js +0 -3
- package/dist/skillToolListsCapability.d.ts +0 -3
- package/dist/skillToolListsCapability.js +0 -3
- package/dist/sqlEngineCapability.d.ts +0 -4
- package/dist/sqlEngineCapability.js +0 -6
- package/dist/steerPriorityCapability.d.ts +0 -3
- package/dist/steerPriorityCapability.js +0 -3
- package/dist/streamDrainingLegs.d.ts +4 -0
- package/dist/streamDrainingLegs.js +6 -1
- package/dist/subagent/engineCompactWire.d.ts +0 -1
- package/dist/subagent/engineCompactWire.js +7 -5
- package/dist/subagent/engineTaskHandleWire.js +4 -7
- package/dist/subagentContentStore.js +1 -11
- package/dist/submitReopen.d.ts +24 -0
- package/dist/submitReopen.js +75 -0
- package/dist/terminalStatuses.d.ts +3 -0
- package/dist/terminalStatuses.js +10 -2
- package/dist/toolResult.d.ts +10 -1
- package/dist/toolResult.js +34 -6
- package/dist/toolRoster.d.ts +0 -2
- package/dist/toolRoster.js +0 -2
- package/dist/turnFailurePresentation.d.ts +28 -0
- package/dist/turnFailurePresentation.js +205 -0
- package/dist/userInvokedSkillsCapability.d.ts +0 -3
- package/dist/userInvokedSkillsCapability.js +0 -3
- package/dist/webSearchBackendCapability.d.ts +0 -4
- package/dist/webSearchBackendCapability.js +0 -6
- package/dist/wireErrorTriage.js +5 -24
- package/dist/wireFailureShape.d.ts +62 -5
- package/dist/wireFailureShape.js +105 -5
- package/dist/wireRefusalCopy.d.ts +12 -2
- package/dist/wireRefusalCopy.js +50 -52
- package/dist/workflowsJournalCapability.d.ts +0 -4
- package/dist/workflowsJournalCapability.js +0 -6
- package/dist/writeProtectionCapability.d.ts +0 -4
- package/dist/writeProtectionCapability.js +0 -6
- package/docs/INTEGRATION-CLIENTS.md +1305 -46
- package/package.json +5 -4
- package/dist/attachmentSeatCapability.d.ts +0 -12
- package/dist/attachmentSeatCapability.js +0 -23
- package/dist/hitl/approvalOutcomeNote.d.ts +0 -10
- package/dist/hitl/approvalOutcomeNote.js +0 -29
- package/dist/sessionReadRedactionCapability.d.ts +0 -13
- package/dist/sessionReadRedactionCapability.js +0 -35
|
@@ -1,39 +1,125 @@
|
|
|
1
|
-
import { ASK_GONE, ASK_GONE_PARKED, isDecideAlreadyResolvedCode, isDecideParkMovedCode, refusalRetriableReading, refusalSaysStillPending } from '../engineErrorCodes.js';
|
|
2
|
-
import { notPendingCauseReading } from './approvalEndingCause.js';
|
|
3
|
-
import { GATE_FAILURE_CODES } from './hitlBridge.js';
|
|
1
|
+
import { ASK_GONE, ASK_GONE_PARKED, RESUME_PREFLIGHT_REJECTED, isDecideAlreadyResolvedCode, isDecideParkMovedCode, refusalRetriableReading, refusalSaysStillPending } from '../engineErrorCodes.js';
|
|
2
|
+
import { notPendingCauseReading, refusalCauseWordOf } from './approvalEndingCause.js';
|
|
3
|
+
import { GATE_FAILURE_CODES, readDecideCurrentPending, readWireCodes } from './hitlBridge.js';
|
|
4
4
|
import { isAlreadyResolvedGateReason, isCodeClassifiedGateFailure } from './parkResolver.js';
|
|
5
5
|
import { decisionConflictOf } from './decisionConflict.js';
|
|
6
6
|
import { readLivePendingRows } from './livePendingAsk.js';
|
|
7
|
-
import { ownDataField } from '../ownKey.js';
|
|
8
|
-
import {
|
|
7
|
+
import { guardedRead, ownDataField, readOwnDataValue } from '../ownKey.js';
|
|
8
|
+
import { PROTOCOL_ERROR_NAME, isDisplayableWireCode, protocolErrorNameReading, readErrorRecord, readRefusalField } from '../wireFailureShape.js';
|
|
9
|
+
import { denyAttributionRefusalFromError } from '../wireRefusalCopy.js';
|
|
9
10
|
const ASK_DECIDED_CODE = 'conflict.ask_decided';
|
|
10
11
|
const TRANSIENT_STATUSES = new Set([408, 425, 429, 502, 503, 504]);
|
|
11
|
-
|
|
12
|
+
export function refusalCarrierOf(err) {
|
|
13
|
+
if (typeof err !== 'object' || err === null)
|
|
14
|
+
return { carrier: err };
|
|
15
|
+
const name = guardedRead(() => readOwnDataValue(err, 'name'));
|
|
16
|
+
if (name !== 'HitlSafetyError')
|
|
17
|
+
return { carrier: err };
|
|
18
|
+
const code = guardedRead(() => readOwnDataValue(err, 'code'));
|
|
19
|
+
const local = typeof code === 'string' && GATE_FAILURE_CODES.includes(code) ? code : undefined;
|
|
20
|
+
const cause = guardedRead(() => readOwnDataValue(err, 'cause'));
|
|
21
|
+
const carrier = typeof cause === 'object' && cause !== null ? cause : err;
|
|
22
|
+
return local !== undefined ? { local, carrier } : { carrier };
|
|
23
|
+
}
|
|
24
|
+
const ROUTE_WORDS = { approval_decide: true, live_respond: true, ask_decide: true, plan_review: true, compact: true };
|
|
25
|
+
const REFUSAL_ROUTES = Object.freeze(Object.keys(ROUTE_WORDS));
|
|
26
|
+
const PRIOR_REFUSAL_EVIDENCE = Object.freeze([
|
|
27
|
+
Object.freeze({
|
|
28
|
+
errorCode: 'corrupt',
|
|
29
|
+
routes: Object.freeze(['plan_review', 'approval_decide', 'live_respond']),
|
|
30
|
+
evidence: 'server resume-legs.ts:1019 / :2752 / :2910 (resume context read, before the claim CAS at :1666 / :1457); plan_review resumePlanReview reads context before settling',
|
|
31
|
+
}),
|
|
32
|
+
]);
|
|
33
|
+
function routeOf(context) {
|
|
34
|
+
const r = guardedRead(() => (typeof context === 'object' && context !== null ? readOwnDataValue(context, 'route') : undefined));
|
|
35
|
+
return typeof r === 'string' && REFUSAL_ROUTES.includes(r) ? r : undefined;
|
|
36
|
+
}
|
|
37
|
+
function carrierStatus(carrier) {
|
|
38
|
+
const raw = typeof carrier === 'object' && carrier !== null ? guardedRead(() => readOwnDataValue(carrier, 'status')) : undefined;
|
|
39
|
+
return typeof raw === 'number' && Number.isFinite(raw) ? raw : undefined;
|
|
40
|
+
}
|
|
41
|
+
function carrierCode(carrier) {
|
|
42
|
+
const raw = typeof carrier === 'object' && carrier !== null ? guardedRead(() => readOwnDataValue(carrier, 'errorCode')) : undefined;
|
|
43
|
+
return typeof raw === 'string' && raw.length > 0 ? raw : undefined;
|
|
44
|
+
}
|
|
45
|
+
export function refusalDeliveryOf(err, context) {
|
|
46
|
+
const { carrier } = refusalCarrierOf(err);
|
|
47
|
+
const status = carrierStatus(carrier);
|
|
48
|
+
const errorCode = carrierCode(carrier);
|
|
49
|
+
const facts = { ...(status !== undefined ? { status } : {}), ...(errorCode !== undefined ? { errorCode } : {}) };
|
|
50
|
+
if (status === undefined || !Number.isInteger(status) || status < 400 || status > 599)
|
|
51
|
+
return { delivery: 'no_answer', ...facts };
|
|
52
|
+
const route = routeOf(context);
|
|
53
|
+
if (route !== undefined && errorCode !== undefined && PRIOR_REFUSAL_EVIDENCE.some((p) => p.errorCode === errorCode && p.routes.includes(route))) {
|
|
54
|
+
return { delivery: 'refused', ...facts };
|
|
55
|
+
}
|
|
56
|
+
if (status < 500 || status === 501)
|
|
57
|
+
return { delivery: 'refused', ...facts };
|
|
58
|
+
return { delivery: 'ambiguous', ...facts };
|
|
59
|
+
}
|
|
12
60
|
export function decisionRefusalSaysAskGone(err) {
|
|
13
61
|
return readDecisionRefusalAsk(err).reading === 'settled';
|
|
14
62
|
}
|
|
15
63
|
const facts = (reading, gateMoved = false, wordingHint = false) => ({ reading, gateMoved, wordingHint });
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
64
|
+
function preflightSettledBitsPresent(carrier) {
|
|
65
|
+
const detail = guardedRead(() => readErrorRecord(carrier, 'detail'));
|
|
66
|
+
if (detail === undefined)
|
|
67
|
+
return false;
|
|
68
|
+
const bit = (k) => guardedRead(() => readOwnDataValue(detail, k));
|
|
69
|
+
const nonEmpty = (v) => typeof v === 'string' && v.length > 0;
|
|
70
|
+
return nonEmpty(bit('settledBy')) || nonEmpty(bit('rowStatus'));
|
|
71
|
+
}
|
|
72
|
+
const RESOLUTION_KINDS = Object.freeze(['decided', 'not_sent', 'unsettled']);
|
|
73
|
+
const ASK_READINGS = Object.freeze(['settled', 'not_settled', 'unreadable']);
|
|
74
|
+
function isResolutionShaped(v) {
|
|
75
|
+
if (typeof v !== 'object' || v === null)
|
|
76
|
+
return false;
|
|
77
|
+
const kind = guardedRead(() => readOwnDataValue(v, 'kind'));
|
|
78
|
+
return typeof kind === 'string' && RESOLUTION_KINDS.includes(kind);
|
|
79
|
+
}
|
|
80
|
+
function askFactsOfResolution(r) {
|
|
81
|
+
try {
|
|
82
|
+
const kind = ownDataField(r, 'kind');
|
|
83
|
+
if (kind === 'not_sent')
|
|
84
|
+
return facts(ownDataField(r, 'cause') === 'no_pending' ? 'settled' : 'not_settled');
|
|
85
|
+
if (kind !== 'unsettled')
|
|
86
|
+
return facts('not_settled');
|
|
87
|
+
const refusal = ownDataField(r, 'refusal');
|
|
88
|
+
if (typeof refusal !== 'object' || refusal === null)
|
|
89
|
+
return facts('not_settled');
|
|
90
|
+
const ask = ownDataField(refusal, 'ask');
|
|
91
|
+
if (typeof ask !== 'string' || !ASK_READINGS.includes(ask))
|
|
92
|
+
return facts('unreadable');
|
|
93
|
+
return facts(ask, ownDataField(refusal, 'gateMoved') === true, ownDataField(refusal, 'wordingHint') === true);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return facts('unreadable');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
21
99
|
export function readDecisionRefusalAsk(failure) {
|
|
22
100
|
if (typeof failure !== 'object' || failure === null)
|
|
23
101
|
return facts('not_settled');
|
|
24
|
-
|
|
102
|
+
if (isResolutionShaped(failure))
|
|
103
|
+
return askFactsOfResolution(failure);
|
|
104
|
+
const { local, carrier } = refusalCarrierOf(failure);
|
|
105
|
+
if (local !== undefined)
|
|
106
|
+
return facts(local === 'no_pending' ? 'settled' : 'not_settled');
|
|
107
|
+
if (typeof carrier !== 'object' || carrier === null)
|
|
108
|
+
return facts('not_settled');
|
|
109
|
+
let localCode, name, protocolName, errorCode, status, retriable, text;
|
|
25
110
|
try {
|
|
26
|
-
const slot = (key) => ownDataField(
|
|
27
|
-
if (slot('unreadable') === true)
|
|
28
|
-
return facts('unreadable');
|
|
29
|
-
flattened = slot('kind') === 'failed';
|
|
111
|
+
const slot = (key) => ownDataField(carrier, key);
|
|
30
112
|
const closed = (v) => (typeof v === 'string' && GATE_FAILURE_CODES.includes(v) ? v : undefined);
|
|
31
|
-
localCode =
|
|
32
|
-
name =
|
|
113
|
+
localCode = closed(slot('code'));
|
|
114
|
+
name = slot('name');
|
|
115
|
+
const pn = protocolErrorNameReading(carrier);
|
|
116
|
+
if (pn.state === 'unreadable')
|
|
117
|
+
throw new TypeError('protocol name unreadable');
|
|
118
|
+
protocolName = pn.state === 'named' ? pn.name : undefined;
|
|
33
119
|
errorCode = slot('errorCode');
|
|
34
120
|
status = slot('status');
|
|
35
|
-
retriable = refusalRetriableReading(
|
|
36
|
-
text =
|
|
121
|
+
retriable = refusalRetriableReading(carrier);
|
|
122
|
+
text = String(carrier);
|
|
37
123
|
}
|
|
38
124
|
catch {
|
|
39
125
|
return facts('unreadable');
|
|
@@ -45,46 +131,117 @@ export function readDecisionRefusalAsk(failure) {
|
|
|
45
131
|
if (name === 'HitlSafetyError')
|
|
46
132
|
return facts('not_settled');
|
|
47
133
|
const code = typeof errorCode === 'string' && errorCode.length > 0 ? errorCode : undefined;
|
|
134
|
+
if (code === RESUME_PREFLIGHT_REJECTED && (preflightSettledBitsPresent(carrier) || retriable !== true))
|
|
135
|
+
return facts('not_settled', true);
|
|
48
136
|
if (isCodeClassifiedGateFailure(code, retriable))
|
|
49
137
|
return facts('not_settled');
|
|
50
138
|
const st = typeof status === 'number' && Number.isInteger(status) && status >= 400 && status <= 599 ? status : undefined;
|
|
51
139
|
if (code === ASK_DECIDED_CODE || code === ASK_GONE || (st === 410 && code !== ASK_GONE_PARKED))
|
|
52
140
|
return facts('settled');
|
|
53
|
-
if (st === 404 && notPendingCauseReading(
|
|
141
|
+
if (st === 404 && notPendingCauseReading(carrier) === 'ended')
|
|
54
142
|
return facts('settled');
|
|
55
|
-
if (code === undefined &&
|
|
143
|
+
if (code === undefined && protocolName === PROTOCOL_ERROR_NAME.AskDecidedError)
|
|
56
144
|
return facts('settled');
|
|
57
|
-
const gateMoved = isDecideAlreadyResolvedCode(code) || isDecideParkMovedCode(code) || code === ASK_GONE_PARKED || (code === undefined &&
|
|
58
|
-
if (gateMoved || st !== undefined ||
|
|
145
|
+
const gateMoved = isDecideAlreadyResolvedCode(code) || isDecideParkMovedCode(code) || code === ASK_GONE_PARKED || (code === undefined && protocolName === PROTOCOL_ERROR_NAME.ApprovalStaleError);
|
|
146
|
+
if (gateMoved || st !== undefined || protocolName === PROTOCOL_ERROR_NAME.ParkedResumeStartupError)
|
|
59
147
|
return facts('not_settled', gateMoved);
|
|
60
148
|
return facts('not_settled', false, isAlreadyResolvedGateReason(text));
|
|
61
149
|
}
|
|
62
150
|
export function decisionRefusalAskReading(failure) {
|
|
63
151
|
return readDecisionRefusalAsk(failure).reading;
|
|
64
152
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
if (
|
|
153
|
+
const USELESS_REFUSAL_TEXTS = new Set(['[object Object]', 'null', 'undefined', '']);
|
|
154
|
+
function refusalTextOf(err) {
|
|
155
|
+
const message = typeof err === 'object' && err !== null ? guardedRead(() => err.message) : undefined;
|
|
156
|
+
if (typeof message === 'string' && message.length > 0)
|
|
157
|
+
return message;
|
|
158
|
+
if (typeof err === 'string' && err.length > 0)
|
|
159
|
+
return err;
|
|
160
|
+
let coerced;
|
|
161
|
+
try {
|
|
162
|
+
coerced = String(err);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
69
165
|
return undefined;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
const
|
|
166
|
+
}
|
|
167
|
+
return USELESS_REFUSAL_TEXTS.has(coerced) ? undefined : coerced;
|
|
168
|
+
}
|
|
169
|
+
function isolated(read) {
|
|
170
|
+
return guardedRead(read);
|
|
171
|
+
}
|
|
172
|
+
export function mintDecisionRefusalReading(err, context, attributionCarried) {
|
|
173
|
+
const { carrier } = refusalCarrierOf(err);
|
|
174
|
+
const obj = typeof carrier === 'object' && carrier !== null ? carrier : undefined;
|
|
175
|
+
const status = carrierStatus(carrier);
|
|
176
|
+
const wire = obj !== undefined ? isolated(() => readWireCodes(obj)) : undefined;
|
|
177
|
+
const errorCode = wire?.errorCode ?? carrierCode(carrier);
|
|
178
|
+
const message = isolated(() => refusalTextOf(carrier));
|
|
179
|
+
const retriable = obj !== undefined && isolated(() => refusalSaysStillPending(obj)) === true;
|
|
180
|
+
const pn = obj !== undefined ? isolated(() => protocolErrorNameReading(obj)) : undefined;
|
|
181
|
+
const protocolName = pn?.state === 'named' ? pn.name : undefined;
|
|
182
|
+
const cause = obj !== undefined ? isolated(() => refusalCauseWordOf(obj)) : undefined;
|
|
183
|
+
const field = obj !== undefined ? isolated(() => readRefusalField(obj)) : undefined;
|
|
184
|
+
const currentPending = obj !== undefined ? isolated(() => readDecideCurrentPending(obj)) : undefined;
|
|
185
|
+
const attribution = attributionCarried !== undefined ? isolated(() => denyAttributionRefusalFromError(carrier, attributionCarried)) : undefined;
|
|
186
|
+
const ask = readDecisionRefusalAsk(err);
|
|
187
|
+
const delivery = refusalDeliveryOf(err, context);
|
|
188
|
+
const standing = delivery.delivery === 'no_answer' ? undefined : ask.reading === 'settled' ? 'settled-elsewhere' : delivery.delivery === 'refused' ? 'refused-pending' : 'ambiguous';
|
|
189
|
+
const inRange = standing !== undefined && status !== undefined;
|
|
190
|
+
const transient = inRange &&
|
|
191
|
+
(TRANSIENT_STATUSES.has(status) || retriable || (status === 404 && obj !== undefined && isolated(() => notPendingCauseReading(obj)) === 'other_replica'));
|
|
192
|
+
const conflict = inRange && status === 409 && obj !== undefined ? isolated(() => decisionConflictOf(obj)) : undefined;
|
|
80
193
|
return Object.freeze({
|
|
81
|
-
|
|
82
|
-
status,
|
|
194
|
+
...(status !== undefined ? { status } : {}),
|
|
83
195
|
...(errorCode !== undefined ? { errorCode } : {}),
|
|
196
|
+
...(message !== undefined ? { message } : {}),
|
|
197
|
+
...(retriable ? { retriable: true } : {}),
|
|
198
|
+
...(protocolName !== undefined ? { protocolName } : {}),
|
|
199
|
+
...(cause !== undefined || field !== undefined ? { extra: Object.freeze({ ...(cause !== undefined ? { cause } : {}), ...(field !== undefined ? { field } : {}) }) } : {}),
|
|
200
|
+
...(wire?.blockedBy !== undefined ? { blockedBy: wire.blockedBy } : {}),
|
|
201
|
+
...(currentPending !== undefined ? { currentPending } : {}),
|
|
202
|
+
...(attribution !== undefined && attribution !== null ? { denyAttributionRefusal: attribution } : {}),
|
|
203
|
+
ask: ask.reading,
|
|
204
|
+
...(ask.gateMoved ? { gateMoved: true } : {}),
|
|
205
|
+
...(ask.wordingHint ? { wordingHint: true } : {}),
|
|
206
|
+
...(standing !== undefined ? { standing } : {}),
|
|
84
207
|
...(transient ? { transient: true } : {}),
|
|
85
208
|
...(conflict !== undefined ? { conflict } : {}),
|
|
86
209
|
});
|
|
87
210
|
}
|
|
211
|
+
export function readDecisionRefusalReading(err, context) {
|
|
212
|
+
return mintDecisionRefusalReading(err, context);
|
|
213
|
+
}
|
|
214
|
+
function classifiedOf(reading) {
|
|
215
|
+
if (typeof reading !== 'object' || reading === null)
|
|
216
|
+
return undefined;
|
|
217
|
+
try {
|
|
218
|
+
const standing = ownDataField(reading, 'standing');
|
|
219
|
+
const status = ownDataField(reading, 'status');
|
|
220
|
+
if ((standing !== 'settled-elsewhere' && standing !== 'ambiguous' && standing !== 'refused-pending') || typeof status !== 'number')
|
|
221
|
+
return undefined;
|
|
222
|
+
const code = ownDataField(reading, 'errorCode');
|
|
223
|
+
const errorCode = typeof code === 'string' && isDisplayableWireCode(code) ? code : undefined;
|
|
224
|
+
const transient = ownDataField(reading, 'transient') === true;
|
|
225
|
+
const conflict = ownDataField(reading, 'conflict');
|
|
226
|
+
return Object.freeze({
|
|
227
|
+
standing,
|
|
228
|
+
status,
|
|
229
|
+
...(errorCode !== undefined ? { errorCode } : {}),
|
|
230
|
+
...(transient ? { transient: true } : {}),
|
|
231
|
+
...(typeof conflict === 'string' ? { conflict: conflict } : {}),
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
return undefined;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
export function classifyDecisionRefusal(err, context) {
|
|
239
|
+
if (isResolutionShaped(err)) {
|
|
240
|
+
const refusal = guardedRead(() => (ownDataField(err, 'kind') === 'unsettled' ? ownDataField(err, 'refusal') : undefined));
|
|
241
|
+
return classifiedOf(refusal);
|
|
242
|
+
}
|
|
243
|
+
return classifiedOf(mintDecisionRefusalReading(err, context));
|
|
244
|
+
}
|
|
88
245
|
export function liveAskPendingReading(envelope, approvalId) {
|
|
89
246
|
if (typeof approvalId !== 'string' || approvalId === '')
|
|
90
247
|
return 'unknown';
|
|
@@ -114,9 +271,9 @@ export function decisionRefusalClosesOut(refusal, pending) {
|
|
|
114
271
|
}
|
|
115
272
|
}
|
|
116
273
|
export function undeliverableDecisionContent(facts) {
|
|
117
|
-
const code = typeof facts.errorCode === 'string' &&
|
|
274
|
+
const code = typeof facts.errorCode === 'string' && isDisplayableWireCode(facts.errorCode) ? ` ${facts.errorCode}` : '';
|
|
118
275
|
const head = `The engine refused the approval decision this client sent (HTTP ${String(facts.status)}${code}), so the call it asked about could not be answered from here and did not run`;
|
|
119
|
-
const runId = typeof facts.runId === 'string' &&
|
|
276
|
+
const runId = typeof facts.runId === 'string' && isDisplayableWireCode(facts.runId) ? ` ${facts.runId}` : '';
|
|
120
277
|
switch (facts.end) {
|
|
121
278
|
case 'run-stopped':
|
|
122
279
|
return `${head}; the run was stopped instead of being left waiting for the approval window to close. Update the client, or run the task in an interactive session and answer the approval there.`;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentEvent } from '@sema-agent/sdk';
|
|
2
2
|
import type { DecideOperationObserver, HitlClientLike } from './hitlBridge.js';
|
|
3
|
-
import { type RespondToolApprovalFn, type ToolApprovalFrame, type ToolApprovalFrameLaneOpts
|
|
3
|
+
import { type RespondToolApprovalFn, type ToolApprovalFrame, type ToolApprovalFrameLaneOpts } from './toolApprovalWire.js';
|
|
4
|
+
import type { ApprovalResolution } from './approvalResolution.js';
|
|
4
5
|
import type { GateLedger } from './gateLedger.js';
|
|
5
6
|
import type { NoAllowCause } from './noAllowCause.js';
|
|
6
7
|
import { type ReplayedApprovalDisposition } from './replayedApproval.js';
|
|
@@ -31,13 +32,14 @@ export interface AskGateWireDeps {
|
|
|
31
32
|
respondToolApproval?: RespondToolApprovalFn;
|
|
32
33
|
onParkReattach?: (e: ParkReattachNotice) => void;
|
|
33
34
|
approvalLane?: ToolApprovalFrameLaneOpts;
|
|
34
|
-
onToolApprovalOutcome?: (frame: ToolApprovalFrame,
|
|
35
|
+
onToolApprovalOutcome?: (frame: ToolApprovalFrame, resolution: ApprovalResolution) => void | Promise<void>;
|
|
35
36
|
onDecideOperation?: DecideOperationObserver;
|
|
36
37
|
onReplayedApproval?: (frame: ToolApprovalFrame, disposition: ReplayedApprovalDisposition) => void | Promise<void>;
|
|
37
38
|
}
|
|
38
39
|
type GateKind = 'ask' | 'fs';
|
|
39
40
|
export interface GatePark {
|
|
40
41
|
gate: GateKind;
|
|
42
|
+
parkFrame: AgentEvent;
|
|
41
43
|
pendingDone?: AgentEvent | undefined;
|
|
42
44
|
gatedCallId?: string | undefined;
|
|
43
45
|
toolName?: string | undefined;
|
|
@@ -50,6 +52,7 @@ export type FrameAction = {
|
|
|
50
52
|
} | {
|
|
51
53
|
kind: 'park';
|
|
52
54
|
gate: GateKind;
|
|
55
|
+
parkFrame: AgentEvent;
|
|
53
56
|
pendingDone?: AgentEvent | undefined;
|
|
54
57
|
gatedCallId?: string | undefined;
|
|
55
58
|
toolName?: string | undefined;
|
package/dist/hitl/frameRouter.js
CHANGED
|
@@ -5,6 +5,8 @@ import { classifierDenyFromToolEnd } from '../classifierVerdictWire.js';
|
|
|
5
5
|
import { toolEndOutputText } from '../toolResultContent.js';
|
|
6
6
|
import { GATE_PARKED_ERROR_CODE } from '../engineErrorCodes.js';
|
|
7
7
|
import { readRunTerminal, runTerminalCode, runTerminalGateKind, runTerminalGateToolName } from '../runTerminal.js';
|
|
8
|
+
import { parkHeldCallIdOf } from '../engineRowRef.js';
|
|
9
|
+
import { inheritFrameBinding } from '../frameBinding.js';
|
|
8
10
|
import { surfaceForCurrentSession, surfaceReplayedApprovalListUnreadable } from './hitlHostSurface.js';
|
|
9
11
|
import { liveCardHoldOf, noteEngineClosedApproval, supersedeLiveCard } from './approvalHolds.js';
|
|
10
12
|
import { approvalCompleteParked } from './approvalCompleteParked.js';
|
|
@@ -69,12 +71,12 @@ function denialKindForTranscript(attribution) {
|
|
|
69
71
|
}
|
|
70
72
|
function denyStampedEnd(ev, attribution) {
|
|
71
73
|
const kind = denialKindForTranscript(attribution);
|
|
72
|
-
return {
|
|
74
|
+
return inheritFrameBinding(ev, {
|
|
73
75
|
...ev,
|
|
74
76
|
output: denyOutputForRender(attribution),
|
|
75
77
|
structured: undefined,
|
|
76
78
|
...(kind !== undefined ? { [SEMA_DENIAL_KIND_KEY]: kind } : {}),
|
|
77
|
-
};
|
|
79
|
+
});
|
|
78
80
|
}
|
|
79
81
|
export const HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE = '[Request interrupted by user for tool use]';
|
|
80
82
|
const RUN_CANCELLED_ERROR_CODE = RUN_CANCELLED_CODE;
|
|
@@ -149,8 +151,7 @@ function parkGateOf(result) {
|
|
|
149
151
|
return arm === null ? null : { taskId, gate: arm, toolName };
|
|
150
152
|
}
|
|
151
153
|
function parkGatedCallId(src) {
|
|
152
|
-
|
|
153
|
-
return typeof v === 'string' && v.length > 0 ? v : undefined;
|
|
154
|
+
return parkHeldCallIdOf(src);
|
|
154
155
|
}
|
|
155
156
|
function argsOfGatedStart(led, callId) {
|
|
156
157
|
if (callId === undefined)
|
|
@@ -192,7 +193,9 @@ export function* flushHeldWithInterruptRewrite(led, evidence) {
|
|
|
192
193
|
yield ev;
|
|
193
194
|
continue;
|
|
194
195
|
}
|
|
195
|
-
yield
|
|
196
|
+
yield inheritFrameBinding(ev, (gateAborted
|
|
197
|
+
? { ...ev, output: HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE, [SEMA_DENIAL_KIND_KEY]: 'interrupted' }
|
|
198
|
+
: { ...ev, output: HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE }));
|
|
196
199
|
}
|
|
197
200
|
}
|
|
198
201
|
const TOOL_END_ARM_ORDER = [
|
|
@@ -216,7 +219,7 @@ const TOOL_END_ARMS = [
|
|
|
216
219
|
const startArgs = led.startArgs().get(callId);
|
|
217
220
|
surfaceForCurrentSession()?.surfaceClassifierDeny(typeof ev.toolName === 'string' ? ev.toolName : 'tool', verdict, { toolCallId: callId, ...(startArgs !== undefined ? { args: startArgs } : {}) });
|
|
218
221
|
hostLog('debug', `liveHitlAskWire: classifier deny verdict on ${callId} (${String(ev.toolName)}) — labeled render + notice`);
|
|
219
|
-
return { kind: 'yield', events: [{ ...ev, output: verdict.message, structured: undefined }] };
|
|
222
|
+
return { kind: 'yield', events: [inheritFrameBinding(ev, { ...ev, output: verdict.message, structured: undefined })] };
|
|
220
223
|
},
|
|
221
224
|
},
|
|
222
225
|
{
|
|
@@ -264,7 +267,7 @@ const TOOL_END_ARMS = [
|
|
|
264
267
|
const answered = led.answerFor(callId);
|
|
265
268
|
if (answered && ev.isError !== true && ev.structured === undefined) {
|
|
266
269
|
led.dropAnswer(callId);
|
|
267
|
-
return { kind: 'yield', events: [{ ...ev, structured: answered }] };
|
|
270
|
+
return { kind: 'yield', events: [inheritFrameBinding(ev, { ...ev, structured: answered })] };
|
|
268
271
|
}
|
|
269
272
|
return { kind: 'yield', events: [ev] };
|
|
270
273
|
},
|
|
@@ -328,14 +331,13 @@ async function routeToolApprovalFrame(ev, ctx) {
|
|
|
328
331
|
}
|
|
329
332
|
function settleLiveCardOutcome(ev, outcome, ctx, fromSubagent, gatedCallId) {
|
|
330
333
|
const { led, deps } = ctx;
|
|
331
|
-
const { decision } = outcome;
|
|
332
334
|
if (deps.onToolApprovalOutcome !== undefined) {
|
|
333
335
|
invokeHostCallbackIsolated('liveHitlAskWire: onToolApprovalOutcome', () => deps.onToolApprovalOutcome?.(ev, outcome));
|
|
334
336
|
}
|
|
335
|
-
if (decision === 'deny' && !fromSubagent) {
|
|
337
|
+
if (outcome.kind === 'decided' && outcome.decision === 'deny' && !fromSubagent) {
|
|
336
338
|
const attribution = {
|
|
337
|
-
...(outcome.
|
|
338
|
-
...(outcome.
|
|
339
|
+
...(outcome.deny?.settledBy !== undefined ? { settledBy: outcome.deny.settledBy } : {}),
|
|
340
|
+
...(outcome.deny?.reason !== undefined ? { reason: outcome.deny.reason } : {}),
|
|
339
341
|
};
|
|
340
342
|
if (gatedCallId !== undefined)
|
|
341
343
|
led.markDenied(gatedCallId, attribution);
|
|
@@ -400,15 +402,16 @@ function routeSuspended(ev, ctx) {
|
|
|
400
402
|
const gatedCallId = parkGatedCallId(ev);
|
|
401
403
|
const arm = parkGateArmOf(ev.gate);
|
|
402
404
|
if (arm === 'ask' && ctx.taskId.current) {
|
|
403
|
-
ctx.led.noteParkGate({ fsOrShellFamily: false });
|
|
404
|
-
return { kind: 'park', gate: 'ask', ...(gatedCallId !== undefined ? { gatedCallId } : {}) };
|
|
405
|
+
ctx.led.noteParkGate({ fsOrShellFamily: false, gatedCallId });
|
|
406
|
+
return { kind: 'park', gate: 'ask', parkFrame: ev, ...(gatedCallId !== undefined ? { gatedCallId } : {}) };
|
|
405
407
|
}
|
|
406
408
|
if (arm === 'fs' && ctx.taskId.current) {
|
|
407
409
|
const gateToolName = ev.gate?.toolName;
|
|
408
|
-
ctx.led.noteParkGate({ fsOrShellFamily: parkFamilyEvidence(ctx.led, gateToolName, gatedCallId) });
|
|
410
|
+
ctx.led.noteParkGate({ fsOrShellFamily: parkFamilyEvidence(ctx.led, gateToolName, gatedCallId), gatedCallId });
|
|
409
411
|
return {
|
|
410
412
|
kind: 'park',
|
|
411
413
|
gate: 'fs',
|
|
414
|
+
parkFrame: ev,
|
|
412
415
|
...(gatedCallId !== undefined ? { gatedCallId } : {}),
|
|
413
416
|
...(typeof gateToolName === 'string' && gateToolName !== '' ? { toolName: gateToolName } : {}),
|
|
414
417
|
};
|
|
@@ -421,10 +424,11 @@ function routeDone(ev, ctx) {
|
|
|
421
424
|
const park = parkGateOf(ev.result);
|
|
422
425
|
if (park !== null) {
|
|
423
426
|
ctx.taskId.current = ctx.taskId.current ?? park.taskId;
|
|
424
|
-
led.noteParkGate({ fsOrShellFamily: park.gate === 'fs' && parkFamilyEvidence(led, park.toolName, gatedCallId) });
|
|
427
|
+
led.noteParkGate({ fsOrShellFamily: park.gate === 'fs' && parkFamilyEvidence(led, park.toolName, gatedCallId), gatedCallId });
|
|
425
428
|
return {
|
|
426
429
|
kind: 'park',
|
|
427
430
|
gate: park.gate,
|
|
431
|
+
parkFrame: ev,
|
|
428
432
|
pendingDone: ev,
|
|
429
433
|
...(gatedCallId !== undefined ? { gatedCallId } : {}),
|
|
430
434
|
...(park.toolName !== undefined && park.toolName !== '' ? { toolName: park.toolName } : {}),
|
|
@@ -434,7 +438,7 @@ function routeDone(ev, ctx) {
|
|
|
434
438
|
const r = ev.result;
|
|
435
439
|
const realTaskId = ctx.taskId.current;
|
|
436
440
|
if (realTaskId && r && r.taskId === r.sessionId && r.taskId !== realTaskId) {
|
|
437
|
-
events.push({ ...ev, result: { ...ev.result, taskId: realTaskId } });
|
|
441
|
+
events.push(inheritFrameBinding(ev, { ...ev, result: { ...ev.result, taskId: realTaskId } }));
|
|
438
442
|
}
|
|
439
443
|
else {
|
|
440
444
|
events.push(ev);
|
|
@@ -14,6 +14,7 @@ export interface AskAnsweredOutput {
|
|
|
14
14
|
}>;
|
|
15
15
|
}
|
|
16
16
|
export declare function durableSeqOf(ev: object): string | undefined;
|
|
17
|
+
export declare const BODY_SEQ_OTHER_AXIS_EVENTS: readonly string[];
|
|
17
18
|
export declare function hasLedgerPositionKey(ev: object): boolean;
|
|
18
19
|
export declare const PREAMBLE_APPROVALS_MAX_ENTRIES = 4096;
|
|
19
20
|
export interface GateLedger {
|
|
@@ -52,6 +53,7 @@ export interface GateLedger {
|
|
|
52
53
|
isFsOrShellGatedCall(callId: string): boolean;
|
|
53
54
|
noteParkGate(evidence: {
|
|
54
55
|
fsOrShellFamily: boolean;
|
|
56
|
+
gatedCallId?: string | undefined;
|
|
55
57
|
}): void;
|
|
56
58
|
hasBatchPark(): boolean;
|
|
57
59
|
rememberAnswer(callId: string, answered: AskAnsweredOutput): void;
|
package/dist/hitl/gateLedger.js
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
+
import { parkedToolEndRoleOf } from '../engineRowRef.js';
|
|
2
|
+
import { inheritFrameBinding } from '../frameBinding.js';
|
|
1
3
|
export const SEMA_COLLATERAL_ABORT_KEY = '_sema_collateral_abort';
|
|
2
4
|
export const SEMA_DENIAL_KIND_KEY = '_sema_denial_kind';
|
|
3
5
|
export function durableSeqOf(ev) {
|
|
4
|
-
const
|
|
6
|
+
const rec = ev;
|
|
7
|
+
const id = rec.id;
|
|
8
|
+
const rawSeq = id ?? (seqIsAnotherAxis(rec.type) ? undefined : rec.seq);
|
|
5
9
|
if (typeof rawSeq === 'string' && rawSeq.length > 0)
|
|
6
10
|
return rawSeq;
|
|
7
11
|
if (typeof rawSeq === 'number' && Number.isFinite(rawSeq))
|
|
8
12
|
return String(rawSeq);
|
|
9
13
|
return undefined;
|
|
10
14
|
}
|
|
15
|
+
export const BODY_SEQ_OTHER_AXIS_EVENTS = Object.freeze(['task_progress', 'task_notification', 'task_started']);
|
|
16
|
+
function seqIsAnotherAxis(type) {
|
|
17
|
+
return typeof type === 'string' && BODY_SEQ_OTHER_AXIS_EVENTS.includes(type);
|
|
18
|
+
}
|
|
11
19
|
export function hasLedgerPositionKey(ev) {
|
|
12
20
|
const { id, seq } = ev;
|
|
13
21
|
return (id !== undefined && id !== null) || (seq !== undefined && seq !== null);
|
|
@@ -27,8 +35,8 @@ export function createGateLedger() {
|
|
|
27
35
|
const startedCalls = new Set();
|
|
28
36
|
const endedCalls = new Set();
|
|
29
37
|
const heldAskEnds = new Map();
|
|
30
|
-
const gatedStartArgsByCall = new Map();
|
|
31
38
|
const startArgsByCall = new Map();
|
|
39
|
+
const gatedStartCalls = new Set();
|
|
32
40
|
const deniedCalls = new Set();
|
|
33
41
|
const denyAttributionByCall = new Map();
|
|
34
42
|
const pendingFsCalls = [];
|
|
@@ -37,6 +45,7 @@ export function createGateLedger() {
|
|
|
37
45
|
let alreadyResolvedKey;
|
|
38
46
|
let alreadyResolvedStreak = 0;
|
|
39
47
|
let fsOrShellFamilyGate = false;
|
|
48
|
+
let batchParkSubject;
|
|
40
49
|
const droppedFromBatch = new Set();
|
|
41
50
|
let batchParkCount = 0;
|
|
42
51
|
let heldSinceLastPark = false;
|
|
@@ -45,6 +54,8 @@ export function createGateLedger() {
|
|
|
45
54
|
const resolveGateSubjects = () => {
|
|
46
55
|
if (batchParkCount !== 1)
|
|
47
56
|
return undefined;
|
|
57
|
+
if (batchParkSubject !== undefined)
|
|
58
|
+
return new Set([batchParkSubject]);
|
|
48
59
|
if (!fsOrShellFamilyGate)
|
|
49
60
|
return undefined;
|
|
50
61
|
for (const id of heldAskEnds.keys()) {
|
|
@@ -78,8 +89,16 @@ export function createGateLedger() {
|
|
|
78
89
|
}
|
|
79
90
|
return n === 1;
|
|
80
91
|
};
|
|
92
|
+
const bystanderUnderIdentity = (ev, subject) => {
|
|
93
|
+
const parent = ev.parentToolCallId;
|
|
94
|
+
if (typeof parent === 'string' && parent !== '')
|
|
95
|
+
return false;
|
|
96
|
+
const own = ev.gatedCallId;
|
|
97
|
+
return !(typeof own === 'string' && own !== '' && own !== subject);
|
|
98
|
+
};
|
|
81
99
|
const retireBatchState = () => {
|
|
82
100
|
fsOrShellFamilyGate = false;
|
|
101
|
+
batchParkSubject = undefined;
|
|
83
102
|
droppedFromBatch.clear();
|
|
84
103
|
batchParkCount = 0;
|
|
85
104
|
heldSinceLastPark = false;
|
|
@@ -101,8 +120,8 @@ export function createGateLedger() {
|
|
|
101
120
|
forgetRunScopedState() {
|
|
102
121
|
seq = undefined;
|
|
103
122
|
startedCalls.clear();
|
|
104
|
-
gatedStartArgsByCall.clear();
|
|
105
123
|
startArgsByCall.clear();
|
|
124
|
+
gatedStartCalls.clear();
|
|
106
125
|
},
|
|
107
126
|
notePreambleApproval(approvalId) {
|
|
108
127
|
if (typeof approvalId !== 'string' || approvalId === '')
|
|
@@ -144,26 +163,41 @@ export function createGateLedger() {
|
|
|
144
163
|
return true;
|
|
145
164
|
},
|
|
146
165
|
noteGatedStart(callId, ev) {
|
|
147
|
-
|
|
166
|
+
if (!startArgsByCall.has(callId))
|
|
167
|
+
startArgsByCall.set(callId, ev.args);
|
|
168
|
+
gatedStartCalls.add(callId);
|
|
148
169
|
},
|
|
149
170
|
gatedStartArgs() {
|
|
150
|
-
|
|
171
|
+
const out = new Map();
|
|
172
|
+
for (const id of gatedStartCalls)
|
|
173
|
+
if (startArgsByCall.has(id))
|
|
174
|
+
out.set(id, startArgsByCall.get(id));
|
|
175
|
+
return out;
|
|
151
176
|
},
|
|
152
177
|
noteStart(callId, ev) {
|
|
178
|
+
if (gatedStartCalls.has(callId))
|
|
179
|
+
return;
|
|
153
180
|
startArgsByCall.delete(callId);
|
|
154
181
|
startArgsByCall.set(callId, ev.args);
|
|
155
|
-
while (startArgsByCall.size > START_ARGS_MAX_ENTRIES) {
|
|
156
|
-
|
|
157
|
-
|
|
182
|
+
while (startArgsByCall.size - gatedStartCalls.size > START_ARGS_MAX_ENTRIES) {
|
|
183
|
+
let victim;
|
|
184
|
+
for (const id of startArgsByCall.keys()) {
|
|
185
|
+
if (!gatedStartCalls.has(id)) {
|
|
186
|
+
victim = id;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (victim === undefined)
|
|
158
191
|
break;
|
|
159
|
-
startArgsByCall.delete(
|
|
192
|
+
startArgsByCall.delete(victim);
|
|
160
193
|
}
|
|
161
194
|
},
|
|
162
195
|
startArgs() {
|
|
163
196
|
return startArgsByCall;
|
|
164
197
|
},
|
|
165
198
|
dropStartArgs(callId) {
|
|
166
|
-
|
|
199
|
+
if (!gatedStartCalls.has(callId))
|
|
200
|
+
startArgsByCall.delete(callId);
|
|
167
201
|
},
|
|
168
202
|
isEnded(callId) {
|
|
169
203
|
return endedCalls.has(callId);
|
|
@@ -195,10 +229,12 @@ export function createGateLedger() {
|
|
|
195
229
|
},
|
|
196
230
|
*flushHeld() {
|
|
197
231
|
const subjects = resolveGateSubjects();
|
|
232
|
+
const identity = subjects !== undefined ? batchParkSubject : undefined;
|
|
198
233
|
for (const [callId, ev] of heldAskEnds) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
234
|
+
if (parkedToolEndRoleOf(ev) !== 'held')
|
|
235
|
+
endedCalls.add(callId);
|
|
236
|
+
yield subjects !== undefined && !subjects.has(callId) && (identity === undefined || bystanderUnderIdentity(ev, identity))
|
|
237
|
+
? inheritFrameBinding(ev, { ...ev, [SEMA_COLLATERAL_ABORT_KEY]: true })
|
|
202
238
|
: ev;
|
|
203
239
|
}
|
|
204
240
|
heldAskEnds.clear();
|
|
@@ -260,6 +296,7 @@ export function createGateLedger() {
|
|
|
260
296
|
return;
|
|
261
297
|
batchParkCount += 1;
|
|
262
298
|
fsOrShellFamilyGate = evidence.fsOrShellFamily;
|
|
299
|
+
batchParkSubject = typeof evidence.gatedCallId === 'string' && evidence.gatedCallId !== '' ? evidence.gatedCallId : undefined;
|
|
263
300
|
heldSinceLastPark = false;
|
|
264
301
|
},
|
|
265
302
|
hasBatchPark() {
|
|
@@ -48,7 +48,6 @@ export type PlanReviewModeAfter = (typeof PLAN_REVIEW_MODE_AFTER_WORDS)[number];
|
|
|
48
48
|
export declare function isPlanReviewModeAfter(v: string | undefined): v is PlanReviewModeAfter;
|
|
49
49
|
export declare const GATE_FAILURE_CODES: readonly ["no_pending", "binding_mismatch", "wrong_gate", "bad_plan_edit", "bad_plan_mode", "empty_answer", "binding_missing"];
|
|
50
50
|
export type HitlSafetyCode = (typeof GATE_FAILURE_CODES)[number];
|
|
51
|
-
export type HitlFailureStage = 'fetch' | 'input' | 'card' | 'decide' | 'orchestration';
|
|
52
51
|
export declare const NO_APPROVAL_CARD_PORT_REASON = "no approval card port installed (print/non-REPL mode, or host forgot installApprovalCardPort)";
|
|
53
52
|
export declare const APPROVAL_CARD_PORT_KEY_MISMATCH_REASON = "no approval card port installed for the default session key, but a non-default sessionKey has one \u2014 likely a keyed-install/default-read mismatch (installApprovalCardPortFor vs the zero-arg default-key read), not a missing install";
|
|
54
53
|
export declare const NO_QUESTION_OVERLAY_REASON = "no question overlay mounted (print/non-REPL mode)";
|
|
@@ -61,7 +60,7 @@ export interface HitlDecideDenyOutcome {
|
|
|
61
60
|
}
|
|
62
61
|
export declare class HitlSafetyError extends Error {
|
|
63
62
|
readonly code: HitlSafetyCode;
|
|
64
|
-
constructor(message: string, code: HitlSafetyCode);
|
|
63
|
+
constructor(message: string, code: HitlSafetyCode, options?: ErrorOptions);
|
|
65
64
|
}
|
|
66
65
|
export declare function hitlSafetyCodeOf(e: unknown): HitlSafetyCode | undefined;
|
|
67
66
|
export type GateCurrentPending = Readonly<NonNullable<ApprovalStaleError['currentPending']>>;
|