@sema-agent/client-core 0.95.0 → 0.97.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 (233) hide show
  1. package/CHANGELOG.md +269 -0
  2. package/README.md +61 -31
  3. package/dist/adapt/arms.js +7 -1
  4. package/dist/adapt/toolCards.d.ts +1 -0
  5. package/dist/adapt/toolCards.js +16 -3
  6. package/dist/adapt/wireShapes.js +2 -16
  7. package/dist/adapter/activeRunSelfHeal.d.ts +4 -2
  8. package/dist/adapter/activeRunSelfHeal.js +32 -6
  9. package/dist/adapter/downstream/eventToSdkMessage.js +11 -3
  10. package/dist/adapter/downstream/terminalToSdkResult.js +14 -11
  11. package/dist/adapter/runStream.js +30 -47
  12. package/dist/agentSession/backgroundView.js +2 -15
  13. package/dist/agentSession/engineAgentRegistryRead.js +5 -4
  14. package/dist/agentSession/engineSessionBackgroundStop.js +22 -15
  15. package/dist/agentsWireCaps.d.ts +1 -1
  16. package/dist/agentsWireCaps.js +29 -12
  17. package/dist/approvalDecidedByCapability.d.ts +2 -0
  18. package/dist/approvalDecidedByCapability.js +0 -1
  19. package/dist/approvalsStreamLiveCapability.d.ts +2 -0
  20. package/dist/approvalsStreamLiveCapability.js +3 -2
  21. package/dist/attachmentSeatCapability.d.ts +2 -0
  22. package/dist/attachmentSeatCapability.js +0 -1
  23. package/dist/callerCwdCapability.d.ts +2 -4
  24. package/dist/callerCwdCapability.js +0 -7
  25. package/dist/centerWiringCapability.d.ts +2 -4
  26. package/dist/centerWiringCapability.js +4 -9
  27. package/dist/classifierVerdictWire.js +4 -16
  28. package/dist/clientSlice.js +1 -1
  29. package/dist/cloudConfigWireCaps.d.ts +4 -4
  30. package/dist/cloudConfigWireCaps.js +241 -85
  31. package/dist/coreValuePorts.d.ts +11 -7
  32. package/dist/coreValuePorts.js +5 -8
  33. package/dist/credentialProvenance.d.ts +28 -0
  34. package/dist/credentialProvenance.js +76 -0
  35. package/dist/decideFailureNote.js +3 -1
  36. package/dist/decideReceipt.js +7 -10
  37. package/dist/declared/supportFloorDeclared.js +3 -3
  38. package/dist/deviceExecutorManagementCapability.d.ts +2 -0
  39. package/dist/deviceExecutorManagementCapability.js +3 -2
  40. package/dist/displayUntrusted.d.ts +10 -3
  41. package/dist/displayUntrusted.js +371 -60
  42. package/dist/engineCapReader.d.ts +8 -2
  43. package/dist/engineCapReader.js +15 -7
  44. package/dist/engineCapsCache.d.ts +17 -3
  45. package/dist/engineCapsCache.js +268 -43
  46. package/dist/engineDirectory.d.ts +79 -0
  47. package/dist/engineDirectory.js +186 -0
  48. package/dist/engineErrorCodes.d.ts +17 -1
  49. package/dist/engineErrorCodes.js +46 -16
  50. package/dist/engineNoticeCodes.d.ts +17 -0
  51. package/dist/engineNoticeCodes.js +54 -1
  52. package/dist/executionLaneCapability.d.ts +2 -0
  53. package/dist/executionLaneCapability.js +3 -2
  54. package/dist/fileHistoryCaptureCapability.d.ts +16 -0
  55. package/dist/fileHistoryCaptureCapability.js +98 -2
  56. package/dist/fileHistoryLegNotice.js +4 -0
  57. package/dist/fleet/bgSubagentRow.d.ts +15 -0
  58. package/dist/fleet/bgSubagentRow.js +67 -0
  59. package/dist/fleet/fleetLedger.d.ts +1 -0
  60. package/dist/fleet/fleetLedger.js +164 -126
  61. package/dist/fleet/fleetProjection.d.ts +1 -0
  62. package/dist/fleet/fleetProjection.js +10 -3
  63. package/dist/fleetTaskDesc.js +4 -17
  64. package/dist/gateOutcome.d.ts +12 -1
  65. package/dist/gateOutcome.js +56 -1
  66. package/dist/gateVocabulary.d.ts +2 -2
  67. package/dist/gateVocabulary.js +4 -3
  68. package/dist/generated/engineAskFaceTables.js +1 -1
  69. package/dist/generated/engineFactTables.d.ts +5 -3
  70. package/dist/generated/engineFactTables.js +17 -4
  71. package/dist/generated/engineNoticeTables.js +12 -3
  72. package/dist/generated/sdkFactTables.d.ts +2 -0
  73. package/dist/generated/sdkFactTables.js +7 -0
  74. package/dist/generated/settingsSchemaFns.d.ts +3 -0
  75. package/dist/generated/settingsSchemaFns.js +53 -0
  76. package/dist/generated/toolNameTables.d.ts +1 -1
  77. package/dist/generated/toolNameTables.js +1 -42
  78. package/dist/hitl/approvalDecisionNoteAudit.js +2 -2
  79. package/dist/hitl/approvalEndingCause.d.ts +2 -0
  80. package/dist/hitl/approvalEndingCause.js +26 -21
  81. package/dist/hitl/approvalHolds.d.ts +16 -1
  82. package/dist/hitl/approvalHolds.js +52 -12
  83. package/dist/hitl/askGateWire.js +1 -0
  84. package/dist/hitl/askParkRowRouting.js +1 -1
  85. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  86. package/dist/hitl/automaticAnswerVerdict.js +13 -10
  87. package/dist/hitl/decisionConflict.js +4 -5
  88. package/dist/hitl/decisionRefusal.d.ts +8 -0
  89. package/dist/hitl/decisionRefusal.js +55 -14
  90. package/dist/hitl/frameRouter.d.ts +3 -1
  91. package/dist/hitl/frameRouter.js +58 -39
  92. package/dist/hitl/gateLedger.d.ts +0 -5
  93. package/dist/hitl/gateLedger.js +0 -21
  94. package/dist/hitl/hitlBridge.d.ts +6 -2
  95. package/dist/hitl/hitlBridge.js +46 -11
  96. package/dist/hitl/localAllowRule.d.ts +1 -0
  97. package/dist/hitl/localAllowRule.js +2 -2
  98. package/dist/hitl/noAllowCause.d.ts +2 -1
  99. package/dist/hitl/noAllowCause.js +3 -2
  100. package/dist/hitl/parkResolver.d.ts +1 -0
  101. package/dist/hitl/parkResolver.js +14 -56
  102. package/dist/hitl/parkRowBirthWait.d.ts +1 -0
  103. package/dist/hitl/parkRowBirthWait.js +2 -2
  104. package/dist/hitl/planReviewWire.d.ts +1 -0
  105. package/dist/hitl/planReviewWire.js +98 -20
  106. package/dist/hitl/replayedApproval.d.ts +3 -3
  107. package/dist/hitl/replayedApproval.js +21 -16
  108. package/dist/hitl/sessionPolicyDeliverable.d.ts +0 -1
  109. package/dist/hitl/sessionPolicyDeliverable.js +17 -17
  110. package/dist/hitl/sessionPolicyWire.d.ts +2 -0
  111. package/dist/hitl/sessionPolicyWire.js +15 -3
  112. package/dist/hitl/standingRows.d.ts +19 -0
  113. package/dist/hitl/standingRows.js +148 -0
  114. package/dist/hitl/suspendedReopen.js +2 -1
  115. package/dist/hitl/toolApprovalWire.d.ts +22 -10
  116. package/dist/hitl/toolApprovalWire.js +286 -47
  117. package/dist/hookMatcherVerdict.d.ts +1 -9
  118. package/dist/hookMatcherVerdict.js +21 -61
  119. package/dist/hooksWireCaps.js +2 -2
  120. package/dist/hostCallbackGuard.d.ts +1 -0
  121. package/dist/hostCallbackGuard.js +6 -0
  122. package/dist/index.d.ts +26 -12
  123. package/dist/index.js +20 -10
  124. package/dist/liveModelCatalog.d.ts +13 -0
  125. package/dist/liveModelCatalog.js +56 -0
  126. package/dist/mcpProbeCapability.d.ts +2 -4
  127. package/dist/mcpProbeCapability.js +3 -8
  128. package/dist/mcpWireCaps.d.ts +1 -0
  129. package/dist/mcpWireCaps.js +4 -1
  130. package/dist/memoryComplianceCapability.d.ts +2 -4
  131. package/dist/memoryComplianceCapability.js +3 -8
  132. package/dist/memoryOriginCapability.d.ts +2 -4
  133. package/dist/memoryOriginCapability.js +3 -8
  134. package/dist/memorySpecWire.js +2 -2
  135. package/dist/modelIdentityResolvability.d.ts +2 -2
  136. package/dist/modelIdentityResolvability.js +14 -5
  137. package/dist/noticePresentation.d.ts +68 -0
  138. package/dist/noticePresentation.js +247 -0
  139. package/dist/outputStyleSeatCapability.d.ts +2 -1
  140. package/dist/outputStyleSeatCapability.js +0 -4
  141. package/dist/ownKey.d.ts +2 -0
  142. package/dist/ownKey.js +18 -0
  143. package/dist/peerFrames.js +13 -9
  144. package/dist/peerLaneCapability.d.ts +2 -0
  145. package/dist/peerLaneCapability.js +3 -2
  146. package/dist/permissionModesCapability.d.ts +2 -4
  147. package/dist/permissionModesCapability.js +0 -7
  148. package/dist/permissionRuleIssue.js +0 -3
  149. package/dist/permissionRulesWriteCapability.d.ts +2 -0
  150. package/dist/permissionRulesWriteCapability.js +3 -2
  151. package/dist/permissionsAllowGrantCapability.d.ts +2 -0
  152. package/dist/permissionsAllowGrantCapability.js +4 -2
  153. package/dist/permissionsDeclaration.d.ts +2 -0
  154. package/dist/permissionsDeclaration.js +72 -59
  155. package/dist/printPermissionOutcome.d.ts +12 -0
  156. package/dist/printPermissionOutcome.js +50 -0
  157. package/dist/printToolResultFrame.d.ts +1 -0
  158. package/dist/printToolResultFrame.js +5 -9
  159. package/dist/promptBlockedCopy.d.ts +5 -0
  160. package/dist/promptBlockedCopy.js +35 -0
  161. package/dist/protocolSegment.d.ts +9 -6
  162. package/dist/protocolSegment.js +31 -21
  163. package/dist/providerRejection.d.ts +4 -0
  164. package/dist/providerRejection.js +75 -14
  165. package/dist/replayBody.d.ts +12 -0
  166. package/dist/replayBody.js +25 -0
  167. package/dist/request/taskRequest.d.ts +1 -4
  168. package/dist/request/taskRequest.js +74 -19
  169. package/dist/resumeRefusalCopy.js +9 -25
  170. package/dist/retryStatus.d.ts +9 -1
  171. package/dist/retryStatus.js +9 -2
  172. package/dist/rewindArchiveCapability.d.ts +3 -13
  173. package/dist/rewindArchiveCapability.js +12 -58
  174. package/dist/rewindArchiveReading.d.ts +17 -0
  175. package/dist/rewindArchiveReading.js +55 -0
  176. package/dist/ruleCompileVerdict.d.ts +9 -1
  177. package/dist/ruleCompileVerdict.js +29 -4
  178. package/dist/runTerminal.d.ts +48 -5
  179. package/dist/runTerminal.js +215 -12
  180. package/dist/sandboxWire.js +13 -0
  181. package/dist/sdkWireTransit.d.ts +2 -1
  182. package/dist/sdkWireTransit.js +1 -0
  183. package/dist/sealedKeyCapability.d.ts +2 -4
  184. package/dist/sealedKeyCapability.js +0 -7
  185. package/dist/seam.js +4 -2
  186. package/dist/seatContract.d.ts +76 -11
  187. package/dist/seatContract.js +222 -27
  188. package/dist/sessionPolicyCapability.d.ts +2 -0
  189. package/dist/sessionPolicyCapability.js +3 -2
  190. package/dist/sessionReadRedactionCapability.d.ts +2 -4
  191. package/dist/sessionReadRedactionCapability.js +0 -7
  192. package/dist/sessionSyncFileHistory.d.ts +4 -0
  193. package/dist/sessionSyncFileHistory.js +66 -0
  194. package/dist/sessionSyncFileHistoryCapability.d.ts +2 -1
  195. package/dist/sessionSyncFileHistoryCapability.js +3 -5
  196. package/dist/skillToolListsCapability.d.ts +2 -1
  197. package/dist/skillToolListsCapability.js +3 -5
  198. package/dist/sqlEngineCapability.d.ts +2 -0
  199. package/dist/sqlEngineCapability.js +4 -3
  200. package/dist/steerPriorityCapability.d.ts +2 -1
  201. package/dist/steerPriorityCapability.js +3 -5
  202. package/dist/storePostureCapability.d.ts +2 -4
  203. package/dist/storePostureCapability.js +4 -9
  204. package/dist/subagent/engineSubagentSteer.js +7 -5
  205. package/dist/subagentContentStore.js +4 -15
  206. package/dist/supportFloor.d.ts +1 -0
  207. package/dist/supportFloor.js +13 -9
  208. package/dist/systemReminderTag.d.ts +1 -0
  209. package/dist/systemReminderTag.js +8 -0
  210. package/dist/toolHistoryBadTurn.js +3 -2
  211. package/dist/toolHistoryMismatch.d.ts +0 -3
  212. package/dist/toolHistoryMismatch.js +3 -7
  213. package/dist/toolResult.d.ts +12 -1
  214. package/dist/toolResult.js +55 -1
  215. package/dist/toolResultContent.d.ts +2 -0
  216. package/dist/toolResultContent.js +63 -0
  217. package/dist/usageAnalytics.js +40 -16
  218. package/dist/userInvokedSkillsCapability.d.ts +2 -1
  219. package/dist/userInvokedSkillsCapability.js +3 -5
  220. package/dist/webSearchBackendCapability.d.ts +2 -0
  221. package/dist/webSearchBackendCapability.js +3 -2
  222. package/dist/wireErrorTriage.d.ts +2 -0
  223. package/dist/wireErrorTriage.js +91 -38
  224. package/dist/wireFailureShape.d.ts +20 -3
  225. package/dist/wireFailureShape.js +128 -72
  226. package/dist/workflowsJournalCapability.d.ts +2 -0
  227. package/dist/workflowsJournalCapability.js +3 -2
  228. package/dist/writeProtectionCapability.d.ts +2 -0
  229. package/dist/writeProtectionCapability.js +3 -2
  230. package/docs/INTEGRATION-CLIENTS.md +1784 -20
  231. package/package.json +5 -5
  232. package/dist/engineRefusedToolName.d.ts +0 -1
  233. package/dist/engineRefusedToolName.js +0 -8
