@sema-agent/client-core 0.94.0 → 0.95.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 (255) hide show
  1. package/CHANGELOG.md +341 -0
  2. package/README.md +70 -47
  3. package/dist/adapt/arms.js +5 -6
  4. package/dist/adapt/panelTasks.js +4 -10
  5. package/dist/adapt/toolCards.js +2 -2
  6. package/dist/adapt/wireShapes.js +3 -8
  7. package/dist/adapter/activeRunSelfHeal.d.ts +8 -3
  8. package/dist/adapter/activeRunSelfHeal.js +20 -12
  9. package/dist/adapter/downstream/eventToSdkMessage.js +24 -17
  10. package/dist/adapter/downstream/terminalToSdkResult.js +11 -3
  11. package/dist/adapter/runStream.js +2 -1
  12. package/dist/adapter/types.d.ts +7 -0
  13. package/dist/adapter/types.js +15 -0
  14. package/dist/agentSession/backgroundView.js +5 -1
  15. package/dist/agentSession/engineAgentRegistryRead.js +2 -1
  16. package/dist/agentSession/engineSessionBackgroundStop.js +3 -2
  17. package/dist/agentsWireCaps.d.ts +2 -0
  18. package/dist/approvalDecidedByCapability.d.ts +0 -1
  19. package/dist/approvalDecidedByCapability.js +2 -7
  20. package/dist/approvalsStreamLiveCapability.d.ts +0 -1
  21. package/dist/approvalsStreamLiveCapability.js +2 -6
  22. package/dist/atMostOnce.d.ts +8 -0
  23. package/dist/atMostOnce.js +36 -0
  24. package/dist/attachmentSeatCapability.d.ts +0 -1
  25. package/dist/attachmentSeatCapability.js +0 -3
  26. package/dist/attachmentsWireCaps.js +11 -6
  27. package/dist/bashExitReading.d.ts +10 -0
  28. package/dist/bashExitReading.js +12 -0
  29. package/dist/callerCwdCapability.d.ts +0 -1
  30. package/dist/callerCwdCapability.js +2 -7
  31. package/dist/centerWiringCapability.d.ts +1 -3
  32. package/dist/centerWiringCapability.js +18 -21
  33. package/dist/classifierStatus.js +4 -4
  34. package/dist/cloudConfigWireCaps.js +43 -21
  35. package/dist/compensations.js +1 -1
  36. package/dist/cycleOrder.d.ts +15 -0
  37. package/dist/cycleOrder.js +45 -0
  38. package/dist/decideFailureNote.js +4 -1
  39. package/dist/decideReceipt.d.ts +2 -1
  40. package/dist/decideReceipt.js +41 -13
  41. package/dist/declared/supportFloorDeclared.d.ts +1 -0
  42. package/dist/declared/supportFloorDeclared.js +5 -0
  43. package/dist/deviceExecutorManagementCapability.d.ts +0 -1
  44. package/dist/deviceExecutorManagementCapability.js +7 -16
  45. package/dist/deviceRebind.d.ts +88 -0
  46. package/dist/deviceRebind.js +242 -0
  47. package/dist/displayUntrusted.d.ts +1 -0
  48. package/dist/displayUntrusted.js +313 -11
  49. package/dist/engineAgentAbsence.d.ts +2 -2
  50. package/dist/engineAgentPanelStore.d.ts +8 -18
  51. package/dist/engineAgentPanelStore.js +19 -537
  52. package/dist/engineCapReader.d.ts +6 -6
  53. package/dist/engineCapReader.js +30 -43
  54. package/dist/engineCapsCache.d.ts +7 -2
  55. package/dist/engineCapsCache.js +64 -26
  56. package/dist/engineCredentialRequirement.d.ts +9 -0
  57. package/dist/engineCredentialRequirement.js +23 -0
  58. package/dist/engineEnvSourcing.d.ts +53 -0
  59. package/dist/engineEnvSourcing.js +81 -0
  60. package/dist/engineErrorCodes.d.ts +14 -3
  61. package/dist/engineErrorCodes.js +31 -10
  62. package/dist/engineIdentity.js +2 -0
  63. package/dist/engineWireSdk.js +2 -2
  64. package/dist/executionLaneCapability.d.ts +2 -3
  65. package/dist/executionLaneCapability.js +18 -23
  66. package/dist/fileHistoryCaptureCapability.d.ts +0 -1
  67. package/dist/fileHistoryCaptureCapability.js +2 -6
  68. package/dist/fileHistoryLegNotice.d.ts +3 -2
  69. package/dist/fileHistoryLegNotice.js +51 -2
  70. package/dist/fleet/fleetLedger.d.ts +2 -0
  71. package/dist/fleet/fleetLedger.js +69 -52
  72. package/dist/fleet/fleetProjection.d.ts +0 -3
  73. package/dist/fleet/fleetProjection.js +9 -16
  74. package/dist/fleetAgentPanelProjection.d.ts +4 -17
  75. package/dist/fleetAgentPanelProjection.js +7 -197
  76. package/dist/fleetAgentRowLike.d.ts +16 -0
  77. package/dist/fleetAgentRowLike.js +1 -0
  78. package/dist/gateOutcome.js +30 -18
  79. package/dist/generated/sdkFactTables.d.ts +2 -0
  80. package/dist/generated/sdkFactTables.js +17 -0
  81. package/dist/generated/settingsSchemaFns.d.ts +10 -0
  82. package/dist/generated/settingsSchemaFns.js +22 -0
  83. package/dist/headlessPermissionModeWire.d.ts +1 -1
  84. package/dist/headlessPermissionModeWire.js +1 -1
  85. package/dist/headlessReconnectWire.js +49 -20
  86. package/dist/hitl/allowRuleShadow.d.ts +1 -1
  87. package/dist/hitl/allowRuleShadow.js +49 -8
  88. package/dist/hitl/approvalCompleteParked.d.ts +1 -0
  89. package/dist/hitl/approvalCompleteParked.js +14 -0
  90. package/dist/hitl/approvalEndingCause.d.ts +5 -0
  91. package/dist/hitl/approvalEndingCause.js +61 -0
  92. package/dist/hitl/approvalHolds.d.ts +12 -2
  93. package/dist/hitl/approvalHolds.js +53 -2
  94. package/dist/hitl/approvalsFeed.js +23 -11
  95. package/dist/hitl/askGateWire.d.ts +2 -1
  96. package/dist/hitl/askGateWire.js +26 -1
  97. package/dist/hitl/automaticAnswerVerdict.js +2 -2
  98. package/dist/hitl/crashConverged.js +2 -0
  99. package/dist/hitl/decisionConflict.d.ts +3 -0
  100. package/dist/hitl/decisionConflict.js +43 -0
  101. package/dist/hitl/decisionRefusal.d.ts +4 -0
  102. package/dist/hitl/decisionRefusal.js +26 -1
  103. package/dist/hitl/frameRouter.js +26 -43
  104. package/dist/hitl/gateLedger.d.ts +5 -0
  105. package/dist/hitl/gateLedger.js +21 -0
  106. package/dist/hitl/hitlBridge.d.ts +12 -1
  107. package/dist/hitl/hitlBridge.js +68 -53
  108. package/dist/hitl/hitlHostSurface.js +3 -11
  109. package/dist/hitl/livePendingAsk.d.ts +16 -6
  110. package/dist/hitl/livePendingAsk.js +36 -4
  111. package/dist/hitl/parkExpiryJudgements.d.ts +19 -0
  112. package/dist/hitl/parkExpiryJudgements.js +46 -0
  113. package/dist/hitl/parkResolver.d.ts +3 -7
  114. package/dist/hitl/parkResolver.js +50 -26
  115. package/dist/hitl/persistedRulesWire.js +5 -1
  116. package/dist/hitl/planReviewWire.d.ts +2 -2
  117. package/dist/hitl/planReviewWire.js +56 -30
  118. package/dist/hitl/replayedApproval.d.ts +8 -0
  119. package/dist/hitl/replayedApproval.js +125 -10
  120. package/dist/hitl/resumeRunningCard.d.ts +2 -0
  121. package/dist/hitl/resumeRunningCard.js +15 -4
  122. package/dist/hitl/toolApprovalWire.d.ts +24 -4
  123. package/dist/hitl/toolApprovalWire.js +115 -38
  124. package/dist/hooksWireCaps.js +38 -6
  125. package/dist/host.d.ts +5 -0
  126. package/dist/host.js +3 -1
  127. package/dist/hostCallbackGuard.d.ts +1 -0
  128. package/dist/hostCallbackGuard.js +25 -0
  129. package/dist/index.d.ts +30 -11
  130. package/dist/index.js +20 -8
  131. package/dist/interactiveInterrupt.d.ts +8 -0
  132. package/dist/interactiveInterrupt.js +54 -0
  133. package/dist/limitsWire.d.ts +5 -0
  134. package/dist/limitsWire.js +49 -3
  135. package/dist/liveModelCatalog.d.ts +95 -0
  136. package/dist/liveModelCatalog.js +297 -32
  137. package/dist/mcpEngineLeg.d.ts +25 -0
  138. package/dist/mcpEngineLeg.js +71 -15
  139. package/dist/mcpPanel.js +2 -1
  140. package/dist/mcpProbeCapability.d.ts +0 -1
  141. package/dist/mcpProbeCapability.js +2 -6
  142. package/dist/mcpReconnect.d.ts +1 -3
  143. package/dist/mcpReconnect.js +10 -5
  144. package/dist/memoryComplianceCapability.d.ts +0 -1
  145. package/dist/memoryComplianceCapability.js +2 -6
  146. package/dist/memoryOriginCapability.d.ts +0 -1
  147. package/dist/memoryOriginCapability.js +2 -6
  148. package/dist/memoryVerbsWire.d.ts +1 -1
  149. package/dist/memoryVerbsWire.js +4 -0
  150. package/dist/model/liveCatalogShape.d.ts +14 -0
  151. package/dist/model/liveCatalogShape.js +71 -0
  152. package/dist/model/modelSupplyRules.d.ts +1 -0
  153. package/dist/model/modelSupplyRules.js +30 -9
  154. package/dist/model/modelsPolicy.d.ts +21 -0
  155. package/dist/model/modelsPolicy.js +90 -0
  156. package/dist/modelIdentityResolvability.d.ts +1 -1
  157. package/dist/modelIdentityResolvability.js +5 -12
  158. package/dist/modelSwitchFallback.d.ts +69 -0
  159. package/dist/modelSwitchFallback.js +206 -0
  160. package/dist/notifications.js +12 -11
  161. package/dist/outputStyleSeatCapability.d.ts +0 -1
  162. package/dist/outputStyleSeatCapability.js +2 -7
  163. package/dist/ownKey.d.ts +6 -0
  164. package/dist/ownKey.js +48 -0
  165. package/dist/panelReduce.d.ts +114 -0
  166. package/dist/panelReduce.js +1135 -0
  167. package/dist/panelStateHolder.d.ts +17 -0
  168. package/dist/panelStateHolder.js +201 -0
  169. package/dist/peerLaneCapability.d.ts +0 -1
  170. package/dist/peerLaneCapability.js +2 -6
  171. package/dist/permissionModesCapability.d.ts +0 -1
  172. package/dist/permissionModesCapability.js +5 -10
  173. package/dist/permissionRulesWriteCapability.d.ts +0 -1
  174. package/dist/permissionRulesWriteCapability.js +2 -6
  175. package/dist/permissionsAllowGrantCapability.d.ts +0 -1
  176. package/dist/permissionsAllowGrantCapability.js +3 -9
  177. package/dist/permissionsDeclaration.d.ts +6 -0
  178. package/dist/permissionsDeclaration.js +45 -0
  179. package/dist/printToolResultFrame.js +2 -10
  180. package/dist/promptDelivery.js +0 -8
  181. package/dist/resumeRefusalCopy.d.ts +18 -1
  182. package/dist/resumeRefusalCopy.js +126 -15
  183. package/dist/rewindArchiveCapability.d.ts +2 -1
  184. package/dist/rewindArchiveCapability.js +15 -7
  185. package/dist/rewindEngineAction.d.ts +21 -0
  186. package/dist/rewindEngineAction.js +36 -0
  187. package/dist/rewindWireCaps.d.ts +2 -1
  188. package/dist/rewindWireCaps.js +1 -0
  189. package/dist/runTerminal.d.ts +0 -11
  190. package/dist/runTerminal.js +4 -27
  191. package/dist/sdkRegistryTransit.d.ts +2 -1
  192. package/dist/sdkRegistryTransit.js +1 -0
  193. package/dist/sealedKeyCapability.d.ts +0 -1
  194. package/dist/sealedKeyCapability.js +3 -9
  195. package/dist/seatContract.d.ts +54 -25
  196. package/dist/seatContract.js +394 -171
  197. package/dist/sessionIdSegment.d.ts +1 -0
  198. package/dist/sessionIdSegment.js +11 -0
  199. package/dist/sessionMemoryErase.d.ts +1 -1
  200. package/dist/sessionMemoryErase.js +6 -1
  201. package/dist/sessionMemoryStatus.js +3 -2
  202. package/dist/sessionPolicyCapability.d.ts +0 -1
  203. package/dist/sessionPolicyCapability.js +2 -6
  204. package/dist/sessionReadRedactionCapability.d.ts +0 -1
  205. package/dist/sessionReadRedactionCapability.js +2 -7
  206. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -1
  207. package/dist/sessionSyncFileHistoryCapability.js +2 -6
  208. package/dist/skillToolListsCapability.d.ts +0 -1
  209. package/dist/skillToolListsCapability.js +2 -6
  210. package/dist/skillsWireCaps.d.ts +4 -0
  211. package/dist/skillsWireCaps.js +66 -1
  212. package/dist/sqlEngineCapability.d.ts +0 -1
  213. package/dist/sqlEngineCapability.js +9 -14
  214. package/dist/steerPriorityCapability.d.ts +0 -1
  215. package/dist/steerPriorityCapability.js +3 -9
  216. package/dist/storePostureCapability.d.ts +1 -1
  217. package/dist/storePostureCapability.js +16 -16
  218. package/dist/streamDrainingLegs.d.ts +6 -0
  219. package/dist/streamDrainingLegs.js +23 -0
  220. package/dist/subagent/engineCompactWire.js +13 -38
  221. package/dist/subagent/engineDelegatedPrompt.js +10 -6
  222. package/dist/subagent/engineSubagentOutput.d.ts +0 -1
  223. package/dist/subagent/engineSubagentOutput.js +5 -20
  224. package/dist/subagent/engineSubagentTail.d.ts +0 -1
  225. package/dist/subagent/engineSubagentTail.js +7 -32
  226. package/dist/subagentContentStore.js +3 -3
  227. package/dist/supportFloor.js +2 -5
  228. package/dist/terminalStatuses.d.ts +30 -0
  229. package/dist/terminalStatuses.js +67 -0
  230. package/dist/toolResult.d.ts +5 -0
  231. package/dist/toolResult.js +88 -36
  232. package/dist/types/engineState.d.ts +2 -1
  233. package/dist/usageAnalytics.d.ts +146 -0
  234. package/dist/usageAnalytics.js +311 -0
  235. package/dist/userInvokedSkillsCapability.d.ts +0 -1
  236. package/dist/userInvokedSkillsCapability.js +2 -6
  237. package/dist/webSearchBackendCapability.d.ts +0 -1
  238. package/dist/webSearchBackendCapability.js +3 -7
  239. package/dist/webSearchWireCaps.js +3 -11
  240. package/dist/wireFailureShape.d.ts +4 -0
  241. package/dist/wireFailureShape.js +42 -2
  242. package/dist/wireRefusalCopy.js +2 -18
  243. package/dist/workflowClient.js +7 -11
  244. package/dist/workflowsJournalCapability.d.ts +0 -1
  245. package/dist/workflowsJournalCapability.js +2 -6
  246. package/dist/writeProtectionCapability.d.ts +0 -1
  247. package/dist/writeProtectionCapability.js +5 -10
  248. package/docs/INTEGRATION-CLIENTS.md +1033 -26
  249. package/package.json +5 -5
  250. package/dist/engineCapsGenerationGuard.d.ts +0 -4
  251. package/dist/engineCapsGenerationGuard.js +0 -19
  252. package/dist/panelRunningHistory.d.ts +0 -22
  253. package/dist/panelRunningHistory.js +0 -82
  254. package/dist/registryConflict.d.ts +0 -3
  255. package/dist/registryConflict.js +0 -44
