merge studio to retain the accepted feedback assertion fix

Problem: the ordinary test synchronization append conflicts with upstream's
independently accepted fix for the same passive draft-persistence boundary.

Root cause: both sides replace the immediate heldDraft assertion with waitFor;
upstream additionally explains why the effect may follow the thumbnail commit.

Fix: resolve the sole conflict to the exact accepted upstream test including
its comment. Preserve all incoming dependency/UI changes and every original
runner-panic implementation Go file. This merge is required by a verified
content conflict, not unrelated base drift; no rebase or force-push.

Verification: final inventory of 239 root packages is reconciled from disjoint
required2 and rest237 commands, both exit0, with frozen Go/module inputs.
Isolation race covers all 51 top-level tests through the original completed
39 trees plus the remaining12 under the same5m budget; original full owner
command hit its cumulative alarm and is retained as exit1, not called pass.
Five affected frontend files have99 tests pass; production typecheck/build,
formatting, root vet, full lint and make check pass without baseline widening.
Exact merge-head hosted/native checks and independent review remain pending.
This commit is contained in:
SivanCola committed 2026-10-26 00:06:20 +08:00
commit 6287044a20
21 files changed
+439 -187

No files matched your search

+6 -6
View File
@@ -32,15 +32,15 @@
"@codemirror/state": "^6.7.6",
"@codemirror/view": "^6.43.14",
"@lezer/highlight": "^1.2.5",
"@mantine/charts": "9.7.2",
"@mantine/core": "9.7.2",
"@mantine/hooks": "9.7.2",
"@mantine/charts": "9.7.3",
"@mantine/core": "9.7.3",
"@mantine/hooks": "9.7.3",
"@noble/curves": "2.4.0",
"codemirror": "^6.0.2",
"dompurify": "^3.4.17",
"katex": "^0.19.0",
"lucide-react": "^1.60.0",
"maplibre-gl": "6.14.0",
"lucide-react": "^1.61.0",
"maplibre-gl": "6.15.0",
"react": "^19.3.1",
"react-dom": "^19.3.1",
"papaparse": "^5.7.0",
@@ -68,7 +68,7 @@
"jsdom": "^30.1.3",
"playwright": "^1.64.1",
"typescript": "^7.0.2",
"vite": "^8.3.4",
"vite": "^8.3.5",
"vitest": "^5.0.4"
}
}
+124 -124
View File
@@ -69,14 +69,14 @@ importers:
specifier: ^1.2.5
version: 1.2.5
'@mantine/charts':
specifier: 9.7.2
version: 9.7.2(@mantine/[email protected].2(@mantine/[email protected].2([email protected]))(@types/[email protected])([email protected]([email protected]))([email protected]))(@mantine/[email protected].2([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))
specifier: 9.7.3
version: 9.7.3(@mantine/[email protected].3(@mantine/[email protected].3([email protected]))(@types/[email protected])([email protected]([email protected]))([email protected]))(@mantine/[email protected].3([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))
'@mantine/core':
specifier: 9.7.2
version: 9.7.2(@mantine/[email protected].2([email protected]))(@types/[email protected])([email protected]([email protected]))([email protected])
specifier: 9.7.3
version: 9.7.3(@mantine/[email protected].3([email protected]))(@types/[email protected])([email protected]([email protected]))([email protected])
'@mantine/hooks':
specifier: 9.7.2
version: 9.7.2([email protected])
specifier: 9.7.3
version: 9.7.3([email protected])
'@noble/curves':
specifier: 2.4.0
version: 2.4.0
@@ -90,11 +90,11 @@ importers:
specifier: ^0.19.0
version: 0.19.0
lucide-react:
specifier: ^1.60.0
version: 1.60.0(@types/[email protected])([email protected])
specifier: ^1.61.0
version: 1.61.0(@types/[email protected])([email protected])
maplibre-gl:
specifier: 6.14.0
version: 6.14.0
specifier: 6.15.0
version: 6.15.0
papaparse:
specifier: ^5.7.0
version: 5.7.0
@@ -109,7 +109,7 @@ importers:
version: 19.3.1([email protected])
react-map-gl:
specifier: 8.1.3
version: 8.1.3([email protected]4.0)([email protected]([email protected]))([email protected])
version: 8.1.3([email protected]5.0)([email protected]([email protected]))([email protected])
react-markdown:
specifier: ^10.1.0
version: 10.1.0(@types/[email protected])([email protected])
@@ -161,7 +161,7 @@ importers:
version: 19.3.0(@types/[email protected])
'@vitejs/plugin-react':
specifier: ^6.1.2
version: 6.1.2([email protected].4(@types/[email protected])([email protected]))
version: 6.1.2([email protected].5(@types/[email protected])([email protected]))
jsdom:
specifier: ^30.1.3
version: 30.1.3(@noble/[email protected])
@@ -172,11 +172,11 @@ importers:
specifier: ^7.0.2
version: 7.0.2
vite:
specifier: ^8.3.4
version: 8.3.4(@types/[email protected])([email protected])
specifier: ^8.3.5
version: 8.3.5(@types/[email protected])([email protected])
vitest:
specifier: ^5.0.4
version: 5.0.4(@types/[email protected])([email protected](@noble/[email protected]))([email protected].4(@types/[email protected])([email protected]))
version: 5.0.4(@types/[email protected])([email protected](@noble/[email protected]))([email protected].5(@types/[email protected])([email protected]))
packages:
@@ -580,24 +580,24 @@ packages:
'@lit/[email protected]':
resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==}
'@mantine/[email protected].2':
resolution: {integrity: sha512-biwAZ4RDSmhy2dqeyqBK1XlFg3+eZGYyt3bEDuTBu/at/fbAguhIsmFTbqYjqMcTpWNyX9BNxJ+mhMFslee1eQ==}
'@mantine/[email protected].3':
resolution: {integrity: sha512-p8SMOVEmQATcHIszSYdKdU6MBq8Ozdm+QJeFz+Zrtpquv0+ZVHIb262emZV544a7UmwOGdMN5DxmhQ8lewrbvg==}
peerDependencies:
'@mantine/core': 9.7.2
'@mantine/hooks': 9.7.2
'@mantine/core': 9.7.3
'@mantine/hooks': 9.7.3
react: ^19.2.0
react-dom: ^19.2.0
recharts: '>=3.2.1'
'@mantine/[email protected].2':
resolution: {integrity: sha512-+cggJDD0PO057SwZU/dKlWPjp0LaAn1nEM9W1m/Ia4Cjb/Hy9DjZ4I7R7xirp/eZ6xnV7OqeGmPFSJ8zeGa5kQ==}
'@mantine/[email protected].3':
resolution: {integrity: sha512-wYJ9Bd82a7HqwJ+hubFqUIocBGMuw6txzdPnnleHvv1h0NlnkESevK/WHTRh4FtOw33B5N2ADT34s3x1/8d8jg==}
peerDependencies:
'@mantine/hooks': 9.7.2
'@mantine/hooks': 9.7.3
react: ^19.2.0
react-dom: ^19.2.0
'@mantine/[email protected].2':
resolution: {integrity: sha512-11emsRp/Mg+vfaKVyoMwiMdCHmO/15XOL6JG9fACkclVZnLPBVvRIaDdRBudsR3ALGZ5iTzrArPJDjjoeO6X4w==}
'@mantine/[email protected].3':
resolution: {integrity: sha512-GMHoMS1qul1dBLIHd/N9ef2Pr8UKYYHfuM+g2ej3gYqU0kH4sTiR9FNHksoTQi0PzATRoaNlUYjjMe9rbDRw5A==}
peerDependencies:
react: ^19.2.0
@@ -620,8 +620,8 @@ packages:
'@mapbox/[email protected]':
resolution: {integrity: sha512-Qf10S1uIHMk20ri/IVBnpS+esUEkVaR5Hftmz88jTInrpmWgPGJfPe3LVjjlE77trLx8tH6qjTG7uWH9hIq/0Q==}
'@maplibre/geojson-vt@6.1.2':
resolution: {integrity: sha512-2ZYhobdAY+y4/P/z1xe0698165LywD0yDdWugdu3NRUrajgVWut+tLkcz7i/RJguMTURwK7gxwmwYMFJbgbQFw==}
'@maplibre/geojson-vt@6.3.0':
resolution: {integrity: sha512-3Zw2jsU9pIJG3G2CQFbLjWj2MlAHodhD7cSY+15iywUuLmmkgzcKRnueVRZ4AcC/5wOtfhidcJAAzBpoBNs3Xg==}
'@maplibre/[email protected]':
resolution: {integrity: sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw==}
@@ -723,8 +723,8 @@ packages:
resolution: {integrity: sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==}
engines: {node: '>= 20.19.0'}
'@oxc-project/[email protected]2.0':
resolution: {integrity: sha512-oM/5rLBm2tPkg0iBgkH/FOeR3PCDpY19GTgAZjMFM8h9WI9VW7cLgzp6nwtarYKmovavIQZ+Fe/RKX/8C8O/Rw==}
'@oxc-project/[email protected]5.0':
resolution: {integrity: sha512-SeE8JPwW1xs1tHeNycjUtUBdhorRa8o4jlvjwk49R7/Z291i+4DQa7JJIgOm/TaYQZx+QrPQbVJ/9c8dMIZN8Q==}
'@preact/[email protected]':
resolution: {integrity: sha512-HNB6HYeYKhQbJ1aKl+YRjrS4+QWHLKX6qKoUsfS/m0vqzsVaEBiZiaKbG/e+NKk2ch5ALQr/ihWaMHxiCuuWHA==}
@@ -740,98 +740,98 @@ packages:
react-redux:
optional: true
'@rolldown/[email protected]2':
resolution: {integrity: sha512-dB/a1214qKfHMXCpgqR4OZT+jS4kTyEXbQGJPqzobt5EwH5rX080pxE37alt3RzvR1bf1Yz/yGqRfrYAxuPw0A==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-aLcgK9gIJ3YRvrrtfSBbRa27F5WrpiTaPulnFpsHPxpUHgFlSgnU4854MHwoRGEBhfRJDWCS2WQ7lIjskE9Olw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [android]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-7KHFgQ5VJxIHcLlrwrc3Xbds7oTNQT7Pgi9gQCJKrd2VGab/UksIOYp6VD8MzCstGxOKMgNamPwUCfxPdP1OHg==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-xD7DdZCrbThKuxNg7ooQmvp07ys4J/pnSEMTG3/OdOWl6daC67m/Q4fL78sRHMxTH/N4fGUbYhcPM0MF5WFHkg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [android]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-3YIhqHD96nA5SaYNRBR16HnGv4oavZvXfD/ayHM+oYZ0WD/8lBAtf6zQua4kEyAvpqrluKXl0lnOBoiNby7x9w==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-m2WuQ6r0B4OTYxyPpNLtXaMRbRDUbG8YQV2Q3KTdSSK8Th6KHCnC8jVCJt8bvYeSB5WivkkNbc85mKadaSdOxA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [darwin]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-UuuJ35MFw4gmFOrE9pEqIV+K3syIKveph+Qc1/ljHZVdoDW4pz/JHR/eMVom+TZGl/5OOvGJOWaOCVt3ZfqhxA==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-5RtnsHM36nodM9WbMy+zip0LGS/G+y5wro5RHrpOlr4ac24+1zSi9kiV2MP1myZeZ/ifEHfulQcWjnAXzc2C2A==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [darwin]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-uMvssit0a4W+/7D8CbHUvG719mH3R2jwXAlh/XcPvuHTE0g++LymF88DCGNX0HM2rBOn0xrzgXktIB6fLSJBTQ==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-g3l09pyFqhu+135JKkbkwiKGQmwU5hUMUPJ4VdBADvuqR8d33L6H578rh8m7rtxbdp+VmX/+nzI7nvhSZlzpUQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [freebsd]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-XcFu0R0xWnwzSf4IQgFH1rJIckPN1pLy2R+4r9IDB7Yfu/ys9cVqfa4pBrMHj7a3gl8mIR4nRNPg0e5IvEVs6g==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-nIe3VugI97nGQtspPxDqA4sXMUpeiocKIP/CqpY/u/vgbT+alX+cVxu1C/oVBPKg4feNTmYovE91v4DgXvXNwQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-260UrKgn8tz39ak+SMDOirKzr7V04M9dWPw5llW00SwBivCZoWcRBKV1d8cXnRkUmSZA3BdiUmBHWk7734Ulpw==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-iTBjXx+B5QSvgI89lJfmqh4wTh8NabR1YZIIN3hNx4zSG0EVfVqkOvLulNpG4251pbd6/IAmZ/LefVk1Y4rPhw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-5YK1I9SqDkbPgc1IA8BgDl34suqUS2q0KWnBrirm0E51YjOs6eo6dV6jbQfNE/argHRSvd0QUGgtpIoYx+WWpw==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-uN26XOnVR7rqQupG3V9oAG2EGGatWjcJHOeDOHUFCh4TBWmP2tHTFoVN13aYbwfm0aHqJAEmcwhAu6sooIjfqQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-Rkcrmp7eFRg74yL5fXEU91JEWbdEPLevWwGtXpmhbjlD1StScbWTmO94Bhly+Mo+ketKYkdmM1vNUKeWSlx8cQ==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-9nWkcdd+H+XhaA3fQIwpHnKIrfx/PQ6rO0pivr78Og07tXlUlctBBJoEYLPfhTmCR/QxEVdn6uPjHV5SymPhdw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-qvK4DuAsQc2BSjlx+Xr+IzOIvvxbGZqxFwdWfG6F518Erj0GGISyQbJ6pIappnOxlNPzNHvo/L0BwB30GZ+zVw==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-Ggh0ciFjLwIusLSLz7LZYEaGdxOAUJXI+Qu5JCbhPJJHEt8vP+IjRATTJheiJsdzzTYgUiHUiw3X1Ea3ZpMBdA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-Q9uLBO53Xd4QIq1WOycVQyPP1O4HhraEV2qqb3uTrnVw6QZih9duY4vNXOivL1xoUS1/z+W8eF4NMfl2a8Sdjw==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-FHg60rS6DBePAYZ9X9F67x+JObFdmgn6tupA1C/a3B+CufFmTD4mX+e8M75tCiAO3foR/6xwVBI0KQiI7sn/rw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-3IBxWFMjbOZskDPKv8Lf9BCnahlKuHthWkYnyIxOH/QcJrFcS4EmcenthApkwr/5+nEqZlLzeYbxeMaX7A5u4g==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-/cvV/7v5VGz/moiz0XKRj2dE8DzsKyhIu1KpOvJGPjRywg3yscON889UGvAe8zfiJLHup7VLjBduoGWi3HusWQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-xtX61xg4LKPkPWilZU1ynKClz5Gj4bf74LML4r3eVLWumKnGjoEr1OSHQhMdbBDoYTi+yjrujvpZe2pUnqCrrA==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-MyzC5Hrv/sm+Z7TSGKP/j8001RO2xQm1zOpCNVL4j0cY/VhBZviludA2YFQ7i4lH6ZAXxQm0lcMdBzM+99mE7w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [openharmony]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-At7fPB6PCaIjzgIhEZFxuT+BBFqiQibJDT4d3PhiR3f4E7bbMZF4aKblbFfEM3sETRDd1YiQx/+U/g/B/ou5Ew==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-+PgYiS+AH5omy6L45ZLxybasauJaj3M8buoT83D+nzPmCayXlxUV9hydhciCKVyIg0B/v0BtXPDE1uGqNwCPpg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [win32]
'@rolldown/[email protected]2':
resolution: {integrity: sha512-WIw2haVKwjuYdXkHaoC0mF8Le71TuCBxjrdKqLbJGctbBABj+ClfmNvtbOnzpq3RokNo5+V1qhtSzJyXorsklQ==}
'@rolldown/[email protected]5':
resolution: {integrity: sha512-HFZd2QNQYn1JbIi+Hpd7H+r/lkWxcfIu28nirZ6eCn2LafuvmExMlb/P96Sfx5tf7pPArw39IdhmCF8vmV+NhQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [win32]
@@ -1613,8 +1613,8 @@ packages:
resolution: {integrity: sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==}
engines: {node: 20 || >=22}
[email protected]0.0:
resolution: {integrity: sha512-UqxOW0FgAfDyb9VmjKb6/BkOzW6yfhf/QNboKtS2NDsscnNRW2CDzlyhbMKBQ1ontmcxuIDqHJ2AVgFR3NI+GA==}
[email protected]1.0:
resolution: {integrity: sha512-v2SQPPPNjnr+BlhL9Spuzmo5yR+hLkftfuE4E3jaxdNPgSH0hJKPcLJBP7yAta87jQNPsSERS59PJjCJ/CorBA==}
peerDependencies:
'@types/react': '*'
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
@@ -1629,8 +1629,8 @@ packages:
[email protected]:
resolution: {integrity: sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==}
[email protected]4.0:
resolution: {integrity: sha512-L7U9y9TyPJ3P/JJbW+eH+A3FzdPq+3fnZFqqeCwf/S6cRGganHwVI5b/C8/zOYzreUzsloDPZVVaMQA94wOt4A==}
[email protected]5.0:
resolution: {integrity: sha512-kxFetbvUHDOVaAP1CYb226Mdk2QhzIPddqM0xJTFD35wu78Mpd6NM7+H68ALjc6Oa0kAOX5EAdMKyvD2u3qfcg==}
engines: {node: '>=16.14.0', npm: '>=8.1.0'}
[email protected]:
@@ -2008,8 +2008,8 @@ packages:
[email protected]:
resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==}
[email protected]2:
resolution: {integrity: sha512-8wafseiaG80xmXSfqidUNqZcylTlhmPZZt+za2m+js2sFZ8dTNlhIOV2WcbIPx2hgwPBJpEUGFAMZ9bgBBLTSQ==}
[email protected]5:
resolution: {integrity: sha512-6odND+fel5zVw3I4Yc2e69gvguDnX0CAAGiNDZSq4ik5WUcaLrkD2GLuog0XcODbor31hZ5ayEMgVDno+KPV5g==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
@@ -2211,13 +2211,13 @@ packages:
[email protected]:
resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==}
[email protected].4:
resolution: {integrity: sha512-IftLE8phJhdNRIGNEV4JCCvfNScoZQVfcXaN8TQropWGJtOHcu+iAB9pHcuGvmEb/kddw0LBe/jS8ztdC6xdiQ==}
[email protected].5:
resolution: {integrity: sha512-z1YpjieJ9g0ebTmQpLBv/oq9E3F9EIlOe+7LahW8SrE3LTiG3udBRUXQOlYXP9b+IC2q2phHeVxj9xGlw34OEQ==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
'@types/node': ^20.19.0 || >=22.12.0
'@vitejs/devtools': ^0.7.1
'@vitejs/devtools': ^0.7.1 || ^0.8.0
esbuild: ^0.27.0 || ^0.28.0
jiti: '>=1.21.0'
less: ^4.0.0
@@ -2783,18 +2783,18 @@ snapshots:
dependencies:
'@lit-labs/ssr-dom-shim': 1.6.0
'@mantine/[email protected].2(@mantine/[email protected].2(@mantine/[email protected].2([email protected]))(@types/[email protected])([email protected]([email protected]))([email protected]))(@mantine/[email protected].2([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))':
'@mantine/[email protected].3(@mantine/[email protected].3(@mantine/[email protected].3([email protected]))(@types/[email protected])([email protected]([email protected]))([email protected]))(@mantine/[email protected].3([email protected]))([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected]))':
dependencies:
'@mantine/core': 9.7.2(@mantine/[email protected].2([email protected]))(@types/[email protected])([email protected]([email protected]))([email protected])
'@mantine/hooks': 9.7.2([email protected])
'@mantine/core': 9.7.3(@mantine/[email protected].3([email protected]))(@types/[email protected])([email protected]([email protected]))([email protected])
'@mantine/hooks': 9.7.3([email protected])
react: 19.3.1
react-dom: 19.3.1([email protected])
recharts: 3.10.1(@types/[email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])
'@mantine/[email protected].2(@mantine/[email protected].2([email protected]))(@types/[email protected])([email protected]([email protected]))([email protected])':
'@mantine/[email protected].3(@mantine/[email protected].3([email protected]))(@types/[email protected])([email protected]([email protected]))([email protected])':
dependencies:
'@floating-ui/react': 0.27.20([email protected]([email protected]))([email protected])
'@mantine/hooks': 9.7.2([email protected])
'@mantine/hooks': 9.7.3([email protected])
clsx: 2.1.1
react: 19.3.1
react-dom: 19.3.1([email protected])
@@ -2804,7 +2804,7 @@ snapshots:
transitivePeerDependencies:
- '@types/react'
'@mantine/[email protected].2([email protected])':
'@mantine/[email protected].3([email protected])':
dependencies:
react: 19.3.1
@@ -2824,7 +2824,7 @@ snapshots:
'@types/geojson': 7946.0.16
pbf: 5.1.2
'@maplibre/geojson-vt@6.1.2':
'@maplibre/geojson-vt@6.3.0':
dependencies:
kdbush: 4.1.0
@@ -2912,7 +2912,7 @@ snapshots:
'@noble/[email protected]': {}
'@oxc-project/[email protected]2.0': {}
'@oxc-project/[email protected]5.0': {}
'@preact/[email protected]': {}
@@ -2928,49 +2928,49 @@ snapshots:
react: 19.3.1
react-redux: 9.3.0(@types/[email protected])([email protected])([email protected])
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]2':
'@rolldown/[email protected]5':
optional: true
'@rolldown/[email protected]': {}
@@ -3152,27 +3152,27 @@ snapshots:
react: 19.3.1
react-dom: 19.3.1([email protected])
'@vis.gl/[email protected]([email protected]4.0)([email protected]([email protected]))([email protected])':
'@vis.gl/[email protected]([email protected]5.0)([email protected]([email protected]))([email protected])':
dependencies:
'@maplibre/maplibre-gl-style-spec': 19.3.3
react: 19.3.1
react-dom: 19.3.1([email protected])
optionalDependencies:
maplibre-gl: 6.14.0
maplibre-gl: 6.15.0
'@vitejs/[email protected]([email protected].4(@types/[email protected])([email protected]))':
'@vitejs/[email protected]([email protected].5(@types/[email protected])([email protected]))':
dependencies:
'@rolldown/pluginutils': 1.0.1
vite: 8.3.4(@types/[email protected])([email protected])
vite: 8.3.5(@types/[email protected])([email protected])
'@vitest/[email protected]([email protected].4(@types/[email protected])([email protected]))':
'@vitest/[email protected]([email protected].5(@types/[email protected])([email protected]))':
dependencies:
'@jridgewell/trace-mapping': 0.3.31
'@vitest/spy': 5.0.4
estree-walker: 3.0.3
magic-string: 1.4.3
optionalDependencies:
vite: 8.3.4(@types/[email protected])([email protected])
vite: 8.3.5(@types/[email protected])([email protected])
'@vitest/[email protected]': {}
@@ -3682,7 +3682,7 @@ snapshots:
[email protected]: {}
[email protected]0.0(@types/[email protected])([email protected]):
[email protected]1.0(@types/[email protected])([email protected]):
dependencies:
react: 19.3.1
optionalDependencies:
@@ -3694,13 +3694,13 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.6.0
[email protected]4.0:
[email protected]5.0:
dependencies:
'@mapbox/point-geometry': 1.1.0
'@mapbox/tiny-sdf': 2.3.0
'@mapbox/unitbezier': 1.0.0
'@mapbox/vector-tile': 3.0.0
'@maplibre/geojson-vt': 6.1.2
'@maplibre/geojson-vt': 6.3.0
'@maplibre/maplibre-gl-style-spec': 26.4.4
'@maplibre/mlt': 1.3.0
'@maplibre/vt-pbf': 4.3.2
@@ -4175,14 +4175,14 @@ snapshots:
[email protected]: {}
[email protected]([email protected]4.0)([email protected]([email protected]))([email protected]):
[email protected]([email protected]5.0)([email protected]([email protected]))([email protected]):
dependencies:
'@vis.gl/react-mapbox': 8.1.3([email protected]([email protected]))([email protected])
'@vis.gl/react-maplibre': 8.1.3([email protected]4.0)([email protected]([email protected]))([email protected])
'@vis.gl/react-maplibre': 8.1.3([email protected]5.0)([email protected]([email protected]))([email protected])
react: 19.3.1
react-dom: 19.3.1([email protected])
optionalDependencies:
maplibre-gl: 6.14.0
maplibre-gl: 6.15.0
[email protected](@types/[email protected])([email protected]):
dependencies:
@@ -4365,26 +4365,26 @@ snapshots:
dependencies:
protocol-buffers-schema: 3.6.1
[email protected]2:
[email protected]5:
dependencies:
'@oxc-project/types': 0.152.0
'@oxc-project/types': 0.155.0
'@rolldown/pluginutils': 1.0.1
optionalDependencies:
'@rolldown/binding-android-arm-eabi': 1.2.12
'@rolldown/binding-android-arm64': 1.2.12
'@rolldown/binding-darwin-arm64': 1.2.12
'@rolldown/binding-darwin-x64': 1.2.12
'@rolldown/binding-freebsd-x64': 1.2.12
'@rolldown/binding-linux-arm-gnueabihf': 1.2.12
'@rolldown/binding-linux-arm64-gnu': 1.2.12
'@rolldown/binding-linux-arm64-musl': 1.2.12
'@rolldown/binding-linux-ppc64-gnu': 1.2.12
'@rolldown/binding-linux-s390x-gnu': 1.2.12
'@rolldown/binding-linux-x64-gnu': 1.2.12
'@rolldown/binding-linux-x64-musl': 1.2.12
'@rolldown/binding-openharmony-arm64': 1.2.12
'@rolldown/binding-win32-arm64-msvc': 1.2.12
'@rolldown/binding-win32-x64-msvc': 1.2.12
'@rolldown/binding-android-arm-eabi': 1.2.15
'@rolldown/binding-android-arm64': 1.2.15
'@rolldown/binding-darwin-arm64': 1.2.15
'@rolldown/binding-darwin-x64': 1.2.15
'@rolldown/binding-freebsd-x64': 1.2.15
'@rolldown/binding-linux-arm-gnueabihf': 1.2.15
'@rolldown/binding-linux-arm64-gnu': 1.2.15
'@rolldown/binding-linux-arm64-musl': 1.2.15
'@rolldown/binding-linux-ppc64-gnu': 1.2.15
'@rolldown/binding-linux-s390x-gnu': 1.2.15
'@rolldown/binding-linux-x64-gnu': 1.2.15
'@rolldown/binding-linux-x64-musl': 1.2.15
'@rolldown/binding-openharmony-arm64': 1.2.15
'@rolldown/binding-win32-arm64-msvc': 1.2.15
'@rolldown/binding-win32-x64-msvc': 1.2.15
[email protected]: {}
@@ -4620,22 +4620,22 @@ snapshots:
d3-time: 3.1.0
d3-timer: 3.0.1
[email protected].4(@types/[email protected])([email protected]):
[email protected].5(@types/[email protected])([email protected]):
dependencies:
lightningcss: 1.33.0
picomatch: 4.0.7
postcss: 8.5.30
rolldown: 1.2.12
rolldown: 1.2.15
tinyglobby: 0.2.17
optionalDependencies:
'@types/node': 26.6.5
esbuild: 0.28.2
fsevents: 2.3.3
[email protected](@types/[email protected])([email protected](@noble/[email protected]))([email protected].4(@types/[email protected])([email protected])):
[email protected](@types/[email protected])([email protected](@noble/[email protected]))([email protected].5(@types/[email protected])([email protected])):
dependencies:
'@types/chai': 5.2.3
'@vitest/mocker': 5.0.4([email protected].4(@types/[email protected])([email protected]))
'@vitest/mocker': 5.0.4([email protected].5(@types/[email protected])([email protected]))
chai: 6.3.0
es-module-lexer: 2.3.2
expect-type: 1.4.0
@@ -4646,7 +4646,7 @@ snapshots:
tinybench: 6.2.2
tinyexec: 1.3.1
tinyglobby: 0.2.17
vite: 8.3.4(@types/[email protected])([email protected])
vite: 8.3.5(@types/[email protected])([email protected])
why-is-node-running: 3.2.1
optionalDependencies:
'@types/node': 26.6.5
+1
View File
@@ -752,6 +752,7 @@ export const ACTIONS: UIAction[] = [
// ── The two side panels. Reached from the keyboard here, and from each
// gutter's own grip, which this pass has not annotated yet.
{ id: "rail.star", kind: "view", target: "none", proof: "interaction" },
{ id: "rail.pick", kind: "view", target: "none", proof: "interaction" },
{ id: "rail.toggle", kind: "view", target: "none", proof: "interaction" },
...SCHEDULE_ACTIONS,
...DOCUMENT_ACTIONS,
+1
View File
@@ -39,6 +39,7 @@ export const EN: Record<string, string> = {
"正在读取历史消息…": "Reading history messages…",
"历史加载失败 · 重试": "History could not be loaded · Retry",
"加载更早的消息": "Load earlier messages",
"更早还有 {n} 条消息,点击加载": "{n} more messages before these — click to load",
"正在查找较早消息…": "Searching earlier messages…",
"部分历史尚未读取": "Some history has not been read",
"此检查点不包含文件快照": "This checkpoint contains no file snapshots",
@@ -0,0 +1,53 @@
import { describe, expect, it } from "vitest";
// `.railhost` is a zero-height sticky layer over the transcript, so it turns
// pointer events off and every child that a person can press has to turn them
// back on. Forgetting that is invisible to jsdom — it does no hit testing — and
// shows up only as "the rows cannot be clicked" in a real browser.
const SHEETS = import.meta.glob("./{app,studio}.css", { query: "?raw", import: "default", eager: true }) as Record<string, string>;
interface Rule {
selector: string;
decls: Map<string, string>;
}
function rules(css: string): Rule[] {
const out: Rule[] = [];
for (const m of css.replace(/\/\*[\s\S]*?\*\//g, "").matchAll(/([^{}]+)\{([^{}]*)\}/g)) {
const decls = new Map<string, string>();
for (const part of m[2].split(";")) {
const at = part.indexOf(":");
if (at > 0) decls.set(part.slice(0, at).trim(), part.slice(at + 1).trim());
}
out.push({ selector: m[1].trim(), decls });
}
return out;
}
/** The declarations that apply to `className`, across every sheet, in source order. */
function declsOf(className: string): Map<string, string> {
const merged = new Map<string, string>();
for (const css of Object.values(SHEETS)) {
for (const rule of rules(css)) {
if (!rule.selector.split(",").some((s) => s.trim() === `.${className}`)) continue;
for (const [k, v] of rule.decls) merged.set(k, v);
}
}
return merged;
}
describe("the conversation rail can be pressed", () => {
it("turns pointer events off on the layer that floats over the transcript", () => {
expect(declsOf("railhost").get("pointer-events")).toBe("none");
});
// Anything a person can press inside that layer has to opt back in. The rail
// itself always did; the two surfaces added with it — the unloaded-history
// marker and the opened run — did not, and their rows fell through to the
// transcript underneath.
for (const surface of ["srail", "srail-earlier", "srail-sub"]) {
it(`lets .${surface} take the pointer`, () => {
expect(declsOf(surface).get("pointer-events"), `.${surface} sits inside pointer-events: none`).toBe("auto");
});
}
});
+1 -1
View File
@@ -714,7 +714,7 @@ body { background: var(--page) !important; }
background: color-mix(in srgb, var(--text) 38%, transparent);
}
.srail-m[data-on] > i { background: #91a7df; }
.srail-peek { right: 42px; width: min(300px, calc(100vw - var(--rail-w) - 78px)); }
.srail-peek { right: 42px; width: min(300px, calc(100vw - var(--rail-w) - 78px)); } .srail-earlier { right: 12px; width: 3px; height: 10px; margin-top: -5px; z-index: 2; padding: 0; border: 0; border-radius: 2px; background: color-mix(in srgb, var(--text) 26%, transparent); cursor: pointer; pointer-events: auto; } .srail-earlier:hover { background: var(--accent-ink) } .srail-sub { position: absolute; right: 42px; z-index: 6; width: 220px; max-height: 260px; overflow-y: auto; padding: 6px; border: 1px solid var(--border); border-radius: 10px; background: var(--float); box-shadow: var(--shadow-float); transform: translateY(-50%); pointer-events: auto; } .srail-subhd { padding: 2px 6px 4px; color: var(--faint); font: 500 calc(10px * var(--fs-scale, 1))/1.4 var(--ui); } .srail-subrow { display: block; width: 100%; padding: 4px 6px; border: 0; border-radius: 6px; background: none; color: var(--text); font: 450 calc(11px * var(--fs-scale, 1))/1.45 var(--ui); text-align: start; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .srail-subrow:hover { background: var(--overlay) }
.flow {
width: min(var(--doc), calc(100% - var(--srail-w) - 44px));
margin-inline: auto;
@@ -247,6 +247,7 @@ describe("screenshots", () => {
const node = target === "heading" ? document.querySelector("#fbk-title")! : document.activeElement!;
fireEvent.paste(node, { clipboardData: { files: [png("dialog.png")] } });
expect(await screen.findByAltText("dialog.png")).toBeTruthy();
// The draft is held from an effect, which can run after the thumbnail is on screen.
await waitFor(() => expect(heldDraft().shots.map((s) => s.name)).toEqual(["dialog.png"]));
});
@@ -86,6 +86,37 @@ describe("a rail longer than it can show", () => {
// that holds the thousandth rather than on the thousandth itself.
expect(Math.abs(picked - 1000)).toBeLessThanOrEqual(40);
});
it("opens a folded run instead of guessing which question it stands for", async () => {
const { view, onJump } = await rail(2000);
const run = view.container.querySelector<HTMLElement>(".srail-m[data-folded]");
expect(run, "2000 questions in 600px must fold").not.toBeNull();
// First press: nothing jumps, because the run names a range and the reader
// has not said which question in it yet.
fireEvent.click(run!);
expect(onJump).not.toHaveBeenCalled();
const rows = view.container.querySelectorAll<HTMLElement>(".srail-subrow");
expect(rows.length).toBeGreaterThan(1);
// Second press, on a row: that question, exactly.
const label = rows[1].textContent ?? "";
fireEvent.click(rows[1]);
expect(onJump).toHaveBeenCalledTimes(1);
expect((onJump.mock.calls[0][0] as RailMark).text).toBe(label);
expect(view.container.querySelector(".srail-sub")).toBeNull();
});
it("jumps on the second press when the run is already open", async () => {
const { view, onJump } = await rail(2000);
const run = view.container.querySelector<HTMLElement>(".srail-m[data-folded]")!;
fireEvent.click(run);
fireEvent.click(run);
// Open, then the same line again: the contract the run carried before rows
// existed, kept so a fast second press is not a dead click.
expect(onJump).toHaveBeenCalledTimes(1);
expect(view.container.querySelector(".srail-sub")).toBeNull();
});
});
describe("a star belongs to the question, not the row id", () => {
+55 -3
View File
@@ -37,6 +37,11 @@ interface Props {
// Only the transcript on screen answers the keys; a pane on another tab keeps
// its rail but must not fight for them.
bound: boolean;
/** Raw messages still unloaded before the first mark. A paged conversation
* mounts only its tail, so the rail would otherwise look complete while most
* of the conversation is still on disk. */
earlier?: number;
onLoadEarlier?: () => void;
}
// The native scrollbar owns continuous position. The semantic rail is a compact
@@ -147,13 +152,17 @@ export function railLocalY(clientY: number, rectTop: number, rectHeight: number,
return (clientY - rectTop) * (railHeight / rectHeight);
}
export function Rail({ marks, total, scroll, flow, onJump, bound, scope }: Props) {
export function Rail({ marks, total, scroll, flow, onJump, bound, scope, earlier = 0, onLoadEarlier }: Props) {
const host = useRef<HTMLDivElement>(null);
const [tops, setTops] = useState<number[]>([]);
// Null while every question keeps its own line; a list once they have to
// share, because reading them apart has stopped working.
const [groups, setGroups] = useState<RailView[] | null>(null);
const [at, setAt] = useState(-1);
// Which folded run has been opened into its own questions. A run is one line
// standing for many; without this a press can only mean "the first of them",
// which is not the question the reader pointed at.
const [opened, setOpened] = useState<number | null>(null);
// Which mark the keys last walked to. Kept apart from `at`, which the pointer
// owns: hovering somewhere else must not move where the keys resume from.
const here = useRef(-1);
@@ -316,11 +325,24 @@ export function Rail({ marks, total, scroll, flow, onJump, bound, scope }: Props
};
if (marks.length === 0) return null;
const shown = at >= 0 && at < view.length ? view[at] : null;
const shown = opened === null && at >= 0 && at < view.length ? view[at] : null;
const head = shown ? marks[shown.from] : null;
return (
<div className="railhost" ref={host} aria-hidden={undefined}>
{/* A paged conversation mounts only its tail. Without this the rail ends
where the loaded window begins and reads as a short conversation. */}
{earlier > 0 && onLoadEarlier && (
<button
type="button"
className="srail-earlier"
style={{ top: Math.max(6, (view[0]?.top ?? PAD) - 14) }}
aria-label={t("更早还有 {n} 条消息,点击加载", { n: earlier })}
title={t("更早还有 {n} 条消息,点击加载", { n: earlier })}
data-action="history.more"
onClick={onLoadEarlier}
/>
)}
<nav
className="srail"
aria-label={t("你说过的话")}
@@ -362,7 +384,11 @@ export function Rail({ marks, total, scroll, flow, onJump, bound, scope }: Props
title={m.msgIndex === undefined ? undefined : starred ? t("右键取消这处星标") : t("右键给这处加星标")}
onFocus={() => setAt(i)}
onBlur={() => setAt(-1)}
onClick={() => onJump(m)}
onClick={() => {
if (!folded) { onJump(m); return; }
if (opened === i) { setOpened(null); onJump(m); return; }
setOpened(i);
}}
onContextMenu={(e) => {
e.preventDefault();
star(m.msgIndex);
@@ -382,6 +408,32 @@ export function Rail({ marks, total, scroll, flow, onJump, bound, scope }: Props
);
})}
</nav>
{/* A folded run is one line standing for many, so a press on it can only
guess. Opening it first lets the reader pick the question they meant;
every row is one mark, and the run closes on the way out. */}
{opened !== null && view[opened] && !view[opened].single && (
<div
className="srail-sub"
style={{ top: Math.min(Math.max(view[opened].top, 60), Math.max(60, geom.current.rail - 60)) }}
>
<div className="srail-subhd">{t("第 {a} 至 {b} 条", { a: view[opened].from + 1, b: view[opened].to + 1 })}</div>
{Array.from({ length: view[opened].to - view[opened].from + 1 }, (_, k) => {
const mk = marks[view[opened]!.from + k];
if (!mk) return null;
return (
<button
key={mk.id}
type="button"
className="srail-subrow"
data-action="rail.pick"
onClick={() => { setOpened(null); onJump(mk); }}
>
{mk.text.slice(0, 60)}
</button>
);
})}
</div>
)}
{/* 贴着轨道两端的那几条,预览要收进容器里 —— 否则它会被裁掉一半 */}
{shown && (
<div
+1 -1
View File
@@ -471,7 +471,7 @@ export function Transcript({ items, port, historyPaging, entering, onEntered, br
ref={scroll}
hidden={hidden}
>
<Rail marks={marks} total={items.length} scroll={scroll} flow={flow} onJump={jumpTo} bound={!hidden} scope={scope} />
<Rail marks={marks} total={items.length} scroll={scroll} flow={flow} onJump={jumpTo} bound={!hidden} scope={scope} earlier={historyPaging?.earlier ?? 0} onLoadEarlier={historyPaging?.hasMore ? loadOlder : undefined} />
<div className="flow-edge" aria-hidden="true" />
{/* 空转录是「窗口的空白」,壁纸该在那儿;一有内容它就是内容了。 */}
<div className="flow" ref={flow} data-empty={items.length === 0 && !historyPaging?.hasMore && !historyPaging?.busy && !historyPaging?.failed ? "" : undefined}>
@@ -27,7 +27,7 @@ function fixture(contents = false) {
const generation = { current: 0 };
const release = vi.fn();
const land = vi.fn();
const paging: HistoryPaging = { snapshot: "one", revision: 1, hasMore: true, busy: false, failed: false, more: vi.fn(async () => {}), reload: vi.fn(async () => {}) };
const paging: HistoryPaging = { snapshot: "one", revision: 1, hasMore: true, busy: false, failed: false, earlier: 0, more: vi.fn(async () => {}), reload: vi.fn(async () => {}) };
const hook = renderHook(({ revision, snapshot = "one", hidden = false }) => useHistoryAnchor({ ...paging, revision, snapshot }, scroll, [[item]], hidden, generation, release, land),
{ initialProps: { revision: 1, snapshot: "one", hidden: false } });
return { ...hook, generation, land, paging };
@@ -127,7 +127,7 @@ it("continues searching when fast page responses batch busy state transitions",
it("searches the next page when a committed revision is the only changed read state", () => {
const more = vi.fn(async () => {});
const paging = { snapshot: "one", revision: 1, hasMore: true, busy: false, failed: false, more, reload: vi.fn(async () => {}) };
const paging = { snapshot: "one", revision: 1, hasMore: true, busy: false, failed: false, earlier: 0, more, reload: vi.fn(async () => {}) };
const { rerender } = renderHook(({ revision }) => useHistorySearch({ ...paging, revision }, true, "needle"), { initialProps: { revision: 1 } });
expect(more).toHaveBeenCalledTimes(1);
rerender({ revision: 2 });
@@ -9,6 +9,10 @@ export interface HistoryPaging {
hasMore: boolean;
busy: boolean;
failed: boolean;
/** How many raw messages sit before the loaded window. The rail draws only
* what is mounted, so without this a paged conversation looks shorter than
* it is until someone scrolls up. */
earlier: number;
more: () => Promise<void>;
reload: () => Promise<void>;
}
@@ -41,7 +45,7 @@ export function useHistoryPages(port: Pick<AgentPort, "history" | "historyPage">
const owner = useMemo(() => ({ epoch: 0, cursor: "", snapshot: "", before: 0, total: 0, paging: !!port.historyPage, more: null as Promise<void> | null }), [port]);
const current = useRef(owner);
current.current = owner;
const [state, setState] = useState({ snapshot: "", revision: 0, hasMore: false, busy: false, failed: false });
const [state, setState] = useState({ snapshot: "", revision: 0, hasMore: false, busy: false, failed: false, earlier: 0 });
useEffect(() => () => { owner.epoch++; }, [owner]);
const load = useCallback(async (applies: () => boolean = () => true) => {
@@ -67,7 +71,7 @@ export function useHistoryPages(port: Pick<AgentPort, "history" | "historyPage">
owner.before = page?.start ?? 0;
owner.total = page?.total ?? 0;
dispatch({ kind: "__restore", ...restored });
setState((old) => ({ snapshot: owner.snapshot, revision: old.revision + 1, hasMore: !!owner.cursor, busy: false, failed: false }));
setState((old) => ({ snapshot: owner.snapshot, revision: old.revision + 1, hasMore: !!owner.cursor, busy: false, failed: false, earlier: owner.before }));
} catch (error) {
if (valid()) setState((old) => ({ ...old, busy: false, failed: true }));
throw error;
@@ -90,7 +94,7 @@ export function useHistoryPages(port: Pick<AgentPort, "history" | "historyPage">
owner.before = page.start;
owner.more = null;
dispatch({ kind: "__history_prepend", ...projection(page) });
setState((old) => ({ ...old, revision: old.revision + 1, hasMore: !!owner.cursor, busy: false, failed: false }));
setState((old) => ({ ...old, revision: old.revision + 1, hasMore: !!owner.cursor, busy: false, failed: false, earlier: owner.before }));
}).catch(async (error) => {
if (!valid()) return;
if (error instanceof HttpError && error.reason?.code === "history.snapshot_changed") { await load(); return; }
+4 -4
View File
@@ -22,22 +22,22 @@ require (
github.com/aymanbagabas/go-udiff v0.4.1 // indirect
github.com/bmatcuk/doublestar/v4 v4.10.3 // indirect
github.com/danieljoos/wincred v1.2.3 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dustin/go-humanize v1.1.0 // indirect
github.com/godbus/dbus/v5 v5.2.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/mattn/go-isatty v0.0.24 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/ncruces/go-strftime v1.1.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.3 // indirect
github.com/zalando/go-keyring v0.2.8 // indirect
golang.org/x/crypto v0.58.0 // indirect
golang.org/x/net v0.61.0 // indirect
golang.org/x/text v0.43.0 // indirect
modernc.org/libc v1.77.1 // indirect
modernc.org/libc v1.79.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.12.1 // indirect
modernc.org/sqlite v1.60.1 // indirect
modernc.org/sqlite v1.61.0 // indirect
mvdan.cc/sh/v3 v3.14.1 // indirect
)
+18 -18
View File
@@ -18,16 +18,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/dustin/go-humanize v1.1.0 h1:dbKTrvD0klcbBV/h4AWJdMuZogJACoMlvWIWZ5b2xWg=
github.com/dustin/go-humanize v1.1.0/go.mod h1:hc1CvRkJMsgxqjmjMQF3QNRAZBwY8AXBAzKYoSX9sFI=
github.com/go-quicktest/qt v1.102.0 h1:HSQxCeh5YZH3EL3W39ixjtyaEhcWSXQHtHnMBzSs474=
github.com/go-quicktest/qt v1.102.0/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI=
github.com/godbus/dbus/v5 v5.2.4 h1:F2gUCy++NMIxGmo9J+z5le/+ZC8W1OgeR51P4i9ZB/U=
github.com/godbus/dbus/v5 v5.2.4/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3 h1:LMLX+LgTNWpfvCBdFebv6EsYotImrt/Ppc5cXIriCSo=
github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3/go.mod h1:jl5iWTm0/hd5PjEYEOuwAJ57L/CibdZfrqZ5XA5GrCk=
github.com/google/pprof v0.0.0-20261016150608-1facf8f91b50 h1:PlNWJRxu5APSV0pWqfIsZ0qt9OOGHSWfZQ4zvx+WgWs=
github.com/google/pprof v0.0.0-20261016150608-1facf8f91b50/go.mod h1:yUo1AMMpsPIDFGuwDK8nLcf8+vvAd5l2O6JDZ6hpwrM=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
@@ -44,8 +44,8 @@ github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsRe
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
github.com/mattn/go-runewidth v0.0.31 h1:1oCV4ReTlosDBc6rYRw5cL8S/4y8iv5oRl4SJ5IBgwo=
github.com/mattn/go-runewidth v0.0.31/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/ncruces/go-strftime v1.1.0 h1:vtPmPWMkb539RGV9WpWT9EwJGvrOCKvMNI4obWL47Hk=
github.com/ncruces/go-strftime v1.1.0/go.mod h1:yVaq7iwCN09vHRrKBrrflXT0M9tTMG2KmZ9Fj7xeG/g=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
@@ -74,24 +74,24 @@ golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA=
golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc=
golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s=
golang.org/x/tools v0.51.0 h1:k4Xc/1Om9jwkBJBo4NVLMSARBoWtK10mx+W5BnXCeAI=
golang.org/x/tools v0.51.0/go.mod h1:9eEncMayCV6zRMGhR5eZEC2iBx98qWcF1HZ9Z7wJOoA=
golang.org/x/tools v0.52.0 h1:ryxg4U63oaUYk7uOLTF37n43f4qgtGvqV4Ioit1BaEs=
golang.org/x/tools v0.52.0/go.mod h1:ItcP5UNaVGG+Yc4eIYmaFLNJ4soEopkx5Y2d4lcEurs=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.29.7 h1:q+NXGJ0bK3b4TXFYQQVr9pYETGnmwFWkrUzJnMya/Tg=
modernc.org/cc/v4 v4.29.7/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.36.1 h1:ZNIUZAryN0UgnJwtyxrdEzcFc3yD4Cu4AzjfPXsLsIE=
modernc.org/ccgo/v4 v4.36.1/go.mod h1:rrtGc2QkS239nYb/mQNuBMyjq3/y3ZXWbBjPoV3wqzA=
modernc.org/cc/v4 v4.30.3 h1:aDq8gIX1X7+VFgO/JYYji6pLWL2H4tv3g8WatT3KCys=
modernc.org/cc/v4 v4.30.3/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.37.0 h1:BAuJCUtIHIxFIYaFhqXIw5YaoMBlNCUlFovejHfMip4=
modernc.org/ccgo/v4 v4.37.0/go.mod h1:/8627VhwWtAbqUXmPORxFQU5SgLrAx2jl9seLw9GBhY=
modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM=
modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.5 h1:21ldfPfRYE31Tb7B3mwAK8gy1AxP4+dKjrOQPfqakoc=
modernc.org/gc/v3 v3.1.5/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/gc/v3 v3.2.0 h1:/Y3LGDMQaoYf55PebP1qsZ5FDGgAZyG1RYKEHeQzh1o=
modernc.org/gc/v3 v3.2.0/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.77.1 h1:Ct8j47QtiZ1Enj2DtFXQtUqrPCAjdCmPjtCuvrYQ0Hs=
modernc.org/libc v1.77.1/go.mod h1:87/pZ4L6nD1zqW4nItuS12YO7hN1igAah34xjnQo/W0=
modernc.org/libc v1.79.0 h1:9Dvvv++bAMSkSuBzuOFAatbTV5OIoq6Y6FohmD3e7q8=
modernc.org/libc v1.79.0/go.mod h1:uT3kR61NsbeKJSLqq83GJwSnZMVLlSjyAz4DfTaBy1M=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.12.1 h1:nFMiWrpStgZczNl6XI9GnIk/rWhYIyHGUaR04pGbp9g=
@@ -100,8 +100,8 @@ modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg=
modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.60.1 h1:/blz53O951KWFOso4QQvEs/Fq6cDBKLtMVrYNSeJVKw=
modernc.org/sqlite v1.60.1/go.mod h1:1dIoEagfDE72QytD5scH1lxARtaUgKgHC/NuApA27r0=
modernc.org/sqlite v1.61.0 h1:sQi63oLQ9uquAUA4CzOisH35Q3pEszkPBuHM0tFL8CY=
modernc.org/sqlite v1.61.0/go.mod h1:f4gr5tbpx2umklaT/QVtbi/50hNdM+4ng+2zMo8KXJ0=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
+45
View File
@@ -1662,6 +1662,51 @@ sources are merged; on a name collision `reasonix.toml` wins.
keep working — move them into `reasonix.toml`'s `[[plugins]]` or a `.mcp.json` when
convenient.
## Custom instructions / 提示词怎么注入
Choose the scope before adding a prompt.
### One task / 单次任务
Type the instructions in chat. For a reusable prompt you invoke explicitly,
use a [custom slash command](#slash-commands).
直接在聊天框输入要求。需要反复手动调用的提示词可写成[自定义斜杠命令](#slash-commands)。
### Repository rules / 仓库规则
- Create `AGENTS.md`, or use the repository's existing `REASONIX.md` / `CLAUDE.md`,
at the workspace root. For example: `- Run the project tests before reporting completion.`
- Use `AGENTS.local.md` for personal rules in that directory, or an instruction
file in your Reasonix home for user-global rules.
- See [standing-instruction resolution](./SESSION_MEMORY_RETRIEVAL.md#instruction-resolution)
for hierarchy, imports, and `/memory instructions` to inspect what loaded.
- 在工作区根目录创建 `AGENTS.md`,或沿用仓库已有的 `REASONIX.md` / `CLAUDE.md`。
例如添加 `- 完成前运行项目测试。`。
- 当前目录的个人规则可放在 `AGENTS.local.md`;跨项目的用户规则放在 Reasonix 主目录中的指令文件。
- 层级、导入及查看已加载内容的 `/memory instructions` 命令见
[常驻指令文档](./SESSION_MEMORY_RETRIEVAL.md#instruction-resolution)。
### User-wide persona / 用户级人设
1. In Studio, open **Settings → Persona → System persona**.
2. Fill **Start of the system prompt** and/or **Additional instructions**, then **Save**.
3. Start a new session, or wait for the existing session's next rebuild
(for example, a model switch). Saving does **not** change the running session's prompt.
These settings supplement built-in guidance; they do not replace it. They are
stored in your user configuration, not a project's `reasonix.toml`.
See [System persona](./PERSONA.md) for configuration fields and limits.
1. 在 Studio 打开**设置 → 人设 → 系统人设**。
2. 填写**系统提示词开头**和/或**补充要求**,点击**保存**。
3. 新建会话,或等现有会话下一次重建(例如切换模型)后生效。
**保存不会改变正在运行的会话提示词**。
这些设置补充而非替换内置指令,写入用户配置,不由项目 `reasonix.toml` 设置。
配置字段及限制见[系统人设](./PERSONA.md)。
## Slash commands
In an interactive `reasonix` session, built-in commands (`/compact`, `/context`, `/new`, `/clear`, `/rewind`,
+60
View File
@@ -34,3 +34,63 @@ of an existing session (for example, a model switch) read the saved persona.
`suffix` 及可选的 `include_runtime_context`。文本会去除首尾空白,每段最多
32 KiB,总计最多 64 KiB。保存本身不重建会话;新会话及现有会话下一次重建
(例如切换模型)时读取已保存的人设。
## Can different projects use different personas? / 不同项目能使用不同人设吗?
**The system persona is user-scoped, not project-scoped.** Use it for preferences
you want across projects. For project-specific roles, terminology and working
conventions, use standing instructions instead; this supplements the system
persona rather than configuring a separate `[agent.persona]`.
**系统人设属于用户级配置,不支持按项目分别配置。** 跨项目通用的偏好放在人设中;
项目特定的角色、术语和工作约定放在常驻指令中。这是对系统人设的补充,
不是为项目配置另一份 `[agent.persona]`。
### How do I add project guidance? / 如何添加项目指引?
Open the project as the session's workspace. Create or edit `REASONIX.md` at its
root, preserving any existing instructions. For example, one project's file
could contain:
将项目作为会话工作区打开,在项目根目录创建或编辑 `REASONIX.md`,保留已有指令。
例如,某个项目的文件可以包含:
```markdown
# Project guidance / 项目指引
- Act as a documentation reviewer for this project.
在本项目中,以文档审阅者的视角工作。
- Use the terminology in docs/GLOSSARY.md when that file exists.
若 docs/GLOSSARY.md 存在,使用其中的术语。
- Explain user-visible changes in both English and Chinese.
用中英文说明用户可见的变更。
```
Give another project its own `REASONIX.md`. Commit shared conventions with the
project; use `REASONIX.local.md` in the same directory for personal instructions
(exclude it from version control yourself if it should stay private). Other
supported instruction files are loaded too, not replaced by `REASONIX.md`.
其他项目可使用各自的 `REASONIX.md`。团队约定随项目提交;个人指令可放在同目录的
`REASONIX.local.md` 中(如不希望提交,请自行将其排除在版本控制之外)。
其他受支持的指令文件也会加载,不会被 `REASONIX.md` 替换。
### When do edits apply, and what can they override? / 何时生效,能覆盖什么?
Standing instructions are rediscovered from disk for each turn. Save the file
before sending the next message; no `/reload` or new session is needed, and an
already-running turn is not retroactively changed. This differs from saving the
user persona, which takes effect only at the next session build described above.
常驻指令每轮都会从磁盘重新发现。发送下一条消息前保存文件即可,无须 `/reload`
或新建会话,也不会追溯修改正在执行的轮次。这与用户人设不同:保存人设后,
要等到上文所述的下一次会话构建才生效。
Project instructions do not replace built-in or higher-priority guidance, change
the user-only persona boundary, or grant tool permissions or sandbox access.
See the [Guide](./GUIDE.md) and [中文指南](./GUIDE.zh-CN.md) for hierarchical
standing instructions, rules, and permissions.
项目指令不能替换内置或更高优先级的指令,不能改变人设仅限用户级配置的边界,
也不能授予工具权限或沙箱访问权限。指令层级、规则和权限说明见
[Guide](./GUIDE.md) 和 [中文指南](./GUIDE.zh-CN.md)。
+5 -5
View File
@@ -28,7 +28,7 @@ require (
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
github.com/santhosh-tekuri/jsonschema/v6 v6.0.3
github.com/spf13/pflag v1.0.10
github.com/tdewolff/parse/v2 v2.8.18
github.com/tdewolff/parse/v2 v2.8.19
github.com/tree-sitter/go-tree-sitter v0.25.0
github.com/tree-sitter/tree-sitter-javascript v0.25.0
github.com/tree-sitter/tree-sitter-python v0.25.0
@@ -46,7 +46,7 @@ require (
golang.org/x/term v0.47.0
golang.org/x/text v0.43.0
gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.60.1
modernc.org/sqlite v1.61.0
mvdan.cc/sh/v3 v3.14.1
rsc.io/qr v0.2.0
)
@@ -60,7 +60,7 @@ require (
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/danieljoos/wincred v1.2.3 // indirect
github.com/dlclark/regexp2/v2 v2.2.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dustin/go-humanize v1.1.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/kr/fs v0.1.0 // indirect
@@ -68,11 +68,11 @@ require (
github.com/mattn/go-isatty v0.0.24 // indirect
github.com/mattn/go-pointer v0.0.1 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/ncruces/go-strftime v1.1.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/xo/terminfo v1.0.0 // indirect
golang.org/x/sync v0.24.0 // indirect
modernc.org/libc v1.77.1 // indirect
modernc.org/libc v1.79.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.12.1 // indirect
)
+20 -20
View File
@@ -51,8 +51,8 @@ github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxK
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2/v2 v2.2.1 h1:mf4KkFUj0gJuarK8P+LgiS+Lit7m9N1yAwEfPbee7R0=
github.com/dlclark/regexp2/v2 v2.2.1/go.mod h1:avUrQvPaLz2DrFNHJF0taWAFFX2C1GMSSoeiqFjcBmU=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/dustin/go-humanize v1.1.0 h1:dbKTrvD0klcbBV/h4AWJdMuZogJACoMlvWIWZ5b2xWg=
github.com/dustin/go-humanize v1.1.0/go.mod h1:hc1CvRkJMsgxqjmjMQF3QNRAZBwY8AXBAzKYoSX9sFI=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-quicktest/qt v1.102.0 h1:HSQxCeh5YZH3EL3W39ixjtyaEhcWSXQHtHnMBzSs474=
@@ -61,8 +61,8 @@ github.com/godbus/dbus/v5 v5.2.4 h1:F2gUCy++NMIxGmo9J+z5le/+ZC8W1OgeR51P4i9ZB/U=
github.com/godbus/dbus/v5 v5.2.4/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3 h1:LMLX+LgTNWpfvCBdFebv6EsYotImrt/Ppc5cXIriCSo=
github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3/go.mod h1:jl5iWTm0/hd5PjEYEOuwAJ57L/CibdZfrqZ5XA5GrCk=
github.com/google/pprof v0.0.0-20261016150608-1facf8f91b50 h1:PlNWJRxu5APSV0pWqfIsZ0qt9OOGHSWfZQ4zvx+WgWs=
github.com/google/pprof v0.0.0-20261016150608-1facf8f91b50/go.mod h1:yUo1AMMpsPIDFGuwDK8nLcf8+vvAd5l2O6JDZ6hpwrM=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
@@ -93,8 +93,8 @@ github.com/mattn/go-runewidth v0.0.31 h1:1oCV4ReTlosDBc6rYRw5cL8S/4y8iv5oRl4SJ5I
github.com/mattn/go-runewidth v0.0.31/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/ncruces/go-strftime v1.1.0 h1:vtPmPWMkb539RGV9WpWT9EwJGvrOCKvMNI4obWL47Hk=
github.com/ncruces/go-strftime v1.1.0/go.mod h1:yVaq7iwCN09vHRrKBrrflXT0M9tTMG2KmZ9Fj7xeG/g=
github.com/pkg/sftp v1.13.11 h1:0N92SLTB8JqASJB14ZLHHzFnBV8mG9zw4K7jghEFWuE=
github.com/pkg/sftp v1.13.11/go.mod h1:uNkH9roSXglNJqM+glJJi+TQXQUm0fXFWqCFmT8hsN0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -117,8 +117,8 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tdewolff/parse/v2 v2.8.18 h1:XkWp4Ow06VF8xGWy3ifh/aOK66UsSAs8p1nsFX0Jj3k=
github.com/tdewolff/parse/v2 v2.8.18/go.mod h1:OemXEPll2+Sn7pQ6xFxC9cEm1wDnNt1hC2q3jIh+OoI=
github.com/tdewolff/parse/v2 v2.8.19 h1:p+JoZI06kApwHWyOe/BAsl7DC06UqyDDbAKU68/9I4w=
github.com/tdewolff/parse/v2 v2.8.19/go.mod h1:OemXEPll2+Sn7pQ6xFxC9cEm1wDnNt1hC2q3jIh+OoI=
github.com/tdewolff/test v1.0.12 h1:7F21DqIajswxuche0geHdrUZRCWE4oko4b7bcmkkrxk=
github.com/tdewolff/test v1.0.12/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
github.com/tree-sitter/go-tree-sitter v0.25.0 h1:sx6kcg8raRFCvc9BnXglke6axya12krCJF5xJ2sftRU=
@@ -178,8 +178,8 @@ golang.org/x/term v0.47.0 h1:cpyOwQkr2Nzxe2p6KnrTG7Ei2wtzjsuSjhpXXepZ/BM=
golang.org/x/term v0.47.0/go.mod h1:efAfAuG6RKABvg1ArGebRkvX6LXul14SM67o2e4mUCY=
golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc=
golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s=
golang.org/x/tools v0.51.0 h1:k4Xc/1Om9jwkBJBo4NVLMSARBoWtK10mx+W5BnXCeAI=
golang.org/x/tools v0.51.0/go.mod h1:9eEncMayCV6zRMGhR5eZEC2iBx98qWcF1HZ9Z7wJOoA=
golang.org/x/tools v0.52.0 h1:ryxg4U63oaUYk7uOLTF37n43f4qgtGvqV4Ioit1BaEs=
golang.org/x/tools v0.52.0/go.mod h1:ItcP5UNaVGG+Yc4eIYmaFLNJ4soEopkx5Y2d4lcEurs=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -188,20 +188,20 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.29.7 h1:q+NXGJ0bK3b4TXFYQQVr9pYETGnmwFWkrUzJnMya/Tg=
modernc.org/cc/v4 v4.29.7/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.36.1 h1:ZNIUZAryN0UgnJwtyxrdEzcFc3yD4Cu4AzjfPXsLsIE=
modernc.org/ccgo/v4 v4.36.1/go.mod h1:rrtGc2QkS239nYb/mQNuBMyjq3/y3ZXWbBjPoV3wqzA=
modernc.org/cc/v4 v4.30.3 h1:aDq8gIX1X7+VFgO/JYYji6pLWL2H4tv3g8WatT3KCys=
modernc.org/cc/v4 v4.30.3/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.37.0 h1:BAuJCUtIHIxFIYaFhqXIw5YaoMBlNCUlFovejHfMip4=
modernc.org/ccgo/v4 v4.37.0/go.mod h1:/8627VhwWtAbqUXmPORxFQU5SgLrAx2jl9seLw9GBhY=
modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM=
modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.5 h1:21ldfPfRYE31Tb7B3mwAK8gy1AxP4+dKjrOQPfqakoc=
modernc.org/gc/v3 v3.1.5/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/gc/v3 v3.2.0 h1:/Y3LGDMQaoYf55PebP1qsZ5FDGgAZyG1RYKEHeQzh1o=
modernc.org/gc/v3 v3.2.0/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.77.1 h1:Ct8j47QtiZ1Enj2DtFXQtUqrPCAjdCmPjtCuvrYQ0Hs=
modernc.org/libc v1.77.1/go.mod h1:87/pZ4L6nD1zqW4nItuS12YO7hN1igAah34xjnQo/W0=
modernc.org/libc v1.79.0 h1:9Dvvv++bAMSkSuBzuOFAatbTV5OIoq6Y6FohmD3e7q8=
modernc.org/libc v1.79.0/go.mod h1:uT3kR61NsbeKJSLqq83GJwSnZMVLlSjyAz4DfTaBy1M=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.12.1 h1:nFMiWrpStgZczNl6XI9GnIk/rWhYIyHGUaR04pGbp9g=
@@ -210,8 +210,8 @@ modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg=
modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.60.1 h1:/blz53O951KWFOso4QQvEs/Fq6cDBKLtMVrYNSeJVKw=
modernc.org/sqlite v1.60.1/go.mod h1:1dIoEagfDE72QytD5scH1lxARtaUgKgHC/NuApA27r0=
modernc.org/sqlite v1.61.0 h1:sQi63oLQ9uquAUA4CzOisH35Q3pEszkPBuHM0tFL8CY=
modernc.org/sqlite v1.61.0/go.mod h1:f4gr5tbpx2umklaT/QVtbi/50hNdM+4ng+2zMo8KXJ0=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
@@ -0,0 +1,2 @@
- 文档:用户指南新增「提示词怎么注入」快速说明,区分聊天要求、仓库常驻指令和用户级人设,并说明设置入口及人设保存后的生效时机。关联 #13512。
- Docs: added a prompt-customization quick start covering chat, repository rules and user-wide personas, including settings navigation and save timing. Refs #13512.
@@ -0,0 +1,2 @@
- 新增:历史对话鱼眼里合并成一条的多轮对话,点一下会展开成具体每一条,再选要跳的那条。关联 #14396。
- Added: a folded run on the conversation rail opens into its own questions on a click, so you pick the one you meant. Refs #14396.