@sema-agent/client-core 0.103.0 → 0.104.1
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 +85 -0
- package/README.md +18 -14
- package/dist/adapter/downstream/eventToSdkMessage.js +2 -0
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +0 -1
- package/dist/adapter/downstream/terminalToSdkResult.js +3 -1
- package/dist/agentSession/engineAgentRegistryRead.js +3 -0
- package/dist/coreValuePorts.d.ts +3 -1
- package/dist/coreValuePorts.js +5 -0
- package/dist/deviceRebind.d.ts +17 -4
- package/dist/deviceRebind.js +43 -14
- package/dist/engineAgentAbsence.d.ts +1 -0
- package/dist/executionPlacementWords.d.ts +3 -0
- package/dist/executionPlacementWords.js +2 -0
- package/dist/generated/engineFactTables.d.ts +3 -2
- package/dist/generated/engineFactTables.js +17 -1
- package/dist/generated/engineNoticeTables.js +12 -0
- package/dist/hitl/automaticAnswerVerdict.js +47 -11
- package/dist/hitl/livePendingAsk.d.ts +2 -1
- package/dist/hitl/livePendingAsk.js +7 -1
- package/dist/hitl/sessionPolicyDeliverable.js +31 -5
- package/dist/hitl/toolApprovalWire.d.ts +5 -4
- package/dist/hitl/toolApprovalWire.js +215 -47
- package/dist/host.d.ts +0 -3
- package/dist/hostTurnSettings.js +3 -1
- package/dist/humanTurn.js +2 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +1 -0
- package/dist/jsonFaithful.js +5 -3
- package/dist/mcpLiveness.d.ts +1 -1
- package/dist/mcpWireCaps.js +1 -1
- package/dist/printModelStatus.d.ts +1 -0
- package/dist/printModelStatus.js +6 -2
- package/dist/retryStatus.d.ts +8 -1
- package/dist/retryStatus.js +13 -4
- package/dist/ruleCompileVerdict.d.ts +1 -0
- package/dist/ruleCompileVerdict.js +3 -1
- package/dist/seatContract.d.ts +7 -7
- package/dist/seatContract.js +39 -10
- package/dist/sessionRowTag.d.ts +24 -0
- package/dist/sessionRowTag.js +77 -0
- package/dist/steering.d.ts +1 -0
- package/dist/steering.js +34 -26
- package/dist/systemReminderTag.js +14 -4
- package/docs/INTEGRATION-CLIENTS.md +346 -11
- package/package.json +5 -5
|
@@ -287,6 +287,7 @@ function projectEvent(ev, ctx) {
|
|
|
287
287
|
const sleptMsRaw = guardedRead(() => readOwnDataFiniteNumber(stWait, 'sleptMs'));
|
|
288
288
|
const sleptMs = sleptMsRaw !== undefined && sleptMsRaw >= 0 ? sleptMsRaw : undefined;
|
|
289
289
|
const waitSegment = readFrameStringKey(stWait, 'waitSegment');
|
|
290
|
+
const seat = readFrameStringKey(ev, 'seat');
|
|
290
291
|
return projected(stamp(ctx, armBody({
|
|
291
292
|
type: 'retry_status',
|
|
292
293
|
phase: ev.phase,
|
|
@@ -304,6 +305,7 @@ function projectEvent(ev, ctx) {
|
|
|
304
305
|
...(providerConditionSource !== undefined ? { providerConditionSource } : {}),
|
|
305
306
|
...(sleptMs !== undefined ? { sleptMs } : {}),
|
|
306
307
|
...(waitSegment !== undefined ? { waitSegment } : {}),
|
|
308
|
+
...(seat !== undefined ? { seat } : {}),
|
|
307
309
|
...(typeof ev.eventId === 'string' ? { eventId: ev.eventId } : {}),
|
|
308
310
|
...(typeof ev.parentToolCallId === 'string' ? { parentToolCallId: ev.parentToolCallId } : {}),
|
|
309
311
|
})));
|
|
@@ -61,7 +61,6 @@ export interface PermissionDenialParts {
|
|
|
61
61
|
export interface SemaCostBreakdown {
|
|
62
62
|
readonly llmRootMicroUsd?: number;
|
|
63
63
|
readonly nestedSubagentMicroUsd?: number;
|
|
64
|
-
readonly memoryConsolidationMicroUsd?: number;
|
|
65
64
|
readonly suggestionsMicroUsd?: number;
|
|
66
65
|
readonly compactionMicroUsd?: number;
|
|
67
66
|
readonly [k: string]: number | undefined;
|
|
@@ -564,6 +564,8 @@ function printArmReadingOf(input) {
|
|
|
564
564
|
const stop_reason = printArmStopReasonOf(lastRow);
|
|
565
565
|
if (kind === 'completed')
|
|
566
566
|
return { arm: Object.freeze({ subtype: 'success', is_error: false, stop_reason }) };
|
|
567
|
+
if (kind === 'paused')
|
|
568
|
+
return { arm: Object.freeze({ subtype: 'error_during_execution', is_error: true, stop_reason }) };
|
|
567
569
|
if (kind === 'failed') {
|
|
568
570
|
const code = readOwnDataValue(terminal, 'code');
|
|
569
571
|
const limit = typeof code === 'string' ? resultLimitRowOfCode(code) : undefined;
|
|
@@ -644,7 +646,6 @@ function errorResult(ctx, parts) {
|
|
|
644
646
|
...('limit' in arm && arm.limit !== undefined ? { _sema_limit: arm.limit } : {}),
|
|
645
647
|
...(parts.wayOut !== undefined ? { _sema_wayOut: wayOutOnFrame(parts.wayOut) } : {}),
|
|
646
648
|
...(parts.codedDetail !== undefined ? { _sema_coded_detail: parts.codedDetail } : {}),
|
|
647
|
-
...(parts.errorCode !== undefined && parts.errorCode.length > 0 && errorsStateCode(errors[0], parts.errorCode) ? { _sema_error_code_in_text: true } : {}),
|
|
648
649
|
};
|
|
649
650
|
if (arm.subtype === 'success') {
|
|
650
651
|
return stamp(ctx, {
|
|
@@ -665,6 +666,7 @@ function errorResult(ctx, parts) {
|
|
|
665
666
|
...head,
|
|
666
667
|
errors,
|
|
667
668
|
...tail,
|
|
669
|
+
...(parts.errorCode !== undefined && parts.errorCode.length > 0 && errorsStateCode(errors[0], parts.errorCode) ? { _sema_error_code_in_text: true } : {}),
|
|
668
670
|
});
|
|
669
671
|
}
|
|
670
672
|
function errorsStateCode(first, code) {
|
|
@@ -2,6 +2,7 @@ import { errCodes } from '../controlRouter.js';
|
|
|
2
2
|
import { hostLog } from '../host.js';
|
|
3
3
|
import { isSessionIdPathSegment } from '../sessionIdSegment.js';
|
|
4
4
|
import { engineCapNestedValue } from '../engineCapsCache.js';
|
|
5
|
+
import { guardedRead, readOwnDataValue } from '../ownKey.js';
|
|
5
6
|
const unavailable = (why) => ({
|
|
6
7
|
kind: 'unavailable',
|
|
7
8
|
why,
|
|
@@ -75,12 +76,14 @@ function readRow(v) {
|
|
|
75
76
|
return undefined;
|
|
76
77
|
const description = Object.hasOwn(o, 'description') ? o.description : undefined;
|
|
77
78
|
const createdAt = Object.hasOwn(o, 'createdAt') ? o.createdAt : undefined;
|
|
79
|
+
const childSessionId = type === 'background_agent' ? guardedRead(() => readOwnDataValue(o, 'sessionId')) : undefined;
|
|
78
80
|
return {
|
|
79
81
|
id,
|
|
80
82
|
type,
|
|
81
83
|
status,
|
|
82
84
|
...(typeof description === 'string' && description.length > 0 ? { description } : {}),
|
|
83
85
|
...(typeof createdAt === 'number' && Number.isFinite(createdAt) ? { createdAt } : {}),
|
|
86
|
+
...(typeof childSessionId === 'string' && childSessionId.length > 0 ? { sessionId: childSessionId } : {}),
|
|
84
87
|
};
|
|
85
88
|
}
|
|
86
89
|
export async function readEngineAgentRegistry(client, sessionId, capsBaseUrl, opts) {
|
package/dist/coreValuePorts.d.ts
CHANGED
|
@@ -149,8 +149,9 @@ export interface CoreValuePorts {
|
|
|
149
149
|
readMcpToolAxes(declared: {} | null | undefined): McpToolAxesReadView;
|
|
150
150
|
ANTHROPIC_DEFAULT_BASE_URL: string;
|
|
151
151
|
readToolFaces(declared: {} | null | undefined): McpToolFacesReadView;
|
|
152
|
+
ruleNameCovers: (ruleName: string, toolName: string) => boolean;
|
|
152
153
|
}
|
|
153
|
-
export declare const CORE_VALUE_PORT_NAMES: readonly ["resolveAutonomousLoopPrompt", "loosenReasons", "combinePolicies", "createAllowDenyPolicy", "MCP_NAMESPACE", "protocolOf", "ruleToolGrammarOf", "validatePermissionRules", "mintNamespacePrefix", "compileAllowList", "routeKeyOf", "joinRequestUrl", "resolveRouteCredential", "adjudicateModelRoute", "routePairingStatus", "judgeRuleToolName", "readRuleEntry", "readMcpToolAxes", "ANTHROPIC_DEFAULT_BASE_URL", "readToolFaces"];
|
|
154
|
+
export declare const CORE_VALUE_PORT_NAMES: readonly ["resolveAutonomousLoopPrompt", "loosenReasons", "combinePolicies", "createAllowDenyPolicy", "MCP_NAMESPACE", "protocolOf", "ruleToolGrammarOf", "validatePermissionRules", "mintNamespacePrefix", "compileAllowList", "routeKeyOf", "joinRequestUrl", "resolveRouteCredential", "adjudicateModelRoute", "routePairingStatus", "judgeRuleToolName", "readRuleEntry", "readMcpToolAxes", "ANTHROPIC_DEFAULT_BASE_URL", "readToolFaces", "ruleNameCovers"];
|
|
154
155
|
export type CoreValuePortName = (typeof CORE_VALUE_PORT_NAMES)[number];
|
|
155
156
|
export declare function installCoreValuePorts(ports: Partial<CoreValuePorts> | null): () => void;
|
|
156
157
|
export declare function hasCoreValuePorts(): boolean;
|
|
@@ -180,3 +181,4 @@ export declare function readRuleEntry(raw: {} | null | undefined, behavior: 'all
|
|
|
180
181
|
export declare function readMcpToolAxes(declared: {} | null | undefined): McpToolAxesReadView | undefined;
|
|
181
182
|
export declare function anthropicDefaultBaseUrl(): string | undefined;
|
|
182
183
|
export declare function readToolFaces(declared: {} | null | undefined): McpToolFacesReadView | undefined;
|
|
184
|
+
export declare function ruleNameCovers(ruleName: string, toolName: string): boolean | undefined;
|
package/dist/coreValuePorts.js
CHANGED
|
@@ -19,6 +19,7 @@ export const CORE_VALUE_PORT_NAMES = Object.freeze([
|
|
|
19
19
|
'readMcpToolAxes',
|
|
20
20
|
'ANTHROPIC_DEFAULT_BASE_URL',
|
|
21
21
|
'readToolFaces',
|
|
22
|
+
'ruleNameCovers',
|
|
22
23
|
]);
|
|
23
24
|
let installed = null;
|
|
24
25
|
export function installCoreValuePorts(ports) {
|
|
@@ -118,3 +119,7 @@ export function readToolFaces(declared) {
|
|
|
118
119
|
const fn = port('readToolFaces');
|
|
119
120
|
return fn === undefined ? undefined : fn(declared);
|
|
120
121
|
}
|
|
122
|
+
export function ruleNameCovers(ruleName, toolName) {
|
|
123
|
+
const fn = port('ruleNameCovers');
|
|
124
|
+
return fn === undefined ? undefined : fn(ruleName, toolName);
|
|
125
|
+
}
|
package/dist/deviceRebind.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { AgentClient, DeviceEnrollRequest } from '@sema-agent/sdk';
|
|
2
|
+
import { type ExecutionPlacementRole } from './executionPlacementWords.js';
|
|
2
3
|
export type DeviceListVerb = Pick<AgentClient['devices'], 'list'>;
|
|
3
|
-
export
|
|
4
|
+
export interface SessionExecutionPlacementVerb {
|
|
5
|
+
executionPlacement(sessionId: string, opts?: {
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
}): Promise<object>;
|
|
8
|
+
}
|
|
4
9
|
export type DeviceRebindVerb = Pick<AgentClient['devices'], 'rebind'>;
|
|
5
10
|
export type DeviceIssueEnrollTokenVerb = Pick<AgentClient['devices'], 'issueEnrollToken'>;
|
|
6
11
|
export type DeviceEnrollVerb = Pick<AgentClient['devices'], 'enroll'>;
|
|
@@ -14,7 +19,6 @@ export interface DeviceRosterRow {
|
|
|
14
19
|
export interface DeviceBindingReading {
|
|
15
20
|
readonly deviceId: string;
|
|
16
21
|
readonly rev: number;
|
|
17
|
-
readonly boundAt?: string;
|
|
18
22
|
}
|
|
19
23
|
export interface DeviceRefused {
|
|
20
24
|
readonly kind: 'refused';
|
|
@@ -37,6 +41,10 @@ export interface DeviceUnreadable {
|
|
|
37
41
|
export interface DeviceUnarmed {
|
|
38
42
|
readonly kind: 'unarmed';
|
|
39
43
|
}
|
|
44
|
+
export interface DeviceFaceUnsupported {
|
|
45
|
+
readonly kind: 'unsupported';
|
|
46
|
+
readonly reason: 'route' | 'capability';
|
|
47
|
+
}
|
|
40
48
|
export type DeviceListOutcome = {
|
|
41
49
|
readonly kind: 'ok';
|
|
42
50
|
readonly devices: readonly DeviceRosterRow[];
|
|
@@ -46,9 +54,12 @@ export type DeviceSessionBindingOutcome = {
|
|
|
46
54
|
readonly kind: 'ok';
|
|
47
55
|
readonly rootSessionId: string;
|
|
48
56
|
readonly boundDevice: DeviceBindingReading;
|
|
57
|
+
} | {
|
|
58
|
+
readonly kind: 'unbound';
|
|
59
|
+
readonly role: ExecutionPlacementRole;
|
|
49
60
|
} | {
|
|
50
61
|
readonly kind: 'not-found';
|
|
51
|
-
} |
|
|
62
|
+
} | DeviceFaceUnsupported | DeviceUnreadable | DeviceRefused | DeviceTransport | DeviceUnarmed;
|
|
52
63
|
export interface DeviceRebindInput {
|
|
53
64
|
readonly rootSessionId: string;
|
|
54
65
|
readonly toDeviceId: string;
|
|
@@ -69,6 +80,8 @@ export type DeviceRebindOutcome = {
|
|
|
69
80
|
} | {
|
|
70
81
|
readonly kind: 'active-run';
|
|
71
82
|
readonly activeTaskId?: string;
|
|
83
|
+
readonly children?: readonly string[];
|
|
84
|
+
readonly retirePath?: string;
|
|
72
85
|
} | {
|
|
73
86
|
readonly kind: 'rev-conflict';
|
|
74
87
|
readonly currentRev?: number;
|
|
@@ -79,7 +92,7 @@ export type DeviceRebindReconcileVerdict = 'landed' | 'already-there' | 'unchang
|
|
|
79
92
|
export declare function listDevices(devices: DeviceListVerb | null | undefined, opts?: {
|
|
80
93
|
readonly signal?: AbortSignal | undefined;
|
|
81
94
|
}): Promise<DeviceListOutcome>;
|
|
82
|
-
export declare function readSessionBinding(
|
|
95
|
+
export declare function readSessionBinding(sessions: SessionExecutionPlacementVerb | null | undefined, rootSessionId: string, opts?: {
|
|
83
96
|
readonly signal?: AbortSignal | undefined;
|
|
84
97
|
}): Promise<DeviceSessionBindingOutcome>;
|
|
85
98
|
export declare function rebindSession(devices: DeviceRebindVerb | null | undefined, req: DeviceRebindInput, opts?: {
|
package/dist/deviceRebind.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { atMostOnceVerdictOf } from './atMostOnce.js';
|
|
2
2
|
import { readOwnDataValue } from './ownKey.js';
|
|
3
|
-
import { isDisplayableWireCode, readErrorString, readThrownSlot, wireFailureShapeOf } from './wireFailureShape.js';
|
|
3
|
+
import { isDisplayableWireCode, readErrorString, readErrorStrictStringList, readThrownSlot, wireFailureShapeOf } from './wireFailureShape.js';
|
|
4
|
+
import { EXECUTION_PLACEMENT_DEVICE_LANE, EXECUTION_PLACEMENT_ROLES } from './executionPlacementWords.js';
|
|
4
5
|
const LANE_ABSENT = 'capability.device_lane_required';
|
|
5
6
|
const RUN_STORE_ABSENT = 'capability.run_store_required';
|
|
6
7
|
const NOT_FOUND = 'not_found.device';
|
|
7
8
|
const ACTIVE_RUN = 'device.rebind_active_run';
|
|
9
|
+
const SESSION_NOT_FOUND = 'not_found.session';
|
|
10
|
+
const ROUTE_ABSENT = 'not_found.route';
|
|
11
|
+
const SESSION_STORE_ABSENT = 'capability.session_store_required';
|
|
8
12
|
const REV_CONFLICT = 'device.rebind_rev_conflict';
|
|
9
13
|
const SERVICE_TOKEN_REQUIRED = 'auth.service_token_required';
|
|
10
14
|
function own(v, key) {
|
|
@@ -123,29 +127,50 @@ function bindingOf(raw) {
|
|
|
123
127
|
const rev = nonNegInt(own(raw, 'rev'));
|
|
124
128
|
if (deviceId === undefined || rev === undefined)
|
|
125
129
|
return null;
|
|
126
|
-
|
|
127
|
-
return { deviceId, rev, ...(boundAt !== undefined ? { boundAt } : {}) };
|
|
130
|
+
return { deviceId, rev };
|
|
128
131
|
}
|
|
129
|
-
|
|
130
|
-
const
|
|
132
|
+
function placementReadFailureOf(e) {
|
|
133
|
+
const v = atMostOnceVerdictOf(e);
|
|
134
|
+
if (v.status === 404 && v.code === SESSION_NOT_FOUND)
|
|
135
|
+
return { kind: 'not-found' };
|
|
136
|
+
if (v.status === 404 && v.code === ROUTE_ABSENT)
|
|
137
|
+
return { kind: 'unsupported', reason: 'route' };
|
|
138
|
+
if (v.status === 501 && v.code === SESSION_STORE_ABSENT)
|
|
139
|
+
return { kind: 'unsupported', reason: 'capability' };
|
|
140
|
+
return v.status !== undefined ? refusedOf(v.status, v.code, e) : transportOf(v);
|
|
141
|
+
}
|
|
142
|
+
const isPlacementRole = (v) => typeof v === 'string' && EXECUTION_PLACEMENT_ROLES.includes(v);
|
|
143
|
+
export async function readSessionBinding(sessions, rootSessionId, opts) {
|
|
144
|
+
if (typeof rootSessionId !== 'string' || rootSessionId === '') {
|
|
145
|
+
return { kind: 'refused', status: 0, errorCode: 'request.id_invalid', message: 'the session id to read the execution placement of must be a non-empty string — nothing was sent' };
|
|
146
|
+
}
|
|
147
|
+
const verb = verbOf(sessions, 'executionPlacement');
|
|
131
148
|
if (verb === undefined)
|
|
132
149
|
return { kind: 'unarmed' };
|
|
133
150
|
let body;
|
|
134
151
|
try {
|
|
135
|
-
body = await verb.call(
|
|
152
|
+
body = await verb.call(sessions, rootSessionId, signalOpts(opts));
|
|
136
153
|
}
|
|
137
154
|
catch (e) {
|
|
138
|
-
return
|
|
155
|
+
return placementReadFailureOf(e);
|
|
156
|
+
}
|
|
157
|
+
const role = own(body, 'role');
|
|
158
|
+
if (!isPlacementRole(role)) {
|
|
159
|
+
return { kind: 'unreadable', why: 'the execution placement it returned names no role this client knows (absent / writer / mirror / forking) — refusing to read it as "not bound"' };
|
|
139
160
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
161
|
+
if (role !== 'writer')
|
|
162
|
+
return { kind: 'unbound', role };
|
|
163
|
+
const lane = own(body, 'lane');
|
|
164
|
+
if (typeof lane !== 'string' || lane === '') {
|
|
165
|
+
return { kind: 'unreadable', why: "the writer's execution lane in the execution placement is missing or not a word — refusing to guess whether a device is bound" };
|
|
143
166
|
}
|
|
144
|
-
|
|
167
|
+
if (lane !== EXECUTION_PLACEMENT_DEVICE_LANE)
|
|
168
|
+
return { kind: 'unbound', role };
|
|
169
|
+
const bound = bindingOf(own(body, 'device'));
|
|
145
170
|
if (bound === null) {
|
|
146
|
-
return { kind: 'unreadable', why: 'the
|
|
171
|
+
return { kind: 'unreadable', why: 'the session is written on the device lane but the execution placement names no readable device (deviceId + rev) — the device is unknown, not unbound' };
|
|
147
172
|
}
|
|
148
|
-
return { kind: 'ok', rootSessionId
|
|
173
|
+
return { kind: 'ok', rootSessionId, boundDevice: bound };
|
|
149
174
|
}
|
|
150
175
|
function rebindFailureOf(e) {
|
|
151
176
|
const v = atMostOnceVerdictOf(e);
|
|
@@ -155,7 +180,11 @@ function rebindFailureOf(e) {
|
|
|
155
180
|
return common;
|
|
156
181
|
if (status === 409 && code === ACTIVE_RUN) {
|
|
157
182
|
const activeTaskId = nonEmpty(own(e, 'activeTaskId'));
|
|
158
|
-
|
|
183
|
+
if (activeTaskId !== undefined)
|
|
184
|
+
return { kind: 'active-run', activeTaskId };
|
|
185
|
+
const children = e !== null && typeof e === 'object' ? readErrorStrictStringList(e, 'children') : undefined;
|
|
186
|
+
const retirePath = e !== null && typeof e === 'object' ? nonEmpty(readErrorString(e, 'retirePath')) : undefined;
|
|
187
|
+
return { kind: 'active-run', ...(children !== undefined && retirePath !== undefined ? { children: Object.freeze([...children]), retirePath } : {}) };
|
|
159
188
|
}
|
|
160
189
|
if (status === 409 && code === REV_CONFLICT) {
|
|
161
190
|
const currentRev = nonNegInt(own(e, 'currentRev'));
|
|
@@ -55,6 +55,7 @@ export interface EngineAgentRegistryRowView {
|
|
|
55
55
|
readonly status: string;
|
|
56
56
|
readonly description?: string;
|
|
57
57
|
readonly createdAt?: number;
|
|
58
|
+
readonly sessionId?: string;
|
|
58
59
|
}
|
|
59
60
|
export type EngineAgentRegistryUnavailableWhy = 'no_list_face' | 'capability_unknown' | 'route_absent' | 'ownership_required' | 'read_failed';
|
|
60
61
|
export type EngineAgentRegistryListing = {
|
|
@@ -23,6 +23,7 @@ export interface CoreModeArbitrationRow {
|
|
|
23
23
|
readonly hookAskFloor: boolean;
|
|
24
24
|
}
|
|
25
25
|
export declare const CORE_MODE_ARBITRATION: Readonly<Record<"content_question" | "hook" | "ancestor" | "dangerous_delete" | "unverifiable_delete" | "unverifiable_shell_text" | "transcript_write" | "org_rule" | "rule_unreadable" | "ask_rule" | "denial_limit_fallback" | "classifier_no_ruling" | "requires_user_interaction" | "cross_boundary" | "operator_forced" | "shell_floor" | "target_unresolved" | "probe" | "write_protection_on_disk" | "write_protection" | "tool_marks_mcp" | "tool_marks_a2a" | "policy_rra" | "artifact_shared_read" | "mode" | "unstated" | "ordinary", CoreModeArbitrationRow>>;
|
|
26
|
+
export declare const CORE_REAL_APPROVAL_ASK_CLASSES: readonly ["ancestor", "dangerous_delete", "unverifiable_delete", "unverifiable_shell_text", "transcript_write", "org_rule", "rule_unreadable", "denial_limit_fallback", "classifier_no_ruling", "requires_user_interaction", "cross_boundary", "policy_rra", "artifact_shared_read"];
|
|
26
27
|
export declare const CORE_SKILL_GRANT_ORIGINS: readonly ["model", "user", "inherited"];
|
|
27
28
|
export declare const CORE_ALLOW_ENTRY_INERT_REASONS: readonly ["wildcard_all", "namespace_wildcard", "content_unsupported", "grammar", "tool_name", "near_miss", "earlier_grammar"];
|
|
28
29
|
export declare const CORE_ALLOW_RULE_MEMBERS: readonly ["hook", "deployment", "persisted", "skill", "request"];
|
|
@@ -37,7 +38,7 @@ export declare const CORE_TASK_HANDLE_PREFIXES: Readonly<Record<"background_bash
|
|
|
37
38
|
export declare const CORE_PERMISSION_MODE_CLASSES: readonly ["bypass", "prompting"];
|
|
38
39
|
export declare const CORE_MCP_LIVENESS_STATES: readonly ["reachable", "unreachable", "unknown"];
|
|
39
40
|
export declare const CORE_RULE_BEHAVIORS: readonly ["deny", "ask", "allow"];
|
|
40
|
-
export declare const
|
|
41
|
+
export declare const CORE_IMAGE_ADMISSION_HARD_IMAGE_BASE64_CHARS: number;
|
|
41
42
|
export declare const CORE_MAX_PENDING_STEER_CHARS: number;
|
|
42
43
|
export declare const CORE_PROMPT_BLOCK_CAUSES: readonly ["block", "crashed", "timeout", "cancelled"];
|
|
43
44
|
export declare const CORE_PERMISSION_MODES: readonly ["default", "acceptEdits", "plan", "auto", "bypassPermissions", "dontAsk"];
|
|
@@ -48,7 +49,7 @@ export declare const CORE_RESUME_STARTUP_CAUSES: readonly ["environment", "sessi
|
|
|
48
49
|
export declare const CORE_BUILTIN_SUBAGENT_TYPES: readonly ["Explore", "Plan", "fork", "general-purpose"];
|
|
49
50
|
export declare const CORE_RULE_OFFERS_ABSENCES: readonly ["mandated", "allow_outranked", "ask_rule_matched", "lane_cannot_speak"];
|
|
50
51
|
export declare const CORE_TOOL_APPROVAL_CARDS: readonly ["file-edit", "file-write", "notebook-edit", "shell", "fetch", "skill", "workflow", "plan", "question", "generic"];
|
|
51
|
-
export declare const CORE_MCP_FAILURE_KINDS: readonly ["connect_refused", "connection_failed", "connection_closed", "unauthorized", "http_status", "not_mcp_response", "spawn_failed", "timeout", "protocol", "invalid_config", "credential_unavailable", "unknown"];
|
|
52
|
+
export declare const CORE_MCP_FAILURE_KINDS: readonly ["connect_refused", "connection_failed", "connection_closed", "unauthorized", "http_status", "not_mcp_response", "spawn_failed", "timeout", "protocol", "invalid_config", "credential_unavailable", "host_refused", "unknown"];
|
|
52
53
|
export declare const CORE_MCP_AUTHORIZATION_REASONS: readonly ["rejected", "scope", "none"];
|
|
53
54
|
export declare const CORE_PERSISTED_RULE_MATCHES: readonly ["exact", "prefix", "wildcard", "pattern", "subpath", "path", "name", "name_prefix", "host", "subdomain", "tool"];
|
|
54
55
|
export declare const CORE_APPROVAL_REMEDY_KINDS: readonly ["approver", "permission_mode"];
|
|
@@ -200,6 +200,21 @@ export const CORE_MODE_ARBITRATION = Object.freeze({
|
|
|
200
200
|
"unstated": Object.freeze({ bypassImmune: false, classifierEligible: true, sandboxAdmission: false, ruleMayClear: true, hookAskFloor: false }),
|
|
201
201
|
"ordinary": Object.freeze({ bypassImmune: false, classifierEligible: true, sandboxAdmission: true, ruleMayClear: true, hookAskFloor: false }),
|
|
202
202
|
});
|
|
203
|
+
export const CORE_REAL_APPROVAL_ASK_CLASSES = Object.freeze([
|
|
204
|
+
"ancestor",
|
|
205
|
+
"dangerous_delete",
|
|
206
|
+
"unverifiable_delete",
|
|
207
|
+
"unverifiable_shell_text",
|
|
208
|
+
"transcript_write",
|
|
209
|
+
"org_rule",
|
|
210
|
+
"rule_unreadable",
|
|
211
|
+
"denial_limit_fallback",
|
|
212
|
+
"classifier_no_ruling",
|
|
213
|
+
"requires_user_interaction",
|
|
214
|
+
"cross_boundary",
|
|
215
|
+
"policy_rra",
|
|
216
|
+
"artifact_shared_read",
|
|
217
|
+
]);
|
|
203
218
|
export const CORE_SKILL_GRANT_ORIGINS = Object.freeze([
|
|
204
219
|
"model",
|
|
205
220
|
"user",
|
|
@@ -286,7 +301,7 @@ export const CORE_RULE_BEHAVIORS = Object.freeze([
|
|
|
286
301
|
"ask",
|
|
287
302
|
"allow",
|
|
288
303
|
]);
|
|
289
|
-
export const
|
|
304
|
+
export const CORE_IMAGE_ADMISSION_HARD_IMAGE_BASE64_CHARS = 5242880;
|
|
290
305
|
export const CORE_MAX_PENDING_STEER_CHARS = 16000;
|
|
291
306
|
export const CORE_PROMPT_BLOCK_CAUSES = Object.freeze([
|
|
292
307
|
"block",
|
|
@@ -364,6 +379,7 @@ export const CORE_MCP_FAILURE_KINDS = Object.freeze([
|
|
|
364
379
|
"protocol",
|
|
365
380
|
"invalid_config",
|
|
366
381
|
"credential_unavailable",
|
|
382
|
+
"host_refused",
|
|
367
383
|
"unknown",
|
|
368
384
|
]);
|
|
369
385
|
export const CORE_MCP_AUTHORIZATION_REASONS = Object.freeze([
|
|
@@ -17,6 +17,7 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
|
|
|
17
17
|
"config.write_protection_target_view_absent",
|
|
18
18
|
"config.path_view_unresolved",
|
|
19
19
|
"config.execution_env_capability_invalid",
|
|
20
|
+
"config.read_deny_floor_unkept",
|
|
20
21
|
"config.tool_card_undeclared",
|
|
21
22
|
"config.tool_face_undeclared",
|
|
22
23
|
"config.tool_face_invalid",
|
|
@@ -42,6 +43,7 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
|
|
|
42
43
|
"peer.idle_subscription",
|
|
43
44
|
"classifier.denial_limit",
|
|
44
45
|
"classifier.fallback",
|
|
46
|
+
"classifier.seat_rate_limited",
|
|
45
47
|
"classifier.role_defaulted",
|
|
46
48
|
"classifier.contract_broken",
|
|
47
49
|
"classifier.unavailable",
|
|
@@ -52,6 +54,7 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
|
|
|
52
54
|
"mcp.revocation_probe_failed",
|
|
53
55
|
"mcp.server_redialed",
|
|
54
56
|
"mcp.authorization_required",
|
|
57
|
+
"mcp.credential_echoed",
|
|
55
58
|
"workflow.governance_key_stripped",
|
|
56
59
|
"workflow.agent_option_ignored",
|
|
57
60
|
"memory.session_polluted",
|
|
@@ -100,6 +103,7 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
|
|
|
100
103
|
"agents.listing_truncated",
|
|
101
104
|
"tool_result.offload_put_failed",
|
|
102
105
|
"tool_result.media_refused",
|
|
106
|
+
"config.image_processor_unavailable",
|
|
103
107
|
"instructions.source_changed",
|
|
104
108
|
"session.records_skipped",
|
|
105
109
|
"memory.layer_locked_legacy",
|
|
@@ -125,6 +129,7 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
|
|
|
125
129
|
"config.write_protection_target_view_absent": "operator",
|
|
126
130
|
"config.path_view_unresolved": "operator",
|
|
127
131
|
"config.execution_env_capability_invalid": "operator",
|
|
132
|
+
"config.read_deny_floor_unkept": "operator",
|
|
128
133
|
"config.tool_card_undeclared": "operator",
|
|
129
134
|
"config.tool_face_undeclared": "operator",
|
|
130
135
|
"config.tool_face_invalid": "operator",
|
|
@@ -150,6 +155,7 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
|
|
|
150
155
|
"peer.idle_subscription": "user",
|
|
151
156
|
"classifier.denial_limit": "user",
|
|
152
157
|
"classifier.fallback": "operator",
|
|
158
|
+
"classifier.seat_rate_limited": "operator",
|
|
153
159
|
"classifier.role_defaulted": "operator",
|
|
154
160
|
"classifier.contract_broken": "operator",
|
|
155
161
|
"classifier.unavailable": "user",
|
|
@@ -160,6 +166,7 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
|
|
|
160
166
|
"mcp.revocation_probe_failed": "operator",
|
|
161
167
|
"mcp.server_redialed": "operator",
|
|
162
168
|
"mcp.authorization_required": "user",
|
|
169
|
+
"mcp.credential_echoed": "operator",
|
|
163
170
|
"workflow.governance_key_stripped": "operator",
|
|
164
171
|
"workflow.agent_option_ignored": "operator",
|
|
165
172
|
"memory.session_polluted": "user",
|
|
@@ -208,6 +215,7 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
|
|
|
208
215
|
"agents.listing_truncated": "operator",
|
|
209
216
|
"tool_result.offload_put_failed": "operator",
|
|
210
217
|
"tool_result.media_refused": "operator",
|
|
218
|
+
"config.image_processor_unavailable": "operator",
|
|
211
219
|
"instructions.source_changed": "user",
|
|
212
220
|
"session.records_skipped": "user",
|
|
213
221
|
"memory.layer_locked_legacy": "operator",
|
|
@@ -239,6 +247,7 @@ export const CORE_NOTICE_MINTER = Object.freeze({
|
|
|
239
247
|
"config.write_protection_target_view_absent": "engine",
|
|
240
248
|
"config.path_view_unresolved": "engine",
|
|
241
249
|
"config.execution_env_capability_invalid": "engine",
|
|
250
|
+
"config.read_deny_floor_unkept": "engine",
|
|
242
251
|
"config.tool_card_undeclared": "engine",
|
|
243
252
|
"config.tool_face_undeclared": "engine",
|
|
244
253
|
"config.tool_face_invalid": "engine",
|
|
@@ -264,6 +273,7 @@ export const CORE_NOTICE_MINTER = Object.freeze({
|
|
|
264
273
|
"peer.idle_subscription": "engine",
|
|
265
274
|
"classifier.denial_limit": "engine",
|
|
266
275
|
"classifier.fallback": "engine",
|
|
276
|
+
"classifier.seat_rate_limited": "engine",
|
|
267
277
|
"classifier.role_defaulted": "engine",
|
|
268
278
|
"classifier.contract_broken": "engine",
|
|
269
279
|
"classifier.unavailable": "engine",
|
|
@@ -274,6 +284,7 @@ export const CORE_NOTICE_MINTER = Object.freeze({
|
|
|
274
284
|
"mcp.revocation_probe_failed": "engine",
|
|
275
285
|
"mcp.server_redialed": "engine",
|
|
276
286
|
"mcp.authorization_required": "engine",
|
|
287
|
+
"mcp.credential_echoed": "engine",
|
|
277
288
|
"workflow.governance_key_stripped": "engine",
|
|
278
289
|
"workflow.agent_option_ignored": "engine",
|
|
279
290
|
"memory.session_polluted": "engine",
|
|
@@ -322,6 +333,7 @@ export const CORE_NOTICE_MINTER = Object.freeze({
|
|
|
322
333
|
"agents.listing_truncated": "engine",
|
|
323
334
|
"tool_result.offload_put_failed": "engine",
|
|
324
335
|
"tool_result.media_refused": "engine",
|
|
336
|
+
"config.image_processor_unavailable": "engine",
|
|
325
337
|
"instructions.source_changed": "server",
|
|
326
338
|
"session.records_skipped": "server",
|
|
327
339
|
"memory.layer_locked_legacy": "server",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CORE_MODE_ARBITRATION, CORE_MODE_RELEASE_REASONS } from '../generated/engineFactTables.js';
|
|
1
|
+
import { CORE_MODE_ARBITRATION, CORE_MODE_RELEASE_REASONS, CORE_REAL_APPROVAL_ASK_CLASSES } from '../generated/engineFactTables.js';
|
|
2
2
|
import { CORE_RELEASABLE_ASK_CLASSES_BY_FACE, CORE_SHELL_FACE_TOOL_NAMES } from '../generated/engineAskFaceTables.js';
|
|
3
3
|
import { mandatedApprovalDetail } from '../gateVocabulary.js';
|
|
4
4
|
import { msg, renderMessage } from '../i18n/translate.js';
|
|
@@ -60,12 +60,13 @@ export function foldModeArbitrationRow(classes, askFace) {
|
|
|
60
60
|
return ORDINARY_ROW;
|
|
61
61
|
return Object.freeze({ bypassImmune, classifierEligible, sandboxAdmission, ruleMayClear, hookAskFloor });
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
return lane === 'mode_posture' ? row.bypassImmune : !row.ruleMayClear;
|
|
65
|
-
}
|
|
63
|
+
const REAL_APPROVAL_CLASSES = new Set(CORE_REAL_APPROVAL_ASK_CLASSES);
|
|
66
64
|
function classBlocks(lane, c, face) {
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
if (lane === 'mode_posture')
|
|
66
|
+
return bypassImmuneOn(c, face);
|
|
67
|
+
if (lane === 'standing_rule')
|
|
68
|
+
return !TABLE[c].ruleMayClear;
|
|
69
|
+
return REAL_APPROVAL_CLASSES.has(c);
|
|
69
70
|
}
|
|
70
71
|
function mustAsk(road, extra) {
|
|
71
72
|
return Object.freeze({ kind: 'must_ask', road, ...(extra?.askClass !== undefined ? { askClass: extra.askClass } : {}), ...(extra?.origin !== undefined ? { origin: extra.origin } : {}) });
|
|
@@ -88,6 +89,42 @@ function evidenceView(card, ...keys) {
|
|
|
88
89
|
}
|
|
89
90
|
return out;
|
|
90
91
|
}
|
|
92
|
+
const SLOT_ABSENT = Object.freeze({ kind: 'absent' });
|
|
93
|
+
const SLOT_UNREADABLE = Object.freeze({ kind: 'unreadable' });
|
|
94
|
+
const EVIDENCE_CHAIN_MAX = 32;
|
|
95
|
+
function evidenceSlotOf(o, key) {
|
|
96
|
+
let at = o;
|
|
97
|
+
for (let depth = 0; at !== null; depth++) {
|
|
98
|
+
if (depth >= EVIDENCE_CHAIN_MAX)
|
|
99
|
+
return SLOT_UNREADABLE;
|
|
100
|
+
const d = Object.getOwnPropertyDescriptor(at, key);
|
|
101
|
+
if (d !== undefined)
|
|
102
|
+
return Object.hasOwn(d, 'value') ? Object.freeze({ kind: 'data', value: d.value }) : SLOT_UNREADABLE;
|
|
103
|
+
at = Object.getPrototypeOf(at);
|
|
104
|
+
}
|
|
105
|
+
return SLOT_ABSENT;
|
|
106
|
+
}
|
|
107
|
+
const EVIDENCE_BOOLEAN_KEYS = Object.freeze(['requiresRealApproval', 'governanceForced', 'mandated']);
|
|
108
|
+
const EVIDENCE_STRING_KEYS = Object.freeze(['origin', 'ruleOffersAbsence', 'mandate']);
|
|
109
|
+
function evidenceUnreadable(card) {
|
|
110
|
+
for (const k of EVIDENCE_BOOLEAN_KEYS) {
|
|
111
|
+
const slot = evidenceSlotOf(card, k);
|
|
112
|
+
if (slot.kind === 'unreadable' || (slot.kind === 'data' && slot.value !== undefined && typeof slot.value !== 'boolean'))
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
for (const k of EVIDENCE_STRING_KEYS) {
|
|
116
|
+
const slot = evidenceSlotOf(card, k);
|
|
117
|
+
if (slot.kind === 'unreadable' || (slot.kind === 'data' && slot.value !== undefined && (typeof slot.value !== 'string' || slot.value === '')))
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
const risk = evidenceSlotOf(card, 'risk');
|
|
121
|
+
if (risk.kind === 'absent' || (risk.kind === 'data' && risk.value === undefined))
|
|
122
|
+
return false;
|
|
123
|
+
if (risk.kind === 'unreadable' || typeof risk.value !== 'object' || risk.value === null)
|
|
124
|
+
return true;
|
|
125
|
+
const nested = evidenceSlotOf(risk.value, 'requiresRealApproval');
|
|
126
|
+
return nested.kind !== 'data' || typeof nested.value !== 'boolean';
|
|
127
|
+
}
|
|
91
128
|
function readHostAskRuleMatched(facts) {
|
|
92
129
|
if (typeof facts !== 'object' || facts === null)
|
|
93
130
|
return undefined;
|
|
@@ -138,14 +175,14 @@ export function automaticAnswerVerdict(card, lane, facts) {
|
|
|
138
175
|
return mustAsk('allow_rule_shadow');
|
|
139
176
|
}
|
|
140
177
|
}
|
|
178
|
+
if (evidenceUnreadable(card))
|
|
179
|
+
return UNKNOWN.card_unreadable;
|
|
141
180
|
const pair = readAskClassPairState(card);
|
|
142
181
|
if (pair.state === 'malformed')
|
|
143
182
|
return UNKNOWN.classes_malformed;
|
|
144
183
|
if (pair.state === 'absent')
|
|
145
184
|
return UNKNOWN.classes_absent;
|
|
146
185
|
const classes = pair.classes;
|
|
147
|
-
const folded = foldModeArbitrationRow(classes, face);
|
|
148
|
-
let anyKnown = false;
|
|
149
186
|
let firstBlocking;
|
|
150
187
|
let anyUnknown = false;
|
|
151
188
|
for (const c of classes) {
|
|
@@ -153,12 +190,11 @@ export function automaticAnswerVerdict(card, lane, facts) {
|
|
|
153
190
|
anyUnknown = true;
|
|
154
191
|
continue;
|
|
155
192
|
}
|
|
156
|
-
anyKnown = true;
|
|
157
193
|
if (firstBlocking === undefined && classBlocks(lane, c, face))
|
|
158
194
|
firstBlocking = c;
|
|
159
195
|
}
|
|
160
|
-
if (
|
|
161
|
-
return mustAsk('ask_class',
|
|
196
|
+
if (firstBlocking !== undefined)
|
|
197
|
+
return mustAsk('ask_class', { askClass: firstBlocking });
|
|
162
198
|
if (anyUnknown)
|
|
163
199
|
return UNKNOWN.class_not_in_table;
|
|
164
200
|
if (lane !== 'mode_posture')
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ApprovalRequestFrame } from '@sema-agent/sdk';
|
|
1
2
|
import type { ApprovalResolution } from './approvalResolution.js';
|
|
2
3
|
import type { ApprovalsFeedEmission } from './approvalsFeed.js';
|
|
3
4
|
import { type RespondToolApprovalFn, type ToolApprovalFrame, type ToolApprovalFrameLaneOpts } from './toolApprovalWire.js';
|
|
@@ -11,7 +12,7 @@ export interface LivePendingAskView {
|
|
|
11
12
|
governanceForced?: true;
|
|
12
13
|
fromSubagent?: true;
|
|
13
14
|
originTaskId?: string;
|
|
14
|
-
frame?: ToolApprovalFrame;
|
|
15
|
+
frame?: ToolApprovalFrame | ApprovalRequestFrame;
|
|
15
16
|
}
|
|
16
17
|
export type LivePendingReading = {
|
|
17
18
|
kind: 'not_reported';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isApprovalRequestFrameV1 } from '@sema-agent/sdk';
|
|
1
2
|
import { appendOwnElement } from '../ownKey.js';
|
|
2
3
|
import { readRequiresRealApproval } from './approvalCardReading.js';
|
|
3
4
|
import { THROWN_SLOT_UNREADABLE, readThrownSlot } from '../wireFailureShape.js';
|
|
@@ -21,6 +22,11 @@ function snapshotMembers(raw) {
|
|
|
21
22
|
}
|
|
22
23
|
return raw.length === length ? out : undefined;
|
|
23
24
|
}
|
|
25
|
+
function openingFrameOf(f) {
|
|
26
|
+
if (isToolApprovalFrame(f))
|
|
27
|
+
return f.type === 'tool_approval' ? f : undefined;
|
|
28
|
+
return isApprovalRequestFrameV1(f) ? f : undefined;
|
|
29
|
+
}
|
|
24
30
|
export function readLivePendingRows(body) {
|
|
25
31
|
if (body === null || typeof body !== 'object' || Array.isArray(body))
|
|
26
32
|
return { kind: 'malformed' };
|
|
@@ -65,7 +71,7 @@ export function readLivePendingRows(body) {
|
|
|
65
71
|
...(o.governanceForced === true ? { governanceForced: true } : {}),
|
|
66
72
|
...(o.fromSubagent === true ? { fromSubagent: true } : {}),
|
|
67
73
|
...(nonEmptyString(o.originTaskId) ? { originTaskId: o.originTaskId } : {}),
|
|
68
|
-
...(
|
|
74
|
+
...((f) => (f !== undefined && f.approvalId === o.approvalId ? { frame: f } : {}))(openingFrameOf(o.frame)),
|
|
69
75
|
});
|
|
70
76
|
}
|
|
71
77
|
if (members.length > 0 && rows.length === 0)
|