@sema-agent/client-core 0.93.0 → 0.94.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 (156) hide show
  1. package/CHANGELOG.md +261 -0
  2. package/README.md +31 -18
  3. package/dist/adapt/arms.js +8 -5
  4. package/dist/adapter/downstream/terminalToSdkResult.js +2 -3
  5. package/dist/agentSession/engineSessionBackgroundStop.js +2 -1
  6. package/dist/agentsWireCaps.d.ts +15 -0
  7. package/dist/agentsWireCaps.js +111 -1
  8. package/dist/approvalReachWire.d.ts +18 -0
  9. package/dist/approvalReachWire.js +58 -0
  10. package/dist/approvalsStreamLiveCapability.js +16 -11
  11. package/dist/callerCwdCapability.d.ts +16 -0
  12. package/dist/callerCwdCapability.js +47 -0
  13. package/dist/controlRouter.js +3 -10
  14. package/dist/coreValuePorts.d.ts +64 -1
  15. package/dist/coreValuePorts.js +30 -0
  16. package/dist/detachWire.d.ts +1 -4
  17. package/dist/detachWire.js +1 -1
  18. package/dist/deviceExecutorManagementCapability.js +39 -34
  19. package/dist/deviceFlowPolling.d.ts +5 -0
  20. package/dist/deviceFlowPolling.js +28 -0
  21. package/dist/displayUntrusted.js +652 -21
  22. package/dist/engineErrorCodes.d.ts +5 -1
  23. package/dist/engineErrorCodes.js +9 -12
  24. package/dist/engineNoticeCodes.d.ts +22 -2
  25. package/dist/engineNoticeCodes.js +73 -6
  26. package/dist/engineRefusedToolName.d.ts +1 -0
  27. package/dist/engineRefusedToolName.js +8 -0
  28. package/dist/executionLaneCapability.js +14 -9
  29. package/dist/fileHistoryCaptureCapability.js +14 -9
  30. package/dist/fileHistoryLegNotice.d.ts +11 -0
  31. package/dist/fileHistoryLegNotice.js +50 -13
  32. package/dist/fleet/fleetLedger.js +5 -0
  33. package/dist/gateOutcome.d.ts +2 -1
  34. package/dist/gateOutcome.js +3 -0
  35. package/dist/gateVocabulary.js +1 -1
  36. package/dist/generated/engineAskFaceTables.d.ts +3 -0
  37. package/dist/generated/engineAskFaceTables.js +12 -0
  38. package/dist/generated/engineFactTables.d.ts +4 -2
  39. package/dist/generated/engineFactTables.js +13 -0
  40. package/dist/generated/engineNoticeTables.d.ts +5 -0
  41. package/dist/generated/engineNoticeTables.js +7 -0
  42. package/dist/generated/sdkFactTables.d.ts +3 -0
  43. package/dist/generated/sdkFactTables.js +17 -0
  44. package/dist/generated/settingsSchemaTables.d.ts +3 -0
  45. package/dist/generated/settingsSchemaTables.js +3 -0
  46. package/dist/headlessPermissionModeWire.d.ts +2 -2
  47. package/dist/headlessPermissionModeWire.js +11 -21
  48. package/dist/hitl/approvalHolds.d.ts +36 -0
  49. package/dist/hitl/approvalHolds.js +89 -0
  50. package/dist/hitl/approvalOutcomeNote.js +2 -1
  51. package/dist/hitl/approvalResolution.d.ts +3 -2
  52. package/dist/hitl/approvalResolution.js +21 -0
  53. package/dist/hitl/approvalsFeed.js +5 -0
  54. package/dist/hitl/askGateWire.js +3 -0
  55. package/dist/hitl/automaticAnswerVerdict.d.ts +8 -2
  56. package/dist/hitl/automaticAnswerVerdict.js +69 -21
  57. package/dist/hitl/decisionRefusal.d.ts +19 -0
  58. package/dist/hitl/decisionRefusal.js +63 -0
  59. package/dist/hitl/frameRouter.d.ts +10 -0
  60. package/dist/hitl/frameRouter.js +59 -3
  61. package/dist/hitl/gateLedger.d.ts +3 -0
  62. package/dist/hitl/gateLedger.js +17 -0
  63. package/dist/hitl/hitlBridge.d.ts +2 -2
  64. package/dist/hitl/hitlBridge.js +8 -10
  65. package/dist/hitl/hitlHostSurface.d.ts +6 -0
  66. package/dist/hitl/hitlHostSurface.js +25 -4
  67. package/dist/hitl/localAllowRule.js +2 -1
  68. package/dist/hitl/noAllowCause.d.ts +9 -0
  69. package/dist/hitl/noAllowCause.js +26 -0
  70. package/dist/hitl/parkResolver.js +6 -3
  71. package/dist/hitl/parkRowBirthWait.js +2 -1
  72. package/dist/hitl/persistedRulesWire.d.ts +6 -1
  73. package/dist/hitl/persistedRulesWire.js +12 -4
  74. package/dist/hitl/planReviewWire.d.ts +0 -1
  75. package/dist/hitl/planReviewWire.js +30 -9
  76. package/dist/hitl/sessionPolicyDeliverable.d.ts +1 -1
  77. package/dist/hitl/sessionPolicyDeliverable.js +3 -8
  78. package/dist/hitl/sessionPolicyWire.js +1 -1
  79. package/dist/hitl/toolApprovalWire.d.ts +37 -2
  80. package/dist/hitl/toolApprovalWire.js +392 -13
  81. package/dist/humanTurnRead.d.ts +15 -1
  82. package/dist/humanTurnRead.js +28 -2
  83. package/dist/index.d.ts +18 -6
  84. package/dist/index.js +14 -5
  85. package/dist/limitsWire.d.ts +0 -1
  86. package/dist/limitsWire.js +2 -10
  87. package/dist/liveModelCatalog.d.ts +14 -0
  88. package/dist/liveModelCatalog.js +61 -0
  89. package/dist/mcpProbeCapability.js +14 -9
  90. package/dist/mcpReconnect.js +13 -8
  91. package/dist/memoryComplianceCapability.js +15 -10
  92. package/dist/memoryOriginCapability.js +15 -10
  93. package/dist/modelIdentityResolvability.d.ts +4 -2
  94. package/dist/modelIdentityResolvability.js +31 -4
  95. package/dist/outputStyleSeatCapability.d.ts +16 -0
  96. package/dist/outputStyleSeatCapability.js +47 -0
  97. package/dist/ownKey.d.ts +1 -0
  98. package/dist/ownKey.js +10 -0
  99. package/dist/peerLaneCapability.js +16 -11
  100. package/dist/permissionRuleIssue.js +1 -1
  101. package/dist/permissionRulesWriteCapability.js +16 -11
  102. package/dist/permissionsAllowGrantCapability.d.ts +2 -0
  103. package/dist/permissionsAllowGrantCapability.js +38 -16
  104. package/dist/permissionsDeclaration.d.ts +10 -1
  105. package/dist/permissionsDeclaration.js +97 -15
  106. package/dist/protocolSegment.d.ts +1 -0
  107. package/dist/protocolSegment.js +13 -1
  108. package/dist/request/taskRequest.d.ts +11 -3
  109. package/dist/request/taskRequest.js +13 -1
  110. package/dist/resultFrameKeys.d.ts +4 -0
  111. package/dist/resultFrameKeys.js +13 -0
  112. package/dist/resumeRefusalCopy.js +6 -16
  113. package/dist/retryStatus.js +6 -4
  114. package/dist/rewindArchiveCapability.js +13 -8
  115. package/dist/{hitl/rosterMountedNames.d.ts → rosterMountedNames.d.ts} +1 -1
  116. package/dist/runCancelContext.js +2 -1
  117. package/dist/sealedKeyCapability.js +19 -14
  118. package/dist/seatContract.d.ts +33 -5
  119. package/dist/seatContract.js +143 -2
  120. package/dist/sessionPolicyCapability.js +15 -10
  121. package/dist/sessionReadRedactionCapability.d.ts +16 -0
  122. package/dist/sessionReadRedactionCapability.js +47 -0
  123. package/dist/sessionSyncFileHistoryCapability.js +14 -9
  124. package/dist/skillToolListsCapability.js +14 -9
  125. package/dist/sqlEngineCapability.js +18 -13
  126. package/dist/steerPriorityCapability.js +21 -16
  127. package/dist/subagent/agentStateDetail.d.ts +1 -0
  128. package/dist/subagent/agentStateDetail.js +41 -0
  129. package/dist/subagent/engineCompactWire.d.ts +15 -0
  130. package/dist/subagent/engineCompactWire.js +75 -13
  131. package/dist/supportFloor.js +1 -1
  132. package/dist/taskRequestWords.d.ts +2 -4
  133. package/dist/taskRequestWords.js +3 -2
  134. package/dist/types/engineState.d.ts +1 -1
  135. package/dist/userAttachmentEnvelope.d.ts +22 -1
  136. package/dist/userAttachmentEnvelope.js +90 -2
  137. package/dist/userInvokedSkillsCapability.js +14 -9
  138. package/dist/webSearchBackendCapability.js +21 -16
  139. package/dist/wireErrorTriage.d.ts +11 -0
  140. package/dist/wireErrorTriage.js +35 -0
  141. package/dist/wireFailureShape.d.ts +6 -0
  142. package/dist/wireFailureShape.js +30 -3
  143. package/dist/wireRefusalCopy.d.ts +6 -1
  144. package/dist/wireRefusalCopy.js +22 -8
  145. package/dist/wiringInstructionsAttribution.d.ts +10 -0
  146. package/dist/wiringInstructionsAttribution.js +67 -0
  147. package/dist/workflowClient.js +22 -1
  148. package/dist/workflowsJournalCapability.js +14 -9
  149. package/dist/writeProtectionCapability.js +28 -23
  150. package/docs/INTEGRATION-CLIENTS.md +817 -45
  151. package/package.json +5 -5
  152. package/dist/askSurvivesStandingAnswer.d.ts +0 -13
  153. package/dist/askSurvivesStandingAnswer.js +0 -53
  154. package/dist/hitl/askSurvivesPosture.d.ts +0 -20
  155. package/dist/hitl/askSurvivesPosture.js +0 -48
  156. /package/dist/{hitl/rosterMountedNames.js → rosterMountedNames.js} +0 -0
