@sema-agent/client-core 0.91.0 → 0.93.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 +351 -0
- package/README.md +51 -34
- package/dist/adapt/arms.js +6 -12
- package/dist/adapt/panelTasks.d.ts +0 -2
- package/dist/adapt/panelTasks.js +6 -26
- package/dist/adapt/toolCards.js +6 -4
- package/dist/adapt.d.ts +1 -1
- package/dist/adapt.js +3 -3
- package/dist/adapter/activeRunSelfHeal.d.ts +0 -2
- package/dist/adapter/activeRunSelfHeal.js +5 -27
- package/dist/adapter/downstream/terminalToSdkResult.js +16 -7
- package/dist/adapter/runStream.js +6 -2
- package/dist/agentsWireCaps.js +1 -1
- package/dist/approvalDecidedByCapability.d.ts +16 -0
- package/dist/approvalDecidedByCapability.js +47 -0
- package/dist/approvalsStreamLiveCapability.js +3 -3
- package/dist/askSurvivesStandingAnswer.d.ts +4 -1
- package/dist/askSurvivesStandingAnswer.js +13 -0
- package/dist/autoModeUnavailable.js +3 -2
- package/dist/centerWiringCapability.js +1 -1
- package/dist/cloudConfigWireCaps.js +10 -9
- package/dist/compensations.js +7 -7
- package/dist/controlRouter.d.ts +23 -23
- package/dist/controlRouter.js +114 -49
- package/dist/coreValuePorts.d.ts +4 -2
- package/dist/coreValuePorts.js +5 -0
- package/dist/decideFailureNote.js +4 -2
- package/dist/decideReceipt.d.ts +11 -0
- package/dist/decideReceipt.js +95 -9
- package/dist/detachWire.d.ts +2 -14
- package/dist/detachWire.js +1 -47
- package/dist/deviceExecutorManagementCapability.d.ts +6 -2
- package/dist/deviceExecutorManagementCapability.js +61 -15
- package/dist/displayUntrusted.js +2 -1
- package/dist/effectiveFacts.d.ts +14 -4
- package/dist/effectiveFacts.js +45 -5
- package/dist/engineAgentAbsence.js +2 -1
- package/dist/engineCapReader.js +16 -10
- package/dist/engineCapsCache.d.ts +2 -0
- package/dist/engineCapsCache.js +13 -2
- package/dist/engineConfigDrift.d.ts +20 -0
- package/dist/engineConfigDrift.js +54 -0
- package/dist/engineErrorCodes.d.ts +17 -0
- package/dist/engineErrorCodes.js +45 -0
- package/dist/engineInlineTaskStats.d.ts +1 -0
- package/dist/engineNoticeCodes.d.ts +16 -2
- package/dist/engineNoticeCodes.js +71 -0
- package/dist/engineWireFor.d.ts +22 -0
- package/dist/engineWireFor.js +154 -9
- package/dist/engineWireSdk.d.ts +0 -1
- package/dist/engineWireSdk.js +0 -3
- package/dist/executionLaneCapability.js +4 -2
- package/dist/fileHistoryCaptureCapability.d.ts +1 -1
- package/dist/fileHistoryCaptureCapability.js +1 -6
- package/dist/fileHistoryLegNotice.d.ts +1 -1
- package/dist/fileHistoryLegNotice.js +1 -6
- package/dist/gateOutcome.js +2 -17
- package/dist/gateVocabulary.d.ts +2 -8
- package/dist/gateVocabulary.js +6 -32
- package/dist/generated/engineFactTables.d.ts +17 -1
- package/dist/generated/engineFactTables.js +91 -0
- package/dist/generated/engineNoticeTables.d.ts +1 -1
- package/dist/generated/engineNoticeTables.js +4 -1
- package/dist/generated/settingsSchemaTables.d.ts +8 -0
- package/dist/generated/settingsSchemaTables.js +40 -0
- package/dist/goalStopHook.d.ts +1 -8
- package/dist/goalStopHook.js +2 -58
- package/dist/headlessPermissionModeWire.d.ts +3 -2
- package/dist/headlessPermissionModeWire.js +46 -5
- package/dist/hitl/allowRuleShadow.d.ts +21 -0
- package/dist/hitl/allowRuleShadow.js +167 -0
- package/dist/hitl/askClassPair.d.ts +14 -0
- package/dist/hitl/askClassPair.js +42 -0
- package/dist/hitl/askGateWire.js +1 -0
- package/dist/hitl/askParkRowRouting.js +2 -2
- package/dist/hitl/askSurvivesPosture.d.ts +5 -0
- package/dist/hitl/askSurvivesPosture.js +17 -0
- package/dist/hitl/automaticAnswerVerdict.d.ts +21 -0
- package/dist/hitl/automaticAnswerVerdict.js +143 -0
- package/dist/hitl/crashConverged.d.ts +1 -0
- package/dist/hitl/crashConverged.js +1 -1
- package/dist/hitl/frameRouter.d.ts +2 -0
- package/dist/hitl/frameRouter.js +73 -16
- package/dist/hitl/gateLedger.d.ts +7 -0
- package/dist/hitl/gateLedger.js +37 -5
- package/dist/hitl/hitlBridge.d.ts +1 -0
- package/dist/hitl/hitlBridge.js +6 -1
- package/dist/hitl/hitlHostSurface.d.ts +5 -2
- package/dist/hitl/hitlHostSurface.js +25 -3
- package/dist/hitl/livePendingAsk.js +24 -5
- package/dist/hitl/parkResolver.js +24 -4
- package/dist/hitl/persistedRulesWire.d.ts +4 -1
- package/dist/hitl/persistedRulesWire.js +38 -19
- package/dist/hitl/planReviewWire.d.ts +0 -2
- package/dist/hitl/planReviewWire.js +3 -20
- package/dist/hitl/replayedApproval.d.ts +21 -0
- package/dist/hitl/replayedApproval.js +89 -0
- package/dist/hitl/sessionPolicyDeliverable.js +20 -2
- package/dist/hitl/sessionPolicyWire.d.ts +10 -0
- package/dist/hitl/sessionPolicyWire.js +19 -6
- package/dist/hitl/toolApprovalWire.d.ts +27 -7
- package/dist/hitl/toolApprovalWire.js +153 -94
- package/dist/hookMatcherVerdict.js +2 -1
- package/dist/hooksWireCaps.d.ts +1 -1
- package/dist/hooksWireCaps.js +1 -1
- package/dist/humanTurn.js +3 -4
- package/dist/index.d.ts +21 -6
- package/dist/index.js +17 -4
- package/dist/inheritEnvWire.d.ts +1 -4
- package/dist/inheritEnvWire.js +3 -22
- package/dist/limitsWire.d.ts +0 -6
- package/dist/limitsWire.js +0 -38
- package/dist/mcpLiveness.js +2 -1
- package/dist/mcpProbeCapability.js +1 -1
- package/dist/mcpProbeWire.js +10 -12
- package/dist/mcpReconnect.d.ts +5 -0
- package/dist/mcpReconnect.js +28 -0
- package/dist/memoryComplianceCapability.js +2 -2
- package/dist/memoryOriginCapability.js +2 -2
- package/dist/memoryVerbsWire.d.ts +1 -1
- package/dist/memoryVerbsWire.js +17 -13
- package/dist/model/catalog.js +2 -1
- package/dist/model/providerPresets.d.ts +3 -1
- package/dist/model/tierVocabulary.d.ts +2 -1
- package/dist/model/tierVocabulary.js +3 -8
- package/dist/ownKey.d.ts +2 -0
- package/dist/ownKey.js +15 -0
- package/dist/peerFrames.js +2 -2
- package/dist/peerLaneCapability.js +2 -2
- package/dist/permissionModesCapability.d.ts +16 -0
- package/dist/permissionModesCapability.js +71 -0
- package/dist/permissionRuleIssue.js +10 -7
- package/dist/permissionRulesWriteCapability.js +2 -2
- package/dist/permissionWireCaps.d.ts +2 -0
- package/dist/permissionWireCaps.js +8 -1
- package/dist/permissionsAllowGrantCapability.js +7 -2
- package/dist/permissionsDeclaration.d.ts +7 -1
- package/dist/permissionsDeclaration.js +29 -20
- package/dist/pluginHooksWire.js +2 -11
- package/dist/postureKnob.js +1 -1
- package/dist/promptProfileWireCaps.d.ts +2 -1
- package/dist/protocolSegment.d.ts +11 -0
- package/dist/protocolSegment.js +31 -0
- package/dist/readFacePosture.js +1 -1
- package/dist/request/taskRequest.js +1 -15
- package/dist/resumeRefusalCopy.d.ts +1 -0
- package/dist/resumeRefusalCopy.js +26 -3
- package/dist/retryStatus.js +2 -1
- package/dist/rewindArchiveCapability.js +2 -2
- package/dist/ruleCompileVerdict.d.ts +2 -0
- package/dist/ruleCompileVerdict.js +13 -0
- package/dist/ruleRemovalConsequence.d.ts +2 -1
- package/dist/runCancelContext.d.ts +12 -0
- package/dist/runCancelContext.js +83 -1
- package/dist/runTerminal.d.ts +16 -0
- package/dist/runTerminal.js +32 -3
- package/dist/seam.d.ts +1 -0
- package/dist/seam.js +1 -1
- package/dist/seatContract.d.ts +2 -1
- package/dist/sessionMemoryStatus.d.ts +2 -4
- package/dist/sessionPolicyCapability.js +1 -1
- package/dist/sessionSyncFileHistoryCapability.d.ts +18 -0
- package/dist/sessionSyncFileHistoryCapability.js +50 -0
- package/dist/skillToolListsCapability.d.ts +18 -0
- package/dist/skillToolListsCapability.js +50 -0
- package/dist/sqlEngineCapability.js +2 -9
- package/dist/steerPriorityCapability.d.ts +18 -0
- package/dist/steerPriorityCapability.js +80 -0
- package/dist/steerReceipt.d.ts +9 -0
- package/dist/steerReceipt.js +25 -0
- package/dist/storePostureCapability.js +2 -2
- package/dist/subagent/engineSubagentSteer.js +2 -9
- package/dist/supportFloor.d.ts +1 -0
- package/dist/supportFloor.js +15 -5
- package/dist/taskRequestWords.d.ts +4 -2
- package/dist/taskRequestWords.js +1 -1
- package/dist/toolHistoryBadTurn.js +1 -2
- package/dist/toolResult.d.ts +10 -1
- package/dist/toolResult.js +80 -6
- package/dist/types/engineState.d.ts +2 -12
- package/dist/userInvokedSkillsCapability.d.ts +18 -0
- package/dist/userInvokedSkillsCapability.js +50 -0
- package/dist/webSearchBackendCapability.js +2 -2
- package/dist/webSearchWireCaps.d.ts +1 -1
- package/dist/webSearchWireCaps.js +40 -2
- package/dist/wireFailureShape.d.ts +2 -0
- package/dist/wireFailureShape.js +6 -2
- package/dist/wireRefusalCopy.d.ts +9 -3
- package/dist/wireRefusalCopy.js +41 -4
- package/dist/workflowsJournalCapability.d.ts +18 -0
- package/dist/workflowsJournalCapability.js +50 -0
- package/dist/writeProtectionCapability.d.ts +2 -4
- package/dist/writeProtectionCapability.js +1 -1
- package/docs/INTEGRATION-CLIENTS.md +1516 -18
- package/package.json +2 -2
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { type GateCurrentPending, type HitlFailureStage, type HitlSafetyCode, type HitlClientLike, type DecideOperationObserver } from './hitlBridge.js';
|
|
2
|
-
import { type
|
|
2
|
+
import { type AllowRuleShadowedWireMember, type ApprovalAllowRuleShadow } from './allowRuleShadow.js';
|
|
3
3
|
import { type ApprovalMandateWord } from '../gateVocabulary.js';
|
|
4
4
|
import type { ToolPermissionRequest } from '../seatContract.js';
|
|
5
5
|
import { type DenyAttributionRefusalDetail } from '../wireRefusalCopy.js';
|
|
6
|
+
import { type ApprovalDecidedByReading } from '../approvalDecidedByCapability.js';
|
|
6
7
|
import { type DecideReceiptView } from '../decideReceipt.js';
|
|
7
8
|
import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS } from '@sema-agent/sdk';
|
|
8
|
-
import type {
|
|
9
|
+
import type { ToolApprovalRespondAck, PersistedRuleAnchor as SdkPersistedRuleAnchor, RuleOfferMatch as SdkRuleOfferMatch, RuleOfferBatchMember as SdkRuleOfferBatchMember, RuleOfferUncoveredDetail as SdkRuleOfferUncoveredDetail, RuleOfferUncoveredReason as SdkRuleOfferUncoveredReason, AskOrigin as SdkAskOrigin, RuleOffersAbsence as SdkRuleOffersAbsence, DenialLimitKind as SdkDenialLimitKind, DenialLimitFallback as SdkDenialLimitFallback } from '@sema-agent/sdk';
|
|
9
10
|
export declare function isFsApprovalGate(gate: {
|
|
10
11
|
kind?: unknown;
|
|
11
12
|
toolName?: unknown;
|
|
@@ -23,6 +24,7 @@ export type FsApprovalOutcome = {
|
|
|
23
24
|
denySettledBy?: ApprovalDenySettledBy | undefined;
|
|
24
25
|
denyReason?: string | undefined;
|
|
25
26
|
denyAttributionDropped?: true;
|
|
27
|
+
denyAttributionRenamed?: true;
|
|
26
28
|
receipt?: DecideReceiptView | undefined;
|
|
27
29
|
} | {
|
|
28
30
|
kind: 'aborted';
|
|
@@ -48,6 +50,7 @@ export interface FsApprovalWireDeps {
|
|
|
48
50
|
client: HitlClientLike;
|
|
49
51
|
onPresented?: () => void;
|
|
50
52
|
onDecideOperation?: DecideOperationObserver;
|
|
53
|
+
approvalDecidedBy?: ApprovalDecidedByReading | undefined;
|
|
51
54
|
}
|
|
52
55
|
export declare function structurallyEqual(a: unknown, b: unknown): boolean;
|
|
53
56
|
export type RuleOfferMatch = SdkRuleOfferMatch;
|
|
@@ -131,8 +134,10 @@ export interface ApprovalCardRequest {
|
|
|
131
134
|
inputHasBidi?: true;
|
|
132
135
|
hasBidiControls?: true;
|
|
133
136
|
persistedRuleShadowed?: string;
|
|
137
|
+
allowRuleShadow?: ApprovalAllowRuleShadow;
|
|
134
138
|
probeCause?: unknown;
|
|
135
139
|
probeReason?: string;
|
|
140
|
+
rememberRefused?: true;
|
|
136
141
|
ruleEvidence?: unknown;
|
|
137
142
|
requiresRealApproval?: true;
|
|
138
143
|
irreversibleParkGate?: true;
|
|
@@ -148,7 +153,6 @@ export interface ApprovalCardRequest {
|
|
|
148
153
|
origin?: string;
|
|
149
154
|
askClass?: string;
|
|
150
155
|
classes?: readonly string[];
|
|
151
|
-
ruleStoreUnreadable?: RuleStoreUnreadableKind;
|
|
152
156
|
}
|
|
153
157
|
export type ApprovalCardPort = (req: ApprovalCardRequest) => Promise<ApprovalCardDecision>;
|
|
154
158
|
export declare function installApprovalCardPort(port: ApprovalCardPort | null): () => void;
|
|
@@ -161,6 +165,11 @@ export declare function approvalCardPortFor(sessionKey: string): ApprovalCardPor
|
|
|
161
165
|
export declare function _resetApprovalCardPortForTest(): void;
|
|
162
166
|
export declare function surfaceApprovalCard(req: ApprovalCardRequest): Promise<ApprovalCardDecision>;
|
|
163
167
|
export declare function surfaceFsApprovalAndDecide(deps: FsApprovalWireDeps, taskId: string, argsByCall: Map<string, unknown>, signal?: AbortSignal, parkGatedCallId?: string): Promise<FsApprovalOutcome>;
|
|
168
|
+
export interface BoundSkillGrantsWire {
|
|
169
|
+
readonly skill: string | null;
|
|
170
|
+
readonly allowedTools: readonly string[];
|
|
171
|
+
readonly disallowedTools: readonly string[];
|
|
172
|
+
}
|
|
164
173
|
export interface ToolApprovalFrame {
|
|
165
174
|
type: 'tool_approval' | 'tool_approval_complete';
|
|
166
175
|
approvalId: string;
|
|
@@ -175,14 +184,17 @@ export interface ToolApprovalFrame {
|
|
|
175
184
|
sourceAgentName?: string;
|
|
176
185
|
governanceForced?: true;
|
|
177
186
|
delegation?: ToolApprovalDelegation;
|
|
178
|
-
ruleSuggestions?: RuleSuggestion[];
|
|
179
187
|
ruleOffers?: readonly WireRuleOffer[];
|
|
180
188
|
ruleOffersAbsence?: string;
|
|
181
189
|
denialLimitFallback?: DenialLimitFallback;
|
|
182
|
-
ruleStoreUnreadable?: string;
|
|
183
190
|
persistedRuleShadowed?: string;
|
|
191
|
+
allowRuleShadowed?: readonly AllowRuleShadowedWireMember[];
|
|
192
|
+
boundGrantDigest?: string;
|
|
193
|
+
boundGrants?: BoundSkillGrantsWire;
|
|
194
|
+
classifierNoRuling?: string;
|
|
184
195
|
probeCause?: unknown;
|
|
185
196
|
probeReason?: string;
|
|
197
|
+
rememberRefused?: true;
|
|
186
198
|
ruleEvidence?: unknown;
|
|
187
199
|
requiresRealApproval?: true;
|
|
188
200
|
mandated?: true;
|
|
@@ -207,7 +219,7 @@ export interface ToolApprovalDelegation {
|
|
|
207
219
|
depth: number;
|
|
208
220
|
agentName?: string;
|
|
209
221
|
}
|
|
210
|
-
export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "
|
|
222
|
+
export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleOffers", "ruleOffersAbsence", "denialLimitFallback", "readRootCandidate", "mandated", "mandate", "origin", "askClass", "classes", "inputHasBidi", "parked", "persistedRuleShadowed", "allowRuleShadowed", "probeCause", "probeReason", "rememberRefused", "boundGrantDigest", "boundGrants", "classifierNoRuling", "ruleEvidence", "requiresRealApproval", "expiresInMs", "expiresAtMs", "serverNowMs", "delegation", "outcome"];
|
|
211
223
|
export interface ApprovalMandatedFacts {
|
|
212
224
|
readonly mandated?: true;
|
|
213
225
|
readonly ruleOffersAbsence?: string;
|
|
@@ -228,11 +240,17 @@ export interface RespondToolApprovalOpts {
|
|
|
228
240
|
persistRuleBatchOfferIndex?: number;
|
|
229
241
|
note?: string;
|
|
230
242
|
settledBy?: 'policy';
|
|
243
|
+
decidedBy?: 'policy';
|
|
231
244
|
}
|
|
232
245
|
export type RespondToolApprovalFn = (approvalId: string, decision: ToolApprovalRespondDecision, opts?: RespondToolApprovalOpts) => Promise<ToolApprovalRespondAck | void>;
|
|
233
246
|
export type ToolApprovalRespondAckView = ToolApprovalRespondAck;
|
|
234
247
|
export type PersistedRuleAnchor = SdkPersistedRuleAnchor;
|
|
235
248
|
export declare function readToolApprovalRespondAck(v: unknown): ToolApprovalRespondAckView | undefined;
|
|
249
|
+
export declare function decisionAttributionKeyOf(reading: ApprovalDecidedByReading | undefined, denySettledBy: ApprovalDenySettledBy | undefined): {
|
|
250
|
+
decidedBy: 'policy';
|
|
251
|
+
} | {
|
|
252
|
+
settledBy: 'policy';
|
|
253
|
+
} | Record<never, never>;
|
|
236
254
|
export interface ToolApprovalFrameOutcome {
|
|
237
255
|
decision: ToolApprovalRespondDecision | 'unresolved';
|
|
238
256
|
ack?: ToolApprovalRespondAckView;
|
|
@@ -243,6 +261,7 @@ export interface ToolApprovalFrameOutcome {
|
|
|
243
261
|
denyReason?: string;
|
|
244
262
|
denyAttributionRefusal?: DenyAttributionRefusalDetail;
|
|
245
263
|
denyAttributionDropped?: true;
|
|
264
|
+
denyAttributionRenamed?: true;
|
|
246
265
|
}
|
|
247
266
|
interface ToolApprovalRespondRefusalFields {
|
|
248
267
|
status?: number;
|
|
@@ -260,11 +279,12 @@ export declare function readToolApprovalRespondRefusal(err: unknown): ToolApprov
|
|
|
260
279
|
export declare function isToolApprovalFrame(ev: unknown): ev is ToolApprovalFrame;
|
|
261
280
|
export declare function readDenialLimitFallback(v: unknown): DenialLimitFallback | undefined;
|
|
262
281
|
export declare function readRuleOffers(v: unknown): RuleOffer[] | undefined;
|
|
263
|
-
export declare function readRuleOfferSupply(offers: unknown
|
|
282
|
+
export declare function readRuleOfferSupply(offers: unknown): RuleOffer[] | undefined;
|
|
264
283
|
export interface ToolApprovalFrameLaneOpts {
|
|
265
284
|
approvalDecisionNoteCapable?: boolean;
|
|
266
285
|
respondFreeFormRulesCapable?: boolean;
|
|
267
286
|
respondBatchRuleOffersCapable?: boolean;
|
|
287
|
+
approvalDecidedBy?: ApprovalDecidedByReading | undefined;
|
|
268
288
|
windowIsCurrent?: boolean;
|
|
269
289
|
argsUnavailable?: true;
|
|
270
290
|
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { APPROVAL_CARD_PORT_KEY_MISMATCH_REASON, DEFAULT_DENY_REASON, DecideTransportRetryExhaustedError, HitlBridge, NO_APPROVAL_CARD_PORT_REASON, HitlSafetyError, denyReasonForWire, findPendingForTask, readDecideCurrentPending, readWireErrorCode, } from './hitlBridge.js';
|
|
2
2
|
import { askParkRowArm } from './askParkRowRouting.js';
|
|
3
3
|
import { hostLog } from '../host.js';
|
|
4
|
-
import { readOwnNonEmptyString } from '../ownKey.js';
|
|
4
|
+
import { readOwnDataValue, readOwnNonEmptyString } from '../ownKey.js';
|
|
5
|
+
import { readAskClassPair } from './askClassPair.js';
|
|
6
|
+
import { legacyShadowedRuleTextOf, readAllowRuleShadowFromWire } from './allowRuleShadow.js';
|
|
5
7
|
import { createSessionSlot, DEFAULT_SESSION_KEY } from '../sessionSlot.js';
|
|
6
8
|
import { readEngineActiveBgTasks } from '../fleet/fleetLedger.js';
|
|
7
9
|
import { observeCancelByDeny, surfaceRememberNotApplied, surfaceEditNotForwarded, surfaceEditRefusedOnBlindAsk, surfaceRuleArmNotSent, surfaceRuleArmRejected } from './hitlHostSurface.js';
|
|
8
10
|
import { approvalCallKey, liveFrameCallKey } from './gateIdentity.js';
|
|
9
|
-
import { isRuleStoreUnreadableKind } from '../gateVocabulary.js';
|
|
10
11
|
import { isApprovalMandateWord } from '../gateVocabulary.js';
|
|
11
12
|
import { denyAttributionRefusalFromError } from '../wireRefusalCopy.js';
|
|
13
|
+
import { approvalDecidedByAdmitted } from '../approvalDecidedByCapability.js';
|
|
12
14
|
import { decideFailureNote } from '../decideFailureNote.js';
|
|
13
15
|
import { refusalSaysStillPending } from '../engineErrorCodes.js';
|
|
14
16
|
import { readDecideReceipt } from '../decideReceipt.js';
|
|
@@ -169,6 +171,7 @@ function isParkRowInputSizeMarker(v) {
|
|
|
169
171
|
return o.truncated === true && typeof o.bytes === 'number' && Number.isFinite(o.bytes) && o.bytes >= 0;
|
|
170
172
|
}
|
|
171
173
|
export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signal, parkGatedCallId) {
|
|
174
|
+
const decidedByReading = decidedByReadingSnapshotOf(deps);
|
|
172
175
|
const found = await findPendingForTask(deps.client, taskId, (toolName) => toolName !== undefined && (toolNameIsFsWrite(toolName) || toolNameIsShellExec(toolName)), signal ? { signal } : undefined, parkGatedCallId, (row) => askParkRowArm(row) === 'tool-gate');
|
|
173
176
|
if (!found.ok)
|
|
174
177
|
return { kind: 'failed', stage: 'fetch', reason: found.reason, ...(found.code !== undefined ? { code: found.code } : {}) };
|
|
@@ -189,12 +192,11 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
|
|
|
189
192
|
}
|
|
190
193
|
const bridge = new HitlBridge(deps.client, taskId, deps.onDecideOperation ? { onDecideOperation: deps.onDecideOperation } : undefined);
|
|
191
194
|
const callKey = approvalCallKey(gatedCallId, taskId);
|
|
192
|
-
const ruleOffersReadOnly =
|
|
195
|
+
const ruleOffersReadOnly = readRuleOffers(pending.ruleOffers);
|
|
193
196
|
const durableProbeCause = pending.riskDescriptor?.probeCause;
|
|
194
197
|
const durableProbeReason = readProbeReason(pending.riskDescriptor);
|
|
195
|
-
const
|
|
198
|
+
const durableShadow = readAllowRuleShadowFromWire(pending, 'row');
|
|
196
199
|
const durableRuleOffersAbsence = pending.ruleOffersAbsence;
|
|
197
|
-
const durableRuleStoreUnreadable = readRuleStoreUnreadable(pending.ruleStoreUnreadable);
|
|
198
200
|
deps.onPresented?.();
|
|
199
201
|
const card = await surfaceApprovalCard({
|
|
200
202
|
toolName,
|
|
@@ -218,12 +220,9 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
|
|
|
218
220
|
...(ruleOffersReadOnly !== undefined ? { ruleOffersReadOnly } : {}),
|
|
219
221
|
...(isWireRecordCarrier(durableProbeCause) ? { probeCause: durableProbeCause } : {}),
|
|
220
222
|
...(durableProbeReason !== undefined ? { probeReason: durableProbeReason } : {}),
|
|
221
|
-
...(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
...(typeof durableShadowedRule === 'string' && durableShadowedRule.trim() !== ''
|
|
225
|
-
? { persistedRuleShadowed: durableShadowedRule }
|
|
226
|
-
: {}),
|
|
223
|
+
...(readRememberRefused(pending) ? { rememberRefused: true } : {}),
|
|
224
|
+
...(durableShadow !== undefined ? { allowRuleShadow: durableShadow } : {}),
|
|
225
|
+
...((t) => (t !== undefined ? { persistedRuleShadowed: t } : {}))(legacyShadowedRuleTextOf(durableShadow)),
|
|
227
226
|
...(typeof durableRuleOffersAbsence === 'string' && durableRuleOffersAbsence !== ''
|
|
228
227
|
? { ruleOffersAbsence: durableRuleOffersAbsence }
|
|
229
228
|
: {}),
|
|
@@ -298,31 +297,56 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
|
|
|
298
297
|
}
|
|
299
298
|
case 'deny': {
|
|
300
299
|
const denySettledByForWire = readApprovalDenySettledBy(card);
|
|
300
|
+
const attributionKeys = decisionAttributionKeyOf(decidedByReading, denySettledByForWire);
|
|
301
301
|
const denyReasonSnapshot = typeof card.reason === 'string' ? card.reason : undefined;
|
|
302
302
|
let lastSendCarriedAttribution = false;
|
|
303
303
|
try {
|
|
304
304
|
const denyBody = {
|
|
305
305
|
decision: 'deny',
|
|
306
306
|
reason: denyReasonForWire(denyReasonSnapshot, `task ${taskId}`) ?? DEFAULT_DENY_REASON,
|
|
307
|
-
...
|
|
307
|
+
...attributionKeys,
|
|
308
308
|
};
|
|
309
309
|
let attributionDropped = false;
|
|
310
|
+
let attributionRenamed = false;
|
|
310
311
|
let raw;
|
|
311
|
-
lastSendCarriedAttribution =
|
|
312
|
+
lastSendCarriedAttribution = carriesAttributionKey(attributionKeys);
|
|
312
313
|
try {
|
|
313
314
|
raw = await bridge.decideTool(denyBody, gatedCallId, decideOpts, pending);
|
|
314
315
|
}
|
|
315
316
|
catch (first) {
|
|
316
|
-
if (
|
|
317
|
+
if (shouldResendWithoutAttribution(first, lastSendCarriedAttribution, signal)) {
|
|
318
|
+
const withoutAttribution = withoutAttributionKey(denyBody);
|
|
319
|
+
lastSendCarriedAttribution = false;
|
|
320
|
+
hostLog('debug', `liveToolApprovalWire: decide(deny) for task ${taskId} was refused because the settlement note is not part of ` +
|
|
321
|
+
'what this deployment signs — re-sending the SAME decision exactly once with that one key removed ' +
|
|
322
|
+
'(the refusal happened before the approval was judged, so nothing was consumed and this is a re-delivery, not a second act)');
|
|
323
|
+
raw = await bridge.decideTool(withoutAttribution, gatedCallId, decideOpts, pending);
|
|
324
|
+
attributionDropped = true;
|
|
325
|
+
}
|
|
326
|
+
else if (shouldResendUnderSuccessorKey(first, Object.hasOwn(denyBody, 'settledBy'), signal)) {
|
|
327
|
+
const renamed = withAttributionKeyRenamed(denyBody);
|
|
328
|
+
hostLog('debug', `liveToolApprovalWire: decide(deny) for task ${taskId} was refused because the settlement note was sent under a name ` +
|
|
329
|
+
'this engine has retired — re-sending the SAME decision exactly once with that one key renamed to the name the refusal points to ' +
|
|
330
|
+
'(the refusal happened before the approval was judged, so nothing was consumed and this is a re-delivery, not a second act)');
|
|
331
|
+
try {
|
|
332
|
+
raw = await bridge.decideTool(renamed, gatedCallId, decideOpts, pending);
|
|
333
|
+
attributionRenamed = true;
|
|
334
|
+
}
|
|
335
|
+
catch (second) {
|
|
336
|
+
if (!shouldResendWithoutAttribution(second, true, signal))
|
|
337
|
+
throw second;
|
|
338
|
+
const renamedWithoutAttribution = withoutAttributionKey(renamed);
|
|
339
|
+
lastSendCarriedAttribution = false;
|
|
340
|
+
hostLog('debug', `liveToolApprovalWire: decide(deny) for task ${taskId} was refused again because the settlement note is not part of ` +
|
|
341
|
+
'what this deployment signs — re-sending the SAME decision exactly once more with that key removed ' +
|
|
342
|
+
'(still before the approval was judged)');
|
|
343
|
+
raw = await bridge.decideTool(renamedWithoutAttribution, gatedCallId, decideOpts, pending);
|
|
344
|
+
attributionDropped = true;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
317
348
|
throw first;
|
|
318
|
-
|
|
319
|
-
void _droppedKey;
|
|
320
|
-
lastSendCarriedAttribution = false;
|
|
321
|
-
hostLog('debug', `liveToolApprovalWire: decide(deny) for task ${taskId} was refused because the settlement note is not part of ` +
|
|
322
|
-
'what this deployment signs — re-sending the SAME decision exactly once with that one key removed ' +
|
|
323
|
-
'(the refusal happened before the approval was judged, so nothing was consumed and this is a re-delivery, not a second act)');
|
|
324
|
-
raw = await bridge.decideTool(withoutAttribution, gatedCallId, decideOpts, pending);
|
|
325
|
-
attributionDropped = true;
|
|
349
|
+
}
|
|
326
350
|
}
|
|
327
351
|
const receipt = readDecideReceipt(raw);
|
|
328
352
|
const denySettledBy = denySettledByForWire;
|
|
@@ -334,6 +358,7 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
|
|
|
334
358
|
...(denySettledBy !== undefined ? { denySettledBy } : {}),
|
|
335
359
|
...(denyReason !== undefined ? { denyReason } : {}),
|
|
336
360
|
...(attributionDropped ? { denyAttributionDropped: true } : {}),
|
|
361
|
+
...(attributionRenamed ? { denyAttributionRenamed: true } : {}),
|
|
337
362
|
...(receipt !== undefined ? { receipt } : {}),
|
|
338
363
|
};
|
|
339
364
|
}
|
|
@@ -363,6 +388,8 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
|
|
|
363
388
|
decideSpan.close();
|
|
364
389
|
}
|
|
365
390
|
}
|
|
391
|
+
const _boundGrantsPin = [true, true, true];
|
|
392
|
+
void _boundGrantsPin;
|
|
366
393
|
function readReadRootCandidate(v) {
|
|
367
394
|
if (typeof v !== 'object' || v === null)
|
|
368
395
|
return undefined;
|
|
@@ -385,11 +412,9 @@ export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
|
|
|
385
412
|
'args',
|
|
386
413
|
'argsOmitted',
|
|
387
414
|
'governanceForced',
|
|
388
|
-
'ruleSuggestions',
|
|
389
415
|
'ruleOffers',
|
|
390
416
|
'ruleOffersAbsence',
|
|
391
417
|
'denialLimitFallback',
|
|
392
|
-
'ruleStoreUnreadable',
|
|
393
418
|
'readRootCandidate',
|
|
394
419
|
'mandated',
|
|
395
420
|
'mandate',
|
|
@@ -399,8 +424,13 @@ export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
|
|
|
399
424
|
'inputHasBidi',
|
|
400
425
|
'parked',
|
|
401
426
|
'persistedRuleShadowed',
|
|
427
|
+
'allowRuleShadowed',
|
|
402
428
|
'probeCause',
|
|
403
429
|
'probeReason',
|
|
430
|
+
'rememberRefused',
|
|
431
|
+
'boundGrantDigest',
|
|
432
|
+
'boundGrants',
|
|
433
|
+
'classifierNoRuling',
|
|
404
434
|
'ruleEvidence',
|
|
405
435
|
'requiresRealApproval',
|
|
406
436
|
'expiresInMs',
|
|
@@ -445,30 +475,6 @@ export function toolPermissionRequestAskBits(card) {
|
|
|
445
475
|
...(askClassPair ?? {}),
|
|
446
476
|
};
|
|
447
477
|
}
|
|
448
|
-
function readAskClassPair(v) {
|
|
449
|
-
if (typeof v !== 'object' || v === null)
|
|
450
|
-
return undefined;
|
|
451
|
-
const askClass = readOwnNonEmptyString(v, 'askClass');
|
|
452
|
-
if (askClass === undefined || !Object.hasOwn(v, 'classes'))
|
|
453
|
-
return undefined;
|
|
454
|
-
const raw = v.classes;
|
|
455
|
-
if (!Array.isArray(raw) || raw.length === 0)
|
|
456
|
-
return undefined;
|
|
457
|
-
const classes = [];
|
|
458
|
-
const seen = new Set();
|
|
459
|
-
for (let i = 0; i < raw.length; i++) {
|
|
460
|
-
if (!Object.hasOwn(raw, i))
|
|
461
|
-
return undefined;
|
|
462
|
-
const c = raw[i];
|
|
463
|
-
if (typeof c !== 'string' || c === '' || seen.has(c))
|
|
464
|
-
return undefined;
|
|
465
|
-
seen.add(c);
|
|
466
|
-
classes.push(c);
|
|
467
|
-
}
|
|
468
|
-
if (classes[0] !== askClass)
|
|
469
|
-
return undefined;
|
|
470
|
-
return { askClass, classes: Object.freeze(classes) };
|
|
471
|
-
}
|
|
472
478
|
function hasOwnStrictTrue(v, key) {
|
|
473
479
|
return Object.hasOwn(v, key) && v[key] === true;
|
|
474
480
|
}
|
|
@@ -575,13 +581,50 @@ function readPersistedRuleAnchors(v) {
|
|
|
575
581
|
function isNonNegativeSafeInt(v) {
|
|
576
582
|
return typeof v === 'number' && Number.isSafeInteger(v) && v >= 0;
|
|
577
583
|
}
|
|
578
|
-
function shouldResendWithoutAttribution(e,
|
|
579
|
-
if (!
|
|
584
|
+
function shouldResendWithoutAttribution(e, sentAttributionKey, signal) {
|
|
585
|
+
if (!sentAttributionKey)
|
|
580
586
|
return false;
|
|
581
587
|
if (signal?.aborted === true)
|
|
582
588
|
return false;
|
|
583
589
|
return denyAttributionRefusalFromError(e, true)?.kind === 'not_in_proof';
|
|
584
590
|
}
|
|
591
|
+
function shouldResendUnderSuccessorKey(e, lastSendCarriedRetiredKey, signal) {
|
|
592
|
+
if (!lastSendCarriedRetiredKey)
|
|
593
|
+
return false;
|
|
594
|
+
if (signal?.aborted === true)
|
|
595
|
+
return false;
|
|
596
|
+
return denyAttributionRefusalFromError(e, true)?.kind === 'retired_key';
|
|
597
|
+
}
|
|
598
|
+
export function decisionAttributionKeyOf(reading, denySettledBy) {
|
|
599
|
+
if (denySettledBy !== 'policy')
|
|
600
|
+
return {};
|
|
601
|
+
return approvalDecidedByAdmitted(reading) ? { decidedBy: 'policy' } : { settledBy: 'policy' };
|
|
602
|
+
}
|
|
603
|
+
function carriesAttributionKey(body) {
|
|
604
|
+
return Object.hasOwn(body, 'settledBy') || Object.hasOwn(body, 'decidedBy');
|
|
605
|
+
}
|
|
606
|
+
function withoutAttributionKey(body) {
|
|
607
|
+
const { settledBy: _droppedSettledBy, decidedBy: _droppedDecidedBy, ...rest } = body;
|
|
608
|
+
void _droppedSettledBy;
|
|
609
|
+
void _droppedDecidedBy;
|
|
610
|
+
return rest;
|
|
611
|
+
}
|
|
612
|
+
function withAttributionKeyRenamed(body) {
|
|
613
|
+
const { settledBy, decidedBy: _replaced, ...rest } = body;
|
|
614
|
+
void _replaced;
|
|
615
|
+
return settledBy === undefined ? rest : { ...rest, decidedBy: settledBy };
|
|
616
|
+
}
|
|
617
|
+
function readDecidedByReadingOf(holder) {
|
|
618
|
+
try {
|
|
619
|
+
return readOwnDataValue(holder, 'approvalDecidedBy');
|
|
620
|
+
}
|
|
621
|
+
catch {
|
|
622
|
+
return undefined;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
function decidedByReadingSnapshotOf(holder) {
|
|
626
|
+
return approvalDecidedByAdmitted(readDecidedByReadingOf(holder)) ? Object.freeze({ kind: 'present', value: true }) : undefined;
|
|
627
|
+
}
|
|
585
628
|
export function readToolApprovalRespondRefusal(err) {
|
|
586
629
|
const pick = (key) => {
|
|
587
630
|
try {
|
|
@@ -663,6 +706,14 @@ function readProbeReason(v) {
|
|
|
663
706
|
return undefined;
|
|
664
707
|
}
|
|
665
708
|
}
|
|
709
|
+
function readRememberRefused(v) {
|
|
710
|
+
try {
|
|
711
|
+
return typeof v === 'object' && v !== null && Object.hasOwn(v, 'rememberRefused') && v.rememberRefused === true;
|
|
712
|
+
}
|
|
713
|
+
catch {
|
|
714
|
+
return false;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
666
717
|
function isNonNegativeFinite(v) {
|
|
667
718
|
return typeof v === 'number' && Number.isFinite(v) && v >= 0;
|
|
668
719
|
}
|
|
@@ -688,9 +739,6 @@ export function readDenialLimitFallback(v) {
|
|
|
688
739
|
autoDenyAfterMs: d.autoDenyAfterMs,
|
|
689
740
|
};
|
|
690
741
|
}
|
|
691
|
-
function readRuleStoreUnreadable(v) {
|
|
692
|
-
return isRuleStoreUnreadableKind(v) ? v : undefined;
|
|
693
|
-
}
|
|
694
742
|
function isRuleOfferMatch(v) {
|
|
695
743
|
return typeof v === 'string' && RULE_OFFER_MATCHES.includes(v);
|
|
696
744
|
}
|
|
@@ -809,24 +857,8 @@ export function readRuleOffers(v) {
|
|
|
809
857
|
}
|
|
810
858
|
return out.length > 0 ? out : undefined;
|
|
811
859
|
}
|
|
812
|
-
function
|
|
813
|
-
|
|
814
|
-
return undefined;
|
|
815
|
-
if (v.length === 0 || v.length > MAX_RULE_OFFERS_TOLERATED)
|
|
816
|
-
return undefined;
|
|
817
|
-
const out = [];
|
|
818
|
-
for (let i = 0; i < v.length; i++) {
|
|
819
|
-
const triple = readRuleTriple(v[i]);
|
|
820
|
-
if (triple === undefined)
|
|
821
|
-
continue;
|
|
822
|
-
out.push({ kind: 'single', offerIndex: i, ...triple });
|
|
823
|
-
}
|
|
824
|
-
return out.length > 0 ? out : undefined;
|
|
825
|
-
}
|
|
826
|
-
export function readRuleOfferSupply(offers, legacy) {
|
|
827
|
-
if (offers !== undefined && offers !== null)
|
|
828
|
-
return readRuleOffers(offers);
|
|
829
|
-
return readLegacyRuleSuggestions(legacy);
|
|
860
|
+
export function readRuleOfferSupply(offers) {
|
|
861
|
+
return readRuleOffers(offers);
|
|
830
862
|
}
|
|
831
863
|
function subagentBadgeFor(frame) {
|
|
832
864
|
let name = typeof frame.sourceAgentName === 'string' && frame.sourceAgentName.length > 0 ? frame.sourceAgentName : '';
|
|
@@ -850,6 +882,7 @@ const MAX_RESPOND_NOTE_CHARS = 2048;
|
|
|
850
882
|
export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamArgs, signal, lane) {
|
|
851
883
|
const approvalId = frame.approvalId;
|
|
852
884
|
const frameToolCallId = typeof frame.toolCallId === 'string' && frame.toolCallId !== '' ? frame.toolCallId : undefined;
|
|
885
|
+
const decidedByReading = decidedByReadingSnapshotOf(lane);
|
|
853
886
|
const toolName = typeof frame.toolName === 'string' ? frame.toolName : 'Write';
|
|
854
887
|
let args = streamArgs !== undefined && streamArgs !== null
|
|
855
888
|
? streamArgs
|
|
@@ -874,8 +907,9 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
874
907
|
}
|
|
875
908
|
}
|
|
876
909
|
const argsNotRealInput = argsFallback || lane?.argsUnavailable === true;
|
|
877
|
-
const ruleOffers =
|
|
910
|
+
const ruleOffers = readRuleOffers(frame.ruleOffers);
|
|
878
911
|
const denialLimitFallback = readDenialLimitFallback(frame.denialLimitFallback);
|
|
912
|
+
const frameShadow = readAllowRuleShadowFromWire(frame, 'frame');
|
|
879
913
|
const card = await surfaceApprovalCard({
|
|
880
914
|
toolName,
|
|
881
915
|
args: args,
|
|
@@ -902,11 +936,11 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
902
936
|
? { delegation: frame.delegation }
|
|
903
937
|
: {}),
|
|
904
938
|
...(ruleOffers !== undefined ? { ruleOffers } : {}),
|
|
905
|
-
...(
|
|
906
|
-
|
|
907
|
-
: {}),
|
|
939
|
+
...((sh) => (sh !== undefined ? { allowRuleShadow: sh } : {}))(frameShadow),
|
|
940
|
+
...((t) => (t !== undefined ? { persistedRuleShadowed: t } : {}))(legacyShadowedRuleTextOf(frameShadow)),
|
|
908
941
|
...(isWireRecordCarrier(frame.probeCause) ? { probeCause: frame.probeCause } : {}),
|
|
909
942
|
...((r) => (r !== undefined ? { probeReason: r } : {}))(readProbeReason(frame)),
|
|
943
|
+
...(readRememberRefused(frame) ? { rememberRefused: true } : {}),
|
|
910
944
|
...(isWireRecordCarrier(frame.ruleEvidence) ? { ruleEvidence: frame.ruleEvidence } : {}),
|
|
911
945
|
...(frame.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
912
946
|
...(hasOwnStrictTrue(frame, 'mandated') ? { mandated: true } : {}),
|
|
@@ -917,7 +951,6 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
917
951
|
? { ruleOffersAbsence: frame.ruleOffersAbsence }
|
|
918
952
|
: {}),
|
|
919
953
|
...(denialLimitFallback !== undefined ? { denialLimitFallback } : {}),
|
|
920
|
-
...((k) => (k !== undefined ? { ruleStoreUnreadable: k } : {}))(readRuleStoreUnreadable(frame.ruleStoreUnreadable)),
|
|
921
954
|
...((o) => (o !== undefined ? { origin: o } : {}))(readOwnNonEmptyString(frame, 'origin')),
|
|
922
955
|
...(readAskClassPair(frame) ?? {}),
|
|
923
956
|
});
|
|
@@ -932,8 +965,9 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
932
965
|
}
|
|
933
966
|
const decision = card.kind === 'allow' ? (card.allowSession ? 'allow_session' : 'allow') : 'deny';
|
|
934
967
|
const denySettledByForWire = card.kind === 'deny' ? readApprovalDenySettledBy(card) : undefined;
|
|
935
|
-
const
|
|
936
|
-
|
|
968
|
+
const attributionKeys = decision === 'deny' ? decisionAttributionKeyOf(decidedByReading, denySettledByForWire) : {};
|
|
969
|
+
const sentAttributionKey = carriesAttributionKey(attributionKeys);
|
|
970
|
+
let lastSendCarriedAttribution = sentAttributionKey;
|
|
937
971
|
const denyReasonSnapshot = card.kind === 'deny' && typeof card.reason === 'string' ? card.reason : undefined;
|
|
938
972
|
if (card.kind === 'failed') {
|
|
939
973
|
hostLog('debug', `liveToolApprovalWire: approval card unavailable (${card.reason}) — fail-closed deny for ${approvalId}`);
|
|
@@ -960,14 +994,14 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
960
994
|
let persistRuleBatchOfferIndex;
|
|
961
995
|
let batchArmTarget;
|
|
962
996
|
let ruleArmDroppedForCaps = false;
|
|
963
|
-
let ruleArmDroppedForCheck
|
|
997
|
+
let ruleArmDroppedForCheck;
|
|
964
998
|
const wantsTextArm = card.kind === 'allow' && typeof card.persistRule === 'string' && card.persistRule !== '';
|
|
965
999
|
const wantsBatchArm = card.kind === 'allow' && card.persistRuleBatchOfferIndex !== undefined;
|
|
966
1000
|
if (wantsTextArm && wantsBatchArm) {
|
|
967
1001
|
hostLog('error', `liveToolApprovalWire: DROPPING the whole persistRule arm for ${approvalId} — the card returned BOTH a rule ` +
|
|
968
1002
|
'text and a batchOfferIndex; the server rejects that combination with a 400 that would take the decision down ' +
|
|
969
1003
|
'with it, and picking one arm here would be deciding on the user\'s behalf (the decision itself still goes through)');
|
|
970
|
-
ruleArmDroppedForCheck =
|
|
1004
|
+
ruleArmDroppedForCheck = 'both_arms';
|
|
971
1005
|
}
|
|
972
1006
|
else if (card.kind === 'allow' &&
|
|
973
1007
|
card.persistRuleBatchOfferIndex !== undefined &&
|
|
@@ -992,7 +1026,7 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
992
1026
|
hostLog('error', `liveToolApprovalWire: DROPPING persistRuleBatchOfferIndex(${String(idx)}) for ${approvalId} — that wire ` +
|
|
993
1027
|
'index is not a batch offer on this frame (out of range, a single offer, or not a non-negative integer); ' +
|
|
994
1028
|
'never redeeming an index the engine did not offer as a batch');
|
|
995
|
-
ruleArmDroppedForCheck =
|
|
1029
|
+
ruleArmDroppedForCheck = 'index_not_a_batch_offer';
|
|
996
1030
|
}
|
|
997
1031
|
}
|
|
998
1032
|
else if (wantsTextArm && card.kind === 'allow' && typeof card.persistRule === 'string' && decision !== 'deny') {
|
|
@@ -1014,7 +1048,7 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
1014
1048
|
}
|
|
1015
1049
|
else {
|
|
1016
1050
|
hostLog('error', `liveToolApprovalWire: DROPPING persistRule for ${approvalId} — the card returned a rule that is not among the frame's SINGLE offers (a batch member's text is not a selectable candidate either: a conjunction batch is redeemed by index, all-or-nothing) — never sending un-offered text to the rule store`);
|
|
1017
|
-
ruleArmDroppedForCheck =
|
|
1051
|
+
ruleArmDroppedForCheck = 'text_not_offered';
|
|
1018
1052
|
}
|
|
1019
1053
|
}
|
|
1020
1054
|
const respondOpts = {
|
|
@@ -1024,24 +1058,48 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
1024
1058
|
...(persistRuleEdited !== undefined ? { persistRuleEdited } : {}),
|
|
1025
1059
|
...(persistRuleBatchOfferIndex !== undefined ? { persistRuleBatchOfferIndex } : {}),
|
|
1026
1060
|
...(note !== undefined ? { note } : {}),
|
|
1027
|
-
...
|
|
1061
|
+
...attributionKeys,
|
|
1028
1062
|
};
|
|
1029
1063
|
let attributionDropped = false;
|
|
1064
|
+
let attributionRenamed = false;
|
|
1030
1065
|
let raw;
|
|
1031
1066
|
try {
|
|
1032
1067
|
raw = await respond(approvalId, decision, respondOpts);
|
|
1033
1068
|
}
|
|
1034
1069
|
catch (first) {
|
|
1035
|
-
if (
|
|
1070
|
+
if (shouldResendWithoutAttribution(first, lastSendCarriedAttribution, signal)) {
|
|
1071
|
+
const withoutAttribution = withoutAttributionKey(respondOpts);
|
|
1072
|
+
lastSendCarriedAttribution = false;
|
|
1073
|
+
hostLog('debug', `liveToolApprovalWire: respond(deny) for ${approvalId} was refused because the settlement note is not part of ` +
|
|
1074
|
+
'what this deployment signs — re-sending the SAME decision exactly once with that one key removed ' +
|
|
1075
|
+
'(the refusal happened before the approval was judged, so nothing was consumed and this is a re-delivery, not a second act)');
|
|
1076
|
+
raw = await respond(approvalId, decision, withoutAttribution);
|
|
1077
|
+
attributionDropped = true;
|
|
1078
|
+
}
|
|
1079
|
+
else if (shouldResendUnderSuccessorKey(first, Object.hasOwn(respondOpts, 'settledBy'), signal)) {
|
|
1080
|
+
const renamed = withAttributionKeyRenamed(respondOpts);
|
|
1081
|
+
hostLog('debug', `liveToolApprovalWire: respond(deny) for ${approvalId} was refused because the settlement note was sent under a name ` +
|
|
1082
|
+
'this engine has retired — re-sending the SAME decision exactly once with that one key renamed to the name the refusal points to ' +
|
|
1083
|
+
'(the refusal happened before the approval was judged, so nothing was consumed and this is a re-delivery, not a second act)');
|
|
1084
|
+
try {
|
|
1085
|
+
raw = await respond(approvalId, decision, renamed);
|
|
1086
|
+
attributionRenamed = true;
|
|
1087
|
+
}
|
|
1088
|
+
catch (second) {
|
|
1089
|
+
if (!shouldResendWithoutAttribution(second, true, signal))
|
|
1090
|
+
throw second;
|
|
1091
|
+
const renamedWithoutAttribution = withoutAttributionKey(renamed);
|
|
1092
|
+
lastSendCarriedAttribution = false;
|
|
1093
|
+
hostLog('debug', `liveToolApprovalWire: respond(deny) for ${approvalId} was refused again because the settlement note is not part of ` +
|
|
1094
|
+
'what this deployment signs — re-sending the SAME decision exactly once more with that key removed ' +
|
|
1095
|
+
'(still before the approval was judged)');
|
|
1096
|
+
raw = await respond(approvalId, decision, renamedWithoutAttribution);
|
|
1097
|
+
attributionDropped = true;
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
else {
|
|
1036
1101
|
throw first;
|
|
1037
|
-
|
|
1038
|
-
void _droppedKey;
|
|
1039
|
-
lastSendCarriedAttribution = false;
|
|
1040
|
-
hostLog('debug', `liveToolApprovalWire: respond(deny) for ${approvalId} was refused because the settlement note is not part of ` +
|
|
1041
|
-
'what this deployment signs — re-sending the SAME decision exactly once with that one key removed ' +
|
|
1042
|
-
'(the refusal happened before the approval was judged, so nothing was consumed and this is a re-delivery, not a second act)');
|
|
1043
|
-
raw = await respond(approvalId, decision, withoutAttribution);
|
|
1044
|
-
attributionDropped = true;
|
|
1102
|
+
}
|
|
1045
1103
|
}
|
|
1046
1104
|
const parsed = readToolApprovalRespondAck(raw);
|
|
1047
1105
|
let ack = parsed;
|
|
@@ -1097,8 +1155,8 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
1097
1155
|
}
|
|
1098
1156
|
if (ruleArmDroppedForCaps)
|
|
1099
1157
|
surfaceRuleArmNotSent();
|
|
1100
|
-
if (ruleArmDroppedForCheck)
|
|
1101
|
-
surfaceRuleArmRejected();
|
|
1158
|
+
if (ruleArmDroppedForCheck !== undefined)
|
|
1159
|
+
surfaceRuleArmRejected(ruleArmDroppedForCheck);
|
|
1102
1160
|
if (decision === 'allow_session' && ack?.rememberApplied === false) {
|
|
1103
1161
|
logAfterDecided(`liveToolApprovalWire: ${approvalId} allow_session ack rememberApplied=false — grant not stored, surfacing honest notice`);
|
|
1104
1162
|
surfaceRememberNotApplied();
|
|
@@ -1114,6 +1172,7 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
1114
1172
|
const denyAttribution = decision === 'deny'
|
|
1115
1173
|
? {
|
|
1116
1174
|
...(attributionDropped ? { denyAttributionDropped: true } : {}),
|
|
1175
|
+
...(attributionRenamed ? { denyAttributionRenamed: true } : {}),
|
|
1117
1176
|
...(denySettledByForWire !== undefined ? { denySettledBy: denySettledByForWire } : {}),
|
|
1118
1177
|
...(denyReasonSnapshot !== undefined && denyReasonSnapshot.trim() !== ''
|
|
1119
1178
|
? { denyReason: denyReasonSnapshot }
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HOOK_TOOL_ALIASES } from './hookToolAliases.js';
|
|
2
|
-
|
|
2
|
+
import { SETTINGS_TOOL_NAME_MATCHER_EVENTS } from './generated/settingsSchemaTables.js';
|
|
3
|
+
const TOOL_NAME_MATCHER_EVENTS = new Set(SETTINGS_TOOL_NAME_MATCHER_EVENTS);
|
|
3
4
|
const MATCHER_MAX_CHARS = 8192;
|
|
4
5
|
const PATTERN_WORK_BUDGET = 10_000_000;
|
|
5
6
|
const PATTERN_MAX_DEPTH = 32;
|
package/dist/hooksWireCaps.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type HooksWirePlan, type HooksWirePlanOptions } from './pluginHooksWire.js';
|
|
2
2
|
import { type HookFailureNotice } from './notifications.js';
|
|
3
3
|
import type { WireHooksConfig } from './finalVerifyWire.js';
|
|
4
|
-
export { GOAL_STOP_HOOK_WIRE_ENV,
|
|
4
|
+
export { GOAL_STOP_HOOK_WIRE_ENV, isGoalStopHookWireArmed, setWireSessionStopHook, getWireSessionStopHook, } from './goalStopHook.js';
|
|
5
5
|
export type { WireHooksConfig };
|
|
6
6
|
export interface HooksForWireOptions {
|
|
7
7
|
readonly plan?: HooksWirePlan;
|
package/dist/hooksWireCaps.js
CHANGED
|
@@ -5,7 +5,7 @@ import { hostLog, hostSettings } from './host.js';
|
|
|
5
5
|
import { createSettingsHookJudge, decidePluginHooks, dedupeSettingsHookGroups, filterSettingsHookGroups, occupancyOf, settingsHookDropText, } from './pluginHooksWire.js';
|
|
6
6
|
import { MAX_HOOK_NOTICE_TEXT_CHARS } from './notifications.js';
|
|
7
7
|
import { goalStopHookMatcher, __resetGoalStopHookForTests } from './goalStopHook.js';
|
|
8
|
-
export { GOAL_STOP_HOOK_WIRE_ENV,
|
|
8
|
+
export { GOAL_STOP_HOOK_WIRE_ENV, isGoalStopHookWireArmed, setWireSessionStopHook, getWireSessionStopHook, } from './goalStopHook.js';
|
|
9
9
|
const EDITABLE_HOOK_SOURCES = ['userSettings', 'projectSettings', 'localSettings'];
|
|
10
10
|
const ALL_HOOK_SOURCES = ['policySettings', ...EDITABLE_HOOK_SOURCES, 'flagSettings'];
|
|
11
11
|
const _hookSourceListsPin = [true, true];
|