@@ -0,0 +1 @@
1
+ export declare function isSessionIdPathSegment(id: unknown): id is string;
@@ -0,0 +1,11 @@
1
+ export function isSessionIdPathSegment(id) {
2
+ if (typeof id !== 'string' || id === '' || id === '.' || id === '..')
3
+ return false;
4
+ try {
5
+ encodeURIComponent(id);
6
+ return true;
7
+ }
8
+ catch {
9
+ return false;
10
+ }
11
+ }
@@ -34,7 +34,7 @@ export type SessionMemoryEraseAnswer = {
34
34
  };
35
35
  export declare function eraseSessionMemory(call: SessionMemoryEraseCall, wire: SessionMemoryEraseWire, opts?: SessionMemoryEraseOptions): Promise<SessionMemoryEraseAnswer>;
36
36
  export type SessionMemoryEraseRefusalReason = 'bad_input' | 'no_connection' | 'cancelled_before_send' | 'credentials_required' | 'not_permitted' | 'memory_engine_absent' | 'session_not_found' | 'route_absent' | 'request_rejected' | 'evidence_unavailable' | 'request_id_reused' | 'store_unreadable';
37
- export type SessionMemoryEraseUnconfirmedWhy = 'no_answer' | 'receipt_unreadable' | 'receipt_mismatch' | 'store_link_outside' | 'control_plane_corrupt' | 'engine_fault' | 'unclassified' | 'no_code' | 'unreadable';
37
+ export type SessionMemoryEraseUnconfirmedWhy = 'no_answer' | 'receipt_unreadable' | 'receipt_mismatch' | 'store_link_outside' | 'store_home_not_directory' | 'control_plane_corrupt' | 'engine_fault' | 'unclassified' | 'no_code' | 'unreadable';
38
38
  export type SessionMemoryEraseRetry = 'not_needed' | 'same_request_id' | 'new_request_id' | 'needs_operator' | 'needs_consent' | 'human_decision' | 'pointless';
