@sema-agent/client-core 0.108.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 +121 -0
- package/README.md +37 -24
- 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.js +1 -1
- 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 +1 -1
- package/dist/checkpointRowVerdict.js +4 -2
- package/dist/compensations.js +1 -1
- package/dist/engineAgentAbsence.d.ts +2 -0
- package/dist/engineAgentAbsence.js +28 -0
- package/dist/engineErrorCodes.d.ts +4 -0
- package/dist/engineErrorCodes.js +4 -0
- package/dist/engineHealthFacts.d.ts +17 -0
- package/dist/engineHealthFacts.js +42 -3
- package/dist/engineNoticeCodes.d.ts +128 -0
- package/dist/engineNoticeCodes.js +630 -55
- package/dist/errorSupplementRoles.js +4 -1
- package/dist/fleetTaskDesc.js +3 -3
- package/dist/generated/engineFactTables.d.ts +1 -0
- package/dist/generated/engineFactTables.js +6 -0
- package/dist/generated/engineNoticeTables.js +3 -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/approvalsFeed.js +1 -1
- package/dist/hitl/askParkRowRouting.js +5 -2
- 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/frameRouter.js +9 -1
- package/dist/hitl/hitlBridge.d.ts +4 -0
- package/dist/hitl/hitlBridge.js +9 -5
- 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 +7 -7
- 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 +2 -0
- package/dist/hitl/persistedRulesWire.js +11 -10
- package/dist/hitl/sessionAllowRoute.js +5 -4
- package/dist/hitl/standingRows.d.ts +1 -5
- package/dist/hitl/standingRows.js +15 -14
- package/dist/hitl/toolApprovalWire.d.ts +8 -2
- package/dist/hitl/toolApprovalWire.js +35 -14
- package/dist/hooksWireCaps.js +4 -3
- package/dist/hostSettingsSource.js +2 -0
- package/dist/i18n/messages.en.d.ts +168 -0
- package/dist/i18n/messages.en.js +169 -1
- package/dist/i18n/messages.zh.js +169 -1
- package/dist/index.d.ts +29 -7
- package/dist/index.js +16 -4
- 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/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/ruleReadings.js +1 -1
- package/dist/seam.d.ts +13 -2
- package/dist/seam.js +8 -1
- package/dist/seatContract.d.ts +42 -4
- package/dist/seatContract.js +180 -3
- package/dist/sessionBackground.js +2 -0
- package/dist/subagentContentStore.d.ts +12 -0
- package/dist/subagentContentStore.js +72 -11
- package/dist/toolResult.js +18 -5
- package/dist/wireFailureShape.d.ts +20 -0
- package/dist/wireFailureShape.js +37 -6
- package/dist/wireRefusalCopy.d.ts +21 -1
- package/dist/wireRefusalCopy.js +91 -2
- package/docs/INTEGRATION-CLIENTS.md +1152 -10
- package/package.json +3 -3
|
@@ -3,31 +3,71 @@ import { rowIdTail } from '../workflow.js';
|
|
|
3
3
|
import { hostSessionFor } from '../host.js';
|
|
4
4
|
import { DEFAULT_SESSION_KEY } from '../sessionSlot.js';
|
|
5
5
|
import { pendingRowIsOfSession } from './parkRowDelegation.js';
|
|
6
|
+
import { slotReadOf } from '../wireFailureShape.js';
|
|
6
7
|
export function pendingRowIsOwnedByThisSession(row, deps) {
|
|
8
|
+
return ownershipVerdictOf(row, deps) === 'owned';
|
|
9
|
+
}
|
|
10
|
+
export function pendingRowOwnershipOf(row, deps) {
|
|
11
|
+
try {
|
|
12
|
+
return ownershipVerdictOf(row, deps);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return 'unknown';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function ownershipVerdictOf(row, deps) {
|
|
7
19
|
const sessionKey = deps?.sessionKey ?? DEFAULT_SESSION_KEY;
|
|
8
20
|
const rowTaskId = typeof row.taskId === 'string' ? row.taskId : '';
|
|
9
21
|
if (rowTaskId.length > 0) {
|
|
10
22
|
const tail = rowIdTail(rowTaskId);
|
|
11
23
|
if (deps?.isOwnRun !== undefined && deps.isOwnRun(tail))
|
|
12
|
-
return
|
|
24
|
+
return 'owned';
|
|
13
25
|
if (sessionKey === DEFAULT_SESSION_KEY && isOwnEngineRun(tail))
|
|
14
|
-
return
|
|
26
|
+
return 'owned';
|
|
15
27
|
}
|
|
16
28
|
const currentSessionId = deps?.currentSessionId ?? (() => hostSessionFor(sessionKey)?.currentSessionId());
|
|
17
29
|
const sessionId = currentSessionId();
|
|
18
30
|
if (typeof sessionId !== 'string' || sessionId.length === 0)
|
|
31
|
+
return 'unknown';
|
|
32
|
+
if (pendingRowIsOfSession(row, sessionId))
|
|
33
|
+
return 'owned';
|
|
34
|
+
return rowIsProvablyForeign(row, sessionId) ? 'foreign' : 'unknown';
|
|
35
|
+
}
|
|
36
|
+
function rowIsProvablyForeign(row, selfSessionId) {
|
|
37
|
+
const own = slotReadOf(row, 'sessionId');
|
|
38
|
+
if (own.presence !== 'present' || typeof own.value !== 'string' || own.value === '' || own.value === selfSessionId)
|
|
39
|
+
return false;
|
|
40
|
+
const agent = slotReadOf(row, 'agent');
|
|
41
|
+
if (agent.presence === 'absent')
|
|
42
|
+
return true;
|
|
43
|
+
if (agent.presence !== 'present' || typeof agent.value !== 'object' || agent.value === null)
|
|
19
44
|
return false;
|
|
20
|
-
|
|
45
|
+
for (const key of ['parentSessionId', 'rootSessionId']) {
|
|
46
|
+
const link = slotReadOf(agent.value, key);
|
|
47
|
+
if (link.presence === 'absent')
|
|
48
|
+
continue;
|
|
49
|
+
if (link.presence !== 'present' || typeof link.value !== 'string' || link.value === selfSessionId)
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
export function usableAskQuestions(value) {
|
|
55
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
56
|
+
return null;
|
|
57
|
+
for (let i = 0; i < value.length; i++) {
|
|
58
|
+
if (!Object.hasOwn(value, i))
|
|
59
|
+
return null;
|
|
60
|
+
const q = value[i];
|
|
61
|
+
if (typeof q !== 'object' || q === null || typeof q.question !== 'string')
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
21
65
|
}
|
|
22
66
|
export function askQuestionsFromPending(pending) {
|
|
23
67
|
const input = pending.input;
|
|
24
68
|
if (typeof input !== 'object' || input === null)
|
|
25
69
|
return null;
|
|
26
|
-
|
|
27
|
-
if (!Array.isArray(qs) || qs.length === 0)
|
|
28
|
-
return null;
|
|
29
|
-
const ok = qs.every(q => typeof q === 'object' && q !== null && typeof q.question === 'string');
|
|
30
|
-
return ok ? qs : null;
|
|
70
|
+
return usableAskQuestions(input.questions);
|
|
31
71
|
}
|
|
32
72
|
export function isHitlSafetyErrorLike(e) {
|
|
33
73
|
return typeof e === 'object' && e !== null && e.name === 'HitlSafetyError';
|
|
@@ -10,6 +10,7 @@ import { denyAttributionOf, flushHeldWithInterruptRewrite, isAskTool } from './f
|
|
|
10
10
|
import { invokeHostCallbackIsolated } from '../hostCallbackGuard.js';
|
|
11
11
|
import { inheritFrameBinding } from '../frameBinding.js';
|
|
12
12
|
import { approvalCallKey, askGateQuestionId } from './gateIdentity.js';
|
|
13
|
+
import { usableAskQuestions } from './parkOwnership.js';
|
|
13
14
|
import { readDecideReceipt } from '../decideReceipt.js';
|
|
14
15
|
import { decideFailureNote } from '../decideFailureNote.js';
|
|
15
16
|
import { wireFailureTextsOf } from '../wireFailureShape.js';
|
|
@@ -69,12 +70,11 @@ async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGat
|
|
|
69
70
|
return { kind: 'not_sent', lane: 'ask', cause: found.code ?? 'fetch_failed', ...(found.reason !== '' ? { detail: found.reason } : {}), ...(found.rowVerdict !== undefined ? { rowVerdict: found.rowVerdict } : {}) };
|
|
70
71
|
const { pending, gatedCallId } = found;
|
|
71
72
|
const at = { lane: 'ask', ...(gatedCallId !== undefined ? { gatedCallId } : {}) };
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
if (!Array.isArray(questions) || questions.length === 0) {
|
|
73
|
+
const rowQuestions = usableAskQuestions(pending.input?.questions);
|
|
74
|
+
const streamQuestions = usableAskQuestions(gatedCallId ? askArgsByCall.get(gatedCallId)?.questions : undefined);
|
|
75
|
+
const questionsFromModelCall = rowQuestions === null && streamQuestions !== null;
|
|
76
|
+
const questions = rowQuestions ?? streamQuestions;
|
|
77
|
+
if (questions === null) {
|
|
78
78
|
const truncated = pending.input?.truncated === true;
|
|
79
79
|
return {
|
|
80
80
|
kind: 'not_sent',
|
|
@@ -107,7 +107,7 @@ async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGat
|
|
|
107
107
|
}
|
|
108
108
|
signal?.addEventListener('abort', onAbort, { once: true });
|
|
109
109
|
onPresented?.();
|
|
110
|
-
publishQuestionFrame({ type: 'question', questionId, questions });
|
|
110
|
+
publishQuestionFrame({ type: 'question', questionId, questions, ...(questionsFromModelCall ? { _sema_questionsFromModelCall: true } : {}) });
|
|
111
111
|
});
|
|
112
112
|
const bridge = new HitlBridge(deps.client, taskId, deps.onDecideOperation ? { onDecideOperation: deps.onDecideOperation } : undefined);
|
|
113
113
|
if (answer === null) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type CheckpointRowBar } from '../checkpointRowVerdict.js';
|
|
2
|
+
import type { UiLanguage } from '../env/uiLanguage.js';
|
|
3
|
+
import type { OwnedPendingListView } from './askParkRowRouting.js';
|
|
4
|
+
import { type ParkOwnershipDeps } from './parkOwnership.js';
|
|
5
|
+
export interface ParkedUnresumableRow {
|
|
6
|
+
readonly rowVerdict: CheckpointRowBar;
|
|
7
|
+
readonly rowKey?: string;
|
|
8
|
+
readonly taskId?: string;
|
|
9
|
+
readonly toolName?: string;
|
|
10
|
+
readonly rowDeadline?: 'armed' | 'none';
|
|
11
|
+
}
|
|
12
|
+
export declare function parkedUnresumableRowsOf(listed: OwnedPendingListView | null | undefined, deps?: ParkOwnershipDeps): readonly ParkedUnresumableRow[];
|
|
13
|
+
export declare function parkedUnresumableLine(row: ParkedUnresumableRow, lang?: UiLanguage | (string & {})): string;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { checkpointDeadlineStateOf, checkpointRowBarOf, checkpointRowBarSentence, rowBarWayOutContent, } from '../checkpointRowVerdict.js';
|
|
2
|
+
import { slotReadOf } from '../wireFailureShape.js';
|
|
3
|
+
import { QUEUE_ROW_FAMILY_UNREADABLE_GATE } from './approvalQueueRow.js';
|
|
4
|
+
import { approvalCallKey } from './gateIdentity.js';
|
|
5
|
+
import { checkpointQueueReadingOf } from './hitlBridge.js';
|
|
6
|
+
import { pendingRowIsOwnedByThisSession } from './parkOwnership.js';
|
|
7
|
+
function ownNonEmpty(o, key) {
|
|
8
|
+
const r = slotReadOf(o, key);
|
|
9
|
+
return r.presence === 'present' && typeof r.value === 'string' && r.value !== '' ? r.value : undefined;
|
|
10
|
+
}
|
|
11
|
+
function memberOf(row, rowVerdict) {
|
|
12
|
+
const taskId = ownNonEmpty(row, 'taskId');
|
|
13
|
+
const callId = ownNonEmpty(row, 'toolCallId') ?? ownNonEmpty(row, 'boundCallId');
|
|
14
|
+
const rowKey = callId !== undefined || taskId !== undefined ? approvalCallKey(callId, taskId ?? '') : undefined;
|
|
15
|
+
const toolName = ownNonEmpty(row, 'toolName');
|
|
16
|
+
const deadline = checkpointDeadlineStateOf(row);
|
|
17
|
+
return Object.freeze({
|
|
18
|
+
rowVerdict,
|
|
19
|
+
...(rowKey !== undefined ? { rowKey } : {}),
|
|
20
|
+
...(taskId !== undefined ? { taskId } : {}),
|
|
21
|
+
...(toolName !== undefined ? { toolName } : {}),
|
|
22
|
+
...(deadline !== 'unknown' ? { rowDeadline: deadline } : {}),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export function parkedUnresumableRowsOf(listed, deps) {
|
|
26
|
+
if (typeof listed !== 'object' || listed === null || Array.isArray(listed)) {
|
|
27
|
+
throw new Error('approvals.list answered without a readable body — the rows this engine cannot continue are unknown');
|
|
28
|
+
}
|
|
29
|
+
const pending = listed.pending;
|
|
30
|
+
if (!Array.isArray(pending)) {
|
|
31
|
+
throw new Error('approvals.list answered without a readable `pending` array — the rows this engine cannot continue are unknown');
|
|
32
|
+
}
|
|
33
|
+
const out = [];
|
|
34
|
+
for (const row of pending) {
|
|
35
|
+
const member = parkedMemberOf(row, deps);
|
|
36
|
+
if (member !== undefined)
|
|
37
|
+
out.push(member);
|
|
38
|
+
}
|
|
39
|
+
return Object.freeze(out);
|
|
40
|
+
}
|
|
41
|
+
function parkedMemberOf(row, deps) {
|
|
42
|
+
try {
|
|
43
|
+
if (typeof row !== 'object' || row === null)
|
|
44
|
+
return undefined;
|
|
45
|
+
const reading = checkpointQueueReadingOf(row);
|
|
46
|
+
if (reading === undefined)
|
|
47
|
+
return undefined;
|
|
48
|
+
if (reading.foreign !== null && reading.foreign !== QUEUE_ROW_FAMILY_UNREADABLE_GATE)
|
|
49
|
+
return undefined;
|
|
50
|
+
const bar = checkpointRowBarOf(reading.r);
|
|
51
|
+
if (bar === undefined)
|
|
52
|
+
return undefined;
|
|
53
|
+
if (!pendingRowIsOwnedByThisSession(reading.r, deps))
|
|
54
|
+
return undefined;
|
|
55
|
+
return memberOf(reading.r, bar);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const UNREADABLE_BAR = Object.freeze({ kind: 'unreadable' });
|
|
62
|
+
export function parkedUnresumableLine(row, lang) {
|
|
63
|
+
let bar = UNREADABLE_BAR;
|
|
64
|
+
let state = 'unknown';
|
|
65
|
+
try {
|
|
66
|
+
if (typeof row === 'object' && row !== null) {
|
|
67
|
+
const v = slotReadOf(row, 'rowVerdict');
|
|
68
|
+
if (v.presence === 'present')
|
|
69
|
+
bar = checkpointRowBarOf({ rowVerdict: v.value }) ?? UNREADABLE_BAR;
|
|
70
|
+
const d = slotReadOf(row, 'rowDeadline');
|
|
71
|
+
if (d.presence === 'present' && (d.value === 'armed' || d.value === 'none'))
|
|
72
|
+
state = d.value;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
bar = UNREADABLE_BAR;
|
|
77
|
+
state = 'unknown';
|
|
78
|
+
}
|
|
79
|
+
return `${checkpointRowBarSentence(bar, lang)} · ${rowBarWayOutContent(bar, state, lang)}`;
|
|
80
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PermissionRuleValue } from '@sema-agent/agent-types';
|
|
2
|
+
export declare function isWholeToolRuleValue(value: PermissionRuleValue): boolean;
|
|
3
|
+
export type AllowRuleScope = 'whole_tool' | 'content' | 'unreadable';
|
|
4
|
+
export declare function allowRuleScopeOf(value: object | null | undefined): AllowRuleScope;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { readOwnDataValue } from '../ownKey.js';
|
|
2
|
+
import { inSlotReadOf } from '../wireFailureShape.js';
|
|
3
|
+
export function isWholeToolRuleValue(value) {
|
|
4
|
+
return value.ruleContent === undefined || value.ruleContent === '';
|
|
5
|
+
}
|
|
6
|
+
export function allowRuleScopeOf(value) {
|
|
7
|
+
try {
|
|
8
|
+
if (typeof value !== 'object' || value === null)
|
|
9
|
+
return 'unreadable';
|
|
10
|
+
const toolName = readOwnDataValue(value, 'toolName');
|
|
11
|
+
if (typeof toolName !== 'string' || toolName === '')
|
|
12
|
+
return 'unreadable';
|
|
13
|
+
let ruleContent;
|
|
14
|
+
const slot = inSlotReadOf(value, 'ruleContent');
|
|
15
|
+
if (slot.state === 'present') {
|
|
16
|
+
const raw = slot.value;
|
|
17
|
+
if (raw !== undefined) {
|
|
18
|
+
if (typeof raw !== 'string' || raw === '')
|
|
19
|
+
return 'unreadable';
|
|
20
|
+
ruleContent = raw;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else if (slot.state !== 'absent')
|
|
24
|
+
return 'unreadable';
|
|
25
|
+
const snapshot = Object.freeze(Object.assign(Object.create(null), ruleContent !== undefined ? { toolName, ruleContent } : { toolName }));
|
|
26
|
+
return isWholeToolRuleValue(snapshot) ? 'whole_tool' : 'content';
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return 'unreadable';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -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';
|
|
@@ -51,7 +51,7 @@ function ruleKeyOfRow(row) {
|
|
|
51
51
|
const scope = keyObj === undefined ? undefined : ownNonEmpty(keyObj, 'scope');
|
|
52
52
|
return behavior !== undefined && rule !== undefined && scope !== undefined ? Object.freeze({ behavior, rule, scope }) : undefined;
|
|
53
53
|
}
|
|
54
|
-
function
|
|
54
|
+
function unsettledRowOf(row) {
|
|
55
55
|
const key = ruleKeyOfRow(row);
|
|
56
56
|
const reason = ownNonEmpty(row, 'reason');
|
|
57
57
|
const d = slotReadOf(row, 'detail');
|
|
@@ -62,10 +62,6 @@ function indeterminateRowOf(row) {
|
|
|
62
62
|
...(shown !== undefined && shown.trim() !== '' ? { detail: shown } : {}),
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
|
-
function refusedRowOf(row) {
|
|
66
|
-
const key = ruleKeyOfRow(row);
|
|
67
|
-
return Object.freeze(key !== undefined ? { key } : {});
|
|
68
|
-
}
|
|
69
65
|
const RECEIPT_ROW_ARMS = {
|
|
70
66
|
persisted: (acc) => {
|
|
71
67
|
acc.persisted += 1;
|
|
@@ -74,10 +70,10 @@ const RECEIPT_ROW_ARMS = {
|
|
|
74
70
|
acc.deduped += 1;
|
|
75
71
|
},
|
|
76
72
|
refused: (acc, row) => {
|
|
77
|
-
appendOwnElement(acc.refused,
|
|
73
|
+
appendOwnElement(acc.refused, unsettledRowOf(row));
|
|
78
74
|
},
|
|
79
75
|
indeterminate: (acc, row) => {
|
|
80
|
-
appendOwnElement(acc.indeterminate,
|
|
76
|
+
appendOwnElement(acc.indeterminate, unsettledRowOf(row));
|
|
81
77
|
},
|
|
82
78
|
};
|
|
83
79
|
function receiptCountsOf(rows) {
|
|
@@ -333,9 +329,14 @@ export function revokeTargetFromPersistedRule(rule, opts) {
|
|
|
333
329
|
};
|
|
334
330
|
}
|
|
335
331
|
function readPrincipalOverride(carrier) {
|
|
336
|
-
if (carrier === null || typeof carrier !== 'object'
|
|
332
|
+
if (carrier === null || typeof carrier !== 'object')
|
|
337
333
|
return { ok: true };
|
|
338
|
-
const
|
|
334
|
+
const slot = inValueOf(carrier, 'principal');
|
|
335
|
+
if (slot.state === 'absent')
|
|
336
|
+
return { ok: true };
|
|
337
|
+
if (slot.state === 'unproven')
|
|
338
|
+
return { ok: false };
|
|
339
|
+
const raw = slot.value;
|
|
339
340
|
if (typeof raw !== 'string' || raw.trim().length === 0)
|
|
340
341
|
return { ok: false };
|
|
341
342
|
return { ok: true, principal: raw };
|
|
@@ -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 {
|
|
@@ -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
|
});
|
|
@@ -12,6 +12,7 @@ import { type ApprovalMandateWord } from '../gateVocabulary.js';
|
|
|
12
12
|
import type { ToolPermissionRequest } from '../seatContract.js';
|
|
13
13
|
import { type ApprovalDecidedByReading } from '../approvalDecidedByCapability.js';
|
|
14
14
|
import { type PolicyDenyCause } from './policyDenyCause.js';
|
|
15
|
+
import { type ApprovalRequestFrameReading, type ApprovalRequestFrameUnreadableWhy } from './approvalRequestFrameReading.js';
|
|
15
16
|
import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS } from '@sema-agent/sdk';
|
|
16
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';
|
|
17
18
|
export declare function toolNameIsFsWrite(name: string): boolean;
|
|
@@ -138,6 +139,7 @@ export interface ApprovalCardRequest {
|
|
|
138
139
|
priorCardsForCall?: readonly ApprovalPriorCard[];
|
|
139
140
|
message?: string;
|
|
140
141
|
cardPayloadUnreadable?: true;
|
|
142
|
+
cardPayloadUnreadableWhy?: ApprovalRequestFrameUnreadableWhy;
|
|
141
143
|
supersedes?: ApprovalCardSupersedes;
|
|
142
144
|
parkRow?: ApprovalCardParkRow;
|
|
143
145
|
}
|
|
@@ -283,7 +285,7 @@ export declare function readDenialLimitFallback(v: unknown): DenialLimitFallback
|
|
|
283
285
|
export declare function readRuleOffers(v: unknown): RuleOfferReading[] | undefined;
|
|
284
286
|
export declare function readRuleOfferSupply(offers: unknown): RuleOfferReading[] | undefined;
|
|
285
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'>;
|
|
286
|
-
export type ApprovalCardFacts = ApprovalCardV1Facts & Pick<ApprovalCardRequest, 'argsRewritten' | 'ruleOffers' | 'probeReason' | 'mandated' | 'mandate' | 'readRootCandidate' | 'origin' | 'boundGrants' | 'classifierNoRuling' | 'allowSessionCarried' | 'cardPayloadUnreadable'>;
|
|
288
|
+
export type ApprovalCardFacts = ApprovalCardV1Facts & Pick<ApprovalCardRequest, 'argsRewritten' | 'ruleOffers' | 'probeReason' | 'mandated' | 'mandate' | 'readRootCandidate' | 'origin' | 'boundGrants' | 'classifierNoRuling' | 'allowSessionCarried' | 'cardPayloadUnreadable' | 'cardPayloadUnreadableWhy'>;
|
|
287
289
|
export interface ApprovalCardFrameFactsOptions {
|
|
288
290
|
readonly streamArgs?: object;
|
|
289
291
|
readonly argsUnavailable?: true;
|
|
@@ -291,7 +293,7 @@ export interface ApprovalCardFrameFactsOptions {
|
|
|
291
293
|
export declare function approvalCardFactsOfV1(card: object | null | undefined): Readonly<ApprovalCardV1Facts> | undefined;
|
|
292
294
|
export declare function approvalCardFactsOfV1Frame(frame: object | null | undefined): Readonly<ApprovalCardFacts> | undefined;
|
|
293
295
|
export declare function approvalCardFactsOfFrame(frame: object | null | undefined, opts?: ApprovalCardFrameFactsOptions | null): Readonly<ApprovalCardFacts> | undefined;
|
|
294
|
-
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;
|
|
295
297
|
export interface ToolApprovalFrameLaneOpts {
|
|
296
298
|
approvalDecisionNoteCapable?: boolean;
|
|
297
299
|
respondFreeFormRulesCapable?: boolean;
|
|
@@ -304,6 +306,10 @@ export declare function surfaceToolApprovalFrameAndRespond(frame: ToolApprovalFr
|
|
|
304
306
|
readonly taskId?: string;
|
|
305
307
|
readonly sessionId?: string;
|
|
306
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>;
|
|
307
313
|
export interface ApprovalHolderIdentity {
|
|
308
314
|
readonly approvalId?: string;
|
|
309
315
|
readonly taskId?: string;
|
|
@@ -30,13 +30,14 @@ import { isApprovalMandateWord } from '../gateVocabulary.js';
|
|
|
30
30
|
import { approvalDecidedByAdmitted } from '../approvalDecidedByCapability.js';
|
|
31
31
|
import { decideFailureNote } from '../decideFailureNote.js';
|
|
32
32
|
import { readPolicyDenyCause } from './policyDenyCause.js';
|
|
33
|
-
import { slotPresenceOf, wireFailureTextsOf } from '../wireFailureShape.js';
|
|
33
|
+
import { inValueOf, slotPresenceOf, wireFailureTextsOf } from '../wireFailureShape.js';
|
|
34
34
|
import { APPROVAL_LIVE_FACE_KEYS, approvalLiveFaceOf, hasOwnStrictTrue } from './approvalLiveFace.js';
|
|
35
|
+
import { approvalFrameUnreadableWhyOf, approvalRequestFrameReadingThrowing, } from './approvalRequestFrameReading.js';
|
|
35
36
|
import { subagentSourceSessionOf } from './subagentSource.js';
|
|
36
37
|
import { isPlainRecord } from '../jsonFaithful.js';
|
|
37
38
|
import { DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED } from '../engineErrorCodes.js';
|
|
38
39
|
import { readDecideReceipt } from '../decideReceipt.js';
|
|
39
|
-
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';
|
|
40
41
|
export function toolNameIsFsWrite(name) {
|
|
41
42
|
const n = name.replace(/[\s_-]+/g, '').toLowerCase();
|
|
42
43
|
return (n === 'write' || n === 'filewrite' || n === 'edit' || n === 'fileedit' || n === 'multiedit' || n === 'notebookedit');
|
|
@@ -493,6 +494,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
493
494
|
const rowArgsGap = reading.from !== 'none' ? undefined : reading.shape === 'absent' ? 'absent' : reading.shape === 'size_marker' ? 'truncated' : undefined;
|
|
494
495
|
const args = reading.from !== 'none' ? reading.args : rowArgsGap !== undefined ? {} : reading.recorded;
|
|
495
496
|
const argsRewritten = reading.from === 'recorded' && reading.rewritten;
|
|
497
|
+
const argsFromModelCall = reading.from === 'stream';
|
|
496
498
|
if (typeof args !== 'object' || args === null) {
|
|
497
499
|
return { kind: 'not_sent', ...at, cause: 'no_input', detail: 'gate has no tool input payload' };
|
|
498
500
|
}
|
|
@@ -516,6 +518,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
516
518
|
}
|
|
517
519
|
: {}),
|
|
518
520
|
...(argsRewritten ? { argsRewritten: true, wireNote: ARGS_REWRITTEN_NOTE } : {}),
|
|
521
|
+
...(argsFromModelCall ? { argsUnavailable: true, wireNote: renderMessage(msg('approval.park.argsFromModelCall')) } : {}),
|
|
519
522
|
...(pending.governanceForced === true ? { governanceForced: true } : {}),
|
|
520
523
|
...(readRequiresRealApproval(pending) ? { requiresRealApproval: true } : {}),
|
|
521
524
|
...approvalLiveFaceOf(pending).facts,
|
|
@@ -541,8 +544,8 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
|
|
|
541
544
|
});
|
|
542
545
|
const card = await surfaceCallTrackedCard(gatedCallId, undefined, ledgerSlot, cardRequest);
|
|
543
546
|
hold.phase = 'respond';
|
|
544
|
-
if (rowArgsGap !== undefined && card.kind === 'allow' && card.updatedInput !== undefined) {
|
|
545
|
-
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)`);
|
|
546
549
|
surfaceEditRefusedOnBlindAsk();
|
|
547
550
|
return { kind: 'not_sent', ...at, cause: 'edit_refused', detail: PARK_EDIT_REFUSED_REASON };
|
|
548
551
|
}
|
|
@@ -685,8 +688,11 @@ function readReadRootCandidate(v) {
|
|
|
685
688
|
const o = v;
|
|
686
689
|
if (typeof o.dir !== 'string' || o.dir.length === 0 || o.clearsThisAsk !== true)
|
|
687
690
|
return undefined;
|
|
688
|
-
|
|
689
|
-
|
|
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;
|
|
690
696
|
return { dir: o.dir, clearsThisAsk: true };
|
|
691
697
|
}
|
|
692
698
|
export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
|
|
@@ -1679,7 +1685,7 @@ function v1Bit(stamp) {
|
|
|
1679
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, " +
|
|
1680
1686
|
'so you are deciding without seeing them; deny it if you are not sure what it will do. ' +
|
|
1681
1687
|
'Edits are not accepted on this card: there is no original input to edit';
|
|
1682
|
-
function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
|
|
1688
|
+
function cardFactsOf(carrier, leg, opts, liveFacts, approvalId, payloadWhy) {
|
|
1683
1689
|
const c = carrier;
|
|
1684
1690
|
const full = leg !== 'generic';
|
|
1685
1691
|
const live = leg === 'frame' ? carrier : leg === 'v1' ? liveFacts : undefined;
|
|
@@ -1865,8 +1871,11 @@ function cardFactsOf(carrier, leg, opts, liveFacts, approvalId) {
|
|
|
1865
1871
|
if (typeof msg === 'string' && msg.trim() !== '')
|
|
1866
1872
|
out.message = msg;
|
|
1867
1873
|
});
|
|
1868
|
-
if (leg === 'generic')
|
|
1874
|
+
if (leg === 'generic') {
|
|
1869
1875
|
out.cardPayloadUnreadable = true;
|
|
1876
|
+
if (payloadWhy !== undefined)
|
|
1877
|
+
out.cardPayloadUnreadableWhy = payloadWhy;
|
|
1878
|
+
}
|
|
1870
1879
|
if (sessionAllowCarried(leg, approvalId))
|
|
1871
1880
|
out.allowSessionCarried = true;
|
|
1872
1881
|
out.grantBinding = readApprovalGrantBinding(carrier);
|
|
@@ -1898,15 +1907,26 @@ export function approvalCardFactsOfFrame(frame, opts) {
|
|
|
1898
1907
|
return undefined;
|
|
1899
1908
|
return Object.freeze(cardFactsOf(frame, 'frame', opts));
|
|
1900
1909
|
}
|
|
1901
|
-
export function approvalCardFactsOfGeneric(card) {
|
|
1910
|
+
export function approvalCardFactsOfGeneric(card, reading) {
|
|
1902
1911
|
if (typeof card !== 'object' || card === null)
|
|
1903
1912
|
return undefined;
|
|
1904
|
-
return Object.freeze(cardFactsOf(card, 'generic'));
|
|
1913
|
+
return Object.freeze(cardFactsOf(card, 'generic', null, undefined, undefined, approvalFrameUnreadableWhyOf(reading)));
|
|
1905
1914
|
}
|
|
1906
1915
|
const MAX_RESPOND_NOTE_CHARS = 2048;
|
|
1907
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) {
|
|
1908
1927
|
const receivedAtMs = Date.now();
|
|
1909
|
-
|
|
1928
|
+
if (typeof approvalId !== 'string' || approvalId === '')
|
|
1929
|
+
return approvalIdUnreadableRefusal();
|
|
1910
1930
|
const carriers = openingFrameCarriersOf(frame);
|
|
1911
1931
|
const entry = { frame, carriers, approvalId, identity: liveCardIdentityOf(approvalId, frame, carriers, run), respond, streamArgs, signal, lane, receivedAtMs };
|
|
1912
1932
|
return enterLiveCard(entry);
|
|
@@ -1916,9 +1936,10 @@ function openingFrameCarriersOf(frame) {
|
|
|
1916
1936
|
return { body: frame, live: frame, leg: 'frame' };
|
|
1917
1937
|
const card = frame.card;
|
|
1918
1938
|
const pinned = Object.create(frame, { card: { value: card, enumerable: true } });
|
|
1919
|
-
|
|
1939
|
+
const reading = approvalRequestFrameReadingThrowing(pinned);
|
|
1940
|
+
if (reading.v1)
|
|
1920
1941
|
return { body: pinned.card, live: frame, leg: 'v1' };
|
|
1921
|
-
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 };
|
|
1922
1943
|
}
|
|
1923
1944
|
function enterLiveCard(e) {
|
|
1924
1945
|
const { approvalId, signal } = e;
|
|
@@ -2016,7 +2037,7 @@ async function presentToolApprovalFrameAndRespond(frame, carriers, approvalId, r
|
|
|
2016
2037
|
const bodyToolCallId = carriers.body.toolCallId;
|
|
2017
2038
|
const frameToolCallId = typeof bodyToolCallId === 'string' && bodyToolCallId !== '' ? bodyToolCallId : undefined;
|
|
2018
2039
|
const decidedByReading = decidedByReadingSnapshotOf(lane);
|
|
2019
|
-
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);
|
|
2020
2041
|
const argsNotRealInput = facts.argsUnavailable === true;
|
|
2021
2042
|
const ruleOffers = facts.ruleOffers;
|
|
2022
2043
|
if (argsNotRealInput && lane?.argsUnavailable !== true && facts.wireNote !== undefined) {
|
package/dist/hooksWireCaps.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { engineCapNestedTrue, engineCapState, engineCapString, engineCapValue } from './engineCapsCache.js';
|
|
2
2
|
import { hooksReaderNotReadKeys } from './hooksReaderGenerations.js';
|
|
3
3
|
import { msg, renderMessage } from './i18n/translate.js';
|
|
4
|
-
import { capForDisplay
|
|
4
|
+
import { capForDisplay } from './fleetTaskDesc.js';
|
|
5
5
|
import { hostLog } from './host.js';
|
|
6
6
|
import { faultText } from './hostCallbackGuard.js';
|
|
7
7
|
import { HostSettingsSourceShapeError, MANAGED_READING_DISPOSITIONS, mergedBooleanOf, nonManagedLayerDown, readHostSettingsOnce } from './hostSettingsSource.js';
|
|
@@ -555,8 +555,9 @@ export function fleetHookFailureNoticeCapable(baseUrl) {
|
|
|
555
555
|
export const HOOK_FAILURE_WARN_PREFIX = 'Hook error';
|
|
556
556
|
export function hookFailureNoticeText(n) {
|
|
557
557
|
const code = n.exitCode !== undefined ? `exit ${n.exitCode}` : n.reason;
|
|
558
|
-
const
|
|
559
|
-
const
|
|
558
|
+
const fold = (s) => s.replace(/\s+/g, ' ').trim();
|
|
559
|
+
const name = fold(n.hookName);
|
|
560
|
+
const tail = n.stderr !== undefined ? `: ${fold(n.stderr)}` : '';
|
|
560
561
|
const line = `${HOOK_FAILURE_WARN_PREFIX}: ${name} (${code})${tail}`;
|
|
561
562
|
return capForDisplay(line, MAX_HOOK_NOTICE_TEXT_CHARS);
|
|
562
563
|
}
|