@sema-agent/client-core 0.103.0 → 0.104.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +16 -13
  3. package/dist/adapter/downstream/eventToSdkMessage.js +2 -0
  4. package/dist/adapter/downstream/terminalToSdkResult.d.ts +0 -1
  5. package/dist/adapter/downstream/terminalToSdkResult.js +3 -1
  6. package/dist/agentSession/engineAgentRegistryRead.js +3 -0
  7. package/dist/coreValuePorts.d.ts +3 -1
  8. package/dist/coreValuePorts.js +5 -0
  9. package/dist/deviceRebind.d.ts +17 -4
  10. package/dist/deviceRebind.js +43 -14
  11. package/dist/engineAgentAbsence.d.ts +1 -0
  12. package/dist/executionPlacementWords.d.ts +3 -0
  13. package/dist/executionPlacementWords.js +2 -0
  14. package/dist/generated/engineFactTables.d.ts +3 -2
  15. package/dist/generated/engineFactTables.js +17 -1
  16. package/dist/generated/engineNoticeTables.js +12 -0
  17. package/dist/hitl/automaticAnswerVerdict.js +47 -11
  18. package/dist/hitl/sessionPolicyDeliverable.js +31 -5
  19. package/dist/hitl/toolApprovalWire.d.ts +3 -2
  20. package/dist/hitl/toolApprovalWire.js +162 -15
  21. package/dist/host.d.ts +0 -3
  22. package/dist/hostTurnSettings.js +3 -1
  23. package/dist/humanTurn.js +2 -2
  24. package/dist/index.d.ts +5 -2
  25. package/dist/index.js +1 -0
  26. package/dist/jsonFaithful.js +5 -3
  27. package/dist/mcpLiveness.d.ts +1 -1
  28. package/dist/mcpWireCaps.js +1 -1
  29. package/dist/printModelStatus.d.ts +1 -0
  30. package/dist/printModelStatus.js +6 -2
  31. package/dist/retryStatus.d.ts +8 -1
  32. package/dist/retryStatus.js +13 -4
  33. package/dist/ruleCompileVerdict.d.ts +1 -0
  34. package/dist/ruleCompileVerdict.js +3 -1
  35. package/dist/seatContract.d.ts +7 -7
  36. package/dist/seatContract.js +39 -10
  37. package/dist/sessionRowTag.d.ts +24 -0
  38. package/dist/sessionRowTag.js +77 -0
  39. package/dist/systemReminderTag.js +14 -4
  40. package/docs/INTEGRATION-CLIENTS.md +252 -11
  41. 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) {
@@ -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;
@@ -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
+ }
@@ -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 type DeviceSessionBindingVerb = Pick<AgentClient['devices'], 'sessionBinding'>;
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
- } | DeviceUnreadable | DeviceLaneAbsent | DeviceRefused | DeviceTransport | DeviceUnarmed;
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(devices: DeviceSessionBindingVerb | null | undefined, rootSessionId: string, opts?: {
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?: {
@@ -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
- const boundAt = nonEmpty(own(raw, 'boundAt'));
127
- return { deviceId, rev, ...(boundAt !== undefined ? { boundAt } : {}) };
130
+ return { deviceId, rev };
128
131
  }
129
- export async function readSessionBinding(devices, rootSessionId, opts) {
130
- const verb = verbOf(devices, 'sessionBinding');
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(devices, rootSessionId, signalOpts(opts));
152
+ body = await verb.call(sessions, rootSessionId, signalOpts(opts));
136
153
  }
137
154
  catch (e) {
138
- return readFailureOf(e);
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
- const rid = own(body, 'rootSessionId');
141
- if (typeof rid !== 'string' || rid !== rootSessionId) {
142
- return { kind: 'unreadable', why: "the binding it returned does not echo the session id that was asked for — refusing to use another session's binding as this one's prior state" };
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
- const bound = bindingOf(own(body, 'boundDevice'));
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 binding it returned has no usable prior state (deviceId + rev) — refusing to treat it as a binding' };
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: rid, boundDevice: bound };
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
- return { kind: 'active-run', ...(activeTaskId !== undefined ? { activeTaskId } : {}) };
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 = {
@@ -0,0 +1,3 @@
1
+ export declare const EXECUTION_PLACEMENT_ROLES: readonly ["absent", "writer", "mirror", "forking"];
2
+ export type ExecutionPlacementRole = (typeof EXECUTION_PLACEMENT_ROLES)[number];
3
+ export declare const EXECUTION_PLACEMENT_DEVICE_LANE = "device";
@@ -0,0 +1,2 @@
1
+ export const EXECUTION_PLACEMENT_ROLES = Object.freeze(['absent', 'writer', 'mirror', 'forking']);
2
+ export const EXECUTION_PLACEMENT_DEVICE_LANE = 'device';
@@ -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 CORE_MCP_IMAGE_MAX_BASE64: number;
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 CORE_MCP_IMAGE_MAX_BASE64 = 5242880;
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
- function rowBlocks(lane, row) {
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
- const row = TABLE[c];
68
- return lane === 'mode_posture' ? bypassImmuneOn(c, face) : !row.ruleMayClear;
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 (anyKnown && rowBlocks(lane, folded))
161
- return mustAsk('ask_class', firstBlocking !== undefined ? { askClass: firstBlocking } : undefined);
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')
@@ -2,6 +2,7 @@ import { rosterMountedNames } from '../rosterMountedNames.js';
2
2
  import { msg, renderMessage } from '../i18n/translate.js';
3
3
  import { readOwnDataValue } from '../ownKey.js';
4
4
  import { denyEntryReading, ruleCompileVerdict } from '../ruleCompileVerdict.js';
5
+ import { hasCoreValuePort, ruleNameCovers } from '../coreValuePorts.js';
5
6
  import { ruleToolNameVerdictOf } from '../protocolSegment.js';
6
7
  import { PREFIXES_IN_PROSE, REFUSED_NAME_FIX } from './refusedToolNameProse.js';
7
8
  import { CORE_PROTOCOL_PREFIXES } from '../generated/toolNameTables.js';
@@ -13,7 +14,7 @@ const WITHHELD_NOTICE = {
13
14
  wildcard: 'Not written to this session’s rule record: this rule uses a wildcard (*), and an engine that matches that record by exact tool name would block none of the tools it covers.',
14
15
  not_a_tool_name: 'Not written to this session’s rule record: this entry is not exactly one tool name — it is empty, not text, has spaces around the name, is not a single tool name in rule syntax (for example it contains a backslash or a parenthesis, or is longer than a rule can be), or spells its server or agent peer part in a way the engine never uses when naming tools (for example with a dot or a space), so no tool would ever match it.',
15
16
  legacy_tool_name: `Not written to this session’s rule record: unless a tool by exactly this name is available, the engine refuses it — it is a retired tool name, or it contains "__" but does not start with ${PREFIXES_IN_PROSE} — and with it in that record every later run of this session would fail at startup until that entry is removed from the record. ${REFUSED_NAME_FIX}`,
16
- not_in_roster: 'Not written to this session’s rule record: the tool roster supplied for this check has no tool by exactly this name, as a name or an alias, with letter case counted — it may be misspelled, or name a tool this deployment does not provide — so recorded as it is it would block nothing here.',
17
+ not_in_roster: 'Not written to this session’s rule record: the tool roster supplied for this check has no tool this rule would block — no tool by exactly this name, as a name or an alias, with letter case counted, and, where the engine also reads the name as naming every tool of a server (a server whose own name contains "__"), no tool of that server either — it may be misspelled, or name a tool this deployment does not provide — so recorded as it is it would block nothing here.',
17
18
  namespace_covering_unconfirmed: msg('session.policy.withheld.namespaceCoveringUnconfirmed'),
18
19
  };
19
20
  export const SESSION_POLICY_WITHHELD_WHY = Object.freeze(Object.keys(WITHHELD_NOTICE));
@@ -151,11 +152,14 @@ export function sessionPolicyDeliverable(behavior, rules, opts) {
151
152
  why = 'not_a_tool_name';
152
153
  }
153
154
  let inertReason;
155
+ let coveringRow = false;
154
156
  if (engineAsked) {
155
157
  const reading = entryReadingOf(r);
156
158
  if (reading === 'unknown')
157
159
  return unreadable();
158
- if (reading !== 'row') {
160
+ if (reading === 'covering')
161
+ coveringRow = true;
162
+ else if (reading !== 'row') {
159
163
  inertReason = reading.reason;
160
164
  if (why === undefined)
161
165
  why = reading.why;
@@ -168,8 +172,13 @@ export function sessionPolicyDeliverable(behavior, rules, opts) {
168
172
  if (grammar === 'refused')
169
173
  why = 'not_a_tool_name';
170
174
  }
171
- if (why === undefined && mounted !== undefined && !mounted.has(r) && covering === undefined)
172
- why = 'not_in_roster';
175
+ if (why === undefined && mounted !== undefined && !mounted.has(r) && covering === undefined) {
176
+ const reach = coveringRow ? coveredRosterName(r, mounted) : 'none';
177
+ if (reach === 'unknown')
178
+ return unreadable();
179
+ if (reach === 'none')
180
+ why = 'not_in_roster';
181
+ }
173
182
  if (why === undefined)
174
183
  exact.push(r);
175
184
  else {
@@ -189,12 +198,29 @@ export function sessionPolicyDeliverable(behavior, rules, opts) {
189
198
  function entryReadingOf(rule) {
190
199
  const reading = denyEntryReading(rule);
191
200
  if (reading.kind === 'row')
192
- return 'row';
201
+ return reading.covering === true ? 'covering' : 'row';
193
202
  if (reading.kind === 'unknown')
194
203
  return 'unknown';
195
204
  const reason = reading.reason;
196
205
  return reason === 'grammar' || reason === 'content_unsupported' ? { why: 'not_a_tool_name', reason } : { why: 'wildcard', reason };
197
206
  }
207
+ function coveredRosterName(rule, mounted) {
208
+ if (!hasCoreValuePort('ruleNameCovers'))
209
+ return 'unknown';
210
+ try {
211
+ for (const name of mounted) {
212
+ const v = ruleNameCovers(rule, name);
213
+ if (v === true)
214
+ return 'covers';
215
+ if (v !== false)
216
+ return 'unknown';
217
+ }
218
+ return 'none';
219
+ }
220
+ catch {
221
+ return 'unknown';
222
+ }
223
+ }
198
224
  export function sessionPolicyWithheldNotice(why, lang) {
199
225
  if (typeof why === 'string' && Object.hasOwn(WITHHELD_NOTICE, why)) {
200
226
  const sentence = WITHHELD_NOTICE[why];