package/dist/ownKey.js CHANGED
@@ -22,3 +22,13 @@ export function readOwnDataValue(v, key) {
22
22
  const d = Object.getOwnPropertyDescriptor(v, key);
23
23
  return d !== undefined && Object.hasOwn(d, 'value') ? d.value : undefined;
24
24
  }
25
+ export function readFrameStringKey(frame, key) {
26
+ try {
27
+ if (frame === null || typeof frame !== 'object' || Array.isArray(frame))
28
+ return undefined;
29
+ return readOwnDataNonEmptyString(frame, key);
30
+ }
31
+ catch {
32
+ return undefined;
33
+ }
34
+ }
@@ -1,18 +1,23 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
3
  export function projectPeerLaneCapability(caps) {
4
- if (caps === null || typeof caps !== 'object')
5
- return undefined;
6
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
7
- return undefined;
8
- if (!Object.hasOwn(caps, 'peerLane'))
9
- return { kind: 'not_reported' };
10
- const v = caps.peerLane;
11
- if (v === undefined)
12
- return { kind: 'not_reported' };
13
- if (typeof v !== 'boolean')
4
+ try {
5
+ if (caps === null || typeof caps !== 'object')
6
+ return undefined;
7
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
8
+ return undefined;
9
+ if (!Object.hasOwn(caps, 'peerLane'))
10
+ return { kind: 'not_reported' };
11
+ const v = caps.peerLane;
12
+ if (v === undefined)
13
+ return { kind: 'not_reported' };
14
+ if (typeof v !== 'boolean')
15
+ return undefined;
16
+ return v ? { kind: 'present' } : { kind: 'absent' };
17
+ }
18
+ catch {
14
19
  return undefined;
15
- return v ? { kind: 'present' } : { kind: 'absent' };
20
+ }
16
21
  }
