diff --git a/.changeset/after-preflight-handoff.md b/.changeset/after-preflight-handoff.md new file mode 100644 index 00000000..4d41f93a --- /dev/null +++ b/.changeset/after-preflight-handoff.md @@ -0,0 +1,5 @@ +--- +'cargo-hauler': patch +--- + +Hand the `tool/after` preflight's session-completed answer to the route as `preflight` data so the after-shell hook does not query the daemon a second time, and pin `agent-bundle` and `@agent-bundle/runtime` to the preview of main `9197015b9` (agent-bundle #661/#664). diff --git a/README.md b/README.md index a0f7f1ab..00ddc047 100644 --- a/README.md +++ b/README.md @@ -916,7 +916,7 @@ ships no preview harness of its own. agent-bundle does not yet have an npm release; this repository pins the [pkg.pr.new](https://pkg.pr.new) preview of main commit -[`d30d9acb6`](https://github.com/ScriptedAlchemy/agent-bundle/commit/d30d9acb6bd106762bb975ac58d6bf437c176091) +[`9197015b9`](https://github.com/ScriptedAlchemy/agent-bundle/commit/9197015b9ae5088eee75c7d2d11a40890b37b367) for both `agent-bundle` and `@agent-bundle/runtime`. `inspect` reports the `agent` component kind as unavailable on every host (agent-bundle G5 deferral); this plugin defines no agents. diff --git a/package.json b/package.json index 0bd52919..a5f21606 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "release:version": "changeset version" }, "devDependencies": { - "@agent-bundle/runtime": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@75c5f46f947f8a4cc90ac5d843d53d421dec8a44", + "@agent-bundle/runtime": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@9197015b9ae5088eee75c7d2d11a40890b37b367", "@changesets/cli": "3.0.1", "@effect/atom-react": "4.0.0-rc.112", "@effect/platform-node": "4.0.0-rc.112", @@ -69,7 +69,7 @@ "@types/react": "^19.2.18", "@types/react-dom": "^19.2.5", "@typescript/native-preview": "^7.0.0-dev.20260707.2", - "agent-bundle": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@75c5f46f947f8a4cc90ac5d843d53d421dec8a44", + "agent-bundle": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@9197015b9ae5088eee75c7d2d11a40890b37b367", "bashjsast": "github:woolkingx/bashjsast#131f4b677d1906774fc49cfceab0ccb7b370b2e6", "effect": "4.0.0-rc.112", "effect-rstest": "https://pkg.pr.new/ScriptedAlchemy/effect-rstest@e5f8d5f", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 169f3cf6..4c8d362b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: devDependencies: '@agent-bundle/runtime': - specifier: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@75c5f46f947f8a4cc90ac5d843d53d421dec8a44 - version: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@75c5f46f947f8a4cc90ac5d843d53d421dec8a44(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + specifier: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@9197015b9ae5088eee75c7d2d11a40890b37b367 + version: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@9197015b9ae5088eee75c7d2d11a40890b37b367(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@changesets/cli': specifier: 3.0.1 version: 3.0.1 @@ -45,8 +45,8 @@ importers: specifier: ^7.0.0-dev.20260707.2 version: 7.0.0-dev.20260707.2 agent-bundle: - specifier: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@75c5f46f947f8a4cc90ac5d843d53d421dec8a44 - version: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@75c5f46f947f8a4cc90ac5d843d53d421dec8a44(@agent-bundle/runtime@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@75c5f46f947f8a4cc90ac5d843d53d421dec8a44(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@rspack/core@2.2.2(@swc/helpers@0.5.23))(@rstest/core@0.11.11)(hono@4.13.5)(react@19.2.8)(typescript@7.0.2) + specifier: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@9197015b9ae5088eee75c7d2d11a40890b37b367 + version: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@9197015b9ae5088eee75c7d2d11a40890b37b367(@agent-bundle/runtime@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@9197015b9ae5088eee75c7d2d11a40890b37b367(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@rspack/core@2.2.2(@swc/helpers@0.5.23))(@rstest/core@0.11.11)(hono@4.13.5)(react@19.2.8)(typescript@7.0.2) bashjsast: specifier: github:woolkingx/bashjsast#131f4b677d1906774fc49cfceab0ccb7b370b2e6 version: https://codeload.github.com/woolkingx/bashjsast/tar.gz/131f4b677d1906774fc49cfceab0ccb7b370b2e6 @@ -77,14 +77,14 @@ importers: packages: - '@agent-bundle/runtime@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@75c5f46f947f8a4cc90ac5d843d53d421dec8a44': - resolution: {integrity: sha512-rY3wHC+KVQFXfaQEJAIigy+7CJsWA4kqqVf/jg7JIwvobFj61JG7Ewh6RK34hEN3qALgJ7RQYFpyYUFbZ3rReQ==, tarball: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@75c5f46f947f8a4cc90ac5d843d53d421dec8a44} - version: 0.0.0-preview-75c5f46 + '@agent-bundle/runtime@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@9197015b9ae5088eee75c7d2d11a40890b37b367': + resolution: {integrity: sha512-yUyApqgUXKVQ7WeOrAPuvPGbntJsyl/mEDfNqPxXEOG9+Icy0a2u8dKskuYr9qV5wEBUdkOsTyQivWD/jJ/81w==, tarball: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@9197015b9ae5088eee75c7d2d11a40890b37b367} + version: 0.0.0-preview-9197015 engines: {node: '>=22.19.0'} peerDependencies: '@rspack/core': ^2.2.0-0 - react: 19.2.8 - react-dom: 19.2.8 + react: ^19.2.0 + react-dom: ^19.2.0 peerDependenciesMeta: '@rspack/core': optional: true @@ -836,13 +836,13 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - agent-bundle@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@75c5f46f947f8a4cc90ac5d843d53d421dec8a44: - resolution: {integrity: sha512-kl8qmy4+jbr37rG6/Y5pFoN89lGQrzdZ8soTVi0TOZOFfZ0tl+G1cl6S+qwbukgsFqLtfJDaqXpeGzn6BrQUKw==, tarball: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@75c5f46f947f8a4cc90ac5d843d53d421dec8a44} - version: 0.0.0-preview-75c5f46 + agent-bundle@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@9197015b9ae5088eee75c7d2d11a40890b37b367: + resolution: {integrity: sha512-KsHKAD2+CaBtaFxhbh7gn6Q9uE+vFS/HLZxFCBCaRdzD/1cqniZ9eExt5s7DZECAxWYwWDrMenHlY46YgGjozw==, tarball: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@9197015b9ae5088eee75c7d2d11a40890b37b367} + version: 0.0.0-preview-9197015 engines: {node: '>=22.19.0'} hasBin: true peerDependencies: - '@agent-bundle/runtime': 0.0.0-preview-75c5f46 + '@agent-bundle/runtime': 0.0.0-preview-9197015 '@rstest/core': ^0.11.10 react: 19.2.8 peerDependenciesMeta: @@ -876,10 +876,6 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - bundle-name@4.1.0: - resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} - engines: {node: '>=18'} - cac@7.0.0: resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} engines: {node: '>=20.19.0'} @@ -903,18 +899,6 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - default-browser-id@5.0.1: - resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} - engines: {node: '>=18'} - - default-browser@5.5.1: - resolution: {integrity: sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==} - engines: {node: '>=18'} - - define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -1010,11 +994,6 @@ packages: import-meta-resolve@4.2.0: resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} - is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -1023,23 +1002,10 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-in-ssh@1.0.0: - resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==} - engines: {node: '>=20'} - - is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-wsl@3.1.1: - resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} - engines: {node: '>=16'} - isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -1094,10 +1060,6 @@ packages: resolution: {integrity: sha512-69XQh3k+dtGa1p+7RaR57IuG3rCko96xr/nUfN4yDYBXbTYICiWcOpsFKLN2GtGE9cyIljE+f1exnaYt9MvM+Q==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} - open@11.0.2: - resolution: {integrity: sha512-RWqF+pBSkqecEvCKOn8QYhaNdRMJDZRIrlS/7rTDdLHaPcfXGCZ/h8zb413NfvdeAV0MR7T1yJcA34/q+CSm1Q==} - engines: {node: '>=20'} - package-manager-detector@1.8.0: resolution: {integrity: sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==} @@ -1120,14 +1082,6 @@ packages: resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} engines: {node: '>=16.20.0'} - powershell-utils@0.1.0: - resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} - engines: {node: '>=20'} - - powershell-utils@0.2.1: - resolution: {integrity: sha512-C+y9x90UElAddDZmV4qOx9W53B61PO7cIqWz2dQsWlwswuq4mr8NEwytdGKboYbQlGZ3awrkTeNvcZiZNHnQ8A==} - engines: {node: '>=20'} - proc-log@7.0.0: resolution: {integrity: sha512-FYgfaA69XZ93zaXLoMNQ+ViDXGGBgR8aLh03txzcFhV+9xOXx7+8DLCULrKKpR9+GsH9ZfHm82aSUPpozX0Ztg==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} @@ -1195,17 +1149,13 @@ packages: typescript: optional: true - rsc-markdown-stream@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@75c5f46f947f8a4cc90ac5d843d53d421dec8a44: - resolution: {integrity: sha512-yuCvBEoV9rFdyKdS1GGdnkkPikA0R7jdxrogZ4qXW5gGigmqGxdrYMkeVEdVw6qBF+cfgw6WrXTxYVnxjdZ82g==, tarball: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@75c5f46f947f8a4cc90ac5d843d53d421dec8a44} - version: 0.0.0-preview-75c5f46 + rsc-markdown-stream@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@9197015b9ae5088eee75c7d2d11a40890b37b367: + resolution: {integrity: sha512-tmVjuRnrxFwjq1o2AsLQl9L4mI8VyQpGWNlnfCRp3zqAQw1SDNK4r5f+v/XVdOUSfVqHMNnlG8fVR0hMtn8A/w==, tarball: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@9197015b9ae5088eee75c7d2d11a40890b37b367} + version: 0.0.0-preview-9197015 engines: {node: '>=22.19.0'} peerDependencies: react: ^19.0.0 - run-applescript@7.1.0: - resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} - engines: {node: '>=18'} - run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -1283,10 +1233,6 @@ packages: utf-8-validate: optional: true - wsl-utils@1.0.0: - resolution: {integrity: sha512-Hl0ZOAs672vg+06kfujwRhoS6/jehvULrlFkuF2dRu6pHgA8U06h3xqNIqNNU1LTXPcedxByAR4GS6pwQK0mgA==} - engines: {node: '>=20'} - yaml@2.9.0: resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} engines: {node: '>= 14.6'} @@ -1297,7 +1243,7 @@ packages: snapshots: - '@agent-bundle/runtime@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@75c5f46f947f8a4cc90ac5d843d53d421dec8a44(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + '@agent-bundle/runtime@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@9197015b9ae5088eee75c7d2d11a40890b37b367(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@modelcontextprotocol/server': 2.0.0 effect: 4.0.0-rc.112 @@ -1305,7 +1251,7 @@ snapshots: react: 19.2.8 react-dom: 19.2.8(react@19.2.8) react-server-dom-rspack: 0.1.0(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - rsc-markdown-stream: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@75c5f46f947f8a4cc90ac5d843d53d421dec8a44(react@19.2.8) + rsc-markdown-stream: https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@9197015b9ae5088eee75c7d2d11a40890b37b367(react@19.2.8) zod: 4.5.4 optionalDependencies: '@rspack/core': 2.2.2(@swc/helpers@0.5.23) @@ -1931,7 +1877,7 @@ snapshots: acorn@8.18.0: {} - agent-bundle@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@75c5f46f947f8a4cc90ac5d843d53d421dec8a44(@agent-bundle/runtime@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@75c5f46f947f8a4cc90ac5d843d53d421dec8a44(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@rspack/core@2.2.2(@swc/helpers@0.5.23))(@rstest/core@0.11.11)(hono@4.13.5)(react@19.2.8)(typescript@7.0.2): + agent-bundle@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@9197015b9ae5088eee75c7d2d11a40890b37b367(@agent-bundle/runtime@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@9197015b9ae5088eee75c7d2d11a40890b37b367(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@rspack/core@2.2.2(@swc/helpers@0.5.23))(@rstest/core@0.11.11)(hono@4.13.5)(react@19.2.8)(typescript@7.0.2): dependencies: '@effect/platform-node-shared': 4.0.0-rc.112(effect@4.0.0-rc.112) '@modelcontextprotocol/client': 2.0.0 @@ -1953,11 +1899,10 @@ snapshots: ignore: 7.0.8 jiti: 2.7.0 npm-package-arg: 14.0.0 - open: 11.0.2 ws: 8.21.3 yaml: 2.9.0 optionalDependencies: - '@agent-bundle/runtime': https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@75c5f46f947f8a4cc90ac5d843d53d421dec8a44(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@agent-bundle/runtime': https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@9197015b9ae5088eee75c7d2d11a40890b37b367(@rspack/core@2.2.2(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rstest/core': 0.11.11 react: 19.2.8 transitivePeerDependencies: @@ -1989,10 +1934,6 @@ snapshots: dependencies: fill-range: 7.1.1 - bundle-name@4.1.0: - dependencies: - run-applescript: 7.1.0 - cac@7.0.0: {} chokidar@5.0.0: @@ -2011,15 +1952,6 @@ snapshots: csstype@3.2.3: {} - default-browser-id@5.0.1: {} - - default-browser@5.5.1: - dependencies: - bundle-name: 4.1.0 - default-browser-id: 5.0.1 - - define-lazy-prop@3.0.0: {} - detect-libc@2.1.2: optional: true @@ -2099,26 +2031,14 @@ snapshots: import-meta-resolve@4.2.0: {} - is-docker@3.0.0: {} - is-extglob@2.1.1: {} is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - is-in-ssh@1.0.0: {} - - is-inside-container@1.0.0: - dependencies: - is-docker: 3.0.0 - is-number@7.0.0: {} - is-wsl@3.1.1: - dependencies: - is-inside-container: 1.0.0 - isexe@2.0.0: {} jiti@2.7.0: {} @@ -2175,15 +2095,6 @@ snapshots: semver: 7.8.5 validate-npm-package-name: 8.0.0 - open@11.0.2: - dependencies: - default-browser: 5.5.1 - define-lazy-prop: 3.0.0 - is-in-ssh: 1.0.0 - is-inside-container: 1.0.0 - powershell-utils: 0.2.1 - wsl-utils: 1.0.0 - package-manager-detector@1.8.0: {} path-key@3.1.1: {} @@ -2196,10 +2107,6 @@ snapshots: pkce-challenge@5.0.1: {} - powershell-utils@0.1.0: {} - - powershell-utils@0.2.1: {} - proc-log@7.0.0: {} proper-lockfile@4.1.2: @@ -2253,12 +2160,10 @@ snapshots: optionalDependencies: typescript: 7.0.2 - rsc-markdown-stream@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@75c5f46f947f8a4cc90ac5d843d53d421dec8a44(react@19.2.8): + rsc-markdown-stream@https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@9197015b9ae5088eee75c7d2d11a40890b37b367(react@19.2.8): dependencies: react: 19.2.8 - run-applescript@7.1.0: {} - run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -2327,11 +2232,6 @@ snapshots: ws@8.21.3: {} - wsl-utils@1.0.0: - dependencies: - is-wsl: 3.1.1 - powershell-utils: 0.1.0 - yaml@2.9.0: {} zod@4.5.4: {} diff --git a/src/events/tool/after.preflight.ts b/src/events/tool/after.preflight.ts index 665847cd..ce43a323 100644 --- a/src/events/tool/after.preflight.ts +++ b/src/events/tool/after.preflight.ts @@ -3,6 +3,7 @@ import type { EventPreflight } from 'agent-bundle'; import { readCursor } from '../../hooks/hook-state.js'; import { pingSessionCompleted } from '../../hooks/session-ping.js'; import { commandMentionsHauler, hiddenCargoRun } from '../../hooks/tokens.js'; +import { documentValue } from '../../lib/json.js'; import { extractShellCommand, extractShellOutput } from '../../lib/tool-input.js'; /** @@ -14,10 +15,8 @@ import { extractShellCommand, extractShellOutput } from '../../lib/tool-input.js * the command itself names cargo or hauler, or the command's output carries * cargo's status lines without the command naming cargo (a wrapper script * ran it past the hook and the shim); a daemon that is down or slow - * answers `unavailable`, which is `continue` here. The gate's result does not - * reach the route, so `after-shell.ts` asks the daemon once more with the - * same cursor and advances it only after announcing — a second answer that - * fails leaves the tickets for the next call rather than losing them. + * answers `unavailable`, which is `continue` here. A finished-ticket answer + * is returned as `data` so the route can announce it without asking again. */ export default (async ({ canonical }) => { const command = extractShellCommand(canonical.payload.toolInput?.value); @@ -28,6 +27,9 @@ export default (async ({ canonical }) => { if (session === undefined || session.length === 0) { return { outcome: 'continue' }; } + const asOfMs = Date.now(); const pinged = await pingSessionCompleted(session, readCursor(session)); - return pinged.kind === 'finished' && pinged.tickets.length > 0 ? 'execute' : { outcome: 'continue' }; + return pinged.kind === 'finished' && pinged.tickets.length > 0 + ? { outcome: 'execute', data: documentValue({ ...pinged, asOfMs }) } + : { outcome: 'continue' }; }) satisfies EventPreflight<'tool/after'>; diff --git a/src/events/tool/after.tsx b/src/events/tool/after.tsx index 21b13fd7..d0cd5b35 100644 --- a/src/events/tool/after.tsx +++ b/src/events/tool/after.tsx @@ -3,6 +3,7 @@ import type { AgentEventRouteConfig, AgentEventRouteProps } from 'agent-bundle'; import React from 'react'; import { handleAfterShell } from '../../hooks/after-shell.js'; +import { finishedTicketsFromPreflight } from '../../hooks/session-ping.js'; import { decisionValue, shellEventFrom } from '../../lib/event-support.js'; export const config = { @@ -17,9 +18,16 @@ export const config = { export { default as preflight } from './after.preflight.js'; /** The telemetry record for a cargo/hauler command and the finished-ticket context, after the preflight ping. */ -export default async function AfterShellTool({ canonical }: AgentEventRouteProps<'tool/after'>) { +export default async function AfterShellTool({ canonical, preflight }: AgentEventRouteProps<'tool/after'>) { const { host, nativeEvent } = canonical.provenance; - const result = await handleAfterShell(shellEventFrom(canonical.payload), { nativeEvent, target: host }); + const event = shellEventFrom(canonical.payload); + const announcement = finishedTicketsFromPreflight(preflight); + const result = await handleAfterShell( + announcement === undefined + ? event + : { ...event, finishedAsOfMs: announcement.asOfMs, finishedTickets: announcement.tickets }, + { nativeEvent, target: host }, + ); return ( {result.additionalContext === undefined ? null : {result.additionalContext}} diff --git a/src/hooks/after-shell.ts b/src/hooks/after-shell.ts index 1a81f56a..51cce5a2 100644 --- a/src/hooks/after-shell.ts +++ b/src/hooks/after-shell.ts @@ -17,6 +17,8 @@ import { hiddenCargoRun } from './tokens.js'; export interface AfterShellEvent { readonly cwd?: string; readonly sessionId?: string; + readonly finishedAsOfMs?: number; + readonly finishedTickets?: readonly FinishedTicket[]; /** The completed call's input as the host sent it: an object on Claude and Cursor, any JSON on Codex. */ readonly toolInput?: unknown; readonly toolName?: string; @@ -44,27 +46,32 @@ const extractExitCode = (toolResponse: unknown): number | undefined => { const notifyContext = async ( session: string | undefined, services: HookServices, + known?: readonly FinishedTicket[], + asOfMs?: number, ): Promise => { if (session === undefined || session.length === 0) { return undefined; } - const read = services.readCursor ?? readCursor; const write = services.writeCursor ?? writeCursor; - const completedSince = services.completedSince ?? listSessionCompleted; - const sinceMs = read(session); const nowMs = (services.nowMs ?? Date.now)(); let finished: readonly FinishedTicket[]; - try { - finished = await completedSince(session, sinceMs); - } catch { - return undefined; + if (known !== undefined) { + finished = known; + } else { + const read = services.readCursor ?? readCursor; + const completedSince = services.completedSince ?? listSessionCompleted; + try { + finished = await completedSince(session, read(session)); + } catch { + return undefined; + } } if (finished.length === 0) { // The query is `finished_at_ms >= cursor`, so leaving the cursor where it // was returns the same (empty) set next time; skip the state-file write. return undefined; } - write(session, nowMs); + write(session, asOfMs ?? nowMs); return finished.map(formatFinishedTicket).join('\n'); }; @@ -98,7 +105,7 @@ const decideAfterShell = async ( ...(event.toolName === undefined ? {} : { toolName: event.toolName }), }); } - const finished = await notifyContext(event.sessionId, services); + const finished = await notifyContext(event.sessionId, services, event.finishedTickets, event.finishedAsOfMs); const notices = [...(hidden ? [hiddenCargoContext] : []), ...(finished === undefined ? [] : [finished])]; return notices.length === 0 ? { outcome: 'continue' } diff --git a/src/hooks/session-ping.ts b/src/hooks/session-ping.ts index 6c2e18db..f6170f0b 100644 --- a/src/hooks/session-ping.ts +++ b/src/hooks/session-ping.ts @@ -1,4 +1,6 @@ -import { finishedTicketsOf, type FinishedTicket } from './finished-ticket.js'; +import { isRecord } from '../lib/guards.js'; + +import { asFinishedTicket, finishedTicketsOf, type FinishedTicket } from './finished-ticket.js'; import { resolveHookSocketPath } from './paths.js'; import { requestOutcome } from './rpc.js'; @@ -26,6 +28,23 @@ export type SessionCompletedPing = } | { readonly kind: 'unavailable'; readonly reason: 'unreachable'; readonly code: string | null }; +/** Tickets the `tool/after` preflight handed the route, or undefined when it did not ping. */ +export const finishedTicketsFromPreflight = ( + value: unknown, +): { readonly asOfMs?: number; readonly tickets: readonly FinishedTicket[] } | undefined => { + if (!isRecord(value) || value.kind !== 'finished' || !Array.isArray(value.tickets)) { + return undefined; + } + const tickets = value.tickets.flatMap((entry) => { + const ticket = asFinishedTicket(entry); + return ticket === null ? [] : [ticket]; + }); + return { + tickets, + ...(typeof value.asOfMs === 'number' ? { asOfMs: value.asOfMs } : {}), + }; +}; + export interface SessionPingOptions { readonly socketPath?: string; readonly timeoutMs?: number; diff --git a/tests/event-preflight.test.ts b/tests/event-preflight.test.ts index 435d6ef2..5f17ecc9 100644 --- a/tests/event-preflight.test.ts +++ b/tests/event-preflight.test.ts @@ -262,7 +262,14 @@ describe('pingSessionCompleted', () => { const previous = process.env.CARGO_HAULER_STATE_DIR; process.env.CARGO_HAULER_STATE_DIR = fixture.config.stateDir; try { - expect(yield* Effect.promise(() => afterPreflight(preflightContext('tool/after', shellPayload('ls -la', session))))).toBe('execute'); + expect(yield* Effect.promise(() => afterPreflight(preflightContext('tool/after', shellPayload('ls -la', session))))).toEqual({ + data: { + asOfMs: expect.any(Number), + kind: 'finished', + tickets: [expect.objectContaining({ exitCode: 0, status: 'done' })], + }, + outcome: 'execute', + }); expect(yield* Effect.promise(() => afterPreflight(preflightContext('tool/after', shellPayload('ls -la', 'sess-other'))))).toEqual({ outcome: 'continue', }); diff --git a/tests/notify.test.ts b/tests/notify.test.ts index db5bbf8f..a7b940df 100644 --- a/tests/notify.test.ts +++ b/tests/notify.test.ts @@ -67,4 +67,41 @@ describe('afterTool completion notify', () => { ); expect(down).toEqual({ outcome: 'continue' }); }); + + it('announces preflight tickets without querying the daemon, at the ping watermark', async () => { + let queried = false; + let cursor: number | undefined; + const result = await handleAfterShell( + { + finishedAsOfMs: 40, + finishedTickets: [ + { + error: null, + errorCount: 0, + exitCode: 0, + status: 'done', + ticket: 'cc-42', + warningCount: 0, + }, + ], + sessionId: 'sess-1', + toolInput: { command: 'ls' }, + }, + { target: 'claude' }, + { + completedSince: async () => { + queried = true; + return []; + }, + nowMs: () => 99, + record: () => undefined, + writeCursor: (_session, atMs) => { + cursor = atMs; + }, + }, + ); + expect(queried).toBe(false); + expect(cursor).toBe(40); + expect(result.additionalContext).toContain('cc-42 finished: success'); + }); });