@sema-agent/client-core 0.107.0 → 0.109.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 +239 -0
- package/README.md +54 -36
- package/dist/adapt/arms.js +23 -8
- package/dist/adapt/textStream.d.ts +2 -0
- package/dist/adapt/textStream.js +37 -16
- package/dist/adapter/activeRunSelfHeal.d.ts +2 -0
- package/dist/adapter/activeRunSelfHeal.js +21 -4
- package/dist/adapter/downstream/eventToSdkMessage.js +2 -1
- package/dist/agentSession/engineAgentRegistryRead.js +2 -0
- package/dist/bashExitReading.d.ts +12 -0
- package/dist/bashExitReading.js +44 -0
- package/dist/checkpointRowVerdict.d.ts +6 -1
- package/dist/checkpointRowVerdict.js +30 -2
- package/dist/cloudConfigWireCaps.d.ts +10 -0
- package/dist/cloudConfigWireCaps.js +33 -0
- package/dist/compensations.js +1 -1
- package/dist/coreValuePorts.d.ts +17 -1
- package/dist/coreValuePorts.js +5 -0
- package/dist/decideReceipt.js +2 -1
- package/dist/engineAgentAbsence.d.ts +2 -0
- package/dist/engineAgentAbsence.js +28 -0
- package/dist/engineErrorCodes.d.ts +9 -0
- package/dist/engineErrorCodes.js +9 -0
- package/dist/engineHealthFacts.d.ts +17 -0
- package/dist/engineHealthFacts.js +42 -3
- package/dist/engineNoticeCodes.d.ts +147 -1
- package/dist/engineNoticeCodes.js +694 -57
- package/dist/engineTargetSeat.js +1 -0
- package/dist/errorSupplementRoles.js +6 -1
- package/dist/eventLeg.js +1 -1
- package/dist/executionLaneWords.js +2 -1
- package/dist/fleetTaskDesc.js +3 -3
- package/dist/gateOutcome.d.ts +10 -1
- package/dist/gateOutcome.js +48 -1
- package/dist/generated/engineFactTables.d.ts +2 -0
- package/dist/generated/engineFactTables.js +11 -0
- package/dist/generated/engineNoticeTables.js +6 -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/approvalCardReasons.js +22 -4
- package/dist/hitl/approvalRequestFrameReading.d.ts +14 -0
- package/dist/hitl/approvalRequestFrameReading.js +79 -0
- package/dist/hitl/approvalResolution.d.ts +3 -0
- package/dist/hitl/approvalResolution.js +22 -4
- package/dist/hitl/approvalsFeed.js +4 -13
- package/dist/hitl/askParkRowRouting.js +10 -3
- package/dist/hitl/automaticAnswerVerdict.d.ts +5 -2
- package/dist/hitl/automaticAnswerVerdict.js +16 -2
- package/dist/hitl/decisionConflict.d.ts +2 -1
- package/dist/hitl/decisionConflict.js +4 -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 +37 -7
- package/dist/hitl/gateLedger.d.ts +2 -0
- package/dist/hitl/gateLedger.js +3 -1
- package/dist/hitl/hitlBridge.d.ts +4 -0
- package/dist/hitl/hitlBridge.js +11 -8
- package/dist/hitl/livePendingAsk.js +17 -16
- package/dist/hitl/localAllowRule.js +2 -1
- package/dist/hitl/noAllowCause.d.ts +1 -1
- package/dist/hitl/noAllowCause.js +4 -2
- package/dist/hitl/parkExpiryJudgements.js +26 -1
- package/dist/hitl/parkOwnership.d.ts +2 -0
- package/dist/hitl/parkOwnership.js +48 -8
- package/dist/hitl/parkResolver.js +39 -30
- package/dist/hitl/parkRowBirthWait.d.ts +2 -0
- package/dist/hitl/parkRowBirthWait.js +8 -1
- package/dist/hitl/parkedUnresumable.d.ts +13 -0
- package/dist/hitl/parkedUnresumable.js +80 -0
- package/dist/hitl/permissionRuleScope.d.ts +4 -0
- package/dist/hitl/permissionRuleScope.js +31 -0
- package/dist/hitl/persistedRulesWire.d.ts +7 -1
- package/dist/hitl/persistedRulesWire.js +25 -8
- 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/sessionAllowRoute.js +5 -4
- package/dist/hitl/sessionPolicyDeliverable.js +1 -1
- package/dist/hitl/standingRows.d.ts +1 -5
- package/dist/hitl/standingRows.js +15 -14
- package/dist/hitl/toolApprovalWire.d.ts +16 -4
- package/dist/hitl/toolApprovalWire.js +57 -17
- package/dist/hooksReaderGenerations.d.ts +1 -0
- package/dist/hooksReaderGenerations.js +12 -0
- package/dist/hooksWireCaps.js +12 -7
- package/dist/hostSettingsSource.js +2 -0
- package/dist/i18n/messages.en.d.ts +206 -1
- package/dist/i18n/messages.en.js +209 -4
- package/dist/i18n/messages.zh.js +214 -4
- package/dist/index.d.ts +35 -8
- package/dist/index.js +20 -5
- package/dist/liveModelCatalog.d.ts +4 -2
- package/dist/liveModelCatalog.js +164 -26
- package/dist/localEngineJudge.d.ts +75 -0
- package/dist/localEngineJudge.js +242 -0
- package/dist/localEngineOccupancy.d.ts +88 -0
- package/dist/localEngineOccupancy.js +269 -0
- package/dist/localEngineSeatReading.d.ts +29 -0
- package/dist/localEngineSeatReading.js +294 -0
- package/dist/localEngineSpawn.d.ts +113 -0
- package/dist/localEngineSpawn.js +486 -0
- package/dist/localEngineStep.d.ts +286 -0
- package/dist/localEngineStep.js +1086 -0
- package/dist/localEngineStopLadder.d.ts +29 -0
- package/dist/localEngineStopLadder.js +139 -0
- package/dist/localEngineSwapCard.d.ts +43 -0
- package/dist/localEngineSwapCard.js +205 -0
- package/dist/localEngineTiming.d.ts +8 -0
- package/dist/localEngineTiming.js +8 -0
- package/dist/mcpReconnect.js +12 -5
- package/dist/mcpWireCaps.js +2 -2
- package/dist/memoryEntriesWire.d.ts +1 -1
- package/dist/memoryEntriesWire.js +5 -0
- package/dist/model/catalogDefault.d.ts +25 -0
- package/dist/model/catalogDefault.js +44 -0
- package/dist/noticePresentation.d.ts +2 -0
- package/dist/noticePresentation.js +79 -1
- package/dist/ownKey.d.ts +10 -0
- package/dist/ownKey.js +15 -1
- 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/ruleReadings.js +1 -1
- package/dist/runPermissionModeSwitch.d.ts +2 -1
- package/dist/runPermissionModeSwitch.js +16 -6
- package/dist/seam.d.ts +13 -2
- package/dist/seam.js +8 -1
- package/dist/seatContract.d.ts +103 -12
- package/dist/seatContract.js +344 -14
- package/dist/sessionBackground.js +2 -0
- 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.d.ts +12 -0
- package/dist/subagentContentStore.js +73 -12
- package/dist/supportFloor.js +2 -0
- package/dist/taskNotificationAdmission.d.ts +19 -0
- package/dist/taskNotificationAdmission.js +84 -0
- package/dist/toolResult.js +20 -6
- package/dist/webSearchWireCaps.js +9 -4
- package/dist/wireFailureShape.d.ts +20 -0
- package/dist/wireFailureShape.js +37 -6
- package/dist/wireRefusalCopy.d.ts +23 -2
- package/dist/wireRefusalCopy.js +93 -4
- package/docs/INTEGRATION-CLIENTS.md +1959 -15
- package/package.json +4 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { displayUntrusted, quoteUntrustedForSentence } from '../displayUntrusted.js';
|
|
2
2
|
import { engineCapTrue } from '../engineCapsCache.js';
|
|
3
3
|
import { CORE_RULE_BEHAVIORS } from '../generated/engineFactTables.js';
|
|
4
|
-
import { slotReadOf, wireFailureShapeOf } from '../wireFailureShape.js';
|
|
4
|
+
import { inValueOf, slotReadOf, wireFailureShapeOf } from '../wireFailureShape.js';
|
|
5
5
|
import { CAPABILITY_OPERATOR_PRINCIPALS_REQUIRED } from '../engineErrorCodes.js';
|
|
6
6
|
import { hostLog } from '../host.js';
|
|
7
7
|
import { msg, renderMessage } from '../i18n/translate.js';
|
|
@@ -43,17 +43,21 @@ 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 unsettledRowOf(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
|
});
|
|
@@ -65,12 +69,15 @@ const RECEIPT_ROW_ARMS = {
|
|
|
65
69
|
'no-op': (acc) => {
|
|
66
70
|
acc.deduped += 1;
|
|
67
71
|
},
|
|
72
|
+
refused: (acc, row) => {
|
|
73
|
+
appendOwnElement(acc.refused, unsettledRowOf(row));
|
|
74
|
+
},
|
|
68
75
|
indeterminate: (acc, row) => {
|
|
69
|
-
appendOwnElement(acc.indeterminate,
|
|
76
|
+
appendOwnElement(acc.indeterminate, unsettledRowOf(row));
|
|
70
77
|
},
|
|
71
78
|
};
|
|
72
79
|
function receiptCountsOf(rows) {
|
|
73
|
-
const acc = { persisted: 0, deduped: 0, indeterminate: [] };
|
|
80
|
+
const acc = { persisted: 0, deduped: 0, indeterminate: [], refused: [] };
|
|
74
81
|
for (const row of rows) {
|
|
75
82
|
if (typeof row !== 'object' || row === null)
|
|
76
83
|
return null;
|
|
@@ -80,7 +87,12 @@ function receiptCountsOf(rows) {
|
|
|
80
87
|
return null;
|
|
81
88
|
RECEIPT_ROW_ARMS[word](acc, row);
|
|
82
89
|
}
|
|
83
|
-
return {
|
|
90
|
+
return {
|
|
91
|
+
persisted: acc.persisted,
|
|
92
|
+
deduped: acc.deduped,
|
|
93
|
+
indeterminate: acc.indeterminate.length === 0 ? NO_INDETERMINATE : Object.freeze(acc.indeterminate),
|
|
94
|
+
...(acc.refused.length === 0 ? {} : { refused: Object.freeze(acc.refused) }),
|
|
95
|
+
};
|
|
84
96
|
}
|
|
85
97
|
function legacyEnvelopeCountsOf(result) {
|
|
86
98
|
if (typeof result !== 'object' || result === null)
|
|
@@ -317,9 +329,14 @@ export function revokeTargetFromPersistedRule(rule, opts) {
|
|
|
317
329
|
};
|
|
318
330
|
}
|
|
319
331
|
function readPrincipalOverride(carrier) {
|
|
320
|
-
if (carrier === null || typeof carrier !== 'object'
|
|
332
|
+
if (carrier === null || typeof carrier !== 'object')
|
|
333
|
+
return { ok: true };
|
|
334
|
+
const slot = inValueOf(carrier, 'principal');
|
|
335
|
+
if (slot.state === 'absent')
|
|
321
336
|
return { ok: true };
|
|
322
|
-
|
|
337
|
+
if (slot.state === 'unproven')
|
|
338
|
+
return { ok: false };
|
|
339
|
+
const raw = slot.value;
|
|
323
340
|
if (typeof raw !== 'string' || raw.trim().length === 0)
|
|
324
341
|
return { ok: false };
|
|
325
342
|
return { ok: true, principal: raw };
|
|
@@ -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
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { inSlotReadOf } from '../wireFailureShape.js';
|
|
1
2
|
export function sessionAllowCarried(leg, approvalId) {
|
|
2
3
|
if (leg === 'frame')
|
|
3
4
|
return true;
|
|
@@ -7,10 +8,10 @@ export function sessionAllowCarried(leg, approvalId) {
|
|
|
7
8
|
}
|
|
8
9
|
export function readCardUnreadableEvidence(card) {
|
|
9
10
|
try {
|
|
10
|
-
|
|
11
|
+
const slot = inSlotReadOf(card, 'unreadableEvidence');
|
|
12
|
+
if (slot.state === 'absent')
|
|
11
13
|
return 'absent';
|
|
12
|
-
const
|
|
13
|
-
const list = d !== undefined && Object.hasOwn(d, 'value') ? d.value : undefined;
|
|
14
|
+
const list = slot.state === 'present' ? slot.value : undefined;
|
|
14
15
|
return Array.isArray(list) && list.every((k) => typeof k === 'string') ? list : 'unreadable';
|
|
15
16
|
}
|
|
16
17
|
catch {
|
|
@@ -21,7 +22,7 @@ export function sessionAllowCardReadable(card) {
|
|
|
21
22
|
if (typeof card !== 'object' || card === null)
|
|
22
23
|
return 'card_unreadable';
|
|
23
24
|
try {
|
|
24
|
-
if ('cardPayloadUnreadable'
|
|
25
|
+
if (inSlotReadOf(card, 'cardPayloadUnreadable').state !== 'absent')
|
|
25
26
|
return 'card_unreadable';
|
|
26
27
|
}
|
|
27
28
|
catch {
|
|
@@ -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'),
|
|
@@ -25,13 +25,9 @@ export interface RememberOfferable {
|
|
|
25
25
|
readonly deploymentList: RememberOffer;
|
|
26
26
|
}
|
|
27
27
|
export declare function rememberOfferable(card: object | null | undefined, host?: StandingRowsHostFacts | null): RememberOfferable;
|
|
28
|
-
export interface LocalAllowRuleHostFacts {
|
|
29
|
-
readonly hostLadderEnforces?: boolean;
|
|
30
|
-
}
|
|
31
28
|
export interface LocalAllowRuleEnforcement {
|
|
32
29
|
readonly enforceable: boolean;
|
|
33
|
-
readonly by?: 'host_ladder' | 'engine_grant';
|
|
34
30
|
readonly engine: 'sent' | 'kept' | 'unreadable';
|
|
35
31
|
readonly keptReason?: PermissionsKeptReason;
|
|
36
32
|
}
|
|
37
|
-
export declare function localAllowRuleEnforceable(rule: string, caps: PermissionsAllowGrantReading
|
|
33
|
+
export declare function localAllowRuleEnforceable(rule: string, caps: PermissionsAllowGrantReading): LocalAllowRuleEnforcement;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { DEPLOYMENT_LIST_ASK_CLASSES, readAskClassPairState } from './askClassPair.js';
|
|
2
|
-
import {
|
|
2
|
+
import { askLevelVerdict } from './automaticAnswerVerdict.js';
|
|
3
3
|
import { readApprovalCardWord, readRuleOffers } from './toolApprovalWire.js';
|
|
4
4
|
import { CORE_SKILL_TOOL_NAME } from '../generated/toolNameTables.js';
|
|
5
|
+
import { inSlotReadOf, inValueOf } from '../wireFailureShape.js';
|
|
5
6
|
import { toolPermissionRequestIdDomain } from '../seatContract.js';
|
|
6
7
|
import { permissionsDeclarationReport } from '../permissionsDeclaration.js';
|
|
7
8
|
import { readCardUnreadableEvidence, sessionAllowCardReadable, sessionAllowEligible } from './sessionAllowRoute.js';
|
|
@@ -15,9 +16,10 @@ function ownData(v, key) {
|
|
|
15
16
|
return undefined;
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
|
-
function
|
|
19
|
+
function candidateSlot(v, key) {
|
|
19
20
|
try {
|
|
20
|
-
|
|
21
|
+
const s = inSlotReadOf(v, key);
|
|
22
|
+
return s.state === 'unproven' ? UNREADABLE : s;
|
|
21
23
|
}
|
|
22
24
|
catch {
|
|
23
25
|
return UNREADABLE;
|
|
@@ -25,8 +27,10 @@ function hasKey(v, key) {
|
|
|
25
27
|
}
|
|
26
28
|
function present(v, key) {
|
|
27
29
|
try {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
+
const s = inValueOf(v, key);
|
|
31
|
+
if (s.state === 'unproven')
|
|
32
|
+
return UNREADABLE;
|
|
33
|
+
return s.state === 'present' ? { inCard: true, value: s.value } : { inCard: false, value: undefined };
|
|
30
34
|
}
|
|
31
35
|
catch {
|
|
32
36
|
return UNREADABLE;
|
|
@@ -42,12 +46,12 @@ function persistentRowOf(card, host, evidenceUnreadable) {
|
|
|
42
46
|
if (evidenceUnreadable)
|
|
43
47
|
return { row: 'none', why: 'evidence_unreadable' };
|
|
44
48
|
for (const key of ['ruleOffers', 'ruleOffersReadOnly']) {
|
|
45
|
-
const p =
|
|
49
|
+
const p = candidateSlot(card, key);
|
|
46
50
|
if (p === UNREADABLE)
|
|
47
51
|
return UNREADABLE;
|
|
48
|
-
if (
|
|
52
|
+
if (p.state === 'absent')
|
|
49
53
|
continue;
|
|
50
|
-
const offers = readRuleOffers(
|
|
54
|
+
const offers = readRuleOffers(p.state === 'present' ? p.value : undefined);
|
|
51
55
|
if (offers === undefined || offers.length === 0)
|
|
52
56
|
return { row: 'none', why: 'offers_unreadable' };
|
|
53
57
|
return { row: 'engine_offer', why: 'given' };
|
|
@@ -69,7 +73,7 @@ function persistentRowOf(card, host, evidenceUnreadable) {
|
|
|
69
73
|
return { row: 'none', why: 'tool_name_unreadable' };
|
|
70
74
|
if (tool === CORE_SKILL_TOOL_NAME)
|
|
71
75
|
return { row: 'none', why: 'grant_binding' };
|
|
72
|
-
if (
|
|
76
|
+
if (askLevelVerdict(card, 'standing_rule').kind !== 'may_answer')
|
|
73
77
|
return { row: 'none', why: 'rule_cannot_clear' };
|
|
74
78
|
const face = readApprovalCardWord(card);
|
|
75
79
|
if (face === undefined)
|
|
@@ -178,8 +182,7 @@ export function rememberOfferable(card, host) {
|
|
|
178
182
|
deploymentList: SESSION_OFFER[rows.why.deploymentList],
|
|
179
183
|
});
|
|
180
184
|
}
|
|
181
|
-
export function localAllowRuleEnforceable(rule, caps
|
|
182
|
-
const ladder = typeof host === 'object' && host !== null && ownData(host, 'hostLadderEnforces') === true;
|
|
185
|
+
export function localAllowRuleEnforceable(rule, caps) {
|
|
183
186
|
let engine = 'unreadable';
|
|
184
187
|
let keptReason;
|
|
185
188
|
if (typeof rule === 'string' && rule.trim() !== '') {
|
|
@@ -199,10 +202,8 @@ export function localAllowRuleEnforceable(rule, caps, host) {
|
|
|
199
202
|
engine = 'unreadable';
|
|
200
203
|
}
|
|
201
204
|
}
|
|
202
|
-
const by = ladder ? 'host_ladder' : engine === 'sent' ? 'engine_grant' : undefined;
|
|
203
205
|
return Object.freeze({
|
|
204
|
-
enforceable:
|
|
205
|
-
...(by !== undefined ? { by } : {}),
|
|
206
|
+
enforceable: engine === 'sent',
|
|
206
207
|
engine,
|
|
207
208
|
...(keptReason !== undefined ? { keptReason } : {}),
|
|
208
209
|
});
|
|
@@ -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,8 @@ 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';
|
|
15
|
+
import { type ApprovalRequestFrameReading, type ApprovalRequestFrameUnreadableWhy } from './approvalRequestFrameReading.js';
|
|
12
16
|
import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS } from '@sema-agent/sdk';
|
|
13
17
|
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
18
|
export declare function toolNameIsFsWrite(name: string): boolean;
|
|
@@ -71,6 +75,7 @@ export interface ApprovalCardDenyDecision {
|
|
|
71
75
|
kind: 'deny';
|
|
72
76
|
reason?: string;
|
|
73
77
|
settledBy?: ApprovalDenySettledBy;
|
|
78
|
+
policyCause?: PolicyDenyCause;
|
|
74
79
|
}
|
|
75
80
|
export declare const APPROVAL_DENY_SETTLED_BY_WORDS: readonly ["human", "policy"];
|
|
76
81
|
export type ApprovalDenySettledBy = (typeof APPROVAL_DENY_SETTLED_BY_WORDS)[number];
|
|
@@ -125,6 +130,8 @@ export interface ApprovalCardRequest {
|
|
|
125
130
|
approvalCard?: ApprovalCardWord;
|
|
126
131
|
askClass?: string;
|
|
127
132
|
classes?: readonly string[];
|
|
133
|
+
agentId?: string;
|
|
134
|
+
askReasons?: readonly ApprovalAskReason[];
|
|
128
135
|
boundGrants?: BoundSkillGrantsWire;
|
|
129
136
|
grantBinding?: ApprovalGrantBinding;
|
|
130
137
|
unreadableEvidence?: readonly string[];
|
|
@@ -132,6 +139,7 @@ export interface ApprovalCardRequest {
|
|
|
132
139
|
priorCardsForCall?: readonly ApprovalPriorCard[];
|
|
133
140
|
message?: string;
|
|
134
141
|
cardPayloadUnreadable?: true;
|
|
142
|
+
cardPayloadUnreadableWhy?: ApprovalRequestFrameUnreadableWhy;
|
|
135
143
|
supersedes?: ApprovalCardSupersedes;
|
|
136
144
|
parkRow?: ApprovalCardParkRow;
|
|
137
145
|
}
|
|
@@ -163,7 +171,7 @@ export declare function approvalCardPortFor(sessionKey: string): ApprovalCardPor
|
|
|
163
171
|
export declare function __resetSettledApprovalsForTests(): void;
|
|
164
172
|
export declare function _resetApprovalCardPortForTest(): void;
|
|
165
173
|
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"];
|
|
174
|
+
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
175
|
export type RememberRefusalCode = (typeof REMEMBER_REFUSAL_CODES)[number];
|
|
168
176
|
export declare function rememberRefusalOf(error: unknown): RememberRefusalCode | undefined;
|
|
169
177
|
export declare function surfaceFsApprovalAndDecide(deps: FsApprovalWireDeps, taskId: string, argsByCall: Map<string, unknown>, signal?: AbortSignal, parkGatedCallId?: string, parkToolName?: string): Promise<ApprovalResolution>;
|
|
@@ -276,8 +284,8 @@ export declare function approvalSupersedesDetail(card: Pick<ApprovalCardRequest,
|
|
|
276
284
|
export declare function readDenialLimitFallback(v: unknown): DenialLimitFallback | undefined;
|
|
277
285
|
export declare function readRuleOffers(v: unknown): RuleOfferReading[] | undefined;
|
|
278
286
|
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'>;
|
|
280
|
-
export type ApprovalCardFacts = ApprovalCardV1Facts & Pick<ApprovalCardRequest, 'argsRewritten' | 'ruleOffers' | 'probeReason' | 'mandated' | 'mandate' | 'readRootCandidate' | 'origin' | 'boundGrants' | 'classifierNoRuling' | 'allowSessionCarried' | 'cardPayloadUnreadable'>;
|
|
287
|
+
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'>;
|
|
288
|
+
export type ApprovalCardFacts = ApprovalCardV1Facts & Pick<ApprovalCardRequest, 'argsRewritten' | 'ruleOffers' | 'probeReason' | 'mandated' | 'mandate' | 'readRootCandidate' | 'origin' | 'boundGrants' | 'classifierNoRuling' | 'allowSessionCarried' | 'cardPayloadUnreadable' | 'cardPayloadUnreadableWhy'>;
|
|
281
289
|
export interface ApprovalCardFrameFactsOptions {
|
|
282
290
|
readonly streamArgs?: object;
|
|
283
291
|
readonly argsUnavailable?: true;
|
|
@@ -285,7 +293,7 @@ export interface ApprovalCardFrameFactsOptions {
|
|
|
285
293
|
export declare function approvalCardFactsOfV1(card: object | null | undefined): Readonly<ApprovalCardV1Facts> | undefined;
|
|
286
294
|
export declare function approvalCardFactsOfV1Frame(frame: object | null | undefined): Readonly<ApprovalCardFacts> | undefined;
|
|
287
295
|
export declare function approvalCardFactsOfFrame(frame: object | null | undefined, opts?: ApprovalCardFrameFactsOptions | null): Readonly<ApprovalCardFacts> | undefined;
|
|
288
|
-
export declare function approvalCardFactsOfGeneric(card: object | null | undefined): Readonly<ApprovalCardFacts> | undefined;
|
|
296
|
+
export declare function approvalCardFactsOfGeneric(card: object | null | undefined, reading?: ApprovalRequestFrameReading | null): Readonly<ApprovalCardFacts> | undefined;
|
|
289
297
|
export interface ToolApprovalFrameLaneOpts {
|
|
290
298
|
approvalDecisionNoteCapable?: boolean;
|
|
291
299
|
respondFreeFormRulesCapable?: boolean;
|
|
@@ -298,6 +306,10 @@ export declare function surfaceToolApprovalFrameAndRespond(frame: ToolApprovalFr
|
|
|
298
306
|
readonly taskId?: string;
|
|
299
307
|
readonly sessionId?: string;
|
|
300
308
|
}): Promise<ApprovalResolution>;
|
|
309
|
+
export declare function surfaceApprovalFrameWithId(frame: ToolApprovalFrame | ApprovalRequestFrame, approvalId: string, respond: RespondToolApprovalFn, streamArgs: Parameters<typeof surfaceToolApprovalFrameAndRespond>[2], signal: AbortSignal | undefined, lane: ToolApprovalFrameLaneOpts | undefined, run: {
|
|
310
|
+
readonly taskId?: string;
|
|
311
|
+
readonly sessionId?: string;
|
|
312
|
+
} | undefined): Promise<ApprovalResolution>;
|
|
301
313
|
export interface ApprovalHolderIdentity {
|
|
302
314
|
readonly approvalId?: string;
|
|
303
315
|
readonly taskId?: string;
|
|
@@ -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,13 +29,15 @@ 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';
|
|
31
|
-
import {
|
|
32
|
+
import { readPolicyDenyCause } from './policyDenyCause.js';
|
|
33
|
+
import { inValueOf, slotPresenceOf, wireFailureTextsOf } from '../wireFailureShape.js';
|
|
32
34
|
import { APPROVAL_LIVE_FACE_KEYS, approvalLiveFaceOf, hasOwnStrictTrue } from './approvalLiveFace.js';
|
|
35
|
+
import { approvalFrameUnreadableWhyOf, approvalRequestFrameReadingThrowing, } from './approvalRequestFrameReading.js';
|
|
33
36
|
import { subagentSourceSessionOf } from './subagentSource.js';
|
|
34
37
|
import { isPlainRecord } from '../jsonFaithful.js';
|
|
35
38
|
import { DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED } from '../engineErrorCodes.js';
|
|
36
39
|
import { readDecideReceipt } from '../decideReceipt.js';
|
|
37
|
-
import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, ASK_ORIGINS,
|
|
40
|
+
import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, ASK_ORIGINS, } from '@sema-agent/sdk';
|
|
38
41
|
export function toolNameIsFsWrite(name) {
|
|
39
42
|
const n = name.replace(/[\s_-]+/g, '').toLowerCase();
|
|
40
43
|
return (n === 'write' || n === 'filewrite' || n === 'edit' || n === 'fileedit' || n === 'multiedit' || n === 'notebookedit');
|
|
@@ -157,11 +160,13 @@ function cardPortMissReason() {
|
|
|
157
160
|
return APPROVAL_CARD_PORT_KEY_MISMATCH_REASON;
|
|
158
161
|
return NO_APPROVAL_CARD_PORT_REASON;
|
|
159
162
|
}
|
|
163
|
+
const LEGACY_REMEMBER_REFUSAL_CODE = 'remember_requires_binding';
|
|
160
164
|
const REMEMBER_REFUSAL_CODES = Object.freeze([
|
|
161
165
|
'remember_not_in_proof',
|
|
162
166
|
'capability.store_required',
|
|
163
167
|
DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED,
|
|
164
168
|
'decide.parked_remember_unsupported',
|
|
169
|
+
LEGACY_REMEMBER_REFUSAL_CODE,
|
|
165
170
|
]);
|
|
166
171
|
export function rememberRefusalOf(error) {
|
|
167
172
|
return rememberRefusalIn(readWireErrorCodeReading(error));
|
|
@@ -489,6 +494,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
489
494
|
const rowArgsGap = reading.from !== 'none' ? undefined : reading.shape === 'absent' ? 'absent' : reading.shape === 'size_marker' ? 'truncated' : undefined;
|
|
490
495
|
const args = reading.from !== 'none' ? reading.args : rowArgsGap !== undefined ? {} : reading.recorded;
|
|
491
496
|
const argsRewritten = reading.from === 'recorded' && reading.rewritten;
|
|
497
|
+
const argsFromModelCall = reading.from === 'stream';
|
|
492
498
|
if (typeof args !== 'object' || args === null) {
|
|
493
499
|
return { kind: 'not_sent', ...at, cause: 'no_input', detail: 'gate has no tool input payload' };
|
|
494
500
|
}
|
|
@@ -512,11 +518,13 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
512
518
|
}
|
|
513
519
|
: {}),
|
|
514
520
|
...(argsRewritten ? { argsRewritten: true, wireNote: ARGS_REWRITTEN_NOTE } : {}),
|
|
521
|
+
...(argsFromModelCall ? { argsUnavailable: true, wireNote: renderMessage(msg('approval.park.argsFromModelCall')) } : {}),
|
|
515
522
|
...(pending.governanceForced === true ? { governanceForced: true } : {}),
|
|
516
523
|
...(readRequiresRealApproval(pending) ? { requiresRealApproval: true } : {}),
|
|
517
524
|
...approvalLiveFaceOf(pending).facts,
|
|
518
525
|
...((w) => (w !== undefined ? { approvalCard: w } : {}))(readApprovalCardWord(pending)),
|
|
519
526
|
...(readAskClassPair(pending) ?? {}),
|
|
527
|
+
...((r) => (r !== undefined ? { askReasons: r } : {}))(approvalAskReasonsOf(pending)),
|
|
520
528
|
...(pending.gateKind === 'irreversible_ask' ? { irreversibleParkGate: true } : {}),
|
|
521
529
|
...(pending.hasBidiControls === true ? { hasBidiControls: true } : {}),
|
|
522
530
|
...(ruleOffersReadOnly !== undefined ? { ruleOffersReadOnly } : {}),
|
|
@@ -536,8 +544,8 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
536
544
|
});
|
|
537
545
|
const card = await surfaceCallTrackedCard(gatedCallId, undefined, ledgerSlot, cardRequest);
|
|
538
546
|
hold.phase = 'respond';
|
|
539
|
-
if (rowArgsGap !== undefined && card.kind === 'allow' && card.updatedInput !== undefined) {
|
|
540
|
-
hostLog('error', `liveToolApprovalWire: approval card for ${gatedCallId ?? `task ${taskId}`} returned an edited approval, but the tool input is ${rowArgsGap === 'truncated' ? 'a size marker on the pending row' : 'missing from both the stream and the pending row'} — nothing sent (the park stays pending)`);
|
|
547
|
+
if ((rowArgsGap !== undefined || argsFromModelCall) && card.kind === 'allow' && card.updatedInput !== undefined) {
|
|
548
|
+
hostLog('error', `liveToolApprovalWire: approval card for ${gatedCallId ?? `task ${taskId}`} returned an edited approval, but the tool input is ${rowArgsGap === 'truncated' ? 'a size marker on the pending row' : rowArgsGap === 'absent' ? 'missing from both the stream and the pending row' : 'not recorded on the pending row'} — nothing sent (the park stays pending)`);
|
|
541
549
|
surfaceEditRefusedOnBlindAsk();
|
|
542
550
|
return { kind: 'not_sent', ...at, cause: 'edit_refused', detail: PARK_EDIT_REFUSED_REASON };
|
|
543
551
|
}
|
|
@@ -609,6 +617,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
609
617
|
}
|
|
610
618
|
case 'deny': {
|
|
611
619
|
const denySettledByForWire = readApprovalDenySettledBy(card);
|
|
620
|
+
const denyPolicyCauseForWire = readPolicyDenyCause(card);
|
|
612
621
|
const attributionKeys = decisionAttributionKeyOf(decidedByReading, denySettledByForWire);
|
|
613
622
|
const denyReasonSnapshot = ((r) => (typeof r === 'string' ? r : undefined))(card.reason);
|
|
614
623
|
let lastSendCarriedAttribution = false;
|
|
@@ -642,7 +651,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
642
651
|
const attributionDropped = ladder.dropped;
|
|
643
652
|
const attributionRenamed = ladder.renamed;
|
|
644
653
|
const receipt = readDecideReceipt(raw);
|
|
645
|
-
const deny = denyFactsOf(denySettledByForWire, denyReasonSnapshot, attributionDropped, attributionRenamed);
|
|
654
|
+
const deny = denyFactsOf(denySettledByForWire, denyReasonSnapshot, attributionDropped, attributionRenamed, denyPolicyCauseForWire);
|
|
646
655
|
return {
|
|
647
656
|
kind: 'decided',
|
|
648
657
|
...at,
|
|
@@ -679,8 +688,11 @@ function readReadRootCandidate(v) {
|
|
|
679
688
|
const o = v;
|
|
680
689
|
if (typeof o.dir !== 'string' || o.dir.length === 0 || o.clearsThisAsk !== true)
|
|
681
690
|
return undefined;
|
|
682
|
-
|
|
683
|
-
|
|
691
|
+
const covers = inValueOf(o, 'covers');
|
|
692
|
+
if (covers.state === 'unproven')
|
|
693
|
+
return undefined;
|
|
694
|
+
if (covers.state === 'present')
|
|
695
|
+
return covers.value === 'exact' ? { dir: o.dir, clearsThisAsk: true, covers: 'exact' } : undefined;
|
|
684
696
|
return { dir: o.dir, clearsThisAsk: true };
|
|
685
697
|
}
|
|
686
698
|
export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
|
|
@@ -1014,14 +1026,16 @@ function readDecidedByReadingOf(holder) {
|
|
|
1014
1026
|
function decidedByReadingSnapshotOf(holder) {
|
|
1015
1027
|
return approvalDecidedByAdmitted(readDecidedByReadingOf(holder)) ? Object.freeze({ kind: 'present', value: true }) : undefined;
|
|
1016
1028
|
}
|
|
1017
|
-
function denyFactsOf(settledBy, reasonSnapshot, dropped, renamed) {
|
|
1029
|
+
function denyFactsOf(settledBy, reasonSnapshot, dropped, renamed, policyCauseSnapshot) {
|
|
1018
1030
|
const reason = reasonSnapshot !== undefined && reasonSnapshot.trim() !== '' ? reasonSnapshot : undefined;
|
|
1019
1031
|
const attributionKey = dropped ? 'dropped' : renamed ? 'renamed' : undefined;
|
|
1032
|
+
const policyCause = settledBy === 'policy' ? policyCauseSnapshot : undefined;
|
|
1020
1033
|
if (settledBy === undefined && reason === undefined && attributionKey === undefined)
|
|
1021
1034
|
return undefined;
|
|
1022
1035
|
return {
|
|
1023
1036
|
...(settledBy !== undefined ? { settledBy } : {}),
|
|
1024
1037
|
...(reason !== undefined ? { reason } : {}),
|
|
1038
|
+
...(policyCause !== undefined ? { policyCause } : {}),
|
|
1025
1039
|
...(attributionKey !== undefined ? { attributionKey } : {}),
|
|
1026
1040
|
};
|
|
1027
1041
|
}
|
|
@@ -1671,7 +1685,7 @@ function v1Bit(stamp) {
|
|
|
1671
1685
|
const SUSPENDED_ASK_ARGS_NOTE = "this request's tool arguments are not available on this surface — it was raised while no client was connected, " +
|
|
1672
1686
|
'so you are deciding without seeing them; deny it if you are not sure what it will do. ' +
|
|
1673
1687
|
'Edits are not accepted on this card: there is no original input to edit';
|
|
1674
|
-
function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
|
|
1688
|
+
function cardFactsOf(carrier, leg, opts, liveFacts, approvalId, payloadWhy) {
|
|
1675
1689
|
const c = carrier;
|
|
1676
1690
|
const full = leg !== 'generic';
|
|
1677
1691
|
const live = leg === 'frame' ? carrier : leg === 'v1' ? liveFacts : undefined;
|
|
@@ -1822,6 +1836,16 @@ function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
|
|
|
1822
1836
|
if (w !== undefined)
|
|
1823
1837
|
out.approvalCard = w;
|
|
1824
1838
|
});
|
|
1839
|
+
v1Bit(() => {
|
|
1840
|
+
const id = approvalAgentIdOf(carrier);
|
|
1841
|
+
if (id !== undefined)
|
|
1842
|
+
out.agentId = id;
|
|
1843
|
+
});
|
|
1844
|
+
v1Bit(() => {
|
|
1845
|
+
const reasons = approvalAskReasonsOf(carrier);
|
|
1846
|
+
if (reasons !== undefined)
|
|
1847
|
+
out.askReasons = reasons;
|
|
1848
|
+
});
|
|
1825
1849
|
}
|
|
1826
1850
|
v1Bit(() => {
|
|
1827
1851
|
const pair = readAskClassPair(carrier);
|
|
@@ -1847,8 +1871,11 @@ function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
|
|
|
1847
1871
|
if (typeof msg === 'string' && msg.trim() !== '')
|
|
1848
1872
|
out.message = msg;
|
|
1849
1873
|
});
|
|
1850
|
-
if (leg === 'generic')
|
|
1874
|
+
if (leg === 'generic') {
|
|
1851
1875
|
out.cardPayloadUnreadable = true;
|
|
1876
|
+
if (payloadWhy !== undefined)
|
|
1877
|
+
out.cardPayloadUnreadableWhy = payloadWhy;
|
|
1878
|
+
}
|
|
1852
1879
|
if (sessionAllowCarried(leg, approvalId))
|
|
1853
1880
|
out.allowSessionCarried = true;
|
|
1854
1881
|
out.grantBinding = readApprovalGrantBinding(carrier);
|
|
@@ -1880,15 +1907,26 @@ export function approvalCardFactsOfFrame(frame, opts) {
|
|
|
1880
1907
|
return undefined;
|
|
1881
1908
|
return Object.freeze(cardFactsOf(frame, 'frame', opts));
|
|
1882
1909
|
}
|
|
1883
|
-
export function approvalCardFactsOfGeneric(card) {
|
|
1910
|
+
export function approvalCardFactsOfGeneric(card, reading) {
|
|
1884
1911
|
if (typeof card !== 'object' || card === null)
|
|
1885
1912
|
return undefined;
|
|
1886
|
-
return Object.freeze(cardFactsOf(card, 'generic'));
|
|
1913
|
+
return Object.freeze(cardFactsOf(card, 'generic', null, undefined, undefined, approvalFrameUnreadableWhyOf(reading)));
|
|
1887
1914
|
}
|
|
1888
1915
|
const MAX_RESPOND_NOTE_CHARS = 2048;
|
|
1889
1916
|
export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamArgs, signal, lane, run) {
|
|
1917
|
+
const approvalId = readOwnDataNonEmptyString(frame, 'approvalId');
|
|
1918
|
+
if (approvalId === undefined)
|
|
1919
|
+
return approvalIdUnreadableRefusal();
|
|
1920
|
+
return surfaceApprovalFrameWithId(frame, approvalId, respond, streamArgs, signal, lane, run);
|
|
1921
|
+
}
|
|
1922
|
+
function approvalIdUnreadableRefusal() {
|
|
1923
|
+
hostLog('debug', 'liveToolApprovalWire: refused (approvalId_unreadable)');
|
|
1924
|
+
return { kind: 'not_sent', lane: 'respond', cause: 'card_unavailable' };
|
|
1925
|
+
}
|
|
1926
|
+
export async function surfaceApprovalFrameWithId(frame, approvalId, respond, streamArgs, signal, lane, run) {
|
|
1890
1927
|
const receivedAtMs = Date.now();
|
|
1891
|
-
|
|
1928
|
+
if (typeof approvalId !== 'string' || approvalId === '')
|
|
1929
|
+
return approvalIdUnreadableRefusal();
|
|
1892
1930
|
const carriers = openingFrameCarriersOf(frame);
|
|
1893
1931
|
const entry = { frame, carriers, approvalId, identity: liveCardIdentityOf(approvalId, frame, carriers, run), respond, streamArgs, signal, lane, receivedAtMs };
|
|
1894
1932
|
return enterLiveCard(entry);
|
|
@@ -1898,9 +1936,10 @@ function openingFrameCarriersOf(frame) {
|
|
|
1898
1936
|
return { body: frame, live: frame, leg: 'frame' };
|
|
1899
1937
|
const card = frame.card;
|
|
1900
1938
|
const pinned = Object.create(frame, { card: { value: card, enumerable: true } });
|
|
1901
|
-
|
|
1939
|
+
const reading = approvalRequestFrameReadingThrowing(pinned);
|
|
1940
|
+
if (reading.v1)
|
|
1902
1941
|
return { body: pinned.card, live: frame, leg: 'v1' };
|
|
1903
|
-
return { body: typeof card === 'object' && card !== null ? card : {}, live: undefined, leg: 'generic' };
|
|
1942
|
+
return { body: typeof card === 'object' && card !== null ? card : {}, live: undefined, leg: 'generic', why: reading.why };
|
|
1904
1943
|
}
|
|
1905
1944
|
function enterLiveCard(e) {
|
|
1906
1945
|
const { approvalId, signal } = e;
|
|
@@ -1998,7 +2037,7 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
|
|
|
1998
2037
|
const bodyToolCallId = carriers.body.toolCallId;
|
|
1999
2038
|
const frameToolCallId = typeof bodyToolCallId === 'string' && bodyToolCallId !== '' ? bodyToolCallId : undefined;
|
|
2000
2039
|
const decidedByReading = decidedByReadingSnapshotOf(lane);
|
|
2001
|
-
const facts = cardFactsOf(carriers.body, carriers.leg, { streamArgs, ...(lane?.argsUnavailable === true ? { argsUnavailable: true } : {}) }, carriers.live, approvalId);
|
|
2040
|
+
const facts = cardFactsOf(carriers.body, carriers.leg, { streamArgs, ...(lane?.argsUnavailable === true ? { argsUnavailable: true } : {}) }, carriers.live, approvalId, carriers.why);
|
|
2002
2041
|
const argsNotRealInput = facts.argsUnavailable === true;
|
|
2003
2042
|
const ruleOffers = facts.ruleOffers;
|
|
2004
2043
|
if (argsNotRealInput && lane?.argsUnavailable !== true && facts.wireNote !== undefined) {
|
|
@@ -2059,6 +2098,7 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
|
|
|
2059
2098
|
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
2099
|
}
|
|
2061
2100
|
const denySettledByForWire = card.kind === 'deny' ? readApprovalDenySettledBy(card) : undefined;
|
|
2101
|
+
const denyPolicyCauseForWire = card.kind === 'deny' ? readPolicyDenyCause(card) : undefined;
|
|
2062
2102
|
const attributionKeys = decision === 'deny' ? decisionAttributionKeyOf(decidedByReading, denySettledByForWire) : {};
|
|
2063
2103
|
const sentAttributionKey = carriesAttributionKey(attributionKeys);
|
|
2064
2104
|
let lastSendCarriedAttribution = sentAttributionKey;
|
|
@@ -2300,7 +2340,7 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
|
|
|
2300
2340
|
'this answer was not delivered, reporting the earlier decision');
|
|
2301
2341
|
return { kind: 'decided', lane: 'respond', decision: replayed.decision, ack: replayed };
|
|
2302
2342
|
}
|
|
2303
|
-
const deny = decision === 'deny' ? denyFactsOf(denySettledByForWire, denyReasonSnapshot, attributionDropped, attributionRenamed) : undefined;
|
|
2343
|
+
const deny = decision === 'deny' ? denyFactsOf(denySettledByForWire, denyReasonSnapshot, attributionDropped, attributionRenamed, denyPolicyCauseForWire) : undefined;
|
|
2304
2344
|
return { kind: 'decided', lane: 'respond', decision, ...(ack !== undefined ? { ack } : {}), ...(deny !== undefined ? { deny } : {}) };
|
|
2305
2345
|
}
|
|
2306
2346
|
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
|
+
}
|