@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
@@ -97,6 +97,7 @@ export interface ApprovalCardRequest {
97
97
  };
98
98
  wireNote?: string;
99
99
  argsUnavailable?: true;
100
+ argsRewritten?: true;
100
101
  governanceForced?: true;
101
102
  delegation?: ToolApprovalDelegation;
102
103
  ruleOffers?: RuleOfferReading[];
@@ -178,7 +179,7 @@ export interface ReadRootCandidateView {
178
179
  covers?: 'exact';
179
180
  }
180
181
  export type ToolApprovalDelegation = ApprovalCardDelegation;
181
- export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleOffers", "ruleOffersAbsence", "denialLimitFallback", "readRootCandidate", "mandated", "mandate", "origin", "approvalCard", "askClass", "classes", "inputHasBidi", "parked", "persistedRuleShadowed", "allowRuleShadowed", "probeCause", "probeReason", "rememberRefused", "boundGrantDigest", "boundGrantAbsence", "boundGrants", "classifierNoRuling", "ruleEvidence", "requiresRealApproval", "expiresInMs", "expiresAtMs", "serverNowMs", "delegation", "outcome", "cause"];
182
+ export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleOffers", "ruleOffersAbsence", "denialLimitFallback", "readRootCandidate", "mandated", "mandate", "origin", "approvalCard", "askClass", "classes", "inputHasBidi", "parked", "persistedRuleShadowed", "allowRuleShadowed", "probeCause", "probeReason", "rememberRefused", "boundGrantDigest", "boundGrantAbsence", "boundGrants", "classifierNoRuling", "ruleEvidence", "requiresRealApproval", "expiresInMs", "expiresAtMs", "serverNowMs", "delegation", "outcome", "cause", "requestedBy"];
182
183
  export interface ApprovalMandatedFacts {
183
184
  readonly mandated?: true;
184
185
  readonly ruleOffersAbsence?: string;
@@ -276,7 +277,7 @@ export declare function readDenialLimitFallback(v: unknown): DenialLimitFallback
276
277
  export declare function readRuleOffers(v: unknown): RuleOfferReading[] | undefined;
277
278
  export declare function readRuleOfferSupply(offers: unknown): RuleOfferReading[] | undefined;
278
279
  export type ApprovalCardV1Facts = Pick<ApprovalCardRequest, 'toolName' | 'args'> & Pick<ApprovalCardRequest, 'toolCallId' | 'workerBadge' | 'wireNote' | 'argsUnavailable' | 'governanceForced' | 'delegation' | 'ruleOffersReadOnly' | 'inputHasBidi' | 'allowRuleShadow' | 'probeCause' | 'rememberRefused' | 'ruleEvidence' | 'requiresRealApproval' | 'ruleOffersAbsence' | 'denialLimitFallback' | 'askClass' | 'classes' | 'grantBinding' | 'unreadableEvidence' | 'message' | 'approvalCard'>;
279
- export type ApprovalCardFacts = ApprovalCardV1Facts & Pick<ApprovalCardRequest, 'ruleOffers' | 'probeReason' | 'mandated' | 'mandate' | 'readRootCandidate' | 'origin' | 'boundGrants' | 'classifierNoRuling' | 'allowSessionCarried' | 'cardPayloadUnreadable'>;
280
+ export type ApprovalCardFacts = ApprovalCardV1Facts & Pick<ApprovalCardRequest, 'argsRewritten' | 'ruleOffers' | 'probeReason' | 'mandated' | 'mandate' | 'readRootCandidate' | 'origin' | 'boundGrants' | 'classifierNoRuling' | 'allowSessionCarried' | 'cardPayloadUnreadable'>;
280
281
  export interface ApprovalCardFrameFactsOptions {
281
282
  readonly streamArgs?: object;
282
283
  readonly argsUnavailable?: true;
@@ -28,6 +28,7 @@ import { isApprovalMandateWord } from '../gateVocabulary.js';
28
28
  import { approvalDecidedByAdmitted } from '../approvalDecidedByCapability.js';
29
29
  import { decideFailureNote } from '../decideFailureNote.js';
30
30
  import { slotPresenceOf, wireFailureTextsOf } from '../wireFailureShape.js';
31
+ import { isPlainRecord } from '../jsonFaithful.js';
31
32
  import { DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED } from '../engineErrorCodes.js';
32
33
  import { readDecideReceipt } from '../decideReceipt.js';
33
34
  import { RULE_OFFER_MATCHES, RULE_OFFER_BATCH_MEMBER_KINDS, RULE_OFFER_UNCOVERED_REASONS, RULE_OFFERS_ABSENCE_REASONS, ASK_ORIGINS, } from '@sema-agent/sdk';
@@ -193,6 +194,11 @@ const PARK_ROW_ARGS_ABSENT_NOTE = "this request's tool arguments are not availab
193
194
  const PARK_ROW_ARGS_TRUNCATED_NOTE = "this request's tool arguments were too large to keep on the pending approval record and were replaced by a size marker, " +
194
195
  'so you are deciding without seeing them; deny it if you are not sure what it will do. ' +
195
196
  'Edits are not accepted on this card: there is no original input to edit';
197
+ const ARGS_REWRITTEN_NOTE = "this request's tool arguments were changed after the model made the call (for example by a hook) — " +
198
+ 'the arguments shown here are the changed ones recorded for this approval, and they differ from the call shown in the conversation';
199
+ const ARGS_FROM_MODEL_CALL_NOTE = 'this approval request did not carry usable tool arguments (for example because they were too large to include), ' +
200
+ "so the arguments shown are the model's original call from the conversation — " +
201
+ 'if they were changed after that call (for example by a hook), what runs differs from what is shown';
196
202
  const PARK_EDIT_REFUSED_REASON = "the card returned an edited approval, but this request's tool arguments are not available on this surface " +
197
203
  '(missing, or replaced by a size marker on the pending approval record), so the edit cannot be applied — nothing was sent; ' +
198
204
  'approve or deny it as it is';
@@ -205,6 +211,139 @@ function isParkRowInputSizeMarker(v) {
205
211
  const o = v;
206
212
  return o.truncated === true && typeof o.bytes === 'number' && Number.isFinite(o.bytes) && o.bytes >= 0;
207
213
  }
214
+ function recordedInputShapeOf(v) {
215
+ if (v === undefined || v === null)
216
+ return 'absent';
217
+ try {
218
+ if (typeof v !== 'object' || !isPlainRecord(v))
219
+ return 'other';
220
+ return isParkRowInputSizeMarker(v) ? 'size_marker' : 'input';
221
+ }
222
+ catch {
223
+ return 'other';
224
+ }
225
+ }
226
+ function argsProvablyDiffer(recorded, streamArgs) {
227
+ try {
228
+ if (typeof streamArgs !== 'object' || streamArgs === null || Array.isArray(streamArgs))
229
+ return false;
230
+ return jsonValuesDiffer(recorded, streamArgs, 0, { nodes: 0 }) === true;
231
+ }
232
+ catch {
233
+ return false;
234
+ }
235
+ }
236
+ function cardInputOf(recorded, stream) {
237
+ const shape = recordedInputShapeOf(recorded);
238
+ const streamPresent = stream !== undefined && stream !== null;
239
+ if (shape === 'input')
240
+ return { from: 'recorded', args: recorded, rewritten: streamPresent && argsProvablyDiffer(recorded, stream) };
241
+ if (streamPresent)
242
+ return { from: 'stream', args: stream, shape };
243
+ return { from: 'none', shape, recorded };
244
+ }
245
+ const CARD_ARGS_COMPARE_MAX_NODES = 20_000;
246
+ const CARD_ARGS_COMPARE_MAX_DEPTH = 256;
247
+ const NOT_COMPARABLE = Symbol('not comparable');
248
+ function ownDataForCompare(o, k) {
249
+ const d = Object.getOwnPropertyDescriptor(o, k);
250
+ return d !== undefined && Object.hasOwn(d, 'value') ? d.value : NOT_COMPARABLE;
251
+ }
252
+ const TO_JSON_CHAIN_MAX = 32;
253
+ function hasToJsonHook(o) {
254
+ let at = o;
255
+ for (let depth = 0; at !== null; depth++) {
256
+ if (depth >= TO_JSON_CHAIN_MAX)
257
+ return true;
258
+ const d = Object.getOwnPropertyDescriptor(at, 'toJSON');
259
+ if (d !== undefined)
260
+ return !Object.hasOwn(d, 'value') || typeof d.value === 'function';
261
+ at = Object.getPrototypeOf(at);
262
+ }
263
+ return false;
264
+ }
265
+ function jsonValueKindOf(v) {
266
+ if (v === null)
267
+ return 'null';
268
+ switch (typeof v) {
269
+ case 'boolean':
270
+ return 'boolean';
271
+ case 'string':
272
+ return 'string';
273
+ case 'number':
274
+ return Number.isFinite(v) ? 'number' : undefined;
275
+ case 'object':
276
+ if (Array.isArray(v))
277
+ return hasToJsonHook(v) ? undefined : 'array';
278
+ return isPlainRecord(v) && !hasToJsonHook(v) ? 'object' : undefined;
279
+ default:
280
+ return undefined;
281
+ }
282
+ }
283
+ function jsonValuesDiffer(a, b, depth, budget) {
284
+ if (++budget.nodes > CARD_ARGS_COMPARE_MAX_NODES || depth > CARD_ARGS_COMPARE_MAX_DEPTH)
285
+ return undefined;
286
+ const ka = jsonValueKindOf(a);
287
+ const kb = jsonValueKindOf(b);
288
+ if (ka === undefined || kb === undefined)
289
+ return undefined;
290
+ if (ka !== kb)
291
+ return true;
292
+ if (ka === 'array') {
293
+ const xa = a;
294
+ const xb = b;
295
+ const la = ownDataForCompare(xa, 'length');
296
+ const lb = ownDataForCompare(xb, 'length');
297
+ if (typeof la !== 'number' || typeof lb !== 'number')
298
+ return undefined;
299
+ if (la !== lb)
300
+ return true;
301
+ for (let i = 0; i < la; i++) {
302
+ const va = ownDataForCompare(xa, String(i));
303
+ const vb = ownDataForCompare(xb, String(i));
304
+ if (va === NOT_COMPARABLE || vb === NOT_COMPARABLE)
305
+ return undefined;
306
+ const d = jsonValuesDiffer(va, vb, depth + 1, budget);
307
+ if (d !== false)
308
+ return d;
309
+ }
310
+ return false;
311
+ }
312
+ if (ka === 'object') {
313
+ const ra = a;
314
+ const rb = b;
315
+ const keysA = Object.keys(ra);
316
+ const keysB = Object.keys(rb);
317
+ budget.nodes += keysA.length + keysB.length;
318
+ if (budget.nodes > CARD_ARGS_COMPARE_MAX_NODES)
319
+ return undefined;
320
+ const inA = new Set(keysA);
321
+ const inB = new Set(keysB);
322
+ for (const k of keysA) {
323
+ const va = ownDataForCompare(ra, k);
324
+ if (va === NOT_COMPARABLE)
325
+ return undefined;
326
+ if (!inB.has(k))
327
+ return jsonValueKindOf(va) === undefined ? undefined : true;
328
+ const vb = ownDataForCompare(rb, k);
329
+ if (vb === NOT_COMPARABLE)
330
+ return undefined;
331
+ const d = jsonValuesDiffer(va, vb, depth + 1, budget);
332
+ if (d !== false)
333
+ return d;
334
+ }
335
+ for (const k of keysB) {
336
+ if (inA.has(k))
337
+ continue;
338
+ const vb = ownDataForCompare(rb, k);
339
+ if (vb === NOT_COMPARABLE)
340
+ return undefined;
341
+ return jsonValueKindOf(vb) === undefined ? undefined : true;
342
+ }
343
+ return false;
344
+ }
345
+ return a === b ? false : true;
346
+ }
208
347
  function durableHoldKey(row, callKey) {
209
348
  const createdAt = typeof row.createdAt === 'number' && Number.isFinite(row.createdAt) ? row.createdAt : null;
210
349
  return JSON.stringify([typeof row.sessionId === 'string' ? row.sessionId : null, typeof row.taskId === 'string' ? row.taskId : null, callKey, createdAt]);
@@ -344,15 +483,10 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
344
483
  const at = { lane: 'decide', ...(gatedCallId !== undefined ? { gatedCallId } : {}) };
345
484
  const toolName = typeof pending.toolName === 'string' ? pending.toolName : '';
346
485
  const streamArgs = gatedCallId !== undefined ? argsByCall.get(gatedCallId) : undefined;
347
- const rowInput = pending.input;
348
- const rowArgsGap = streamArgs !== undefined && streamArgs !== null
349
- ? undefined
350
- : rowInput === undefined || rowInput === null
351
- ? 'absent'
352
- : isParkRowInputSizeMarker(rowInput)
353
- ? 'truncated'
354
- : undefined;
355
- const args = streamArgs !== undefined && streamArgs !== null ? streamArgs : rowArgsGap !== undefined ? {} : rowInput;
486
+ const reading = cardInputOf(pending.input, streamArgs);
487
+ const rowArgsGap = reading.from !== 'none' ? undefined : reading.shape === 'absent' ? 'absent' : reading.shape === 'size_marker' ? 'truncated' : undefined;
488
+ const args = reading.from !== 'none' ? reading.args : rowArgsGap !== undefined ? {} : reading.recorded;
489
+ const argsRewritten = reading.from === 'recorded' && reading.rewritten;
356
490
  if (typeof args !== 'object' || args === null) {
357
491
  return { kind: 'not_sent', ...at, cause: 'no_input', detail: 'gate has no tool input payload' };
358
492
  }
@@ -375,6 +509,7 @@ async function presentFsApprovalAndDecide(deps, taskId, argsByCall, signal, foun
375
509
  wireNote: rowArgsGap === 'truncated' ? PARK_ROW_ARGS_TRUNCATED_NOTE : PARK_ROW_ARGS_ABSENT_NOTE,
376
510
  }
377
511
  : {}),
512
+ ...(argsRewritten ? { argsRewritten: true, wireNote: ARGS_REWRITTEN_NOTE } : {}),
378
513
  ...(pending.governanceForced === true ? { governanceForced: true } : {}),
379
514
  ...(readRequiresRealApproval(pending) ? { requiresRealApproval: true } : {}),
380
515
  ...(hasOwnStrictTrue(pending, 'mandated') ? { mandated: true } : {}),
@@ -583,6 +718,7 @@ export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
583
718
  'delegation',
584
719
  'outcome',
585
720
  'cause',
721
+ 'requestedBy',
586
722
  ];
587
723
  const _mirrorPin = [true];
588
724
  void _mirrorPin;
@@ -1088,7 +1224,7 @@ const UNREADABLE_EVIDENCE_KEYS = Object.freeze({
1088
1224
  ]),
1089
1225
  generic: Object.freeze([['ruleOffersAbsence', 'ruleOffersAbsence'], ['askClass', 'askClass'], ['classes', 'classes']]),
1090
1226
  });