@@ -1,16 +1,22 @@
1
1
  interface EngineCapReaderSpec<R> {
2
2
  name: string;
3
3
  project: (caps: unknown) => R | undefined;
4
- makeUnobserved: () => R;
5
4
  }
5
+ type ReaderUnobserved = {
6
+ kind: 'unobserved';
7
+ };
8
+ type ReaderUnreadable = {
9
+ kind: 'unreadable';
10
+ };
6
11
  interface EngineCapReader<R> {
7
12
  note(baseUrl: string, caps: unknown, opts?: {
8
13
  generation?: number;
9
14
  }): void;
10
- observed(baseUrl: string | undefined): R;
15
+ observed(baseUrl: string | undefined): R | ReaderUnobserved | ReaderUnreadable;
11
16
  __resetForTests(): void;
12
17
  }
13
18
  export declare function createEngineCapReader<R>(spec: EngineCapReaderSpec<R>): EngineCapReader<R>;
19
+ export declare function unreadableReadingDetail(subject?: string): string;
14
20
  export type StoreSeat = {
15
21
  kind: 'object';
16
22
  store: object;
@@ -1,5 +1,7 @@
1
1
  import { engineCapsLandingOf } from './engineCapsCache.js';
2
2
  import { ownDataField } from './ownKey.js';
3
+ const unobserved = () => ({ kind: 'unobserved' });
4
+ const unreadable = () => ({ kind: 'unreadable' });
3
5
  function freezeReading(reading, seen = new Set()) {
4
6
  if (reading === null || typeof reading !== 'object' || seen.has(reading))
5
7
  return reading;
@@ -18,15 +20,17 @@ export function createEngineCapReader(spec) {
18
20
  note(_baseUrl, _caps, _opts) { },
19
21
  observed(baseUrl) {
20
22
  if (typeof baseUrl !== 'string' || baseUrl === '')
21
- return spec.makeUnobserved();
23
+ return unobserved();
22
24
  const landing = engineCapsLandingOf(baseUrl);
23
- if (landing === undefined)
24
- return spec.makeUnobserved();
25
+ if (landing.kind === 'not_landed')
26
+ return unobserved();
27
+ if (landing.kind === 'unreadable')
28
+ return unreadable();
25
29
  const hit = memo.get(landing);
26
30
  if (hit === PROJECTING)
27
- return spec.makeUnobserved();
31
+ return unobserved();
28
32
  if (hit !== undefined)
29
- return hit.reading === undefined ? spec.makeUnobserved() : hit.reading;
33
+ return hit.reading === undefined ? unreadable() : hit.reading;
30
34
  const mine = memo;
31
35
  mine.set(landing, PROJECTING);
32
36
  let reading;
@@ -38,17 +42,21 @@ export function createEngineCapReader(spec) {
38
42
  }
39
43
  if (engineCapsLandingOf(baseUrl) !== landing) {
40
44
  mine.delete(landing);
41
- return spec.makeUnobserved();
45
+ return unobserved();
42
46
  }
43
47
  const done = { reading: reading === undefined ? undefined : freezeReading(reading) };
44
48
  mine.set(landing, done);
45
- return done.reading === undefined ? spec.makeUnobserved() : done.reading;
49
+ return done.reading === undefined ? unreadable() : done.reading;
46
50
  },
47
51
  __resetForTests() {
48
52
  memo = new WeakMap();
49
53
  },
50
54
  };
51
55
  }
56
+ export function unreadableReadingDetail(subject) {
57
+ const head = typeof subject === 'string' && subject.length > 0 ? `${subject} could not be read` : 'could not be read';
58
+ 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`;
59
+ }
52
60
  export function storeSeatOf(caps) {
53
61
  try {
54
62
  const store = ownDataField(caps, 'store');
@@ -1,7 +1,13 @@
1
+ export type EngineCapsLanding = {
2
+ readonly kind: 'landed';
3
+ readonly caps: Readonly<Record<string, unknown>>;
4
+ } | {
5
+ readonly kind: 'not_landed';
6
+ } | {
7
+ readonly kind: 'unreadable';
8
+ };
1
9
  export declare function engineCapsGeneration(baseUrl: string): number;
2
- export declare function engineCapsLandingOf(baseUrl: string): {
3
- readonly caps: object;
4
- } | undefined;
10
+ export declare function engineCapsLandingOf(baseUrl: string | undefined): EngineCapsLanding;
5
11
  export declare function kickEngineCapsProbe(baseUrl: string, probe: () => Promise<unknown>): void;
6
12
  export declare function engineCapsSettled(baseUrl: string | undefined, opts?: {
7
13
  withinMs?: number;
@@ -14,10 +20,13 @@ export declare function engineCapStateVia(baseUrl: string | undefined, key: stri
14
20
  }): Promise<EngineCapState>;
15
21
  export declare function engineCapTrue(baseUrl: string | undefined, key: string): boolean;
16
22
  export declare function engineCapNestedTrue(baseUrl: string | undefined, parentKey: string, key: string): boolean;
23
+ export declare function engineCapNestedValue(baseUrl: string | undefined, parentKey: string, key: string): EngineCapValueState;
17
24
  export type EngineCapValueState = {
18
25
  kind: 'unobserved';
19
26
  } | {
20
27
  kind: 'not_reported';
28
+ } | {
29
+ kind: 'unreadable';
21
30
  } | {
22
31
  kind: 'null';
23
32
  } | {
@@ -27,4 +36,9 @@ export type EngineCapValueState = {
27
36
  export declare function engineCapValue(baseUrl: string | undefined, key: string): EngineCapValueState;
28
37
  export declare function engineCapString(baseUrl: string | undefined, key: string): string | undefined;
29
38
  export declare function invalidateEngineCaps(baseUrl: string | undefined, probe?: () => Promise<unknown>): void;
39
+ export type EngineCapsProbeRotation = 'started' | 'registered' | 'ignored';
40
+ export declare function rotateEngineCapsProbe(baseUrl: string | undefined, probe: () => Promise<unknown>): EngineCapsProbeRotation;
41
+ export declare function refreshEngineCapsOnce(baseUrl: string | undefined, opts?: {
42
+ withinMs?: number;
43
+ }): Promise<'settled' | 'timed_out' | 'no_probe'>;
30
44
  export declare function __resetEngineCapsCacheForTests(): void;
@@ -1,7 +1,12 @@
1
+ import { settleWithinDeadline } from './abortableSleep.js';
2
+ import { ownDataField } from './ownKey.js';
3
+ const NOT_LANDED = Object.freeze({ kind: 'not_landed' });
1
4
  const capsByBase = new Map();
2
5
  const inFlight = new Set();
3
6
  const settleByBase = new Map();
4
7
  const genByBase = new Map();
8
+ const probeByBase = new Map();
9
+ const refreshByBase = new Map();
5
10
  function capsGeneration(baseUrl) {
6
11
  return genByBase.get(baseUrl) ?? 0;
7
12
  }
@@ -9,11 +14,17 @@ export function engineCapsGeneration(baseUrl) {
9
14
  return capsGeneration(baseUrl);
10
15
  }
11
16
  export function engineCapsLandingOf(baseUrl) {
12
- return capsByBase.get(baseUrl);
17
+ if (typeof baseUrl !== 'string' || baseUrl === '')
18
+ return NOT_LANDED;
19
+ return capsByBase.get(baseUrl) ?? NOT_LANDED;
13
20
  }
14
21
  export function kickEngineCapsProbe(baseUrl, probe) {
22
+ startEngineCapsProbe(baseUrl, probe);
23
+ }
24
+ function startEngineCapsProbe(baseUrl, probe) {
15
25
  if (!baseUrl || capsByBase.has(baseUrl) || inFlight.has(baseUrl))
16
- return;
26
+ return false;
27
+ probeByBase.set(baseUrl, probe);
17
28
  const gen = capsGeneration(baseUrl);
18
29
  inFlight.add(baseUrl);
19
30
  let wake = () => { };
@@ -30,9 +41,7 @@ export function kickEngineCapsProbe(baseUrl, probe) {
30
41
  const caps = await probe();
31
42
  if (gen !== capsGeneration(baseUrl))
32
43
  return;
33
- if (caps && typeof caps === 'object') {
34
- capsByBase.set(baseUrl, Object.freeze({ caps: caps }));
35
- }
44
+ landCapsSnapshot(baseUrl, gen, caps);
36
45
  }
37
46
  catch {
38
47
  }
@@ -45,6 +54,7 @@ export function kickEngineCapsProbe(baseUrl, probe) {
45
54
  markSettled();
46
55
  }
47
56
  })();
57
+ return true;
48
58
  }
49
59
  const MAX_WITHIN_MS = 2_147_483_647;
50
60
  function waitBudgetOf(opts) {
@@ -114,25 +124,152 @@ export async function engineCapsSettled(baseUrl, opts) {
114
124
  }
115
125
  }
116
126
  export function engineCapState(baseUrl, key) {
117
- if (!baseUrl)
118
- return 'unprobed';
119
- return capStateIn(capsByBase.get(baseUrl)?.caps, key);
127
+ return stateOfSlot(slotInLanding(engineCapsLandingOf(baseUrl), key));
120
128
  }
121
- function capStateIn(caps, key) {
129
+ const SNAPSHOT_MAX_DEPTH = 64;
130
+ const SNAPSHOT_MAX_NODES = 100_000;
131
+ const SNAPSHOT_PROBE_KEY = '\u0000capabilities-snapshot-probe\u0000';
132
+ const FOREIGN_PROTOTYPE = Object.freeze(Object.create(null));
133
+ function unreadableError() {
134
+ return new TypeError('capabilities body position is not readable (accessor or throwing proxy)');
135
+ }
136
+ const UNREADABLE_NODE = new Proxy(Object.freeze({}), {
137
+ getOwnPropertyDescriptor: () => {
138
+ throw unreadableError();
139
+ },
140
+ ownKeys: () => {
141
+ throw unreadableError();
142
+ },
143
+ has: () => {
144
+ throw unreadableError();
145
+ },
146
+ get: () => {
147
+ throw unreadableError();
148
+ },
149
+ getPrototypeOf: () => {
150
+ throw unreadableError();
151
+ },
152
+ });
153
+ function throwingAccessor() {
154
+ return {
155
+ get: () => {
156
+ throw unreadableError();
157
+ },
158
+ enumerable: true,
159
+ configurable: false,
160
+ };
161
+ }
162
+ function landCapsSnapshot(baseUrl, gen, caps) {
163
+ if (!isPlainCapsBody(caps))
164
+ return 'not_a_record';
165
+ const snapshot = snapshotCapsBody(caps);
166
+ if (gen !== capsGeneration(baseUrl))
167
+ return 'superseded';
168
+ const record = snapshot === UNREADABLE_NODE
169
+ ? Object.freeze({ kind: 'unreadable' })
170
+ : Object.freeze({ kind: 'landed', caps: snapshot });
171
+ capsByBase.set(baseUrl, record);
172
+ return 'landed';
173
+ }
174
+ function snapshotCapsBody(body) {
175
+ if (body === null || typeof body !== 'object')
176
+ return body;
177
+ const seen = new WeakMap();
178
+ let nodes = 0;
179
+ const copy = (src, depth) => {
180
+ const known = seen.get(src);
181
+ if (known !== undefined)
182
+ return known;
183
+ if (depth > SNAPSHOT_MAX_DEPTH || ++nodes > SNAPSHOT_MAX_NODES)
184
+ return UNREADABLE_NODE;
185
+ let keys;
186
+ let out;
187
+ let isArray;
188
+ try {
189
+ isArray = Array.isArray(src);
190
+ keys = Object.getOwnPropertyNames(src);
191
+ Object.getOwnPropertyDescriptor(src, SNAPSHOT_PROBE_KEY);
192
+ let length = 0;
193
+ if (isArray) {
194
+ const ld = Object.getOwnPropertyDescriptor(src, 'length');
195
+ if (ld === undefined || !Object.hasOwn(ld, 'value') || typeof ld.value !== 'number')
196
+ return UNREADABLE_NODE;
197
+ length = ld.value;
198
+ }
199
+ const proto = isArray ? null : Object.getPrototypeOf(src);
200
+ out = isArray ? new Array(length) : proto === Object.prototype || proto === null ? {} : Object.create(FOREIGN_PROTOTYPE);
201
+ }
202
+ catch {
203
+ return UNREADABLE_NODE;
204
+ }
205
+ seen.set(src, out);
206
+ for (const k of keys) {
207
+ if (isArray && k === 'length')
208
+ continue;
209
+ let d;
210
+ try {
211
+ d = Object.getOwnPropertyDescriptor(src, k);
212
+ }
213
+ catch {
214
+ Object.defineProperty(out, k, throwingAccessor());
215
+ continue;
216
+ }
217
+ if (d === undefined)
218
+ continue;
219
+ if (!Object.hasOwn(d, 'value')) {
220
+ Object.defineProperty(out, k, throwingAccessor());
221
+ continue;
222
+ }
223
+ const v = d.value;
224
+ Object.defineProperty(out, k, {
225
+ value: v !== null && typeof v === 'object' ? copy(v, depth + 1) : v,
226
+ enumerable: d.enumerable === true,
227
+ writable: false,
228
+ configurable: false,
229
+ });
230
+ }
231
+ Object.freeze(out);
232
+ return out;
233
+ };
234
+ return copy(body, 0);
235
+ }
236
+ const SLOT_UNOBSERVED = Object.freeze({ kind: 'unobserved' });
237
+ const SLOT_ABSENT = Object.freeze({ kind: 'absent' });
238
+ const SLOT_UNREADABLE = Object.freeze({ kind: 'unreadable' });
239
+ function capSlotIn(caps, key) {
122
240
  if (caps === undefined || caps === null || typeof caps !== 'object')
123
- return 'unprobed';
241
+ return SLOT_UNOBSERVED;
124
242
  try {
125
- if (!(key in caps))
126
- return 'absent';
127
- const v = caps[key];
128
- if (v === true)
129
- return 'true';
130
- if (v === false)
131
- return 'false';
132
- return 'non_boolean';
243
+ const v = ownDataField(caps, key);
244
+ return v === undefined ? SLOT_ABSENT : { kind: 'present', value: v };
133
245
  }
134
246
  catch {
135
- return 'unprobed';
247
+ return SLOT_UNREADABLE;
248
+ }
249
+ }
250
+ function slotInLanding(landing, key) {
251
+ switch (landing.kind) {
252
+ case 'not_landed':
253
+ return SLOT_UNOBSERVED;
254
+ case 'unreadable':
255
+ return SLOT_UNREADABLE;
256
+ case 'landed':
257
+ return capSlotIn(landing.caps, key);
258
+ }
259
+ }
260
+ function capStateIn(caps, key) {
261
+ return stateOfSlot(capSlotIn(caps, key));
262
+ }
263
+ function stateOfSlot(slot) {
264
+ switch (slot.kind) {
265
+ case 'unobserved':
266
+ return 'unprobed';
267
+ case 'absent':
268
+ return 'absent';
269
+ case 'unreadable':
270
+ return 'non_boolean';
271
+ case 'present':
272
+ return slot.value === true ? 'true' : slot.value === false ? 'false' : 'non_boolean';
136
273
  }
137
274
  }
138
275
  async function untilSettledOrAborted(p, signal) {
@@ -161,7 +298,8 @@ export async function engineCapStateVia(baseUrl, key, probe, opts) {
161
298
  try {
162
299
  if (signal?.aborted)
163
300
  return 'unprobed';
164
- return capStateIn(await probe(signal), key);
301
+ const body = await probe(signal);
302
+ return isPlainCapsBody(body) ? capStateIn(body, key) : 'unprobed';
165
303
  }
166
304
  catch {
167
305
  return 'unprobed';
@@ -178,37 +316,42 @@ export function engineCapTrue(baseUrl, key) {
178
316
  return engineCapState(baseUrl, key) === 'true';
179
317
  }
180
318
  export function engineCapNestedTrue(baseUrl, parentKey, key) {
181
- if (!baseUrl)
182
- return false;
183
- const parent = capsByBase.get(baseUrl)?.caps[parentKey];
184
- if (parent === null || typeof parent !== 'object')
185
- return false;
186
- return parent[key] === true;
319
+ const state = engineCapNestedValue(baseUrl, parentKey, key);
320
+ return state.kind === 'value' && state.value === true;
187
321
  }
188
- export function engineCapValue(baseUrl, key) {
189
- if (!baseUrl)
190
- return { kind: 'unobserved' };
191
- const caps = capsByBase.get(baseUrl)?.caps;
192
- if (caps === undefined)
193
- return { kind: 'unobserved' };
194
- if (!(key in caps))
322
+ export function engineCapNestedValue(baseUrl, parentKey, key) {
323
+ const parent = slotInLanding(engineCapsLandingOf(baseUrl), parentKey);
324
+ if (parent.kind !== 'present')
325
+ return valueStateOfSlot(parent);
326
+ const group = parent.value;
327
+ if (group === null || typeof group !== 'object')
195
328
  return { kind: 'not_reported' };
196
- const v = caps[key];
197
- if (v === undefined)
198
- return { kind: 'not_reported' };
199
- if (v === null)
200
- return { kind: 'null' };
201
- return { kind: 'value', value: v };
329
+ return valueStateOfSlot(capSlotIn(group, key));
330
+ }
331
+ export function engineCapValue(baseUrl, key) {
332
+ return valueStateOfSlot(slotInLanding(engineCapsLandingOf(baseUrl), key));
333
+ }
334
+ function valueStateOfSlot(slot) {
335
+ switch (slot.kind) {
336
+ case 'unobserved':
337
+ return { kind: 'unobserved' };
338
+ case 'absent':
339
+ return { kind: 'not_reported' };
340
+ case 'unreadable':
341
+ return { kind: 'unreadable' };
342
+ case 'present':
343
+ return slot.value === null ? { kind: 'null' } : { kind: 'value', value: slot.value };
344
+ }
202
345
  }
203
346
  export function engineCapString(baseUrl, key) {
204
- if (!baseUrl)
205
- return undefined;
206
- const v = capsByBase.get(baseUrl)?.caps[key];
207
- return typeof v === 'string' && v.length > 0 ? v : undefined;
347
+ const slot = slotInLanding(engineCapsLandingOf(baseUrl), key);
348
+ return slot.kind === 'present' && typeof slot.value === 'string' && slot.value.length > 0 ? slot.value : undefined;
208
349
  }
209
350
  export function invalidateEngineCaps(baseUrl, probe) {
210
351
  if (!baseUrl)
211
352
  return;
353
+ if (probe === undefined)
354
+ probeByBase.delete(baseUrl);
212
355
  const hadState = capsByBase.has(baseUrl) ||
213
356
  inFlight.has(baseUrl) ||
214
357
  settleByBase.has(baseUrl) ||
@@ -222,9 +365,91 @@ export function invalidateEngineCaps(baseUrl, probe) {
222
365
  if (probe !== undefined)
223
366
  kickEngineCapsProbe(baseUrl, probe);
224
367
  }
368
+ export function rotateEngineCapsProbe(baseUrl, probe) {
369
+ try {
370
+ if (typeof baseUrl !== 'string' || baseUrl === '' || typeof probe !== 'function')
371
+ return 'ignored';
372
+ if (startEngineCapsProbe(baseUrl, probe))
373
+ return 'started';
374
+ probeByBase.set(baseUrl, probe);
375
+ return 'registered';
376
+ }
377
+ catch {
378
+ return 'ignored';
379
+ }
380
+ }
381
+ export async function refreshEngineCapsOnce(baseUrl, opts) {
382
+ try {
383
+ if (typeof baseUrl !== 'string' || baseUrl === '')
384
+ return 'no_probe';
385
+ const budget = waitBudgetOf(opts);
386
+ const probe = probeByBase.get(baseUrl);
387
+ if (probe === undefined)
388
+ return 'no_probe';
389
+ const flying = refreshByBase.get(baseUrl);
390
+ if (flying !== undefined && flying.gen === capsGeneration(baseUrl))
391
+ return await awaitRefreshWithin(flying, budget);
392
+ if (!capsByBase.has(baseUrl)) {
393
+ kickEngineCapsProbe(baseUrl, probe);
394
+ return await engineCapsSettled(baseUrl, budget === undefined ? undefined : { withinMs: budget });
395
+ }
396
+ const gen = capsGeneration(baseUrl);
397
+ let finish = () => { };
398
+ const entry = { gen, promise: new Promise((resolve) => { finish = resolve; }) };
399
+ refreshByBase.set(baseUrl, entry);
400
+ void (async () => {
401
+ try {
402
+ const caps = await probe();
403
+ if (gen !== capsGeneration(baseUrl) || !capsByBase.has(baseUrl))
404
+ return false;
405
+ return landCapsSnapshot(baseUrl, gen, caps) === 'landed';
406
+ }
407
+ catch {
408
+ return false;
409
+ }
410
+ finally {
411
+ if (refreshByBase.get(baseUrl) === entry)
412
+ refreshByBase.delete(baseUrl);
413
+ }
414
+ })().then(finish);
415
+ return await awaitRefreshWithin(entry, budget);
416
+ }
417
+ catch {
418
+ return 'timed_out';
419
+ }
420
+ }
421
+ function isPlainCapsBody(caps) {
422
+ try {
423
+ if (typeof caps !== 'object' || caps === null)
424
+ return false;
425
+ if (Array.isArray(caps))
426
+ return false;
427
+ const proto = Object.getPrototypeOf(caps);
428
+ if (proto !== null && Object.getPrototypeOf(proto) !== null)
429
+ return false;
430
+ for (const key of Reflect.ownKeys(caps))
431
+ Object.getOwnPropertyDescriptor(caps, key);
432
+ return true;
433
+ }
434
+ catch {
435
+ return false;
436
+ }
437
+ }
438
+ async function awaitRefreshWithin(entry, budget) {
439
+ if (budget === undefined) {
440
+ await entry.promise;
441
+ return 'settled';
442
+ }
443
+ if (budget === 0)
444
+ return 'timed_out';
445
+ const out = await settleWithinDeadline(budget, () => entry.promise);
446
+ return out.kind === 'deadline' ? 'timed_out' : 'settled';
447
+ }
225
448
  export function __resetEngineCapsCacheForTests() {
226
449
  capsByBase.clear();
227
450
  inFlight.clear();
228
451
  settleByBase.clear();
229
452
  genByBase.clear();
453
+ probeByBase.clear();
454
+ refreshByBase.clear();
230
455
  }
@@ -0,0 +1,79 @@
1
+ declare const KIND_WORDS: readonly ["managed"];
2
+ declare const POSTURE_WORDS: readonly ["single", "multi"];
3
+ declare const RULE_WORDS: readonly ["only-one", "none", "ambiguous"];
4
+ export type EngineKindWord = (typeof KIND_WORDS)[number];
5
+ export type EnginePostureWord = (typeof POSTURE_WORDS)[number];
6
+ export type MeEngineRuleWord = (typeof RULE_WORDS)[number];
7
+ export type OpenWordReading<K extends string> = {
8
+ readonly kind: 'listed';
9
+ readonly word: K;
10
+ } | {
11
+ readonly kind: 'unlisted';
12
+ readonly word: string;
13
+ } | {
14
+ readonly kind: 'unreadable';
15
+ };
16
+ export interface EngineRowReading {
17
+ readonly name: string;
18
+ readonly kind: OpenWordReading<EngineKindWord>;
19
+ readonly scope: string | undefined;
20
+ readonly online: boolean | undefined;
21
+ readonly posture: OpenWordReading<EnginePostureWord>;
22
+ readonly viaCenter: string;
23
+ }
24
+ export interface EngineRowSet {
25
+ readonly rows: readonly EngineRowReading[];
26
+ readonly unreadableRows: number;
27
+ readonly unreadableNames: readonly string[];
28
+ }
29
+ export type MeEngineTargetReading = {
30
+ readonly kind: 'row';
31
+ readonly row: EngineRowReading;
32
+ } | {
33
+ readonly kind: 'null';
34
+ } | {
35
+ readonly kind: 'unreadable';
36
+ };
37
+ export interface MeEngineReading {
38
+ readonly rule: OpenWordReading<MeEngineRuleWord>;
39
+ readonly target: MeEngineTargetReading;
40
+ readonly candidates: EngineRowSet | undefined;
41
+ }
42
+ export type MeEngineUnresolvedReason = 'body' | 'rule' | 'rule-unlisted' | 'target' | 'candidates' | 'conflict';
43
+ export type MeEngineDecision = {
44
+ readonly kind: 'connect';
45
+ readonly engine: EngineRowReading;
46
+ readonly rule: OpenWordReading<MeEngineRuleWord>;
47
+ } | {
48
+ readonly kind: 'no-engine';
49
+ } | {
50
+ readonly kind: 'choose';
51
+ readonly candidates: EngineRowSet;
52
+ } | {
53
+ readonly kind: 'unresolved';
54
+ readonly reason: MeEngineUnresolvedReason;
55
+ readonly rule: OpenWordReading<MeEngineRuleWord>;
56
+ readonly candidates: EngineRowSet | undefined;
57
+ };
58
+ export type EngineOverrideDecision = {
59
+ readonly kind: 'select';
60
+ readonly engine: EngineRowReading;
61
+ } | {
62
+ readonly kind: 'not-listed';
63
+ readonly candidates: EngineRowSet;
64
+ } | {
65
+ readonly kind: 'duplicate';
66
+ readonly name: string;
67
+ } | {
68
+ readonly kind: 'row-unreadable';
69
+ readonly name: string;
70
+ } | {
71
+ readonly kind: 'unreadable';
72
+ } | {
73
+ readonly kind: 'invalid';
74
+ };
75
+ export declare function projectEngineDirectory(body: unknown): EngineRowSet | undefined;
76
+ export declare function projectMeEngine(body: unknown): MeEngineReading | undefined;
77
+ export declare function decideMeEngine(reading: MeEngineReading | undefined): MeEngineDecision;
78
+ export declare function engineOverrideOf(set: EngineRowSet | undefined, requested: unknown): EngineOverrideDecision;
79
+ export {};