@sema-agent/client-core 0.107.0 → 0.108.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 +118 -0
- package/README.md +19 -14
- package/dist/adapter/activeRunSelfHeal.d.ts +2 -0
- package/dist/adapter/activeRunSelfHeal.js +20 -3
- package/dist/checkpointRowVerdict.d.ts +5 -0
- package/dist/checkpointRowVerdict.js +26 -0
- package/dist/cloudConfigWireCaps.d.ts +10 -0
- package/dist/cloudConfigWireCaps.js +33 -0
- package/dist/coreValuePorts.d.ts +17 -1
- package/dist/coreValuePorts.js +5 -0
- package/dist/decideReceipt.js +2 -1
- package/dist/engineErrorCodes.d.ts +5 -0
- package/dist/engineErrorCodes.js +5 -0
- package/dist/engineNoticeCodes.d.ts +19 -1
- package/dist/engineNoticeCodes.js +65 -3
- package/dist/engineTargetSeat.js +1 -0
- package/dist/errorSupplementRoles.js +2 -0
- package/dist/eventLeg.js +1 -1
- package/dist/executionLaneWords.js +2 -1
- package/dist/gateOutcome.d.ts +10 -1
- package/dist/gateOutcome.js +48 -1
- package/dist/generated/engineFactTables.d.ts +1 -0
- package/dist/generated/engineFactTables.js +5 -0
- package/dist/generated/engineNoticeTables.js +3 -0
- package/dist/generated/settingsSchemaFns.d.ts +4 -2
- package/dist/generated/settingsSchemaFns.js +9 -3
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
- package/dist/generated/settingsSchemaMcpRequestEntry.js +9 -18
- package/dist/generated/settingsSchemaReservedMemberName.d.ts +1 -0
- package/dist/generated/settingsSchemaReservedMemberName.js +7 -0
- package/dist/generated/settingsSchemaTables.d.ts +2 -0
- package/dist/generated/settingsSchemaTables.js +10 -0
- package/dist/generated/settingsSchemaWireName.d.ts +1 -0
- package/dist/generated/settingsSchemaWireName.js +8 -0
- package/dist/headlessReconnectWire.js +12 -7
- package/dist/hitl/approvalAskers.d.ts +13 -0
- package/dist/hitl/approvalAskers.js +79 -0
- package/dist/hitl/approvalResolution.d.ts +3 -0
- package/dist/hitl/approvalResolution.js +22 -4
- package/dist/hitl/approvalsFeed.js +3 -12
- package/dist/hitl/askParkRowRouting.js +5 -1
- package/dist/hitl/decisionRefusal.d.ts +1 -0
- package/dist/hitl/decisionRefusal.js +5 -2
- package/dist/hitl/decisionSend.js +2 -6
- package/dist/hitl/frameRouter.d.ts +3 -2
- package/dist/hitl/frameRouter.js +28 -6
- package/dist/hitl/gateLedger.d.ts +2 -0
- package/dist/hitl/gateLedger.js +3 -1
- package/dist/hitl/hitlBridge.js +2 -3
- package/dist/hitl/parkResolver.js +32 -23
- package/dist/hitl/parkRowBirthWait.d.ts +2 -0
- package/dist/hitl/parkRowBirthWait.js +8 -1
- package/dist/hitl/persistedRulesWire.d.ts +5 -1
- package/dist/hitl/persistedRulesWire.js +20 -4
- package/dist/hitl/planReviewWire.js +12 -16
- package/dist/hitl/policyDenyCause.d.ts +3 -0
- package/dist/hitl/policyDenyCause.js +16 -0
- package/dist/hitl/sessionPolicyDeliverable.js +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +8 -2
- package/dist/hitl/toolApprovalWire.js +22 -3
- package/dist/hooksReaderGenerations.d.ts +1 -0
- package/dist/hooksReaderGenerations.js +12 -0
- package/dist/hooksWireCaps.js +8 -4
- package/dist/i18n/messages.en.d.ts +38 -1
- package/dist/i18n/messages.en.js +40 -3
- package/dist/i18n/messages.zh.js +45 -3
- package/dist/index.d.ts +6 -1
- package/dist/index.js +4 -1
- package/dist/liveModelCatalog.d.ts +4 -2
- package/dist/liveModelCatalog.js +164 -26
- package/dist/model/catalogDefault.d.ts +25 -0
- package/dist/model/catalogDefault.js +44 -0
- package/dist/permissionWireCaps.d.ts +1 -0
- package/dist/permissionWireCaps.js +11 -0
- package/dist/pluginHooksWire.d.ts +5 -3
- package/dist/pluginHooksWire.js +116 -7
- package/dist/queuedDelivery.d.ts +1 -0
- package/dist/queuedDelivery.js +12 -0
- package/dist/resultFrameKeys.js +4 -2
- package/dist/resumeRefusalCopy.js +15 -8
- package/dist/runPermissionModeSwitch.d.ts +2 -1
- package/dist/runPermissionModeSwitch.js +16 -6
- package/dist/seatContract.d.ts +63 -10
- package/dist/seatContract.js +164 -11
- package/dist/sessionEngine.d.ts +2 -1
- package/dist/sessionEngine.js +5 -0
- package/dist/settingsHooksSalvage.d.ts +5 -0
- package/dist/settingsHooksSalvage.js +54 -0
- package/dist/subagentContentStore.js +1 -1
- package/dist/supportFloor.js +2 -0
- package/dist/taskNotificationAdmission.d.ts +19 -0
- package/dist/taskNotificationAdmission.js +84 -0
- package/dist/toolResult.js +2 -1
- package/dist/webSearchWireCaps.js +9 -4
- package/dist/wireRefusalCopy.d.ts +2 -1
- package/dist/wireRefusalCopy.js +2 -2
- package/docs/INTEGRATION-CLIENTS.md +816 -14
- package/package.json +4 -4
package/dist/hitl/hitlBridge.js
CHANGED
|
@@ -11,8 +11,7 @@ import { suspendedReopenOf } from './suspendedReopen.js';
|
|
|
11
11
|
import { closeDecisionOp, decisionLedgerKeysOf, openDecisionOp } from './decisionLedger.js';
|
|
12
12
|
import { askParkBlockGeneration, noteAskParkDecideSettled } from './askParkAutoReopenBlock.js';
|
|
13
13
|
import { checkpointQueueRowSortOf, QUEUE_ROW_FAMILY_UNREADABLE_GATE } from './approvalQueueRow.js';
|
|
14
|
-
import { checkpointRowBarOf, checkpointRowBarSentence } from '../checkpointRowVerdict.js';
|
|
15
|
-
import { msg, renderMessage } from '../i18n/translate.js';
|
|
14
|
+
import { checkpointDeadlineStateOf, checkpointRowBarOf, checkpointRowBarSentence, unboundWayOutContent } from '../checkpointRowVerdict.js';
|
|
16
15
|
export const DEFAULT_DENY_REASON = 'The user rejected this tool use';
|
|
17
16
|
export const MAX_DENY_REASON_CHARS = 4096;
|
|
18
17
|
export function denyReasonForWire(reason, tag) {
|
|
@@ -365,7 +364,7 @@ export class HitlBridge {
|
|
|
365
364
|
if (typeof boundCallId !== 'string' || boundCallId.length === 0 || typeof boundInputHash !== 'string' || boundInputHash.length === 0) {
|
|
366
365
|
throw new HitlSafetyError(`pending checkpoint ${p.id ?? '<no-id>'} is missing D-1 binding fields ` +
|
|
367
366
|
`(boundCallId=${String(boundCallId)}, boundInputHash=${String(boundInputHash)}) — ` +
|
|
368
|
-
`the row itself carries no binding to echo, so ${
|
|
367
|
+
`the row itself carries no binding to echo, so ${unboundWayOutContent(checkpointDeadlineStateOf(p))}`, 'binding_missing');
|
|
369
368
|
}
|
|
370
369
|
return { boundCallId, boundInputHash };
|
|
371
370
|
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { putOwnKey, readOwnDataValue } from '../ownKey.js';
|
|
2
2
|
import { HitlBridge, NO_QUESTION_OVERLAY_REASON, findPendingForTask, isNoDecisionSurfaceReason, } from './hitlBridge.js';
|
|
3
|
-
import { approvalResolutionDetail, directSafetyStopOf, resolutionOfDecisionFailure } from './approvalResolution.js';
|
|
3
|
+
import { approvalResolutionDetail, approvalResolutionStatusTag, directSafetyStopOf, resolutionOfDecisionFailure } from './approvalResolution.js';
|
|
4
4
|
import { readDecisionRefusalAsk } from './decisionRefusal.js';
|
|
5
5
|
import { publishQuestionFrame, registerLocalQuestionResponder, hasQuestionOverlay, } from '../liveQuestionStore.js';
|
|
6
6
|
import { hostLog } from '../host.js';
|
|
7
7
|
import { surfaceFsApprovalAndDecide } from './toolApprovalWire.js';
|
|
8
8
|
import { INTERRUPT_DENY_REASON, observeCancelByDeny } from './hitlHostSurface.js';
|
|
9
|
-
import { flushHeldWithInterruptRewrite, isAskTool } from './frameRouter.js';
|
|
9
|
+
import { denyAttributionOf, flushHeldWithInterruptRewrite, isAskTool } from './frameRouter.js';
|
|
10
|
+
import { invokeHostCallbackIsolated } from '../hostCallbackGuard.js';
|
|
10
11
|
import { inheritFrameBinding } from '../frameBinding.js';
|
|
11
12
|
import { approvalCallKey, askGateQuestionId } from './gateIdentity.js';
|
|
12
13
|
import { readDecideReceipt } from '../decideReceipt.js';
|
|
13
14
|
import { decideFailureNote } from '../decideFailureNote.js';
|
|
14
15
|
import { wireFailureTextsOf } from '../wireFailureShape.js';
|
|
15
16
|
import { msg, renderMessage } from '../i18n/translate.js';
|
|
17
|
+
import { refusedParkFromError } from '../resumeRefusalCopy.js';
|
|
16
18
|
export const MAX_GATE_HOPS = 2;
|
|
17
19
|
export function nextHopBudget(prev, round) {
|
|
18
20
|
const total = (prev?.total ?? 0) + 1;
|
|
@@ -160,6 +162,10 @@ function failureReasonOf(r) {
|
|
|
160
162
|
return '';
|
|
161
163
|
return r.detail ?? approvalResolutionDetail(r) ?? r.cause;
|
|
162
164
|
}
|
|
165
|
+
function failsoftReasonOf(r) {
|
|
166
|
+
const tag = approvalResolutionStatusTag(r);
|
|
167
|
+
return tag === '' ? failureReasonOf(r) : `${failureReasonOf(r)} ${tag}`;
|
|
168
|
+
}
|
|
163
169
|
function orchestrationEnd(park, gatedCallId, detail) {
|
|
164
170
|
return { kind: 'unsettled', lane: park.gate === 'fs' ? 'decide' : 'ask', cause: 'orchestration', ...(gatedCallId !== undefined ? { gatedCallId } : {}), detail };
|
|
165
171
|
}
|
|
@@ -180,10 +186,7 @@ async function surfaceParkGate(park, ctx, gatedCallId, onPresented) {
|
|
|
180
186
|
...(decidedByReading !== undefined ? { approvalDecidedBy: decidedByReading } : {}),
|
|
181
187
|
}, taskId, argsByCallOf(led), ctx.signal, gatedCallId, park.toolName);
|
|
182
188
|
if (outcome.kind === 'decided' && outcome.decision === 'deny' && outcome.gatedCallId) {
|
|
183
|
-
led.markDenied(outcome.gatedCallId,
|
|
184
|
-
...(outcome.deny?.settledBy !== undefined ? { settledBy: outcome.deny.settledBy } : {}),
|
|
185
|
-
...(outcome.deny?.reason !== undefined ? { reason: outcome.deny.reason } : {}),
|
|
186
|
-
});
|
|
189
|
+
led.markDenied(outcome.gatedCallId, denyAttributionOf(outcome.deny));
|
|
187
190
|
}
|
|
188
191
|
return outcome;
|
|
189
192
|
}
|
|
@@ -283,10 +286,9 @@ export async function resolvePark(park, ctx) {
|
|
|
283
286
|
? undefined
|
|
284
287
|
: outcome.kind === 'not_sent' && outcome.cause === 'retracted'
|
|
285
288
|
? 'the approval card was retracted by the host without a decision (nothing was sent; the run stays parked and remains decidable elsewhere)'
|
|
286
|
-
:
|
|
289
|
+
: failsoftReasonOf(outcome);
|
|
287
290
|
const noDecisionSurface = outcome.kind === 'not_sent' && outcome.cause === 'card_unavailable' && outcome.detail !== undefined && isNoDecisionSurfaceReason(outcome.detail);
|
|
288
|
-
|
|
289
|
-
return { kind: 'failsoft', events: failsoftEvents(park, ctx, interrupted, failedReason, undefined, noDecisionSurface, undecidableHere) };
|
|
291
|
+
return { kind: 'failsoft', events: failsoftEvents(park, ctx, interrupted, failedReason, undefined, noDecisionSurface, failsoftWayOutOf(outcome)) };
|
|
290
292
|
}
|
|
291
293
|
led.dropHeldForDecidedPark(outcome.gatedCallId, park.gatedCallId);
|
|
292
294
|
if (outcome.gatedCallId) {
|
|
@@ -309,17 +311,27 @@ export async function resolvePark(park, ctx) {
|
|
|
309
311
|
...(handoffTaskId !== undefined ? { handoffTaskId } : {}),
|
|
310
312
|
};
|
|
311
313
|
}
|
|
312
|
-
function
|
|
314
|
+
function failsoftWayOutOf(outcome) {
|
|
315
|
+
if (outcome.kind === 'not_sent' && (outcome.cause === 'row_unresumable' || (outcome.cause === 'safety_stop' && outcome.safetyCode === 'binding_missing')))
|
|
316
|
+
return 'reason';
|
|
317
|
+
if (outcome.kind === 'unsettled' && outcome.cause === 'engine_refused' && refusedParkFromError(outcome.refusal) !== null)
|
|
318
|
+
return 'cancel';
|
|
319
|
+
return 'card';
|
|
320
|
+
}
|
|
321
|
+
function failsoftReasonSentence(park, failedReason, terminal, wayOut = 'card') {
|
|
313
322
|
if (terminal !== undefined)
|
|
314
323
|
return terminal.errorMessage;
|
|
315
324
|
if (failedReason === undefined)
|
|
316
325
|
return undefined;
|
|
317
|
-
|
|
318
|
-
|
|
326
|
+
const gate = park.gate === 'fs' ? 'Tool approval' : 'AskUserQuestion';
|
|
327
|
+
if (wayOut === 'reason')
|
|
328
|
+
return renderMessage(msg('approval.park.stillParked', { gate, reason: failedReason }));
|
|
329
|
+
if (wayOut === 'cancel')
|
|
330
|
+
return renderMessage(msg('approval.park.refusedNotResumable', { gate, reason: failedReason }));
|
|
319
331
|
return (`${park.gate === 'fs' ? 'Tool approval' : 'AskUserQuestion'} gate could not be answered: ${failedReason}` +
|
|
320
332
|
' — the run is still parked on this approval: decide it on the card when it is shown again, or cancel the run.');
|
|
321
333
|
}
|
|
322
|
-
function failsoftEvents(park, ctx, gateAbortedByUser, failedReason, terminal, noDecisionSurface = false,
|
|
334
|
+
function failsoftEvents(park, ctx, gateAbortedByUser, failedReason, terminal, noDecisionSurface = false, wayOut = 'card') {
|
|
323
335
|
const events = [
|
|
324
336
|
...flushHeldWithInterruptRewrite(ctx.led, {
|
|
325
337
|
terminal: park.pendingDone,
|
|
@@ -327,7 +339,7 @@ function failsoftEvents(park, ctx, gateAbortedByUser, failedReason, terminal, no
|
|
|
327
339
|
gateAbortedByUser,
|
|
328
340
|
}),
|
|
329
341
|
];
|
|
330
|
-
const reason = failsoftReasonSentence(park, failedReason, terminal,
|
|
342
|
+
const reason = failsoftReasonSentence(park, failedReason, terminal, wayOut);
|
|
331
343
|
if (park.pendingDone) {
|
|
332
344
|
events.push(reason === undefined || noDecisionSurface ? park.pendingDone : inheritFrameBinding(park.pendingDone, { ...park.pendingDone, _sema_park_failed_reason: reason }));
|
|
333
345
|
}
|
|
@@ -356,15 +368,12 @@ export function stalledTerminal(park, ctx, stalledRounds, lastStallReason, decid
|
|
|
356
368
|
return { kind: 'failsoft', events: failsoftEvents(park, ctx, false, reason) };
|
|
357
369
|
}
|
|
358
370
|
function notifyParkReattach(ctx, attempt, max, reason) {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
cb({ attempt, max, reason });
|
|
364
|
-
}
|
|
365
|
-
catch (e) {
|
|
366
|
-
hostLog('debug', `liveHitlAskWire: onParkReattach threw (${String(e)}) — ignored`);
|
|
367
|
-
}
|
|
371
|
+
invokeHostCallbackIsolated('liveHitlAskWire: onParkReattach', () => {
|
|
372
|
+
const cb = ctx.deps.onParkReattach;
|
|
373
|
+
if (typeof cb !== 'function' || ctx.signal?.aborted === true)
|
|
374
|
+
return;
|
|
375
|
+
return cb.call(ctx.deps, { attempt, max, reason });
|
|
376
|
+
});
|
|
368
377
|
}
|
|
369
378
|
function transportReasonToken(reason) {
|
|
370
379
|
const m = /(ECONNREFUSED|ECONNRESET|ETIMEDOUT|EPIPE|EAI_AGAIN|TimeoutError|AbortError|fetch failed|network)/i.exec(reason);
|
|
@@ -11,6 +11,7 @@ export type ParkRowProbe<Row> = {
|
|
|
11
11
|
rowVerdict?: Exclude<CheckpointRowVerdictReading, {
|
|
12
12
|
readonly kind: 'ok';
|
|
13
13
|
}>;
|
|
14
|
+
rowTaskId?: string;
|
|
14
15
|
};
|
|
15
16
|
export type ParkRowWaitVerdict<Row> = {
|
|
16
17
|
kind: 'row';
|
|
@@ -30,6 +31,7 @@ export type ParkRowWaitVerdict<Row> = {
|
|
|
30
31
|
rowVerdict?: Exclude<CheckpointRowVerdictReading, {
|
|
31
32
|
readonly kind: 'ok';
|
|
32
33
|
}>;
|
|
34
|
+
rowTaskId?: string;
|
|
33
35
|
} | {
|
|
34
36
|
kind: 'aborted';
|
|
35
37
|
waitedMs: number;
|
|
@@ -103,7 +103,14 @@ export async function waitForParkRowBirth(deps) {
|
|
|
103
103
|
if (probed.kind === 'row')
|
|
104
104
|
return { kind: 'row', row: probed.row, waitedMs: now() - startedAt, probes };
|
|
105
105
|
if (probed.kind === 'settled') {
|
|
106
|
-
return {
|
|
106
|
+
return {
|
|
107
|
+
kind: 'settled',
|
|
108
|
+
reason: probed.reason,
|
|
109
|
+
waitedMs: now() - startedAt,
|
|
110
|
+
probes,
|
|
111
|
+
...(probed.rowVerdict !== undefined ? { rowVerdict: probed.rowVerdict } : {}),
|
|
112
|
+
...(probed.rowTaskId !== undefined ? { rowTaskId: probed.rowTaskId } : {}),
|
|
113
|
+
};
|
|
107
114
|
}
|
|
108
115
|
lastReason = probed.reason;
|
|
109
116
|
const remainingMs = budgetMs - (now() - startedAt);
|
|
@@ -31,12 +31,16 @@ export interface CcImportRedeemRuleKey {
|
|
|
31
31
|
readonly rule: string;
|
|
32
32
|
readonly scope: string;
|
|
33
33
|
}
|
|
34
|
+
export interface CcImportRedeemRefused {
|
|
35
|
+
readonly key?: CcImportRedeemRuleKey;
|
|
36
|
+
}
|
|
34
37
|
export interface CcImportRedeemCounts {
|
|
35
38
|
persisted: number;
|
|
36
39
|
deduped: number;
|
|
37
40
|
indeterminate: readonly CcImportRedeemIndeterminate[];
|
|
41
|
+
refused?: readonly CcImportRedeemRefused[];
|
|
38
42
|
}
|
|
39
|
-
export type CcImportReceiptOutcome = 'persisted' | 'no-op' | 'indeterminate';
|
|
43
|
+
export type CcImportReceiptOutcome = 'persisted' | 'no-op' | 'refused' | 'indeterminate';
|
|
40
44
|
export declare function readCcImportRedeemCounts(body: unknown): CcImportRedeemCounts | null;
|
|
41
45
|
export type RulesFailure = {
|
|
42
46
|
kind: 'lane-unavailable';
|
|
@@ -43,21 +43,29 @@ function ownNonEmpty(o, key) {
|
|
|
43
43
|
const r = slotReadOf(o, key);
|
|
44
44
|
return r.presence === 'present' && typeof r.value === 'string' && r.value !== '' ? r.value : undefined;
|
|
45
45
|
}
|
|
46
|
-
function
|
|
46
|
+
function ruleKeyOfRow(row) {
|
|
47
47
|
const k = slotReadOf(row, 'key');
|
|
48
48
|
const keyObj = k.presence === 'present' && typeof k.value === 'object' && k.value !== null ? k.value : undefined;
|
|
49
49
|
const behavior = keyObj === undefined ? undefined : ownNonEmpty(keyObj, 'behavior');
|
|
50
50
|
const rule = keyObj === undefined ? undefined : ownNonEmpty(keyObj, 'rule');
|
|
51
51
|
const scope = keyObj === undefined ? undefined : ownNonEmpty(keyObj, 'scope');
|
|
52
|
+
return behavior !== undefined && rule !== undefined && scope !== undefined ? Object.freeze({ behavior, rule, scope }) : undefined;
|
|
53
|
+
}
|
|
54
|
+
function indeterminateRowOf(row) {
|
|
55
|
+
const key = ruleKeyOfRow(row);
|
|
52
56
|
const reason = ownNonEmpty(row, 'reason');
|
|
53
57
|
const d = slotReadOf(row, 'detail');
|
|
54
58
|
const shown = d.presence === 'present' && typeof d.value === 'string' ? displayUntrusted(d.value, { max: INDETERMINATE_DETAIL_SHOWN_MAX }) : undefined;
|
|
55
59
|
return Object.freeze({
|
|
56
|
-
...(
|
|
60
|
+
...(key !== undefined ? { key } : {}),
|
|
57
61
|
...(reason !== undefined ? { reason } : {}),
|
|
58
62
|
...(shown !== undefined && shown.trim() !== '' ? { detail: shown } : {}),
|
|
59
63
|
});
|
|
60
64
|
}
|
|
65
|
+
function refusedRowOf(row) {
|
|
66
|
+
const key = ruleKeyOfRow(row);
|
|
67
|
+
return Object.freeze(key !== undefined ? { key } : {});
|
|
68
|
+
}
|
|
61
69
|
const RECEIPT_ROW_ARMS = {
|
|
62
70
|
persisted: (acc) => {
|
|
63
71
|
acc.persisted += 1;
|
|
@@ -65,12 +73,15 @@ const RECEIPT_ROW_ARMS = {
|
|
|
65
73
|
'no-op': (acc) => {
|
|
66
74
|
acc.deduped += 1;
|
|
67
75
|
},
|
|
76
|
+
refused: (acc, row) => {
|
|
77
|
+
appendOwnElement(acc.refused, refusedRowOf(row));
|
|
78
|
+
},
|
|
68
79
|
indeterminate: (acc, row) => {
|
|
69
80
|
appendOwnElement(acc.indeterminate, indeterminateRowOf(row));
|
|
70
81
|
},
|
|
71
82
|
};
|
|
72
83
|
function receiptCountsOf(rows) {
|
|
73
|
-
const acc = { persisted: 0, deduped: 0, indeterminate: [] };
|
|
84
|
+
const acc = { persisted: 0, deduped: 0, indeterminate: [], refused: [] };
|
|
74
85
|
for (const row of rows) {
|
|
75
86
|
if (typeof row !== 'object' || row === null)
|
|
76
87
|
return null;
|
|
@@ -80,7 +91,12 @@ function receiptCountsOf(rows) {
|
|
|
80
91
|
return null;
|
|
81
92
|
RECEIPT_ROW_ARMS[word](acc, row);
|
|
82
93
|
}
|
|
83
|
-
return {
|
|
94
|
+
return {
|
|
95
|
+
persisted: acc.persisted,
|
|
96
|
+
deduped: acc.deduped,
|
|
97
|
+
indeterminate: acc.indeterminate.length === 0 ? NO_INDETERMINATE : Object.freeze(acc.indeterminate),
|
|
98
|
+
...(acc.refused.length === 0 ? {} : { refused: Object.freeze(acc.refused) }),
|
|
99
|
+
};
|
|
84
100
|
}
|
|
85
101
|
function legacyEnvelopeCountsOf(result) {
|
|
86
102
|
if (typeof result !== 'object' || result === null)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { publishQuestionFrame, publishQuestionFrameFor, registerLocalQuestionResponder, unregisterLocalQuestionResponder, hasLocalQuestionResponder, hasQuestionOverlayFor, } from '../liveQuestionStore.js';
|
|
2
2
|
import { hostLog } from '../host.js';
|
|
3
|
+
import { invokeHostCallbackIsolated } from '../hostCallbackGuard.js';
|
|
3
4
|
import { abortableSleep, settleWithinDeadline } from '../abortableSleep.js';
|
|
4
5
|
import { clientHasVerbs, engineWireFor, noAnswerKindOf, sendOnce } from '../engineWireFor.js';
|
|
5
6
|
import { engineWireTarget } from '../engineWireTarget.js';
|
|
@@ -1028,22 +1029,17 @@ async function decidePlanReviewInner(taskId, decision, permissionModeAfter, disp
|
|
|
1028
1029
|
hostLog('debug', `planReviewWire: outcome enqueue threw: ${String(e)}`);
|
|
1029
1030
|
}
|
|
1030
1031
|
if (onOutcome !== undefined) {
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
});
|
|
1043
|
-
}
|
|
1044
|
-
catch (e) {
|
|
1045
|
-
hostLog('debug', `planReviewWire: onOutcome callback threw for task ${taskId} (ignored): ${String(e)}`);
|
|
1046
|
-
}
|
|
1032
|
+
invokeHostCallbackIsolated(`planReviewWire: onOutcome callback (task ${taskId})`, () => onOutcome({
|
|
1033
|
+
taskId,
|
|
1034
|
+
dispatchNo,
|
|
1035
|
+
decision: semanticDecision,
|
|
1036
|
+
effect,
|
|
1037
|
+
...(effect === 'still_parked' && stillParkedCause !== undefined ? { cause: stillParkedCause } : {}),
|
|
1038
|
+
detail: outcome,
|
|
1039
|
+
tail,
|
|
1040
|
+
prompt,
|
|
1041
|
+
...(statusSeen !== undefined ? { status: statusSeen } : {}),
|
|
1042
|
+
}));
|
|
1047
1043
|
}
|
|
1048
1044
|
}
|
|
1049
1045
|
function reopenIdSuffix() {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const POLICY_DENY_CAUSES: readonly ["no_approval_ui", "dont_ask", "deny_rule", "engine_floor"];
|
|
2
|
+
export type PolicyDenyCause = (typeof POLICY_DENY_CAUSES)[number];
|
|
3
|
+
export declare function readPolicyDenyCause(decision: object | null | undefined): PolicyDenyCause | undefined;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const POLICY_DENY_CAUSES = Object.freeze(['no_approval_ui', 'dont_ask', 'deny_rule', 'engine_floor']);
|
|
2
|
+
export function readPolicyDenyCause(decision) {
|
|
3
|
+
if (decision === null || typeof decision !== 'object')
|
|
4
|
+
return undefined;
|
|
5
|
+
let d;
|
|
6
|
+
try {
|
|
7
|
+
d = Object.getOwnPropertyDescriptor(decision, 'policyCause');
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
if (d === undefined || !Object.hasOwn(d, 'value'))
|
|
13
|
+
return undefined;
|
|
14
|
+
const v = d.value;
|
|
15
|
+
return typeof v === 'string' && POLICY_DENY_CAUSES.includes(v) ? v : undefined;
|
|
16
|
+
}
|
|
@@ -12,7 +12,7 @@ const WITHHELD_NOTICE = {
|
|
|
12
12
|
qualified_deny: 'Not written to this session’s rule record: that record holds whole tool names and command names only, and this rule has a part in parentheses it cannot carry — recording just the name could block more than this rule does.',
|
|
13
13
|
peer_wide: 'Not written to this session’s rule record: this rule names a server or agent peer without naming one of its tools, and an engine that matches that record by exact tool name would block none of that peer’s tools.',
|
|
14
14
|
wildcard: 'Not written to this session’s rule record: this rule uses a wildcard (*), and an engine that matches that record by exact tool name would block none of the tools it covers.',
|
|
15
|
-
not_a_tool_name: 'Not written to this session’s rule record: this entry is not exactly one tool name — it is empty, not text, has spaces around the name, is not a single tool name in rule syntax (for example it contains a backslash or a parenthesis, or is longer than a rule can be), or spells its server or agent peer part in a
|
|
15
|
+
not_a_tool_name: 'Not written to this session’s rule record: this entry is not exactly one tool name — it is empty, not text, has spaces around the name, is not a single tool name in rule syntax (for example it contains a backslash or a parenthesis, or is longer than a rule can be), or spells its server or agent peer part in a form this record does not accept (for example with a dot or a space) · This record does not take entries of that form; record the exact name of a single tool instead.',
|
|
16
16
|
legacy_tool_name: `Not written to this session’s rule record: unless a tool by exactly this name is available, the engine refuses it — it is a retired tool name, or it contains "__" but does not start with ${PREFIXES_IN_PROSE} — and with it in that record every later run of this session would fail at startup until that entry is removed from the record. ${REFUSED_NAME_FIX}`,
|
|
17
17
|
not_in_roster: 'Not written to this session’s rule record: the tool roster supplied for this check has no tool this rule would block — no tool by exactly this name, as a name or an alias, with letter case counted, and, where the engine also reads the name as naming every tool of a server (a server whose own name contains "__"), no tool of that server either — it may be misspelled, or name a tool this deployment does not provide — so recorded as it is it would block nothing here.',
|
|
18
18
|
namespace_covering_unconfirmed: msg('session.policy.withheld.namespaceCoveringUnconfirmed'),
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type HitlClientLike, type DecideOperationObserver } from './hitlBridge.js';
|
|
2
|
+
import { type ApprovalAskReason } from './approvalAskers.js';
|
|
3
|
+
export type { ApprovalAskReason, ApprovalAskReasonByHook, ApprovalAskReasonByPolicy } from './approvalAskers.js';
|
|
2
4
|
import { readApprovalCardWord, type ApprovalCardWord } from './approvalCardReading.js';
|
|
3
5
|
import { type ApprovalAllowRuleShadow } from './allowRuleShadow.js';
|
|
4
6
|
import { CORE_PERSISTED_RULE_MATCHES } from '../generated/engineFactTables.js';
|
|
@@ -9,6 +11,7 @@ import { type ApprovalResolution } from './approvalResolution.js';
|
|
|
9
11
|
import { type ApprovalMandateWord } from '../gateVocabulary.js';
|
|
10
12
|
import type { ToolPermissionRequest } from '../seatContract.js';
|
|
11
13
|
import { type ApprovalDecidedByReading } from '../approvalDecidedByCapability.js';
|
|
14
|
+
import { type PolicyDenyCause } from './policyDenyCause.js';
|
|
12
15
|
import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS } from '@sema-agent/sdk';
|
|
13
16
|
import type { ApprovalDecidedBy, ApprovalCardDelegation, ToolApprovalDecision as SdkToolApprovalDecision, ToolApprovalRespondAck, ToolApprovalRespondReplayed, PersistedRuleAnchor, RuleOfferMatch, RuleOfferBatchMember, RuleOfferUncoveredDetail, RuleOfferUncoveredReason, AskOrigin, RuleOffersAbsence, DenialLimitKind, DenialLimitFallback, ToolApprovalFrame, ApprovalRequestFrame, RuleOffer as SdkRuleOffer } from '@sema-agent/sdk';
|
|
14
17
|
export declare function toolNameIsFsWrite(name: string): boolean;
|
|
@@ -71,6 +74,7 @@ export interface ApprovalCardDenyDecision {
|
|
|
71
74
|
kind: 'deny';
|
|
72
75
|
reason?: string;
|
|
73
76
|
settledBy?: ApprovalDenySettledBy;
|
|
77
|
+
policyCause?: PolicyDenyCause;
|
|
74
78
|
}
|
|
75
79
|
export declare const APPROVAL_DENY_SETTLED_BY_WORDS: readonly ["human", "policy"];
|
|
76
80
|
export type ApprovalDenySettledBy = (typeof APPROVAL_DENY_SETTLED_BY_WORDS)[number];
|
|
@@ -125,6 +129,8 @@ export interface ApprovalCardRequest {
|
|
|
125
129
|
approvalCard?: ApprovalCardWord;
|
|
126
130
|
askClass?: string;
|
|
127
131
|
classes?: readonly string[];
|
|
132
|
+
agentId?: string;
|
|
133
|
+
askReasons?: readonly ApprovalAskReason[];
|
|
128
134
|
boundGrants?: BoundSkillGrantsWire;
|
|
129
135
|
grantBinding?: ApprovalGrantBinding;
|
|
130
136
|
unreadableEvidence?: readonly string[];
|
|
@@ -163,7 +169,7 @@ export declare function approvalCardPortFor(sessionKey: string): ApprovalCardPor
|
|
|
163
169
|
export declare function __resetSettledApprovalsForTests(): void;
|
|
164
170
|
export declare function _resetApprovalCardPortForTest(): void;
|
|
165
171
|
export declare function surfaceApprovalCard(req: ApprovalCardRequest): Promise<ApprovalCardDecision>;
|
|
166
|
-
declare const REMEMBER_REFUSAL_CODES: readonly ["remember_not_in_proof", "capability.store_required", "decide.workflow_remember_unsupported", "decide.parked_remember_unsupported"];
|
|
172
|
+
declare const REMEMBER_REFUSAL_CODES: readonly ["remember_not_in_proof", "capability.store_required", "decide.workflow_remember_unsupported", "decide.parked_remember_unsupported", "remember_requires_binding"];
|
|
167
173
|
export type RememberRefusalCode = (typeof REMEMBER_REFUSAL_CODES)[number];
|
|
168
174
|
export declare function rememberRefusalOf(error: unknown): RememberRefusalCode | undefined;
|
|
169
175
|
export declare function surfaceFsApprovalAndDecide(deps: FsApprovalWireDeps, taskId: string, argsByCall: Map<string, unknown>, signal?: AbortSignal, parkGatedCallId?: string, parkToolName?: string): Promise<ApprovalResolution>;
|
|
@@ -276,7 +282,7 @@ export declare function approvalSupersedesDetail(card: Pick<ApprovalCardRequest,
|
|
|
276
282
|
export declare function readDenialLimitFallback(v: unknown): DenialLimitFallback | undefined;
|
|
277
283
|
export declare function readRuleOffers(v: unknown): RuleOfferReading[] | undefined;
|
|
278
284
|
export declare function readRuleOfferSupply(offers: unknown): RuleOfferReading[] | undefined;
|
|
279
|
-
export type ApprovalCardV1Facts = Pick<ApprovalCardRequest, 'toolName' | 'args'> & Pick<ApprovalCardRequest, 'toolCallId' | 'workerBadge' | 'wireNote' | 'argsUnavailable' | 'governanceForced' | 'delegation' | 'ruleOffersReadOnly' | 'inputHasBidi' | 'allowRuleShadow' | 'probeCause' | 'rememberRefused' | 'ruleEvidence' | 'requiresRealApproval' | 'ruleOffersAbsence' | 'denialLimitFallback' | 'askClass' | 'classes' | 'grantBinding' | 'unreadableEvidence' | 'message' | 'approvalCard'>;
|
|
285
|
+
export type ApprovalCardV1Facts = Pick<ApprovalCardRequest, 'toolName' | 'args'> & Pick<ApprovalCardRequest, 'toolCallId' | 'workerBadge' | 'wireNote' | 'argsUnavailable' | 'governanceForced' | 'delegation' | 'ruleOffersReadOnly' | 'inputHasBidi' | 'allowRuleShadow' | 'probeCause' | 'rememberRefused' | 'ruleEvidence' | 'requiresRealApproval' | 'ruleOffersAbsence' | 'denialLimitFallback' | 'askClass' | 'classes' | 'agentId' | 'askReasons' | 'grantBinding' | 'unreadableEvidence' | 'message' | 'approvalCard'>;
|
|
280
286
|
export type ApprovalCardFacts = ApprovalCardV1Facts & Pick<ApprovalCardRequest, 'argsRewritten' | 'ruleOffers' | 'probeReason' | 'mandated' | 'mandate' | 'readRootCandidate' | 'origin' | 'boundGrants' | 'classifierNoRuling' | 'allowSessionCarried' | 'cardPayloadUnreadable'>;
|
|
281
287
|
export interface ApprovalCardFrameFactsOptions {
|
|
282
288
|
readonly streamArgs?: object;
|
|
@@ -7,6 +7,7 @@ import { trimEditedRuleText } from './editedRuleTextPrecheck.js';
|
|
|
7
7
|
import { appendOwnElement, guardedRead, readAskOrigin, readOwnDataNonEmptyString, readOwnDataValue, readOwnNonEmptyString } from '../ownKey.js';
|
|
8
8
|
import { ownReadingSlot } from '../engineWireFor.js';
|
|
9
9
|
import { DEPLOYMENT_LIST_ASK_CLASSES, readAskClassPair } from './askClassPair.js';
|
|
10
|
+
import { approvalAgentIdOf, approvalAskReasonsOf } from './approvalAskers.js';
|
|
10
11
|
import { invokeHostCallbackIsolated } from '../hostCallbackGuard.js';
|
|
11
12
|
import { approvalWindowKeysOf, readApprovalCardWord, readRequiresRealApproval } from './approvalCardReading.js';
|
|
12
13
|
import { readAllowRuleShadowFromWire, retiredAllowRuleShadowKeyPresent, RETIRED_SHADOW_EVIDENCE_LABEL } from './allowRuleShadow.js';
|
|
@@ -28,6 +29,7 @@ import { parkRowDeadlineState } from './parkExpiryJudgements.js';
|
|
|
28
29
|
import { isApprovalMandateWord } from '../gateVocabulary.js';
|
|
29
30
|
import { approvalDecidedByAdmitted } from '../approvalDecidedByCapability.js';
|
|
30
31
|
import { decideFailureNote } from '../decideFailureNote.js';
|
|
32
|
+
import { readPolicyDenyCause } from './policyDenyCause.js';
|
|
31
33
|
import { slotPresenceOf, wireFailureTextsOf } from '../wireFailureShape.js';
|
|
32
34
|
import { APPROVAL_LIVE_FACE_KEYS, approvalLiveFaceOf, hasOwnStrictTrue } from './approvalLiveFace.js';
|
|
33
35
|
import { subagentSourceSessionOf } from './subagentSource.js';
|
|
@@ -157,11 +159,13 @@ function cardPortMissReason() {
|
|
|
157
159
|
return APPROVAL_CARD_PORT_KEY_MISMATCH_REASON;
|
|
158
160
|
return NO_APPROVAL_CARD_PORT_REASON;
|
|
159
161
|
}
|
|
162
|
+
const LEGACY_REMEMBER_REFUSAL_CODE = 'remember_requires_binding';
|
|
160
163
|
const REMEMBER_REFUSAL_CODES = Object.freeze([
|
|
161
164
|
'remember_not_in_proof',
|
|
162
165
|
'capability.store_required',
|
|
163
166
|
DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED,
|
|
164
167
|
'decide.parked_remember_unsupported',
|
|
168
|
+
LEGACY_REMEMBER_REFUSAL_CODE,
|
|
165
169
|
]);
|
|
166
170
|
export function rememberRefusalOf(error) {
|
|
167
171
|
return rememberRefusalIn(readWireErrorCodeReading(error));
|
|
@@ -517,6 +521,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
517
521
|
...approvalLiveFaceOf(pending).facts,
|
|
518
522
|
...((w) => (w !== undefined ? { approvalCard: w } : {}))(readApprovalCardWord(pending)),
|
|
519
523
|
...(readAskClassPair(pending) ?? {}),
|
|
524
|
+
...((r) => (r !== undefined ? { askReasons: r } : {}))(approvalAskReasonsOf(pending)),
|
|
520
525
|
...(pending.gateKind === 'irreversible_ask' ? { irreversibleParkGate: true } : {}),
|
|
521
526
|
...(pending.hasBidiControls === true ? { hasBidiControls: true } : {}),
|
|
522
527
|
...(ruleOffersReadOnly !== undefined ? { ruleOffersReadOnly } : {}),
|
|
@@ -609,6 +614,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
609
614
|
}
|
|
610
615
|
case 'deny': {
|
|
611
616
|
const denySettledByForWire = readApprovalDenySettledBy(card);
|
|
617
|
+
const denyPolicyCauseForWire = readPolicyDenyCause(card);
|
|
612
618
|
const attributionKeys = decisionAttributionKeyOf(decidedByReading, denySettledByForWire);
|
|
613
619
|
const denyReasonSnapshot = ((r) => (typeof r === 'string' ? r : undefined))(card.reason);
|
|
614
620
|
let lastSendCarriedAttribution = false;
|
|
@@ -642,7 +648,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
642
648
|
const attributionDropped = ladder.dropped;
|
|
643
649
|
const attributionRenamed = ladder.renamed;
|
|
644
650
|
const receipt = readDecideReceipt(raw);
|
|
645
|
-
const deny = denyFactsOf(denySettledByForWire, denyReasonSnapshot, attributionDropped, attributionRenamed);
|
|
651
|
+
const deny = denyFactsOf(denySettledByForWire, denyReasonSnapshot, attributionDropped, attributionRenamed, denyPolicyCauseForWire);
|
|
646
652
|
return {
|
|
647
653
|
kind: 'decided',
|
|
648
654
|
...at,
|
|
@@ -1014,14 +1020,16 @@ function readDecidedByReadingOf(holder) {
|
|
|
1014
1020
|
function decidedByReadingSnapshotOf(holder) {
|
|
1015
1021
|
return approvalDecidedByAdmitted(readDecidedByReadingOf(holder)) ? Object.freeze({ kind: 'present', value: true }) : undefined;
|
|
1016
1022
|
}
|
|
1017
|
-
function denyFactsOf(settledBy, reasonSnapshot, dropped, renamed) {
|
|
1023
|
+
function denyFactsOf(settledBy, reasonSnapshot, dropped, renamed, policyCauseSnapshot) {
|
|
1018
1024
|
const reason = reasonSnapshot !== undefined && reasonSnapshot.trim() !== '' ? reasonSnapshot : undefined;
|
|
1019
1025
|
const attributionKey = dropped ? 'dropped' : renamed ? 'renamed' : undefined;
|
|
1026
|
+
const policyCause = settledBy === 'policy' ? policyCauseSnapshot : undefined;
|
|
1020
1027
|
if (settledBy === undefined && reason === undefined && attributionKey === undefined)
|
|
1021
1028
|
return undefined;
|
|
1022
1029
|
return {
|
|
1023
1030
|
...(settledBy !== undefined ? { settledBy } : {}),
|
|
1024
1031
|
...(reason !== undefined ? { reason } : {}),
|
|
1032
|
+
...(policyCause !== undefined ? { policyCause } : {}),
|
|
1025
1033
|
...(attributionKey !== undefined ? { attributionKey } : {}),
|
|
1026
1034
|
};
|
|
1027
1035
|
}
|
|
@@ -1822,6 +1830,16 @@ function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
|
|
|
1822
1830
|
if (w !== undefined)
|
|
1823
1831
|
out.approvalCard = w;
|
|
1824
1832
|
});
|
|
1833
|
+
v1Bit(() => {
|
|
1834
|
+
const id = approvalAgentIdOf(carrier);
|
|
1835
|
+
if (id !== undefined)
|
|
1836
|
+
out.agentId = id;
|
|
1837
|
+
});
|
|
1838
|
+
v1Bit(() => {
|
|
1839
|
+
const reasons = approvalAskReasonsOf(carrier);
|
|
1840
|
+
if (reasons !== undefined)
|
|
1841
|
+
out.askReasons = reasons;
|
|
1842
|
+
});
|
|
1825
1843
|
}
|
|
1826
1844
|
v1Bit(() => {
|
|
1827
1845
|
const pair = readAskClassPair(carrier);
|
|
@@ -2059,6 +2077,7 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
|
|
|
2059
2077
|
hostLog('debug', `liveToolApprovalWire: ${approvalId} card carried a note on Yes (len=${card.note.length}) — this engine has no field that brings it to the model, so it was not sent`);
|
|
2060
2078
|
}
|
|
2061
2079
|
const denySettledByForWire = card.kind === 'deny' ? readApprovalDenySettledBy(card) : undefined;
|
|
2080
|
+
const denyPolicyCauseForWire = card.kind === 'deny' ? readPolicyDenyCause(card) : undefined;
|
|
2062
2081
|
const attributionKeys = decision === 'deny' ? decisionAttributionKeyOf(decidedByReading, denySettledByForWire) : {};
|
|
2063
2082
|
const sentAttributionKey = carriesAttributionKey(attributionKeys);
|
|
2064
2083
|
let lastSendCarriedAttribution = sentAttributionKey;
|
|
@@ -2300,7 +2319,7 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
|
|
|
2300
2319
|
'this answer was not delivered, reporting the earlier decision');
|
|
2301
2320
|
return { kind: 'decided', lane: 'respond', decision: replayed.decision, ack: replayed };
|
|
2302
2321
|
}
|
|
2303
|
-
const deny = decision === 'deny' ? denyFactsOf(denySettledByForWire, denyReasonSnapshot, attributionDropped, attributionRenamed) : undefined;
|
|
2322
|
+
const deny = decision === 'deny' ? denyFactsOf(denySettledByForWire, denyReasonSnapshot, attributionDropped, attributionRenamed, denyPolicyCauseForWire) : undefined;
|
|
2304
2323
|
return { kind: 'decided', lane: 'respond', decision, ...(ack !== undefined ? { ack } : {}), ...(deny !== undefined ? { deny } : {}) };
|
|
2305
2324
|
}
|
|
2306
2325
|
catch (e) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function hooksReaderNotReadKeys(serverVersion: string | undefined): readonly string[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { engineVersionTier } from './supportFloor.js';
|
|
2
|
+
const HOOKS_READER_GENERATIONS = Object.freeze([
|
|
3
|
+
Object.freeze({ from: '7.139.0', below: '7.147.0', notRead: Object.freeze(['onFailure']) }),
|
|
4
|
+
]);
|
|
5
|
+
const HOOKS_READER_FAIL_CLOSED = Object.freeze([...new Set(HOOKS_READER_GENERATIONS.flatMap((g) => g.notRead))]);
|
|
6
|
+
export function hooksReaderNotReadKeys(serverVersion) {
|
|
7
|
+
for (const g of HOOKS_READER_GENERATIONS) {
|
|
8
|
+
if (engineVersionTier(serverVersion, g.from) === 'engine' && engineVersionTier(serverVersion, g.below) === 'legacy')
|
|
9
|
+
return g.notRead;
|
|
10
|
+
}
|
|
11
|
+
return HOOKS_READER_FAIL_CLOSED;
|
|
12
|
+
}
|
package/dist/hooksWireCaps.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { engineCapNestedTrue, engineCapState, engineCapValue } from './engineCapsCache.js';
|
|
1
|
+
import { engineCapNestedTrue, engineCapState, engineCapString, engineCapValue } from './engineCapsCache.js';
|
|
2
|
+
import { hooksReaderNotReadKeys } from './hooksReaderGenerations.js';
|
|
2
3
|
import { msg, renderMessage } from './i18n/translate.js';
|
|
3
4
|
import { capForDisplay, collapseLabel } from './fleetTaskDesc.js';
|
|
4
5
|
import { hostLog } from './host.js';
|
|
@@ -185,7 +186,8 @@ export function hooksWirePlan(opts) {
|
|
|
185
186
|
const types = typesByEvent.get(event);
|
|
186
187
|
return types === undefined || (typeof type === 'string' && types.has(type));
|
|
187
188
|
};
|
|
188
|
-
|
|
189
|
+
const readerNotRead = hooksReaderNotReadKeys(engineCapString(o.baseUrl, 'version'));
|
|
190
|
+
return buildHooksWirePlan(read, engine, shellRuns, promptAuthoredByUserOf(o), suppressedLocallyOf(o), readerNotRead, compactionOnShellOf(o));
|
|
189
191
|
}
|
|
190
192
|
function taskHooksCapability(baseUrl) {
|
|
191
193
|
const v = engineCapValue(baseUrl, 'taskSettings');
|
|
@@ -298,7 +300,7 @@ function withheldRowsOf(candidates, trust, layers) {
|
|
|
298
300
|
}
|
|
299
301
|
return rows;
|
|
300
302
|
}
|
|
301
|
-
function buildHooksWirePlan(read, engine, shellRuns, promptAuthoredByUser, suppressedLocally, compactionOnShell = false) {
|
|
303
|
+
function buildHooksWirePlan(read, engine, shellRuns, promptAuthoredByUser, suppressedLocally, readerNotRead, compactionOnShell = false) {
|
|
302
304
|
const settingsDropped = [];
|
|
303
305
|
const settingsVerdicts = [];
|
|
304
306
|
const settingsExcluded = [];
|
|
@@ -344,6 +346,7 @@ function buildHooksWirePlan(read, engine, shellRuns, promptAuthoredByUser, suppr
|
|
|
344
346
|
shellRuns,
|
|
345
347
|
promptAuthoredByUser,
|
|
346
348
|
occupied: new Map(),
|
|
349
|
+
readerNotRead,
|
|
347
350
|
}));
|
|
348
351
|
if (d === undefined)
|
|
349
352
|
return planOf('failed', undefined);
|
|
@@ -465,7 +468,7 @@ function buildHooksWirePlan(read, engine, shellRuns, promptAuthoredByUser, suppr
|
|
|
465
468
|
continue;
|
|
466
469
|
if (!Array.isArray(groups) || groups.length === 0)
|
|
467
470
|
continue;
|
|
468
|
-
const kept = filterSettingsHookGroups(source, event, groups, engine.pluginHooksCapable === true, (type) => shellRuns(event, type), judge, layer.mask);
|
|
471
|
+
const kept = filterSettingsHookGroups(source, event, groups, engine.pluginHooksCapable === true, (type) => shellRuns(event, type), judge, readerNotRead, layer.mask);
|
|
469
472
|
settingsDropped.push(...kept.drops);
|
|
470
473
|
settingsVerdicts.push(...kept.verdicts);
|
|
471
474
|
settingsExcluded.push(...kept.excluded);
|
|
@@ -531,6 +534,7 @@ function buildHooksWirePlan(read, engine, shellRuns, promptAuthoredByUser, suppr
|
|
|
531
534
|
promptAuthoredByUser,
|
|
532
535
|
occupied,
|
|
533
536
|
...(suppressedLocally !== undefined ? { suppressedLocally } : {}),
|
|
537
|
+
readerNotRead,
|
|
534
538
|
});
|
|
535
539
|
});
|
|
536
540
|
if (d === undefined)
|