39
39
  type SessionMemoryEraseReceipt = Extract<MemoryEraseReceiptReading, {
40
40
  kind: 'present';
@@ -2,6 +2,7 @@ import { isLoopbackWireUrl, resolveWireAuth } from './engineWireSdk.js';
2
2
  import { INJECTED_WIRE_SETTLE_MS, connectionLostDetail, noAnswerDetailFrom, noAnswerKindOf, provablyNotSent, settleInjected } from './engineWireFor.js';
3
3
  import { memoryEraseReplayPosture, readMemoryEraseReceipt } from './memoryEntriesWire.js';
4
4
  import { normalizeWirePrincipal } from './principalWire.js';
5
+ import { isSessionIdPathSegment } from './sessionIdSegment.js';
5
6
  const PRINCIPAL_HEADER = 'x-agent-principal';
6
7
  const MAX_TIMER_MS = 2_147_483_647;
7
8
  const NOT_SENT = ' — nothing was sent';
@@ -117,7 +118,7 @@ export async function eraseSessionMemory(call, wire, opts) {
117
118
  const allowUnevidenced = Object.hasOwn(call, 'allowUnevidenced') ? call.allowUnevidenced : undefined;
118
119
  if (!nonEmptyString(sessionId) || !nonEmptyString(requestId))
119
120
  return notSent('bad_input', DETAIL_BAD_CALL);
120
- if (sessionId === '.' || sessionId === '..')
121
+ if (!isSessionIdPathSegment(sessionId))
121
122
  return notSent('bad_input', DETAIL_BAD_CALL);
122
123
  if (allowUnevidenced !== undefined && typeof allowUnevidenced !== 'boolean')
123
124
  return notSent('bad_input', DETAIL_BAD_CALL);
@@ -236,6 +237,7 @@ const UNCONFIRMED_TEXT = {
236
237
  receipt_unreadable: 'Not confirmed: the engine answered, but its erase receipt could not be read.',
237
238
  receipt_mismatch: 'Not confirmed: the engine answered with a receipt for a different erase request.',
238
239
  store_link_outside: 'Not confirmed: the memory store contains a link that leads outside it, so the erase stopped before finishing and may have erased part of this memory or none of it; the deployment operator needs to remove the link.',
240
+ store_home_not_directory: 'Not confirmed: a folder in the memory store that holds this memory has turned into a link or a plain file, so the erase stopped before finishing and may have erased part of this memory or none of it; the deployment operator needs to restore the real folder.',
239
241
  control_plane_corrupt: "Not confirmed: the memory store's own records could not be read cleanly, so the erase may have changed nothing or may already be committed; the deployment operator needs to repair them.",
240
242
  engine_fault: 'Not confirmed: the engine reported an internal failure during the erase, so it may or may not have happened.',
241
243
  unclassified: 'Not confirmed: the engine refused in a way this client does not recognise.',
@@ -280,6 +282,7 @@ function unconfirmedRetry(why, allowUnevidenced) {
280
282
  return 'human_decision';
281
283
  switch (why) {
282
284
  case 'store_link_outside':
285
+ case 'store_home_not_directory':
283
286
  case 'control_plane_corrupt':
284
287
  return 'needs_operator';
285
288
  case 'receipt_mismatch':
@@ -327,6 +330,8 @@ function bandOfCode(code) {
327
330
  return { refused: 'store_unreadable' };
328
331
  case 'memory.target_outside_store':
329
332
  return { unconfirmed: 'store_link_outside' };
333
+ case 'memory.scope_home_not_directory':
334
+ return { unconfirmed: 'store_home_not_directory' };
330
335
  case 'internal.memory_control_plane_corrupt':
331
336
  return { unconfirmed: 'control_plane_corrupt' };
332
337
  case 'internal.error':
@@ -1,3 +1,4 @@
1
+ import { isSessionIdPathSegment } from './sessionIdSegment.js';
1
2
  export function classifyMemoryStatusFailure(e) {
2
3
  let code;
3
4
  let status;
@@ -44,8 +45,8 @@ export function readLastCapture(s) {
44
45
  return { state: 'indeterminate' };
45
46
  }
46
47
  export async function readSessionMemoryStatus(client, sessionId, opts) {
47
- if (typeof sessionId !== 'string' || sessionId.length === 0) {
48
- return { kind: 'failed', error: new Error('memoryStatus: empty sessionId') };
48
+ if (!isSessionIdPathSegment(sessionId)) {
49
+ return { kind: 'failed', error: new Error('memoryStatus: sessionId is not usable as a URL path segment') };
49
50
  }
50
51
  try {
51
52
  const raw = await client.sessions.memoryStatus(sessionId, opts?.signal ? { signal: opts.signal } : {});
@@ -14,5 +14,4 @@ export declare function noteEngineCapsForSessionPolicy(baseUrl: string, caps: un
14
14
  export declare function observedSessionPolicy(baseUrl?: string | undefined): SessionPolicyReading;
15
15
  export declare function sessionPolicyFaceAvailable(reading: SessionPolicyReading): 'yes' | 'no' | 'unknown';
16
16
  export declare function sessionPolicyDoctorDetail(reading: SessionPolicyReading): string;
17
- export declare function forgetSessionPolicyReading(baseUrl: string | undefined): void;
18
17
  export declare function __resetSessionPolicyReadingsForTests(): void;
@@ -1,13 +1,12 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
+ import { ownDataField } from './ownKey.js';
3
4
  export function projectSessionPolicyCapability(caps) {
4
5
  try {
5
6
  if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
6
7
  return undefined;
7
8
  const c = caps;
8
- if (!Object.hasOwn(c, 'sessionPolicy'))
9
- return { kind: 'not_reported' };
10
- const v = c.sessionPolicy;
9
+ const v = ownDataField(c, 'sessionPolicy');
11
10
  if (v === undefined)
12
11
  return { kind: 'not_reported' };
13
12
  if (typeof v !== 'boolean')
@@ -48,9 +47,6 @@ export function sessionPolicyDoctorDetail(reading) {
48
47
  return 'per-session rule face on — this session’s tool rules can be read, and a tightening write is accepted or refused by the engine call by call';
49
48
  }
50
49
  }
51
- export function forgetSessionPolicyReading(baseUrl) {
52
- reader.forget(baseUrl);
53
- }
54
50
  export function __resetSessionPolicyReadingsForTests() {
55
51
  reader.__resetForTests();
56
52
  }
@@ -12,5 +12,4 @@ export declare function noteEngineCapsForSessionReadRedaction(baseUrl: string, c
12
12
  }): void;
13
13
  export declare function observedSessionReadRedaction(baseUrl?: string | undefined): SessionReadRedactionReading;
14
14
  export declare function sessionReadRedactionAdmitted(reading: SessionReadRedactionReading | undefined): boolean;
15
- export declare function forgetSessionReadRedactionReading(baseUrl: string | undefined): void;
16
15
  export declare function __resetSessionReadRedactionReadingsForTests(): void;
@@ -1,13 +1,11 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
- import { readOwnDataValue } from './ownKey.js';
3
+ import { ownDataField, readOwnDataValue } from './ownKey.js';
4
4
  export function projectSessionReadRedactionCapability(caps) {
5
5
  try {
6
6
  if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
7
7
  return undefined;
8
- if (!Object.hasOwn(caps, 'sessionReadRedaction'))
9
- return { kind: 'not_reported' };
10
- const v = caps.sessionReadRedaction;
8
+ const v = ownDataField(caps, 'sessionReadRedaction');
11
9
  if (v === undefined)
12
10
  return { kind: 'not_reported' };
13
11
  return v === true ? { kind: 'present', value: true } : undefined;
@@ -39,9 +37,6 @@ export function sessionReadRedactionAdmitted(reading) {
39
37
  return false;
40
38
  }
41
39
  }
42
- export function forgetSessionReadRedactionReading(baseUrl) {
43
- reader.forget(baseUrl);
44
- }
45
40
  export function __resetSessionReadRedactionReadingsForTests() {
46
41
  reader.__resetForTests();
47
42
  }
@@ -14,5 +14,4 @@ export declare function noteEngineCapsForSessionSyncFileHistory(baseUrl: string,
14
14
  export declare function observedSessionSyncFileHistory(baseUrl?: string | undefined): SessionSyncFileHistoryReading;
15
15
  export declare function sessionSyncFileHistoryAvailable(reading: SessionSyncFileHistoryReading): 'yes' | 'no' | 'unknown';
16
16
  export declare function sessionSyncFileHistoryDoctorDetail(reading: SessionSyncFileHistoryReading): string;
17
- export declare function forgetSessionSyncFileHistoryReading(baseUrl: string | undefined): void;
18
17
  export declare function __resetSessionSyncFileHistoryReadingsForTests(): void;
@@ -1,12 +1,11 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
+ import { ownDataField } from './ownKey.js';
3
4
  export function projectSessionSyncFileHistoryCapability(caps) {
4
5
  try {
5
6
  if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
6
7
  return undefined;
7
- if (!Object.hasOwn(caps, 'sessionSyncFileHistory'))
8
- return { kind: 'not_reported' };
9
- const v = caps.sessionSyncFileHistory;
8
+ const v = ownDataField(caps, 'sessionSyncFileHistory');
10
9
  if (v === undefined)
11
10
  return { kind: 'not_reported' };
12
11
  if (typeof v !== 'boolean')
@@ -47,9 +46,6 @@ export function sessionSyncFileHistoryDoctorDetail(reading) {
47
46
  return 'session-sync file history on — syncing a session can also move its edited-file history';
48
47
  }
49
48
  }
50
- export function forgetSessionSyncFileHistoryReading(baseUrl) {
51
- reader.forget(baseUrl);
52
- }
53
49
  export function __resetSessionSyncFileHistoryReadingsForTests() {
54
50
  reader.__resetForTests();
55
51
  }
@@ -14,5 +14,4 @@ export declare function noteEngineCapsForSkillToolLists(baseUrl: string, caps: u
14
14
  export declare function observedSkillToolLists(baseUrl?: string | undefined): SkillToolListsReading;
15
15
  export declare function skillToolListsAvailable(reading: SkillToolListsReading): 'yes' | 'no' | 'unknown';
16
16
  export declare function skillToolListsDoctorDetail(reading: SkillToolListsReading): string;
17
- export declare function forgetSkillToolListsReading(baseUrl: string | undefined): void;
18
17
  export declare function __resetSkillToolListsReadingsForTests(): void;
@@ -1,12 +1,11 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
+ import { ownDataField } from './ownKey.js';
3
4
  export function projectSkillToolListsCapability(caps) {
4
5
  try {
5
6
  if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
6
7
  return undefined;
7
- if (!Object.hasOwn(caps, 'skillToolLists'))
8
- return { kind: 'not_reported' };
9
- const v = caps.skillToolLists;
8
+ const v = ownDataField(caps, 'skillToolLists');
10
9
  if (v === undefined)
11
10
  return { kind: 'not_reported' };
12
11
  if (typeof v !== 'boolean')
@@ -47,9 +46,6 @@ export function skillToolListsDoctorDetail(reading) {
47
46
  return 'skill tool lists on — a request skill’s allowed and disallowed tool lists are read as this run’s rules';
48
47
  }
49
48
  }
50
- export function forgetSkillToolListsReading(baseUrl) {
51
- reader.forget(baseUrl);
52
- }
53
49
  export function __resetSkillToolListsReadingsForTests() {
54
50
  reader.__resetForTests();
55
51
  }
@@ -1,4 +1,5 @@
1
1
  import type { SkillSpec } from '@sema-agent/sdk';
2
+ import { type SkillToolListsReading } from './skillToolListsCapability.js';
2
3
  export declare const SKILL_CAPS: {
3
4
  readonly content: 1048576;
4
5
  };
@@ -10,6 +11,8 @@ export interface SkillCmdLike {
10
11
  source?: string;
11
12
  disableModelInvocation?: boolean;
12
13
  skillRoot?: string;
14
+ allowedTools?: readonly string[];
15
+ disallowedTools?: readonly string[];
13
16
  }
14
17
  export declare function toCappedSpec(name: string, description: string, whenToUse: string, body: string): SkillSpec | null;
15
18
  export type SkillSpecOnWire = SkillSpec & {
@@ -18,6 +21,7 @@ export type SkillSpecOnWire = SkillSpec & {
18
21
  export interface SkillSpecsOptions {
19
22
  toolsRunHere?: boolean;
20
23
  platform?: 'posix' | 'win32';
24
+ skillToolLists?: SkillToolListsReading;
21
25
  }
22
26
  export declare function skillBaseDirOf(skillRoot: string | undefined, platform?: 'posix' | 'win32'): string | undefined;
23
27
  export declare function skillCommandsToSpecs(cmds: SkillCmdLike[], resolveBody: (cmd: SkillCmdLike) => string | null, opts?: SkillSpecsOptions): SkillSpecOnWire[];
@@ -1,3 +1,4 @@
1
+ import { skillToolListsAvailable } from './skillToolListsCapability.js';
1
2
  export const SKILL_CAPS = { content: 1_048_576 };
2
3
  export function toCappedSpec(name, description, whenToUse, body) {
3
4
  const n = name.trim();
@@ -27,9 +28,64 @@ export function skillBaseDirOf(skillRoot, platform = 'posix') {
27
28
  return undefined;
28
29
  return skillRoot;
29
30
  }
31
+ function readSkillToolList(skillName, key, cmd) {
32
+ const who = `skillCommandsToSpecs: skill ${JSON.stringify(skillName.slice(0, 80))} ${key}`;
33
+ const hint = 'The list is the skill’s own tool rule list and is sent exactly as given (entries are never dropped, repaired, reordered or truncated here), ' +
34
+ 'so a value that is not a list of strings is refused instead of being silently reduced.';
35
+ const unreadable = () => new TypeError(`${who} could not be read — reading it (the property, the array length or an entry) threw. ${hint}`);
36
+ let v;
37
+ try {
38
+ v = cmd[key];
39
+ }
40
+ catch {
41
+ throw unreadable();
42
+ }
43
+ if (v === undefined)
44
+ return undefined;
45
+ let isArray;
46
+ try {
47
+ isArray = Array.isArray(v);
48
+ }
49
+ catch {
50
+ throw unreadable();
51
+ }
52
+ if (!isArray) {
53
+ throw new TypeError(`${who} must be an array of strings or absent — got ${v === null ? 'null' : typeof v === 'object' ? 'a non-array object' : `typeof ${typeof v}`}. ${hint}`);
54
+ }
55
+ const list = v;
56
+ let lengthRead;
57
+ try {
58
+ lengthRead = list.length;
59
+ }
60
+ catch {
61
+ throw unreadable();
62
+ }
63
+ if (typeof lengthRead !== 'number' || !Number.isSafeInteger(lengthRead) || lengthRead < 0 || lengthRead > 4_294_967_295) {
64
+ throw new TypeError(`${who} must be an array of strings or absent — its length is not a valid array length. ${hint}`);
65
+ }
66
+ const n = lengthRead;
67
+ const out = [];
68
+ for (let i = 0; i < n; i++) {
69
+ let e;
70
+ try {
71
+ e = list[i];
72
+ }
73
+ catch {
74
+ throw unreadable();
75
+ }
76
+ if (typeof e !== 'string') {
77
+ throw new TypeError(`${who} must be an array of strings or absent — the entry at index ${i} is ${e === null ? 'null' : `typeof ${typeof e}`}. ${hint}`);
78
+ }
79
+ out.push(e);
80
+ }
81
+ return out;
82
+ }
30
83
  export function skillCommandsToSpecs(cmds, resolveBody, opts) {
31
84
  const specs = [];
32
85
  const seen = new Set();
86
+ const reading = opts?.skillToolLists;
87
+ const wired = reading !== undefined;
88
+ const toolListsOn = wired && skillToolListsAvailable(reading ?? { kind: 'unobserved' }) === 'yes';
33
89
  for (const cmd of cmds) {
34
90
  if (cmd.type !== 'prompt' || cmd.disableModelInvocation)
35
91
  continue;
@@ -41,7 +97,16 @@ export function skillCommandsToSpecs(cmds, resolveBody, opts) {
41
97
  continue;
42
98
  seen.add(spec.name);
43
99
  const baseDir = opts?.toolsRunHere === true ? skillBaseDirOf(cmd.skillRoot, opts.platform ?? 'posix') : undefined;
44
- specs.push(baseDir !== undefined ? { ...spec, baseDir } : spec);
100
+ const allowedTools = wired ? readSkillToolList(spec.name, 'allowedTools', cmd) : undefined;
101
+ const disallowedTools = wired ? readSkillToolList(spec.name, 'disallowedTools', cmd) : undefined;
102
+ let wire = spec;
103
+ if (baseDir !== undefined)
104
+ wire = { ...wire, baseDir };
105
+ if (toolListsOn && allowedTools !== undefined)
106
+ wire = { ...wire, allowedTools };
107
+ if (toolListsOn && disallowedTools !== undefined)
108
+ wire = { ...wire, disallowedTools };
109
+ specs.push(wire);
45
110
  }
46
111
  return specs;
47
112
  }
@@ -19,5 +19,4 @@ export declare function noteEngineCapsForSqlEngine(baseUrl: string, caps: unknow
19
19
  }): void;
20
20
  export declare function observedSqlEngine(baseUrl?: string | undefined): SqlEngineReading;
21
21
  export declare function sqlEngineDoctorDetail(reading: SqlEngineReading): string;
22
- export declare function forgetSqlEngineReading(baseUrl: string | undefined): void;
23
22
  export declare function __resetSqlEngineReadingsForTests(): void;
@@ -1,18 +1,17 @@
1
1
  import { capForDisplay } from './fleetTaskDesc.js';
2
2
  import { engineWireTarget } from './engineWireTarget.js';
3
- import { capsGenerationOf, createEngineCapReader } from './engineCapReader.js';
3
+ import { storeSeatOf, createEngineCapReader } from './engineCapReader.js';
4
+ import { ownDataField } from './ownKey.js';
4
5
  export function projectSqlEngineCapability(caps) {
5
6
  try {
6
7
  if (caps === null || typeof caps !== 'object')
7
8
  return undefined;
8
9
  if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
9
10
  return undefined;
10
- const gen = capsGenerationOf(caps);
11
- if (gen.generation === 'new') {
12
- const store = gen.store;
13
- if (!Object.hasOwn(store, 'sql'))
14
- return { kind: 'none' };
15
- const nested = store.sql;
11
+ const seat = storeSeatOf(caps);
12
+ if (seat.kind === 'object') {
13
+ const store = seat.store;
14
+ const nested = ownDataField(store, 'sql');
16
15
  if (nested === undefined)
17
16
  return { kind: 'none' };
18
17
  return projectSqlEngineView(nested);
@@ -26,10 +25,9 @@ export function projectSqlEngineCapability(caps) {
26
25
  function projectSqlEngineView(sql) {
27
26
  if (sql === null || typeof sql !== 'object')
28
27
  return undefined;
29
- const s = sql;
30
- const engine = s.engine;
31
- const isolation = s.isolation;
32
- const txnMode = s.txnMode;
28
+ const engine = ownDataField(sql, 'engine');
29
+ const isolation = ownDataField(sql, 'isolation');
30
+ const txnMode = ownDataField(sql, 'txnMode');
33
31
  if (typeof engine !== 'string' || engine === '')
34
32
  return undefined;
35
33
  if (typeof isolation !== 'string' || isolation === '')
@@ -73,9 +71,6 @@ export function sqlEngineDoctorDetail(reading) {
73
71
  }
74
72
  }
75
73
  }
76
- export function forgetSqlEngineReading(baseUrl) {
77
- reader.forget(baseUrl);
78
- }
79
74
  export function __resetSqlEngineReadingsForTests() {
80
75
  reader.__resetForTests();
81
76
  }
@@ -14,5 +14,4 @@ export declare function noteEngineCapsForSteerPriority(baseUrl: string, caps: un
14
14
  export declare function observedSteerPriority(baseUrl?: string | undefined): SteerPriorityReading;
15
15
  export declare function steerPriorityMode(reading: SteerPriorityReading): SteerPriorityMode;
16
16
  export declare function steerPriorityDoctorDetail(reading: SteerPriorityReading): string;
17
- export declare function forgetSteerPriorityReading(baseUrl: string | undefined): void;
18
17
  export declare function __resetSteerPriorityReadingsForTests(): void;
@@ -1,20 +1,17 @@
1
1
  import { capForDisplay } from './fleetTaskDesc.js';
2
2
  import { engineWireTarget } from './engineWireTarget.js';
3
3
  import { createEngineCapReader } from './engineCapReader.js';
4
+ import { ownDataField } from './ownKey.js';
4
5
  export function projectSteerPriorityCapability(caps) {
5
6
  try {
6
7
  if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
7
8
  return undefined;
8
- if (!Object.hasOwn(caps, 'fleet'))
9
- return { kind: 'not_reported' };
10
- const fleet = caps.fleet;
9
+ const fleet = ownDataField(caps, 'fleet');
11
10
  if (fleet === undefined || fleet === false)
12
11
  return { kind: 'not_reported' };
13
12
  if (fleet === null || typeof fleet !== 'object' || Array.isArray(fleet))
14
13
  return undefined;
15
- if (!Object.hasOwn(fleet, 'steerPriority'))
16
- return { kind: 'not_reported' };
17
- const v = fleet.steerPriority;
14
+ const v = ownDataField(fleet, 'steerPriority');
18
15
  if (v === undefined)
19
16
  return { kind: 'not_reported' };
20
17
  if (typeof v !== 'string' || v.length === 0)
@@ -77,9 +74,6 @@ export function steerPriorityDoctorDetail(reading) {
77
74
  }
78
75
  return `steer priority reported as "${capForDisplay(word, WORD_DETAIL_MAX)}" — a value this client does not know yet, so whether it is applied is unknown and a "now" or "later" steer is not sent`;
79
76
  }
80
- export function forgetSteerPriorityReading(baseUrl) {
81
- reader.forget(baseUrl);
82
- }
83
77
  export function __resetSteerPriorityReadingsForTests() {
84
78
  reader.__resetForTests();
85
79
  }
@@ -20,6 +20,6 @@ export declare function noteEngineCapsForStorePosture(baseUrl: string, caps: unk
20
20
  }): void;
21
21
  export declare function observedStorePosture(baseUrl?: string | undefined): StorePostureReading;
22
22
  export declare function storePersistence(reading: StorePostureReading): 'durable' | 'not_durable' | 'unknown';
23
+ export declare function storePostureHeadWord(reading: StorePostureReading): string | undefined;
23
24
  export declare function storePostureDoctorDetail(reading: StorePostureReading): string;
24
- export declare function forgetStorePostureReading(baseUrl: string | undefined): void;
25
25
  export declare function __resetStorePostureReadingsForTests(): void;
@@ -1,7 +1,8 @@
1
1
  import { capForDisplay } from './fleetTaskDesc.js';
2
2
  import { engineWireTarget } from './engineWireTarget.js';
3
- import { capsGenerationOf, createEngineCapReader } from './engineCapReader.js';
3
+ import { storeSeatOf, createEngineCapReader } from './engineCapReader.js';
4
4
  import { projectSqlEngineCapability } from './sqlEngineCapability.js';
5
+ import { ownDataField } from './ownKey.js';
5
6
  const nonEmpty = (v) => typeof v === 'string' && v !== '';
6
7
  export function projectStorePostureCapability(caps) {
7
8
  try {
@@ -14,19 +15,17 @@ export function projectStorePostureCapability(caps) {
14
15
  function projectStorePostureOf(caps) {
15
16
  if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
16
17
  return undefined;
17
- const gen = capsGenerationOf(caps);
18
- if (gen.generation === 'old')
19
- return gen.store === 'absent' ? { kind: 'not_reported' } : undefined;
20
- const store = gen.store;
21
- const s = store;
22
- const declared = s.declared;
23
- const backend = s.backend;
24
- const durable = s.durable;
18
+ const seat = storeSeatOf(caps);
19
+ if (seat.kind !== 'object')
20
+ return seat.kind === 'absent' ? { kind: 'not_reported' } : undefined;
21
+ const store = seat.store;
22
+ const declared = ownDataField(store, 'declared');
23
+ const backend = ownDataField(store, 'backend');
24
+ const durable = ownDataField(store, 'durable');
25
25
  if (!nonEmpty(declared) || !nonEmpty(backend) || typeof durable !== 'boolean')
26
26
  return undefined;
27
- const hasReason = Object.hasOwn(store, 'degradedReason');
28
- const reason = hasReason ? s.degradedReason : undefined;
29
- if (hasReason && reason !== undefined && !nonEmpty(reason))
27
+ const reason = ownDataField(store, 'degradedReason');
28
+ if (reason !== undefined && !nonEmpty(reason))
30
29
  return undefined;
31
30
  const sqlReading = projectSqlEngineCapability({ store });
32
31
  if (sqlReading === undefined)
@@ -84,6 +83,10 @@ export function storePersistence(reading) {
84
83
  }
85
84
  return durable === true ? 'durable' : durable === false ? 'not_durable' : 'unknown';
86
85
  }
86
+ const STORE_NOT_DURABLE_HEAD = 'NOT durable';
87
+ export function storePostureHeadWord(reading) {
88
+ return storePersistence(reading) === 'not_durable' ? STORE_NOT_DURABLE_HEAD : undefined;
89
+ }
87
90
  const WORD_DETAIL_MAX = 40;
88
91
  const word = (v) => capForDisplay(v, WORD_DETAIL_MAX);
89
92
  export function storePostureDoctorDetail(reading) {
@@ -113,7 +116,7 @@ export function storePostureDoctorDetail(reading) {
113
116
  if (durable) {
114
117
  return `${assembled} — durable: this replica persists its state, so it survives a restart`;
115
118
  }
116
- const lost = 'NOT durable: this replica holds its state in memory and loses it on restart';
119
+ const lost = `${STORE_NOT_DURABLE_HEAD}: this replica holds its state in memory and loses it on restart`;
117
120
  if (!nonEmpty(reason))
118
121
  return `${assembled} — ${lost}`;
119
122
  if (reason === 'db_unreachable') {
@@ -124,9 +127,6 @@ export function storePostureDoctorDetail(reading) {
124
127
  }
125
128
  return `${assembled} — ${lost} (degraded for a reason this client does not know yet: "${word(reason)}")`;
126
129
  }
127
- export function forgetStorePostureReading(baseUrl) {
128
- reader.forget(baseUrl);
129
- }
130
130
  export function __resetStorePostureReadingsForTests() {
131
131
  reader.__resetForTests();
132
132
  }
@@ -0,0 +1,6 @@
1
+ import { type StreamDrainingDecision } from './wireErrorTriage.js';
2
+ export interface StreamDrainingLegs<F> {
3
+ see(frame: F): boolean;
4
+ legEnded(how: 'returned' | 'threw'): StreamDrainingDecision | undefined;
5
+ }
6
+ export declare function createStreamDrainingLegs<F>(): StreamDrainingLegs<F>;
@@ -0,0 +1,23 @@
1
+ import { isInStreamDrainingEnd, streamDrainingDecision } from './wireErrorTriage.js';
2
+ export function createStreamDrainingLegs() {
3
+ let consecutive = 0;
4
+ let drainEnd;
5
+ return {
6
+ see(frame) {
7
+ if (isInStreamDrainingEnd(frame)) {
8
+ drainEnd = { frame };
9
+ return true;
10
+ }
11
+ drainEnd = undefined;
12
+ consecutive = 0;
13
+ return false;
14
+ },
15
+ legEnded(how) {
16
+ const ended = drainEnd;
17
+ drainEnd = undefined;
18
+ if (how !== 'returned' || ended === undefined)
19
+ return undefined;
20
+ return streamDrainingDecision(ended.frame, consecutive++);
21
+ },
22
+ };
23
+ }
@@ -1,10 +1,12 @@
1
1
  import { hostLog, hostTimersFor } from '../host.js';
2
+ import { invokeHostCallbackIsolated } from '../hostCallbackGuard.js';
2
3
  import { COMPACT_NOT_RUNNING, isUnavailableFaceCode } from '../engineErrorCodes.js';
3
4
  import { surfaceCompactNotRunning } from '../hitl/hitlHostSurface.js';
4
5
  import { wireFailureShapeOf, wireFailureTextsOf } from '../wireFailureShape.js';
5
6
  import { clientHasVerbs, engineWireFor, INJECTED_WIRE_SETTLE_MS, noAnswerDetailFrom, settleInjected, } from '../engineWireFor.js';
6
7
  import { activeEngineRunIdFor, engineSessionParamFor } from '../engineSessionParam.js';
7
8
  import { DEFAULT_SESSION_KEY } from '../sessionSlot.js';
9
+ import { engineCapState, kickEngineCapsProbe } from '../engineCapsCache.js';
8
10
  function usableCompactClient(client) {
9
11
  return clientHasVerbs(client, [['capabilities'], ['runs', 'compact']]);
10
12
  }
@@ -14,43 +16,21 @@ const pendingCompactSinks = new Map();
14
16
  export function isEngineCompactPending(sessionKey = DEFAULT_SESSION_KEY) {
15
17
  return pendingCompactKeys.has(sessionKey);
16
18
  }
17
- const manualCompactCapableByBase = new Map();
18
- const capabilitiesProbeByBase = new Map();
19
19
  function probeManualCompactCapability(wire) {
20
20
  const base = wire.kind === 'injected' ? wire.capsBaseUrl : wire.target.baseUrl;
21
21
  if (base === undefined)
22
22
  return;
23
- if (capabilitiesProbeByBase.has(base))
23
+ if (wire.kind === 'injected') {
24
+ const injected = wire.client;
25
+ kickEngineCapsProbe(base, () => settleInjected(COMPACT_PROBE_SETTLE_MS, undefined, (signal) => injected.capabilities({ signal })));
24
26
  return;
25
- capabilitiesProbeByBase.set(base, (async () => {
26
- try {
27
- let caps;
28
- if (wire.kind === 'injected') {
29
- const injected = wire.client;
30
- caps = await settleInjected(COMPACT_PROBE_SETTLE_MS, undefined, (signal) => injected.capabilities({ signal }));
31
- }
32
- else {
33
- const client = wire.make({ timeoutMs: 5000 });
34
- if (!client) {
35
- capabilitiesProbeByBase.delete(base);
36
- return;
37
- }
38
- caps = await client.capabilities();
39
- }
40
- if (typeof caps.manualCompact === 'boolean')
41
- manualCompactCapableByBase.set(base, caps.manualCompact);
42
- else
43
- capabilitiesProbeByBase.delete(base);
44
- }
45
- catch {
46
- capabilitiesProbeByBase.delete(base);
47
- }
48
- })());
49
- }
50
- export function resetManualCompactCapability() {
51
- manualCompactCapableByBase.clear();
52
- capabilitiesProbeByBase.clear();
27
+ }
28
+ const client = wire.make({ timeoutMs: 5000 });
29
+ if (!client)
30
+ return;
31
+ kickEngineCapsProbe(base, () => client.capabilities());
53
32
  }
33
+ export function resetManualCompactCapability() { }
54
34
  export function __resetEngineCompactArmForTests() {
55
35
  pendingCompactKeys.clear();
56
36
  pendingCompactSinks.clear();
@@ -91,12 +71,7 @@ function emitCompactOutcome(sink, outcome) {
91
71
  void Promise.resolve().then(() => callSinkIsolated(sink, outcome));
92
72
  }
93
73
  function callSinkIsolated(sink, outcome) {
94
- try {
95
- sink(outcome);
96
- }
97
- catch (e) {
98
- hostLog('debug', `engineCompactWire: onSettled sink threw (ignored): ${wireFailureTextsOf(e).log}`);
99
- }
74
+ invokeHostCallbackIsolated('engineCompactWire: onSettled sink', () => sink(outcome));
100
75
  }
101
76
  function fanOutCompactSinks(sinks) {
102
77
  if (sinks === undefined || sinks.length === 0)
@@ -157,7 +132,7 @@ export function requestEngineCompact(sessionKey = DEFAULT_SESSION_KEY, opts) {
157
132
  return 'offline';
158
133
  probeManualCompactCapability(wire);
159
134
  const capsKey = wire.kind === 'injected' ? wire.capsBaseUrl : wire.target.baseUrl;
160
- if (capsKey !== undefined && manualCompactCapableByBase.get(capsKey) === false) {
135
+ if (engineCapState(capsKey, 'manualCompact') === 'false') {
161
136
  hostLog('debug', 'engineCompactWire: engine capabilities report manualCompact:false — verb suppressed (TOC-local runStore-less engine, [488])');
162
137
  return 'unsupported';
163
138
  }