@lelouchhe/webagent 0.4.0 → 0.6.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.
@@ -0,0 +1 @@
1
+ import{b as m,k as f,l as g}from"./chunk.ON2W5X2T.js";import"./chunk.D4ZYHJAM.js";import"./chunk.AJZBJBMO.js";var C=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function u(t){return String(t).padStart(2,"0")}function h(t,r){if(!t)return"";let s=new Date(t),a=s.getTime();if(isNaN(a))return"";let l=Math.floor((r.getTime()-a)/1e3);if(l<60)return"just now";let i=Math.floor(l/60);if(i<60)return`${i}m ago`;let o=Math.floor(i/60);if(o<24)return`${o}h ago`;let e=Math.floor(o/24);if(e<7)return`${e}d ago`;let n=s.getUTCFullYear()===r.getUTCFullYear(),c=C[s.getUTCMonth()],d=s.getUTCDate();return n?`${c} ${d}`:`${c} ${d}, ${s.getUTCFullYear()}`}function p(t){if(!t)return"";let r=new Date(t);return isNaN(r.getTime())?"":`${r.getUTCFullYear()}-${u(r.getUTCMonth()+1)}-${u(r.getUTCDate())} ${u(r.getUTCHours())}:${u(r.getUTCMinutes())} UTC`}function y(t){let r=/^\/api\/v1\/sessions\/[^/]+\/attachments\/([A-Za-z0-9._-]+)(?:\?.*)?$/;return s=>{let a=r.exec(s);return a?`/s/${encodeURIComponent(t)}/attachments/${a[1]}`:s}}function E(t){if(typeof t.data=="string")try{return JSON.parse(t.data)}catch{return{}}return t.data}function T(t,r,s){let a=new Set;for(let n of t)if(n.type==="permission_response")try{let c=JSON.parse(n.data);typeof c.requestId=="string"&&a.add(c.requestId)}catch{}let l=new Map,i=new Map,o=null,e={rewriteAttachmentSrc:y(s),enhanceMarkdown:m,findToolCallEl:n=>l.get(n)??null,findPermissionEl:n=>i.get(n)??null,findBashEl:()=>o,isPermissionResolved:n=>a.has(n)};for(let n of t){if(!f(n.type))continue;let c=E(n),d=g(n.type,c,e);d?(r.appendChild(d),n.type==="tool_call"&&typeof c.id=="string"?l.set(c.id,d):n.type==="permission_request"&&typeof c.requestId=="string"?i.set(c.requestId,d):n.type==="bash_command"&&(o=d)):n.type==="bash_result"&&(o=null)}}async function v(){try{let e=localStorage.getItem("theme")??"auto";document.documentElement.setAttribute("data-theme",e)}catch{}let t=/^\/s\/([A-Za-z0-9_-]{24})(?:[/?#]|$)/.exec(location.pathname);if(!t){document.body.textContent="invalid share URL";return}let r=t[1],s=document.getElementById("session-info"),a=document.getElementById("messages"),l=document.querySelector(".share-footer-author"),i=document.querySelector(".share-footer-meta");if(!a)return;let o;try{let e=await fetch(`/api/v1/shared/${encodeURIComponent(r)}/events`,{headers:{Accept:"application/json"},credentials:"omit"});if(e.status===410){document.body.innerHTML="<div class='share-gone'>\u6B64\u94FE\u63A5\u5DF2\u64A4\u9500\u6216\u8FC7\u671F\u3002</div>";return}if(!e.ok){document.body.textContent=`error ${e.status}`;return}o=await e.json()}catch(e){document.body.textContent=`failed to load: ${String(e)}`;return}if(document.title=o.share.session_title?`${o.share.session_title} \u2014 shared`:"shared session",s&&(s.textContent=o.share.session_title??"(untitled)"),l){let e=o.share.display_name??"";l.textContent=e?`by ${e}`:""}if(T(o.events,a,r),i){let e=o.share.shared_at??o.share.created_at;i.textContent=h(e,new Date),i instanceof HTMLElement&&(i.title=p(e))}}v();
package/dist/login.html CHANGED
@@ -17,7 +17,7 @@
17
17
  media="(prefers-color-scheme: light)"
18
18
  />
19
19
  <script src="/theme-init.js"></script>
20
- <link rel="stylesheet" href="/styles.012p32dz.css" />
20
+ <link rel="stylesheet" href="/styles.01ky3cex.css" />
21
21
  </head>
22
22
  <body class="login-page">
23
23
  <div class="login-card">
@@ -16,9 +16,10 @@
16
16
  media="(prefers-color-scheme: light)"
17
17
  />
18
18
  <meta name="robots" content="noindex, nofollow" />
19
- <link rel="stylesheet" href="/s/_/styles.012p32dz.css" />
19
+ <link rel="stylesheet" href="/s/_/styles.01ky3cex.css" />
20
20
  <link rel="stylesheet" href="/s/_/share-viewer.00gubshk.css" />
21
- <link rel="modulepreload" href="/s/_/chunk.CGWFHJI2.js">
21
+ <link rel="modulepreload" href="/s/_/chunk.ON2W5X2T.js">
22
+ <link rel="modulepreload" href="/s/_/chunk.D4ZYHJAM.js">
22
23
  <link rel="modulepreload" href="/s/_/chunk.AJZBJBMO.js">
23
24
  </head>
24
25
  <body class="share-viewer">
@@ -48,6 +49,6 @@
48
49
  >
49
50
  </div>
50
51
  </footer>
51
- <script type="module" src="/s/_/viewer.6DT53STL.js"></script>
52
+ <script type="module" src="/s/_/viewer.VY4PO2O5.js"></script>
52
53
  </body>
53
54
  </html>
@@ -15,6 +15,8 @@
15
15
  --permission-bg: #1c1305;
16
16
  --permission-title: #d29922;
17
17
  --accent-soft: rgba(88, 166, 255, 0.18);
18
+ --user-image-max-width: 200px;
19
+ --user-image-max-height: 150px;
18
20
  }
19
21
  [data-theme="light"] {
20
22
  --bg: #ffffff;
@@ -175,6 +177,7 @@ body {
175
177
  display: flex;
176
178
  flex-direction: column;
177
179
  gap: 4px;
180
+ overflow-anchor: none;
178
181
  }
179
182
  #messages > * {
180
183
  min-width: 0;
@@ -485,10 +488,19 @@ body {
485
488
  border-left: 3px solid var(--blue);
486
489
  border-radius: 0 var(--radius) var(--radius) 0;
487
490
  }
488
- .plan-title {
491
+ .plan-summary {
489
492
  color: var(--blue);
490
493
  font-weight: bold;
491
494
  margin-bottom: 2px;
495
+ cursor: pointer;
496
+ }
497
+ .plan-counts {
498
+ color: var(--text-dim);
499
+ font-weight: normal;
500
+ margin-left: 14px;
501
+ }
502
+ .plan-entries {
503
+ margin-top: 2px;
492
504
  }
493
505
  .plan-entry {
494
506
  padding: 1px 0;
@@ -945,8 +957,8 @@ body {
945
957
  padding: 0;
946
958
  }
947
959
  .msg.user img.user-image {
948
- max-width: 200px;
949
- max-height: 150px;
960
+ max-width: var(--user-image-max-width);
961
+ max-height: var(--user-image-max-height);
950
962
  border-radius: 4px;
951
963
  border: 1px solid var(--border);
952
964
  display: block;
@@ -994,10 +1006,17 @@ body {
994
1006
 
995
1007
  /* History pagination sentinel */
996
1008
  .history-sentinel {
1009
+ height: 1px;
1010
+ padding: 0;
1011
+ opacity: 0;
1012
+ pointer-events: none;
1013
+ }
1014
+ .history-loading {
997
1015
  text-align: center;
998
1016
  padding: 8px;
999
1017
  opacity: 0.5;
1000
1018
  font-size: 0.85em;
1019
+ pointer-events: none;
1001
1020
  }
1002
1021
 
1003
1022
  /* Utility: dim out cancelled / settled / past states. Used in dynamic innerHTML
@@ -1076,6 +1095,45 @@ body.login-page {
1076
1095
  border-radius: 3px;
1077
1096
  }
1078
1097
 
1098
+ /* --- Math (Temml MathML output) --- */
1099
+ /* Block math is wrapped in <div class="math-block"> by the renderer.
1100
+ Safari's overflow on <math> is broken — long equations escape the
1101
+ element and push the parent's width, causing page-level horizontal
1102
+ scroll. The wrapper div absorbs the overflow into a local scrollbar. */
1103
+ .math-block {
1104
+ overflow-x: auto;
1105
+ overflow-y: hidden;
1106
+ max-width: 100%;
1107
+ }
1108
+ /* Long inline math: wrap in an inline-block box so it can carry its own
1109
+ max-width + overflow-x without pushing page width. Applying these
1110
+ directly to <math> doesn't work on WebKit. vertical-align: middle keeps
1111
+ the formula visually centered with surrounding CJK/Latin text. */
1112
+ .math-inline {
1113
+ display: inline-block;
1114
+ max-width: 100%;
1115
+ overflow-x: auto;
1116
+ overflow-y: hidden;
1117
+ vertical-align: middle;
1118
+ }
1119
+ math:not(.tml-display) {
1120
+ max-width: 100%;
1121
+ }
1122
+ /* When Temml fails to parse math, the renderer falls back to a span
1123
+ containing the literal $...$ source (instead of Temml's red inline
1124
+ error message, which breaks paragraph flow and pollutes copy/paste).
1125
+ Styling is intentionally minimal — just dim text. We tried dotted /
1126
+ wavy / dashed underlines and thicker custom strokes, but iOS Safari
1127
+ silently drops non-solid text-decoration-style on inline spans
1128
+ (WebKit bug #233181), and any solid/colored underline that *does*
1129
+ render reads as "wrong" rather than "soft warning". The dim color
1130
+ alone signals "something off here" without distracting from the
1131
+ surrounding correct prose. The actual parse error is preserved in
1132
+ the span's title attribute for desktop hover. */
1133
+ .math-error {
1134
+ color: var(--text-dim);
1135
+ }
1136
+
1079
1137
  /* --- highlight.js themes (vendored from highlight.js@common, BSD-3-Clause) --- */
1080
1138
  /* light: default */
1081
1139
  pre code.hljs {
@@ -1441,3 +1499,358 @@ code.hljs {
1441
1499
  }
1442
1500
  }
1443
1501
  }
1502
+
1503
+ /* --- Temml (LaTeX → MathML rendering, MIT) --- */
1504
+ /*
1505
+ Temml.woff2 is a clone of KaTeX_Script-Regular, except that the code points
1506
+ have been changed from ASCII to Unicode Mathematical Alphanumeric Symbols Script capitals,
1507
+ Unicode range 1D49C to 1D4B5.
1508
+ */
1509
+
1510
+ @font-face {
1511
+ font-family: 'Temml';
1512
+ src: url('/fonts/temml/Temml.woff2') format('woff2');
1513
+ font-weight: normal;
1514
+ font-style: normal;
1515
+ }
1516
+
1517
+ math {
1518
+ font-family: "Cambria Math", 'STIXTwoMath-Regular', 'NotoSansMath-Regular', math;
1519
+ font-style: normal;
1520
+ font-weight: normal;
1521
+ line-height: normal;
1522
+ font-size-adjust: none;
1523
+ text-indent: 0;
1524
+ text-transform: none;
1525
+ letter-spacing: normal;
1526
+ word-wrap: normal;
1527
+ direction: ltr;
1528
+ /* Prevent Firefox from omitting the dot on i or j. */
1529
+ font-feature-settings: "dtls" off;
1530
+ }
1531
+
1532
+ math * {
1533
+ border-color: currentColor;
1534
+ }
1535
+
1536
+ /* display: block is necessary in Firefox and Safari.
1537
+ * Not in Chromium, which recognizes display: "block math" written inline. */
1538
+ math.tml-display {
1539
+ display: block;
1540
+ width: 100%;
1541
+ }
1542
+
1543
+ *.mathcal {
1544
+ /* NotoSans */
1545
+ font-feature-settings: 'ss01';
1546
+ }
1547
+
1548
+ math .mathscr {
1549
+ font-family: "Temml";
1550
+ }
1551
+
1552
+ mo.tml-prime {
1553
+ font-family: Temml;
1554
+ }
1555
+
1556
+ /* Cramped superscripts in WebKit */
1557
+ mfrac > :nth-child(2),
1558
+ msqrt,
1559
+ mover > :first-child {
1560
+ math-shift: compact
1561
+ }
1562
+
1563
+ .menclose {
1564
+ display: inline-block;
1565
+ position: relative;
1566
+ padding: 0.5ex 0ex;
1567
+ }
1568
+ .tml-cancelto {
1569
+ display: inline-block;
1570
+ position: absolute;
1571
+ top: 0;
1572
+ left: 0;
1573
+ padding: 0.5ex 0ex;
1574
+ background-color: currentColor;
1575
+ /* Use the SVG as an alpha mask (painted by background-color) */
1576
+ -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><defs><marker id='a' markerHeight='5' markerUnits='strokeWidth' markerWidth='7' orient='auto' refX='7' refY='2.5'><path fill='black' d='m0 0 7 2.5L0 5z'/></marker></defs><line x2='100%25' y1='100%25' stroke='black' stroke-width='.06em' marker-end='url(%23a)' vector-effect='non-scaling-stroke'/></svg>");
1577
+ mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><defs><marker id='a' markerHeight='5' markerUnits='strokeWidth' markerWidth='7' orient='auto' refX='7' refY='2.5'><path fill='black' d='m0 0 7 2.5L0 5z'/></marker></defs><line x2='100%25' y1='100%25' stroke='black' stroke-width='.06em' marker-end='url(%23a)' vector-effect='non-scaling-stroke'/></svg>");
1578
+ -webkit-mask-repeat: no-repeat;
1579
+ mask-repeat: no-repeat;
1580
+ -webkit-mask-size: 100% 100%;
1581
+ mask-size: 100% 100%;
1582
+ -webkit-mask-position: 0 0;
1583
+ mask-position: 0 0;
1584
+ }
1585
+
1586
+ @supports (-moz-appearance: none) {
1587
+ /* \vec w/o italic correction for Firefox */
1588
+ .tml-vec {
1589
+ transform: scale(0.75)
1590
+ }
1591
+ /* Fix \cancelto in Firefox */
1592
+ .ff-narrow {
1593
+ width: 0em;
1594
+ }
1595
+ .ff-nudge-left {
1596
+ margin-left: -0.2em;
1597
+ }
1598
+ }
1599
+
1600
+ @supports (not (-moz-appearance: none)) {
1601
+ /* Chromium and WebKit */
1602
+ /* prime vertical alignment */
1603
+ mo.tml-prime {
1604
+ font-family: Temml;
1605
+ }
1606
+ /* Italic correction on superscripts */
1607
+ .tml-sml-pad {
1608
+ padding-left: 0.05em;
1609
+ }
1610
+ .tml-med-pad {
1611
+ padding-left: 0.10em;
1612
+ }
1613
+ .tml-lrg-pad {
1614
+ padding-left: 0.15em;
1615
+ }
1616
+ }
1617
+
1618
+ @supports (-webkit-backdrop-filter: blur(1px)) {
1619
+ /* WebKit vertical & italic correction on accents */
1620
+ .wbk-acc {
1621
+ /* lower by x-height distance */
1622
+ transform: translate(0em, 0.431em);
1623
+ }
1624
+ .wbk-sml {
1625
+ transform: translate(0.07em, 0);
1626
+ }
1627
+ .wbk-sml-acc {
1628
+ transform: translate(0.07em, 0.431em);
1629
+ }
1630
+ .wbk-sml-vec {
1631
+ transform: scale(0.75) translate(0.07em, 0);
1632
+ }
1633
+ .wbk-med {
1634
+ transform: translate(0.14em, 0);
1635
+ }
1636
+ .wbk-med-acc {
1637
+ transform: translate(0.14em, 0.431em);
1638
+ }
1639
+ .wbk-med-vec {
1640
+ transform: scale(0.75) translate(0.14em, 0);
1641
+ }
1642
+ .wbk-lrg {
1643
+ transform: translate(0.21em, 0);
1644
+ }
1645
+ .wbk-lrg-acc {
1646
+ transform: translate(0.21em, 0.431em);
1647
+ }
1648
+ .wbk-lrg-vec {
1649
+ transform: scale(0.75) translate(0.21em, 0);
1650
+ }
1651
+ }
1652
+
1653
+ /* \cancel & \phase use background images. Get them to print. */
1654
+ menclose {
1655
+ -webkit-print-color-adjust: exact; /* Chrome & Edge */
1656
+ print-color-adjust: exact;
1657
+ }
1658
+
1659
+ /* Array cell justification in Firefox & WebKit */
1660
+ .tml-right {
1661
+ text-align: right;
1662
+ }
1663
+ .tml-left {
1664
+ text-align: left;
1665
+ }
1666
+
1667
+ /* For CD labels that grow to the left in Firefox and WebKit */
1668
+ .tml-shift-left { margin-left:-200% }
1669
+
1670
+ /* Styles for Chromium only */
1671
+ @supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
1672
+ /* Italic correction on accents */
1673
+ .chr-sml {
1674
+ transform: translate(0.07em, 0)
1675
+ }
1676
+ .chr-sml-vec {
1677
+ transform: scale(0.75) translate(0.07em, 0)
1678
+ }
1679
+ .chr-med {
1680
+ transform: translate(0.14em, 0)
1681
+ }
1682
+ .chr-med-vec {
1683
+ transform: scale(0.75) translate(0.14em, 0)
1684
+ }
1685
+ .chr-lrg {
1686
+ transform: translate(0.21em, 0)
1687
+ }
1688
+ .chr-lrg-vec {
1689
+ transform: scale(0.75) translate(0.21em, 0)
1690
+ }
1691
+
1692
+ /* For CD labels that grow to the left */
1693
+ .tml-shift-left { margin-left:-100% }
1694
+
1695
+ /* MathML Core & Chromium do not support the MathML 3.0 element <menclose> attributes. */
1696
+ /* So use styles. */
1697
+ menclose {
1698
+ position: relative;
1699
+ padding: 0.5ex 0ex;
1700
+ }
1701
+
1702
+ .tml-overline {
1703
+ padding: 0.1em 0 0 0;
1704
+ border-top: 0.065em solid;
1705
+ }
1706
+
1707
+ .tml-underline {
1708
+ padding: 0 0 0.1em 0;
1709
+ border-bottom: 0.065em solid;
1710
+ }
1711
+
1712
+ .tml-cancel {
1713
+ display: inline-block;
1714
+ position: absolute;
1715
+ left: 0.5px;
1716
+ bottom: 0;
1717
+ width: 100%;
1718
+ height: 100%;
1719
+ background-color: currentColor;
1720
+ }
1721
+ .upstrike {
1722
+ clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);
1723
+ }
1724
+ .downstrike {
1725
+ clip-path: polygon(0em 0.05em, 0.05em 0em, 100% calc(100% - 0.05em), calc(100% - 0.05em) 100%);
1726
+ }
1727
+ .sout {
1728
+ clip-path: polygon(0em calc(55% + 0.0333em), 0em calc(55% - 0.0333em), 100% calc(55% - 0.0333em), 100% calc(55% + 0.0333em));
1729
+ }
1730
+ .tml-xcancel {
1731
+ clip-path: polygon(0.05em 0em, 0em 0.05em, calc(50% - 0.05em) 50%, 0em calc(100% - 0.05em), 0.05em 100%, 50% calc(50% + 0.05em), calc(100% - 0.05em) 100%, 100% calc(100% - 0.05em), calc(50% + 0.05em) 50%, 100% 0.05em, calc(100% - 0.05em) 0%, 50% calc(50% - 0.05em));
1732
+ }
1733
+
1734
+ .longdiv-top {
1735
+ border-top: 0.067em solid;
1736
+ padding: 0.1em 0.2em 0.2em 0.433em;
1737
+ }
1738
+ .longdiv-arc {
1739
+ position: absolute;
1740
+ top: 0;
1741
+ bottom: 0.1em;
1742
+ left: -0.4em;
1743
+ width: 0.7em;
1744
+ border: 0.067em solid;
1745
+ transform: translateY(-0.067em);
1746
+ border-radius: 70%;
1747
+ clip-path: inset(0 0 0 0.4em);
1748
+ box-sizing: border-box;}
1749
+ .menclose {display: inline-block;
1750
+ text-align: left;
1751
+ position: relative;
1752
+ }
1753
+
1754
+ .phasor-bottom {
1755
+ border-bottom: 0.067em solid;
1756
+ padding: 0.2em 0.2em 0.1em 0.6em;
1757
+ }
1758
+ .phasor-angle {
1759
+ display: inline-block;
1760
+ position: absolute;
1761
+ left: 0.5px;
1762
+ bottom: -0.04em;
1763
+ height: 100%;
1764
+ aspect-ratio: 0.5;
1765
+ background-color: currentColor;
1766
+ clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);
1767
+ }
1768
+
1769
+ .tml-fbox {
1770
+ padding: 3pt;
1771
+ border: 1px solid;
1772
+ }
1773
+
1774
+ .circle-pad {
1775
+ padding: 0.267em;
1776
+ }
1777
+ .textcircle {
1778
+ position: absolute;
1779
+ top: 0;
1780
+ bottom: 0;
1781
+ right: 0;
1782
+ left: 0;
1783
+ border: 0.067em solid;
1784
+ border-radius: 50%;
1785
+ }
1786
+
1787
+ .actuarial {
1788
+ padding: 0.03889em 0.03889em 0 0.03889em;
1789
+ border-width: 0.08em 0.08em 0em 0em;
1790
+ border-style: solid;
1791
+ margin-right: 0.03889em;
1792
+ }
1793
+
1794
+ /* Stretch \widetilde */
1795
+ .tml-crooked-2 {
1796
+ transform: scale(2.0, 1.1)
1797
+ }
1798
+ .tml-crooked-3 {
1799
+ transform: scale(3.0, 1.3)
1800
+ }
1801
+ .tml-crooked-4 {
1802
+ transform: scale(4.0, 1.4)
1803
+ }
1804
+ /* set array cell justification */
1805
+ .tml-right {
1806
+ text-align: -webkit-right;
1807
+ }
1808
+ .tml-left {
1809
+ text-align: -webkit-left;
1810
+ }
1811
+ }
1812
+
1813
+ .special-fraction {
1814
+ font-family: 'STIX TWO', 'Times New Roman', Times, Tinos, serif;
1815
+ }
1816
+
1817
+ /* flex-wrap for line-breaking in Chromium */
1818
+ math {
1819
+ display: inline-flex;
1820
+ flex-wrap: wrap;
1821
+ align-items: baseline;
1822
+ }
1823
+ math > mrow {
1824
+ padding: 0.5ex 0ex;
1825
+ }
1826
+
1827
+ /* Default mtd top padding is 0.5ex per MathML-Core and user-agent CSS */
1828
+ /* We adjust for jot and small */
1829
+ mtable.tml-jot mtd {
1830
+ padding-top: 0.7ex;
1831
+ padding-bottom: 0.7ex;
1832
+ }
1833
+ mtable.tml-small mtd {
1834
+ padding-top: 0.35ex;
1835
+ padding-bottom: 0.35ex;
1836
+ }
1837
+
1838
+ /* Firefox */
1839
+ @-moz-document url-prefix() {
1840
+ /* Avoid flex-wrap */
1841
+ math { display: inline; }
1842
+ math > mrow { padding: 0 }
1843
+ /* Adjust Firefox spacing between array rows */
1844
+ mtd, mtable.tml-small mtd { padding-top: 0; padding-bottom: 0; }
1845
+ mtable.tml-jot mtd { padding-top: 0.2ex; padding-bottom: 0.ex; }
1846
+ }
1847
+
1848
+ /* AMS environment auto-numbering via CSS counter. */
1849
+ .tml-eqn::before {
1850
+ counter-increment: tmlEqnNo;
1851
+ content: "(" counter(tmlEqnNo) ")";
1852
+ }
1853
+
1854
+ body {
1855
+ counter-reset: tmlEqnNo;
1856
+ }
@@ -18,6 +18,9 @@ const WHITELIST = [
18
18
  { method: "GET", test: (p) => p === "/styles.css" },
19
19
  // Icons directory (no traversal: enforced by the check below)
20
20
  { method: "GET", test: (p) => /^\/icons\/[A-Za-z0-9._-]+$/.test(p) },
21
+ // Temml math font (loaded from CSS @font-face, no Authorization header
22
+ // available). Single fixed file: dist/fonts/temml/Temml.woff2.
23
+ { method: "GET", test: (p) => p === "/fonts/temml/Temml.woff2" },
21
24
  // SSE streams — authenticated via short-lived ticket in query string
22
25
  // (EventSource cannot send custom headers).
23
26
  { method: "GET", test: (p) => p === "/api/v1/events/stream" },
@@ -0,0 +1,29 @@
1
+ // Builds the EventHandlerConfig object passed to handleAgentEvent for every
2
+ // bridge event. Lives in its own file so a unit test can lock the wiring
3
+ // without booting the full server.
4
+ //
5
+ // Why this matters: missing fields on the inline config object handed to
6
+ // handleAgentEvent are silent at runtime — the affected feature just stops
7
+ // working, and the bug only surfaces in dogfood. A small structural test
8
+ // next to this builder makes future "merge --theirs" / refactor passes
9
+ // fail loudly instead.
10
+ import { log } from "./log.js";
11
+ export function buildBridgeEventHandlerConfig(deps) {
12
+ return {
13
+ cancelTimeout: deps.cancelTimeout,
14
+ recentPathsLimit: deps.recentPathsLimit,
15
+ attachmentInterceptor: {
16
+ counters: deps.attachmentInterceptorCounters,
17
+ logger: log.scope("attachment-interceptor"),
18
+ onSchemaDrift: (ctx) => {
19
+ if (!deps.shouldLogSchemaDrift())
20
+ return;
21
+ log
22
+ .scope("attachment-interceptor")
23
+ .error("schema drift detected — rawInput has no known path key", {
24
+ ctx,
25
+ });
26
+ },
27
+ },
28
+ };
29
+ }
package/lib/bridge.js CHANGED
@@ -95,10 +95,10 @@ export class AgentBridge extends EventEmitter {
95
95
  async newSession(cwd, opts) {
96
96
  if (!this.conn)
97
97
  throw new Error("Not connected");
98
- const session = (await this.conn.newSession({
98
+ const session = await this.conn.newSession({
99
99
  cwd,
100
100
  mcpServers: [],
101
- }));
101
+ });
102
102
  const configOptions = (session.configOptions ??
103
103
  []);
104
104
  if (!opts?.silent) {
@@ -116,11 +116,11 @@ export class AgentBridge extends EventEmitter {
116
116
  throw new Error("Not connected");
117
117
  let session;
118
118
  try {
119
- session = (await this.conn.loadSession({
119
+ session = await this.conn.loadSession({
120
120
  sessionId,
121
121
  cwd,
122
122
  mcpServers: [],
123
- }));
123
+ });
124
124
  }
125
125
  catch (err) {
126
126
  // -32002 = Resource not found. Some agents (e.g. claude-agent-acp) don't
@@ -147,11 +147,13 @@ export class AgentBridge extends EventEmitter {
147
147
  async setConfigOption(sessionId, configId, value) {
148
148
  if (!this.conn)
149
149
  throw new Error("Not connected");
150
- const result = (await this.conn.setSessionConfigOption({
150
+ const result = await this.conn.setSessionConfigOption({
151
151
  sessionId,
152
152
  configId,
153
- value,
154
- }));
153
+ ...(typeof value === "boolean"
154
+ ? { type: "boolean", value }
155
+ : { value }),
156
+ });
155
157
  return result.configOptions;
156
158
  }
157
159
  async prompt(sessionId, text, attachments) {