@sema-agent/client-core 0.98.0 → 0.99.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 (192) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/README.md +35 -22
  3. package/dist/adapt/arms.js +61 -20
  4. package/dist/adapt/panelTasks.d.ts +1 -1
  5. package/dist/adapt/panelTasks.js +2 -2
  6. package/dist/adapter/activeRunSelfHeal.d.ts +4 -3
  7. package/dist/adapter/activeRunSelfHeal.js +162 -293
  8. package/dist/adapter/downstream/eventToSdkMessage.js +52 -4
  9. package/dist/adapter/runStream.js +52 -37
  10. package/dist/adapter/types.js +2 -1
  11. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  12. package/dist/agentsWireCaps.d.ts +0 -3
  13. package/dist/agentsWireCaps.js +33 -24
  14. package/dist/cloudConfigWireCaps.d.ts +1 -1
  15. package/dist/cloudConfigWireCaps.js +26 -4
  16. package/dist/controlRouter.d.ts +4 -2
  17. package/dist/controlRouter.js +39 -51
  18. package/dist/coreValuePorts.d.ts +26 -1
  19. package/dist/coreValuePorts.js +10 -0
  20. package/dist/corruptSessionCopy.d.ts +2 -1
  21. package/dist/corruptSessionCopy.js +3 -3
  22. package/dist/declared/supportFloorDeclared.js +1 -1
  23. package/dist/detachWire.js +3 -2
  24. package/dist/devicesFace.d.ts +34 -0
  25. package/dist/devicesFace.js +90 -0
  26. package/dist/displayUntrusted.d.ts +1 -0
  27. package/dist/displayUntrusted.js +3 -0
  28. package/dist/engineAgentPanelStore.d.ts +7 -0
  29. package/dist/engineAgentPanelStore.js +14 -0
  30. package/dist/engineCapReader.d.ts +2 -1
  31. package/dist/engineCapReader.js +7 -5
  32. package/dist/engineCapsCache.d.ts +8 -0
  33. package/dist/engineCapsCache.js +59 -6
  34. package/dist/engineCapsChange.d.ts +2 -0
  35. package/dist/engineCapsChange.js +9 -0
  36. package/dist/engineErrorCodes.d.ts +2 -1
  37. package/dist/engineErrorCodes.js +2 -7
  38. package/dist/engineRowRef.js +3 -0
  39. package/dist/engineSessionMessages.d.ts +1 -0
  40. package/dist/engineSessionMessages.js +7 -1
  41. package/dist/engineTargetSeat.d.ts +27 -0
  42. package/dist/engineTargetSeat.js +199 -0
  43. package/dist/engineWireFor.js +3 -8
  44. package/dist/env/uiLanguage.d.ts +2 -1
  45. package/dist/env/uiLanguage.js +3 -2
  46. package/dist/eventLeg.d.ts +8 -0
  47. package/dist/eventLeg.js +61 -41
  48. package/dist/fileHistoryCaptureCapability.d.ts +2 -1
  49. package/dist/fileHistoryCaptureCapability.js +12 -18
  50. package/dist/fileHistoryLegNotice.d.ts +2 -1
  51. package/dist/fileHistoryLegNotice.js +3 -3
  52. package/dist/frameBinding.d.ts +3 -0
  53. package/dist/frameBinding.js +12 -0
  54. package/dist/gateOutcome.js +16 -2
  55. package/dist/gateVocabulary.d.ts +8 -7
  56. package/dist/gateVocabulary.js +71 -73
  57. package/dist/generated/engineFactTables.d.ts +17 -1
  58. package/dist/generated/engineFactTables.js +29 -0
  59. package/dist/generated/engineNoticeTables.js +9 -3
  60. package/dist/generated/settingsSchemaFns.d.ts +6 -0
  61. package/dist/generated/settingsSchemaFns.js +57 -0
  62. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  63. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  64. package/dist/generated/settingsSchemaTables.d.ts +1 -0
  65. package/dist/generated/settingsSchemaTables.js +4 -0
  66. package/dist/generated/settingsSchemaTypes.d.ts +105 -0
  67. package/dist/generated/settingsSchemaTypes.js +1 -0
  68. package/dist/hitl/allowRuleShadow.d.ts +2 -1
  69. package/dist/hitl/allowRuleShadow.js +17 -14
  70. package/dist/hitl/approvalCardReasons.d.ts +3 -2
  71. package/dist/hitl/approvalCardReasons.js +27 -28
  72. package/dist/hitl/approvalHolds.d.ts +3 -0
  73. package/dist/hitl/approvalHolds.js +73 -29
  74. package/dist/hitl/askClassPair.d.ts +1 -1
  75. package/dist/hitl/askClassPair.js +16 -0
  76. package/dist/hitl/askGateWire.js +2 -1
  77. package/dist/hitl/askSettlementLine.d.ts +14 -4
  78. package/dist/hitl/askSettlementLine.js +67 -47
  79. package/dist/hitl/automaticAnswerVerdict.d.ts +2 -1
  80. package/dist/hitl/automaticAnswerVerdict.js +8 -8
  81. package/dist/hitl/crashConvergedNotice.d.ts +5 -4
  82. package/dist/hitl/crashConvergedNotice.js +28 -41
  83. package/dist/hitl/frameRouter.js +7 -8
  84. package/dist/hitl/hitlBridge.d.ts +1 -0
  85. package/dist/hitl/hitlBridge.js +3 -3
  86. package/dist/hitl/persistedRulesWire.d.ts +6 -5
  87. package/dist/hitl/persistedRulesWire.js +55 -73
  88. package/dist/hitl/planReviewWire.d.ts +5 -0
  89. package/dist/hitl/planReviewWire.js +8 -0
  90. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  91. package/dist/hitl/sessionPolicyDeliverable.js +46 -3
  92. package/dist/hitl/sessionPolicyWire.d.ts +2 -1
  93. package/dist/hitl/sessionPolicyWire.js +23 -24
  94. package/dist/hitl/suspendedReopen.d.ts +2 -1
  95. package/dist/hitl/suspendedReopen.js +7 -10
  96. package/dist/hitl/toolApprovalWire.d.ts +17 -5
  97. package/dist/hitl/toolApprovalWire.js +79 -40
  98. package/dist/hooksWireCaps.js +145 -56
  99. package/dist/host.d.ts +21 -0
  100. package/dist/hostTurnSettings.d.ts +71 -0
  101. package/dist/hostTurnSettings.js +291 -0
  102. package/dist/humanTurn.d.ts +14 -1
  103. package/dist/humanTurn.js +100 -12
  104. package/dist/humanTurnRead.d.ts +2 -0
  105. package/dist/humanTurnRead.js +22 -1
  106. package/dist/i18n/messages.en.d.ts +582 -0
  107. package/dist/i18n/messages.en.js +582 -0
  108. package/dist/i18n/messages.zh.js +718 -1
  109. package/dist/index.d.ts +29 -13
  110. package/dist/index.js +18 -9
  111. package/dist/inheritEnvCapability.d.ts +3 -2
  112. package/dist/inheritEnvCapability.js +3 -3
  113. package/dist/inheritEnvWire.d.ts +3 -2
  114. package/dist/inheritEnvWire.js +12 -14
  115. package/dist/interactiveHalt.js +17 -6
  116. package/dist/liveModelCatalog.d.ts +2 -1
  117. package/dist/liveModelCatalog.js +14 -8
  118. package/dist/mcpPanel.d.ts +10 -1
  119. package/dist/mcpPanel.js +40 -13
  120. package/dist/mcpProbeCapability.d.ts +2 -1
  121. package/dist/mcpProbeCapability.js +7 -11
  122. package/dist/mcpProbeWire.d.ts +3 -1
  123. package/dist/mcpProbeWire.js +5 -0
  124. package/dist/mcpWireCaps.d.ts +34 -0
  125. package/dist/mcpWireCaps.js +117 -17
  126. package/dist/memoryEntriesWire.js +5 -10
  127. package/dist/model/onboardJudgement.d.ts +93 -0
  128. package/dist/model/onboardJudgement.js +415 -0
  129. package/dist/model/tierVocabulary.d.ts +2 -0
  130. package/dist/model/tierVocabulary.js +17 -5
  131. package/dist/modelCapabilityProbe.d.ts +64 -0
  132. package/dist/modelCapabilityProbe.js +600 -0
  133. package/dist/modelIdentityResolvability.d.ts +3 -0
  134. package/dist/modelIdentityResolvability.js +26 -17
  135. package/dist/ownKey.d.ts +7 -0
  136. package/dist/ownKey.js +34 -0
  137. package/dist/panelReduce.d.ts +6 -1
  138. package/dist/panelReduce.js +50 -3
  139. package/dist/permissionRuleIssue.js +2 -0
  140. package/dist/permissionRulesWriteCapability.d.ts +2 -1
  141. package/dist/permissionRulesWriteCapability.js +8 -6
  142. package/dist/pluginHooksWire.d.ts +46 -3
  143. package/dist/pluginHooksWire.js +217 -11
  144. package/dist/printModelStatus.d.ts +63 -0
  145. package/dist/printModelStatus.js +155 -0
  146. package/dist/request/taskRequest.d.ts +11 -5
  147. package/dist/request/taskRequest.js +112 -16
  148. package/dist/resumeRefusalCopy.d.ts +12 -9
  149. package/dist/resumeRefusalCopy.js +70 -143
  150. package/dist/retryStatus.d.ts +37 -0
  151. package/dist/retryStatus.js +79 -0
  152. package/dist/scenarioRefusal.d.ts +9 -0
  153. package/dist/scenarioRefusal.js +111 -0
  154. package/dist/seam.d.ts +25 -1
  155. package/dist/seam.js +10 -1
  156. package/dist/seatContract.d.ts +260 -10
  157. package/dist/seatContract.js +692 -19
  158. package/dist/selfOrchestrationDenial.js +7 -19
  159. package/dist/sessionIdSegment.d.ts +6 -0
  160. package/dist/sessionIdSegment.js +24 -0
  161. package/dist/sessionMemoryStatus.js +6 -11
  162. package/dist/sessionPolicyCapability.d.ts +2 -1
  163. package/dist/sessionPolicyCapability.js +8 -6
  164. package/dist/settingsHooksSalvage.d.ts +44 -0
  165. package/dist/settingsHooksSalvage.js +211 -0
  166. package/dist/skillToolListsCapability.d.ts +2 -1
  167. package/dist/skillToolListsCapability.js +8 -6
  168. package/dist/sseIdleTriage.js +3 -2
  169. package/dist/subagent/engineSubagentResume.js +15 -9
  170. package/dist/subagentContentStore.d.ts +3 -0
  171. package/dist/subagentContentStore.js +22 -0
  172. package/dist/toolHistoryMismatch.js +3 -2
  173. package/dist/toolRoster.d.ts +3 -2
  174. package/dist/toolRoster.js +21 -20
  175. package/dist/turnFailurePresentation.d.ts +12 -1
  176. package/dist/turnFailurePresentation.js +212 -15
  177. package/dist/usageAnalytics.js +6 -11
  178. package/dist/userAttachmentEnvelope.d.ts +1 -0
  179. package/dist/userAttachmentEnvelope.js +37 -7
  180. package/dist/userAttachmentSeat.d.ts +21 -0
  181. package/dist/userAttachmentSeat.js +75 -0
  182. package/dist/userInvokedSkillsCapability.d.ts +11 -1
  183. package/dist/userInvokedSkillsCapability.js +31 -7
  184. package/dist/wireErrorTriage.d.ts +7 -0
  185. package/dist/wireErrorTriage.js +23 -1
  186. package/dist/wireFailureShape.js +2 -1
  187. package/dist/wireRefusalCopy.d.ts +13 -1
  188. package/dist/wireRefusalCopy.js +24 -28
  189. package/dist/workflowsJournalCapability.d.ts +2 -1
  190. package/dist/workflowsJournalCapability.js +8 -6
  191. package/docs/INTEGRATION-CLIENTS.md +542 -30
  192. package/package.json +5 -5
