@sema-agent/client-core 0.100.0 → 0.102.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 (358) hide show
  1. package/CHANGELOG.md +452 -0
  2. package/README.md +172 -120
  3. package/dist/adapt/arms.js +51 -16
  4. package/dist/adapt/textStream.js +7 -4
  5. package/dist/adapt/toolCards.d.ts +2 -1
  6. package/dist/adapt/toolCards.js +28 -13
  7. package/dist/adapt.d.ts +1 -1
  8. package/dist/adapt.js +8 -2
  9. package/dist/adapter/activeRunSelfHeal.d.ts +24 -2
  10. package/dist/adapter/activeRunSelfHeal.js +108 -6
  11. package/dist/adapter/downstream/eventToSdkMessage.js +38 -79
  12. package/dist/adapter/downstream/terminalToSdkResult.d.ts +60 -1
  13. package/dist/adapter/downstream/terminalToSdkResult.js +209 -39
  14. package/dist/adapter/downstream/wiringManifestView.d.ts +1 -0
  15. package/dist/adapter/downstream/wiringManifestView.js +138 -0
  16. package/dist/adapter/runStream.d.ts +4 -4
  17. package/dist/adapter/runStream.js +158 -43
  18. package/dist/agentsWireCaps.d.ts +2 -7
  19. package/dist/agentsWireCaps.js +1 -2
  20. package/dist/approvalDecidedByCapability.js +2 -2
  21. package/dist/approvalFrameFamilies.d.ts +33 -0
  22. package/dist/approvalFrameFamilies.js +120 -0
  23. package/dist/approvalsStreamLiveCapability.js +2 -2
  24. package/dist/attachmentsWireCaps.js +41 -13
  25. package/dist/callerCwdCapability.js +2 -2
  26. package/dist/centerWiringCapability.js +2 -2
  27. package/dist/clockReading.d.ts +2 -0
  28. package/dist/clockReading.js +4 -0
  29. package/dist/cloudConfigWireCaps.d.ts +19 -5
  30. package/dist/cloudConfigWireCaps.js +193 -56
  31. package/dist/compensations.js +1 -1
  32. package/dist/coreValuePorts.d.ts +12 -2
  33. package/dist/coreValuePorts.js +9 -0
  34. package/dist/decideFailureNote.js +5 -3
  35. package/dist/decideReceipt.js +2 -2
  36. package/dist/deviceExecutorManagementCapability.js +2 -2
  37. package/dist/deviceFlowPolling.js +1 -1
  38. package/dist/disableSkillsWire.d.ts +1 -1
  39. package/dist/disableSkillsWire.js +4 -3
  40. package/dist/displayUntrusted.d.ts +9 -4
  41. package/dist/displayUntrusted.js +834 -104
  42. package/dist/engineCapReader.js +1 -1
  43. package/dist/engineConfigDrift.js +1 -1
  44. package/dist/engineErrorCodes.d.ts +14 -5
  45. package/dist/engineErrorCodes.js +27 -6
  46. package/dist/engineGenerationConvergence.d.ts +39 -0
  47. package/dist/engineGenerationConvergence.js +95 -0
  48. package/dist/engineGenerationPort.d.ts +61 -0
  49. package/dist/engineGenerationPort.js +144 -0
  50. package/dist/engineHealthFacts.d.ts +23 -0
  51. package/dist/engineHealthFacts.js +92 -0
  52. package/dist/engineIdentity.d.ts +4 -0
  53. package/dist/engineIdentity.js +11 -0
  54. package/dist/engineNoticeCodes.d.ts +2 -5
  55. package/dist/engineRowRef.js +4 -0
  56. package/dist/engineSessionMessages.js +2 -2
  57. package/dist/engineToolDirectory.js +2 -2
  58. package/dist/engineWireFor.d.ts +99 -0
  59. package/dist/engineWireFor.js +248 -6
  60. package/dist/engineWireTarget.d.ts +1 -0
  61. package/dist/engineWireTarget.js +8 -0
  62. package/dist/env/uiLanguage.js +1 -1
  63. package/dist/errorSupplementRoles.d.ts +3 -0
  64. package/dist/errorSupplementRoles.js +37 -0
  65. package/dist/executionLaneCapability.js +2 -2
  66. package/dist/fileHistoryCaptureCapability.js +3 -3
  67. package/dist/finalVerifyWire.d.ts +6 -3
  68. package/dist/finalVerifyWire.js +6 -23
  69. package/dist/flagInput.d.ts +4 -0
  70. package/dist/flagInput.js +24 -0
  71. package/dist/fleet/fleetLedger.js +5 -2
  72. package/dist/fleet/fleetProjection.d.ts +1 -0
  73. package/dist/fleet/fleetProjection.js +16 -3
  74. package/dist/gateVocabulary.js +3 -0
  75. package/dist/generated/engineFactTables.d.ts +7 -3
  76. package/dist/generated/engineFactTables.js +52 -0
  77. package/dist/generated/engineNoticeTables.js +12 -0
  78. package/dist/generated/settingsSchemaActiveTiers.d.ts +1 -0
  79. package/dist/generated/settingsSchemaActiveTiers.js +14 -0
  80. package/dist/generated/settingsSchemaCallerTextEcho.d.ts +1 -0
  81. package/dist/generated/settingsSchemaCallerTextEcho.js +8 -0
  82. package/dist/generated/settingsSchemaControlAndBidi.d.ts +1 -0
  83. package/dist/generated/settingsSchemaControlAndBidi.js +8 -0
  84. package/dist/generated/settingsSchemaDefaultModel.d.ts +11 -0
  85. package/dist/generated/settingsSchemaDefaultModel.js +25 -0
  86. package/dist/generated/settingsSchemaFns.d.ts +54 -0
  87. package/dist/generated/settingsSchemaFns.js +26 -1
  88. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
  89. package/dist/generated/settingsSchemaMcpRequestEntry.js +1 -7
  90. package/dist/generated/settingsSchemaSafetyMergeSpec.d.ts +1 -0
  91. package/dist/generated/settingsSchemaSafetyMergeSpec.js +95 -0
  92. package/dist/generated/settingsSchemaSettingsSources.d.ts +1 -0
  93. package/dist/generated/settingsSchemaSettingsSources.js +58 -0
  94. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  95. package/dist/generated/settingsSchemaTables.js +13 -0
  96. package/dist/generated/settingsSchemaUrlPattern.d.ts +1 -0
  97. package/dist/generated/settingsSchemaUrlPattern.js +183 -0
  98. package/dist/headlessPermissionModeWire.d.ts +18 -2
  99. package/dist/headlessPermissionModeWire.js +30 -19
  100. package/dist/hitl/allowRuleShadow.js +7 -5
  101. package/dist/hitl/approvalCardReading.d.ts +3 -0
  102. package/dist/hitl/approvalCardReading.js +17 -0
  103. package/dist/hitl/approvalCompleteParked.js +1 -1
  104. package/dist/hitl/approvalDelivery.d.ts +87 -0
  105. package/dist/hitl/approvalDelivery.js +193 -0
  106. package/dist/hitl/approvalResolution.d.ts +11 -0
  107. package/dist/hitl/approvalResolution.js +50 -11
  108. package/dist/hitl/askClassPair.d.ts +6 -0
  109. package/dist/hitl/askClassPair.js +30 -3
  110. package/dist/hitl/askParkAutoReopenBlock.d.ts +30 -0
  111. package/dist/hitl/askParkAutoReopenBlock.js +117 -0
  112. package/dist/hitl/askParkRowRouting.js +4 -1
  113. package/dist/hitl/attributionLadder.d.ts +42 -3
  114. package/dist/hitl/attributionLadder.js +79 -8
  115. package/dist/hitl/automaticAnswerVerdict.d.ts +6 -1
  116. package/dist/hitl/automaticAnswerVerdict.js +46 -11
  117. package/dist/hitl/crashConverged.js +2 -2
  118. package/dist/hitl/decisionConflict.d.ts +6 -2
  119. package/dist/hitl/decisionConflict.js +24 -9
  120. package/dist/hitl/decisionRefusal.d.ts +20 -10
  121. package/dist/hitl/decisionRefusal.js +99 -54
  122. package/dist/hitl/decisionSend.d.ts +3 -0
  123. package/dist/hitl/decisionSend.js +87 -103
  124. package/dist/hitl/frameRouter.d.ts +1 -0
  125. package/dist/hitl/frameRouter.js +9 -2
  126. package/dist/hitl/hitlBridge.d.ts +18 -6
  127. package/dist/hitl/hitlBridge.js +41 -37
  128. package/dist/hitl/livePendingAsk.js +4 -3
  129. package/dist/hitl/noAllowCause.js +1 -1
  130. package/dist/hitl/parkResolver.js +3 -2
  131. package/dist/hitl/persistedRulesWire.js +1 -0
  132. package/dist/hitl/planReviewWire.d.ts +4 -0
  133. package/dist/hitl/planReviewWire.js +59 -30
  134. package/dist/hitl/resumeRunningCard.d.ts +3 -2
  135. package/dist/hitl/resumeRunningCard.js +17 -11
  136. package/dist/hitl/sessionPolicyDeliverable.d.ts +5 -2
  137. package/dist/hitl/sessionPolicyDeliverable.js +62 -29
  138. package/dist/hitl/sessionPolicyWire.d.ts +13 -3
  139. package/dist/hitl/sessionPolicyWire.js +81 -16
  140. package/dist/hitl/standingRows.js +1 -1
  141. package/dist/hitl/toolApprovalWire.d.ts +9 -10
  142. package/dist/hitl/toolApprovalWire.js +72 -54
  143. package/dist/hookMatcherVerdict.d.ts +2 -0
  144. package/dist/hookMatcherVerdict.js +12 -0
  145. package/dist/hooksCompactTransition.d.ts +19 -0
  146. package/dist/hooksCompactTransition.js +41 -0
  147. package/dist/hooksWireCaps.d.ts +1 -1
  148. package/dist/hooksWireCaps.js +202 -203
  149. package/dist/host.d.ts +1 -14
  150. package/dist/host.js +0 -8
  151. package/dist/hostCallbackGuard.d.ts +1 -0
  152. package/dist/hostCallbackGuard.js +1 -1
  153. package/dist/hostSettingsSource.d.ts +172 -0
  154. package/dist/hostSettingsSource.js +675 -0
  155. package/dist/hostTurnSettings.d.ts +73 -17
  156. package/dist/hostTurnSettings.js +594 -97
  157. package/dist/httpHookPolicy.d.ts +37 -0
  158. package/dist/httpHookPolicy.js +176 -0
  159. package/dist/humanTurn.d.ts +2 -1
  160. package/dist/humanTurn.js +37 -7
  161. package/dist/humanTurnRead.js +4 -3
  162. package/dist/humanTurnSentences.d.ts +10 -0
  163. package/dist/humanTurnSentences.js +74 -0
  164. package/dist/i18n/messages.en.d.ts +222 -2
  165. package/dist/i18n/messages.en.js +225 -5
  166. package/dist/i18n/messages.zh.js +237 -5
  167. package/dist/i18n/translate.js +3 -3
  168. package/dist/index.d.ts +77 -15
  169. package/dist/index.js +50 -13
  170. package/dist/inheritEnvCapability.d.ts +3 -1
  171. package/dist/inheritEnvCapability.js +31 -17
  172. package/dist/inheritEnvWire.d.ts +2 -1
  173. package/dist/inheritEnvWire.js +11 -5
  174. package/dist/interactiveHalt.d.ts +3 -1
  175. package/dist/interactiveHalt.js +2 -0
  176. package/dist/interactiveInterrupt.d.ts +2 -0
  177. package/dist/interactiveInterrupt.js +15 -0
  178. package/dist/interactiveToolsWire.d.ts +4 -2
  179. package/dist/interactiveToolsWire.js +5 -5
  180. package/dist/jsonFaithful.d.ts +20 -0
  181. package/dist/jsonFaithful.js +152 -0
  182. package/dist/limitsWire.d.ts +7 -2
  183. package/dist/limitsWire.js +19 -13
  184. package/dist/liveInitToolFace.d.ts +6 -1
  185. package/dist/liveInitToolFace.js +5 -3
  186. package/dist/liveModelCatalog.d.ts +22 -0
  187. package/dist/liveModelCatalog.js +132 -18
  188. package/dist/mcpPanel.js +1 -1
  189. package/dist/mcpProbeCapability.js +2 -2
  190. package/dist/mcpStatusSupersetKeys.d.ts +24 -0
  191. package/dist/mcpStatusSupersetKeys.js +45 -0
  192. package/dist/mcpToolToggles.js +2 -1
  193. package/dist/mcpWireCaps.d.ts +39 -1
  194. package/dist/mcpWireCaps.js +254 -50
  195. package/dist/memoryComplianceCapability.js +2 -2
  196. package/dist/memoryOriginCapability.js +2 -2
  197. package/dist/model/catalogDefault.d.ts +24 -0
  198. package/dist/model/catalogDefault.js +4 -0
  199. package/dist/model/liveCatalogShape.js +5 -4
  200. package/dist/model/modelsPolicy.js +4 -3
  201. package/dist/model/onboardJudgement.d.ts +1 -0
  202. package/dist/model/onboardJudgement.js +1 -1
  203. package/dist/model/subagentModelWord.js +2 -2
  204. package/dist/modelCapabilityProbe.js +6 -6
  205. package/dist/modelIdentityResolvability.d.ts +10 -1
  206. package/dist/modelIdentityResolvability.js +62 -39
  207. package/dist/modsFace.d.ts +8 -0
  208. package/dist/modsFace.js +59 -0
  209. package/dist/modsKernelIdentity.d.ts +10 -0
  210. package/dist/modsKernelIdentity.js +103 -0
  211. package/dist/modsKernelTransit.d.ts +8 -0
  212. package/dist/modsKernelTransit.js +6 -0
  213. package/dist/notifications.d.ts +30 -12
  214. package/dist/notifications.js +241 -53
  215. package/dist/outputStyleSeatCapability.js +2 -2
  216. package/dist/ownKey.d.ts +12 -0
  217. package/dist/ownKey.js +179 -3
  218. package/dist/panelReduce.js +1 -1
  219. package/dist/peerFrames.d.ts +1 -1
  220. package/dist/peerFrames.js +6 -2
  221. package/dist/peerLaneCapability.js +2 -2
  222. package/dist/permissionModesCapability.js +4 -4
  223. package/dist/permissionRuleIssue.js +2 -0
  224. package/dist/permissionRulesWriteCapability.js +2 -2
  225. package/dist/permissionsAllowGrantCapability.js +2 -2
  226. package/dist/permissionsDeclaration.d.ts +43 -4
  227. package/dist/permissionsDeclaration.js +102 -35
  228. package/dist/pluginHooksWire.d.ts +20 -4
  229. package/dist/pluginHooksWire.js +92 -53
  230. package/dist/prepareRefusal.d.ts +3 -2
  231. package/dist/prepareRefusal.js +27 -9
  232. package/dist/printInitToolFace.js +2 -2
  233. package/dist/printModelStatus.js +1 -1
  234. package/dist/printToolResultFrame.js +1 -1
  235. package/dist/projectMemory.d.ts +32 -0
  236. package/dist/projectMemory.js +70 -0
  237. package/dist/promptBlockedCopy.d.ts +2 -1
  238. package/dist/promptBlockedCopy.js +2 -1
  239. package/dist/promptDelivery.d.ts +23 -3
  240. package/dist/promptDelivery.js +169 -30
  241. package/dist/providerRejection.d.ts +19 -1
  242. package/dist/providerRejection.js +75 -4
  243. package/dist/queuedDelivery.d.ts +48 -0
  244. package/dist/queuedDelivery.js +233 -0
  245. package/dist/reattachWindow.d.ts +94 -0
  246. package/dist/reattachWindow.js +127 -0
  247. package/dist/request/printNotification.d.ts +1 -1
  248. package/dist/request/printNotification.js +6 -2
  249. package/dist/request/submissionIdentity.d.ts +37 -0
  250. package/dist/request/submissionIdentity.js +65 -0
  251. package/dist/request/taskRequest.d.ts +33 -4
  252. package/dist/request/taskRequest.js +341 -156
  253. package/dist/resultFrameKeys.d.ts +1 -0
  254. package/dist/resultFrameKeys.js +4 -1
  255. package/dist/retryStatus.d.ts +8 -0
  256. package/dist/retryStatus.js +57 -9
  257. package/dist/rewindArchiveCapability.js +2 -2
  258. package/dist/rewindEngineAction.d.ts +2 -0
  259. package/dist/rewindEngineAction.js +23 -1
  260. package/dist/rowKind.d.ts +36 -0
  261. package/dist/rowKind.js +97 -0
  262. package/dist/ruleCompileVerdict.d.ts +18 -0
  263. package/dist/ruleCompileVerdict.js +67 -2
  264. package/dist/ruleReadings.d.ts +58 -0
  265. package/dist/ruleReadings.js +132 -0
  266. package/dist/ruleRefusalSentence.d.ts +4 -0
  267. package/dist/ruleRefusalSentence.js +9 -3
  268. package/dist/runCancelContext.d.ts +0 -1
  269. package/dist/runCancelContext.js +1 -2
  270. package/dist/runTerminal.d.ts +5 -0
  271. package/dist/runTerminal.js +52 -17
  272. package/dist/sandboxWire.d.ts +1 -1
  273. package/dist/sandboxWire.js +4 -6
  274. package/dist/scenarioRefusal.js +1 -1
  275. package/dist/scenarioSkills.d.ts +20 -0
  276. package/dist/scenarioSkills.js +72 -0
  277. package/dist/scenarioWire.d.ts +5 -2
  278. package/dist/scenarioWire.js +9 -9
  279. package/dist/sealedKeyCapability.js +2 -2
  280. package/dist/seam.d.ts +2 -0
  281. package/dist/seam.js +3 -3
  282. package/dist/seatContract.d.ts +68 -7
  283. package/dist/seatContract.js +84 -25
  284. package/dist/selfOrchestrationDenial.js +1 -1
  285. package/dist/sessionBackground.d.ts +165 -0
  286. package/dist/sessionBackground.js +781 -0
  287. package/dist/sessionBackgroundHandoff.d.ts +54 -0
  288. package/dist/sessionBackgroundHandoff.js +321 -0
  289. package/dist/sessionMap.js +4 -1
  290. package/dist/sessionPolicyCapability.js +2 -2
  291. package/dist/sessionRulesChildrenReadLive.d.ts +6 -0
  292. package/dist/sessionRulesChildrenReadLive.js +5 -0
  293. package/dist/sessionRulesNamespaceFormsCapability.d.ts +12 -0
  294. package/dist/sessionRulesNamespaceFormsCapability.js +29 -0
  295. package/dist/sessionSyncFileHistoryCapability.js +2 -2
  296. package/dist/settingsCredentialKeyPaths.js +55 -15
  297. package/dist/settingsHooksSalvage.d.ts +1 -0
  298. package/dist/settingsHooksSalvage.js +7 -1
  299. package/dist/settingsLayerAdmission.d.ts +4 -0
  300. package/dist/settingsLayerAdmission.js +16 -0
  301. package/dist/skillToolListsCapability.js +6 -5
  302. package/dist/skillsWireCaps.d.ts +14 -0
  303. package/dist/skillsWireCaps.js +47 -16
  304. package/dist/slashCommandGate.d.ts +24 -0
  305. package/dist/slashCommandGate.js +74 -0
  306. package/dist/slashCommandTable.d.ts +14 -0
  307. package/dist/slashCommandTable.js +99 -0
  308. package/dist/sqlEngineCapability.js +2 -2
  309. package/dist/steerPriorityCapability.js +2 -2
  310. package/dist/storePostureCapability.js +2 -2
  311. package/dist/subagent/agentStateDetail.js +1 -1
  312. package/dist/subagent/engineDelegatedPrompt.d.ts +9 -0
  313. package/dist/subagent/engineDelegatedPrompt.js +38 -7
  314. package/dist/subagent/engineRowStopGate.js +2 -2
  315. package/dist/subagent/engineSubagentResume.js +3 -3
  316. package/dist/subagent/engineTaskHandleWire.d.ts +1 -0
  317. package/dist/subagent/engineTaskHandleWire.js +10 -0
  318. package/dist/submitFailure.d.ts +8 -0
  319. package/dist/submitFailure.js +17 -0
  320. package/dist/supportFloor.d.ts +1 -0
  321. package/dist/supportFloor.js +7 -0
  322. package/dist/terminationIntent.d.ts +55 -0
  323. package/dist/terminationIntent.js +352 -0
  324. package/dist/thinkingLatch.d.ts +69 -0
  325. package/dist/thinkingLatch.js +255 -0
  326. package/dist/thinkingLatchWords.d.ts +7 -0
  327. package/dist/thinkingLatchWords.js +4 -0
  328. package/dist/toolHistoryMismatch.d.ts +8 -0
  329. package/dist/toolHistoryMismatch.js +37 -6
  330. package/dist/toolResult.d.ts +13 -3
  331. package/dist/toolResult.js +159 -32
  332. package/dist/toolResultContent.d.ts +13 -0
  333. package/dist/toolResultContent.js +82 -7
  334. package/dist/toolRoster.d.ts +18 -0
  335. package/dist/toolRoster.js +64 -0
  336. package/dist/turnFailurePresentation.js +27 -90
  337. package/dist/usageLimitAutoResume.d.ts +74 -0
  338. package/dist/usageLimitAutoResume.js +227 -0
  339. package/dist/userAttachmentEnvelope.js +1 -1
  340. package/dist/userAttachmentSeat.js +5 -5
  341. package/dist/userInvokedSkillsCapability.js +2 -2
  342. package/dist/webSearchBackendCapability.js +2 -2
  343. package/dist/wireErrorTriage.js +99 -50
  344. package/dist/wireFailureShape.d.ts +25 -1
  345. package/dist/wireFailureShape.js +92 -5
  346. package/dist/wireRefusalCopy.d.ts +24 -1
  347. package/dist/wireRefusalCopy.js +253 -32
  348. package/dist/wiringFleetDoctor.d.ts +3 -0
  349. package/dist/wiringFleetDoctor.js +21 -0
  350. package/dist/workflow.d.ts +2 -1
  351. package/dist/workflow.js +38 -1
  352. package/dist/workflowClient.d.ts +2 -7
  353. package/dist/workflowsJournalCapability.js +2 -2
  354. package/dist/writeProtectionCapability.js +2 -2
  355. package/docs/INTEGRATION-CLIENTS.md +907 -182
  356. package/package.json +14 -3
  357. package/dist/argvFlagValue.d.ts +0 -8
  358. package/dist/argvFlagValue.js +0 -37