17
22
  const reader = createEngineCapReader({
18
23
  name: 'peerLane',
@@ -31,7 +31,7 @@ const ISSUE_SENTENCES = Object.freeze({
31
31
  'unsupported.param_unknown': 'this parameter rule is not supported: the tool carries no such parameter, so it could never match',
32
32
  'unsupported.param_non_scalar': 'this parameter rule is not supported: that parameter holds an object or an array, so it could never match',
33
33
  'unsupported.tool_unknown': "this rule is not supported on this leg: the resolver it supplied does not know the tool, so the rule's face cannot be checked",
34
- 'unsupported.path_base': 'this path rule is not supported as spelled: it needs a base this policy was not given, so it would reach nothing and is refused rather than compiled',
34
+ 'unsupported.path_base': 'this path rule is not supported as spelled: the base it is relative to is missing or is not a usable absolute path, so it would reach nothing and is refused rather than compiled',
35
35
  'unsupported.mcp_paren': 'a parenthesised parameter rule is not supported on an MCP tool name',
36
36
  'unsupported.covering_paren': 'a parenthesised parameter rule is not supported on a covering protocol name — the parameter grammar is keyed by an exact tool name, so no mounted tool could ever bear it',
37
37
  'invalid.allow_param_rule': 'this rule is invalid: an allow rule cannot carry a parameter pattern — only bare tool rules auto-allow',
@@ -1,18 +1,23 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
3
  export function projectPermissionRulesWriteCapability(caps) {
4
- if (caps === null || typeof caps !== 'object')
5
- return undefined;
6
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
7
- return undefined;
8
- if (!Object.hasOwn(caps, 'permissionRulesWrite'))
9
- return { kind: 'not_reported' };
10
- const v = caps.permissionRulesWrite;
11
- if (v === undefined)
12
- return { kind: 'not_reported' };
13
- if (typeof v !== 'boolean')
4
+ try {
5
+ if (caps === null || typeof caps !== 'object')
6
+ return undefined;
7
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
8
+ return undefined;
9
+ if (!Object.hasOwn(caps, 'permissionRulesWrite'))
10
+ return { kind: 'not_reported' };
11
+ const v = caps.permissionRulesWrite;
12
+ if (v === undefined)
13
+ return { kind: 'not_reported' };
14
+ if (typeof v !== 'boolean')
15
+ return undefined;
16
+ return v ? { kind: 'present' } : { kind: 'absent' };
17
+ }
18
+ catch {
14
19
  return undefined;
15
- return v ? { kind: 'present' } : { kind: 'absent' };
20
+ }
16
21
  }
17
22
  const reader = createEngineCapReader({
18
23
  name: 'permissionRulesWrite',
@@ -5,6 +5,7 @@ export type PermissionsAllowGrantReading = {
5
5
  } | {
6
6
  kind: 'present';
7
7
  grants: boolean;
8
+ layer?: boolean;
8
9
  };
9
10
  export declare function projectPermissionsAllowGrantCapability(caps: unknown): PermissionsAllowGrantReading | undefined;
10
11
  export declare function noteEngineCapsForPermissionsAllowGrant(baseUrl: string, caps: unknown, opts?: {
@@ -12,6 +13,7 @@ export declare function noteEngineCapsForPermissionsAllowGrant(baseUrl: string,
12
13
  }): void;
13
14
  export declare function observedPermissionsAllowGrant(baseUrl?: string | undefined): PermissionsAllowGrantReading;
14
15
  export declare function permissionsAllowGrantAvailable(reading: PermissionsAllowGrantReading): boolean;
16
+ export declare function allowWireForm(reading: PermissionsAllowGrantReading): 'layer' | 'grant' | 'off';
15
17
  export declare function allowRulesGate(reading: PermissionsAllowGrantReading, settingsRead: 'clean' | 'partial' | 'unreadable' | undefined): 'open' | 'capability_off' | 'settings_read_not_clean';
16
18
  export declare function permissionsAllowGrantDoctorDetail(reading: PermissionsAllowGrantReading, settingsRead?: 'clean' | 'partial' | 'unreadable'): string;
17
19
  export declare function forgetPermissionsAllowGrantReading(baseUrl: string | undefined): void;
@@ -1,25 +1,39 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
+ import { hasCoreValuePort } from './coreValuePorts.js';
3
4
  const ALLOW_GRANT_CAP_PATH = ['settings', 'permissions', 'allowGrant'];
5
+ const ALLOW_LAYER_CAP_LEAF = 'allowLayer';
4
6
  export function projectPermissionsAllowGrantCapability(caps) {
5
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
6
- return undefined;
7
- let node = caps;
8
- for (let i = 0; i < ALLOW_GRANT_CAP_PATH.length; i++) {
9
- const seg = ALLOW_GRANT_CAP_PATH[i];
10
- if (!Object.hasOwn(node, seg))
11
- return { kind: 'not_reported' };
12
- const v = node[seg];
13
- if (v === undefined)
14
- return { kind: 'not_reported' };
15
- if (i === ALLOW_GRANT_CAP_PATH.length - 1) {
16
- return typeof v === 'boolean' ? { kind: 'present', grants: v } : undefined;
17
- }
18
- if (v === null || typeof v !== 'object' || Array.isArray(v))
7
+ try {
8
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
19
9
  return undefined;
20
- node = v;
10
+ let node = caps;
11
+ for (let i = 0; i < ALLOW_GRANT_CAP_PATH.length; i++) {
12
+ const seg = ALLOW_GRANT_CAP_PATH[i];
13
+ if (!Object.hasOwn(node, seg))
14
+ return { kind: 'not_reported' };
15
+ const v = node[seg];
16
+ if (v === undefined)
17
+ return { kind: 'not_reported' };
18
+ if (i === ALLOW_GRANT_CAP_PATH.length - 1) {
19
+ if (typeof v !== 'boolean')
20
+ return undefined;
21
+ if (!Object.hasOwn(node, ALLOW_LAYER_CAP_LEAF))
22
+ return { kind: 'present', grants: v };
23
+ const layer = node[ALLOW_LAYER_CAP_LEAF];
24
+ if (layer === undefined)
25
+ return { kind: 'present', grants: v };
26
+ return typeof layer === 'boolean' ? { kind: 'present', grants: v, layer } : undefined;
27
+ }
28
+ if (v === null || typeof v !== 'object' || Array.isArray(v))
29
+ return undefined;
30
+ node = v;
31
+ }
32
+ return undefined;
33
+ }
34
+ catch {
35
+ return undefined;
21
36
  }
22
- return undefined;
23
37
  }
24
38
  const reader = createEngineCapReader({
25
39
  name: ALLOW_GRANT_CAP_PATH.join('.'),
@@ -44,6 +58,11 @@ export function permissionsAllowGrantAvailable(reading) {
44
58
  return false;
45
59
  }
46
60
  }
61
+ export function allowWireForm(reading) {
62
+ if (!permissionsAllowGrantAvailable(reading))
63
+ return 'off';
64
+ return ownReadingField(reading, 'layer') === true && hasCoreValuePort('compileAllowList') ? 'layer' : 'grant';
65
+ }
47
66
  export function allowRulesGate(reading, settingsRead) {
48
67
  if (!permissionsAllowGrantAvailable(reading))
49
68
  return 'capability_off';
@@ -62,6 +81,9 @@ function ownReadingField(reading, key) {
62
81
  export function permissionsAllowGrantDoctorDetail(reading, settingsRead) {
63
82
  const gate = allowRulesGate(reading, settingsRead);
64
83
  if (gate === 'open') {
84
+ if (allowWireForm(reading) === 'layer') {
85
+ return 'allow rules sent to the engine, content forms included — a matching call is not asked, except for the kinds of question the engine always puts to a person, and an entry the engine reads as granting nothing is reported when the run starts';
86
+ }
65
87
  return 'allow rules sent to the engine — it reads them as rules, not as an exclusive list: a matching call counts as answered for, and the engine still raises its own prompts where it requires them';
66
88
  }
67
89
  if (gate === 'settings_read_not_clean') {
@@ -1,4 +1,5 @@
1
1
  import { type PermissionsAllowGrantReading } from './permissionsAllowGrantCapability.js';
2
+ export declare const WIRE_RULE_TRUST_ORDER: readonly ["policySettings", "cliArg", "flagSettings", "session", "userSettings", "localSettings", "projectSettings"];
2
3
  declare const RULE_TRUST_ORDER: readonly ["policySettings", "cliArg", "flagSettings", "session", "userSettings", "localSettings", "projectSettings"];
3
4
  export type WireRuleOrigin = (typeof RULE_TRUST_ORDER)[number];
4
5
  export interface WireRuleOrigins {
@@ -13,6 +14,7 @@ export interface PermissionsDeclarationInput {
13
14
  readonly origins?: WireRuleOrigins;
14
15
  readonly cliDeny?: readonly string[];
15
16
  readonly settingsRead: 'clean' | 'partial' | 'unreadable';
17
+ readonly clientOwnedServers?: readonly string[];
16
18
  }
17
19
  export interface PermissionsDeclarationBuckets {
18
20
  deny?: string[];
@@ -22,7 +24,7 @@ export interface PermissionsDeclarationBuckets {
22
24
  export interface PermissionsDeclaration {
23
25
  permissions?: PermissionsDeclarationBuckets;
24
26
  }
25
- export declare const PERMISSIONS_KEPT_REASONS: readonly ["allow_capability_off", "settings_read_not_clean", "empty_rule", "paren_in_tool_name", "retired_tool_name", "unprefixed_namespaced_name", "incomplete_protocol_name", "unminted_protocol_segment", "home_relative_path", "compile_refused", "content_form_not_grantable", "judge_failed", "duplicate"];
27
+ export declare const PERMISSIONS_KEPT_REASONS: readonly ["allow_capability_off", "settings_read_not_clean", "empty_rule", "paren_in_tool_name", "retired_tool_name", "unprefixed_namespaced_name", "incomplete_protocol_name", "unminted_protocol_segment", "home_relative_path", "compile_refused", "content_form_not_grantable", "judge_failed", "duplicate", "voids_allow_list"];
26
28
  export type PermissionsKeptReason = (typeof PERMISSIONS_KEPT_REASONS)[number];
27
29
  export interface PermissionsKeptRule {
28
30
  rule: string;
@@ -48,6 +50,13 @@ export interface PermissionsDeclarationReport extends PermissionsDeclaration {
48
50
  rewritten: PermissionsRewrittenRule[];
49
51
  unchecked: PermissionsUncheckedRule[];
50
52
  unreachable: PermissionsUnreachableRule[];
53
+ clientOwned?: PermissionsClientOwnedStatement[];
54
+ }
55
+ export interface PermissionsClientOwnedStatement {
56
+ server: string;
57
+ rule?: string;
58
+ sent: boolean;
59
+ reason?: PermissionsKeptReason;
51
60
  }
52
61
  export declare function permissionsDeclaration(input: PermissionsDeclarationInput, caps: PermissionsAllowGrantReading): PermissionsDeclaration;
53
62
  export declare function permissionsDeclarationReport(input: PermissionsDeclarationInput, caps: PermissionsAllowGrantReading): PermissionsDeclarationReport;
@@ -1,8 +1,8 @@
1
- import { hasCoreValuePort, protocolOf, retiredToolNames, ruleToolGrammarOf } from './coreValuePorts.js';
2
- import { protocolSegmentOf } from './protocolSegment.js';
1
+ import { compileAllowList, hasCoreValuePort, protocolOf, retiredToolNames, ruleToolGrammarOf } from './coreValuePorts.js';
2
+ import { clientOwnedServerPrefix, protocolSegmentOf } from './protocolSegment.js';
3
3
  import { ruleCompileVerdict } from './ruleCompileVerdict.js';
4
- import { allowRulesGate } from './permissionsAllowGrantCapability.js';
5
- const RULE_TRUST_ORDER = [
4
+ import { allowRulesGate, allowWireForm } from './permissionsAllowGrantCapability.js';
5
+ export const WIRE_RULE_TRUST_ORDER = Object.freeze([
6
6
  'policySettings',
7
7
  'cliArg',
8
8
  'flagSettings',
@@ -10,7 +10,8 @@ const RULE_TRUST_ORDER = [
10
10
  'userSettings',
11
11
  'localSettings',
12
12
  'projectSettings',
13
- ];
13
+ ]);
14
+ const RULE_TRUST_ORDER = WIRE_RULE_TRUST_ORDER;
14
15
  export const PERMISSIONS_KEPT_REASONS = Object.freeze([
15
16
  'allow_capability_off',
16
17
  'settings_read_not_clean',
@@ -25,6 +26,7 @@ export const PERMISSIONS_KEPT_REASONS = Object.freeze([
25
26
  'content_form_not_grantable',
26
27
  'judge_failed',
27
28
  'duplicate',
29
+ 'voids_allow_list',
28
30
  ]);
29
31
  function normalizeLegacyToolName(name) {
30
32
  switch (name) {
@@ -104,7 +106,7 @@ function sentFate(wire, toolName, unchecked) {
104
106
  ? { sent: true, wire, unchecked, unreachable: segment.minted !== undefined ? { minted: segment.minted } : {} }
105
107
  : { sent: true, wire, unchecked };
106
108
  }
107
- function judgeList(rules, behavior) {
109
+ function judgeList(rules, behavior, allowForm = 'grant') {
108
110
  let portsChecked = false;
109
111
  return rules.map((rule) => {
110
112
  if (rule === '')
@@ -138,8 +140,16 @@ function judgeList(rules, behavior) {
138
140
  return kept(issue);
139
141
  if (ruleToolGrammarOf(parsed.toolName) === 'path' && parsed.ruleContent.startsWith('~/'))
140
142
  return kept('home_relative_path');
141
- if (behavior === 'allow')
142
- return kept('content_form_not_grantable');
143
+ if (behavior === 'allow') {
144
+ if (allowForm !== 'layer')
145
+ return kept('content_form_not_grantable');
146
+ const segment = protocolSegmentOf(parsed.toolName);
147
+ if (segment.kind === 'unminted')
148
+ return kept('unminted_protocol_segment');
149
+ if (segment.kind === 'unknown')
150
+ return kept('judge_failed');
151
+ return { sent: true, wire: rule, unchecked: false };
152
+ }
143
153
  const verdict = compileVerdict(rule, behavior);
144
154
  if (verdict === 'refused')
145
155
  return kept('compile_refused');
@@ -149,7 +159,50 @@ function judgeList(rules, behavior) {
149
159
  function outsideSettingsFiles(origin) {
150
160
  return origin === 'cliArg' || origin === 'session';
151
161
  }
152
- function judgeBucket(raw, behavior, originOf, cli, settingsGate) {
162
+ function allowListVoiders(sent) {
163
+ const roster = new Set();
164
+ try {
165
+ const inertOf = (list) => {
166
+ const r = compileAllowList(list, 'allow', roster);
167
+ if (r === undefined || !Array.isArray(r.inert))
168
+ return undefined;
169
+ const out = new Map();
170
+ for (const i of r.inert) {
171
+ if (i === null || typeof i !== 'object' || typeof i.entry !== 'string' || typeof i.reason !== 'string')
172
+ return undefined;
173
+ if (!out.has(i.entry))
174
+ out.set(i.entry, i.reason);
175
+ }
176
+ return out;
177
+ };
178
+ const whole = inertOf(sent);
179
+ if (whole === undefined)
180
+ return 'unknown';
181
+ const alone = new Map();
182
+ for (const e of sent) {
183
+ const one = inertOf([e]);
184
+ if (one === undefined)
185
+ return 'unknown';
186
+ alone.set(e, one.get(e));
187
+ }
188
+ const collateral = [...whole].filter(([e]) => alone.get(e) === undefined);
189
+ if (collateral.length === 0)
190
+ return new Set();
191
+ const reasons = new Set(collateral.map(([, r]) => r));
192
+ const culprits = new Set(sent.filter((e) => { const r = alone.get(e); return r !== undefined && reasons.has(r); }));
193
+ if (culprits.size === 0)
194
+ return 'unknown';
195
+ const rest = sent.filter((e) => !culprits.has(e));
196
+ const after = inertOf(rest);
197
+ if (after === undefined || [...after.keys()].some((e) => alone.get(e) === undefined))
198
+ return 'unknown';
199
+ return culprits;
200
+ }
201
+ catch {
202
+ return 'unknown';
203
+ }
204
+ }
205
+ function judgeBucket(raw, behavior, originOf, cli, settingsGate, allowForm = 'grant', dropWire, owned = []) {
153
206
  const firstSlot = new Map();
154
207
  for (const s of raw)
155
208
  if (!firstSlot.has(s.rule))
@@ -171,6 +224,9 @@ function judgeBucket(raw, behavior, originOf, cli, settingsGate) {
171
224
  const place = (slot, fate) => {
172
225
  if (!fate.sent)
173
226
  return fate;
227
+ const dropped = dropWire?.(fate.wire);
228
+ if (dropped !== undefined)
229
+ return kept(dropped);
174
230
  if (winnerOf.has(fate.wire))
175
231
  return kept('duplicate');
176
232
  winnerOf.set(fate.wire, slot);
@@ -179,7 +235,7 @@ function judgeBucket(raw, behavior, originOf, cli, settingsGate) {
179
235
  };
180
236
  const appendGroup = (group, origin) => {
181
237
  const held = settingsGate !== undefined && !outsideSettingsFiles(origin);
182
- const fates = held ? group.map(() => kept(settingsGate)) : judgeList(group, behavior);
238
+ const fates = held ? group.map(() => kept(settingsGate)) : judgeList(group, behavior, allowForm);
183
239
  group.forEach((r, k) => fateOfRule.set(r, place(firstSlot.get(r), fates[k])));
184
240
  };
185
241
  RULE_TRUST_ORDER.forEach((origin, rank) => {
@@ -187,6 +243,7 @@ function judgeBucket(raw, behavior, originOf, cli, settingsGate) {
187
243
  cli.slots.forEach((s, k) => (cliFates[k] = place(s, cliFates[k])));
188
244
  appendGroup(groups[rank], origin);
189
245
  });
246
+ const ownedFates = owned.map((fate, k) => place({ rule: fate.sent ? fate.wire : '', list: 'allow', at: -1 - k }, fate));
190
247
  appendGroup(unknownOrigin, undefined);
191
248
  const fates = raw.map((s) => {
192
249
  const f = fateOfRule.get(s.rule);
@@ -194,7 +251,15 @@ function judgeBucket(raw, behavior, originOf, cli, settingsGate) {
194
251
  return f;
195
252
  return f.sent || f.reason === 'duplicate' ? kept('duplicate') : f;
196
253
  });
197
- return { sent, fates: [...fates, ...cliFates], winnerOf };
254
+ return { sent, fates: [...fates, ...cliFates], winnerOf, ownedFates };
255
+ }
256
+ function clientOwnedFate(server) {
257
+ if (server.length === 0)
258
+ return kept('empty_rule');
259
+ const prefix = clientOwnedServerPrefix(server);
260
+ if (typeof prefix !== 'string' || prefix.length <= 2 || !prefix.endsWith('__'))
261
+ return kept('judge_failed');
262
+ return judgeList([`${prefix}*`], 'allow')[0];
198
263
  }
199
264
  const WHO = 'permissionsDeclaration';
200
265
  function ownField(obj, key, where) {
@@ -248,6 +313,7 @@ function assemble(input, caps) {
248
313
  const ask = ruleList(ownField(input, 'ask', ''), 'ask');
249
314
  const allow = ruleList(ownField(input, 'allow', ''), 'allow');
250
315
  const cliDeny = ruleList(ownField(input, 'cliDeny', ''), 'cliDeny');
316
+ const ownedServers = [...new Set(ruleList(ownField(input, 'clientOwnedServers', ''), 'clientOwnedServers') ?? [])];
251
317
  const originsRaw = ownField(input, 'origins', '');
252
318
  let origins = {};
253
319
  if (originsRaw !== undefined && originsRaw !== null) {
@@ -267,9 +333,18 @@ function assemble(input, caps) {
267
333
  const allowSlots = slotsOf(allow, 'allow');
268
334
  const denyJ = judgeBucket(denySlots, 'deny', origins.deny, cli);
269
335
  const askJ = judgeBucket(askSlots, 'ask', origins.ask, undefined);
270
- const allowJ = gate === 'capability_off'
271
- ? { sent: [], fates: allowSlots.map(() => kept('allow_capability_off')), winnerOf: new Map() }
272
- : judgeBucket(allowSlots, 'allow', origins.allow, undefined, gate === 'settings_read_not_clean' ? 'settings_read_not_clean' : undefined);
336
+ const allowForm = allowWireForm(caps) === 'layer' ? 'layer' : 'grant';
337
+ const settingsGate = gate === 'settings_read_not_clean' ? 'settings_read_not_clean' : undefined;
338
+ let allowJ = gate === 'capability_off'
339
+ ? { sent: [], fates: allowSlots.map(() => kept('allow_capability_off')), winnerOf: new Map(), ownedFates: ownedServers.map(() => kept('allow_capability_off')) }
340
+ : judgeBucket(allowSlots, 'allow', origins.allow, undefined, settingsGate, allowForm, undefined, ownedServers.map(clientOwnedFate));
341
+ if (gate !== 'capability_off' && allowForm === 'layer' && allowJ.sent.length > 0) {
342
+ const voiders = allowListVoiders(allowJ.sent);
343
+ if (voiders === 'unknown' || voiders.size > 0) {
344
+ const drop = voiders === 'unknown' ? () => 'judge_failed' : (w) => (voiders.has(w) ? 'voids_allow_list' : undefined);
345
+ allowJ = judgeBucket(allowSlots, 'allow', origins.allow, undefined, settingsGate, allowForm, drop, ownedServers.map(clientOwnedFate));
346
+ }
347
+ }
273
348
  const buckets = {};
274
349
  if (denyJ.sent.length > 0)
275
350
  buckets.deny = [...denyJ.sent];
@@ -286,6 +361,11 @@ function assemble(input, caps) {
286
361
  ['ask', askSlots, askJ],
287
362
  ['allow', allowSlots, allowJ],
288
363
  ];
364
+ const clientOwned = ownedServers.map((server, k) => {
365
+ const f = allowJ.ownedFates[k];
366
+ const minted = f.sent ? f.wire : undefined;
367
+ return f.sent ? { server, rule: minted, sent: true } : { server, sent: false, reason: f.reason };
368
+ });
289
369
  for (const [bucket, slots, j] of rows) {
290
370
  slots.forEach((s, k) => {
291
371
  const f = j.fates[k];
@@ -294,6 +374,8 @@ function assemble(input, caps) {
294
374
  });
295
375
  for (const wire of j.sent) {
296
376
  const winner = j.winnerOf.get(wire);
377
+ if (winner.at < 0)
378
+ continue;
297
379
  if (winner.rule !== wire)
298
380
  rewritten.push({ from: winner.rule, to: wire, bucket });
299
381
  const f = (winner.list === 'cliDeny' ? j.fates[denySlots.length + winner.at] : j.fates[winner.at]);
@@ -304,7 +386,7 @@ function assemble(input, caps) {
304
386
  }
305
387
  }
306
388
  }
307
- return { buckets, report: { kept: keptRows, rewritten, unchecked, unreachable } };
389
+ return { buckets, report: { kept: keptRows, rewritten, unchecked, unreachable, ...(clientOwned.length > 0 ? { clientOwned } : {}) } };
308
390
  }
309
391
  export function permissionsDeclaration(input, caps) {
310
392
  const { buckets } = assemble(input, caps);
@@ -9,3 +9,4 @@ export type ProtocolSegment = {
9
9
  readonly kind: 'unknown';
10
10
  };
11
11
  export declare function protocolSegmentOf(name: string): ProtocolSegment;
12
+ export declare function clientOwnedServerPrefix(server: string): string | undefined;
@@ -1,4 +1,4 @@
1
- import { hasCoreValuePort, mintNamespacePrefix, protocolOf } from './coreValuePorts.js';
1
+ import { hasCoreValuePort, mcpNamespace, mintNamespacePrefix, protocolOf } from './coreValuePorts.js';
2
2
  import { CORE_PROTOCOL_PREFIXES } from './generated/toolNameTables.js';
3
3
  export function protocolSegmentOf(name) {
4
4
  if (CORE_PROTOCOL_PREFIXES.some((prefix) => name.startsWith(prefix) && name.slice(prefix.length).split('__')[0] === ''))
@@ -29,3 +29,15 @@ export function protocolSegmentOf(name) {
29
29
  return { kind: 'unknown' };
30
30
  return minted === `${ns.prefix}${peer}__` ? { kind: 'ok' } : { kind: 'unminted', minted };
31
31
  }
32
+ export function clientOwnedServerPrefix(server) {
33
+ try {
34
+ const ns = mcpNamespace();
35
+ if (ns === undefined)
36
+ return undefined;
37
+ const prefix = mintNamespacePrefix(ns, server);
38
+ return typeof prefix === 'string' ? prefix : undefined;
39
+ }
40
+ catch {
41
+ return undefined;
42
+ }
43
+ }
@@ -1,4 +1,6 @@
1
1
  import type { TaskRequest } from '@sema-agent/sdk';
2
+ import { type OutputStyleSeatReading } from '../outputStyleSeatCapability.js';
3
+ import { type ApprovalReachWord } from '../approvalReachWire.js';
2
4
  export type RequestLane = 'interactive' | 'print' | 'utility';
3
5
  export type TaskRequestLike = Record<string, unknown>;
4
6
  export interface RequestFieldSpec {
@@ -10,7 +12,7 @@ export interface RequestFieldSpec {
10
12
  whyUtilityLane: string;
11
13
  }
12
14
  export declare const REQUEST_FIELD_MATRIX: readonly RequestFieldSpec[];
13
- export declare const LIVE_DEFAULT_FIELDS: readonly ["cwd", "additionalDirectories", "additionalReadDirectories", "forwardSubagentEvents", "retainSubagentSessions", "agents", "appendSystemPrompt|settings.outputStyle", "suggestNextPrompts", "compactionModel", "sessionId(三态解析)"];
15
+ export declare const LIVE_DEFAULT_FIELDS: readonly ["cwd", "additionalDirectories", "additionalReadDirectories", "forwardSubagentEvents", "retainSubagentSessions", "agents", "appendSystemPrompt|settings.outputStyle", "outputStyle(每轮一句座,见位才落)", "suggestNextPrompts", "compactionModel", "sessionId(三态解析)"];
14
16
  export interface TaskRequestInput {
15
17
  objective: string;
16
18
  sessionId: string;
@@ -38,6 +40,7 @@ export interface TaskRequestInput {
38
40
  limits?: Record<string, unknown>;
39
41
  interactiveTools?: false;
40
42
  oneShot?: true;
43
+ approvalReach?: ApprovalReachWord;
41
44
  excludeAllTools?: true;
42
45
  outputSchema?: NonNullable<TaskRequest['outputSchema']>;
43
46
  outputRetries?: number;
@@ -48,10 +51,10 @@ export interface TaskRequestInput {
48
51
  maxThinkingTokens?: number;
49
52
  memoryCapture?: 'off';
50
53
  memory?: 'off';
51
- fileHistory?: 'disabled';
54
+ fileHistory?: TaskRequest['fileHistory'];
52
55
  inheritEnv?: InheritEnvWord;
53
56
  requireExistingSession?: TaskRequest['requireExistingSession'];
54
- disableSkills?: true;
57
+ disableSkills?: TaskRequest['disableSkills'];
55
58
  rewind?: Record<string, unknown>;
56
59
  repo?: string;
57
60
  council?: boolean;
@@ -133,6 +136,11 @@ export interface LiveDefaultsInput {
133
136
  forAppend: string;
134
137
  forOutputStyle: string;
135
138
  };
139
+ outputStyleSeat?: {
140
+ name: string;
141
+ turnReminder?: string;
142
+ };
143
+ outputStyleSeatReading?: OutputStyleSeatReading;
136
144
  suggestNextPrompts?: boolean;
137
145
  compactionModel?: string;
138
146
  capturedSessionId?: string;
@@ -1,6 +1,8 @@
1
1
  import { refuseBadDisableSkills, refuseDisableSkillsConflict } from '../disableSkillsWire.js';
2
2
  import { ATTACHMENTS_SPEC_KEYS, AttachmentsSpecRefused } from '../attachmentsWireCaps.js';
3
3
  import { retiredAttachmentsKeyOf } from '../taskRequestWords.js';
4
+ import { outputStyleSeatAdmitted } from '../outputStyleSeatCapability.js';
5
+ import { refuseBadApprovalReach } from '../approvalReachWire.js';
4
6
  export const REQUEST_FIELD_MATRIX = [
5
7
  { field: 'objective', lanes: ['interactive', 'print', 'utility'], live: false, why: '本 turn 的真实输入,每条车道都必需', whyUtilityLane: '恒座:三条车道都必须带上本次提交的模型面输入' },
6
8
  { field: 'sessionId', lanes: ['interactive', 'print', 'utility'], live: false, why: '单命名空间(TP-A Step 2):壳 id 即引擎 session id;print 在非 live 下保留 mock 常量', whyUtilityLane: '恒座:side-channel 提交走**独立**会话 id(壳另铸一个,绝不复用用户会话那一个 —— 复用会把这次提交的转录混进用户会话)' },
@@ -48,6 +50,7 @@ export const REQUEST_FIELD_MATRIX = [
48
50
  { field: 'resumeAt/resumeAtMode/restoreFiles/rewindFilesTo', lanes: ['interactive'], live: false, why: 'E18 `/rewind` 是交互命令;四键同生同灭(CC-145:core 6.0.0 起 both 臂发 restoreFiles;CC-223 起退役键 rewindFiles 不再有座 —— 交它按表外子键响亮拒;resumeAtMode 是 both/conversation 两臂恒带的排他截语义位)', whyUtilityLane: '无座:回退是交互命令,而 side-channel 是一次性的独立会话,没有可回退的历史' },
49
51
  { field: 'clientContext', lanes: ['interactive'], live: false, why: 'IANA 时区 + 可选邮箱 → core 本地化 `# Environment` 的 today;print 同样跑在用户机器上,缺席让引擎误标 (UTC)', gap: true, whyUtilityLane: '无座:本地化 today 的用途在用户会话的环境段,而 side-channel 的系统提示由壳整段给出 —— 这一列我判不准要不要(与本行 `gap` 同一条待办:要补先单独立项)' },
50
52
  { field: 'scratchpadDir', lanes: ['interactive'], live: true, why: '[816]③ per-session 暂存目录;print 也有 session,缺席让 `-p` 的工具写不进 exemptDir', gap: true, whyUtilityLane: '无座:per-session 暂存目录是给**工具**写的,零工具面上没人写' },
53
+ { field: 'approvalReach', lanes: ['print'], live: true, why: '「这条运行上没有人能答审批」的**逐运行声明**(服务端 7.118.0 提交体键,值闭集由引擎 `APPROVAL_REACH` 派生;声明在场 ⇒ 这条腿的问不发活卡、第一个要审批的调用停驻或拒)。只有无人值守车道有座:那里「审批函数在 ≠ 有人能答」;交互车道恒有人坐在对面能答,声明 none 会把能答的人挡在外面。🔴 只在能力读数为真时由片段口 `approvalReachDeclaration` 给值(老服务端对表外键整份 400)', whyUtilityLane: '无座:side-channel 强制零工具面(`excludeAllTools`),没有门控调用、不会问审批 ⇒ 声明没有对象;带上它只会在不认识这一键的老服务端上给这条提交多一种 400' },
51
54
  ];
52
55
  export const LIVE_DEFAULT_FIELDS = Object.freeze([
53
56
  'cwd',
@@ -57,6 +60,7 @@ export const LIVE_DEFAULT_FIELDS = Object.freeze([
57
60
  'retainSubagentSessions',
58
61
  'agents',
59
62
  'appendSystemPrompt|settings.outputStyle',
63
+ 'outputStyle(每轮一句座,见位才落)',
60
64
  'suggestNextPrompts',
61
65
  'compactionModel',
62
66
  'sessionId(三态解析)',
@@ -143,6 +147,7 @@ const INPUT_KEY_ROUTES = {
143
147
  limits: row('limits'),
144
148
  interactiveTools: row('interactiveTools'),
145
149
  oneShot: row('oneShot'),
150
+ approvalReach: row('approvalReach'),
146
151
  outputSchema: row('outputSchema'),
147
152
  outputRetries: row('outputRetries'),
148
153
  maxCostUsd: row('maxCostUsd'),
@@ -586,7 +591,7 @@ export function parseMaxCostUsd(text) {
586
591
  return { ok: false, why: 'not_positive' };
587
592
  return { ok: true, value };
588
593
  }
589
- const ACCESSOR_READ_ORDER = ['live', 'memoryCapture', 'memory', 'settings', 'maxCostUsd', 'excludeAllTools', 'maxTokens', 'outputRetries', 'fileHistory', 'inheritEnv', 'requireExistingSession', 'disableSkills'];
594
+ const ACCESSOR_READ_ORDER = ['live', 'memoryCapture', 'memory', 'settings', 'maxCostUsd', 'excludeAllTools', 'maxTokens', 'outputRetries', 'fileHistory', 'inheritEnv', 'requireExistingSession', 'disableSkills', 'approvalReach'];
590
595
  function dataFirstSnapshot(input, afterData) {
591
596
  let descs;
592
597
  try {
@@ -657,6 +662,7 @@ export function assembleTaskRequest(input, lane) {
657
662
  const inheritEnvIn = src.inheritEnv;
658
663
  const requireExistingSessionIn = src.requireExistingSession;
659
664
  const disableSkillsIn = src.disableSkills;
665
+ const approvalReachIn = src.approvalReach;
660
666
  const INPUT_KEYS = Object.keys(INPUT_KEY_ROUTES);
661
667
  const i = snapshotByName(src, INPUT_KEYS, {
662
668
  live,
@@ -670,6 +676,7 @@ export function assembleTaskRequest(input, lane) {
670
676
  inheritEnv: inheritEnvIn,
671
677
  requireExistingSession: requireExistingSessionIn,
672
678
  disableSkills: disableSkillsIn,
679
+ approvalReach: approvalReachIn,
673
680
  settings: settingsIn,
674
681
  });
675
682
  const SETTINGS_KEYS = Object.keys(SETTINGS_KEY_ROUTES);
@@ -684,6 +691,7 @@ export function assembleTaskRequest(input, lane) {
684
691
  refuseBadInheritEnv(inheritEnvIn);
685
692
  refuseBadRequireExistingSession(requireExistingSessionIn);
686
693
  refuseBadDisableSkills(disableSkillsIn, 'buildTaskRequest');
694
+ refuseBadApprovalReach(approvalReachIn, 'buildTaskRequest');
687
695
  const rewindRoute = INPUT_KEY_ROUTES.rewind;
688
696
  const RETIRED_REWIND_FILES_KEY = 'rewindFiles';
689
697
  const REWIND_KEYS = rewindRoute.via === 'matrix' ? rewindRoute.field.split('/') : [];
@@ -839,6 +847,7 @@ export function assembleTaskRequest(input, lane) {
839
847
  ...(on('inheritEnv') ? { inheritEnv: inheritEnvIn } : {}),
840
848
  ...(on('requireExistingSession') ? { requireExistingSession: true } : {}),
841
849
  ...(on('disableSkills') ? { disableSkills: true } : {}),
850
+ ...(on('approvalReach') ? { approvalReach: approvalReachIn } : {}),
842
851
  ...(Object.keys(settingsOut).length > 0 ? { settings: settingsOut } : {}),
843
852
  };
844
853
  return Object.freeze({ request: out, omitted: Object.freeze([...omitted, ...lateOmitted]) });
@@ -875,6 +884,9 @@ export function applyLiveRequestDefaults(req, host) {
875
884
  out.settings = { ...settings, outputStyle: host.selfKnowledge.forOutputStyle };
876
885
  }
877
886
  }
887
+ if (out.outputStyle === undefined && host.outputStyleSeat !== undefined && outputStyleSeatAdmitted(host.outputStyleSeatReading)) {
888
+ out.outputStyle = { ...host.outputStyleSeat };
889
+ }
878
890
  if (out.suggestNextPrompts === undefined &&
879
891
  out.verify === undefined &&
880
892
  out.cascade === undefined &&
@@ -0,0 +1,4 @@
1
+ export declare function resultErrorCodeOf(frame: unknown): string | undefined;
2
+ export declare function resultSelectedModelOf(frame: unknown): string | undefined;
3
+ export declare function resultSalvagedResultOf(frame: unknown): string | undefined;
4
+ export declare function resultParkFailedReasonOf(frame: unknown): string | undefined;
@@ -0,0 +1,13 @@
1
+ import { readFrameStringKey } from './ownKey.js';
2
+ export function resultErrorCodeOf(frame) {
3
+ return readFrameStringKey(frame, '_sema_error_code');
4
+ }
5
+ export function resultSelectedModelOf(frame) {
6
+ return readFrameStringKey(frame, '_sema_selected_model');
7
+ }
8
+ export function resultSalvagedResultOf(frame) {
9
+ return readFrameStringKey(frame, '_sema_salvaged_result');
10
+ }
11
+ export function resultParkFailedReasonOf(frame) {
12
+ return readFrameStringKey(frame, '_sema_park_failed_reason');
13
+ }