@sema-agent/client-core 0.107.0 → 0.108.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +118 -0
- package/README.md +19 -14
- package/dist/adapter/activeRunSelfHeal.d.ts +2 -0
- package/dist/adapter/activeRunSelfHeal.js +20 -3
- package/dist/checkpointRowVerdict.d.ts +5 -0
- package/dist/checkpointRowVerdict.js +26 -0
- package/dist/cloudConfigWireCaps.d.ts +10 -0
- package/dist/cloudConfigWireCaps.js +33 -0
- package/dist/coreValuePorts.d.ts +17 -1
- package/dist/coreValuePorts.js +5 -0
- package/dist/decideReceipt.js +2 -1
- package/dist/engineErrorCodes.d.ts +5 -0
- package/dist/engineErrorCodes.js +5 -0
- package/dist/engineNoticeCodes.d.ts +19 -1
- package/dist/engineNoticeCodes.js +65 -3
- package/dist/engineTargetSeat.js +1 -0
- package/dist/errorSupplementRoles.js +2 -0
- package/dist/eventLeg.js +1 -1
- package/dist/executionLaneWords.js +2 -1
- package/dist/gateOutcome.d.ts +10 -1
- package/dist/gateOutcome.js +48 -1
- package/dist/generated/engineFactTables.d.ts +1 -0
- package/dist/generated/engineFactTables.js +5 -0
- package/dist/generated/engineNoticeTables.js +3 -0
- package/dist/generated/settingsSchemaFns.d.ts +4 -2
- package/dist/generated/settingsSchemaFns.js +9 -3
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
- package/dist/generated/settingsSchemaMcpRequestEntry.js +9 -18
- package/dist/generated/settingsSchemaReservedMemberName.d.ts +1 -0
- package/dist/generated/settingsSchemaReservedMemberName.js +7 -0
- package/dist/generated/settingsSchemaTables.d.ts +2 -0
- package/dist/generated/settingsSchemaTables.js +10 -0
- package/dist/generated/settingsSchemaWireName.d.ts +1 -0
- package/dist/generated/settingsSchemaWireName.js +8 -0
- package/dist/headlessReconnectWire.js +12 -7
- package/dist/hitl/approvalAskers.d.ts +13 -0
- package/dist/hitl/approvalAskers.js +79 -0
- package/dist/hitl/approvalResolution.d.ts +3 -0
- package/dist/hitl/approvalResolution.js +22 -4
- package/dist/hitl/approvalsFeed.js +3 -12
- package/dist/hitl/askParkRowRouting.js +5 -1
- package/dist/hitl/decisionRefusal.d.ts +1 -0
- package/dist/hitl/decisionRefusal.js +5 -2
- package/dist/hitl/decisionSend.js +2 -6
- package/dist/hitl/frameRouter.d.ts +3 -2
- package/dist/hitl/frameRouter.js +28 -6
- package/dist/hitl/gateLedger.d.ts +2 -0
- package/dist/hitl/gateLedger.js +3 -1
- package/dist/hitl/hitlBridge.js +2 -3
- package/dist/hitl/parkResolver.js +32 -23
- package/dist/hitl/parkRowBirthWait.d.ts +2 -0
- package/dist/hitl/parkRowBirthWait.js +8 -1
- package/dist/hitl/persistedRulesWire.d.ts +5 -1
- package/dist/hitl/persistedRulesWire.js +20 -4
- package/dist/hitl/planReviewWire.js +12 -16
- package/dist/hitl/policyDenyCause.d.ts +3 -0
- package/dist/hitl/policyDenyCause.js +16 -0
- package/dist/hitl/sessionPolicyDeliverable.js +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +8 -2
- package/dist/hitl/toolApprovalWire.js +22 -3
- package/dist/hooksReaderGenerations.d.ts +1 -0
- package/dist/hooksReaderGenerations.js +12 -0
- package/dist/hooksWireCaps.js +8 -4
- package/dist/i18n/messages.en.d.ts +38 -1
- package/dist/i18n/messages.en.js +40 -3
- package/dist/i18n/messages.zh.js +45 -3
- package/dist/index.d.ts +6 -1
- package/dist/index.js +4 -1
- package/dist/liveModelCatalog.d.ts +4 -2
- package/dist/liveModelCatalog.js +164 -26
- package/dist/model/catalogDefault.d.ts +25 -0
- package/dist/model/catalogDefault.js +44 -0
- package/dist/permissionWireCaps.d.ts +1 -0
- package/dist/permissionWireCaps.js +11 -0
- package/dist/pluginHooksWire.d.ts +5 -3
- package/dist/pluginHooksWire.js +116 -7
- package/dist/queuedDelivery.d.ts +1 -0
- package/dist/queuedDelivery.js +12 -0
- package/dist/resultFrameKeys.js +4 -2
- package/dist/resumeRefusalCopy.js +15 -8
- package/dist/runPermissionModeSwitch.d.ts +2 -1
- package/dist/runPermissionModeSwitch.js +16 -6
- package/dist/seatContract.d.ts +63 -10
- package/dist/seatContract.js +164 -11
- package/dist/sessionEngine.d.ts +2 -1
- package/dist/sessionEngine.js +5 -0
- package/dist/settingsHooksSalvage.d.ts +5 -0
- package/dist/settingsHooksSalvage.js +54 -0
- package/dist/subagentContentStore.js +1 -1
- package/dist/supportFloor.js +2 -0
- package/dist/taskNotificationAdmission.d.ts +19 -0
- package/dist/taskNotificationAdmission.js +84 -0
- package/dist/toolResult.js +2 -1
- package/dist/webSearchWireCaps.js +9 -4
- package/dist/wireRefusalCopy.d.ts +2 -1
- package/dist/wireRefusalCopy.js +2 -2
- package/docs/INTEGRATION-CLIENTS.md +816 -14
- package/package.json +4 -4
|
@@ -34,18 +34,20 @@ export declare const SETTINGS_READ_KEY: (record: object, key: PropertyKey) => ob
|
|
|
34
34
|
export declare const SETTINGS_IS_RESERVED_MCP_SERVER_NAME: (name: string) => boolean;
|
|
35
35
|
export declare const SETTINGS_REMOTE_MCP_SERVER_NAME_PREFIX: "remote-";
|
|
36
36
|
export declare const SETTINGS_RESERVED_MCP_SERVER_NAME_REASON: "the \"remote-\" prefix is reserved for the remote MCP servers a device executor offers";
|
|
37
|
+
export declare const SETTINGS_IS_USABLE_WIRE_NAME: (v: unknown) => v is string;
|
|
38
|
+
export declare const SETTINGS_TOOL_WIRE_NAME_MAX_CHARS: 128;
|
|
39
|
+
export declare const SETTINGS_HAS_EDGE_WHITESPACE: (v: string) => boolean;
|
|
40
|
+
export declare const SETTINGS_IS_RESERVED_MEMBER_NAME: (name: string) => boolean;
|
|
37
41
|
export declare const SETTINGS_READ_REQUEST_MCP_TRANSPORT: (t: unknown) => RequestMcpTransportRead;
|
|
38
42
|
export declare const SETTINGS_READ_MCP_IDENTITY_HEADERS: (transport: Record<string, unknown>) => {
|
|
39
43
|
principalHeader?: string;
|
|
40
44
|
assertionHeader?: string;
|
|
41
45
|
};
|
|
42
|
-
export declare const SETTINGS_IS_USABLE_WIRE_NAME: (v: unknown) => v is string;
|
|
43
46
|
export declare const SETTINGS_DESCRIBE_BAD_WIRE_NAME: (v: unknown) => string;
|
|
44
47
|
export declare const SETTINGS_IS_USABLE_MCP_SERVER_NAME: (v: unknown) => v is string;
|
|
45
48
|
export declare const SETTINGS_DESCRIBE_BAD_MCP_SERVER_NAME: (v: unknown) => string;
|
|
46
49
|
export declare const SETTINGS_IS_CONTENT_ORIGIN_WORD: (v: unknown) => v is McpContentOrigin;
|
|
47
50
|
export declare const SETTINGS_DESCRIBE_BAD_CONTENT_ORIGIN: (v: unknown) => string;
|
|
48
|
-
export declare const SETTINGS_TOOL_WIRE_NAME_MAX_CHARS: 128;
|
|
49
51
|
export declare const SETTINGS_URL_ALLOW_PATTERN_MATCHES: (url: string, pattern: string) => boolean;
|
|
50
52
|
export declare const SETTINGS_IS_AT_LEAST: (layer: string, minTrust: string) => boolean;
|
|
51
53
|
export declare const SETTINGS_MEMBER_ADMISSION: (category: string, member: string) => object;
|
|
@@ -4,6 +4,8 @@ import { SETTINGS_CALLER_TEXT_ECHO_CLOSURE } from './settingsSchemaCallerTextEch
|
|
|
4
4
|
import { SETTINGS_PLAIN_JSON_OBJECT_CLOSURE } from './settingsSchemaPlainJsonObject.js';
|
|
5
5
|
import { SETTINGS_OWN_KEY_READ_CLOSURE } from './settingsSchemaOwnKeyRead.js';
|
|
6
6
|
import { SETTINGS_MCP_SERVER_NAME_CLOSURE } from './settingsSchemaMcpServerName.js';
|
|
7
|
+
import { SETTINGS_WIRE_NAME_CLOSURE } from './settingsSchemaWireName.js';
|
|
8
|
+
import { SETTINGS_RESERVED_MEMBER_NAME_CLOSURE } from './settingsSchemaReservedMemberName.js';
|
|
7
9
|
import { SETTINGS_MCP_REQUEST_ENTRY_CLOSURE } from './settingsSchemaMcpRequestEntry.js';
|
|
8
10
|
import { SETTINGS_MCP_CONTENT_ORIGINS } from './settingsSchemaTables.js';
|
|
9
11
|
import { SETTINGS_URL_ALLOW_PATTERN_MATCHES_CLOSURE } from './settingsSchemaUrlPattern.js';
|
|
@@ -167,16 +169,20 @@ const SETTINGS_MCP_SERVER_NAME = SETTINGS_MCP_SERVER_NAME_CLOSURE();
|
|
|
167
169
|
export const SETTINGS_IS_RESERVED_MCP_SERVER_NAME = SETTINGS_MCP_SERVER_NAME.isReservedMcpServerName;
|
|
168
170
|
export const SETTINGS_REMOTE_MCP_SERVER_NAME_PREFIX = SETTINGS_MCP_SERVER_NAME.REMOTE_MCP_SERVER_NAME_PREFIX;
|
|
169
171
|
export const SETTINGS_RESERVED_MCP_SERVER_NAME_REASON = SETTINGS_MCP_SERVER_NAME.RESERVED_MCP_SERVER_NAME_REASON;
|
|
170
|
-
const
|
|
172
|
+
const SETTINGS_WIRE_NAME = SETTINGS_WIRE_NAME_CLOSURE();
|
|
173
|
+
export const SETTINGS_IS_USABLE_WIRE_NAME = SETTINGS_WIRE_NAME.isUsableWireName;
|
|
174
|
+
export const SETTINGS_TOOL_WIRE_NAME_MAX_CHARS = SETTINGS_WIRE_NAME.TOOL_WIRE_NAME_MAX_CHARS;
|
|
175
|
+
export const SETTINGS_HAS_EDGE_WHITESPACE = SETTINGS_WIRE_NAME.hasEdgeWhitespace;
|
|
176
|
+
const SETTINGS_RESERVED_MEMBER_NAME = SETTINGS_RESERVED_MEMBER_NAME_CLOSURE();
|
|
177
|
+
export const SETTINGS_IS_RESERVED_MEMBER_NAME = SETTINGS_RESERVED_MEMBER_NAME.isReservedMemberName;
|
|
178
|
+
const SETTINGS_MCP_REQUEST_ENTRY = SETTINGS_MCP_REQUEST_ENTRY_CLOSURE(SETTINGS_MCP_CONTENT_ORIGINS, SETTINGS_STARTS_WITH_HTTP_SCHEME, SETTINGS_ECHO_CALLER_TEXT, SETTINGS_UNINSPECTABLE, SETTINGS_CAPTURE_STRING_ARRAY, SETTINGS_DATA_DESCRIPTOR, SETTINGS_INSPECT, SETTINGS_OWN_FIELDS_OF, SETTINGS_OWN_VALUE_OF, SETTINGS_READ_KEY, SETTINGS_IS_JSON_ARRAY, SETTINGS_JSON_SHAPE_OF, SETTINGS_IS_RESERVED_MCP_SERVER_NAME, SETTINGS_RESERVED_MCP_SERVER_NAME_REASON, SETTINGS_TOOL_WIRE_NAME_MAX_CHARS, SETTINGS_HAS_EDGE_WHITESPACE, SETTINGS_IS_USABLE_WIRE_NAME, SETTINGS_IS_RESERVED_MEMBER_NAME);
|
|
171
179
|
export const SETTINGS_READ_REQUEST_MCP_TRANSPORT = SETTINGS_MCP_REQUEST_ENTRY.readRequestMcpTransport;
|
|
172
180
|
export const SETTINGS_READ_MCP_IDENTITY_HEADERS = SETTINGS_MCP_REQUEST_ENTRY.readMcpIdentityHeaders;
|
|
173
|
-
export const SETTINGS_IS_USABLE_WIRE_NAME = SETTINGS_MCP_REQUEST_ENTRY.isUsableWireName;
|
|
174
181
|
export const SETTINGS_DESCRIBE_BAD_WIRE_NAME = SETTINGS_MCP_REQUEST_ENTRY.describeBadWireName;
|
|
175
182
|
export const SETTINGS_IS_USABLE_MCP_SERVER_NAME = SETTINGS_MCP_REQUEST_ENTRY.isUsableMcpServerName;
|
|
176
183
|
export const SETTINGS_DESCRIBE_BAD_MCP_SERVER_NAME = SETTINGS_MCP_REQUEST_ENTRY.describeBadMcpServerName;
|
|
177
184
|
export const SETTINGS_IS_CONTENT_ORIGIN_WORD = SETTINGS_MCP_REQUEST_ENTRY.isContentOriginWord;
|
|
178
185
|
export const SETTINGS_DESCRIBE_BAD_CONTENT_ORIGIN = SETTINGS_MCP_REQUEST_ENTRY.describeBadContentOrigin;
|
|
179
|
-
export const SETTINGS_TOOL_WIRE_NAME_MAX_CHARS = SETTINGS_MCP_REQUEST_ENTRY.TOOL_WIRE_NAME_MAX_CHARS;
|
|
180
186
|
export const SETTINGS_URL_ALLOW_PATTERN_MATCHES = SETTINGS_URL_ALLOW_PATTERN_MATCHES_CLOSURE();
|
|
181
187
|
const SETTINGS_SAFETY_MERGE = SETTINGS_SAFETY_MERGE_CLOSURE(SETTINGS_MIN_TRUST_WORDS);
|
|
182
188
|
export const SETTINGS_IS_AT_LEAST = SETTINGS_SAFETY_MERGE.isAtLeast;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE: (MCP_CONTENT_ORIGINS: readonly ["local", "execution", "external"], startsWithHttpScheme: (raw: string) => boolean, echoCallerText: (text: string) => string, UNINSPECTABLE: "an object that could not be inspected (a proxy trap threw)", captureStringArray: (v: unknown, classification: "strict" | "wide") => string[] | undefined, dataDescriptor: (value: unknown) => PropertyDescriptor, inspect: (read: () => unknown) => object, ownFieldsOf: (record: object, keys: readonly string[]) => object, ownValueOf: (record: object, key: string) => object, readKey: (record: object, key: PropertyKey) => object, isJsonArray: (v: unknown) => v is unknown[], jsonShapeOf: (v: unknown) => "plain" | "non_plain_object" | "array" | "null" | "primitive" | "uninspectable", isReservedMcpServerName: (name: string) => boolean, RESERVED_MCP_SERVER_NAME_REASON: "the \"remote-\" prefix is reserved for the remote MCP servers a device executor offers") => any;
|
|
1
|
+
export declare const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE: (MCP_CONTENT_ORIGINS: readonly ["local", "execution", "external"], startsWithHttpScheme: (raw: string) => boolean, echoCallerText: (text: string) => string, UNINSPECTABLE: "an object that could not be inspected (a proxy trap threw)", captureStringArray: (v: unknown, classification: "strict" | "wide") => string[] | undefined, dataDescriptor: (value: unknown) => PropertyDescriptor, inspect: (read: () => unknown) => object, ownFieldsOf: (record: object, keys: readonly string[]) => object, ownValueOf: (record: object, key: string) => object, readKey: (record: object, key: PropertyKey) => object, isJsonArray: (v: unknown) => v is unknown[], jsonShapeOf: (v: unknown) => "plain" | "non_plain_object" | "array" | "null" | "primitive" | "uninspectable", isReservedMcpServerName: (name: string) => boolean, RESERVED_MCP_SERVER_NAME_REASON: "the \"remote-\" prefix is reserved for the remote MCP servers a device executor offers", TOOL_WIRE_NAME_MAX_CHARS: 128, hasEdgeWhitespace: (v: string) => boolean, isUsableWireName: (v: unknown) => v is string, isReservedMemberName: (name: string) => boolean) => any;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE = (MCP_CONTENT_ORIGINS, startsWithHttpScheme, echoCallerText, UNINSPECTABLE, captureStringArray, dataDescriptor, inspect, ownFieldsOf, ownValueOf, readKey, isJsonArray, jsonShapeOf, isReservedMcpServerName, RESERVED_MCP_SERVER_NAME_REASON) => {
|
|
1
|
+
export const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE = (MCP_CONTENT_ORIGINS, startsWithHttpScheme, echoCallerText, UNINSPECTABLE, captureStringArray, dataDescriptor, inspect, ownFieldsOf, ownValueOf, readKey, isJsonArray, jsonShapeOf, isReservedMcpServerName, RESERVED_MCP_SERVER_NAME_REASON, TOOL_WIRE_NAME_MAX_CHARS, hasEdgeWhitespace, isUsableWireName, isReservedMemberName) => {
|
|
2
2
|
function describeKindWord(v) {
|
|
3
3
|
const shape = jsonShapeOf(v);
|
|
4
4
|
switch (shape) {
|
|
@@ -46,11 +46,6 @@ export const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE = (MCP_CONTENT_ORIGINS, startsWi
|
|
|
46
46
|
function quotedCallerText(text) {
|
|
47
47
|
return `"${echoCallerText(text)}"`;
|
|
48
48
|
}
|
|
49
|
-
const TOOL_WIRE_NAME_MAX_CHARS = 128;
|
|
50
|
-
const hasEdgeWhitespace = (v) => v.trim() !== v;
|
|
51
|
-
function isUsableWireName(v) {
|
|
52
|
-
return typeof v === "string" && v.length > 0 && v.length <= TOOL_WIRE_NAME_MAX_CHARS && !hasEdgeWhitespace(v);
|
|
53
|
-
}
|
|
54
49
|
function describeBadWireName(v) {
|
|
55
50
|
if (typeof v !== "string")
|
|
56
51
|
return describeKindWord(v);
|
|
@@ -202,8 +197,7 @@ export const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE = (MCP_CONTENT_ORIGINS, startsWi
|
|
|
202
197
|
}
|
|
203
198
|
return { ok: true, value: { kind: "other", value: kind.value } };
|
|
204
199
|
}
|
|
205
|
-
const
|
|
206
|
-
const RESERVED_MEMBER_FAULT = `no member of a declaration may be named "${PLAIN_STRING_RECORD_RESERVED_MEMBER}"`;
|
|
200
|
+
const reservedMemberFault = (name) => `no member of a declaration may be named "${name}"`;
|
|
207
201
|
function notPlainDetail(shape, v) {
|
|
208
202
|
switch (shape) {
|
|
209
203
|
case "null":
|
|
@@ -233,28 +227,25 @@ export const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE = (MCP_CONTENT_ORIGINS, startsWi
|
|
|
233
227
|
return { ok: false, fault: "not_plain_record", detail: `got ${namesRead.sentence}` };
|
|
234
228
|
const names = namesRead.value;
|
|
235
229
|
const members = Object.create(null);
|
|
236
|
-
|
|
230
|
+
const reservedMembers = names.filter(isReservedMemberName);
|
|
237
231
|
for (const name of names) {
|
|
238
232
|
const read = readKey(v, name);
|
|
239
233
|
const unreadable = read.presence === "unreadable";
|
|
240
234
|
const value = read.presence === "own" ? read.value : undefined;
|
|
241
235
|
if (unreadable || typeof value !== "string") {
|
|
242
236
|
const valueFault = unreadable ? "could not be read (its getter threw)" : `must be a string — got ${describeValueShape(value)}`;
|
|
243
|
-
const
|
|
244
|
-
const fault = reserved ? "member_name_reserved" : "member_not_string";
|
|
237
|
+
const fault = isReservedMemberName(name) ? "member_name_reserved" : "member_not_string";
|
|
245
238
|
return {
|
|
246
239
|
ok: false,
|
|
247
240
|
fault,
|
|
248
241
|
member: echoCallerText(name),
|
|
249
|
-
detail: `its member "${echoCallerText(name)}" ${
|
|
242
|
+
detail: `its member "${echoCallerText(name)}" ${isReservedMemberName(name) ? `is not allowed (${reservedMemberFault(name)}) and its value ${valueFault}` : valueFault}`,
|
|
250
243
|
};
|
|
251
244
|
}
|
|
252
|
-
if (name
|
|
253
|
-
reservedMember = true;
|
|
254
|
-
else
|
|
245
|
+
if (!isReservedMemberName(name))
|
|
255
246
|
Object.defineProperty(members, name, dataDescriptor(value));
|
|
256
247
|
}
|
|
257
|
-
return { ok: true, record: { ...members },
|
|
248
|
+
return { ok: true, record: { ...members }, reservedMembers };
|
|
258
249
|
}
|
|
259
250
|
const issuesOf = (...candidates) => candidates.filter((c) => c !== undefined);
|
|
260
251
|
function readTransportRecord(path, raw) {
|
|
@@ -269,8 +260,8 @@ export const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE = (MCP_CONTENT_ORIGINS, startsWi
|
|
|
269
260
|
}
|
|
270
261
|
return {
|
|
271
262
|
record: read.record,
|
|
272
|
-
issues: read.
|
|
263
|
+
issues: read.reservedMembers.map((name) => ({ path: `${path}.${name}`, reason: reservedMemberFault(name), member: name, fault: "member_name_reserved" })),
|
|
273
264
|
};
|
|
274
265
|
}
|
|
275
|
-
return { readRequestMcpTransport, readMcpIdentityHeaders,
|
|
266
|
+
return { readRequestMcpTransport, readMcpIdentityHeaders, describeBadWireName, isUsableMcpServerName, describeBadMcpServerName, isContentOriginWord, describeBadContentOrigin };
|
|
276
267
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SETTINGS_RESERVED_MEMBER_NAME_CLOSURE: () => any;
|
|
@@ -13,3 +13,5 @@ export declare const SETTINGS_UI_LANGUAGE_VALUES: readonly ["en", "zh"];
|
|
|
13
13
|
export declare const SETTINGS_MCP_CONTENT_ORIGINS: readonly ["local", "execution", "external"];
|
|
14
14
|
export declare const SETTINGS_MIN_TRUST_WORDS: readonly ["local", "session", "project", "global", "managed", "task"];
|
|
15
15
|
export declare const SETTINGS_WORKSPACE_TRUST_STATES: readonly ["accepted", "declined", "no_trust_step"];
|
|
16
|
+
export declare const SETTINGS_MODEL_PLANE_REFUSAL_CODES: readonly ["config.default_model_missing", "config.model_refused_name_minted", "config.model_route_endpoint_missing", "config.gateway_fallback_without_primary", "config.catalog_replaces_env_models"];
|
|
17
|
+
export declare const SETTINGS_NO_EXECUTION_TARGET_LANES: readonly ["none"];
|
|
@@ -63,3 +63,13 @@ export const SETTINGS_WORKSPACE_TRUST_STATES = Object.freeze([
|
|
|
63
63
|
"declined",
|
|
64
64
|
"no_trust_step",
|
|
65
65
|
]);
|
|
66
|
+
export const SETTINGS_MODEL_PLANE_REFUSAL_CODES = Object.freeze([
|
|
67
|
+
"config.default_model_missing",
|
|
68
|
+
"config.model_refused_name_minted",
|
|
69
|
+
"config.model_route_endpoint_missing",
|
|
70
|
+
"config.gateway_fallback_without_primary",
|
|
71
|
+
"config.catalog_replaces_env_models",
|
|
72
|
+
]);
|
|
73
|
+
export const SETTINGS_NO_EXECUTION_TARGET_LANES = Object.freeze([
|
|
74
|
+
"none",
|
|
75
|
+
]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SETTINGS_WIRE_NAME_CLOSURE: () => any;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const SETTINGS_WIRE_NAME_CLOSURE = () => {
|
|
2
|
+
const TOOL_WIRE_NAME_MAX_CHARS = 128;
|
|
3
|
+
const hasEdgeWhitespace = (v) => v.trim() !== v;
|
|
4
|
+
function isUsableWireName(v) {
|
|
5
|
+
return typeof v === "string" && v.length > 0 && v.length <= TOOL_WIRE_NAME_MAX_CHARS && !hasEdgeWhitespace(v);
|
|
6
|
+
}
|
|
7
|
+
return { isUsableWireName, TOOL_WIRE_NAME_MAX_CHARS, hasEdgeWhitespace };
|
|
8
|
+
};
|
|
@@ -53,7 +53,7 @@ export async function* withHeadlessR1Reconnect(live, deps) {
|
|
|
53
53
|
let attempts = 0;
|
|
54
54
|
let lastSeenSeq;
|
|
55
55
|
const probe = deps.probeAlive ?? probeEngineAlive;
|
|
56
|
-
let
|
|
56
|
+
let tearShape;
|
|
57
57
|
const drains = createStreamDrainingLegs();
|
|
58
58
|
let drainReopenAfterMs;
|
|
59
59
|
let lastBreak;
|
|
@@ -62,6 +62,11 @@ export async function* withHeadlessR1Reconnect(live, deps) {
|
|
|
62
62
|
registerRunNotFollowed(originalTearErr, fact);
|
|
63
63
|
throw originalTearErr;
|
|
64
64
|
};
|
|
65
|
+
const unboundHandle = (cause) => {
|
|
66
|
+
if (tearShape === 'transport')
|
|
67
|
+
throw originalTearErr;
|
|
68
|
+
return giveUp(mintRunNotFollowed(cause));
|
|
69
|
+
};
|
|
65
70
|
const terminalFromRunRow = async (taskId) => {
|
|
66
71
|
const row = await deps.getRun(taskId).catch(() => null);
|
|
67
72
|
const terminal = terminalEventFromRunRow(row);
|
|
@@ -72,21 +77,21 @@ export async function* withHeadlessR1Reconnect(live, deps) {
|
|
|
72
77
|
for (;;) {
|
|
73
78
|
if (deps.signal?.aborted)
|
|
74
79
|
throw originalTearErr;
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
if (
|
|
80
|
+
if (tearShape === undefined)
|
|
81
|
+
tearShape = isSseIdleError(originalTearErr) ? 'idle' : guardedTransport(originalTearErr) ? 'transport' : 'other';
|
|
82
|
+
if (tearShape === 'other')
|
|
78
83
|
throw originalTearErr;
|
|
79
84
|
let handle;
|
|
80
85
|
try {
|
|
81
86
|
handle = deps.getTaskId();
|
|
82
87
|
}
|
|
83
88
|
catch {
|
|
84
|
-
return
|
|
89
|
+
return unboundHandle('bad_input');
|
|
85
90
|
}
|
|
86
91
|
if (handle === null || handle === undefined)
|
|
87
|
-
return
|
|
92
|
+
return unboundHandle('no_run_id');
|
|
88
93
|
if (typeof handle !== 'string' || handle === '')
|
|
89
|
-
return
|
|
94
|
+
return unboundHandle('bad_input');
|
|
90
95
|
const taskId = handle;
|
|
91
96
|
if (drainReopenAfterMs !== undefined) {
|
|
92
97
|
const waitMs = drainReopenAfterMs;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ApprovalAskReasonByHook {
|
|
2
|
+
readonly by: 'hook';
|
|
3
|
+
readonly cause: string;
|
|
4
|
+
readonly registration?: string;
|
|
5
|
+
readonly words?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ApprovalAskReasonByPolicy {
|
|
8
|
+
readonly by: string;
|
|
9
|
+
readonly words: string;
|
|
10
|
+
}
|
|
11
|
+
export type ApprovalAskReason = ApprovalAskReasonByHook | ApprovalAskReasonByPolicy;
|
|
12
|
+
export declare function approvalAskReasonsOf(carrier: object | null | undefined): readonly ApprovalAskReason[] | undefined;
|
|
13
|
+
export declare function approvalAgentIdOf(carrier: object | null | undefined): string | undefined;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { appendOwnElement } from '../ownKey.js';
|
|
2
|
+
import { slotReadOf } from '../wireFailureShape.js';
|
|
3
|
+
function ownNonEmptyText(o, key) {
|
|
4
|
+
const r = slotReadOf(o, key);
|
|
5
|
+
return r.presence === 'present' && typeof r.value === 'string' && r.value !== '' ? r.value : undefined;
|
|
6
|
+
}
|
|
7
|
+
function optionalText(o, key) {
|
|
8
|
+
const r = slotReadOf(o, key);
|
|
9
|
+
if (r.presence === 'absent')
|
|
10
|
+
return { state: 'absent' };
|
|
11
|
+
if (r.presence === 'present' && typeof r.value === 'string')
|
|
12
|
+
return { state: 'text', value: r.value };
|
|
13
|
+
return { state: 'bad' };
|
|
14
|
+
}
|
|
15
|
+
function askReasonOf(item) {
|
|
16
|
+
if (typeof item !== 'object' || item === null)
|
|
17
|
+
return undefined;
|
|
18
|
+
const by = ownNonEmptyText(item, 'by');
|
|
19
|
+
if (by === undefined)
|
|
20
|
+
return undefined;
|
|
21
|
+
const words = optionalText(item, 'words');
|
|
22
|
+
if (words.state === 'bad')
|
|
23
|
+
return undefined;
|
|
24
|
+
if (by === 'hook') {
|
|
25
|
+
const cause = ownNonEmptyText(item, 'cause');
|
|
26
|
+
if (cause === undefined)
|
|
27
|
+
return undefined;
|
|
28
|
+
const registration = optionalText(item, 'registration');
|
|
29
|
+
if (registration.state === 'bad')
|
|
30
|
+
return undefined;
|
|
31
|
+
return Object.freeze({
|
|
32
|
+
by: 'hook',
|
|
33
|
+
cause,
|
|
34
|
+
...(registration.state === 'text' ? { registration: registration.value } : {}),
|
|
35
|
+
...(words.state === 'text' ? { words: words.value } : {}),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (words.state !== 'text')
|
|
39
|
+
return undefined;
|
|
40
|
+
return Object.freeze({ by, words: words.value });
|
|
41
|
+
}
|
|
42
|
+
export function approvalAskReasonsOf(carrier) {
|
|
43
|
+
try {
|
|
44
|
+
if (typeof carrier !== 'object' || carrier === null)
|
|
45
|
+
return undefined;
|
|
46
|
+
const slot = slotReadOf(carrier, 'askReasons');
|
|
47
|
+
if (slot.presence !== 'present')
|
|
48
|
+
return undefined;
|
|
49
|
+
const raw = slot.value;
|
|
50
|
+
if (typeof raw !== 'object' || raw === null || !Array.isArray(raw))
|
|
51
|
+
return undefined;
|
|
52
|
+
const len = slotReadOf(raw, 'length');
|
|
53
|
+
if (len.presence !== 'present' || typeof len.value !== 'number' || !Number.isSafeInteger(len.value) || len.value < 0)
|
|
54
|
+
return undefined;
|
|
55
|
+
const out = [];
|
|
56
|
+
for (let i = 0; i < len.value; i++) {
|
|
57
|
+
const el = slotReadOf(raw, String(i));
|
|
58
|
+
if (el.presence !== 'present')
|
|
59
|
+
return undefined;
|
|
60
|
+
const reason = askReasonOf(el.value);
|
|
61
|
+
if (reason !== undefined)
|
|
62
|
+
appendOwnElement(out, reason);
|
|
63
|
+
}
|
|
64
|
+
return out.length === 0 ? undefined : Object.freeze(out);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function approvalAgentIdOf(carrier) {
|
|
71
|
+
try {
|
|
72
|
+
if (typeof carrier !== 'object' || carrier === null)
|
|
73
|
+
return undefined;
|
|
74
|
+
return ownNonEmptyText(carrier, 'agentId');
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DecideReceiptView } from '../decideReceipt.js';
|
|
2
2
|
import { type HitlSafetyCode } from './hitlBridge.js';
|
|
3
3
|
import type { AskAnsweredOutput } from './gateLedger.js';
|
|
4
|
+
import type { PolicyDenyCause } from './policyDenyCause.js';
|
|
4
5
|
import type { ApprovalDenySettledBy, ToolApprovalRespondAckView, ToolApprovalRespondDecision, ToolApprovalRespondParkingView } from './toolApprovalWire.js';
|
|
5
6
|
import { type DecisionRefusalReading, type RefusalRouteContext } from './decisionRefusal.js';
|
|
6
7
|
import { type DeliveredReading, type LadderSafetyStop } from './attributionLadder.js';
|
|
@@ -14,6 +15,7 @@ export type ApprovalUnsettledCause = (typeof APPROVAL_UNSETTLED_CAUSES)[number];
|
|
|
14
15
|
export interface ApprovalDenyFacts {
|
|
15
16
|
readonly settledBy?: ApprovalDenySettledBy;
|
|
16
17
|
readonly reason?: string;
|
|
18
|
+
readonly policyCause?: PolicyDenyCause;
|
|
17
19
|
readonly attributionKey?: 'dropped' | 'renamed';
|
|
18
20
|
}
|
|
19
21
|
interface ApprovalResolutionBase {
|
|
@@ -53,6 +55,7 @@ export declare function approvalUnsettledCause(r: ApprovalResolution): ApprovalU
|
|
|
53
55
|
export declare const APPROVAL_NOTE_RETRACTED_DETAIL = "the card was retracted (this host no longer has a decision port for it)";
|
|
54
56
|
export declare const APPROVAL_NOTE_EDIT_REFUSED_DETAIL = "edits are not accepted on this card";
|
|
55
57
|
export declare function approvalResolutionDetail(r: ApprovalResolution): string | undefined;
|
|
58
|
+
export declare function approvalResolutionStatusTag(r: ApprovalResolution): string;
|
|
56
59
|
export declare function unsettledCauseOfReading(reading: DecisionRefusalReading): 'engine_refused' | 'engine_error' | 'no_answer';
|
|
57
60
|
export interface DecisionFailureMint {
|
|
58
61
|
readonly lane: ApprovalResolutionLane;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { DecideTransportRetryExhaustedError, refusalCarrierOf, safetyStopHeadOf, safetyStopNamed } from './hitlBridge.js';
|
|
2
|
-
import { mintDecisionRefusalReading } from './decisionRefusal.js';
|
|
2
|
+
import { decisionStatusTag, mintDecisionRefusalReading } from './decisionRefusal.js';
|
|
3
3
|
import { isSlotCarrier, thrownIsInstanceOf } from '../wireFailureShape.js';
|
|
4
4
|
import { carrierReadOf, isLocalSafetyStop, localCodeReadOf, topCauseReadOf } from './attributionLadder.js';
|
|
5
5
|
import { directFailureReadingOf, transportReadingOf } from './approvalDelivery.js';
|
|
6
6
|
import { ownReadingSlot } from '../engineWireFor.js';
|
|
7
|
-
import { CHECKPOINT_ROW_BAR_SENTENCE } from '../checkpointRowVerdict.js';
|
|
8
|
-
import { msg, renderMessage } from '../i18n/translate.js';
|
|
7
|
+
import { CHECKPOINT_ROW_BAR_SENTENCE, unboundWayOutContent } from '../checkpointRowVerdict.js';
|
|
9
8
|
export const APPROVAL_RESOLUTION_LANES = Object.freeze(['respond', 'decide', 'ask']);
|
|
10
9
|
export const APPROVAL_NOT_SENT_CAUSES = Object.freeze([
|
|
11
10
|
'retracted',
|
|
@@ -95,7 +94,7 @@ export function approvalResolutionDetail(r) {
|
|
|
95
94
|
const code = cause === 'safety_stop' ? ownStr(r, 'safetyCode') : undefined;
|
|
96
95
|
if (code === undefined)
|
|
97
96
|
return sentence;
|
|
98
|
-
return code === 'binding_missing' ? `${sentence} (${code}) · ${
|
|
97
|
+
return code === 'binding_missing' ? `${sentence} (${code}) · ${unboundWayOutContent('unknown')}` : `${sentence} (${code})`;
|
|
99
98
|
}
|
|
100
99
|
if (kind !== 'unsettled')
|
|
101
100
|
return undefined;
|
|
@@ -110,6 +109,25 @@ export function approvalResolutionDetail(r) {
|
|
|
110
109
|
const parts = [ownStr(refusal, 'errorCode'), ownStr(r, 'detail') ?? ownStr(refusal, 'message')].filter((x) => x !== undefined);
|
|
111
110
|
return parts.length > 0 ? parts.join(' · ') : undefined;
|
|
112
111
|
}
|
|
112
|
+
export function approvalResolutionStatusTag(r) {
|
|
113
|
+
try {
|
|
114
|
+
if (typeof r !== 'object' || r === null)
|
|
115
|
+
return '';
|
|
116
|
+
const kd = Object.getOwnPropertyDescriptor(r, 'kind');
|
|
117
|
+
if (kd === undefined || !Object.hasOwn(kd, 'value') || kd.value !== 'unsettled')
|
|
118
|
+
return '';
|
|
119
|
+
const rd = Object.getOwnPropertyDescriptor(r, 'refusal');
|
|
120
|
+
const refusal = rd !== undefined && Object.hasOwn(rd, 'value') ? rd.value : undefined;
|
|
121
|
+
if (typeof refusal !== 'object' || refusal === null)
|
|
122
|
+
return '';
|
|
123
|
+
const sd = Object.getOwnPropertyDescriptor(refusal, 'status');
|
|
124
|
+
const status = sd !== undefined && Object.hasOwn(sd, 'value') ? sd.value : undefined;
|
|
125
|
+
return typeof status === 'number' && Number.isInteger(status) && status >= 400 && status <= 599 ? decisionStatusTag(status) : '';
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return '';
|
|
129
|
+
}
|
|
130
|
+
}
|
|
113
131
|
export function unsettledCauseOfReading(reading) {
|
|
114
132
|
const standing = ownReadingSlot(reading, 'standing');
|
|
115
133
|
if (standing === 'ambiguous')
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { hostLog } from '../host.js';
|
|
2
|
+
import { invokeHostCallbackIsolated } from '../hostCallbackGuard.js';
|
|
2
3
|
import { unrefTimer } from '../unrefTimer.js';
|
|
3
4
|
import { readLivePendingRows } from './livePendingAsk.js';
|
|
4
5
|
import { createStreamDrainingLegs } from '../streamDrainingLegs.js';
|
|
@@ -176,12 +177,7 @@ export function startApprovalsFeed(client, onSnapshot, opts) {
|
|
|
176
177
|
const at = Date.now();
|
|
177
178
|
blind = { why, at };
|
|
178
179
|
stats.unknowns++;
|
|
179
|
-
|
|
180
|
-
onSnapshot({ kind: 'unknown', why, at, mode: via });
|
|
181
|
-
}
|
|
182
|
-
catch (e) {
|
|
183
|
-
hostLog('debug', `approvalsFeed: subscriber threw on the unknown arm (swallowed): ${String(e)}`);
|
|
184
|
-
}
|
|
180
|
+
invokeHostCallbackIsolated('approvalsFeed: subscriber (unknown arm)', () => onSnapshot({ kind: 'unknown', why, at, mode: via }));
|
|
185
181
|
}
|
|
186
182
|
async function take(via, leg) {
|
|
187
183
|
if (stopped)
|
|
@@ -293,12 +289,7 @@ export function startApprovalsFeed(client, onSnapshot, opts) {
|
|
|
293
289
|
};
|
|
294
290
|
last = snap;
|
|
295
291
|
stats.snapshots++;
|
|
296
|
-
|
|
297
|
-
onSnapshot(snap);
|
|
298
|
-
}
|
|
299
|
-
catch (e) {
|
|
300
|
-
hostLog('debug', `approvalsFeed: subscriber threw (swallowed): ${String(e)}`);
|
|
301
|
-
}
|
|
292
|
+
invokeHostCallbackIsolated('approvalsFeed: subscriber', () => onSnapshot(snap));
|
|
302
293
|
}
|
|
303
294
|
function schedulePoll() {
|
|
304
295
|
if (stopped || ac.signal.aborted)
|
|
@@ -37,6 +37,7 @@ export function classifyAskParkRows(queueRows, taskId, deps) {
|
|
|
37
37
|
kind: 'settled',
|
|
38
38
|
reason: renderMessage(msg('approval.rowUnresumable.askNotSurfaced', { taskId: String(pending.taskId), sentence: checkpointRowBarSentence(bar) })),
|
|
39
39
|
rowVerdict: bar,
|
|
40
|
+
rowTaskId: askParkRowTaskIdOf(taskId, pending),
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
if (foreignKind !== null) {
|
|
@@ -50,8 +51,11 @@ export function classifyAskParkRows(queueRows, taskId, deps) {
|
|
|
50
51
|
function askParkRowGateKind(row) {
|
|
51
52
|
return typeof row.gateKind === 'string' && row.gateKind.length > 0 ? row.gateKind : null;
|
|
52
53
|
}
|
|
54
|
+
function askParkRowTaskIdOf(taskId, row) {
|
|
55
|
+
return typeof row.taskId === 'string' && row.taskId.length > 0 ? row.taskId : taskId;
|
|
56
|
+
}
|
|
53
57
|
export function askParkRowIdentity(taskId, row) {
|
|
54
|
-
const rowTaskId =
|
|
58
|
+
const rowTaskId = askParkRowTaskIdOf(taskId, row);
|
|
55
59
|
const gatedCallId = row.toolCallId ?? row.boundCallId ?? undefined;
|
|
56
60
|
return { rowTaskId, gatedCallId, armedKey: approvalCallKey(gatedCallId, rowTaskId) };
|
|
57
61
|
}
|
|
@@ -78,5 +78,6 @@ export interface UndeliverableDecisionFacts {
|
|
|
78
78
|
readonly end: UndeliverableDecisionEnd;
|
|
79
79
|
readonly runId?: string;
|
|
80
80
|
}
|
|
81
|
+
export declare function decisionStatusTag(status: number, errorCode?: string): string;
|
|
81
82
|
export declare function undeliverableDecisionContent(facts: UndeliverableDecisionFacts): string;
|
|
82
83
|
export declare function decideRowUnrevivableNotice(lang?: UiLanguage | (string & {})): string;
|
|
@@ -314,9 +314,12 @@ export function decisionRefusalClosesOut(refusal, pending) {
|
|
|
314
314
|
return false;
|
|
315
315
|
return standing === 'ambiguous' || standing === 'refused-pending';
|
|
316
316
|
}
|
|
317
|
+
export function decisionStatusTag(status, errorCode) {
|
|
318
|
+
const code = typeof errorCode === 'string' && isDisplayableWireCode(errorCode) ? ` ${errorCode}` : '';
|
|
319
|
+
return `(HTTP ${String(status)}${code})`;
|
|
320
|
+
}
|
|
317
321
|
export function undeliverableDecisionContent(facts) {
|
|
318
|
-
const
|
|
319
|
-
const head = `The engine refused the approval decision this client sent (HTTP ${String(facts.status)}${code}), so the call it asked about could not be answered from here and did not run`;
|
|
322
|
+
const head = `The engine refused the approval decision this client sent ${decisionStatusTag(facts.status, facts.errorCode)}, so the call it asked about could not be answered from here and did not run`;
|
|
320
323
|
const runId = typeof facts.runId === 'string' && isDisplayableWireCode(facts.runId) ? ` ${facts.runId}` : '';
|
|
321
324
|
switch (facts.end) {
|
|
322
325
|
case 'run-stopped':
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { settleWithinDeadline } from '../abortableSleep.js';
|
|
2
2
|
import { hostLog } from '../host.js';
|
|
3
|
+
import { invokeHostCallbackIsolated } from '../hostCallbackGuard.js';
|
|
3
4
|
import { msg, renderMessage } from '../i18n/translate.js';
|
|
4
5
|
import { askGoneFromError } from '../decideReceipt.js';
|
|
5
6
|
import { appendOwnElement, guardedRead, readOwnDataNonEmptyString, readOwnDataValue } from '../ownKey.js';
|
|
@@ -343,12 +344,7 @@ function holdFits(handle, req) {
|
|
|
343
344
|
}
|
|
344
345
|
}
|
|
345
346
|
function callHold(call) {
|
|
346
|
-
|
|
347
|
-
call();
|
|
348
|
-
}
|
|
349
|
-
catch (e) {
|
|
350
|
-
hostLog('debug', `decisionSend.callHold: ${String(e).slice(0, 120)}`);
|
|
351
|
-
}
|
|
347
|
+
invokeHostCallbackIsolated('decisionSend: hold verb', call);
|
|
352
348
|
}
|
|
353
349
|
function hostField(holder, key) {
|
|
354
350
|
if (typeof holder !== 'object' || holder === null)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { AgentEvent } from '@sema-agent/sdk';
|
|
2
2
|
import type { DecideOperationObserver, HitlClientLike } from './hitlBridge.js';
|
|
3
3
|
import { type RespondToolApprovalFn, type ToolApprovalFrame, type ToolApprovalFrameLaneOpts } from './toolApprovalWire.js';
|
|
4
|
-
import type { ApprovalResolution } from './approvalResolution.js';
|
|
5
|
-
import type { GateLedger } from './gateLedger.js';
|
|
4
|
+
import type { ApprovalDenyFacts, ApprovalResolution } from './approvalResolution.js';
|
|
5
|
+
import type { GateLedger, GateDenyAttribution } from './gateLedger.js';
|
|
6
6
|
import type { NoAllowCause } from './noAllowCause.js';
|
|
7
7
|
import { type ReplayedApprovalDisposition } from './replayedApproval.js';
|
|
8
8
|
import type { ReattachDrainingEvent } from '../runReattachPolicy.js';
|
|
@@ -17,6 +17,7 @@ export interface PolicyDenyReasonFacts {
|
|
|
17
17
|
readonly budgetSetting?: string;
|
|
18
18
|
}
|
|
19
19
|
export declare function policyDenyReason(facts: PolicyDenyReasonFacts): string;
|
|
20
|
+
export declare function denyAttributionOf(deny: ApprovalDenyFacts | undefined): GateDenyAttribution;
|
|
20
21
|
export declare const HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE = "[Request interrupted by user for tool use]";
|
|
21
22
|
export declare const ENGINE_ABORT_TOOL_RESULT = "Operation aborted";
|
|
22
23
|
export interface ParkReattachNotice {
|
package/dist/hitl/frameRouter.js
CHANGED
|
@@ -13,6 +13,8 @@ import { surfaceForCurrentSession, surfaceReplayedApprovalListUnreadable } from
|
|
|
13
13
|
import { liveCardHoldOf, noteEngineClosedApproval, settleEngineClosedApproval } from './approvalHolds.js';
|
|
14
14
|
import { approvalCompleteParked } from './approvalCompleteParked.js';
|
|
15
15
|
import { liveFrameCallKey } from './gateIdentity.js';
|
|
16
|
+
import { readPolicyDenyCause } from './policyDenyCause.js';
|
|
17
|
+
import { msg, renderMessage } from '../i18n/translate.js';
|
|
16
18
|
import { SEMA_DENIAL_KIND_KEY, hasLedgerPositionKey } from './gateLedger.js';
|
|
17
19
|
import { replayedApprovalClosesCardFrame, replayedApprovalDisposition, settledApprovalDisposition } from './replayedApproval.js';
|
|
18
20
|
import { settleWithinDeadline } from '../abortableSleep.js';
|
|
@@ -64,10 +66,33 @@ export function policyDenyReason(facts) {
|
|
|
64
66
|
function denyOutputForRender(attribution) {
|
|
65
67
|
if (attribution?.settledBy !== 'policy')
|
|
66
68
|
return HITL_REJECT_MESSAGE;
|
|
69
|
+
const head = policyDenyHeadFor(readPolicyDenyCause(attribution));
|
|
67
70
|
const reason = attribution.reason;
|
|
68
71
|
return reason !== undefined && reason.trim() !== ''
|
|
69
|
-
? `${
|
|
70
|
-
:
|
|
72
|
+
? `${head}\n${reason}`
|
|
73
|
+
: head;
|
|
74
|
+
}
|
|
75
|
+
function policyDenyHeadFor(cause) {
|
|
76
|
+
const tail = msg('approval.policyDeny.tail');
|
|
77
|
+
switch (cause) {
|
|
78
|
+
case 'dont_ask':
|
|
79
|
+
return renderMessage(msg('approval.policyDeny.dontAsk', { tail }));
|
|
80
|
+
case 'deny_rule':
|
|
81
|
+
return renderMessage(msg('approval.policyDeny.denyRule', { tail }));
|
|
82
|
+
case 'engine_floor':
|
|
83
|
+
return renderMessage(msg('approval.policyDeny.engineFloor', { tail }));
|
|
84
|
+
case 'no_approval_ui':
|
|
85
|
+
case undefined:
|
|
86
|
+
return HITL_POLICY_DENY_MESSAGE;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export function denyAttributionOf(deny) {
|
|
90
|
+
const policyCause = readPolicyDenyCause(deny);
|
|
91
|
+
return {
|
|
92
|
+
...(deny?.settledBy !== undefined ? { settledBy: deny.settledBy } : {}),
|
|
93
|
+
...(deny?.reason !== undefined ? { reason: deny.reason } : {}),
|
|
94
|
+
...(policyCause !== undefined ? { policyCause } : {}),
|
|
95
|
+
};
|
|
71
96
|
}
|
|
72
97
|
function denialKindForTranscript(attribution) {
|
|
73
98
|
return ccToolDenialKindForSettledBy(attribution?.settledBy);
|
|
@@ -354,10 +379,7 @@ function settleLiveCardOutcome(ev, outcome, ctx, fromSubagent, gatedCallId) {
|
|
|
354
379
|
invokeHostCallbackIsolated('liveHitlAskWire: onToolApprovalOutcome', () => deps.onToolApprovalOutcome?.(ev, outcome));
|
|
355
380
|
}
|
|
356
381
|
if (outcome.kind === 'decided' && outcome.decision === 'deny' && !fromSubagent) {
|
|
357
|
-
const attribution =
|
|
358
|
-
...(outcome.deny?.settledBy !== undefined ? { settledBy: outcome.deny.settledBy } : {}),
|
|
359
|
-
...(outcome.deny?.reason !== undefined ? { reason: outcome.deny.reason } : {}),
|
|
360
|
-
};
|
|
382
|
+
const attribution = denyAttributionOf(outcome.deny);
|
|
361
383
|
if (gatedCallId !== undefined)
|
|
362
384
|
led.markDenied(gatedCallId, attribution);
|
|
363
385
|
else
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { AgentEvent } from '@sema-agent/sdk';
|
|
2
|
+
import { type PolicyDenyCause } from './policyDenyCause.js';
|
|
2
3
|
export declare const SEMA_COLLATERAL_ABORT_KEY = "_sema_collateral_abort";
|
|
3
4
|
export declare const SEMA_DENIAL_KIND_KEY = "_sema_denial_kind";
|
|
4
5
|
export interface GateDenyAttribution {
|
|
5
6
|
settledBy?: 'human' | 'policy';
|
|
6
7
|
reason?: string;
|
|
8
|
+
policyCause?: PolicyDenyCause;
|
|
7
9
|
}
|
|
8
10
|
export interface AskAnsweredOutput {
|
|
9
11
|
type: 'ask-user-question';
|
package/dist/hitl/gateLedger.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parkedToolEndRoleOf } from '../engineRowRef.js';
|
|
2
2
|
import { inheritFrameBinding } from '../frameBinding.js';
|
|
3
|
+
import { readPolicyDenyCause } from './policyDenyCause.js';
|
|
3
4
|
export const SEMA_COLLATERAL_ABORT_KEY = '_sema_collateral_abort';
|
|
4
5
|
export const SEMA_DENIAL_KIND_KEY = '_sema_denial_kind';
|
|
5
6
|
export function durableSeqOf(ev) {
|
|
@@ -27,9 +28,10 @@ function normalizeDenyAttribution(a) {
|
|
|
27
28
|
return undefined;
|
|
28
29
|
const settledBy = a.settledBy === 'human' || a.settledBy === 'policy' ? a.settledBy : undefined;
|
|
29
30
|
const reason = typeof a.reason === 'string' && a.reason.trim() !== '' ? a.reason : undefined;
|
|
31
|
+
const policyCause = settledBy === 'policy' ? readPolicyDenyCause(a) : undefined;
|
|
30
32
|
if (settledBy === undefined && reason === undefined)
|
|
31
33
|
return undefined;
|
|
32
|
-
return { ...(settledBy !== undefined ? { settledBy } : {}), ...(reason !== undefined ? { reason } : {}) };
|
|
34
|
+
return { ...(settledBy !== undefined ? { settledBy } : {}), ...(reason !== undefined ? { reason } : {}), ...(policyCause !== undefined ? { policyCause } : {}) };
|
|
33
35
|
}
|
|
34
36
|
export function createGateLedger() {
|
|
35
37
|
const startedCalls = new Set();
|