@sema-agent/client-core 0.93.1 → 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 (321) hide show
  1. package/CHANGELOG.md +554 -0
  2. package/README.md +89 -55
  3. package/dist/adapt/arms.js +13 -11
  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 +13 -6
  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 +5 -3
  17. package/dist/agentsWireCaps.d.ts +17 -0
  18. package/dist/agentsWireCaps.js +111 -1
  19. package/dist/approvalDecidedByCapability.d.ts +0 -1
  20. package/dist/approvalDecidedByCapability.js +2 -7
  21. package/dist/approvalReachWire.d.ts +18 -0
  22. package/dist/approvalReachWire.js +58 -0
  23. package/dist/approvalsStreamLiveCapability.d.ts +0 -1
  24. package/dist/approvalsStreamLiveCapability.js +15 -14
  25. package/dist/atMostOnce.d.ts +8 -0
  26. package/dist/atMostOnce.js +36 -0
  27. package/dist/attachmentSeatCapability.d.ts +0 -1
  28. package/dist/attachmentSeatCapability.js +0 -3
  29. package/dist/attachmentsWireCaps.js +11 -6
  30. package/dist/bashExitReading.d.ts +10 -0
  31. package/dist/bashExitReading.js +12 -0
  32. package/dist/callerCwdCapability.d.ts +15 -0
  33. package/dist/callerCwdCapability.js +42 -0
  34. package/dist/centerWiringCapability.d.ts +1 -3
  35. package/dist/centerWiringCapability.js +18 -21
  36. package/dist/classifierStatus.js +4 -4
  37. package/dist/cloudConfigWireCaps.js +43 -21
  38. package/dist/compensations.js +1 -1
  39. package/dist/controlRouter.js +3 -10
  40. package/dist/coreValuePorts.d.ts +64 -1
  41. package/dist/coreValuePorts.js +30 -0
  42. package/dist/cycleOrder.d.ts +15 -0
  43. package/dist/cycleOrder.js +45 -0
  44. package/dist/decideFailureNote.js +4 -1
  45. package/dist/decideReceipt.d.ts +2 -1
  46. package/dist/decideReceipt.js +41 -13
  47. package/dist/declared/supportFloorDeclared.d.ts +1 -0
  48. package/dist/declared/supportFloorDeclared.js +5 -0
  49. package/dist/detachWire.d.ts +1 -4
  50. package/dist/detachWire.js +1 -1
  51. package/dist/deviceExecutorManagementCapability.d.ts +0 -1
  52. package/dist/deviceExecutorManagementCapability.js +36 -40
  53. package/dist/deviceFlowPolling.d.ts +5 -0
  54. package/dist/deviceFlowPolling.js +28 -0
  55. package/dist/deviceRebind.d.ts +88 -0
  56. package/dist/deviceRebind.js +242 -0
  57. package/dist/displayUntrusted.d.ts +1 -0
  58. package/dist/displayUntrusted.js +963 -30
  59. package/dist/engineAgentAbsence.d.ts +2 -2
  60. package/dist/engineAgentPanelStore.d.ts +8 -18
  61. package/dist/engineAgentPanelStore.js +19 -537
  62. package/dist/engineCapReader.d.ts +6 -6
  63. package/dist/engineCapReader.js +30 -43
  64. package/dist/engineCapsCache.d.ts +7 -2
  65. package/dist/engineCapsCache.js +64 -26
  66. package/dist/engineCredentialRequirement.d.ts +9 -0
  67. package/dist/engineCredentialRequirement.js +23 -0
  68. package/dist/engineEnvSourcing.d.ts +53 -0
  69. package/dist/engineEnvSourcing.js +81 -0
  70. package/dist/engineErrorCodes.d.ts +19 -4
  71. package/dist/engineErrorCodes.js +39 -21
  72. package/dist/engineIdentity.js +2 -0
  73. package/dist/engineNoticeCodes.d.ts +22 -2
  74. package/dist/engineNoticeCodes.js +73 -6
  75. package/dist/engineRefusedToolName.d.ts +1 -0
  76. package/dist/engineRefusedToolName.js +8 -0
  77. package/dist/engineWireSdk.js +2 -2
  78. package/dist/executionLaneCapability.d.ts +2 -3
  79. package/dist/executionLaneCapability.js +28 -28
  80. package/dist/fileHistoryCaptureCapability.d.ts +0 -1
  81. package/dist/fileHistoryCaptureCapability.js +13 -12
  82. package/dist/fileHistoryLegNotice.d.ts +14 -2
  83. package/dist/fileHistoryLegNotice.js +101 -15
  84. package/dist/fleet/fleetLedger.d.ts +2 -0
  85. package/dist/fleet/fleetLedger.js +74 -52
  86. package/dist/fleet/fleetProjection.d.ts +0 -3
  87. package/dist/fleet/fleetProjection.js +9 -16
  88. package/dist/fleetAgentPanelProjection.d.ts +4 -17
  89. package/dist/fleetAgentPanelProjection.js +7 -197
  90. package/dist/fleetAgentRowLike.d.ts +16 -0
  91. package/dist/fleetAgentRowLike.js +1 -0
  92. package/dist/gateOutcome.d.ts +2 -1
  93. package/dist/gateOutcome.js +33 -18
  94. package/dist/gateVocabulary.js +1 -1
  95. package/dist/generated/engineAskFaceTables.d.ts +3 -0
  96. package/dist/generated/engineAskFaceTables.js +12 -0
  97. package/dist/generated/engineFactTables.d.ts +4 -2
  98. package/dist/generated/engineFactTables.js +13 -0
  99. package/dist/generated/engineNoticeTables.d.ts +5 -0
  100. package/dist/generated/engineNoticeTables.js +7 -0
  101. package/dist/generated/sdkFactTables.d.ts +5 -0
  102. package/dist/generated/sdkFactTables.js +34 -0
  103. package/dist/generated/settingsSchemaFns.d.ts +10 -0
  104. package/dist/generated/settingsSchemaFns.js +22 -0
  105. package/dist/generated/settingsSchemaTables.d.ts +3 -0
  106. package/dist/generated/settingsSchemaTables.js +3 -0
  107. package/dist/headlessPermissionModeWire.d.ts +2 -2
  108. package/dist/headlessPermissionModeWire.js +11 -21
  109. package/dist/headlessReconnectWire.js +49 -20
  110. package/dist/hitl/allowRuleShadow.d.ts +1 -1
  111. package/dist/hitl/allowRuleShadow.js +49 -8
  112. package/dist/hitl/approvalCompleteParked.d.ts +1 -0
  113. package/dist/hitl/approvalCompleteParked.js +14 -0
  114. package/dist/hitl/approvalEndingCause.d.ts +5 -0
  115. package/dist/hitl/approvalEndingCause.js +61 -0
  116. package/dist/hitl/approvalHolds.d.ts +46 -0
  117. package/dist/hitl/approvalHolds.js +140 -0
  118. package/dist/hitl/approvalOutcomeNote.js +2 -1
  119. package/dist/hitl/approvalResolution.js +9 -1
  120. package/dist/hitl/approvalsFeed.js +23 -6
  121. package/dist/hitl/askGateWire.d.ts +2 -1
  122. package/dist/hitl/askGateWire.js +29 -1
  123. package/dist/hitl/automaticAnswerVerdict.d.ts +8 -2
  124. package/dist/hitl/automaticAnswerVerdict.js +71 -23
  125. package/dist/hitl/crashConverged.js +2 -0
  126. package/dist/hitl/decisionConflict.d.ts +3 -0
  127. package/dist/hitl/decisionConflict.js +43 -0
  128. package/dist/hitl/decisionRefusal.d.ts +23 -0
  129. package/dist/hitl/decisionRefusal.js +88 -0
  130. package/dist/hitl/frameRouter.d.ts +10 -0
  131. package/dist/hitl/frameRouter.js +71 -32
  132. package/dist/hitl/gateLedger.d.ts +8 -0
  133. package/dist/hitl/gateLedger.js +38 -0
  134. package/dist/hitl/hitlBridge.d.ts +14 -3
  135. package/dist/hitl/hitlBridge.js +75 -62
  136. package/dist/hitl/hitlHostSurface.d.ts +3 -0
  137. package/dist/hitl/hitlHostSurface.js +17 -15
  138. package/dist/hitl/livePendingAsk.d.ts +16 -6
  139. package/dist/hitl/livePendingAsk.js +36 -4
  140. package/dist/hitl/localAllowRule.js +2 -1
  141. package/dist/hitl/noAllowCause.d.ts +9 -0
  142. package/dist/hitl/noAllowCause.js +26 -0
  143. package/dist/hitl/parkExpiryJudgements.d.ts +19 -0
  144. package/dist/hitl/parkExpiryJudgements.js +46 -0
  145. package/dist/hitl/parkResolver.d.ts +3 -7
  146. package/dist/hitl/parkResolver.js +55 -28
  147. package/dist/hitl/parkRowBirthWait.js +2 -1
  148. package/dist/hitl/persistedRulesWire.d.ts +6 -1
  149. package/dist/hitl/persistedRulesWire.js +16 -4
  150. package/dist/hitl/planReviewWire.d.ts +2 -3
  151. package/dist/hitl/planReviewWire.js +86 -39
  152. package/dist/hitl/replayedApproval.d.ts +8 -0
  153. package/dist/hitl/replayedApproval.js +125 -10
  154. package/dist/hitl/resumeRunningCard.d.ts +2 -0
  155. package/dist/hitl/resumeRunningCard.js +15 -4
  156. package/dist/hitl/sessionPolicyDeliverable.d.ts +1 -1
  157. package/dist/hitl/sessionPolicyDeliverable.js +3 -8
  158. package/dist/hitl/sessionPolicyWire.js +1 -1
  159. package/dist/hitl/toolApprovalWire.d.ts +50 -5
  160. package/dist/hitl/toolApprovalWire.js +368 -56
  161. package/dist/hooksWireCaps.js +38 -6
  162. package/dist/host.d.ts +5 -0
  163. package/dist/host.js +3 -1
  164. package/dist/hostCallbackGuard.d.ts +1 -0
  165. package/dist/hostCallbackGuard.js +25 -0
  166. package/dist/humanTurnRead.d.ts +15 -1
  167. package/dist/humanTurnRead.js +28 -2
  168. package/dist/index.d.ts +45 -14
  169. package/dist/index.js +33 -12
  170. package/dist/interactiveInterrupt.d.ts +8 -0
  171. package/dist/interactiveInterrupt.js +54 -0
  172. package/dist/limitsWire.d.ts +5 -1
  173. package/dist/limitsWire.js +51 -13
  174. package/dist/liveModelCatalog.d.ts +109 -0
  175. package/dist/liveModelCatalog.js +344 -18
  176. package/dist/mcpEngineLeg.d.ts +25 -0
  177. package/dist/mcpEngineLeg.js +71 -15
  178. package/dist/mcpPanel.js +2 -1
  179. package/dist/mcpProbeCapability.d.ts +0 -1
  180. package/dist/mcpProbeCapability.js +13 -12
  181. package/dist/mcpReconnect.d.ts +1 -3
  182. package/dist/mcpReconnect.js +20 -10
  183. package/dist/memoryComplianceCapability.d.ts +0 -1
  184. package/dist/memoryComplianceCapability.js +14 -13
  185. package/dist/memoryOriginCapability.d.ts +0 -1
  186. package/dist/memoryOriginCapability.js +14 -13
  187. package/dist/memoryVerbsWire.d.ts +1 -1
  188. package/dist/memoryVerbsWire.js +4 -0
  189. package/dist/model/liveCatalogShape.d.ts +14 -0
  190. package/dist/model/liveCatalogShape.js +71 -0
  191. package/dist/model/modelSupplyRules.d.ts +1 -0
  192. package/dist/model/modelSupplyRules.js +30 -9
  193. package/dist/model/modelsPolicy.d.ts +21 -0
  194. package/dist/model/modelsPolicy.js +90 -0
  195. package/dist/modelIdentityResolvability.d.ts +4 -2
  196. package/dist/modelIdentityResolvability.js +25 -5
  197. package/dist/modelSwitchFallback.d.ts +69 -0
  198. package/dist/modelSwitchFallback.js +206 -0
  199. package/dist/notifications.js +12 -11
  200. package/dist/outputStyleSeatCapability.d.ts +15 -0
  201. package/dist/outputStyleSeatCapability.js +42 -0
  202. package/dist/ownKey.d.ts +7 -0
  203. package/dist/ownKey.js +58 -0
  204. package/dist/panelReduce.d.ts +114 -0
  205. package/dist/panelReduce.js +1135 -0
  206. package/dist/panelStateHolder.d.ts +17 -0
  207. package/dist/panelStateHolder.js +201 -0
  208. package/dist/peerLaneCapability.d.ts +0 -1
  209. package/dist/peerLaneCapability.js +15 -14
  210. package/dist/permissionModesCapability.d.ts +0 -1
  211. package/dist/permissionModesCapability.js +5 -10
  212. package/dist/permissionRuleIssue.js +1 -1
  213. package/dist/permissionRulesWriteCapability.d.ts +0 -1
  214. package/dist/permissionRulesWriteCapability.js +15 -14
  215. package/dist/permissionsAllowGrantCapability.d.ts +2 -1
  216. package/dist/permissionsAllowGrantCapability.js +35 -19
  217. package/dist/permissionsDeclaration.d.ts +16 -1
  218. package/dist/permissionsDeclaration.js +142 -15
  219. package/dist/printToolResultFrame.js +2 -10
  220. package/dist/promptDelivery.js +0 -8
  221. package/dist/protocolSegment.d.ts +1 -0
  222. package/dist/protocolSegment.js +13 -1
  223. package/dist/request/taskRequest.d.ts +11 -3
  224. package/dist/request/taskRequest.js +13 -1
  225. package/dist/resultFrameKeys.d.ts +4 -0
  226. package/dist/resultFrameKeys.js +13 -0
  227. package/dist/resumeRefusalCopy.d.ts +18 -1
  228. package/dist/resumeRefusalCopy.js +132 -31
  229. package/dist/retryStatus.js +6 -4
  230. package/dist/rewindArchiveCapability.d.ts +2 -1
  231. package/dist/rewindArchiveCapability.js +28 -15
  232. package/dist/rewindEngineAction.d.ts +21 -0
  233. package/dist/rewindEngineAction.js +36 -0
  234. package/dist/rewindWireCaps.d.ts +2 -1
  235. package/dist/rewindWireCaps.js +1 -0
  236. package/dist/{hitl/rosterMountedNames.d.ts → rosterMountedNames.d.ts} +1 -1
  237. package/dist/runCancelContext.js +2 -1
  238. package/dist/runTerminal.d.ts +0 -11
  239. package/dist/runTerminal.js +4 -27
  240. package/dist/sdkRegistryTransit.d.ts +2 -1
  241. package/dist/sdkRegistryTransit.js +1 -0
  242. package/dist/sealedKeyCapability.d.ts +0 -1
  243. package/dist/sealedKeyCapability.js +19 -20
  244. package/dist/seatContract.d.ts +85 -28
  245. package/dist/seatContract.js +512 -148
  246. package/dist/sessionIdSegment.d.ts +1 -0
  247. package/dist/sessionIdSegment.js +11 -0
  248. package/dist/sessionMemoryErase.d.ts +1 -1
  249. package/dist/sessionMemoryErase.js +6 -1
  250. package/dist/sessionMemoryStatus.js +3 -2
  251. package/dist/sessionPolicyCapability.d.ts +0 -1
  252. package/dist/sessionPolicyCapability.js +14 -13
  253. package/dist/sessionReadRedactionCapability.d.ts +15 -0
  254. package/dist/sessionReadRedactionCapability.js +42 -0
  255. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -1
  256. package/dist/sessionSyncFileHistoryCapability.js +13 -12
  257. package/dist/skillToolListsCapability.d.ts +0 -1
  258. package/dist/skillToolListsCapability.js +13 -12
  259. package/dist/skillsWireCaps.d.ts +4 -0
  260. package/dist/skillsWireCaps.js +66 -1
  261. package/dist/sqlEngineCapability.d.ts +0 -1
  262. package/dist/sqlEngineCapability.js +21 -21
  263. package/dist/steerPriorityCapability.d.ts +0 -1
  264. package/dist/steerPriorityCapability.js +18 -19
  265. package/dist/storePostureCapability.d.ts +1 -1
  266. package/dist/storePostureCapability.js +16 -16
  267. package/dist/streamDrainingLegs.d.ts +6 -0
  268. package/dist/streamDrainingLegs.js +23 -0
  269. package/dist/subagent/agentStateDetail.d.ts +1 -0
  270. package/dist/subagent/agentStateDetail.js +41 -0
  271. package/dist/subagent/engineCompactWire.d.ts +15 -0
  272. package/dist/subagent/engineCompactWire.js +82 -45
  273. package/dist/subagent/engineDelegatedPrompt.js +10 -6
  274. package/dist/subagent/engineSubagentOutput.d.ts +0 -1
  275. package/dist/subagent/engineSubagentOutput.js +5 -20
  276. package/dist/subagent/engineSubagentTail.d.ts +0 -1
  277. package/dist/subagent/engineSubagentTail.js +7 -32
  278. package/dist/subagentContentStore.js +3 -3
  279. package/dist/supportFloor.js +2 -5
  280. package/dist/taskRequestWords.d.ts +2 -4
  281. package/dist/taskRequestWords.js +3 -2
  282. package/dist/terminalStatuses.d.ts +30 -0
  283. package/dist/terminalStatuses.js +67 -0
  284. package/dist/toolResult.d.ts +5 -0
  285. package/dist/toolResult.js +88 -36
  286. package/dist/types/engineState.d.ts +2 -1
  287. package/dist/usageAnalytics.d.ts +146 -0
  288. package/dist/usageAnalytics.js +311 -0
  289. package/dist/userAttachmentEnvelope.d.ts +22 -1
  290. package/dist/userAttachmentEnvelope.js +90 -2
  291. package/dist/userInvokedSkillsCapability.d.ts +0 -1
  292. package/dist/userInvokedSkillsCapability.js +13 -12
  293. package/dist/webSearchBackendCapability.d.ts +0 -1
  294. package/dist/webSearchBackendCapability.js +20 -19
  295. package/dist/webSearchWireCaps.js +3 -11
  296. package/dist/wireErrorTriage.d.ts +11 -0
  297. package/dist/wireErrorTriage.js +35 -0
  298. package/dist/wireFailureShape.d.ts +10 -0
  299. package/dist/wireFailureShape.js +72 -5
  300. package/dist/wireRefusalCopy.d.ts +6 -1
  301. package/dist/wireRefusalCopy.js +23 -25
  302. package/dist/wiringInstructionsAttribution.d.ts +10 -0
  303. package/dist/wiringInstructionsAttribution.js +67 -0
  304. package/dist/workflowClient.js +19 -2
  305. package/dist/workflowsJournalCapability.d.ts +0 -1
  306. package/dist/workflowsJournalCapability.js +13 -12
  307. package/dist/writeProtectionCapability.d.ts +0 -1
  308. package/dist/writeProtectionCapability.js +26 -26
  309. package/docs/INTEGRATION-CLIENTS.md +1733 -52
  310. package/package.json +5 -5
  311. package/dist/askSurvivesStandingAnswer.d.ts +0 -13
  312. package/dist/askSurvivesStandingAnswer.js +0 -53
  313. package/dist/engineCapsGenerationGuard.d.ts +0 -4
  314. package/dist/engineCapsGenerationGuard.js +0 -19
  315. package/dist/hitl/askSurvivesPosture.d.ts +0 -20
  316. package/dist/hitl/askSurvivesPosture.js +0 -48
  317. package/dist/panelRunningHistory.d.ts +0 -22
  318. package/dist/panelRunningHistory.js +0 -82
  319. package/dist/registryConflict.d.ts +0 -3
  320. package/dist/registryConflict.js +0 -44
  321. /package/dist/{hitl/rosterMountedNames.js → rosterMountedNames.js} +0 -0