@@ -11,7 +11,7 @@ function isMarker(v) {
11
11
  return core === RETIRED_MARKER || MARKER_RE.test(core);
12
12
  }
13
13
  const VIEW_SEPARATOR = '\ufeff';
14
- function pushEdit(edits, src, start, end, text) {
14
+ function pushEdit(edits, src, start, end, text, phases) {
15
15
  let a = start;
16
16
  let b = end;
17
17
  while (a < b && src[a] === VIEW_SEPARATOR)
@@ -22,7 +22,7 @@ function pushEdit(edits, src, start, end, text) {
22
22
  a = b = start;
23
23
  if (src.slice(a, b) === text)
24
24
  return;
25
- edits.push({ start: a, end: b, text });
25
+ edits.push(phases === undefined ? { start: a, end: b, text } : { start: a, end: b, text, phases });
26
26
  }
27
27
  const UNIT_NONE = 0;
28
28
  const UNIT_SEQUENCE = 1;
@@ -220,7 +220,7 @@ const isHostChar = (c) => (c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x5a) |
220
220
  const isIpv6Char = (c) => (c >= 0x30 && c <= 0x3a) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66) || c === 0x2e;
221
221
  const endsSchemelessHost = (c) => Number.isNaN(c) || c === 0x2f || c === 0x3f || c === 0x23 || c === 0x22 || c === 0x3c || c === 0x3e || c === 0x60 ||
222
222
  c === 0x7c || c === 0x5c || c === 0x5e || c === 0x7b || c === 0x7d || isRegexSpace(c);
223
- function schemelessHostEnd(text, from) {
223
+ function schemelessHostEnd(text, from, wide = false) {
224
224
  let k = from;
225
225
  if (text.charCodeAt(k) === 0x5b) {
226
226
  k++;
@@ -238,14 +238,25 @@ function schemelessHostEnd(text, from) {
238
238
  }
239
239
  if (text.charCodeAt(k) === 0x3a) {
240
240
  let d = k + 1;
241
- while (d < text.length && text.charCodeAt(d) >= 0x30 && text.charCodeAt(d) <= 0x39)
242
- d++;
243
- if (d > k + 1)
241
+ if (wide) {
242
+ while (d < text.length && isSchemelessPortChar(text.charCodeAt(d)))
243
+ d++;
244
244
  k = d;
245
+ }
246
+ else {
247
+ while (d < text.length && text.charCodeAt(d) >= 0x30 && text.charCodeAt(d) <= 0x39)
248
+ d++;
249
+ if (d > k + 1)
250
+ k = d;
251
+ }
245
252
  }
246
253
  const c = text.charCodeAt(k);
247
- return endsSchemelessHost(c) || c === 0x27 ? k : -1;
254
+ return endsSchemelessHost(c) || c === 0x27 || (wide && endsSchemelessHostInProse(c)) ? k : -1;
248
255
  }
256
+ const isSchemelessPortChar = (c) => (c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a) || c === 0x2e || c === 0x5f || c === 0x7e || c === 0x25 || c === 0x2d;
257
+ const endsSchemelessHostInProse = (c) => c === 0x29 || c === 0x2c || c === 0x3b || c === 0x21 || c === 0x5d;
258
+ const SCHEMELESS_USERINFO_WIDE_SPAN = 64 + 1 + 256;
259
+ const isUserinfoWideDelimiter = (ch) => ch === '?' || ch === '#' || ch === '@';
249
260
  const MAX_PORT = 65535;
250
261
  function authorityIsHostPort(text, from, to) {
251
262
  if (to <= from || schemelessHostEnd(text.slice(0, to), from) !== to)
@@ -282,32 +293,32 @@ function queryCandidates(src, base, query, edits, soft, byShape = false) {
282
293
  const eq = part.indexOf('=');
283
294
  if (eq === -1) {
284
295
  const at = pos;
285
- if (!slotIsWholeMarker(part, soft && ((i) => soft(at + i))) && (!byShape || queryPartCarriesCredential(null, part, relax)))
286
- pushEdit(edits, src, pos, pos + part.length, REDACTED_QUERY);
296
+ if (!slotIsWholeMarker(part, soft && ((i) => soft(at + i)))) {
297
+ const phases = byShape ? queryPartPhases(null, part, relax) : phaseRange(0, scanUpto);
298
+ if (phases !== 0)
299
+ pushEdit(edits, src, pos, pos + part.length, REDACTED_QUERY, phasesOrAll(phases));
300
+ }
287
301
  }
288
302
  else {
289
303
  const value = part.slice(eq + 1);
290
304
  const at = pos + eq + 1;
291
- if (value.length > 0 && !slotIsWholeMarker(value, soft && ((i) => soft(at + i))) && (!byShape || queryPartCarriesCredential(part.slice(0, eq), value, relax))) {
292
- pushEdit(edits, src, pos + eq + 1, pos + part.length, REDACTED_QUERY);
305
+ if (value.length > 0 && !slotIsWholeMarker(value, soft && ((i) => soft(at + i)))) {
306
+ const phases = byShape ? queryPartPhases(part.slice(0, eq), value, relax) : phaseRange(0, scanUpto);
307
+ if (phases !== 0)
308
+ pushEdit(edits, src, pos + eq + 1, pos + part.length, REDACTED_QUERY, phasesOrAll(phases));
293
309
  }
294
310
  }
295
311
  }
296
312
  pos += part.length + 1;
297
313
  }
298
314
  }
299
- function pathCandidates(src, base, path, opaqueSegments, edits, soft) {
315
+ function pathCandidates(src, base, path, opaqueSegments, edits, soft, whole = false) {
300
316
  let pos = base;
301
317
  for (const segment of path.split('/')) {
302
318
  const semi = segment.indexOf(';');
303
319
  const head = semi === -1 ? segment : segment.slice(0, semi);
304
320
  if (opaqueSegments) {
305
- let a = 0;
306
- let b = head.length;
307
- while (a < b && !isKeyWordChar(head.charCodeAt(a)) && !(head.charCodeAt(a) === 0x25 && hasNonAsciiPercentEscape(head.slice(a, a + 3))))
308
- a++;
309
- while (b > a && !isKeyWordChar(head.charCodeAt(b - 1)))
310
- b--;
321
+ const [a, b] = markerAtomicCut(head, ...segmentWordCut(head));
311
322
  if (isKnownSecretSegment(head)) {
312
323
  if (b > a)
313
324
  pushEdit(edits, src, pos + a, pos + b, REDACTED_SECRET);
@@ -317,6 +328,10 @@ function pathCandidates(src, base, path, opaqueSegments, edits, soft) {
317
328
  if (glued > 0)
318
329
  pushEdit(edits, src, pos + a + glued, pos + b, REDACTED_SECRET);
319
330
  }
331
+ if (whole && b > a) {
332
+ const at = pos;
333
+ emitRow('path-slot', (phases) => pathSlotEdits(src, at, head, a, b, phases, edits, soft));
334
+ }
320
335
  }
321
336
  if (semi !== -1) {
322
337
  let ppos = pos + semi + 1;
@@ -334,9 +349,76 @@ function pathCandidates(src, base, path, opaqueSegments, edits, soft) {
334
349
  pos += segment.length + 1;
335
350
  }
336
351
  }
337
- function addressCandidates(src, from, end, opaqueSegments, edits, regions, soft, byShape = false, whole = false, hostRegion = whole) {
352
+ function segmentWordCut(head) {
353
+ let a = 0;
354
+ let b = head.length;
355
+ while (a < b && !isKeyWordChar(head.charCodeAt(a)) && !(head.charCodeAt(a) === 0x25 && hasNonAsciiPercentEscape(head.slice(a, a + 3))))
356
+ a++;
357
+ while (b > a && !isKeyWordChar(head.charCodeAt(b - 1)))
358
+ b--;
359
+ return [a, b];
360
+ }
361
+ function markerAtomicCut(head, a, b) {
362
+ if (!head.includes(REDACTION_MARKER_PREFIX))
363
+ return [a, b];
364
+ let s = a;
365
+ let e = b;
366
+ const re = new RegExp(MARKER_ANYWHERE.source, MARKER_ANYWHERE.flags);
367
+ for (let m = re.exec(head); m !== null; m = re.exec(head)) {
368
+ const ms = m.index;
369
+ const me = ms + m[0].length;
370
+ if (ms < s && s < me)
371
+ s = ms;
372
+ if (ms < e && e < me)
373
+ e = me;
374
+ }
375
+ return [s, e];
376
+ }
377
+ function pathSlotEdits(src, pos, head, a, b, rowPhases, edits, soft) {
378
+ const softFrom = (at) => (soft === undefined ? undefined : (i) => soft(pos + at + i));
379
+ const eq = head.indexOf('=', a);
380
+ let named = 0;
381
+ if (eq > a && eq < b) {
382
+ const name = head.slice(a, eq);
383
+ if (!slotIsWholeMarker(name, softFrom(a))) {
384
+ named = queryPartPhases(null, name, false) & rowPhases;
385
+ if (named !== 0)
386
+ pushEdit(edits, src, pos + a, pos + b, REDACTED_SECRET, named);
387
+ if (named === rowPhases)
388
+ return;
389
+ }
390
+ }
391
+ const [s, e] = markerAtomicCut(head, eq !== -1 && eq < b ? eq + 1 : a, b);
392
+ if (s >= e)
393
+ return;
394
+ const slot = head.slice(s, e);
395
+ if (slotIsWholeMarker(slot, softFrom(s)))
396
+ return;
397
+ const valued = queryPartPhases(null, slot, false) & rowPhases & ~named;
398
+ if (valued !== 0)
399
+ pushEdit(edits, src, pos + s, pos + e, REDACTED_SECRET, valued);
400
+ }
401
+ const anchoredFormPattern = (form) => new RegExp(`(?:https?:\/\/)?${form.host.split('.').join('\\.')}${form.trailingDot ? '\\.?' : ''}\/(?:${form.pathKinds.join('|')})\/((?:[${form.tailClass}]|${MARKER_ANYWHERE.source})+)`, 'gi');
402
+ function anchoredFormCandidates(text, out) {
403
+ for (const { id, form, probe, pattern } of ANCHORED_FORM_ROWS) {
404
+ if (!probe.test(text))
405
+ continue;
406
+ emitRow(id, (phases) => {
407
+ const re = new RegExp(pattern.source, pattern.flags);
408
+ for (let m = re.exec(text); m !== null; m = re.exec(text)) {
409
+ const tail = m[1] ?? '';
410
+ const end = m.index + m[0].length;
411
+ if (tail.length > 0 && (tail.includes(REDACTION_MARKER_PREFIX) || tail.length >= form.minTailLength))
412
+ out.push({ a: end - tail.length, b: end, kind: 'secret', cls: 'url', te: -1, phases });
413
+ if (m[0].length === 0)
414
+ re.lastIndex++;
415
+ }
416
+ });
417
+ }
418
+ }
419
+ function addressCandidates(src, from, end, opaqueSegments, edits, regions, soft, byShape = false, whole = false, hostRegion = whole, pathOnly = false) {
338
420
  const rest = src.slice(from, end);
339
- const authorityEnd = rest.search(/[/?#]/);
421
+ const authorityEnd = pathOnly ? 0 : rest.search(/[/?#]/);
340
422
  const authority = authorityEnd === -1 ? rest : rest.slice(0, authorityEnd);
341
423
  const tailStart = from + authority.length;
342
424
  const tail = src.slice(tailStart, end);
@@ -347,7 +429,7 @@ function addressCandidates(src, from, end, opaqueSegments, edits, regions, soft,
347
429
  const beforeHash = hash === -1 ? tail : tail.slice(0, hash);
348
430
  const question = beforeHash.indexOf('?');
349
431
  const path = question === -1 ? beforeHash : beforeHash.slice(0, question);
350
- pathCandidates(src, tailStart, path, opaqueSegments, edits, soft);
432
+ pathCandidates(src, tailStart, path, opaqueSegments, edits, soft, whole);
351
433
  if (whole) {
352
434
  const cut = pathCutAfterFirstLabel(path, true);
353
435
  if (cut !== -1 && fragmentTerminatorFrom(path, cut))
@@ -376,7 +458,8 @@ function relativeAddressCandidates(text, out, regions, unitPos, soft, hostRegion
376
458
  while (p0 < text.length && (isWhitespaceOrControl(text.charAt(p0)) || text.charAt(p0) === VIEW_SEPARATOR))
377
459
  p0++;
378
460
  const c0 = text.charAt(p0);
379
- if (c0 !== '/' && c0 !== '?' && c0 !== '#')
461
+ const pathOnly = c0 !== '/' && c0 !== '?' && c0 !== '#' && isRelativeRequestAt(text, p0);
462
+ if (c0 !== '/' && c0 !== '?' && c0 !== '#' && !pathOnly)
380
463
  return false;
381
464
  let end = text.length;
382
465
  while (end > p0 && (text.charAt(end - 1) === VIEW_SEPARATOR || isWhitespaceOrControl(text.charAt(end - 1)) || isUnicodeBlank(text.charCodeAt(end - 1))))
@@ -384,10 +467,19 @@ function relativeAddressCandidates(text, out, regions, unitPos, soft, hostRegion
384
467
  end = trailingCloserEnd(text, p0, p0 + 1, end, unitPos);
385
468
  const from = text.startsWith('//', p0) ? p0 + 2 : p0;
386
469
  const tokenEdits = [];
387
- addressCandidates(text, from, end, true, tokenEdits, regions, soft, false, true, hostRegion);
470
+ addressCandidates(text, from, end, true, tokenEdits, regions, soft, false, true, hostRegion, pathOnly);
388
471
  editsToCandidates(tokenEdits, 'url', out, end);
389
472
  return true;
390
473
  }
474
+ function isRelativeRequestAt(text, p0) {
475
+ const rest = text.slice(p0);
476
+ if (/^[A-Za-z][A-Za-z0-9+.-]*:/.test(rest))
477
+ return false;
478
+ const q = rest.search(/[?#]/);
479
+ if (q <= 0)
480
+ return false;
481
+ return !/[\s=\ufeff]/.test(rest.slice(0, q)) && rest.indexOf('=', q + 1) !== -1;
482
+ }
391
483
  function urlCandidates(text, out, regions, unitPos = () => false, soft, byShape = false, whole = false, hostRegion = whole) {
392
484
  if (whole && relativeAddressCandidates(text, out, regions, unitPos, soft, hostRegion))
393
485
  return;
@@ -457,6 +549,8 @@ function urlCandidates(text, out, regions, unitPos = () => false, soft, byShape
457
549
  end = runStart;
458
550
  end = trailingCloserEnd(text, start, mark + 3, end, unitPos);
459
551
  const tokenEdits = [];
552
+ if (userinfoBoundaryAmbiguous(text.slice(start, end)))
553
+ pushEdit(tokenEdits, text, start, end, REDACTED_SECRET);
460
554
  addressCandidates(text, mark + 3, end, !/^file:/i.test(text.slice(start, mark + 3)), tokenEdits, regions, soft, byShape, whole, hostRegion);
461
555
  editsToCandidates(tokenEdits, 'url', out, end);
462
556
  mark = text.indexOf('://', end > mark + 3 ? end : mark + 3);
@@ -635,13 +729,7 @@ function userinfoCandidates(S, out, words = true) {
635
729
  return nextBareStop(from) >= at;
636
730
  };
637
731
  let floor = 0;
638
- for (let at = text.indexOf('@'); at !== -1; at = text.indexOf('@', at + 1)) {
639
- let hostEnd = schemelessHostEnd(text, at + 1);
640
- const hidden = hostEnd === -1;
641
- if (hidden)
642
- hostEnd = hiddenHostEnd(text, at + 1, unitAt);
643
- if (hostEnd === -1)
644
- continue;
732
+ const readAt = (at, hostEnd, hidden, runStartIn) => {
645
733
  let shaped = null;
646
734
  const hostShaped = () => {
647
735
  if (shaped === null) {
@@ -673,9 +761,7 @@ function userinfoCandidates(S, out, words = true) {
673
761
  return hostShaped() ? 'bare' : null;
674
762
  };
675
763
  const refused = [];
676
- let runStart = at;
677
- while (runStart > floor && (!breaksUserinfo(text.charCodeAt(runStart - 1)) || (hidden && unitAt(runStart - 1) !== UNIT_NONE)))
678
- runStart--;
764
+ let runStart = runStartIn;
679
765
  if (text.charCodeAt(runStart) === 0x3a && runStart > floor && text[runStart - 1] === VIEW_SEPARATOR) {
680
766
  while (runStart > floor && text[runStart - 1] === VIEW_SEPARATOR)
681
767
  runStart--;
@@ -723,7 +809,7 @@ function userinfoCandidates(S, out, words = true) {
723
809
  continue;
724
810
  }
725
811
  }
726
- if (USERNAME_DELIMITERS.has(ch)) {
812
+ if (USERNAME_DELIMITERS.has(ch) || isUserinfoWideDelimiter(ch)) {
727
813
  lo = colon + 1;
728
814
  continue;
729
815
  }
@@ -791,10 +877,50 @@ function userinfoCandidates(S, out, words = true) {
791
877
  }
792
878
  }
793
879
  }
794
- if (found === -1)
795
- continue;
796
- out.push({ a: found, b: at, kind: 'userinfo', cls: hidden ? 'userinfo-hidden' : 'structural', te: hostEnd });
797
- floor = hostEnd;
880
+ return found;
881
+ };
882
+ const walkFrom = (at, hidden) => {
883
+ let r = at;
884
+ while (r > floor && (!breaksUserinfo(text.charCodeAt(r - 1)) || (hidden && unitAt(r - 1) !== UNIT_NONE)))
885
+ r--;
886
+ return r;
887
+ };
888
+ const widen = (at, r) => {
889
+ const wideFloor = Math.max(floor, at - SCHEMELESS_USERINFO_WIDE_SPAN);
890
+ let w = r;
891
+ while (w > wideFloor && isUserinfoWideDelimiter(text.charAt(w - 1))) {
892
+ w--;
893
+ while (w > wideFloor && !breaksUserinfo(text.charCodeAt(w - 1)))
894
+ w--;
895
+ }
896
+ return w;
897
+ };
898
+ for (let at = text.indexOf('@'); at !== -1; at = text.indexOf('@', at + 1)) {
899
+ let hostEnd = schemelessHostEnd(text, at + 1);
900
+ const hidden = hostEnd === -1;
901
+ if (hidden)
902
+ hostEnd = hiddenHostEnd(text, at + 1, unitAt);
903
+ const cursor = markerFrom;
904
+ const runStart = hostEnd === -1 ? -1 : walkFrom(at, hidden);
905
+ const found = runStart === -1 ? -1 : readAt(at, hostEnd, hidden, runStart);
906
+ if (found !== -1)
907
+ out.push({ a: found, b: at, kind: 'userinfo', cls: hidden ? 'userinfo-hidden' : 'structural', te: hostEnd });
908
+ const wideEnd = schemelessHostEnd(text, at + 1, true);
909
+ const wHidden = wideEnd === -1 ? hidden : false;
910
+ const wHostEnd = wideEnd === -1 ? hostEnd : wideEnd;
911
+ if (wHostEnd !== -1) {
912
+ const wRunStart = widen(at, wHostEnd === hostEnd && wHidden === hidden && runStart !== -1 ? runStart : walkFrom(at, wHidden));
913
+ if (wHostEnd !== hostEnd || wHidden !== hidden || wRunStart !== runStart) {
914
+ const after = markerFrom;
915
+ markerFrom = cursor;
916
+ const wFound = readAt(at, wHostEnd, wHidden, wRunStart);
917
+ markerFrom = Math.max(after, markerFrom);
918
+ if (wFound !== -1 && (wFound !== found || wHostEnd !== hostEnd))
919
+ out.push({ a: wFound, b: at, kind: 'userinfo', cls: wHidden ? 'userinfo-hidden' : 'structural', te: wHostEnd });
920
+ }
921
+ }
922
+ if (found !== -1)
923
+ floor = hostEnd;
798
924
  }
799
925
  }
800
926
  function labelWashedBefore(text, a, floor) {
@@ -1407,6 +1533,10 @@ function percentBoundaryDecode(text) {
1407
1533
  }
1408
1534
  return { decoded: chars.join(''), from, to };
1409
1535
  }
1536
+ export function percentBoundaryReadingOf(text) {
1537
+ const wide = percentBoundaryDecode(text);
1538
+ return wide === null ? text : wide.decoded;
1539
+ }
1410
1540
  const MAX_PERCENT_VIEW_LAYERS = 3;
1411
1541
  function percentLayers(text) {
1412
1542
  const out = [];
@@ -3911,11 +4041,12 @@ function screenSurfaces(text, o) {
3911
4041
  function percentSurfaces(raw, text, base, o) {
3912
4042
  const surfaces = [];
3913
4043
  const contents = [];
4044
+ const locals = [];
3914
4045
  for (const layer of percentLayers(text))
3915
- layerSurfaces(raw, layer, base, o, surfaces, contents);
3916
- return { surfaces, contents };
4046
+ layerSurfaces(raw, layer, base, o, surfaces, contents, true, base === null ? locals : undefined);
4047
+ return { surfaces, contents, locals };
3917
4048
  }
3918
- function layerSurfaces(raw, layer, base, o, surfaces, contents, decoded = true) {
4049
+ function layerSurfaces(raw, layer, base, o, surfaces, contents, decoded = true, locals) {
3919
4050
  const n = layer.text.length;
3920
4051
  const ps = new Int32Array(n);
3921
4052
  const pe = new Int32Array(n);
@@ -3937,6 +4068,52 @@ function layerSurfaces(raw, layer, base, o, surfaces, contents, decoded = true)
3937
4068
  surfaces.push(base === null ? { ...joined, rawDot: null, decoded } : { ...joined, decoded });
3938
4069
  for (const [a, b] of VD.contents)
3939
4070
  contents.push({ sub: layer.text.slice(a, b), rawAt: (k) => ps[a + k] ?? 0, rawEndAt: (k) => pe[a + k] ?? 0 });
4071
+ if (locals !== undefined && decoded && base === null && hasLineBreakAny(layer.text)) {
4072
+ locals.push({ text: layer.text, view: VD, ps, pe });
4073
+ if (layer.text.includes('+')) {
4074
+ const spaced = layer.text.split('+').join(' ');
4075
+ locals.push({ text: spaced, view: buildScanView(spaced, o), ps, pe });
4076
+ }
4077
+ }
4078
+ }
4079
+ function hasLineBreakAny(text) {
4080
+ for (let i = 0; i < text.length; i++) {
4081
+ const c = text.charCodeAt(i);
4082
+ if ((c === 0x0a || c === 0x0d || c === 0x5c) && lineBreakLengthAt(text, i) > 0)
4083
+ return true;
4084
+ }
4085
+ return false;
4086
+ }
4087
+ function decodedLayerLocalCandidates(L, o, out) {
4088
+ const layerSep = { ...separatedSurface(L.text, L.view), rawDot: null, decoded: true };
4089
+ const layerJoined = joinedSurface(L.text, L.view);
4090
+ const surfaces = layerJoined === null ? [layerSep] : [layerSep, { ...layerJoined, rawDot: null, decoded: true }];
4091
+ const blocks = { raw: L.text, view: L.view, out: [], lines: [null, null], marks: null };
4092
+ const found = [];
4093
+ for (const S of surfaces) {
4094
+ const cands = [];
4095
+ const regions = [];
4096
+ if (o.urls) {
4097
+ const unitPos = (k) => S.dropped(k) || L.view.rawUnit[S.rawStart(k)] === 1;
4098
+ urlCandidates(S.text, [], regions, unitPos, (k) => unitPos(k) || S.painted(k), o.queryByShape ?? false, o.wholeAddress === true, false);
4099
+ }
4100
+ runLabelPasses(S, regions, cands, blocks);
4101
+ for (const c of cands) {
4102
+ const r = toRaw(S, c);
4103
+ if (r !== null)
4104
+ found.push(r);
4105
+ }
4106
+ }
4107
+ for (const r of blocks.out)
4108
+ found.push(r);
4109
+ for (const r of found) {
4110
+ const start = L.ps[r.start];
4111
+ const end = L.pe[r.end - 1];
4112
+ if (start === undefined || end === undefined || end <= start)
4113
+ continue;
4114
+ const tokenEnd = r.tokenEnd > r.start ? (L.pe[Math.min(r.tokenEnd, L.text.length) - 1] ?? end) : end;
4115
+ out.push({ ...r, start, end, tokenEnd });
4116
+ }
3940
4117
  }
3941
4118
  function parserViewLayer(text) {
3942
4119
  if (!/[\t\n\r]/.test(text))
@@ -3989,7 +4166,7 @@ function editsToCandidates(edits, cls, out, te = -1) {
3989
4166
  const kind = KIND_BY_TEXT.get(e.text);
3990
4167
  if (kind === undefined || e.end <= e.start)
3991
4168
  continue;
3992
- out.push({ a: e.start, b: e.end, kind, cls, te });
4169
+ out.push(e.phases === undefined ? { a: e.start, b: e.end, kind, cls, te } : { a: e.start, b: e.end, kind, cls, te, phases: e.phases });
3993
4170
  }
3994
4171
  }
3995
4172
  function pemRegions(recognized) {
@@ -4207,7 +4384,15 @@ function toRaw(S, c) {
4207
4384
  if (a >= b)
4208
4385
  return null;
4209
4386
  const te = c.te > b ? S.rawEnd(c.te - 1) : S.rawEnd(b - 1);
4210
- return { start: S.rawStart(a), end: S.rawEnd(b - 1), kind: c.kind, cls: c.cls, tokenEnd: te };
4387
+ const r = { start: S.rawStart(a), end: S.rawEnd(b - 1), kind: c.kind, cls: c.cls, tokenEnd: te };
4388
+ return c.phases === undefined ? r : { ...r, phases: c.phases };
4389
+ }
4390
+ function runLabelPasses(S, regions, cands, blocks) {
4391
+ labelCandidates(S, 'scheme', regions, cands, blocks);
4392
+ labelCandidates(S, 'token', regions, cands, blocks);
4393
+ labelCandidates(S, 'label', regions, cands, blocks);
4394
+ labelCandidates(S, 'scheme', regions, cands, blocks, true);
4395
+ labelCandidates(S, 'label', regions, cands, blocks, true);
4211
4396
  }
4212
4397
  function collectCandidates(text, o, nested) {
4213
4398
  const V = buildScanView(text, o);
@@ -4249,14 +4434,11 @@ function collectCandidates(text, o, nested) {
4249
4434
  if (r[2] === 'host')
4250
4435
  regions.push(r);
4251
4436
  }
4437
+ anchoredFormCandidates(S.text, cands);
4252
4438
  if (o.words) {
4253
4439
  editsToCandidates(pemEdits(S, (blk) => { if (S === regionSurface)
4254
4440
  pemBlocksSeen.push(pemBlockToRaw(S, blk)); }), 'pem', cands);
4255
- labelCandidates(S, 'scheme', regions, cands, blocks);
4256
- labelCandidates(S, 'token', regions, cands, blocks);
4257
- labelCandidates(S, 'label', regions, cands, blocks);
4258
- labelCandidates(S, 'scheme', regions, cands, blocks, true);
4259
- labelCandidates(S, 'label', regions, cands, blocks, true);
4441
+ runLabelPasses(S, regions, cands, blocks);
4260
4442
  editsToCandidates(authParamEdits(S.text), 'param', cands);
4261
4443
  editsToCandidates(proseLiteralEdits(S.text), 'prose', cands);
4262
4444
  }
@@ -4266,30 +4448,107 @@ function collectCandidates(text, o, nested) {
4266
4448
  raw.push(S.rawDot !== null ? { ...r, dotted: true } : r);
4267
4449
  }
4268
4450
  }
4451
+ if (o.words)
4452
+ for (const L of decoded.locals)
4453
+ decodedLayerLocalCandidates(L, o, raw);
4269
4454
  if (!nested) {
4270
4455
  for (const [a, b] of V.contents) {
4271
4456
  const sub = text.slice(a, b);
4272
4457
  const inner = collectCandidates(sub, o, true);
4273
- for (const iv of resolveCandidates(sub, inner.cands, inner.rawUnit, inner.rawDot, o.words ? pemRegions(inner.pemBlocksSeen) : [], inner.rawSoft, inner.rawPlain)) {
4274
- raw.push({ start: a + iv.start, end: a + iv.end, kind: iv.kind, cls: 'nested', tokenEnd: a + iv.end, pretrimmed: true });
4458
+ for (const [iv, phases] of resolveEachPhase(sub, inner, o)) {
4459
+ const c = { start: a + iv.start, end: a + iv.end, kind: iv.kind, cls: 'nested', tokenEnd: a + iv.end, pretrimmed: true };
4460
+ raw.push(phases === undefined ? c : { ...c, phases });
4275
4461
  }
4276
4462
  }
4277
4463
  for (const c of [...screen.contents, ...decodedContents]) {
4278
4464
  const inner = collectCandidates(c.sub, o, true);
4279
- for (const iv of resolveCandidates(c.sub, inner.cands, inner.rawUnit, inner.rawDot, o.words ? pemRegions(inner.pemBlocksSeen) : [], inner.rawSoft, inner.rawPlain)) {
4465
+ for (const [iv, phases] of resolveEachPhase(c.sub, inner, o)) {
4280
4466
  const start = c.rawAt(iv.start);
4281
4467
  const end = c.rawEndAt(iv.end - 1);
4282
- if (end > start)
4283
- raw.push({ start, end, kind: iv.kind, cls: 'nested', tokenEnd: end, pretrimmed: true });
4468
+ if (end <= start)
4469
+ continue;
4470
+ const r = { start, end, kind: iv.kind, cls: 'nested', tokenEnd: end, pretrimmed: true };
4471
+ raw.push(phases === undefined ? r : { ...r, phases });
4284
4472
  }
4285
4473
  }
4286
4474
  }
4287
4475
  return { cands: raw, rawUnit: V.rawUnit, rawDot: screen.surfaces[0]?.rawDot ?? null, rawSoft: screen.rawSoft, rawPlain: screen.rawPlain, pemBlocksSeen };
4288
4476
  }
4289
- function scanOnce(text, o, trace) {
4290
- const { cands, rawUnit, rawDot, rawSoft, rawPlain, pemBlocksSeen } = collectCandidates(text, o, false);
4291
- const intervals = resolveCandidates(text, cands, rawUnit, rawDot, o.words ? pemRegions(pemBlocksSeen) : [], rawSoft, rawPlain);
4292
- return materialize(text, intervals, trace);
4477
+ const RULES_BY_VERSION = {
4478
+ '0.102.0': [
4479
+ { id: 'path-slot', ticket: 'CC-849', kind: 'generator' },
4480
+ {
4481
+ id: 'anchored-form:slack-webhook-url',
4482
+ ticket: 'CC-849',
4483
+ kind: 'generator',
4484
+ form: { host: 'hooks.slack.com', trailingDot: true, pathKinds: ['services', 'workflows', 'triggers'], tailClass: 'A-Za-z0-9+/_-', minTailLength: 40 },
4485
+ },
4486
+ ],
4487
+ };
4488
+ const RULE_ROWS_ARE_GENERATORS = true;
4489
+ void RULE_ROWS_ARE_GENERATORS;
4490
+ function rowPhaseTable() {
4491
+ const m = new Map();
4492
+ const keys = Object.keys(RULES_BY_VERSION);
4493
+ keys.forEach((k, j) => {
4494
+ for (const row of RULES_BY_VERSION[k])
4495
+ m.set(row.id, j + 1);
4496
+ });
4497
+ return m;
4498
+ }
4499
+ const ROW_PHASE = rowPhaseTable();
4500
+ const LAST_PHASE = Object.keys(RULES_BY_VERSION).length;
4501
+ const ANCHORED_FORM_ROWS = Object.values(RULES_BY_VERSION)
4502
+ .flatMap((rows) => rows.filter((r) => 'form' in r))
4503
+ .map((r) => ({ id: r.id, form: r.form, probe: new RegExp(r.form.host.split('.').join('\\.'), 'i'), pattern: anchoredFormPattern(r.form) }));
4504
+ let scanUpto = LAST_PHASE;
4505
+ const phaseRange = (from, to) => (to < from ? 0 : ((1 << (to + 1)) - 1) & ~((1 << from) - 1));
4506
+ const phasesOrAll = (mask) => (mask === phaseRange(0, scanUpto) ? undefined : mask);
4507
+ const inPhase = (phases, k) => phases === undefined || ((phases >> k) & 1) === 1;
4508
+ function emitRow(rowId, emit) {
4509
+ const p = ROW_PHASE.get(rowId) ?? Number.POSITIVE_INFINITY;
4510
+ if (p > scanUpto)
4511
+ return;
4512
+ emit(phaseRange(p, scanUpto));
4513
+ }
4514
+ function resolveEachPhase(text, c, o) {
4515
+ const pems = o.words ? pemRegions(c.pemBlocksSeen) : [];
4516
+ const run = (cs) => resolveCandidates(text, cs, c.rawUnit, c.rawDot, pems, c.rawSoft, c.rawPlain);
4517
+ if (!c.cands.some((x) => x.phases !== undefined))
4518
+ return run(c.cands).map((iv) => [iv, undefined]);
4519
+ const per = [];
4520
+ for (let k = 0; k <= scanUpto; k++)
4521
+ per.push(run(c.cands.filter((x) => inPhase(x.phases, k))));
4522
+ const key = (ivs) => ivs.map((iv) => `${iv.start}:${iv.end}:${iv.kind}`).join(',');
4523
+ const k0 = key(per[0] ?? []);
4524
+ if (per.every((ivs) => key(ivs) === k0))
4525
+ return (per[0] ?? []).map((iv) => [iv, undefined]);
4526
+ const out = [];
4527
+ per.forEach((ivs, k) => {
4528
+ for (const iv of ivs)
4529
+ out.push([iv, 1 << k]);
4530
+ });
4531
+ return out;
4532
+ }
4533
+ function scanPhases(text, o, trace, upto) {
4534
+ const saved = scanUpto;
4535
+ scanUpto = upto;
4536
+ try {
4537
+ const c = collectCandidates(text, o, false);
4538
+ const pems = o.words ? pemRegions(c.pemBlocksSeen) : [];
4539
+ const run = (cs) => materialize(text, resolveCandidates(text, cs, c.rawUnit, c.rawDot, pems, c.rawSoft, c.rawPlain), trace);
4540
+ if (!c.cands.some((x) => x.phases !== undefined)) {
4541
+ const one = run(c.cands);
4542
+ return Array.from({ length: upto + 1 }, () => one);
4543
+ }
4544
+ const outs = [];
4545
+ for (let k = 0; k <= upto; k++)
4546
+ outs.push(run(c.cands.filter((x) => inPhase(x.phases, k))));
4547
+ return outs;
4548
+ }
4549
+ finally {
4550
+ scanUpto = saved;
4551
+ }
4293
4552
  }
4294
4553
  const MAX_WASH_REWRITES = 8;
4295
4554
  function composeOrigin(first, second) {
@@ -4304,36 +4563,76 @@ function composeOrigin(first, second) {
4304
4563
  }
4305
4564
  return out;
4306
4565
  }
4307
- function scanAndMask(text, o, trace, stats) {
4566
+ function scanAndMask(text, o, trace, stats, phaseOut) {
4308
4567
  if (!o.urls && !o.words) {
4309
4568
  if (stats !== undefined) {
4310
4569
  stats.passes = 0;
4311
4570
  stats.capped = false;
4571
+ stats.collections = 0;
4312
4572
  }
4573
+ phaseOut?.push({ text });
4313
4574
  return { text };
4314
4575
  }
4315
- let cur = scanOnce(text, o, trace);
4316
- let passes = 1;
4576
+ const upto = scanUpto;
4577
+ let memoText = null;
4578
+ let memo = [];
4579
+ let collections = 0;
4580
+ let passes = 0;
4581
+ const op = (t, k) => {
4582
+ if (t !== memoText) {
4583
+ memo = scanPhases(t, o, trace, upto);
4584
+ memoText = t;
4585
+ collections++;
4586
+ }
4587
+ passes++;
4588
+ return memo[k] ?? { text: t };
4589
+ };
4590
+ const advance = (cur, next) => {
4591
+ const origin = trace ? composeOrigin(cur.origin, next.origin) : undefined;
4592
+ return origin === undefined ? { text: next.text } : { text: next.text, origin };
4593
+ };
4594
+ let cur = op(text, 0);
4317
4595
  let rewrites = cur.text !== text ? 1 : 0;
4318
4596
  let changed = rewrites > 0;
4319
4597
  while (changed && rewrites < MAX_WASH_REWRITES) {
4320
- const next = scanOnce(cur.text, o, trace);
4321
- passes++;
4598
+ const next = op(cur.text, 0);
4322
4599
  changed = next.text !== cur.text;
4323
4600
  if (!changed)
4324
4601
  break;
4325
4602
  rewrites++;
4326
- const origin = trace ? composeOrigin(cur.origin, next.origin) : undefined;
4327
- cur = origin === undefined ? { text: next.text } : { text: next.text, origin };
4603
+ cur = advance(cur, next);
4604
+ }
4605
+ const stable = [!changed];
4606
+ phaseOut?.push(cur);
4607
+ for (let j = 1; j <= upto; j++) {
4608
+ stable.push(false);
4609
+ let rw = 0;
4610
+ let k = j;
4611
+ while (rw < MAX_WASH_REWRITES && !stable.every(Boolean)) {
4612
+ if (stable[k] === true) {
4613
+ k = (k + j) % (j + 1);
4614
+ continue;
4615
+ }
4616
+ const next = op(cur.text, k);
4617
+ if (next.text === cur.text)
4618
+ stable[k] = true;
4619
+ else {
4620
+ rw++;
4621
+ cur = advance(cur, next);
4622
+ stable.fill(false);
4623
+ }
4624
+ k = (k + j) % (j + 1);
4625
+ }
4626
+ phaseOut?.push(cur);
4328
4627
  }
4329
4628
  if (stats !== undefined) {
4330
4629
  let capped = false;
4331
- if (changed) {
4332
- passes++;
4333
- capped = scanOnce(cur.text, o, false).text !== cur.text;
4334
- }
4630
+ for (let k = 0; k < stable.length; k++)
4631
+ if (stable[k] !== true && op(cur.text, k).text !== cur.text)
4632
+ capped = true;
4335
4633
  stats.passes = passes;
4336
4634
  stats.capped = capped;
4635
+ stats.collections = collections;
4337
4636
  }
4338
4637
  return cur;
4339
4638
  }
@@ -4732,14 +5031,28 @@ function scanOptionsOf(o, face, queryByShape = false, wholeAddress = false) {
4732
5031
  };
4733
5032
  }
4734
5033
  export function credentialWashPasses(text, opts = {}) {
4735
- const input = typeof text === 'string' ? text : String(text ?? '');
4736
- const stats = { passes: 0, capped: false };
5034
+ const input = displayInputText(text);
5035
+ const stats = { passes: 0, capped: false, collections: 0 };
4737
5036
  const scan = opts === null ? WASH_OPTIONS : scanOptionsOf(opts, publicFace(opts));
4738
5037
  scanAndMask(input, scan, false, stats);
4739
- return { passes: stats.passes, capped: stats.capped };
5038
+ return { collections: stats.collections, passes: stats.passes, capped: stats.capped };
5039
+ }
5040
+ function displayInputText(text) {
5041
+ switch (typeof text) {
5042
+ case 'string':
5043
+ return text;
5044
+ case 'number':
5045
+ case 'bigint':
5046
+ case 'boolean':
5047
+ return String(text);
5048
+ case 'undefined':
5049
+ return '';
5050
+ default:
5051
+ return text === null ? '' : REDACTED_SECRET;
5052
+ }
4740
5053
  }
4741
5054
  function renderUntrusted(text, opts, ledger, queryByShape = false, wholeAddress = false) {
4742
- const input = typeof text === 'string' ? text : String(text ?? '');
5055
+ const input = displayInputText(text);
4743
5056
  const o = opts ?? {};
4744
5057
  const face = publicFace(o);
4745
5058
  const scan = scanOptionsOf(o, face, queryByShape, wholeAddress);
@@ -4938,51 +5251,74 @@ function hasOpaquePiece(text) {
4938
5251
  }
4939
5252
  return false;
4940
5253
  }
4941
- function carriesCredentialStructure(value) {
4942
- const netChanges = (v) => {
4943
- if (washCredentials(v) !== v || hasOpaquePiece(v))
4944
- return true;
4945
- if (!v.includes('+'))
4946
- return false;
4947
- const spaced = v.split('+').join(' ');
4948
- return washCredentials(spaced) !== spaced;
5254
+ function carriesCredentialStructurePhases(value) {
5255
+ const all = phaseRange(0, scanUpto);
5256
+ let hit = 0;
5257
+ const net = (v) => {
5258
+ if (hasOpaquePiece(v)) {
5259
+ hit = all;
5260
+ return;
5261
+ }
5262
+ hit |= washChangesPhases(v);
5263
+ if (hit === all || !v.includes('+'))
5264
+ return;
5265
+ hit |= washChangesPhases(v.split('+').join(' '));
4949
5266
  };
4950
5267
  let view = value;
4951
5268
  for (let layer = 0; layer < MAX_PERCENT_VIEW_LAYERS; layer++) {
4952
- if (netChanges(view))
4953
- return true;
5269
+ net(view);
5270
+ if (hit === all)
5271
+ return all;
4954
5272
  const next = percentDecodeForMatching(view).decoded;
4955
5273
  if (next === view)
4956
- return false;
5274
+ return hit;
4957
5275
  view = next;
4958
5276
  }
4959
- if (netChanges(view))
4960
- return true;
4961
- return percentDecodeForMatching(view).decoded !== view;
5277
+ net(view);
5278
+ if (hit === all)
5279
+ return all;
5280
+ return percentDecodeForMatching(view).decoded !== view ? all : hit;
4962
5281
  }
4963
- function queryPartCarriesCredential(key, value, relax) {
5282
+ function washChangesPhases(v) {
5283
+ const ends = [];
5284
+ scanAndMask(v, WASH_OPTIONS, false, undefined, ends);
5285
+ let mask = 0;
5286
+ ends.forEach((t, k) => {
5287
+ if (t.text !== v)
5288
+ mask |= 1 << k;
5289
+ });
5290
+ return mask;
5291
+ }
5292
+ function queryPartPhases(key, value, relax) {
5293
+ const all = phaseRange(0, scanUpto);
4964
5294
  if (value.length === 0 || isMarker(value))
4965
- return false;
5295
+ return 0;
4966
5296
  if (key !== null) {
4967
5297
  if (isCredentialLabelName(key))
4968
- return true;
5298
+ return all;
4969
5299
  if (relax && isNonSecretFieldName(key) && isReadableWordChain(value))
4970
- return isKnownSecretSegment(value);
5300
+ return isKnownSecretSegment(value) ? all : 0;
4971
5301
  }
4972
- if (isOpaqueSecretValue(value) || carriesCredentialStructure(value))
4973
- return true;
5302
+ if (isOpaqueSecretValue(value))
5303
+ return all;
5304
+ let hit = carriesCredentialStructurePhases(value);
5305
+ if (hit === all)
5306
+ return all;
4974
5307
  let from = 0;
4975
5308
  for (let i = 0; i <= value.length; i++) {
4976
5309
  if (i < value.length && !endsUrlFragmentAt(value, i))
4977
5310
  continue;
4978
5311
  if (i > from && (from > 0 || i < value.length)) {
4979
5312
  const chunk = value.slice(from, i);
4980
- if (isOpaqueSecretValue(chunk) || carriesCredentialStructure(chunk))
4981
- return true;
5313
+ if (isOpaqueSecretValue(chunk))
5314
+ return all;
5315
+ hit |= carriesCredentialStructurePhases(chunk);
5316
+ if (hit === all)
5317
+ return all;
4982
5318
  }
4983
5319
  from = i + 1;
4984
5320
  }
4985
- return false;
5321
+ return hit;
4986
5322
  }
4987
5323
  const UPLOAD_PROBE_PREFIX = 'https://q.invalid/?';
4988
5324
  const UPLOAD_SCAN_OPTIONS = Object.freeze({ urls: true, queryByShape: 'strict', wholeAddress: true, words: true, blanks: false, fold: false, face: null, escapeSpaces: null });
@@ -4990,27 +5326,421 @@ export function queryCarriesCredential(query) {
4990
5326
  if (typeof query !== 'string' || query.length === 0)
4991
5327
  return false;
4992
5328
  const probe = `${UPLOAD_PROBE_PREFIX}${query}`;
4993
- return scanOnce(probe, UPLOAD_SCAN_OPTIONS, false).text !== probe;
5329
+ return scanAndMask(probe, UPLOAD_SCAN_OPTIONS, false).text !== probe;
4994
5330
  }
4995
5331
  export function displayConfiguredUrl(url, opts = {}) {
4996
- const out = renderUntrusted(typeof url === 'string' ? configuredUrlScannable(url) : url, opts, null, 'relaxed', true);
5332
+ const reading = typeof url === 'string' ? configuredAddressReading(url) : null;
5333
+ const out = renderUntrusted(reading === null ? url : reading.withheld ? REDACTED_SECRET : reading.text, opts, null, 'relaxed', true);
4997
5334
  return typeof out === 'string' ? out : out.text;
4998
5335
  }
4999
- function configuredUrlScannable(url) {
5000
- const view = url.replace(/[\t\n\r]/g, '').replace(/^[\u0000-\u0020]+/, '');
5001
- if (/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(view) || !/^[A-Za-z][A-Za-z0-9+.-]*:/.test(view))
5002
- return url;
5336
+ function parserViewOf(url) {
5337
+ return url.replace(/[\t\n\r]/g, '').replace(/^[\u0000-\u0020]+/, '');
5338
+ }
5339
+ const AMBIGUOUS_USERINFO_BOUNDARY = /^(?:[A-Za-z][A-Za-z0-9+.-]*:\/\/|(?:https?|wss?|ftp):[\\/]*)[^/\\?#@]*[?#][^@]*@/i;
5340
+ function userinfoBoundaryAmbiguous(view) {
5341
+ return AMBIGUOUS_USERINFO_BOUNDARY.test(view);
5342
+ }
5343
+ function authorityHasBackslash(view) {
5344
+ const scheme = /^(?:https?|wss?|ftp|file):\/\//i.exec(view);
5345
+ if (scheme === null)
5346
+ return false;
5347
+ const from = scheme[0].length;
5348
+ let end = from;
5349
+ while (end < view.length && !'/?#'.includes(view.charAt(end)))
5350
+ end++;
5351
+ const marks = markerSpans(view);
5352
+ for (let s = 0; s < marks.length; s += 2)
5353
+ if ((marks[s] ?? end) >= from && (marks[s] ?? end) < end)
5354
+ return false;
5355
+ let backslash = false;
5356
+ for (let k = from; k < end; k++) {
5357
+ if (view.charAt(k) !== '\\')
5358
+ continue;
5359
+ if (outletAtomEnd(view, k) > k)
5360
+ return false;
5361
+ backslash = true;
5362
+ }
5363
+ return backslash;
5364
+ }
5365
+ function outletAtomEnd(text, at) {
5366
+ return escapeTokenAt(text, at)?.end ?? (nameBlankTokenAt(text, at) !== -1 ? at + 6 : -1);
5367
+ }
5368
+ function rebuiltAddress(url) {
5003
5369
  let u;
5004
5370
  try {
5005
5371
  u = new URL(url);
5006
5372
  }
5007
5373
  catch {
5008
- return url;
5374
+ return null;
5009
5375
  }
5010
5376
  if (u.host === '')
5011
- return url;
5377
+ return null;
5012
5378
  const userinfo = u.username !== '' || u.password !== '' ? `${u.username}${u.password !== '' ? `:${u.password}` : ''}@` : '';
5013
- return `${u.protocol}//${userinfo}${u.host}${u.pathname}${u.search}${u.hash}`;
5379
+ const text = `${u.protocol}//${userinfo}${u.host}${u.pathname}${u.search}${u.hash}`;
5380
+ const fwdA = new Int32Array(url.length).fill(-2);
5381
+ const fwdB = new Int32Array(url.length).fill(-2);
5382
+ const backA = new Int32Array(text.length).fill(-2);
5383
+ const backB = new Int32Array(text.length).fill(-2);
5384
+ const parts = new Int8Array(url.length);
5385
+ const out = { text, toRebuilt: [fwdA, fwdB], toOriginal: [backA, backB], parts };
5386
+ const encoder = new TextEncoder();
5387
+ const at = [];
5388
+ for (let i = 0; i < url.length; i++) {
5389
+ const c = url.charCodeAt(i);
5390
+ if (c === 0x09 || c === 0x0a || c === 0x0d)
5391
+ fwdA[i] = -1;
5392
+ else
5393
+ at.push(i);
5394
+ }
5395
+ let a = 0;
5396
+ let b = at.length;
5397
+ while (a < b && url.charCodeAt(at[a] ?? 0) <= 0x20)
5398
+ fwdA[at[a++] ?? 0] = -1;
5399
+ while (b > a && url.charCodeAt(at[b - 1] ?? 0) <= 0x20)
5400
+ fwdA[at[--b] ?? 0] = -1;
5401
+ const ch = (k) => url.charAt(at[k] ?? -1);
5402
+ let e = a;
5403
+ while (e < b && ch(e) !== ':')
5404
+ e++;
5405
+ const scheme = at.slice(a, e).map((i) => url.charAt(i)).join('');
5406
+ if (e === b || !/^(?:https?|wss?|ftp)$/i.test(scheme))
5407
+ return out;
5408
+ const align = (from, to, rFrom, rTo, mode, part) => {
5409
+ const pairs = [];
5410
+ let r = rFrom;
5411
+ for (let k = from; k < to;) {
5412
+ const i = at[k] ?? -1;
5413
+ const cp = url.codePointAt(i) ?? 0;
5414
+ const wide = cp > 0xffff && k + 1 < to && at[k + 1] === i + 1;
5415
+ const c = wide ? String.fromCodePoint(cp) : url.charAt(i);
5416
+ const step = c.length;
5417
+ let len = -1;
5418
+ if (text.startsWith(c, r))
5419
+ len = c.length;
5420
+ else if (mode === 'fold' && c.length === 1 && /[A-Z]/.test(c) && text.charAt(r) === c.toLowerCase())
5421
+ len = 1;
5422
+ else if (mode === 'path' && c === '\\' && text.charAt(r) === '/')
5423
+ len = 1;
5424
+ else if (mode === 'encoded' || mode === 'path') {
5425
+ const enc = [...encoder.encode(c)].map((x) => `%${x.toString(16).toUpperCase().padStart(2, '0')}`).join('');
5426
+ if (text.startsWith(enc, r))
5427
+ len = enc.length;
5428
+ }
5429
+ if (len < 0 || r + len > rTo)
5430
+ return;
5431
+ pairs.push(i, step, r, r + len);
5432
+ r += len;
5433
+ k += step;
5434
+ }
5435
+ if (r !== rTo)
5436
+ return;
5437
+ for (let p = 0; p < pairs.length; p += 4) {
5438
+ const i = pairs[p] ?? -1;
5439
+ const n = pairs[p + 1] ?? 1;
5440
+ const s = pairs[p + 2] ?? 0;
5441
+ const t = pairs[p + 3] ?? 0;
5442
+ for (let j = i; j < i + n; j++) {
5443
+ fwdA[j] = s;
5444
+ fwdB[j] = t;
5445
+ parts[j] = part;
5446
+ }
5447
+ backA.fill(i, s, t);
5448
+ backB.fill(i + n, s, t);
5449
+ }
5450
+ };
5451
+ const drop = (from, to) => {
5452
+ for (let k = from; k < to; k++)
5453
+ fwdA[at[k] ?? -1] = -1;
5454
+ };
5455
+ const insert = (rFrom, rTo) => {
5456
+ backA.fill(-1, rFrom, rTo);
5457
+ };
5458
+ align(a, e + 1, 0, u.protocol.length, 'fold', 1);
5459
+ let k = e + 1;
5460
+ while (k < b && (ch(k) === '/' || ch(k) === '\\'))
5461
+ k++;
5462
+ drop(e + 1, k);
5463
+ insert(u.protocol.length, u.protocol.length + 2);
5464
+ let r = u.protocol.length + 2;
5465
+ let end = k;
5466
+ while (end < b && !'/\\?#'.includes(ch(end)))
5467
+ end++;
5468
+ let lastAt = -1;
5469
+ for (let j = k; j < end; j++)
5470
+ if (ch(j) === '@')
5471
+ lastAt = j;
5472
+ if (lastAt >= 0) {
5473
+ let colon = lastAt;
5474
+ for (let j = k; j < lastAt; j++)
5475
+ if (ch(j) === ':') {
5476
+ colon = j;
5477
+ break;
5478
+ }
5479
+ align(k, colon, r, r + u.username.length, 'encoded', 2);
5480
+ r += u.username.length;
5481
+ if (colon < lastAt) {
5482
+ if (u.password !== '') {
5483
+ align(colon, colon + 1, r, r + 1, 'exact', 2);
5484
+ r += 1;
5485
+ }
5486
+ else
5487
+ drop(colon, colon + 1);
5488
+ align(colon + 1, lastAt, r, r + u.password.length, 'encoded', 2);
5489
+ r += u.password.length;
5490
+ }
5491
+ if (userinfo !== '') {
5492
+ align(lastAt, lastAt + 1, r, r + 1, 'exact', 3);
5493
+ r += 1;
5494
+ }
5495
+ else
5496
+ drop(lastAt, lastAt + 1);
5497
+ k = lastAt + 1;
5498
+ }
5499
+ let portColon = end;
5500
+ let bracket = false;
5501
+ for (let j = k; j < end; j++) {
5502
+ const c = ch(j);
5503
+ if (c === '[')
5504
+ bracket = true;
5505
+ else if (c === ']')
5506
+ bracket = false;
5507
+ else if (c === ':' && !bracket) {
5508
+ portColon = j;
5509
+ break;
5510
+ }
5511
+ }
5512
+ align(k, portColon, r, r + u.hostname.length, 'fold', 4);
5513
+ r += u.hostname.length;
5514
+ if (portColon < end) {
5515
+ if (u.port !== '') {
5516
+ align(portColon, end, r, r + 1 + u.port.length, 'exact', 5);
5517
+ r += 1 + u.port.length;
5518
+ }
5519
+ else
5520
+ drop(portColon, end);
5521
+ }
5522
+ let q = end;
5523
+ if (q < b && (ch(q) === '/' || ch(q) === '\\'))
5524
+ while (q < b && ch(q) !== '?' && ch(q) !== '#')
5525
+ q++;
5526
+ if (q === end)
5527
+ insert(r, r + u.pathname.length);
5528
+ else
5529
+ align(end, q, r, r + u.pathname.length, 'path', 6);
5530
+ r += u.pathname.length;
5531
+ let h = q;
5532
+ if (h < b && ch(h) === '?')
5533
+ while (h < b && ch(h) !== '#')
5534
+ h++;
5535
+ if (h - q === 1)
5536
+ drop(q, h);
5537
+ else if (h > q)
5538
+ align(q, h, r, r + u.search.length, 'encoded', 7);
5539
+ r += u.search.length;
5540
+ if (b - h === 1)
5541
+ drop(h, b);
5542
+ else if (b > h)
5543
+ align(h, b, r, r + u.hash.length, 'encoded', 8);
5544
+ return out;
5545
+ }
5546
+ function restoreAtoms(url, c) {
5547
+ const atoms = [];
5548
+ const marks = markerSpans(url);
5549
+ for (let s = 0; s + 1 < marks.length; s += 2)
5550
+ atoms.push([marks[s] ?? 0, marks[s + 1] ?? 0]);
5551
+ for (let i = url.indexOf('\\'); i >= 0; i = url.indexOf('\\', i + 1)) {
5552
+ const end = outletAtomEnd(url, i);
5553
+ if (end > i)
5554
+ atoms.push([i, end]);
5555
+ }
5556
+ atoms.sort((x, y) => x[0] - y[0]);
5557
+ const [fwdA, fwdB] = c.toRebuilt;
5558
+ const [backA, backB] = c.toOriginal;
5559
+ const swaps = [];
5560
+ for (const [from, to] of atoms) {
5561
+ let ok = (fwdA[from] ?? -1) >= 0;
5562
+ for (let i = from; ok && i + 1 < to; i++)
5563
+ ok = (fwdA[i + 1] ?? -1) >= 0 && fwdB[i] === fwdA[i + 1];
5564
+ if (ok)
5565
+ swaps.push(fwdA[from] ?? 0, fwdB[to - 1] ?? 0, from, to);
5566
+ }
5567
+ if (swaps.length === 0)
5568
+ return c;
5569
+ const old = c.text;
5570
+ const shift = new Int32Array(old.length + 1);
5571
+ let text = '';
5572
+ const nA = [];
5573
+ const nB = [];
5574
+ let w = 0;
5575
+ for (let k = 0; k <= old.length;) {
5576
+ if (w < swaps.length && k === swaps[w]) {
5577
+ const rTo = swaps[w + 1] ?? k;
5578
+ const from = swaps[w + 2] ?? 0;
5579
+ const to = swaps[w + 3] ?? 0;
5580
+ shift[k] = text.length;
5581
+ for (let j = k + 1; j < rTo; j++)
5582
+ shift[j] = -1;
5583
+ for (let i = from; i < to; i++) {
5584
+ fwdA[i] = text.length;
5585
+ fwdB[i] = text.length + 1;
5586
+ nA.push(i);
5587
+ nB.push(i + 1);
5588
+ text += url.charAt(i);
5589
+ }
5590
+ w += 4;
5591
+ k = rTo;
5592
+ continue;
5593
+ }
5594
+ shift[k] = text.length;
5595
+ if (k < old.length) {
5596
+ nA.push(backA[k] ?? -2);
5597
+ nB.push(backB[k] ?? -2);
5598
+ text += old.charAt(k);
5599
+ }
5600
+ k++;
5601
+ }
5602
+ const inSwap = new Uint8Array(url.length);
5603
+ for (let s = 0; s < swaps.length; s += 4)
5604
+ inSwap.fill(1, swaps[s + 2], swaps[s + 3]);
5605
+ for (let i = 0; i < url.length; i++) {
5606
+ if (inSwap[i] === 1 || (fwdA[i] ?? -2) < 0)
5607
+ continue;
5608
+ fwdA[i] = shift[fwdA[i] ?? 0] ?? -2;
5609
+ fwdB[i] = shift[fwdB[i] ?? 0] ?? -2;
5610
+ }
5611
+ return { text, toRebuilt: [fwdA, fwdB], toOriginal: [Int32Array.from(nA), Int32Array.from(nB)], parts: c.parts };
5612
+ }
5613
+ function hiddenUnits(text, queryByShape) {
5614
+ const r = scanAndMask(text, scanOptionsOf({}, publicFace({}), queryByShape, true), true);
5615
+ const hidden = new Uint8Array(text.length);
5616
+ if (r.text !== text) {
5617
+ if (r.origin === undefined)
5618
+ return null;
5619
+ hidden.fill(1);
5620
+ for (const k of r.origin)
5621
+ if (k >= 0)
5622
+ hidden[k] = 0;
5623
+ }
5624
+ return hidden;
5625
+ }
5626
+ function coversHidden(from, to, image) {
5627
+ for (let i = 0; i < from.length; i++) {
5628
+ if (from[i] !== 1)
5629
+ continue;
5630
+ const s = image[0][i] ?? -2;
5631
+ if (s === -1)
5632
+ continue;
5633
+ if (s === -2)
5634
+ return false;
5635
+ for (let k = s; k < (image[1][i] ?? s); k++)
5636
+ if (to[k] !== 1)
5637
+ return false;
5638
+ }
5639
+ return true;
5640
+ }
5641
+ const CONFIGURED_ADDRESS_WITHHELD = Object.freeze({ withheld: true });
5642
+ function rebuiltKeepsRuns(url, rebuilt, hidden) {
5643
+ const [fwdA, fwdB] = rebuilt.toRebuilt;
5644
+ for (let i = 0; i < url.length;) {
5645
+ if (hidden[i] !== 1) {
5646
+ i++;
5647
+ continue;
5648
+ }
5649
+ let j = i;
5650
+ while (j < url.length && hidden[j] === 1)
5651
+ j++;
5652
+ const s = fwdA[i] ?? -2;
5653
+ const t = fwdB[j - 1] ?? -2;
5654
+ if (s < 0 || t - s !== j - i || rebuilt.text.slice(s, t) !== url.slice(i, j))
5655
+ return false;
5656
+ for (let k = i; k < j; k++)
5657
+ if (rebuilt.parts[k] !== rebuilt.parts[i])
5658
+ return false;
5659
+ i = j;
5660
+ }
5661
+ return true;
5662
+ }
5663
+ function readingOf(url, rebuilt, n1) {
5664
+ if (!n1) {
5665
+ const hidden = hiddenUnits(url, 'strict');
5666
+ return hidden !== null && rebuiltKeepsRuns(url, rebuilt, hidden) ? { withheld: false, text: rebuilt.text } : CONFIGURED_ADDRESS_WITHHELD;
5667
+ }
5668
+ let original = true;
5669
+ let viaRebuilt = true;
5670
+ for (const mode of ['relaxed', 'strict']) {
5671
+ const hiddenOriginal = hiddenUnits(url, mode);
5672
+ const hiddenRebuilt = hiddenUnits(rebuilt.text, mode);
5673
+ if (hiddenOriginal === null || hiddenRebuilt === null)
5674
+ return CONFIGURED_ADDRESS_WITHHELD;
5675
+ original &&= coversHidden(hiddenRebuilt, hiddenOriginal, rebuilt.toOriginal);
5676
+ viaRebuilt &&= coversHidden(hiddenOriginal, hiddenRebuilt, rebuilt.toRebuilt);
5677
+ }
5678
+ return original ? { withheld: false, text: url } : viaRebuilt ? { withheld: false, text: rebuilt.text } : CONFIGURED_ADDRESS_WITHHELD;
5679
+ }
5680
+ function configuredAddressReading(url) {
5681
+ const view = parserViewOf(url);
5682
+ if (userinfoBoundaryAmbiguous(view))
5683
+ return CONFIGURED_ADDRESS_WITHHELD;
5684
+ if (!/^[A-Za-z][A-Za-z0-9+.-]*:/.test(view))
5685
+ return { withheld: false, text: url };
5686
+ if (/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(view)) {
5687
+ const n1 = authorityHasBackslash(view) ? rebuiltAddress(url) : null;
5688
+ return n1 === null ? { withheld: false, text: url } : readingOf(url, restoreAtoms(url, n1), true);
5689
+ }
5690
+ const rebuilt = rebuiltAddress(url);
5691
+ if (rebuilt !== null)
5692
+ return readingOf(url, rebuilt, false);
5693
+ if (/^(?:https?|wss?|ftp):/i.test(view) && /[@?#]/.test(view) && !schemelessUserinfoLeads(view))
5694
+ return CONFIGURED_ADDRESS_WITHHELD;
5695
+ return { withheld: false, text: url };
5696
+ }
5697
+ function schemelessUserinfoLeads(view) {
5698
+ const V = buildScanView(view, WASH_OPTIONS);
5699
+ const S = separatedSurface(view, V);
5700
+ const out = [];
5701
+ userinfoCandidates(S, out, true);
5702
+ return out.some((c) => c.kind === 'userinfo' && S.rawStart(c.a) === 0);
5703
+ }
5704
+ export function configuredValueCarriesCredential(value) {
5705
+ if (typeof value !== 'string' || value.length === 0)
5706
+ return false;
5707
+ const reading = configuredAddressReading(value);
5708
+ if (reading.withheld)
5709
+ return true;
5710
+ const text = reading.text;
5711
+ const r = scanAndMask(text, scanOptionsOf({}, publicFace({}), 'strict', true), true);
5712
+ const origin = r.origin;
5713
+ if (r.text === text || origin === undefined)
5714
+ return false;
5715
+ let prevVisible = -1;
5716
+ for (let k = 0; k < r.text.length;) {
5717
+ const o = origin[k] ?? -1;
5718
+ if (o >= 0) {
5719
+ prevVisible = o;
5720
+ k++;
5721
+ continue;
5722
+ }
5723
+ let e = k;
5724
+ while (e < r.text.length && (origin[e] ?? -1) < 0)
5725
+ e++;
5726
+ const hiddenStart = prevVisible + 1;
5727
+ const hiddenEnd = e < r.text.length ? (origin[e] ?? text.length) : text.length;
5728
+ const shown = r.text.slice(k, e);
5729
+ const re = new RegExp(MARKER_ANYWHERE.source, MARKER_ANYWHERE.flags);
5730
+ for (let m = re.exec(shown); m !== null; m = re.exec(shown)) {
5731
+ const kind = KIND_BY_TEXT.get(m[0]);
5732
+ if (kind === 'userinfo' || kind === 'query' || kind === 'secret')
5733
+ return true;
5734
+ if (kind === 'fragment') {
5735
+ if (hiddenStart === 0 || text[hiddenStart - 1] !== '#')
5736
+ return true;
5737
+ if (queryCarriesCredential(text.slice(hiddenStart, hiddenEnd)))
5738
+ return true;
5739
+ }
5740
+ }
5741
+ k = e;
5742
+ }
5743
+ return false;
5014
5744
  }
5015
5745
  export function quoteUntrustedForSentence(text, max) {
5016
5746
  const shown = displayUntrusted(text, { max, blanks: true, escapeBackslashes: true });