@sema-agent/client-core 0.93.0 → 0.94.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 (156) hide show
  1. package/CHANGELOG.md +261 -0
  2. package/README.md +31 -18
  3. package/dist/adapt/arms.js +8 -5
  4. package/dist/adapter/downstream/terminalToSdkResult.js +2 -3
  5. package/dist/agentSession/engineSessionBackgroundStop.js +2 -1
  6. package/dist/agentsWireCaps.d.ts +15 -0
  7. package/dist/agentsWireCaps.js +111 -1
  8. package/dist/approvalReachWire.d.ts +18 -0
  9. package/dist/approvalReachWire.js +58 -0
  10. package/dist/approvalsStreamLiveCapability.js +16 -11
  11. package/dist/callerCwdCapability.d.ts +16 -0
  12. package/dist/callerCwdCapability.js +47 -0
  13. package/dist/controlRouter.js +3 -10
  14. package/dist/coreValuePorts.d.ts +64 -1
  15. package/dist/coreValuePorts.js +30 -0
  16. package/dist/detachWire.d.ts +1 -4
  17. package/dist/detachWire.js +1 -1
  18. package/dist/deviceExecutorManagementCapability.js +39 -34
  19. package/dist/deviceFlowPolling.d.ts +5 -0
  20. package/dist/deviceFlowPolling.js +28 -0
  21. package/dist/displayUntrusted.js +652 -21
  22. package/dist/engineErrorCodes.d.ts +5 -1
  23. package/dist/engineErrorCodes.js +9 -12
  24. package/dist/engineNoticeCodes.d.ts +22 -2
  25. package/dist/engineNoticeCodes.js +73 -6
  26. package/dist/engineRefusedToolName.d.ts +1 -0
  27. package/dist/engineRefusedToolName.js +8 -0
  28. package/dist/executionLaneCapability.js +14 -9
  29. package/dist/fileHistoryCaptureCapability.js +14 -9
  30. package/dist/fileHistoryLegNotice.d.ts +11 -0
  31. package/dist/fileHistoryLegNotice.js +50 -13
  32. package/dist/fleet/fleetLedger.js +5 -0
  33. package/dist/gateOutcome.d.ts +2 -1
  34. package/dist/gateOutcome.js +3 -0
  35. package/dist/gateVocabulary.js +1 -1
  36. package/dist/generated/engineAskFaceTables.d.ts +3 -0
  37. package/dist/generated/engineAskFaceTables.js +12 -0
  38. package/dist/generated/engineFactTables.d.ts +4 -2
  39. package/dist/generated/engineFactTables.js +13 -0
  40. package/dist/generated/engineNoticeTables.d.ts +5 -0
  41. package/dist/generated/engineNoticeTables.js +7 -0
  42. package/dist/generated/sdkFactTables.d.ts +3 -0
  43. package/dist/generated/sdkFactTables.js +17 -0
  44. package/dist/generated/settingsSchemaTables.d.ts +3 -0
  45. package/dist/generated/settingsSchemaTables.js +3 -0
  46. package/dist/headlessPermissionModeWire.d.ts +2 -2
  47. package/dist/headlessPermissionModeWire.js +11 -21
  48. package/dist/hitl/approvalHolds.d.ts +36 -0
  49. package/dist/hitl/approvalHolds.js +89 -0
  50. package/dist/hitl/approvalOutcomeNote.js +2 -1
  51. package/dist/hitl/approvalResolution.d.ts +3 -2
  52. package/dist/hitl/approvalResolution.js +21 -0
  53. package/dist/hitl/approvalsFeed.js +5 -0
  54. package/dist/hitl/askGateWire.js +3 -0
  55. package/dist/hitl/automaticAnswerVerdict.d.ts +8 -2
  56. package/dist/hitl/automaticAnswerVerdict.js +69 -21
  57. package/dist/hitl/decisionRefusal.d.ts +19 -0
  58. package/dist/hitl/decisionRefusal.js +63 -0
  59. package/dist/hitl/frameRouter.d.ts +10 -0
  60. package/dist/hitl/frameRouter.js +59 -3
  61. package/dist/hitl/gateLedger.d.ts +3 -0
  62. package/dist/hitl/gateLedger.js +17 -0
  63. package/dist/hitl/hitlBridge.d.ts +2 -2
  64. package/dist/hitl/hitlBridge.js +8 -10
  65. package/dist/hitl/hitlHostSurface.d.ts +6 -0
  66. package/dist/hitl/hitlHostSurface.js +25 -4
  67. package/dist/hitl/localAllowRule.js +2 -1
  68. package/dist/hitl/noAllowCause.d.ts +9 -0
  69. package/dist/hitl/noAllowCause.js +26 -0
  70. package/dist/hitl/parkResolver.js +6 -3
  71. package/dist/hitl/parkRowBirthWait.js +2 -1
  72. package/dist/hitl/persistedRulesWire.d.ts +6 -1
  73. package/dist/hitl/persistedRulesWire.js +12 -4
  74. package/dist/hitl/planReviewWire.d.ts +0 -1
  75. package/dist/hitl/planReviewWire.js +30 -9
  76. package/dist/hitl/sessionPolicyDeliverable.d.ts +1 -1
  77. package/dist/hitl/sessionPolicyDeliverable.js +3 -8
  78. package/dist/hitl/sessionPolicyWire.js +1 -1
  79. package/dist/hitl/toolApprovalWire.d.ts +37 -2
  80. package/dist/hitl/toolApprovalWire.js +392 -13
  81. package/dist/humanTurnRead.d.ts +15 -1
  82. package/dist/humanTurnRead.js +28 -2
  83. package/dist/index.d.ts +18 -6
  84. package/dist/index.js +14 -5
  85. package/dist/limitsWire.d.ts +0 -1
  86. package/dist/limitsWire.js +2 -10
  87. package/dist/liveModelCatalog.d.ts +14 -0
  88. package/dist/liveModelCatalog.js +61 -0
  89. package/dist/mcpProbeCapability.js +14 -9
  90. package/dist/mcpReconnect.js +13 -8
  91. package/dist/memoryComplianceCapability.js +15 -10
  92. package/dist/memoryOriginCapability.js +15 -10
  93. package/dist/modelIdentityResolvability.d.ts +4 -2
  94. package/dist/modelIdentityResolvability.js +31 -4
  95. package/dist/outputStyleSeatCapability.d.ts +16 -0
  96. package/dist/outputStyleSeatCapability.js +47 -0
  97. package/dist/ownKey.d.ts +1 -0
  98. package/dist/ownKey.js +10 -0
  99. package/dist/peerLaneCapability.js +16 -11
  100. package/dist/permissionRuleIssue.js +1 -1
  101. package/dist/permissionRulesWriteCapability.js +16 -11
  102. package/dist/permissionsAllowGrantCapability.d.ts +2 -0
  103. package/dist/permissionsAllowGrantCapability.js +38 -16
  104. package/dist/permissionsDeclaration.d.ts +10 -1
  105. package/dist/permissionsDeclaration.js +97 -15
  106. package/dist/protocolSegment.d.ts +1 -0
  107. package/dist/protocolSegment.js +13 -1
  108. package/dist/request/taskRequest.d.ts +11 -3
  109. package/dist/request/taskRequest.js +13 -1
  110. package/dist/resultFrameKeys.d.ts +4 -0
  111. package/dist/resultFrameKeys.js +13 -0
  112. package/dist/resumeRefusalCopy.js +6 -16
  113. package/dist/retryStatus.js +6 -4
  114. package/dist/rewindArchiveCapability.js +13 -8
  115. package/dist/{hitl/rosterMountedNames.d.ts → rosterMountedNames.d.ts} +1 -1
  116. package/dist/runCancelContext.js +2 -1
  117. package/dist/sealedKeyCapability.js +19 -14
  118. package/dist/seatContract.d.ts +33 -5
  119. package/dist/seatContract.js +143 -2
  120. package/dist/sessionPolicyCapability.js +15 -10
  121. package/dist/sessionReadRedactionCapability.d.ts +16 -0
  122. package/dist/sessionReadRedactionCapability.js +47 -0
  123. package/dist/sessionSyncFileHistoryCapability.js +14 -9
  124. package/dist/skillToolListsCapability.js +14 -9
  125. package/dist/sqlEngineCapability.js +18 -13
  126. package/dist/steerPriorityCapability.js +21 -16
  127. package/dist/subagent/agentStateDetail.d.ts +1 -0
  128. package/dist/subagent/agentStateDetail.js +41 -0
  129. package/dist/subagent/engineCompactWire.d.ts +15 -0
  130. package/dist/subagent/engineCompactWire.js +75 -13
  131. package/dist/supportFloor.js +1 -1
  132. package/dist/taskRequestWords.d.ts +2 -4
  133. package/dist/taskRequestWords.js +3 -2
  134. package/dist/types/engineState.d.ts +1 -1
  135. package/dist/userAttachmentEnvelope.d.ts +22 -1
  136. package/dist/userAttachmentEnvelope.js +90 -2
  137. package/dist/userInvokedSkillsCapability.js +14 -9
  138. package/dist/webSearchBackendCapability.js +21 -16
  139. package/dist/wireErrorTriage.d.ts +11 -0
  140. package/dist/wireErrorTriage.js +35 -0
  141. package/dist/wireFailureShape.d.ts +6 -0
  142. package/dist/wireFailureShape.js +30 -3
  143. package/dist/wireRefusalCopy.d.ts +6 -1
  144. package/dist/wireRefusalCopy.js +22 -8
  145. package/dist/wiringInstructionsAttribution.d.ts +10 -0
  146. package/dist/wiringInstructionsAttribution.js +67 -0
  147. package/dist/workflowClient.js +22 -1
  148. package/dist/workflowsJournalCapability.js +14 -9
  149. package/dist/writeProtectionCapability.js +28 -23
  150. package/docs/INTEGRATION-CLIENTS.md +817 -45
  151. package/package.json +5 -5
  152. package/dist/askSurvivesStandingAnswer.d.ts +0 -13
  153. package/dist/askSurvivesStandingAnswer.js +0 -53
  154. package/dist/hitl/askSurvivesPosture.d.ts +0 -20
  155. package/dist/hitl/askSurvivesPosture.js +0 -48
  156. /package/dist/{hitl/rosterMountedNames.js → rosterMountedNames.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { SETTINGS_SECRET_LITERAL_RE } from './generated/settingsSchemaTables.js';
1
+ import { SETTINGS_PRIVATE_KEY_PEM_HEADER, SETTINGS_SECRET_LITERAL_RE } from './generated/settingsSchemaTables.js';
2
2
  export const REDACTION_MARKER_PREFIX = '\u00abredacted';
3
3
  const MARKER_RE = /^\u00abredacted(?::[a-z-]{1,16}){0,2}\u00bb$/;
4
4
  const REDACTED_USERINFO = '\u00abredacted:userinfo\u00bb';
@@ -28,9 +28,12 @@ const UNIT_NONE = 0;
28
28
  const UNIT_SEQUENCE = 1;
29
29
  const UNIT_SINGLE = 2;
30
30
  const SECRET_LITERAL_RE = SETTINGS_SECRET_LITERAL_RE;
31
+ const PRIVATE_KEY_PEM_HEADER = SETTINGS_PRIVATE_KEY_PEM_HEADER;
31
32
  const SCHEME_TOKEN_RE = /(?:^|[^A-Za-z0-9_-])(?:bearer|basic)[ \t]+\S{8,4096}/i;
32
33
  const JWT_RE = /(?:^|[^A-Za-z0-9_-])eyJ[A-Za-z0-9_-]{8,2048}\.[A-Za-z0-9_-]{8,2048}\.[A-Za-z0-9_-]{4,2048}/i;
33
34
  function scanForSecretLiteral(s) {
35
+ if (PRIVATE_KEY_PEM_HEADER.test(s))
36
+ return true;
34
37
  if (SECRET_LITERAL_RE.test(s) || SCHEME_TOKEN_RE.test(s) || JWT_RE.test(s))
35
38
  return true;
36
39
  return s.split(/[^A-Za-z0-9_-]+/).some(tok => tok !== '' && SECRET_LITERAL_RE.test(tok));
@@ -1474,6 +1477,453 @@ function quotedAddressEnd(S, from, to) {
1474
1477
  }
1475
1478
  return to;
1476
1479
  }
1480
+ function isInlineBlank(ch) {
1481
+ if (ch === VIEW_SEPARATOR)
1482
+ return true;
1483
+ const c = ch.charCodeAt(0);
1484
+ if (c === 0x0a || c === 0x0d || c === 0x2028 || c === 0x2029)
1485
+ return false;
1486
+ return isRegexSpace(c) || isNameBlank(c);
1487
+ }
1488
+ const isAnyBlank = (ch) => ch === VIEW_SEPARATOR || isRegexSpace(ch.charCodeAt(0)) || isNameBlank(ch.charCodeAt(0));
1489
+ function nodePropertyEnd(text, at) {
1490
+ const sigil = text.charAt(at);
1491
+ let j = at + 1;
1492
+ if (sigil === '!') {
1493
+ if (text.charAt(j) === '<') {
1494
+ const limit = Math.min(text.length, j + 512);
1495
+ let k = j + 1;
1496
+ while (k < limit && text.charAt(k) !== '>' && !isAnyBlank(text.charAt(k)))
1497
+ k++;
1498
+ if (text.charAt(k) !== '>' || k === j + 1)
1499
+ return -1;
1500
+ j = k + 1;
1501
+ }
1502
+ else {
1503
+ while (j < text.length && !isBareValueStop(text.charAt(j)))
1504
+ j++;
1505
+ }
1506
+ }
1507
+ else if (sigil === '&') {
1508
+ while (j < text.length && !isBareValueStop(text.charAt(j)))
1509
+ j++;
1510
+ if (j === at + 1)
1511
+ return -1;
1512
+ }
1513
+ else
1514
+ return -1;
1515
+ return j < text.length && isInlineBlank(text.charAt(j)) ? j : -1;
1516
+ }
1517
+ function nodeProperties(text, from) {
1518
+ let i = from;
1519
+ while (text.charAt(i) === VIEW_SEPARATOR)
1520
+ i++;
1521
+ const start = i;
1522
+ let end = -1;
1523
+ for (;;) {
1524
+ const c = text.charAt(i);
1525
+ if (c !== '!' && c !== '&')
1526
+ break;
1527
+ const e = nodePropertyEnd(text, i);
1528
+ if (e === -1)
1529
+ break;
1530
+ end = e;
1531
+ i = e;
1532
+ while (i < text.length && isInlineBlank(text.charAt(i)))
1533
+ i++;
1534
+ }
1535
+ return end === -1 ? null : { start, end, next: i };
1536
+ }
1537
+ function propertiesSameLine(S, pr) {
1538
+ if (pr.next >= S.text.length)
1539
+ return false;
1540
+ const a = S.rawStart(pr.start);
1541
+ const b = S.rawStart(pr.next);
1542
+ return b >= a && !/[\n\r\u2028\u2029\u0085]/.test(S.raw.slice(a, b));
1543
+ }
1544
+ function hasValueAt(text, at) {
1545
+ if (at >= text.length)
1546
+ return false;
1547
+ const c = text.charAt(at);
1548
+ if (c === '|' || c === '>' || c === '[' || c === '\\' || isQuoteChar(c))
1549
+ return true;
1550
+ return !isBareValueStop(c) && c !== VIEW_SEPARATOR;
1551
+ }
1552
+ const SGR_REMNANT = /^\[[0-9;]*m(?:\u00abredacted|\s|$)/;
1553
+ function bracketPairs(text) {
1554
+ const pairs = new Int32Array(text.length).fill(-1);
1555
+ const stack = [];
1556
+ for (let i = 0; i < text.length; i++) {
1557
+ const c = text.charCodeAt(i);
1558
+ if (c === 0x5b)
1559
+ stack.push(i);
1560
+ else if (c === 0x5d) {
1561
+ const o = stack.pop();
1562
+ if (o !== undefined)
1563
+ pairs[o] = i;
1564
+ }
1565
+ }
1566
+ return pairs;
1567
+ }
1568
+ const LIST_NEUTRAL_ITEM = /^(?:object Object|Object|Array|Circular|Getter|Setter|Getter\/Setter|native code|hidden|masked|omitted|truncated)$/i;
1569
+ function afterClosingQuote(text, end) {
1570
+ let k = end;
1571
+ while (text.charAt(k) === VIEW_SEPARATOR)
1572
+ k++;
1573
+ let q = k;
1574
+ while (text.charCodeAt(q) === 0x5c)
1575
+ q++;
1576
+ const c = text.charAt(q);
1577
+ return isQuoteChar(c) ? q + 1 : end;
1578
+ }
1579
+ function matchBrace(text, open) {
1580
+ let depth = 0;
1581
+ let quote = '';
1582
+ for (let i = open; i < text.length; i++) {
1583
+ const c = text.charAt(i);
1584
+ if (quote !== '') {
1585
+ if (c === '\\')
1586
+ i++;
1587
+ else if (c === quote)
1588
+ quote = '';
1589
+ continue;
1590
+ }
1591
+ if (isQuoteChar(c))
1592
+ quote = c;
1593
+ else if (c === '{')
1594
+ depth++;
1595
+ else if (c === '}' && --depth === 0)
1596
+ return i;
1597
+ }
1598
+ return text.length;
1599
+ }
1600
+ function flowListItems(text, open, idx, budget) {
1601
+ if (budget.left <= 0 || SGR_REMNANT.test(text.slice(open, open + 32)))
1602
+ return null;
1603
+ budget.pairs ??= bracketPairs(text);
1604
+ const plainClose = budget.pairs[open] ?? -1;
1605
+ if (plainClose >= 0 && text.charAt(plainClose + 1) === '(')
1606
+ return null;
1607
+ const out = flowListScan(text, open, idx);
1608
+ budget.left -= out.end - open;
1609
+ return out.link ? null : { items: out.items, end: out.end };
1610
+ }
1611
+ function flowListScan(text, open, idx) {
1612
+ const items = [];
1613
+ const n = text.length;
1614
+ let depth = 0;
1615
+ let i = open;
1616
+ while (i < n) {
1617
+ const ch = text.charAt(i);
1618
+ if (ch === '[') {
1619
+ depth++;
1620
+ i++;
1621
+ continue;
1622
+ }
1623
+ if (ch === ']') {
1624
+ depth--;
1625
+ i++;
1626
+ if (depth <= 0)
1627
+ return { items, end: i, link: text.charAt(i) === '(' };
1628
+ continue;
1629
+ }
1630
+ if (ch === ',' || ch === '}' || isAnyBlank(ch) || ch === '\n' || ch === '\r') {
1631
+ i++;
1632
+ continue;
1633
+ }
1634
+ const escapedBreak = ch === '\\' ? lineBreakLengthAt(text, i) : 0;
1635
+ if (escapedBreak > 0) {
1636
+ i += escapedBreak;
1637
+ continue;
1638
+ }
1639
+ if (ch === '{') {
1640
+ const e = matchBrace(text, i);
1641
+ if (e > i + 1)
1642
+ items.push({ start: i + 1, end: e });
1643
+ i = Math.min(n, e + 1);
1644
+ continue;
1645
+ }
1646
+ let q = i;
1647
+ while (text.charCodeAt(q) === 0x5c)
1648
+ q++;
1649
+ if (isQuoteChar(text.charAt(q))) {
1650
+ const v = scanSecretValue(text, i, idx);
1651
+ if (v === null) {
1652
+ i = q + 1;
1653
+ continue;
1654
+ }
1655
+ items.push({ start: v.start, end: v.end, quoted: true });
1656
+ i = Math.max(afterClosingQuote(text, v.end), i + 1);
1657
+ continue;
1658
+ }
1659
+ let j = i;
1660
+ while (j < n) {
1661
+ const c = text.charAt(j);
1662
+ if (c === ',' || c === ']' || c === '[' || c === '{' || c === '}' || c === '\n' || c === '\r' || (c === '\\' && lineBreakLengthAt(text, j) > 0))
1663
+ break;
1664
+ j++;
1665
+ }
1666
+ let e = j;
1667
+ while (e > i && isAnyBlank(text.charAt(e - 1)))
1668
+ e--;
1669
+ if (e > i)
1670
+ items.push({ start: i, end: e });
1671
+ i = j > i ? j : i + 1;
1672
+ }
1673
+ return { items, end: n, link: false };
1674
+ }
1675
+ const PAIR_ITEM = /^[A-Za-z_][A-Za-z0-9_.-]*(?:=|:(?!\/))[^\s,;]/;
1676
+ function lineBreakAtView(S, k) {
1677
+ const ch = S.text.charAt(k);
1678
+ if (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029')
1679
+ return true;
1680
+ if (ch !== VIEW_SEPARATOR)
1681
+ return false;
1682
+ const a = S.rawStart(k);
1683
+ return /[\n\r\u2028\u2029\u0085]/.test(S.raw.slice(a, Math.max(a + 1, S.rawEnd(k))));
1684
+ }
1685
+ function scanListItem(S, i, idx) {
1686
+ const text = S.text;
1687
+ const v = scanSecretValue(text, i, idx);
1688
+ if (v === null)
1689
+ return null;
1690
+ let q = i;
1691
+ while (text.charCodeAt(q) === 0x5c)
1692
+ q++;
1693
+ if (isQuoteChar(text.charAt(q)))
1694
+ return v;
1695
+ for (let k = v.start; k < v.end; k++) {
1696
+ if (text.charAt(k) !== VIEW_SEPARATOR || !lineBreakAtView(S, k))
1697
+ continue;
1698
+ let e = k;
1699
+ while (e > v.start && text.charAt(e - 1) === VIEW_SEPARATOR)
1700
+ e--;
1701
+ return e > v.start ? { start: v.start, end: e } : null;
1702
+ }
1703
+ return v;
1704
+ }
1705
+ function commaListTail(S, from, idx) {
1706
+ const text = S.text;
1707
+ const items = [];
1708
+ const n = text.length;
1709
+ let i = from;
1710
+ let end = from;
1711
+ for (;;) {
1712
+ let k = i;
1713
+ while (k < n && isInlineBlank(text.charAt(k)) && !lineBreakAtView(S, k))
1714
+ k++;
1715
+ if (text.charAt(k) !== ',')
1716
+ break;
1717
+ k++;
1718
+ while (k < n && isInlineBlank(text.charAt(k)) && !lineBreakAtView(S, k))
1719
+ k++;
1720
+ if (k >= n || credentialWordStartsAt(text, k, idx.tokenInner) || PAIR_ITEM.test(text.slice(k, k + 256)))
1721
+ break;
1722
+ let q = k;
1723
+ while (text.charCodeAt(q) === 0x5c)
1724
+ q++;
1725
+ const quotedItem = isQuoteChar(text.charAt(q));
1726
+ if (q > k && !quotedItem)
1727
+ break;
1728
+ const v = scanListItem(S, k, idx);
1729
+ if (v === null)
1730
+ break;
1731
+ const after = quotedItem ? afterClosingQuote(text, v.end) : v.end;
1732
+ let t = after;
1733
+ let lineEnd = false;
1734
+ while (t < n && isInlineBlank(text.charAt(t))) {
1735
+ if (lineBreakAtView(S, t)) {
1736
+ lineEnd = true;
1737
+ break;
1738
+ }
1739
+ t++;
1740
+ }
1741
+ const term = text.charAt(t);
1742
+ const stops = lineEnd || t >= n || term === ',' || term === ';' || term === ')' || term === ']' || term === '}' || term === '\\' || isQuoteChar(term) || term === '\n' || term === '\r';
1743
+ if (!stops)
1744
+ break;
1745
+ items.push(v);
1746
+ i = after;
1747
+ end = after;
1748
+ }
1749
+ return { items, end };
1750
+ }
1751
+ function viewIndexOfRaw(S, p) {
1752
+ let lo = 0;
1753
+ let hi = S.text.length;
1754
+ while (lo < hi) {
1755
+ const mid = (lo + hi) >> 1;
1756
+ if (S.rawStart(mid) < p)
1757
+ lo = mid + 1;
1758
+ else
1759
+ hi = mid;
1760
+ }
1761
+ while (lo < S.text.length && S.text.charAt(lo) === VIEW_SEPARATOR)
1762
+ lo++;
1763
+ return lo;
1764
+ }
1765
+ function dotsBeforeMarker(raw, p) {
1766
+ let k = p;
1767
+ while (raw.charCodeAt(k) === 0x2e)
1768
+ k++;
1769
+ if (k === p)
1770
+ return p;
1771
+ let m = k;
1772
+ while (m < k + 3 && (raw.charCodeAt(m) === 0x5c || raw.charCodeAt(m) === 0x22 || raw.charCodeAt(m) === 0x27))
1773
+ m++;
1774
+ if (raw.startsWith(REDACTION_MARKER_PREFIX, m) || /^\[[0-9;]{0,12}m\u00abredacted/.test(raw.slice(k, k + 24)))
1775
+ return k;
1776
+ return p;
1777
+ }
1778
+ function escapedBlankLen(raw, p) {
1779
+ if (raw.charCodeAt(p) !== 0x5c || raw.charCodeAt(p + 1) !== 0x75)
1780
+ return 0;
1781
+ const hex = raw.slice(p + 2, p + 6);
1782
+ return /^[0-9A-Fa-f]{4}$/.test(hex) && isRawBlank(Number.parseInt(hex, 16)) ? 6 : 0;
1783
+ }
1784
+ function dotsBeforeDash(raw, p) {
1785
+ let k = p;
1786
+ while (raw.charCodeAt(k) === 0x2e)
1787
+ k++;
1788
+ return k > p && raw.charCodeAt(k) === 0x2d ? k : p;
1789
+ }
1790
+ function dashEntryAt(scan, p, escaped) {
1791
+ const raw = scan.raw;
1792
+ if (raw.charCodeAt(p) !== 0x2d)
1793
+ return false;
1794
+ if (p + 1 >= raw.length)
1795
+ return true;
1796
+ return isRawBlank(raw.charCodeAt(p + 1)) || scan.view.rawUnit[p + 1] === 1 || blockBreakAt(raw, p + 1, escaped) > 0 || escapedBlankLen(raw, p + 1) > 0 || dotsBeforeMarker(raw, p + 1) !== p + 1;
1797
+ }
1798
+ function lineContentStart(scan, lines, i, skipDots = true) {
1799
+ const raw = scan.raw;
1800
+ const unit = scan.view.rawUnit;
1801
+ const { seq, payload } = blockMarks(scan);
1802
+ const end = lines.ends[i] ?? raw.length;
1803
+ let k = lines.starts[i] ?? 0;
1804
+ while (k < end) {
1805
+ if (payload[k] === 1)
1806
+ break;
1807
+ if (seq[k] === 1 || isRawBlank(raw.charCodeAt(k)) || unit[k] === 1)
1808
+ k++;
1809
+ else if (escapedBlankLen(raw, k) > 0)
1810
+ k += 6;
1811
+ else
1812
+ break;
1813
+ }
1814
+ return skipDots && k < end ? dotsBeforeDash(raw, k) : k;
1815
+ }
1816
+ function seqLineIndent(scan, lines, i) {
1817
+ const base = lines.indent[i] ?? -1;
1818
+ if (base < 0)
1819
+ return base;
1820
+ const raw = scan.raw;
1821
+ const unit = scan.view.rawUnit;
1822
+ const { seq, payload } = blockMarks(scan);
1823
+ const end = lines.ends[i] ?? raw.length;
1824
+ let k = lines.starts[i] ?? 0;
1825
+ let width = 0;
1826
+ while (k < end) {
1827
+ if (payload[k] === 1)
1828
+ break;
1829
+ if (escapedBlankLen(raw, k) > 0) {
1830
+ width++;
1831
+ k += 6;
1832
+ }
1833
+ else if (seq[k] === 1)
1834
+ k++;
1835
+ else if (isRawBlank(raw.charCodeAt(k))) {
1836
+ width++;
1837
+ k++;
1838
+ }
1839
+ else if (unit[k] === 1)
1840
+ k++;
1841
+ else
1842
+ break;
1843
+ }
1844
+ if (k < end) {
1845
+ const d = dotsBeforeDash(raw, k);
1846
+ width += d - k;
1847
+ }
1848
+ return width;
1849
+ }
1850
+ function blockSeqEntries(scan, rawFrom, rawLabel) {
1851
+ const raw = scan.raw;
1852
+ const unit = scan.view.rawUnit;
1853
+ let p = dotsBeforeDash(raw, rawFrom);
1854
+ let escaped = false;
1855
+ if (raw.charCodeAt(p) === 0x5c && lineBreakLengthAt(raw, p) > 0) {
1856
+ escaped = true;
1857
+ for (;;) {
1858
+ const n = lineBreakLengthAt(raw, p);
1859
+ if (n === 0 || raw.charCodeAt(p) !== 0x5c)
1860
+ break;
1861
+ p += n;
1862
+ while (p < raw.length && (isRawBlank(raw.charCodeAt(p)) || unit[p] === 1 || escapedBlankLen(raw, p) > 0)) {
1863
+ const n = escapedBlankLen(raw, p);
1864
+ p += n > 0 ? n : 1;
1865
+ }
1866
+ p = dotsBeforeDash(raw, p);
1867
+ }
1868
+ }
1869
+ if (!dashEntryAt(scan, p, escaped))
1870
+ return null;
1871
+ const lines = blockLines(scan, escaped);
1872
+ const first = blockLineOf(lines, p);
1873
+ const labelLine = blockLineOf(lines, rawLabel);
1874
+ const labelIndent = Math.max(0, lines.indent[labelLine] ?? 0);
1875
+ const entryIndent = seqLineIndent(scan, lines, first);
1876
+ const labelHead = lineContentStart(scan, lines, labelLine, false);
1877
+ const labelFirst = rawLabel >= labelHead && !/\s/.test(raw.slice(labelHead, rawLabel));
1878
+ if (lineContentStart(scan, lines, first) !== p || entryIndent < 0 || (labelFirst ? entryIndent < labelIndent : entryIndent <= labelIndent))
1879
+ return null;
1880
+ const out = [];
1881
+ const work = [first];
1882
+ const total = lines.starts.length;
1883
+ while (work.length > 0) {
1884
+ let i = work.pop() ?? total;
1885
+ const ind = seqLineIndent(scan, lines, i);
1886
+ while (i < total) {
1887
+ const dash = lineContentStart(scan, lines, i);
1888
+ const end = lines.ends[i] ?? raw.length;
1889
+ let v = dash + 1;
1890
+ while (v < end && (isRawBlank(raw.charCodeAt(v)) || unit[v] === 1 || escapedBlankLen(raw, v) > 0)) {
1891
+ const n = escapedBlankLen(raw, v);
1892
+ v += n > 0 ? n : 1;
1893
+ }
1894
+ v = dotsBeforeMarker(raw, v);
1895
+ if (v < end) {
1896
+ let whole = -1;
1897
+ if (dashEntryAt(scan, v, escaped)) {
1898
+ let last = (lines.outOf[i] ?? total) - 1;
1899
+ while (last > i && (lines.indent[last] ?? -1) === -1)
1900
+ last--;
1901
+ whole = lines.ends[last] ?? end;
1902
+ }
1903
+ out.push({ dash, value: v, whole });
1904
+ }
1905
+ else {
1906
+ const k = lines.nextContent[i + 1] ?? total;
1907
+ if (k < total && seqLineIndent(scan, lines, k) > ind) {
1908
+ const kp = lineContentStart(scan, lines, k);
1909
+ if (dashEntryAt(scan, kp, escaped)) {
1910
+ out.push({ dash, value: -1, whole: -1 });
1911
+ work.push(k);
1912
+ }
1913
+ else
1914
+ out.push({ dash, value: kp, whole: -1 });
1915
+ }
1916
+ else
1917
+ out.push({ dash, value: -1, whole: -1 });
1918
+ }
1919
+ const j = lines.outOf[i] ?? total;
1920
+ if (j >= total || seqLineIndent(scan, lines, j) !== ind || !dashEntryAt(scan, lineContentStart(scan, lines, j), escaped))
1921
+ break;
1922
+ i = j;
1923
+ }
1924
+ }
1925
+ return out;
1926
+ }
1477
1927
  function labelCandidates(S, pass, regions, out, blocks) {
1478
1928
  const text = S.text;
1479
1929
  const unitAt = (k) => S.unitAt(k);
@@ -1481,6 +1931,11 @@ function labelCandidates(S, pass, regions, out, blocks) {
1481
1931
  const schemePass = pass !== 'label';
1482
1932
  const tokenPass = pass === 'token';
1483
1933
  const idx = new InnerWordIndex(text, tokenPass);
1934
+ let listIdx = null;
1935
+ const listIndex = () => (listIdx ??= new InnerWordIndex(text, idx.tokenInner));
1936
+ let skipFrom = -1;
1937
+ let skipTo = -1;
1938
+ const flowBudget = { left: 4 * text.length + 4096, pairs: null };
1484
1939
  const extensionCache = new Map();
1485
1940
  let stops;
1486
1941
  const push = (start, end, kindText, te = -1, cls) => {
@@ -1603,6 +2058,88 @@ function labelCandidates(S, pass, regions, out, blocks) {
1603
2058
  r0++;
1604
2059
  maskGaps(r0, outerEnd);
1605
2060
  };
2061
+ const itemNeutral = (a, b) => {
2062
+ const rawItem = text.slice(a, b);
2063
+ const item = withoutSeparators(rawItem).trim();
2064
+ if (item === '')
2065
+ return true;
2066
+ return valueIsWholeMarker(S, a, b, idx.tokenInner) || MARKER_WITH_DOTS.test(item) || isDiagnosticValue(item, rawItem) || LIST_NEUTRAL_ITEM.test(item);
2067
+ };
2068
+ const flowListLike = (label, items) => {
2069
+ if (/s$/i.test(label) || items.length !== 1)
2070
+ return true;
2071
+ const only = items[0];
2072
+ return only === undefined || only.quoted === true || !/\s/.test(withoutSeparators(text.slice(only.start, only.end)).trim());
2073
+ };
2074
+ const listMask = (label, spans, valueLike) => {
2075
+ const neutral = spans.map((s) => itemNeutral(s.start, s.end));
2076
+ const names = !valueLike && spans.every((s, i) => neutral[i] === true || isNamedNotValue(label, withoutSeparators(text.slice(s.start, s.end)).trim()));
2077
+ return spans.map((_, i) => !names && neutral[i] !== true);
2078
+ };
2079
+ const seqItems = (scan, ents, label) => {
2080
+ const li = listIndex();
2081
+ const spans = [];
2082
+ let valueLike = false;
2083
+ for (const e of ents) {
2084
+ if (e.value < 0)
2085
+ continue;
2086
+ if (e.whole >= 0) {
2087
+ scan.out.push({ start: e.value, end: e.whole, kind: 'secret', cls: 'word', tokenEnd: e.whole, pretrimmed: true });
2088
+ valueLike = true;
2089
+ continue;
2090
+ }
2091
+ let vi = viewIndexOfRaw(S, e.value);
2092
+ if (vi >= text.length)
2093
+ continue;
2094
+ const pr = nodeProperties(text, vi);
2095
+ if (pr !== null && hasValueAt(text, pr.next) && propertiesSameLine(S, pr)) {
2096
+ push(pr.start, pr.end, REDACTED_SECRET);
2097
+ vi = pr.next;
2098
+ }
2099
+ const c = text.charAt(vi);
2100
+ if (c === '|' || c === '>') {
2101
+ const blk = blockScalarExtent(scan, S.rawStart(vi), e.dash);
2102
+ if (blk !== null) {
2103
+ scan.out.push({ start: blk.start, end: blk.end, kind: 'secret', cls: 'word', tokenEnd: blk.end, pretrimmed: true });
2104
+ valueLike = true;
2105
+ continue;
2106
+ }
2107
+ }
2108
+ if (c === '[') {
2109
+ const fl = flowListItems(text, vi, li, flowBudget);
2110
+ if (fl !== null && flowListLike(label, fl.items)) {
2111
+ for (const it of fl.items)
2112
+ spans.push(it);
2113
+ continue;
2114
+ }
2115
+ }
2116
+ if (c === '{') {
2117
+ const close = matchBrace(text, vi);
2118
+ if (close > vi + 1)
2119
+ spans.push({ start: vi + 1, end: close });
2120
+ continue;
2121
+ }
2122
+ if (c === '*')
2123
+ continue;
2124
+ let q = vi;
2125
+ while (text.charCodeAt(q) === 0x5c)
2126
+ q++;
2127
+ const quotedItem = isQuoteChar(text.charAt(q));
2128
+ const v = scanListItem(S, vi, li);
2129
+ if (v === null)
2130
+ continue;
2131
+ const keyAt = quotedItem ? afterClosingQuote(text, v.end) : v.end - 1;
2132
+ const keyNext = text.charAt(keyAt + 1);
2133
+ if (text.charAt(keyAt) === ':' && (keyAt + 1 >= text.length || isAnyBlank(keyNext) || keyNext === '\n' || keyNext === '\r'))
2134
+ continue;
2135
+ spans.push(v);
2136
+ }
2137
+ const flags = listMask(label, spans, valueLike);
2138
+ spans.forEach((s, i) => {
2139
+ if (flags[i] === true)
2140
+ push(s.start, s.end, REDACTED_SECRET);
2141
+ });
2142
+ };
1606
2143
  const regionKind = regions.length === 0 ? null : new Uint8Array(text.length);
1607
2144
  if (regionKind !== null)
1608
2145
  for (const r of regions)
@@ -1632,8 +2169,10 @@ function labelCandidates(S, pass, regions, out, blocks) {
1632
2169
  return a;
1633
2170
  };
1634
2171
  re.lastIndex = 0;
1635
- for (let hit = re.exec(text); hit !== null; hit = re.exec(text)) {
2172
+ hits: for (let hit = re.exec(text); hit !== null; hit = re.exec(text)) {
1636
2173
  const label = hit[1] ?? '';
2174
+ if (hit.index >= skipFrom && hit.index < skipTo)
2175
+ continue;
1637
2176
  if (schemePass && (label.toLowerCase() === 'token') !== tokenPass)
1638
2177
  continue;
1639
2178
  if (isTokenCountLabel(text, hit.index, label))
@@ -1642,16 +2181,67 @@ function labelCandidates(S, pass, regions, out, blocks) {
1642
2181
  continue;
1643
2182
  if (schemePass && labelStartsAt(text, hit.index))
1644
2183
  continue;
1645
- const from = hit.index + hit[0].length;
1646
- if (blocks !== undefined && (text.charCodeAt(from) === 0x7c || text.charCodeAt(from) === 0x3e) && isColonSeparator(hit[0].slice((hit[1] ?? '').length))) {
1647
- const blk = blockScalarExtent(blocks, S.rawStart(from), S.rawStart(hit.index));
1648
- if (blk !== null)
1649
- blocks.out.push({ start: blk.start, end: blk.end, kind: 'secret', cls: 'word', tokenEnd: blk.end, pretrimmed: true });
1650
- }
1651
- if (credentialWordStartsAt(text, from, idx.tokenInner)) {
1652
- pushInnerRemainder(from);
1653
- re.lastIndex = from;
1654
- continue;
2184
+ let from = hit.index + hit[0].length;
2185
+ const colonSep = isColonSeparator(hit[0].slice((hit[1] ?? '').length));
2186
+ let bulletSkipped = false;
2187
+ for (;;) {
2188
+ if (colonSep) {
2189
+ const pr = nodeProperties(text, from);
2190
+ if (pr !== null && hasValueAt(text, pr.next) && propertiesSameLine(S, pr) && !credentialWordStartsAt(text, pr.next, idx.tokenInner)) {
2191
+ push(pr.start, pr.end, REDACTED_SECRET);
2192
+ from = pr.next;
2193
+ }
2194
+ }
2195
+ if (blocks !== undefined && (text.charCodeAt(from) === 0x7c || text.charCodeAt(from) === 0x3e) && colonSep) {
2196
+ const blk = blockScalarExtent(blocks, S.rawStart(from), S.rawStart(hit.index));
2197
+ if (blk !== null)
2198
+ blocks.out.push({ start: blk.start, end: blk.end, kind: 'secret', cls: 'word', tokenEnd: blk.end, pretrimmed: true });
2199
+ }
2200
+ if (credentialWordStartsAt(text, from, idx.tokenInner)) {
2201
+ pushInnerRemainder(from);
2202
+ re.lastIndex = from;
2203
+ continue hits;
2204
+ }
2205
+ if (!schemePass && text.charAt(from) === '[') {
2206
+ const fl = flowListItems(text, from, listIndex(), flowBudget);
2207
+ if (fl !== null && flowListLike(label, fl.items)) {
2208
+ const flags = listMask(label, fl.items, false);
2209
+ fl.items.forEach((s, i) => {
2210
+ if (flags[i] === true)
2211
+ push(s.start, s.end, REDACTED_SECRET);
2212
+ });
2213
+ re.lastIndex = Math.max(fl.end, from);
2214
+ continue hits;
2215
+ }
2216
+ }
2217
+ if (!schemePass && colonSep && blocks !== undefined && (text.charAt(from) === '-' || text.charAt(from) === '\\' || text.charAt(from) === '.')) {
2218
+ const ents = blockSeqEntries(blocks, S.rawStart(from), S.rawStart(hit.index));
2219
+ if (ents !== null) {
2220
+ seqItems(blocks, ents, label);
2221
+ re.lastIndex = from;
2222
+ continue hits;
2223
+ }
2224
+ }
2225
+ if (!(colonSep && text.charAt(from) === '-' && from + 1 < text.length))
2226
+ break;
2227
+ const afterDots = dotsBeforeMarker(text, from + 1);
2228
+ if (!(isInlineBlank(text.charAt(from + 1)) || S.gapAfter(from) || afterDots !== from + 1))
2229
+ break;
2230
+ let b = afterDots;
2231
+ while (b < text.length && isInlineBlank(text.charAt(b)))
2232
+ b++;
2233
+ if (b >= text.length || isAnyBlank(text.charAt(b)))
2234
+ break;
2235
+ from = b;
2236
+ bulletSkipped = true;
2237
+ }
2238
+ if (bulletSkipped) {
2239
+ const first = scanListItem(S, from, listIndex());
2240
+ const j = first === null ? from : first.end;
2241
+ if (j > from + 1 && text.charAt(j - 1) === ':' && (j >= text.length || isAnyBlank(text.charAt(j)))) {
2242
+ re.lastIndex = from;
2243
+ continue;
2244
+ }
1655
2245
  }
1656
2246
  let v0s = scanSecretValue(text, from, idx);
1657
2247
  if (v0s === null) {
@@ -1702,6 +2292,23 @@ function labelCandidates(S, pass, regions, out, blocks) {
1702
2292
  continue;
1703
2293
  }
1704
2294
  }
2295
+ let forceFirstMask = false;
2296
+ if (!schemePass && /s$/i.test(label) && !inQuery(v.start)) {
2297
+ const afterFirst = quoted ? afterClosingQuote(text, v0.end) : v0.end;
2298
+ const tail = commaListTail(S, afterFirst, listIndex());
2299
+ if (tail.items.length > 0) {
2300
+ const spans = [{ start: v.start, end: v.end }, ...tail.items];
2301
+ const flags = listMask(label, spans, false);
2302
+ for (let i = 1; i < spans.length; i++) {
2303
+ const s = spans[i];
2304
+ if (s !== undefined && flags[i] === true)
2305
+ push(s.start, s.end, REDACTED_SECRET);
2306
+ }
2307
+ forceFirstMask = flags[0] === true;
2308
+ skipFrom = afterFirst;
2309
+ skipTo = tail.end;
2310
+ }
2311
+ }
1705
2312
  if (valueIsWholeMarker(S, v.start, v.end, idx.tokenInner)) {
1706
2313
  re.lastIndex = quoted ? from : v.end;
1707
2314
  continue;
@@ -1757,7 +2364,7 @@ function labelCandidates(S, pass, regions, out, blocks) {
1757
2364
  re.lastIndex = v.end;
1758
2365
  continue;
1759
2366
  }
1760
- if (!schemePass && isNamedNotValue(label, value)) {
2367
+ if (!schemePass && !forceFirstMask && isNamedNotValue(label, value)) {
1761
2368
  re.lastIndex = v.end;
1762
2369
  continue;
1763
2370
  }
@@ -1866,8 +2473,20 @@ function longestAlnumRun(word) {
1866
2473
  return best;
1867
2474
  }
1868
2475
  const JWT_WORD = /^eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{4,}$/;
1869
- const PEM_BEGIN_SOURCE = '-----BEGIN [A-Z0-9 ]*PRIVATE KEY(?: BLOCK)?-----';
2476
+ const PEM_BEGIN_SOURCE = `${PRIVATE_KEY_PEM_HEADER.source}(?: BLOCK)?-----`;
2477
+ const PEM_CASE_FLAGS = PRIVATE_KEY_PEM_HEADER.flags.includes('i') ? 'i' : '';
2478
+ const PEM_LEAD = '-----BEGIN';
1870
2479
  const PEM_END_MARK = '-----END';
2480
+ function pemEndIndex(text, from) {
2481
+ const re = new RegExp(PEM_END_MARK, `g${PEM_CASE_FLAGS}`);
2482
+ re.lastIndex = from;
2483
+ const m = re.exec(text);
2484
+ return m === null ? -1 : m.index;
2485
+ }
2486
+ function pemLeadAt(s, at) {
2487
+ const seg = s.slice(at, at + PEM_LEAD.length);
2488
+ return PEM_CASE_FLAGS === 'i' ? seg.toUpperCase() === PEM_LEAD : seg === PEM_LEAD;
2489
+ }
1871
2490
  function lineBreakLengthAt(text, at) {
1872
2491
  if (text.startsWith('\r\n', at))
1873
2492
  return 2;
@@ -1971,7 +2590,18 @@ function blockLines(scan, escaped) {
1971
2590
  nextContent[starts.length] = starts.length;
1972
2591
  for (let i = starts.length - 1; i >= 0; i--)
1973
2592
  nextContent[i] = (indent[i] ?? -1) !== -1 ? i : (nextContent[i + 1] ?? starts.length);
1974
- const built = { starts, ends, indent, nextContent, memo: new Map() };
2593
+ const outOf = new Int32Array(starts.length + 1).fill(starts.length);
2594
+ const stack = [];
2595
+ for (let i = starts.length - 1; i >= 0; i--) {
2596
+ const ind = indent[i] ?? -1;
2597
+ if (ind === -1)
2598
+ continue;
2599
+ while (stack.length > 0 && (indent[stack[stack.length - 1] ?? 0] ?? -1) > ind)
2600
+ stack.pop();
2601
+ outOf[i] = stack.length > 0 ? (stack[stack.length - 1] ?? starts.length) : starts.length;
2602
+ stack.push(i);
2603
+ }
2604
+ const built = { starts, ends, indent, nextContent, outOf, memo: new Map() };
1975
2605
  scan.lines[slot] = built;
1976
2606
  return built;
1977
2607
  }
@@ -2068,11 +2698,11 @@ function pemBodyEndWithoutTrailer(text, from) {
2068
2698
  }
2069
2699
  function pemBlocks(text, soft = () => false) {
2070
2700
  const out = [];
2071
- if (!text.includes('-----BEGIN'))
2701
+ if (!(PEM_CASE_FLAGS === 'i' ? text.toUpperCase().includes(PEM_LEAD) : text.includes(PEM_LEAD)))
2072
2702
  return out;
2073
2703
  const head = pemHeadView(text, soft);
2074
- const begin = new RegExp(PEM_BEGIN_SOURCE, 'g');
2075
- const trailer = /-----END[A-Z0-9 ]*-----/y;
2704
+ const begin = new RegExp(PEM_BEGIN_SOURCE, `g${PEM_CASE_FLAGS}`);
2705
+ const trailer = new RegExp(`${PEM_END_MARK}[A-Z0-9 ]*-----`, `y${PEM_CASE_FLAGS}`);
2076
2706
  let nextEnd = -2;
2077
2707
  for (let b = begin.exec(head); b !== null; b = begin.exec(head)) {
2078
2708
  let bodyStart = b.index + b[0].length;
@@ -2083,7 +2713,7 @@ function pemBlocks(text, soft = () => false) {
2083
2713
  while (bodyStart < text.length && (text[bodyStart] === ' ' || text[bodyStart] === '\t'))
2084
2714
  bodyStart++;
2085
2715
  if (nextEnd !== -1 && nextEnd < bodyStart)
2086
- nextEnd = text.indexOf(PEM_END_MARK, bodyStart);
2716
+ nextEnd = pemEndIndex(text, bodyStart);
2087
2717
  let bodyEnd;
2088
2718
  let regionEnd;
2089
2719
  if (nextEnd === -1) {
@@ -2114,8 +2744,8 @@ function pemHeadView(text, soft) {
2114
2744
  return chars === null ? text : chars.join('');
2115
2745
  }
2116
2746
  function pemBeginAt(S, at) {
2117
- const k = at + '-----BEGIN'.length;
2118
- return S.text.startsWith('-----BEGIN', at) && (S.text[k] === ' ' || (k < S.text.length && pemSoft(S, k)));
2747
+ const k = at + PEM_LEAD.length;
2748
+ return pemLeadAt(S.text, at) && (S.text[k] === ' ' || (k < S.text.length && pemSoft(S, k)));
2119
2749
  }
2120
2750
  const pemSoft = (S, k) => S.dropped(k) || S.painted(k);
2121
2751
  function pemBlockToRaw(S, blk) {
@@ -3458,3 +4088,4 @@ export function displayUntrustedMarks(text, opts = {}) {
3458
4088
  return { text: out, marks: [] };
3459
4089
  return { text: out.text, marks: collectMarks(out, ledger) };
3460
4090
  }
4091
+ const isQuoteChar = (c) => c.charCodeAt(0) === 0x22 || c.charCodeAt(0) === 0x27 || (c === '' && /`/.test(c));