@@ -1,4 +1,5 @@
1
1
  import { isMcpLivenessState } from './mcpLiveness.js';
2
+ import { mcpSectionDroppedNamedRowsOf } from './ownKey.js';
2
3
  void true;
3
4
  void true;
4
5
  void true;
@@ -18,6 +19,26 @@ const readKey = (o, k) => {
18
19
  }
19
20
  };
20
21
  export function mcpEngineLegLivenessOf(serverName, rows) {
22
+ const hit = findMcpLegRow(serverName, rows);
23
+ if (hit.kind === 'row-unreadable')
24
+ return { kind: 'unreadable' };
25
+ if (hit.kind !== 'row')
26
+ return hit;
27
+ const first = hit.row;
28
+ const flag = readKey(first, 'livenessUnreadable');
29
+ if (flag === UNREADABLE_CELL || flag === true)
30
+ return { kind: 'unreadable' };
31
+ const cell = readKey(first, 'liveness');
32
+ if (cell === ABSENT_CELL)
33
+ return { kind: 'absent' };
34
+ if (cell === UNREADABLE_CELL || cell === null || typeof cell !== 'object')
35
+ return { kind: 'unreadable' };
36
+ const state = readKey(cell, 'state');
37
+ if (typeof state !== 'string' || state === '')
38
+ return { kind: 'unreadable' };
39
+ return { kind: 'observed', state };
40
+ }
41
+ function findMcpLegRow(serverName, rows) {
21
42
  let isArray = false;
22
43
  try {
23
44
  isArray = Array.isArray(rows);
@@ -56,22 +77,57 @@ export function mcpEngineLegLivenessOf(serverName, rows) {
56
77
  }
57
78
  if (incomplete)
58
79
  return { kind: 'unobserved' };
59
- if (matches >= 2)
60
- return { kind: 'ambiguous', rows: matches };
61
- if (matches === 0)
80
+ const dropped = mcpSectionDroppedNamedRowsOf(rows, serverName);
81
+ const total = matches + dropped;
82
+ if (total >= 2)
83
+ return { kind: 'ambiguous', rows: total };
84
+ if (total === 0)
62
85
  return { kind: 'not-listed' };
63
- const flag = readKey(first, 'livenessUnreadable');
64
- if (flag === UNREADABLE_CELL || flag === true)
65
- return { kind: 'unreadable' };
66
- const cell = readKey(first, 'liveness');
67
- if (cell === ABSENT_CELL)
68
- return { kind: 'absent' };
69
- if (cell === UNREADABLE_CELL || cell === null || typeof cell !== 'object')
70
- return { kind: 'unreadable' };
71
- const state = readKey(cell, 'state');
72
- if (typeof state !== 'string' || state === '')
73
- return { kind: 'unreadable' };
74
- return { kind: 'observed', state };
86
+ if (first === undefined)
87
+ return { kind: 'row-unreadable' };
88
+ return { kind: 'row', row: first };
89
+ }
90
+ const MCP_LEG_CONNECT_STATUS_ARMS = Object.freeze({
91
+ connected: 'connected',
92
+ failed: 'failed',
93
+ skipped: 'skipped',
94
+ });
95
+ void true;
96
+ export function mcpEngineLegConnectionOf(serverName, rows) {
97
+ const hit = findMcpLegRow(serverName, rows);
98
+ if (hit.kind === 'unobserved')
99
+ return { state: 'unknown', cause: 'unobserved' };
100
+ if (hit.kind === 'ambiguous')
101
+ return { state: 'unknown', cause: 'ambiguous', rows: hit.rows };
102
+ if (hit.kind === 'not-listed')
103
+ return { state: 'not_connected', cause: 'not_listed' };
104
+ if (hit.kind === 'row-unreadable')
105
+ return { state: 'unknown', cause: 'unreadable' };
106
+ const row = hit.row;
107
+ const status = readKey(row, 'status');
108
+ if (typeof status !== 'string' || status === '')
109
+ return { state: 'unknown', cause: 'unreadable' };
110
+ const arm = Object.hasOwn(MCP_LEG_CONNECT_STATUS_ARMS, status)
111
+ ? MCP_LEG_CONNECT_STATUS_ARMS[status]
112
+ : undefined;
113
+ if (arm === undefined)
114
+ return { state: 'unknown', cause: 'unrecognized_status', status };
115
+ if (arm === 'skipped')
116
+ return { state: 'not_connected', cause: 'skipped' };
117
+ if (arm === 'connected') {
118
+ const n = readKey(row, 'toolCount');
119
+ return typeof n === 'number' && Number.isInteger(n) && n >= 0 ? { state: 'connected', toolCount: n } : { state: 'connected' };
120
+ }
121
+ const errorCode = readKey(row, 'errorCode');
122
+ const delivered = readKey(row, 'delivered');
123
+ const httpStatus = readKey(row, 'httpStatus');
124
+ return {
125
+ state: 'not_connected',
126
+ cause: 'failed',
127
+ ...(typeof errorCode === 'string' && errorCode !== '' ? { errorCode } : {}),
128
+ ...(typeof delivered === 'string' && delivered !== '' ? { delivered } : {}),
129
+ ...(typeof httpStatus === 'number' && Number.isFinite(httpStatus) ? { httpStatus } : {}),
130
+ };
75
131
  }
76
132
  const rosterReadingOf = (v) => {
77
133
  if (v === UNREADABLE_CELL)
package/dist/mcpPanel.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { hostLog } from './host.js';
2
+ import { isSessionIdPathSegment } from './sessionIdSegment.js';
2
3
  import { projectMcpSection } from './adapter/downstream/eventToSdkMessage.js';
3
4
  import { capForDisplay } from './fleetTaskDesc.js';
4
5
  import { mcpLivenessRollupOf } from './mcpLiveness.js';
@@ -62,7 +63,7 @@ export function projectMcpPanel(body) {
62
63
  return view;
63
64
  }
64
65
  export async function fetchMcpPanel(client, sessionId, opts) {
65
- if (typeof sessionId !== 'string' || sessionId.length === 0)
66
+ if (!isSessionIdPathSegment(sessionId))
66
67
  return undefined;
67
68
  let body;
68
69
  try {
@@ -14,5 +14,4 @@ export declare function noteEngineCapsForMcpProbe(baseUrl: string, caps: unknown
14
14
  export declare function observedMcpProbe(baseUrl?: string | undefined): McpProbeReading;
15
15
  export declare function mcpProbeAvailable(reading: McpProbeReading): 'yes' | 'no' | 'unknown';
16
16
  export declare function mcpProbeDoctorDetail(reading: McpProbeReading): string;
17
- export declare function forgetMcpProbeReading(baseUrl: string | undefined): void;
18
17
  export declare function __resetMcpProbeReadingsForTests(): void;
@@ -1,16 +1,20 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
+ import { ownDataField } from './ownKey.js';
3
4
  export function projectMcpProbeCapability(caps) {
4
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
5
- return undefined;
6
- if (!Object.hasOwn(caps, 'mcpProbe'))
7
- return { kind: 'not_reported' };
8
- const v = caps.mcpProbe;
9
- if (v === undefined)
10
- return { kind: 'not_reported' };
11
- if (typeof v !== 'boolean')
5
+ try {
6
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
7
+ return undefined;
8
+ const v = ownDataField(caps, 'mcpProbe');
9
+ if (v === undefined)
10
+ return { kind: 'not_reported' };
11
+ if (typeof v !== 'boolean')
12
+ return undefined;
13
+ return v ? { kind: 'present' } : { kind: 'absent' };
14
+ }
15
+ catch {
12
16
  return undefined;
13
- return v ? { kind: 'present' } : { kind: 'absent' };
17
+ }
14
18
  }
15
19
  const reader = createEngineCapReader({
16
20
  name: 'mcpProbe',
@@ -47,9 +51,6 @@ export function mcpProbeDoctorDetail(reading) {
47
51
  'and a probe of caller-supplied declarations answers with the very same body shape');
48
52
  }
49
53
  }
50
- export function forgetMcpProbeReading(baseUrl) {
51
- reader.forget(baseUrl);
52
- }
53
54
  export function __resetMcpProbeReadingsForTests() {
54
55
  reader.__resetForTests();
55
56
  }
@@ -62,9 +62,7 @@ export type McpReconnectVerdict = {
62
62
  };
63
63
  export interface McpReconnectClientLike {
64
64
  sessions: {
65
- mcpReconnect?: (sessionId: string, body: {
66
- server: string;
67
- }, opts?: {
65
+ mcpReconnect?: (sessionId: string, server: string, opts?: {
68
66
  signal?: AbortSignal;
69
67
  }) => Promise<unknown>;
70
68
  };
@@ -1,10 +1,14 @@
1
1
  import { capForDisplay } from './fleetTaskDesc.js';
2
+ import { ownDataField } from './ownKey.js';
3
+ import { isSessionIdPathSegment } from './sessionIdSegment.js';
2
4
  export const MCP_RECONNECT_OUTCOMES = Object.freeze(['accepted', 'refused', 'unsupported']);
3
5
  export const MCP_RECONNECT_TRANSACTION_NOTICE = 'Reconnecting closes the current connection before dialing again. On a healthy server this is a transaction, ' +
4
6
  'not a refresh: a failed re-dial leaves the server down and withdraws its tools from the model until a later re-dial succeeds.';
5
7
  export const MCP_RECONNECT_UNSETTLED_NOTICE = 'The MCP re-dial did not settle within the time this request waits, so there is no result yet: the re-dial was not cancelled and may still be running. ' +
6
8
  "Check the server's state before re-dialing it again — a second request that arrives after the dial has settled closes the connection and dials once more.";
7
9
  const UNSETTLED_CODE = 'state.mcp_reconnect_unsettled';
10
+ const _sdkClientIsAnInjection = [true];
11
+ void _sdkClientIsAnInjection;
8
12
  const RECONNECT_TEXT_MAX = 200;
9
13
  const RECONNECT_WORD_MAX = 40;
10
14
  const SERVER_NAME_MAX = 190;
@@ -137,7 +141,7 @@ export function classifyMcpReconnectFailure(e) {
137
141
  return { kind: 'failed', error: e };
138
142
  }
139
143
  export async function reconnectMcpServer(client, sessionId, server, opts) {
140
- if (!nonEmpty(sessionId))
144
+ if (!isSessionIdPathSegment(sessionId))
141
145
  return { kind: 'invalid' };
142
146
  if (!nonEmpty(server) || server.length > SERVER_NAME_MAX)
143
147
  return { kind: 'invalid' };
@@ -148,7 +152,7 @@ export async function reconnectMcpServer(client, sessionId, server, opts) {
148
152
  if (opts?.signal?.aborted === true) {
149
153
  return { kind: 'failed', error: opts.signal.reason ?? new Error('mcpReconnect: aborted before the verb was called') };
150
154
  }
151
- const raw = await client.sessions.mcpReconnect(sessionId, { server }, opts?.signal ? { signal: opts.signal } : undefined);
155
+ const raw = await client.sessions.mcpReconnect(sessionId, server, opts?.signal ? { signal: opts.signal } : undefined);
152
156
  if (isUnsettledBody(raw))
153
157
  return unsettledVerdict(raw);
154
158
  const view = projectMcpReconnectResult(raw);
@@ -163,15 +167,21 @@ export async function reconnectMcpServer(client, sessionId, server, opts) {
163
167
  }
164
168
  }
165
169
  export function projectMcpReconnectCapability(caps) {
166
- if (!isRecord(caps))
170
+ try {
171
+ if (!isRecord(caps))
172
+ return undefined;
173
+ const v = ownDataField(caps, 'mcpReconnect');
174
+ if (v === undefined)
175
+ return 'not_reported';
176
+ if (v === true)
177
+ return 'available';
178
+ if (v === false)
179
+ return 'unavailable';
180
+ return undefined;
181
+ }
182
+ catch {
167
183
  return undefined;
168
- if (!Object.hasOwn(caps, 'mcpReconnect') || caps.mcpReconnect === undefined)
169
- return 'not_reported';
170
- if (caps.mcpReconnect === true)
171
- return 'available';
172
- if (caps.mcpReconnect === false)
173
- return 'unavailable';
174
- return undefined;
184
+ }
175
185
  }
176
186
  export function mcpReconnectOutcomeDetail(view) {
177
187
  const name = capForDisplay(view.server, RECONNECT_WORD_MAX);
@@ -15,5 +15,4 @@ export declare function noteEngineCapsForMemoryCompliance(baseUrl: string, caps:
15
15
  export declare function observedMemoryCompliance(baseUrl?: string | undefined): MemoryComplianceReading;
16
16
  export declare function memoryComplianceVerbsAvailable(reading: MemoryComplianceReading): 'yes' | 'no' | 'unknown';
17
17
  export declare function memoryComplianceDoctorDetail(reading: MemoryComplianceReading): string;
18
- export declare function forgetMemoryComplianceReading(baseUrl: string | undefined): void;
19
18
  export declare function __resetMemoryComplianceReadingsForTests(): void;
@@ -1,18 +1,22 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
+ import { ownDataField } from './ownKey.js';
3
4
  export const MEMORY_ENGINE_REQUIRED_CODE = 'capability.memory_engine_required';
4
5
  export function projectMemoryComplianceCapability(caps) {
5
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
6
- return undefined;
7
- const c = caps;
8
- if (!Object.hasOwn(c, 'memoryCompliance'))
9
- return { kind: 'not_reported' };
10
- const v = c.memoryCompliance;
11
- if (v === undefined)
12
- return { kind: 'not_reported' };
13
- if (typeof v !== 'boolean')
6
+ try {
7
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
8
+ return undefined;
9
+ const c = caps;
10
+ const v = ownDataField(c, 'memoryCompliance');
11
+ if (v === undefined)
12
+ return { kind: 'not_reported' };
13
+ if (typeof v !== 'boolean')
14
+ return undefined;
15
+ return v ? { kind: 'present' } : { kind: 'absent' };
16
+ }
17
+ catch {
14
18
  return undefined;
15
- return v ? { kind: 'present' } : { kind: 'absent' };
19
+ }
16
20
  }
17
21
  const reader = createEngineCapReader({
18
22
  name: 'memoryCompliance',
@@ -44,9 +48,6 @@ export function memoryComplianceDoctorDetail(reading) {
44
48
  return 'memory compliance face on — the entry-provenance and erasure endpoints are mounted and the operator roster is non-empty on this engine; this says the door opens, not that any one call succeeds (a damaged control-plane ledger is a runtime fact and arrives as a typed 500)';
45
49
  }
46
50
  }
47
- export function forgetMemoryComplianceReading(baseUrl) {
48
- reader.forget(baseUrl);
49
- }
50
51
  export function __resetMemoryComplianceReadingsForTests() {
51
52
  reader.__resetForTests();
52
53
  }
@@ -14,5 +14,4 @@ export declare function noteEngineCapsForMemoryOrigin(baseUrl: string, caps: unk
14
14
  export declare function observedMemoryOrigin(baseUrl?: string | undefined): MemoryOriginReading;
15
15
  export declare function memoryOriginVerbsAvailable(reading: MemoryOriginReading): 'yes' | 'no' | 'unknown';
16
16
  export declare function memoryOriginDoctorDetail(reading: MemoryOriginReading): string;
17
- export declare function forgetMemoryOriginReading(baseUrl: string | undefined): void;
18
17
  export declare function __resetMemoryOriginReadingsForTests(): void;
@@ -1,18 +1,22 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader } from './engineCapReader.js';
3
+ import { ownDataField } from './ownKey.js';
3
4
  import { MEMORY_ENGINE_REQUIRED_CODE } from './memoryComplianceCapability.js';
4
5
  export function projectMemoryOriginCapability(caps) {
5
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
6
- return undefined;
7
- const c = caps;
8
- if (!Object.hasOwn(c, 'memoryOrigin'))
9
- return { kind: 'not_reported' };
10
- const v = c.memoryOrigin;
11
- if (v === undefined)
12
- return { kind: 'not_reported' };
13
- if (typeof v !== 'boolean')
6
+ try {
7
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
8
+ return undefined;
9
+ const c = caps;
10
+ const v = ownDataField(c, 'memoryOrigin');
11
+ if (v === undefined)
12
+ return { kind: 'not_reported' };
13
+ if (typeof v !== 'boolean')
14
+ return undefined;
15
+ return v ? { kind: 'present' } : { kind: 'absent' };
16
+ }
17
+ catch {
14
18
  return undefined;
15
- return v ? { kind: 'present' } : { kind: 'absent' };
19
+ }
16
20
  }
17
21
  const reader = createEngineCapReader({
18
22
  name: 'memoryOrigin',
@@ -44,9 +48,6 @@ export function memoryOriginDoctorDetail(reading) {
44
48
  return 'external-origin face on — the origin listing and clearance endpoints are mounted and the operator roster is non-empty on this engine; this says the door opens, not that any one call succeeds, and it says nothing about the listing being complete (the engine has no scope-enumeration read face, so an answer covers only the scopes the caller named and an empty one must never be read as a clean store)';
45
49
  }
46
50
  }
47
- export function forgetMemoryOriginReading(baseUrl) {
48
- reader.forget(baseUrl);
49
- }
50
51
  export function __resetMemoryOriginReadingsForTests() {
51
52
  reader.__resetForTests();
52
53
  }
@@ -21,7 +21,7 @@ export interface MemoryFacade {
21
21
  }
22
22
  export declare const MEMORY_VERB_REFUSAL_CAUSES: readonly ["face_absent", "client_too_old", "unreadable_request", "store_absent", "operator_only", "operators_unconfigured", "unauthorized", "service_token_required", "id_invalid", "request_id_required", "body_shape", "query_invalid", "selector_invalid", "evidence_unavailable", "selector_mismatch", "census_incomplete", "clear_unattributed", "clear_invalid", "clear_not_marked", "clear_challenged", "clear_conflict", "clear_pending"];
23
23
  export type MemoryVerbRefusalCause = (typeof MEMORY_VERB_REFUSAL_CAUSES)[number];
24
- export declare const MEMORY_VERB_UNKNOWN_WHYS: readonly ["no_verdict", "server_fault", "control_plane_corrupt", "clear_unknown", "clear_failed", "result_unreadable", "unsupported_version", "identity_mismatch", "unclassified"];
24
+ export declare const MEMORY_VERB_UNKNOWN_WHYS: readonly ["no_verdict", "server_fault", "control_plane_corrupt", "clear_unknown", "clear_failed", "result_unreadable", "unsupported_version", "identity_mismatch", "store_form_refused", "unclassified"];
25
25
  export type MemoryVerbUnknownWhy = (typeof MEMORY_VERB_UNKNOWN_WHYS)[number];
26
26
  export type MemoryVerbRefused = {
27
27
  status: 'refused';
@@ -35,6 +35,7 @@ export const MEMORY_VERB_UNKNOWN_WHYS = Object.freeze([
35
35
  'result_unreadable',
36
36
  'unsupported_version',
37
37
  'identity_mismatch',
38
+ 'store_form_refused',
38
39
  'unclassified',
39
40
  ]);
40
41
  function refusedBy(cause, message) {
@@ -90,6 +91,9 @@ export function classifyMemoryFailure(e) {
90
91
  return unknownBy('clear_unknown', message);
91
92
  case 'memory.origin_clear_failed':
92
93
  return unknownBy('clear_failed', message);
94
+ case 'memory.target_outside_store':
95
+ case 'memory.scope_home_not_directory':
96
+ return unknownBy('store_form_refused', message);
93
97
  case 'internal.memory_control_plane_corrupt':
94
98
  return unknownBy('control_plane_corrupt', message);
95
99
  default:
@@ -0,0 +1,14 @@
1
+ export type FrozenJsonValue = string | number | boolean | null | readonly FrozenJsonValue[] | {
2
+ readonly [k: string]: FrozenJsonValue;
3
+ };
4
+ export declare function frozenJsonCopyOf(v: unknown): FrozenJsonValue | undefined;
5
+ export declare function liveModelRowCopy(row: unknown): FrozenJsonRow | undefined;
6
+ export type FrozenJsonRow = {
7
+ readonly [k: string]: FrozenJsonValue;
8
+ } & {
9
+ readonly name: string;
10
+ };
11
+ export declare function liveDefaultModelCopy(v: unknown): {
12
+ readonly id: string;
13
+ readonly name?: string;
14
+ } | undefined;
@@ -0,0 +1,71 @@
1
+ const MAX_DEPTH = 16;
2
+ class Unreadable extends Error {
3
+ }
4
+ function frozenJsonCopy(v, depth) {
5
+ if (depth > MAX_DEPTH)
6
+ throw new Unreadable();
7
+ if (v === null || typeof v === 'string' || typeof v === 'boolean')
8
+ return v;
9
+ if (typeof v === 'number') {
10
+ if (!Number.isFinite(v))
11
+ throw new Unreadable();
12
+ return v;
13
+ }
14
+ if (typeof v !== 'object')
15
+ throw new Unreadable();
16
+ if (Array.isArray(v)) {
17
+ const n = Object.getOwnPropertyDescriptor(v, 'length')?.value;
18
+ if (typeof n !== 'number' || !Number.isSafeInteger(n) || n < 0)
19
+ throw new Unreadable();
20
+ const out = [];
21
+ for (let i = 0; i < n; i += 1) {
22
+ const d = Object.getOwnPropertyDescriptor(v, String(i));
23
+ if (d === undefined || !('value' in d))
24
+ throw new Unreadable();
25
+ out.push(frozenJsonCopy(d.value, depth + 1));
26
+ }
27
+ return Object.freeze(out);
28
+ }
29
+ const out = {};
30
+ for (const k of Object.keys(v)) {
31
+ const d = Object.getOwnPropertyDescriptor(v, k);
32
+ if (d === undefined || !('value' in d))
33
+ throw new Unreadable();
34
+ if (d.value === undefined)
35
+ continue;
36
+ Object.defineProperty(out, k, { value: frozenJsonCopy(d.value, depth + 1), enumerable: true, writable: true, configurable: true });
37
+ }
38
+ return Object.freeze(out);
39
+ }
40
+ export function frozenJsonCopyOf(v) {
41
+ try {
42
+ return frozenJsonCopy(v, 0);
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ }
48
+ export function liveModelRowCopy(row) {
49
+ if (row === null || typeof row !== 'object' || Array.isArray(row))
50
+ return undefined;
51
+ const copy = frozenJsonCopyOf(row);
52
+ if (!isFrozenJsonObject(copy))
53
+ return undefined;
54
+ const name = copy.name;
55
+ return typeof name === 'string' && name.length > 0 ? copy : undefined;
56
+ }
57
+ const isFrozenJsonObject = (v) => v !== undefined && v !== null && typeof v === 'object' && !Array.isArray(v);
58
+ export function liveDefaultModelCopy(v) {
59
+ if (v === null || typeof v !== 'object' || Array.isArray(v))
60
+ return undefined;
61
+ const c = frozenJsonCopyOf(v);
62
+ if (!isFrozenJsonObject(c))
63
+ return undefined;
64
+ const id = c.id;
65
+ const name = c.name;
66
+ if (typeof id !== 'string' || id.length === 0)
67
+ return undefined;
68
+ if (Object.hasOwn(c, 'name') && (typeof name !== 'string' || name.length === 0))
69
+ return undefined;
70
+ return c;
71
+ }
@@ -26,6 +26,7 @@ export interface DeleteWarningsInput {
26
26
  id: string;
27
27
  doc: {
28
28
  atModelAllowlist?: unknown;
29
+ atMention?: unknown;
29
30
  tierGroups?: unknown;
30
31
  } | null;
31
32
  tierGroups: TierGroupsView | null;
@@ -1,3 +1,5 @@
1
+ import { SETTINGS_NARROW_AT_MENTION } from '../generated/settingsSchemaFns.js';
2
+ import { modelsPolicyOf } from './modelsPolicy.js';
1
3
  import { inferFamily } from './providerPresets.js';
2
4
  function isPlainObject(v) {
3
5
  return typeof v === 'object' && v !== null && !Array.isArray(v);
@@ -13,15 +15,16 @@ export function resolveEntryVision(entry) {
13
15
  export function computeDeleteWarnings(input) {
14
16
  const { id, doc, tierGroups, survivingIds } = input;
15
17
  const out = [];
16
- const allow = doc?.atModelAllowlist;
17
- if (Array.isArray(allow)) {
18
- const declared = allow.filter((x) => typeof x === 'string');
19
- const effectiveBefore = declared.filter(n => n === id || survivingIds.includes(n));
20
- const effectiveAfter = declared.filter(n => n !== id && survivingIds.includes(n));
21
- if (effectiveBefore.length > 0 && effectiveAfter.length === 0) {
18
+ const am = modelsPolicyOf(doc).atMention;
19
+ if (am?.kind === 'read' && am.value.mode === 'only') {
20
+ const before = SETTINGS_NARROW_AT_MENTION(am.value, new Set([id, ...survivingIds]));
21
+ const after = SETTINGS_NARROW_AT_MENTION(am.value, new Set(survivingIds.filter((n) => n !== id)));
22
+ if (before.mode === 'only' && after.mode === 'none') {
22
23
  out.push({
23
24
  kind: 'allowlist-empties',
24
- consequence: 'it is the last usable model on your @-mention allowlist — deleting it empties the list, which means EVERY enabled model becomes @-mentionable',
25
+ consequence: am.from === 'atModelAllowlist'
26
+ ? 'it is the last usable model on your @-mention allowlist — deleting it empties the list, which means EVERY enabled model becomes @-mentionable'
27
+ : 'it is the last usable model on your @-mention allowlist — deleting it leaves no model that can be @-mentioned',
25
28
  });
26
29
  }
27
30
  }
@@ -47,15 +50,33 @@ export function computeDeleteWarnings(input) {
47
50
  export function computeDeleteBlockers(input) {
48
51
  const { id, doc, rosters } = input;
49
52
  const out = [];
50
- if (doc && typeof doc.default === 'string' && doc.default === id) {
53
+ const policy = modelsPolicyOf(doc);
54
+ if (policy.unreadable) {
55
+ out.push({
56
+ kind: 'unreadable',
57
+ where: 'models.json (the document could not be read)',
58
+ fix: 'fix or re-save models.json so it can be read, then delete this model',
59
+ });
60
+ }
61
+ if (policy.defaultUnreadable) {
62
+ out.push({
63
+ kind: 'unreadable',
64
+ where: 'models.json `default` (the default model could not be read)',
65
+ fix: 'fix or re-save models.json so its default model can be read, then delete this model',
66
+ });
67
+ }
68
+ const dm = policy.defaultModel;
69
+ if (dm !== undefined && dm.name === id) {
51
70
  out.push({
52
71
  kind: 'default',
53
- where: 'models.json `default`',
72
+ where: dm.from === 'default' ? 'models.json `default`' : 'models.json roles.default',
54
73
  fix: 'point another model at the default first (Model Hub: select it and press u), then delete this one',
55
74
  });
56
75
  }
57
76
  if (doc && isPlainObject(doc.roles)) {
58
77
  for (const [role, target] of Object.entries(doc.roles)) {
78
+ if (role === 'default' && dm?.from === 'roles.default')
79
+ continue;
59
80
  if (!isPlainObject(target) || typeof target.model !== 'string')
60
81
  continue;
61
82
  if (target.model !== id)
@@ -0,0 +1,21 @@
1
+ import { type SettingsAtMention } from '../generated/settingsSchemaFns.js';
2
+ export interface CanonicalDefaultModel {
3
+ readonly name: string;
4
+ readonly from: 'default' | 'roles.default';
5
+ }
6
+ export type CanonicalAtMention = {
7
+ readonly kind: 'read';
8
+ readonly value: SettingsAtMention;
9
+ readonly from: 'atMention' | 'atModelAllowlist';
10
+ readonly unreadableEntries: number;
11
+ } | {
12
+ readonly kind: 'unreadable';
13
+ readonly from: 'atMention' | 'atModelAllowlist';
14
+ };
15
+ export interface CanonicalModelsPolicy {
16
+ readonly defaultModel?: CanonicalDefaultModel;
17
+ readonly defaultUnreadable?: true;
18
+ readonly atMention?: CanonicalAtMention;
19
+ readonly unreadable?: true;
20
+ }
21
+ export declare function modelsPolicyOf(doc: unknown): CanonicalModelsPolicy;
@@ -0,0 +1,90 @@
1
+ import { SETTINGS_AT_MENTION_MODES } from '../generated/settingsSchemaFns.js';
2
+ function ownData(o, key) {
3
+ try {
4
+ const d = Object.getOwnPropertyDescriptor(o, key);
5
+ return d !== undefined && 'value' in d ? d.value : undefined;
6
+ }
7
+ catch {
8
+ return undefined;
9
+ }
10
+ }
11
+ const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
12
+ function atMentionOf(v) {
13
+ try {
14
+ if (!isRecord(v))
15
+ return undefined;
16
+ const mode = ownData(v, 'mode');
17
+ if (typeof mode !== 'string' || !SETTINGS_AT_MENTION_MODES.includes(mode))
18
+ return undefined;
19
+ if (mode !== 'only')
20
+ return { mode: mode };
21
+ const list = ownData(v, 'models');
22
+ if (!Array.isArray(list) || list.length === 0)
23
+ return undefined;
24
+ const out = [];
25
+ for (let i = 0; i < list.length; i += 1) {
26
+ const d = Object.getOwnPropertyDescriptor(list, i);
27
+ if (d === undefined || !('value' in d) || typeof d.value !== 'string' || d.value.length === 0)
28
+ return undefined;
29
+ out.push(d.value);
30
+ }
31
+ return { mode: 'only', models: out };
32
+ }
33
+ catch {
34
+ return undefined;
35
+ }
36
+ }
37
+ function atModelAllowlistOf(v) {
38
+ if (!Array.isArray(v))
39
+ return { kind: 'unreadable', from: 'atModelAllowlist' };
40
+ const names = [];
41
+ let bad = 0;
42
+ for (let i = 0; i < v.length; i += 1) {
43
+ const d = Object.getOwnPropertyDescriptor(v, i);
44
+ const x = d !== undefined && 'value' in d ? d.value : undefined;
45
+ if (typeof x === 'string' && x.length > 0)
46
+ names.push(x);
47
+ else
48
+ bad += 1;
49
+ }
50
+ const value = names.length > 0 ? { mode: 'only', models: names } : { mode: 'all' };
51
+ return { kind: 'read', value, from: 'atModelAllowlist', unreadableEntries: bad };
52
+ }
53
+ export function modelsPolicyOf(doc) {
54
+ try {
55
+ if (!isRecord(doc))
56
+ return {};
57
+ let defaultModel;
58
+ let defaultUnreadable = false;
59
+ if (Object.hasOwn(doc, 'default')) {
60
+ const d = ownData(doc, 'default');
61
+ if (typeof d === 'string' && d.length > 0)
62
+ defaultModel = { name: d, from: 'default' };
63
+ else
64
+ defaultUnreadable = true;
65
+ }
66
+ if (defaultModel === undefined && !defaultUnreadable) {
67
+ const roles = ownData(doc, 'roles');
68
+ const rd = isRecord(roles) ? ownData(roles, 'default') : undefined;
69
+ const model = isRecord(rd) ? ownData(rd, 'model') : undefined;
70
+ if (typeof model === 'string' && model.length > 0)
71
+ defaultModel = { name: model, from: 'roles.default' };
72
+ }
73
+ let atMention;
74
+ if (Object.hasOwn(doc, 'atMention')) {
75
+ const am = atMentionOf(ownData(doc, 'atMention'));
76
+ atMention = am === undefined ? { kind: 'unreadable', from: 'atMention' } : { kind: 'read', value: am, from: 'atMention', unreadableEntries: 0 };
77
+ }
78
+ else if (Object.hasOwn(doc, 'atModelAllowlist')) {
79
+ atMention = atModelAllowlistOf(ownData(doc, 'atModelAllowlist'));
80
+ }
81
+ return {
82
+ ...(defaultModel !== undefined ? { defaultModel } : {}),
83
+ ...(defaultUnreadable ? { defaultUnreadable: true } : {}),
84
+ ...(atMention !== undefined ? { atMention } : {}),
85
+ };
86
+ }
87
+ catch {
88
+ return { unreadable: true };
89
+ }
90
+ }