1091
- function v1RiskUnreadable(card) {
1227
+ function riskSubtreeUnreadable(card) {
1092
1228
  if (slotPresenceOf(card, 'risk') === 'absent')
1093
1229
  return false;
1094
1230
  try {
@@ -1115,7 +1251,7 @@ function withUnreadableEvidence(carrier, leg, req, reported = []) {
1115
1251
  if (retiredAllowRuleShadowKeyPresent(carrier, shadowLeg))
1116
1252
  keys.add(RETIRED_SHADOW_EVIDENCE_LABEL[shadowLeg]);
1117
1253
  }
1118
- if (leg === 'v1' && v1RiskUnreadable(carrier))
1254
+ if ((leg === 'v1' || leg === 'frame') && riskSubtreeUnreadable(carrier))
1119
1255
  keys.add('risk');
1120
1256
  return keys.size === 0 ? req : { ...req, unreadableEvidence: Object.freeze([...keys].sort()) };
1121
1257
  }
@@ -1509,10 +1645,19 @@ function cardFactsOf(carrier, leg, opts) {
1509
1645
  stream = opts.streamArgs;
1510
1646
  blind = opts.argsUnavailable === true;
1511
1647
  }
1512
- const raw = stream !== undefined && stream !== null ? stream : c.args !== undefined && c.args !== null ? c.args : undefined;
1513
- if (typeof raw === 'object' && raw !== null)
1514
- return blind ? { args: raw, argsUnavailable: true } : { args: raw };
1515
- const fallback = argsFallbackOf(c.message, c.argsOmitted);
1648
+ const reading = cardInputOf(c.args, stream);
1649
+ if (reading.from === 'recorded') {
1650
+ if (blind)
1651
+ return { args: reading.args, argsUnavailable: true };
1652
+ return reading.rewritten ? { args: reading.args, argsRewritten: true, wireNote: ARGS_REWRITTEN_NOTE } : { args: reading.args };
1653
+ }
1654
+ if (reading.from === 'stream' && typeof reading.args === 'object' && reading.args !== null) {
1655
+ if (blind)
1656
+ return { args: reading.args, argsUnavailable: true };
1657
+ return { args: reading.args, wireNote: ARGS_FROM_MODEL_CALL_NOTE };
1658
+ }
1659
+ const omitted = c.argsOmitted === true || reading.shape === 'size_marker';
1660
+ const fallback = argsFallbackOf(c.message, omitted);
1516
1661
  const note = blind ? SUSPENDED_ASK_ARGS_NOTE : fallback.omittedNote;
1517
1662
  return { args: fallback.args, argsUnavailable: true, ...(note !== undefined ? { wireNote: note } : {}) };
1518
1663
  }
@@ -1538,6 +1683,8 @@ function cardFactsOf(carrier, leg, opts) {
1538
1683
  out.wireNote = argsPart.wireNote;
1539
1684
  if (argsPart.argsUnavailable === true)
1540
1685
  out.argsUnavailable = true;
1686
+ if (argsPart.argsRewritten === true)
1687
+ out.argsRewritten = true;
1541
1688
  if (full) {
1542
1689
  v1Bit(() => {
1543
1690
  if (c.governanceForced === true)
package/dist/host.d.ts CHANGED
@@ -3,9 +3,6 @@ import type { WireHooksConfig } from './finalVerifyWire.js';
3
3
  import { type NotificationQueuePort } from './notifications.js';
4
4
  export type SettingsDocument = Record<string, unknown>;
5
5
  export type ManagedPolicyState = 'absent' | 'in-effect' | 'in-effect-pieces' | 'unreadable-covered' | 'unreadable-uncovered' | 'remote-unknown';
6
- export interface ManagedPolicyReading {
7
- readonly state: ManagedPolicyState;
8
- }
9
6
  export type HooksStartupMode = 'safe' | 'bare';
10
7
  export type PluginHookOptionValue = string | number | boolean;
11
8
  export interface PluginHookSensitiveOption {
@@ -454,8 +454,10 @@ function permissionsArm(src, side, adoption) {
454
454
  appendOwnElement(buckets[bucket], rule);
455
455
  origins[bucket].set(rule, origin);
456
456
  }
457
- else if (rank(origin) < rank(prev))
457
+ else if (rank(origin) < rank(prev)) {
458
+ origins[bucket].delete(rule);
458
459
  origins[bucket].set(rule, origin);
460
+ }
459
461
  };
460
462
  let projectionError;
461
463
  const portsProjection = newRulePortsProjection();
package/dist/humanTurn.js CHANGED
@@ -1,4 +1,4 @@
1
- import { CORE_MAX_PENDING_STEER_CHARS, CORE_MCP_IMAGE_MAX_BASE64, CORE_USER_ATTACHMENT_LABEL_MAX } from './generated/engineFactTables.js';
1
+ import { CORE_IMAGE_ADMISSION_HARD_IMAGE_BASE64_CHARS, CORE_MAX_PENDING_STEER_CHARS, CORE_USER_ATTACHMENT_LABEL_MAX } from './generated/engineFactTables.js';
2
2
  import { mintEnvelopeOf, mintReferenceOf, seatTextOf } from './userAttachmentEnvelope.js';
3
3
  import { readEncodingShares, readHumanTurnInput } from './humanTurnRead.js';
4
4
  import { putOwnKey } from './ownKey.js';
@@ -224,7 +224,7 @@ function encodeObjective(v) {
224
224
  let count = 0;
225
225
  let total = 0;
226
226
  const seat = (len) => {
227
- if (len > CORE_MCP_IMAGE_MAX_BASE64)
227
+ if (len > CORE_IMAGE_ADMISSION_HARD_IMAGE_BASE64_CHARS)
228
228
  return 'image_too_large';
229
229
  if (count + 1 > IMAGE_SEAT_MAX_COUNT)
230
230
  return 'seat_count';
package/dist/index.d.ts CHANGED
@@ -361,13 +361,16 @@ export { BACKGROUND_HANDOFF_ABORT_REASON, handoffInteractiveRun, handedOffRunsOf
361
361
  export type { BackgroundHandoffRequest, BackgroundHandoffOutcome, BackgroundRun, BackgroundRunSettlement, HandedOffRunRow, HandedOffRunsReading, } from './sessionBackgroundHandoff.js';
362
362
  export { listDevices, readSessionBinding, rebindSession, reconcileRebindOutcome, rebindProvesRequestNotApplied } from './deviceRebind.js';
363
363
  export { issueEnrollToken, enrollDevice, revokeDevice, deviceIdentityMismatchOf, deviceIdentityMismatchLine, deviceRegistrationOutcomeLine } from './deviceRebind.js';
364
- export type { DeviceSummary, DeviceListResult, DeviceBinding, DeviceSessionBinding, DeviceRebindRequest, DeviceRevokeRequest, DeviceRebindResult, DeviceEnrollToken, DeviceEnrollRequest, DeviceEnrollResult, DeviceRevokeResult, } from '@sema-agent/sdk';
365
- export type { DeviceListVerb, DeviceSessionBindingVerb, DeviceRebindVerb, DeviceRosterRow, DeviceBindingReading, DeviceRefused, DeviceLaneAbsent, DeviceTransport, DeviceUnreadable, DeviceUnarmed, DeviceListOutcome, DeviceSessionBindingOutcome, DeviceRebindInput, DeviceRebindUnconfirmed, DeviceRebindOutcome, DeviceRebindReconcileVerdict, DeviceIssueEnrollTokenVerb, DeviceEnrollVerb, DeviceRevokeVerb, DeviceEnrollOptions, DeviceRateLimited, DeviceEnrollTokenOutcome, DeviceEnrollOutcome, DeviceRevokeOutcome, DeviceRegistrationVerb, DeviceIdentityMismatch, } from './deviceRebind.js';
364
+ export type { DeviceSummary, DeviceListResult, DeviceRebindRequest, DeviceRevokeRequest, DeviceRebindResult, DeviceEnrollToken, DeviceEnrollRequest, DeviceEnrollResult, DeviceRevokeResult, } from '@sema-agent/sdk';
365
+ export type { ExecutionPlacementRole } from './executionPlacementWords.js';
366
+ export type { DeviceListVerb, SessionExecutionPlacementVerb, DeviceFaceUnsupported, DeviceRebindVerb, DeviceRosterRow, DeviceBindingReading, DeviceRefused, DeviceLaneAbsent, DeviceTransport, DeviceUnreadable, DeviceUnarmed, DeviceListOutcome, DeviceSessionBindingOutcome, DeviceRebindInput, DeviceRebindUnconfirmed, DeviceRebindOutcome, DeviceRebindReconcileVerdict, DeviceIssueEnrollTokenVerb, DeviceEnrollVerb, DeviceRevokeVerb, DeviceEnrollOptions, DeviceRateLimited, DeviceEnrollTokenOutcome, DeviceEnrollOutcome, DeviceRevokeOutcome, DeviceRegistrationVerb, DeviceIdentityMismatch, } from './deviceRebind.js';
366
367
  export { resolveEngineEnvSourcing, engineEnvView } from './engineEnvSourcing.js';
367
368
  export type { EngineEnvView, EngineEnvGroupDecl, EngineEnvSourcingInput, EngineEnvTouchedKey, EngineEnvGroupReading, EngineEnvKeyReason, EngineEnvSourcingVerdict, } from './engineEnvSourcing.js';
368
369
  export * from './compensations.js';
369
370
  export * from './request/printNotification.js';
370
371
  export * from './seatContract.js';
372
+ export { sessionRowTagOf, sessionRowPatchRefusalOf } from './sessionRowTag.js';
373
+ export type { SessionRowCurrentReading, SessionRowPatchRefusal } from './sessionRowTag.js';
371
374
  export { mcpToolTogglesToExcludeTools } from './mcpToolToggles.js';
372
375
  export type { McpToolToggleKey, McpMountedServers } from './mcpToolToggles.js';
373
376
  export { readThinkingLatch, writeThinkingLatch, thinkingLatchView, thinkingLatchSentence, thinkingLatchRowWordOf, readSeatThinkingLatch } from './thinkingLatch.js';
package/dist/index.js CHANGED
@@ -299,6 +299,7 @@ export { resolveEngineEnvSourcing, engineEnvView } from './engineEnvSourcing.js'
299
299
  export * from './compensations.js';
300
300
  export * from './request/printNotification.js';
301
301
  export * from './seatContract.js';
302
+ export { sessionRowTagOf, sessionRowPatchRefusalOf } from './sessionRowTag.js';
302
303
  export { mcpToolTogglesToExcludeTools } from './mcpToolToggles.js';
303
304
  export { readThinkingLatch, writeThinkingLatch, thinkingLatchView, thinkingLatchSentence, thinkingLatchRowWordOf, readSeatThinkingLatch } from './thinkingLatch.js';
304
305
  export { devicesFaceOf, devicesWritesAllowed, devicesFaceDetail } from './devicesFace.js';
@@ -19,14 +19,16 @@ export const isPlainRecord = (v) => {
19
19
  return true;
20
20
  if (typeof proto !== 'object')
21
21
  return false;
22
- if (!Object.prototype.hasOwnProperty.call(proto, 'constructor'))
22
+ const ctorDesc = Object.getOwnPropertyDescriptor(proto, 'constructor');
23
+ if (ctorDesc === undefined || !Object.hasOwn(ctorDesc, 'value'))
23
24
  return false;
24
- const ctor = proto.constructor;
25
+ const ctor = ctorDesc.value;
25
26
  if (typeof ctor !== 'function')
26
27
  return false;
27
28
  if (Function.prototype.toString.call(ctor) !== Function.prototype.toString.call(Object))
28
29
  return false;
29
- return ctor.prototype === proto;
30
+ const protoDesc = Object.getOwnPropertyDescriptor(ctor, 'prototype');
31
+ return protoDesc !== undefined && Object.hasOwn(protoDesc, 'value') && protoDesc.value === proto;
30
32
  };
31
33
  export const materializeJsonFaithful = (v, path, seen = new Set(), opts = {}) => {
32
34
  const guard = opts.guard;
@@ -29,7 +29,7 @@ export interface McpEngineLegHealth {
29
29
  }
30
30
  export declare function mcpLivenessRollupOf(rows: readonly McpLivenessBearingRow[] | undefined): McpEngineLegHealth;
31
31
  export declare function mcpEngineLegHealthDetail(health: McpEngineLegHealth | undefined): string;
32
- export declare const 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"];
32
+ export declare const 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"];
33
33
  export declare const MCP_AUTHORIZATION_REASONS: readonly ["rejected", "scope", "none"];
34
34
  export declare const MCP_FAILURE_UNAUTHORIZED: Extract<(typeof CORE_MCP_FAILURE_KINDS)[number], 'unauthorized'>;
35
35
  export interface McpAuthorizationView {
@@ -437,6 +437,6 @@ export function mcpAssertionHeaderNotSentNotice(specs) {
437
437
  const parts = distinct.slice(0, ASSERTION_NOTICE_NAMES_SHOWN).map((x) => `"${x}"`);
438
438
  if (distinct.length > ASSERTION_NOTICE_NAMES_SHOWN)
439
439
  parts.push(`+${distinct.length - ASSERTION_NOTICE_NAMES_SHOWN} more`);
440
- return (`MCP servers that declare an assertion header (assertionHeader): ${parts.join(', ')} — server versions up to 7.134.0 accept this setting but do not send the header, ` +
440
+ return (`MCP servers that declare an assertion header (assertionHeader): ${parts.join(', ')} — server versions up to 7.139.0 accept this setting but do not send the header, ` +
441
441
  'and this client cannot tell whether the engine it uses sends it; a connector that requires the header will refuse requests from these servers');
442
442
  }
@@ -20,6 +20,7 @@ export interface PrintModelStatusPayload {
20
20
  readonly elapsed_ms?: number;
21
21
  readonly timeout_ms?: number;
22
22
  readonly model?: string;
23
+ readonly seat?: string;
23
24
  readonly phase: RetryStatusNotice['phase'];
24
25
  readonly recourse?: NonNullable<RetryStatusNotice['recourse']>;
25
26
  readonly message: string;
@@ -41,6 +41,7 @@ function modelStatusPayload(status, ctx) {
41
41
  ...(elapsed !== undefined ? { elapsed_ms: elapsed } : {}),
42
42
  ...(ceiling !== undefined ? { timeout_ms: ceiling } : {}),
43
43
  ...(model !== undefined ? { model } : {}),
44
+ ...(typeof status.seat === 'string' ? { seat: status.seat } : {}),
44
45
  phase: notice.phase,
45
46
  ...(notice.recourse !== undefined ? { recourse: notice.recourse } : {}),
46
47
  message: notice.line,
@@ -49,6 +50,8 @@ function modelStatusPayload(status, ctx) {
49
50
  function apiRetryKeyOf(status) {
50
51
  const terminal = 'terminal' in status && status.terminal === true;
51
52
  const ok = (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0;
53
+ if (status.seat !== undefined)
54
+ return null;
52
55
  if (status.kind === 'waiting' || terminal || !ok(status.attempt) || !ok(status.maxRetries))
53
56
  return null;
54
57
  return `${String(status.attempt)}/${String(status.maxRetries)}/${String(status.errClass ?? '')}/${String(status.errorStatus ?? '')}`;
@@ -126,12 +129,13 @@ export function createPrintModelStatusTracker() {
126
129
  clear();
127
130
  return null;
128
131
  }
129
- const model = readOwnDataNonEmptyString(ctx, 'model');
132
+ const model = status.seat === undefined ? readOwnDataNonEmptyString(ctx, 'model') : undefined;
130
133
  const key = apiRetryKeyOf(status);
131
134
  const refresh = key !== null && key === lastApiRetryKey;
132
135
  const safeCtx = { sessionId, nowMs, mintUuid, ...(model !== undefined ? { model } : {}) };
133
136
  const frame = statusFrameOf(status, safeCtx, mintUuid(), refresh);
134
- lastApiRetryKey = key;
137
+ if (status.seat === undefined)
138
+ lastApiRetryKey = key;
135
139
  last = { status, model };
136
140
  return frame;
137
141
  }
@@ -13,6 +13,7 @@ export type RetryStatus = {
13
13
  timeoutMs?: number;
14
14
  sleptMs?: number;
15
15
  waitSegment?: BrainStatusWaitSegment | (string & {});
16
+ seat?: BrainStatusSeat | (string & {});
16
17
  detail?: string;
17
18
  } | {
18
19
  kind: 'error';
@@ -30,6 +31,7 @@ export type RetryStatus = {
30
31
  timeoutMs?: number;
31
32
  sleptMs?: number;
32
33
  waitSegment?: BrainStatusWaitSegment | (string & {});
34
+ seat?: BrainStatusSeat | (string & {});
33
35
  } | {
34
36
  kind: 'waiting';
35
37
  deadline: number;
@@ -44,6 +46,7 @@ export type RetryStatus = {
44
46
  timeoutMs?: number;
45
47
  sleptMs?: number;
46
48
  waitSegment?: BrainStatusWaitSegment | (string & {});
49
+ seat?: BrainStatusSeat | (string & {});
47
50
  terminal?: never;
48
51
  error: RetryStatusErrorPayload;
49
52
  };
@@ -77,10 +80,13 @@ export interface BrainStatusPayload {
77
80
  providerConditionSource?: string;
78
81
  sleptMs?: number;
79
82
  waitSegment?: BrainStatusWaitSegment | (string & {});
83
+ seat?: BrainStatusSeat | (string & {});
80
84
  }
81
85
  export declare const BRAIN_STATUS_WAIT_SEGMENTS: readonly ["response_headers", "first_token"];
82
86
  export type BrainStatusWaitSegment = (typeof BRAIN_STATUS_WAIT_SEGMENTS)[number];
83
- export declare const BRAIN_STATUS_PAYLOAD_KEYS: readonly ["phase", "detail", "retryInSec", "retryInMs", "attempt", "maxRetries", "errClass", "retryAtMs", "errorStatus", "elapsedMs", "timeoutMs", "providerCondition", "providerConditionSource", "sleptMs", "waitSegment"];
87
+ export declare const BRAIN_STATUS_SEATS: readonly ["classifier"];
88
+ type BrainStatusSeat = (typeof BRAIN_STATUS_SEATS)[number];
89
+ export declare const BRAIN_STATUS_PAYLOAD_KEYS: readonly ["phase", "detail", "retryInSec", "retryInMs", "attempt", "maxRetries", "errClass", "retryAtMs", "errorStatus", "elapsedMs", "timeoutMs", "providerCondition", "providerConditionSource", "sleptMs", "waitSegment", "seat"];
84
90
  export declare function mapBrainStatusToRetry(p: BrainStatusPayload, nowMs: number): RetryStatus | null;
85
91
  export interface RetryStatusArmLike {
86
92
  readonly phase?: string;
@@ -98,6 +104,7 @@ export interface RetryStatusArmLike {
98
104
  readonly providerConditionSource?: string;
99
105
  readonly sleptMs?: number;
100
106
  readonly waitSegment?: string;
107
+ readonly seat?: string;
101
108
  readonly parentToolCallId?: string;
102
109
  }
103
110
  export declare function retryStatusFromArm(arm: RetryStatusArmLike | null | undefined, nowMs: number): RetryStatus | null | undefined;
@@ -14,6 +14,9 @@ export const BRAIN_STATUS_PHASES = [
14
14
  export const BRAIN_STATUS_WAIT_SEGMENTS = Object.freeze(['response_headers', 'first_token']);
15
15
  void true;
16
16
  void true;
17
+ export const BRAIN_STATUS_SEATS = Object.freeze(['classifier']);
18
+ void true;
19
+ void true;
17
20
  export const BRAIN_STATUS_PAYLOAD_KEYS = [
18
21
  'phase',
19
22
  'detail',
@@ -30,6 +33,7 @@ export const BRAIN_STATUS_PAYLOAD_KEYS = [
30
33
  'providerConditionSource',
31
34
  'sleptMs',
32
35
  'waitSegment',
36
+ 'seat',
33
37
  ];
34
38
  const _brainStatusKeyPin = [true, true];
35
39
  void _brainStatusKeyPin;
@@ -61,9 +65,11 @@ export function mapBrainStatusToRetry(p, nowMs) {
61
65
  };
62
66
  const sleptMs = saneMs(p.sleptMs);
63
67
  const waitSegment = p.waitSegment;
68
+ const seat = p.seat;
64
69
  const waitFacts = {
65
70
  ...(sleptMs !== undefined ? { sleptMs } : {}),
66
71
  ...(typeof waitSegment === 'string' && waitSegment.length > 0 ? { waitSegment } : {}),
72
+ ...(typeof seat === 'string' && seat.length > 0 ? { seat } : {}),
67
73
  };
68
74
  const stalledShown = typeof p.detail === 'string' && p.detail.length > 0 ? displayUntrusted(p.detail) : '';
69
75
  const stalledDetail = stalledShown.length > 0 ? { detail: stalledShown } : {};
@@ -112,8 +118,8 @@ export function retryStatusFromArm(arm, nowMs) {
112
118
  const v = str(key);
113
119
  return v !== undefined && v.length > 0 ? v : undefined;
114
120
  };
115
- const [detail, retryInSec, retryInMs, attempt, maxRetries, errClass, retryAtMs, errorStatus, elapsedMs, timeoutMs, providerCondition, providerConditionSource, sleptMs, waitSegment] = [
116
- str('detail'), num('retryInSec'), num('retryInMs'), num('attempt'), num('maxRetries'), str('errClass'), num('retryAtMs'), num('errorStatus'), num('elapsedMs'), num('timeoutMs'), word('providerCondition'), word('providerConditionSource'), num('sleptMs'), word('waitSegment'),
121
+ const [detail, retryInSec, retryInMs, attempt, maxRetries, errClass, retryAtMs, errorStatus, elapsedMs, timeoutMs, providerCondition, providerConditionSource, sleptMs, waitSegment, seat] = [
122
+ str('detail'), num('retryInSec'), num('retryInMs'), num('attempt'), num('maxRetries'), str('errClass'), num('retryAtMs'), num('errorStatus'), num('elapsedMs'), num('timeoutMs'), word('providerCondition'), word('providerConditionSource'), num('sleptMs'), word('waitSegment'), word('seat'),
117
123
  ];
118
124
  const phase = str('phase');
119
125
  if (phase === undefined)
@@ -134,6 +140,7 @@ export function retryStatusFromArm(arm, nowMs) {
134
140
  ...(providerConditionSource !== undefined ? { providerConditionSource } : {}),
135
141
  ...(sleptMs !== undefined ? { sleptMs } : {}),
136
142
  ...(waitSegment !== undefined ? { waitSegment } : {}),
143
+ ...(seat !== undefined ? { seat } : {}),
137
144
  }, nowMs);
138
145
  }
139
146
  const WAIT_SWITCH_FRACTION = 0.5;
@@ -218,7 +225,8 @@ function sealParts(p) {
218
225
  }
219
226
  export function retryStatusParts(status, ctx) {
220
227
  const modelName = washedText(noticeText(ctx, 'modelName'))?.trim();
221
- const model = modelName === undefined || modelName === '' ? undefined : modelName;
228
+ const otherSeat = status !== null && noticeText(status, 'seat') !== undefined;
229
+ const model = otherSeat || modelName === undefined || modelName === '' ? undefined : modelName;
222
230
  if (status === null)
223
231
  return sealParts({ phase: 'cleared' });
224
232
  const armWord = noticeText(status, 'kind');
@@ -243,7 +251,7 @@ export function retryStatusParts(status, ctx) {
243
251
  const condition = reading === undefined ? undefined : `${reading.clause.charAt(0).toUpperCase()}${reading.clause.slice(1)}`;
244
252
  const serviceSide = http !== undefined && isServiceSideStatus(http);
245
253
  const knownArm = armWord === 'stalled' || armWord === 'error';
246
- const recourse = !knownArm
254
+ const recourseOfArm = !knownArm
247
255
  ? undefined
248
256
  : reading !== undefined
249
257
  ? conditionRecourseOf(conditionWord)
@@ -252,6 +260,7 @@ export function retryStatusParts(status, ctx) {
252
260
  : !terminal
253
261
  ? 'wait'
254
262
  : undefined;
263
+ const recourse = otherSeat && recourseOfArm === 'switch_model' ? (terminal ? undefined : 'wait') : recourseOfArm;
255
264
  const deadlineRaw = knownArm && !terminal && noticeNumber(status, 'retryAtMs') !== undefined ? noticeNumber(status, 'deadline') : undefined;
256
265
  const retryAtMs = deadlineRaw !== undefined && deadlineRaw > 0 ? deadlineRaw : undefined;
257
266
  return sealParts({
@@ -17,6 +17,7 @@ export declare function ruleCompileVerdictUnder(rule: string, behavior: 'deny' |
17
17
  export type DenyEntryInertReason = 'grammar' | 'content_unsupported' | 'wildcard_all' | 'namespace_wildcard';
18
18
  export type DenyEntryReading = {
19
19
  readonly kind: 'row';
20
+ readonly covering?: true;
20
21
  } | {
21
22
  readonly kind: 'inert';
22
23
  readonly reason: DenyEntryInertReason;
@@ -58,7 +58,9 @@ export function denyEntryReading(rule) {
58
58
  const kind = readOwnDataValue(reading, 'kind');
59
59
  if (kind === 'row') {
60
60
  const compiled = readOwnDataValue(reading, 'compiled');
61
- return typeof compiled === 'object' && compiled !== null ? { kind: 'row' } : { kind: 'unknown' };
61
+ if (typeof compiled !== 'object' || compiled === null)
62
+ return { kind: 'unknown' };
63
+ return readOwnDataValue(compiled, 'kind') === 'covering' ? { kind: 'row', covering: true } : { kind: 'row' };
62
64
  }
63
65
  if (kind !== 'inert')
64
66
  return { kind: 'unknown' };
@@ -14,6 +14,7 @@ import type { DeviceEnrollTokenOutcome, DeviceListOutcome, DeviceRebindOutcome,
14
14
  import type { McpPanelView } from "./mcpPanel.js";
15
15
  import type { McpToolToggleKey } from "./mcpToolToggles.js";
16
16
  import { type ThinkingLatchEvent, type ThinkingLatchRowWord } from "./thinkingLatchWords.js";
17
+ import type { SessionRowPatchFields } from "./sessionRowTag.js";
17
18
  export interface SeatValidationFailure {
18
19
  reason: string;
19
20
  field?: string;
@@ -48,6 +49,7 @@ export interface LocalSessionRecord {
48
49
  }>;
49
50
  parked?: boolean;
50
51
  pinned?: boolean;
52
+ rowTag?: string;
51
53
  thinkingLatch?: ThinkingLatchRowWord;
52
54
  }
53
55
  export declare const TOOL_PERMISSION_REQUEST_ID_DOMAINS: readonly ["live:", "durable:", "question:", "elicit:", "plan:"];
@@ -301,12 +303,10 @@ export declare const ATTACHMENT_UPLOAD_REQUEST_KEYS: readonly ["name", "mimeType
301
303
  export interface SessionScopedRequest {
302
304
  sessionId: string;
303
305
  }
304
- export interface SessionRowPatchRequest {
306
+ export interface SessionRowPatchRequest extends SessionRowPatchFields {
305
307
  sessionId: string;
306
- title?: string | null;
307
- pinned?: boolean;
308
308
  }
309
- export declare const SESSION_ROW_PATCH_REQUEST_KEYS: readonly ["sessionId", "title", "pinned"];
309
+ export declare const SESSION_ROW_PATCH_REQUEST_KEYS: readonly ["sessionId", "title", "pinned", "expectedRowTag"];
310
310
  export interface SetThinkingLatchRequest {
311
311
  readonly sessionId: string;
312
312
  readonly event: ThinkingLatchEvent;
@@ -688,7 +688,7 @@ export declare const SEAT_STORE_PROPS: readonly ["sessionsStateStore", "focusedS
688
688
  export declare const SEAT_EVENT_METHOD_NAMES: readonly ["onEvent", "onToolPermissionRequest"];
689
689
  export declare const LOCAL_SESSION_EVENT_KEYS: readonly ["type", "sessionId", "message", "error", "errorCategory", "code", "session", "userMessageUuid", "requestId", "outcome", "parked", "chrome", "_sema_turnFailure", "subagentContent"];
690
690
  export declare const TOOL_PERMISSION_REQUEST_KEYS: readonly ["requestId", "sessionId", "toolName", "toolCallId", "input", "message", "toctouBinding", "createdAtMs", "governanceForced", "delegation", "mandated", "mandate", "origin", "ruleOffersAbsence", "askClass", "classes", "sessionRow"];
691
- export declare const LOCAL_SESSION_RECORD_KEYS: readonly ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked", "pinned", "thinkingLatch"];
691
+ export declare const LOCAL_SESSION_RECORD_KEYS: readonly ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked", "pinned", "rowTag", "thinkingLatch"];
692
692
  export declare const SEND_MESSAGE_REQUEST_KEYS: readonly ["sessionId", "text", "model", "userMessageUuid", "permissionMode", "attachmentIds", "reasoningEffort", "retainBackgroundProcesses", "forwardSubagentEvents", "retainSubagentSessions", "settings", "scenario", "rewind"];
693
693
  export declare const SEAT_SEND_MESSAGE_KEY_ORIGINS: {
694
694
  readonly sessionId: {
@@ -738,7 +738,7 @@ export declare const SEAT_VALIDATOR_KEY_COVERAGE: {
738
738
  readonly LocalSessionRecord: {
739
739
  readonly guard: "isLocalSessionRecord";
740
740
  readonly check: (v: unknown) => SeatValidation;
741
- readonly validated: readonly ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked", "pinned", "thinkingLatch"];
741
+ readonly validated: readonly ["sessionId", "engineSessionId", "model", "title", "cwd", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked", "pinned", "rowTag", "thinkingLatch"];
742
742
  readonly unchecked: readonly [];
743
743
  };
744
744
  readonly ToolPermissionRequest: {
@@ -815,7 +815,7 @@ export declare const SEAT_VALIDATOR_KEY_COVERAGE: {
815
815
  readonly SessionRowPatchRequest: {
816
816
  readonly guard: "isSessionRowPatchRequest";
817
817
  readonly check: (v: unknown) => SeatValidation;
818
- readonly validated: readonly ["sessionId", "title", "pinned"];
818
+ readonly validated: readonly ["sessionId", "title", "pinned", "expectedRowTag"];
819
819
  readonly unchecked: readonly [];
820
820
  };
821
821
  readonly SetThinkingLatchRequest: {