@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
@@ -0,0 +1,311 @@
1
+ export const USAGE_SENTENCES = Object.freeze({
2
+ analyticsUnavailable: 'Usage analytics aren’t available on this backend.',
3
+ analyticsUnread: 'Usage analytics couldn’t be read just now.',
4
+ modelsUnavailable: "Per-model usage breakdown isn't available on this backend.",
5
+ modelsUnread: 'Per-model usage breakdown couldn’t be read just now.',
6
+ });
7
+ const _sdkClientIsAnInjection = [true];
8
+ void _sdkClientIsAnInjection;
9
+ const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
10
+ const nonNeg = (v) => typeof v === 'number' && Number.isFinite(v) && v >= 0;
11
+ const nonEmpty = (v) => typeof v === 'string' && v.length > 0;
12
+ export function classifyUsageFailure(e) {
13
+ let code;
14
+ let status;
15
+ try {
16
+ const o = e;
17
+ const rawCode = o?.errorCode;
18
+ const rawStatus = o?.status;
19
+ code = typeof rawCode === 'string' ? rawCode : undefined;
20
+ status = typeof rawStatus === 'number' ? rawStatus : undefined;
21
+ }
22
+ catch {
23
+ return { kind: 'failed', error: e };
24
+ }
25
+ if (code !== undefined) {
26
+ if (code.startsWith('capability.'))
27
+ return { kind: 'unavailable', why: 'capability' };
28
+ if (code.startsWith('feature.'))
29
+ return { kind: 'unavailable', why: 'feature' };
30
+ if (code === 'not_found.route')
31
+ return { kind: 'unavailable', why: 'route' };
32
+ return { kind: 'failed', error: e };
33
+ }
34
+ if (status === 501)
35
+ return { kind: 'unavailable', why: 'capability' };
36
+ return { kind: 'failed', error: e };
37
+ }
38
+ function windowOf(o) {
39
+ const w = { truncated: o.truncated === true };
40
+ if (nonEmpty(o.from))
41
+ w.from = o.from;
42
+ if (nonEmpty(o.to))
43
+ w.to = o.to;
44
+ return w;
45
+ }
46
+ const precisionOf = (estimated) => (estimated === false ? 'exact' : 'estimated');
47
+ const TOTAL_FIELDS = ['tasks', 'tokensIn', 'tokensOut', 'cost'];
48
+ const TOTAL_WIRE_KEYS = Object.freeze({ tasks: 'tasks', tokensIn: 'tokensIn', tokensOut: 'tokensOut', cost: 'costUsd' });
49
+ function totalsOf(o) {
50
+ const t = { precision: precisionOf(o.estimated) };
51
+ for (const field of TOTAL_FIELDS) {
52
+ const v = o[TOTAL_WIRE_KEYS[field]];
53
+ if (nonNeg(v))
54
+ t[field] = v;
55
+ }
56
+ return t;
57
+ }
58
+ export function projectUsageSummary(body) {
59
+ try {
60
+ if (!isRecord(body))
61
+ return undefined;
62
+ return { ...windowOf(body), ...totalsOf(body) };
63
+ }
64
+ catch {
65
+ return undefined;
66
+ }
67
+ }
68
+ export function projectUsageSeries(body) {
69
+ try {
70
+ if (!isRecord(body))
71
+ return undefined;
72
+ const series = body.series;
73
+ if (!Array.isArray(series))
74
+ return undefined;
75
+ const points = [];
76
+ let unreadable = 0;
77
+ for (const raw of series) {
78
+ if (!isRecord(raw) || !nonEmpty(raw.t) || !nonNeg(raw.v)) {
79
+ unreadable++;
80
+ continue;
81
+ }
82
+ const p = { t: raw.t, v: raw.v };
83
+ if (typeof raw.estimated === 'boolean')
84
+ p.estimated = raw.estimated;
85
+ points.push(p);
86
+ }
87
+ return { ...windowOf(body), points, unreadable };
88
+ }
89
+ catch {
90
+ return undefined;
91
+ }
92
+ }
93
+ export function projectUsageBreakdown(body) {
94
+ try {
95
+ if (!isRecord(body))
96
+ return undefined;
97
+ const breakdown = body.breakdown;
98
+ if (!Array.isArray(breakdown))
99
+ return undefined;
100
+ const rows = [];
101
+ let unreadable = 0;
102
+ for (const raw of breakdown) {
103
+ if (!isRecord(raw) || !nonEmpty(raw.key)) {
104
+ unreadable++;
105
+ continue;
106
+ }
107
+ rows.push({ key: raw.key, ...totalsOf(raw) });
108
+ }
109
+ return { ...windowOf(body), rows, unreadable };
110
+ }
111
+ catch {
112
+ return undefined;
113
+ }
114
+ }
115
+ function windowBag(opts) {
116
+ const bag = {};
117
+ if (opts.from !== undefined)
118
+ bag.from = opts.from;
119
+ if (opts.to !== undefined)
120
+ bag.to = opts.to;
121
+ if (opts.principal !== undefined)
122
+ bag.principal = opts.principal;
123
+ if (opts.signal !== undefined)
124
+ bag.signal = opts.signal;
125
+ return bag;
126
+ }
127
+ async function readOne(call, project, what) {
128
+ try {
129
+ const pending = call();
130
+ if (pending === undefined)
131
+ return { kind: 'unavailable', why: 'route' };
132
+ const view = project(await pending);
133
+ if (view === undefined)
134
+ return { kind: 'failed', error: new Error(`usage ${what}: malformed body`) };
135
+ return { kind: 'ok', value: view };
136
+ }
137
+ catch (e) {
138
+ return classifyUsageFailure(e);
139
+ }
140
+ }
141
+ export function readUsageSummary(client, opts = {}) {
142
+ return readOne(() => (typeof client?.usage?.summary === 'function' ? client.usage.summary(windowBag(opts)) : undefined), projectUsageSummary, 'summary');
143
+ }
144
+ export function readUsageSeries(client, opts = {}) {
145
+ return readOne(() => {
146
+ if (typeof client?.usage?.series !== 'function')
147
+ return undefined;
148
+ const bag = windowBag(opts);
149
+ if (opts.metric !== undefined)
150
+ bag.metric = opts.metric;
151
+ if (opts.granularity !== undefined)
152
+ bag.granularity = opts.granularity;
153
+ return client.usage.series(bag);
154
+ }, projectUsageSeries, 'series');
155
+ }
156
+ export function readUsageBreakdown(client, opts = {}) {
157
+ return readOne(() => {
158
+ if (typeof client?.usage?.breakdown !== 'function')
159
+ return undefined;
160
+ const bag = windowBag(opts);
161
+ if (opts.dimension !== undefined)
162
+ bag.dimension = opts.dimension;
163
+ return client.usage.breakdown(bag);
164
+ }, projectUsageBreakdown, 'breakdown');
165
+ }
166
+ export function usageBoundPrefix(bound) {
167
+ return bound === 'lower' ? '≥' : bound === 'approximate' ? '≈' : '';
168
+ }
169
+ const DAY_MS = 86_400_000;
170
+ export const USAGE_HEATMAP_MAX_DAYS = 70;
171
+ export function usageWindowOfRange(range, now) {
172
+ if (range === 'all')
173
+ return { from: 0, to: now };
174
+ const days = range === '30d' ? 30 : 7;
175
+ return { from: now - days * DAY_MS, to: now };
176
+ }
177
+ function unavailableCauseOf(v) {
178
+ return v.kind === 'unavailable' ? 'no_backend_face' : 'read_failed';
179
+ }
180
+ function modelsUnavailable(cause) {
181
+ return { state: 'unavailable', cause, sentence: cause === 'no_backend_face' ? USAGE_SENTENCES.modelsUnavailable : USAGE_SENTENCES.modelsUnread };
182
+ }
183
+ const DAY_KEY_RE = /^(\d{4})-(\d{2})-(\d{2})(?:[T ]|$)/;
184
+ function dayKeyOf(iso) {
185
+ const m = DAY_KEY_RE.exec(iso);
186
+ if (m === null)
187
+ return undefined;
188
+ const y = Number(m[1]);
189
+ const mo = Number(m[2]);
190
+ const d = Number(m[3]);
191
+ const at = new Date(Date.UTC(y, mo - 1, d));
192
+ return at.getUTCFullYear() === y && at.getUTCMonth() === mo - 1 && at.getUTCDate() === d ? iso.slice(0, 10) : undefined;
193
+ }
194
+ const isWhole = (v) => v.unreadable === 0 && !v.truncated;
195
+ function hourOfDayUtc(iso) {
196
+ const d = new Date(iso);
197
+ return Number.isNaN(d.getTime()) ? undefined : d.getUTCHours();
198
+ }
199
+ function peakHourOf(points) {
200
+ if (points.length === 0)
201
+ return undefined;
202
+ const perHour = new Array(24).fill(0);
203
+ for (const p of points) {
204
+ const h = hourOfDayUtc(p.t);
205
+ if (h === undefined)
206
+ return undefined;
207
+ perHour[h] = (perHour[h] ?? 0) + p.v;
208
+ }
209
+ let peakHour = -1;
210
+ let peakValue = -1;
211
+ perHour.forEach((value, h) => {
212
+ if (value > peakValue) {
213
+ peakValue = value;
214
+ peakHour = h;
215
+ }
216
+ });
217
+ return peakHour >= 0 && peakValue > 0 ? peakHour : undefined;
218
+ }
219
+ function heatmapOf(window, dayValues) {
220
+ if (!Number.isFinite(window.from) || !Number.isFinite(window.to))
221
+ return null;
222
+ const windowDays = Math.max(1, Math.round((window.to - window.from) / DAY_MS) + 1);
223
+ const days = Math.min(windowDays, USAGE_HEATMAP_MAX_DAYS);
224
+ const cells = [];
225
+ for (let i = days - 1; i >= 0; i--) {
226
+ const at = new Date(window.to - i * DAY_MS);
227
+ if (Number.isNaN(at.getTime()))
228
+ return null;
229
+ const key = at.toISOString().slice(0, 10);
230
+ cells.push({ date: key, tasks: dayValues.get(key) ?? 0 });
231
+ }
232
+ return cells;
233
+ }
234
+ export function projectUsageAnalytics(inputs, window) {
235
+ const s = inputs.summary;
236
+ if (s.kind !== 'ok') {
237
+ const cause = unavailableCauseOf(s);
238
+ return {
239
+ state: 'unavailable',
240
+ cause,
241
+ sentence: cause === 'no_backend_face' ? USAGE_SENTENCES.analyticsUnavailable : USAGE_SENTENCES.analyticsUnread,
242
+ models: modelsUnavailable(cause),
243
+ };
244
+ }
245
+ const sv = s.value;
246
+ const readings = {
247
+ state: sv.precision === 'estimated' ? 'estimated' : 'available',
248
+ truncated: sv.truncated,
249
+ heatmap: null,
250
+ models: modelsUnavailable('read_failed'),
251
+ };
252
+ if (sv.tasks !== undefined)
253
+ readings.runs = sv.tasks;
254
+ const exact = sv.precision === 'exact';
255
+ if (sv.tokensIn !== undefined && sv.tokensOut !== undefined) {
256
+ readings.tokens = { value: sv.tokensIn + sv.tokensOut, bound: !exact ? 'approximate' : sv.truncated ? 'lower' : 'exact' };
257
+ }
258
+ if (sv.cost !== undefined)
259
+ readings.cost = { value: sv.cost, bound: exact && !sv.truncated ? 'exact' : 'lower' };
260
+ const day = inputs.daySeries;
261
+ if (day.kind === 'ok' && isWhole(day.value)) {
262
+ const dayValues = new Map();
263
+ let allKeysReadable = true;
264
+ for (const p of day.value.points) {
265
+ const key = dayKeyOf(p.t);
266
+ if (key === undefined)
267
+ allKeysReadable = false;
268
+ else
269
+ dayValues.set(key, (dayValues.get(key) ?? 0) + p.v);
270
+ }
271
+ if (allKeysReadable) {
272
+ readings.activeDays = [...dayValues.values()].filter((v) => v > 0).length;
273
+ readings.heatmap = heatmapOf(window, dayValues);
274
+ }
275
+ }
276
+ const hour = inputs.hourSeries;
277
+ if (hour.kind === 'ok' && isWhole(hour.value)) {
278
+ const peak = peakHourOf(hour.value.points);
279
+ if (peak !== undefined)
280
+ readings.peakHourUtc = peak;
281
+ }
282
+ const br = inputs.modelBreakdown;
283
+ if (br.kind === 'ok') {
284
+ readings.models = { state: 'available', rows: br.value.rows, unreadable: br.value.unreadable };
285
+ if (isWhole(br.value)) {
286
+ let favorite;
287
+ for (const row of br.value.rows) {
288
+ if (row.tasks === undefined)
289
+ continue;
290
+ if (favorite === undefined || row.tasks > (favorite.tasks ?? -1))
291
+ favorite = row;
292
+ }
293
+ if (favorite !== undefined)
294
+ readings.favoriteModel = favorite.key;
295
+ }
296
+ }
297
+ else {
298
+ readings.models = modelsUnavailable(unavailableCauseOf(br));
299
+ }
300
+ return readings;
301
+ }
302
+ export async function readUsageAnalytics(client, window, opts = {}) {
303
+ const base = { from: window.from, to: window.to, ...(opts.signal ? { signal: opts.signal } : {}) };
304
+ const [summary, daySeries, hourSeries, modelBreakdown] = await Promise.all([
305
+ readUsageSummary(client, base),
306
+ readUsageSeries(client, { ...base, metric: 'tasks', granularity: 'day' }),
307
+ readUsageSeries(client, { ...base, metric: 'tasks', granularity: 'hour' }),
308
+ readUsageBreakdown(client, { ...base, dimension: 'model' }),
309
+ ]);
310
+ return projectUsageAnalytics({ summary, daySeries, hourSeries, modelBreakdown }, window);
311
+ }
@@ -1,6 +1,13 @@
1
1
  import { type DescriptorView } from './humanTurnRead.js';