@@ -1,7 +1,8 @@
1
1
  import { cancelConflictContent, cancelConflictFromError } from './wireRefusalCopy.js';
2
- import { PROTOCOL_ERROR_NAME, protocolErrorNameOf } from './wireFailureShape.js';
2
+ import { PROTOCOL_ERROR_NAME, THROWN_SLOT_UNREADABLE, protocolErrorNameOf, readThrownSlot, readThrownStatusSlot } from './wireFailureShape.js';
3
3
  import { steerPriorityMode } from './steerPriorityCapability.js';
4
4
  import { preemptReadingOfAck, preemptReadingOfError } from './preemptWire.js';
5
+ import { msg, renderMessage } from './i18n/translate.js';
5
6
  export class ControlSafetyError extends Error {
6
7
  code;
7
8
  cause;
@@ -156,10 +157,11 @@ export class ControlRouter {
156
157
  export function errCodes(e) {
157
158
  if (!e || typeof e !== 'object')
158
159
  return {};
159
- const o = e;
160
- const code = typeof o.errorCode === 'string' ? o.errorCode : undefined;
161
- const name = typeof o.name === 'string' ? o.name : undefined;
162
- const rawStatus = o.status ?? o.statusCode;
160
+ const rawCode = readThrownSlot(e, 'errorCode', 'data');
161
+ const code = typeof rawCode === 'string' ? rawCode : undefined;
162
+ const rawName = readThrownSlot(e, 'name');
163
+ const name = typeof rawName === 'string' ? rawName : undefined;
164
+ const rawStatus = readThrownStatusSlot(e);
163
165
  const status = typeof rawStatus === 'number' ? rawStatus : undefined;
164
166
  return { code, name, status };
165
167
  }
@@ -185,48 +187,32 @@ const STEERING_NAME_TO_SAFETY = {
185
187
  SteeringError: 'steering_other',
186
188
  };
187
189
  const STEERING_COPY = {
188
- not_running: {
189
- happened: 'that run is not accepting messages right now — it has just finished, is running on another server, or is not the active run of its session',
190
- nextStep: 'check its current state and send the message to the run that is active',
191
- },
192
- invalid_content: {
193
- happened: 'the message was refused because its text contains control markers the engine does not accept, so nothing was delivered',
194
- nextStep: 'rewrite the message and send it again',
195
- },
196
- queue_full: {
197
- happened: 'that run is paused and already holds as many waiting messages as it can, so this one was not accepted',
198
- nextStep: 'send it again once the waiting messages have been delivered (when the run resumes or the session is woken)',
199
- },
200
- duplicate_input_id: {
201
- happened: 'a different instruction was already accepted under this idempotency key, and that earlier instruction stands',
202
- nextStep: 'if you changed the text, send the new text under a new key; otherwise do not resend it — a new key would deliver the same instruction twice',
203
- },
204
- ambiguous_target: {
205
- happened: 'more than one running agent matches that target, so the message was not delivered',
206
- nextStep: 'address a sub-agent by its tool-call id; a workflow agent cannot be singled out while another running agent shares its label, so send it again once only one does',
207
- },
208
- still_running: {
209
- happened: 'that agent is still running, so it cannot be resumed',
210
- nextStep: 'send it a message instead, or wait for it to finish',
211
- },
212
- blocked_by_hook: {
213
- happened: "the message was not accepted: a prompt check on this deployment blocked it, so nothing was delivered",
214
- nextStep: 'edit the message and send it again — that is not a duplicate submission',
215
- },
216
- ledger_unavailable: {
217
- happened: 'the server could not record the message and refused it before anything reached the engine, so nothing was delivered',
218
- nextStep: 'send the same text again later',
219
- },
220
- steering_other: {
221
- happened: 'the message was refused for a reason this version does not recognise, so it did not land',
222
- nextStep: 'report its error code if this keeps happening; do not guess what it means',
223
- },
190
+ not_running: { happened: 'session.steerRefusal.notRunning.happened', nextStep: 'session.steerRefusal.notRunning.nextStep' },
191
+ invalid_content: { happened: 'session.steerRefusal.invalidContent.happened', nextStep: 'session.steerRefusal.invalidContent.nextStep' },
192
+ queue_full: { happened: 'session.steerRefusal.queueFull.happened', nextStep: 'session.steerRefusal.queueFull.nextStep' },
193
+ duplicate_input_id: { happened: 'session.steerRefusal.duplicateInputId.happened', nextStep: 'session.steerRefusal.duplicateInputId.nextStep' },
194
+ ambiguous_target: { happened: 'session.steerRefusal.ambiguousTarget.happened', nextStep: 'session.steerRefusal.ambiguousTarget.nextStep' },
195
+ still_running: { happened: 'session.steerRefusal.stillRunning.happened', nextStep: 'session.steerRefusal.stillRunning.nextStep' },
196
+ blocked_by_hook: { happened: 'session.steerRefusal.blockedByHook.happened', nextStep: 'session.steerRefusal.blockedByHook.nextStep' },
197
+ ledger_unavailable: { happened: 'session.steerRefusal.ledgerUnavailable.happened', nextStep: 'session.steerRefusal.ledgerUnavailable.nextStep' },
198
+ steering_other: { happened: 'session.steerRefusal.steeringOther.happened', nextStep: 'session.steerRefusal.steeringOther.nextStep' },
224
199
  };
225
- const adviceOfCopy = (c) => `${c.happened} — ${c.nextStep}`;
226
- const STEERING_ADVICE = Object.freeze(Object.fromEntries(Object.entries(STEERING_COPY).map(([k, c]) => [k, adviceOfCopy(c)])));
200
+ const adviceOfCopy = (c, lang) => renderMessage(msg('session.steerRefusal.advice', { happened: c.happened, nextStep: c.nextStep }), lang);
201
+ function hostQueueFactOf(v) {
202
+ return v === 'queued_until_turn_end' || v === 'dropped' ? v : 'unknown';
203
+ }
204
+ function renderedCopyOf(keys, lang, hostQueue) {
205
+ const happened = renderMessage(msg(keys.happened), lang);
206
+ const tableNextStep = renderMessage(msg(keys.nextStep), lang);
207
+ if (hostQueue === 'queued_until_turn_end')
208
+ return { happened, nextStep: renderMessage(msg('session.steerRefusal.hostQueue.queued'), lang) };
209
+ if (hostQueue === 'dropped')
210
+ return { happened, nextStep: renderMessage(msg('session.steerRefusal.hostQueue.dropped', { nextStep: tableNextStep }), lang) };
211
+ return { happened, nextStep: tableNextStep };
212
+ }
227
213
  const STEERING_OTHER_UNKNOWN_COPY = {
228
- happened: 'the message was refused for a reason this version does not recognise, and whether it was delivered is not known',
229
- nextStep: 'do not resend it as if it had certainly been dropped — check the run first, and report its error code if this keeps happening',
214
+ happened: 'session.steerRefusal.steeringOtherUnknown.happened',
215
+ nextStep: 'session.steerRefusal.steeringOtherUnknown.nextStep',
230
216
  };
231
217
  const CANCEL_NOT_FOUND_COPY = {
232
218
  happened: 'this server has no run with that id for you — it does not exist, or it belongs to someone else',
@@ -262,7 +248,7 @@ function steeringCopyOf(e, safety) {
262
248
  return STEERING_COPY[safety];
263
249
  }
264
250
  const STEERING_REFUSED_BEFORE_ENGINE = new Map([['ledger_unavailable', 503]]);
265
- export function steeringRefusedBeforeEngine(e) {
251
+ export function steeringRefusedBeforeEngine(e, hostQueue, lang) {
266
252
  try {
267
253
  const { status } = errCodes(e);
268
254
  if (status === undefined)
@@ -270,8 +256,8 @@ export function steeringRefusedBeforeEngine(e) {
270
256
  const safety = steeringVerdict(e);
271
257
  if (safety === undefined || STEERING_REFUSED_BEFORE_ENGINE.get(safety) !== status)
272
258
  return undefined;
273
- const copy = STEERING_COPY[safety];
274
- return { safety, advice: STEERING_ADVICE[safety], happened: copy.happened, nextStep: copy.nextStep };
259
+ const copy = renderedCopyOf(STEERING_COPY[safety], lang, hostQueueFactOf(hostQueue));
260
+ return { safety, advice: adviceOfCopy(copy, lang), happened: copy.happened, nextStep: copy.nextStep };
275
261
  }
276
262
  catch {
277
263
  return undefined;
@@ -288,17 +274,19 @@ function steeringVerdict(e) {
288
274
  if (typeof code === 'string' && code.startsWith('steering.')) {
289
275
  return STEERING_CODE_TO_SAFETY.get(code) ?? 'steering_other';
290
276
  }
277
+ if (readThrownSlot(e, 'errorCode', 'data') === THROWN_SLOT_UNREADABLE)
278
+ return undefined;
291
279
  const protocolName = protocolErrorNameOf(e);
292
280
  return protocolName !== undefined ? STEERING_NAME_TO_SAFETY[protocolName] : undefined;
293
281
  }
294
- export function steerRefusalAdviceOf(e) {
282
+ export function steerRefusalAdviceOf(e, hostQueue, lang) {
295
283
  try {
296
284
  const verdict = steeringVerdict(e);
297
285
  if (verdict === undefined)
298
286
  return undefined;
299
287
  const safety = steeringSafetyOf(e, verdict);
300
- const copy = steeringCopyOf(e, safety);
301
- return { safety, advice: adviceOfCopy(copy), happened: copy.happened, nextStep: copy.nextStep };
288
+ const copy = renderedCopyOf(steeringCopyOf(e, safety), lang, hostQueueFactOf(hostQueue));
289
+ return { safety, advice: adviceOfCopy(copy, lang), happened: copy.happened, nextStep: copy.nextStep };
302
290
  }
303
291
  catch {
304
292
  return undefined;
@@ -97,6 +97,27 @@ export interface RuleToolNameVerdictView {
97
97
  readonly guidance?: string;
98
98
  readonly currentName?: string;
99
99
  }
100
+ export type RuleEntryReadingView = {
101
+ readonly kind: 'row';
102
+ readonly compiled: RuleEntryCompiledView;
103
+ } | {
104
+ readonly kind: 'inert';
105
+ readonly reason: string;
106
+ readonly verdict?: string;
107
+ readonly guidance?: string;
108
+ readonly currentName?: string;
109
+ readonly valueType?: string;
110
+ };
111
+ export interface RuleEntryCompiledView {
112
+ readonly kind: string;
113
+ }
114
+ export type McpToolAxesReadView = {
115
+ readonly ok: true;
116
+ readonly toolAxes?: Readonly<Record<string, object>>;
117
+ } | {
118
+ readonly ok: false;
119
+ readonly problem: string;
120
+ };
100
121
  export interface CoreValuePorts {
101
122
  resolveAutonomousLoopPrompt: (prompt: string, opts?: AutonomousLoopPromptOptionsView) => string | null;
102
123
  loosenReasons: (prior: SessionPermissionRules, next: SessionPermissionRules) => string[];
@@ -118,8 +139,10 @@ export interface CoreValuePorts {
118
139
  adjudicateRoute?(model: RouteModelView, perModelAuth?: PerModelAuthView): RouteAdjudicationView | undefined;
119
140
  }, model: RouteModelView, perModelAuth?: PerModelAuthView): RoutePairingStatusView;
120
141
  judgeRuleToolName(name: string, roster: ReadonlySet<string>): RuleToolNameVerdictView;
142
+ readRuleEntry(raw: {} | null | undefined, behavior: 'allow' | 'deny', roster?: ReadonlySet<string>): RuleEntryReadingView;
143
+ readMcpToolAxes(declared: {} | null | undefined): McpToolAxesReadView;
121
144
  }
122
- 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"];
145
+ 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"];
123
146
  export type CoreValuePortName = (typeof CORE_VALUE_PORT_NAMES)[number];
124
147
  export declare function installCoreValuePorts(ports: Partial<CoreValuePorts> | null): () => void;
125
148
  export declare function hasCoreValuePorts(): boolean;
@@ -145,3 +168,5 @@ export declare function adjudicateModelRoute(model: RouteModelView, credential:
145
168
  export declare function routePairingStatus(brain: {
146
169
  adjudicateRoute?(model: RouteModelView, perModelAuth?: PerModelAuthView): RouteAdjudicationView | undefined;
147
170
  }, model: RouteModelView, perModelAuth?: PerModelAuthView): RoutePairingStatusView | undefined;
171
+ export declare function readRuleEntry(raw: {} | null | undefined, behavior: 'allow' | 'deny', roster?: ReadonlySet<string>): RuleEntryReadingView | undefined;
172
+ export declare function readMcpToolAxes(declared: {} | null | undefined): McpToolAxesReadView | undefined;
@@ -15,6 +15,8 @@ export const CORE_VALUE_PORT_NAMES = Object.freeze([
15
15
  'adjudicateModelRoute',
16
16
  'routePairingStatus',
17
17
  'judgeRuleToolName',
18
+ 'readRuleEntry',
19
+ 'readMcpToolAxes',
18
20
  ]);
19
21
  let installed = null;
20
22
  export function installCoreValuePorts(ports) {
@@ -99,3 +101,11 @@ export function routePairingStatus(brain, model, perModelAuth) {
99
101
  const fn = port('routePairingStatus');
100
102
  return fn === undefined ? undefined : fn(brain, model, perModelAuth);
101
103
  }
104
+ export function readRuleEntry(raw, behavior, roster) {
105
+ const fn = port('readRuleEntry');
106
+ return fn === undefined ? undefined : fn(raw, behavior, roster);
107
+ }
108
+ export function readMcpToolAxes(declared) {
109
+ const fn = port('readMcpToolAxes');
110
+ return fn === undefined ? undefined : fn(declared);
111
+ }
@@ -1 +1,2 @@
1
- export declare function corruptSessionContent(): string;
1
+ import type { UiLanguage } from './env/uiLanguage.js';
2
+ export declare function corruptSessionContent(lang?: UiLanguage): string;
@@ -1,4 +1,4 @@
1
- export function corruptSessionContent() {
2
- return ("This session's saved history cannot be read — its stored log is damaged — so the engine cannot open this session. " +
3
- 'Retrying will not help: whoever operates this engine has to repair or remove that stored log. Until then, continue in a new session.');
1
+ import { msg, renderMessage } from './i18n/translate.js';
2
+ export function corruptSessionContent(lang) {
3
+ return renderMessage(msg('session.corrupt.content'), lang);
4
4
  }
@@ -1,5 +1,5 @@
1
1
  export const DECLARED_SUPPORT_FLOOR = Object.freeze({
2
2
  server: "7.129.1",
3
3
  core: "7.51.2",
4
- sdk: "23.0.2",
4
+ sdk: "23.1.0",
5
5
  });
@@ -1,5 +1,6 @@
1
1
  import { hostEnv } from './hostEnv.js';
2
2
  import { envFlagOff } from './envFlag.js';
3
+ import { readThrownSlot } from './wireFailureShape.js';
3
4
  import { resolveWireAuth } from './engineWireSdk.js';
4
5
  export const DETACH_HEADER = 'x-detach-on-disconnect';
5
6
  export const HEADLESS_DETACH_ENV = 'SEMA_HEADLESS_DETACH';
@@ -13,10 +14,10 @@ export async function resolveHeadlessDetach(env = hostEnv()) {
13
14
  }
14
15
  export const DETACH_DURABLE_OFF_400_ANCHOR = 'x-detach-on-disconnect requires a durable run';
15
16
  export function isDetachDurableOff400(err) {
17
+ if (readThrownSlot(err, 'status', 'data') !== 400)
18
+ return false;
16
19
  try {
17
20
  const e = err;
18
- if (e?.status !== 400)
19
- return false;
20
21
  const msg = e?.message;
21
22
  return typeof msg === 'string' && msg.includes(DETACH_DURABLE_OFF_400_ANCHOR);
22
23
  }
@@ -0,0 +1,34 @@
1
+ import { type SeatCapabilityReading } from './seatContract.js';
2
+ import { type DeviceExecutorManagementReading } from './deviceExecutorManagementCapability.js';
3
+ import type { DeviceListOutcome } from './deviceRebind.js';
4
+ import type { UiLanguage } from './env/uiLanguage.js';
5
+ export type DevicesFaceUnavailableWhy = 'host_not_wired' | 'host_not_reported' | 'host_report_unreadable' | 'lane_absent' | 'lane_unreported';
6
+ export type DevicesFace = {
7
+ readonly kind: 'unavailable';
8
+ readonly why: DevicesFaceUnavailableWhy;
9
+ } | {
10
+ readonly kind: 'probe_pending';
11
+ } | {
12
+ readonly kind: 'probe_failed';
13
+ readonly retryable: true;
14
+ readonly cause: 'transport' | 'refused' | 'unreadable';
15
+ } | {
16
+ readonly kind: 'verbs_off';
17
+ } | {
18
+ readonly kind: 'manage';
19
+ readonly probe: boolean;
20
+ };
21
+ export interface DevicesFaceInput {
22
+ readonly host: {
23
+ readonly kind: 'seat';
24
+ readonly capability: SeatCapabilityReading;
25
+ } | {
26
+ readonly kind: 'direct';
27
+ readonly sliceArmed: boolean;
28
+ };
29
+ readonly engine?: DeviceExecutorManagementReading | undefined;
30
+ readonly lastList?: DeviceListOutcome | undefined;
31
+ }
32
+ export declare function devicesFaceOf(input: DevicesFaceInput): DevicesFace;
33
+ export declare function devicesWritesAllowed(face: DevicesFace): boolean;
34
+ export declare function devicesFaceDetail(face: DevicesFace, lang?: UiLanguage): string | undefined;
@@ -0,0 +1,90 @@
1
+ import { seatCapabilityUnavailableDetail } from './seatContract.js';
2
+ import { deviceLaneOpen, deviceManagementVerbsAvailable } from './deviceExecutorManagementCapability.js';
3
+ import { ownDataField } from './ownKey.js';
4
+ import { msg, renderMessage } from './i18n/translate.js';
5
+ const freeze = (v) => Object.freeze(v);
6
+ const field = (v, key) => {
7
+ if (v === null || typeof v !== 'object')
8
+ return undefined;
9
+ try {
10
+ return ownDataField(v, key);
11
+ }
12
+ catch {
13
+ return undefined;
14
+ }
15
+ };
16
+ function hostProblem(host) {
17
+ const kind = field(host, 'kind');
18
+ if (kind === 'direct')
19
+ return field(host, 'sliceArmed') === true ? undefined : 'host_not_wired';
20
+ if (kind !== 'seat')
21
+ return 'host_report_unreadable';
22
+ const reading = field(host, 'capability');
23
+ const rk = field(reading, 'kind');
24
+ if (rk === 'reported')
25
+ return field(reading, 'available') === true ? undefined : 'host_not_wired';
26
+ if (rk === 'not_reported')
27
+ return 'host_not_reported';
28
+ return 'host_report_unreadable';
29
+ }
30
+ export function devicesFaceOf(input) {
31
+ const engineRaw = field(input, 'engine');
32
+ const engine = { kind: field(engineRaw, 'kind'), management: field(engineRaw, 'management') };
33
+ const lane = deviceLaneOpen(engine);
34
+ const listKind = field(field(input, 'lastList'), 'kind');
35
+ if (lane === 'no' || listKind === 'lane-absent')
36
+ return freeze({ kind: 'unavailable', why: 'lane_absent' });
37
+ const host = field(input, 'host');
38
+ const hostWhy = hostProblem(host);
39
+ if (hostWhy !== undefined)
40
+ return freeze({ kind: 'unavailable', why: hostWhy });
41
+ if (listKind === 'unarmed')
42
+ return freeze({ kind: 'unavailable', why: 'host_not_wired' });
43
+ if (lane === 'unknown') {
44
+ if (field(host, 'kind') === 'direct')
45
+ return freeze({ kind: 'unavailable', why: 'lane_unreported' });
46
+ if (listKind === undefined)
47
+ return freeze({ kind: 'probe_pending' });
48
+ if (listKind === 'ok')
49
+ return freeze({ kind: 'manage', probe: true });
50
+ const cause = listKind === 'transport' || listKind === 'refused' ? listKind : 'unreadable';
51
+ return freeze({ kind: 'probe_failed', retryable: true, cause });
52
+ }
53
+ const verbs = deviceManagementVerbsAvailable(engine);
54
+ if (verbs === 'no')
55
+ return freeze({ kind: 'verbs_off' });
56
+ return freeze({ kind: 'manage', probe: verbs === 'unknown' });
57
+ }
58
+ export function devicesWritesAllowed(face) {
59
+ return field(face, 'kind') === 'manage';
60
+ }
61
+ const UNWIRED = freeze({ kind: 'reported', available: false });
62
+ const NOT_REPORTED = freeze({ kind: 'not_reported' });
63
+ const MALFORMED = freeze({ kind: 'malformed' });
64
+ export function devicesFaceDetail(face, lang) {
65
+ const kind = field(face, 'kind');
66
+ if (kind === 'manage')
67
+ return undefined;
68
+ if (kind === 'probe_pending')
69
+ return renderMessage(msg('session.devices.probePending'), lang);
70
+ if (kind === 'verbs_off')
71
+ return renderMessage(msg('session.devices.verbsOff'), lang);
72
+ if (kind === 'probe_failed') {
73
+ const cause = field(face, 'cause');
74
+ if (cause === 'transport')
75
+ return renderMessage(msg('session.devices.probeFailedTransport'), lang);
76
+ if (cause === 'refused')
77
+ return renderMessage(msg('session.devices.probeFailedRefused'), lang);
78
+ return renderMessage(msg('session.devices.probeFailedUnreadable'), lang);
79
+ }
80
+ const why = kind === 'unavailable' ? field(face, 'why') : undefined;
81
+ if (why === 'lane_absent')
82
+ return renderMessage(msg('session.devices.laneAbsent'), lang);
83
+ if (why === 'lane_unreported')
84
+ return renderMessage(msg('session.devices.laneUnreported'), lang);
85
+ if (why === 'host_not_wired')
86
+ return seatCapabilityUnavailableDetail('devices', UNWIRED);
87
+ if (why === 'host_not_reported')
88
+ return seatCapabilityUnavailableDetail('devices', NOT_REPORTED);
89
+ return seatCapabilityUnavailableDetail('devices', MALFORMED);
90
+ }
@@ -44,6 +44,7 @@ export declare function credentialWashPasses(text: string, opts?: DisplayUntrust
44
44
  capped: boolean;
45
45
  };
46
46
  export declare function displayUntrusted(text: string, opts?: DisplayUntrustedOptions): string;
47
+ export declare function cleanUntrustedScalar(v: string | number | bigint | boolean | null | undefined): string;
47
48
  export declare function queryCarriesCredential(query: string): boolean;
48
49
  export declare function displayConfiguredUrl(url: string, opts?: DisplayUntrustedOptions): string;
49
50
  export declare function quoteUntrustedForSentence(text: string, max: number): string | undefined;
@@ -4663,6 +4663,9 @@ export function displayUntrusted(text, opts = {}) {
4663
4663
  const out = renderUntrusted(text, opts, null);
4664
4664
  return typeof out === 'string' ? out : out.text;
4665
4665
  }
4666
+ export function cleanUntrustedScalar(v) {
4667
+ return displayUntrusted(String(v ?? ''), { credentialUrls: false, credentialWords: false, foldLines: false });
4668
+ }
4666
4669
  const NON_SECRET_FIELD_NAMES = new Set([
4667
4670
  'deployment', 'deploymentname', 'deploymentid', 'name', 'tenant', 'tenantname', 'tenantid', 'region', 'location', 'zone',
4668
4671
  'project', 'projectname', 'projectid', 'workspace', 'workspacename', 'workspaceid', 'resource', 'resourcename', 'resourcegroup',
@@ -46,6 +46,7 @@ export type EngineAgentPanelEvent = {
46
46
  report?: string;
47
47
  wireTaskId?: string;
48
48
  taskIdOrigin?: 'fleet-row' | 'wire';
49
+ sessionId?: string;
49
50
  } | {
50
51
  kind: 'sweep';
51
52
  };
@@ -58,6 +59,12 @@ export declare function clearEnginePanelTaskResidentByWire(wireTaskId: string, c
58
59
  export declare function __resetEngineAgentPanelIdentityForTests(): void;
59
60
  export declare function __resetEnginePanelStateForTests(): void;
60
61
  export declare function publishEngineAgentPanelEvent(ev: EngineAgentPanelEvent): void;
62
+ export interface EngineAgentPanelStart {
63
+ taskId: string;
64
+ startedAt?: number;
65
+ workflowRunId?: string;
66
+ }
67
+ export declare function publishEngineAgentPanelStart(ev: EngineAgentPanelStart): void;
61
68
  export declare function subscribeEnginePanelRows(fn: (delta: PanelDelta) => void): () => void;
62
69
  export interface EngineAgentPanelAbsence {
63
70
  taskId: string;
@@ -1,4 +1,5 @@
1
1
  import { isNewEngineAgentPanelCycle, isStaleEngineAgentPanelEnd, panelIsResident, panelResolveTaskId, MAX_HELD_WIRE_TICK_BEATS, } from './panelReduce.js';
2
+ import { guardedRead, readOwnDataFiniteNumber, readOwnDataNonEmptyString } from './ownKey.js';
2
3
  import { clearEnginePanelIdentity, panelStateNow, stepEnginePanel, subscribeRows, resetEnginePanelHolder } from './panelStateHolder.js';
3
4
  export { isNewEngineAgentPanelCycle, isStaleEngineAgentPanelEnd, MAX_HELD_WIRE_TICK_BEATS };
4
5
  const _panelToolUsesLanePins = [true, true];
@@ -31,6 +32,19 @@ export function __resetEnginePanelStateForTests() {
31
32
  export function publishEngineAgentPanelEvent(ev) {
32
33
  stepEnginePanel(ev);
33
34
  }
35
+ export function publishEngineAgentPanelStart(ev) {
36
+ const taskId = guardedRead(() => readOwnDataNonEmptyString(ev, 'taskId'));
37
+ if (taskId === undefined)
38
+ return;
39
+ const startedAt = guardedRead(() => readOwnDataFiniteNumber(ev, 'startedAt'));
40
+ const workflowRunId = guardedRead(() => readOwnDataNonEmptyString(ev, 'workflowRunId'));
41
+ stepEnginePanel({
42
+ kind: 'start',
43
+ taskId,
44
+ ...(startedAt !== undefined ? { startedAt } : {}),
45
+ ...(workflowRunId !== undefined ? { workflowRunId } : {}),
46
+ });
47
+ }
34
48
  export function subscribeEnginePanelRows(fn) {
35
49
  return subscribeRows(fn);
36
50
  }
@@ -1,3 +1,4 @@
1
+ import type { UiLanguage } from './env/uiLanguage.js';
1
2
  interface EngineCapReaderSpec<R> {
2
3
  name: string;
3
4
  project: (caps: unknown) => R | undefined;
@@ -12,7 +13,7 @@ interface EngineCapReader<R> {
12
13
  observed(baseUrl: string | undefined): R | ReaderUnobserved | ReaderUnreadable;
13
14
  }
14
15
  export declare function createEngineCapReader<R>(spec: EngineCapReaderSpec<R>): EngineCapReader<R>;
15
- export declare function unreadableReadingDetail(subject?: string): string;
16
+ export declare function unreadableReadingDetail(subject?: string, lang?: UiLanguage): string;
16
17
  export type StoreSeat = {
17
18
  kind: 'object';
18
19
  store: object;
@@ -1,7 +1,10 @@
1
1
  import { engineCapsLandingOf } from './engineCapsCache.js';
2
+ import { msg, renderMessage } from './i18n/translate.js';
2
3
  import { ownDataField } from './ownKey.js';
3
- const unobserved = () => ({ kind: 'unobserved' });
4
- const unreadable = () => ({ kind: 'unreadable' });
4
+ const UNOBSERVED = Object.freeze({ kind: 'unobserved' });
5
+ const UNREADABLE = Object.freeze({ kind: 'unreadable' });
6
+ const unobserved = () => UNOBSERVED;
7
+ const unreadable = () => UNREADABLE;
5
8
  function freezeReading(reading, seen = new Set()) {
6
9
  if (reading === null || typeof reading !== 'object' || seen.has(reading))
7
10
  return reading;
@@ -49,9 +52,8 @@ export function createEngineCapReader(spec) {
49
52
  },
50
53
  };
51
54
  }
52
- export function unreadableReadingDetail(subject) {
53
- const head = typeof subject === 'string' && subject.length > 0 ? `${subject} could not be read` : 'could not be read';
54
- return `${head} — the engine's /v1/capabilities report arrived, but this entry is not in a form this client reads, so it is shown as unknown, not as absent; probing the same engine again will not change it while the engine reports it this way`;
55
+ export function unreadableReadingDetail(subject, lang) {
56
+ return renderMessage(typeof subject === 'string' && subject.length > 0 ? msg('notice.capability.unreadable.subject', { subject }) : msg('notice.capability.unreadable.bare'), lang);
55
57
  }
56
58
  export function storeSeatOf(caps) {
57
59
  try {
@@ -6,6 +6,11 @@ export type EngineCapsLanding = {
6
6
  } | {
7
7
  readonly kind: 'unreadable';
8
8
  };
9
+ export interface EngineCapsChange {
10
+ readonly kind: 'landed' | 'invalidated' | 'replaced';
11
+ readonly baseUrl: string;
12
+ readonly generation: number;
13
+ }
9
14
  export declare function engineCapsGeneration(baseUrl: string): number;
10
15
  export declare function engineCapsLandingOf(baseUrl: string | undefined): EngineCapsLanding;
11
16
  export declare function kickEngineCapsProbe(baseUrl: string, probe: () => Promise<unknown>): void;
@@ -42,6 +47,9 @@ export declare function engineCapString(baseUrl: string | undefined, key: string
42
47
  export declare function invalidateEngineCaps(baseUrl: string | undefined, probe?: () => Promise<unknown>): void;
43
48
  export type EngineCapsProbeRotation = 'started' | 'registered' | 'ignored';
44
49
  export declare function rotateEngineCapsProbe(baseUrl: string | undefined, probe: () => Promise<unknown>): EngineCapsProbeRotation;
50
+ export type EngineCapsReprobe = 'reprobed' | 'no_probe' | 'ignored';
51
+ export declare function invalidateEngineCapsAndReprobe(baseUrl: string | undefined): EngineCapsReprobe;
52
+ export declare function registerCapsChangeDelivery(baseUrl: string | undefined, deliver: (change: EngineCapsChange) => void): () => void;
45
53
  export declare function refreshEngineCapsOnce(baseUrl: string | undefined, opts?: {
46
54
  withinMs?: number;
47
55
  }): Promise<'settled' | 'timed_out' | 'no_probe'>;
@@ -4,11 +4,11 @@ const NOT_LANDED = Object.freeze({ kind: 'not_landed' });
4
4
  const capsByBase = new Map();
5
5
  const inFlight = new Set();
6
6
  const settleByBase = new Map();
7
- const genByBase = new Map();
7
+ const stateByBase = new Map();
8
8
  const probeByBase = new Map();
9
9
  const refreshByBase = new Map();
10
10
  function capsGeneration(baseUrl) {
11
- return genByBase.get(baseUrl) ?? 0;
11
+ return stateByBase.get(baseUrl)?.gen ?? 0;
12
12
  }
13
13
  export function engineCapsGeneration(baseUrl) {
14
14
  return capsGeneration(baseUrl);
@@ -169,6 +169,7 @@ function landCapsSnapshot(baseUrl, gen, caps) {
169
169
  ? Object.freeze({ kind: 'unreadable' })
170
170
  : Object.freeze({ kind: 'landed', caps: snapshot });
171
171
  capsByBase.set(baseUrl, record);
172
+ publishCapsChange(baseUrl, 'landed');
172
173
  return 'landed';
173
174
  }
174
175
  function snapshotCapsBody(body) {
@@ -355,18 +356,25 @@ export function invalidateEngineCaps(baseUrl, probe) {
355
356
  return;
356
357
  if (probe === undefined)
357
358
  probeByBase.delete(baseUrl);
358
- const hadState = capsByBase.has(baseUrl) ||
359
+ const hadLanding = capsByBase.has(baseUrl);
360
+ const hadState = hadLanding ||
359
361
  inFlight.has(baseUrl) ||
360
362
  settleByBase.has(baseUrl) ||
361
- genByBase.has(baseUrl);
363
+ stateByBase.get(baseUrl)?.gen !== undefined;
362
364
  if (hadState) {
363
- genByBase.set(baseUrl, capsGeneration(baseUrl) + 1);
365
+ const st = stateByBase.get(baseUrl);
366
+ if (st === undefined)
367
+ stateByBase.set(baseUrl, { gen: 1, subscribers: new Set() });
368
+ else
369
+ st.gen = capsGeneration(baseUrl) + 1;
364
370
  capsByBase.delete(baseUrl);
365
371
  inFlight.delete(baseUrl);
366
372
  settleByBase.get(baseUrl)?.wake();
367
373
  }
368
374
  if (probe !== undefined)
369
375
  kickEngineCapsProbe(baseUrl, probe);
376
+ if (hadLanding)
377
+ publishCapsChange(baseUrl, probe !== undefined ? 'replaced' : 'invalidated');
370
378
  }
371
379
  export function rotateEngineCapsProbe(baseUrl, probe) {
372
380
  try {
@@ -381,6 +389,51 @@ export function rotateEngineCapsProbe(baseUrl, probe) {
381
389
  return 'ignored';
382
390
  }
383
391
  }
392
+ export function invalidateEngineCapsAndReprobe(baseUrl) {
393
+ try {
394
+ if (typeof baseUrl !== 'string' || baseUrl === '')
395
+ return 'ignored';
396
+ const probe = probeByBase.get(baseUrl);
397
+ if (probe === undefined)
398
+ return 'no_probe';
399
+ invalidateEngineCaps(baseUrl, probe);
400
+ return 'reprobed';
401
+ }
402
+ catch {
403
+ return 'ignored';
404
+ }
405
+ }
406
+ export function registerCapsChangeDelivery(baseUrl, deliver) {
407
+ if (typeof baseUrl !== 'string' || baseUrl === '' || typeof deliver !== 'function')
408
+ return () => { };
409
+ let st = stateByBase.get(baseUrl);
410
+ if (st === undefined) {
411
+ st = { gen: undefined, subscribers: new Set() };
412
+ stateByBase.set(baseUrl, st);
413
+ }
414
+ const sub = { deliver, live: true };
415
+ const owner = st;
416
+ owner.subscribers.add(sub);
417
+ return () => {
418
+ if (!sub.live)
419
+ return;
420
+ sub.live = false;
421
+ owner.subscribers.delete(sub);
422
+ if (owner.subscribers.size === 0 && owner.gen === undefined && stateByBase.get(baseUrl) === owner)
423
+ stateByBase.delete(baseUrl);
424
+ };
425
+ }
426
+ function publishCapsChange(baseUrl, kind) {
427
+ const subs = stateByBase.get(baseUrl)?.subscribers;
428
+ if (subs === undefined || subs.size === 0)
429
+ return;
430
+ const change = Object.freeze({ kind, baseUrl, generation: capsGeneration(baseUrl) });
431
+ for (const sub of [...subs]) {
432
+ if (!sub.live)
433
+ continue;
434
+ sub.deliver(change);
435
+ }
436
+ }
384
437
  export async function refreshEngineCapsOnce(baseUrl, opts) {
385
438
  try {
386
439
  if (typeof baseUrl !== 'string' || baseUrl === '')
@@ -454,7 +507,7 @@ export function __resetEngineCapsCacheForTests() {
454
507
  capsByBase.clear();
455
508
  inFlight.clear();
456
509
  settleByBase.clear();
457
- genByBase.clear();
510
+ stateByBase.clear();
458
511
  probeByBase.clear();
459
512
  refreshByBase.clear();
460
513
  }
@@ -0,0 +1,2 @@
1
+ import { type EngineCapsChange } from './engineCapsCache.js';
2
+ export declare function onEngineCapsChange(baseUrl: string | undefined, listener: (change: EngineCapsChange) => void): () => void;
@@ -0,0 +1,9 @@
1
+ import { registerCapsChangeDelivery } from './engineCapsCache.js';
2
+ import { invokeHostCallbackIsolated } from './hostCallbackGuard.js';
3
+ export function onEngineCapsChange(baseUrl, listener) {
4
+ if (typeof listener !== 'function')
5
+ return () => { };
6
+ return registerCapsChangeDelivery(baseUrl, (change) => {
7
+ invokeHostCallbackIsolated('engineCapsChange: listener', () => listener(change));
8
+ });
9
+ }