@sema-agent/client-core 0.97.1 → 0.99.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 +607 -0
- package/README.md +96 -46
- package/dist/adapt/arms.d.ts +1 -0
- package/dist/adapt/arms.js +188 -53
- 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/panelTasks.d.ts +1 -1
- package/dist/adapt/panelTasks.js +2 -2
- 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 +9 -3
- package/dist/adapter/activeRunSelfHeal.js +205 -313
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -5
- package/dist/adapter/downstream/eventToSdkMessage.js +77 -36
- 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 +79 -48
- package/dist/adapter/types.d.ts +4 -4
- package/dist/adapter/types.js +2 -1
- package/dist/agentSession/backgroundView.js +2 -1
- package/dist/agentSession/engineAgentRegistryRead.d.ts +2 -2
- package/dist/agentSession/engineAgentRegistryRead.js +12 -13
- package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
- package/dist/agentsWireCaps.d.ts +8 -11
- package/dist/agentsWireCaps.js +196 -194
- 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 +5 -3
- package/dist/cloudConfigWireCaps.js +106 -64
- package/dist/compensations.js +1 -1
- package/dist/connectorStatus.d.ts +21 -0
- package/dist/connectorStatus.js +112 -0
- package/dist/controlRouter.d.ts +18 -3
- package/dist/controlRouter.js +106 -67
- package/dist/coreValuePorts.d.ts +29 -4
- package/dist/coreValuePorts.js +10 -0
- package/dist/corruptSessionCopy.d.ts +2 -1
- package/dist/corruptSessionCopy.js +3 -3
- package/dist/decideReceipt.d.ts +2 -2
- package/dist/decideReceipt.js +5 -2
- package/dist/declared/supportFloorDeclared.js +3 -3
- package/dist/detachWire.js +3 -2
- 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/devicesFace.d.ts +34 -0
- package/dist/devicesFace.js +90 -0
- package/dist/displayUntrusted.d.ts +2 -0
- package/dist/displayUntrusted.js +253 -76
- package/dist/engineAgentAbsence.d.ts +1 -1
- package/dist/engineAgentPanelStore.d.ts +12 -4
- package/dist/engineAgentPanelStore.js +16 -11
- package/dist/engineCapReader.d.ts +2 -5
- package/dist/engineCapReader.js +8 -10
- package/dist/engineCapsCache.d.ts +12 -0
- package/dist/engineCapsCache.js +76 -18
- package/dist/engineCapsChange.d.ts +2 -0
- package/dist/engineCapsChange.js +9 -0
- package/dist/engineClosedSets.d.ts +1 -0
- package/dist/engineClosedSets.js +4 -1
- package/dist/engineErrorCodes.d.ts +11 -3
- package/dist/engineErrorCodes.js +11 -8
- package/dist/engineIdentity.d.ts +1 -0
- package/dist/engineIdentity.js +8 -0
- package/dist/engineRowRef.d.ts +28 -0
- package/dist/engineRowRef.js +114 -0
- package/dist/engineSessionMessages.d.ts +68 -0
- package/dist/engineSessionMessages.js +370 -0
- package/dist/engineTargetSeat.d.ts +27 -0
- package/dist/engineTargetSeat.js +199 -0
- package/dist/engineToolDirectory.d.ts +0 -9
- package/dist/engineToolDirectory.js +1 -94
- package/dist/engineUrl.d.ts +18 -0
- package/dist/engineUrl.js +52 -0
- package/dist/engineWireFor.js +3 -8
- package/dist/env/uiLanguage.d.ts +11 -1
- package/dist/env/uiLanguage.js +38 -2
- package/dist/eventLeg.d.ts +100 -0
- package/dist/eventLeg.js +305 -0
- package/dist/executionLaneCapability.d.ts +0 -4
- package/dist/executionLaneCapability.js +3 -16
- package/dist/fileHistoryCaptureCapability.d.ts +2 -5
- package/dist/fileHistoryCaptureCapability.js +13 -21
- package/dist/fileHistoryLegNotice.d.ts +2 -1
- package/dist/fileHistoryLegNotice.js +3 -3
- 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 +8 -0
- package/dist/frameBinding.js +35 -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 +41 -8
- package/dist/gateVocabulary.d.ts +10 -4
- package/dist/gateVocabulary.js +107 -47
- package/dist/generated/engineAskFaceTables.js +2 -2
- package/dist/generated/engineFactTables.d.ts +22 -3
- package/dist/generated/engineFactTables.js +51 -4
- package/dist/generated/engineNoticeTables.js +18 -3
- package/dist/generated/settingsSchemaFns.d.ts +6 -0
- package/dist/generated/settingsSchemaFns.js +57 -0
- package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
- package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
- package/dist/generated/settingsSchemaTables.d.ts +1 -0
- package/dist/generated/settingsSchemaTables.js +4 -0
- package/dist/generated/settingsSchemaTypes.d.ts +105 -0
- package/dist/generated/settingsSchemaTypes.js +1 -0
- package/dist/generated/toolNameTables.d.ts +1 -0
- package/dist/generated/toolNameTables.js +1 -0
- package/dist/hitl/allowRuleShadow.d.ts +8 -2
- package/dist/hitl/allowRuleShadow.js +36 -29
- package/dist/hitl/approvalCardReading.d.ts +15 -0
- package/dist/hitl/approvalCardReading.js +154 -0
- package/dist/hitl/approvalCardReasons.d.ts +14 -0
- package/dist/hitl/approvalCardReasons.js +119 -0
- package/dist/hitl/approvalHolds.d.ts +50 -15
- package/dist/hitl/approvalHolds.js +177 -27
- 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 +17 -0
- package/dist/hitl/askGateWire.d.ts +20 -2
- package/dist/hitl/askGateWire.js +50 -1
- package/dist/hitl/askParkRowRouting.d.ts +5 -0
- package/dist/hitl/askParkRowRouting.js +32 -1
- package/dist/hitl/askSettlementLine.d.ts +28 -0
- package/dist/hitl/askSettlementLine.js +99 -0
- package/dist/hitl/automaticAnswerVerdict.d.ts +3 -2
- package/dist/hitl/automaticAnswerVerdict.js +29 -13
- package/dist/hitl/crashConverged.d.ts +11 -20
- package/dist/hitl/crashConverged.js +56 -0
- package/dist/hitl/crashConvergedNotice.d.ts +6 -3
- package/dist/hitl/crashConvergedNotice.js +48 -24
- 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 +27 -24
- package/dist/hitl/gateLedger.d.ts +2 -0
- package/dist/hitl/gateLedger.js +50 -13
- package/dist/hitl/hitlBridge.d.ts +2 -2
- package/dist/hitl/hitlBridge.js +13 -10
- 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 +25 -0
- package/dist/hitl/persistedRulesWire.js +104 -2
- package/dist/hitl/planReviewWire.d.ts +31 -13
- package/dist/hitl/planReviewWire.js +120 -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.d.ts +2 -0
- package/dist/hitl/sessionPolicyDeliverable.js +48 -7
- package/dist/hitl/sessionPolicyWire.d.ts +34 -21
- package/dist/hitl/sessionPolicyWire.js +179 -70
- package/dist/hitl/standingRows.d.ts +20 -2
- package/dist/hitl/standingRows.js +69 -8
- package/dist/hitl/suspendedReopen.d.ts +2 -1
- package/dist/hitl/suspendedReopen.js +7 -10
- package/dist/hitl/toolApprovalWire.d.ts +103 -156
- package/dist/hitl/toolApprovalWire.js +661 -411
- package/dist/hookMatcherVerdict.d.ts +6 -1
- package/dist/hookMatcherVerdict.js +14 -7
- package/dist/hooksWireCaps.d.ts +2 -2
- package/dist/hooksWireCaps.js +174 -81
- package/dist/host.d.ts +21 -0
- package/dist/hostTurnSettings.d.ts +71 -0
- package/dist/hostTurnSettings.js +291 -0
- package/dist/humanTurn.d.ts +14 -1
- package/dist/humanTurn.js +100 -12
- package/dist/humanTurnRead.d.ts +2 -0
- package/dist/humanTurnRead.js +22 -1
- package/dist/i18n/messages.en.d.ts +703 -0
- package/dist/i18n/messages.en.js +701 -0
- package/dist/i18n/messages.zh.d.ts +3 -0
- package/dist/i18n/messages.zh.js +837 -0
- package/dist/i18n/translate.d.ts +25 -0
- package/dist/i18n/translate.js +127 -0
- package/dist/index.d.ts +78 -29
- package/dist/index.js +54 -18
- package/dist/inheritEnvCapability.d.ts +32 -0
- package/dist/inheritEnvCapability.js +104 -0
- package/dist/inheritEnvWire.d.ts +3 -2
- package/dist/inheritEnvWire.js +12 -14
- package/dist/interactiveHalt.js +17 -6
- package/dist/liveModelCatalog.d.ts +3 -3
- package/dist/liveModelCatalog.js +15 -13
- package/dist/liveQuestionStore.d.ts +2 -21
- package/dist/mcpLiveness.d.ts +2 -1
- package/dist/mcpPanel.d.ts +10 -1
- package/dist/mcpPanel.js +40 -13
- package/dist/mcpProbeCapability.d.ts +2 -1
- package/dist/mcpProbeCapability.js +7 -11
- package/dist/mcpProbeWire.d.ts +9 -2
- package/dist/mcpProbeWire.js +6 -1
- package/dist/mcpWireCaps.d.ts +47 -2
- package/dist/mcpWireCaps.js +164 -16
- package/dist/memoryEntriesWire.d.ts +4 -9
- package/dist/memoryEntriesWire.js +5 -10
- 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/onboardJudgement.d.ts +93 -0
- package/dist/model/onboardJudgement.js +415 -0
- package/dist/model/subagentModelWord.d.ts +31 -0
- package/dist/model/subagentModelWord.js +261 -0
- package/dist/model/tierVocabulary.d.ts +2 -0
- package/dist/model/tierVocabulary.js +17 -5
- package/dist/modelCapabilityProbe.d.ts +64 -0
- package/dist/modelCapabilityProbe.js +600 -0
- package/dist/modelIdentityResolvability.d.ts +3 -0
- package/dist/modelIdentityResolvability.js +26 -17
- 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 +22 -0
- package/dist/ownKey.js +94 -3
- package/dist/panelReduce.d.ts +21 -10
- package/dist/panelReduce.js +728 -550
- 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/permissionRuleIssue.js +2 -0
- package/dist/permissionRulesWriteCapability.d.ts +2 -5
- package/dist/permissionRulesWriteCapability.js +8 -12
- 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 +46 -3
- package/dist/pluginHooksWire.js +219 -16
- package/dist/preemptWire.d.ts +44 -0
- package/dist/preemptWire.js +83 -0
- package/dist/printModelStatus.d.ts +63 -0
- package/dist/printModelStatus.js +155 -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 +11 -6
- package/dist/request/taskRequest.js +112 -19
- package/dist/resumeRefusalCopy.d.ts +13 -9
- package/dist/resumeRefusalCopy.js +81 -118
- package/dist/retryStatus.d.ts +45 -0
- package/dist/retryStatus.js +185 -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/scenarioRefusal.d.ts +9 -0
- package/dist/scenarioRefusal.js +111 -0
- package/dist/scenarioWire.js +1 -1
- package/dist/seam.d.ts +48 -2
- package/dist/seam.js +25 -4
- package/dist/seatContract.d.ts +311 -18
- package/dist/seatContract.js +824 -100
- package/dist/selfOrchestrationDenial.js +7 -19
- package/dist/sessionIdSegment.d.ts +6 -0
- package/dist/sessionIdSegment.js +24 -0
- package/dist/sessionMemoryStatus.js +6 -11
- package/dist/sessionPolicyCapability.d.ts +2 -5
- package/dist/sessionPolicyCapability.js +8 -12
- package/dist/sessionSyncFileHistoryCapability.d.ts +0 -3
- package/dist/sessionSyncFileHistoryCapability.js +0 -3
- package/dist/settingsHooksSalvage.d.ts +44 -0
- package/dist/settingsHooksSalvage.js +211 -0
- package/dist/skillToolListsCapability.d.ts +2 -4
- package/dist/skillToolListsCapability.js +8 -9
- package/dist/sqlEngineCapability.d.ts +0 -4
- package/dist/sqlEngineCapability.js +0 -6
- package/dist/sseIdleTriage.js +3 -2
- 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/engineSubagentResume.js +15 -9
- package/dist/subagent/engineTaskHandleWire.js +4 -7
- package/dist/subagentContentStore.d.ts +3 -0
- package/dist/subagentContentStore.js +22 -10
- 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/toolHistoryMismatch.js +3 -2
- package/dist/toolResult.d.ts +10 -1
- package/dist/toolResult.js +34 -6
- package/dist/toolRoster.d.ts +3 -4
- package/dist/toolRoster.js +21 -22
- package/dist/turnFailurePresentation.d.ts +39 -0
- package/dist/turnFailurePresentation.js +402 -0
- package/dist/usageAnalytics.js +6 -11
- package/dist/userAttachmentEnvelope.d.ts +1 -0
- package/dist/userAttachmentEnvelope.js +37 -7
- package/dist/userAttachmentSeat.d.ts +21 -0
- package/dist/userAttachmentSeat.js +75 -0
- package/dist/userInvokedSkillsCapability.d.ts +11 -4
- package/dist/userInvokedSkillsCapability.js +31 -10
- package/dist/webSearchBackendCapability.d.ts +0 -4
- package/dist/webSearchBackendCapability.js +0 -6
- package/dist/wireErrorTriage.d.ts +7 -0
- package/dist/wireErrorTriage.js +26 -23
- package/dist/wireFailureShape.d.ts +62 -5
- package/dist/wireFailureShape.js +106 -5
- package/dist/wireRefusalCopy.d.ts +25 -3
- package/dist/wireRefusalCopy.js +74 -80
- package/dist/workflowsJournalCapability.d.ts +2 -5
- package/dist/workflowsJournalCapability.js +8 -12
- package/dist/writeProtectionCapability.d.ts +0 -4
- package/dist/writeProtectionCapability.js +0 -6
- package/docs/INTEGRATION-CLIENTS.md +1775 -56
- package/package.json +6 -5
- 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,10 +1,13 @@
|
|
|
1
|
+
import { displayUntrusted, quoteUntrustedForSentence } from '../displayUntrusted.js';
|
|
1
2
|
import { engineCapTrue } from '../engineCapsCache.js';
|
|
2
3
|
import { CORE_RULE_BEHAVIORS } from '../generated/engineFactTables.js';
|
|
3
4
|
import { wireFailureShapeOf } from '../wireFailureShape.js';
|
|
4
5
|
import { CAPABILITY_OPERATOR_PRINCIPALS_REQUIRED } from '../engineErrorCodes.js';
|
|
5
6
|
import { hostLog } from '../host.js';
|
|
7
|
+
import { msg, renderMessage } from '../i18n/translate.js';
|
|
8
|
+
import { guardedRead, readOwnDataValue } from '../ownKey.js';
|
|
6
9
|
import { observedPermissionRulesWrite, permissionRulesWriteAvailable } from '../permissionRulesWriteCapability.js';
|
|
7
|
-
import { readToolApprovalRespondAck } from './toolApprovalWire.js';
|
|
10
|
+
import { isToolApprovalRespondReplayed, readToolApprovalRespondAck } from './toolApprovalWire.js';
|
|
8
11
|
export function persistedRulesLaneAvailable(baseUrl) {
|
|
9
12
|
return engineCapTrue(baseUrl, 'permissionRules');
|
|
10
13
|
}
|
|
@@ -112,6 +115,105 @@ export const PERSISTED_RULE_BEHAVIOR_UNKNOWN = '(unknown)';
|
|
|
112
115
|
export function persistedRuleBehaviorLabel(rule) {
|
|
113
116
|
return rowStr(rule, 'behavior') ?? PERSISTED_RULE_BEHAVIOR_UNKNOWN;
|
|
114
117
|
}
|
|
118
|
+
const PERSISTED_RULE_ORIGIN_KEYS = Object.freeze({
|
|
119
|
+
user: 'rules.origin.user',
|
|
120
|
+
'imported-cc': 'rules.origin.importedCc',
|
|
121
|
+
starter: 'rules.origin.starter',
|
|
122
|
+
});
|
|
123
|
+
const UNKNOWN_ORIGIN_KEY = 'rules.origin.unknownWord';
|
|
124
|
+
const NO_ORIGIN_KEY = 'rules.origin.none';
|
|
125
|
+
function originKeyOf(origin) {
|
|
126
|
+
return typeof origin === 'string' && Object.hasOwn(PERSISTED_RULE_ORIGIN_KEYS, origin) ? PERSISTED_RULE_ORIGIN_KEYS[origin] : UNKNOWN_ORIGIN_KEY;
|
|
127
|
+
}
|
|
128
|
+
function ownSlot(o, key) {
|
|
129
|
+
if (typeof o !== 'object' || o === null)
|
|
130
|
+
return undefined;
|
|
131
|
+
return guardedRead(() => readOwnDataValue(o, key));
|
|
132
|
+
}
|
|
133
|
+
const ORIGINS_READ_MAX = 256;
|
|
134
|
+
export function persistedRuleAddOriginLabel(origin, lang) {
|
|
135
|
+
return renderMessage(msg(originKeyOf(origin)), lang);
|
|
136
|
+
}
|
|
137
|
+
export function persistedRuleOriginsLabel(rule, lang) {
|
|
138
|
+
const adds = ownSlot(rule, 'adds');
|
|
139
|
+
const isArr = guardedRead(() => (Array.isArray(adds) ? true : undefined));
|
|
140
|
+
if (isArr !== true)
|
|
141
|
+
return renderMessage(msg(NO_ORIGIN_KEY), lang);
|
|
142
|
+
const lenRaw = ownSlot(adds, 'length');
|
|
143
|
+
const len = typeof lenRaw === 'number' && Number.isSafeInteger(lenRaw) && lenRaw > 0 ? Math.min(lenRaw, ORIGINS_READ_MAX) : 0;
|
|
144
|
+
const seen = [];
|
|
145
|
+
for (let i = 0; i < len; i++) {
|
|
146
|
+
const origin = ownSlot(ownSlot(adds, String(i)), 'origin');
|
|
147
|
+
const key = originKeyOf(typeof origin === 'string' ? origin : undefined);
|
|
148
|
+
if (!seen.includes(key))
|
|
149
|
+
seen.push(key);
|
|
150
|
+
}
|
|
151
|
+
return seen.length === 0 ? renderMessage(msg(NO_ORIGIN_KEY), lang) : seen.map((k) => renderMessage(msg(k), lang)).join(renderMessage(msg('rules.origin.join'), lang));
|
|
152
|
+
}
|
|
153
|
+
const UNKNOWN_SCOPE_KEY = 'rules.scope.unknown';
|
|
154
|
+
export function persistedRuleScopeLabel(scope, lang) {
|
|
155
|
+
if (scope === 'global')
|
|
156
|
+
return renderMessage(msg('rules.scope.all'), lang);
|
|
157
|
+
if (typeof scope === 'string' && scope.startsWith('project:') && scope.length > 'project:'.length) {
|
|
158
|
+
const shown = displayUntrusted(scope.slice('project:'.length), { max: 400, blanks: true });
|
|
159
|
+
return shown === '' ? renderMessage(msg(UNKNOWN_SCOPE_KEY), lang) : shown;
|
|
160
|
+
}
|
|
161
|
+
return renderMessage(msg(UNKNOWN_SCOPE_KEY), lang);
|
|
162
|
+
}
|
|
163
|
+
const PERSISTED_RULE_REVOKE_KEYS = Object.freeze({
|
|
164
|
+
removed: {
|
|
165
|
+
yes: { notice: 'rules.revoke.removed.yes.notice', change: 'rules.revoke.removed.yes.change' },
|
|
166
|
+
unknown: { notice: 'rules.revoke.removed.unknown.notice', change: 'rules.revoke.removed.unknown.change' },
|
|
167
|
+
no: { notice: 'rules.revoke.removed.no.notice', change: 'rules.revoke.removed.no.change' },
|
|
168
|
+
},
|
|
169
|
+
'nothing-written': {
|
|
170
|
+
yes: { notice: 'rules.revoke.nothingWritten.yes.notice', change: 'rules.revoke.nothingWritten.yes.change' },
|
|
171
|
+
unknown: { notice: 'rules.revoke.nothingWritten.unknown.notice', change: 'rules.revoke.nothingWritten.unknown.change' },
|
|
172
|
+
no: { notice: 'rules.revoke.nothingWritten.no.notice', change: 'rules.revoke.nothingWritten.no.change' },
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
const REVOKE_UNKNOWN_STATUS_KEYS = Object.freeze({
|
|
176
|
+
absent: { notice: 'rules.revoke.absent.notice', change: 'rules.revoke.absent.change' },
|
|
177
|
+
unrecognised: { notice: 'rules.revoke.unrecognised.notice', change: 'rules.revoke.unrecognised.change' },
|
|
178
|
+
liveness: { yes: 'rules.revoke.liveness.yes', unknown: 'rules.revoke.liveness.unknown', no: undefined },
|
|
179
|
+
});
|
|
180
|
+
export function persistedRuleRevokeOutcome(ruleText, result, lang) {
|
|
181
|
+
const quoted = typeof ruleText === 'string' ? quoteUntrustedForSentence(ruleText, 120) : undefined;
|
|
182
|
+
const rule = quoted ?? msg('rules.revoke.thisRule');
|
|
183
|
+
const status = ownSlot(result, 'status');
|
|
184
|
+
const rawLive = ownSlot(result, 'stillLive');
|
|
185
|
+
const liveness = rawLive === 'yes' || rawLive === 'no' || rawLive === 'unknown' ? rawLive : 'unknown';
|
|
186
|
+
if (status === 'removed' || status === 'no-op') {
|
|
187
|
+
const outcome = status === 'removed' ? 'removed' : 'nothing-written';
|
|
188
|
+
const line = PERSISTED_RULE_REVOKE_KEYS[outcome][liveness];
|
|
189
|
+
return Object.freeze({ outcome, liveness, notice: renderMessage(msg(line.notice, { rule }), lang), change: renderMessage(msg(line.change, { rule }), lang) });
|
|
190
|
+
}
|
|
191
|
+
const head = typeof status === 'string' && status !== '' ? REVOKE_UNKNOWN_STATUS_KEYS.unrecognised : REVOKE_UNKNOWN_STATUS_KEYS.absent;
|
|
192
|
+
const tailKey = REVOKE_UNKNOWN_STATUS_KEYS.liveness[liveness];
|
|
193
|
+
return Object.freeze({
|
|
194
|
+
outcome: 'unknown-status',
|
|
195
|
+
liveness,
|
|
196
|
+
notice: `${renderMessage(msg(head.notice, { rule }), lang)}${tailKey === undefined ? '' : renderMessage(msg(tailKey), lang)}`,
|
|
197
|
+
change: renderMessage(msg(head.change, { rule }), lang),
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
const PERSISTED_RULE_MATCH_KEYS = Object.freeze({
|
|
201
|
+
exact: 'rules.match.exact',
|
|
202
|
+
prefix: 'rules.match.prefix',
|
|
203
|
+
wildcard: 'rules.match.wildcard',
|
|
204
|
+
subpath: 'rules.match.subpath',
|
|
205
|
+
path: 'rules.match.path',
|
|
206
|
+
name: 'rules.match.name',
|
|
207
|
+
name_prefix: 'rules.match.namePrefix',
|
|
208
|
+
host: 'rules.match.host',
|
|
209
|
+
subdomain: 'rules.match.subdomain',
|
|
210
|
+
});
|
|
211
|
+
export function persistedRuleMatchLabel(ruleOrMatch, lang) {
|
|
212
|
+
const word = typeof ruleOrMatch === 'string' ? ruleOrMatch : ownSlot(ruleOrMatch, 'match');
|
|
213
|
+
if (typeof word !== 'string' || word === '')
|
|
214
|
+
return renderMessage(msg('rules.match.unreported'), lang);
|
|
215
|
+
return renderMessage(msg(Object.hasOwn(PERSISTED_RULE_MATCH_KEYS, word) ? PERSISTED_RULE_MATCH_KEYS[word] : 'rules.match.unknown'), lang);
|
|
216
|
+
}
|
|
115
217
|
export function revokeTargetFromPersistedRule(rule, opts) {
|
|
116
218
|
const behavior = persistedRuleBehaviorOf(rule);
|
|
117
219
|
if (behavior === undefined)
|
|
@@ -434,7 +536,7 @@ export function classifySkippedReason(reason) {
|
|
|
434
536
|
}
|
|
435
537
|
export function readRulePersistOutcome(ack) {
|
|
436
538
|
const parsed = readToolApprovalRespondAck(ack);
|
|
437
|
-
if (parsed === undefined)
|
|
539
|
+
if (parsed === undefined || isToolApprovalRespondReplayed(parsed))
|
|
438
540
|
return { state: 'unknown' };
|
|
439
541
|
if (parsed.rulePersisted === true)
|
|
440
542
|
return { state: 'persisted' };
|
|
@@ -28,6 +28,21 @@ export declare function _resetArmedPlanReviewsForTest(): void;
|
|
|
28
28
|
export type PlanReviewReopenTrigger = 'user' | 'automatic';
|
|
29
29
|
export type PlanReviewGateInstanceReader = (taskId: string) => Promise<ReadonlySet<string> | null>;
|
|
30
30
|
export declare function clearPlanReviewUserDismissals(sessionKey?: string): void;
|
|
31
|
+
export type PlanReviewOfferedMode = 'three_choice' | 'two_choice' | 'unknown';
|
|
32
|
+
export interface PlanReviewCardLike {
|
|
33
|
+
readonly questionId?: string;
|
|
34
|
+
readonly questions?: ReadonlyArray<{
|
|
35
|
+
readonly options?: ReadonlyArray<{
|
|
36
|
+
readonly label?: string;
|
|
37
|
+
}>;
|
|
38
|
+
}>;
|
|
39
|
+
}
|
|
40
|
+
export interface PlanReviewQuestionIdReading {
|
|
41
|
+
readonly taskId: string;
|
|
42
|
+
readonly reopened: boolean;
|
|
43
|
+
}
|
|
44
|
+
export declare function planReviewTaskIdFromQuestionId(questionId: {} | null | undefined): PlanReviewQuestionIdReading | undefined;
|
|
45
|
+
export declare function planReviewOfferedModeOf(card: string | PlanReviewCardLike): PlanReviewOfferedMode;
|
|
31
46
|
export interface ArmPlanReviewOptions {
|
|
32
47
|
submittedInPlanMode?: boolean;
|
|
33
48
|
readGateInstanceKeys?: PlanReviewGateInstanceReader;
|
|
@@ -76,22 +91,25 @@ export declare function notePlanReviewGateLeft(taskId: string): void;
|
|
|
76
91
|
export declare function latestPlanReviewDecisionMark(taskId: string): number | null;
|
|
77
92
|
export declare function __resetPlanReviewDecisionLatchForTests(): void;
|
|
78
93
|
export declare function decidePlanReview(taskId: string, decision: 'approve' | 'reject', permissionModeAfter?: string, opts?: DecidePlanReviewOptions): Promise<void>;
|
|
79
|
-
export interface
|
|
80
|
-
mintFreshQuestionId?: boolean;
|
|
81
|
-
deliverDecision?: (taskId: string, decision: 'approve' | 'reject', reason?: string) => void | Promise<void>;
|
|
94
|
+
export interface ReopenPlanReviewSharedOpts {
|
|
82
95
|
sessionKey?: string;
|
|
83
|
-
|
|
84
|
-
onOutcome?: PlanReviewDeliveryOptions['onOutcome'];
|
|
85
|
-
presentationReceiptMs?: number;
|
|
96
|
+
presentationReceiptMs: number;
|
|
86
97
|
trigger?: PlanReviewReopenTrigger;
|
|
87
98
|
readGateInstanceKeys?: PlanReviewGateInstanceReader;
|
|
88
99
|
pendingReadStartedAt?: number;
|
|
89
100
|
}
|
|
101
|
+
export interface ReopenPlanReviewFreshOpts extends ReopenPlanReviewSharedOpts {
|
|
102
|
+
mintFreshQuestionId?: true;
|
|
103
|
+
deliverDecision?: (taskId: string, decision: 'approve' | 'reject', reason?: string) => void | Promise<void>;
|
|
104
|
+
wire?: PlanReviewWire;
|
|
105
|
+
onOutcome?: PlanReviewDeliveryOptions['onOutcome'];
|
|
106
|
+
}
|
|
107
|
+
export interface ReopenPlanReviewReuseOpts extends ReopenPlanReviewSharedOpts {
|
|
108
|
+
mintFreshQuestionId: false;
|
|
109
|
+
deliverDecision?: never;
|
|
110
|
+
wire?: never;
|
|
111
|
+
onOutcome?: never;
|
|
112
|
+
}
|
|
113
|
+
export type ReopenPlanReviewOpts = ReopenPlanReviewFreshOpts | ReopenPlanReviewReuseOpts;
|
|
90
114
|
export declare function _resetActiveReopenRespondersForTest(): void;
|
|
91
|
-
export declare function reopenPlanReviewCard(taskId: string, opts: ReopenPlanReviewOpts
|
|
92
|
-
presentationReceiptMs: number;
|
|
93
|
-
}): Promise<ReopenCardVerdict>;
|
|
94
|
-
export declare function reopenPlanReviewCard(taskId: string, opts?: ReopenPlanReviewOpts & {
|
|
95
|
-
presentationReceiptMs?: undefined;
|
|
96
|
-
}): ReopenCardVerdict;
|
|
97
|
-
export declare function reopenPlanReviewCard(taskId: string, opts?: ReopenPlanReviewOpts): ReopenCardVerdict | Promise<ReopenCardVerdict>;
|
|
115
|
+
export declare function reopenPlanReviewCard(taskId: string, opts: ReopenPlanReviewOpts): Promise<ReopenCardVerdict>;
|
|
@@ -7,11 +7,13 @@ import { enqueuePlanReviewOutcome } from '../notifications.js';
|
|
|
7
7
|
import { corruptStoredRowContent, corruptStoredRowWhere } from '../wireErrorTriage.js';
|
|
8
8
|
import { decideFailureNote } from '../decideFailureNote.js';
|
|
9
9
|
import { wireFailureTextsOf } from '../wireFailureShape.js';
|
|
10
|
+
import { readOwnDataNonEmptyString, readOwnDataValue } from '../ownKey.js';
|
|
10
11
|
import { checkpointUnsupportedVersionContent, checkpointUnsupportedVersionFromError, resumeContextUnavailableContent, resumeContextUnavailableFromError } from '../resumeRefusalCopy.js';
|
|
11
|
-
import { REQUEST_FIELD_CONFLICT
|
|
12
|
+
import { REQUEST_FIELD_CONFLICT } from '../engineErrorCodes.js';
|
|
13
|
+
import { refusalDeliveryOf } from './decisionRefusal.js';
|
|
12
14
|
import { denyReasonForWire, isPlanReviewModeAfter } from './hitlBridge.js';
|
|
13
15
|
import { planReviewQuestionId, REOPEN_ID_TAIL, taskIdFromPlanReviewQuestionId } from './gateIdentity.js';
|
|
14
|
-
import { notePlanReviewAnswered, notePlanReviewAnsweredFor, planReviewArmedKeyFor,
|
|
16
|
+
import { notePlanReviewAnswered, notePlanReviewAnsweredFor, planReviewArmedKeyFor, waitForGateArmedFor, wasGateArmedFor, } from './armedGateRegistry.js';
|
|
15
17
|
import { createSessionSlot, DEFAULT_SESSION_KEY } from '../sessionSlot.js';
|
|
16
18
|
import { PLAN_REVIEW_GATE_KIND, durableDecideLegOf } from '../adapter/activeRunSelfHeal.js';
|
|
17
19
|
import { readRunTerminal, runTerminalGateKind } from '../runTerminal.js';
|
|
@@ -144,9 +146,12 @@ function pausedGateKindOf(carrier) {
|
|
|
144
146
|
}
|
|
145
147
|
const armedPlanReviewTaskIds = new Set();
|
|
146
148
|
const offerModeAfterByTask = new Map();
|
|
149
|
+
const offeredModeByQuestionId = new Map();
|
|
150
|
+
const OFFERED_MODE_LEDGER_MAX = 64;
|
|
147
151
|
export function _resetArmedPlanReviewsForTest() {
|
|
148
152
|
armedPlanReviewTaskIds.clear();
|
|
149
153
|
offerModeAfterByTask.clear();
|
|
154
|
+
offeredModeByQuestionId.clear();
|
|
150
155
|
planReviewDismissalsByKey.clear();
|
|
151
156
|
}
|
|
152
157
|
const ON_SCREEN = Promise.resolve(true);
|
|
@@ -247,12 +252,85 @@ function planReviewQuestions(question, offerModeAfter = false) {
|
|
|
247
252
|
},
|
|
248
253
|
];
|
|
249
254
|
}
|
|
255
|
+
function planReviewQuestionFrame(questionId, question, offerModeAfter, reopened = false) {
|
|
256
|
+
if (!reopened) {
|
|
257
|
+
offeredModeByQuestionId.delete(questionId);
|
|
258
|
+
offeredModeByQuestionId.set(questionId, offerModeAfter);
|
|
259
|
+
while (offeredModeByQuestionId.size > OFFERED_MODE_LEDGER_MAX) {
|
|
260
|
+
const oldest = offeredModeByQuestionId.keys().next();
|
|
261
|
+
if (oldest.done === true)
|
|
262
|
+
break;
|
|
263
|
+
offeredModeByQuestionId.delete(oldest.value);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return { type: 'question', questionId, questions: planReviewQuestions(question, offerModeAfter) };
|
|
267
|
+
}
|
|
250
268
|
function publishPlanReviewCard(taskId) {
|
|
251
|
-
publishQuestionFrame(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
269
|
+
publishQuestionFrame(planReviewQuestionFrame(planReviewQuestionId(taskId), ARM_QUESTION, offerModeAfterByTask.get(taskId) === true));
|
|
270
|
+
}
|
|
271
|
+
const OFFERED_MODE_SCAN_MAX = 32;
|
|
272
|
+
function ownElementsOf(v, max) {
|
|
273
|
+
if (!Array.isArray(v))
|
|
274
|
+
return [];
|
|
275
|
+
const n = Math.min(v.length, max);
|
|
276
|
+
const out = [];
|
|
277
|
+
for (let i = 0; i < n; i++)
|
|
278
|
+
out.push(readOwnDataValue(v, String(i)));
|
|
279
|
+
return out;
|
|
280
|
+
}
|
|
281
|
+
function offeredModeFromLabels(card) {
|
|
282
|
+
let modeAfter = false;
|
|
283
|
+
let plain = false;
|
|
284
|
+
for (const q of ownElementsOf(readOwnDataValue(card, 'questions'), OFFERED_MODE_SCAN_MAX)) {
|
|
285
|
+
if (typeof q !== 'object' || q === null)
|
|
286
|
+
continue;
|
|
287
|
+
for (const o of ownElementsOf(readOwnDataValue(q, 'options'), OFFERED_MODE_SCAN_MAX)) {
|
|
288
|
+
if (typeof o !== 'object' || o === null)
|
|
289
|
+
continue;
|
|
290
|
+
const label = readOwnDataNonEmptyString(o, 'label');
|
|
291
|
+
if (label === PLAN_REVIEW_APPROVE_AUTO_LABEL || label === PLAN_REVIEW_APPROVE_MANUAL_LABEL)
|
|
292
|
+
modeAfter = true;
|
|
293
|
+
else if (label === APPROVE_LABEL)
|
|
294
|
+
plain = true;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (modeAfter && !plain)
|
|
298
|
+
return 'three_choice';
|
|
299
|
+
if (plain && !modeAfter)
|
|
300
|
+
return 'two_choice';
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
303
|
+
export function planReviewTaskIdFromQuestionId(questionId) {
|
|
304
|
+
if (typeof questionId !== 'string')
|
|
305
|
+
return undefined;
|
|
306
|
+
const taskId = taskIdFromPlanReviewQuestionId(questionId);
|
|
307
|
+
if (taskId === undefined)
|
|
308
|
+
return undefined;
|
|
309
|
+
return Object.freeze({ taskId, reopened: questionId.includes(REOPEN_ID_TAIL) });
|
|
310
|
+
}
|
|
311
|
+
function offeredModeFromQuestionId(questionId) {
|
|
312
|
+
if (taskIdFromPlanReviewQuestionId(questionId) === undefined)
|
|
313
|
+
return 'unknown';
|
|
314
|
+
const recorded = offeredModeByQuestionId.get(questionId);
|
|
315
|
+
if (recorded !== undefined)
|
|
316
|
+
return recorded ? 'three_choice' : 'two_choice';
|
|
317
|
+
return questionId.includes(REOPEN_ID_TAIL) ? 'two_choice' : 'unknown';
|
|
318
|
+
}
|
|
319
|
+
export function planReviewOfferedModeOf(card) {
|
|
320
|
+
try {
|
|
321
|
+
if (typeof card === 'string')
|
|
322
|
+
return offeredModeFromQuestionId(card);
|
|
323
|
+
if (typeof card !== 'object' || card === null)
|
|
324
|
+
return 'unknown';
|
|
325
|
+
const fromLabels = offeredModeFromLabels(card);
|
|
326
|
+
if (fromLabels !== undefined)
|
|
327
|
+
return fromLabels;
|
|
328
|
+
const questionId = readOwnDataNonEmptyString(card, 'questionId');
|
|
329
|
+
return questionId === undefined ? 'unknown' : offeredModeFromQuestionId(questionId);
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
return 'unknown';
|
|
333
|
+
}
|
|
256
334
|
}
|
|
257
335
|
export function armPlanReviewApproval(result, sessionKey, opts) {
|
|
258
336
|
let armedTaskId;
|
|
@@ -752,13 +830,13 @@ async function decidePlanReviewInner(taskId, decision, permissionModeAfter, disp
|
|
|
752
830
|
else if (typeof status === 'number' && corruptStoredRowWhere(e) !== undefined) {
|
|
753
831
|
const where = corruptStoredRowWhere(e);
|
|
754
832
|
hostLog('debug', `planReviewWire: ${decision} → ${String(status)} corrupt (stored resume context unreadable)`);
|
|
755
|
-
effect = 'not_applied';
|
|
833
|
+
effect = refusalDeliveryOf(e, { route: 'plan_review' }).delivery === 'refused' ? 'not_applied' : 'unconfirmed';
|
|
756
834
|
outcome = `This ${decision} was not applied. ${corruptStoredRowContent(where)}`;
|
|
757
835
|
}
|
|
758
836
|
else if (typeof status === 'number') {
|
|
759
837
|
const failureTexts = wireFailureTextsOf(e);
|
|
760
838
|
hostLog('debug', `planReviewWire: ${decision} → ${status} ${failureTexts.log.slice(0, 200)}`);
|
|
761
|
-
effect = (
|
|
839
|
+
effect = refusalDeliveryOf(e, { route: 'plan_review' }).delivery === 'refused' ? 'not_applied' : 'unconfirmed';
|
|
762
840
|
outcome = `${`The plan_review decision failed: HTTP ${status} ${failureTexts.reason}`.trim()}${decideFailureNote(e)}`;
|
|
763
841
|
}
|
|
764
842
|
else if (noAnswer === 'time-limit' || noAnswer === 'deadline') {
|
|
@@ -828,8 +906,6 @@ export function _resetActiveReopenRespondersForTest() {
|
|
|
828
906
|
const reopenFlights = new Map();
|
|
829
907
|
function joinReopenFlight(flight, taskId, receiptMs) {
|
|
830
908
|
hostLog('debug', `planReviewWire: reopen for task ${taskId} joined the card already on its way (no second card, its answer path kept)`);
|
|
831
|
-
if (receiptMs === undefined)
|
|
832
|
-
return { reopened: true, firstSight: false };
|
|
833
909
|
const ac = new AbortController();
|
|
834
910
|
return Promise.race([
|
|
835
911
|
flight.presented.then((v) => v === true, () => false),
|
|
@@ -867,17 +943,13 @@ function mintPlanReviewReopen(taskId, opts, sessionKey, receiptMs) {
|
|
|
867
943
|
settle(false);
|
|
868
944
|
throw e;
|
|
869
945
|
}
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
});
|
|
878
|
-
}
|
|
879
|
-
settle(verdict.reopened === true);
|
|
880
|
-
return verdict;
|
|
946
|
+
return verdict.then((v) => {
|
|
947
|
+
settle(v.reopened === true);
|
|
948
|
+
return v;
|
|
949
|
+
}, (e) => {
|
|
950
|
+
settle(false);
|
|
951
|
+
throw e;
|
|
952
|
+
});
|
|
881
953
|
}
|
|
882
954
|
function mintPlanReviewReopenCard(taskId, opts, sessionKey, receiptMs) {
|
|
883
955
|
const markBefore = dismissalEntryFor(sessionKey, taskId);
|
|
@@ -893,30 +965,10 @@ function mintPlanReviewReopenCard(taskId, opts, sessionKey, receiptMs) {
|
|
|
893
965
|
const mintFresh = opts?.mintFreshQuestionId !== false;
|
|
894
966
|
if (!mintFresh && hasLocalQuestionResponder(canonicalId)) {
|
|
895
967
|
hostLog('debug', `planReviewWire: reopen for task ${taskId} reusing the canonical responder (path=reopen-canonical)`);
|
|
896
|
-
if (opts?.deliverDecision !== undefined) {
|
|
897
|
-
hostLog('debug', `planReviewWire: reopen canonical-reuse branch for task ${taskId} ignores opts.deliverDecision (answers route through the existing arm responder — documented exception)`);
|
|
898
|
-
}
|
|
899
|
-
if (opts?.wire !== undefined || opts?.onOutcome !== undefined) {
|
|
900
|
-
hostLog('debug', `planReviewWire: reopen canonical-reuse branch for task ${taskId} ignores opts.wire / opts.onOutcome (answers route through the existing arm responder and the wire it was armed with — documented exception)`);
|
|
901
|
-
}
|
|
902
968
|
retireActiveReopen(sessionKey, canonicalId);
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
type: 'question',
|
|
907
|
-
questionId: canonicalId,
|
|
908
|
-
questions: planReviewQuestions(ARM_QUESTION, offerModeAfterByTask.get(taskId) === true),
|
|
909
|
-
});
|
|
910
|
-
return settleOnReceipt(receipt, firstSight);
|
|
911
|
-
}
|
|
912
|
-
publishQuestionFrameFor(sessionKey, {
|
|
913
|
-
type: 'question',
|
|
914
|
-
questionId: canonicalId,
|
|
915
|
-
questions: planReviewQuestions(ARM_QUESTION, offerModeAfterByTask.get(taskId) === true),
|
|
916
|
-
});
|
|
917
|
-
registerArmedGateFor(sessionKey, armedKey);
|
|
918
|
-
revokePlanReviewUserDismissal(sessionKey, taskId, markBefore);
|
|
919
|
-
return { reopened: true, firstSight };
|
|
969
|
+
const receipt = waitForGateArmedFor(sessionKey, [canonicalId], receiptMs);
|
|
970
|
+
publishQuestionFrameFor(sessionKey, planReviewQuestionFrame(canonicalId, ARM_QUESTION, offerModeAfterByTask.get(taskId) === true));
|
|
971
|
+
return settleOnReceipt(receipt, firstSight);
|
|
920
972
|
}
|
|
921
973
|
retireActiveReopen(sessionKey, canonicalId);
|
|
922
974
|
if (unregisterLocalQuestionResponder(canonicalId)) {
|
|
@@ -961,23 +1013,9 @@ function mintPlanReviewReopenCard(taskId, opts, sessionKey, receiptMs) {
|
|
|
961
1013
|
return { ok: true };
|
|
962
1014
|
});
|
|
963
1015
|
activeReopenResponders.set(activeKey, { questionId, unregister });
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
type: 'question',
|
|
968
|
-
questionId,
|
|
969
|
-
questions: planReviewQuestions(REOPEN_QUESTION),
|
|
970
|
-
});
|
|
971
|
-
return settleOnReceipt(receipt, firstSight);
|
|
972
|
-
}
|
|
973
|
-
registerArmedGateFor(sessionKey, armedKey);
|
|
974
|
-
publishQuestionFrameFor(sessionKey, {
|
|
975
|
-
type: 'question',
|
|
976
|
-
questionId,
|
|
977
|
-
questions: planReviewQuestions(REOPEN_QUESTION),
|
|
978
|
-
});
|
|
979
|
-
revokePlanReviewUserDismissal(sessionKey, taskId, markBefore);
|
|
980
|
-
return { reopened: true, firstSight };
|
|
1016
|
+
const receipt = waitForGateArmedFor(sessionKey, [questionId], receiptMs);
|
|
1017
|
+
publishQuestionFrameFor(sessionKey, planReviewQuestionFrame(questionId, REOPEN_QUESTION, false, true));
|
|
1018
|
+
return settleOnReceipt(receipt, firstSight);
|
|
981
1019
|
}
|
|
982
1020
|
function noPresentationSurfaceVerdict(taskId, sessionKey) {
|
|
983
1021
|
const verdict = { reopened: false, _sema_noPresentationSurface: true };
|
|
@@ -1075,44 +1113,48 @@ async function staleDismissalVerdict(current, sessionKey, taskId, receiptMs) {
|
|
|
1075
1113
|
}
|
|
1076
1114
|
export function reopenPlanReviewCard(taskId, opts) {
|
|
1077
1115
|
const receiptMs = opts?.presentationReceiptMs;
|
|
1116
|
+
if (typeof receiptMs !== 'number' || Number.isNaN(receiptMs)) {
|
|
1117
|
+
hostLog('debug', `planReviewWire: reopen for task ${String(taskId)} refused — presentationReceiptMs is required (a number of milliseconds); the synchronous form was retired in 0.98.0`);
|
|
1118
|
+
return Promise.resolve({ reopened: false });
|
|
1119
|
+
}
|
|
1078
1120
|
try {
|
|
1079
1121
|
if (typeof taskId !== 'string' || taskId.length === 0) {
|
|
1080
|
-
return
|
|
1122
|
+
return Promise.resolve({ reopened: false });
|
|
1123
|
+
}
|
|
1124
|
+
const injected = opts;
|
|
1125
|
+
if (opts?.mintFreshQuestionId === false && (injected?.deliverDecision !== undefined || injected?.wire !== undefined || injected?.onOutcome !== undefined)) {
|
|
1126
|
+
hostLog('error', `planReviewWire: plan_review reopen for task ${taskId} refused — mintFreshQuestionId:false reuses the armed card's responder and its delivery, ` +
|
|
1127
|
+
'so deliverDecision / wire / onOutcome cannot be given with it; drop mintFreshQuestionId:false to deliver through the injected path');
|
|
1128
|
+
return Promise.resolve({ reopened: false });
|
|
1081
1129
|
}
|
|
1082
|
-
const readStart = typeof opts
|
|
1130
|
+
const readStart = typeof opts.pendingReadStartedAt === 'number' && Number.isFinite(opts.pendingReadStartedAt) ? opts.pendingReadStartedAt : undefined;
|
|
1083
1131
|
if (planReviewDecisionInFlight(taskId, readStart)) {
|
|
1084
1132
|
hostLog('debug', `planReviewWire: reopen for task ${taskId} refused — a decision for this task is in flight (its answer is still being delivered)`);
|
|
1085
1133
|
const refused = { reopened: false, _sema_decisionInFlight: true };
|
|
1086
|
-
return
|
|
1134
|
+
return Promise.resolve(refused);
|
|
1087
1135
|
}
|
|
1088
1136
|
const guardStartedAt = planReviewPendingReadMark();
|
|
1089
1137
|
const recheckReadStart = readStart === undefined ? guardStartedAt : Math.min(readStart, guardStartedAt);
|
|
1090
|
-
const sessionKey = opts
|
|
1138
|
+
const sessionKey = opts.sessionKey ?? DEFAULT_SESSION_KEY;
|
|
1091
1139
|
if (!hasQuestionOverlayFor(sessionKey)) {
|
|
1092
|
-
|
|
1093
|
-
return receiptMs === undefined ? noSurface : Promise.resolve(noSurface);
|
|
1140
|
+
return Promise.resolve(noPresentationSurfaceVerdict(taskId, sessionKey));
|
|
1094
1141
|
}
|
|
1095
|
-
if (sessionKey !== DEFAULT_SESSION_KEY && opts
|
|
1142
|
+
if (sessionKey !== DEFAULT_SESSION_KEY && opts.deliverDecision === undefined && opts.wire === undefined) {
|
|
1096
1143
|
hostLog('error', `planReviewWire: plan_review 卡未重开 —— sessionKey=${JSON.stringify(sessionKey)} 是非默认槽,` +
|
|
1097
1144
|
'而缺省决断投递口(decidePlanReview)今天固定打默认槽的 baseUrl/token/principal。' +
|
|
1098
1145
|
'整条链转 keyed 之前,非默认槽要重开请自带 deliverDecision(按本槽投递);' +
|
|
1099
1146
|
'此处拒绝而不是照发 —— 照发会把这条会话的决断发到另一个槽上。');
|
|
1100
|
-
return
|
|
1147
|
+
return Promise.resolve({ reopened: false });
|
|
1101
1148
|
}
|
|
1102
|
-
const trigger = opts
|
|
1149
|
+
const trigger = opts.trigger === undefined ? undefined : opts.trigger === 'user' ? 'user' : 'automatic';
|
|
1103
1150
|
if (trigger === 'automatic') {
|
|
1104
1151
|
const mark = planReviewUserDismissalMarkFor(sessionKey, taskId);
|
|
1105
|
-
if (mark !== undefined)
|
|
1106
|
-
if (receiptMs === undefined || opts === undefined) {
|
|
1107
|
-
hostLog('debug', `planReviewWire: automatic reopen for task ${taskId} refused — the user closed this gate's card`);
|
|
1108
|
-
return { reopened: false, dismissedByUser: true };
|
|
1109
|
-
}
|
|
1152
|
+
if (mark !== undefined)
|
|
1110
1153
|
return reopenAfterDismissalCheck(taskId, opts, sessionKey, receiptMs, mark, recheckReadStart);
|
|
1111
|
-
}
|
|
1112
1154
|
}
|
|
1113
1155
|
return mintPlanReviewReopen(taskId, opts, sessionKey, receiptMs);
|
|
1114
1156
|
}
|
|
1115
1157
|
catch {
|
|
1116
|
-
return
|
|
1158
|
+
return Promise.resolve({ reopened: false });
|
|
1117
1159
|
}
|
|
1118
1160
|
}
|
|
@@ -2,6 +2,3 @@ import { CORE_PROTOCOL_PREFIXES } from '../generated/toolNameTables.js';
|
|
|
2
2
|
export const PREFIXES_IN_PROSE = CORE_PROTOCOL_PREFIXES.map((prefix) => `"${prefix}"`).join(' or ');
|
|
3
3
|
export const REFUSED_NAME_CLASSES = `a retired tool name, or a name that contains "__" but does not start with ${PREFIXES_IN_PROSE}`;
|
|
4
4
|
export const REFUSED_NAME_FIX = `If the tool still exists, use its current name; a server or agent-peer tool name starts with ${PREFIXES_IN_PROSE}.`;
|
|
5
|
-
export const RULES_LEGACY_TOOL_NAME_WRITE_NOTE = `The engine refused to write these session rules, and the stored record was not changed at all: they name a tool the engine refuses — ${REFUSED_NAME_CLASSES} (the engine's own error text names the entry). ` +
|
|
6
|
-
`${REFUSED_NAME_FIX} Then write the rules again. ` +
|
|
7
|
-
'If that entry was already in this session’s rule record, it has to be removed from the record before the record can be written again.';
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { type ApprovalSettledHow } from './approvalHolds.js';
|
|
2
|
-
import { type ApprovalsListEnvelope, type
|
|
2
|
+
import { type ApprovalsListEnvelope, type CrashConvergedRowReading } from './crashConverged.js';
|
|
3
3
|
export type ReplayedApprovalDisposition = {
|
|
4
4
|
readonly kind: 'live';
|
|
5
5
|
readonly basis: 'live_leg' | 'preamble' | 'pending_list';
|
|
6
6
|
} | {
|
|
7
7
|
readonly kind: 'decided';
|
|
8
|
-
readonly cause?:
|
|
9
|
-
readonly needsHumanReason?: NonNullable<
|
|
8
|
+
readonly cause?: CrashConvergedRowReading['cause'];
|
|
9
|
+
readonly needsHumanReason?: NonNullable<CrashConvergedRowReading['needsHumanReason']>;
|
|
10
10
|
readonly settled?: ApprovalSettledHow;
|
|
11
|
+
readonly parked?: true;
|
|
11
12
|
} | {
|
|
12
13
|
readonly kind: 'unknown';
|
|
13
14
|
readonly why: 'unreadable_frame' | 'no_approval_id' | 'not_read' | 'list_unreadable' | 'list_not_reported' | 'list_incomplete';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hasLedgerPositionKey } from './gateLedger.js';
|
|
2
|
-
import { anyApprovalSettled, settledApprovalOf } from './approvalHolds.js';
|
|
2
|
+
import { anyApprovalSettled, APPROVAL_SETTLED_HOWS, settledApprovalOf } from './approvalHolds.js';
|
|
3
3
|
import { readLivePendingRows } from './livePendingAsk.js';
|
|
4
4
|
import { projectCrashConverged } from './crashConverged.js';
|
|
5
5
|
import { quoteUntrustedForSentence } from '../displayUntrusted.js';
|
|
@@ -9,7 +9,7 @@ const unknown = (why) => Object.freeze({ kind: 'unknown', why });
|
|
|
9
9
|
const decided = (row) => Object.freeze(row === undefined
|
|
10
10
|
? { kind: 'decided' }
|
|
11
11
|
: { kind: 'decided', cause: row.cause, ...(row.needsHumanReason !== undefined ? { needsHumanReason: row.needsHumanReason } : {}) });
|
|
12
|
-
const decidedSettled = (how) => Object.freeze({ kind: 'decided', settled: how });
|
|
12
|
+
const decidedSettled = (how, parked) => Object.freeze(parked && how === 'closed_by_engine' ? { kind: 'decided', settled: how, parked: true } : { kind: 'decided', settled: how });
|
|
13
13
|
function approvalIdOf(frame) {
|
|
14
14
|
const v = frame.approvalId;
|
|
15
15
|
return typeof v === 'string' && v !== '' ? v : undefined;
|
|
@@ -29,7 +29,7 @@ export function settledApprovalDisposition(frame) {
|
|
|
29
29
|
if (!anyApprovalSettled())
|
|
30
30
|
return undefined;
|
|
31
31
|
const entry = settledApprovalOf(approvalIdOf(frame));
|
|
32
|
-
return entry === undefined ? undefined : decidedSettled(entry.how);
|
|
32
|
+
return entry === undefined ? undefined : decidedSettled(entry.how, entry.parked);
|
|
33
33
|
}
|
|
34
34
|
catch {
|
|
35
35
|
return undefined;
|
|
@@ -161,7 +161,10 @@ export function replayedApprovalClosesCardFrame(disposition) {
|
|
|
161
161
|
if (readOwnDataValue(disposition, 'kind') !== 'decided')
|
|
162
162
|
return false;
|
|
163
163
|
const cause = readOwnDataValue(disposition, 'cause');
|
|
164
|
-
|
|
164
|
+
if (typeof cause === 'string' && Object.hasOwn(STOPPED_BY_CAUSE, cause))
|
|
165
|
+
return true;
|
|
166
|
+
const settled = readOwnDataValue(disposition, 'settled');
|
|
167
|
+
return typeof settled === 'string' && APPROVAL_SETTLED_HOWS.includes(settled) && !('parked' in disposition);
|
|
165
168
|
}
|
|
166
169
|
catch {
|
|
167
170
|
return false;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { SessionPermissionRules } from '@sema-agent/sdk';
|
|
2
2
|
import type { ToolRosterView } from '../toolRoster.js';
|
|
3
|
+
import type { SessionRuleInertReason } from './sessionPolicyWire.js';
|
|
3
4
|
export type SessionPolicyWithheldWhy = 'ask_no_bucket' | 'qualified_deny' | 'peer_wide' | 'wildcard' | 'not_a_tool_name' | 'legacy_tool_name' | 'not_in_roster';
|
|
4
5
|
export declare const SESSION_POLICY_WITHHELD_WHY: readonly SessionPolicyWithheldWhy[];
|
|
5
6
|
export interface SessionPolicyWithheldRule {
|
|
6
7
|
readonly rule: string;
|
|
7
8
|
readonly why: SessionPolicyWithheldWhy;
|
|
8
9
|
readonly currentName?: string;
|
|
10
|
+
readonly inertReason?: SessionRuleInertReason;
|
|
9
11
|
}
|
|
10
12
|
export interface SessionPolicyDeliverability {
|
|
11
13
|
readonly deliverable: SessionPermissionRules;
|