2
2
  export type UserAttachmentSource = 'at-mention' | 'compact-restore';
3
- export type UserAttachmentNotIncludedReason = 'too-large' | 'unreadable' | 'read-denied';
3
+ export type UserAttachmentNotIncludedReason = 'too-large' | 'unreadable' | 'read-denied' | 'approval-required' | 'server-not-connected' | 'resource-not-listed' | 'read-failed';
4
+ export type UserAttachmentMcpResourcePart = {
5
+ readonly kind: 'text';
6
+ readonly text: string;
7
+ } | {
8
+ readonly kind: 'binary';
9
+ readonly mimeType: string | null;
10
+ };
4
11
  export interface UserAttachmentNotebookCell {
5
12
  readonly cellType?: string;
6
13
  readonly source?: string;
@@ -54,6 +61,20 @@ export type UserAttachmentDescriptor = {
54
61
  readonly path: string;
55
62
  readonly sizeBytes: number | null;
56
63
  readonly reason: UserAttachmentNotIncludedReason;
64
+ } | {
65
+ readonly kind: 'not-included';
66
+ readonly target: 'mcp-resource';
67
+ readonly server: string;
68
+ readonly uri: string;
69
+ readonly name: string;
70
+ readonly reason: UserAttachmentNotIncludedReason;
71
+ } | {
72
+ readonly kind: 'mcp-resource';
73
+ readonly server: string;
74
+ readonly uri: string;
75
+ readonly name: string;
76
+ readonly parts: readonly UserAttachmentMcpResourcePart[];
77
+ readonly truncated: boolean;
57
78
  };
58
79
  export declare function showAttachmentName(s: string): string;
59
80
  export declare function mintEnvelopeOf(d: DescriptorView, imageDelivery: 'attached' | 'not-attached'): string;
@@ -162,16 +162,93 @@ const NOT_INCLUDED_REASON = Object.freeze({
162
162
  'too-large': "it is larger than the client's size limit for attaching files",
163
163
  unreadable: 'the client could not read it',
164
164
  'read-denied': "the user's permission rules do not allow reading it",
165
+ 'approval-required': "this deployment's rules require approval before it is read, so the client did not attach it without asking",
166
+ 'server-not-connected': 'the MCP server it comes from is not connected',
167
+ 'resource-not-listed': 'the MCP server does not list that resource',
168
+ 'read-failed': 'reading it from the MCP server failed',
165
169
  });
166
170
  function targetWhat(target) {
167
171
  return target === 'directory' ? 'a directory' : target === 'file' ? 'a file' : 'a file or directory';
168
172
  }
173
+ function mcpWhere(server, uri) {
174
+ return `Server: ${showAttachmentName(server)}. URI: ${showAttachmentName(uri)}`;
175
+ }
176
+ function mintMcpResource(d) {
177
+ const l1 = firstLine('at-mention', 'an MCP resource', d.name);
178
+ const texts = d.parts.flatMap((p) => (p.kind === 'text' ? [p.text] : []));
179
+ const binaries = d.parts.flatMap((p) => (p.kind === 'binary' ? [p.mimeType] : []));
180
+ const typed = [...new Set(binaries.filter((t) => t !== null))];
181
+ const binaryNote = binaries.length > 0
182
+ ? `${plural(binaries.length, 'binary part', 'binary parts')}${typed.length > 0 ? ` (${typed.map(showAttachmentName).join(', ')})` : ''} ${binaries.length === 1 ? 'is' : 'are'} not included.`
183
+ : null;
184
+ const truncNote = d.truncated ? 'The client shortened the text; the rest is not included.' : null;
185
+ if (texts.length === 0) {
186
+ return [`${l1}\n${mcpWhere(d.server, d.uri)} (no text parts). The client read it from that server; it has no text to include.`, binaryNote, truncNote].filter((s) => s !== null).join(' ');
187
+ }
188
+ let anyEscaped = false;
189
+ const body = texts
190
+ .join('\n')
191
+ .split('\n')
192
+ .map((line, i) => {
193
+ const shown = showBodyLine(line);
194
+ if (shown.escaped)
195
+ anyEscaped = true;
196
+ return `${i + 1}\t${shown.text}`;
197
+ });
198
+ const head = [
199
+ l1,
200
+ `${mcpWhere(d.server, d.uri)} (${plural(texts.length, 'text part', 'text parts')}). The client read it from that server and copied the text between the two fence lines below. ${dataNote('at-mention', "the resource's contents")}`,
201
+ ];
202
+ if (binaryNote !== null)
203
+ head.push(binaryNote);
204
+ if (truncNote !== null)
205
+ head.push(truncNote);
206
+ if (anyEscaped)
207
+ head.push(ESCAPE_NOTE);
208
+ return fenced(head, body);
209
+ }
169
210
  function mintNotIncluded(d) {
211
+ if (d.target === 'mcp-resource') {
212
+ return `${firstLine('at-mention', 'an MCP resource', d.name)}\n${mcpWhere(d.server, d.uri)}. It is not included in this message: ${NOT_INCLUDED_REASON[d.reason]}.`;
213
+ }
170
214
  const size = sizePart(d.sizeBytes);
171
215
  return (`${firstLine('at-mention', targetWhat(d.target), d.name)}\n` +
172
216
  `Full path: ${showAttachmentName(d.path)}${size !== null ? ` (${size})` : ''}. It is not included in this message: ${NOT_INCLUDED_REASON[d.reason]}.`);
173
217
  }
174
- export function mintEnvelopeOf(d, imageDelivery) {
218
+ const TAG_OPEN = '<attachment';
219
+ const TAG_CLOSE = '</attachment>';
220
+ function attributeValue(s) {
221
+ let out = '';
222
+ for (const c of s) {
223
+ switch (c) {
224
+ case '&':
225
+ out += '&amp;';
226
+ break;
227
+ case '"':
228
+ out += '&quot;';
229
+ break;
230
+ case '<':
231
+ out += '&lt;';
232
+ break;
233
+ case '>':
234
+ out += '&gt;';
235
+ break;
236
+ default:
237
+ out += c;
238
+ }
239
+ }
240
+ return out;
241
+ }
242
+ function pathOf(d) {
243
+ if (d.kind === 'mcp-resource' || (d.kind === 'not-included' && d.target === 'mcp-resource'))
244
+ return undefined;
245
+ return d.path;
246
+ }
247
+ function tagAttributes(d) {
248
+ const path = pathOf(d);
249
+ return path === undefined ? '' : ` path="${attributeValue(showAttachmentName(path))}"`;
250
+ }
251
+ function envelopeInner(d, imageDelivery) {
175
252
  switch (d.kind) {
176
253
  case 'text':
177
254
  return mintText(d);
@@ -185,10 +262,18 @@ export function mintEnvelopeOf(d, imageDelivery) {
185
262
  return mintDirectory(d);
186
263
  case 'not-included':
187
264
  return mintNotIncluded(d);
265
+ case 'mcp-resource':
266
+ return mintMcpResource(d);
188
267
  }
189
268
  }
190
- export function mintReferenceOf(d) {
269
+ export function mintEnvelopeOf(d, imageDelivery) {
270
+ return `${TAG_OPEN}${tagAttributes(d)}>\n${envelopeInner(d, imageDelivery)}\n${TAG_CLOSE}`;
271
+ }
272
+ function referenceSentence(d) {
191
273
  const name = showAttachmentName(d.name);
274
+ if (d.kind === 'mcp-resource' || (d.kind === 'not-included' && d.target === 'mcp-resource')) {
275
+ return `The user mentioned the MCP resource ${name} (${showAttachmentName(d.uri)} on the server ${showAttachmentName(d.server)}) in this message; its contents are not included here.`;
276
+ }
192
277
  const path = showAttachmentName(d.path);
193
278
  const what = d.kind === 'directory' ? 'directory' : d.kind === 'not-included' ? targetWhat(d.target).replace(/^an? /, '') : 'file';
194
279
  if (d.kind !== 'directory' && d.kind !== 'not-included' && d.source === 'compact-restore') {
@@ -196,6 +281,9 @@ export function mintReferenceOf(d) {
196
281
  }
197
282
  return `The user mentioned the ${what} ${name} (${path}) in this message; its contents are not included here.`;
198
283
  }
284
+ export function mintReferenceOf(d) {
285
+ return `${TAG_OPEN}${tagAttributes(d)} />\n${referenceSentence(d)}`;
286
+ }
199
287
  export function mintUserAttachmentEnvelope(descriptor) {
200
288
  const d = readDescriptor(descriptor, 'required');
201
289
  if (d === undefined)
@@ -14,5 +14,4 @@ export declare function noteEngineCapsForUserInvokedSkills(baseUrl: string, caps
14
14
  export declare function observedUserInvokedSkills(baseUrl?: string | undefined): UserInvokedSkillsReading;
15
15
  export declare function userInvokedSkillsAvailable(reading: UserInvokedSkillsReading): 'yes' | 'no' | 'unknown';
16
16
  export declare function userInvokedSkillsDoctorDetail(reading: UserInvokedSkillsReading): string;
17
- export declare function forgetUserInvokedSkillsReading(baseUrl: string | undefined): void;
18
17
  export declare function __resetUserInvokedSkillsReadingsForTests(): 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 projectUserInvokedSkillsCapability(caps) {
4
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
5
- return undefined;
6
- if (!Object.hasOwn(caps, 'userInvokedSkills'))
7
- return { kind: 'not_reported' };
8
- const v = caps.userInvokedSkills;
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, 'userInvokedSkills');
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: 'userInvokedSkills',
@@ -42,9 +46,6 @@ export function userInvokedSkillsDoctorDetail(reading) {
42
46
  return 'user-invoked skills on — skills the user names on a request take effect when the run starts';
43
47
  }
44
48
  }
45
- export function forgetUserInvokedSkillsReading(baseUrl) {
46
- reader.forget(baseUrl);
47
- }
48
49
  export function __resetUserInvokedSkillsReadingsForTests() {
49
50
  reader.__resetForTests();
50
51
  }
@@ -18,5 +18,4 @@ export declare function noteEngineCapsForWebSearchBackend(baseUrl: string, caps:
18
18
  }): void;
19
19
  export declare function observedWebSearchBackend(baseUrl?: string | undefined): WebSearchBackendReading;
20
20
  export declare function webSearchBackendDoctorDetail(reading: WebSearchBackendReading): string;
21
- export declare function forgetWebSearchBackendReading(baseUrl: string | undefined): void;
22
21
  export declare function __resetWebSearchBackendReadingsForTests(): void;
@@ -1,25 +1,29 @@
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 const WEB_SEARCH_BACKEND_NONE = 'none';
5
6
  export function projectWebSearchBackendCapability(caps) {
6
- if (caps === null || typeof caps !== 'object')
7
- return undefined;
8
- if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
9
- return undefined;
10
- if (!Object.hasOwn(caps, 'webSearch'))
11
- return { kind: 'not_reported' };
12
- const ws = caps.webSearch;
13
- if (ws === undefined)
14
- return { kind: 'not_reported' };
15
- if (ws === null || typeof ws !== 'object' || Array.isArray(ws))
16
- return undefined;
17
- const backend = ws.backend;
18
- if (typeof backend !== 'string' || backend === '')
7
+ try {
8
+ if (caps === null || typeof caps !== 'object')
9
+ return undefined;
10
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
11
+ return undefined;
12
+ const ws = ownDataField(caps, 'webSearch');
13
+ if (ws === undefined)
14
+ return { kind: 'not_reported' };
15
+ if (ws === null || typeof ws !== 'object' || Array.isArray(ws))
16
+ return undefined;
17
+ const backend = ownDataField(ws, 'backend');
18
+ if (typeof backend !== 'string' || backend === '')
19
+ return undefined;
20
+ if (backend === WEB_SEARCH_BACKEND_NONE)
21
+ return { kind: 'none' };
22
+ return { kind: 'present', view: { backend } };
23
+ }
24
+ catch {
19
25
  return undefined;
20
- if (backend === WEB_SEARCH_BACKEND_NONE)
21
- return { kind: 'none' };
22
- return { kind: 'present', view: { backend } };
26
+ }
23
27
  }
24
28
  const reader = createEngineCapReader({
25
29
  name: 'webSearch.backend',
@@ -51,9 +55,6 @@ export function webSearchBackendDoctorDetail(reading) {
51
55
  '(per-request overrides are not echoed here)');
52
56
  }
53
57
  }
54
- export function forgetWebSearchBackendReading(baseUrl) {
55
- reader.forget(baseUrl);
56
- }
57
58
  export function __resetWebSearchBackendReadingsForTests() {
58
59
  reader.__resetForTests();
59
60
  }
@@ -1,3 +1,4 @@
1
+ import { SETTINGS_IS_HIERARCHICAL_URL } from './generated/settingsSchemaFns.js';
1
2
  import { hostEnv } from './hostEnv.js';
2
3
  export const WEBSEARCH_ENV = {
3
4
  provider: 'SEMA_WEBSEARCH_PROVIDER',
@@ -6,15 +7,6 @@ export const WEBSEARCH_ENV = {
6
7
  maxResults: 'SEMA_WEBSEARCH_MAX_RESULTS',
7
8
  };
8
9
  const isBlankText = (v) => v.trim() === '';
9
- function isHierarchicalUrl(raw) {
10
- try {
11
- const u = new URL(raw);
12
- return u.href.startsWith(u.protocol + '//');
13
- }
14
- catch {
15
- return false;
16
- }
17
- }
18
10
  function judgeProvider(raw) {
19
11
  const word = typeof raw === 'string' ? raw.trim().toLowerCase() : undefined;
20
12
  if (word === 'brave' || word === 'tavily' || word === 'searxng')
@@ -71,7 +63,7 @@ function judgeEndpoint(raw) {
71
63
  return { ok: false, issue: ENDPOINT_ISSUE };
72
64
  if (isBlankText(raw))
73
65
  return { ok: true, value: undefined };
74
- if (!isHierarchicalUrl(raw))
66
+ if (!SETTINGS_IS_HIERARCHICAL_URL(raw))
75
67
  return { ok: false, issue: ENDPOINT_ISSUE };
76
68
  const u = new URL(raw);
77
69
  return u.username !== '' || u.password !== ''
@@ -236,7 +228,7 @@ export function webSearchVerdictMessage(verdict, context = 'submit') {
236
228
  : `Web search is misconfigured: ${where} ${verdict.issue}. Requests will be refused until you ${fix}.`;
237
229
  }
238
230
  export function webSearchEndpointForDisplay(raw) {
239
- if (typeof raw !== 'string' || !isHierarchicalUrl(raw))
231
+ if (typeof raw !== 'string' || !SETTINGS_IS_HIERARCHICAL_URL(raw))
240
232
  return undefined;
241
233
  try {
242
234
  const u = new URL(raw);
@@ -28,6 +28,17 @@ export declare function drainingRetryDelayMs(err: unknown, attempt: number, opts
28
28
  ladder?: readonly number[];
29
29
  retryAfterCapMs?: number;
30
30
  }): number;
31
+ export declare function isInStreamDrainingEnd(frame: unknown): boolean;
32
+ export declare const STREAM_DRAINING_RECONNECT_MAX = 3;
33
+ export type StreamDrainingGiveUp = 'not_draining_end' | 'attempts_exhausted';
34
+ export type StreamDrainingDecision = {
35
+ readonly reconnectAfterMs: number;
36
+ } | {
37
+ readonly giveUp: StreamDrainingGiveUp;
38
+ };
39
+ export declare function streamDrainingDecision(frame: unknown, attempt: number, opts?: {
40
+ ladder?: readonly number[];
41
+ }): StreamDrainingDecision;
31
42
  export interface ScenarioDenyDetail {
32
43
  allowlist: string[];
33
44
  }