diff --git a/package.json b/package.json index 0f488e4..1e0a18b 100644 --- a/package.json +++ b/package.json @@ -27,30 +27,30 @@ "postinstall": "quasar prepare" }, "dependencies": { - "@anthropic-ai/claude-agent-sdk": "0.3.299", - "@fastify/static": "10.1.6", + "@anthropic-ai/claude-agent-sdk": "0.3.310", + "@fastify/static": "10.1.7", "@fontsource/inter": "5.3.0", "@fontsource/jetbrains-mono": "5.3.0", "@quasar/extras": "2.1.0", - "chart.js": "4.5.1", + "chart.js": "4.6.1", "dompurify": "3.4.17", "fastify": "5.12.7", "highlight.js": "11.12.0", "lottie-web": "5.13.0", - "markdown-it": "15.0.2", + "markdown-it": "15.0.3", "mermaid": "12.2.0", "node-telegram-bot-api": "2.1.0", - "pinia": "4.0.3", - "quasar": "2.35.1", + "pinia": "4.1.0", + "quasar": "2.35.2", "vue": "3.5.44", - "vue-i18n": "11.4.14", + "vue-i18n": "11.4.16", "vue-router": "5.4.0", "zod": "4.6.7" }, "devDependencies": { "@eslint/js": "10.0.1", "@lehoczky/eslint-config-vitest": "2.1.0", - "@quasar/app-vite": "3.10.2", + "@quasar/app-vite": "3.10.3", "@types/node": "24.19.2", "@vue/eslint-config-typescript": "14.9.0", "autoprefixer": "10.6.1", @@ -59,7 +59,7 @@ "eslint-plugin-prettier": "5.5.7", "eslint-plugin-vue": "10.11.1", "globals": "17.13.0", - "playwright": "1.64.0", + "playwright": "1.64.1", "prettier": "3.9.10", "tsx": "4.23.15", "typescript": "6.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cebeeab..0322ea8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -173,11 +173,11 @@ importers: .: dependencies: '@anthropic-ai/claude-agent-sdk': - specifier: 0.3.299 - version: 0.3.299(@anthropic-ai/sdk@0.115.0(zod@4.6.7))(@modelcontextprotocol/sdk@1.32.1(supports-color@10.2.2)(zod@4.6.7))(zod@4.6.7) + specifier: 0.3.310 + version: 0.3.310(@anthropic-ai/sdk@0.115.0(zod@4.6.7))(@modelcontextprotocol/sdk@1.32.1(supports-color@10.2.2)(zod@4.6.7))(zod@4.6.7) '@fastify/static': - specifier: 10.1.6 - version: 10.1.6 + specifier: 10.1.7 + version: 10.1.7 '@fontsource/inter': specifier: 5.3.0 version: 5.3.0 @@ -188,8 +188,8 @@ importers: specifier: 2.1.0 version: 2.1.0 chart.js: - specifier: 4.5.1 - version: 4.5.1 + specifier: 4.6.1 + version: 4.6.1 dompurify: specifier: 3.4.17 version: 3.4.17 @@ -203,8 +203,8 @@ importers: specifier: 5.13.0 version: 5.13.0 markdown-it: - specifier: 15.0.2 - version: 15.0.2 + specifier: 15.0.3 + version: 15.0.3 mermaid: specifier: 12.2.0 version: 12.2.0 @@ -212,20 +212,20 @@ importers: specifier: 2.1.0 version: 2.1.0 pinia: - specifier: 4.0.3 - version: 4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)) + specifier: 4.1.0 + version: 4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)) quasar: - specifier: 2.35.1 - version: 2.35.1 + specifier: 2.35.2 + version: 2.35.2 vue: specifier: 3.5.44 version: 3.5.44(typescript@6.0.3) vue-i18n: - specifier: 11.4.14 - version: 11.4.14(vue@3.5.44(typescript@6.0.3)) + specifier: 11.4.16 + version: 11.4.16(vue@3.5.44(typescript@6.0.3)) vue-router: specifier: 5.4.0 - version: 5.4.0(@vue/compiler-sfc@3.5.43)(esbuild@0.28.2)(pinia@4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(rolldown@1.2.9)(rollup@4.62.4)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)) + version: 5.4.0(@vue/compiler-sfc@3.5.43)(esbuild@0.28.2)(pinia@4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(rolldown@1.2.9)(rollup@4.62.4)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)) zod: specifier: 4.6.7 version: 4.6.7 @@ -237,8 +237,8 @@ importers: specifier: 2.1.0 version: 2.1.0(@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.12.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)(vitest@5.0.4(@types/node@24.19.2)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))) '@quasar/app-vite': - specifier: 3.10.2 - version: 3.10.2(@types/node@24.19.2)(esbuild@0.28.2)(pinia@4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(quasar@2.35.1)(sass@1.104.1)(supports-color@10.2.2)(terser@5.51.2)(tsx@4.23.15)(typescript@6.0.3)(vue-router@5.4.0(@vue/compiler-sfc@3.5.43)(esbuild@0.28.2)(pinia@4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(rolldown@1.2.9)(rollup@4.62.4)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)))(vue@3.5.44(typescript@6.0.3))(yaml@2.9.0) + specifier: 3.10.3 + version: 3.10.3(@types/node@24.19.2)(esbuild@0.28.2)(pinia@4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(quasar@2.35.2)(sass@1.104.1)(supports-color@10.2.2)(terser@5.51.2)(tsx@4.23.15)(typescript@6.0.3)(vue-router@5.4.0(@vue/compiler-sfc@3.5.43)(esbuild@0.28.2)(pinia@4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(rolldown@1.2.9)(rollup@4.62.4)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)))(vue@3.5.44(typescript@6.0.3))(yaml@2.9.0) '@types/node': specifier: <25 version: 24.19.2 @@ -264,8 +264,8 @@ importers: specifier: 17.13.0 version: 17.13.0 playwright: - specifier: 1.64.0 - version: 1.64.0 + specifier: 1.64.1 + version: 1.64.1 prettier: specifier: 3.9.10 version: 3.9.10 @@ -372,52 +372,52 @@ packages: '@antfu/install-pkg@2.1.0': resolution: {integrity: sha512-sdg9NxU3zR4Mnawfbc/x6GB5Wf17WYud5qOuEuxXjaKpYpMkISSJEjItGebXJ2bQ4DIcly4NYH23mtkGJjvKUw==} - '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.299': - resolution: {integrity: sha512-KfkR3Ve7Eku1QuxT3LhC5e9Oj7c8UXvLJFFLbCw0u3OrhpzJUQ0ldd9ArmYNU3J47gpaqYgafnk9ztVPLdcajA==} + '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.310': + resolution: {integrity: sha512-gpzMjDZdcdA2Webuqm9j76exG8yNK/755ZYWbS3MM4vVBlAsm+enEO+hhNt0Mx1VMil28RWetvTO4ZJ3YODVMA==} cpu: [arm64] os: [darwin] - '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.299': - resolution: {integrity: sha512-7G6qjn+xNCmyewcQ/XG/ElBoEGr8uDD4D8X33bqXEbNZ4vXbssiOzmcyxfuWLa7YqR8g9cJnmaWB6UzFEwiC6Q==} + '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.310': + resolution: {integrity: sha512-ZRQ4ZrzE2OOfR+Fx8h+CM4NKh0UiYqlh5TowP7HUhn5KUoYMjoSR/xIhix8ow42X2IDiBy0FjEVaA/Awhu2KAw==} cpu: [x64] os: [darwin] - '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.299': - resolution: {integrity: sha512-kYsC/vxzXfe74Tq6XmaFI6MkQmAnG8R8po45KbWh6/3VD6UbAzps6g+DhmFruE8iuJlLRLdhJss8OfKsnwzX4g==} + '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.310': + resolution: {integrity: sha512-viXuvvtli3pfHzTEI+oeJzk3nldkfHvj757Xh/uAeximUT9ANZIq4SMZw2cSqbhASjni0qcO6B1x4BGx2LuQpw==} cpu: [arm64] os: [linux] libc: [musl] - '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.299': - resolution: {integrity: sha512-8b5apRvHageZ/9xDfoIu8tJ6lpPAGjg4tD9JYef4SjpsY4KM/gvR6qC+Kqq5JHiH/Tq/mjgGYZjMkTZS8TOnsQ==} + '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.310': + resolution: {integrity: sha512-l6SPgUmJknjx+6/Pb7OR353fm3xBNAWqodFoC/Cflg0yMcLfz9iwNIc3Drgos2DqfHnid+ODqDzSO93AgQ7RmA==} cpu: [arm64] os: [linux] libc: [glibc] - '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.299': - resolution: {integrity: sha512-LZ8THwwe0IQ/sRESh2fBVTCBn8n45bHpqiSyV9ELz7HxtRYK0QkHwRKh98H14oZxuwI5jRuWS7v5EaoUaAg2cg==} + '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.310': + resolution: {integrity: sha512-/qFgN5LcofB8PayxBXoa+xDxkYPPQeo/eCyN0DsyyeI67ifH/l49pz9J+sH0+ctDe9und0vMCJPzng70bx2K+Q==} cpu: [x64] os: [linux] libc: [musl] - '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.299': - resolution: {integrity: sha512-Q+sweKF/ruNq4Gmf4CzglwaKJmtQjhBK5MT3U1oUhlNStwHejgBg1GLa/KrQMRE0R4u0ayapLyVNrfu0hQYGkQ==} + '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.310': + resolution: {integrity: sha512-jx7awHPoofXuE6cRRQSzLUFyW6aUXbYD9AtnNIDUHmmPPrgJ9nSnqjPaqcNhOdaZH7onUUujEAq26N2tx29fYg==} cpu: [x64] os: [linux] libc: [glibc] - '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.299': - resolution: {integrity: sha512-sKvddLLYlXzk0FwjT9gNZDzmdzupI7qI0Dok7uu/KYGFgMGiSEGIsB9bfg+31HMDDftaT16P80MLzH+F8zQBFA==} + '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.310': + resolution: {integrity: sha512-tRmDMhZpoWAIrZxFBTh6vyZB8W5gldU5/Rfo+cyq/OvBKTxxbim+/0tIa9QlJQncoVLXVN9eySYeeB9KMjio7w==} cpu: [arm64] os: [win32] - '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.299': - resolution: {integrity: sha512-PWHbjAdrecVlmR0kdgsX20QvUiFgWQl4zskuWd6Ieg3e5w+Ol0FZGXYRLS+Erd+pYUEZBNjDCqK2yd2KdBbDQw==} + '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.310': + resolution: {integrity: sha512-zvrIApxPccTJc6gCOtw5hj27QjWhhTi3z5x5iMmf9f0LZAKR+9mrgENVeFL7PP7zRGdYVhhX2SahbzxN83L/eA==} cpu: [x64] os: [win32] - '@anthropic-ai/claude-agent-sdk@0.3.299': - resolution: {integrity: sha512-E3JzXZ/xza/FW/13MfLYyW1z4l/kut1WY4GXFoLkqJlLm5ilK9cey/dA9SwjNy1B1N206gDlPAzXSM9AUBErbQ==} + '@anthropic-ai/claude-agent-sdk@0.3.310': + resolution: {integrity: sha512-fo+sr+9Ks73P001f6XKRQlyzfIBAJMgXArLUkH5Tu98NikRDZeGtFQVj23d5/hj2ijpFgzffrr4fHywY9qUkoQ==} engines: {node: '>=18.0.0'} peerDependencies: '@anthropic-ai/sdk': '>=0.93.0' @@ -916,8 +916,8 @@ packages: '@fastify/send@4.1.1': resolution: {integrity: sha512-BYo+EiaKwlxH+WetGk6hAs1d39iP0y1gqB8lGF/qwkJ9ZZ/cBY1vx5NvExb9Sc3yRMFjD5X4Eyh4e4+TzRkzdw==} - '@fastify/static@10.1.6': - resolution: {integrity: sha512-f3x9XisI+y6AIhIfA/+Q3SFsuXeqNNk5HQh5htgHsPxmMLb4pLFskV6eFaLSW3IbI4azrS5np+/tkzXNH99LyQ==} + '@fastify/static@10.1.7': + resolution: {integrity: sha512-7+lUiPRraENCiULgjhcqZyWSW6qnwIT87Is0u3c2Z3iGEEEGB45wJhYxzrSdzu12gHM4qcviEYcPEiCe4J6MCQ==} '@fontsource/inter@5.3.0': resolution: {integrity: sha512-RofMylZmjlJEfELXeNHFWBRcSs75rGU/6bV2S2jfnvv/3rPXPGe0LgUJTklcHZ9lM4OZmAVFhcJPnACfb91A3g==} @@ -960,20 +960,20 @@ packages: '@iconify/utils@3.1.7': resolution: {integrity: sha512-JZHlwdID+dy+lTgbYC8NEC4zeugqeYsc6jewvzb4c58kHauJn+X7rNwQjxz5p2qSjqaEeQoLkCIQ9v/H4PK0/w==} - '@intlify/core-base@11.4.14': - resolution: {integrity: sha512-Lox+qRGBLnEYfNz4iajqKpw1zuvSAWl4PtzEk654bEM+0NT1GBy9AbOecxzSh7krsyqn9mGKhgmvtuyBsqS6oQ==} + '@intlify/core-base@11.4.16': + resolution: {integrity: sha512-xB8nMdMRLNx7b0zPvrHy0+N9uq9Vfi1aUxHqWgn2e2/TbjCKy8HfoFpnUXXxVP8I0p1ccd6LFSC3XsFjZ3vweA==} engines: {node: '>= 22'} - '@intlify/devtools-types@11.4.14': - resolution: {integrity: sha512-EQHRYveQg6yHQ51kePfsFyaW2WW+0hk3FdVxSpLDyuKtqFtsRFoyQR2QzASZPmY767ujs9ipuxc2DiGJARkuiQ==} + '@intlify/devtools-types@11.4.16': + resolution: {integrity: sha512-Bl7arICsKgwcSEQuZJun3swenN4jwSpg35lCpijFznYbW9GvkfH4wLxcI5+gz7d/EHqu66UT9CZDIdnQdgMAGg==} engines: {node: '>= 22'} - '@intlify/message-compiler@11.4.14': - resolution: {integrity: sha512-y79GatHfMhN672Vooxw0v6mgX/vclFHggO1ENL6aH/QubLXiV529WXu/+FhVUbYF+HLTeDDkQpmnpfvSJddBCg==} + '@intlify/message-compiler@11.4.16': + resolution: {integrity: sha512-p4lDWmBAsi3ja+PuEfPRavYyvqkYn/Upxz7UpnyI9LgIIy8XawcGIDzN+k99Z+99etO3HmDXGeTxnJIJGgSZ+g==} engines: {node: '>= 22'} - '@intlify/shared@11.4.14': - resolution: {integrity: sha512-f8zSlPs4+Yd9za3CPQfW9OHxAJBOeRQzB/hhOhkbGA7hlqWk0W0bUtSV/LmyrGNwdl8JriBnFtJqZyF140bjGg==} + '@intlify/shared@11.4.16': + resolution: {integrity: sha512-xehmkbEgbbNh/V+d8r3hFup0ViaN29YTJSAfRr28C54rxjyZEO0RNQKqW7VVajj16gLdglotNjiq+sIVNtHGzw==} engines: {node: '>= 22'} '@jridgewell/gen-mapping@0.3.13': @@ -1202,8 +1202,8 @@ packages: resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==} engines: {node: ^14.18.0 || >=16.0.0} - '@quasar/app-vite@3.10.2': - resolution: {integrity: sha512-MwRLbmwqiMvyCXtj0nNxPWUyxBJer3Or5XmuiMLNRWQgAka7DvJ0aXYL+biyMwfWowq/kpDSRWwN4xmCrVht/w==} + '@quasar/app-vite@3.10.3': + resolution: {integrity: sha512-9MgKUzplGcez88r5aEgCu/xgCc1ZSGXNELkVhnGiOBLJ+0TBbMl+W7sCBy3kkxrhMgGk1az25EU/JYBHVHGqYQ==} engines: {node: ^30 || ^28 || ^26 || ^24 || ^22.22.0} hasBin: true peerDependencies: @@ -1981,8 +1981,8 @@ packages: alien-signals@3.2.1: resolution: {integrity: sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==} - argparse@3.0.2: - resolution: {integrity: sha512-mFdDM6WqWKraGLsVb+C9CahPnzTXOefAOLq3jYcca2YZ8bEWpr++Tzj+zSaKW9+X9L5uSxcm1AZ3Y6aZJ09OhQ==} + argparse@3.0.3: + resolution: {integrity: sha512-Sn98ftV3KfsO8xfLPHG6oT8y+b0yvbrLgZjgPDXsharNY15tTAjqIsIju4S32nl6/iEUNNE4v+yL2Zhm8ooP3w==} asn1js@3.0.10: resolution: {integrity: sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==} @@ -2095,8 +2095,8 @@ packages: character-entities-legacy@3.0.0: resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} - chart.js@4.5.1: - resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==} + chart.js@4.6.1: + resolution: {integrity: sha512-hJyniucsFmq//EvXYvJ6c6mahPoI3kaxdjVH8awTaJ/fDNWeSqqqArixMJWkWNN6fcYvPU3HneSANFNYtRi61g==} engines: {pnpm: '>=8'} chevrotain@13.2.0: @@ -3079,8 +3079,8 @@ packages: mark.js@8.11.1: resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} - markdown-it@15.0.2: - resolution: {integrity: sha512-q4IGxMv56jCqT4OCRCADBoDP3LO4MhmTXjFbphHPXs4g3j9Xg5RDnxqN8IF/3vIWEU+VCnUq+7JUg/cfy2E6Qw==} + markdown-it@15.0.3: + resolution: {integrity: sha512-+Az7Ojz3iRGu8KYMvJ6xVhvrxP3eE+vEtJX75Ow88XBpcQNV/0lGX5ZynIIBftREo4DC2jsveAMDaeltmm8QvQ==} hasBin: true marked@16.4.2: @@ -3200,9 +3200,6 @@ packages: resolution: {integrity: sha512-IXWp7Qzhwv21DqTw0g1CcppTb4TCzrQ949RVdtAmgiHAu3KbcRPyCAFXLaFAViqWDVx8GLZjnWiWJ7pWSj2PRA==} engines: {node: '>=18'} - nostics@1.2.0: - resolution: {integrity: sha512-FGqEfhQjrvo1lL8KFifdTQiNwwQHJxC1jtYE1Rc54qF/jxONUNL+kC9gS1krX8Q65PgrQ5fCqH/I4NhWBvdSqg==} - nostics@1.3.0: resolution: {integrity: sha512-wzRsrJwNlFbqIRQt8aCeL2WE8USip/uuvGSOZV1D02CxX8ABTMbw8IywKjH7yWHETMXbWJI4OBpihg9rmz2Vyg==} @@ -3317,10 +3314,10 @@ packages: resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} engines: {node: '>=12'} - pinia@4.0.3: - resolution: {integrity: sha512-XMQqpvjgG7LMqVhhFUzKLT4KEbsYbfZZ0CZU9PgdFm1O2VKBmIkykL8+SfNhOaT7sR0wT6BEgKT0YNDYWgmVRA==} + pinia@4.1.0: + resolution: {integrity: sha512-+5/HMuVjYQfKlCD5xQ7zfXn1xUzYFEa7pd0DQK5SaMfZCaFRTHlaH/c02N1FoGOdlzSiwf5EOPgJx//1QDw6gw==} peerDependencies: - '@vue/devtools-api': ^8.1.5 + '@vue/devtools-api': ^8.2.1 typescript: <7 vue: ^3.5.11 peerDependenciesMeta: @@ -3351,13 +3348,13 @@ packages: resolution: {integrity: sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==} engines: {node: '>=16.0.0'} - playwright-core@1.64.0: - resolution: {integrity: sha512-T9r+MZkTECl2+oUcZ26YgZzTrYidTsIhYYkJix+6iDOymOb1FB2RLLSOxRGnZGv5DStt+aduIVbt+E8WygXYpg==} + playwright-core@1.64.1: + resolution: {integrity: sha512-BC4s8y6SEVA6Q1rSxZTto8hI1KUI3xXlHGZgvGqP4IqPdI/a6FX9H29IDNz7vKo9l21b6LfYosScPL6M3xxyDQ==} engines: {node: '>=20'} hasBin: true - playwright@1.64.0: - resolution: {integrity: sha512-kVzTnYFYEyQ9RGzBjNCd2+yEqWmVbxl3AHPynv3qQ6JTjv4a+kwRcnqQwIpuP3NnrnIrE/Q6wWAIAvMfIE2/Yg==} + playwright@1.64.1: + resolution: {integrity: sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA==} engines: {node: '>=20'} hasBin: true @@ -3453,8 +3450,8 @@ packages: quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} - quasar@2.35.1: - resolution: {integrity: sha512-Y8HJm5AVary0DJAT4Up5wWJCzbCo27nprugWTXHJ0rlQ6OuC1ftmBArBBPaXJFAHqLTafoxsMfRQ7qAncqvgBw==} + quasar@2.35.2: + resolution: {integrity: sha512-zxX7yojl3usZDDD8fk03U6JYyCefxxEhYtFJT8iDjsNoW+Y3Zmet2io1pNsnSB060HwduJuoBJhKgIPv8WD10A==} engines: {node: '>= 22.0.0'} queue-microtask@1.2.3: @@ -4215,8 +4212,8 @@ packages: peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - vue-i18n@11.4.14: - resolution: {integrity: sha512-oRFZtQjRDRQtfxu7tFlsZlnCa5gPkg/KX89kJDKdC9bz4GIYgo3cAMaD0XFeUx/WHuKoVbDMRTIo9Hvg67HnPw==} + vue-i18n@11.4.16: + resolution: {integrity: sha512-Kv9tp6iTmaAeOwop7hkAo28N1IBsbSVpnxyE26b6gqc4Q2E9Ke3ZHHA3oqqwS6/cYLT1henZU4etTaLQxrK98Q==} engines: {node: '>= 22'} peerDependencies: vue: ^3.0.0 @@ -4427,44 +4424,44 @@ snapshots: package-manager-detector: 1.8.0 tinyexec: 1.3.1 - '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.299': + '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.310': optional: true - '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.299': + '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.310': optional: true - '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.299': + '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.310': optional: true - '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.299': + '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.310': optional: true - '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.299': + '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.310': optional: true - '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.299': + '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.310': optional: true - '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.299': + '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.310': optional: true - '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.299': + '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.310': optional: true - '@anthropic-ai/claude-agent-sdk@0.3.299(@anthropic-ai/sdk@0.115.0(zod@4.6.7))(@modelcontextprotocol/sdk@1.32.1(supports-color@10.2.2)(zod@4.6.7))(zod@4.6.7)': + '@anthropic-ai/claude-agent-sdk@0.3.310(@anthropic-ai/sdk@0.115.0(zod@4.6.7))(@modelcontextprotocol/sdk@1.32.1(supports-color@10.2.2)(zod@4.6.7))(zod@4.6.7)': dependencies: '@anthropic-ai/sdk': 0.115.0(zod@4.6.7) '@modelcontextprotocol/sdk': 1.32.1(supports-color@10.2.2)(zod@4.6.7) zod: 4.6.7 optionalDependencies: - '@anthropic-ai/claude-agent-sdk-darwin-arm64': 0.3.299 - '@anthropic-ai/claude-agent-sdk-darwin-x64': 0.3.299 - '@anthropic-ai/claude-agent-sdk-linux-arm64': 0.3.299 - '@anthropic-ai/claude-agent-sdk-linux-arm64-musl': 0.3.299 - '@anthropic-ai/claude-agent-sdk-linux-x64': 0.3.299 - '@anthropic-ai/claude-agent-sdk-linux-x64-musl': 0.3.299 - '@anthropic-ai/claude-agent-sdk-win32-arm64': 0.3.299 - '@anthropic-ai/claude-agent-sdk-win32-x64': 0.3.299 + '@anthropic-ai/claude-agent-sdk-darwin-arm64': 0.3.310 + '@anthropic-ai/claude-agent-sdk-darwin-x64': 0.3.310 + '@anthropic-ai/claude-agent-sdk-linux-arm64': 0.3.310 + '@anthropic-ai/claude-agent-sdk-linux-arm64-musl': 0.3.310 + '@anthropic-ai/claude-agent-sdk-linux-x64': 0.3.310 + '@anthropic-ai/claude-agent-sdk-linux-x64-musl': 0.3.310 + '@anthropic-ai/claude-agent-sdk-win32-arm64': 0.3.310 + '@anthropic-ai/claude-agent-sdk-win32-x64': 0.3.310 '@anthropic-ai/sdk@0.115.0(zod@4.6.7)': dependencies: @@ -4804,7 +4801,7 @@ snapshots: http-errors: 2.0.1 mime: 3.0.0 - '@fastify/static@10.1.6': + '@fastify/static@10.1.7': dependencies: '@fastify/accept-negotiator': 2.1.0 '@fastify/error': 4.2.0 @@ -4850,23 +4847,23 @@ snapshots: '@iconify/types': 2.0.0 import-meta-resolve: 4.2.0 - '@intlify/core-base@11.4.14': + '@intlify/core-base@11.4.16': dependencies: - '@intlify/devtools-types': 11.4.14 - '@intlify/message-compiler': 11.4.14 - '@intlify/shared': 11.4.14 + '@intlify/devtools-types': 11.4.16 + '@intlify/message-compiler': 11.4.16 + '@intlify/shared': 11.4.16 - '@intlify/devtools-types@11.4.14': + '@intlify/devtools-types@11.4.16': dependencies: - '@intlify/core-base': 11.4.14 - '@intlify/shared': 11.4.14 + '@intlify/core-base': 11.4.16 + '@intlify/shared': 11.4.16 - '@intlify/message-compiler@11.4.14': + '@intlify/message-compiler@11.4.16': dependencies: - '@intlify/shared': 11.4.14 + '@intlify/shared': 11.4.16 source-map-js: 1.2.2 - '@intlify/shared@11.4.14': {} + '@intlify/shared@11.4.16': {} '@jridgewell/gen-mapping@0.3.13': dependencies: @@ -5119,13 +5116,13 @@ snapshots: '@pkgr/core@0.3.6': {} - '@quasar/app-vite@3.10.2(@types/node@24.19.2)(esbuild@0.28.2)(pinia@4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(quasar@2.35.1)(sass@1.104.1)(supports-color@10.2.2)(terser@5.51.2)(tsx@4.23.15)(typescript@6.0.3)(vue-router@5.4.0(@vue/compiler-sfc@3.5.43)(esbuild@0.28.2)(pinia@4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(rolldown@1.2.9)(rollup@4.62.4)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)))(vue@3.5.44(typescript@6.0.3))(yaml@2.9.0)': + '@quasar/app-vite@3.10.3(@types/node@24.19.2)(esbuild@0.28.2)(pinia@4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(quasar@2.35.2)(sass@1.104.1)(supports-color@10.2.2)(terser@5.51.2)(tsx@4.23.15)(typescript@6.0.3)(vue-router@5.4.0(@vue/compiler-sfc@3.5.43)(esbuild@0.28.2)(pinia@4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(rolldown@1.2.9)(rollup@4.62.4)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)))(vue@3.5.44(typescript@6.0.3))(yaml@2.9.0)': dependencies: '@clack/prompts': 1.8.1 '@quasar/art': 1.0.0 '@quasar/render-ssr-error': 2.2.6 '@quasar/ssl-certificate': 2.1.0 - '@quasar/vite-plugin': 2.0.2(@vitejs/plugin-vue@6.0.9(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)))(quasar@2.35.1)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)) + '@quasar/vite-plugin': 2.0.2(@vitejs/plugin-vue@6.0.9(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)))(quasar@2.35.2)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)) '@types/chrome': 0.3.0 '@types/cordova': 11.0.3 '@vitejs/plugin-vue': 6.0.9(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)) @@ -5144,7 +5141,7 @@ snapshots: mlly: 1.8.2 open: 11.0.4 picomatch: 4.0.7 - quasar: 2.35.1 + quasar: 2.35.2 rolldown: 1.2.9 sass-embedded: 1.104.1 semver: 7.8.5 @@ -5154,10 +5151,10 @@ snapshots: ts-essentials: 10.2.1(typescript@6.0.3) vite: 8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0) vue: 3.5.44(typescript@6.0.3) - vue-router: 5.4.0(@vue/compiler-sfc@3.5.43)(esbuild@0.28.2)(pinia@4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(rolldown@1.2.9)(rollup@4.62.4)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)) + vue-router: 5.4.0(@vue/compiler-sfc@3.5.43)(esbuild@0.28.2)(pinia@4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(rolldown@1.2.9)(rollup@4.62.4)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)) webpack-merge: 6.0.1 optionalDependencies: - pinia: 4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)) + pinia: 4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)) typescript: 6.0.3 transitivePeerDependencies: - '@types/node' @@ -5185,10 +5182,10 @@ snapshots: fs-extra: 11.4.0 selfsigned: 5.5.0 - '@quasar/vite-plugin@2.0.2(@vitejs/plugin-vue@6.0.9(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)))(quasar@2.35.1)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3))': + '@quasar/vite-plugin@2.0.2(@vitejs/plugin-vue@6.0.9(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)))(quasar@2.35.2)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3))': dependencies: '@vitejs/plugin-vue': 6.0.9(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)) - quasar: 2.35.1 + quasar: 2.35.2 vite: 8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0) vue: 3.5.44(typescript@6.0.3) @@ -5926,7 +5923,7 @@ snapshots: alien-signals@3.2.1: {} - argparse@3.0.2: {} + argparse@3.0.3: {} asn1js@3.0.10: dependencies: @@ -6050,7 +6047,7 @@ snapshots: character-entities-legacy@3.0.0: {} - chart.js@4.5.1: + chart.js@4.6.1: dependencies: '@kurkle/color': 0.3.4 @@ -7069,9 +7066,9 @@ snapshots: mark.js@8.11.1: {} - markdown-it@15.0.2: + markdown-it@15.0.3: dependencies: - argparse: 3.0.2 + argparse: 3.0.3 entities: 8.1.0 linkify-it: 6.1.0 mdurl: 2.1.0 @@ -7199,8 +7196,6 @@ snapshots: node-telegram-bot-api@2.1.0: {} - nostics@1.2.0: {} - nostics@1.3.0: {} npm-run-path@6.0.0: @@ -7305,10 +7300,10 @@ snapshots: picomatch@4.0.7: {} - pinia@4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)): + pinia@4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)): dependencies: '@vue/devtools-api': 8.2.1 - nostics: 1.2.0 + nostics: 1.3.0 vue: 3.5.44(typescript@6.0.3) optionalDependencies: typescript: 6.0.3 @@ -7356,11 +7351,11 @@ snapshots: pvutils: 1.2.0 tslib: 2.8.1 - playwright-core@1.64.0: {} + playwright-core@1.64.1: {} - playwright@1.64.0: + playwright@1.64.1: dependencies: - playwright-core: 1.64.0 + playwright-core: 1.64.1 points-on-curve@0.2.0: {} @@ -7440,7 +7435,7 @@ snapshots: quansync@0.2.11: {} - quasar@2.35.1: {} + quasar@2.35.2: {} queue-microtask@1.2.3: {} @@ -8140,15 +8135,15 @@ snapshots: transitivePeerDependencies: - supports-color - vue-i18n@11.4.14(vue@3.5.44(typescript@6.0.3)): + vue-i18n@11.4.16(vue@3.5.44(typescript@6.0.3)): dependencies: - '@intlify/core-base': 11.4.14 - '@intlify/devtools-types': 11.4.14 - '@intlify/shared': 11.4.14 + '@intlify/core-base': 11.4.16 + '@intlify/devtools-types': 11.4.16 + '@intlify/shared': 11.4.16 '@vue/devtools-api': 6.6.4 vue: 3.5.44(typescript@6.0.3) - vue-router@5.4.0(@vue/compiler-sfc@3.5.43)(esbuild@0.28.2)(pinia@4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(rolldown@1.2.9)(rollup@4.62.4)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)): + vue-router@5.4.0(@vue/compiler-sfc@3.5.43)(esbuild@0.28.2)(pinia@4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)))(rolldown@1.2.9)(rollup@4.62.4)(vite@8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0))(vue@3.5.44(typescript@6.0.3)): dependencies: '@vue-macros/common': 3.1.4(vue@3.5.44(typescript@6.0.3)) '@vue/devtools-api': 8.2.1 @@ -8169,7 +8164,7 @@ snapshots: vue: 3.5.44(typescript@6.0.3) optionalDependencies: '@vue/compiler-sfc': 3.5.43 - pinia: 4.0.3(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)) + pinia: 4.1.0(@vue/devtools-api@8.2.1)(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3)) vite: 8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass-embedded@1.104.1)(sass@1.104.1)(terser@5.51.2)(tsx@4.23.15)(yaml@2.9.0) transitivePeerDependencies: - '@farmfe/core' diff --git a/test/corpus.test.ts b/test/corpus.test.ts index 373220c..6d7a010 100644 --- a/test/corpus.test.ts +++ b/test/corpus.test.ts @@ -20,35 +20,99 @@ import { CONTEXT_CATEGORIES, type SessionContext } from '../shared/context.ts' const PROJECTS = join(homedir(), '.claude', 'projects') const HAS_CORPUS = existsSync(PROJECTS) -/** Assez pour que les propriétés mordent, assez peu pour rester une seconde. */ +/** Assez pour que les propriétés mordent. */ const SAMPLE = 60 +/** + * Ce que l'échantillon a le droit de peser, sous-agents compris. + * + * Un plafond en sessions ne borne rien : le corpus d'une machine ne fait que + * grossir, et les sessions à sous-agents — celles qu'on prend d'abord — sont les + * plus lourdes, si bien que le fichier a fini par dépasser ses deux minutes. Un + * budget en octets garde le coût constant quoi qu'il arrive au disque. + */ +const BUDGET_BYTES = 250 * 1024 * 1024 + +/** Au-delà, une seule session mangerait le budget de dix autres. */ +const MAX_SESSION_BYTES = BUDGET_BYTES / 10 + +/** Une session écrite il y a moins que cela tourne peut-être encore. */ +const SETTLED_MS = 2 * 60 * 1000 + interface Session { name: string path: string /** Ce transcript a-t-il des sous-agents ? Eux seuls exercent l'isolation. */ hasSubagents: boolean + bytes: number + modifiedAt: number +} + +function sizeOf(dir: string): number { + let bytes = 0 + for (const file of readdirSync(dir)) bytes += statSync(join(dir, file)).size + return bytes } function sample(): Session[] { - const out: Session[] = [] + const all: Session[] = [] for (const project of readdirSync(PROJECTS)) { const dir = join(PROJECTS, project) if (!statSync(dir).isDirectory()) continue for (const file of readdirSync(dir)) { if (!file.endsWith('.jsonl')) continue const id = file.slice(0, -6) - out.push({ + const path = join(dir, file) + const subagents = join(dir, id, 'subagents') + const hasSubagents = existsSync(subagents) + const stat = statSync(path) + all.push({ name: `${project}/${id.slice(0, 8)}`, - path: join(dir, file), - hasSubagents: existsSync(join(dir, id, 'subagents')), + path, + hasSubagents, + bytes: stat.size + (hasSubagents ? sizeOf(subagents) : 0), + modifiedAt: stat.mtimeMs, }) } } // Les sessions à sous-agents d'abord : ce sont elles qui portent l'invariant - // le plus fragile, et elles sont minoritaires. - out.sort((a, b) => Number(b.hasSubagents) - Number(a.hasSubagents)) - return out.slice(0, SAMPLE) + // le plus fragile, et elles sont minoritaires. Puis les plus récentes : ce + // sont elles qui portent le format que le CLI écrit aujourd'hui. + all.sort((a, b) => Number(b.hasSubagents) - Number(a.hasSubagents) || b.modifiedAt - a.modifiedAt) + + // Une session vivante bouge sous le test : une ligne lue à moitié n'est pas + // une régression. + const settled = Date.now() - SETTLED_MS + const out: Session[] = [] + let spent = 0 + for (const s of all) { + if (out.length === SAMPLE) break + if (s.modifiedAt > settled || s.bytes > MAX_SESSION_BYTES || spent + s.bytes > BUDGET_BYTES) continue + out.push(s) + spent += s.bytes + } + return out +} + +/** + * Chaque test lit les mêmes sessions : les parser une fois pour tous. L'identifiant + * fait partie de la clé parce qu'il change ce que le parseur rattache — deux tests + * passent `''` exprès. + */ +const parsed = new Map>() +function parse(path: string, id: string): ReturnType { + const key = `${path}\0${id}` + let p = parsed.get(key) + if (!p) parsed.set(key, (p = parseTranscript(path, id))) + return p +} + +/** Les lignes d'un fichier, lues une fois quel que soit le nombre d'images qu'il porte. */ +const linesOf = new Map() +function lines(file: string): string[] { + let l = linesOf.get(file) + if (!l) linesOf.set(file, (l = readFileSync(file, 'utf8').split('\n'))) + return l } function attributedAt(c: SessionContext, i: number): number { @@ -58,13 +122,10 @@ function attributedAt(c: SessionContext, i: number): number { /** * Le délai laissé à un test qui lit le vrai disque. * - * Les cinq secondes de vitest ont été écrites pour des fixtures ; ici chaque - * test relit soixante transcrits réels, et le corpus d'une machine ne cesse de - * grossir. Quatre de ces tests tombaient donc en dépassement — un `pnpm verifie` - * rouge en permanence, pour une propriété qui tenait pourtant à chaque fois. - * - * On allonge plutôt que de réduire l'échantillon : ce fichier est un filet, et - * un filet qu'on rétrécit pour qu'il aille plus vite n'attrape plus rien. + * Les cinq secondes de vitest ont été écrites pour des fixtures ; ici le premier + * test qui touche une session la parse depuis le vrai disque. Le budget en octets + * borne ce coût — quelques secondes — et ce délai n'est qu'une marge : s'il est + * atteint, c'est que le parseur a ralenti, pas que le corpus a grossi. */ const TIMEOUT_MS = 120_000 @@ -77,7 +138,7 @@ describe.skipIf(!HAS_CORPUS)('invariants sur ~/.claude', { timeout: TIMEOUT_MS } it("n'attribue jamais plus que la fenêtre exacte", async () => { for (const s of sessions) { - const { context } = await parseTranscript(s.path, '') + const { context } = await parse(s.path, '') context.turns.forEach((turn, i) => { if (!turn.total) return // Une estimation qui dépasse son ancre ne dit plus rien : `unattributed` @@ -89,7 +150,7 @@ describe.skipIf(!HAS_CORPUS)('invariants sur ~/.claude', { timeout: TIMEOUT_MS } it('déduit un socle plausible dès que le premier tour est ancré', async () => { for (const s of sessions) { - const { context } = await parseTranscript(s.path, '') + const { context } = await parse(s.path, '') const first = context.turns[0] if (!first?.total) continue // Le prompt système et les schémas d'outils de Claude Code. Mesuré sur 488 @@ -105,7 +166,7 @@ describe.skipIf(!HAS_CORPUS)('invariants sur ~/.claude', { timeout: TIMEOUT_MS } let seen = 0 for (const s of sessions) { const id = s.path.split(/[\\/]/).at(-1)!.slice(0, -6) - const { events } = await parseTranscript(s.path, id) + const { events } = await parse(s.path, id) for (const ev of events) { for (const b of ev.blocks) { for (const img of b.images ?? b.result?.images ?? []) { @@ -120,8 +181,7 @@ describe.skipIf(!HAS_CORPUS)('invariants sur ~/.claude', { timeout: TIMEOUT_MS } // Et elle doit désigner les octets, pas seulement exister : on relit // le fichier comme le fera le BFF, en repartant de l'adresse seule. const file = img.agentId ? join(dirname(s.path), id, 'subagents', `agent-${img.agentId}.jsonl`) : s.path - const row = readFileSync(file, 'utf8') - .split('\n') + const row = lines(file) .filter((l) => l.includes(`"uuid":"${img.uuid}"`)) .map((l) => JSON.parse(l) as Record) .find((r) => r.uuid === img.uuid) @@ -157,7 +217,7 @@ describe.skipIf(!HAS_CORPUS)('invariants sur ~/.claude', { timeout: TIMEOUT_MS } let runs = 0 for (const s of withSub) { const id = s.path.split(/[\\/]/).at(-1)!.slice(0, -6) - const { subagents, events } = await parseTranscript(s.path, id) + const { subagents, events } = await parse(s.path, id) runs += subagents.length const inStream = new Set(events.flatMap((e) => (e.agentId ? [e.agentId] : []))) @@ -183,7 +243,7 @@ describe.skipIf(!HAS_CORPUS)('invariants sur ~/.claude', { timeout: TIMEOUT_MS } expect(withSub.length, 'aucune session à sous-agents dans l’échantillon').toBeGreaterThan(0) for (const s of withSub) { - const { context } = await parseTranscript(s.path, s.path.split(/[\\/]/).at(-1)!.slice(0, -6)) + const { context } = await parse(s.path, s.path.split(/[\\/]/).at(-1)!.slice(0, -6)) // Une fenêtre grandit, tour après tour, jusqu'à ce qu'une compaction la // vide — et une compaction ouvre une phase. Un effondrement *au sein* d'une // phase n'a donc qu'une explication : deux fenêtres se sont mélangées.