From 5d9270335ea7cfaaa5bfa39750d89291bd683546 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 00:48:29 -0400 Subject: [PATCH 01/31] build: pin bun and add canonical lockfile --- .bun-version | 1 + bun.lock | 1054 +++++ bunfig.toml | 3 + package-lock.json | 5837 ---------------------------- package.json | 4 +- packages/coding-agent/package.json | 5 +- 6 files changed, 1060 insertions(+), 5844 deletions(-) create mode 100644 .bun-version create mode 100644 bun.lock create mode 100644 bunfig.toml delete mode 100644 package-lock.json diff --git a/.bun-version b/.bun-version new file mode 100644 index 0000000000..085c0f2666 --- /dev/null +++ b/.bun-version @@ -0,0 +1 @@ +1.3.14 diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000000..aa34d8105e --- /dev/null +++ b/bun.lock @@ -0,0 +1,1054 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "prime-agent", + "dependencies": { + "@earendil-works/pi-coding-agent": "^0.8.1", + "get-east-asian-width": "^1.6.0", + }, + "devDependencies": { + "@anthropic-ai/sandbox-runtime": "^0.0.55", + "@biomejs/biome": "2.5.5", + "@types/node": "^22.10.5", + "@typescript/native-preview": "7.0.0-dev.20260120.1", + "concurrently": "^9.2.4", + "husky": "^9.1.7", + "jiti": "^2.7.0", + "shx": "^0.4.0", + "tsx": "^4.23.1", + "typescript": "^7.0.2", + }, + }, + "packages/agent": { + "name": "@earendil-works/pi-agent-core", + "version": "0.8.1", + "dependencies": { + "@earendil-works/pi-ai": "^0.8.1", + "typebox": "^1.3.9", + }, + "devDependencies": { + "@types/node": "^24.3.0", + "typescript": "^7.0.2", + "vitest": "^4.1.10", + }, + }, + "packages/ai": { + "name": "@earendil-works/pi-ai", + "version": "0.8.1", + "bin": { + "pi-ai": "./dist/cli.js", + }, + "dependencies": { + "@anthropic-ai/sdk": "^0.91.1", + "@aws-sdk/client-bedrock-runtime": "^3.1095.0", + "@google/genai": "^1.40.0", + "@mistralai/mistralai": "^2.2.0", + "chalk": "^5.6.2", + "openai": "6.47.0", + "partial-json": "^0.1.7", + "proxy-agent": "^6.5.0", + "typebox": "^1.3.9", + "undici": "^7.29.0", + "zod-to-json-schema": "^3.24.6", + }, + "devDependencies": { + "@types/node": "^24.3.0", + "canvas": "^3.2.0", + "vitest": "^4.1.10", + }, + }, + "packages/coding-agent": { + "name": "@earendil-works/pi-coding-agent", + "version": "0.8.1", + "bin": { + "pi": "dist/bundle/cli.js", + }, + "dependencies": { + "@agentclientprotocol/sdk": "^1.3.0", + "@earendil-works/pi-agent-core": "^0.8.1", + "@earendil-works/pi-ai": "^0.8.1", + "@earendil-works/pi-tui": "^0.8.1", + "@silvia-odwyer/photon-node": "^0.3.4", + "chalk": "^5.5.0", + "cli-highlight": "^2.1.11", + "diff": "^9.0.0", + "extract-zip": "^2.0.1", + "file-type": "^21.1.1", + "glob": "^13.0.1", + "grok-mermaid": "0.2.3", + "hosted-git-info": "^9.0.2", + "ignore": "^7.0.5", + "jiti": "^2.7.0", + "marked": "^18.0.7", + "minimatch": "^10.2.3", + "proper-lockfile": "^4.1.2", + "strip-ansi": "^7.1.0", + "typebox": "^1.3.9", + "undici": "^7.29.0", + "uuid": "^14.0.0", + "yaml": "^2.9.0", + }, + "devDependencies": { + "@types/diff": "^8.0.0", + "@types/hosted-git-info": "^3.0.5", + "@types/ms": "^2.1.0", + "@types/node": "^24.3.0", + "@types/proper-lockfile": "^4.1.4", + "esbuild": "^0.28.1", + "shx": "^0.4.0", + "typescript": "^7.0.2", + "vitest": "^4.1.10", + }, + "optionalDependencies": { + "@mariozechner/clipboard": "^0.3.9", + }, + }, + "packages/coding-agent/examples/extensions/custom-provider-anthropic": { + "name": "pi-extension-custom-provider-anthropic", + "version": "0.0.1", + "dependencies": { + "@anthropic-ai/sdk": "^0.52.0", + }, + }, + "packages/coding-agent/examples/extensions/custom-provider-gitlab-duo": { + "name": "pi-extension-custom-provider-gitlab-duo", + "version": "0.0.1", + }, + "packages/coding-agent/examples/extensions/sandbox": { + "name": "pi-extension-sandbox", + "version": "1.4.0", + "dependencies": { + "@anthropic-ai/sandbox-runtime": "^0.0.55", + }, + }, + "packages/coding-agent/examples/extensions/with-deps": { + "name": "pi-extension-with-deps", + "version": "0.0.1", + "dependencies": { + "ms": "^2.1.3", + }, + "devDependencies": { + "@types/ms": "^2.1.0", + }, + }, + "packages/tui": { + "name": "@earendil-works/pi-tui", + "version": "0.8.1", + "dependencies": { + "@types/mime-types": "^3.0.1", + "chalk": "^5.5.0", + "get-east-asian-width": "^1.6.0", + "marked": "^18.0.7", + "mime-types": "^3.0.1", + }, + "devDependencies": { + "@xterm/headless": "^6.0.0", + "@xterm/xterm": "^6.0.0", + }, + "optionalDependencies": { + "koffi": "^2.9.0", + }, + }, + }, + "overrides": { + "rimraf": "6.1.2", + "shell-quote": "^1.10.0", + }, + "packages": { + "@agentclientprotocol/sdk": ["@agentclientprotocol/sdk@1.4.0", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-/eufudw+aFY1LKLolT6yFE6UMmYRl7fMJ/DEONSIyR6wI3slHWITBsANRGqXEY8FRzqUxwh7QEaGiZHcJPVThg=="], + + "@anthropic-ai/sandbox-runtime": ["@anthropic-ai/sandbox-runtime@0.0.55", "", { "dependencies": { "@pondwader/socks5-server": "^1.0.10", "commander": "^12.1.0", "node-forge": "^1.4.0", "shell-quote": "^1.8.4", "zod": "^3.24.1" }, "bin": { "srt": "dist/cli.js" } }, "sha512-XGTLbzitn0y6OCdmqP5aYrBR0HlNi87ue++m9vMPxcNwaQeOj9i3f9CSWmXua8mv+Q8E55k4ZGlzJmpDHzQFBw=="], + + "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.91.1", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw=="], + + "@aws-sdk/client-bedrock-runtime": ["@aws-sdk/client-bedrock-runtime@3.1117.0", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/credential-provider-node": "^3.972.81", "@aws-sdk/eventstream-handler-node": "^3.972.34", "@aws-sdk/middleware-eventstream": "^3.972.29", "@aws-sdk/middleware-websocket": "^3.972.52", "@aws-sdk/token-providers": "3.1117.0", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/fetch-http-handler": "^5.7.2", "@smithy/node-http-handler": "^4.11.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-rUc58ZS5GgsvzfM265XsrNno35dsRIwQb0aDfJIZbJyn1VGP+6XVL5Pwm8Rg9uABQSdKpdTayu5R3ZuDlFfIHg=="], + + "@aws-sdk/core": ["@aws-sdk/core@3.977.9", "", { "dependencies": { "@aws-sdk/types": "^3.974.5", "@aws-sdk/xml-builder": "^3.972.40", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.33.3", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.17.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-reqPFEQrZxDZpeGj4PFMepBeR5LGYHRqq/L0motTzgFkCRBA4rFdaVXDSLYyGHhxVz7sT2PDnPN9CluGSfgyJA=="], + + "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.70", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-H404B7dJl2mCrBqahDEYsanB0xhdDp6tXnXcTUnXmmpy2Q3J0Ho0bUajZ2jr/RdwzCyS59Gi8xXIFwPLGBl6Uw=="], + + "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.72", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/fetch-http-handler": "^5.7.2", "@smithy/node-http-handler": "^4.11.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-X98zYOrVOeuosCX+6ktf29FC2N2GHPLia7qv6mzPzTc+RPAuHWCDS++Z6JK7eGYqb/v6uaW7bAXaOvDBfol+0w=="], + + "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.973.15", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/credential-provider-env": "^3.972.70", "@aws-sdk/credential-provider-http": "^3.972.72", "@aws-sdk/credential-provider-login": "^3.972.77", "@aws-sdk/credential-provider-process": "^3.972.70", "@aws-sdk/credential-provider-sso": "^3.973.14", "@aws-sdk/credential-provider-web-identity": "^3.972.76", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/credential-provider-imds": "^4.4.16", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-Rykg6s5ceBuynMOGWgoowO4N+27JfnqXAnVaSunZl0hOO1XodSrxGNz6sCEbnmS0lAfQZDKyb3fbr46gSuv6Sg=="], + + "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.77", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-Jb59xfEISoN5mmbnA+HYqdtrSX3CgCtJoof+V5D8/TgUI56W63GEEd5Y58WijU3Ou6+WEgaLD1feVzaRXV5IDQ=="], + + "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.81", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.70", "@aws-sdk/credential-provider-http": "^3.972.72", "@aws-sdk/credential-provider-ini": "^3.973.15", "@aws-sdk/credential-provider-process": "^3.972.70", "@aws-sdk/credential-provider-sso": "^3.973.14", "@aws-sdk/credential-provider-web-identity": "^3.972.76", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/credential-provider-imds": "^4.4.16", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-Rml+WitoFvXmv6JZ18U/xGdGDGGvB/mOin0ya0lTnTrdC0Z1lrVxTYh7iNklZBcvcRMrs4DoEf6xy1KWyrLQQw=="], + + "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.70", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-2ry03fGRJr4sV3jI+ocjj5JqALnFD6ymM5KiNCDZMvq8bX2GSbE0vji4aM43TVCl2nXqqLRZaUxdq/KeWRAY4Q=="], + + "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.973.14", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/token-providers": "3.1116.0", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-jkhg/8ocAAoc0RFyLMhCw+/zZh7gystQgd4F4hznNa8P4Cc501PQmxd+jGLiMHodPJ+7Zv/3znM62gZojyasmA=="], + + "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.76", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-d3AGyVu759PGr35mEB2s22xxlNEA5rpdxtSPJthfPFJvoQ8dt357iVPECqWfUxXp1toJAvKmbtcIYVGigaGsCA=="], + + "@aws-sdk/eventstream-handler-node": ["@aws-sdk/eventstream-handler-node@3.972.34", "", { "dependencies": { "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-cTeVzpu1xEAkryTZBYhGwnQ6gOGyp8ZYZvmn0Sg/nI/ABmy/CRHHxPDJDUi9PxwxUtGGaatvfRUB3FCgT/rSWw=="], + + "@aws-sdk/middleware-eventstream": ["@aws-sdk/middleware-eventstream@3.972.29", "", { "dependencies": { "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-dlRzHCgyB8W6hLuDC5pcT5q+ziPt00n4QGgGBE17ucLVU4zMa6lsbuUdQ2Pm75Z5VA8GF+R/+SgrRcaTdIzSIQ=="], + + "@aws-sdk/middleware-websocket": ["@aws-sdk/middleware-websocket@3.972.52", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/fetch-http-handler": "^5.7.2", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-vsPPM+nMbKJlUCFU+eoGZbdxdxDIAX9LbpjSXaR5Ufpmqgp8TdYQnoExhLu4T3umW/JIIPny1ydbhWidZZYokQ=="], + + "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.44", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/signature-v4-multi-region": "^3.996.46", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/fetch-http-handler": "^5.7.2", "@smithy/node-http-handler": "^4.11.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-NhEgryjlBF9w38ZXqGymQV28IhkYa1mKhlbYnqIis57AYwWGVYfUPgg/qC2rLRqOUfblxx++irvju10kVTa8Vw=="], + + "@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.46", "", { "dependencies": { "@aws-sdk/types": "^3.974.5", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-L+2xZTye/2T96f3lwCws0Zw6GG2JHZW9e8FpVgGBeeExSKyeoZ6CWRpBml/7DNiK/O26jrgPM9F+Ay8VkgzUWQ=="], + + "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1117.0", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-I7QIf9aR0+J4Q1qlLQw006d8hs3Pb/J6mOVSCQ/fnQ4AXHTQ6Y/M45O2dWDRKoYqsQJ2kN8sg6b5709/qCzp9A=="], + + "@aws-sdk/types": ["@aws-sdk/types@3.974.5", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ=="], + + "@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.40", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-wlFmCIGUlwF4zx/kncw+bmxTQh1HeSJq4mYV/V5cZUSJadDP3kXvGW8Rn21cimj/7y9ju+47oYWXi97vF7czaA=="], + + "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], + + "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="], + + "@biomejs/biome": ["@biomejs/biome@2.5.5", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.5.5", "@biomejs/cli-darwin-x64": "2.5.5", "@biomejs/cli-linux-arm64": "2.5.5", "@biomejs/cli-linux-arm64-musl": "2.5.5", "@biomejs/cli-linux-x64": "2.5.5", "@biomejs/cli-linux-x64-musl": "2.5.5", "@biomejs/cli-win32-arm64": "2.5.5", "@biomejs/cli-win32-x64": "2.5.5" }, "bin": { "biome": "bin/biome" } }, "sha512-r1S8nFsAG1MY+vJFZALzIvwXAJv6ejDQ0mxP21Tgr9YK3ZFtjrvbBwDdNhx1rUqvccEIeNg20cYCNzl6Cr69pQ=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.5.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kUrAhXVWUrwmAUnV2iXSK7umxKFysTwvqK+Ty6ptUcLY/7T3SnCAjUowE4uvwaEej6nXZ7hu/dTtbokKdsPeag=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.5.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-DamiYc5bUYZ2uxlfc+RLEPtz1Abb6PO5eTbOkufLpSGwd/7AMQAdxhFYiXmwwkJL8IsT8S7GvdgwDHqaMFAvKw=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.5.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-lRKF/pH/1RiYiBKExi3TCZVAtvzEm77aifrvcNiDFrR9WxeAnDUjDnseb6y2XV85mjitLs6SILGm2XG77cHtSQ=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.5.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-U4WMl/sy/E/Q73vf15VspakLRRs2LDFcCeBxJnQfXzssb88zpV6PJPaQ3ezhQ7H6Ht2/8bvuZeHgJWzmoxllZg=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.5.5", "", { "os": "linux", "cpu": "x64" }, "sha512-H/O39nJEw/2Zm/fm7hrmxxoF8kK/aU1uCoPp70ruXVbomaAdLpJJnCmL11Q2JotT8QVHH06So04Oq53lCSwSwQ=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.5.5", "", { "os": "linux", "cpu": "x64" }, "sha512-m7wC7tjX5Lrmo69dc4md8FeKpPU1NTCY1v7xUoQQ2vadWwNnBS0KZOG8471otFPHrTHihQJAjQPgMObpLvDe6A=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.5.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-7BryINPuYypLUAH3o/o5ZdgomJ4zn3EDR0ChZJst7n32S6ZhKbgHXuYydLu+YAnx59ehGFR0z/MG6qnzQi3Yyw=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.5.5", "", { "os": "win32", "cpu": "x64" }, "sha512-bIBFo+n6MIxdNcVFy5CrurbKiZQiUciK3bt8+O9I4wjFZNTfXLpi+giq47522eXqW5NBc9ulx7dR1SlZKi2J5g=="], + + "@borewit/text-codec": ["@borewit/text-codec@0.2.2", "", {}, "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ=="], + + "@earendil-works/pi-agent-core": ["@earendil-works/pi-agent-core@workspace:packages/agent"], + + "@earendil-works/pi-ai": ["@earendil-works/pi-ai@workspace:packages/ai"], + + "@earendil-works/pi-coding-agent": ["@earendil-works/pi-coding-agent@workspace:packages/coding-agent"], + + "@earendil-works/pi-tui": ["@earendil-works/pi-tui@workspace:packages/tui"], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.28.2", "", { "os": "android", "cpu": "arm" }, "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.2", "", { "os": "android", "cpu": "arm64" }, "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.28.2", "", { "os": "android", "cpu": "x64" }, "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.2", "", { "os": "linux", "cpu": "arm" }, "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.2", "", { "os": "linux", "cpu": "x64" }, "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.2", "", { "os": "none", "cpu": "arm64" }, "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.2", "", { "os": "none", "cpu": "x64" }, "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.2", "", { "os": "none", "cpu": "arm64" }, "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g=="], + + "@google/genai": ["@google/genai@1.52.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@mariozechner/clipboard": ["@mariozechner/clipboard@0.3.9", "", { "optionalDependencies": { "@mariozechner/clipboard-darwin-arm64": "0.3.9", "@mariozechner/clipboard-darwin-universal": "0.3.9", "@mariozechner/clipboard-darwin-x64": "0.3.9", "@mariozechner/clipboard-linux-arm64-gnu": "0.3.9", "@mariozechner/clipboard-linux-arm64-musl": "0.3.9", "@mariozechner/clipboard-linux-riscv64-gnu": "0.3.9", "@mariozechner/clipboard-linux-x64-gnu": "0.3.9", "@mariozechner/clipboard-linux-x64-musl": "0.3.9", "@mariozechner/clipboard-win32-arm64-msvc": "0.3.9", "@mariozechner/clipboard-win32-x64-msvc": "0.3.9" } }, "sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA=="], + + "@mariozechner/clipboard-darwin-arm64": ["@mariozechner/clipboard-darwin-arm64@0.3.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BfgV7vCEWZwJwZJw03r6bP5+tf0iI/ANuQYCxi9RNn7FrWB3yzGuMKCrNLRl6V761vXRdL8+OqZ0wd4TqlsNOQ=="], + + "@mariozechner/clipboard-darwin-universal": ["@mariozechner/clipboard-darwin-universal@0.3.9", "", { "os": "darwin" }, "sha512-BGGR4iA9Z2shAjI65eI5xtyb3LYNlDW9X3gxKxDbqtbnREohsrqznov6zpKoIrsRWpzlYVEdKphS7ksJ0/ndSQ=="], + + "@mariozechner/clipboard-darwin-x64": ["@mariozechner/clipboard-darwin-x64@0.3.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-4kURmCbS6nt8uYhtmWpUcJWyPHfmAr5dTpXD1nO3pIfa+TSQ9DbrGOYCKH+aEFW47XhQ4Vp8ZTszie+wfFvDKg=="], + + "@mariozechner/clipboard-linux-arm64-gnu": ["@mariozechner/clipboard-linux-arm64-gnu@0.3.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-g59OkUGP2DDfCOIKypHeYgv2M55u/cKvXa5dSxFbEJ34XvIQMdcVmpKCkGUro3ZgefXiGVdwguvTMQGpHWzIXw=="], + + "@mariozechner/clipboard-linux-arm64-musl": ["@mariozechner/clipboard-linux-arm64-musl@0.3.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-AGuJdgKsmJdm4Pych7kv3sqe591ERRaAHW3xjLooiFzn8J+PxUyof++7YZrB5Y5tpnTO+K18Og3taj2NpluCRQ=="], + + "@mariozechner/clipboard-linux-riscv64-gnu": ["@mariozechner/clipboard-linux-riscv64-gnu@0.3.9", "", { "os": "linux", "cpu": "none" }, "sha512-DXBEAiuMpk7dhS1a9NzNxVAFi1vaKoPu7rQNgY8LIDLGrK3lnIp3nT10DUum+PKVJoJppIP+NAA8IZe4DMNDPw=="], + + "@mariozechner/clipboard-linux-x64-gnu": ["@mariozechner/clipboard-linux-x64-gnu@0.3.9", "", { "os": "linux", "cpu": "x64" }, "sha512-WORrMLd6EpElEME7JRKfSaY34nW1P5LbdgK5YNCS1ncG2LqmITsSMEJ8nh2mpvxb3TxqbOOKgY7k9eMJYlW9Mw=="], + + "@mariozechner/clipboard-linux-x64-musl": ["@mariozechner/clipboard-linux-x64-musl@0.3.9", "", { "os": "linux", "cpu": "x64" }, "sha512-/DHn+1DrfL6oRaPPWXaOKvonFFrni666fxd+zFqiQEfvBH0tsHVWjq9iqBk0oDp0qaPA72lIMy5BptxISBEhZQ=="], + + "@mariozechner/clipboard-win32-arm64-msvc": ["@mariozechner/clipboard-win32-arm64-msvc@0.3.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-O5FHD3ErkMwMhNzAfu3ggy0ug4z7btZuoQgwwxlzPrwV2bxlD6WDpqBY4NCgICAgZdDKdp+loUEKVAVt8aYnhQ=="], + + "@mariozechner/clipboard-win32-x64-msvc": ["@mariozechner/clipboard-win32-x64-msvc@0.3.9", "", { "os": "win32", "cpu": "x64" }, "sha512-ihQC3EufqEY81vhXBgVBtK4prL+wc62zJsSvxrgz7K1hsdt6OObz6v9p3Rn1OG3GJksTTKMJF0u/guMISHPhSA=="], + + "@mistralai/mistralai": ["@mistralai/mistralai@2.6.4", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.40.0", "ws": "^8.18.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.25.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/exporter-trace-otlp-http": "^0.220.0", "@opentelemetry/resources": "^2.9.0", "@opentelemetry/sdk-trace-base": "^2.9.0" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/exporter-trace-otlp-http", "@opentelemetry/resources", "@opentelemetry/sdk-trace-base"] }, "sha512-PPt4GyJqs2hEsWrYCJZK5f0ORmT+L2MSm75LVGD7kBLf6ZKsoDpld/FRBQXr8xG6iFCBOFJFYzvGYhUb+UCkbw=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.43.0", "", {}, "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg=="], + + "@oxc-project/types": ["@oxc-project/types@0.146.0", "", {}, "sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA=="], + + "@pondwader/socks5-server": ["@pondwader/socks5-server@1.0.10", "", {}, "sha512-bQY06wzzR8D2+vVCUoBsr5QS2U6UgPUQRmErNwtsuI6vLcyRKkafjkr3KxbtGFf9aBBIV2mcvlsKD1UYaIV+sg=="], + + "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], + + "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], + + "@protobufjs/codegen": ["@protobufjs/codegen@2.0.5", "", {}, "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g=="], + + "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.1", "", {}, "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg=="], + + "@protobufjs/fetch": ["@protobufjs/fetch@1.1.1", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1" } }, "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw=="], + + "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="], + + "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="], + + "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="], + + "@protobufjs/utf8": ["@protobufjs/utf8@1.1.2", "", {}, "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug=="], + + "@rolldown/binding-android-arm-eabi": ["@rolldown/binding-android-arm-eabi@1.2.5", "", { "os": "android", "cpu": "arm" }, "sha512-DLe/i+l8ynIBY7XEQ191TeZvCoowIGa18R+dIV30GW7DiOtp74i/xX8hs8GUjW5ARV7VZuie3d6AumSmCwbeRA=="], + + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.2.5", "", { "os": "android", "cpu": "arm64" }, "sha512-zXcwKlQApYAOELHd8PwKDFkagYF9Wy4e0RJ+0qnzl9Pjnpj75TEG8ufv40p2J7kCEfwZAsNiuzRIyNNMWT38ig=="], + + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.2.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dK4QakI42nzWgJT5sm4y4y/O//D4OxM75/cH28RLV+nzIN9AY+YsbuUVrUTjlLjXR6vpyxFbSsbmNuJ6BP9sww=="], + + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.2.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-fqSALaUu1Wjd1nK2uW2kJDWdLCc8lx1IcY+MTY26Aurfdx19anlzhqXOgCFbBFQnlFDTn4TC1/7Nz4Bl2mLP3A=="], + + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.2.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-/vCnNxlkxs9tKxNDcyWUePpJ/PgTzxIaVhoM5SmG8UV+GR/IcPam4VYxi7GIMo7PSDuNqlJqvprqii9NqqVCMw=="], + + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.2.5", "", { "os": "linux", "cpu": "arm" }, "sha512-abk0NLA519LxRCszmbE0jYKuQ9YPocOXTiOXOo6Yr+YAT95VH+PtqYAjOJvGKt3viEd/x4qzabAlwd5bHOOARg=="], + + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.2.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-Y7eALiJ8lr0M2HH103Js+g7V34wf6snlpZLAsHI90uLhr3PVlNsbFVAXJC9d/V6BnPyKtpSwI+NcB/RLxsQxuA=="], + + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.2.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-xMvZgnbZg4YVnR/AX2b3oOPDTFYJvUVaJg5FedA/LuvexAtXibZQej4cnTkw3rjsJ/ggUROB64TdtETiim+FYA=="], + + "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.2.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-GRjeqTUDHTo5GwntsLaAMcBahG3nlpjftXWZLN73HiYQlhwEowvarFgQnRnQZtIp4keXX7quXFbG38uPZBa2EA=="], + + "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.2.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-vLNTR45F2Uwc8AufkNXPmB4VliaXs+FvcheEogIzOXzO4l+LzieXF5A/TWxLy5HtqpsRCHUfd0lPVrrdgXdLHQ=="], + + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.2.5", "", { "os": "linux", "cpu": "x64" }, "sha512-Mgj59/HTuYeK9Gz2MA+mBWKnHsAgkBSec15ZMb1st3oIfFbX7gCjOae7GydHhzcyQi9Z/7M1QuN9bR3oFqF0jQ=="], + + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.2.5", "", { "os": "linux", "cpu": "x64" }, "sha512-mY8AP0/ichsbhAxGnLa3d3+MwV0EfgrPND2bplI3Ym8T6R2pJ0N87bvrKVwNXmdy3jnr6eQBecdqx/HMknBmpA=="], + + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.2.5", "", { "os": "none", "cpu": "arm64" }, "sha512-8SLssA2oweAxyRgDp789ACfRb/3P+zNRJpzZxSizxF9m8NUDQ4+3xjo8ttjhVGGw6Qxb70oZiEtIjaKikCO7Yw=="], + + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.2.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-vGbruD5zquhoc8D9SViXgN2FBJtNdTyQ4DtG+SWiEGlJiAzoKcZ2xp+xuXCffhubVdt0NJlTZqkeRuERy7g8Cw=="], + + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.2.5", "", { "os": "win32", "cpu": "x64" }, "sha512-e/SXpgISz+IoqVcSSI0rx/d/he8zqLex+/rCWpnHpmVfmPIUjag9H6P7zotf0gJHwPUhQxZ/mF8tr6acebT9yw=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="], + + "@silvia-odwyer/photon-node": ["@silvia-odwyer/photon-node@0.3.4", "", {}, "sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA=="], + + "@smithy/core": ["@smithy/core@3.33.3", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-CsOeKq/9kA3y6VJHt+/+VTCtBaxJ4OTFpgrjIUhPpDIKxBci1k2bJaQASF2h/ELWrulGp+t97DZ0mevfAD8idg=="], + + "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.5.2", "", { "dependencies": { "@smithy/core": "^3.33.2", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg=="], + + "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.7.2", "", { "dependencies": { "@smithy/core": "^3.33.2", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-nZyWTmSpJEXl6VtWVMBJve/7x12DZu6sIX1z1a+ZMaHlQQRs9Zpu6NbTe/gmxYXVRpkjxyDYpZ5gx2IM6f/Wkw=="], + + "@smithy/node-http-handler": ["@smithy/node-http-handler@4.11.3", "", { "dependencies": { "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-2jY1tSpERfPfWqyBV2pH+iGFaghVsIJszJNsT7hxtQYhVJpWDyc0LqOWI+nXOxOAHaEfZ4PXXtp1wW1TGpHhkA=="], + + "@smithy/signature-v4": ["@smithy/signature-v4@5.7.3", "", { "dependencies": { "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-7ImGm+FkHRLcBaRttIAMZ6bzJZWb2cJGoYjq46F2UjycujWzrL9GEN9h4w7eQyXJYnltrUhxbbieBAIRrdqpow=="], + + "@smithy/types": ["@smithy/types@4.17.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-FOKpVZob9MPTn2znRzGrnsMHv7BOsKVw3XiP/cOyYLDVZ9qKp4nifIiSCuUU/fIj5Vu0UOAxCFr+qRAtG0NUkA=="], + + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + + "@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="], + + "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], + + "@tootallnate/quickjs-emscripten": ["@tootallnate/quickjs-emscripten@0.23.0", "", {}, "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="], + + "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], + + "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], + + "@types/diff": ["@types/diff@8.0.0", "", { "dependencies": { "diff": "*" } }, "sha512-o7jqJM04gfaYrdCecCVMbZhNdG6T1MHg/oQoRFdERLV+4d+V7FijhiEAbFu0Usww84Yijk9yH58U4Jk4HbtzZw=="], + + "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], + + "@types/hosted-git-info": ["@types/hosted-git-info@3.0.5", "", {}, "sha512-Dmngh7U003cOHPhKGyA7LWqrnvcTyILNgNPmNCxlx7j8MIi54iBliiT8XqVLIQ3GchoOjVAyBzNJVyuaJjqokg=="], + + "@types/mime-types": ["@types/mime-types@3.0.1", "", {}, "sha512-xRMsfuQbnRq1Ef+C+RKaENOxXX87Ygl38W1vDfPHRku02TgQr+Qd8iivLtAMcR0KF5/29xlnFihkTlbqFrGOVQ=="], + + "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], + + "@types/node": ["@types/node@22.20.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q=="], + + "@types/proper-lockfile": ["@types/proper-lockfile@4.1.4", "", { "dependencies": { "@types/retry": "*" } }, "sha512-uo2ABllncSqg9F1D4nugVl9v93RmjxF6LJzQLMLDdPaXCUIDPeOJ21Gbqi43xNKzBi/WQ0Q0dICqufzQbMjipQ=="], + + "@types/retry": ["@types/retry@0.12.5", "", {}, "sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw=="], + + "@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="], + + "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260120.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260120.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260120.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260120.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260120.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260120.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260120.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260120.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-nnEf37C9ue7OBRnF2zmV/OCBmV5Y7T/K4mCHa+nxgiXcF/1w8sA0cgdFl+gHQ0mysqUJ+Bu5btAMeWgpLyjrgg=="], + + "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260120.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-r3pWFuR2H7mn6ScwpH5jJljKQqKto0npVuJSk6pRwFwexpTyxOGmJTZJ1V0AWiisaNxU2+CNAqWFJSJYIE/QTg=="], + + "@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260120.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cuC1+wLbUP+Ip2UT94G134fqRdp5w3b3dhcCO6/FQ4yXxvRNyv/WK+upHBUFDaeSOeHgDTyO9/QFYUWwC4If1A=="], + + "@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260120.1", "", { "os": "linux", "cpu": "arm" }, "sha512-vN6OYVySol/kQZjJGmAzd6L30SyVlCgmCXS8WjUYtE5clN0YrzQHop16RK29fYZHMxpkOniVBtRPxUYQANZBlQ=="], + + "@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260120.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-zZGvEGY7wcHYefMZ87KNmvjN3NLIhsCMHEpHZiGCS3khKf+8z6ZsanrzCjOTodvL01VPyBzHxV1EtkSxAcLiQg=="], + + "@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260120.1", "", { "os": "linux", "cpu": "x64" }, "sha512-JBfNhWd/asd5MDeS3VgRvE24pGKBkmvLub6tsux6ypr+Yhy+o0WaAEzVpmlRYZUqss2ai5tvOu4dzPBXzZAtFw=="], + + "@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260120.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-tTndRtYCq2xwgE0VkTi9ACNiJaV43+PqvBqCxk8ceYi3X36Ve+CCnwlZfZJ4k9NxZthtrAwF/kUmpC9iIYbq1w=="], + + "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260120.1", "", { "os": "win32", "cpu": "x64" }, "sha512-oZia7hFL6k9pVepfonuPI86Jmyz6WlJKR57tWCDwRNmpA7odxuTq1PbvcYgy1z4+wHF1nnKKJY0PMAiq6ac18w=="], + + "@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="], + + "@typescript/typescript-darwin-arm64": ["@typescript/typescript-darwin-arm64@7.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA=="], + + "@typescript/typescript-darwin-x64": ["@typescript/typescript-darwin-x64@7.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA=="], + + "@typescript/typescript-freebsd-arm64": ["@typescript/typescript-freebsd-arm64@7.0.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ=="], + + "@typescript/typescript-freebsd-x64": ["@typescript/typescript-freebsd-x64@7.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw=="], + + "@typescript/typescript-linux-arm": ["@typescript/typescript-linux-arm@7.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ=="], + + "@typescript/typescript-linux-arm64": ["@typescript/typescript-linux-arm64@7.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ=="], + + "@typescript/typescript-linux-loong64": ["@typescript/typescript-linux-loong64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ=="], + + "@typescript/typescript-linux-mips64el": ["@typescript/typescript-linux-mips64el@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA=="], + + "@typescript/typescript-linux-ppc64": ["@typescript/typescript-linux-ppc64@7.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA=="], + + "@typescript/typescript-linux-riscv64": ["@typescript/typescript-linux-riscv64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ=="], + + "@typescript/typescript-linux-s390x": ["@typescript/typescript-linux-s390x@7.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw=="], + + "@typescript/typescript-linux-x64": ["@typescript/typescript-linux-x64@7.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A=="], + + "@typescript/typescript-netbsd-arm64": ["@typescript/typescript-netbsd-arm64@7.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA=="], + + "@typescript/typescript-netbsd-x64": ["@typescript/typescript-netbsd-x64@7.0.2", "", { "os": "none", "cpu": "x64" }, "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA=="], + + "@typescript/typescript-openbsd-arm64": ["@typescript/typescript-openbsd-arm64@7.0.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ=="], + + "@typescript/typescript-openbsd-x64": ["@typescript/typescript-openbsd-x64@7.0.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg=="], + + "@typescript/typescript-sunos-x64": ["@typescript/typescript-sunos-x64@7.0.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g=="], + + "@typescript/typescript-win32-arm64": ["@typescript/typescript-win32-arm64@7.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ=="], + + "@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="], + + "@vitest/expect": ["@vitest/expect@4.1.11", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.11", "@vitest/utils": "4.1.11", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw=="], + + "@vitest/mocker": ["@vitest/mocker@4.1.11", "", { "dependencies": { "@vitest/spy": "4.1.11", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ=="], + + "@vitest/pretty-format": ["@vitest/pretty-format@4.1.11", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw=="], + + "@vitest/runner": ["@vitest/runner@4.1.11", "", { "dependencies": { "@vitest/utils": "4.1.11", "pathe": "^2.0.3" } }, "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw=="], + + "@vitest/snapshot": ["@vitest/snapshot@4.1.11", "", { "dependencies": { "@vitest/pretty-format": "4.1.11", "@vitest/utils": "4.1.11", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog=="], + + "@vitest/spy": ["@vitest/spy@4.1.11", "", {}, "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA=="], + + "@vitest/utils": ["@vitest/utils@4.1.11", "", { "dependencies": { "@vitest/pretty-format": "4.1.11", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ=="], + + "@xterm/headless": ["@xterm/headless@6.0.0", "", {}, "sha512-5Yj1QINYCyzrZtf8OFIHi47iQtI+0qYFPHmouEfG8dHNxbZ9Tb9YGSuLcsEwj9Z+OL75GJqPyJbyoFer80a2Hw=="], + + "@xterm/xterm": ["@xterm/xterm@6.0.0", "", {}, "sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg=="], + + "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], + + "ansi-regex": ["ansi-regex@6.3.0", "", {}, "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], + + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + + "ast-types": ["ast-types@0.13.4", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w=="], + + "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "basic-ftp": ["basic-ftp@5.3.1", "", {}, "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw=="], + + "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], + + "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], + + "bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="], + + "brace-expansion": ["brace-expansion@5.0.9", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + + "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], + + "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], + + "canvas": ["canvas@3.2.3", "", { "dependencies": { "node-addon-api": "^7.0.0", "prebuild-install": "^7.1.3" } }, "sha512-PzE5nJZPz72YUAfo8oTp0u3fqqY7IzlTubneAihqDYAUcBk7ryeCmBbdJBEdaH0bptSOe2VT2Zwcb3UaFyaSWw=="], + + "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], + + "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="], + + "cli-highlight": ["cli-highlight@2.1.11", "", { "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", "mz": "^2.4.0", "parse5": "^5.1.1", "parse5-htmlparser2-tree-adapter": "^6.0.0", "yargs": "^16.0.0" }, "bin": { "highlight": "bin/highlight" } }, "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg=="], + + "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + + "concurrently": ["concurrently@9.2.4", "", { "dependencies": { "chalk": "4.1.2", "rxjs": "7.8.2", "shell-quote": "1.9.0", "supports-color": "8.1.1", "tree-kill": "1.2.2", "yargs": "17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } }, "sha512-TZ0CEhyzvFjgtAvHTusDMgj7wNdihCh7LLLrzdUOXIhdlnL2JBBGA9eJxR24rtqgmdjh3OA3hrN1rCHj6HM8qA=="], + + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + + "cross-spawn": ["cross-spawn@6.0.6", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="], + + "data-uri-to-buffer": ["data-uri-to-buffer@6.0.2", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], + + "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], + + "degenerator": ["degenerator@5.0.1", "", { "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", "esprima": "^4.0.1" } }, "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ=="], + + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "diff": ["diff@9.0.0", "", {}, "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw=="], + + "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], + + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-module-lexer": ["es-module-lexer@2.3.2", "", {}, "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw=="], + + "esbuild": ["esbuild@0.28.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.2", "@esbuild/android-arm": "0.28.2", "@esbuild/android-arm64": "0.28.2", "@esbuild/android-x64": "0.28.2", "@esbuild/darwin-arm64": "0.28.2", "@esbuild/darwin-x64": "0.28.2", "@esbuild/freebsd-arm64": "0.28.2", "@esbuild/freebsd-x64": "0.28.2", "@esbuild/linux-arm": "0.28.2", "@esbuild/linux-arm64": "0.28.2", "@esbuild/linux-ia32": "0.28.2", "@esbuild/linux-loong64": "0.28.2", "@esbuild/linux-mips64el": "0.28.2", "@esbuild/linux-ppc64": "0.28.2", "@esbuild/linux-riscv64": "0.28.2", "@esbuild/linux-s390x": "0.28.2", "@esbuild/linux-x64": "0.28.2", "@esbuild/netbsd-arm64": "0.28.2", "@esbuild/netbsd-x64": "0.28.2", "@esbuild/openbsd-arm64": "0.28.2", "@esbuild/openbsd-x64": "0.28.2", "@esbuild/openharmony-arm64": "0.28.2", "@esbuild/sunos-x64": "0.28.2", "@esbuild/win32-arm64": "0.28.2", "@esbuild/win32-ia32": "0.28.2", "@esbuild/win32-x64": "0.28.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escodegen": ["escodegen@2.1.0", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w=="], + + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "execa": ["execa@1.0.0", "", { "dependencies": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA=="], + + "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="], + + "expect-type": ["expect-type@1.4.0", "", {}, "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA=="], + + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], + + "extract-zip": ["extract-zip@2.0.1", "", { "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "optionalDependencies": { "@types/yauzl": "^2.9.1" }, "bin": { "extract-zip": "cli.js" } }, "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + + "fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], + + "file-type": ["file-type@21.3.4", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], + + "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "gaxios": ["gaxios@7.3.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ=="], + + "gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="], + + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="], + + "get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], + + "get-uri": ["get-uri@6.0.5", "", { "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", "debug": "^4.3.4" } }, "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg=="], + + "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="], + + "glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "google-auth-library": ["google-auth-library@10.9.1", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw=="], + + "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "grok-mermaid": ["grok-mermaid@0.2.3", "", {}, "sha512-/4KopAbsjvuRP9MdPtlDjOHUmUVEohOX73JNcsWpzAtFxh+bq5+Dhb6gzvRieLDwIPQIR3/vy8V1NNTuz4Zsmg=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], + + "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], + + "hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="], + + "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], + + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + + "husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="], + + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "ignore": ["ignore@7.0.6", "", {}, "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], + + "interpret": ["interpret@1.4.0", "", {}, "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA=="], + + "ip-address": ["ip-address@10.5.0", "", {}, "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g=="], + + "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="], + + "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], + + "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], + + "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], + + "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], + + "koffi": ["koffi@2.16.3", "", {}, "sha512-E9y1AsgYGlaxMhcZzHr8y96QF2U5XzA12GGVAfbWqIubTwPNMXQarfBzePNXHe0xtIEtNd6ifAv3GAKYGUeBAQ=="], + + "lightningcss": ["lightningcss@1.33.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.33.0", "lightningcss-darwin-arm64": "1.33.0", "lightningcss-darwin-x64": "1.33.0", "lightningcss-freebsd-x64": "1.33.0", "lightningcss-linux-arm-gnueabihf": "1.33.0", "lightningcss-linux-arm64-gnu": "1.33.0", "lightningcss-linux-arm64-musl": "1.33.0", "lightningcss-linux-x64-gnu": "1.33.0", "lightningcss-linux-x64-musl": "1.33.0", "lightningcss-win32-arm64-msvc": "1.33.0", "lightningcss-win32-x64-msvc": "1.33.0" } }, "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA=="], + + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.33.0", "", { "os": "android", "cpu": "arm64" }, "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.33.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.33.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.33.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.33.0", "", { "os": "linux", "cpu": "arm" }, "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.33.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.33.0", "", { "os": "win32", "cpu": "x64" }, "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA=="], + + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + + "lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], + + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "marked": ["marked@18.0.11", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-HnslJfsZkRPBDJRHvVtAaWlZHEpSu7u8LgQuJCELjRKuWR+hpq4A7sLq3p8HaI9ypVoXDXxV34CsQJEe1+J5Aw=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + + "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], + + "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], + + "minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], + + "mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], + + "nanoid": ["nanoid@3.3.18", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w=="], + + "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], + + "netmask": ["netmask@2.1.1", "", {}, "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA=="], + + "nice-try": ["nice-try@1.0.5", "", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="], + + "node-abi": ["node-abi@3.95.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-T9iGctuocf0qIWFFOTxPzjT5q0SILqaBYXt272tlBHvTKC5+3JnkMirLxNJNkXHtFyBjU2Jx+NL4Zipr0B/c6Q=="], + + "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], + + "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], + + "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], + + "node-forge": ["node-forge@1.4.0", "", {}, "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ=="], + + "npm-run-path": ["npm-run-path@2.0.2", "", { "dependencies": { "path-key": "^2.0.0" } }, "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "obug": ["obug@2.1.4", "", {}, "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA=="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "openai": ["openai@6.47.0", "", { "peerDependencies": { "@aws-sdk/credential-provider-node": ">=3.972.0 <4", "@smithy/hash-node": ">=4.3.0 <5", "@smithy/signature-v4": ">=5.4.0 <6", "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["@aws-sdk/credential-provider-node", "@smithy/hash-node", "@smithy/signature-v4", "ws", "zod"] }, "sha512-xYr+R9woSzWxVxeiqkkNbHhv89tZDEI6eBMbrdPnv3poh+mijHvbhS35a+3o6xHa411/ns8j5ENY3So9DCXWYw=="], + + "p-finally": ["p-finally@1.0.0", "", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="], + + "p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="], + + "pac-proxy-agent": ["pac-proxy-agent@7.2.0", "", { "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.1.2", "debug": "^4.3.4", "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.6", "pac-resolver": "^7.0.1", "socks-proxy-agent": "^8.0.5" } }, "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA=="], + + "pac-resolver": ["pac-resolver@7.0.1", "", { "dependencies": { "degenerator": "^5.0.0", "netmask": "^2.0.2" } }, "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg=="], + + "parse5": ["parse5@5.1.1", "", {}, "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug=="], + + "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@6.0.1", "", { "dependencies": { "parse5": "^6.0.1" } }, "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA=="], + + "partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="], + + "path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="], + + "pi-extension-custom-provider-anthropic": ["pi-extension-custom-provider-anthropic@workspace:packages/coding-agent/examples/extensions/custom-provider-anthropic"], + + "pi-extension-custom-provider-gitlab-duo": ["pi-extension-custom-provider-gitlab-duo@workspace:packages/coding-agent/examples/extensions/custom-provider-gitlab-duo"], + + "pi-extension-sandbox": ["pi-extension-sandbox@workspace:packages/coding-agent/examples/extensions/sandbox"], + + "pi-extension-with-deps": ["pi-extension-with-deps@workspace:packages/coding-agent/examples/extensions/with-deps"], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="], + + "postcss": ["postcss@8.5.26", "", { "dependencies": { "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ=="], + + "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="], + + "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], + + "protobufjs": ["protobufjs@7.6.5", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw=="], + + "proxy-agent": ["proxy-agent@6.5.0", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "http-proxy-agent": "^7.0.1", "https-proxy-agent": "^7.0.6", "lru-cache": "^7.14.1", "pac-proxy-agent": "^7.1.0", "proxy-from-env": "^1.1.0", "socks-proxy-agent": "^8.0.5" } }, "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A=="], + + "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + + "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], + + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "rechoir": ["rechoir@0.6.2", "", { "dependencies": { "resolve": "^1.1.6" } }, "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw=="], + + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + + "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], + + "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "rolldown": ["rolldown@1.2.5", "", { "dependencies": { "@oxc-project/types": "=0.146.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm-eabi": "1.2.5", "@rolldown/binding-android-arm64": "1.2.5", "@rolldown/binding-darwin-arm64": "1.2.5", "@rolldown/binding-darwin-x64": "1.2.5", "@rolldown/binding-freebsd-x64": "1.2.5", "@rolldown/binding-linux-arm-gnueabihf": "1.2.5", "@rolldown/binding-linux-arm64-gnu": "1.2.5", "@rolldown/binding-linux-arm64-musl": "1.2.5", "@rolldown/binding-linux-ppc64-gnu": "1.2.5", "@rolldown/binding-linux-s390x-gnu": "1.2.5", "@rolldown/binding-linux-x64-gnu": "1.2.5", "@rolldown/binding-linux-x64-musl": "1.2.5", "@rolldown/binding-openharmony-arm64": "1.2.5", "@rolldown/binding-win32-arm64-msvc": "1.2.5", "@rolldown/binding-win32-x64-msvc": "1.2.5" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-VD2IE5PUG4Oj8zz2VGykiYd5wbnjdIiSsNQb8Qu5B+noEp+A78mu2iVvpp27g8es14Tk9rofNs5Tku9iQCS4fA=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + + "shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="], + + "shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], + + "shell-quote": ["shell-quote@1.10.0", "", {}, "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA=="], + + "shelljs": ["shelljs@0.9.2", "", { "dependencies": { "execa": "^1.0.0", "fast-glob": "^3.3.2", "interpret": "^1.0.0", "rechoir": "^0.6.2" }, "bin": { "shjs": "bin/shjs" } }, "sha512-S3I64fEiKgTZzKCC46zT/Ib9meqofLrQVbpSswtjFfAVDW+AZ54WTnAM/3/yENoxz/V1Cy6u3kiiEbQ4DNphvw=="], + + "shx": ["shx@0.4.0", "", { "dependencies": { "minimist": "^1.2.8", "shelljs": "^0.9.2" }, "bin": { "shx": "lib/cli.js" } }, "sha512-Z0KixSIlGPpijKgcH6oCMCbltPImvaKy0sGH8AkLRXw1KyzpKtaCTizP2xen+hNDqVF4xxgvA0KXSb9o4Q6hnA=="], + + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], + + "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="], + + "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="], + + "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="], + + "socks": ["socks@2.8.9", "", { "dependencies": { "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" } }, "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw=="], + + "socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="], + + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], + + "std-env": ["std-env@4.2.0", "", {}, "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw=="], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + + "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "strip-eof": ["strip-eof@1.0.0", "", {}, "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q=="], + + "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], + + "strtok3": ["strtok3@10.3.5", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA=="], + + "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "tar-fs": ["tar-fs@2.1.5", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw=="], + + "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], + + "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], + + "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], + + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], + + "tinyexec": ["tinyexec@1.3.0", "", {}, "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ=="], + + "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], + + "tinyrainbow": ["tinyrainbow@3.1.1", "", {}, "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "token-types": ["token-types@6.1.2", "", { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww=="], + + "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + + "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tsx": ["tsx@4.23.12", "", { "dependencies": { "esbuild": "~0.28.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q=="], + + "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], + + "typebox": ["typebox@1.3.18", "", {}, "sha512-/wYPoDqxWZSxV/XD8Eskzr3YluXC9CaWJOuUYMkj+lLVLkyeEIQKzHvMuS/IRc3OLTIBC32LAtHgXo/WFEOMHQ=="], + + "typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="], + + "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], + + "undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="], + + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "uuid": ["uuid@14.0.2", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ=="], + + "vite": ["vite@8.2.2", "", { "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.5", "postcss": "^8.5.26", "rolldown": "~1.2.4", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.4.0 || ^0.5.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q=="], + + "vitest": ["vitest@4.1.11", "", { "dependencies": { "@vitest/expect": "4.1.11", "@vitest/mocker": "4.1.11", "@vitest/pretty-format": "4.1.11", "@vitest/runner": "4.1.11", "@vitest/snapshot": "4.1.11", "@vitest/spy": "4.1.11", "@vitest/utils": "4.1.11", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.11", "@vitest/browser-preview": "4.1.11", "@vitest/browser-webdriverio": "4.1.11", "@vitest/coverage-istanbul": "4.1.11", "@vitest/coverage-v8": "4.1.11", "@vitest/ui": "4.1.11", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "./vitest.mjs" } }, "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw=="], + + "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], + + "which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="], + + "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], + + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "ws": ["ws@8.21.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="], + + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], + + "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="], + + "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + + "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], + + "@aws-sdk/credential-provider-sso/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1116.0", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-ygIivKqh8aHzNkucOCXHyIBgBpLPfrSI0mCqXF+vLBsPTUKqj0VSqAY0GFPe7lQl4HntjOcQ+KSyS7oUV2C54Q=="], + + "@earendil-works/pi-agent-core/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], + + "@earendil-works/pi-ai/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], + + "@earendil-works/pi-coding-agent/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], + + "@mistralai/mistralai/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + + "@types/yauzl/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], + + "cli-highlight/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "cli-highlight/yargs": ["yargs@16.2.2", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w=="], + + "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "concurrently/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "cross-spawn/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + + "execa/get-stream": ["get-stream@4.1.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w=="], + + "hosted-git-info/lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="], + + "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + + "node-fetch/data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], + + "p-retry/@types/retry": ["@types/retry@0.12.0", "", {}, "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="], + + "p-retry/retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], + + "parse5-htmlparser2-tree-adapter/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="], + + "path-scurry/lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="], + + "pi-extension-custom-provider-anthropic/@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.52.0", "", { "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-d4c+fg+xy9e46c8+YnrrgIQR45CZlAi7PwdzIfDXDM6ACxEZli1/fxhURsq30ZpMZy6LvSkr41jGq5aF5TD7rQ=="], + + "protobufjs/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], + + "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@earendil-works/pi-agent-core/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + + "@earendil-works/pi-ai/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + + "@earendil-works/pi-coding-agent/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + + "@types/yauzl/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + + "cli-highlight/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "cli-highlight/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], + + "cli-highlight/yargs/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], + + "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "concurrently/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "protobufjs/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + + "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "cli-highlight/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "cli-highlight/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + } +} diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000000..35daac4864 --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,3 @@ +[install] +linker = "hoisted" +minimumReleaseAge = 604800 diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index b5fb6acd3e..0000000000 --- a/package-lock.json +++ /dev/null @@ -1,5837 +0,0 @@ -{ - "name": "prime-agent", - "version": "0.9.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "prime-agent", - "version": "0.9.1", - "workspaces": [ - "packages/*", - "packages/coding-agent/examples/extensions/with-deps", - "packages/coding-agent/examples/extensions/custom-provider-anthropic", - "packages/coding-agent/examples/extensions/custom-provider-gitlab-duo", - "packages/coding-agent/examples/extensions/sandbox" - ], - "dependencies": { - "@earendil-works/pi-coding-agent": "^0.9.1", - "get-east-asian-width": "^1.6.0" - }, - "devDependencies": { - "@anthropic-ai/sandbox-runtime": "^0.0.55", - "@biomejs/biome": "2.5.5", - "@types/node": "^22.10.5", - "@typescript/native-preview": "7.0.0-dev.20260120.1", - "concurrently": "^9.2.4", - "husky": "^9.1.7", - "jiti": "^2.7.0", - "shx": "^0.4.0", - "tsx": "^4.23.1", - "typescript": "^7.0.2" - }, - "engines": { - "node": ">=22.8.0" - } - }, - "node_modules/@agentclientprotocol/sdk": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-1.3.0.tgz", - "integrity": "sha512-i3h/efaeuMUFAO1HSfo97QZQnnvMd7wWBYtBsdL6UMZg3a78sk3Ffya5Xu7C7tYsXomXoDXJBAzQF2PcFKAhIQ==", - "license": "Apache-2.0", - "peerDependencies": { - "zod": "^3.25.0 || ^4.0.0" - } - }, - "node_modules/@anthropic-ai/sandbox-runtime": { - "version": "0.0.55", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sandbox-runtime/-/sandbox-runtime-0.0.55.tgz", - "integrity": "sha512-XGTLbzitn0y6OCdmqP5aYrBR0HlNi87ue++m9vMPxcNwaQeOj9i3f9CSWmXua8mv+Q8E55k4ZGlzJmpDHzQFBw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@pondwader/socks5-server": "^1.0.10", - "commander": "^12.1.0", - "node-forge": "^1.4.0", - "shell-quote": "^1.8.4", - "zod": "^3.24.1" - }, - "bin": { - "srt": "dist/cli.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@anthropic-ai/sdk": { - "version": "0.91.1", - "license": "MIT", - "dependencies": { - "json-schema-to-ts": "^3.1.1" - }, - "bin": { - "anthropic-ai-sdk": "bin/cli" - }, - "peerDependencies": { - "zod": "^3.25.0 || ^4.0.0" - }, - "peerDependenciesMeta": { - "zod": { - "optional": true - } - } - }, - "node_modules/@aws-sdk/client-bedrock-runtime": { - "version": "3.1095.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1095.0.tgz", - "integrity": "sha512-DWcwoQdQPrQJxnG3hz1sG88EjfzGv3SReRy4mtAO+pZXtLX+trriTa20o+qcTmVzwqS43JXtX26ythOzErev9A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/credential-provider-node": "^3.972.72", - "@aws-sdk/eventstream-handler-node": "^3.972.30", - "@aws-sdk/middleware-eventstream": "^3.972.25", - "@aws-sdk/middleware-websocket": "^3.972.43", - "@aws-sdk/token-providers": "3.1095.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/fetch-http-handler": "^5.6.10", - "@smithy/node-http-handler": "^4.9.10", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/core": { - "version": "3.977.1", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.977.1.tgz", - "integrity": "sha512-KVtQRtc00ES/y+Sc3vYXeP6pCIcNlBJCZOwvqSy8ZpVGmbM5+IG+AfhuTKQ2oXmIVqZJewaGMMpzPkywC6xg0w==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.974.2", - "@aws-sdk/xml-builder": "^3.972.37", - "@aws/lambda-invoke-store": "^0.3.0", - "@smithy/core": "^3.29.8", - "@smithy/signature-v4": "^5.6.9", - "@smithy/types": "^4.16.1", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.61", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.61.tgz", - "integrity": "sha512-qihs2ekMb89Nxd2JenCgVFhjbkb3EIo7HEBCBzyZACKVJdrLUZBLOmAE3xr0Sayml8n/jZSzwO/IufIiIzO7PQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.63", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.63.tgz", - "integrity": "sha512-yfozsS8wkWZEi/n6IsrodcFKBWZ0iNAezhJbTReMNc0z1Px17qdeAeuL1/wziCAmCZyXiW7QzP75ggJkBQv8jQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/fetch-http-handler": "^5.6.10", - "@smithy/node-http-handler": "^4.9.10", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.973.6", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.6.tgz", - "integrity": "sha512-jGLTW1bj148GL/6/IMlfY2fMYS9FtHOG+NahkFD4y0qkzYudNUahelxryY68/HGMslYuHClk1XaS/3b3eJzEkg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/credential-provider-env": "^3.972.61", - "@aws-sdk/credential-provider-http": "^3.972.63", - "@aws-sdk/credential-provider-login": "^3.972.68", - "@aws-sdk/credential-provider-process": "^3.972.61", - "@aws-sdk/credential-provider-sso": "^3.973.5", - "@aws-sdk/credential-provider-web-identity": "^3.972.67", - "@aws-sdk/nested-clients": "^3.997.35", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/credential-provider-imds": "^4.4.13", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.68", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.68.tgz", - "integrity": "sha512-w6tNci6g7RqFpLhj1f5xseBvaNojb4Pkgp5Jp5apl9hrJtaf2AA+rX9+qlhlWUK6kcyAFYPA7emO+55zj+S98Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/nested-clients": "^3.997.35", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.72", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.72.tgz", - "integrity": "sha512-blQ7F5QGzylnzeh5549zQLoCAiMHkXFLjFovEMaVy4b2X8JhUu+u9NXro1hyK95YHdVFNmBHKs2hIHtZchxKlQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.61", - "@aws-sdk/credential-provider-http": "^3.972.63", - "@aws-sdk/credential-provider-ini": "^3.973.6", - "@aws-sdk/credential-provider-process": "^3.972.61", - "@aws-sdk/credential-provider-sso": "^3.973.5", - "@aws-sdk/credential-provider-web-identity": "^3.972.67", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/credential-provider-imds": "^4.4.13", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.61", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.61.tgz", - "integrity": "sha512-xzRuj+fUVO4nkafKQJVKAF97kGpeQbfjuwmRrtGZNf42/1dkmcz6o7dswBy7alY0htQn5sCL1GWQYEykviWZkA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.973.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.5.tgz", - "integrity": "sha512-fZRjjWhLFelsDoOYjqShQTrIGYC3Pf9Mx9Czf+1ikfQDgktxjze33dVo1q1/ZQ+T0qbtejVoHNHrfD5aJVpv/w==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/nested-clients": "^3.997.35", - "@aws-sdk/token-providers": "3.1095.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.67", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.67.tgz", - "integrity": "sha512-FTNZ05gkPBA6CKbU3N4zPgybV+stdazwMOya75CmGdcJL7p8Fw/BdHP8WVxJd0mvzyPK2cg/C3gli58Ir4HgCw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/nested-clients": "^3.997.35", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/eventstream-handler-node": { - "version": "3.972.30", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.30.tgz", - "integrity": "sha512-hJboPgIpq5+ADc++/B9TBqn65CXV21cZLGB8V5RBQbxkZ/rQ6qMfcxTnW/SvQlasX4jhaSG8B1wsVjhQyDrsnQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-eventstream": { - "version": "3.972.25", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.25.tgz", - "integrity": "sha512-9SFbPzJDHHR5k6Q6KvXVas/veUm/TzNcNTFM2UhdXHZHpyIvI2lS+s4cxljw1BihGpVhsAkQDo/2nW7dHxpf4Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/middleware-websocket": { - "version": "3.972.43", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.43.tgz", - "integrity": "sha512-n29++15Vma64Kd0enp9Bo8a6LTm8TvUoMbJEwqXtIksv0oEs+SUCRMm3gozDfPD1Ly0k/sSBughxarlLlRF6Xw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/fetch-http-handler": "^5.6.10", - "@smithy/signature-v4": "^5.6.9", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients": { - "version": "3.997.35", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.35.tgz", - "integrity": "sha512-2MJfseVG/aXvIyOIBlYA/Oaf6qFDdsu4D8RKsEUdOQpVuLaor0BdxIBBtJLBNQQEe6Ku3YMvLljwb1MwVUpzRw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/signature-v4-multi-region": "^3.996.42", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/fetch-http-handler": "^5.6.10", - "@smithy/node-http-handler": "^4.9.10", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.996.42", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.42.tgz", - "integrity": "sha512-DBV4naZP6HYBlAvPpoQzOP12Wvfou/5rN8yJPXjBTBylU5qwCbh/tXr2MddHoIjgoRkEl/eS+IljiUqvmwey1Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.974.2", - "@smithy/signature-v4": "^5.6.9", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.1095.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1095.0.tgz", - "integrity": "sha512-65SudS6y4nzaYHybtqcpm3sHe5jLhdMn68HRKS1nUx690BtQeaAQOoujQ+dpOjBATIVGVgKKjEP8tR+U06QJQA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.977.0", - "@aws-sdk/nested-clients": "^3.997.35", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.8", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.974.2", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.2.tgz", - "integrity": "sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.37", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.37.tgz", - "integrity": "sha512-zKq4HQum8JwDyEuyfuI4bbiAcU0KxP6qy+9PR/IsR92IyE/DaBAikzAS50tjxip4bqIIANpCcG+Yyj6CVhXupg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws/lambda-invoke-store": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.3.0.tgz", - "integrity": "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.29.2", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@biomejs/biome": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.5.tgz", - "integrity": "sha512-r1S8nFsAG1MY+vJFZALzIvwXAJv6ejDQ0mxP21Tgr9YK3ZFtjrvbBwDdNhx1rUqvccEIeNg20cYCNzl6Cr69pQ==", - "dev": true, - "license": "MIT OR Apache-2.0", - "bin": { - "biome": "bin/biome" - }, - "engines": { - "node": ">=14.21.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/biome" - }, - "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "2.5.5", - "@biomejs/cli-darwin-x64": "2.5.5", - "@biomejs/cli-linux-arm64": "2.5.5", - "@biomejs/cli-linux-arm64-musl": "2.5.5", - "@biomejs/cli-linux-x64": "2.5.5", - "@biomejs/cli-linux-x64-musl": "2.5.5", - "@biomejs/cli-win32-arm64": "2.5.5", - "@biomejs/cli-win32-x64": "2.5.5" - } - }, - "node_modules/@biomejs/cli-darwin-arm64": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.5.tgz", - "integrity": "sha512-kUrAhXVWUrwmAUnV2iXSK7umxKFysTwvqK+Ty6ptUcLY/7T3SnCAjUowE4uvwaEej6nXZ7hu/dTtbokKdsPeag==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-darwin-x64": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.5.tgz", - "integrity": "sha512-DamiYc5bUYZ2uxlfc+RLEPtz1Abb6PO5eTbOkufLpSGwd/7AMQAdxhFYiXmwwkJL8IsT8S7GvdgwDHqaMFAvKw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-linux-arm64": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.5.tgz", - "integrity": "sha512-lRKF/pH/1RiYiBKExi3TCZVAtvzEm77aifrvcNiDFrR9WxeAnDUjDnseb6y2XV85mjitLs6SILGm2XG77cHtSQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.5.tgz", - "integrity": "sha512-U4WMl/sy/E/Q73vf15VspakLRRs2LDFcCeBxJnQfXzssb88zpV6PJPaQ3ezhQ7H6Ht2/8bvuZeHgJWzmoxllZg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-linux-x64": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.5.tgz", - "integrity": "sha512-H/O39nJEw/2Zm/fm7hrmxxoF8kK/aU1uCoPp70ruXVbomaAdLpJJnCmL11Q2JotT8QVHH06So04Oq53lCSwSwQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.5.tgz", - "integrity": "sha512-m7wC7tjX5Lrmo69dc4md8FeKpPU1NTCY1v7xUoQQ2vadWwNnBS0KZOG8471otFPHrTHihQJAjQPgMObpLvDe6A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-win32-arm64": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.5.tgz", - "integrity": "sha512-7BryINPuYypLUAH3o/o5ZdgomJ4zn3EDR0ChZJst7n32S6ZhKbgHXuYydLu+YAnx59ehGFR0z/MG6qnzQi3Yyw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-win32-x64": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.5.tgz", - "integrity": "sha512-bIBFo+n6MIxdNcVFy5CrurbKiZQiUciK3bt8+O9I4wjFZNTfXLpi+giq47522eXqW5NBc9ulx7dR1SlZKi2J5g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@borewit/text-codec": { - "version": "0.2.2", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/@earendil-works/pi-agent-core": { - "resolved": "packages/agent", - "link": true - }, - "node_modules/@earendil-works/pi-ai": { - "resolved": "packages/ai", - "link": true - }, - "node_modules/@earendil-works/pi-coding-agent": { - "resolved": "packages/coding-agent", - "link": true - }, - "node_modules/@earendil-works/pi-tui": { - "resolved": "packages/tui", - "link": true - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@google/genai": { - "version": "1.52.0", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "google-auth-library": "^10.3.0", - "p-retry": "^4.6.2", - "protobufjs": "^7.5.4", - "ws": "^8.18.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@modelcontextprotocol/sdk": "^1.25.2" - }, - "peerDependenciesMeta": { - "@modelcontextprotocol/sdk": { - "optional": true - } - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@mariozechner/clipboard": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard/-/clipboard-0.3.9.tgz", - "integrity": "sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@mariozechner/clipboard-darwin-arm64": "0.3.9", - "@mariozechner/clipboard-darwin-universal": "0.3.9", - "@mariozechner/clipboard-darwin-x64": "0.3.9", - "@mariozechner/clipboard-linux-arm64-gnu": "0.3.9", - "@mariozechner/clipboard-linux-arm64-musl": "0.3.9", - "@mariozechner/clipboard-linux-riscv64-gnu": "0.3.9", - "@mariozechner/clipboard-linux-x64-gnu": "0.3.9", - "@mariozechner/clipboard-linux-x64-musl": "0.3.9", - "@mariozechner/clipboard-win32-arm64-msvc": "0.3.9", - "@mariozechner/clipboard-win32-x64-msvc": "0.3.9" - } - }, - "node_modules/@mariozechner/clipboard-darwin-arm64": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-arm64/-/clipboard-darwin-arm64-0.3.9.tgz", - "integrity": "sha512-BfgV7vCEWZwJwZJw03r6bP5+tf0iI/ANuQYCxi9RNn7FrWB3yzGuMKCrNLRl6V761vXRdL8+OqZ0wd4TqlsNOQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@mariozechner/clipboard-darwin-universal": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-universal/-/clipboard-darwin-universal-0.3.9.tgz", - "integrity": "sha512-BGGR4iA9Z2shAjI65eI5xtyb3LYNlDW9X3gxKxDbqtbnREohsrqznov6zpKoIrsRWpzlYVEdKphS7ksJ0/ndSQ==", - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@mariozechner/clipboard-darwin-x64": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-x64/-/clipboard-darwin-x64-0.3.9.tgz", - "integrity": "sha512-4kURmCbS6nt8uYhtmWpUcJWyPHfmAr5dTpXD1nO3pIfa+TSQ9DbrGOYCKH+aEFW47XhQ4Vp8ZTszie+wfFvDKg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@mariozechner/clipboard-linux-arm64-gnu": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-arm64-gnu/-/clipboard-linux-arm64-gnu-0.3.9.tgz", - "integrity": "sha512-g59OkUGP2DDfCOIKypHeYgv2M55u/cKvXa5dSxFbEJ34XvIQMdcVmpKCkGUro3ZgefXiGVdwguvTMQGpHWzIXw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@mariozechner/clipboard-linux-arm64-musl": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-arm64-musl/-/clipboard-linux-arm64-musl-0.3.9.tgz", - "integrity": "sha512-AGuJdgKsmJdm4Pych7kv3sqe591ERRaAHW3xjLooiFzn8J+PxUyof++7YZrB5Y5tpnTO+K18Og3taj2NpluCRQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@mariozechner/clipboard-linux-riscv64-gnu": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-riscv64-gnu/-/clipboard-linux-riscv64-gnu-0.3.9.tgz", - "integrity": "sha512-DXBEAiuMpk7dhS1a9NzNxVAFi1vaKoPu7rQNgY8LIDLGrK3lnIp3nT10DUum+PKVJoJppIP+NAA8IZe4DMNDPw==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@mariozechner/clipboard-linux-x64-gnu": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-x64-gnu/-/clipboard-linux-x64-gnu-0.3.9.tgz", - "integrity": "sha512-WORrMLd6EpElEME7JRKfSaY34nW1P5LbdgK5YNCS1ncG2LqmITsSMEJ8nh2mpvxb3TxqbOOKgY7k9eMJYlW9Mw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@mariozechner/clipboard-linux-x64-musl": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-x64-musl/-/clipboard-linux-x64-musl-0.3.9.tgz", - "integrity": "sha512-/DHn+1DrfL6oRaPPWXaOKvonFFrni666fxd+zFqiQEfvBH0tsHVWjq9iqBk0oDp0qaPA72lIMy5BptxISBEhZQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@mariozechner/clipboard-win32-arm64-msvc": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-win32-arm64-msvc/-/clipboard-win32-arm64-msvc-0.3.9.tgz", - "integrity": "sha512-O5FHD3ErkMwMhNzAfu3ggy0ug4z7btZuoQgwwxlzPrwV2bxlD6WDpqBY4NCgICAgZdDKdp+loUEKVAVt8aYnhQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@mariozechner/clipboard-win32-x64-msvc": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-win32-x64-msvc/-/clipboard-win32-x64-msvc-0.3.9.tgz", - "integrity": "sha512-ihQC3EufqEY81vhXBgVBtK4prL+wc62zJsSvxrgz7K1hsdt6OObz6v9p3Rn1OG3GJksTTKMJF0u/guMISHPhSA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@mistralai/mistralai": { - "version": "2.2.1", - "license": "Apache-2.0", - "dependencies": { - "ws": "^8.18.0", - "zod": "^3.25.0 || ^4.0.0", - "zod-to-json-schema": "^3.25.0" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.0.tgz", - "integrity": "sha512-kDoONqMa+VnZ4vvvu/ZUurpJ4gkZU57e7g69qpNgWhYcZFPUHZM2CEMKm+cG6ufDVALbjMvfmMjFVqaK7uEMnA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.3" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=23.5.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^2.0.0-alpha.3", - "@emnapi/runtime": "^2.0.0-alpha.3" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@oxc-project/types": { - "version": "0.139.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", - "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, - "node_modules/@pondwader/socks5-server": { - "version": "1.0.10", - "license": "MIT" - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.5", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", - "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", - "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.1", - "license": "BSD-3-Clause" - }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", - "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", - "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", - "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", - "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", - "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", - "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", - "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", - "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", - "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", - "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", - "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", - "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", - "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.11.1", - "@emnapi/runtime": "1.11.1", - "@napi-rs/wasm-runtime": "^1.1.6" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", - "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", - "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", - "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", - "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", - "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", - "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@silvia-odwyer/photon-node": { - "version": "0.3.4", - "license": "Apache-2.0" - }, - "node_modules/@smithy/core": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.30.0.tgz", - "integrity": "sha512-dl2yRglDxfzH9uJ4fSo4zTaAHa0zH7+V7BZMRWy8hEYIKT1BiqMUK/CN6T3ADQ3kbA5N1tmUulroJ2UtONS7Kw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.4.14", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.4.14.tgz", - "integrity": "sha512-QgbuahIb2qxQeZQvNK0sw3aF3JH5zwH8j2lLp5DUasVXexGGMWULAR+7z0omPXFolCP/m5wN9M5lm9EGdSviTQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.30.0", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.6.11", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.6.11.tgz", - "integrity": "sha512-o0Zkj1nKqJAoq+a+BrkhU39tRftMNjLwpc/z06Frfl43wpbHrJMaSAVZE4vTqlxtVkNaGaT0bIDxOp7tkFTuQQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.30.0", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "4.9.11", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.9.11.tgz", - "integrity": "sha512-slbzbz8taEOzoXv/9y34YNBoE+ZHmddLykCgjDAjvMAsu2nM5s2Gzwa5OGF721tD8s+CKeFUBds5lSj9lcbuDg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.30.0", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "5.6.10", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.6.10.tgz", - "integrity": "sha512-EXhWePm3SXJAX38npIy4TXL2Aex/OVgCClTjelN2QHw/U+8CQUH8C7AaxsVzQcYieYPseywn48s89DmvuGjiAg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.30.0", - "@smithy/types": "^4.16.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.16.1.tgz", - "integrity": "sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tokenizer/inflate": { - "version": "0.4.1", - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "token-types": "^6.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "license": "MIT" - }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "license": "MIT" - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", - "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/chai": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" - } - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/diff": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@types/diff/-/diff-8.0.0.tgz", - "integrity": "sha512-o7jqJM04gfaYrdCecCVMbZhNdG6T1MHg/oQoRFdERLV+4d+V7FijhiEAbFu0Usww84Yijk9yH58U4Jk4HbtzZw==", - "deprecated": "This is a stub types definition. diff provides its own type definitions, so you do not need this installed.", - "dev": true, - "license": "MIT", - "dependencies": { - "diff": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/hosted-git-info": { - "version": "3.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRMsfuQbnRq1Ef+C+RKaENOxXX87Ygl38W1vDfPHRku02TgQr+Qd8iivLtAMcR0KF5/29xlnFihkTlbqFrGOVQ==", - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "22.20.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", - "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/proper-lockfile": { - "version": "4.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/retry": "*" - } - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "license": "MIT" - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript/native-preview": { - "version": "7.0.0-dev.20260120.1", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsgo": "bin/tsgo.js" - }, - "optionalDependencies": { - "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260120.1", - "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260120.1", - "@typescript/native-preview-linux-arm": "7.0.0-dev.20260120.1", - "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260120.1", - "@typescript/native-preview-linux-x64": "7.0.0-dev.20260120.1", - "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260120.1", - "@typescript/native-preview-win32-x64": "7.0.0-dev.20260120.1" - } - }, - "node_modules/@typescript/native-preview-darwin-arm64": { - "version": "7.0.0-dev.20260120.1", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@typescript/native-preview-darwin-x64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-x64/-/native-preview-darwin-x64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-cuC1+wLbUP+Ip2UT94G134fqRdp5w3b3dhcCO6/FQ4yXxvRNyv/WK+upHBUFDaeSOeHgDTyO9/QFYUWwC4If1A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@typescript/native-preview-linux-arm": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm/-/native-preview-linux-arm-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-vN6OYVySol/kQZjJGmAzd6L30SyVlCgmCXS8WjUYtE5clN0YrzQHop16RK29fYZHMxpkOniVBtRPxUYQANZBlQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@typescript/native-preview-linux-arm64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm64/-/native-preview-linux-arm64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-zZGvEGY7wcHYefMZ87KNmvjN3NLIhsCMHEpHZiGCS3khKf+8z6ZsanrzCjOTodvL01VPyBzHxV1EtkSxAcLiQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@typescript/native-preview-linux-x64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-x64/-/native-preview-linux-x64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-JBfNhWd/asd5MDeS3VgRvE24pGKBkmvLub6tsux6ypr+Yhy+o0WaAEzVpmlRYZUqss2ai5tvOu4dzPBXzZAtFw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@typescript/native-preview-win32-arm64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-arm64/-/native-preview-win32-arm64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-tTndRtYCq2xwgE0VkTi9ACNiJaV43+PqvBqCxk8ceYi3X36Ve+CCnwlZfZJ4k9NxZthtrAwF/kUmpC9iIYbq1w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@typescript/native-preview-win32-x64": { - "version": "7.0.0-dev.20260120.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-x64/-/native-preview-win32-x64-7.0.0-dev.20260120.1.tgz", - "integrity": "sha512-oZia7hFL6k9pVepfonuPI86Jmyz6WlJKR57tWCDwRNmpA7odxuTq1PbvcYgy1z4+wHF1nnKKJY0PMAiq6ac18w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@typescript/typescript-aix-ppc64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", - "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-darwin-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", - "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-darwin-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", - "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-freebsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", - "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-freebsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", - "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-arm": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", - "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", - "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-loong64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", - "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-mips64el": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", - "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-ppc64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", - "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-riscv64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", - "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-s390x": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", - "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-linux-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", - "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-netbsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", - "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-netbsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", - "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-openbsd-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", - "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-openbsd-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", - "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-sunos-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", - "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-win32-arm64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", - "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@typescript/typescript-win32-x64": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", - "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@vitest/expect": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", - "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.1.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.10", - "@vitest/utils": "4.1.10", - "chai": "^6.2.2", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", - "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "4.1.10", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/pretty-format": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", - "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", - "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "4.1.10", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", - "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.1.10", - "@vitest/utils": "4.1.10", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", - "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", - "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.1.10", - "convert-source-map": "^2.0.0", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@xterm/headless": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@xterm/headless/-/headless-6.0.0.tgz", - "integrity": "sha512-5Yj1QINYCyzrZtf8OFIHi47iQtI+0qYFPHmouEfG8dHNxbZ9Tb9YGSuLcsEwj9Z+OL75GJqPyJbyoFer80a2Hw==", - "dev": true, - "license": "MIT", - "workspaces": [ - "addons/*" - ] - }, - "node_modules/@xterm/xterm": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-6.0.0.tgz", - "integrity": "sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg==", - "dev": true, - "license": "MIT", - "workspaces": [ - "addons/*" - ] - }, - "node_modules/agent-base": { - "version": "7.1.4", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "license": "MIT" - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/ast-types": { - "version": "0.13.4", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/balanced-match": { - "version": "4.0.4", - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/basic-ftp": { - "version": "5.3.1", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/bignumber.js": { - "version": "9.3.1", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bowser": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", - "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "license": "BSD-3-Clause" - }, - "node_modules/canvas": { - "version": "3.2.3", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^7.0.0", - "prebuild-install": "^7.1.3" - }, - "engines": { - "node": "^18.12.0 || >= 20.9.0" - } - }, - "node_modules/chai": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/chalk": { - "version": "5.6.2", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "dev": true, - "license": "ISC" - }, - "node_modules/cli-highlight": { - "version": "2.1.11", - "license": "ISC", - "dependencies": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "bin": { - "highlight": "bin/highlight" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, - "node_modules/cli-highlight/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cli-highlight/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/commander": { - "version": "12.1.0", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/concurrently": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.4.tgz", - "integrity": "sha512-TZ0CEhyzvFjgtAvHTusDMgj7wNdihCh7LLLrzdUOXIhdlnL2JBBGA9eJxR24rtqgmdjh3OA3hrN1rCHj6HM8qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "4.1.2", - "rxjs": "7.8.2", - "shell-quote": "1.9.0", - "supports-color": "8.1.1", - "tree-kill": "1.2.2", - "yargs": "17.7.2" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" - } - }, - "node_modules/concurrently/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/concurrently/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/concurrently/node_modules/cliui": { - "version": "8.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/concurrently/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/concurrently/node_modules/yargs": { - "version": "17.7.2", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/concurrently/node_modules/yargs-parser": { - "version": "21.1.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "6.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/cross-spawn/node_modules/semver": { - "version": "5.7.2", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/degenerator": { - "version": "5.0.1", - "license": "MIT", - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", - "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "license": "MIT" - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", - "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/execa/node_modules/get-stream": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "dev": true, - "license": "(MIT OR WTFPL)", - "engines": { - "node": ">=6" - } - }, - "node_modules/expect-type": { - "version": "1.3.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "license": "MIT" - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.20.1", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/file-type": { - "version": "21.3.4", - "license": "MIT", - "dependencies": { - "@tokenizer/inflate": "^0.4.1", - "strtok3": "^10.3.4", - "token-types": "^6.1.1", - "uint8array-extras": "^1.4.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gaxios": { - "version": "7.1.4", - "license": "Apache-2.0", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "node-fetch": "^3.3.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/gcp-metadata": { - "version": "8.1.2", - "license": "Apache-2.0", - "dependencies": { - "gaxios": "^7.0.0", - "google-logging-utils": "^1.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", - "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-uri": { - "version": "6.0.5", - "license": "MIT", - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/get-uri/node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/github-from-package": { - "version": "0.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/glob": { - "version": "13.0.6", - "license": "BlueOak-1.0.0", - "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/google-auth-library": { - "version": "10.6.2", - "license": "Apache-2.0", - "dependencies": { - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "gaxios": "^7.1.4", - "gcp-metadata": "8.1.2", - "google-logging-utils": "1.1.3", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/google-logging-utils": { - "version": "1.1.3", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "license": "ISC" - }, - "node_modules/grok-mermaid": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/grok-mermaid/-/grok-mermaid-0.2.3.tgz", - "integrity": "sha512-/4KopAbsjvuRP9MdPtlDjOHUmUVEohOX73JNcsWpzAtFxh+bq5+Dhb6gzvRieLDwIPQIR3/vy8V1NNTuz4Zsmg==", - "license": "Apache-2.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hasown": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "license": "BSD-3-Clause", - "engines": { - "node": "*" - } - }, - "node_modules/hosted-git-info": { - "version": "9.0.3", - "license": "ISC", - "dependencies": { - "lru-cache": "^11.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/husky": { - "version": "9.1.7", - "dev": true, - "license": "MIT", - "bin": { - "husky": "bin.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "7.0.5", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "dev": true, - "license": "ISC" - }, - "node_modules/ini": { - "version": "1.3.8", - "dev": true, - "license": "ISC" - }, - "node_modules/interpret": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ip-address": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz", - "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/is-core-module": { - "version": "2.16.2", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/jiti": { - "version": "2.7.0", - "license": "MIT", - "peer": true, - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/json-bigint": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, - "node_modules/json-schema-to-ts": { - "version": "3.1.1", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.3", - "ts-algebra": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/jwa": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "4.0.1", - "license": "MIT", - "dependencies": { - "jwa": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/koffi": { - "version": "2.16.2", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "funding": { - "url": "https://liberapay.com/Koromix" - } - }, - "node_modules/lightningcss": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", - "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.33.0", - "lightningcss-darwin-arm64": "1.33.0", - "lightningcss-darwin-x64": "1.33.0", - "lightningcss-freebsd-x64": "1.33.0", - "lightningcss-linux-arm-gnueabihf": "1.33.0", - "lightningcss-linux-arm64-gnu": "1.33.0", - "lightningcss-linux-arm64-musl": "1.33.0", - "lightningcss-linux-x64-gnu": "1.33.0", - "lightningcss-linux-x64-musl": "1.33.0", - "lightningcss-win32-arm64-msvc": "1.33.0", - "lightningcss-win32-x64-msvc": "1.33.0" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", - "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", - "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", - "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", - "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", - "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", - "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", - "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", - "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", - "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", - "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", - "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/long": { - "version": "5.3.2", - "license": "Apache-2.0" - }, - "node_modules/lru-cache": { - "version": "11.5.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", - "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/marked": { - "version": "18.0.7", - "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.7.tgz", - "integrity": "sha512-iDVQ5ldaiKXn6b2JroX5kgRfmwgqolW7NpaEzTl1k/2Zh1njIEN9yniyLV/mOvWwtsE8OGgkjsCYvijuPk1dtA==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.2", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/mimic-response": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "10.2.5", - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.3", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "dev": true, - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.3", - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.17", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz", - "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-build-utils": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/netmask": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/nice-try": { - "version": "1.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/node-abi": { - "version": "3.92.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "7.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.2", - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/node-forge": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", - "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", - "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/obug": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.2.tgz", - "integrity": "sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==", - "dev": true, - "funding": [ - "https://github.com/sponsors/sxzz", - "https://opencollective.com/debug" - ], - "license": "MIT", - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/openai": { - "version": "6.47.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-6.47.0.tgz", - "integrity": "sha512-xYr+R9woSzWxVxeiqkkNbHhv89tZDEI6eBMbrdPnv3poh+mijHvbhS35a+3o6xHa411/ns8j5ENY3So9DCXWYw==", - "license": "Apache-2.0", - "peerDependencies": { - "@aws-sdk/credential-provider-node": ">=3.972.0 <4", - "@smithy/hash-node": ">=4.3.0 <5", - "@smithy/signature-v4": ">=5.4.0 <6", - "ws": "^8.18.0", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-provider-node": { - "optional": true - }, - "@smithy/hash-node": { - "optional": true - }, - "@smithy/signature-v4": { - "optional": true - }, - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pac-proxy-agent": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.6", - "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.5" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "license": "MIT", - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/parse5": { - "version": "5.1.1", - "license": "MIT" - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { - "version": "6.0.1", - "license": "MIT" - }, - "node_modules/partial-json": { - "version": "0.1.7", - "license": "MIT" - }, - "node_modules/path-key": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "2.0.2", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/pend": { - "version": "1.2.0", - "license": "MIT" - }, - "node_modules/pi-extension-custom-provider-anthropic": { - "resolved": "packages/coding-agent/examples/extensions/custom-provider-anthropic", - "link": true - }, - "node_modules/pi-extension-custom-provider-gitlab-duo": { - "resolved": "packages/coding-agent/examples/extensions/custom-provider-gitlab-duo", - "link": true - }, - "node_modules/pi-extension-sandbox": { - "resolved": "packages/coding-agent/examples/extensions/sandbox", - "link": true - }, - "node_modules/pi-extension-with-deps": { - "resolved": "packages/coding-agent/examples/extensions/with-deps", - "link": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.25", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", - "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.16", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prebuild-install": { - "version": "7.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^2.0.0", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/proper-lockfile": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "retry": "^0.12.0", - "signal-exit": "^3.0.2" - } - }, - "node_modules/proper-lockfile/node_modules/retry": { - "version": "0.12.0", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/protobufjs": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz", - "integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.5", - "@protobufjs/eventemitter": "^1.1.1", - "@protobufjs/fetch": "^1.1.1", - "@protobufjs/float": "^1.0.2", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.1", - "@types/node": ">=13.7.0", - "long": "^5.3.2" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/proxy-agent": { - "version": "6.5.0", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.6", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.1.0", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.5" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/pump": { - "version": "3.0.4", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/rc": { - "version": "1.2.8", - "dev": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.12", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rolldown": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", - "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@oxc-project/types": "=0.139.0", - "@rolldown/pluginutils": "^1.0.0" - }, - "bin": { - "rolldown": "bin/cli.mjs" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.1.5", - "@rolldown/binding-darwin-arm64": "1.1.5", - "@rolldown/binding-darwin-x64": "1.1.5", - "@rolldown/binding-freebsd-x64": "1.1.5", - "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", - "@rolldown/binding-linux-arm64-gnu": "1.1.5", - "@rolldown/binding-linux-arm64-musl": "1.1.5", - "@rolldown/binding-linux-ppc64-gnu": "1.1.5", - "@rolldown/binding-linux-s390x-gnu": "1.1.5", - "@rolldown/binding-linux-x64-gnu": "1.1.5", - "@rolldown/binding-linux-x64-musl": "1.1.5", - "@rolldown/binding-openharmony-arm64": "1.1.5", - "@rolldown/binding-wasm32-wasi": "1.1.5", - "@rolldown/binding-win32-arm64-msvc": "1.1.5", - "@rolldown/binding-win32-x64-msvc": "1.1.5" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.2", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shell-quote": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", - "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/shelljs": { - "version": "0.9.2", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "execa": "^1.0.0", - "fast-glob": "^3.3.2", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/shx": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.8", - "shelljs": "^0.9.2" - }, - "bin": { - "shx": "lib/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "license": "ISC" - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/simple-get": { - "version": "4.0.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.8", - "license": "MIT", - "dependencies": { - "ip-address": "^10.1.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.5", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/std-env": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", - "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strtok3": { - "version": "10.3.5", - "license": "MIT", - "dependencies": { - "@tokenizer/token": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tar-fs": { - "version": "2.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/thenify": { - "version": "3.3.1", - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tinybench": { - "version": "2.9.0", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", - "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", - "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/tinyrainbow": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", - "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/token-types": { - "version": "6.1.2", - "license": "MIT", - "dependencies": { - "@borewit/text-codec": "^0.2.1", - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/ts-algebra": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/tslib": { - "version": "2.8.1", - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.1.tgz", - "integrity": "sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "esbuild": "~0.28.0" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/typebox": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/typebox/-/typebox-1.3.10.tgz", - "integrity": "sha512-L0MT00X96q0P30f1NrGULgaSbmu8hfTjWbLULeVoM+j5u0jR5wyefoDquX2NmRa39f0KiNIBo1wWSaVvHJTZlA==", - "license": "MIT" - }, - "node_modules/typescript": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", - "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc" - }, - "engines": { - "node": ">=16.20.0" - }, - "optionalDependencies": { - "@typescript/typescript-aix-ppc64": "7.0.2", - "@typescript/typescript-darwin-arm64": "7.0.2", - "@typescript/typescript-darwin-x64": "7.0.2", - "@typescript/typescript-freebsd-arm64": "7.0.2", - "@typescript/typescript-freebsd-x64": "7.0.2", - "@typescript/typescript-linux-arm": "7.0.2", - "@typescript/typescript-linux-arm64": "7.0.2", - "@typescript/typescript-linux-loong64": "7.0.2", - "@typescript/typescript-linux-mips64el": "7.0.2", - "@typescript/typescript-linux-ppc64": "7.0.2", - "@typescript/typescript-linux-riscv64": "7.0.2", - "@typescript/typescript-linux-s390x": "7.0.2", - "@typescript/typescript-linux-x64": "7.0.2", - "@typescript/typescript-netbsd-arm64": "7.0.2", - "@typescript/typescript-netbsd-x64": "7.0.2", - "@typescript/typescript-openbsd-arm64": "7.0.2", - "@typescript/typescript-openbsd-x64": "7.0.2", - "@typescript/typescript-sunos-x64": "7.0.2", - "@typescript/typescript-win32-arm64": "7.0.2", - "@typescript/typescript-win32-x64": "7.0.2" - } - }, - "node_modules/uint8array-extras": { - "version": "1.5.0", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/undici": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", - "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "license": "MIT" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/uuid": { - "version": "14.0.0", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist-node/bin/uuid" - } - }, - "node_modules/vite": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz", - "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.5", - "postcss": "^8.5.17", - "rolldown": "~1.1.5", - "tinyglobby": "^0.2.17" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.3.0", - "esbuild": "^0.27.0 || ^0.28.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "@vitejs/devtools": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/vitest": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", - "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "4.1.10", - "@vitest/mocker": "4.1.10", - "@vitest/pretty-format": "4.1.10", - "@vitest/runner": "4.1.10", - "@vitest/snapshot": "4.1.10", - "@vitest/spy": "4.1.10", - "@vitest/utils": "4.1.10", - "es-module-lexer": "^2.0.0", - "expect-type": "^1.3.0", - "magic-string": "^0.30.21", - "obug": "^2.1.1", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^4.0.0-rc.1", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.1.0", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@opentelemetry/api": "^1.9.0", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.10", - "@vitest/browser-preview": "4.1.10", - "@vitest/browser-webdriverio": "4.1.10", - "@vitest/coverage-istanbul": "4.1.10", - "@vitest/coverage-v8": "4.1.10", - "@vitest/ui": "4.1.10", - "happy-dom": "*", - "jsdom": "*", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser-playwright": { - "optional": true - }, - "@vitest/browser-preview": { - "optional": true - }, - "@vitest/browser-webdriverio": { - "optional": true - }, - "@vitest/coverage-istanbul": { - "optional": true - }, - "@vitest/coverage-v8": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - }, - "vite": { - "optional": false - } - } - }, - "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/which": { - "version": "1.3.1", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "license": "ISC" - }, - "node_modules/ws": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", - "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", - "license": "ISC", - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, - "node_modules/yargs": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz", - "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==", - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "peer": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.2", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25.28 || ^4" - } - }, - "packages/agent": { - "name": "@earendil-works/pi-agent-core", - "version": "0.9.1", - "license": "MIT", - "dependencies": { - "@earendil-works/pi-ai": "^0.9.1", - "typebox": "^1.3.9" - }, - "devDependencies": { - "@types/node": "^24.3.0", - "typescript": "^7.0.2", - "vitest": "^4.1.10" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "packages/agent/node_modules/@types/node": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", - "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.18.0" - } - }, - "packages/agent/node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", - "dev": true, - "license": "MIT" - }, - "packages/ai": { - "name": "@earendil-works/pi-ai", - "version": "0.9.1", - "license": "MIT", - "dependencies": { - "@anthropic-ai/sdk": "^0.91.1", - "@aws-sdk/client-bedrock-runtime": "^3.1095.0", - "@google/genai": "^1.40.0", - "@mistralai/mistralai": "^2.2.0", - "chalk": "^5.6.2", - "openai": "6.47.0", - "partial-json": "^0.1.7", - "proxy-agent": "^6.5.0", - "typebox": "^1.3.9", - "undici": "^7.29.0", - "zod-to-json-schema": "^3.24.6" - }, - "bin": { - "pi-ai": "dist/cli.js" - }, - "devDependencies": { - "@types/node": "^24.3.0", - "canvas": "^3.2.0", - "vitest": "^4.1.10" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "packages/ai/node_modules/@types/node": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", - "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.18.0" - } - }, - "packages/ai/node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", - "dev": true, - "license": "MIT" - }, - "packages/coding-agent": { - "name": "@earendil-works/pi-coding-agent", - "version": "0.9.1", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@agentclientprotocol/sdk": "^1.3.0", - "@earendil-works/pi-agent-core": "^0.9.1", - "@earendil-works/pi-ai": "^0.9.1", - "@earendil-works/pi-tui": "^0.9.1", - "@silvia-odwyer/photon-node": "^0.3.4", - "chalk": "^5.5.0", - "cli-highlight": "^2.1.11", - "diff": "^9.0.0", - "extract-zip": "^2.0.1", - "file-type": "^21.1.1", - "glob": "^13.0.1", - "grok-mermaid": "0.2.3", - "hosted-git-info": "^9.0.2", - "ignore": "^7.0.5", - "jiti": "^2.7.0", - "marked": "^18.0.7", - "minimatch": "^10.2.3", - "proper-lockfile": "^4.1.2", - "strip-ansi": "^7.1.0", - "typebox": "^1.3.9", - "undici": "^7.29.0", - "uuid": "^14.0.0", - "yaml": "^2.9.0" - }, - "bin": { - "pi": "dist/bundle/cli.js" - }, - "devDependencies": { - "@types/diff": "^8.0.0", - "@types/hosted-git-info": "^3.0.5", - "@types/ms": "^2.1.0", - "@types/node": "^24.3.0", - "@types/proper-lockfile": "^4.1.4", - "esbuild": "^0.28.1", - "shx": "^0.4.0", - "typescript": "^7.0.2", - "vitest": "^4.1.10" - }, - "engines": { - "node": ">=22.8.0" - }, - "optionalDependencies": { - "@mariozechner/clipboard": "^0.3.9" - } - }, - "packages/coding-agent/examples/extensions/custom-provider-anthropic": { - "name": "pi-extension-custom-provider-anthropic", - "version": "0.1.1", - "dependencies": { - "@anthropic-ai/sdk": "^0.52.0" - } - }, - "packages/coding-agent/examples/extensions/custom-provider-gitlab-duo": { - "name": "pi-extension-custom-provider-gitlab-duo", - "version": "0.1.1" - }, - "packages/coding-agent/examples/extensions/sandbox": { - "name": "pi-extension-sandbox", - "version": "1.5.1", - "dependencies": { - "@anthropic-ai/sandbox-runtime": "^0.0.55" - } - }, - "packages/coding-agent/examples/extensions/sandbox/node_modules/@anthropic-ai/sandbox-runtime": { - "version": "0.0.26", - "license": "Apache-2.0", - "dependencies": { - "@pondwader/socks5-server": "^1.0.10", - "@types/lodash-es": "^4.17.12", - "commander": "^12.1.0", - "lodash-es": "^4.17.21", - "shell-quote": "^1.8.3", - "zod": "^3.24.1" - }, - "bin": { - "srt": "dist/cli.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "packages/coding-agent/examples/extensions/sandbox/node_modules/@types/lodash": { - "version": "4.17.23", - "license": "MIT" - }, - "packages/coding-agent/examples/extensions/sandbox/node_modules/@types/lodash-es": { - "version": "4.17.12", - "license": "MIT", - "dependencies": { - "@types/lodash": "*" - } - }, - "packages/coding-agent/examples/extensions/sandbox/node_modules/lodash-es": { - "version": "4.18.1", - "license": "MIT" - }, - "packages/coding-agent/examples/extensions/with-deps": { - "name": "pi-extension-with-deps", - "version": "0.1.1", - "dependencies": { - "ms": "^2.1.3" - }, - "devDependencies": { - "@types/ms": "^2.1.0" - } - }, - "packages/coding-agent/node_modules/@anthropic-ai/sdk": { - "version": "0.52.0", - "license": "MIT", - "bin": { - "anthropic-ai-sdk": "bin/cli" - } - }, - "packages/coding-agent/node_modules/@types/node": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", - "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.18.0" - } - }, - "packages/coding-agent/node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", - "dev": true, - "license": "MIT" - }, - "packages/tui": { - "name": "@earendil-works/pi-tui", - "version": "0.9.1", - "license": "MIT", - "dependencies": { - "@types/mime-types": "^3.0.1", - "chalk": "^5.5.0", - "get-east-asian-width": "^1.6.0", - "marked": "^18.0.7", - "mime-types": "^3.0.1" - }, - "devDependencies": { - "@xterm/headless": "^6.0.0", - "@xterm/xterm": "^6.0.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "optionalDependencies": { - "koffi": "^2.9.0" - } - } - } -} diff --git a/package.json b/package.json index 6d64610db8..c406109e15 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "prime-agent", "private": true, "type": "module", + "packageManager": "bun@1.3.14", "workspaces": [ "packages/*", "packages/coding-agent/examples/extensions/with-deps", @@ -55,9 +56,6 @@ }, "overrides": { "rimraf": "6.1.2", - "gaxios": { - "rimraf": "6.1.2" - }, "shell-quote": "^1.10.0" } } diff --git a/packages/coding-agent/package.json b/packages/coding-agent/package.json index b9dafc7990..994c27e8d1 100644 --- a/packages/coding-agent/package.json +++ b/packages/coding-agent/package.json @@ -72,10 +72,7 @@ "yaml": "^2.9.0" }, "overrides": { - "rimraf": "6.1.2", - "gaxios": { - "rimraf": "6.1.2" - } + "rimraf": "6.1.2" }, "optionalDependencies": { "@mariozechner/clipboard": "^0.3.9" From 1eb597fe77684b8ee38ff111a240b3dbbdffb14f Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 00:55:04 -0400 Subject: [PATCH 02/31] build: make bun the primary development runtime --- .husky/pre-commit | 2 +- bun.lock | 33 ++-------- package.json | 27 +++++---- packages/agent/package.json | 8 +-- packages/ai/package.json | 14 ++--- packages/coding-agent/package.json | 18 +++--- packages/coding-agent/scripts/copy-assets.ts | 63 ++++++++++++++++++++ packages/coding-agent/src/bun/cli.ts | 2 +- packages/tui/package.json | 8 +-- prime-agent.sh | 27 +++++---- scripts/dev.ts | 41 +++++++++++++ scripts/remove-paths.ts | 9 +++ 12 files changed, 176 insertions(+), 76 deletions(-) create mode 100644 packages/coding-agent/scripts/copy-assets.ts create mode 100644 scripts/dev.ts create mode 100644 scripts/remove-paths.ts diff --git a/.husky/pre-commit b/.husky/pre-commit index 64a0169cd0..4453e34be2 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -4,7 +4,7 @@ STAGED_FILES=$(git diff --cached --name-only) echo "Running formatting, linting, and type checking..." -npm run check +bun run check if [ $? -ne 0 ]; then echo "Checks failed. Please fix the errors before committing." exit 1 diff --git a/bun.lock b/bun.lock index aa34d8105e..8fafded7e3 100644 --- a/bun.lock +++ b/bun.lock @@ -13,7 +13,6 @@ "@biomejs/biome": "2.5.5", "@types/node": "^22.10.5", "@typescript/native-preview": "7.0.0-dev.20260120.1", - "concurrently": "^9.2.4", "husky": "^9.1.7", "jiti": "^2.7.0", "shx": "^0.4.0", @@ -44,7 +43,7 @@ "@anthropic-ai/sdk": "^0.91.1", "@aws-sdk/client-bedrock-runtime": "^3.1095.0", "@google/genai": "^1.40.0", - "@mistralai/mistralai": "^2.2.0", + "@mistralai/mistralai": "2.2.1", "chalk": "^5.6.2", "openai": "6.47.0", "partial-json": "^0.1.7", @@ -309,7 +308,7 @@ "@mariozechner/clipboard-win32-x64-msvc": ["@mariozechner/clipboard-win32-x64-msvc@0.3.9", "", { "os": "win32", "cpu": "x64" }, "sha512-ihQC3EufqEY81vhXBgVBtK4prL+wc62zJsSvxrgz7K1hsdt6OObz6v9p3Rn1OG3GJksTTKMJF0u/guMISHPhSA=="], - "@mistralai/mistralai": ["@mistralai/mistralai@2.6.4", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.40.0", "ws": "^8.18.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.25.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/exporter-trace-otlp-http": "^0.220.0", "@opentelemetry/resources": "^2.9.0", "@opentelemetry/sdk-trace-base": "^2.9.0" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/exporter-trace-otlp-http", "@opentelemetry/resources", "@opentelemetry/sdk-trace-base"] }, "sha512-PPt4GyJqs2hEsWrYCJZK5f0ORmT+L2MSm75LVGD7kBLf6ZKsoDpld/FRBQXr8xG6iFCBOFJFYzvGYhUb+UCkbw=="], + "@mistralai/mistralai": ["@mistralai/mistralai@2.2.1", "", { "dependencies": { "ws": "^8.18.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.25.0" } }, "sha512-uKU8CZmL2RzYKmplsU01hii4p3pe4HqJefpWNRWXm1Tcm0Sm4xXfwSLIy4k7ZCPlbETCGcp69E7hZs+WOJ5itQ=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -317,8 +316,6 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.43.0", "", {}, "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg=="], - "@oxc-project/types": ["@oxc-project/types@0.146.0", "", {}, "sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA=="], "@pondwader/socks5-server": ["@pondwader/socks5-server@1.0.10", "", {}, "sha512-bQY06wzzR8D2+vVCUoBsr5QS2U6UgPUQRmErNwtsuI6vLcyRKkafjkr3KxbtGFf9aBBIV2mcvlsKD1UYaIV+sg=="], @@ -535,7 +532,7 @@ "cli-highlight": ["cli-highlight@2.1.11", "", { "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", "mz": "^2.4.0", "parse5": "^5.1.1", "parse5-htmlparser2-tree-adapter": "^6.0.0", "yargs": "^16.0.0" }, "bin": { "highlight": "bin/highlight" } }, "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg=="], - "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + "cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], @@ -543,8 +540,6 @@ "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], - "concurrently": ["concurrently@9.2.4", "", { "dependencies": { "chalk": "4.1.2", "rxjs": "7.8.2", "shell-quote": "1.9.0", "supports-color": "8.1.1", "tree-kill": "1.2.2", "yargs": "17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } }, "sha512-TZ0CEhyzvFjgtAvHTusDMgj7wNdihCh7LLLrzdUOXIhdlnL2JBBGA9eJxR24rtqgmdjh3OA3hrN1rCHj6HM8qA=="], - "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], "cross-spawn": ["cross-spawn@6.0.6", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="], @@ -849,8 +844,6 @@ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], - "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], @@ -923,8 +916,6 @@ "token-types": ["token-types@6.1.2", "", { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww=="], - "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], - "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], @@ -967,9 +958,9 @@ "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], - "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + "yargs": ["yargs@16.2.2", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w=="], - "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + "yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], "yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="], @@ -991,12 +982,8 @@ "cli-highlight/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "cli-highlight/yargs": ["yargs@16.2.2", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w=="], - "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "concurrently/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "cross-spawn/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], "execa/get-stream": ["get-stream@4.1.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w=="], @@ -1033,22 +1020,12 @@ "cli-highlight/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "cli-highlight/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], - - "cli-highlight/yargs/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], - "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "concurrently/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "protobufjs/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "cli-highlight/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "cli-highlight/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], } } diff --git a/package.json b/package.json index c406109e15..6d936c8d7e 100644 --- a/package.json +++ b/package.json @@ -11,15 +11,15 @@ "packages/coding-agent/examples/extensions/sandbox" ], "scripts": { - "clean": "npm run clean --workspaces", - "build": "cd packages/tui && npm run build && cd ../ai && npm run build && cd ../agent && npm run build && cd ../coding-agent && npm run build", - "dev": "concurrently --names \"ai,agent,coding-agent,tui\" --prefix-colors \"cyan,yellow,red,magenta\" \"cd packages/ai && npm run dev\" \"cd packages/agent && npm run dev\" \"cd packages/coding-agent && npm run dev\" \"cd packages/tui && npm run dev\"", - "dev:tsc": "cd packages/ai && npm run dev:tsc", - "check": "biome check --write --error-on-warnings . && tsgo --noEmit && npm run check:installer && npm run check:browser-smoke", - "check:installer": "node scripts/check-installer-render.mjs", - "check:browser-smoke": "node scripts/check-browser-smoke.mjs", - "profile:tui": "node scripts/profile-coding-agent-node.mjs --mode tui", - "profile:rpc": "node scripts/profile-coding-agent-node.mjs --mode rpc", + "clean": "bun scripts/remove-paths.ts packages/tui/dist packages/ai/dist packages/agent/dist packages/coding-agent/dist", + "build": "bun run --cwd packages/tui build && bun run --cwd packages/ai build && bun run --cwd packages/agent build && bun run --cwd packages/coding-agent build", + "dev": "bun scripts/dev.ts", + "dev:tsc": "bun run --cwd packages/ai dev:tsc", + "check": "bun --bun biome check --write --error-on-warnings . && bun run check:type && bun run check:installer && bun run check:browser-smoke", + "check:installer": "bun scripts/check-installer-render.mjs", + "check:browser-smoke": "bun scripts/check-browser-smoke.mjs", + "profile:tui": "bun scripts/profile-coding-agent-node.mjs --mode tui", + "profile:rpc": "bun scripts/profile-coding-agent-node.mjs --mode rpc", "test": "npm run test --workspaces --if-present", "version:patch": "npm version patch -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install", "version:minor": "npm version minor -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install", @@ -32,14 +32,16 @@ "release:patch": "node scripts/release.mjs patch", "release:minor": "node scripts/release.mjs minor", "release:major": "node scripts/release.mjs major", - "prepare": "husky" + "prepare": "bun --bun husky", + "build:binary": "bun run --cwd packages/coding-agent build:binary", + "dev:cli": "bun packages/coding-agent/src/bun/cli.ts", + "check:type": "bun --bun tsgo --noEmit" }, "devDependencies": { "@anthropic-ai/sandbox-runtime": "^0.0.55", "@biomejs/biome": "2.5.5", "@types/node": "^22.10.5", "@typescript/native-preview": "7.0.0-dev.20260120.1", - "concurrently": "^9.2.4", "husky": "^9.1.7", "jiti": "^2.7.0", "shx": "^0.4.0", @@ -47,7 +49,8 @@ "typescript": "^7.0.2" }, "engines": { - "node": ">=22.8.0" + "node": ">=22.8.0", + "bun": "1.3.14" }, "version": "0.9.1", "dependencies": { diff --git a/packages/agent/package.json b/packages/agent/package.json index e512344cc3..751c50bac9 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -10,11 +10,11 @@ "README.md" ], "scripts": { - "clean": "shx rm -rf dist", - "build": "tsgo -p tsconfig.build.json", - "dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput", + "clean": "bun ../../scripts/remove-paths.ts dist", + "build": "bun --bun tsgo -p tsconfig.build.json", + "dev": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", "test": "vitest --run", - "prepublishOnly": "npm run clean && npm run build" + "prepublishOnly": "bun run clean && bun run build" }, "dependencies": { "@earendil-works/pi-ai": "^0.9.1", diff --git a/packages/ai/package.json b/packages/ai/package.json index 3e8400cb5e..0e0748117d 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -63,19 +63,19 @@ "README.md" ], "scripts": { - "clean": "shx rm -rf dist", - "generate-models": "npx tsx scripts/generate-models.ts", - "build": "npm run generate-models && tsgo -p tsconfig.build.json", - "dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput", - "dev:tsc": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput", + "clean": "bun ../../scripts/remove-paths.ts dist", + "generate-models": "bun scripts/generate-models.ts", + "build": "bun run generate-models && bun --bun tsgo -p tsconfig.build.json", + "dev": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", + "dev:tsc": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", "test": "vitest --run", - "prepublishOnly": "npm run clean && npm run build" + "prepublishOnly": "bun run clean && bun run build" }, "dependencies": { "@anthropic-ai/sdk": "^0.91.1", "@aws-sdk/client-bedrock-runtime": "^3.1095.0", "@google/genai": "^1.40.0", - "@mistralai/mistralai": "^2.2.0", + "@mistralai/mistralai": "2.2.1", "typebox": "^1.3.9", "chalk": "^5.6.2", "openai": "6.47.0", diff --git a/packages/coding-agent/package.json b/packages/coding-agent/package.json index 994c27e8d1..6fa9370fe3 100644 --- a/packages/coding-agent/package.json +++ b/packages/coding-agent/package.json @@ -31,19 +31,19 @@ "CHANGELOG.md" ], "scripts": { - "clean": "shx rm -rf dist", - "dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput", - "build": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js && npm run copy-assets && npm run bundle", - "build:binary": "npm --prefix ../tui run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm run build && bun build --compile ./dist/bun/cli.js --outfile dist/pi && npm run copy-binary-assets", - "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/ && shx rm -rf dist/prime-agent-runtime && shx cp -r ../../prime-agent-runtime dist/prime-agent-runtime && shx rm -rf dist/skills && shx cp -r skills dist/skills", - "copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/assets && shx cp src/modes/interactive/assets/*.png dist/assets/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/ && shx rm -rf dist/skills && shx cp -r skills dist/skills", + "clean": "bun ../../scripts/remove-paths.ts dist", + "dev": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", + "build": "bun --bun tsgo -p tsconfig.build.json && bun scripts/copy-assets.ts package && bun run bundle", + "build:binary": "bun run --cwd ../tui build && bun run --cwd ../ai build && bun run --cwd ../agent build && bun run build && bun build --compile ./dist/bun/cli.js --outfile dist/pi && bun scripts/copy-assets.ts binary", + "copy-assets": "bun scripts/copy-assets.ts package", + "copy-binary-assets": "bun scripts/copy-assets.ts binary", "test": "vitest --run", "test:ci": "tsx src/core/kernel/bootstrap-cli.ts && vitest --run --exclude test/daemon-supervisor-process.test.ts", "test:process": "vitest --run test/daemon-supervisor-process.test.ts", "test:process-stress": "vitest --run --tagsFilter process-stress test/daemon-supervisor-process.test.ts", - "postinstall": "node postinstall.cjs", - "prepublishOnly": "npm run clean && npm run build", - "bundle": "node scripts/bundle.mjs", + "postinstall": "bun postinstall.cjs", + "prepublishOnly": "bun run clean && bun run build", + "bundle": "bun scripts/bundle.mjs", "test:kernel": "vitest --run --no-file-parallelism --tagsFilter kernel-heavy test/acp-kernel-features.test.ts test/acp-cold-cli.test.ts test/kernel-goal-skill.test.ts test/repl-kernel-state-roundtrip.test.ts test/repl-kernel-mcp-shutdown.test.ts" }, "dependencies": { diff --git a/packages/coding-agent/scripts/copy-assets.ts b/packages/coding-agent/scripts/copy-assets.ts new file mode 100644 index 0000000000..40b491bee0 --- /dev/null +++ b/packages/coding-agent/scripts/copy-assets.ts @@ -0,0 +1,63 @@ +import { chmod, cp, mkdir, readdir, rm } from "node:fs/promises"; +import { basename, dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const packageDir = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const repoDir = resolve(packageDir, "../.."); +const distDir = join(packageDir, "dist"); +const mode = process.argv[2]; + +async function copyFiles(sourceDir: string, targetDir: string, suffix: string): Promise { + await mkdir(targetDir, { recursive: true }); + for (const entry of await readdir(sourceDir, { withFileTypes: true })) { + if (entry.isFile() && entry.name.endsWith(suffix)) { + await cp(join(sourceDir, entry.name), join(targetDir, entry.name)); + } + } +} + +async function replaceDirectory(source: string, target: string): Promise { + await rm(target, { recursive: true, force: true }); + await cp(source, target, { recursive: true }); +} + +async function copyFile(source: string, targetDir: string): Promise { + await mkdir(targetDir, { recursive: true }); + await cp(source, join(targetDir, basename(source))); +} + +async function copyPackageAssets(): Promise { + await chmod(join(distDir, "cli.js"), 0o755); + await copyFiles(join(packageDir, "src/modes/interactive/theme"), join(distDir, "modes/interactive/theme"), ".json"); + await copyFiles(join(packageDir, "src/modes/interactive/assets"), join(distDir, "modes/interactive/assets"), ".png"); + const exportDir = join(distDir, "core/export-html"); + for (const name of ["template.html", "template.css", "template.js"]) { + await copyFile(join(packageDir, "src/core/export-html", name), exportDir); + } + await copyFiles(join(packageDir, "src/core/export-html/vendor"), join(exportDir, "vendor"), ".js"); + await replaceDirectory(join(repoDir, "prime-agent-runtime"), join(distDir, "prime-agent-runtime")); + await replaceDirectory(join(packageDir, "skills"), join(distDir, "skills")); +} + +async function copyBinaryAssets(): Promise { + for (const name of ["package.json", "README.md", "CHANGELOG.md"]) { + await copyFile(join(packageDir, name), distDir); + } + await copyFiles(join(packageDir, "src/modes/interactive/theme"), join(distDir, "theme"), ".json"); + await copyFiles(join(packageDir, "src/modes/interactive/assets"), join(distDir, "assets"), ".png"); + await copyFile(join(packageDir, "src/core/export-html/template.html"), join(distDir, "export-html")); + await copyFiles(join(packageDir, "src/core/export-html/vendor"), join(distDir, "export-html/vendor"), ".js"); + await replaceDirectory(join(packageDir, "docs"), join(distDir, "docs")); + await replaceDirectory(join(packageDir, "examples"), join(distDir, "examples")); + await copyFile(join(repoDir, "node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm"), distDir); + await replaceDirectory(join(packageDir, "skills"), join(distDir, "skills")); +} + +if (mode === "package") { + await copyPackageAssets(); +} else if (mode === "binary") { + await copyBinaryAssets(); +} else { + console.error("Usage: bun scripts/copy-assets.ts "); + process.exit(2); +} diff --git a/packages/coding-agent/src/bun/cli.ts b/packages/coding-agent/src/bun/cli.ts index 0aacb95b08..fb9318f941 100644 --- a/packages/coding-agent/src/bun/cli.ts +++ b/packages/coding-agent/src/bun/cli.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env bun import { APP_NAME } from "../config.js"; process.title = APP_NAME; diff --git a/packages/tui/package.json b/packages/tui/package.json index ee67bf2d75..7e0ecbd82d 100644 --- a/packages/tui/package.json +++ b/packages/tui/package.json @@ -5,11 +5,11 @@ "type": "module", "main": "dist/index.js", "scripts": { - "clean": "shx rm -rf dist", - "build": "tsgo -p tsconfig.build.json", - "dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput", + "clean": "bun ../../scripts/remove-paths.ts dist", + "build": "bun --bun tsgo -p tsconfig.build.json", + "dev": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", "test": "node --test --import tsx test/*.test.ts", - "prepublishOnly": "npm run clean && npm run build" + "prepublishOnly": "bun run clean && bun run build" }, "files": [ "dist/**/*", diff --git a/prime-agent.sh b/prime-agent.sh index 8baf90081f..53691f8e13 100755 --- a/prime-agent.sh +++ b/prime-agent.sh @@ -62,20 +62,27 @@ if [[ "$NO_ENV" == "true" ]]; then echo "Running Prime Agent without API keys..." fi -# --dist runs the bundled build (what users get; ~3x faster startup than tsx). +BUN_BIN="$(command -v bun || true)" +if [[ -z "$BUN_BIN" ]]; then + echo "Bun is required. Install version $(cat "$SCRIPT_DIR/.bun-version") and run bun install --frozen-lockfile." >&2 + exit 1 +fi + +EXPECTED_BUN_VERSION="$(cat "$SCRIPT_DIR/.bun-version")" +ACTUAL_BUN_VERSION="$($BUN_BIN --version)" +if [[ "$ACTUAL_BUN_VERSION" != "$EXPECTED_BUN_VERSION" ]]; then + echo "Prime Agent requires Bun $EXPECTED_BUN_VERSION; found $ACTUAL_BUN_VERSION." >&2 + exit 1 +fi + +# --dist runs the bundled build. Source mode runs TypeScript directly with Bun. if [[ "$USE_DIST" == "true" ]]; then BUNDLE="$SCRIPT_DIR/packages/coding-agent/dist/bundle/cli.js" if [[ ! -f "$BUNDLE" ]]; then - echo "Bundle not found at $BUNDLE. Run npm run build first." >&2 + echo "Bundle not found at $BUNDLE. Run bun run build first." >&2 exit 1 fi - exec node "$BUNDLE" ${ARGS[@]+"${ARGS[@]}"} -fi - -TSX_BIN="$SCRIPT_DIR/node_modules/.bin/tsx" -if [[ ! -x "$TSX_BIN" ]]; then - echo "tsx not found at $TSX_BIN. Run npm install from the repo root first." >&2 - exit 1 + exec "$BUN_BIN" "$BUNDLE" ${ARGS[@]+"${ARGS[@]}"} fi -"$TSX_BIN" "$SCRIPT_DIR/packages/coding-agent/src/cli.ts" ${ARGS[@]+"${ARGS[@]}"} +exec "$BUN_BIN" "$SCRIPT_DIR/packages/coding-agent/src/bun/cli.ts" ${ARGS[@]+"${ARGS[@]}"} diff --git a/scripts/dev.ts b/scripts/dev.ts new file mode 100644 index 0000000000..3027221be3 --- /dev/null +++ b/scripts/dev.ts @@ -0,0 +1,41 @@ +import { fileURLToPath } from "node:url"; + +const workspaceDirs = ["packages/ai", "packages/agent", "packages/coding-agent", "packages/tui"] as const; +const rootDir = fileURLToPath(new URL("..", import.meta.url)); +const children = workspaceDirs.map((cwd) => + Bun.spawn([process.execPath, "run", "--bun", "--cwd", cwd, "dev"], { + cwd: rootDir, + env: process.env, + stdin: "inherit", + stdout: "inherit", + stderr: "inherit", + }), +); + +let stopping = false; + +async function stop(signal: NodeJS.Signals, exitCode: number): Promise { + if (!stopping) { + stopping = true; + for (const child of children) { + child.kill(signal); + } + } + await Promise.allSettled(children.map((child) => child.exited)); + process.exit(exitCode); +} + +process.once("SIGINT", () => { + void stop("SIGINT", 130); +}); +process.once("SIGTERM", () => { + void stop("SIGTERM", 143); +}); + +const firstExit = await Promise.race( + children.map(async (child, index) => ({ index, exitCode: await child.exited })), +); +if (!stopping) { + console.error(`${workspaceDirs[firstExit.index]} watcher exited with code ${firstExit.exitCode}`); + await stop("SIGTERM", firstExit.exitCode || 1); +} diff --git a/scripts/remove-paths.ts b/scripts/remove-paths.ts new file mode 100644 index 0000000000..312d708fed --- /dev/null +++ b/scripts/remove-paths.ts @@ -0,0 +1,9 @@ +import { rm } from "node:fs/promises"; +import { resolve } from "node:path"; + +if (process.argv.length < 3) { + console.error("Usage: bun scripts/remove-paths.ts [...path]"); + process.exit(2); +} + +await Promise.all(process.argv.slice(2).map((path) => rm(resolve(path), { recursive: true, force: true }))); From ae5ed1edcfac882a87aae581d47270977ec995a6 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 17:38:08 -0400 Subject: [PATCH 03/31] fix: support Bun runtime process semantics --- packages/ai/src/cli.ts | 12 +++--- packages/coding-agent/src/cli.ts | 12 +++--- .../coding-agent/src/cli/daemon-launch.ts | 29 ++++++++++---- packages/coding-agent/src/cli/daemon-ps.ts | 4 +- .../src/cli/daemon-update-restart.ts | 7 ++-- .../src/cli/node-version-check.ts | 5 --- .../coding-agent/src/cli/subprocess-launch.ts | 27 ++----------- packages/coding-agent/src/config.ts | 40 ++++++++++++++----- .../src/core/extensions/loader.ts | 10 ++--- .../coding-agent/src/core/kernel/bootstrap.ts | 2 +- .../coding-agent/src/core/output-guard.ts | 17 ++++++++ .../src/core/prime-inference-auth.ts | 2 +- packages/coding-agent/src/core/prompts/rlm.ts | 2 +- packages/coding-agent/src/main.ts | 11 +++-- .../modes/daemon/daemon-catalog-process.ts | 9 +---- .../src/modes/daemon/daemon-client.ts | 5 ++- .../src/modes/daemon/daemon-mode.ts | 1 + .../src/modes/daemon/daemon-socket.ts | 5 ++- .../src/modes/daemon/daemon-supervisor.ts | 31 +++++++++++--- .../src/modes/interactive/interactive-mode.ts | 4 +- .../src/modes/interactive/theme/theme.ts | 6 ++- packages/coding-agent/src/utils/photon.ts | 2 +- .../coding-agent/src/utils/tools-manager.ts | 14 +++---- scripts/setup-kernel-venv.sh | 2 +- 24 files changed, 161 insertions(+), 98 deletions(-) diff --git a/packages/ai/src/cli.ts b/packages/ai/src/cli.ts index 7a4ff1fd33..a378141c64 100644 --- a/packages/ai/src/cli.ts +++ b/packages/ai/src/cli.ts @@ -64,7 +64,7 @@ async function main(): Promise { if (!command || command === "help" || command === "--help" || command === "-h") { const providerList = PROVIDERS.map((p) => ` ${p.id.padEnd(20)} ${p.name}`).join("\n"); - console.log(`Usage: npx @earendil-works/pi-ai [provider] + console.log(`Usage: bunx @earendil-works/pi-ai [provider] Commands: login [provider] Login to an OAuth provider @@ -74,9 +74,9 @@ Providers: ${providerList} Examples: - npx @earendil-works/pi-ai login # interactive provider selection - npx @earendil-works/pi-ai login anthropic # login to specific provider - npx @earendil-works/pi-ai list # list providers + bunx @earendil-works/pi-ai login # interactive provider selection + bunx @earendil-works/pi-ai login anthropic # login to specific provider + bunx @earendil-works/pi-ai list # list providers `); return; } @@ -113,7 +113,7 @@ Examples: if (!PROVIDERS.some((p) => p.id === provider)) { console.error(`Unknown provider: ${provider}`); - console.error(`Use 'npx @earendil-works/pi-ai list' to see available providers`); + console.error(`Use 'bunx @earendil-works/pi-ai list' to see available providers`); process.exit(1); } @@ -123,7 +123,7 @@ Examples: } console.error(`Unknown command: ${command}`); - console.error(`Use 'npx @earendil-works/pi-ai --help' for usage`); + console.error(`Use 'bunx @earendil-works/pi-ai --help' for usage`); process.exit(1); } diff --git a/packages/coding-agent/src/cli.ts b/packages/coding-agent/src/cli.ts index 07d1b9b3d0..38b8024c7a 100644 --- a/packages/coding-agent/src/cli.ts +++ b/packages/coding-agent/src/cli.ts @@ -3,11 +3,13 @@ // behind the dynamic import, after the dependency-free guard runs. import { assertNodeVersion } from "./cli/node-version-check.js"; -const supported = assertNodeVersion({ - version: process.versions.node, - log: console.error, - exit: (code) => process.exit(code), -}); +const supported = process.versions.bun + ? true + : assertNodeVersion({ + version: process.versions.node, + log: console.error, + exit: (code) => process.exit(code), + }); if (supported) { const { runCli } = await import("./cli-main.js"); diff --git a/packages/coding-agent/src/cli/daemon-launch.ts b/packages/coding-agent/src/cli/daemon-launch.ts index 0d57425064..37073959a7 100644 --- a/packages/coding-agent/src/cli/daemon-launch.ts +++ b/packages/coding-agent/src/cli/daemon-launch.ts @@ -346,11 +346,22 @@ async function shutdownStaleDaemonIfNotBusy(socketPath: string): Promise { +export interface DaemonLaunchTiming { + startupTimeoutMs?: number; + initialHelloTimeoutMs?: number; +} + +async function ensureDaemonRunning( + socketPath: string, + spawnCwd?: string, + timing: DaemonLaunchTiming = {}, +): Promise { + const startupTimeoutMs = timing.startupTimeoutMs ?? DAEMON_STARTUP_TIMEOUT_MS; + const initialHelloTimeoutMs = timing.initialHelloTimeoutMs ?? 2000; const probeStartedAt = Date.now(); - let probe = await probeDaemonVersion(socketPath); + let probe = await probeDaemonVersion(socketPath, initialHelloTimeoutMs); if (probe.status === "unresponsive") { - const remainingStartupMs = Math.max(1, DAEMON_STARTUP_TIMEOUT_MS - (Date.now() - probeStartedAt)); + const remainingStartupMs = Math.max(1, startupTimeoutMs - (Date.now() - probeStartedAt)); probe = await probeDaemonVersion(socketPath, remainingStartupMs); } if (probe.status === "current") { @@ -358,7 +369,7 @@ async function ensureDaemonRunning(socketPath: string, spawnCwd?: string): Promi } if (probe.status === "unresponsive") { throw new Error( - `Prime Agent daemon on ${socketPath} accepted connections but did not finish startup within ${DAEMON_STARTUP_TIMEOUT_MS / 1000} seconds. ` + + `Prime Agent daemon on ${socketPath} accepted connections but did not finish startup within ${startupTimeoutMs / 1000} seconds. ` + `It was left running to avoid interrupting active work. Run: @@ -436,7 +447,7 @@ Then retry the original command.`, // A child exit is not immediately fatal: it may have lost the socket to a // concurrent launcher whose daemon is still booting. Keep probing for a // short grace window before attributing the failure to the exit. - const deadline = Date.now() + DAEMON_STARTUP_TIMEOUT_MS; + const deadline = Date.now() + startupTimeoutMs; let exitDeadline: number | undefined; while (Date.now() < Math.min(deadline, exitDeadline ?? Number.POSITIVE_INFINITY)) { const started = await probeDaemonVersion(socketPath); @@ -489,10 +500,14 @@ const ensurePromises = new Map>(); * main.ts share one probe/spawn; failed attempts are forgotten so a later call * retries (and surfaces the real error at its await site). */ -export function ensureInteractiveDaemonRunning(socketPath: string, spawnCwd?: string): Promise { +export function ensureInteractiveDaemonRunning( + socketPath: string, + spawnCwd?: string, + timing?: DaemonLaunchTiming, +): Promise { let promise = ensurePromises.get(socketPath); if (!promise) { - promise = ensureDaemonRunning(socketPath, spawnCwd); + promise = ensureDaemonRunning(socketPath, spawnCwd, timing); ensurePromises.set(socketPath, promise); const clear = () => { if (ensurePromises.get(socketPath) === promise) { diff --git a/packages/coding-agent/src/cli/daemon-ps.ts b/packages/coding-agent/src/cli/daemon-ps.ts index 42c05f9a73..17dbf005a7 100644 --- a/packages/coding-agent/src/cli/daemon-ps.ts +++ b/packages/coding-agent/src/cli/daemon-ps.ts @@ -120,7 +120,9 @@ export function parseLsofListeners(stdout: string): DiscoveredDaemonProcess[] { if (field === "p") { pid = Number.parseInt(value, 10); } else if (field === "n" && pid !== undefined && value.startsWith("/")) { - const socketPath = normalizeSocketPath(value); + // Linux lsof appends metadata such as " type=STREAM" to Unix socket + // names, while macOS reports only the path. + const socketPath = normalizeSocketPath(value.replace(/\s+type=\w+(?:\s.*)?$/, "")); const key = `${pid}:${socketPath}`; if (!seen.has(key)) { seen.add(key); diff --git a/packages/coding-agent/src/cli/daemon-update-restart.ts b/packages/coding-agent/src/cli/daemon-update-restart.ts index f436f2f6d1..3d6d251ee7 100644 --- a/packages/coding-agent/src/cli/daemon-update-restart.ts +++ b/packages/coding-agent/src/cli/daemon-update-restart.ts @@ -250,8 +250,9 @@ export class DaemonUpdateRestartStatusWriter { private readonly path: string, requestId: string, socketPath: string, + private readonly clock: () => Date = () => new Date(), ) { - const now = new Date().toISOString(); + const now = this.clock().toISOString(); const processStartId = getProcessStartId(process.pid); this.status = { version: 1, @@ -270,7 +271,7 @@ export class DaemonUpdateRestartStatusWriter { update( update: Partial>, ): void { - const now = new Date().toISOString(); + const now = this.clock().toISOString(); this.status = { ...this.status, ...update, @@ -293,7 +294,7 @@ export class DaemonUpdateRestartStatusWriter { } touch(): void { - this.status = { ...this.status, heartbeatAt: new Date().toISOString() }; + this.status = { ...this.status, heartbeatAt: this.clock().toISOString() }; this.persist(); } diff --git a/packages/coding-agent/src/cli/node-version-check.ts b/packages/coding-agent/src/cli/node-version-check.ts index 24eef4eb8d..8e53590508 100644 --- a/packages/coding-agent/src/cli/node-version-check.ts +++ b/packages/coding-agent/src/cli/node-version-check.ts @@ -38,11 +38,6 @@ function isSupportedNodeVersion(version: ParsedNodeVersion): boolean { } export function assertNodeVersion(io: NodeVersionGuardIO): boolean { - // Bun ships its own runtime; its node-compat version is unrelated to the user's Node. - if (process.versions.bun) { - return true; - } - const version = parseVersion(io.version); if (!version || isSupportedNodeVersion(version)) { return true; diff --git a/packages/coding-agent/src/cli/subprocess-launch.ts b/packages/coding-agent/src/cli/subprocess-launch.ts index f5843b48d1..d634bdb81a 100644 --- a/packages/coding-agent/src/cli/subprocess-launch.ts +++ b/packages/coding-agent/src/cli/subprocess-launch.ts @@ -1,5 +1,4 @@ -import { existsSync } from "node:fs"; -import { dirname, isAbsolute, join, resolve } from "node:path"; +import { isAbsolute, resolve } from "node:path"; import { isBunBinary } from "../config.js"; export interface CliSubprocessLaunchSpec { @@ -7,28 +6,8 @@ export interface CliSubprocessLaunchSpec { args: string[]; } -export function createCliSubprocessEnv( - source: NodeJS.ProcessEnv = process.env, - entrypoint = process.argv[1], - execArgs: readonly string[] = process.execArgv, -): NodeJS.ProcessEnv { - const environment = { ...source }; - if (environment.TSX_TSCONFIG_PATH !== undefined || !entrypoint || !execArgs.some((arg) => arg.includes("tsx"))) { - return environment; - } - let directory = dirname(resolve(entrypoint)); - while (true) { - const tsconfigPath = join(directory, "tsconfig.json"); - if (existsSync(tsconfigPath) && existsSync(join(directory, "node_modules", "tsx", "package.json"))) { - environment.TSX_TSCONFIG_PATH = tsconfigPath; - return environment; - } - const parent = dirname(directory); - if (parent === directory) { - return environment; - } - directory = parent; - } +export function createCliSubprocessEnv(source: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv { + return { ...source }; } function quoteCommandArgument(value: string): string { diff --git a/packages/coding-agent/src/config.ts b/packages/coding-agent/src/config.ts index 596d468d1a..1d6fbbc8c7 100644 --- a/packages/coding-agent/src/config.ts +++ b/packages/coding-agent/src/config.ts @@ -98,7 +98,7 @@ export function detectInstallMethod(): InstallMethod { if (resolvedPath.includes("/yarn/") || resolvedPath.includes("/.yarn/")) { return "yarn"; } - if (isBunRuntime || resolvedPath.includes("/install/global/node_modules/")) { + if (resolvedPath.includes("/install/global/node_modules/")) { return "bun"; } if (resolvedPath.includes("/npm/") || resolvedPath.includes("/node_modules/")) { @@ -159,7 +159,20 @@ function getSelfUpdateCommandForMethod( ): SelfUpdateCommand | undefined { const uninstallAfterInstall = isDirectPackageArtifactSpec(updateSpec); switch (method) { - case "bun-binary": + case "bun-binary": { + // Bun-compiled binary: use install.sh sidecar for self-update + const installScript = join(getPackageDir(), "install.sh"); + if (existsSync(installScript)) { + const updateCmd = makeSelfUpdateCommandStep(installScript, ["--update"]); + return { + ...updateCmd, + steps: [updateCmd], + }; + } + // install.sh not bundled; self-update not available via command. + // The caller shows a download link as fallback. + return undefined; + } case "homebrew": return undefined; case "pnpm": @@ -211,6 +224,7 @@ function readCommandOutput( encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], shell: shouldUseWindowsShell(command), + env: process.env, }); if (result.status === 0) return result.stdout.trim() || undefined; if (options.requireSuccess) { @@ -314,8 +328,12 @@ export function getSelfUpdateCommand( ): SelfUpdateCommand | undefined { const method = detectInstallMethod(); const command = getSelfUpdateCommandForMethod(method, packageName, updateSpec, npmCommand, updatePackageName); - if (!command || !isManagedByGlobalPackageManager(method, packageName, npmCommand) || !isSelfUpdatePathWritable()) { - return undefined; + if (!command) return undefined; + // Compiled binary installs are managed by their versioned installer directory. + if (method !== "bun-binary") { + if (!isManagedByGlobalPackageManager(method, packageName, npmCommand) || !isSelfUpdatePathWritable()) { + return undefined; + } } return command; } @@ -328,6 +346,10 @@ export function getSelfUpdateUnavailableInstruction( ): string { const method = detectInstallMethod(); if (method === "bun-binary") { + const installScript = join(getPackageDir(), "install.sh"); + if (existsSync(installScript)) { + return `Update with: ${installScript} --update`; + } return `Download from: https://github.com/PrimeIntellect-ai/prime-agent/releases/latest`; } if (method === "homebrew") { @@ -360,7 +382,7 @@ export function getUpdateInstruction(packageName: string): string { * Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md). * - For Bun binary: returns the directory containing the executable * - For Node.js (dist/): returns __dirname (the dist/ directory) - * - For tsx (src/): returns parent directory (the package root) + * - For direct source execution (src/): returns parent directory (the package root) */ export function getPackageDir(): string { // Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly) @@ -391,7 +413,7 @@ export function getPackageDir(): string { * Get path to built-in themes directory (shipped with package) * - For Bun binary: theme/ next to executable * - For Node.js (dist/): dist/modes/interactive/theme/ - * - For tsx (src/): src/modes/interactive/theme/ + * - For direct source execution (src/): src/modes/interactive/theme/ */ export function getThemesDir(): string { if (isBunBinary) { @@ -407,7 +429,7 @@ export function getThemesDir(): string { * Get path to HTML export template directory (shipped with package) * - For Bun binary: export-html/ next to executable * - For Node.js (dist/): dist/core/export-html/ - * - For tsx (src/): src/core/export-html/ + * - For direct source execution (src/): src/core/export-html/ */ export function getExportTemplateDir(): string { if (isBunBinary) { @@ -437,7 +459,7 @@ export function getChangelogPath(): string { * Get path to built-in interactive assets directory. * - For Bun binary: assets/ next to executable * - For Node.js (dist/): dist/modes/interactive/assets/ - * - For tsx (src/): src/modes/interactive/assets/ + * - For direct source execution (src/): src/modes/interactive/assets/ */ export function getInteractiveAssetsDir(): string { if (isBunBinary) { @@ -457,7 +479,7 @@ export function getBundledInteractiveAssetPath(name: string): string { * Get the directory containing built-in skills shipped with the package. * - For Bun binary: skills/ next to executable * - For Node.js (dist/): dist/skills/ - * - For tsx (src/): skills/ at the package root + * - For direct source execution (src/): skills/ at the package root */ export function getBundledSkillsDir(): string { if (isBunBinary) { diff --git a/packages/coding-agent/src/core/extensions/loader.ts b/packages/coding-agent/src/core/extensions/loader.ts index 2c7e81ad6b..ff978c8e8c 100644 --- a/packages/coding-agent/src/core/extensions/loader.ts +++ b/packages/coding-agent/src/core/extensions/loader.ts @@ -320,8 +320,8 @@ function createExtensionAPI( return api; } -// Replaced with `true` by the esbuild CLI bundle (scripts/bundle.mjs); stays -// undefined in unbundled dist/ and under tsx. +// Replaced with `true` by the Bun CLI bundle (scripts/bundle.mjs); stays +// undefined in unbundled dist/ and direct source execution. declare const __PI_BUNDLED__: boolean | undefined; const isBundledCli = typeof __PI_BUNDLED__ !== "undefined" && __PI_BUNDLED__ === true; @@ -333,11 +333,11 @@ async function loadExtensionModule(extensionPath: string) { const { createJiti } = await import("jiti/static"); const jiti = createJiti(import.meta.url, { moduleCache: false, - // In the Bun binary and the esbuild CLI bundle: serve pi packages from + // In the Bun binary and the Bun CLI bundle: serve pi packages from // virtualModules so extensions share the bundle's module instances // (file-path aliases would load a second, divergent copy of each package). // Also disable tryNative so jiti handles ALL imports (not just the entry point) - // In Node.js/dev: use aliases to resolve to node_modules paths + // In direct source execution: use aliases to resolve to node_modules paths ...(isBunBinary || isBundledCli ? { virtualModules: (await import("./bundled-modules.js")).VIRTUAL_MODULES, tryNative: false } : { alias: getAliases() }), @@ -522,7 +522,7 @@ function discoverExtensionsInDir(dir: string): string[] { const discovered: string[] = []; try { - const entries = fs.readdirSync(dir, { withFileTypes: true }); + const entries = fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name)); for (const entry of entries) { const entryPath = path.join(dir, entry.name); diff --git a/packages/coding-agent/src/core/kernel/bootstrap.ts b/packages/coding-agent/src/core/kernel/bootstrap.ts index 2390749308..16f13fac7d 100644 --- a/packages/coding-agent/src/core/kernel/bootstrap.ts +++ b/packages/coding-agent/src/core/kernel/bootstrap.ts @@ -651,7 +651,7 @@ function runtimeCandidateDirs(): string[] { const moduleDir = path.dirname(fileURLToPath(import.meta.url)); // dist/prime-agent-runtime is listed first deliberately: it is the only path stable // across every shipped layout (dist/, dist/bundle/, bun), where import.meta.url-relative - // resolution breaks. `npm run build` rebuilds it from live source (copy-assets does + // resolution breaks. `bun run build` rebuilds it from live source (copy-assets does // rm -rf + cp), so the staleness hash still refreshes on every build. The relative // paths below cover running from source (tsx) where dist/ hasn't been built. return [ diff --git a/packages/coding-agent/src/core/output-guard.ts b/packages/coding-agent/src/core/output-guard.ts index c078376046..59c1465566 100644 --- a/packages/coding-agent/src/core/output-guard.ts +++ b/packages/coding-agent/src/core/output-guard.ts @@ -2,6 +2,9 @@ interface StdoutTakeoverState { rawStdoutWrite: (chunk: string, callback?: (error?: Error | null) => void) => boolean; rawStderrWrite: (chunk: string, callback?: (error?: Error | null) => void) => boolean; originalStdoutWrite: typeof process.stdout.write; + originalConsoleLog: typeof console.log; + originalConsoleInfo: typeof console.info; + originalConsoleDebug: typeof console.debug; } let stdoutTakeoverState: StdoutTakeoverState | undefined; @@ -14,6 +17,9 @@ export function takeOverStdout(): void { const rawStdoutWrite = process.stdout.write.bind(process.stdout) as StdoutTakeoverState["rawStdoutWrite"]; const rawStderrWrite = process.stderr.write.bind(process.stderr) as StdoutTakeoverState["rawStderrWrite"]; const originalStdoutWrite = process.stdout.write; + const originalConsoleLog = console.log; + const originalConsoleInfo = console.info; + const originalConsoleDebug = console.debug; process.stdout.write = (( chunk: string | Uint8Array, @@ -25,11 +31,19 @@ export function takeOverStdout(): void { } return rawStderrWrite(String(chunk), callback); }) as typeof process.stdout.write; + // Bun's console methods write through native bindings instead of the mutable + // process.stdout.write property. Redirect them explicitly as well. + console.log = (...args: unknown[]) => console.error(...args); + console.info = (...args: unknown[]) => console.error(...args); + console.debug = (...args: unknown[]) => console.error(...args); stdoutTakeoverState = { rawStdoutWrite, rawStderrWrite, originalStdoutWrite, + originalConsoleLog, + originalConsoleInfo, + originalConsoleDebug, }; } @@ -39,6 +53,9 @@ export function restoreStdout(): void { } process.stdout.write = stdoutTakeoverState.originalStdoutWrite; + console.log = stdoutTakeoverState.originalConsoleLog; + console.info = stdoutTakeoverState.originalConsoleInfo; + console.debug = stdoutTakeoverState.originalConsoleDebug; stdoutTakeoverState = undefined; } diff --git a/packages/coding-agent/src/core/prime-inference-auth.ts b/packages/coding-agent/src/core/prime-inference-auth.ts index 3331ae3605..f761489ec6 100644 --- a/packages/coding-agent/src/core/prime-inference-auth.ts +++ b/packages/coding-agent/src/core/prime-inference-auth.ts @@ -87,7 +87,7 @@ export type PrimeTeam = { }; function defaultPrimeCliConfigPath(): string { - return join(homedir(), ".prime", "config.json"); + return join(process.env.HOME || homedir(), ".prime", "config.json"); } export function getPrimeCliConfigPath(configPath?: string): string { diff --git a/packages/coding-agent/src/core/prompts/rlm.ts b/packages/coding-agent/src/core/prompts/rlm.ts index ef610268e6..735f96a9f5 100644 --- a/packages/coding-agent/src/core/prompts/rlm.ts +++ b/packages/coding-agent/src/core/prompts/rlm.ts @@ -34,7 +34,7 @@ const REPL_CONTROL_PROMPT = [ "", "Do not assume the REPL is the native runtime of the external thing being investigated. A repository, package, service, dataset, paper, website, benchmark, or API may have its own environment and normal interface. Evaluate external systems through their own interface, then use the REPL to coordinate the process and analyze what comes back.", "", - "`bash(command)` starts a shell command in the background and returns a handle immediately: `h = bash('npm test')`. Use `h.pid` / `h.running` for liveness, `h.tail(n)` / `h.output()` for combined stdout+stderr so far, `h.poll()` for a non-blocking result, `h.kill()` to terminate (SIGTERM, escalating to SIGKILL; on Windows kill() uses taskkill /T and detached or reparented descendants may survive), and `await h` (or `await bash('cmd')`) for the completed result with exit_code, output, and duration. Prefer bash() for long-running commands so the turn keeps working. Run shell commands with `bash()`, not `subprocess`/`os.system`: subprocess calls block the kernel, show the user nothing while they run, and spawn processes the harness cannot see or stop.", + "`bash(command)` starts a shell command in the background and returns a handle immediately: `h = bash('bun test')`. Use `h.pid` / `h.running` for liveness, `h.tail(n)` / `h.output()` for combined stdout+stderr so far, `h.poll()` for a non-blocking result, `h.kill()` to terminate (SIGTERM, escalating to SIGKILL; on Windows kill() uses taskkill /T and detached or reparented descendants may survive), and `await h` (or `await bash('cmd')`) for the completed result with exit_code, output, and duration. Prefer bash() for long-running commands so the turn keeps working. Run shell commands with `bash()`, not `subprocess`/`os.system`: subprocess calls block the kernel, show the user nothing while they run, and spawn processes the harness cannot see or stop.", "", "Important: do not install dependencies into the kernel just to make an external project import or run there. If a project import, test, script, CLI, or dependency check is needed, run it through that project's own environment and normal command interface. For example, in a Python repo use its documented commands, `uv run ...`, `.venv/bin/python ...`, or the active project interpreter from the repo root. Treat failures from that native environment as the relevant result.", "", diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index e90b2e5dcc..b4968d66c2 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -59,7 +59,7 @@ import { KeybindingsManager } from "./core/keybindings.js"; import { installFileLogSink, setLogContext } from "./core/logging.js"; import type { ModelRegistry } from "./core/model-registry.js"; import { findInitialModel, resolveCliModel, resolveModelScope, type ScopedModel } from "./core/model-resolver.js"; -import { restoreStdout, takeOverStdout } from "./core/output-guard.js"; +import { restoreStdout, takeOverStdout, writeRawStdout } from "./core/output-guard.js"; import type { CreateAgentSessionOptions } from "./core/sdk.js"; import { formatMissingSessionCwdPrompt, @@ -1095,12 +1095,17 @@ export async function main(args: string[], options?: MainOptions) { takeOverStdout(); } + const writeCliMetadata = (text: string): void => { + const explicitMachineMode = parsed.print || parsed.mode !== undefined; + if (explicitMachineMode) console.error(text); + else writeRawStdout(`${text}\n`); + }; if (parsed.version) { - console.log(VERSION); + writeCliMetadata(VERSION); process.exit(0); } if (parsed.help) { - console.log(formatTopLevelHelp()); + writeCliMetadata(formatTopLevelHelp()); process.exit(0); } diff --git a/packages/coding-agent/src/modes/daemon/daemon-catalog-process.ts b/packages/coding-agent/src/modes/daemon/daemon-catalog-process.ts index 17453aaabb..670cb2abb4 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-catalog-process.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-catalog-process.ts @@ -1,7 +1,6 @@ import { type ChildProcess, spawn } from "node:child_process"; import { randomUUID } from "node:crypto"; import { existsSync } from "node:fs"; -import { createRequire } from "node:module"; import { join, sep } from "node:path"; import { fileURLToPath } from "node:url"; import { createCliSubprocessEnv, createCliSubprocessLaunchSpec } from "../../cli/subprocess-launch.js"; @@ -344,20 +343,16 @@ export class DaemonCatalogClient { private async spawnCatalog(): Promise { let command: string; let args: string[]; - let environment = createCliSubprocessEnv({ ...process.env, [DAEMON_CATALOG_ROLE_ENV]: "1" }); + const environment = createCliSubprocessEnv({ ...process.env, [DAEMON_CATALOG_ROLE_ENV]: "1" }); if (isBunBinary) { const launch = createCliSubprocessLaunchSpec(["--version"]); command = launch.command; args = launch.args; } else { const catalogEntry = resolveDaemonCatalogEntrypoint(); - const execArgs = catalogEntry.endsWith(".ts") - ? [...process.execArgv, "--import", createRequire(import.meta.url).resolve("tsx")] - : process.execArgv; - const launch = createCliSubprocessLaunchSpec([], undefined, execArgs, catalogEntry); + const launch = createCliSubprocessLaunchSpec([], undefined, process.execArgv, catalogEntry); command = launch.command; args = launch.args; - environment = createCliSubprocessEnv(environment, catalogEntry, execArgs); } const child = spawn(command, args, { cwd: process.cwd(), diff --git a/packages/coding-agent/src/modes/daemon/daemon-client.ts b/packages/coding-agent/src/modes/daemon/daemon-client.ts index b5ded67982..6af47df0ac 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-client.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-client.ts @@ -1,5 +1,5 @@ import { randomUUID } from "node:crypto"; -import { createConnection, type Socket } from "node:net"; +import { Socket } from "node:net"; import { getDaemonLogPath } from "../../config.js"; import { attachJsonlLineReader, serializeJsonLine } from "../rpc/jsonl.js"; import { @@ -200,7 +200,7 @@ export class DaemonClient { } this.helloMessage = undefined; this.daemonClosingReason = undefined; - const socket = createConnection(this.socketPath); + const socket = new Socket(); this.socket = socket; this.detachReader = attachJsonlLineReader(socket, (line) => this.handleLine(line)); @@ -235,6 +235,7 @@ export class DaemonClient { }; socket.once("connect", onConnect); socket.once("error", onError); + socket.connect(this.socketPath); }); socket.on("error", (error) => diff --git a/packages/coding-agent/src/modes/daemon/daemon-mode.ts b/packages/coding-agent/src/modes/daemon/daemon-mode.ts index b99c047ccf..bcecaba035 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-mode.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-mode.ts @@ -7314,6 +7314,7 @@ export class AgentDaemon { for (const client of this.clients) { client.detachInput(); client.socket.end(); + client.socket.destroy(); } await new Promise((resolveClose) => { if (!this.server) { diff --git a/packages/coding-agent/src/modes/daemon/daemon-socket.ts b/packages/coding-agent/src/modes/daemon/daemon-socket.ts index 99a3a15105..dd6d5e2cf7 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-socket.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-socket.ts @@ -278,7 +278,10 @@ function assertSocketLeaseHeld(socketPath: string, lease: DaemonSocketPathLease) export function defaultDaemonSocketDir(): string { const suffix = typeof process.getuid === "function" ? String(process.getuid()) : "user"; - return join(tmpdir(), `prime-agent-${suffix}`); + // Bun caches os.tmpdir() at startup. Read the standard overrides here so + // isolated processes and tests can select a runtime temporary directory. + const runtimeTmpDir = process.env.TMPDIR || process.env.TMP || process.env.TEMP || tmpdir(); + return join(runtimeTmpDir, `prime-agent-${suffix}`); } function ensureDefaultDaemonSocketDir(socketPath: string): void { diff --git a/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts b/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts index b5afde5da3..bf92424d32 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts @@ -481,20 +481,29 @@ function unrefDelay(ms: number): Promise { function commitWorkerStartupGate(gate: Writable): Promise { return new Promise((resolveCommit, rejectCommit) => { let settled = false; + let onError: (error: Error) => void; + let onClose: () => void; const finish = (error?: Error | null) => { if (settled) { return; } settled = true; + gate.off("error", onError); + gate.off("close", onClose); if (error) { rejectCommit(error); } else { resolveCommit(); } }; - const onError = (error: Error) => finish(error); - gate.on("error", onError); - gate.once("close", () => gate.off("error", onError)); + onError = (error: Error) => finish(error); + onClose = () => finish(new Error("Daemon session worker startup gate closed before commit")); + gate.once("error", onError); + gate.once("close", onClose); + if (gate.destroyed || gate.closed || !gate.writable) { + onClose(); + return; + } gate.end(DAEMON_WORKER_STARTUP_GATE_COMMIT, (error?: Error | null) => finish(error)); }); } @@ -2881,7 +2890,10 @@ export class DaemonSupervisor { }) : () => {}; child.once("close", detachWorkerStderr); - const childClosed = new Promise((resolveClose) => child.once("close", () => resolveClose())); + const childClosed = + child.exitCode !== null || child.signalCode !== null + ? Promise.resolve() + : new Promise((resolveClose) => child.once("close", () => resolveClose())); let spawnFailure: Error | undefined; const spawnSettled = new Promise((resolveSpawn) => { child.once("spawn", () => resolveSpawn()); @@ -2889,6 +2901,9 @@ export class DaemonSupervisor { spawnFailure = error instanceof Error ? error : new Error(String(error)); resolveSpawn(); }); + // Bun can emit "spawn" while a test or instrumentation wrapper is still + // returning the ChildProcess. A pid already proves successful admission. + if (child.pid) resolveSpawn(); }); child.on("error", (error) => { this.log( @@ -2983,7 +2998,12 @@ export class DaemonSupervisor { try { try { - await commitWorkerStartupGate(startupGate); + await Promise.race([ + commitWorkerStartupGate(startupGate), + childClosed.then(() => { + throw new Error("Daemon session worker exited before startup gate commit"); + }), + ]); } catch (error) { startupGate.destroy(); await childClosed; @@ -6535,6 +6555,7 @@ export class DaemonSupervisor { for (const client of this.clients) { client.detachInput(); client.socket.end(); + client.socket.destroy(); } await new Promise((resolveClose) => this.server?.close(() => resolveClose()) ?? resolveClose()); await this.runCleanupStep("daemon socket", () => this.cleanupSocket()); diff --git a/packages/coding-agent/src/modes/interactive/interactive-mode.ts b/packages/coding-agent/src/modes/interactive/interactive-mode.ts index 53cc14670c..9c81ae25e8 100644 --- a/packages/coding-agent/src/modes/interactive/interactive-mode.ts +++ b/packages/coding-agent/src/modes/interactive/interactive-mode.ts @@ -3348,11 +3348,11 @@ export class InteractiveMode { } private clearFeatureHintPresentation(): void { - if (this.featureHintTimer) { + if (this.featureHintTimer !== undefined) { clearTimeout(this.featureHintTimer); this.featureHintTimer = undefined; } - if (this.featureHintAnimationTimer) { + if (this.featureHintAnimationTimer !== undefined) { clearInterval(this.featureHintAnimationTimer); this.featureHintAnimationTimer = undefined; } diff --git a/packages/coding-agent/src/modes/interactive/theme/theme.ts b/packages/coding-agent/src/modes/interactive/theme/theme.ts index dd4a48f7f7..40424a81aa 100644 --- a/packages/coding-agent/src/modes/interactive/theme/theme.ts +++ b/packages/coding-agent/src/modes/interactive/theme/theme.ts @@ -820,7 +820,7 @@ function getDefaultTheme(): string { // Global Theme Instance // ============================================================================ -// Use globalThis to share theme across module loaders (tsx + jiti in dev mode) +// Use globalThis to share theme across module loaders (direct Bun source execution + jiti in dev mode) const THEME_KEY = Symbol.for("@earendil-works/pi-coding-agent:theme"); // Export theme as a getter that reads from globalThis @@ -1026,6 +1026,10 @@ function startThemeWatcher(): void { ) ?? undefined; } +export function getActiveThemeWatcher(): fs.FSWatcher | undefined { + return themeWatcher; +} + export function stopThemeWatcher(): void { if (themeReloadTimer) { clearTimeout(themeReloadTimer); diff --git a/packages/coding-agent/src/utils/photon.ts b/packages/coding-agent/src/utils/photon.ts index 6c320705eb..ed6d3e24c2 100644 --- a/packages/coding-agent/src/utils/photon.ts +++ b/packages/coding-agent/src/utils/photon.ts @@ -2,7 +2,7 @@ * Photon image processing wrapper. * * This module provides a unified interface to @silvia-odwyer/photon-node that works in: - * 1. Node.js (development, npm run build) + * 1. Bun (development and build) * 2. Bun compiled binaries (standalone distribution) * * The challenge: photon-node's CJS entry uses fs.readFileSync(__dirname + '/photon_rs_bg.wasm') diff --git a/packages/coding-agent/src/utils/tools-manager.ts b/packages/coding-agent/src/utils/tools-manager.ts index c3da7045ec..414c5cb50c 100644 --- a/packages/coding-agent/src/utils/tools-manager.ts +++ b/packages/coding-agent/src/utils/tools-manager.ts @@ -8,7 +8,6 @@ import { Readable } from "stream"; import { pipeline } from "stream/promises"; import { APP_NAME, getBinDir } from "../config.js"; -const TOOLS_DIR = getBinDir(); const NETWORK_TIMEOUT_MS = 10_000; const DOWNLOAD_TIMEOUT_MS = 120_000; const COMMAND_TIMEOUT_MS = 5_000; @@ -100,7 +99,7 @@ const TOOLS: Record = { // Check that a command both launches and reports a successful version. function commandWorks(cmd: string): boolean { try { - const result = spawnSync(cmd, ["--version"], { stdio: "pipe", timeout: COMMAND_TIMEOUT_MS }); + const result = spawnSync(cmd, ["--version"], { env: process.env, stdio: "pipe", timeout: COMMAND_TIMEOUT_MS }); return !result.error && result.status === 0; } catch { return false; @@ -113,7 +112,7 @@ export function getToolPath(tool: ManagedTool): string | null { if (!config) return null; // Check our tools directory first - const localPath = join(TOOLS_DIR, config.binaryName + (platform() === "win32" ? ".exe" : "")); + const localPath = join(getBinDir(), config.binaryName + (platform() === "win32" ? ".exe" : "")); if (existsSync(localPath) && commandWorks(localPath)) { return localPath; } @@ -190,6 +189,7 @@ class UnsupportedToolPlatformError extends Error {} async function downloadTool(tool: ManagedTool): Promise { const config = TOOLS[tool]; if (!config) throw new Error(`Unknown tool: ${tool}`); + const toolsDir = getBinDir(); const plat = platform(); const architecture = arch(); @@ -204,12 +204,12 @@ async function downloadTool(tool: ManagedTool): Promise { if (!assetName) throw new UnsupportedToolPlatformError(`Unsupported platform: ${plat}/${architecture}`); // Create tools directory - mkdirSync(TOOLS_DIR, { recursive: true }); + mkdirSync(toolsDir, { recursive: true }); const downloadUrl = `https://github.com/${config.repo}/releases/download/${config.tagPrefix}${version}/${assetName}`; - const archivePath = join(TOOLS_DIR, assetName); + const archivePath = join(toolsDir, assetName); const binaryExt = plat === "win32" ? ".exe" : ""; - const binaryPath = join(TOOLS_DIR, config.binaryName + binaryExt); + const binaryPath = join(toolsDir, config.binaryName + binaryExt); // Download await downloadFile(downloadUrl, archivePath); @@ -217,7 +217,7 @@ async function downloadTool(tool: ManagedTool): Promise { // Extract into a unique temp directory. fd and rg downloads can run concurrently // during startup, so sharing a fixed directory causes races. const extractDir = join( - TOOLS_DIR, + toolsDir, `extract_tmp_${config.binaryName}_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`, ); mkdirSync(extractDir, { recursive: true }); diff --git a/scripts/setup-kernel-venv.sh b/scripts/setup-kernel-venv.sh index 4a2df7314a..cd02b0a859 100755 --- a/scripts/setup-kernel-venv.sh +++ b/scripts/setup-kernel-venv.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")/.." -npx tsx packages/coding-agent/src/core/kernel/bootstrap-cli.ts +bun packages/coding-agent/src/core/kernel/bootstrap-cli.ts From 7ae24933778d71c8ed04614b2396e29391484501 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 17:38:30 -0400 Subject: [PATCH 04/31] test: run suites with Bun isolation --- bun.lock | 305 +------ bunfig.toml | 5 + package.json | 37 +- packages/agent/package.json | 8 +- packages/agent/vitest.config.ts | 21 - packages/ai/package.json | 8 +- packages/ai/test/anthropic-oauth.test.ts | 20 +- .../ai/test/azure-openai-base-url.test.ts | 10 +- .../test/bedrock-endpoint-resolution.test.ts | 10 +- .../ai/test/codex-websocket-cached-probe.ts | 4 +- .../ai/test/github-copilot-anthropic.test.ts | 15 +- packages/ai/test/github-copilot-oauth.test.ts | 118 ++- .../google-vertex-api-key-resolution.test.ts | 10 +- .../google-vertex-thinking-budget.test.ts | 25 +- packages/ai/test/lazy-module-load.test.ts | 84 +- packages/ai/test/mcp-oauth.test.ts | 197 ++-- packages/ai/test/openai-codex-oauth.test.ts | 34 +- packages/ai/test/openai-codex-stream.test.ts | 5 +- ...i-completions-cache-control-format.test.ts | 6 +- .../openai-completions-empty-tools.test.ts | 8 +- .../openai-completions-prompt-cache.test.ts | 11 +- .../openai-completions-response-model.test.ts | 6 +- .../openai-completions-tool-choice.test.ts | 29 +- packages/ai/vitest.config.ts | 9 - packages/coding-agent/bunfig.toml | 3 + packages/coding-agent/package.json | 18 +- packages/coding-agent/scripts/run-tests.ts | 61 ++ .../coding-agent/test/acp-cold-cli.test.ts | 10 +- .../test/acp-kernel-features.test.ts | 300 +++--- .../test/agent-connection-daemon.test.ts | 6 +- .../test/agent-session-concurrent.test.ts | 2 +- .../test/agent-session-services.test.ts | 4 +- .../test/agents-view-mode.test.ts | 25 +- .../test/assistant-message-streaming-bench.ts | 2 +- .../coding-agent/test/builtin-skills.test.ts | 19 +- packages/coding-agent/test/bun-bundle.test.ts | 122 +++ .../test/bun-installer-e2e.test.ts | 104 +++ .../coding-agent/test/bun-installer.test.ts | 214 +++++ .../test/bun-release-archives.test.ts | 150 +++ .../coding-agent/test/bun-test-preload.ts | 142 +++ .../test/bun-test-runtime-isolation.test.ts | 33 + .../clipboard-image-bmp-conversion.test.ts | 6 +- .../coding-agent/test/clipboard-image.test.ts | 1 - .../test/compaction-summary-reasoning.test.ts | 13 +- .../test/compiled-artifact-smoke.test.ts | 61 ++ .../coding-agent/test/daemon-client.test.ts | 40 +- .../coding-agent/test/daemon-command.test.ts | 11 +- .../coding-agent/test/daemon-launch.test.ts | 43 +- .../coding-agent/test/daemon-mode.test.ts | 15 +- .../test/daemon-multiclient-bench.ts | 8 +- packages/coding-agent/test/daemon-ps.test.ts | 6 +- .../daemon-supervisor-lazy-subagents.test.ts | 144 ++- .../test/daemon-supervisor-monitor.test.ts | 176 ++-- .../test/daemon-supervisor-process.test.ts | 862 +++++++++--------- packages/coding-agent/test/file-lines.test.ts | 13 +- .../fixtures/eng-4600-supervisor-fixture.ts | 56 +- .../test/fixtures/eng-4606-update-launcher.ts | 3 +- .../coding-agent/test/git-context.test.ts | 2 +- packages/coding-agent/test/git-update.test.ts | 1 + .../test/interactive-mode-status.test.ts | 67 +- .../test/interactive-update-relaunch.test.ts | 14 +- .../test/kernel-bash-shell.test.ts | 15 +- .../test/kernel-goal-skill.test.ts | 5 +- .../coding-agent/test/mcp-command.test.ts | 10 +- .../test/owned-session-worker-process.test.ts | 4 +- .../test/package-command-paths.test.ts | 16 +- .../test/package-self-update-daemon.test.ts | 20 +- packages/coding-agent/test/print-mode.test.ts | 2 +- .../coding-agent/test/public-command.test.ts | 4 +- packages/coding-agent/test/refinement.test.ts | 26 +- .../test/repl-kernel-abort.test.ts | 7 +- .../test/repl-kernel-mcp-shutdown.test.ts | 5 +- .../test/repl-kernel-parent-watchdog.test.ts | 20 +- .../test/repl-kernel-startup.test.ts | 10 +- .../test/repl-kernel-state-roundtrip.test.ts | 5 +- packages/coding-agent/test/rlm-ledger.test.ts | 4 +- packages/coding-agent/test/rpc-example.ts | 2 +- .../test/sdk-codex-cache-probe-tool-loop.ts | 4 +- .../test/session-manager-flush.test.ts | 4 +- .../test/stdout-cleanliness.test.ts | 4 +- .../test/streaming-render-debug.ts | 2 +- .../test/suite/acp-features.test.ts | 2 +- .../coding-agent/test/suite/acp-mode.test.ts | 2 +- .../suite/agent-session-action-races.test.ts | 4 +- ...nt-session-compaction-continuation.test.ts | 3 +- .../suite/agent-session-compaction.test.ts | 32 +- .../test/suite/agent-session-prompt.test.ts | 12 +- .../test/suite/agent-session-queue.test.ts | 31 +- .../daemon-serialized-refine-process.test.ts | 5 +- .../2791-fswatch-error-crash.test.ts | 12 +- .../4600-supervisor-singleton.test.ts | 8 +- ...4602-snapshot-transfer-idempotency.test.ts | 4 +- .../regressions/4603-worker-recovery.test.ts | 55 +- .../4606-update-restart-coordinator.test.ts | 23 +- .../4685-daemon-client-modes.test.ts | 14 +- ...17-subagent-terminal-agent-message.test.ts | 2 +- .../regressions/623-acp-canonical-cwd.test.ts | 2 +- .../coding-agent/test/suite/scheduling.ts | 16 + ...rialized-refine-config-integration.test.ts | 2 +- packages/coding-agent/test/test-tags.ts | 6 + .../coding-agent/test/test-theme-colors.ts | 6 +- packages/coding-agent/vitest.config.ts | 50 - packages/tui/package.json | 5 +- packages/tui/test/image-test.ts | 2 +- packages/tui/test/key-tester.ts | 2 +- packages/tui/vitest.config.ts | 7 - scripts/publish-workspaces.ts | 18 + scripts/run-with-clean-env.ts | 34 + scripts/set-version.ts | 88 ++ scripts/sync-versions.js | 90 -- test.sh | 2 +- tsconfig.json | 4 +- types/vitest.d.ts | 45 + 113 files changed, 2583 insertions(+), 1916 deletions(-) delete mode 100644 packages/agent/vitest.config.ts delete mode 100644 packages/ai/vitest.config.ts create mode 100644 packages/coding-agent/bunfig.toml create mode 100644 packages/coding-agent/scripts/run-tests.ts create mode 100644 packages/coding-agent/test/bun-bundle.test.ts create mode 100644 packages/coding-agent/test/bun-installer-e2e.test.ts create mode 100644 packages/coding-agent/test/bun-installer.test.ts create mode 100644 packages/coding-agent/test/bun-release-archives.test.ts create mode 100644 packages/coding-agent/test/bun-test-preload.ts create mode 100644 packages/coding-agent/test/bun-test-runtime-isolation.test.ts create mode 100644 packages/coding-agent/test/compiled-artifact-smoke.test.ts create mode 100644 packages/coding-agent/test/test-tags.ts delete mode 100644 packages/coding-agent/vitest.config.ts delete mode 100644 packages/tui/vitest.config.ts create mode 100644 scripts/publish-workspaces.ts create mode 100644 scripts/run-with-clean-env.ts create mode 100644 scripts/set-version.ts delete mode 100644 scripts/sync-versions.js create mode 100644 types/vitest.d.ts diff --git a/bun.lock b/bun.lock index 8fafded7e3..dcae26ccae 100644 --- a/bun.lock +++ b/bun.lock @@ -5,7 +5,7 @@ "": { "name": "prime-agent", "dependencies": { - "@earendil-works/pi-coding-agent": "^0.8.1", + "@earendil-works/pi-coding-agent": "^0.9.1", "get-east-asian-width": "^1.6.0", }, "devDependencies": { @@ -13,29 +13,30 @@ "@biomejs/biome": "2.5.5", "@types/node": "^22.10.5", "@typescript/native-preview": "7.0.0-dev.20260120.1", + "@vitest/expect": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/spy": "4.1.10", + "bun-types": "1.3.14", "husky": "^9.1.7", "jiti": "^2.7.0", - "shx": "^0.4.0", - "tsx": "^4.23.1", "typescript": "^7.0.2", }, }, "packages/agent": { "name": "@earendil-works/pi-agent-core", - "version": "0.8.1", + "version": "0.9.1", "dependencies": { - "@earendil-works/pi-ai": "^0.8.1", + "@earendil-works/pi-ai": "^0.9.1", "typebox": "^1.3.9", }, "devDependencies": { "@types/node": "^24.3.0", "typescript": "^7.0.2", - "vitest": "^4.1.10", }, }, "packages/ai": { "name": "@earendil-works/pi-ai", - "version": "0.8.1", + "version": "0.9.1", "bin": { "pi-ai": "./dist/cli.js", }, @@ -55,20 +56,19 @@ "devDependencies": { "@types/node": "^24.3.0", "canvas": "^3.2.0", - "vitest": "^4.1.10", }, }, "packages/coding-agent": { "name": "@earendil-works/pi-coding-agent", - "version": "0.8.1", + "version": "0.9.1", "bin": { "pi": "dist/bundle/cli.js", }, "dependencies": { "@agentclientprotocol/sdk": "^1.3.0", - "@earendil-works/pi-agent-core": "^0.8.1", - "@earendil-works/pi-ai": "^0.8.1", - "@earendil-works/pi-tui": "^0.8.1", + "@earendil-works/pi-agent-core": "^0.9.1", + "@earendil-works/pi-ai": "^0.9.1", + "@earendil-works/pi-tui": "^0.9.1", "@silvia-odwyer/photon-node": "^0.3.4", "chalk": "^5.5.0", "cli-highlight": "^2.1.11", @@ -95,10 +95,7 @@ "@types/ms": "^2.1.0", "@types/node": "^24.3.0", "@types/proper-lockfile": "^4.1.4", - "esbuild": "^0.28.1", - "shx": "^0.4.0", "typescript": "^7.0.2", - "vitest": "^4.1.10", }, "optionalDependencies": { "@mariozechner/clipboard": "^0.3.9", @@ -106,25 +103,25 @@ }, "packages/coding-agent/examples/extensions/custom-provider-anthropic": { "name": "pi-extension-custom-provider-anthropic", - "version": "0.0.1", + "version": "0.1.1", "dependencies": { "@anthropic-ai/sdk": "^0.52.0", }, }, "packages/coding-agent/examples/extensions/custom-provider-gitlab-duo": { "name": "pi-extension-custom-provider-gitlab-duo", - "version": "0.0.1", + "version": "0.1.1", }, "packages/coding-agent/examples/extensions/sandbox": { "name": "pi-extension-sandbox", - "version": "1.4.0", + "version": "1.5.1", "dependencies": { "@anthropic-ai/sandbox-runtime": "^0.0.55", }, }, "packages/coding-agent/examples/extensions/with-deps": { "name": "pi-extension-with-deps", - "version": "0.0.1", + "version": "0.1.1", "dependencies": { "ms": "^2.1.3", }, @@ -134,7 +131,7 @@ }, "packages/tui": { "name": "@earendil-works/pi-tui", - "version": "0.8.1", + "version": "0.9.1", "dependencies": { "@types/mime-types": "^3.0.1", "chalk": "^5.5.0", @@ -230,62 +227,8 @@ "@earendil-works/pi-tui": ["@earendil-works/pi-tui@workspace:packages/tui"], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ=="], - - "@esbuild/android-arm": ["@esbuild/android-arm@0.28.2", "", { "os": "android", "cpu": "arm" }, "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg=="], - - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.2", "", { "os": "android", "cpu": "arm64" }, "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A=="], - - "@esbuild/android-x64": ["@esbuild/android-x64@0.28.2", "", { "os": "android", "cpu": "x64" }, "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q=="], - - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw=="], - - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw=="], - - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw=="], - - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg=="], - - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.2", "", { "os": "linux", "cpu": "arm" }, "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w=="], - - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug=="], - - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ=="], - - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ=="], - - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA=="], - - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ=="], - - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.2", "", { "os": "linux", "cpu": "none" }, "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA=="], - - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg=="], - - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.2", "", { "os": "linux", "cpu": "x64" }, "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ=="], - - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.2", "", { "os": "none", "cpu": "arm64" }, "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw=="], - - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.2", "", { "os": "none", "cpu": "x64" }, "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw=="], - - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ=="], - - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw=="], - - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.2", "", { "os": "none", "cpu": "arm64" }, "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q=="], - - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g=="], - - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ=="], - - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA=="], - - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g=="], - "@google/genai": ["@google/genai@1.52.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q=="], - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], - "@mariozechner/clipboard": ["@mariozechner/clipboard@0.3.9", "", { "optionalDependencies": { "@mariozechner/clipboard-darwin-arm64": "0.3.9", "@mariozechner/clipboard-darwin-universal": "0.3.9", "@mariozechner/clipboard-darwin-x64": "0.3.9", "@mariozechner/clipboard-linux-arm64-gnu": "0.3.9", "@mariozechner/clipboard-linux-arm64-musl": "0.3.9", "@mariozechner/clipboard-linux-riscv64-gnu": "0.3.9", "@mariozechner/clipboard-linux-x64-gnu": "0.3.9", "@mariozechner/clipboard-linux-x64-musl": "0.3.9", "@mariozechner/clipboard-win32-arm64-msvc": "0.3.9", "@mariozechner/clipboard-win32-x64-msvc": "0.3.9" } }, "sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA=="], "@mariozechner/clipboard-darwin-arm64": ["@mariozechner/clipboard-darwin-arm64@0.3.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BfgV7vCEWZwJwZJw03r6bP5+tf0iI/ANuQYCxi9RNn7FrWB3yzGuMKCrNLRl6V761vXRdL8+OqZ0wd4TqlsNOQ=="], @@ -310,14 +253,6 @@ "@mistralai/mistralai": ["@mistralai/mistralai@2.2.1", "", { "dependencies": { "ws": "^8.18.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.25.0" } }, "sha512-uKU8CZmL2RzYKmplsU01hii4p3pe4HqJefpWNRWXm1Tcm0Sm4xXfwSLIy4k7ZCPlbETCGcp69E7hZs+WOJ5itQ=="], - "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], - - "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], - - "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - - "@oxc-project/types": ["@oxc-project/types@0.146.0", "", {}, "sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA=="], - "@pondwader/socks5-server": ["@pondwader/socks5-server@1.0.10", "", {}, "sha512-bQY06wzzR8D2+vVCUoBsr5QS2U6UgPUQRmErNwtsuI6vLcyRKkafjkr3KxbtGFf9aBBIV2mcvlsKD1UYaIV+sg=="], "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], @@ -338,38 +273,6 @@ "@protobufjs/utf8": ["@protobufjs/utf8@1.1.2", "", {}, "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug=="], - "@rolldown/binding-android-arm-eabi": ["@rolldown/binding-android-arm-eabi@1.2.5", "", { "os": "android", "cpu": "arm" }, "sha512-DLe/i+l8ynIBY7XEQ191TeZvCoowIGa18R+dIV30GW7DiOtp74i/xX8hs8GUjW5ARV7VZuie3d6AumSmCwbeRA=="], - - "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.2.5", "", { "os": "android", "cpu": "arm64" }, "sha512-zXcwKlQApYAOELHd8PwKDFkagYF9Wy4e0RJ+0qnzl9Pjnpj75TEG8ufv40p2J7kCEfwZAsNiuzRIyNNMWT38ig=="], - - "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.2.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dK4QakI42nzWgJT5sm4y4y/O//D4OxM75/cH28RLV+nzIN9AY+YsbuUVrUTjlLjXR6vpyxFbSsbmNuJ6BP9sww=="], - - "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.2.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-fqSALaUu1Wjd1nK2uW2kJDWdLCc8lx1IcY+MTY26Aurfdx19anlzhqXOgCFbBFQnlFDTn4TC1/7Nz4Bl2mLP3A=="], - - "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.2.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-/vCnNxlkxs9tKxNDcyWUePpJ/PgTzxIaVhoM5SmG8UV+GR/IcPam4VYxi7GIMo7PSDuNqlJqvprqii9NqqVCMw=="], - - "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.2.5", "", { "os": "linux", "cpu": "arm" }, "sha512-abk0NLA519LxRCszmbE0jYKuQ9YPocOXTiOXOo6Yr+YAT95VH+PtqYAjOJvGKt3viEd/x4qzabAlwd5bHOOARg=="], - - "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.2.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-Y7eALiJ8lr0M2HH103Js+g7V34wf6snlpZLAsHI90uLhr3PVlNsbFVAXJC9d/V6BnPyKtpSwI+NcB/RLxsQxuA=="], - - "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.2.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-xMvZgnbZg4YVnR/AX2b3oOPDTFYJvUVaJg5FedA/LuvexAtXibZQej4cnTkw3rjsJ/ggUROB64TdtETiim+FYA=="], - - "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.2.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-GRjeqTUDHTo5GwntsLaAMcBahG3nlpjftXWZLN73HiYQlhwEowvarFgQnRnQZtIp4keXX7quXFbG38uPZBa2EA=="], - - "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.2.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-vLNTR45F2Uwc8AufkNXPmB4VliaXs+FvcheEogIzOXzO4l+LzieXF5A/TWxLy5HtqpsRCHUfd0lPVrrdgXdLHQ=="], - - "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.2.5", "", { "os": "linux", "cpu": "x64" }, "sha512-Mgj59/HTuYeK9Gz2MA+mBWKnHsAgkBSec15ZMb1st3oIfFbX7gCjOae7GydHhzcyQi9Z/7M1QuN9bR3oFqF0jQ=="], - - "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.2.5", "", { "os": "linux", "cpu": "x64" }, "sha512-mY8AP0/ichsbhAxGnLa3d3+MwV0EfgrPND2bplI3Ym8T6R2pJ0N87bvrKVwNXmdy3jnr6eQBecdqx/HMknBmpA=="], - - "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.2.5", "", { "os": "none", "cpu": "arm64" }, "sha512-8SLssA2oweAxyRgDp789ACfRb/3P+zNRJpzZxSizxF9m8NUDQ4+3xjo8ttjhVGGw6Qxb70oZiEtIjaKikCO7Yw=="], - - "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.2.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-vGbruD5zquhoc8D9SViXgN2FBJtNdTyQ4DtG+SWiEGlJiAzoKcZ2xp+xuXCffhubVdt0NJlTZqkeRuERy7g8Cw=="], - - "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.2.5", "", { "os": "win32", "cpu": "x64" }, "sha512-e/SXpgISz+IoqVcSSI0rx/d/he8zqLex+/rCWpnHpmVfmPIUjag9H6P7zotf0gJHwPUhQxZ/mF8tr6acebT9yw=="], - - "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="], - "@silvia-odwyer/photon-node": ["@silvia-odwyer/photon-node@0.3.4", "", {}, "sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA=="], "@smithy/core": ["@smithy/core@3.33.3", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-CsOeKq/9kA3y6VJHt+/+VTCtBaxJ4OTFpgrjIUhPpDIKxBci1k2bJaQASF2h/ELWrulGp+t97DZ0mevfAD8idg=="], @@ -398,8 +301,6 @@ "@types/diff": ["@types/diff@8.0.0", "", { "dependencies": { "diff": "*" } }, "sha512-o7jqJM04gfaYrdCecCVMbZhNdG6T1MHg/oQoRFdERLV+4d+V7FijhiEAbFu0Usww84Yijk9yH58U4Jk4HbtzZw=="], - "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], - "@types/hosted-git-info": ["@types/hosted-git-info@3.0.5", "", {}, "sha512-Dmngh7U003cOHPhKGyA7LWqrnvcTyILNgNPmNCxlx7j8MIi54iBliiT8XqVLIQ3GchoOjVAyBzNJVyuaJjqokg=="], "@types/mime-types": ["@types/mime-types@3.0.1", "", {}, "sha512-xRMsfuQbnRq1Ef+C+RKaENOxXX87Ygl38W1vDfPHRku02TgQr+Qd8iivLtAMcR0KF5/29xlnFihkTlbqFrGOVQ=="], @@ -470,19 +371,15 @@ "@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="], - "@vitest/expect": ["@vitest/expect@4.1.11", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.11", "@vitest/utils": "4.1.11", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw=="], - - "@vitest/mocker": ["@vitest/mocker@4.1.11", "", { "dependencies": { "@vitest/spy": "4.1.11", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ=="], + "@vitest/expect": ["@vitest/expect@4.1.10", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.10", "@vitest/utils": "4.1.10", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA=="], - "@vitest/pretty-format": ["@vitest/pretty-format@4.1.11", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw=="], + "@vitest/pretty-format": ["@vitest/pretty-format@4.1.10", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q=="], - "@vitest/runner": ["@vitest/runner@4.1.11", "", { "dependencies": { "@vitest/utils": "4.1.11", "pathe": "^2.0.3" } }, "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw=="], + "@vitest/runner": ["@vitest/runner@4.1.10", "", { "dependencies": { "@vitest/utils": "4.1.10", "pathe": "^2.0.3" } }, "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg=="], - "@vitest/snapshot": ["@vitest/snapshot@4.1.11", "", { "dependencies": { "@vitest/pretty-format": "4.1.11", "@vitest/utils": "4.1.11", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog=="], + "@vitest/spy": ["@vitest/spy@4.1.10", "", {}, "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw=="], - "@vitest/spy": ["@vitest/spy@4.1.11", "", {}, "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA=="], - - "@vitest/utils": ["@vitest/utils@4.1.11", "", { "dependencies": { "@vitest/pretty-format": "4.1.11", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ=="], + "@vitest/utils": ["@vitest/utils@4.1.10", "", { "dependencies": { "@vitest/pretty-format": "4.1.10", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA=="], "@xterm/headless": ["@xterm/headless@6.0.0", "", {}, "sha512-5Yj1QINYCyzrZtf8OFIHi47iQtI+0qYFPHmouEfG8dHNxbZ9Tb9YGSuLcsEwj9Z+OL75GJqPyJbyoFer80a2Hw=="], @@ -514,14 +411,14 @@ "brace-expansion": ["brace-expansion@5.0.9", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg=="], - "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], + "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + "canvas": ["canvas@3.2.3", "", { "dependencies": { "node-addon-api": "^7.0.0", "prebuild-install": "^7.1.3" } }, "sha512-PzE5nJZPz72YUAfo8oTp0u3fqqY7IzlTubneAihqDYAUcBk7ryeCmBbdJBEdaH0bptSOe2VT2Zwcb3UaFyaSWw=="], "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], @@ -542,8 +439,6 @@ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], - "cross-spawn": ["cross-spawn@6.0.6", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="], - "data-uri-to-buffer": ["data-uri-to-buffer@6.0.2", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="], "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], @@ -564,12 +459,6 @@ "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], - "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - - "es-module-lexer": ["es-module-lexer@2.3.2", "", {}, "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw=="], - - "esbuild": ["esbuild@0.28.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.2", "@esbuild/android-arm": "0.28.2", "@esbuild/android-arm64": "0.28.2", "@esbuild/android-x64": "0.28.2", "@esbuild/darwin-arm64": "0.28.2", "@esbuild/darwin-x64": "0.28.2", "@esbuild/freebsd-arm64": "0.28.2", "@esbuild/freebsd-x64": "0.28.2", "@esbuild/linux-arm": "0.28.2", "@esbuild/linux-arm64": "0.28.2", "@esbuild/linux-ia32": "0.28.2", "@esbuild/linux-loong64": "0.28.2", "@esbuild/linux-mips64el": "0.28.2", "@esbuild/linux-ppc64": "0.28.2", "@esbuild/linux-riscv64": "0.28.2", "@esbuild/linux-s390x": "0.28.2", "@esbuild/linux-x64": "0.28.2", "@esbuild/netbsd-arm64": "0.28.2", "@esbuild/netbsd-x64": "0.28.2", "@esbuild/openbsd-arm64": "0.28.2", "@esbuild/openbsd-x64": "0.28.2", "@esbuild/openharmony-arm64": "0.28.2", "@esbuild/sunos-x64": "0.28.2", "@esbuild/win32-arm64": "0.28.2", "@esbuild/win32-ia32": "0.28.2", "@esbuild/win32-x64": "0.28.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA=="], - "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], "escodegen": ["escodegen@2.1.0", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w=="], @@ -578,42 +467,24 @@ "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], - "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], - "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], - "execa": ["execa@1.0.0", "", { "dependencies": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA=="], - "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="], - "expect-type": ["expect-type@1.4.0", "", {}, "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA=="], - "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], "extract-zip": ["extract-zip@2.0.1", "", { "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "optionalDependencies": { "@types/yauzl": "^2.9.1" }, "bin": { "extract-zip": "cli.js" } }, "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg=="], - "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], - - "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], - "fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="], - "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], - "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], "file-type": ["file-type@21.3.4", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g=="], - "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], - "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - - "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - "gaxios": ["gaxios@7.3.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ=="], "gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="], @@ -630,8 +501,6 @@ "glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], - "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "google-auth-library": ["google-auth-library@10.9.1", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw=="], "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], @@ -642,8 +511,6 @@ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], - "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], "hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="], @@ -662,24 +529,10 @@ "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], - "interpret": ["interpret@1.4.0", "", {}, "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA=="], - "ip-address": ["ip-address@10.5.0", "", {}, "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g=="], - "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], - - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - - "is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], - - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - "jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="], "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], @@ -692,42 +545,12 @@ "koffi": ["koffi@2.16.3", "", {}, "sha512-E9y1AsgYGlaxMhcZzHr8y96QF2U5XzA12GGVAfbWqIubTwPNMXQarfBzePNXHe0xtIEtNd6ifAv3GAKYGUeBAQ=="], - "lightningcss": ["lightningcss@1.33.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.33.0", "lightningcss-darwin-arm64": "1.33.0", "lightningcss-darwin-x64": "1.33.0", "lightningcss-freebsd-x64": "1.33.0", "lightningcss-linux-arm-gnueabihf": "1.33.0", "lightningcss-linux-arm64-gnu": "1.33.0", "lightningcss-linux-arm64-musl": "1.33.0", "lightningcss-linux-x64-gnu": "1.33.0", "lightningcss-linux-x64-musl": "1.33.0", "lightningcss-win32-arm64-msvc": "1.33.0", "lightningcss-win32-x64-msvc": "1.33.0" } }, "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA=="], - - "lightningcss-android-arm64": ["lightningcss-android-arm64@1.33.0", "", { "os": "android", "cpu": "arm64" }, "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg=="], - - "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.33.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg=="], - - "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.33.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ=="], - - "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.33.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg=="], - - "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.33.0", "", { "os": "linux", "cpu": "arm" }, "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ=="], - - "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg=="], - - "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ=="], - - "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg=="], - - "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw=="], - - "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.33.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA=="], - - "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.33.0", "", { "os": "win32", "cpu": "x64" }, "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA=="], - "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], "lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], - "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], - "marked": ["marked@18.0.11", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-HnslJfsZkRPBDJRHvVtAaWlZHEpSu7u8LgQuJCELjRKuWR+hpq4A7sLq3p8HaI9ypVoXDXxV34CsQJEe1+J5Aw=="], - "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - - "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], - "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], @@ -746,14 +569,10 @@ "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], - "nanoid": ["nanoid@3.3.18", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w=="], - "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], "netmask": ["netmask@2.1.1", "", {}, "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA=="], - "nice-try": ["nice-try@1.0.5", "", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="], - "node-abi": ["node-abi@3.95.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-T9iGctuocf0qIWFFOTxPzjT5q0SILqaBYXt272tlBHvTKC5+3JnkMirLxNJNkXHtFyBjU2Jx+NL4Zipr0B/c6Q=="], "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], @@ -764,18 +583,12 @@ "node-forge": ["node-forge@1.4.0", "", {}, "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ=="], - "npm-run-path": ["npm-run-path@2.0.2", "", { "dependencies": { "path-key": "^2.0.0" } }, "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw=="], - "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], - "obug": ["obug@2.1.4", "", {}, "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA=="], - "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], "openai": ["openai@6.47.0", "", { "peerDependencies": { "@aws-sdk/credential-provider-node": ">=3.972.0 <4", "@smithy/hash-node": ">=4.3.0 <5", "@smithy/signature-v4": ">=5.4.0 <6", "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["@aws-sdk/credential-provider-node", "@smithy/hash-node", "@smithy/signature-v4", "ws", "zod"] }, "sha512-xYr+R9woSzWxVxeiqkkNbHhv89tZDEI6eBMbrdPnv3poh+mijHvbhS35a+3o6xHa411/ns8j5ENY3So9DCXWYw=="], - "p-finally": ["p-finally@1.0.0", "", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="], - "p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="], "pac-proxy-agent": ["pac-proxy-agent@7.2.0", "", { "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.1.2", "debug": "^4.3.4", "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.6", "pac-resolver": "^7.0.1", "socks-proxy-agent": "^8.0.5" } }, "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA=="], @@ -788,10 +601,6 @@ "partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="], - "path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], - - "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], @@ -806,12 +615,6 @@ "pi-extension-with-deps": ["pi-extension-with-deps@workspace:packages/coding-agent/examples/extensions/with-deps"], - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - - "picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="], - - "postcss": ["postcss@8.5.26", "", { "dependencies": { "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ=="], - "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="], "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], @@ -824,42 +627,20 @@ "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], - "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - "rechoir": ["rechoir@0.6.2", "", { "dependencies": { "resolve": "^1.1.6" } }, "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw=="], - "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], - "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], - "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], - "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - - "rolldown": ["rolldown@1.2.5", "", { "dependencies": { "@oxc-project/types": "=0.146.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm-eabi": "1.2.5", "@rolldown/binding-android-arm64": "1.2.5", "@rolldown/binding-darwin-arm64": "1.2.5", "@rolldown/binding-darwin-x64": "1.2.5", "@rolldown/binding-freebsd-x64": "1.2.5", "@rolldown/binding-linux-arm-gnueabihf": "1.2.5", "@rolldown/binding-linux-arm64-gnu": "1.2.5", "@rolldown/binding-linux-arm64-musl": "1.2.5", "@rolldown/binding-linux-ppc64-gnu": "1.2.5", "@rolldown/binding-linux-s390x-gnu": "1.2.5", "@rolldown/binding-linux-x64-gnu": "1.2.5", "@rolldown/binding-linux-x64-musl": "1.2.5", "@rolldown/binding-openharmony-arm64": "1.2.5", "@rolldown/binding-win32-arm64-msvc": "1.2.5", "@rolldown/binding-win32-x64-msvc": "1.2.5" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-VD2IE5PUG4Oj8zz2VGykiYd5wbnjdIiSsNQb8Qu5B+noEp+A78mu2iVvpp27g8es14Tk9rofNs5Tku9iQCS4fA=="], - - "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], - "shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="], - - "shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], - "shell-quote": ["shell-quote@1.10.0", "", {}, "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA=="], - "shelljs": ["shelljs@0.9.2", "", { "dependencies": { "execa": "^1.0.0", "fast-glob": "^3.3.2", "interpret": "^1.0.0", "rechoir": "^0.6.2" }, "bin": { "shjs": "bin/shjs" } }, "sha512-S3I64fEiKgTZzKCC46zT/Ib9meqofLrQVbpSswtjFfAVDW+AZ54WTnAM/3/yENoxz/V1Cy6u3kiiEbQ4DNphvw=="], - - "shx": ["shx@0.4.0", "", { "dependencies": { "minimist": "^1.2.8", "shelljs": "^0.9.2" }, "bin": { "shx": "lib/cli.js" } }, "sha512-Z0KixSIlGPpijKgcH6oCMCbltPImvaKy0sGH8AkLRXw1KyzpKtaCTizP2xen+hNDqVF4xxgvA0KXSb9o4Q6hnA=="], - - "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], - "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="], @@ -874,28 +655,18 @@ "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], - - "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], - - "std-env": ["std-env@4.2.0", "", {}, "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw=="], - "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], - "strip-eof": ["strip-eof@1.0.0", "", {}, "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q=="], - "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], "strtok3": ["strtok3@10.3.5", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA=="], "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - "tar-fs": ["tar-fs@2.1.5", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw=="], "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], @@ -904,24 +675,14 @@ "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], - "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], - - "tinyexec": ["tinyexec@1.3.0", "", {}, "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ=="], - - "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], - "tinyrainbow": ["tinyrainbow@3.1.1", "", {}, "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw=="], - "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - "token-types": ["token-types@6.1.2", "", { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww=="], "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "tsx": ["tsx@4.23.12", "", { "dependencies": { "esbuild": "~0.28.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q=="], - "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], "typebox": ["typebox@1.3.18", "", {}, "sha512-/wYPoDqxWZSxV/XD8Eskzr3YluXC9CaWJOuUYMkj+lLVLkyeEIQKzHvMuS/IRc3OLTIBC32LAtHgXo/WFEOMHQ=="], @@ -938,16 +699,8 @@ "uuid": ["uuid@14.0.2", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ=="], - "vite": ["vite@8.2.2", "", { "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.5", "postcss": "^8.5.26", "rolldown": "~1.2.4", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.4.0 || ^0.5.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q=="], - - "vitest": ["vitest@4.1.11", "", { "dependencies": { "@vitest/expect": "4.1.11", "@vitest/mocker": "4.1.11", "@vitest/pretty-format": "4.1.11", "@vitest/runner": "4.1.11", "@vitest/snapshot": "4.1.11", "@vitest/spy": "4.1.11", "@vitest/utils": "4.1.11", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.11", "@vitest/browser-preview": "4.1.11", "@vitest/browser-webdriverio": "4.1.11", "@vitest/coverage-istanbul": "4.1.11", "@vitest/coverage-v8": "4.1.11", "@vitest/ui": "4.1.11", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "./vitest.mjs" } }, "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw=="], - "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], - "which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="], - - "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], - "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], @@ -980,18 +733,14 @@ "@types/yauzl/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], + "bun-types/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], + "cli-highlight/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "cross-spawn/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - - "execa/get-stream": ["get-stream@4.1.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w=="], - "hosted-git-info/lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="], - "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], - "node-fetch/data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], "p-retry/@types/retry": ["@types/retry@0.12.0", "", {}, "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="], @@ -1018,6 +767,8 @@ "@types/yauzl/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + "bun-types/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + "cli-highlight/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], diff --git a/bunfig.toml b/bunfig.toml index 35daac4864..09021efcc1 100644 --- a/bunfig.toml +++ b/bunfig.toml @@ -1,3 +1,8 @@ [install] linker = "hoisted" minimumReleaseAge = 604800 + +[test] +preload = ["./packages/coding-agent/test/bun-test-preload.ts"] +timeout = 30000 +pathIgnorePatterns = ["**/daemon-supervisor-process.test.ts", "**/compiled-artifact-smoke.test.ts", "**/daemon-supervisor-monitor.test.ts"] diff --git a/package.json b/package.json index 6d936c8d7e..5009177fa1 100644 --- a/package.json +++ b/package.json @@ -20,33 +20,38 @@ "check:browser-smoke": "bun scripts/check-browser-smoke.mjs", "profile:tui": "bun scripts/profile-coding-agent-node.mjs --mode tui", "profile:rpc": "bun scripts/profile-coding-agent-node.mjs --mode rpc", - "test": "npm run test --workspaces --if-present", - "version:patch": "npm version patch -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install", - "version:minor": "npm version minor -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install", - "version:major": "npm version major -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install", - "version:set": "npm version -ws", - "prepublishOnly": "npm run clean && npm run build && npm run check", - "publish": "npm run prepublishOnly && npm publish -ws --access public", - "publish:dry": "npm run prepublishOnly && npm publish -ws --access public --dry-run", - "release:pack": "node scripts/pack-prime-agent-release.mjs", - "release:patch": "node scripts/release.mjs patch", - "release:minor": "node scripts/release.mjs minor", - "release:major": "node scripts/release.mjs major", + "test": "bun run --cwd packages/tui test && bun run --cwd packages/ai test && bun run --cwd packages/agent test && bun run --cwd packages/coding-agent test", + "version:patch": "bun scripts/set-version.ts patch", + "version:minor": "bun scripts/set-version.ts minor", + "version:major": "bun scripts/set-version.ts major", + "version:set": "bun scripts/set-version.ts", + "prepublishOnly": "bun run clean && bun run build && bun run check", + "publish": "bun run prepublishOnly && bun scripts/publish-workspaces.ts", + "publish:dry": "bun run prepublishOnly && bun scripts/publish-workspaces.ts --dry-run", + "release:pack": "bun scripts/pack-prime-agent-release.mjs", + "release:patch": "bun scripts/release.mjs patch", + "release:minor": "bun scripts/release.mjs minor", + "release:major": "bun scripts/release.mjs major", "prepare": "bun --bun husky", "build:binary": "bun run --cwd packages/coding-agent build:binary", "dev:cli": "bun packages/coding-agent/src/bun/cli.ts", - "check:type": "bun --bun tsgo --noEmit" + "check:type": "bun --bun tsgo --noEmit", + "test:process": "bun run --cwd packages/coding-agent test:process", + "test:process-stress": "bun run --cwd packages/coding-agent test:process-stress", + "test:kernel": "bun run --cwd packages/coding-agent test:kernel" }, "devDependencies": { "@anthropic-ai/sandbox-runtime": "^0.0.55", "@biomejs/biome": "2.5.5", "@types/node": "^22.10.5", "@typescript/native-preview": "7.0.0-dev.20260120.1", + "bun-types": "1.3.14", "husky": "^9.1.7", "jiti": "^2.7.0", - "shx": "^0.4.0", - "tsx": "^4.23.1", - "typescript": "^7.0.2" + "typescript": "^7.0.2", + "@vitest/expect": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/spy": "4.1.10" }, "engines": { "node": ">=22.8.0", diff --git a/packages/agent/package.json b/packages/agent/package.json index 751c50bac9..a056fb3609 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -13,7 +13,7 @@ "clean": "bun ../../scripts/remove-paths.ts dist", "build": "bun --bun tsgo -p tsconfig.build.json", "dev": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", - "test": "vitest --run", + "test": "bun ../../scripts/run-with-clean-env.ts bun test --isolate --timeout 30000", "prepublishOnly": "bun run clean && bun run build" }, "dependencies": { @@ -35,11 +35,11 @@ "directory": "packages/agent" }, "engines": { - "node": ">=20.0.0" + "node": ">=20.0.0", + "bun": "1.3.14" }, "devDependencies": { "@types/node": "^24.3.0", - "typescript": "^7.0.2", - "vitest": "^4.1.10" + "typescript": "^7.0.2" } } diff --git a/packages/agent/vitest.config.ts b/packages/agent/vitest.config.ts deleted file mode 100644 index f80e2c0497..0000000000 --- a/packages/agent/vitest.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { fileURLToPath } from "node:url"; -import { defineConfig } from "vitest/config"; - -const aiSrcIndex = fileURLToPath(new URL("../ai/src/index.ts", import.meta.url)); -const aiSrcOAuth = fileURLToPath(new URL("../ai/src/oauth.ts", import.meta.url)); - -export default defineConfig({ - test: { - globals: true, - environment: "node", - testTimeout: 30000, // 30 seconds for API calls - }, - resolve: { - alias: [ - { find: /^@earendil-works\/pi-ai$/, replacement: aiSrcIndex }, - { find: /^@earendil-works\/pi-ai\/oauth$/, replacement: aiSrcOAuth }, - { find: /^@mariozechner\/pi-ai$/, replacement: aiSrcIndex }, - { find: /^@mariozechner\/pi-ai\/oauth$/, replacement: aiSrcOAuth }, - ], - }, -}); diff --git a/packages/ai/package.json b/packages/ai/package.json index 0e0748117d..73ada05d79 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -68,7 +68,7 @@ "build": "bun run generate-models && bun --bun tsgo -p tsconfig.build.json", "dev": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", "dev:tsc": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", - "test": "vitest --run", + "test": "bun ../../scripts/run-with-clean-env.ts bun test --isolate --timeout 30000", "prepublishOnly": "bun run clean && bun run build" }, "dependencies": { @@ -102,11 +102,11 @@ "directory": "packages/ai" }, "engines": { - "node": ">=20.0.0" + "node": ">=20.0.0", + "bun": "1.3.14" }, "devDependencies": { "@types/node": "^24.3.0", - "canvas": "^3.2.0", - "vitest": "^4.1.10" + "canvas": "^3.2.0" } } diff --git a/packages/ai/test/anthropic-oauth.test.ts b/packages/ai/test/anthropic-oauth.test.ts index f8e066c669..49b8d790aa 100644 --- a/packages/ai/test/anthropic-oauth.test.ts +++ b/packages/ai/test/anthropic-oauth.test.ts @@ -1,4 +1,4 @@ -import { afterEach, describe, expect, it, vi } from "vitest"; +import { afterEach, describe, expect, it, vi } from "bun:test"; import { loginAnthropic, refreshAnthropicToken } from "../src/utils/oauth/anthropic.js"; function jsonResponse(body: unknown, status: number = 200): Response { @@ -30,12 +30,17 @@ function getJsonBody(init?: RequestInit): Record { return JSON.parse(init.body) as Record; } -describe.sequential("Anthropic OAuth", () => { +describe("Anthropic OAuth", () => { + let origFetch: typeof globalThis.fetch | undefined; afterEach(() => { - vi.unstubAllGlobals(); + if (origFetch !== undefined) { + globalThis.fetch = origFetch; + origFetch = undefined; + } }); it("keeps the localhost redirect_uri for manual callback login", async () => { + origFetch = globalThis.fetch; let authUrl = ""; const fetchMock = vi.fn(async (input: unknown, init?: RequestInit): Promise => { expect(getUrl(input)).toBe("https://platform.claude.com/v1/oauth/token"); @@ -50,7 +55,7 @@ describe.sequential("Anthropic OAuth", () => { expires_in: 3600, }); }); - vi.stubGlobal("fetch", fetchMock); + globalThis.fetch = fetchMock; const credentials = await loginAnthropic({ onAuth: (info) => { @@ -70,10 +75,11 @@ describe.sequential("Anthropic OAuth", () => { expect(credentials.access).toBe("access-token"); expect(credentials.refresh).toBe("refresh-token"); - expect(fetchMock).toHaveBeenCalledOnce(); + expect(fetchMock).toHaveBeenCalledTimes(1); }); it("omits scope from refresh token requests", async () => { + origFetch = globalThis.fetch; const fetchMock = vi.fn(async (input: unknown, init?: RequestInit): Promise => { expect(getUrl(input)).toBe("https://platform.claude.com/v1/oauth/token"); expect(init?.method).toBe("POST"); @@ -88,12 +94,12 @@ describe.sequential("Anthropic OAuth", () => { expires_in: 3600, }); }); - vi.stubGlobal("fetch", fetchMock); + globalThis.fetch = fetchMock; const credentials = await refreshAnthropicToken("refresh-token"); expect(credentials.access).toBe("new-access-token"); expect(credentials.refresh).toBe("new-refresh-token"); - expect(fetchMock).toHaveBeenCalledOnce(); + expect(fetchMock).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/ai/test/azure-openai-base-url.test.ts b/packages/ai/test/azure-openai-base-url.test.ts index 3a8e9c1916..4271eb1c52 100644 --- a/packages/ai/test/azure-openai-base-url.test.ts +++ b/packages/ai/test/azure-openai-base-url.test.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test"; import { getModel } from "../src/models.js"; import { streamAzureOpenAIResponses } from "../src/providers/azure-openai-responses.js"; import type { Context } from "../src/types.js"; @@ -11,11 +11,11 @@ interface CapturedAzureClientOptions { baseURL: string; } -const azureMock = vi.hoisted(() => ({ - constructorCalls: [] as CapturedAzureClientOptions[], -})); +const azureMock: { constructorCalls: CapturedAzureClientOptions[] } = { + constructorCalls: [], +}; -vi.mock("openai", () => { +mock.module("openai", () => { class AzureOpenAI { responses = { create: () => { diff --git a/packages/ai/test/bedrock-endpoint-resolution.test.ts b/packages/ai/test/bedrock-endpoint-resolution.test.ts index 374599a473..d2f8d69ddd 100644 --- a/packages/ai/test/bedrock-endpoint-resolution.test.ts +++ b/packages/ai/test/bedrock-endpoint-resolution.test.ts @@ -1,10 +1,10 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test"; -const bedrockMock = vi.hoisted(() => ({ - constructorCalls: [] as Array>, -})); +const bedrockMock: { constructorCalls: Array> } = { + constructorCalls: [], +}; -vi.mock("@aws-sdk/client-bedrock-runtime", () => { +mock.module("@aws-sdk/client-bedrock-runtime", () => { class BedrockRuntimeServiceException extends Error {} class BedrockRuntimeClient { diff --git a/packages/ai/test/codex-websocket-cached-probe.ts b/packages/ai/test/codex-websocket-cached-probe.ts index 9bab146687..93e72f9a36 100644 --- a/packages/ai/test/codex-websocket-cached-probe.ts +++ b/packages/ai/test/codex-websocket-cached-probe.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env tsx +#!/usr/bin/env bun import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; @@ -79,7 +79,7 @@ function required(value: string | undefined, flag: string): string { } function printHelp(): void { - console.log(`Usage: npx tsx test/codex-websocket-cached-probe.ts [options] + console.log(`Usage: bun test/codex-websocket-cached-probe.ts [options] Options: --turns Number of user turns. Default: ${DEFAULT_TURNS} diff --git a/packages/ai/test/github-copilot-anthropic.test.ts b/packages/ai/test/github-copilot-anthropic.test.ts index 92bff083be..5362c4171e 100644 --- a/packages/ai/test/github-copilot-anthropic.test.ts +++ b/packages/ai/test/github-copilot-anthropic.test.ts @@ -1,13 +1,16 @@ -import { describe, expect, it, vi } from "vitest"; +import { describe, expect, it, mock } from "bun:test"; import { getModel } from "../src/models.js"; import type { Context } from "../src/types.js"; -const mockState = vi.hoisted(() => ({ - constructorOpts: undefined as Record | undefined, - createParams: undefined as Record | undefined, -})); +const mockState: { + constructorOpts: Record | undefined; + createParams: Record | undefined; +} = { + constructorOpts: undefined, + createParams: undefined, +}; -vi.mock("@anthropic-ai/sdk", () => { +mock.module("@anthropic-ai/sdk", () => { function createSseResponse(): Response { const body = [ `event: message_start\ndata: ${JSON.stringify({ diff --git a/packages/ai/test/github-copilot-oauth.test.ts b/packages/ai/test/github-copilot-oauth.test.ts index 0367892cb8..9808b16624 100644 --- a/packages/ai/test/github-copilot-oauth.test.ts +++ b/packages/ai/test/github-copilot-oauth.test.ts @@ -1,6 +1,13 @@ -import { afterEach, describe, expect, it, vi } from "vitest"; +import { afterEach, describe, expect, it, vi } from "bun:test"; import { loginGitHubCopilot } from "../src/utils/oauth/github-copilot.js"; +/** Flush microtask queue so async continuations run */ +async function flush(times = 10): Promise { + for (let i = 0; i < times; i++) { + await new Promise((resolve) => queueMicrotask(() => resolve())); + } +} + function jsonResponse(body: unknown, status: number = 200): Response { return new Response(JSON.stringify(body), { status, @@ -20,19 +27,22 @@ function getUrl(input: unknown): string { if (input instanceof Request) { return input.url; } - throw new Error(`Unsupported fetch input: ${String(input)}`); + throw new Error(`Unsupported fetch input: \${String(input)}`); } describe("GitHub Copilot OAuth device flow", () => { + let origFetchGH: typeof globalThis.fetch | undefined; afterEach(() => { - vi.unstubAllGlobals(); + if (origFetchGH !== undefined) { + globalThis.fetch = origFetchGH; + origFetchGH = undefined; + } vi.useRealTimers(); }); it("waits before the first poll and increases the safety margin after slow_down", async () => { vi.useFakeTimers(); - const startTime = new Date("2026-03-09T00:00:00Z"); - vi.setSystemTime(startTime); + const baseTime = Date.now(); const accessTokenPollTimes: number[] = []; const accessTokenResponses = [ @@ -89,10 +99,11 @@ describe("GitHub Copilot OAuth device flow", () => { return new Response("", { status: 200 }); } - throw new Error(`Unexpected fetch URL: ${url}`); + throw new Error(`Unexpected fetch URL: \${url}`); }); - vi.stubGlobal("fetch", fetchMock); + origFetchGH = globalThis.fetch; + globalThis.fetch = fetchMock; const loginPromise = loginGitHubCopilot({ onAuth: () => {}, @@ -100,38 +111,41 @@ describe("GitHub Copilot OAuth device flow", () => { onProgress: () => {}, }); - await vi.advanceTimersByTimeAsync(0); + // Let loginGitHubCopilot initialize and enter the poll loop + await flush(30); + expect(accessTokenPollTimes).toHaveLength(0); - await vi.advanceTimersByTimeAsync(5999); + vi.advanceTimersByTime(5999); + await flush(); expect(accessTokenPollTimes).toHaveLength(0); - await vi.advanceTimersByTimeAsync(1); + vi.advanceTimersByTime(1); + await flush(); expect(accessTokenPollTimes).toHaveLength(1); - await vi.advanceTimersByTimeAsync(5999); + vi.advanceTimersByTime(5999); + await flush(); expect(accessTokenPollTimes).toHaveLength(1); - await vi.advanceTimersByTimeAsync(1); + vi.advanceTimersByTime(1); + await flush(); expect(accessTokenPollTimes).toHaveLength(2); - await vi.advanceTimersByTimeAsync(13999); + vi.advanceTimersByTime(13999); + await flush(); expect(accessTokenPollTimes).toHaveLength(2); - await vi.advanceTimersByTimeAsync(1); + vi.advanceTimersByTime(1); + await flush(); await loginPromise; - expect(accessTokenPollTimes).toEqual([ - startTime.getTime() + 6000, - startTime.getTime() + 12000, - startTime.getTime() + 26000, - ]); + expect(accessTokenPollTimes).toEqual([baseTime + 6000, baseTime + 12000, baseTime + 26000]); }); it("uses the remaining lifetime for a final poll before timing out after repeated slow_down responses", async () => { vi.useFakeTimers(); - const startTime = new Date("2026-03-09T00:00:00Z"); - vi.setSystemTime(startTime); + const baseTime = Date.now(); const accessTokenPollTimes: number[] = []; const accessTokenResponses = [ @@ -142,7 +156,6 @@ describe("GitHub Copilot OAuth device flow", () => { const fetchMock = vi.fn(async (input: unknown): Promise => { const url = getUrl(input); - if (url.endsWith("/login/device/code")) { return jsonResponse({ device_code: "device-code", @@ -152,45 +165,50 @@ describe("GitHub Copilot OAuth device flow", () => { expires_in: 25, }); } - if (url.endsWith("/login/oauth/access_token")) { accessTokenPollTimes.push(Date.now()); const response = accessTokenResponses.shift(); - if (!response) { - throw new Error("Unexpected extra access token poll"); - } + if (!response) throw new Error("Unexpected extra access token poll"); return response; } - - throw new Error(`Unexpected fetch URL: ${url}`); + throw new Error(`Unexpected fetch URL: \${url}`); }); - vi.stubGlobal("fetch", fetchMock); + origFetchGH = globalThis.fetch; + globalThis.fetch = fetchMock; const loginPromise = loginGitHubCopilot({ onAuth: () => {}, onPrompt: async () => "", }); - const rejection = expect(loginPromise).rejects.toThrow( - /Device flow timed out after one or more slow_down responses/, - ); - - await vi.advanceTimersByTimeAsync(6000); - expect(accessTokenPollTimes).toEqual([startTime.getTime() + 6000]); - - await vi.advanceTimersByTimeAsync(14000); - expect(accessTokenPollTimes).toEqual([startTime.getTime() + 6000, startTime.getTime() + 20000]); - - await vi.advanceTimersByTimeAsync(4999); - expect(accessTokenPollTimes).toEqual([startTime.getTime() + 6000, startTime.getTime() + 20000]); - - await vi.advanceTimersByTimeAsync(1); - await rejection; - - expect(accessTokenPollTimes).toEqual([ - startTime.getTime() + 6000, - startTime.getTime() + 20000, - startTime.getTime() + 25000, - ]); + // Let loginGitHubCopilot initialize and enter the poll loop + await flush(30); + + // First wait: ceil(5000 * 1.2) = 6000ms + vi.advanceTimersByTime(6000); + await flush(); + expect(accessTokenPollTimes).toEqual([baseTime + 6000]); + + // After slow_down: ceil(10000 * 1.4) = 14000ms + vi.advanceTimersByTime(14000); + await flush(); + expect(accessTokenPollTimes).toEqual([baseTime + 6000, baseTime + 20000]); + + // After second slow_down: min(ceil(15000*1.4), remaining=5000) = 5000ms + vi.advanceTimersByTime(4999); + await flush(); + expect(accessTokenPollTimes).toEqual([baseTime + 6000, baseTime + 20000]); + + // Deadline crossed, loop exits, slowDownResponses>0 -> throws + vi.advanceTimersByTime(1); + await flush(); + try { + await loginPromise; + expect.unreachable("should have thrown"); + } catch (e) { + expect((e as Error).message).toMatch(/Device flow timed out after one or more slow_down responses/); + } + + expect(accessTokenPollTimes).toEqual([baseTime + 6000, baseTime + 20000, baseTime + 25000]); }); }); diff --git a/packages/ai/test/google-vertex-api-key-resolution.test.ts b/packages/ai/test/google-vertex-api-key-resolution.test.ts index d05702c3af..be1d69945a 100644 --- a/packages/ai/test/google-vertex-api-key-resolution.test.ts +++ b/packages/ai/test/google-vertex-api-key-resolution.test.ts @@ -1,10 +1,10 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test"; -const googleGenAiMock = vi.hoisted(() => ({ - constructorCalls: [] as Array>, -})); +const googleGenAiMock: { constructorCalls: Array> } = { + constructorCalls: [], +}; -vi.mock("@google/genai", () => { +mock.module("@google/genai", () => { class GoogleGenAI { models = { generateContentStream: async function* () { diff --git a/packages/ai/test/google-vertex-thinking-budget.test.ts b/packages/ai/test/google-vertex-thinking-budget.test.ts index 8851388215..9406b137c8 100644 --- a/packages/ai/test/google-vertex-thinking-budget.test.ts +++ b/packages/ai/test/google-vertex-thinking-budget.test.ts @@ -1,9 +1,10 @@ -import type * as GoogleGenAi from "@google/genai"; +import { describe, expect, it, mock } from "bun:test"; import type { GenerateContentParameters } from "@google/genai"; -import { describe, expect, it, vi } from "vitest"; -vi.mock("@google/genai", async (importOriginal) => { - const actual = await importOriginal(); +// Import the module normally before mocking so we can spread its exports +import * as googleGenAiActual from "@google/genai"; + +mock.module("@google/genai", () => { class GoogleGenAI { models = { generateContentStream: async function* () { @@ -16,7 +17,7 @@ vi.mock("@google/genai", async (importOriginal) => { } return { - ...actual, + ...googleGenAiActual, GoogleGenAI, ResourceScope: { COLLECTION: "COLLECTION" }, ThinkingLevel: { @@ -62,12 +63,14 @@ async function captureMinimalReasoningPayload( } describe("Google Vertex thinking budget payload", () => { - it.each(flashLiteModels)("uses the supported minimal budget for $id", async (model) => { - const payload = await captureMinimalReasoningPayload(model); + for (const model of flashLiteModels) { + it(`uses the supported minimal budget for ${model.id}`, async () => { + const payload = await captureMinimalReasoningPayload(model); - expect(payload.config?.thinkingConfig).toEqual({ - includeThoughts: true, - thinkingBudget: 512, + expect(payload.config?.thinkingConfig).toEqual({ + includeThoughts: true, + thinkingBudget: 512, + }); }); - }); + } }); diff --git a/packages/ai/test/lazy-module-load.test.ts b/packages/ai/test/lazy-module-load.test.ts index c94669abfb..7c707c8684 100644 --- a/packages/ai/test/lazy-module-load.test.ts +++ b/packages/ai/test/lazy-module-load.test.ts @@ -1,12 +1,11 @@ import { spawnSync } from "node:child_process"; -import { createRequire } from "node:module"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, expect, it } from "vitest"; -const require = createRequire(import.meta.url); -const tsxLoader = require.resolve("tsx/esm"); -const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const packageRoot = resolve(__dirname, ".."); const aiEntryUrl = new URL("../src/index.ts", import.meta.url).href; const SDK_SPECIFIERS = [ @@ -22,27 +21,17 @@ type ProbeResult = { }; function runProbe(action: string): ProbeResult { - const script = ` - import { registerHooks } from "node:module"; - - const targets = new Set(${JSON.stringify(SDK_SPECIFIERS)}); - const loaded = []; - - registerHooks({ - resolve(specifier, context, nextResolve) { - if (targets.has(specifier)) { - loaded.push(specifier); - } - return nextResolve(specifier, context); - }, - }); - - const mod = await import(${JSON.stringify(aiEntryUrl)}); - ${action} - console.log(JSON.stringify({ loadedSpecifiers: [...new Set(loaded)] })); - `; - - const result = spawnSync(process.execPath, ["--import", tsxLoader, "--input-type=module", "--eval", script], { + const script = [ + `const targets = ${JSON.stringify([...SDK_SPECIFIERS])};`, + `const mod = await import("${aiEntryUrl}");`, + action, + `const Module = require("module");`, + `const cacheKeys = Object.keys(Module._cache);`, + `const loaded = targets.filter((spec) => cacheKeys.some((k) => k.includes(spec)));`, + `console.log(JSON.stringify({ loadedSpecifiers: loaded }));`, + ].join("\n"); + + const result = spawnSync(process.execPath, ["--eval", script], { cwd: packageRoot, encoding: "utf8", }); @@ -70,32 +59,35 @@ describe("lazy provider module loading", () => { }); it("loads only the Anthropic SDK when calling the root lazy wrapper", () => { - const result = runProbe(` - const model = { - id: "claude-sonnet-4-6", - name: "Claude Sonnet 4", - api: "anthropic-messages", - provider: "anthropic", - baseUrl: "https://api.anthropic.com", - reasoning: true, - input: ["text"], - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - contextWindow: 200000, - maxTokens: 8192, - }; - const context = { messages: [{ role: "user", content: "hi" }] }; - await mod.streamSimpleAnthropic(model, context).result(); - `); + const result = runProbe( + [ + `const model = {`, + ` id: "claude-sonnet-4-6",`, + ` api: "anthropic-messages",`, + ` provider: "anthropic",`, + ` baseUrl: "http://127.0.0.1:9",`, + ` reasoning: true,`, + ` input: ["text"],`, + ` cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },`, + ` contextWindow: 200000,`, + ` maxTokens: 8192,`, + `};`, + `const context = { messages: [{ role: "user", content: "hi", timestamp: Date.now() }] };`, + `try { await mod.streamSimpleAnthropic(model, context).result(); } catch (_e) {}`, + ].join("\n"), + ); expect(result.loadedSpecifiers).toEqual(["@anthropic-ai/sdk"]); }); it("loads only the Anthropic SDK when dispatching through streamSimple", () => { - const result = runProbe(` - const model = mod.getModel("anthropic", "claude-sonnet-4-6"); - const context = { messages: [{ role: "user", content: "hi" }] }; - await mod.streamSimple(model, context).result(); - `); + const result = runProbe( + [ + `const model = mod.getModel("anthropic", "claude-sonnet-4-6");`, + `const context = { messages: [{ role: "user", content: "hi", timestamp: Date.now() }] };`, + `try { await mod.streamSimple(model, context).result(); } catch (_e) {}`, + ].join("\n"), + ); expect(result.loadedSpecifiers).toEqual(["@anthropic-ai/sdk"]); }); diff --git a/packages/ai/test/mcp-oauth.test.ts b/packages/ai/test/mcp-oauth.test.ts index e35f2a009d..7d222c7a37 100644 --- a/packages/ai/test/mcp-oauth.test.ts +++ b/packages/ai/test/mcp-oauth.test.ts @@ -1,5 +1,5 @@ +import { afterEach, describe, expect, it, vi } from "bun:test"; import { createServer } from "node:http"; -import { afterEach, describe, expect, it, vi } from "vitest"; import { createMcpOAuthProvider } from "../src/mcp/oauth.js"; function jsonResponse(body: unknown, status = 200, headers?: Record): Response { @@ -58,9 +58,13 @@ async function loginWithManualCode( return { creds, authUrl }; } -describe.sequential("MCP OAuth provider", () => { +describe("MCP OAuth provider", () => { + let origFetchMCP: typeof globalThis.fetch | undefined; afterEach(() => { - vi.unstubAllGlobals(); + if (origFetchMCP !== undefined) { + globalThis.fetch = origFetchMCP; + origFetchMCP = undefined; + } }); it("has a namespaced id and label", () => { @@ -92,7 +96,8 @@ describe.sequential("MCP OAuth provider", () => { } throw new Error(`unexpected fetch: ${url}`); }); - vi.stubGlobal("fetch", fetchMock); + origFetchMCP = globalThis.fetch; + globalThis.fetch = fetchMock; const { creds, authUrl } = await loginWithManualCode(createMcpOAuthProvider({ server: "plane", url: RESOURCE })); expect(creds).toMatchObject({ @@ -119,45 +124,40 @@ describe.sequential("MCP OAuth provider", () => { token_endpoint: "https://login.example/tenant/token", registration_endpoint: "https://login.example/tenant/register", }; - vi.stubGlobal( - "fetch", - vi.fn(async (input: unknown): Promise => { - const url = urlOf(input); - if (url === RESOURCE) return new Response("", { status: 404 }); - if (url === PLANE_PRM_URL) return jsonResponse({ resource: RESOURCE, authorization_servers: [issuer] }); - if (url === "https://login.example/.well-known/oauth-authorization-server/tenant") - return new Response("not metadata", { - status: 200, - headers: { "Content-Type": "text/html" }, - }); - if (url === oidcMeta) return jsonResponse(metadata); - if (url === metadata.registration_endpoint) return jsonResponse({ client_id: "c" }); - if (url === metadata.token_endpoint) return jsonResponse({ access_token: "a", expires_in: 60 }); - throw new Error(`unexpected fetch: ${url}`); - }), - ); + origFetchMCP = globalThis.fetch; + globalThis.fetch = vi.fn(async (input: unknown): Promise => { + const url = urlOf(input); + if (url === RESOURCE) return new Response("", { status: 404 }); + if (url === PLANE_PRM_URL) return jsonResponse({ resource: RESOURCE, authorization_servers: [issuer] }); + if (url === "https://login.example/.well-known/oauth-authorization-server/tenant") + return new Response("not metadata", { + status: 200, + headers: { "Content-Type": "text/html" }, + }); + if (url === oidcMeta) return jsonResponse(metadata); + if (url === metadata.registration_endpoint) return jsonResponse({ client_id: "c" }); + if (url === metadata.token_endpoint) return jsonResponse({ access_token: "a", expires_in: 60 }); + throw new Error(`unexpected fetch: ${url}`); + }); const { creds } = await loginWithManualCode(createMcpOAuthProvider({ server: "plane", url: RESOURCE })); expect(creds).toMatchObject({ resource: RESOURCE, issuer }); }); it("fails closed after protected-resource metadata selects an issuer", async () => { - vi.stubGlobal( - "fetch", - vi.fn(async (input: unknown): Promise => { - const url = urlOf(input); - if (url === RESOURCE) - return new Response("", { - status: 401, - headers: { "WWW-Authenticate": `Bearer resource_metadata="${PLANE_PRM_URL}"` }, - }); - if (url === PLANE_PRM_URL) - return jsonResponse({ resource: RESOURCE, authorization_servers: [PLANE_ISSUER] }); - if (url === PLANE_META_URL) return jsonResponse({ ...PLANE_META, issuer: "https://wrong.example" }); - if (url === "https://mcp.plane.so/http/.well-known/openid-configuration") - return new Response("", { status: 404 }); - throw new Error(`unexpected fetch: ${url}`); - }), - ); + origFetchMCP = globalThis.fetch; + globalThis.fetch = vi.fn(async (input: unknown): Promise => { + const url = urlOf(input); + if (url === RESOURCE) + return new Response("", { + status: 401, + headers: { "WWW-Authenticate": `Bearer resource_metadata="${PLANE_PRM_URL}"` }, + }); + if (url === PLANE_PRM_URL) return jsonResponse({ resource: RESOURCE, authorization_servers: [PLANE_ISSUER] }); + if (url === PLANE_META_URL) return jsonResponse({ ...PLANE_META, issuer: "https://wrong.example" }); + if (url === "https://mcp.plane.so/http/.well-known/openid-configuration") + return new Response("", { status: 404 }); + throw new Error(`unexpected fetch: ${url}`); + }); await expect( createMcpOAuthProvider({ server: "plane", url: RESOURCE }).login({ onAuth: () => {}, @@ -180,7 +180,8 @@ describe.sequential("MCP OAuth provider", () => { } throw new Error(`unexpected fetch: ${url}`); }); - vi.stubGlobal("fetch", fetchMock); + origFetchMCP = globalThis.fetch; + globalThis.fetch = fetchMock; const { creds, authUrl } = await loginWithManualCode( createMcpOAuthProvider({ server: "origin", url: ORIGIN_URL }), ); @@ -213,7 +214,8 @@ describe.sequential("MCP OAuth provider", () => { } throw new Error(`unexpected fetch: ${url}`); }); - vi.stubGlobal("fetch", fetchMock); + origFetchMCP = globalThis.fetch; + globalThis.fetch = fetchMock; const provider = createMcpOAuthProvider({ server: "plane", url: RESOURCE }); const refreshed = await provider.refreshToken({ access: "access-1", @@ -260,17 +262,15 @@ describe.sequential("MCP OAuth provider", () => { authorization_endpoint: "https://root.example/authorize", token_endpoint: "https://root.example/token", }; - vi.stubGlobal( - "fetch", - vi.fn(async (input: unknown): Promise => { - const url = urlOf(input); - if (url === "https://root.example/") return new Response("", { status: 401 }); - if (url === prm) return jsonResponse({ resource, authorization_servers: [issuer] }); - if (url === asMetadata) return jsonResponse(metadata); - if (url === metadata.token_endpoint) return jsonResponse({ access_token: "root-access" }); - throw new Error(`unexpected fetch: ${url}`); - }), - ); + origFetchMCP = globalThis.fetch; + globalThis.fetch = vi.fn(async (input: unknown): Promise => { + const url = urlOf(input); + if (url === "https://root.example/") return new Response("", { status: 401 }); + if (url === prm) return jsonResponse({ resource, authorization_servers: [issuer] }); + if (url === asMetadata) return jsonResponse(metadata); + if (url === metadata.token_endpoint) return jsonResponse({ access_token: "root-access" }); + throw new Error(`unexpected fetch: ${url}`); + }); const { creds, authUrl } = await loginWithManualCode( createMcpOAuthProvider({ server: "root", url: resource, clientId: "root-client" }), ); @@ -296,7 +296,8 @@ describe.sequential("MCP OAuth provider", () => { if (url === metadata.token_endpoint) return jsonResponse({ access_token: "query-access" }); throw new Error(`unexpected fetch: ${url}`); }); - vi.stubGlobal("fetch", fetchMock); + origFetchMCP = globalThis.fetch; + globalThis.fetch = fetchMock; const { creds } = await loginWithManualCode( createMcpOAuthProvider({ server: "query", url: resource, clientId: "query-client" }), ); @@ -314,7 +315,8 @@ describe.sequential("MCP OAuth provider", () => { if (url === PLANE_META_URL) return jsonResponse(PLANE_META); throw new Error(`unexpected fetch: ${url}`); }); - vi.stubGlobal("fetch", fetchMock); + origFetchMCP = globalThis.fetch; + globalThis.fetch = fetchMock; await expect( createMcpOAuthProvider({ server: "plane", url: RESOURCE }).refreshToken({ access: "origin-access", @@ -329,20 +331,18 @@ describe.sequential("MCP OAuth provider", () => { }); it("rejects a redirected token POST", async () => { - vi.stubGlobal( - "fetch", - vi.fn(async (input: unknown, init?: RequestInit): Promise => { - const missing = absentPrm(input); - if (missing) return missing; - const url = urlOf(input); - if (url === "https://srv.test/.well-known/oauth-authorization-server") return jsonResponse(ORIGIN_META); - if (url === ORIGIN_META.token_endpoint) { - expect(init?.redirect).toBe("error"); - return new Response("redirect", { status: 302, headers: { Location: "https://evil.test/token" } }); - } - throw new Error(`unexpected fetch: ${url}`); - }), - ); + origFetchMCP = globalThis.fetch; + globalThis.fetch = vi.fn(async (input: unknown, init?: RequestInit): Promise => { + const missing = absentPrm(input); + if (missing) return missing; + const url = urlOf(input); + if (url === "https://srv.test/.well-known/oauth-authorization-server") return jsonResponse(ORIGIN_META); + if (url === ORIGIN_META.token_endpoint) { + expect(init?.redirect).toBe("error"); + return new Response("redirect", { status: 302, headers: { Location: "https://evil.test/token" } }); + } + throw new Error(`unexpected fetch: ${url}`); + }); const provider = createMcpOAuthProvider({ server: "origin", url: ORIGIN_URL, clientId: "c" }); await expect( provider.refreshToken({ @@ -370,7 +370,8 @@ describe.sequential("MCP OAuth provider", () => { if (url === PLANE_META.token_endpoint) return jsonResponse({ access_token: "pointer-access" }); throw new Error(`unexpected fetch: ${url}`); }); - vi.stubGlobal("fetch", fetchMock); + origFetchMCP = globalThis.fetch; + globalThis.fetch = fetchMock; const { creds } = await loginWithManualCode(createMcpOAuthProvider({ server: "plane", url: RESOURCE })); expect(creds).toMatchObject({ access: "pointer-access", resource: RESOURCE, issuer: PLANE_ISSUER }); @@ -378,16 +379,14 @@ describe.sequential("MCP OAuth provider", () => { }); it("rejects protected-resource metadata for a different resource", async () => { - vi.stubGlobal( - "fetch", - vi.fn(async (input: unknown): Promise => { - const url = urlOf(input); - if (url === RESOURCE) return new Response("", { status: 401 }); - if (url === PLANE_PRM_URL) - return jsonResponse({ resource: "https://attacker.example/mcp", authorization_servers: [PLANE_ISSUER] }); - throw new Error(`unexpected fetch: ${url}`); - }), - ); + origFetchMCP = globalThis.fetch; + globalThis.fetch = vi.fn(async (input: unknown): Promise => { + const url = urlOf(input); + if (url === RESOURCE) return new Response("", { status: 401 }); + if (url === PLANE_PRM_URL) + return jsonResponse({ resource: "https://attacker.example/mcp", authorization_servers: [PLANE_ISSUER] }); + throw new Error(`unexpected fetch: ${url}`); + }); await expect( createMcpOAuthProvider({ server: "plane", url: RESOURCE }).login({ @@ -404,18 +403,16 @@ describe.sequential("MCP OAuth provider", () => { blocker.listen(53700, "127.0.0.1", () => resolve(true)); }); try { - vi.stubGlobal( - "fetch", - vi.fn(async (input: unknown): Promise => { - const missing = absentPrm(input); - if (missing) return missing; - const url = urlOf(input); - if (url === "https://srv.test/.well-known/oauth-authorization-server") return jsonResponse(ORIGIN_META); - if (url === ORIGIN_META.registration_endpoint) return jsonResponse({ client_id: "c" }); - if (url === ORIGIN_META.token_endpoint) return jsonResponse({ access_token: "a", expires_in: 60 }); - throw new Error(`unexpected fetch: ${url}`); - }), - ); + origFetchMCP = globalThis.fetch; + globalThis.fetch = vi.fn(async (input: unknown): Promise => { + const missing = absentPrm(input); + if (missing) return missing; + const url = urlOf(input); + if (url === "https://srv.test/.well-known/oauth-authorization-server") return jsonResponse(ORIGIN_META); + if (url === ORIGIN_META.registration_endpoint) return jsonResponse({ client_id: "c" }); + if (url === ORIGIN_META.token_endpoint) return jsonResponse({ access_token: "a", expires_in: 60 }); + throw new Error(`unexpected fetch: ${url}`); + }); const { authUrl } = await loginWithManualCode(createMcpOAuthProvider({ server: "demo", url: ORIGIN_URL })); const redirect = new URL(authUrl).searchParams.get("redirect_uri") ?? ""; expect(redirect).not.toContain(":53700/"); @@ -426,17 +423,15 @@ describe.sequential("MCP OAuth provider", () => { }); it("fails clearly when dynamic client registration is unavailable", async () => { - vi.stubGlobal( - "fetch", - vi.fn(async (input: unknown): Promise => { - const missing = absentPrm(input); - if (missing) return missing; - const url = urlOf(input); - if (url === "https://srv.test/.well-known/oauth-authorization-server") - return jsonResponse({ ...ORIGIN_META, registration_endpoint: undefined }); - throw new Error(`unexpected fetch: ${url}`); - }), - ); + origFetchMCP = globalThis.fetch; + globalThis.fetch = vi.fn(async (input: unknown): Promise => { + const missing = absentPrm(input); + if (missing) return missing; + const url = urlOf(input); + if (url === "https://srv.test/.well-known/oauth-authorization-server") + return jsonResponse({ ...ORIGIN_META, registration_endpoint: undefined }); + throw new Error(`unexpected fetch: ${url}`); + }); await expect( createMcpOAuthProvider({ server: "slackish", url: ORIGIN_URL }).login({ onAuth: () => {}, diff --git a/packages/ai/test/openai-codex-oauth.test.ts b/packages/ai/test/openai-codex-oauth.test.ts index 276abe1bfe..6e86f5e982 100644 --- a/packages/ai/test/openai-codex-oauth.test.ts +++ b/packages/ai/test/openai-codex-oauth.test.ts @@ -1,28 +1,30 @@ -import { afterEach, describe, expect, it, vi } from "vitest"; +import { afterEach, describe, expect, it, vi } from "bun:test"; import { refreshOpenAICodexToken } from "../src/utils/oauth/openai-codex.js"; describe("OpenAI Codex OAuth", () => { + let origFetchCodex: typeof globalThis.fetch | undefined; afterEach(() => { vi.restoreAllMocks(); - vi.unstubAllGlobals(); + if (origFetchCodex !== undefined) { + globalThis.fetch = origFetchCodex; + origFetchCodex = undefined; + } }); it("does not write token refresh failures to stderr", async () => { const consoleError = vi.spyOn(console, "error").mockImplementation(() => {}); - vi.stubGlobal( - "fetch", - vi.fn(async (): Promise => { - return new Response( - JSON.stringify({ - error: { - message: "Could not validate your token. Please try signing in again.", - type: "invalid_request_error", - }, - }), - { status: 401, statusText: "Unauthorized", headers: { "Content-Type": "application/json" } }, - ); - }), - ); + origFetchCodex = globalThis.fetch; + globalThis.fetch = vi.fn(async (): Promise => { + return new Response( + JSON.stringify({ + error: { + message: "Could not validate your token. Please try signing in again.", + type: "invalid_request_error", + }, + }), + { status: 401, statusText: "Unauthorized", headers: { "Content-Type": "application/json" } }, + ); + }); await expect(refreshOpenAICodexToken("invalid-refresh-token")).rejects.toThrow( /OpenAI Codex token refresh failed \(401\).*Could not validate your token/, diff --git a/packages/ai/test/openai-codex-stream.test.ts b/packages/ai/test/openai-codex-stream.test.ts index e05b9d9831..4a6c84b583 100644 --- a/packages/ai/test/openai-codex-stream.test.ts +++ b/packages/ai/test/openai-codex-stream.test.ts @@ -543,6 +543,7 @@ describe("openai-codex streaming", () => { provider: "openai-codex", baseUrl: "https://chatgpt.com/backend-api", reasoning: true, + thinkingLevelMap: { minimal: "low" }, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 400000, @@ -554,9 +555,9 @@ describe("openai-codex streaming", () => { messages: [{ role: "user", content: "Say hello", timestamp: Date.now() }], }; - const streamResult = streamOpenAICodexResponses(model, context, { + const streamResult = streamSimpleOpenAICodexResponses(model, context, { apiKey: token, - reasoningEffort: "minimal", + reasoning: "minimal", }); await streamResult.result(); }); diff --git a/packages/ai/test/openai-completions-cache-control-format.test.ts b/packages/ai/test/openai-completions-cache-control-format.test.ts index 9b6f66c46a..66ac4ed9b8 100644 --- a/packages/ai/test/openai-completions-cache-control-format.test.ts +++ b/packages/ai/test/openai-completions-cache-control-format.test.ts @@ -28,9 +28,9 @@ interface CapturedParams { tools?: ToolWithCacheControl[]; } -const mockState = vi.hoisted(() => ({ - lastParams: undefined as CapturedParams | undefined, -})); +const mockState: { lastParams: CapturedParams | undefined } = { + lastParams: undefined, +}; const emptyUsage: Usage = { input: 0, diff --git a/packages/ai/test/openai-completions-empty-tools.test.ts b/packages/ai/test/openai-completions-empty-tools.test.ts index 61a65c1df4..9dbb733905 100644 --- a/packages/ai/test/openai-completions-empty-tools.test.ts +++ b/packages/ai/test/openai-completions-empty-tools.test.ts @@ -4,10 +4,10 @@ import { CLOUDFLARE_AI_GATEWAY_COMPAT_BASE_URL } from "../src/providers/cloudfla import { streamSimple } from "../src/stream.js"; import type { Model } from "../src/types.js"; -const mockState = vi.hoisted(() => ({ - lastParams: undefined as unknown, - lastClientOptions: undefined as unknown, -})); +const mockState: { lastParams: unknown; lastClientOptions: unknown } = { + lastParams: undefined, + lastClientOptions: undefined, +}; vi.mock("openai", () => { class FakeOpenAI { diff --git a/packages/ai/test/openai-completions-prompt-cache.test.ts b/packages/ai/test/openai-completions-prompt-cache.test.ts index 147097efc4..d2c54f2fff 100644 --- a/packages/ai/test/openai-completions-prompt-cache.test.ts +++ b/packages/ai/test/openai-completions-prompt-cache.test.ts @@ -15,10 +15,13 @@ interface CapturedCompletionsPayload { prompt_cache_retention?: "24h" | "in-memory" | null; } -const mockState = vi.hoisted(() => ({ - lastParams: undefined as CapturedCompletionsPayload | undefined, - lastClientOptions: undefined as FakeOpenAIClientOptions | undefined, -})); +const mockState: { + lastParams: CapturedCompletionsPayload | undefined; + lastClientOptions: FakeOpenAIClientOptions | undefined; +} = { + lastParams: undefined, + lastClientOptions: undefined, +}; vi.mock("openai", () => { class FakeOpenAI { diff --git a/packages/ai/test/openai-completions-response-model.test.ts b/packages/ai/test/openai-completions-response-model.test.ts index a7592b0eb0..a85f14fec7 100644 --- a/packages/ai/test/openai-completions-response-model.test.ts +++ b/packages/ai/test/openai-completions-response-model.test.ts @@ -2,9 +2,9 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { complete } from "../src/stream.js"; import type { Model } from "../src/types.js"; -const mockState = vi.hoisted(() => ({ - chunks: [] as unknown[], -})); +const mockState: { chunks: unknown[] } = { + chunks: [], +}; vi.mock("openai", () => { class FakeOpenAI { diff --git a/packages/ai/test/openai-completions-tool-choice.test.ts b/packages/ai/test/openai-completions-tool-choice.test.ts index 64dd360b75..4f305bacf8 100644 --- a/packages/ai/test/openai-completions-tool-choice.test.ts +++ b/packages/ai/test/openai-completions-tool-choice.test.ts @@ -5,21 +5,20 @@ import { streamSimple } from "../src/stream.js"; import type { Tool } from "../src/types.js"; import { getZaiTestModel } from "./zai-test-model.js"; -const mockState = vi.hoisted(() => ({ - lastParams: undefined as unknown, - chunks: undefined as - | Array; finish_reason: string | null; usage?: unknown }>; - usage?: { - prompt_tokens: number; - completion_tokens: number; - prompt_tokens_details: { cached_tokens: number; cache_write_tokens?: number }; - completion_tokens_details: { reasoning_tokens: number }; - }; - }> - | undefined, -})); +interface ChunkItem { + id?: string; + choices?: Array<{ delta: Record; finish_reason: string | null; usage?: unknown }>; + usage?: { + prompt_tokens: number; + completion_tokens: number; + prompt_tokens_details: { cached_tokens: number; cache_write_tokens?: number }; + completion_tokens_details: { reasoning_tokens: number }; + }; +} +const mockState: { lastParams: unknown; chunks: Array | undefined } = { + lastParams: undefined, + chunks: undefined, +}; vi.mock("openai", () => { class FakeOpenAI { diff --git a/packages/ai/vitest.config.ts b/packages/ai/vitest.config.ts deleted file mode 100644 index 1b07c96f24..0000000000 --- a/packages/ai/vitest.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { defineConfig } from 'vitest/config'; - -export default defineConfig({ - test: { - globals: true, - environment: 'node', - testTimeout: 30000, // 30 seconds for API calls - } -}); \ No newline at end of file diff --git a/packages/coding-agent/bunfig.toml b/packages/coding-agent/bunfig.toml new file mode 100644 index 0000000000..03378bb026 --- /dev/null +++ b/packages/coding-agent/bunfig.toml @@ -0,0 +1,3 @@ +[test] +preload = ["./test/bun-test-preload.ts"] +timeout = 30000 diff --git a/packages/coding-agent/package.json b/packages/coding-agent/package.json index 6fa9370fe3..7d2896f277 100644 --- a/packages/coding-agent/package.json +++ b/packages/coding-agent/package.json @@ -37,14 +37,14 @@ "build:binary": "bun run --cwd ../tui build && bun run --cwd ../ai build && bun run --cwd ../agent build && bun run build && bun build --compile ./dist/bun/cli.js --outfile dist/pi && bun scripts/copy-assets.ts binary", "copy-assets": "bun scripts/copy-assets.ts package", "copy-binary-assets": "bun scripts/copy-assets.ts binary", - "test": "vitest --run", - "test:ci": "tsx src/core/kernel/bootstrap-cli.ts && vitest --run --exclude test/daemon-supervisor-process.test.ts", - "test:process": "vitest --run test/daemon-supervisor-process.test.ts", - "test:process-stress": "vitest --run --tagsFilter process-stress test/daemon-supervisor-process.test.ts", + "test": "bun ../../scripts/run-with-clean-env.ts bun scripts/run-tests.ts", + "test:ci": "bun ../../scripts/run-with-clean-env.ts bun src/core/kernel/bootstrap-cli.ts && bun ../../scripts/run-with-clean-env.ts bun scripts/run-tests.ts", + "test:process": "bun ../../scripts/run-with-clean-env.ts bun test --isolate --timeout 30000 test/daemon-supervisor-process.test.ts", + "test:process-stress": "PRIME_AGENT_TEST_TAGS=process-stress bun ../../scripts/run-with-clean-env.ts bun test --isolate --timeout 30000 test/daemon-supervisor-process.test.ts", "postinstall": "bun postinstall.cjs", "prepublishOnly": "bun run clean && bun run build", "bundle": "bun scripts/bundle.mjs", - "test:kernel": "vitest --run --no-file-parallelism --tagsFilter kernel-heavy test/acp-kernel-features.test.ts test/acp-cold-cli.test.ts test/kernel-goal-skill.test.ts test/repl-kernel-state-roundtrip.test.ts test/repl-kernel-mcp-shutdown.test.ts" + "test:kernel": "PRIME_AGENT_TEST_TAGS=kernel-heavy bun ../../scripts/run-with-clean-env.ts bun test --isolate --timeout 30000 test/acp-kernel-features.test.ts test/acp-cold-cli.test.ts test/kernel-goal-skill.test.ts test/repl-kernel-state-roundtrip.test.ts test/repl-kernel-mcp-shutdown.test.ts test/repl-kernel-parent-watchdog.test.ts" }, "dependencies": { "@agentclientprotocol/sdk": "^1.3.0", @@ -83,10 +83,7 @@ "@types/ms": "^2.1.0", "@types/node": "^24.3.0", "@types/proper-lockfile": "^4.1.4", - "esbuild": "^0.28.1", - "shx": "^0.4.0", - "typescript": "^7.0.2", - "vitest": "^4.1.10" + "typescript": "^7.0.2" }, "keywords": [ "coding-agent", @@ -104,6 +101,7 @@ "directory": "packages/coding-agent" }, "engines": { - "node": ">=22.8.0" + "node": ">=22.8.0", + "bun": "1.3.14" } } diff --git a/packages/coding-agent/scripts/run-tests.ts b/packages/coding-agent/scripts/run-tests.ts new file mode 100644 index 0000000000..caaf9d42ac --- /dev/null +++ b/packages/coding-agent/scripts/run-tests.ts @@ -0,0 +1,61 @@ +#!/usr/bin/env bun + +interface Shard { + index: number; + total: number; +} + +function parseShard(args: string[]): { shard?: Shard; forwarded: string[] } { + let shard: Shard | undefined; + const forwarded: string[] = []; + for (const arg of args) { + if (!arg.startsWith("--shard=")) { + forwarded.push(arg); + continue; + } + const match = arg.slice("--shard=".length).match(/^(\d+)\/(\d+)$/); + if (!match) throw new Error(`Invalid shard: ${arg}`); + const index = Number(match[1]); + const total = Number(match[2]); + if (!Number.isInteger(index) || !Number.isInteger(total) || index < 1 || index > total) { + throw new Error(`Invalid shard: ${arg}`); + } + shard = { index, total }; + } + return { shard, forwarded }; +} + +const excluded = new Set(["test/compiled-artifact-smoke.test.ts", "test/daemon-supervisor-process.test.ts"]); +const { shard, forwarded } = parseShard(process.argv.slice(2)); +const discovered: string[] = []; +for await (const file of new Bun.Glob("test/**/*.test.ts").scan({ cwd: process.cwd(), onlyFiles: true })) { + if (!excluded.has(file)) discovered.push(file); +} +discovered.sort(); +const selected = shard + ? discovered.filter((_file, position) => position % shard.total === shard.index - 1) + : discovered; + +console.log( + `Running ${selected.length}/${discovered.length} coding-agent test files${shard ? ` (shard ${shard.index}/${shard.total})` : ""}`, +); + +const failures: Array<{ file: string; exitCode: number }> = []; +for (const file of selected) { + const child = Bun.spawn([process.execPath, "test", "--isolate", "--timeout", "30000", ...forwarded, file], { + cwd: process.cwd(), + env: process.env, + stdin: "ignore", + stdout: "inherit", + stderr: "inherit", + }); + const exitCode = await child.exited; + if (exitCode !== 0) failures.push({ file, exitCode }); +} + +if (failures.length > 0) { + console.error(`Failed coding-agent test files (${failures.length}/${selected.length}):`); + for (const failure of failures) console.error(`- ${failure.file} (exit ${failure.exitCode})`); + process.exit(1); +} +console.log(`Passed ${selected.length} coding-agent test files.`); diff --git a/packages/coding-agent/test/acp-cold-cli.test.ts b/packages/coding-agent/test/acp-cold-cli.test.ts index 38a3760e1a..a91ca9039b 100644 --- a/packages/coding-agent/test/acp-cold-cli.test.ts +++ b/packages/coding-agent/test/acp-cold-cli.test.ts @@ -5,6 +5,7 @@ import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import { ENV_AGENT_DIR } from "../src/config.js"; +import { isTestTagEnabled } from "./test-tags.js"; /** * Cold real-CLI ACP coverage. @@ -17,7 +18,6 @@ import { ENV_AGENT_DIR } from "../src/config.js"; */ const cliPath = resolve(__dirname, "../src/cli.ts"); -const tsxPath = resolve(__dirname, "../../../node_modules/tsx/dist/cli.mjs"); const tempDirs: string[] = []; const servers: Server[] = []; @@ -74,7 +74,6 @@ async function driveAcpTurn(baseUrl: string): Promise { const child = spawn( process.execPath, [ - tsxPath, cliPath, "--mode", "acp", @@ -93,7 +92,6 @@ async function driveAcpTurn(baseUrl: string): Promise { ...process.env, [ENV_AGENT_DIR]: agentDir, HOME: agentDir, - TSX_TSCONFIG_PATH: resolve(__dirname, "../../../tsconfig.json"), }, stdio: ["pipe", "pipe", "pipe"], }, @@ -186,10 +184,8 @@ async function driveAcpTurn(baseUrl: string): Promise { } describe("ACP mode over a cold real CLI process", () => { - it("reports a provider failure instead of a silent end_turn", { - tags: ["kernel-heavy"], - timeout: 180_000, - }, async () => { + const kernelHeavyIt = isTestTagEnabled("kernel-heavy") ? it : it.skip; + kernelHeavyIt("reports a provider failure instead of a silent end_turn", { timeout: 180_000 }, async () => { const baseUrl = await startRejectingProvider(); const { responses, updates } = await driveAcpTurn(baseUrl); diff --git a/packages/coding-agent/test/acp-kernel-features.test.ts b/packages/coding-agent/test/acp-kernel-features.test.ts index e333d382e6..78303ff199 100644 --- a/packages/coding-agent/test/acp-kernel-features.test.ts +++ b/packages/coding-agent/test/acp-kernel-features.test.ts @@ -9,6 +9,7 @@ import { IpythonKernelProvisioner } from "../src/core/tools/ipython.js"; import { acpUpdatesForSessionEvent } from "../src/modes/acp/acp-events.js"; import { PRIME_AGENT_META_NAMESPACE } from "../src/modes/acp/acp-meta.js"; import type { AgentConnectionSessionEvent } from "../src/modes/agent-connection/types.js"; +import { isTestTagEnabled } from "./test-tags.js"; /** * Real-kernel verification for ACP mode. @@ -43,6 +44,7 @@ function toolEndEvent(toolCallId: string, output: string, isError = false): Agen } describe("ACP mode over a real Python kernel", () => { + const kernelHeavyIt = isTestTagEnabled("kernel-heavy") ? it : it.skip; let tempDir: string; let provisioner: IpythonKernelProvisioner | undefined; @@ -57,43 +59,44 @@ describe("ACP mode over a real Python kernel", () => { rmSync(tempDir, { recursive: true, force: true }); }); - it("keeps Python state across cells and represents each cell as an ACP execute call", { - tags: ["kernel-heavy"], - timeout: 180_000, - }, async () => { - // Every provisioner in this file requests the same skill set: the kernel venv - // is shared, and a skill-less kernel here can leave a later skill-dependent - // test with an unsynced venv when files run concurrently. - provisioner = new IpythonKernelProvisioner(tempDir, { pythonSkills: [AGENT_MESSAGE_SKILL] }); - const manager: KernelClient = await provisioner.ensure(); + kernelHeavyIt( + "keeps Python state across cells and represents each cell as an ACP execute call", + { timeout: 180_000 }, + async () => { + // Every provisioner in this file requests the same skill set: the kernel venv + // is shared, and a skill-less kernel here can leave a later skill-dependent + // test with an unsynced venv when files run concurrently. + provisioner = new IpythonKernelProvisioner(tempDir, { pythonSkills: [AGENT_MESSAGE_SKILL] }); + const manager: KernelClient = await provisioner.ensure(); - const first = await manager.execute("acp_state = 41\nprint('set')"); - expect(first.status).toBe("ok"); - // Persistence is the whole point of the kernel: a second cell must see it. - const second = await manager.execute("print(acp_state + 1)"); - expect(second.status).toBe("ok"); - expect(second.stdout.trim()).toBe("42"); + const first = await manager.execute("acp_state = 41\nprint('set')"); + expect(first.status).toBe("ok"); + // Persistence is the whole point of the kernel: a second cell must see it. + const second = await manager.execute("print(acp_state + 1)"); + expect(second.status).toBe("ok"); + expect(second.stdout.trim()).toBe("42"); - const updates = acpUpdatesForSessionEvent(toolEndEvent("cell-2", second.stdout)); - expect(updates[0]).toMatchObject({ - sessionUpdate: "tool_call_update", - toolCallId: "cell-2", - status: "completed", - }); - expect(JSON.stringify(updates[0]?.content)).toContain("42"); - }); + const updates = acpUpdatesForSessionEvent(toolEndEvent("cell-2", second.stdout)); + expect(updates[0]).toMatchObject({ + sessionUpdate: "tool_call_update", + toolCallId: "cell-2", + status: "completed", + }); + expect(JSON.stringify(updates[0]?.content)).toContain("42"); + }, + ); - it("runs continual-harness CRUD in the kernel and can represent the result over ACP", { - tags: ["kernel-heavy"], - timeout: 180_000, - }, async () => { - provisioner = new IpythonKernelProvisioner(tempDir, { - pythonSkills: [AGENT_MESSAGE_SKILL], - env: { RLM_GLOBAL_HARNESS_STATE_DIR: join(tempDir, "harness") }, - }); - const manager = await provisioner.ensure(); + kernelHeavyIt( + "runs continual-harness CRUD in the kernel and can represent the result over ACP", + { timeout: 180_000 }, + async () => { + provisioner = new IpythonKernelProvisioner(tempDir, { + pythonSkills: [AGENT_MESSAGE_SKILL], + env: { RLM_GLOBAL_HARNESS_STATE_DIR: join(tempDir, "harness") }, + }); + const manager = await provisioner.ensure(); - const allKinds = await manager.execute(` + const allKinds = await manager.execute(` import json mem = rlm.harness.create_memory(title="m", content="memory content", global_=True) note = rlm.harness.create_prompt_note(title="n", content="prompt note content", global_=True) @@ -110,15 +113,15 @@ print(json.dumps({ "skill_ref": skill.reference.get("import"), }, sort_keys=True)) `); - expect(allKinds.status, why(allKinds)).toBe("ok"); - // Every editable harness kind, not just memory: skills additionally require - // a python reference and an argument contract. - expect(JSON.parse(allKinds.stdout.trim())).toMatchObject({ - kinds: ["memory", "prompt", "skill", "subagent"], - skill_ref: "pkg.mod", - }); + expect(allKinds.status, why(allKinds)).toBe("ok"); + // Every editable harness kind, not just memory: skills additionally require + // a python reference and an argument contract. + expect(JSON.parse(allKinds.stdout.trim())).toMatchObject({ + kinds: ["memory", "prompt", "skill", "subagent"], + skill_ref: "pkg.mod", + }); - const result = await manager.execute(` + const result = await manager.execute(` import json entry = rlm.harness.create_memory( title="ACP verification memory", @@ -137,61 +140,62 @@ print(json.dumps({ "after": after.title if after else None, }, sort_keys=True)) `); - expect(result.status, why(result)).toBe("ok"); - const payload = JSON.parse(result.stdout.trim()); - expect(payload.found).toBe("ACP verification memory"); - expect(payload.listed).toContain(payload.created); - expect(payload.deleted).toBe(true); - expect(payload.after).toBeNull(); + expect(result.status, why(result)).toBe("ok"); + const payload = JSON.parse(result.stdout.trim()); + expect(payload.found).toBe("ACP verification memory"); + expect(payload.listed).toContain(payload.created); + expect(payload.deleted).toBe(true); + expect(payload.after).toBeNull(); - // A refinement outcome for that CRUD is expressible as namespaced metadata. - const refined = acpUpdatesForSessionEvent({ - type: "refine_complete", - result: { - summary: "persisted ACP verification memory", - appliedEdits: [{ applied: true, action: "create", kind: "memory", id: payload.created }], - }, - } as AgentConnectionSessionEvent); - expect(refined[0]?._meta).toMatchObject({ - [PRIME_AGENT_META_NAMESPACE]: { refinement: { status: "complete" } }, - }); - }); + // A refinement outcome for that CRUD is expressible as namespaced metadata. + const refined = acpUpdatesForSessionEvent({ + type: "refine_complete", + result: { + summary: "persisted ACP verification memory", + appliedEdits: [{ applied: true, action: "create", kind: "memory", id: payload.created }], + }, + } as AgentConnectionSessionEvent); + expect(refined[0]?._meta).toMatchObject({ + [PRIME_AGENT_META_NAMESPACE]: { refinement: { status: "complete" } }, + }); + }, + ); - it("exposes rlm depth and subagent APIs to the kernel behind the ACP front end", { - tags: ["kernel-heavy"], - timeout: 180_000, - }, async () => { - provisioner = new IpythonKernelProvisioner(tempDir, { - pythonSkills: [AGENT_MESSAGE_SKILL], - env: { RLM_DEPTH: "0", RLM_MAX_DEPTH: "1" }, - hostHandlers: { - "rlm.list_subagents": async () => ({ - subagents: [ - { - rlm_child_id: "child-1", - active_session_id: "active-1", + kernelHeavyIt( + "exposes rlm depth and subagent APIs to the kernel behind the ACP front end", + { timeout: 180_000 }, + async () => { + provisioner = new IpythonKernelProvisioner(tempDir, { + pythonSkills: [AGENT_MESSAGE_SKILL], + env: { RLM_DEPTH: "0", RLM_MAX_DEPTH: "1" }, + hostHandlers: { + "rlm.list_subagents": async () => ({ + subagents: [ + { + rlm_child_id: "child-1", + active_session_id: "active-1", + session_id: "session-1", + session_name: "reviewer", + session_dir: tempDir, + status: "completed", + }, + ], + }), + "rlm.delete_subagent": async (payload) => ({ + subagent: { + rlm_child_id: String(payload.target), + active_session_id: null, session_id: "session-1", session_name: "reviewer", session_dir: tempDir, status: "completed", }, - ], - }), - "rlm.delete_subagent": async (payload) => ({ - subagent: { - rlm_child_id: String(payload.target), - active_session_id: null, - session_id: "session-1", - session_name: "reviewer", - session_dir: tempDir, - status: "completed", - }, - }), - }, - }); - const manager = await provisioner.ensure(); + }), + }, + }); + const manager = await provisioner.ensure(); - const result = await manager.execute(` + const result = await manager.execute(` import json, os children = await rlm.list_subagents() removed = await rlm.delete_subagent(children[0]) @@ -202,50 +206,53 @@ print(json.dumps({ "removed": removed.session_name, }, sort_keys=True)) `); - expect(result.status, why(result)).toBe("ok"); - const payload = JSON.parse(result.stdout.trim()); - expect(payload.names).toEqual(["reviewer"]); - expect(payload.removed).toBe("reviewer"); - expect(payload.depth).toBe("0"); - expect(payload.max_depth).toBe("1"); - }); + expect(result.status, why(result)).toBe("ok"); + const payload = JSON.parse(result.stdout.trim()); + expect(payload.names).toEqual(["reviewer"]); + expect(payload.removed).toBe("reviewer"); + expect(payload.depth).toBe("0"); + expect(payload.max_depth).toBe("1"); + }, + ); - it("sends an agent-to-agent message from the kernel and surfaces it over ACP", { - tags: ["kernel-heavy"], - timeout: 180_000, - }, async () => { - provisioner = new IpythonKernelProvisioner(tempDir, { - pythonSkills: [AGENT_MESSAGE_SKILL], - hostHandlers: { - // The family roster: parent, siblings, and children of this agent. - "agent_message.list_agents": async () => ({ - current: { name: "root", id: "session-alpha", depth: 0 }, - entries: [{ relationship: "child", name: "reviewer", id: "session-beta", depth: 1, status: "idle" }], - }), - "agent_message.send": async (payload) => ({ - id: "agentmsg-acp", - source: "agent_message", - target: { activeSessionId: "beta", sessionId: "session-beta", sessionName: "reviewer" }, - message: payload.message, - deliveryStatus: "queued", - queuedAt: "2026-08-04T00:00:00.000Z", - deliveryMode: payload.mode ?? "auto", - }), - }, - }); - const manager = await provisioner.ensure(); + kernelHeavyIt( + "sends an agent-to-agent message from the kernel and surfaces it over ACP", + { timeout: 180_000 }, + async () => { + provisioner = new IpythonKernelProvisioner(tempDir, { + pythonSkills: [AGENT_MESSAGE_SKILL], + hostHandlers: { + // The family roster: parent, siblings, and children of this agent. + "agent_message.list_agents": async () => ({ + current: { name: "root", id: "session-alpha", depth: 0 }, + entries: [{ relationship: "child", name: "reviewer", id: "session-beta", depth: 1, status: "idle" }], + }), + "agent_message.send": async (payload) => ({ + id: "agentmsg-acp", + source: "agent_message", + target: { activeSessionId: "beta", sessionId: "session-beta", sessionName: "reviewer" }, + message: payload.message, + deliveryStatus: "queued", + queuedAt: "2026-08-04T00:00:00.000Z", + deliveryMode: payload.mode ?? "auto", + }), + }, + }); + const manager = await provisioner.ensure(); - // The kernel venv is shared across test files. If a concurrently running - // file rebuilt it without this skill, say so plainly rather than failing - // later with an opaque AttributeError on the stub object. - const available = await manager.execute("import json; print(json.dumps({'kind': type(agent_message).__name__}))"); - expect(available.status, why(available)).toBe("ok"); - expect( - JSON.parse(available.stdout.trim()).kind, - "agent_message skill was not installed into the shared kernel venv", - ).not.toBe("_PrimeAgentUnavailableSkill"); + // The kernel venv is shared across test files. If a concurrently running + // file rebuilt it without this skill, say so plainly rather than failing + // later with an opaque AttributeError on the stub object. + const available = await manager.execute( + "import json; print(json.dumps({'kind': type(agent_message).__name__}))", + ); + expect(available.status, why(available)).toBe("ok"); + expect( + JSON.parse(available.stdout.trim()).kind, + "agent_message skill was not installed into the shared kernel venv", + ).not.toBe("_PrimeAgentUnavailableSkill"); - const result = await manager.execute(` + const result = await manager.execute(` import json roster = await agent_message.list_agents() receipt = await agent_message.send("status update", receiver_role="child", receiver_name="reviewer") @@ -254,22 +261,23 @@ print(json.dumps({ "status": receipt["deliveryStatus"], })) `); - expect(result.status, why(result)).toBe("ok"); - const payload = JSON.parse(result.stdout.trim()); - expect(payload.roster).toEqual(["reviewer"]); - expect(payload.status).toBe("queued"); + expect(result.status, why(result)).toBe("ok"); + const payload = JSON.parse(result.stdout.trim()); + expect(payload.roster).toEqual(["reviewer"]); + expect(payload.status).toBe("queued"); - // The kernel reports the send; ACP carries it as namespaced metadata. - const sentMessages = result.sentAgentMessages ?? []; - expect(sentMessages.length).toBeGreaterThan(0); - const sent = sentMessages[0]; - const updates = acpUpdatesForSessionEvent({ - type: "ipython_sent_agent_message", - toolCallId: "cell-msg", - message: sent, - } as AgentConnectionSessionEvent); - expect(updates[0]?._meta).toMatchObject({ - [PRIME_AGENT_META_NAMESPACE]: { agentMessage: { toolCallId: "cell-msg", deliveryStatus: "queued" } }, - }); - }); + // The kernel reports the send; ACP carries it as namespaced metadata. + const sentMessages = result.sentAgentMessages ?? []; + expect(sentMessages.length).toBeGreaterThan(0); + const sent = sentMessages[0]; + const updates = acpUpdatesForSessionEvent({ + type: "ipython_sent_agent_message", + toolCallId: "cell-msg", + message: sent, + } as AgentConnectionSessionEvent); + expect(updates[0]?._meta).toMatchObject({ + [PRIME_AGENT_META_NAMESPACE]: { agentMessage: { toolCallId: "cell-msg", deliveryStatus: "queued" } }, + }); + }, + ); }); diff --git a/packages/coding-agent/test/agent-connection-daemon.test.ts b/packages/coding-agent/test/agent-connection-daemon.test.ts index a0ebd66557..5c2ec6e500 100644 --- a/packages/coding-agent/test/agent-connection-daemon.test.ts +++ b/packages/coding-agent/test/agent-connection-daemon.test.ts @@ -1958,11 +1958,9 @@ describe("DaemonAgentConnection", () => { expect(fakeClient.reconnectCount).toBe(0); expect(closedEvents).toHaveLength(1); - expect(closedEvents[0]).toMatchObject({ - type: "closed", - error: expect.stringContaining("The Prime Agent daemon shut down while this window was attached."), - }); + expect(closedEvents[0]?.type).toBe("closed"); const closedError = closedEvents[0]?.type === "closed" ? closedEvents[0].error : undefined; + expect(closedError).toContain("The Prime Agent daemon shut down while this window was attached."); expect(closedError).toContain("Session ID: session-current."); expect(closedError).toContain("Session file: /tmp/session-current.jsonl."); expect(closedError).toContain("Diagnostic log:"); diff --git a/packages/coding-agent/test/agent-session-concurrent.test.ts b/packages/coding-agent/test/agent-session-concurrent.test.ts index 1c8a6f950f..2e8db829a6 100644 --- a/packages/coding-agent/test/agent-session-concurrent.test.ts +++ b/packages/coding-agent/test/agent-session-concurrent.test.ts @@ -817,7 +817,7 @@ describe("AgentSession concurrent prompt guard", () => { await session.prompt("First message"); expect(session.isStreaming).toBe(false); - await expect(session.prompt("Second message")).resolves.not.toThrow(); + await expect(session.prompt("Second message")).resolves.toBeUndefined(); }); it("should wait for queued agent events before emitting tool_call", async () => { diff --git a/packages/coding-agent/test/agent-session-services.test.ts b/packages/coding-agent/test/agent-session-services.test.ts index 7c1eec6c7c..244b4866c4 100644 --- a/packages/coding-agent/test/agent-session-services.test.ts +++ b/packages/coding-agent/test/agent-session-services.test.ts @@ -298,7 +298,7 @@ describe("createAgentSessionFromServices", () => { _createKernelHostHandlers(): Record; } )._createKernelHostHandlers(), - ).not.toHaveProperty("agent_message.send"); + ).not.toHaveProperty(["agent_message.send"]); } finally { session.dispose(); } @@ -403,7 +403,7 @@ describe("createAgentSessionFromServices", () => { }); try { expect(visibleSkillNames(withMessageController)).toContain(AGENT_MESSAGE_SKILL_NAME); - expect(kernelHostHandlers(withMessageController)).toHaveProperty("agent_message.send"); + expect(kernelHostHandlers(withMessageController)).toHaveProperty(["agent_message.send"]); } finally { withMessageController.dispose(); } diff --git a/packages/coding-agent/test/agents-view-mode.test.ts b/packages/coding-agent/test/agents-view-mode.test.ts index d471269723..1e5ef8a03e 100644 --- a/packages/coding-agent/test/agents-view-mode.test.ts +++ b/packages/coding-agent/test/agents-view-mode.test.ts @@ -1,3 +1,4 @@ +import { createRequire } from "node:module"; import { setKeybindings } from "@earendil-works/pi-tui"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { KeybindingsManager } from "../src/core/keybindings.js"; @@ -29,10 +30,8 @@ const modeMocks = vi.hoisted(() => ({ clientRequest: vi.fn<() => Promise>(), })); -vi.mock("../src/config.js", async (importOriginal) => { - const actual = await importOriginal(); - return { ...actual, appendRotatingLog: vi.fn() }; -}); +const __configJs = createRequire(import.meta.url)("../src/config.js"); +vi.mock("../src/config.js", () => ({ ...__configJs, appendRotatingLog: vi.fn() })); vi.mock("../src/modes/daemon/daemon-client.js", () => ({ DaemonClient: class { @@ -49,16 +48,14 @@ vi.mock("../src/modes/agent-connection/daemon-agent-connection.js", () => ({ }), })); -vi.mock("../src/modes/interactive/interactive-mode.js", async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - InteractiveMode: class { - run = modeMocks.interactiveRun; - teardownSessionUi = modeMocks.teardownSessionUi; - }, - }; -}); +const __interactiveMode = createRequire(import.meta.url)("../src/modes/interactive/interactive-mode.js"); +vi.mock("../src/modes/interactive/interactive-mode.js", () => ({ + ...__interactiveMode, + InteractiveMode: class { + run = modeMocks.interactiveRun; + teardownSessionUi = modeMocks.teardownSessionUi; + }, +})); function summary(overrides: Partial = {}): SessionSummary { return { diff --git a/packages/coding-agent/test/assistant-message-streaming-bench.ts b/packages/coding-agent/test/assistant-message-streaming-bench.ts index 1597ca6dec..b22d70b351 100644 --- a/packages/coding-agent/test/assistant-message-streaming-bench.ts +++ b/packages/coding-agent/test/assistant-message-streaming-bench.ts @@ -4,7 +4,7 @@ * Mimics the interactive-mode `message_update` handler: for each token chunk, * call updateContent() with the grown message and render(). Run with: * - * npx tsx test/assistant-message-streaming-bench.ts + * bun test/assistant-message-streaming-bench.ts */ import { performance } from "node:perf_hooks"; import type { AssistantMessage } from "@earendil-works/pi-ai"; diff --git a/packages/coding-agent/test/builtin-skills.test.ts b/packages/coding-agent/test/builtin-skills.test.ts index 8272ff0ca1..a94f81b146 100644 --- a/packages/coding-agent/test/builtin-skills.test.ts +++ b/packages/coding-agent/test/builtin-skills.test.ts @@ -2,6 +2,7 @@ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; +import { REQUIRED_BINARY_SIDECARS } from "../../../scripts/compiled-artifact-smoke.js"; import { getBundledSkillsDir } from "../src/config.js"; import { DefaultPackageManager } from "../src/core/package-manager.js"; import { DefaultResourceLoader } from "../src/core/resource-loader.js"; @@ -297,26 +298,16 @@ describe("builtin skills", () => { // Verify every shipping path includes bundled skills; source-only success would hide a release packaging regression. describe("packaging ships bundled skills", () => { const packageRoot = join(__dirname, ".."); - const repoRoot = join(packageRoot, "..", ".."); - it("npm build (copy-assets) copies skills into dist", () => { + it("package and binary builds require bundled skills", () => { const pkg = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf-8")) as { files?: string[]; scripts?: Record; }; - expect(pkg.scripts?.["copy-assets"]).toContain("skills dist/skills"); - // npm publish ships the source skills/ dir via the files allowlist too. + expect(pkg.scripts?.["copy-assets"]).toBe("bun scripts/copy-assets.ts package"); + expect(pkg.scripts?.["copy-binary-assets"]).toBe("bun scripts/copy-assets.ts binary"); expect(pkg.files).toContain("skills"); - }); - - it("binary release script copies skills next to the executable", () => { - const script = readFileSync(join(repoRoot, "scripts", "build-binaries.sh"), "utf-8"); - expect(script).toMatch(/cp -r skills binaries\/\$platform\//); - }); - - it("release packer includes skills in the packed package", () => { - const script = readFileSync(join(repoRoot, "scripts", "pack-prime-agent-release.mjs"), "utf-8"); - expect(script).toContain('"skills"'); + expect(REQUIRED_BINARY_SIDECARS).toContain("skills"); }); }); }); diff --git a/packages/coding-agent/test/bun-bundle.test.ts b/packages/coding-agent/test/bun-bundle.test.ts new file mode 100644 index 0000000000..24aaa3689b --- /dev/null +++ b/packages/coding-agent/test/bun-bundle.test.ts @@ -0,0 +1,122 @@ +import { execFileSync } from "node:child_process"; +import { existsSync, readdirSync, readFileSync, rmSync, statSync } from "node:fs"; +import { join } from "node:path"; +import { beforeAll, describe, expect, it } from "vitest"; + +const bundleDir = join(process.cwd(), "dist", "bundle"); +const bundleEntry = join(bundleDir, "cli.js"); +const distEntry = join(process.cwd(), "dist", "cli.js"); +const bundleScript = join(process.cwd(), "scripts", "bundle.mjs"); + +beforeAll(() => { + if (!existsSync(distEntry)) { + for (const packageDir of ["../tui", "../ai", "../agent", "."]) { + execFileSync("bun", ["--bun", "tsgo", "-p", "tsconfig.build.json"], { + cwd: join(process.cwd(), packageDir), + }); + } + } + if (existsSync(bundleDir)) { + rmSync(bundleDir, { recursive: true, force: true }); + } + execFileSync("bun", [bundleScript], { + cwd: process.cwd(), + encoding: "utf8", + }); +}); + +function readEntry(): string { + return readFileSync(bundleEntry, "utf8"); +} + +function listDir(): string[] { + return readdirSync(bundleDir); +} + +describe("bun-bundle build output", () => { + it("creates dist/bundle/ directory", () => { + expect(existsSync(bundleDir)).toBe(true); + }); + + it("creates entry point cli.js", () => { + expect(existsSync(bundleEntry)).toBe(true); + }); + + it("sets cli.js executable", () => { + const mode = statSync(bundleEntry).mode; + expect(mode & 0o100).toBeTruthy(); + }); +}); + +describe("bun-bundle entry content", () => { + it("preserves shebang", () => { + expect(readEntry().startsWith("#!/usr/bin/env node")).toBe(true); + }); + + it("injects require polyfill banner (createRequire)", () => { + const text = readEntry(); + expect(text).toContain("createRequire as __piBundleCreateRequire"); + expect(text).toContain("node:module"); + }); + + it("inlines __PI_BUNDLED__ define", () => { + expect(readEntry()).not.toContain("__PI_BUNDLED__"); + }); + + it("inlines __PI_BUILD_ID__ define", () => { + expect(readEntry()).not.toContain("__PI_BUILD_ID__"); + }); +}); + +describe("bun-bundle externals", () => { + const packages = ["koffi", "undici", "@silvia-odwyer/photon-node", "@mariozechner/clipboard"]; + for (const pkg of packages) { + it(`keeps ${pkg} external (not inlined)`, () => { + expect(readEntry()).not.toContain(pkg); + }); + } +}); + +describe("bun-bundle structure", () => { + it("produces at least 20 chunk files", () => { + const chunks = listDir().filter((f) => f !== "cli.js"); + expect(chunks.length).toBeGreaterThanOrEqual(20); + }); + + it("produces named provider chunks", () => { + const named = listDir().filter( + (f) => + f.startsWith("anthropic-") || + f.startsWith("google-") || + f.startsWith("azure-") || + f.startsWith("code-highlighter-"), + ); + expect(named.length).toBeGreaterThanOrEqual(3); + }); + + it("entry imports relative chunks", () => { + const relativeImports = readEntry().match(/from\s+["']\.\//g) || []; + expect(relativeImports.length).toBeGreaterThanOrEqual(1); + }); + + it("writes linked source maps for the entry and chunks", () => { + const files = listDir(); + const scripts = files.filter((file) => file.endsWith(".js")); + const maps = files.filter((file) => file.endsWith(".js.map")); + expect(maps.length).toBe(scripts.length); + expect(readEntry()).toContain("sourceMappingURL=cli.js.map"); + }); +}); + +describe("bun-bundle banner in chunks", () => { + it("injects require polyfill into chunk files too", () => { + const chunks = listDir() + .filter((file) => file.endsWith(".js") && file !== "cli.js") + .slice(0, 3); + for (const chunk of chunks) { + const content = readFileSync(join(bundleDir, chunk), "utf8"); + expect(content).toContain("createRequire"); + expect(content).toContain("node:module"); + } + }); +}); diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts new file mode 100644 index 0000000000..298278cb2b --- /dev/null +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -0,0 +1,104 @@ +import { afterEach, describe, expect, test } from "bun:test"; +import { spawnSync } from "node:child_process"; +import { createHash } from "node:crypto"; +import { chmodSync, mkdirSync, mkdtempSync, readFileSync, readlinkSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const installer = join(dirname(fileURLToPath(import.meta.url)), "../../../install.sh"); +const temporaryRoots: string[] = []; + +afterEach(() => { + for (const root of temporaryRoots.splice(0)) rmSync(root, { recursive: true, force: true }); +}); + +function makeRelease(root: string, version: string, executable: string, checksumIsValid = true): void { + const platform = `${process.platform === "darwin" ? "darwin" : "linux"}-${process.arch === "arm64" ? "arm64" : "x64"}`; + const releaseDir = join(root, "server", "releases", `v${version}`); + const stage = join(root, `stage-${version}`); + mkdirSync(releaseDir, { recursive: true }); + mkdirSync(stage, { recursive: true }); + writeFileSync(join(stage, "prime-agent"), executable); + chmodSync(join(stage, "prime-agent"), 0o755); + writeFileSync(join(stage, "package.json"), JSON.stringify({ name: "prime-agent", version })); + writeFileSync(join(stage, "install.sh"), "#!/bin/sh\n"); + const archiveName = `prime-agent-${version}-${platform}.tar.gz`; + const archive = join(releaseDir, archiveName); + const packed = spawnSync("tar", ["-czf", archive, "-C", stage, "."], { encoding: "utf8" }); + if (packed.status !== 0) throw new Error(packed.stderr || "tar failed"); + const checksum = checksumIsValid ? createHash("sha256").update(readFileSync(archive)).digest("hex") : "0".repeat(64); + writeFileSync(join(releaseDir, "SHA256SUMS"), `${checksum} ${archiveName}\n`); +} + +function runInstaller(root: string, args: string[]): { exitCode: number; stdout: string; stderr: string } { + const home = join(root, "home"); + const versions = join(root, "apps", "versions"); + const bin = join(root, "bin"); + mkdirSync(join(home, ".prime"), { recursive: true }); + writeFileSync(join(home, ".prime", "sentinel"), "user data"); + const result = spawnSync("sh", [installer, ...args], { + env: { + ...process.env, + HOME: home, + PRIME_AGENT_DOWNLOAD_BASE_URL: `file://${join(root, "server")}`, + PRIME_AGENT_VERSIONS_DIR: versions, + PRIME_AGENT_BIN_DIR: bin, + TERM: "dumb", + }, + encoding: "utf8", + }); + return { + exitCode: result.status ?? 1, + stdout: result.stdout ?? "", + stderr: result.stderr ?? result.error?.message ?? "", + }; +} + +function goodExecutable(version: string): string { + return `#!/bin/sh\nif [ "${"$"}1" = "--version" ]; then echo "prime-agent ${version}"; exit 0; fi\nexit 0\n`; +} + +describe("compiled binary installer", () => { + test("installs a flat archive into a versioned app directory and preserves user data", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + + const result = runInstaller(root, ["1.2.3"]); + expect(result.exitCode, result.stderr).toBe(0); + const target = join(root, "apps", "versions", "v1.2.3", "prime-agent"); + expect(readlinkSync(join(root, "bin", "prime-agent"))).toBe(target); + expect(readFileSync(join(root, "apps", "versions", "v1.2.3", "package.json"), "utf8")).toContain('"1.2.3"'); + expect(readFileSync(join(root, "home", ".prime", "sentinel"), "utf8")).toBe("user data"); + + const secondInstall = runInstaller(root, ["1.2.3"]); + expect(secondInstall.exitCode, secondInstall.stderr).toBe(0); + expect(readlinkSync(join(root, "bin", "prime-agent"))).toBe(target); + }); + + test("rejects a bad checksum before changing the active version", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3"), false); + + const result = runInstaller(root, ["1.2.3"]); + expect(result.exitCode).not.toBe(0); + expect(() => readlinkSync(join(root, "bin", "prime-agent"))).toThrow(); + }); + + test("keeps the previous symlink when an update fails its smoke test", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + expect(runInstaller(root, ["1.2.3"]).exitCode).toBe(0); + const link = join(root, "bin", "prime-agent"); + const oldTarget = readlinkSync(link); + + makeRelease(root, "2.0.0", "#!/bin/sh\nexit 1\n"); + const result = runInstaller(root, ["--update", "2.0.0"]); + expect(result.exitCode).not.toBe(0); + expect(readlinkSync(link)).toBe(oldTarget); + expect(readFileSync(join(root, "home", ".prime", "sentinel"), "utf8")).toBe("user data"); + }); +}); diff --git a/packages/coding-agent/test/bun-installer.test.ts b/packages/coding-agent/test/bun-installer.test.ts new file mode 100644 index 0000000000..12ba085d72 --- /dev/null +++ b/packages/coding-agent/test/bun-installer.test.ts @@ -0,0 +1,214 @@ +import { afterEach, describe, expect, it } from "bun:test"; +import { execFileSync } from "node:child_process"; +import { mkdtempSync, readFileSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const repoRoot = join(dirname(fileURLToPath(import.meta.url)), "..", "..", ".."); +const installer = join(repoRoot, "install.sh"); +const installerText = readFileSync(installer, "utf-8"); + +let tempDirs: string[] = []; +afterEach(() => { + for (const d of tempDirs) { + try { + rmSync(d, { recursive: true, force: true }); + } catch {} + } + tempDirs = []; +}); +function mkTemp(): string { + const d = mkdtempSync(join(tmpdir(), "pi-installer-")); + tempDirs.push(d); + return d; +} + +function sourceVar(v: string): string { + // Source installer with main call disabled via sed, capture variable + const result = execFileSync( + "sh", + ["-c", `eval "$(sed 's/^main "$@"/# &/' "$1")" 2>/dev/null; printf '%s' "$${v}"`, "--", installer], + { encoding: "utf-8", env: process.env as any }, + ); + return result.trim(); +} + +// ============================================================================ +describe("install.sh shell syntax", () => { + it("passes POSIX shell syntax check", () => { + expect(() => execFileSync("sh", ["-n", installer], { stdio: "pipe" })).not.toThrow(); + }); + + it("contains the npm install function", () => { + expect(installerText).toContain("prime_agent_npm_install"); + }); + + it("supports --method and --update flags", () => { + expect(installerText).toContain("--method=*"); + expect(installerText).toContain("binary|npm|auto"); + expect(installerText).toContain("--update"); + }); +}); + +// ============================================================================ +describe("default install method (auto) routes to binary", () => { + it("routes auto and binary to binary_fresh_install, never npm", () => { + expect(installerText).toMatch(/\$prime_agent_install_method" != npm/); + }); + + it("uses npm only with explicit --method=npm", () => { + const matches = installerText.match(/\$prime_agent_install_method"\s*!=\s*npm/g); + expect(matches).not.toBeNull(); + expect(matches!.length).toBeGreaterThanOrEqual(1); + }); +}); + +// ============================================================================ +describe("versioned-dir variables", () => { + it("uses XDG_DATA_HOME/prime-agent/versions for versions dir", () => { + const dir = sourceVar("prime_agent_binary_versions_dir"); + expect(dir).toMatch(/prime-agent.versions$/); + expect(dir).not.toContain(".prime"); + }); + + it("sets symlink to XDG_BIN_HOME/prime-agent", () => { + const link = sourceVar("prime_agent_binary_symlink"); + expect(link).toMatch(/prime-agent$/); + expect(link).not.toContain(".prime"); + }); + + it("respects PRIME_AGENT_VERSIONS_DIR env var", () => { + const result = execFileSync( + "sh", + [ + "-c", + "PRIME_AGENT_VERSIONS_DIR=/custom/versions; " + + 'eval "$(sed \'s/^main "$@"$/# &/\' "$1")" 2>/dev/null; ' + + "printf '%s' $prime_agent_binary_versions_dir", + "--", + installer, + ], + { encoding: "utf-8", env: process.env as any }, + ).trim(); + expect(result).toBe("/custom/versions"); + }); + + it("respects PRIME_AGENT_BIN_DIR env var for symlink path", () => { + const result = execFileSync( + "sh", + [ + "-c", + "PRIME_AGENT_BIN_DIR=/custom/bin; " + + 'eval "$(sed \'s/^main "$@"$/# &/\' "$1")" 2>/dev/null; ' + + "printf '%s' $prime_agent_binary_symlink", + "--", + installer, + ], + { encoding: "utf-8", env: process.env as any }, + ).trim(); + expect(result).toBe("/custom/bin/prime-agent"); + }); +}); + +// ============================================================================ +describe("platform detection", () => { + it("detects current platform as a valid binary platform", () => { + const platform = execFileSync( + "sh", + [ + "-c", + 'eval "$(sed \'s/^main "$@"$/# &/\' "$1")" 2>/dev/null; prime_agent_detect_binary_platform', + "--", + installer, + ], + { encoding: "utf-8", env: process.env as any }, + ).trim(); + expect(["darwin-arm64", "darwin-x64", "linux-x64", "linux-arm64"]).toContain(platform); + }); +}); + +// ============================================================================ +describe("atomic symlink function", () => { + it("creates and replaces symlink atomically", () => { + const tmp = mkTemp(); + const v1 = `${tmp}/versions/v1`; + const v2 = `${tmp}/versions/v2`; + const link = `${tmp}/bin/prime-agent`; + const cmd = + 'eval "$(sed \'s/^main "$@"$/# &/\' "$1")" 2>/dev/null' + + "; mkdir -p " + + v1 + + " " + + v2 + + "; touch " + + v1 + + "/pi " + + v2 + + "/pi" + + "; chmod +x " + + v1 + + "/pi " + + v2 + + "/pi" + + "; mkdir -p " + + tmp + + "/bin" + + "; prime_agent_binary_symlink=" + + link + + "; prime_agent_binary_atomic_symlink " + + v1 + + "/pi " + + link + + "; prime_agent_binary_atomic_symlink " + + v2 + + "/pi " + + link + + '; [ "$(readlink ' + + link + + ')" = "' + + v2 + + "/pi\" ] && printf 'OK'"; + const result = execFileSync("sh", ["-c", cmd, "--", installer], { + encoding: "utf-8", + env: process.env as any, + }).trim(); + expect(result).toBe("OK"); + }); +}); + +// ============================================================================ +describe("config dir isolation", () => { + it("does not use ~/.prime for binary install paths", () => { + const versionsLine = installerText.match(/^prime_agent_binary_versions_dir=.*$/m); + const symlinkLine = installerText.match(/^prime_agent_binary_symlink=.*$/m); + if (versionsLine) expect(versionsLine[0]).not.toContain(".prime"); + if (symlinkLine) expect(symlinkLine[0]).not.toContain(".prime"); + }); + + it("uses XDG data dir for versions", () => { + expect(installerText).toContain("XDG_DATA_HOME"); + }); + + it("uses separate bin dir for symlink", () => { + expect(installerText).toContain("prime_agent_binary_symlink"); + }); + + it("does not copy sidecars into ~/.prime", () => { + const freshSection = installerText.match(/prime_agent_binary_fresh_install[^}]*}/s)?.[0] || ""; + expect(freshSection).not.toContain(".prime"); + }); +}); + +// ============================================================================ +describe("install.sh sidecar", () => { + it("ensures install.sh is made executable in versioned dir", () => { + expect(installerText).toContain('chmod +x "$_version_dir/install.sh"'); + }); + + it("appears in both fresh_install and update paths", () => { + const matches = installerText.match(/chmod \+x "\$_version_dir\/install\.sh"/g); + expect(matches).not.toBeNull(); + expect(matches!.length).toBe(2); + }); +}); diff --git a/packages/coding-agent/test/bun-release-archives.test.ts b/packages/coding-agent/test/bun-release-archives.test.ts new file mode 100644 index 0000000000..d92b6f9af1 --- /dev/null +++ b/packages/coding-agent/test/bun-release-archives.test.ts @@ -0,0 +1,150 @@ +import { afterEach, describe, expect, test } from "bun:test"; +import { spawnSync } from "node:child_process"; +import { + chmodSync, + cpSync, + existsSync, + mkdirSync, + mkdtempSync, + readdirSync, + readFileSync, + rmSync, + writeFileSync, +} from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const packageDir = join(dirname(fileURLToPath(import.meta.url)), ".."); +const repoRoot = join(packageDir, "..", ".."); +const packScript = join(repoRoot, "scripts", "pack-prime-agent-release.mjs"); +const releaseRoot = join(packageDir, "release"); +const temporaryRoots: string[] = []; +const outputDirs: string[] = []; +const platforms = ["darwin-arm64", "darwin-x64", "linux-arm64", "linux-x64"]; + +function fixture(): { root: string; binaries: string; sidecars: string; output: string } { + const root = mkdtempSync(join(tmpdir(), "prime-agent-release-")); + temporaryRoots.push(root); + const binaries = join(root, "binaries"); + const sidecars = join(root, "sidecars"); + for (const platform of platforms) { + const dir = join(binaries, platform); + mkdirSync(dir, { recursive: true }); + cpSync("/bin/echo", join(dir, "pi")); + chmodSync(join(dir, "pi"), 0o755); + } + mkdirSync(sidecars, { recursive: true }); + for (const name of ["prime-agent-runtime", "skills", "theme", "assets", "export-html", "docs", "examples"]) { + mkdirSync(join(sidecars, name)); + writeFileSync(join(sidecars, name, ".keep"), "fixture"); + } + writeFileSync(join(sidecars, "package.json"), JSON.stringify({ name: "prime-agent", version: "1.2.3" })); + writeFileSync(join(sidecars, "README.md"), "readme"); + writeFileSync(join(sidecars, "CHANGELOG.md"), "changelog"); + writeFileSync( + join(sidecars, "install.sh"), + '#!/bin/sh\nbase="__PRIME_AGENT_DOWNLOAD_BASE_URL__"\nchannel="__PRIME_AGENT_DEFAULT_RELEASE_CHANNEL__"\n', + ); + writeFileSync(join(sidecars, "photon_rs_bg.wasm"), "wasm"); + const output = join(releaseRoot, `test-${process.pid}-${Math.random().toString(36).slice(2)}`); + outputDirs.push(output); + return { root, binaries, sidecars, output }; +} + +function pack(f: ReturnType, extra: string[] = []) { + return spawnSync( + process.execPath, + [ + packScript, + "--base-url", + "https://downloads.example.test", + "--channel", + "stable", + "--version", + "1.2.3", + "--binary-base-dir", + f.binaries, + "--sidecar-dir", + f.sidecars, + "--out-dir", + f.output, + ...extra, + ], + { encoding: "utf8" }, + ); +} + +afterEach(() => { + for (const root of temporaryRoots.splice(0)) rmSync(root, { recursive: true, force: true }); + for (const output of outputDirs.splice(0)) rmSync(output, { recursive: true, force: true }); +}); + +describe("compiled release archives", () => { + test("creates all platform archives with flat required sidecars and rendered installer", () => { + const f = fixture(); + const result = pack(f); + expect(result.status, result.stderr).toBe(0); + const artifacts = join(f.output, "artifacts"); + const archives = readdirSync(artifacts).filter((name) => name.endsWith(".tar.gz")); + expect(archives.sort()).toEqual(platforms.map((platform) => `prime-agent-1.2.3-${platform}.tar.gz`).sort()); + expect(readFileSync(join(artifacts, "stable"), "utf8")).toBe("v1.2.3\n"); + expect(readFileSync(join(artifacts, "SHA256SUMS"), "utf8").trim().split("\n")).toHaveLength(4); + + const extracted = join(f.root, "extracted"); + mkdirSync(extracted); + const archive = join(artifacts, "prime-agent-1.2.3-darwin-arm64.tar.gz"); + expect(spawnSync("tar", ["-xzf", archive, "-C", extracted]).status).toBe(0); + expect(readFileSync(join(extracted, "install.sh"), "utf8")).toContain('base="https://downloads.example.test"'); + expect(readFileSync(join(extracted, "install.sh"), "utf8")).toContain('channel="stable"'); + const manifest = JSON.parse(readFileSync(join(extracted, "package.json"), "utf8")); + expect(manifest).toMatchObject({ + name: "prime-agent", + version: "1.2.3", + bin: { "prime-agent": "./prime-agent" }, + packageManager: "bun@1.3.14", + }); + for (const name of [ + "prime-agent", + "package.json", + "README.md", + "CHANGELOG.md", + "install.sh", + "prime-agent-runtime", + "skills", + "theme", + "assets", + "export-html", + "docs", + "examples", + "photon_rs_bg.wasm", + ]) { + expect(existsSync(join(extracted, name))).toBe(true); + } + }); + + test("supports a single-platform local archive", () => { + const f = fixture(); + const result = pack(f, ["--platform", "linux-x64"]); + expect(result.status, result.stderr).toBe(0); + expect(readdirSync(join(f.output, "artifacts")).filter((name) => name.endsWith(".tar.gz"))).toEqual([ + "prime-agent-1.2.3-linux-x64.tar.gz", + ]); + }); + + test("fails closed when a required sidecar is missing", () => { + const f = fixture(); + rmSync(join(f.sidecars, "theme"), { recursive: true }); + const result = pack(f); + expect(result.status).not.toBe(0); + expect(result.stderr).toContain("Missing required sidecars"); + }); + + test("rejects dependency directories in release sidecars", () => { + const f = fixture(); + mkdirSync(join(f.sidecars, "examples", "node_modules")); + const result = pack(f); + expect(result.status).not.toBe(0); + expect(result.stderr).toContain("forbidden dependency or cache directory"); + }); +}); diff --git a/packages/coding-agent/test/bun-test-preload.ts b/packages/coding-agent/test/bun-test-preload.ts new file mode 100644 index 0000000000..aa313ca953 --- /dev/null +++ b/packages/coding-agent/test/bun-test-preload.ts @@ -0,0 +1,142 @@ +import { jest } from "bun:test"; +import { readFile } from "node:fs/promises"; +import { describe, expect, vi } from "vitest"; + +type AnyFunction = (...args: never[]) => unknown; +type ViCompat = Record; + +const compat = vi as unknown as ViCompat; +const nativeSetTimeout = globalThis.setTimeout; +process.env.DO_NOT_TRACK ??= "1"; +// Do not let the parent Prime Agent daemon make CLI tests operate on live sessions. +for (const name of Object.keys(process.env)) { + if (name.startsWith("PRIME_AGENT_INTERNAL_") || name.startsWith("RLM_")) { + delete process.env[name]; + } +} +delete process.env.PRIME_AGENT_CODING_AGENT_DIR; +delete process.env.PRIME_AGENT_KERNEL_OWNER_PID; +const gitConfigCount = Number.parseInt(process.env.GIT_CONFIG_COUNT ?? "0", 10) || 0; +process.env[`GIT_CONFIG_KEY_${gitConfigCount}`] = "commit.gpgsign"; +process.env[`GIT_CONFIG_VALUE_${gitConfigCount}`] = "false"; +process.env.GIT_CONFIG_COUNT = String(gitConfigCount + 1); +const originalEnv = new Map(); +const originalGlobals = new Map(); + +compat.hoisted ??= (factory: AnyFunction) => factory(); +compat.mocked ??= (value: unknown) => value; +compat.setSystemTime ??= (value: Date | number) => jest.setSystemTime(value); +compat.advanceTimersByTime = (milliseconds: number) => { + const targetTime = Date.now() + milliseconds; + jest.advanceTimersByTime(milliseconds); + jest.setSystemTime(targetTime); + return vi; +}; +const flushMicrotasks = async (): Promise => { + // Timer callbacks in these tests often cross several awaited boundaries before + // scheduling the next timer. Keep fake time still while those jobs settle. + for (let index = 0; index < 8; index++) await Promise.resolve(); +}; + +compat.advanceTimersByTimeAsync ??= async (milliseconds: number) => { + await flushMicrotasks(); + let remaining = milliseconds; + while (remaining > 0) { + const step = Math.min(remaining, 10); + const targetTime = Date.now() + step; + jest.advanceTimersByTime(step); + jest.setSystemTime(targetTime); + remaining -= step; + await flushMicrotasks(); + } + if (milliseconds === 0) { + jest.advanceTimersByTime(0); + await flushMicrotasks(); + } +}; +compat.runAllTimersAsync ??= async () => { + await flushMicrotasks(); + for (let pass = 0; pass < 10_000 && jest.getTimerCount() > 0; pass++) { + jest.runAllTimers(); + await flushMicrotasks(); + } +}; +compat.advanceTimersToNextTimerAsync ??= async () => { + await flushMicrotasks(); + jest.advanceTimersToNextTimer(); + await flushMicrotasks(); +}; +compat.runOnlyPendingTimersAsync ??= async () => { + await flushMicrotasks(); + jest.runOnlyPendingTimers(); + await flushMicrotasks(); +}; +compat.waitFor ??= async (assertion: AnyFunction, options: { timeout?: number; interval?: number } = {}) => { + const timeout = options.timeout ?? 1_000; + const interval = options.interval ?? 20; + const deadline = Date.now() + timeout; + let lastError: unknown; + while (Date.now() <= deadline) { + try { + return await assertion(); + } catch (error) { + lastError = error; + } + if (jest.isFakeTimers()) { + const targetTime = Date.now() + interval; + jest.advanceTimersByTime(interval); + jest.setSystemTime(targetTime); + await flushMicrotasks(); + // Promise jobs alone do not let spawned-process and socket events run. + await readFile("/dev/null"); + } else { + await new Promise((resolve) => nativeSetTimeout(resolve, interval)); + } + } + throw lastError ?? new Error(`waitFor timed out after ${timeout} ms`); +}; + +const expectCompat = expect as typeof expect & { + poll?: (actual: () => unknown | Promise, options?: { timeout?: number; interval?: number }) => unknown; +}; +expectCompat.poll ??= (actual: () => unknown | Promise, options?: { timeout?: number; interval?: number }) => + new Proxy( + {}, + { + get: + (_target, matcher: string) => + async (...args: unknown[]) => + vi.waitFor(async () => { + const received = await actual(); + return (expect(received) as unknown as Record unknown>)[matcher]?.( + ...args, + ); + }, options), + }, + ); + +compat.stubEnv ??= (name: string, value: string | undefined) => { + if (!originalEnv.has(name)) originalEnv.set(name, process.env[name]); + if (value === undefined) delete process.env[name]; + else process.env[name] = value; +}; +compat.unstubAllEnvs ??= () => { + for (const [name, value] of originalEnv) { + if (value === undefined) delete process.env[name]; + else process.env[name] = value; + } + originalEnv.clear(); +}; +compat.stubGlobal ??= (name: PropertyKey, value: unknown) => { + if (!originalGlobals.has(name)) originalGlobals.set(name, Object.getOwnPropertyDescriptor(globalThis, name)); + Object.defineProperty(globalThis, name, { configurable: true, writable: true, value }); +}; +compat.unstubAllGlobals ??= () => { + for (const [name, descriptor] of originalGlobals) { + if (descriptor) Object.defineProperty(globalThis, name, descriptor); + else Reflect.deleteProperty(globalThis, name); + } + originalGlobals.clear(); +}; + +(describe as typeof describe & { sequential?: typeof describe }).sequential ??= describe; diff --git a/packages/coding-agent/test/bun-test-runtime-isolation.test.ts b/packages/coding-agent/test/bun-test-runtime-isolation.test.ts new file mode 100644 index 0000000000..07d9fdd1ec --- /dev/null +++ b/packages/coding-agent/test/bun-test-runtime-isolation.test.ts @@ -0,0 +1,33 @@ +import { spawnSync } from "node:child_process"; +import { resolve } from "node:path"; +import { describe, expect, it } from "vitest"; + +const repoRoot = resolve(import.meta.dirname, "../../.."); +const launcher = resolve(repoRoot, "scripts/run-with-clean-env.ts"); + +describe("Bun test runtime isolation", () => { + it("removes live Prime Agent orchestration state before Bun and its descendants start", () => { + const probe = `console.log(JSON.stringify({ + internal: process.env.PRIME_AGENT_INTERNAL_ORPHAN_PROCESS_JOURNAL, + rlm: process.env.RLM_SESSION_DIR, + agentDir: process.env.PRIME_AGENT_CODING_AGENT_DIR, + owner: process.env.PRIME_AGENT_KERNEL_OWNER_PID, + tags: process.env.PRIME_AGENT_TEST_TAGS, + }))`; + const result = spawnSync(process.execPath, [launcher, "bun", "-e", probe], { + cwd: repoRoot, + encoding: "utf8", + env: { + ...process.env, + PRIME_AGENT_INTERNAL_ORPHAN_PROCESS_JOURNAL: "/live/orphans.jsonl", + RLM_SESSION_DIR: "/live/session", + PRIME_AGENT_CODING_AGENT_DIR: "/live/agent", + PRIME_AGENT_KERNEL_OWNER_PID: "1234", + PRIME_AGENT_TEST_TAGS: "kernel-heavy", + }, + }); + + expect(result.status, result.stderr).toBe(0); + expect(JSON.parse(result.stdout)).toEqual({ tags: "kernel-heavy" }); + }); +}); diff --git a/packages/coding-agent/test/clipboard-image-bmp-conversion.test.ts b/packages/coding-agent/test/clipboard-image-bmp-conversion.test.ts index 95107506b5..87a7e0e166 100644 --- a/packages/coding-agent/test/clipboard-image-bmp-conversion.test.ts +++ b/packages/coding-agent/test/clipboard-image-bmp-conversion.test.ts @@ -5,6 +5,7 @@ * This tests the fix for WSL2/WSLg where clipboard often provides image/bmp * instead of image/png. */ +import * as childProcess from "node:child_process"; import { describe, expect, test, vi } from "vitest"; function createTinyBmp1x1Red24bpp(): Uint8Array { @@ -42,10 +43,9 @@ function createTinyBmp1x1Red24bpp(): Uint8Array { } // Mock wl-paste to return BMP -vi.mock("child_process", async () => { - const actual = await vi.importActual("child_process"); +vi.mock("child_process", () => { return { - ...actual, + ...childProcess, spawnSync: vi.fn((command: string, args: string[]) => { if (command === "wl-paste" && args.includes("--list-types")) { return { status: 0, stdout: Buffer.from("image/bmp\n"), error: null }; diff --git a/packages/coding-agent/test/clipboard-image.test.ts b/packages/coding-agent/test/clipboard-image.test.ts index eda61a29e5..c99a03387c 100644 --- a/packages/coding-agent/test/clipboard-image.test.ts +++ b/packages/coding-agent/test/clipboard-image.test.ts @@ -49,7 +49,6 @@ function spawnError(error: Error): SpawnSyncReturns { describe("readClipboardImage", () => { beforeEach(() => { - vi.resetModules(); mocks.spawnSync.mockReset(); mocks.clipboard.hasImage.mockReset(); mocks.clipboard.getImageBinary.mockReset(); diff --git a/packages/coding-agent/test/compaction-summary-reasoning.test.ts b/packages/coding-agent/test/compaction-summary-reasoning.test.ts index c674ef1a7d..886760bc4f 100644 --- a/packages/coding-agent/test/compaction-summary-reasoning.test.ts +++ b/packages/coding-agent/test/compaction-summary-reasoning.test.ts @@ -1,3 +1,4 @@ +import { createRequire } from "node:module"; import type { AgentMessage } from "@earendil-works/pi-agent-core"; import type { AssistantMessage, Model } from "@earendil-works/pi-ai"; import { beforeEach, describe, expect, it, vi } from "vitest"; @@ -7,13 +8,11 @@ const { completeSimpleMock } = vi.hoisted(() => ({ completeSimpleMock: vi.fn(), })); -vi.mock("@earendil-works/pi-ai", async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - completeSimple: completeSimpleMock, - }; -}); +const __piAi = createRequire(import.meta.url)("@earendil-works/pi-ai"); +vi.mock("@earendil-works/pi-ai", () => ({ + ...__piAi, + completeSimple: completeSimpleMock, +})); function createModel(reasoning: boolean): Model<"anthropic-messages"> { return { diff --git a/packages/coding-agent/test/compiled-artifact-smoke.test.ts b/packages/coding-agent/test/compiled-artifact-smoke.test.ts new file mode 100644 index 0000000000..4215ce290f --- /dev/null +++ b/packages/coding-agent/test/compiled-artifact-smoke.test.ts @@ -0,0 +1,61 @@ +import { describe, expect, it } from "bun:test"; +import { existsSync, readdirSync, statSync } from "node:fs"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { + inspectNativeExecutable, + REQUIRED_BINARY_SIDECARS, + runEmptyDiagnostic, + runPackagedSmoke, +} from "../../../scripts/compiled-artifact-smoke.js"; + +const packageDir = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const distDir = join(packageDir, "dist"); +const binary = join(distDir, "pi"); + +function dependencyDirectories(root: string): string[] { + const found: string[] = []; + for (const entry of readdirSync(root, { withFileTypes: true })) { + if (!entry.isDirectory()) continue; + const path = join(root, entry.name); + if (["node_modules", ".venv", "__pycache__", ".pytest_cache"].includes(entry.name)) found.push(path); + else found.push(...dependencyDirectories(path)); + } + return found; +} + +describe("compiled Bun artifact", () => { + it("is a native executable", () => { + expect(existsSync(binary)).toBe(true); + expect(statSync(binary).size).toBeGreaterThan(10 * 1024 * 1024); + expect(["elf", "mach-o"]).toContain(inspectNativeExecutable(binary)); + }); + + it("documents the unsupported binary-only layout", () => { + const result = runEmptyDiagnostic(binary); + expect(result.detectedMissingPackageJson).toBe(true); + expect(result.run.exitCode).not.toBe(0); + }); + + it("contains the complete supported sidecar set", () => { + for (const name of REQUIRED_BINARY_SIDECARS) { + expect(existsSync(join(distDir, name)), name).toBe(true); + } + }); + + it("contains no installed dependency or cache directories", () => { + expect(dependencyDirectories(distDir)).toEqual([]); + }); + + it("runs --version and --help with no Node or npm on PATH", () => { + const result = runPackagedSmoke(binary, distDir); + expect(result.nodeAvailable).toBe(false); + expect(result.npmAvailable).toBe(false); + expect(result.passed).toBe(true); + for (const run of result.runs) { + expect(run.exitCode).toBe(0); + expect(run.stdout.trim().length).toBeGreaterThan(0); + expect(run.stderr).not.toContain("ENOENT"); + } + }); +}); diff --git a/packages/coding-agent/test/daemon-client.test.ts b/packages/coding-agent/test/daemon-client.test.ts index f7614733fa..42d75a3caf 100644 --- a/packages/coding-agent/test/daemon-client.test.ts +++ b/packages/coding-agent/test/daemon-client.test.ts @@ -15,7 +15,17 @@ const netMock = vi.hoisted(() => { readonly writes: string[] = []; destroyed = false; - constructor(readonly path: string) {} + path = ""; + + constructor(path = "") { + this.path = path; + } + + connect(path: string): this { + this.path = path; + sockets.push(this); + return this; + } on(event: string, listener: Listener): this { const listeners = this.listeners.get(event) ?? new Set(); @@ -83,11 +93,12 @@ const netMock = vi.hoisted(() => { return socket; }); - return { createConnection, sockets }; + return { createConnection, MockSocket, sockets }; }); vi.mock("node:net", () => ({ createConnection: netMock.createConnection, + Socket: netMock.MockSocket, })); function emitHello( @@ -155,11 +166,9 @@ describe("DaemonClient", () => { expect(netMock.sockets).toHaveLength(1); const firstSocket = netMock.sockets[0]!; - const timeoutRejection = expect(firstAttempt).resolves.toMatchObject({ - message: expect.stringContaining("Timed out after 5ms connecting to the Prime Agent daemon."), - }); await vi.advanceTimersByTimeAsync(5); - await timeoutRejection; + const timeoutError = await firstAttempt; + expect(timeoutError.message).toContain("Timed out after 5ms connecting to the Prime Agent daemon."); expect(firstSocket.destroyed).toBe(true); expect(firstSocket.listenerCount("data")).toBe(0); @@ -419,17 +428,12 @@ describe("DaemonClient", () => { const request = client.request({ type: "list", all: true }); - await expect(request).rejects.toMatchObject({ - message: expect.stringContaining( - 'Cannot send daemon command "list" because the Prime Agent daemon is not connected.', - ), - }); - await expect(request).rejects.toMatchObject({ - message: expect.stringContaining("Socket: /tmp/prime-agent.sock."), - }); - await expect(request).rejects.toMatchObject({ - message: expect.stringContaining("Daemon log:"), - }); + const requestError = await captureRejection(request); + expect(requestError.message).toContain( + 'Cannot send daemon command "list" because the Prime Agent daemon is not connected.', + ); + expect(requestError.message).toContain("Socket: /tmp/prime-agent.sock."); + expect(requestError.message).toContain("Daemon log:"); }); it("keeps durable command envelopes on the session-action protocol", async () => { @@ -931,7 +935,7 @@ describe("DaemonClient", () => { }); }); -async function captureRejection(promise: Promise): Promise { +async function captureRejection(promise: Promise): Promise { try { await promise; } catch (error) { diff --git a/packages/coding-agent/test/daemon-command.test.ts b/packages/coding-agent/test/daemon-command.test.ts index 65866521c9..43e0e0ef4e 100644 --- a/packages/coding-agent/test/daemon-command.test.ts +++ b/packages/coding-agent/test/daemon-command.test.ts @@ -1,3 +1,4 @@ +import { createRequire } from "node:module"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; const daemonClientMock = vi.hoisted(() => { @@ -121,10 +122,8 @@ const spawnMock = vi.hoisted(() => { }; }); -vi.mock("node:child_process", async (importOriginal) => { - const original = (await importOriginal()) as Record; - return { ...original, spawn: spawnMock.mockSpawn as never }; -}); +const __childProcess = createRequire(import.meta.url)("node:child_process"); +vi.mock("node:child_process", () => ({ ...__childProcess, spawn: spawnMock.mockSpawn as never })); import { handleDaemonCommand } from "../src/cli/daemon-command.js"; @@ -132,7 +131,7 @@ describe("daemon command", () => { let consoleErrorMessages: unknown[]; beforeEach(() => { - process.exitCode = undefined; + process.exitCode = 0; daemonClientMock.instances.length = 0; daemonClientMock.behavior.promptSucceeds = false; daemonClientMock.behavior.emitStaleAgentEndOnAttach = false; @@ -149,7 +148,7 @@ describe("daemon command", () => { }); afterEach(() => { - process.exitCode = undefined; + process.exitCode = 0; vi.restoreAllMocks(); }); diff --git a/packages/coding-agent/test/daemon-launch.test.ts b/packages/coding-agent/test/daemon-launch.test.ts index 26cc049ef3..3a12012b31 100644 --- a/packages/coding-agent/test/daemon-launch.test.ts +++ b/packages/coding-agent/test/daemon-launch.test.ts @@ -3,7 +3,7 @@ import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node: import { createServer, type Server, type Socket } from "node:net"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; -import { afterEach, describe, expect, it, vi } from "vitest"; +import { afterEach, describe, expect, it } from "vitest"; import { ensureInteractiveDaemonRunning, probeDaemonVersion, @@ -292,7 +292,6 @@ describe("ensureInteractiveDaemonRunning", () => { }); it("reuses a daemon that becomes current inside the startup window", async () => { - vi.useFakeTimers(); let resolveFirstConnection = () => {}; let resolveSecondConnection = () => {}; const firstConnection = new Promise((resolve) => { @@ -311,19 +310,16 @@ describe("ensureInteractiveDaemonRunning", () => { }); cleanups.push(daemon.close); - try { - const ensuring = ensureInteractiveDaemonRunning(daemon.socketPath); - await firstConnection; - await vi.advanceTimersByTimeAsync(2000); - await secondConnection; - await expect(ensuring).resolves.toBeUndefined(); - } finally { - vi.useRealTimers(); - } + const ensuring = ensureInteractiveDaemonRunning(daemon.socketPath, undefined, { + initialHelloTimeoutMs: 10, + startupTimeoutMs: 100, + }); + await firstConnection; + await secondConnection; + await expect(ensuring).resolves.toBeUndefined(); }); it("leaves a connected unresponsive daemon running after the startup window", async () => { - vi.useFakeTimers(); const connections: Array<() => void> = []; const connected = [0, 1].map( (index) => @@ -339,19 +335,16 @@ describe("ensureInteractiveDaemonRunning", () => { }); cleanups.push(daemon.close); - try { - const ensuring = ensureInteractiveDaemonRunning(daemon.socketPath); - const rejected = expect(ensuring).rejects.toThrow(/accepted connections but did not finish startup/); - await connected[0]; - await vi.advanceTimersByTimeAsync(2000); - await connected[1]; - await vi.advanceTimersByTimeAsync(30_000); - await rejected; - expect(commands).not.toContain("list"); - expect(commands).not.toContain("shutdown"); - } finally { - vi.useRealTimers(); - } + const ensuring = ensureInteractiveDaemonRunning(daemon.socketPath, undefined, { + initialHelloTimeoutMs: 10, + startupTimeoutMs: 100, + }); + const rejected = expect(ensuring).rejects.toThrow(/accepted connections but did not finish startup/); + await connected[0]; + await connected[1]; + await rejected; + expect(commands).not.toContain("list"); + expect(commands).not.toContain("shutdown"); }); it("cancels replacement when a stale-looking daemon becomes current", async () => { diff --git a/packages/coding-agent/test/daemon-mode.test.ts b/packages/coding-agent/test/daemon-mode.test.ts index 2fe4077d06..e2705dbf53 100644 --- a/packages/coding-agent/test/daemon-mode.test.ts +++ b/packages/coding-agent/test/daemon-mode.test.ts @@ -1837,8 +1837,11 @@ describe("daemon mode helpers", () => { const tempDir = mkdtempSync(join(tmpdir(), "pa-msg-")); const socketPath = join(tempDir, "d.sock"); let connectionCount = 0; + const sockets = new Set(); const server: Server = createServer((socket) => { connectionCount++; + sockets.add(socket); + socket.once("close", () => sockets.delete(socket)); socket.on("error", () => undefined); socket.write( `${JSON.stringify({ @@ -1893,9 +1896,14 @@ describe("daemon mode helpers", () => { } ).sendRemoteAgentSessionMessage.bind(daemon); - await expect(sendRemoteAgentSessionMessage(makeState("source"), "remote", "continue")).rejects.toThrow( - "Target session has too many pending messages", - ); + let rejection: unknown; + try { + await sendRemoteAgentSessionMessage(makeState("source"), "remote", "continue"); + } catch (error) { + rejection = error; + } + expect(rejection).toBeInstanceOf(Error); + expect((rejection as Error).message).toContain("Target session has too many pending messages"); expect(connectionCount).toBe(1); } finally { if (previousSupervisorSocket === undefined) { @@ -1903,6 +1911,7 @@ describe("daemon mode helpers", () => { } else { process.env[DAEMON_WORKER_SUPERVISOR_SOCKET_ENV] = previousSupervisorSocket; } + for (const socket of sockets) socket.destroy(); await new Promise((resolve) => server.close(() => resolve())); rmSync(tempDir, { recursive: true, force: true }); } diff --git a/packages/coding-agent/test/daemon-multiclient-bench.ts b/packages/coding-agent/test/daemon-multiclient-bench.ts index 998e4b48c1..91a5bf1822 100644 --- a/packages/coding-agent/test/daemon-multiclient-bench.ts +++ b/packages/coding-agent/test/daemon-multiclient-bench.ts @@ -7,10 +7,10 @@ * * Run from packages/coding-agent: * - * npx tsx test/daemon-multiclient-bench.ts - * npx tsx test/daemon-multiclient-bench.ts --session-file /path/to/session.jsonl - * npx tsx test/daemon-multiclient-bench.ts --generated-session-mib 100 - * npx tsx test/daemon-multiclient-bench.ts --generated-session-mib 500 + * bun test/daemon-multiclient-bench.ts + * bun test/daemon-multiclient-bench.ts --session-file /path/to/session.jsonl + * bun test/daemon-multiclient-bench.ts --generated-session-mib 100 + * bun test/daemon-multiclient-bench.ts --generated-session-mib 500 */ import { randomUUID } from "node:crypto"; import { createWriteStream } from "node:fs"; diff --git a/packages/coding-agent/test/daemon-ps.test.ts b/packages/coding-agent/test/daemon-ps.test.ts index 6233a9353e..bf2dce7d09 100644 --- a/packages/coding-agent/test/daemon-ps.test.ts +++ b/packages/coding-agent/test/daemon-ps.test.ts @@ -19,7 +19,7 @@ import { getProcessStartId } from "../src/core/session-lease.js"; import { defaultDaemonSocketDir } from "../src/modes/daemon/daemon-socket.js"; describe("worker socket classification", () => { - it.runIf(process.platform !== "win32")("recognizes only worker sockets in the default service directory", () => { + it.skipIf(process.platform === "win32")("recognizes only worker sockets in the default service directory", () => { expect(isWorkerSocketPath(join(defaultDaemonSocketDir(), "worker-abc.sock"))).toBe(true); expect(isWorkerSocketPath(join(defaultDaemonSocketDir(), "daemon.sock"))).toBe(false); expect(isWorkerSocketPath("/tmp/worker-abc.sock")).toBe(false); @@ -57,7 +57,9 @@ describe("parseSsListeners", () => { describe("parseLsofListeners", () => { it("pairs each pid with its listening unix socket paths", () => { - const stdout = ["p1234", "fu", "n/tmp/a.sock", "p5678", "n/tmp/b.sock", "n0x0 (not a path)", ""].join("\n"); + const stdout = ["p1234", "fu", "n/tmp/a.sock type=STREAM", "p5678", "n/tmp/b.sock", "n0x0 (not a path)", ""].join( + "\n", + ); expect(parseLsofListeners(stdout)).toEqual([ { pid: 1234, socketPath: "/tmp/a.sock" }, { pid: 5678, socketPath: "/tmp/b.sock" }, diff --git a/packages/coding-agent/test/daemon-supervisor-lazy-subagents.test.ts b/packages/coding-agent/test/daemon-supervisor-lazy-subagents.test.ts index becf9a98f3..7d6a030634 100644 --- a/packages/coding-agent/test/daemon-supervisor-lazy-subagents.test.ts +++ b/packages/coding-agent/test/daemon-supervisor-lazy-subagents.test.ts @@ -19,6 +19,9 @@ interface SupervisorInternals { workers: Map; start(): Promise; cleanupSupervisorResources(): Promise; + clearIdleEvictionTimer(): void; + clearRosterWatchdogTimer(): void; + catalog: { stop?: () => Promise }; refreshWorkerSummaries(worker: WorkerFixture): Promise; findSummaryInWorker(worker: WorkerFixture, selector: string): SessionSummary | undefined; createOrReuseWorker( @@ -55,11 +58,33 @@ interface WorkerFixture { } const tempDirs: string[] = []; - -afterEach(() => { +const supervisors: SupervisorInternals[] = []; + +afterEach(async () => { + for (const supervisor of supervisors.splice(0)) { + supervisor.clearIdleEvictionTimer(); + supervisor.clearRosterWatchdogTimer(); + await supervisor.catalog.stop?.(); + } for (const directory of tempDirs.splice(0)) rmSync(directory, { recursive: true, force: true }); }); +function createSupervisor(directory: string): SupervisorInternals { + const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { + defaultSessionConfig: { agentDir: directory, cwd: directory }, + descriptorDir: join(directory, "workers"), + }) as unknown as SupervisorInternals; + supervisors.push(supervisor); + return supervisor; +} + +function capturePromise(promise: Promise): Promise<{ value?: T; error?: unknown }> { + return promise.then( + (value) => ({ value }), + (error: unknown) => ({ error }), + ); +} + function summary(overrides: Partial & Pick): SessionSummary { return { lifecycle: "live", @@ -98,10 +123,7 @@ describe("daemon supervisor passive subagent topology", () => { it("finds a child summary by its displayed session ID suffix", () => { const directory = mkdtempSync(join(tmpdir(), "prime-supervisor-child-suffix-")); tempDirs.push(directory); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); const child = summary({ id: "bbbb6666777788889999cccc", activeSessionId: "bbbb6666777788889999cccc", @@ -116,10 +138,7 @@ describe("daemon supervisor passive subagent topology", () => { it("rejects an explicit root name that collides with a saved root", async () => { const directory = mkdtempSync(join(tmpdir(), "prime-supervisor-root-name-")); tempDirs.push(directory); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); const launchWorker = vi.fn(); Object.assign(supervisor, { catalog: { @@ -160,10 +179,7 @@ describe("daemon supervisor passive subagent topology", () => { if (!forkedPath) throw new Error("Missing forked session path"); const forkedInfo = await readSessionInfo(forkedPath); if (!forkedInfo) throw new Error("Missing forked session info"); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); Object.assign(supervisor, { catalog: { siblings: vi.fn(async () => [forkedInfo]), @@ -193,10 +209,7 @@ describe("daemon supervisor passive subagent topology", () => { it("normalizes explicit root names before supervisor validation and launch", async () => { const directory = mkdtempSync(join(tmpdir(), "prime-supervisor-normalized-root-name-")); tempDirs.push(directory); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); const launchWorker = vi.fn(); Object.assign(supervisor, { catalog: { @@ -243,10 +256,7 @@ describe("daemon supervisor passive subagent topology", () => { allMessagesText: "", }; const duplicate = { ...target, id: "duplicate", path: duplicatePath, name: "taken" }; - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); Object.assign(supervisor, { rlmLedgerSiblings: vi.fn(async () => [target]), catalog: { @@ -263,10 +273,7 @@ describe("daemon supervisor passive subagent topology", () => { it("retains a legacy child's parent edge when its depth is unknown", () => { const directory = mkdtempSync(join(tmpdir(), "prime-supervisor-legacy-family-")); tempDirs.push(directory); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); const parentPath = join(directory, "parent.jsonl"); const child = supervisor.familyCatalogEntry( summary({ @@ -312,10 +319,7 @@ describe("daemon supervisor passive subagent topology", () => { }; const target = { ...base, id: "target", path: join(directory, "target.jsonl"), parentSessionPath, rlmDepth: 1 }; const legacy = { ...base, id: "legacy", path: join(directory, "legacy.jsonl"), parentSessionPath, name: "taken" }; - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); expect(() => supervisor.assertSavedSiblingNameAvailable([target, legacy], target, "taken")).toThrow( "an agent of that name already exists at depth 1 under this parent", @@ -330,10 +334,7 @@ describe("daemon supervisor passive subagent topology", () => { const siblingGate = new Promise((resolve) => { releaseSiblings = resolve; }); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); const resident = worker("opened"); const launchWorker = vi.fn(async () => resident); Object.assign(supervisor, { @@ -367,10 +368,7 @@ describe("daemon supervisor passive subagent topology", () => { const launchGate = new Promise((resolve) => { releaseLaunch = resolve; }); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); const resident = worker("opened"); resident.descriptor.ownerClientId = "owner"; const launchWorker = vi.fn(async () => { @@ -383,13 +381,13 @@ describe("daemon supervisor passive subagent topology", () => { const first = supervisor.createOrReuseWorker("owner", create); const sameOwner = supervisor.createOrReuseWorker("owner", create); const otherClient = supervisor.createOrReuseWorker("intruder", create); - const expectations = Promise.all([ - expect(first).resolves.toBe(resident), - expect(sameOwner).resolves.toBe(resident), - expect(otherClient).rejects.toMatchObject({ code: "session_already_active" }), - ]); + const firstResult = capturePromise(first); + const sameOwnerResult = capturePromise(sameOwner); + const otherClientResult = capturePromise(otherClient); releaseLaunch(); - await expectations; + expect(await firstResult).toEqual({ value: resident }); + expect(await sameOwnerResult).toEqual({ value: resident }); + expect((await otherClientResult).error).toHaveProperty("code", "session_already_active"); expect(launchWorker).toHaveBeenCalledOnce(); }); @@ -401,10 +399,7 @@ describe("daemon supervisor passive subagent topology", () => { const reclaimGate = new Promise((resolve) => { releaseReclaim = resolve; }); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); const stale = worker("stale"); stale.descriptor.createCommand = { config: { cwd: directory }, sessionPath }; supervisor.workers.set(stale.descriptor.workerId, stale); @@ -422,13 +417,13 @@ describe("daemon supervisor passive subagent topology", () => { const first = supervisor.createOrReuseWorker("owner", create); const second = supervisor.createOrReuseWorker("owner", create); const intruder = supervisor.createOrReuseWorker("intruder", create); - const expectations = Promise.all([ - expect(first).resolves.toBe(resident), - expect(second).resolves.toBe(resident), - expect(intruder).rejects.toMatchObject({ code: "session_already_active" }), - ]); + const firstResult = capturePromise(first); + const secondResult = capturePromise(second); + const intruderResult = capturePromise(intruder); releaseReclaim(); - await expectations; + expect(await firstResult).toEqual({ value: resident }); + expect(await secondResult).toEqual({ value: resident }); + expect((await intruderResult).error).toHaveProperty("code", "session_already_active"); expect(launchWorker).toHaveBeenCalledOnce(); }); @@ -440,10 +435,7 @@ describe("daemon supervisor passive subagent topology", () => { const launchGate = new Promise((resolve) => { releaseLaunch = resolve; }); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); const launchWorker = vi.fn(async () => { await launchGate; throw new Error("launch exploded"); @@ -453,12 +445,13 @@ describe("daemon supervisor passive subagent topology", () => { const create = { type: "create" as const, sessionPath, lifecycle: "client_owned" as const }; const first = supervisor.createOrReuseWorker("owner", create); const joiner = supervisor.createOrReuseWorker("intruder", create); - const expectations = Promise.all([ - expect(first).rejects.toThrow("launch exploded"), - expect(joiner).rejects.toThrow("launch exploded"), - ]); + const firstResult = capturePromise(first); + const joinerResult = capturePromise(joiner); releaseLaunch(); - await expectations; + expect((await firstResult).error).toBeInstanceOf(Error); + expect((await firstResult).error).toHaveProperty("message", "launch exploded"); + expect((await joinerResult).error).toBeInstanceOf(Error); + expect((await joinerResult).error).toHaveProperty("message", "launch exploded"); }); it("uses injective structural session name reservation keys", () => { @@ -497,10 +490,7 @@ describe("daemon supervisor passive subagent topology", () => { }); const secondWorker = worker("second", [secondSummary]); secondWorker.client.request.mockResolvedValue(success(undefined, "rename", secondSummary)); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); supervisor.workers.set("first", firstWorker); supervisor.workers.set("second", secondWorker); seedSupervisorRoster(supervisor, firstWorker, secondWorker); @@ -542,10 +532,7 @@ describe("daemon supervisor passive subagent topology", () => { const ownedWorker = worker("owned", [ownedSummary]); ownedWorker.descriptor.ownerClientId = "interactive-client"; ownedWorker.client.request.mockResolvedValue(success(undefined, "set_session_name")); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); supervisor.workers.set("owned", ownedWorker); seedSupervisorRoster(supervisor, ownedWorker); Object.assign(supervisor, { catalog: { list: vi.fn(async () => []) } }); @@ -614,10 +601,7 @@ describe("daemon supervisor passive subagent topology", () => { }); const secondWorker = worker("second", [secondSummary]); secondWorker.client.request.mockResolvedValue(success(undefined, "rename_saved_session", secondSummary)); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); supervisor.workers.set("first", firstWorker); supervisor.workers.set("second", secondWorker); seedSupervisorRoster(supervisor, firstWorker, secondWorker); @@ -677,10 +661,7 @@ describe("daemon supervisor passive subagent topology", () => { releaseRename = resolve; }); const rename = vi.fn(async () => renameGate); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); Object.assign(supervisor, { rlmLedgerSiblings: vi.fn(async () => saved), rlmSpawnLedger: vi.fn(() => ({ appendRenameByChildPath: vi.fn(async () => {}) })), @@ -734,10 +715,7 @@ describe("daemon supervisor passive subagent topology", () => { await launchGate; return launched; }); - const supervisor = new DaemonSupervisor(join(directory, "daemon.sock"), { - defaultSessionConfig: { agentDir: directory, cwd: directory }, - descriptorDir: join(directory, "workers"), - }) as unknown as SupervisorInternals; + const supervisor = createSupervisor(directory); Object.assign(supervisor, { rlmLedgerSiblings: vi.fn(async (path: string) => [path === firstChild.path ? firstChild : secondChild]), catalog: { diff --git a/packages/coding-agent/test/daemon-supervisor-monitor.test.ts b/packages/coding-agent/test/daemon-supervisor-monitor.test.ts index 8d6954ffde..e017e6f195 100644 --- a/packages/coding-agent/test/daemon-supervisor-monitor.test.ts +++ b/packages/coding-agent/test/daemon-supervisor-monitor.test.ts @@ -1,6 +1,7 @@ import type { ChildProcess, SpawnOptions } from "node:child_process"; import { EventEmitter } from "node:events"; import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { createRequire } from "node:module"; import type { Socket } from "node:net"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -50,96 +51,92 @@ const workerLaunchTestState = vi.hoisted(() => ({ spawned: [] as Array<{ child: ChildProcess; args: readonly string[] }>, })); -vi.mock("node:child_process", async (importOriginal) => { - const actual = (await importOriginal()) as Record & { - spawn(command: string, args: readonly string[], options: SpawnOptions): ChildProcess; - }; - return { - ...actual, - spawn(command: string, args: readonly string[], options: SpawnOptions): ChildProcess { - const failureCode = workerLaunchTestState.spawnFailureCode; - if (failureCode) { - // Node's failed-spawn shape: no pid, stdio undefined, "error" then "close". - const failing = Object.assign(new EventEmitter(), { - pid: undefined, - stdio: undefined, - stderr: undefined, - unref: () => {}, - }) as unknown as ChildProcess; - process.nextTick(() => { - failing.emit( - "error", - Object.assign(new Error(`spawn ${command} ${failureCode}`), { code: failureCode }), - ); - failing.emit("close", null, null); - }); - return failing; - } - const child = actual.spawn(command, args, options); - if (workerLaunchTestState.capture) { - workerLaunchTestState.spawned.push({ child, args }); - } - return child; - }, - }; -}); +const __childProcess = createRequire(import.meta.url)("node:child_process") as Record & { + spawn(command: string, args: readonly string[], options: SpawnOptions): ChildProcess; +}; +const spawnChildProcess = __childProcess.spawn; +vi.mock("node:child_process", () => ({ + ...__childProcess, + spawn(command: string, args: readonly string[], options: SpawnOptions): ChildProcess { + const failureCode = workerLaunchTestState.spawnFailureCode; + if (failureCode) { + // Node's failed-spawn shape: no pid, stdio undefined, "error" then "close". + const failing = Object.assign(new EventEmitter(), { + pid: undefined, + stdio: undefined, + stderr: undefined, + unref: () => {}, + }) as unknown as ChildProcess; + queueMicrotask(() => { + failing.emit("error", Object.assign(new Error(`spawn ${command} ${failureCode}`), { code: failureCode })); + failing.emit("close", null, null); + }); + return failing; + } + const child = spawnChildProcess(command, args, options); + if (workerLaunchTestState.capture) { + workerLaunchTestState.spawned.push({ child, args }); + } + return child; + }, +})); -vi.mock("../src/cli/subprocess-launch.js", async (importOriginal) => { - const actual = (await importOriginal()) as Record; - return { - ...actual, - createCliSubprocessLaunchSpec(args: readonly string[]) { - if (!workerLaunchTestState.capture) { - return (actual.createCliSubprocessLaunchSpec as (args: readonly string[]) => unknown)(args); - } - if (workerLaunchTestState.fixtureMode === "rollback-gate") { - const markerPath = JSON.stringify(workerLaunchTestState.gateMarkerPath); - const commitMarker = JSON.stringify(DAEMON_WORKER_STARTUP_GATE_COMMIT); - return { - command: process.execPath, - args: [ - "--eval", - `const fs = require("node:fs"); const marker = fs.readFileSync(3, "utf8"); if (marker === ${commitMarker}) { fs.writeFileSync(${markerPath}, marker); setInterval(() => {}, 1000); }`, - "--", - ...args, - ], - }; - } - if (workerLaunchTestState.fixtureMode === "close-gate") { - return { - command: process.execPath, - args: ["--eval", 'require("node:fs").closeSync(3)'], - }; - } - if (workerLaunchTestState.fixtureMode === "successful-gate") { - const markerPath = JSON.stringify(workerLaunchTestState.gateMarkerPath); - return { - command: process.execPath, - args: [ - "--eval", - `const fs = require("node:fs"); const marker = fs.readFileSync(3, "utf8"); fs.writeFileSync(${markerPath}, marker); setInterval(() => {}, 1000);`, - ], - }; - } +const __subprocessLaunch = createRequire(import.meta.url)("../src/cli/subprocess-launch.js") as Record; +const createSubprocessLaunchSpec = __subprocessLaunch.createCliSubprocessLaunchSpec as ( + args: readonly string[], +) => unknown; +vi.mock("../src/cli/subprocess-launch.js", () => ({ + ...__subprocessLaunch, + createCliSubprocessLaunchSpec(args: readonly string[]) { + if (!workerLaunchTestState.capture) { + return createSubprocessLaunchSpec(args); + } + if (workerLaunchTestState.fixtureMode === "rollback-gate") { + const markerPath = JSON.stringify(workerLaunchTestState.gateMarkerPath); + const commitMarker = JSON.stringify(DAEMON_WORKER_STARTUP_GATE_COMMIT); return { command: process.execPath, - args: [workerLaunchTestState.tsxCliPath, workerLaunchTestState.cliEntrypoint, ...args], + args: [ + "--eval", + `const fs = require("node:fs"); const marker = fs.readFileSync(3, "utf8"); if (marker === ${commitMarker}) { fs.writeFileSync(${markerPath}, marker); setInterval(() => {}, 1000); }`, + "--", + ...args, + ], }; - }, - }; -}); + } + if (workerLaunchTestState.fixtureMode === "close-gate") { + return { + command: process.execPath, + args: ["--eval", 'require("node:fs").closeSync(3); process.reallyExit(0)'], + }; + } + if (workerLaunchTestState.fixtureMode === "successful-gate") { + const markerPath = JSON.stringify(workerLaunchTestState.gateMarkerPath); + return { + command: process.execPath, + args: [ + "--eval", + `const fs = require("node:fs"); const marker = fs.readFileSync(3, "utf8"); fs.writeFileSync(${markerPath}, marker); setInterval(() => {}, 1000);`, + ], + }; + } + return { + command: process.execPath, + args: [workerLaunchTestState.tsxCliPath, workerLaunchTestState.cliEntrypoint, ...args], + }; + }, +})); -vi.mock("../src/core/session-lease.js", async (importOriginal) => { - const actual = (await importOriginal()) as Record & { - getProcessStartId(pid: number): string | undefined; - }; - return { - ...actual, - getProcessStartId(pid: number): string | undefined { - return workerLaunchTestState.forceMissingProcessStartId ? undefined : actual.getProcessStartId(pid); - }, - }; -}); +const __sessionLease = createRequire(import.meta.url)("../src/core/session-lease.js") as Record & { + getProcessStartId(pid: number): string | undefined; +}; +const readProcessStartId = __sessionLease.getProcessStartId; +vi.mock("../src/core/session-lease.js", () => ({ + ...__sessionLease, + getProcessStartId(pid: number): string | undefined { + return workerLaunchTestState.forceMissingProcessStartId ? undefined : readProcessStartId(pid); + }, +})); const supervisorRegistryDirEnv = "PRIME_AGENT_INTERNAL_DAEMON_SUPERVISOR_REGISTRY_DIR"; const previousSupervisorRegistryDir = process.env[supervisorRegistryDirEnv]; @@ -699,9 +696,12 @@ describe("daemon worker supervisor monitoring", () => { launchWorker(command: { type: "create"; config: { cwd: string; agentDir: string } }): Promise; }; - await expect(supervisor.launchWorker({ type: "create", config: { cwd: root, agentDir: root } })).rejects.toThrow( - /EMFILE.*resident session workers.*ulimit -n/s, - ); + const emfileFailure = await supervisor + .launchWorker({ type: "create", config: { cwd: root, agentDir: root } }) + .then(() => undefined) + .catch((error: Error) => error); + expect(emfileFailure).toBeInstanceOf(Error); + expect(emfileFailure?.message).toMatch(/EMFILE.*resident session workers.*ulimit -n/s); expect(workers.size).toBe(0); workerLaunchTestState.spawnFailureCode = "ENOENT"; diff --git a/packages/coding-agent/test/daemon-supervisor-process.test.ts b/packages/coding-agent/test/daemon-supervisor-process.test.ts index 765a9edc26..7fb14bc803 100644 --- a/packages/coding-agent/test/daemon-supervisor-process.test.ts +++ b/packages/coding-agent/test/daemon-supervisor-process.test.ts @@ -23,9 +23,9 @@ import { isDaemonWorkerFrameHeader, } from "../src/modes/daemon/daemon-worker-protocol.js"; import { encodePrivateFrame, PrivateFrameDecoder } from "../src/modes/session-worker/private-framing.js"; +import { isTestTagEnabled } from "./test-tags.js"; const cliPath = resolve(__dirname, "../src/cli.ts"); -const tsxPath = resolve(__dirname, "../../../node_modules/tsx/dist/cli.mjs"); const blockingProcessPath = resolve(__dirname, "fixtures/blocking-process.mjs"); const tempDirs: string[] = []; const children = new Set(); @@ -33,6 +33,7 @@ const workerPids = new Set(); const daemonSockets = new Set(); const childDiagnostics = new WeakMap(); const PROCESS_STRESS_WORKERS = Number.parseInt(process.env.PRIME_AGENT_STRESS_WORKERS ?? "10", 10); +const processStressIt = isTestTagEnabled("process-stress") ? it : it.skip; afterEach(async () => { for (const socketPath of daemonSockets) { @@ -94,7 +95,7 @@ function spawnSupervisor( daemonSockets.add(socketPath); const child = spawn( process.execPath, - [tsxPath, cliPath, "--mode", "daemon", "--daemon-socket", socketPath, "--offline", ...extraArgs], + [cliPath, "--mode", "daemon", "--daemon-socket", socketPath, "--offline", ...extraArgs], { cwd, env: { @@ -102,7 +103,6 @@ function spawnSupervisor( ...extraEnv, [ENV_AGENT_DIR]: agentDir, PI_OFFLINE: "1", - TSX_TSCONFIG_PATH: resolve(__dirname, "../../../tsconfig.json"), }, stdio: ["ignore", "pipe", "pipe"], }, @@ -697,7 +697,7 @@ describe("daemon supervisor resident workers", () => { type: "create", lifecycle: "client_owned", noSession: true, - launchEnv: { TSX_TSCONFIG_PATH: resolve(__dirname, "../../../tsconfig.json") }, + launchEnv: {}, config: { cwd: projectDir, agentDir, noTools: true, noExtensions: true }, }); if (!created.success) { @@ -782,7 +782,7 @@ describe("daemon supervisor resident workers", () => { await waitForSocketGone(socketPath); }, 30_000); - it("cancels an archived session heartbeat without spawning a worker", { tags: ["process-stress"] }, async () => { + processStressIt("cancels an archived session heartbeat without spawning a worker", async () => { const root = tempDir(); const agentDir = join(root, "agent"); const projectDir = join(root, "project"); @@ -835,9 +835,7 @@ describe("daemon supervisor resident workers", () => { await waitForSocketGone(socketPath); }); - it("cancels an orphan heartbeat instead of recreating a descriptorless active session", { - tags: ["process-stress"], - }, async () => { + processStressIt("cancels an orphan heartbeat instead of recreating a descriptorless active session", async () => { const root = tempDir(); const agentDir = join(root, "agent"); const projectDir = join(root, "project"); @@ -912,7 +910,7 @@ describe("daemon supervisor resident workers", () => { await waitForSocketGone(socketPath); }); - it("survives a worker process spawn error", { tags: ["process-stress"] }, async () => { + processStressIt("survives a worker process spawn error", async () => { const root = tempDir(); const agentDir = join(root, "agent"); const projectDir = join(root, "project"); @@ -1008,233 +1006,244 @@ describe("daemon supervisor resident workers", () => { await waitForSocketGone(socketPath); }, 30_000); - it("finalizes a timed-out worker stop by force-stopping the process and removing its registration", { - tags: ["process-stress"], - timeout: 45_000, - }, async () => { - const root = tempDir(); - const agentDir = join(root, "agent"); - const projectDir = join(root, "project"); - const sessionDir = join(agentDir, "sessions"); - const socketPath = join( - tmpdir(), - `prime-supervisor-stop-finalize-${process.pid}-${randomUUID().slice(0, 8)}.sock`, - ); - mkdirSync(projectDir, { recursive: true }); - const sessionManager = SessionManager.create(projectDir, sessionDir); - sessionManager.appendMessage({ role: "user", content: "finalize me", timestamp: 1 }); - const sessionFile = sessionManager.getSessionFile(); - if (!sessionFile) { - throw new Error("Fixture session did not persist"); - } - - const supervisor = spawnSupervisor(agentDir, socketPath, projectDir); - const client = await connectEventually(socketPath, supervisor); - const created = await client.request({ - type: "create", - sessionPath: sessionFile, - lifecycle: "client_owned", - config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, - }); - if (!created.success) { - throw new Error(created.error); - } - const summary = requireSummary(created.data); - if (!summary.workerPid) { - throw new Error("Resident worker did not expose its pid"); - } - workerPids.add(summary.workerPid); - const activeSessionId = summary.activeSessionId ?? summary.id; - - // A suspended worker cannot exit within the stop deadline, so the stop - // times out and used to leave a tombstoned registration behind forever. - process.kill(summary.workerPid, "SIGSTOP"); - const stopResult = await client.request({ type: "complete_owned_session", activeSessionId }, 30_000); - expect(stopResult).toMatchObject({ - success: false, - error: expect.stringContaining("did not stop"), - }); - const tombstone = readWorkerDescriptor(agentDir); - expect(tombstone.stopRequestedAt).toEqual(expect.any(String)); - - // The supervisor finishes the interrupted stop on its own: it escalates - // to SIGKILL, waits for the process to die, and removes the registration. - await waitForProcessGone(summary.workerPid); - workerPids.delete(summary.workerPid); - await waitForCondition( - () => countWorkerDescriptors(agentDir) === 0, - "Timed-out worker stop was not finalized", - 20_000, - ); - - await client.request({ type: "shutdown" }); - client.close(); - await waitForSocketGone(socketPath); - }); - - it("resumes a saved session immediately after a worker stop fails and the process dies", { - tags: ["process-stress"], - timeout: 45_000, - }, async () => { - const root = tempDir(); - const agentDir = join(root, "agent"); - const projectDir = join(root, "project"); - const sessionDir = join(agentDir, "sessions"); - const socketPath = join(tmpdir(), `prime-supervisor-resume-heal-${process.pid}-${randomUUID().slice(0, 8)}.sock`); - mkdirSync(projectDir, { recursive: true }); - const sessionManager = SessionManager.create(projectDir, sessionDir); - sessionManager.appendMessage({ role: "user", content: "resume me", timestamp: 1 }); - const sessionFile = sessionManager.getSessionFile(); - if (!sessionFile) { - throw new Error("Fixture session did not persist"); - } - - const supervisor = spawnSupervisor(agentDir, socketPath, projectDir); - const client = await connectEventually(socketPath, supervisor); - const created = await client.request({ - type: "create", - sessionPath: sessionFile, - lifecycle: "client_owned", - config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, - }); - if (!created.success) { - throw new Error(created.error); - } - const summary = requireSummary(created.data); - if (!summary.workerPid) { - throw new Error("Resident worker did not expose its pid"); - } - workerPids.add(summary.workerPid); - const activeSessionId = summary.activeSessionId ?? summary.id; + processStressIt( + "finalizes a timed-out worker stop by force-stopping the process and removing its registration", + { timeout: 45_000 }, + async () => { + const root = tempDir(); + const agentDir = join(root, "agent"); + const projectDir = join(root, "project"); + const sessionDir = join(agentDir, "sessions"); + const socketPath = join( + tmpdir(), + `prime-supervisor-stop-finalize-${process.pid}-${randomUUID().slice(0, 8)}.sock`, + ); + mkdirSync(projectDir, { recursive: true }); + const sessionManager = SessionManager.create(projectDir, sessionDir); + sessionManager.appendMessage({ role: "user", content: "finalize me", timestamp: 1 }); + const sessionFile = sessionManager.getSessionFile(); + if (!sessionFile) { + throw new Error("Fixture session did not persist"); + } - // A suspended worker forces the stop past its deadline, leaving a - // tombstoned registration for a process that dies moments later. - process.kill(summary.workerPid, "SIGSTOP"); - const stopResult = await client.request({ type: "complete_owned_session", activeSessionId }, 30_000); - expect(stopResult).toMatchObject({ - success: false, - error: expect.stringContaining("did not stop"), - }); - process.kill(summary.workerPid, "SIGKILL"); - await waitForProcessGone(summary.workerPid); - workerPids.delete(summary.workerPid); + const supervisor = spawnSupervisor(agentDir, socketPath, projectDir); + const client = await connectEventually(socketPath, supervisor); + const created = await client.request({ + type: "create", + sessionPath: sessionFile, + lifecycle: "client_owned", + config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, + }); + if (!created.success) { + throw new Error(created.error); + } + const summary = requireSummary(created.data); + if (!summary.workerPid) { + throw new Error("Resident worker did not expose its pid"); + } + workerPids.add(summary.workerPid); + const activeSessionId = summary.activeSessionId ?? summary.id; + + // A suspended worker cannot exit within the stop deadline, so the stop + // times out and used to leave a tombstoned registration behind forever. + process.kill(summary.workerPid, "SIGSTOP"); + const stopResult = await client.request({ type: "complete_owned_session", activeSessionId }, 30_000); + expect(stopResult).toMatchObject({ + success: false, + error: expect.stringContaining("did not stop"), + }); + const tombstone = readWorkerDescriptor(agentDir); + expect(tombstone.stopRequestedAt).toEqual(expect.any(String)); + + // The supervisor finishes the interrupted stop on its own: it escalates + // to SIGKILL, waits for the process to die, and removes the registration. + await waitForProcessGone(summary.workerPid); + workerPids.delete(summary.workerPid); + await waitForCondition( + () => countWorkerDescriptors(agentDir) === 0, + "Timed-out worker stop was not finalized", + 20_000, + ); - // Resuming the saved transcript must not be blocked by the stale - // registration. Whichever cleanup wins the race — the background stop - // finalizer or the resume-time reclaim (each covered deterministically - // by unit tests) — the user-visible guarantee is the same: the resume - // below must succeed with a fresh worker. - const resumed = await client.request({ - type: "create", - sessionPath: sessionFile, - config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, - }); - expect(resumed.success).toBe(true); - const resumedSummary = requireSummary(resumed.success ? resumed.data : undefined); - expect(resumedSummary.sessionId).toBe(summary.sessionId); - expect(resumedSummary.workerPid).not.toBe(summary.workerPid); - expect(resumedSummary.workerState).toBe("ready"); - if (resumedSummary.workerPid) { - workerPids.add(resumedSummary.workerPid); - } + await client.request({ type: "shutdown" }); + client.close(); + await waitForSocketGone(socketPath); + }, + ); - const attached = await client.request({ - type: "attach", - activeSessionId: resumedSummary.activeSessionId ?? resumedSummary.id, - }); - expect(attached.success).toBe(true); + processStressIt( + "resumes a saved session immediately after a worker stop fails and the process dies", + { timeout: 45_000 }, + async () => { + const root = tempDir(); + const agentDir = join(root, "agent"); + const projectDir = join(root, "project"); + const sessionDir = join(agentDir, "sessions"); + const socketPath = join( + tmpdir(), + `prime-supervisor-resume-heal-${process.pid}-${randomUUID().slice(0, 8)}.sock`, + ); + mkdirSync(projectDir, { recursive: true }); + const sessionManager = SessionManager.create(projectDir, sessionDir); + sessionManager.appendMessage({ role: "user", content: "resume me", timestamp: 1 }); + const sessionFile = sessionManager.getSessionFile(); + if (!sessionFile) { + throw new Error("Fixture session did not persist"); + } - await client.request({ type: "shutdown" }); - client.close(); - await waitForSocketGone(socketPath); - if (resumedSummary.workerPid) { - await waitForProcessGone(resumedSummary.workerPid); - workerPids.delete(resumedSummary.workerPid); - } - }); + const supervisor = spawnSupervisor(agentDir, socketPath, projectDir); + const client = await connectEventually(socketPath, supervisor); + const created = await client.request({ + type: "create", + sessionPath: sessionFile, + lifecycle: "client_owned", + config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, + }); + if (!created.success) { + throw new Error(created.error); + } + const summary = requireSummary(created.data); + if (!summary.workerPid) { + throw new Error("Resident worker did not expose its pid"); + } + workerPids.add(summary.workerPid); + const activeSessionId = summary.activeSessionId ?? summary.id; + + // A suspended worker forces the stop past its deadline, leaving a + // tombstoned registration for a process that dies moments later. + process.kill(summary.workerPid, "SIGSTOP"); + const stopResult = await client.request({ type: "complete_owned_session", activeSessionId }, 30_000); + expect(stopResult).toMatchObject({ + success: false, + error: expect.stringContaining("did not stop"), + }); + process.kill(summary.workerPid, "SIGKILL"); + await waitForProcessGone(summary.workerPid); + workerPids.delete(summary.workerPid); + + // Resuming the saved transcript must not be blocked by the stale + // registration. Whichever cleanup wins the race — the background stop + // finalizer or the resume-time reclaim (each covered deterministically + // by unit tests) — the user-visible guarantee is the same: the resume + // below must succeed with a fresh worker. + const resumed = await client.request({ + type: "create", + sessionPath: sessionFile, + config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, + }); + expect(resumed.success).toBe(true); + const resumedSummary = requireSummary(resumed.success ? resumed.data : undefined); + expect(resumedSummary.sessionId).toBe(summary.sessionId); + expect(resumedSummary.workerPid).not.toBe(summary.workerPid); + expect(resumedSummary.workerState).toBe("ready"); + if (resumedSummary.workerPid) { + workerPids.add(resumedSummary.workerPid); + } - it("does not resurrect an intentionally stopped root when the supervisor dies during kill", { - tags: ["process-stress"], - timeout: 30_000, - }, async () => { - const root = tempDir(); - const agentDir = join(root, "agent"); - const projectDir = join(root, "project"); - const sessionDir = join(agentDir, "sessions"); - const socketPath = join(tmpdir(), `prime-supervisor-stop-race-${process.pid}-${randomUUID().slice(0, 8)}.sock`); - mkdirSync(projectDir, { recursive: true }); - const sessionManager = SessionManager.create(projectDir, sessionDir); - sessionManager.appendMessage({ role: "user", content: "stop me", timestamp: 1 }); - sessionManager.appendSessionState({ status: "active" }); - const sessionFile = sessionManager.getSessionFile(); - if (!sessionFile) { - throw new Error("Fixture session did not persist"); - } + const attached = await client.request({ + type: "attach", + activeSessionId: resumedSummary.activeSessionId ?? resumedSummary.id, + }); + expect(attached.success).toBe(true); - const firstSupervisor = spawnSupervisor(agentDir, socketPath, projectDir); - const client = await connectEventually(socketPath, firstSupervisor); - const firstSupervisorPid = client.hello?.supervisorPid; - if (!firstSupervisorPid) { - throw new Error("Daemon hello did not expose its supervisor pid"); - } - const created = await client.request({ - type: "create", - sessionPath: sessionFile, - config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, - }); - if (!created.success) { - throw new Error(created.error); - } - const summary = requireSummary(created.data); - if (!summary.workerPid) { - throw new Error("Resident worker did not expose its pid"); - } - workerPids.add(summary.workerPid); - const activeSessionId = summary.activeSessionId ?? summary.id; - const heartbeatResponse = await client.request({ - type: "heartbeat_set", - activeSessionId, - schedule: "every 1h", - prompt: "continue old work", - }); - if (!heartbeatResponse.success || !heartbeatResponse.data || typeof heartbeatResponse.data !== "object") { - throw new Error(heartbeatResponse.success ? "Heartbeat response was missing data" : heartbeatResponse.error); - } - const heartbeat = (heartbeatResponse.data as { heartbeat: { id: string } }).heartbeat; - const cronStore = AgentCronJobStore.forSessionArtifacts(); - cronStore.registerSessionArtifact(summary.sessionId, sessionManager.getSessionArtifactDir()!); - process.kill(summary.workerPid, "SIGSTOP"); - const killResult = client.request({ type: "kill", activeSessionId }).catch((error: unknown) => error); - const tombstone = await waitForWorkerStopTombstone(agentDir); - expect(tombstone.stopRequestedAt).toEqual(expect.any(String)); - expect(tombstone.archiveOnStop).toBe(true); + await client.request({ type: "shutdown" }); + client.close(); + await waitForSocketGone(socketPath); + if (resumedSummary.workerPid) { + await waitForProcessGone(resumedSummary.workerPid); + workerPids.delete(resumedSummary.workerPid); + } + }, + ); - process.kill(firstSupervisorPid, "SIGKILL"); - await waitForExit(firstSupervisor); - children.delete(firstSupervisor); - client.close(); - await expect(killResult).resolves.toBeInstanceOf(Error); + processStressIt( + "does not resurrect an intentionally stopped root when the supervisor dies during kill", + { timeout: 30_000 }, + async () => { + const root = tempDir(); + const agentDir = join(root, "agent"); + const projectDir = join(root, "project"); + const sessionDir = join(agentDir, "sessions"); + const socketPath = join( + tmpdir(), + `prime-supervisor-stop-race-${process.pid}-${randomUUID().slice(0, 8)}.sock`, + ); + mkdirSync(projectDir, { recursive: true }); + const sessionManager = SessionManager.create(projectDir, sessionDir); + sessionManager.appendMessage({ role: "user", content: "stop me", timestamp: 1 }); + sessionManager.appendSessionState({ status: "active" }); + const sessionFile = sessionManager.getSessionFile(); + if (!sessionFile) { + throw new Error("Fixture session did not persist"); + } - const replacementSupervisor = spawnSupervisor(agentDir, socketPath, projectDir); - const replacementClient = await connectEventually(socketPath, replacementSupervisor); - const listed = await replacementClient.request({ type: "list" }); - expect(listed.success).toBe(true); - const sessions = requireSessionList(listed.success ? listed.data : undefined); - expect(sessions.filter((session) => session.activeSessionId || session.workerPid)).toEqual([]); - await waitForProcessGone(summary.workerPid); - workerPids.delete(summary.workerPid); - await waitForCondition( - () => countWorkerDescriptors(agentDir) === 0, - "Intentional worker stop descriptor was not removed", - ); - expect(countWorkerDescriptors(agentDir)).toBe(0); - expect((await readSessionInfo(sessionFile))?.state).toEqual({ status: "archived" }); - expect(cronStore.list().find((job) => job.id === heartbeat.id)).toMatchObject({ status: "cancelled" }); + const firstSupervisor = spawnSupervisor(agentDir, socketPath, projectDir); + const client = await connectEventually(socketPath, firstSupervisor); + const firstSupervisorPid = client.hello?.supervisorPid; + if (!firstSupervisorPid) { + throw new Error("Daemon hello did not expose its supervisor pid"); + } + const created = await client.request({ + type: "create", + sessionPath: sessionFile, + config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, + }); + if (!created.success) { + throw new Error(created.error); + } + const summary = requireSummary(created.data); + if (!summary.workerPid) { + throw new Error("Resident worker did not expose its pid"); + } + workerPids.add(summary.workerPid); + const activeSessionId = summary.activeSessionId ?? summary.id; + const heartbeatResponse = await client.request({ + type: "heartbeat_set", + activeSessionId, + schedule: "every 1h", + prompt: "continue old work", + }); + if (!heartbeatResponse.success || !heartbeatResponse.data || typeof heartbeatResponse.data !== "object") { + throw new Error( + heartbeatResponse.success ? "Heartbeat response was missing data" : heartbeatResponse.error, + ); + } + const heartbeat = (heartbeatResponse.data as { heartbeat: { id: string } }).heartbeat; + const cronStore = AgentCronJobStore.forSessionArtifacts(); + cronStore.registerSessionArtifact(summary.sessionId, sessionManager.getSessionArtifactDir()!); + process.kill(summary.workerPid, "SIGSTOP"); + const killResult = client.request({ type: "kill", activeSessionId }).catch((error: unknown) => error); + const tombstone = await waitForWorkerStopTombstone(agentDir); + expect(tombstone.stopRequestedAt).toEqual(expect.any(String)); + expect(tombstone.archiveOnStop).toBe(true); + + process.kill(firstSupervisorPid, "SIGKILL"); + await waitForExit(firstSupervisor); + children.delete(firstSupervisor); + client.close(); + await expect(killResult).resolves.toBeInstanceOf(Error); + + const replacementSupervisor = spawnSupervisor(agentDir, socketPath, projectDir); + const replacementClient = await connectEventually(socketPath, replacementSupervisor); + const listed = await replacementClient.request({ type: "list" }); + expect(listed.success).toBe(true); + const sessions = requireSessionList(listed.success ? listed.data : undefined); + expect(sessions.filter((session) => session.activeSessionId || session.workerPid)).toEqual([]); + await waitForProcessGone(summary.workerPid); + workerPids.delete(summary.workerPid); + await waitForCondition( + () => countWorkerDescriptors(agentDir) === 0, + "Intentional worker stop descriptor was not removed", + ); + expect(countWorkerDescriptors(agentDir)).toBe(0); + expect((await readSessionInfo(sessionFile))?.state).toEqual({ status: "archived" }); + expect(cronStore.list().find((job) => job.id === heartbeat.id)).toMatchObject({ status: "cancelled" }); - await replacementClient.request({ type: "shutdown" }); - replacementClient.close(); - await waitForSocketGone(socketPath); - }); + await replacementClient.request({ type: "shutdown" }); + replacementClient.close(); + await waitForSocketGone(socketPath); + }, + ); it("hosts and adopts isolated worker processes", async () => { const root = tempDir(); @@ -1307,142 +1316,146 @@ describe("daemon supervisor resident workers", () => { ); }, 60_000); - it("hosts resident roots in isolated worker processes without a session cap", { - tags: ["process-stress"], - timeout: 180_000, - }, async () => { - const root = tempDir(); - const agentDir = join(root, "agent"); - const projectDir = join(root, "project"); - const sessionDir = join(agentDir, "sessions"); - const socketPath = join(tmpdir(), `prime-supervisor-many-roots-${process.pid}-${randomUUID().slice(0, 8)}.sock`); - mkdirSync(projectDir, { recursive: true }); - const sessionFiles = Array.from({ length: PROCESS_STRESS_WORKERS }, (_, index) => { - const manager = SessionManager.create(projectDir, sessionDir); - manager.appendMessage({ role: "user", content: `root ${index}`, timestamp: index + 1 }); - const sessionFile = manager.getSessionFile(); - if (!sessionFile) { - throw new Error("Fixture session did not persist"); - } - return sessionFile; - }); + processStressIt( + "hosts resident roots in isolated worker processes without a session cap", + { timeout: 180_000 }, + async () => { + const root = tempDir(); + const agentDir = join(root, "agent"); + const projectDir = join(root, "project"); + const sessionDir = join(agentDir, "sessions"); + const socketPath = join( + tmpdir(), + `prime-supervisor-many-roots-${process.pid}-${randomUUID().slice(0, 8)}.sock`, + ); + mkdirSync(projectDir, { recursive: true }); + const sessionFiles = Array.from({ length: PROCESS_STRESS_WORKERS }, (_, index) => { + const manager = SessionManager.create(projectDir, sessionDir); + manager.appendMessage({ role: "user", content: `root ${index}`, timestamp: index + 1 }); + const sessionFile = manager.getSessionFile(); + if (!sessionFile) { + throw new Error("Fixture session did not persist"); + } + return sessionFile; + }); - const supervisor = spawnSupervisor(agentDir, socketPath, projectDir); - const client = await connectEventually(socketPath, supervisor); - const externalLease = acquireSessionLease(sessionFiles[0], agentDir, { - [SESSION_LEASES_ENABLED_ENV]: "1", - [SESSION_LEASE_OWNER_ID_ENV]: "external-owner", - }); - const conflict = await client.request({ - type: "create", - sessionPath: sessionFiles[0], - config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, - }); - expect(conflict).toMatchObject({ - success: false, - errorInfo: { code: "session_already_active", activeSessionId: "external-owner" }, - }); - const emptyAfterConflict = await client.request({ type: "list" }); - expect(requireSessionList(emptyAfterConflict.success ? emptyAfterConflict.data : undefined)).toHaveLength(0); - externalLease?.release(); - const created = await Promise.all( - sessionFiles.map((sessionPath) => - client.request({ - type: "create", - sessionPath, - config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, - }), - ), - ); - const summaries = created.map((response) => { - if (!response.success) { - throw new Error(response.error); + const supervisor = spawnSupervisor(agentDir, socketPath, projectDir); + const client = await connectEventually(socketPath, supervisor); + const externalLease = acquireSessionLease(sessionFiles[0], agentDir, { + [SESSION_LEASES_ENABLED_ENV]: "1", + [SESSION_LEASE_OWNER_ID_ENV]: "external-owner", + }); + const conflict = await client.request({ + type: "create", + sessionPath: sessionFiles[0], + config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, + }); + expect(conflict).toMatchObject({ + success: false, + errorInfo: { code: "session_already_active", activeSessionId: "external-owner" }, + }); + const emptyAfterConflict = await client.request({ type: "list" }); + expect(requireSessionList(emptyAfterConflict.success ? emptyAfterConflict.data : undefined)).toHaveLength(0); + externalLease?.release(); + const created = await Promise.all( + sessionFiles.map((sessionPath) => + client.request({ + type: "create", + sessionPath, + config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, + }), + ), + ); + const summaries = created.map((response) => { + if (!response.success) { + throw new Error(response.error); + } + return requireSummary(response.data); + }); + const pids = summaries.map((summary) => summary.workerPid); + expect(new Set(pids).size).toBe(PROCESS_STRESS_WORKERS); + expect(pids).not.toContain(supervisor.pid); + for (const pid of pids) { + if (!pid) { + throw new Error("Resident root did not expose a worker pid"); + } + workerPids.add(pid); } - return requireSummary(response.data); - }); - const pids = summaries.map((summary) => summary.workerPid); - expect(new Set(pids).size).toBe(PROCESS_STRESS_WORKERS); - expect(pids).not.toContain(supervisor.pid); - for (const pid of pids) { - if (!pid) { - throw new Error("Resident root did not expose a worker pid"); + const firstActiveSessionId = summaries[0]!.activeSessionId ?? summaries[0]!.id; + const addedCron = await client.request({ + type: "cron_add", + activeSessionId: firstActiveSessionId, + schedule: "every 1h", + prompt: "check status", + }); + expect(addedCron.success).toBe(true); + const cronJob = (addedCron.success ? addedCron.data : undefined) as { job?: { id?: string } } | undefined; + if (!cronJob?.job?.id) { + throw new Error("Supervisor did not persist the cron job"); } - workerPids.add(pid); - } - const firstActiveSessionId = summaries[0]!.activeSessionId ?? summaries[0]!.id; - const addedCron = await client.request({ - type: "cron_add", - activeSessionId: firstActiveSessionId, - schedule: "every 1h", - prompt: "check status", - }); - expect(addedCron.success).toBe(true); - const cronJob = (addedCron.success ? addedCron.data : undefined) as { job?: { id?: string } } | undefined; - if (!cronJob?.job?.id) { - throw new Error("Supervisor did not persist the cron job"); - } - const listedCron = await client.request({ type: "cron_list", activeSessionId: firstActiveSessionId }); - expect(listedCron).toMatchObject({ success: true, data: { jobs: [{ id: cronJob.job.id }] } }); - const cancelledCron = await client.request({ type: "cron_cancel", jobId: cronJob.job.id }); - expect(cancelledCron.success).toBe(true); - const activeSessionIds = summaries.map((summary) => summary.activeSessionId ?? summary.id); - await Promise.all( - activeSessionIds.map((activeSessionId, index) => - startBlockingBash(client, activeSessionId, join(root, `stress-blocker-${index}.ready`)), - ), - ); - const heartbeats = await Promise.all( - activeSessionIds.map((activeSessionId, index) => - client.request({ - type: "heartbeat_set", - activeSessionId, - schedule: "every 10s", - prompt: `heartbeat ${index}`, - }), - ), - ); - expect(heartbeats.every((response) => response.success)).toBe(true); - await waitForCondition( - () => { - const stores = summaries.map((summary, index) => { - const store = AgentCronJobStore.forSessionArtifacts(); - store.registerSessionArtifact( - summary.sessionId, - join(dirname(dirname(sessionFiles[index]!)), "session-artifacts", summary.sessionId), - ); - return store; - }); - return stores.every((store) => store.list().some((job) => job.lastSkippedAt !== undefined)); - }, - "Session workers did not advance their heartbeats independently", - 15_000, - ); + const listedCron = await client.request({ type: "cron_list", activeSessionId: firstActiveSessionId }); + expect(listedCron).toMatchObject({ success: true, data: { jobs: [{ id: cronJob.job.id }] } }); + const cancelledCron = await client.request({ type: "cron_cancel", jobId: cronJob.job.id }); + expect(cancelledCron.success).toBe(true); + const activeSessionIds = summaries.map((summary) => summary.activeSessionId ?? summary.id); + await Promise.all( + activeSessionIds.map((activeSessionId, index) => + startBlockingBash(client, activeSessionId, join(root, `stress-blocker-${index}.ready`)), + ), + ); + const heartbeats = await Promise.all( + activeSessionIds.map((activeSessionId, index) => + client.request({ + type: "heartbeat_set", + activeSessionId, + schedule: "every 10s", + prompt: `heartbeat ${index}`, + }), + ), + ); + expect(heartbeats.every((response) => response.success)).toBe(true); + await waitForCondition( + () => { + const stores = summaries.map((summary, index) => { + const store = AgentCronJobStore.forSessionArtifacts(); + store.registerSessionArtifact( + summary.sessionId, + join(dirname(dirname(sessionFiles[index]!)), "session-artifacts", summary.sessionId), + ); + return store; + }); + return stores.every((store) => store.list().some((job) => job.lastSkippedAt !== undefined)); + }, + "Session workers did not advance their heartbeats independently", + 15_000, + ); - const listed = await client.request({ type: "list" }); - expect(listed.success).toBe(true); - expect(requireSessionList(listed.success ? listed.data : undefined)).toHaveLength(PROCESS_STRESS_WORKERS); - supervisor.kill("SIGTERM"); - await waitForExit(supervisor); - children.delete(supervisor); - client.close(); - const replacementClient = await connectEventually(socketPath); - const adopted = await replacementClient.request({ type: "list" }); - expect(adopted.success).toBe(true); - expect( - new Set(requireSessionList(adopted.success ? adopted.data : undefined).map((summary) => summary.workerPid)), - ).toEqual(new Set(pids)); - await replacementClient.request({ type: "shutdown" }); - replacementClient.close(); - await waitForSocketGone(socketPath); - await Promise.all( - pids.map(async (pid) => { - if (pid) { - await waitForProcessGone(pid); - workerPids.delete(pid); - } - }), - ); - }); + const listed = await client.request({ type: "list" }); + expect(listed.success).toBe(true); + expect(requireSessionList(listed.success ? listed.data : undefined)).toHaveLength(PROCESS_STRESS_WORKERS); + supervisor.kill("SIGTERM"); + await waitForExit(supervisor); + children.delete(supervisor); + client.close(); + const replacementClient = await connectEventually(socketPath); + const adopted = await replacementClient.request({ type: "list" }); + expect(adopted.success).toBe(true); + expect( + new Set(requireSessionList(adopted.success ? adopted.data : undefined).map((summary) => summary.workerPid)), + ).toEqual(new Set(pids)); + await replacementClient.request({ type: "shutdown" }); + replacementClient.close(); + await waitForSocketGone(socketPath); + await Promise.all( + pids.map(async (pid) => { + if (pid) { + await waitForProcessGone(pid); + workerPids.delete(pid); + } + }), + ); + }, + ); it("isolates a root, streams a chunked snapshot, and adopts the same worker after restart", async () => { const root = tempDir(); @@ -1643,71 +1656,72 @@ describe("daemon supervisor resident workers", () => { workerPids.delete(recovered.workerPid); }); - it("runs a session-artifact cron job while the supervisor is being replaced", { - tags: ["process-stress"], - timeout: 30_000, - }, async () => { - const root = tempDir(); - const agentDir = join(root, "agent"); - const projectDir = join(root, "project"); - const sessionDir = join(agentDir, "sessions"); - const socketPath = join(tmpdir(), `prime-worker-cron-${process.pid}-${randomUUID().slice(0, 8)}.sock`); - mkdirSync(projectDir, { recursive: true }); - const sessionManager = SessionManager.create(projectDir, sessionDir); - sessionManager.appendMessage({ role: "user", content: "scheduled work", timestamp: 1 }); - sessionManager.appendSessionState({ status: "active" }); - const sessionFile = sessionManager.getSessionFile(); - const artifactDir = sessionManager.getSessionArtifactDir(); - if (!sessionFile || !artifactDir) { - throw new Error("Fixture session did not persist"); - } - - const supervisor = spawnSupervisor(agentDir, socketPath, projectDir); - const client = await connectEventually(socketPath, supervisor); - const created = await client.request({ - type: "create", - sessionPath: sessionFile, - config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, - }); - if (!created.success) { - throw new Error(created.error); - } - const summary = requireSummary(created.data); - if (!summary.workerPid) { - throw new Error("Resident worker did not expose its pid"); - } - workerPids.add(summary.workerPid); - await startBlockingBash(client, summary.activeSessionId ?? summary.id, join(root, "heartbeat-blocker.ready")); - const scheduled = await client.request({ - type: "heartbeat_set", - activeSessionId: summary.activeSessionId ?? summary.id, - schedule: "every 10s", - prompt: "continue without the supervisor", - }); - if (!scheduled.success || !scheduled.data || typeof scheduled.data !== "object") { - throw new Error(scheduled.success ? "Heartbeat response was missing its job" : scheduled.error); - } - const job = (scheduled.data as { heartbeat: { id: string } }).heartbeat; - - client.close(); - supervisor.kill("SIGKILL"); - await waitForExit(supervisor); - children.delete(supervisor); + processStressIt( + "runs a session-artifact cron job while the supervisor is being replaced", + { timeout: 30_000 }, + async () => { + const root = tempDir(); + const agentDir = join(root, "agent"); + const projectDir = join(root, "project"); + const sessionDir = join(agentDir, "sessions"); + const socketPath = join(tmpdir(), `prime-worker-cron-${process.pid}-${randomUUID().slice(0, 8)}.sock`); + mkdirSync(projectDir, { recursive: true }); + const sessionManager = SessionManager.create(projectDir, sessionDir); + sessionManager.appendMessage({ role: "user", content: "scheduled work", timestamp: 1 }); + sessionManager.appendSessionState({ status: "active" }); + const sessionFile = sessionManager.getSessionFile(); + const artifactDir = sessionManager.getSessionArtifactDir(); + if (!sessionFile || !artifactDir) { + throw new Error("Fixture session did not persist"); + } - const store = AgentCronJobStore.forSessionArtifacts(); - store.registerSessionArtifact(sessionManager.getSessionId(), artifactDir); - await waitForCondition( - () => store.list().find((candidate) => candidate.id === job.id)?.lastSkippedAt !== undefined, - "Resident worker did not advance its heartbeat without the supervisor", - 15_000, - ); - expect(store.list().find((candidate) => candidate.id === job.id)).toBeDefined(); + const supervisor = spawnSupervisor(agentDir, socketPath, projectDir); + const client = await connectEventually(socketPath, supervisor); + const created = await client.request({ + type: "create", + sessionPath: sessionFile, + config: { cwd: projectDir, agentDir, sessionDir, noTools: true, noExtensions: true }, + }); + if (!created.success) { + throw new Error(created.error); + } + const summary = requireSummary(created.data); + if (!summary.workerPid) { + throw new Error("Resident worker did not expose its pid"); + } + workerPids.add(summary.workerPid); + await startBlockingBash(client, summary.activeSessionId ?? summary.id, join(root, "heartbeat-blocker.ready")); + const scheduled = await client.request({ + type: "heartbeat_set", + activeSessionId: summary.activeSessionId ?? summary.id, + schedule: "every 10s", + prompt: "continue without the supervisor", + }); + if (!scheduled.success || !scheduled.data || typeof scheduled.data !== "object") { + throw new Error(scheduled.success ? "Heartbeat response was missing its job" : scheduled.error); + } + const job = (scheduled.data as { heartbeat: { id: string } }).heartbeat; - const replacement = await connectEventually(socketPath); - await replacement.request({ type: "shutdown" }); - replacement.close(); - await waitForSocketGone(socketPath); - await waitForProcessGone(summary.workerPid); - workerPids.delete(summary.workerPid); - }); + client.close(); + supervisor.kill("SIGKILL"); + await waitForExit(supervisor); + children.delete(supervisor); + + const store = AgentCronJobStore.forSessionArtifacts(); + store.registerSessionArtifact(sessionManager.getSessionId(), artifactDir); + await waitForCondition( + () => store.list().find((candidate) => candidate.id === job.id)?.lastSkippedAt !== undefined, + "Resident worker did not advance its heartbeat without the supervisor", + 15_000, + ); + expect(store.list().find((candidate) => candidate.id === job.id)).toBeDefined(); + + const replacement = await connectEventually(socketPath); + await replacement.request({ type: "shutdown" }); + replacement.close(); + await waitForSocketGone(socketPath); + await waitForProcessGone(summary.workerPid); + workerPids.delete(summary.workerPid); + }, + ); }); diff --git a/packages/coding-agent/test/file-lines.test.ts b/packages/coding-agent/test/file-lines.test.ts index 92421e9f99..d78fdad463 100644 --- a/packages/coding-agent/test/file-lines.test.ts +++ b/packages/coding-agent/test/file-lines.test.ts @@ -1,3 +1,4 @@ +import { createRequire } from "node:module"; import { Readable } from "node:stream"; import { afterEach, describe, expect, it, vi } from "vitest"; @@ -5,13 +6,11 @@ const fsMocks = vi.hoisted(() => ({ createReadStream: vi.fn(), })); -vi.mock("node:fs", async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - createReadStream: fsMocks.createReadStream, - }; -}); +const __fs = createRequire(import.meta.url)("node:fs"); +vi.mock("node:fs", () => ({ + ...__fs, + createReadStream: fsMocks.createReadStream, +})); const { readLinesAsBuffers } = await import("../src/utils/file-lines.js"); diff --git a/packages/coding-agent/test/fixtures/eng-4600-supervisor-fixture.ts b/packages/coding-agent/test/fixtures/eng-4600-supervisor-fixture.ts index 11adf1bc85..f44431ad4a 100644 --- a/packages/coding-agent/test/fixtures/eng-4600-supervisor-fixture.ts +++ b/packages/coding-agent/test/fixtures/eng-4600-supervisor-fixture.ts @@ -20,16 +20,43 @@ function send(message: Record): void { process.send?.(message); } +function exitFixture(code: number): never { + process.exitCode = code; + if (process.connected) process.disconnect(); + const reallyExit = (process as NodeJS.Process & { reallyExit?: (exitCode?: number) => never }).reallyExit; + if (reallyExit) return reallyExit.call(process, code); + process.exit(code); +} + +function sendAndExit(message: Record, code: number): void { + send(message); + setTimeout(() => exitFixture(code), 10); +} + +const pendingControls = new Map void>>(); +const controlBacklog: ControlMessage["type"][] = []; + +process.on("message", (message: unknown) => { + if (!message || typeof message !== "object" || typeof (message as Partial).type !== "string") { + return; + } + const type = (message as ControlMessage).type; + const waiters = pendingControls.get(type); + const waiter = waiters?.shift(); + if (waiter) waiter(); + else controlBacklog.push(type); +}); + function waitForControl(type: ControlMessage["type"]): Promise { + const queuedIndex = controlBacklog.indexOf(type); + if (queuedIndex !== -1) { + controlBacklog.splice(queuedIndex, 1); + return Promise.resolve(); + } return new Promise((resolve) => { - const onMessage = (message: unknown) => { - if (!message || typeof message !== "object" || (message as Partial).type !== type) { - return; - } - process.off("message", onMessage); - resolve(); - }; - process.on("message", onMessage); + const waiters = pendingControls.get(type) ?? []; + waiters.push(resolve); + pendingControls.set(type, waiters); }); } @@ -47,7 +74,7 @@ async function runOwnershipHolder(): Promise { await ownership.release(); send({ type: "owner_released" }); await waitForControl("shutdown"); - process.exit(0); + exitFixture(0); } async function runSupervisor(): Promise { @@ -82,8 +109,8 @@ async function runSupervisor(): Promise { }); return await new Promise(() => {}); } catch (error) { - send({ type: "failed", error: error instanceof Error ? error.message : String(error) }); - process.exit(0); + sendAndExit({ type: "failed", error: error instanceof Error ? error.message : String(error) }, 0); + return await new Promise(() => {}); } } @@ -129,8 +156,8 @@ async function runLegacyCleanup(): Promise { } } } - send({ type: "cleanup_complete", skipped }); - process.exit(0); + sendAndExit({ type: "cleanup_complete", skipped }, 0); + return await new Promise(() => {}); } async function main(): Promise { @@ -158,6 +185,5 @@ async function main(): Promise { } void main().catch((error) => { - send({ type: "failed", error: error instanceof Error ? error.message : String(error) }); - process.exit(1); + sendAndExit({ type: "failed", error: error instanceof Error ? error.message : String(error) }, 1); }); diff --git a/packages/coding-agent/test/fixtures/eng-4606-update-launcher.ts b/packages/coding-agent/test/fixtures/eng-4606-update-launcher.ts index 1e7b693882..8cacf3a74b 100644 --- a/packages/coding-agent/test/fixtures/eng-4606-update-launcher.ts +++ b/packages/coding-agent/test/fixtures/eng-4606-update-launcher.ts @@ -14,11 +14,10 @@ const cliPath = requireEnvironment("ENG_4606_CLI_PATH"); const completionPath = requireEnvironment("ENG_4606_COMPLETION_PATH"); const pidPath = requireEnvironment("ENG_4606_PID_PATH"); const socketPath = requireEnvironment("ENG_4606_SOCKET_PATH"); -const tsxPath = requireEnvironment("ENG_4606_TSX_PATH"); const originActiveSessionId = requireEnvironment("PRIME_AGENT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID"); process.argv[1] = cliPath; -process.execArgv.splice(0, process.execArgv.length, tsxPath); +process.execArgv.splice(0, process.execArgv.length); writeFileSync(pidPath, `${process.pid}\n`); await launchDaemonUpdateRestartCoordinator({ diff --git a/packages/coding-agent/test/git-context.test.ts b/packages/coding-agent/test/git-context.test.ts index 07b61ddc05..ea61ff707a 100644 --- a/packages/coding-agent/test/git-context.test.ts +++ b/packages/coding-agent/test/git-context.test.ts @@ -6,7 +6,7 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { captureGitContext, gitContextsEqual } from "../src/utils/git.js"; function git(cwd: string, ...args: string[]): string { - return execFileSync("git", args, { cwd, encoding: "utf8" }).trim(); + return execFileSync("git", args, { cwd, encoding: "utf8", env: process.env }).trim(); } function initRepo(dir: string): void { diff --git a/packages/coding-agent/test/git-update.test.ts b/packages/coding-agent/test/git-update.test.ts index eb50d6003c..e7df416356 100644 --- a/packages/coding-agent/test/git-update.test.ts +++ b/packages/coding-agent/test/git-update.test.ts @@ -11,6 +11,7 @@ function git(args: string[], cwd: string): string { const result = spawnSync("git", args, { cwd, encoding: "utf-8", + env: process.env, }); if (result.status !== 0) { throw new Error(`Command failed: git ${args.join(" ")}\n${result.stderr}`); diff --git a/packages/coding-agent/test/interactive-mode-status.test.ts b/packages/coding-agent/test/interactive-mode-status.test.ts index 2ffdd91f7c..dfdefce78a 100644 --- a/packages/coding-agent/test/interactive-mode-status.test.ts +++ b/packages/coding-agent/test/interactive-mode-status.test.ts @@ -5026,9 +5026,9 @@ describe("InteractiveMode.showLoadedResources", () => { force: true, }); - expect(normalizeRenderedOutput(fakeThis.chatContainer)).toMatchInlineSnapshot(` -"[Extensions] - @scope/pi-scoped, answer.ts, cli-extension.ts, HazAT/pi-interactive-subagents, HazAT/pi-interactive-subagents:subagents, local-index, pi-markdown-preview, user-index"`); + expect(normalizeRenderedOutput(fakeThis.chatContainer)).toBe( + "[Extensions]\n @scope/pi-scoped, answer.ts, cli-extension.ts, HazAT/pi-interactive-subagents, HazAT/pi-interactive-subagents:subagents, local-index, pi-markdown-preview, user-index", + ); }); test("adds more parent folders until local extension labels are unique", () => { @@ -5072,9 +5072,7 @@ describe("InteractiveMode.showLoadedResources", () => { force: true, }); - expect(normalizeRenderedOutput(fakeThis.chatContainer)).toMatchInlineSnapshot(` -"[Extensions] - alpha/one, beta/one, gamma/one"`); + expect(normalizeRenderedOutput(fakeThis.chatContainer)).toBe("[Extensions]\n alpha/one, beta/one, gamma/one"); }); test("strips index.ts from local extension label, showing parent dir", () => { @@ -5100,9 +5098,7 @@ describe("InteractiveMode.showLoadedResources", () => { force: true, }); - expect(normalizeRenderedOutput(fakeThis.chatContainer)).toMatchInlineSnapshot(` -"[Extensions] - plan-mode"`); + expect(normalizeRenderedOutput(fakeThis.chatContainer)).toBe("[Extensions]\n plan-mode"); }); test("strips index.js from local extension label, showing parent dir", () => { @@ -5128,9 +5124,7 @@ describe("InteractiveMode.showLoadedResources", () => { force: true, }); - expect(normalizeRenderedOutput(fakeThis.chatContainer)).toMatchInlineSnapshot(` -"[Extensions] - plan-mode"`); + expect(normalizeRenderedOutput(fakeThis.chatContainer)).toBe("[Extensions]\n plan-mode"); }); test("mixed single-file and subdirectory index.ts extensions strip index.ts", () => { @@ -5165,9 +5159,7 @@ describe("InteractiveMode.showLoadedResources", () => { force: true, }); - expect(normalizeRenderedOutput(fakeThis.chatContainer)).toMatchInlineSnapshot(` -"[Extensions] - plan-mode, webfetch.ts"`); + expect(normalizeRenderedOutput(fakeThis.chatContainer)).toBe("[Extensions]\n plan-mode, webfetch.ts"); }); test("multiple index.ts with unique parent dirs need no disambiguation", () => { @@ -5202,9 +5194,7 @@ describe("InteractiveMode.showLoadedResources", () => { force: true, }); - expect(normalizeRenderedOutput(fakeThis.chatContainer)).toMatchInlineSnapshot(` -"[Extensions] - bar, foo"`); + expect(normalizeRenderedOutput(fakeThis.chatContainer)).toBe("[Extensions]\n bar, foo"); }); test("multiple index.ts with same parent dir name disambiguated with grandparent", () => { @@ -5239,9 +5229,7 @@ describe("InteractiveMode.showLoadedResources", () => { force: true, }); - expect(normalizeRenderedOutput(fakeThis.chatContainer)).toMatchInlineSnapshot(` -"[Extensions] - alpha/tools, beta/tools"`); + expect(normalizeRenderedOutput(fakeThis.chatContainer)).toBe("[Extensions]\n alpha/tools, beta/tools"); }); test("non-index file in subdirectory stays as filename", () => { @@ -5267,9 +5255,7 @@ describe("InteractiveMode.showLoadedResources", () => { force: true, }); - expect(normalizeRenderedOutput(fakeThis.chatContainer)).toMatchInlineSnapshot(` -"[Extensions] - main.ts"`); + expect(normalizeRenderedOutput(fakeThis.chatContainer)).toBe("[Extensions]\n main.ts"); }); test("package extensions still strip index.ts correctly (regression guard)", () => { @@ -5295,9 +5281,7 @@ describe("InteractiveMode.showLoadedResources", () => { force: true, }); - expect(normalizeRenderedOutput(fakeThis.chatContainer)).toMatchInlineSnapshot(` -"[Extensions] - pi-markdown-preview"`); + expect(normalizeRenderedOutput(fakeThis.chatContainer)).toBe("[Extensions]\n pi-markdown-preview"); }); test("captures mixed extension layouts in expanded output", () => { const fakeThis = createShowLoadedResourcesThis({ @@ -5311,22 +5295,9 @@ describe("InteractiveMode.showLoadedResources", () => { force: true, }); - expect(normalizeRenderedOutput(fakeThis.chatContainer)).toMatchInlineSnapshot(` -"[Extensions] - project - /tmp/project/.pi/extensions/answer.ts - /tmp/project/.pi/extensions/local-index - git:github.com/HazAT/pi-interactive-subagents - extensions - extensions/subagents - npm:@scope/pi-scoped - extensions - npm:pi-markdown-preview - extensions - user - /tmp/agent/extensions/user-index - path - /tmp/temp/cli-extension.ts"`); + expect(normalizeRenderedOutput(fakeThis.chatContainer)).toBe( + "[Extensions]\n project\n /tmp/project/.pi/extensions/answer.ts\n /tmp/project/.pi/extensions/local-index\n git:github.com/HazAT/pi-interactive-subagents\n extensions\n extensions/subagents\n npm:@scope/pi-scoped\n extensions\n npm:pi-markdown-preview\n extensions\n user\n /tmp/agent/extensions/user-index\n path\n /tmp/temp/cli-extension.ts", + ); }); test("shows context paths relative to cwd while preserving full external paths", () => { @@ -5419,13 +5390,9 @@ describe("InteractiveMode.showLoadedResources", () => { }); const output = normalizeRenderedOutput(fakeThis.chatContainer, 100); - expect(output).toMatchInlineSnapshot(` -"[Skill warning] - first line of the warning. - second line with guidance. - - indented detail" -`); + expect(output).toBe( + "[Skill warning]\n first line of the warning.\n second line with guidance.\n\n indented detail", + ); expect(output).not.toContain("[Skill conflicts]"); }); }); diff --git a/packages/coding-agent/test/interactive-update-relaunch.test.ts b/packages/coding-agent/test/interactive-update-relaunch.test.ts index b13e6b216d..8a215bbe07 100644 --- a/packages/coding-agent/test/interactive-update-relaunch.test.ts +++ b/packages/coding-agent/test/interactive-update-relaunch.test.ts @@ -1,19 +1,21 @@ -import type * as ChildProcessModule from "child_process"; +import { createRequire } from "node:module"; import { describe, expect, it, vi } from "vitest"; -import type * as DaemonUpdateRestartModule from "../src/cli/daemon-update-restart.js"; const updateMocks = vi.hoisted(() => ({ spawnSync: vi.fn(), launchCoordinator: vi.fn(), })); -vi.mock("child_process", async (importOriginal) => ({ - ...(await importOriginal()), +const __childProcess = createRequire(import.meta.url)("child_process"); +const __daemonUpdateRestart = createRequire(import.meta.url)("../src/cli/daemon-update-restart.js"); + +vi.mock("child_process", () => ({ + ...__childProcess, spawnSync: updateMocks.spawnSync, })); -vi.mock("../src/cli/daemon-update-restart.js", async (importOriginal) => ({ - ...(await importOriginal()), +vi.mock("../src/cli/daemon-update-restart.js", () => ({ + ...__daemonUpdateRestart, launchDaemonUpdateRestartCoordinator: updateMocks.launchCoordinator, })); diff --git a/packages/coding-agent/test/kernel-bash-shell.test.ts b/packages/coding-agent/test/kernel-bash-shell.test.ts index bced79ae99..80302b7b86 100644 --- a/packages/coding-agent/test/kernel-bash-shell.test.ts +++ b/packages/coding-agent/test/kernel-bash-shell.test.ts @@ -1,3 +1,4 @@ +import { createRequire } from "node:module"; import { afterEach, describe, expect, it, vi } from "vitest"; const mocks = vi.hoisted(() => ({ @@ -5,17 +6,15 @@ const mocks = vi.hoisted(() => ({ spawnSync: vi.fn(), })); -vi.mock("node:fs", async (importOriginal) => { - const actual = await importOriginal(); +const __fs = createRequire(import.meta.url)("node:fs") as typeof import("node:fs"); +vi.mock("node:fs", () => { // Module-load reads (config.ts) must see the real fs; tests override per case. - mocks.existsSync.mockImplementation(actual.existsSync); - return { ...actual, existsSync: mocks.existsSync }; + mocks.existsSync.mockImplementation(__fs.existsSync); + return { ...__fs, existsSync: mocks.existsSync }; }); -vi.mock("child_process", async (importOriginal) => { - const actual = await importOriginal(); - return { ...actual, spawnSync: mocks.spawnSync }; -}); +const __childProcess = createRequire(import.meta.url)("child_process") as typeof import("child_process"); +vi.mock("child_process", () => ({ ...__childProcess, spawnSync: mocks.spawnSync })); import { resolveKernelBashShell } from "../src/utils/shell.js"; diff --git a/packages/coding-agent/test/kernel-goal-skill.test.ts b/packages/coding-agent/test/kernel-goal-skill.test.ts index 71a544b640..76fded711b 100644 --- a/packages/coding-agent/test/kernel-goal-skill.test.ts +++ b/packages/coding-agent/test/kernel-goal-skill.test.ts @@ -5,6 +5,7 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { getBundledSkillsDir } from "../src/config.js"; import type { PythonSkillRuntimeInfo } from "../src/core/skills.js"; import { IpythonKernelProvisioner } from "../src/core/tools/ipython.js"; +import { isTestTagEnabled } from "./test-tags.js"; function bundledGoalSkill(): PythonSkillRuntimeInfo { const packagePath = join(getBundledSkillsDir(), "goal"); @@ -16,7 +17,9 @@ function bundledGoalSkill(): PythonSkillRuntimeInfo { }; } -describe("goal skill over the kernel host bridge", { tags: ["kernel-heavy"] }, () => { +const kernelHeavyDescribe = isTestTagEnabled("kernel-heavy") ? describe : describe.skip; + +kernelHeavyDescribe("goal skill over the kernel host bridge", () => { let tempDir: string; let provisioner: IpythonKernelProvisioner | undefined; diff --git a/packages/coding-agent/test/mcp-command.test.ts b/packages/coding-agent/test/mcp-command.test.ts index 81f19581b5..21ce779296 100644 --- a/packages/coding-agent/test/mcp-command.test.ts +++ b/packages/coding-agent/test/mcp-command.test.ts @@ -43,10 +43,12 @@ describe("MCP management commands", () => { "--", "node", ]); - expect(config).toMatchObject({ - type: "stdio", - env: { __proto__: { env: "PROTO_SOURCE" }, constructor: { env: "CONSTRUCTOR_SOURCE" } }, - }); + expect(config.type).toBe("stdio"); + if (config.type !== "stdio") throw new Error("Expected stdio MCP config"); + expect(Object.hasOwn(config.env ?? {}, "__proto__")).toBe(true); + expect(Reflect.get(config.env ?? {}, "__proto__")).toEqual({ env: "PROTO_SOURCE" }); + expect(Object.hasOwn(config.env ?? {}, "constructor")).toBe(true); + expect(config.env?.constructor).toEqual({ env: "CONSTRUCTOR_SOURCE" }); }); it("validates transport, URL, names, auth, and stdio environment syntax", () => { diff --git a/packages/coding-agent/test/owned-session-worker-process.test.ts b/packages/coding-agent/test/owned-session-worker-process.test.ts index 0b661ff631..d19cc8f01c 100644 --- a/packages/coding-agent/test/owned-session-worker-process.test.ts +++ b/packages/coding-agent/test/owned-session-worker-process.test.ts @@ -5,7 +5,6 @@ import { join, resolve } from "node:path"; import { afterEach, describe, expect, it } from "vitest"; const fixturePath = resolve(__dirname, "fixtures/owned-session-worker-fixture.ts"); -const tsxPath = resolve(__dirname, "../../../node_modules/tsx/dist/cli.mjs"); const tempDirs: string[] = []; const children = new Set(); const workerPids = new Set(); @@ -45,14 +44,13 @@ function spawnFrontend( keepAlive = false, environment: NodeJS.ProcessEnv = {}, ): ChildProcess { - const child = spawn(process.execPath, [tsxPath, fixturePath, ...args], { + const child = spawn(process.execPath, [fixturePath, ...args], { env: { ...process.env, ...environment, PRIME_AGENT_INTERNAL_LEGACY_OWNED_WORKER_FRONTEND: "1", PRIME_AGENT_TEST_OWNED_PID_PATH: pidPath, ...(keepAlive ? { PRIME_AGENT_TEST_KEEP_ALIVE: "1" } : {}), - TSX_TSCONFIG_PATH: resolve(__dirname, "../../../tsconfig.json"), }, stdio: ["pipe", "pipe", "pipe"], }); diff --git a/packages/coding-agent/test/package-command-paths.test.ts b/packages/coding-agent/test/package-command-paths.test.ts index 3ddb7055a4..980da26b1d 100644 --- a/packages/coding-agent/test/package-command-paths.test.ts +++ b/packages/coding-agent/test/package-command-paths.test.ts @@ -57,7 +57,7 @@ describe("package commands", () => { originalTmpDir = process.env.TMPDIR; originalExitCode = process.exitCode; originalExecPath = process.execPath; - process.exitCode = undefined; + process.exitCode = 0; process.env[ENV_AGENT_DIR] = agentDir; process.env.TMPDIR = tempDir; process.chdir(projectDir); @@ -66,7 +66,7 @@ describe("package commands", () => { afterEach(() => { vi.unstubAllGlobals(); process.chdir(originalCwd); - process.exitCode = originalExitCode; + process.exitCode = originalExitCode ?? 0; restoreEnv(ENV_AGENT_DIR, originalAgentDir); restoreEnv("PI_PACKAGE_DIR", originalPiPackageDir); restoreEnv("PRIME_AGENT_DOWNLOAD_BASE_URL", originalPrimeAgentDownloadBaseUrl); @@ -113,7 +113,7 @@ describe("package commands", () => { expect(stdout).toContain("Usage:"); expect(stdout).toContain(`${APP_NAME} package install [--local]`); expect(errorSpy).not.toHaveBeenCalled(); - expect(process.exitCode).toBeUndefined(); + expect(process.exitCode ?? 0).toBe(0); } finally { logSpy.mockRestore(); errorSpy.mockRestore(); @@ -219,7 +219,7 @@ else fs.writeFileSync(${JSON.stringify(recordPath)},JSON.stringify(args)); try { await expect(runSelfUpdateInstallChild(["update", "--self", "--force"])).resolves.toBeUndefined(); - expect(process.exitCode).toBeUndefined(); + expect(process.exitCode ?? 0).toBe(0); expect(errorSpy).not.toHaveBeenCalled(); expect(fetchMock).toHaveBeenCalledOnce(); const recordedArgs = JSON.parse(readFileSync(recordPath, "utf-8")) as string[]; @@ -263,7 +263,7 @@ else fs.writeFileSync(${JSON.stringify(recordPath)},JSON.stringify(args)); try { await expect(runSelfUpdateInstallChild(["update", "--self"])).resolves.toBeUndefined(); - expect(process.exitCode).toBeUndefined(); + expect(process.exitCode ?? 0).toBe(0); expect(errorSpy).not.toHaveBeenCalled(); expect(fetchMock).toHaveBeenCalledOnce(); const recordedArgs = JSON.parse(readFileSync(recordPath, "utf-8")) as string[]; @@ -312,7 +312,7 @@ else { try { await expect(runSelfUpdateInstallChild(["update", "--self"])).resolves.toBeUndefined(); - expect(process.exitCode).toBeUndefined(); + expect(process.exitCode ?? 0).toBe(0); expect(errorSpy).not.toHaveBeenCalled(); const recordedCalls = JSON.parse(readFileSync(recordPath, "utf-8")) as string[][]; expect(recordedCalls).toEqual([ @@ -365,7 +365,7 @@ else { try { await expect(runSelfUpdateInstallChild(["update", "--self"])).resolves.toBeUndefined(); - expect(process.exitCode).toBeUndefined(); + expect(process.exitCode ?? 0).toBe(0); expect(errorSpy).not.toHaveBeenCalled(); const recordedCalls = JSON.parse(readFileSync(recordPath, "utf-8")) as string[][]; expect(recordedCalls).toEqual([ @@ -419,7 +419,7 @@ else fs.writeFileSync(${JSON.stringify(recordPath)},JSON.stringify(args)); try { await expect(main(["update"])).resolves.toBeUndefined(); - expect(process.exitCode).toBeUndefined(); + expect(process.exitCode ?? 0).toBe(0); expect(errorSpy).not.toHaveBeenCalled(); expect(logSpy.mock.calls.map(([message]) => String(message)).join("\n")).toContain("is already up to date"); expect(existsSync(recordPath)).toBe(false); diff --git a/packages/coding-agent/test/package-self-update-daemon.test.ts b/packages/coding-agent/test/package-self-update-daemon.test.ts index af8ebf000d..0245271506 100644 --- a/packages/coding-agent/test/package-self-update-daemon.test.ts +++ b/packages/coding-agent/test/package-self-update-daemon.test.ts @@ -2,7 +2,6 @@ import { existsSync, mkdirSync, rmSync, statSync, writeFileSync } from "node:fs" import { tmpdir } from "node:os"; import { join } from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import type * as DaemonUpdateRestartModule from "../src/cli/daemon-update-restart.js"; import { acquireDaemonUpdateRestartCoordinator, type DaemonUpdateRestartStatus, @@ -20,7 +19,6 @@ import { } from "../src/config.js"; import type { AgentSessionRuntimeMetadata } from "../src/core/agent-session-runtime.js"; import { DAEMON_PROTOCOL_VERSION, DAEMON_SCHEMA_ID } from "../src/modes/daemon/daemon-protocol.js"; -import type * as DaemonSocketModule from "../src/modes/daemon/daemon-socket.js"; import { handlePackageCommand, prepareDaemonUpdateRestart, @@ -198,8 +196,8 @@ vi.mock("child_process", () => ({ })), })); -vi.mock("../src/cli/daemon-update-restart.js", async (importOriginal) => { - const original = await importOriginal(); +vi.mock("../src/cli/daemon-update-restart.js", () => { + const original = require("../src/cli/daemon-update-restart.js"); return { ...original, launchDaemonUpdateRestartCoordinator: vi.fn(async (options: { socketPath: string }) => { @@ -218,10 +216,10 @@ vi.mock("../src/cli/daemon-update-restart.js", async (importOriginal) => { }; }); -vi.mock("../src/modes/daemon/daemon-socket.js", async (importOriginal) => ({ - ...(await importOriginal()), - defaultDaemonSocketPath: () => mockState.socketPath, -})); +vi.mock("../src/modes/daemon/daemon-socket.js", () => { + const actual = require("../src/modes/daemon/daemon-socket.js"); + return { ...actual, defaultDaemonSocketPath: () => mockState.socketPath }; +}); vi.mock("../src/modes/daemon/daemon-supervisor-ownership.js", () => ({ acquireDaemonShutdownAdmission: vi.fn(async () => { @@ -511,7 +509,7 @@ describe("self-update daemon restart", () => { originalCwd = process.cwd(); originalExecPath = process.execPath; originalExitCode = process.exitCode; - process.exitCode = undefined; + process.exitCode = 0; process.env[ENV_AGENT_DIR] = agentDir; process.env.PI_PACKAGE_DIR = packageDir; process.chdir(projectDir); @@ -529,7 +527,7 @@ describe("self-update daemon restart", () => { afterEach(() => { vi.unstubAllGlobals(); process.chdir(originalCwd); - process.exitCode = originalExitCode; + process.exitCode = originalExitCode ?? 0; if (originalAgentDir === undefined) { delete process.env[ENV_AGENT_DIR]; } else { @@ -884,7 +882,7 @@ describe("self-update daemon restart", () => { try { await expect(performUpdateAndRunCoordinator()).resolves.toBeUndefined(); - expect(process.exitCode).toBeUndefined(); + expect(process.exitCode ?? 0).toBe(0); const spawnIndex = mockState.calls.findIndex((call) => call.startsWith("spawn:npm ")); const launchIndex = mockState.calls.indexOf(`launch-coordinator:${mockState.socketPath}`); const fenceIndex = mockState.calls.indexOf("persist-daemon-startup-fence"); diff --git a/packages/coding-agent/test/print-mode.test.ts b/packages/coding-agent/test/print-mode.test.ts index 065d5d04ae..e75b48e3ec 100644 --- a/packages/coding-agent/test/print-mode.test.ts +++ b/packages/coding-agent/test/print-mode.test.ts @@ -754,7 +754,7 @@ describe("runPrintMode", () => { }); expect(exitCode).toBe(0); - expect(session.waitForIdle).toHaveBeenCalledBefore(session.prompt); + expect(session.waitForIdle.mock.invocationCallOrder[0]).toBeLessThan(session.prompt.mock.invocationCallOrder[0]!); expect(session.prompt).toHaveBeenCalledTimes(2); expect(session.prompt.mock.calls[0][0]).toContain("Autonomous quality gate failed (attempt 1/3)"); expect(session.prompt.mock.calls[0][0]).toContain("0/9"); diff --git a/packages/coding-agent/test/public-command.test.ts b/packages/coding-agent/test/public-command.test.ts index 5fc4ae676e..d0bca2b58b 100644 --- a/packages/coding-agent/test/public-command.test.ts +++ b/packages/coding-agent/test/public-command.test.ts @@ -63,13 +63,13 @@ describe("public command routing", () => { mocks.reapCalls.length = 0; mocks.shutdownCalls.length = 0; mocks.mcpCommands.length = 0; - process.exitCode = undefined; + process.exitCode = 0; vi.spyOn(console, "log").mockImplementation(() => {}); vi.spyOn(console, "error").mockImplementation(() => {}); }); afterEach(() => { - process.exitCode = undefined; + process.exitCode = 0; vi.restoreAllMocks(); }); diff --git a/packages/coding-agent/test/refinement.test.ts b/packages/coding-agent/test/refinement.test.ts index 19a7313975..bc7dbbe86d 100644 --- a/packages/coding-agent/test/refinement.test.ts +++ b/packages/coding-agent/test/refinement.test.ts @@ -2,7 +2,6 @@ import { appendFileSync, chmodSync, mkdtempSync, readdirSync, rmSync, statSync, import { tmpdir } from "node:os"; import { join } from "node:path"; import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type * as PiAi from "@earendil-works/pi-ai"; import type { AssistantMessage, Model } from "@earendil-works/pi-ai"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { @@ -34,8 +33,8 @@ const { completeSimpleMock } = vi.hoisted(() => ({ completeSimpleMock: vi.fn(), })); -vi.mock("@earendil-works/pi-ai", async (importOriginal) => { - const actual = await importOriginal(); +vi.mock("@earendil-works/pi-ai", () => { + const actual = require("@earendil-works/pi-ai"); return { ...actual, completeSimple: completeSimpleMock, @@ -1015,20 +1014,13 @@ describe("harness refinement", () => { ); expect(completeSimpleMock).toHaveBeenCalledTimes(1); - expect(completeSimpleMock.mock.calls[0][1]).toMatchObject({ - systemPrompt: expect.stringContaining("The default editable continual harness store is local"), - }); - expect(completeSimpleMock.mock.calls[0][1]).toMatchObject({ - systemPrompt: expect.stringContaining("A caller may explicitly request global refinement"), - }); - expect(completeSimpleMock.mock.calls[0][1]).toMatchObject({ - systemPrompt: expect.stringContaining("Always use the bare id (no prefix) in edits"), - }); - expect(completeSimpleMock.mock.calls[0][1]).toMatchObject({ - systemPrompt: expect.stringContaining( - "During a local refinement, global entries are read-only context: never propose update or delete edits for them", - ), - }); + const refinementSystemPrompt = completeSimpleMock.mock.calls[0][1]?.systemPrompt; + expect(refinementSystemPrompt).toContain("The default editable continual harness store is local"); + expect(refinementSystemPrompt).toContain("A caller may explicitly request global refinement"); + expect(refinementSystemPrompt).toContain("Always use the bare id (no prefix) in edits"); + expect(refinementSystemPrompt).toContain( + "During a local refinement, global entries are read-only context: never propose update or delete edits for them", + ); // Budget is derived from the model (8192) rather than a fixed literal. expect(completeSimpleMock.mock.calls[0][2]).toMatchObject({ maxTokens: 8192, diff --git a/packages/coding-agent/test/repl-kernel-abort.test.ts b/packages/coding-agent/test/repl-kernel-abort.test.ts index b3283a4191..dbfdfd54a8 100644 --- a/packages/coding-agent/test/repl-kernel-abort.test.ts +++ b/packages/coding-agent/test/repl-kernel-abort.test.ts @@ -204,13 +204,12 @@ describe("ReplKernelManager abort handling", () => { await expect(executePromise).resolves.toMatchObject({ status: "aborted" }); const secondExecutePromise = manager.execute("x = 1"); - const secondExecuteExpectation = expect(secondExecutePromise).rejects.toThrow( - "The Python kernel is still running the previously interrupted cell", - ); await Promise.resolve(); await vi.advanceTimersByTimeAsync(5000); - await secondExecuteExpectation; + await expect(secondExecutePromise).rejects.toThrow( + "The Python kernel is still running the previously interrupted cell", + ); expect(writeLine.mock.calls.filter((call) => (call[0] as { type?: string }).type === "execute")).toHaveLength(1); expect(writeLine.mock.calls.some((call) => (call[0] as { type?: string }).type === "interrupt")).toBe(true); manager.disposeSync(); diff --git a/packages/coding-agent/test/repl-kernel-mcp-shutdown.test.ts b/packages/coding-agent/test/repl-kernel-mcp-shutdown.test.ts index ca5545c7b2..dca42a4e2b 100644 --- a/packages/coding-agent/test/repl-kernel-mcp-shutdown.test.ts +++ b/packages/coding-agent/test/repl-kernel-mcp-shutdown.test.ts @@ -4,6 +4,7 @@ import { homedir, tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { ReplKernelManager } from "../src/core/kernel/index.js"; +import { isTestTagEnabled } from "./test-tags.js"; const runtimePython = resolve("../../prime-agent-runtime/.venv/bin/python"); const fallbackPython = join(homedir(), ".prime", "agent", "kernel-venv", "bin", "python"); @@ -18,7 +19,7 @@ function resolveKernelPython(): string | null { } const python = resolveKernelPython(); -const describeIfKernel = python ? describe : describe.skip; +const describeIfKernel = python && isTestTagEnabled("kernel-heavy") ? describe : describe.skip; const MCP_SERVER = `import asyncio, json, os, sys from pathlib import Path @@ -56,7 +57,7 @@ async function waitForExit(pid: number, timeoutMs: number): Promise { return !pidExists(pid); } -describeIfKernel("real REPL kernel MCP shutdown", { tags: ["kernel-heavy"] }, () => { +describeIfKernel("real REPL kernel MCP shutdown", () => { let dir = ""; let fixture = ""; let pidFile = ""; diff --git a/packages/coding-agent/test/repl-kernel-parent-watchdog.test.ts b/packages/coding-agent/test/repl-kernel-parent-watchdog.test.ts index 5924881fce..e3a6e897f5 100644 --- a/packages/coding-agent/test/repl-kernel-parent-watchdog.test.ts +++ b/packages/coding-agent/test/repl-kernel-parent-watchdog.test.ts @@ -4,14 +4,14 @@ import { chmodSync, existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync import { homedir, tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import type * as kernelBootstrap from "../src/core/kernel/bootstrap.js"; import { ReplKernelManager } from "../src/core/kernel/index.js"; import { ORPHAN_PROCESS_JOURNAL_ENV } from "../src/core/orphan-process-journal.js"; +import { isTestTagEnabled } from "./test-tags.js"; const ensureKernelPythonMock = vi.hoisted(() => vi.fn()); -vi.mock("../src/core/kernel/bootstrap.js", async (importOriginal) => { - const original = await importOriginal(); +vi.mock("../src/core/kernel/bootstrap.js", () => { + const original = require("../src/core/kernel/bootstrap.js"); return { ...original, ensureKernelPython: ensureKernelPythonMock }; }); @@ -70,12 +70,17 @@ describe("repl kernel parent watchdog", () => { expect(readFileSync(envDump, "utf8")).toMatch(new RegExp(`^PRIME_AGENT_KERNEL_OWNER_PID=${process.pid}$`, "m")); - // Self-exited child: the kill signals nothing, so the record must stay active. + // The append-only journal starts with an active ownership record. Bun can + // observe the child exit soon enough to append its inactive tombstone too. await vi.waitFor(() => { const records = readJournalRecords(journalPath); - expect(records).toHaveLength(1); + expect(records.length).toBeGreaterThanOrEqual(1); expect(records[0]?.ownerPid).toBe(process.pid); expect(records[0]?.active).toBe(true); + expect(records.every((record) => record.pid === records[0]?.pid && record.ownerPid === process.pid)).toBe( + true, + ); + if (records.length > 1) expect(records.at(-1)?.active).toBe(false); }); }); @@ -287,9 +292,10 @@ function resolveReplPython(): string | null { } const replPython = resolveReplPython(); -const describeIf = replPython && process.platform !== "win32" ? describe : describe.skip; +const describeIf = + replPython && process.platform !== "win32" && isTestTagEnabled("kernel-heavy") ? describe : describe.skip; -describeIf("repl runtime outlives-owner watchdog (real runtime)", { tags: ["kernel-heavy"] }, () => { +describeIf("repl runtime outlives-owner watchdog (real runtime)", () => { it("runtime exits after its owner is SIGKILLed (stdin EOF watchdog)", async () => { const dir = mkdtempSync(join(tmpdir(), "prime-agent-repl-watchdog-int-")); const pidFile = join(dir, "runtime.pid"); diff --git a/packages/coding-agent/test/repl-kernel-startup.test.ts b/packages/coding-agent/test/repl-kernel-startup.test.ts index 219453f729..e52605d8cf 100644 --- a/packages/coding-agent/test/repl-kernel-startup.test.ts +++ b/packages/coding-agent/test/repl-kernel-startup.test.ts @@ -78,12 +78,16 @@ describe("ReplKernelManager startup", () => { const manager = new ReplKernelManager({ python, cwd: tempDir }); try { - const startPromise = manager.start(); - const expectation = expect(startPromise).rejects.toThrow(/did not become ready within 30000ms/); + const startResult = manager + .start() + .then(() => undefined) + .catch((error: Error) => error); await vi.advanceTimersByTimeAsync(30_000); // The failure path runs a graceful shutdown bounded by its own deadline. await vi.advanceTimersByTimeAsync(5_000); - await expectation; + const startError = await startResult; + expect(startError).toBeInstanceOf(Error); + expect(startError?.message).toMatch(/did not become ready within 30000ms/); } finally { vi.useRealTimers(); errorSpy.mockRestore(); diff --git a/packages/coding-agent/test/repl-kernel-state-roundtrip.test.ts b/packages/coding-agent/test/repl-kernel-state-roundtrip.test.ts index e08ece79a5..d0c0e0e3e3 100644 --- a/packages/coding-agent/test/repl-kernel-state-roundtrip.test.ts +++ b/packages/coding-agent/test/repl-kernel-state-roundtrip.test.ts @@ -4,6 +4,7 @@ import { homedir, tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { ReplKernelManager } from "../src/core/kernel/index.js"; +import { isTestTagEnabled } from "./test-tags.js"; function resolveReplPython(): string | null { const candidates = [ @@ -20,9 +21,9 @@ function resolveReplPython(): string | null { } const python = resolveReplPython(); -const describeIfKernel = python ? describe : describe.skip; +const describeIfKernel = python && isTestTagEnabled("kernel-heavy") ? describe : describe.skip; -describeIfKernel("repl kernel state snapshot round-trip (real runtime)", { tags: ["kernel-heavy"] }, () => { +describeIfKernel("repl kernel state snapshot round-trip (real runtime)", () => { let dir = ""; let snapshotPath = ""; let manifestPath = ""; diff --git a/packages/coding-agent/test/rlm-ledger.test.ts b/packages/coding-agent/test/rlm-ledger.test.ts index 2ebb9286dc..8bac64dc1f 100644 --- a/packages/coding-agent/test/rlm-ledger.test.ts +++ b/packages/coding-agent/test/rlm-ledger.test.ts @@ -11,8 +11,8 @@ import { import { tmpdir } from "node:os"; const linkFailure = vi.hoisted(() => ({ code: undefined as string | undefined })); -vi.mock("node:fs", async (importOriginal) => { - const actual = await importOriginal(); +vi.mock("node:fs", () => { + const actual = require("node:fs"); return { ...actual, linkSync: ( diff --git a/packages/coding-agent/test/rpc-example.ts b/packages/coding-agent/test/rpc-example.ts index d82bd93492..be8c2df56d 100644 --- a/packages/coding-agent/test/rpc-example.ts +++ b/packages/coding-agent/test/rpc-example.ts @@ -7,7 +7,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); /** * Interactive example of using coding-agent via RpcClient. - * Usage: npx tsx test/rpc-example.ts + * Usage: bun test/rpc-example.ts */ async function main() { diff --git a/packages/coding-agent/test/sdk-codex-cache-probe-tool-loop.ts b/packages/coding-agent/test/sdk-codex-cache-probe-tool-loop.ts index 3c71c5f254..1bfa6328ec 100644 --- a/packages/coding-agent/test/sdk-codex-cache-probe-tool-loop.ts +++ b/packages/coding-agent/test/sdk-codex-cache-probe-tool-loop.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env tsx +#!/usr/bin/env bun /** * Manual SDK probe for OpenAI Codex prompt caching through the tool loop. * @@ -123,7 +123,7 @@ function parseArgs(argv: string[]): Args { } function printHelp(): void { - console.log(`Usage: npx tsx test/sdk-codex-cache-probe-tool-loop.ts [options] + console.log(`Usage: bun test/sdk-codex-cache-probe-tool-loop.ts [options] Options: --turns Number of turns to run. Must be between ${MIN_TURNS} and ${MAX_TURNS}. Default: ${DEFAULT_TURNS} diff --git a/packages/coding-agent/test/session-manager-flush.test.ts b/packages/coding-agent/test/session-manager-flush.test.ts index 50ddafd555..4448bd04fc 100644 --- a/packages/coding-agent/test/session-manager-flush.test.ts +++ b/packages/coding-agent/test/session-manager-flush.test.ts @@ -30,8 +30,8 @@ const fsMocks = vi.hoisted(() => ({ renameSync: vi.fn(), writeFileSync: vi.fn(), })); -vi.mock("node:fs", async (importOriginal) => { - const actual = await importOriginal(); +vi.mock("node:fs", () => { + const actual = require("node:fs"); fsMocks.actualWriteFileSync = actual.writeFileSync; fsMocks.chmodSync.mockImplementation(actual.chmodSync); fsMocks.chownSync.mockImplementation(actual.chownSync); diff --git a/packages/coding-agent/test/stdout-cleanliness.test.ts b/packages/coding-agent/test/stdout-cleanliness.test.ts index 95b057b9ac..b889e50a44 100644 --- a/packages/coding-agent/test/stdout-cleanliness.test.ts +++ b/packages/coding-agent/test/stdout-cleanliness.test.ts @@ -6,7 +6,6 @@ import { afterEach, describe, expect, it } from "vitest"; import { ENV_AGENT_DIR } from "../src/config.js"; const cliPath = resolve(__dirname, "../src/cli.ts"); -const tsxPath = resolve(__dirname, "../../../node_modules/tsx/dist/cli.mjs"); const tempDirs: string[] = []; @@ -55,12 +54,11 @@ async function runCli(args: string[]): Promise<{ stdout: string; stderr: string; ); return await new Promise((resolvePromise, reject) => { - const child = spawn(process.execPath, [tsxPath, cliPath, ...args], { + const child = spawn(process.execPath, [cliPath, ...args], { cwd: projectDir, env: { ...process.env, [ENV_AGENT_DIR]: agentDir, - TSX_TSCONFIG_PATH: resolve(__dirname, "../../../tsconfig.json"), }, stdio: ["ignore", "pipe", "pipe"], }); diff --git a/packages/coding-agent/test/streaming-render-debug.ts b/packages/coding-agent/test/streaming-render-debug.ts index ffd4cc89b3..322c8ef59d 100644 --- a/packages/coding-agent/test/streaming-render-debug.ts +++ b/packages/coding-agent/test/streaming-render-debug.ts @@ -1,7 +1,7 @@ /** * Debug script to reproduce streaming rendering issues. * Uses real fixture data that caused the bug. - * Run with: npx tsx test/streaming-render-debug.ts + * Run with: bun test/streaming-render-debug.ts */ import type { AssistantMessage } from "@earendil-works/pi-ai"; diff --git a/packages/coding-agent/test/suite/acp-features.test.ts b/packages/coding-agent/test/suite/acp-features.test.ts index 5e92bc424d..33b0406f0c 100644 --- a/packages/coding-agent/test/suite/acp-features.test.ts +++ b/packages/coding-agent/test/suite/acp-features.test.ts @@ -765,7 +765,7 @@ describe("ACP mode preserves prime-agent features", () => { expect(init.agentInfo).toMatchObject({ name: "prime-agent" }); expect(typeof init.agentInfo?.version).toBe("string"); // Namespaced only: unknown root keys are reserved for future ACP fields. - expect(init._meta).toHaveProperty(PRIME_AGENT_META_NAMESPACE); + expect(init._meta).toHaveProperty([PRIME_AGENT_META_NAMESPACE]); expect(Object.keys(init.agentCapabilities ?? {})).not.toContain("subagents"); // close is advertised, so a client knows it may release the session slot. expect(init.agentCapabilities?.sessionCapabilities?.close).toBeDefined(); diff --git a/packages/coding-agent/test/suite/acp-mode.test.ts b/packages/coding-agent/test/suite/acp-mode.test.ts index 7f386305b7..b7bc4ebb74 100644 --- a/packages/coding-agent/test/suite/acp-mode.test.ts +++ b/packages/coding-agent/test/suite/acp-mode.test.ts @@ -212,7 +212,7 @@ describe("ACP mode end to end", () => { }); expect(init.protocolVersion).toBe(acp.PROTOCOL_VERSION); expect(init.agentInfo?.name).toBe("prime-agent"); - expect(init._meta).toHaveProperty(PRIME_AGENT_META_NAMESPACE); + expect(init._meta).toHaveProperty([PRIME_AGENT_META_NAMESPACE]); const session = await client.request("session/new", { cwd: harness.tempDir, mcpServers: [] }); expect(typeof session.sessionId).toBe("string"); diff --git a/packages/coding-agent/test/suite/agent-session-action-races.test.ts b/packages/coding-agent/test/suite/agent-session-action-races.test.ts index 8239c1f2f2..1d55728e11 100644 --- a/packages/coding-agent/test/suite/agent-session-action-races.test.ts +++ b/packages/coding-agent/test/suite/agent-session-action-races.test.ts @@ -3,7 +3,7 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import type { CustomMessage } from "../../src/core/messages.js"; import type { ActionStore, SessionAction } from "../../src/core/session-action-store.js"; import { createHarness, getMessageText, getUserTexts, type Harness } from "./harness.js"; -import { createDeferred } from "./scheduling.js"; +import { createDeferred, expectPromiseRejection } from "./scheduling.js"; type ActionKind = "turn" | "command"; @@ -225,7 +225,7 @@ describe("AgentSession action commit-fence races", () => { schedule.mockRestore(); internals._scheduleSessionInputPump(); await vi.waitFor(() => expect(internals._actionStore.unfinishedActions()[0]?.lifecycle.state).toBe("selected")); - const rejection = expect(completion).rejects.toThrow("cleared before delivery"); + const rejection = expectPromiseRejection(completion, "cleared before delivery"); expect(harness.session.clearQueue().followUp).toEqual([text]); heldFence.release(); diff --git a/packages/coding-agent/test/suite/agent-session-compaction-continuation.test.ts b/packages/coding-agent/test/suite/agent-session-compaction-continuation.test.ts index 06c9a215e4..bd57754811 100644 --- a/packages/coding-agent/test/suite/agent-session-compaction-continuation.test.ts +++ b/packages/coding-agent/test/suite/agent-session-compaction-continuation.test.ts @@ -16,6 +16,7 @@ import { Type } from "typebox"; import { afterEach, describe, expect, it, vi } from "vitest"; import type { AgentSession } from "../../src/core/agent-session.js"; import { createHarness, type Harness } from "./harness.js"; +import { expectPromiseRejection } from "./scheduling.js"; type SessionInternals = { _shouldStopAfterTurn: (context: ShouldStopAfterTurnContext) => boolean | Promise; @@ -250,7 +251,7 @@ describe("compaction continuation", () => { sessionInternals._schedulePostCompactionContinue(); const idle = harness.session.waitForHeadlessIdle(); - const rejectedIdle = expect(idle).rejects.toThrow("continuation failed"); + const rejectedIdle = expectPromiseRejection(idle, "continuation failed"); await vi.advanceTimersByTimeAsync(100); await rejectedIdle; diff --git a/packages/coding-agent/test/suite/agent-session-compaction.test.ts b/packages/coding-agent/test/suite/agent-session-compaction.test.ts index f19ce5b304..044f4715f5 100644 --- a/packages/coding-agent/test/suite/agent-session-compaction.test.ts +++ b/packages/coding-agent/test/suite/agent-session-compaction.test.ts @@ -158,10 +158,10 @@ describe("AgentSession compaction characterization", () => { tokensBefore: result.tokensBefore, fromHook: false, }); - expect(harness.session.messages[0]).toMatchObject({ - role: "compactionSummary", - summary: expect.stringContaining("model-generated summary"), - }); + const compactedMessage = harness.session.messages[0]; + expect(compactedMessage?.role).toBe("compactionSummary"); + if (compactedMessage?.role !== "compactionSummary") throw new Error("Expected compaction summary"); + expect(compactedMessage.summary).toContain("model-generated summary"); expect(harness.eventsOfType("compaction_start")).toEqual([expect.objectContaining({ reason: "manual" })]); expect(harness.eventsOfType("compaction_end")).toEqual([ expect.objectContaining({ @@ -1336,7 +1336,6 @@ describe("AgentSession compaction characterization", () => { }); it("waits for threshold-compaction autonomous continuations before finishing prompt", async () => { - vi.useFakeTimers(); const harness = await createHarness({ autonomous: { enabled: true, @@ -1356,7 +1355,6 @@ describe("AgentSession compaction characterization", () => { const promptPromise = harness.session.prompt("make the change"); await vi.waitFor(() => expect(harness.session.getAutonomousStatus().continuationsUsed).toBe(1)); - await vi.advanceTimersByTimeAsync(100); await promptPromise; expect(harness.session.getAutonomousStatus()).toMatchObject({ @@ -1475,12 +1473,12 @@ describe("AgentSession compaction characterization", () => { internals._persistCompactionOutcome("requested", "failed", "Requested compaction failed"), ).not.toThrow(); // The live outcome message discloses that it was not saved. - expect(harness.session.messages.at(-1)).toMatchObject({ - role: "custom", - customType: "compaction_outcome", - content: expect.stringContaining("could not be saved to session history"), - details: { reason: "requested", outcome: "failed" }, - }); + const liveOutcome = harness.session.messages.at(-1); + expect(liveOutcome?.role).toBe("custom"); + if (liveOutcome?.role !== "custom") throw new Error("Expected custom compaction outcome"); + expect(liveOutcome.customType).toBe("compaction_outcome"); + expect(liveOutcome.content).toContain("could not be saved to session history"); + expect(liveOutcome.details).toEqual({ reason: "requested", outcome: "failed" }); // In-memory state is fully rolled back: no outcome entry, same leaf and entries. expect(harness.sessionManager.getLeafId()).toBe(persistedLeafId); expect(harness.sessionManager.getEntries()).toEqual(persistedEntries); @@ -1497,11 +1495,11 @@ describe("AgentSession compaction characterization", () => { ); // The unpersisted disclosure survives context rebuilds (e.g. thinking toggle). const rebuilt = harness.session.buildSessionContext(); - expect(rebuilt.messages.at(-1)).toMatchObject({ - role: "custom", - customType: "compaction_outcome", - content: expect.stringContaining("could not be saved to session history"), - }); + const rebuiltOutcome = rebuilt.messages.at(-1); + expect(rebuiltOutcome?.role).toBe("custom"); + if (rebuiltOutcome?.role !== "custom") throw new Error("Expected custom compaction outcome"); + expect(rebuiltOutcome.customType).toBe("compaction_outcome"); + expect(rebuiltOutcome.content).toContain("could not be saved to session history"); // Cross a millisecond boundary so the later turn's timestamp is strictly newer. await new Promise((resolve) => setTimeout(resolve, 5)); diff --git a/packages/coding-agent/test/suite/agent-session-prompt.test.ts b/packages/coding-agent/test/suite/agent-session-prompt.test.ts index 8ade5795d0..eaf1ba6903 100644 --- a/packages/coding-agent/test/suite/agent-session-prompt.test.ts +++ b/packages/coding-agent/test/suite/agent-session-prompt.test.ts @@ -10,7 +10,7 @@ import type { PromptTemplate } from "../../src/core/prompt-templates.js"; import { createSyntheticSourceInfo } from "../../src/core/source-info.js"; import { createTestResourceLoader } from "../utilities.js"; import { createHarness, getAssistantTexts, getMessageText, getUserTexts, type Harness } from "./harness.js"; -import { createDeferred, createWaitingHarness, gatedHook } from "./scheduling.js"; +import { createDeferred, createWaitingHarness, expectPromiseRejection, gatedHook } from "./scheduling.js"; function gateNextAgentStart(harness: Harness): { reached: Promise; release(): void } { let markReached = () => {}; @@ -1166,8 +1166,8 @@ stale post-hook extension instructions`, const delivery = harness.session.waitForAgentMessagePromptDelivery(agentMessageId); const accepted = harness.session.acceptAgentMessagePrompt(agentPrompt, { expandPromptTemplates: false }); - const acceptedRejection = expect(accepted).rejects.toThrow("cleared before delivery"); - const deliveryRejection = expect(delivery).rejects.toThrow("cleared before delivery"); + const acceptedRejection = expectPromiseRejection(accepted, "cleared before delivery"); + const deliveryRejection = expectPromiseRejection(delivery, "cleared before delivery"); await admitted; expect(harness.session.clearQueuedUserMessagesMatching((text) => text.includes(agentMessageId))).toEqual({ @@ -1232,7 +1232,7 @@ stale post-hook extension instructions`, const prompt = "Agent-to-agent message received.\nSource: agent_message\nTo: Target, active target, session session-target\nMessage id: agentmsg_idle_cleanup\n\ncancel me"; const accepted = harness.session.acceptAgentMessagePrompt(prompt, { expandPromptTemplates: false }); - const rejected = expect(accepted).rejects.toThrow("cleared before delivery"); + const rejected = expectPromiseRejection(accepted, "cleared before delivery"); await Promise.all([eventQueueReached.promise, dispatchGate.reached]); harness.session.clearQueuedUserMessagesMatching((text) => text === prompt); @@ -2053,8 +2053,8 @@ stale post-hook extension instructions`, followUp: [clearedAgentPrompt], }); admission.release(); - await expect(accepted).rejects.toThrow("cleared before delivery"); - await expect(delivery).rejects.toThrow("cleared before delivery"); + await expectPromiseRejection(accepted, "cleared before delivery"); + await expectPromiseRejection(delivery, "cleared before delivery"); await harness.session.agent.waitForIdle(); await (harness.session as unknown as { _agentEventQueue: Promise })._agentEventQueue; const persistedAfter = harness.sessionManager.getEntries().filter((entry) => entry.type === "message").length; diff --git a/packages/coding-agent/test/suite/agent-session-queue.test.ts b/packages/coding-agent/test/suite/agent-session-queue.test.ts index 14e31404a1..e800414d79 100644 --- a/packages/coding-agent/test/suite/agent-session-queue.test.ts +++ b/packages/coding-agent/test/suite/agent-session-queue.test.ts @@ -30,7 +30,13 @@ import { } from "../../src/core/refinement/index.js"; import { parseSessionSlashCommand } from "../../src/core/slash-commands.js"; import { createHarness, getAssistantTexts, getMessageText, getUserTexts, type Harness } from "./harness.js"; -import { createDeferred, createWaitingHarness, gatedHook, withStreaming } from "./scheduling.js"; +import { + createDeferred, + createWaitingHarness, + expectPromiseRejection, + gatedHook, + withStreaming, +} from "./scheduling.js"; type AutoRefineReason = "turn_interval" | "compact"; @@ -1554,7 +1560,7 @@ describe("AgentSession queue characterization", () => { { customType: "hidden-trigger", content: "hidden queued prompt", display: false }, { triggerTurn: true }, ); - const hiddenRejection = expect(hidden).rejects.toThrow("Prompt aborted before delivery."); + const hiddenRejection = expectPromiseRejection(hidden, "Prompt aborted before delivery."); await vi.waitFor(() => expect(harness.session.getSessionActionRecoverySnapshot().actions).toHaveLength(2)); expect(harness.session.getFollowUpMessages()).toEqual(["visible queued prompt"]); @@ -2023,8 +2029,8 @@ describe("AgentSession queue characterization", () => { streamingBehavior: "followUp", resumeIfIdle: true, }); - const firstCompletionRejection = expect(firstCompletion).rejects.toThrow("cleared before delivery"); - const completionRejection = expect(completion).rejects.toThrow("cleared before delivery"); + const firstCompletionRejection = expectPromiseRejection(firstCompletion, "cleared before delivery"); + const completionRejection = expectPromiseRejection(completion, "cleared before delivery"); withStreaming(harness, false); await waitForPreparation; gatePreparation = false; @@ -2062,7 +2068,7 @@ describe("AgentSession queue characterization", () => { streamingBehavior: "followUp", resumeIfIdle: true, }); - const terminalRejection = expect(terminalCompletion).rejects.toThrow("No API key"); + const terminalRejection = expectPromiseRejection(terminalCompletion, "No API key"); await vi.waitFor(() => expect(authHarness.session.getFollowUpMessages()).toEqual(["cannot start"])); withStreaming(authHarness, false); await authHarness.session.waitForSessionInputIdle(); @@ -2237,10 +2243,11 @@ describe("AgentSession queue characterization", () => { const id = "agentmsg_command_append_failed"; const delivery = harness.session.waitForAgentMessagePromptDelivery(id); const completion = harness.session.promptAndWait("/autonomous status", { agentMessageId: id }); + const deliveryFailure = expectPromiseRejection(delivery, "durable invocation append failed"); + const completionFailure = expectPromiseRejection(completion, "durable invocation append failed"); pause.release(); - await expect(delivery).rejects.toThrow("durable invocation append failed"); - await expect(completion).rejects.toThrow("durable invocation append failed"); + await Promise.all([deliveryFailure, completionFailure]); // The failed append must roll back fully: no live-only command message and // no unsaved leaf, so later durable entries persist cleanly. @@ -2900,7 +2907,7 @@ describe("AgentSession queue characterization", () => { const lateAgentMessage = harness.session.acceptAgentMessagePrompt( agentPromptText("agentmsg_after_abort", "late child result"), ); - const lateRejection = expect(lateAgentMessage).rejects.toThrow("queued session input is suspended"); + const lateRejection = expectPromiseRejection(lateAgentMessage, "queued session input is suspended"); await new Promise((resolve) => setTimeout(resolve, 0)); await harness.session.prompt("explicit user resume"); @@ -2916,7 +2923,7 @@ describe("AgentSession queue characterization", () => { const lateAgentMessage = harness.session.acceptAgentMessagePrompt( agentPromptText("agentmsg_resume_queue", "late child result"), ); - const lateRejection = expect(lateAgentMessage).rejects.toThrow("queued session input is suspended"); + const lateRejection = expectPromiseRejection(lateAgentMessage, "queued session input is suspended"); await new Promise((resolve) => setTimeout(resolve, 0)); harness.session.resumeQueuedWork(); @@ -3251,7 +3258,8 @@ describe("AgentSession scheduler scenarios", () => { await harness.session.queueAgentMessagePrompt(agentPrompt, "steer"); // Phase 3: keyed duplicates reject both agent-message outcome legs. - const dupDelivery = expect(harness.session.waitForAgentMessagePromptDelivery("agentmsg_s2_dup")).rejects.toThrow( + const dupDelivery = expectPromiseRejection( + harness.session.waitForAgentMessagePromptDelivery("agentmsg_s2_dup"), "equivalent follow-up is already pending", ); await expect( @@ -3528,9 +3536,10 @@ describe("AgentSession scheduler scenarios", () => { const failedId = "agentmsg_failed_command"; const failedDelivery = harness.session.waitForAgentMessagePromptDelivery(failedId); const failedCompletion = harness.session.promptAndWait("/refine --local", { agentMessageId: failedId }); + const failedCompletionRejection = expectPromiseRejection(failedCompletion, "refine execution failed"); failedPause.release(); await expect(failedDelivery).resolves.toBeUndefined(); - await expect(failedCompletion).rejects.toThrow("refine execution failed"); + await failedCompletionRejection; }); it("S6: auto-refine reviews after real turns, defers while busy, and drops reviews on navigation", async () => { diff --git a/packages/coding-agent/test/suite/daemon-serialized-refine-process.test.ts b/packages/coding-agent/test/suite/daemon-serialized-refine-process.test.ts index 6b25ce1178..cd5fc9215a 100644 --- a/packages/coding-agent/test/suite/daemon-serialized-refine-process.test.ts +++ b/packages/coding-agent/test/suite/daemon-serialized-refine-process.test.ts @@ -43,8 +43,6 @@ import { } from "../../src/modes/daemon/daemon-worker-protocol.js"; const cliPath = resolve(__dirname, "../../src/cli.ts"); -const tsxPath = resolve(__dirname, "../../../../node_modules/tsx/dist/cli.mjs"); -const repoTsconfigPath = resolve(__dirname, "../../../../tsconfig.json"); const fauxRefineExtensionPath = resolve(__dirname, "../fixtures/eng-4685-faux-refine-extension.ts"); const eventOrderExtensionPath = resolve(__dirname, "../fixtures/eng-4685-event-order-extension.ts"); const children = new Set(); @@ -83,10 +81,9 @@ async function runCli( args: string[], options: { agentDir: string; stdin?: string; environment?: NodeJS.ProcessEnv }, ): Promise<{ code: number | null; signal: NodeJS.Signals | null; stdout: string; stderr: string }> { - const child = spawn(process.execPath, [tsxPath, cliPath, ...args], { + const child = spawn(process.execPath, [cliPath, ...args], { env: { ...process.env, - TSX_TSCONFIG_PATH: repoTsconfigPath, [ENV_AGENT_DIR]: options.agentDir, PI_SKIP_VERSION_CHECK: "1", PRIME_AGENT_INTERNAL_LEGACY_OWNED_WORKER_FRONTEND: "0", diff --git a/packages/coding-agent/test/suite/regressions/2791-fswatch-error-crash.test.ts b/packages/coding-agent/test/suite/regressions/2791-fswatch-error-crash.test.ts index 81a7a26823..2fea180660 100644 --- a/packages/coding-agent/test/suite/regressions/2791-fswatch-error-crash.test.ts +++ b/packages/coding-agent/test/suite/regressions/2791-fswatch-error-crash.test.ts @@ -50,18 +50,14 @@ describe("issue #2791 fs.watch error event crashes process", () => { writeFileSync( scriptPath, ` -import { setTheme, stopThemeWatcher } from "${themeModulePath}"; - process.env[${JSON.stringify(ENV_AGENT_DIR)}] = ${JSON.stringify(agentDir)}; +const { getActiveThemeWatcher, setTheme, stopThemeWatcher } = await import("${themeModulePath}"); setTheme("custom-test", true); - -// Find the FSWatcher among active handles -const handles = (process as any)._getActiveHandles(); -const fsWatcher = handles.find((h: any) => h.constructor?.name === "FSWatcher"); +const fsWatcher = getActiveThemeWatcher(); if (!fsWatcher) { - process.stderr.write("no FSWatcher found among active handles\\n"); + process.stderr.write("theme did not create an FSWatcher\\n"); process.exit(2); } @@ -88,7 +84,7 @@ process.exit(0); let stderr = ""; let exitCode: number; try { - _stdout = execFileSync("npx", ["tsx", scriptPath], { + _stdout = execFileSync(process.execPath, [scriptPath], { timeout: 10000, encoding: "utf-8", env: { ...process.env, [ENV_AGENT_DIR]: agentDir }, diff --git a/packages/coding-agent/test/suite/regressions/4600-supervisor-singleton.test.ts b/packages/coding-agent/test/suite/regressions/4600-supervisor-singleton.test.ts index c526a4c443..81613ce544 100644 --- a/packages/coding-agent/test/suite/regressions/4600-supervisor-singleton.test.ts +++ b/packages/coding-agent/test/suite/regressions/4600-supervisor-singleton.test.ts @@ -70,8 +70,6 @@ interface CleanupProcessIdentity { const fixturePath = resolve(__dirname, "../../fixtures/eng-4600-supervisor-fixture.ts"); const fauxExtensionPath = resolve(__dirname, "../../fixtures/eng-4600-faux-extension.ts"); const cliPath = resolve(__dirname, "../../../src/cli.ts"); -const tsxPath = resolve(__dirname, "../../../../../node_modules/tsx/dist/cli.mjs"); -const tsconfigPath = resolve(__dirname, "../../../../../tsconfig.json"); const supervisorRegistryDirEnv = "PRIME_AGENT_INTERNAL_DAEMON_SUPERVISOR_REGISTRY_DIR"; const handles = new Set(); const harnesses: Harness[] = []; @@ -128,7 +126,7 @@ function spawnFixture( paths: { agentDir: string; descriptorDir: string; registryDir: string; socketPath: string }, options: { extraEnv?: NodeJS.ProcessEnv; generation?: string } = {}, ): FixtureHandle { - const child = spawn(process.execPath, [tsxPath, fixturePath], { + const child = spawn(process.execPath, [fixturePath], { cwd: paths.agentDir, env: { ...process.env, @@ -142,7 +140,6 @@ function spawnFixture( ENG_4600_REGISTRY_DIR: paths.registryDir, ENG_4600_SOCKET_PATH: paths.socketPath, PI_OFFLINE: "1", - TSX_TSCONFIG_PATH: tsconfigPath, }, stdio: ["ignore", "pipe", "pipe", "ipc"], }); @@ -169,7 +166,7 @@ function spawnRealSupervisor( ): FixtureHandle { const child = spawn( process.execPath, - [tsxPath, cliPath, "--mode", "daemon", "--daemon-socket", paths.socketPath, "--offline"], + [cliPath, "--mode", "daemon", "--daemon-socket", paths.socketPath, "--offline"], { cwd: paths.agentDir, env: { @@ -178,7 +175,6 @@ function spawnRealSupervisor( [supervisorRegistryDirEnv]: paths.registryDir, [ENV_AGENT_DIR]: paths.agentDir, PI_OFFLINE: "1", - TSX_TSCONFIG_PATH: tsconfigPath, }, stdio: ["ignore", "pipe", "pipe"], }, diff --git a/packages/coding-agent/test/suite/regressions/4602-snapshot-transfer-idempotency.test.ts b/packages/coding-agent/test/suite/regressions/4602-snapshot-transfer-idempotency.test.ts index 56b99ebe0b..0b7c6e3d30 100644 --- a/packages/coding-agent/test/suite/regressions/4602-snapshot-transfer-idempotency.test.ts +++ b/packages/coding-agent/test/suite/regressions/4602-snapshot-transfer-idempotency.test.ts @@ -20,6 +20,8 @@ import { SnapshotTranscriptCache } from "../../../src/modes/daemon/snapshot-tran import { type PrivateFrame, PrivateFrameDecoder } from "../../../src/modes/session-worker/private-framing.js"; import { seedSupervisorRoster } from "../../fixtures/roster-seed.js"; +import { expectPromiseRejection } from "../scheduling.js"; + const activeSessionId = "active-4602"; const snapshotId = "snapshot-4602"; @@ -526,7 +528,7 @@ describe("ENG-4602 snapshot transfer containment", () => { const unhandled = vi.fn(); process.on("unhandledRejection", unhandled); try { - const validationFailure = expect(validation).rejects.toThrow("stopped during snapshot transfer"); + const validationFailure = expectPromiseRejection(validation, "stopped during snapshot transfer"); await internals.stopWorker(worker, false); await validationFailure; await catchup; diff --git a/packages/coding-agent/test/suite/regressions/4603-worker-recovery.test.ts b/packages/coding-agent/test/suite/regressions/4603-worker-recovery.test.ts index 19ab4a7f43..f362045402 100644 --- a/packages/coding-agent/test/suite/regressions/4603-worker-recovery.test.ts +++ b/packages/coding-agent/test/suite/regressions/4603-worker-recovery.test.ts @@ -8,6 +8,7 @@ import { readFileSync, renameSync, rmSync, + symlinkSync, writeFileSync, } from "node:fs"; import { createConnection, type Socket } from "node:net"; @@ -93,8 +94,6 @@ interface TestPaths { const fixturePath = resolve(__dirname, "../../fixtures/eng-4600-supervisor-fixture.ts"); const fauxExtensionPath = resolve(__dirname, "../../fixtures/eng-4600-faux-extension.ts"); const cliPath = resolve(__dirname, "../../../src/cli.ts"); -const tsxPath = resolve(__dirname, "../../../../../node_modules/tsx/dist/cli.mjs"); -const tsconfigPath = resolve(__dirname, "../../../../../tsconfig.json"); const supervisorRegistryDirEnv = "PRIME_AGENT_INTERNAL_DAEMON_SUPERVISOR_REGISTRY_DIR"; const handles = new Set(); const harnesses: Harness[] = []; @@ -126,7 +125,14 @@ async function createPaths(): Promise { const harness = await createHarness(); harnesses.push(harness); const executablePath = join(harness.tempDir, APP_NAME); - linkSync(process.execPath, executablePath); + try { + linkSync(process.execPath, executablePath); + } catch (error) { + if ((error as NodeJS.ErrnoException).code !== "EPERM" && (error as NodeJS.ErrnoException).code !== "EXDEV") { + throw error; + } + symlinkSync(process.execPath, executablePath); + } const socketTmpDir = `/tmp/eng-4603-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`; mkdirSync(socketTmpDir, { recursive: true, mode: 0o700 }); socketTempDirs.add(socketTmpDir); @@ -147,7 +153,7 @@ async function createPaths(): Promise { function spawnSupervisor(paths: TestPaths): ProcessHandle { return trackProcess( - spawn(paths.executablePath, [tsxPath, fixturePath], { + spawn(paths.executablePath, [fixturePath], { cwd: paths.agentDir, env: { ...process.env, @@ -160,7 +166,6 @@ function spawnSupervisor(paths: TestPaths): ProcessHandle { ENG_4600_SOCKET_PATH: paths.socketPath, PI_OFFLINE: "1", TMPDIR: paths.socketTmpDir, - TSX_TSCONFIG_PATH: tsconfigPath, }, stdio: ["ignore", "pipe", "pipe", "ipc"], }), @@ -175,26 +180,21 @@ function spawnStandaloneWorker( extraEnv: NodeJS.ProcessEnv = {}, ): ProcessHandle { return trackProcess( - spawn( - paths.executablePath, - [tsxPath, cliPath, "--mode", "daemon", "--daemon-socket", workerSocketPath, "--offline"], - { - cwd: paths.agentDir, - env: { - ...process.env, - ...extraEnv, - [supervisorRegistryDirEnv]: paths.registryDir, - [ENV_AGENT_DIR]: paths.agentDir, - [DAEMON_WORKER_ROLE_ENV]: "1", - [DAEMON_WORKER_TOKEN_ENV]: token, - [DAEMON_WORKER_ACTIVE_SESSION_ID_ENV]: "eng-4603-worker", - [DAEMON_WORKER_SUPERVISOR_SOCKET_ENV]: paths.socketPath, - PI_OFFLINE: "1", - TSX_TSCONFIG_PATH: tsconfigPath, - }, - stdio: ["ignore", "pipe", "pipe"], + spawn(paths.executablePath, [cliPath, "--mode", "daemon", "--daemon-socket", workerSocketPath, "--offline"], { + cwd: paths.agentDir, + env: { + ...process.env, + ...extraEnv, + [supervisorRegistryDirEnv]: paths.registryDir, + [ENV_AGENT_DIR]: paths.agentDir, + [DAEMON_WORKER_ROLE_ENV]: "1", + [DAEMON_WORKER_TOKEN_ENV]: token, + [DAEMON_WORKER_ACTIVE_SESSION_ID_ENV]: "eng-4603-worker", + [DAEMON_WORKER_SUPERVISOR_SOCKET_ENV]: paths.socketPath, + PI_OFFLINE: "1", }, - ), + stdio: ["ignore", "pipe", "pipe"], + }), "worker", ); } @@ -677,7 +677,7 @@ async function runCli( extraEnv: NodeJS.ProcessEnv = {}, ): Promise<{ code: number; stdout: string; stderr: string }> { const handle = trackProcess( - spawn(process.execPath, [tsxPath, cliPath, ...args], { + spawn(process.execPath, [cliPath, ...args], { cwd: paths.agentDir, env: { ...process.env, @@ -686,7 +686,6 @@ async function runCli( [ENV_AGENT_DIR]: paths.agentDir, PI_OFFLINE: "1", TMPDIR: paths.socketTmpDir, - TSX_TSCONFIG_PATH: tsconfigPath, }, stdio: ["ignore", "pipe", "pipe"], }), @@ -1066,7 +1065,9 @@ describe("ENG-4603 worker recovery convergence", () => { expect(listenersBeforeShutdown).toContain(`p${successor.child.pid}`); const shutdown = await runCli(paths, ["shutdown", "--force", "--json"], 60_000, lsofEnvironment); - expect(shutdown.code).toBe(0); + if (shutdown.code !== 0) { + throw new Error(`Shutdown failed with code ${shutdown.code}: ${shutdown.stderr}\n${shutdown.stdout}`); + } const shutdownResult = JSON.parse(shutdown.stdout) as { stopped: unknown[]; failed: unknown[] }; const survivingIdentities = [ { pid: predecessor.child.pid!, processStartId: predecessorStartId }, diff --git a/packages/coding-agent/test/suite/regressions/4606-update-restart-coordinator.test.ts b/packages/coding-agent/test/suite/regressions/4606-update-restart-coordinator.test.ts index 26ce76e1b5..4546033b2e 100644 --- a/packages/coding-agent/test/suite/regressions/4606-update-restart-coordinator.test.ts +++ b/packages/coding-agent/test/suite/regressions/4606-update-restart-coordinator.test.ts @@ -29,8 +29,6 @@ interface SupervisorOwnerRecord { const cliPath = resolve(__dirname, "../../../src/cli.ts"); const fauxExtensionPath = resolve(__dirname, "../../fixtures/eng-4600-faux-extension.ts"); const launcherFixturePath = resolve(__dirname, "../../fixtures/eng-4606-update-launcher.ts"); -const tsxPath = resolve(__dirname, "../../../../../node_modules/tsx/dist/cli.mjs"); -const tsconfigPath = resolve(__dirname, "../../../../../tsconfig.json"); const supervisorRegistryDirEnv = "PRIME_AGENT_INTERNAL_DAEMON_SUPERVISOR_REGISTRY_DIR"; const supervisors = new Set(); const harnesses: Harness[] = []; @@ -49,7 +47,7 @@ function spawnSupervisor(paths: { }): SupervisorHandle { const child = spawn( process.execPath, - [tsxPath, cliPath, "--mode", "daemon", "--daemon-socket", paths.socketPath, "--offline"], + [cliPath, "--mode", "daemon", "--daemon-socket", paths.socketPath, "--offline"], { cwd: paths.agentDir, env: { @@ -61,9 +59,7 @@ function spawnSupervisor(paths: { ENG_4606_COMPLETION_PATH: paths.completionPath, ENG_4606_PID_PATH: paths.pidPath, ENG_4606_SOCKET_PATH: paths.socketPath, - ENG_4606_TSX_PATH: tsxPath, PI_OFFLINE: "1", - TSX_TSCONFIG_PATH: tsconfigPath, }, stdio: ["ignore", "pipe", "pipe"], }, @@ -190,21 +186,11 @@ async function withSourceCliEntrypoint(action: () => Promise): Promise if (!previousEntrypoint) { throw new Error("Test process has no CLI entrypoint"); } - const previousExecArgv = [...process.execArgv]; - const previousTsconfigPath = process.env.TSX_TSCONFIG_PATH; process.argv[1] = cliPath; - process.execArgv.splice(0, process.execArgv.length, tsxPath); - process.env.TSX_TSCONFIG_PATH = tsconfigPath; try { return await action(); } finally { process.argv[1] = previousEntrypoint; - process.execArgv.splice(0, process.execArgv.length, ...previousExecArgv); - if (previousTsconfigPath === undefined) { - delete process.env.TSX_TSCONFIG_PATH; - } else { - process.env.TSX_TSCONFIG_PATH = previousTsconfigPath; - } } } @@ -276,9 +262,10 @@ describe("ENG-4606 update restart coordinator", () => { vi.useFakeTimers(); try { - vi.setSystemTime(new Date("2026-07-14T00:00:00.000Z")); - const writer = new DaemonUpdateRestartStatusWriter(statusPath, "test-request", "/tmp/daemon.sock"); + let now = new Date("2026-07-14T00:00:00.000Z"); + const writer = new DaemonUpdateRestartStatusWriter(statusPath, "test-request", "/tmp/daemon.sock", () => now); const stopHeartbeat = writer.startHeartbeat(); + now = new Date("2026-07-14T00:00:05.000Z"); vi.advanceTimersByTime(5000); stopHeartbeat(); @@ -385,7 +372,7 @@ describe("ENG-4606 update restart coordinator", () => { ), ); const originalActiveSessionId = created.activeSessionId ?? created.id; - const updateCommand = [process.execPath, tsxPath, launcherFixturePath].map(shellQuote).join(" "); + const updateCommand = [process.execPath, launcherFixturePath].map(shellQuote).join(" "); const executeResponse = await client.request( { type: "execute_bash", activeSessionId: originalActiveSessionId, command: updateCommand }, 5000, diff --git a/packages/coding-agent/test/suite/regressions/4685-daemon-client-modes.test.ts b/packages/coding-agent/test/suite/regressions/4685-daemon-client-modes.test.ts index 1dee7be89c..2d05b0720b 100644 --- a/packages/coding-agent/test/suite/regressions/4685-daemon-client-modes.test.ts +++ b/packages/coding-agent/test/suite/regressions/4685-daemon-client-modes.test.ts @@ -4,7 +4,7 @@ import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { fauxAssistantMessage } from "@earendil-works/pi-ai"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { createCliSubprocessEnv, createCliSubprocessLaunchSpec } from "../../../src/cli/subprocess-launch.js"; +import { createCliSubprocessLaunchSpec } from "../../../src/cli/subprocess-launch.js"; import { ENV_AGENT_DIR } from "../../../src/config.js"; import type { AutonomousRuntimeState } from "../../../src/core/autonomous.js"; import type { DaemonSocketClient } from "../../../src/modes/daemon/active-session-state.js"; @@ -19,8 +19,6 @@ const fixturePath = resolve(__dirname, "../../fixtures/rpc-connection-mode-fixtu const fauxExtensionPath = resolve(__dirname, "../../fixtures/eng-4600-faux-extension.ts"); const rpcEofFauxExtensionPath = resolve(__dirname, "../../fixtures/rpc-eof-faux-extension.ts"); const cliPath = resolve(__dirname, "../../../src/cli.ts"); -const tsxPath = resolve(__dirname, "../../../../../node_modules/tsx/dist/cli.mjs"); -const repoTsconfigPath = resolve(__dirname, "../../../../../tsconfig.json"); const children = new Set(); const harnesses: Harness[] = []; const daemonSockets = new Set(); @@ -68,10 +66,9 @@ async function runCli( args: string[], options: { agentDir: string; stdin?: string; environment?: NodeJS.ProcessEnv }, ): Promise { - const child = spawn(process.execPath, [tsxPath, cliPath, ...args], { + const child = spawn(process.execPath, [cliPath, ...args], { env: { ...process.env, - TSX_TSCONFIG_PATH: repoTsconfigPath, [ENV_AGENT_DIR]: options.agentDir, PI_SKIP_VERSION_CHECK: "1", PRIME_AGENT_INTERNAL_LEGACY_OWNED_WORKER_FRONTEND: "0", @@ -114,8 +111,8 @@ async function runRpc( commands: unknown[], options: { trailingNewline?: boolean } = {}, ): Promise<{ stdout: object[]; stderr: string }> { - const child = spawn(process.execPath, [tsxPath, fixturePath], { - env: { ...process.env, TSX_TSCONFIG_PATH: repoTsconfigPath }, + const child = spawn(process.execPath, [fixturePath], { + env: { ...process.env }, stdio: ["pipe", "pipe", "pipe"], }); children.add(child); @@ -233,12 +230,9 @@ describe("ENG-4685 daemon-backed client modes", () => { }); it("resolves source subprocesses independently of a spaced runtime cwd", () => { - const entrypoint = resolve(__dirname, "../../../src/cli.ts"); const launch = createCliSubprocessLaunchSpec([], process.execPath, [], "packages/coding-agent/src/cli.ts"); - const environment = createCliSubprocessEnv({}, entrypoint, ["--import", "tsx"]); expect(launch.args[0]).toBe(resolve("packages/coding-agent/src/cli.ts")); - expect(environment.TSX_TSCONFIG_PATH).toBe(repoTsconfigPath); }); it("launches real daemon workers for every migrated client surface", async () => { diff --git a/packages/coding-agent/test/suite/regressions/617-subagent-terminal-agent-message.test.ts b/packages/coding-agent/test/suite/regressions/617-subagent-terminal-agent-message.test.ts index 7f04a5169f..ad7b6bec6e 100644 --- a/packages/coding-agent/test/suite/regressions/617-subagent-terminal-agent-message.test.ts +++ b/packages/coding-agent/test/suite/regressions/617-subagent-terminal-agent-message.test.ts @@ -50,7 +50,7 @@ describe("#617 subagent terminal agent messages", () => { const spawned = await parent.session.runRlmChild("finish without replying", { name: childSessionName }); - await expect.poll(() => terminalNotices(parent!.session.messages)).toHaveLength(1); + await vi.waitFor(() => expect(terminalNotices(parent!.session.messages)).toHaveLength(1)); expect(sendAgentMessage).not.toHaveBeenCalled(); expect(terminalNotices(parent.session.messages)[0]).toMatchObject({ customType: "rlm_child_terminal_notice", diff --git a/packages/coding-agent/test/suite/regressions/623-acp-canonical-cwd.test.ts b/packages/coding-agent/test/suite/regressions/623-acp-canonical-cwd.test.ts index c975a5a116..ae0e0f8bc2 100644 --- a/packages/coding-agent/test/suite/regressions/623-acp-canonical-cwd.test.ts +++ b/packages/coding-agent/test/suite/regressions/623-acp-canonical-cwd.test.ts @@ -88,7 +88,7 @@ describe("#623 ACP canonical cwd comparison", () => { expect(cwdMeta(created)).toBeUndefined(); }, 30_000); - it.runIf(caseVariantCwd !== undefined)( + it.skipIf(caseVariantCwd === undefined)( "uses filesystem identity when realpath preserves different component casing", async () => { if (!caseVariantCwd) throw new Error("Expected a case-only cwd variant"); diff --git a/packages/coding-agent/test/suite/scheduling.ts b/packages/coding-agent/test/suite/scheduling.ts index 7d6f8cf07a..489eb64f35 100644 --- a/packages/coding-agent/test/suite/scheduling.ts +++ b/packages/coding-agent/test/suite/scheduling.ts @@ -20,6 +20,22 @@ export function createDeferred(): Deferred { return { promise, resolve, reject }; } +/** Attach an immediate rejection handler without Bun's pending `.rejects` matcher deadlock. */ +export function expectPromiseRejection(promise: Promise, expected: string | RegExp): Promise { + return promise.then( + () => { + throw new Error(`Expected promise to reject with ${String(expected)}`); + }, + (error: unknown) => { + const message = error instanceof Error ? error.message : String(error); + const matches = typeof expected === "string" ? message.includes(expected) : expected.test(message); + if (!matches) { + throw new Error(`Expected rejection ${String(expected)}, received: ${message}`); + } + }, + ); +} + /** * A before_agent_start gate as an extension factory: `reached` resolves when the * hook first runs (optionally filtered by prompt), `release()` lets gated runs diff --git a/packages/coding-agent/test/suite/serialized-refine-config-integration.test.ts b/packages/coding-agent/test/suite/serialized-refine-config-integration.test.ts index 17d0d8d781..9fb9710dda 100644 --- a/packages/coding-agent/test/suite/serialized-refine-config-integration.test.ts +++ b/packages/coding-agent/test/suite/serialized-refine-config-integration.test.ts @@ -162,7 +162,7 @@ describe("Serialized refine controller availability (unit)", () => { expect(internals._rlmHeartbeatController).toBe(fakeController); expect(internals._ipythonKernelProvisioner).not.toBe(initialProvisioner); - expect(internals._createKernelHostHandlers()).toHaveProperty("rlm_heartbeat.create"); + expect(internals._createKernelHostHandlers()).toHaveProperty(["rlm_heartbeat.create"]); // Verify the controller is usable via host request. const result = harness.session.handleRlmHeartbeatHostRequest("rlm_heartbeat.list"); diff --git a/packages/coding-agent/test/test-tags.ts b/packages/coding-agent/test/test-tags.ts new file mode 100644 index 0000000000..6e899aa646 --- /dev/null +++ b/packages/coding-agent/test/test-tags.ts @@ -0,0 +1,6 @@ +export function isTestTagEnabled(tag: string): boolean { + return (process.env.PRIME_AGENT_TEST_TAGS ?? "") + .split(",") + .map((value) => value.trim()) + .includes(tag); +} diff --git a/packages/coding-agent/test/test-theme-colors.ts b/packages/coding-agent/test/test-theme-colors.ts index 7ee88732aa..21e8a709f5 100644 --- a/packages/coding-agent/test/test-theme-colors.ts +++ b/packages/coding-agent/test/test-theme-colors.ts @@ -241,7 +241,7 @@ if (cmd === "contrast") { cmdTheme(cmd); } else { console.log("Usage:"); - console.log(" npx tsx test-theme-colors.ts light|dark Test built-in theme"); - console.log(" npx tsx test-theme-colors.ts contrast 4.5 Compute colors at ratio"); - console.log(" npx tsx test-theme-colors.ts test file.json Test any JSON file"); + console.log(" bun test-theme-colors.ts light|dark Test built-in theme"); + console.log(" bun test-theme-colors.ts contrast 4.5 Compute colors at ratio"); + console.log(" bun test-theme-colors.ts test file.json Test any JSON file"); } diff --git a/packages/coding-agent/vitest.config.ts b/packages/coding-agent/vitest.config.ts deleted file mode 100644 index 320ff2a983..0000000000 --- a/packages/coding-agent/vitest.config.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { fileURLToPath } from "node:url"; -import { defineConfig } from "vitest/config"; - -const aiSrcIndex = fileURLToPath(new URL("../ai/src/index.ts", import.meta.url)); -const aiSrcOAuth = fileURLToPath(new URL("../ai/src/oauth.ts", import.meta.url)); -const aiSrcMcp = fileURLToPath(new URL("../ai/src/mcp.ts", import.meta.url)); -const agentSrcIndex = fileURLToPath(new URL("../agent/src/index.ts", import.meta.url)); -const tuiSrcIndex = fileURLToPath(new URL("../tui/src/index.ts", import.meta.url)); - -export default defineConfig({ - test: { - globals: true, - environment: "node", - testTimeout: 30000, - env: { DO_NOT_TRACK: "1" }, - tags: [ - { - name: "process-stress", - description: "Slow real-process stress and wall-clock scheduling coverage", - }, - { - name: "kernel-heavy", - description: "Boots a real Python kernel and syncs skills into the shared venv", - }, - ], - // Kernel-heavy tests are excluded from the default sharded run: several files - // booting real kernels in one shard starve the neighbouring kernel tests that - // rely on the 30s default timeout. `test:kernel` runs them on their own. - tagsFilter: ["!process-stress", "!kernel-heavy"], - server: { - deps: { - external: [/@silvia-odwyer\/photon-node/], - }, - }, - }, - resolve: { - alias: [ - { find: /^@earendil-works\/pi-ai$/, replacement: aiSrcIndex }, - { find: /^@earendil-works\/pi-ai\/oauth$/, replacement: aiSrcOAuth }, - { find: /^@earendil-works\/pi-ai\/mcp$/, replacement: aiSrcMcp }, - { find: /^@earendil-works\/pi-agent-core$/, replacement: agentSrcIndex }, - { find: /^@earendil-works\/pi-tui$/, replacement: tuiSrcIndex }, - { find: /^@mariozechner\/pi-ai$/, replacement: aiSrcIndex }, - { find: /^@mariozechner\/pi-ai\/oauth$/, replacement: aiSrcOAuth }, - { find: /^@mariozechner\/pi-ai\/mcp$/, replacement: aiSrcMcp }, - { find: /^@mariozechner\/pi-agent-core$/, replacement: agentSrcIndex }, - { find: /^@mariozechner\/pi-tui$/, replacement: tuiSrcIndex }, - ], - }, -}); diff --git a/packages/tui/package.json b/packages/tui/package.json index 7e0ecbd82d..9f991b1af8 100644 --- a/packages/tui/package.json +++ b/packages/tui/package.json @@ -8,7 +8,7 @@ "clean": "bun ../../scripts/remove-paths.ts dist", "build": "bun --bun tsgo -p tsconfig.build.json", "dev": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", - "test": "node --test --import tsx test/*.test.ts", + "test": "bun ../../scripts/run-with-clean-env.ts bun test --isolate --timeout 30000", "prepublishOnly": "bun run clean && bun run build" }, "files": [ @@ -32,7 +32,8 @@ "directory": "packages/tui" }, "engines": { - "node": ">=20.0.0" + "node": ">=20.0.0", + "bun": "1.3.14" }, "types": "./dist/index.d.ts", "dependencies": { diff --git a/packages/tui/test/image-test.ts b/packages/tui/test/image-test.ts index 6a29d16d97..e263ce71a8 100644 --- a/packages/tui/test/image-test.ts +++ b/packages/tui/test/image-test.ts @@ -16,7 +16,7 @@ try { imageBuffer = readFileSync(testImagePath); } catch (_e) { console.error(`Failed to load image: ${testImagePath}`); - console.error("Usage: npx tsx test/image-test.ts [path-to-image.png]"); + console.error("Usage: bun test/image-test.ts [path-to-image.png]"); process.exit(1); } diff --git a/packages/tui/test/key-tester.ts b/packages/tui/test/key-tester.ts index 5103d54418..9983a1659a 100755 --- a/packages/tui/test/key-tester.ts +++ b/packages/tui/test/key-tester.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env bun import { matchesKey } from "../src/keys.js"; import { ProcessTerminal } from "../src/terminal.js"; import { type Component, TUI } from "../src/tui.js"; diff --git a/packages/tui/vitest.config.ts b/packages/tui/vitest.config.ts deleted file mode 100644 index a90c176d92..0000000000 --- a/packages/tui/vitest.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - include: ["test/wrap-ansi.test.ts"], - }, -}); diff --git a/scripts/publish-workspaces.ts b/scripts/publish-workspaces.ts new file mode 100644 index 0000000000..ed78c44076 --- /dev/null +++ b/scripts/publish-workspaces.ts @@ -0,0 +1,18 @@ +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const rootDir = dirname(dirname(fileURLToPath(import.meta.url))); +const packageDirs = ["tui", "ai", "agent", "coding-agent"] as const; +const dryRun = process.argv.includes("--dry-run"); + +for (const packageDir of packageDirs) { + const command = [process.execPath, "publish", "--access", "public", "--ignore-scripts"]; + if (dryRun) command.push("--dry-run"); + const result = Bun.spawnSync(command, { + cwd: join(rootDir, "packages", packageDir), + stdin: "inherit", + stdout: "inherit", + stderr: "inherit", + }); + if (result.exitCode !== 0) process.exit(result.exitCode); +} diff --git a/scripts/run-with-clean-env.ts b/scripts/run-with-clean-env.ts new file mode 100644 index 0000000000..c99f4e3a6e --- /dev/null +++ b/scripts/run-with-clean-env.ts @@ -0,0 +1,34 @@ +/** Run a command without inheriting live Prime Agent orchestration state. */ + +const [requestedCommand, ...args] = process.argv.slice(2); +if (!requestedCommand) { + console.error("Usage: bun scripts/run-with-clean-env.ts [args...]"); + process.exit(2); +} + +const env = { ...process.env }; +for (const name of Object.keys(env)) { + if (name.startsWith("PRIME_AGENT_INTERNAL_") || name.startsWith("RLM_")) { + delete env[name]; + } +} +for (const name of ["PRIME_AGENT_CODING_AGENT_DIR", "PRIME_AGENT_KERNEL_OWNER_PID"]) { + delete env[name]; +} + +const command = requestedCommand === "bun" ? process.execPath : requestedCommand; +const child = Bun.spawn([command, ...args], { + cwd: process.cwd(), + env, + stdin: "inherit", + stdout: "inherit", + stderr: "inherit", +}); + +for (const signal of ["SIGINT", "SIGTERM"] as const) { + process.on(signal, () => { + child.kill(signal); + }); +} + +process.exit(await child.exited); diff --git a/scripts/set-version.ts b/scripts/set-version.ts new file mode 100644 index 0000000000..d40c1b594b --- /dev/null +++ b/scripts/set-version.ts @@ -0,0 +1,88 @@ +import { readFile, writeFile } from "node:fs/promises"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const rootDir = dirname(dirname(fileURLToPath(import.meta.url))); +const manifestPaths = [ + "package.json", + "packages/tui/package.json", + "packages/ai/package.json", + "packages/agent/package.json", + "packages/coding-agent/package.json", +] as const; +const target = process.argv.find((arg, index) => index >= 2 && !arg.startsWith("--")); +const dryRun = process.argv.includes("--dry-run"); +const semverPattern = /^(\d+)\.(\d+)\.(\d+)$/; + +if (!target || (!semverPattern.test(target) && !["patch", "minor", "major"].includes(target))) { + console.error("Usage: bun scripts/set-version.ts [--dry-run]"); + process.exit(2); +} + +const manifests = await Promise.all( + manifestPaths.map(async (path) => { + const text = await readFile(join(rootDir, path), "utf8"); + return { path, text, value: JSON.parse(text) }; + }), +); +const currentVersions = new Set(manifests.map(({ value }) => value.version as string)); +if (currentVersions.size !== 1) { + throw new Error(`Workspace versions are not in lockstep: ${[...currentVersions].join(", ")}`); +} +const currentVersion = manifests[0].value.version as string; +const currentMatch = currentVersion.match(semverPattern); +if (!currentMatch) { + throw new Error(`Current version is not x.y.z: ${currentVersion}`); +} + +function nextVersion(): string { + if (semverPattern.test(target!)) return target!; + let major = Number(currentMatch![1]); + let minor = Number(currentMatch![2]); + let patch = Number(currentMatch![3]); + if (target === "major") { + major += 1; + minor = 0; + patch = 0; + } else if (target === "minor") { + minor += 1; + patch = 0; + } else { + patch += 1; + } + return `${major}.${minor}.${patch}`; +} + +const version = nextVersion(); +const workspaceVersions = new Map(manifests.slice(1).map(({ value }) => [value.name as string, version])); +for (const manifest of manifests) { + manifest.value.version = version; + for (const section of ["dependencies", "devDependencies", "optionalDependencies"] as const) { + const dependencies = manifest.value[section] as Record | undefined; + if (!dependencies) continue; + for (const name of Object.keys(dependencies)) { + if (workspaceVersions.has(name)) dependencies[name] = `^${version}`; + } + } +} + +console.log(`${currentVersion} -> ${version}`); +if (dryRun) process.exit(0); + +const lockPath = join(rootDir, "bun.lock"); +const originalLock = await readFile(lockPath, "utf8"); +for (const manifest of manifests) { + await writeFile(join(rootDir, manifest.path), `${JSON.stringify(manifest.value, null, "\t")}\n`); +} +const install = Bun.spawnSync([process.execPath, "install", "--lockfile-only"], { + cwd: rootDir, + stdin: "inherit", + stdout: "inherit", + stderr: "inherit", +}); +if (install.exitCode !== 0) { + await Promise.all(manifests.map((manifest) => writeFile(join(rootDir, manifest.path), manifest.text))); + await writeFile(lockPath, originalLock); + console.error("Version update failed; restored manifests and bun.lock."); + process.exit(install.exitCode); +} diff --git a/scripts/sync-versions.js b/scripts/sync-versions.js deleted file mode 100644 index c850b4c75e..0000000000 --- a/scripts/sync-versions.js +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env node - -/** - * Syncs all workspace package dependency versions to match their current versions. - * This ensures lockstep versioning across the monorepo. - */ - -import { readFileSync, writeFileSync, readdirSync } from 'fs'; -import { join } from 'path'; - -const packagesDir = join(process.cwd(), 'packages'); -const packageDirs = readdirSync(packagesDir, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .map(dirent => dirent.name); - -const packages = {}; -const versionMap = {}; - -for (const dir of packageDirs) { - const pkgPath = join(packagesDir, dir, 'package.json'); - try { - const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')); - packages[dir] = { path: pkgPath, data: pkg }; - versionMap[pkg.name] = pkg.version; - } catch (e) { - console.error(`Failed to read ${pkgPath}:`, e.message); - } -} - -console.log('Current versions:'); -for (const [name, version] of Object.entries(versionMap).sort()) { - console.log(` ${name}: ${version}`); -} - -const versions = new Set(Object.values(versionMap)); -if (versions.size > 1) { - console.error('\n❌ ERROR: Not all packages have the same version!'); - console.error('Expected lockstep versioning. Run one of:'); - console.error(' npm run version:patch'); - console.error(' npm run version:minor'); - console.error(' npm run version:major'); - process.exit(1); -} - -console.log('\n✅ All packages at same version (lockstep)'); - -let totalUpdates = 0; -for (const [dir, pkg] of Object.entries(packages)) { - let updated = false; - - if (pkg.data.dependencies) { - for (const [depName, currentVersion] of Object.entries(pkg.data.dependencies)) { - if (versionMap[depName]) { - const newVersion = `^${versionMap[depName]}`; - if (currentVersion !== newVersion) { - console.log(`\n${pkg.data.name}:`); - console.log(` ${depName}: ${currentVersion} → ${newVersion}`); - pkg.data.dependencies[depName] = newVersion; - updated = true; - totalUpdates++; - } - } - } - } - - if (pkg.data.devDependencies) { - for (const [depName, currentVersion] of Object.entries(pkg.data.devDependencies)) { - if (versionMap[depName]) { - const newVersion = `^${versionMap[depName]}`; - if (currentVersion !== newVersion) { - console.log(`\n${pkg.data.name}:`); - console.log(` ${depName}: ${currentVersion} → ${newVersion} (devDependencies)`); - pkg.data.devDependencies[depName] = newVersion; - updated = true; - totalUpdates++; - } - } - } - } - - if (updated) { - writeFileSync(pkg.path, JSON.stringify(pkg.data, null, '\t') + '\n'); - } -} - -if (totalUpdates === 0) { - console.log('\nAll inter-package dependencies already in sync.'); -} else { - console.log(`\n✅ Updated ${totalUpdates} dependency version(s)`); -} diff --git a/test.sh b/test.sh index 19b21dade1..081b6af55a 100755 --- a/test.sh +++ b/test.sh @@ -60,4 +60,4 @@ unset BEDROCK_EXTENSIVE_MODEL_TEST unset FIREWORKS_API_KEY echo "Running tests without API keys..." -npm test +bun scripts/run-with-clean-env.ts bun test --isolate --timeout 30000 diff --git a/tsconfig.json b/tsconfig.json index 4dfbf3d254..a54d87e145 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,9 @@ "@earendil-works/pi-tui": ["./packages/tui/src/index.ts"], "@earendil-works/pi-tui/*": ["./packages/tui/src/*"], "@earendil-works/pi-agent-old": ["./packages/agent-old/src/index.ts"], - "@earendil-works/pi-agent-old/*": ["./packages/agent-old/src/*"] + "@earendil-works/pi-agent-old/*": ["./packages/agent-old/src/*"], + "bun:test": ["./node_modules/bun-types/test.d.ts"], + "vitest": ["./types/vitest.d.ts"] } }, "include": ["packages/*/src/**/*", "packages/*/test/**/*", "packages/coding-agent/examples/**/*"], diff --git a/types/vitest.d.ts b/types/vitest.d.ts new file mode 100644 index 0000000000..3e6c6a8be7 --- /dev/null +++ b/types/vitest.d.ts @@ -0,0 +1,45 @@ +export * from "@vitest/runner"; +export { assert, createExpect, expect } from "@vitest/expect"; +export type { Mock, MockedFunction, MockInstance, MockedObject } from "@vitest/spy"; + +import type { MockInstance } from "@vitest/spy"; + +type Awaitable = T | Promise; +type CompatMocked = T extends (...args: any[]) => any + ? T & MockInstance + : T extends object + ? { [K in keyof T]: CompatMocked } + : T; +export type Mocked = CompatMocked; + +type VitestCompat = { + advanceTimersByTime(milliseconds: number): VitestCompat; + advanceTimersByTimeAsync(milliseconds: number): Promise; + advanceTimersToNextTimer(): VitestCompat; + advanceTimersToNextTimerAsync(): Promise; + clearAllMocks(): VitestCompat; + clearAllTimers(): VitestCompat; + fn: typeof import("@vitest/spy").fn; + getTimerCount(): number; + hoisted(factory: () => T): T; + isFakeTimers(): boolean; + isMockFunction(fn: unknown): fn is MockInstance; + mock(path: string, factory?: () => unknown): void; + mocked(value: T): CompatMocked; + resetAllMocks(): VitestCompat; + restoreAllMocks(): VitestCompat; + runAllTimers(): VitestCompat; + runAllTimersAsync(): Promise; + runOnlyPendingTimers(): VitestCompat; + runOnlyPendingTimersAsync(): Promise; + setSystemTime(value: Date | number): VitestCompat; + spyOn: typeof import("@vitest/spy").spyOn; + stubEnv(name: string, value: string | undefined): VitestCompat; + stubGlobal(name: PropertyKey, value: unknown): VitestCompat; + unstubAllEnvs(): VitestCompat; + unstubAllGlobals(): VitestCompat; + useFakeTimers(options?: { now?: Date | number }): VitestCompat; + useRealTimers(): VitestCompat; + waitFor(assertion: () => Awaitable, options?: { timeout?: number; interval?: number }): Promise; +}; +export const vi: VitestCompat; From 624c83dfbeddae075147a42d22bfebd877f73e23 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 17:38:53 -0400 Subject: [PATCH 05/31] build: ship Bun binaries with verified sidecars --- .npmrc | 6 - install.sh | 579 +++++++++++++++++-- packages/ai/scripts/generate-models.ts | 4 +- packages/ai/scripts/generate-test-image.ts | 2 +- packages/coding-agent/scripts/bundle.mjs | 33 +- packages/coding-agent/scripts/copy-assets.ts | 10 +- scripts/assemble-release-archives.mjs | 312 ++++++++++ scripts/build-binaries.sh | 207 +++---- scripts/check-browser-smoke.mjs | 38 +- scripts/compiled-artifact-smoke.ts | 161 ++++++ scripts/pack-prime-agent-release.mjs | 376 ++++-------- scripts/release.mjs | 26 +- 12 files changed, 1222 insertions(+), 532 deletions(-) delete mode 100644 .npmrc create mode 100755 scripts/assemble-release-archives.mjs create mode 100644 scripts/compiled-artifact-smoke.ts mode change 100644 => 100755 scripts/pack-prime-agent-release.mjs diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 2ebd6374a1..0000000000 --- a/.npmrc +++ /dev/null @@ -1,6 +0,0 @@ -# Supply-chain cooldown: never resolve to package versions published -# less than 7 days ago. Only affects version resolution (install/update of new -# versions); already-locked versions and `npm ci` are unaffected. -# Requires npm >= 11.10 to be enforced; older npm ignores this key. -# Urgent security patch override: npm install --min-release-age=0 -min-release-age=7 diff --git a/install.sh b/install.sh index c1b5c52458..c2bbce253f 100755 --- a/install.sh +++ b/install.sh @@ -57,6 +57,11 @@ prime_agent_screen_status= prime_agent_screen_detail= prime_agent_screen_question= prime_agent_animation_frame=0 +prime_agent_install_method="${PRIME_AGENT_INSTALL_METHOD:-auto}" +prime_agent_binary_versions_dir="${PRIME_AGENT_VERSIONS_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/prime-agent/versions}" +prime_agent_binary_symlink="${PRIME_AGENT_BIN_DIR:-${XDG_BIN_HOME:-$HOME/.local/bin}}/prime-agent" +prime_agent_binary_rollback_version= +prime_agent_is_update=0 main() { if [ "$prime_agent_base_url" = "$prime_agent_unconfigured_base_url" ]; then @@ -65,81 +70,62 @@ main() { exit 1 fi + # Parse flags before positional args + prime_agent_install_method="${PRIME_AGENT_INSTALL_METHOD:-auto}" + prime_agent_is_update=0 + _prime_agent_positional= + for _prime_agent_arg in "$@"; do + case "$_prime_agent_arg" in + --method=*) + prime_agent_install_method="${_prime_agent_arg#--method=}" + case "$prime_agent_install_method" in + binary|npm|auto) ;; + *) + printf 'error: invalid install method: %s (must be binary, npm, or auto)\n' "$prime_agent_install_method" >&2 + exit 1 + ;; + esac + ;; + --update) + prime_agent_is_update=1 + prime_agent_install_method=binary + ;; + *) + if [ -z "$_prime_agent_positional" ]; then + _prime_agent_positional="$_prime_agent_arg" + else + _prime_agent_positional="$_prime_agent_positional $_prime_agent_arg" + fi + ;; + esac + done + prime_agent_install_traps prime_agent_init_screen - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Installing Prime Agent" "" "" "" - else - printf '\n\033[1m Installing Prime Agent\033[0m\n\033[2m npm global install\033[0m\n\n' - fi - start_preflight_checks - - if finish_preflight_checks; then - check_status=0 - else - check_status=$? - fi - - if [ "$check_status" -ne 0 ]; then - if ! install_node_npm_interactive; then - exit "$check_status" - fi - - start_preflight_checks - if finish_preflight_checks; then - check_status=0 + if [ "$prime_agent_is_update" = 1 ]; then + if [ "$prime_agent_screen_enabled" = 1 ]; then + prime_agent_screen "Updating Prime Agent" "" "" "" else - check_status=$? - fi - - if [ "$check_status" -ne 0 ]; then - exit "$check_status" + printf '\n\033[1m Updating Prime Agent\033[0m\n' fi + prime_agent_binary_update "${_prime_agent_positional:-}" + return fi - version="$(resolve_prime_agent_version "$@")" - tarball_name="$prime_agent_package-$version.tgz" - tarball_url="$prime_agent_base_url/releases/v$version/$tarball_name" - - confirm_install "$version" "$tarball_url" - confirm_kernel_runtime_setup - - download_dir=$(create_temp_dir) - prime_agent_download_dir="$download_dir" - tarball_path="$download_dir/$tarball_name" - - download_prime_agent_package "$version" "$tarball_url" "$tarball_path" - install_prime_agent_package "$tarball_path" - rm -rf "$download_dir" - prime_agent_download_dir= - - if [ "${PRIME_AGENT_NODE_INSTALLED_STANDALONE:-0}" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "Checking your shell PATH." "" - configure_standalone_node_path - elif command -v "$prime_agent_cmd" >/dev/null 2>&1; then + # Default auto and explicit --method=binary both use compiled binary + if [ "$prime_agent_install_method" != npm ]; then if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "Run it with: $prime_agent_cmd" "" + prime_agent_screen "Installing Prime Agent" "" "" "" else - printf '\nPrime Agent was installed successfully.\n' - printf '\nRun it with: %s\n' "$prime_agent_cmd" - fi - else - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "PATH update needed for $prime_agent_cmd." "" - prime_agent_restore_terminal - else - printf '\nPrime Agent was installed successfully.\n' + printf '\n\033[1m Installing Prime Agent\033[0m\n\033[2m compiled binary\033[0m\n\n' fi - cat </ +# and point a stable symlink at it from ~/.local/bin/prime-agent. +# On update: download to a fresh version dir, smoke-test the binary there, +# then atomically switch the symlink. Rollback by restoring the old symlink. +# Never copy runtime sidecars into user config dirs (~/.prime/*). + +prime_agent_detect_binary_platform() { + _os=$(uname -s) + _arch=$(uname -m) + case "$_os" in + Darwin) + case "$_arch" in + x86_64|amd64) printf 'darwin-x64' ;; + arm64|aarch64) printf 'darwin-arm64' ;; + *) return 1 ;; + esac + ;; + Linux) + case "$_arch" in + x86_64|amd64) printf 'linux-x64' ;; + arm64|aarch64) printf 'linux-arm64' ;; + *) return 1 ;; + esac + ;; + *) return 1 ;; + esac +} + +prime_agent_binary_artifact_name() { + _version="$1" + _platform="$2" + printf 'prime-agent-%s-%s.tar.gz' "$_version" "$_platform" +} + +prime_agent_binary_target_version_dir() { + printf '%s/v%s' "$prime_agent_binary_versions_dir" "$1" +} + +prime_agent_binary_smoke_binary() { + _binary="$1" + if [ ! -x "$_binary" ]; then + return 1 + fi + if ! "$_binary" --version >/dev/null 2>&1; then + return 1 + fi +} + +prime_agent_binary_atomic_symlink() { + _target="$1" + _link="$2" + # Create parent dir if needed + _link_dir=$(dirname "$_link") + if [ ! -d "$_link_dir" ]; then + mkdir -p "$_link_dir" + fi + # Atomic replacement with temp symlink + _tmp="${_link}.tmp.$$" + ln -sf "$_target" "$_tmp" + mv -f "$_tmp" "$_link" +} + +prime_agent_binary_fresh_install() { + _version= + _version="$(resolve_prime_agent_version "$@")" + _platform= + if ! _platform=$(prime_agent_detect_binary_platform); then + printf 'error: unsupported platform for binary install: %s %s\n' "$(uname -s)" "$(uname -m)" >&2 + exit 1 + fi + _artifact_name="$(prime_agent_binary_artifact_name "$_version" "$_platform")" + _artifact_url="$prime_agent_base_url/releases/v$_version/$_artifact_name" + _versions_dir="$prime_agent_binary_versions_dir" + _version_dir="$(prime_agent_binary_target_version_dir "$_version")" + + _download_dir=$(create_temp_dir) + prime_agent_download_dir="$_download_dir" + _artifact_path="$_download_dir/$_artifact_name" + + mkdir -p "$_versions_dir" + + # Version directories are immutable. Reuse a healthy existing install instead + # of replacing files underneath the active command symlink. + _existing_binary="$_version_dir/$prime_agent_cmd" + if [ ! -x "$_existing_binary" ] && [ -x "$_version_dir/pi" ]; then + _existing_binary="$_version_dir/pi" + fi + if [ -x "$_existing_binary" ] && prime_agent_binary_smoke_binary "$_existing_binary"; then + prime_agent_binary_atomic_symlink "$_existing_binary" "$prime_agent_binary_symlink" + prime_agent_configure_binary_path "$_version" + return + fi + + prime_agent_run_quiet_with_animation "Downloading Prime Agent v$_version" "Downloading Prime Agent v$_version" "Fetching the compiled binary for $_platform." curl -fsSL "$_artifact_url" -o "$_artifact_path" + + _checksums_url="$prime_agent_base_url/releases/v$_version/SHA256SUMS" + _checksums_path="$_download_dir/SHA256SUMS" + prime_agent_run_quiet_with_animation "Downloading checksums" "Downloading release checksums" "Prime Agent v$_version" curl -fsSL "$_checksums_url" -o "$_checksums_path" + + prime_agent_verify_binary_checksum "$_checksums_path" "$_artifact_path" + + # Extract to a clean versioned directory + rm -rf "$_version_dir" + mkdir -p "$_version_dir" + prime_agent_run_quiet_with_animation "Extracting Prime Agent" "Extracting Prime Agent v$_version" "Installing to $_version_dir" tar -xzf "$_artifact_path" -C "$_version_dir" + + # Find the binary inside the extracted archive. + # The archive may contain a wrapper dir (e.g. pi/) or be flat. + _binary_path= + if [ -f "$_version_dir/pi" ]; then + _binary_path="$_version_dir/pi" + elif [ -f "$_version_dir/$prime_agent_cmd" ]; then + _binary_path="$_version_dir/$prime_agent_cmd" + else + for _d in "$_version_dir"/*/; do + _d="${_d%/}" + if [ -f "${_d}/pi" ]; then + _binary_path="${_d}/pi" + break + elif [ -f "${_d}/$prime_agent_cmd" ]; then + _binary_path="${_d}/$prime_agent_cmd" + break + fi + done + fi + + if [ -z "$_binary_path" ]; then + printf 'error: could not find the prime-agent binary in the downloaded artifact.\n' >&2 + rm -rf "$_version_dir" "$_download_dir" + prime_agent_download_dir= + exit 1 + fi + + chmod +x "$_binary_path" 2>/dev/null || true + # Ensure bundled install.sh is executable (required sidecar for self-update) + if [ -f "$_version_dir/install.sh" ]; then + chmod +x "$_version_dir/install.sh" 2>/dev/null || true + fi + + if ! "$_binary_path" --version >/dev/null 2>&1; then + printf 'error: the downloaded binary did not run correctly.\n' >&2 + rm -rf "$_version_dir" "$_download_dir" + prime_agent_download_dir= + exit 1 + fi + + # If the binary was inside a wrapper dir, move contents up to version_dir + _binary_dir=$(dirname "$_binary_path") + if [ "$_binary_dir" != "$_version_dir" ]; then + cp -R "$_binary_dir/." "$_version_dir/" + rm -rf "$_binary_dir" + _binary_path="$_version_dir/$(basename "$_binary_path")" + fi + + # Create the stable symlink + mkdir -p "$(dirname "$prime_agent_binary_symlink")" + prime_agent_binary_atomic_symlink "$_binary_path" "$prime_agent_binary_symlink" + + rm -rf "$_download_dir" + prime_agent_download_dir= + + prime_agent_configure_binary_path "$_version" + # The Python kernel will be bootstrapped on first ipython use. +} + +prime_agent_binary_update() { + _update_version= + _update_version="$(resolve_prime_agent_version "$@")" + + # Read current version from the symlink target's package.json + _current_version= + if [ -L "$prime_agent_binary_symlink" ]; then + _symlink_target=$(readlink "$prime_agent_binary_symlink") + _pkg_dir=$(dirname "$_symlink_target") + if [ -f "$_pkg_dir/package.json" ]; then + _current_version=$(sed -n 's/.*"version": *"\([^"]*\)".*/\1/p' "$_pkg_dir/package.json" 2>/dev/null || printf '') + fi + fi + + if [ -n "$_current_version" ] && [ "$_current_version" = "$_update_version" ]; then + if [ "$prime_agent_screen_enabled" = 1 ]; then + prime_agent_screen "Prime Agent is up to date" "" "v$_current_version" "" + else + printf '\nPrime Agent v%s is already installed.\n' "$_current_version" + fi + return + fi + + _platform= + if ! _platform=$(prime_agent_detect_binary_platform); then + printf 'error: unsupported platform for binary update: %s %s\n' "$(uname -s)" "$(uname -m)" >&2 + exit 1 + fi + _artifact_name="$(prime_agent_binary_artifact_name "$_update_version" "$_platform")" + _artifact_url="$prime_agent_base_url/releases/v$_update_version/$_artifact_name" + _versions_dir="$prime_agent_binary_versions_dir" + _version_dir="$(prime_agent_binary_target_version_dir "$_update_version")" + + _download_dir=$(create_temp_dir) + prime_agent_download_dir="$_download_dir" + _artifact_path="$_download_dir/$_artifact_name" + + if [ "$prime_agent_screen_enabled" = 1 ]; then + if [ -n "$_current_version" ]; then + prime_agent_screen "Updating Prime Agent" "" "v$_current_version to v$_update_version" "" + else + prime_agent_screen "Updating Prime Agent" "" "to v$_update_version" "" + fi + fi + + prime_agent_run_quiet_with_animation "Downloading Prime Agent v$_update_version" "Downloading Prime Agent v$_update_version" "Fetching the compiled binary for $_platform." curl -fsSL "$_artifact_url" -o "$_artifact_path" + + _checksums_url="$prime_agent_base_url/releases/v$_update_version/SHA256SUMS" + _checksums_path="$_download_dir/SHA256SUMS" + prime_agent_run_quiet_with_animation "Downloading checksums" "Downloading release checksums" "Prime Agent v$_update_version" curl -fsSL "$_checksums_url" -o "$_checksums_path" + + prime_agent_verify_binary_checksum "$_checksums_path" "$_artifact_path" + + # Extract to a fresh version directory + rm -rf "$_version_dir" + mkdir -p "$_version_dir" + prime_agent_run_quiet_with_animation "Extracting Prime Agent" "Extracting Prime Agent v$_update_version" "Preparing the update." tar -xzf "$_artifact_path" -C "$_version_dir" + + # Find the binary + _binary_path= + if [ -f "$_version_dir/pi" ]; then + _binary_path="$_version_dir/pi" + elif [ -f "$_version_dir/$prime_agent_cmd" ]; then + _binary_path="$_version_dir/$prime_agent_cmd" + else + for _d in "$_version_dir"/*/; do + _d="${_d%/}" + if [ -f "${_d}/pi" ]; then + _binary_path="${_d}/pi" + break + elif [ -f "${_d}/$prime_agent_cmd" ]; then + _binary_path="${_d}/$prime_agent_cmd" + break + fi + done + fi + + if [ -z "$_binary_path" ]; then + printf 'error: could not find the prime-agent binary in the downloaded artifact.\n' >&2 + rm -rf "$_version_dir" "$_download_dir" + prime_agent_download_dir= + exit 1 + fi + + chmod +x "$_binary_path" 2>/dev/null || true + # Ensure bundled install.sh is executable (required sidecar for self-update) + if [ -f "$_version_dir/install.sh" ]; then + chmod +x "$_version_dir/install.sh" 2>/dev/null || true + fi + + # Smoke-test the new binary BEFORE switching the symlink + if ! "$_binary_path" --version >/dev/null 2>&1; then + # New binary is bad: remove it, keep old symlink + rm -rf "$_version_dir" "$_download_dir" + prime_agent_download_dir= + if [ "$prime_agent_screen_enabled" = 1 ]; then + prime_agent_screen "Update failed" "" "New binary did not run correctly." "" + else + printf '\nUpdate failed: the new binary did not run correctly.\n' + fi + exit 1 + fi + + # If the binary was inside a wrapper dir, move contents up + _binary_dir=$(dirname "$_binary_path") + if [ "$_binary_dir" != "$_version_dir" ]; then + cp -R "$_binary_dir/." "$_version_dir/" + rm -rf "$_binary_dir" + _binary_path="$_version_dir/$(basename "$_binary_path")" + fi + + # Remember old version for rollback + if [ -L "$prime_agent_binary_symlink" ]; then + _old_target=$(readlink "$prime_agent_binary_symlink" 2>/dev/null || printf '') + _old_version_dir=$(dirname "$_old_target" 2>/dev/null || printf '') + prime_agent_binary_rollback_version="$_old_version_dir" + fi + + # Atomically switch the symlink + prime_agent_binary_atomic_symlink "$_binary_path" "$prime_agent_binary_symlink" + + rm -rf "$_download_dir" + prime_agent_download_dir= + + if [ "$prime_agent_screen_enabled" = 1 ]; then + prime_agent_screen "Prime Agent updated" "" "v$_update_version installed." "" + else + printf '\nPrime Agent was updated to v%s.\n' "$_update_version" + fi + + prime_agent_configure_binary_path "$_update_version" +} + +prime_agent_binary_rollback() { + if [ -z "$prime_agent_binary_rollback_version" ] || [ ! -d "$prime_agent_binary_rollback_version" ]; then + return 1 + fi + _rollback_binary= + if [ -f "$prime_agent_binary_rollback_version/pi" ]; then + _rollback_binary="$prime_agent_binary_rollback_version/pi" + elif [ -f "$prime_agent_binary_rollback_version/$prime_agent_cmd" ]; then + _rollback_binary="$prime_agent_binary_rollback_version/$prime_agent_cmd" + fi + if [ -z "$_rollback_binary" ] || [ ! -x "$_rollback_binary" ]; then + return 1 + fi + prime_agent_binary_atomic_symlink "$_rollback_binary" "$prime_agent_binary_symlink" +} + +prime_agent_verify_binary_checksum() { + _checksums_path="$1" + _artifact_path="$2" + _checksum_dir=$(dirname "$_artifact_path") + _artifact_name=$(basename "$_artifact_path") + _selected_checksums_path="$_checksum_dir/SHA256SUMS.selected" + + if ! awk -v file="$_artifact_name" '$2 == file { print; found = 1; exit } END { if (!found) exit 1 }' "$_checksums_path" >"$_selected_checksums_path"; then + printf 'error: checksum for %s was not found in %s\n' "$_artifact_name" "$_checksums_path" >&2 + exit 1 + fi + + if command -v sha256sum >/dev/null 2>&1; then + prime_agent_run_quiet_with_animation "Verifying download" "Verifying Prime Agent download" "Checking SHA-256." prime_agent_run_checksum_check "$_checksum_dir" "$(basename "$_selected_checksums_path")" sha256sum + elif command -v shasum >/dev/null 2>&1; then + prime_agent_run_quiet_with_animation "Verifying download" "Verifying Prime Agent download" "Checking SHA-256." prime_agent_run_checksum_check "$_checksum_dir" "$(basename "$_selected_checksums_path")" shasum + else + printf 'error: sha256sum or shasum is required to verify the download.\n' >&2 + exit 1 + fi +} + +prime_agent_configure_binary_path() { + _installed_version="${1:-}" + + if command -v "$prime_agent_cmd" >/dev/null 2>&1; then + _existing_path="$(command -v "$prime_agent_cmd")" + if [ "$_existing_path" = "$prime_agent_binary_symlink" ]; then + if [ "$prime_agent_screen_enabled" = 1 ]; then + prime_agent_screen "Prime Agent installed" "" "Run it with: $prime_agent_cmd" "" + else + printf '\nRun it with: %s\n' "$prime_agent_cmd" + fi + return + fi + fi + + _bin_dir=$(dirname "$prime_agent_binary_symlink") + case ":$PATH:" in + *":$_bin_dir:"*) + if [ "$prime_agent_screen_enabled" = 1 ]; then + prime_agent_screen "Prime Agent installed" "" "Run it with: $prime_agent_cmd" "" + else + printf '\nRun it with: %s\n' "$prime_agent_cmd" + fi + return + ;; + esac + + if [ "$prime_agent_screen_enabled" = 1 ]; then + prime_agent_screen "Prime Agent installed" "" "PATH update needed for $prime_agent_cmd." "" + prime_agent_restore_terminal + else + printf '\nPrime Agent was installed to %s.\n' "$_bin_dir" + fi + + _profile=$(detect_shell_profile) + if [ -n "$_profile" ] && [ -w "$_profile" ] 2>/dev/null; then + if ! grep -q "$_bin_dir" "$_profile" 2>/dev/null; then + printf '\nexport PATH="%s:$PATH"\n' "$_bin_dir" >> "$_profile" + printf 'Added %s to %s.\n' "$_bin_dir" "$_profile" + fi + printf '\nRestart your shell or run: export PATH="%s:$PATH" && %s\n' "$_bin_dir" "$prime_agent_cmd" + else + printf '\nAdd to your shell profile:\n' + printf ' export PATH="%s:$PATH"\n' "$_bin_dir" + printf '\nThen restart your shell and run: %s\n' "$prime_agent_cmd" + fi +} + +# ============================================================================= +# NPM Install Path (extracted from main) +# ============================================================================= + +prime_agent_npm_install() { + start_preflight_checks + + if finish_preflight_checks; then + check_status=0 + else + check_status=$? + fi + + if [ "$check_status" -ne 0 ]; then + if ! install_node_npm_interactive; then + exit "$check_status" + fi + + start_preflight_checks + if finish_preflight_checks; then + check_status=0 + else + check_status=$? + fi + + if [ "$check_status" -ne 0 ]; then + exit "$check_status" + fi + fi + + version="$(resolve_prime_agent_version "$@")" + tarball_name="$prime_agent_package-$version.tgz" + tarball_url="$prime_agent_base_url/releases/v$version/$tarball_name" + + confirm_install "$version" "$tarball_url" + confirm_kernel_runtime_setup + + download_dir=$(create_temp_dir) + prime_agent_download_dir="$download_dir" + tarball_path="$download_dir/$tarball_name" + + download_prime_agent_package "$version" "$tarball_url" "$tarball_path" + install_prime_agent_package "$tarball_path" + rm -rf "$download_dir" + prime_agent_download_dir= + + if [ "${PRIME_AGENT_NODE_INSTALLED_STANDALONE:-0}" = 1 ]; then + prime_agent_screen "Prime Agent installed" "" "Checking your shell PATH." "" + configure_standalone_node_path + elif command -v "$prime_agent_cmd" >/dev/null 2>&1; then + if [ "$prime_agent_screen_enabled" = 1 ]; then + prime_agent_screen "Prime Agent installed" "" "Run it with: $prime_agent_cmd" "" + else + printf '\nPrime Agent was installed successfully.\n' + printf '\nRun it with: %s\n' "$prime_agent_cmd" + fi + else + if [ "$prime_agent_screen_enabled" = 1 ]; then + prime_agent_screen "Prime Agent installed" "" "PATH update needed for $prime_agent_cmd." "" + prime_agent_restore_terminal + else + printf '\nPrime Agent was installed successfully.\n' + fi + cat < dist/bundle/"); diff --git a/packages/coding-agent/scripts/copy-assets.ts b/packages/coding-agent/scripts/copy-assets.ts index 40b491bee0..a322995b49 100644 --- a/packages/coding-agent/scripts/copy-assets.ts +++ b/packages/coding-agent/scripts/copy-assets.ts @@ -16,9 +16,15 @@ async function copyFiles(sourceDir: string, targetDir: string, suffix: string): } } +const excludedReleaseDirectoryNames = new Set(["node_modules", ".venv", "__pycache__", ".pytest_cache"]); + +function includeReleasePath(source: string): boolean { + return !source.split(/[\\/]/).some((part) => excludedReleaseDirectoryNames.has(part)); +} + async function replaceDirectory(source: string, target: string): Promise { await rm(target, { recursive: true, force: true }); - await cp(source, target, { recursive: true }); + await cp(source, target, { recursive: true, filter: includeReleasePath }); } async function copyFile(source: string, targetDir: string): Promise { @@ -43,6 +49,7 @@ async function copyBinaryAssets(): Promise { for (const name of ["package.json", "README.md", "CHANGELOG.md"]) { await copyFile(join(packageDir, name), distDir); } + await copyFile(join(repoDir, "install.sh"), distDir); await copyFiles(join(packageDir, "src/modes/interactive/theme"), join(distDir, "theme"), ".json"); await copyFiles(join(packageDir, "src/modes/interactive/assets"), join(distDir, "assets"), ".png"); await copyFile(join(packageDir, "src/core/export-html/template.html"), join(distDir, "export-html")); @@ -50,6 +57,7 @@ async function copyBinaryAssets(): Promise { await replaceDirectory(join(packageDir, "docs"), join(distDir, "docs")); await replaceDirectory(join(packageDir, "examples"), join(distDir, "examples")); await copyFile(join(repoDir, "node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm"), distDir); + await replaceDirectory(join(repoDir, "prime-agent-runtime"), join(distDir, "prime-agent-runtime")); await replaceDirectory(join(packageDir, "skills"), join(distDir, "skills")); } diff --git a/scripts/assemble-release-archives.mjs b/scripts/assemble-release-archives.mjs new file mode 100755 index 0000000000..3f085a15ff --- /dev/null +++ b/scripts/assemble-release-archives.mjs @@ -0,0 +1,312 @@ +#!/usr/bin/env bun +/** + * Assembles Bun-compiled platform release archives with metadata. + * + * Usage: + * bun scripts/assemble-release-archives.mjs \ + * --base-url \ + * --version x.y.z \ + * --binary-dir \ + * --sidecar-dir \ + * [--channel stable|beta] \ + * [--out-dir ] + * + * Produces /artifacts/: + * prime-agent--.tar.gz (one per platform) + * SHA256SUMS (aggregate checksums) + * (plain version pointer) + * latest.json|beta.json (manifest) + * + * Platforms: darwin-arm64, darwin-x64, linux-arm64, linux-x64 + * + * Archive layout (each .tar.gz): + * prime-agent (compiled binary, executable) + * package.json + * README.md + * CHANGELOG.md + * prime-agent-runtime/ (Python runtime, recursive) + * skills/ (skill files) + * theme/ (UI theme JSON files) + * assets/ (UI assets) + * export-html/ (HTML export templates) + * docs/ (documentation) + * examples/ (example files) + * photon_rs_bg.wasm (image-processing WASM) + + */ + +import { createHash } from "node:crypto"; +import { chmodSync, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; +import { spawnSync } from "node:child_process"; +import { isAbsolute, join, relative, resolve } from "node:path"; + +const root = resolve(import.meta.dirname, ".."); +const defaultOutDir = join(root, "packages", "coding-agent", "release"); +const releaseChannels = new Set(["stable", "beta"]); +const publicPackageName = "prime-agent"; +const binaryName = "prime-agent"; + +const PLATFORMS = ["darwin-arm64", "darwin-x64", "linux-arm64", "linux-x64"]; + +const REQUIRED_SIDECARS = [ + "package.json", + "README.md", + "CHANGELOG.md", + "install.sh", + "prime-agent-runtime", + "skills", + "theme", + "assets", + "export-html", + "docs", + "examples", + "photon_rs_bg.wasm", +]; + +function parseArgs(args) { + const parsed = { + baseUrl: undefined, + channel: "stable", + binaryDir: undefined, + sidecarDir: undefined, + outDir: defaultOutDir, + version: undefined, + platforms: [], + }; + + for (let i = 0; i < args.length; i += 1) { + const arg = args[i]; + switch (arg) { + case "--channel": { + const value = args[++i]; + if (!value || !releaseChannels.has(value)) throw new Error("--channel must be stable or beta"); + parsed.channel = value; + break; + } + case "--base-url": { + parsed.baseUrl = args[++i]; + if (!parsed.baseUrl) throw new Error("--base-url requires a value"); + break; + } + case "--version": { + parsed.version = args[++i]; + if (!parsed.version) throw new Error("--version requires a value"); + break; + } + case "--binary-dir": { + parsed.binaryDir = resolve(root, args[++i]); + break; + } + case "--sidecar-dir": { + parsed.sidecarDir = resolve(root, args[++i]); + break; + } + case "--out-dir": { + parsed.outDir = resolve(root, args[++i]); + break; + } + case "--platform": { + const platform = args[++i]; + if (!PLATFORMS.includes(platform)) throw new Error(`Unsupported platform: ${platform}`); + parsed.platforms.push(platform); + break; + } + case "--help": + case "-h": + printHelp(); + process.exit(0); + default: + throw new Error(`Unknown argument: ${arg}`); + } + } + + if (!parsed.baseUrl) throw new Error("--base-url is required"); + if (!parsed.version) throw new Error("--version is required"); + if (!parsed.binaryDir) throw new Error("--binary-dir is required"); + if (!parsed.sidecarDir) throw new Error("--sidecar-dir is required"); + + if (!existsSync(parsed.binaryDir)) throw new Error(`Binary dir not found: ${parsed.binaryDir}`); + if (!existsSync(parsed.sidecarDir)) throw new Error(`Sidecar dir not found: ${parsed.sidecarDir}`); + + parsed.version = normalizeVersion(parsed.version); + if (parsed.platforms.length === 0) parsed.platforms = [...PLATFORMS]; + parsed.baseUrl = parsed.baseUrl.replace(/\/+$/, ""); + return parsed; +} + +function printHelp() { + console.log(`Usage: bun scripts/assemble-release-archives.mjs --base-url --binary-dir --sidecar-dir --version x.y.z [--channel stable|beta] [--platform ] [--out-dir ] + +Assembles platform-specific release archives from a Bun-compiled binary and sidecar files. + +Output: + /artifacts/prime-agent--.tar.gz + /artifacts/SHA256SUMS + /artifacts/ + /artifacts/latest.json (stable) or beta.json (beta) +`); +} + +function normalizeVersion(version) { + const normalized = version.startsWith("v") ? version.slice(1) : version; + if (!/^[0-9A-Za-z.-]+$/.test(normalized)) throw new Error(`Invalid release version: ${version}`); + return normalized; +} + +function assertSafeOutputDir(outDir) { + const base = resolve(defaultOutDir); + const pathFromBase = relative(base, resolve(outDir)); + if (pathFromBase === "" || (!pathFromBase.startsWith("..") && !isAbsolute(pathFromBase))) return; + throw new Error(`Refusing to write output outside ${base}: ${outDir}`); +} + +function sha256File(path) { + const hash = createHash("sha256"); + hash.update(readFileSync(path)); + return hash.digest("hex"); +} + +function createArchive(sourceDir, archivePath) { + const result = spawnSync("tar", ["-czf", archivePath, "-C", sourceDir, "."], { + stdio: "pipe", + encoding: "utf8", + }); + if (result.status !== 0) throw new Error(`tar failed: ${result.stderr || result.stdout}`); +} + +function validateSidecars(sidecarDir) { + const missing = []; + for (const name of REQUIRED_SIDECARS) { + if (!existsSync(join(sidecarDir, name))) { + missing.push(name); + } + } + return missing; +} + +const FORBIDDEN_RELEASE_DIRECTORIES = new Set(["node_modules", ".venv", "__pycache__", ".pytest_cache"]); + +function findForbiddenReleaseDirectory(root, relativePath = "") { + for (const entry of readdirSync(join(root, relativePath), { withFileTypes: true })) { + const child = join(relativePath, entry.name); + if (FORBIDDEN_RELEASE_DIRECTORIES.has(entry.name)) return child; + if (entry.isDirectory()) { + const found = findForbiddenReleaseDirectory(root, child); + if (found) return found; + } + } + return undefined; +} + +function renderPackageManifest(path, version) { + const manifest = JSON.parse(readFileSync(path, "utf8")); + manifest.name = publicPackageName; + manifest.version = version; + manifest.bin = { [binaryName]: `./${binaryName}` }; + manifest.packageManager = "bun@1.3.14"; + writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\n`); +} + +function renderInstaller(path, baseUrl, channel) { + const rendered = readFileSync(path, "utf8") + .replaceAll("__PRIME_AGENT_DOWNLOAD_BASE_URL__", baseUrl) + .replaceAll("__PRIME_AGENT_DEFAULT_RELEASE_CHANNEL__", channel); + if (rendered.includes("__PRIME_AGENT_DOWNLOAD_BASE_URL__") || rendered.includes("__PRIME_AGENT_DEFAULT_RELEASE_CHANNEL__")) { + throw new Error("Release installer still contains an unresolved configuration marker"); + } + writeFileSync(path, rendered); + chmodSync(path, 0o755); +} + +function main() { + const args = parseArgs(process.argv.slice(2)); + const outDir = resolve(args.outDir); + assertSafeOutputDir(outDir); + rmSync(outDir, { force: true, recursive: true }); + + const versionDir = join(outDir, "artifacts"); + mkdirSync(versionDir, { recursive: true }); + + const missing = validateSidecars(args.sidecarDir); + if (missing.length > 0) { + throw new Error( + `Missing required sidecars in ${args.sidecarDir}: ${missing.join(", ")}. ` + + `Run "bun run copy-binary-assets" first.`, + ); + } + const forbiddenDirectory = findForbiddenReleaseDirectory(args.sidecarDir); + if (forbiddenDirectory) { + throw new Error(`Release sidecars contain a forbidden dependency or cache directory: ${forbiddenDirectory}`); + } + + const archives = []; + + for (const platform of args.platforms) { + const binarySource = join(args.binaryDir, platform, "pi"); + if (!existsSync(binarySource)) { + throw new Error(`Binary not found for platform ${platform}: ${binarySource}`); + } + + const stagingDir = join(outDir, "staging", platform); + mkdirSync(stagingDir, { recursive: true }); + + // Copy binary to archive root as "prime-agent" + const dstBinary = join(stagingDir, binaryName); + cpSync(binarySource, dstBinary); + chmodSync(dstBinary, 0o755); + + // Copy all sidecars to archive root + for (const name of REQUIRED_SIDECARS) { + const src = join(args.sidecarDir, name); + cpSync(src, join(stagingDir, name), { recursive: true, dereference: true }); + } + renderPackageManifest(join(stagingDir, "package.json"), args.version); + renderInstaller(join(stagingDir, "install.sh"), args.baseUrl, args.channel); + + const archiveName = `prime-agent-${args.version}-${platform}.tar.gz`; + const archivePath = join(versionDir, archiveName); + createArchive(stagingDir, archivePath); + + const sha256 = sha256File(archivePath); + archives.push({ platform, file: archiveName, sha256 }); + console.log(`Created ${archivePath}`); + + rmSync(join(outDir, "staging"), { force: true, recursive: true }); + } + + if (archives.length === 0) throw new Error("No platform archives created"); + + archives.sort((a, b) => a.file.localeCompare(b.file)); + const sumsContent = archives.map((a) => `${a.sha256} ${a.file}`).join("\n") + "\n"; + writeFileSync(join(versionDir, "SHA256SUMS"), sumsContent); + writeFileSync(join(versionDir, args.channel), `v${args.version}\n`); + + const manifestName = args.channel === "stable" ? "latest.json" : "beta.json"; + writeFileSync( + join(versionDir, manifestName), + JSON.stringify( + { + version: `v${args.version}`, + package: publicPackageName, + platforms: archives.map((a) => ({ + platform: a.platform, + file: a.file, + sha256: a.sha256, + })), + baseUrl: `${args.baseUrl}/releases/v${args.version}`, + }, + null, + 2, + ) + "\n", + ); + + console.log(`\nSHA256SUMS -> ${join(versionDir, "SHA256SUMS")}`); + console.log(`${manifestName} -> ${join(versionDir, manifestName)}`); +} + +try { + main(); +} catch (error) { + console.error(error instanceof Error ? error.message : String(error)); + process.exit(1); +} diff --git a/scripts/build-binaries.sh b/scripts/build-binaries.sh index cbc029f81f..b41cf1e3cc 100755 --- a/scripts/build-binaries.sh +++ b/scripts/build-binaries.sh @@ -1,176 +1,123 @@ #!/usr/bin/env bash # -# Build pi binaries for all platforms locally. -# Mirrors .github/workflows/build-binaries.yml +# Build pi binaries for supported platforms locally. +# Mirrors the Bun-compiled release lane in .github/workflows/build-binaries.yml. # # Usage: # ./scripts/build-binaries.sh [--skip-deps] [--platform ] # # Options: -# --skip-deps Skip installing cross-platform dependencies -# --platform Build only for specified platform (darwin-arm64, darwin-x64, linux-x64, linux-arm64, windows-x64) +# --skip-deps Skip frozen dependency install and package build +# --platform Build only for specified platform +# (darwin-arm64, darwin-x64, linux-x64, linux-arm64) # # Output: # packages/coding-agent/binaries/ -# pi-darwin-arm64.tar.gz -# pi-darwin-x64.tar.gz -# pi-linux-x64.tar.gz -# pi-linux-arm64.tar.gz -# pi-windows-x64.zip +# /pi +# +# packages/coding-agent/release/artifacts/ +# prime-agent--.tar.gz +# SHA256SUMS +# stable +# latest.json set -euo pipefail cd "$(dirname "$0")/.." +# Require Bun 1.3.14 +EXPECTED_BUN_VERSION="1.3.14" +ACTUAL_BUN_VERSION=$(bun --version 2>/dev/null || echo "not-found") +if [ "$ACTUAL_BUN_VERSION" != "$EXPECTED_BUN_VERSION" ]; then + echo "ERROR: Expected Bun ${EXPECTED_BUN_VERSION}, got ${ACTUAL_BUN_VERSION}" + echo "Install Bun ${EXPECTED_BUN_VERSION}:" + echo " curl -fsSL https://bun.sh/install | bash -s -- bun-v${EXPECTED_BUN_VERSION}" + exit 1 +fi + SKIP_DEPS=false PLATFORM="" while [[ $# -gt 0 ]]; do - case $1 in - --skip-deps) - SKIP_DEPS=true - shift - ;; - --platform) - PLATFORM="$2" - shift 2 - ;; - *) - echo "Unknown option: $1" - exit 1 - ;; - esac + case $1 in + --skip-deps) + SKIP_DEPS=true + shift + ;; + --platform) + PLATFORM="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac done # Validate platform if specified if [[ -n "$PLATFORM" ]]; then - case "$PLATFORM" in - darwin-arm64|darwin-x64|linux-x64|linux-arm64|windows-x64) - ;; - *) - echo "Invalid platform: $PLATFORM" - echo "Valid platforms: darwin-arm64, darwin-x64, linux-x64, linux-arm64, windows-x64" - exit 1 - ;; - esac + case "$PLATFORM" in + darwin-arm64|darwin-x64|linux-x64|linux-arm64) ;; + *) + echo "Invalid platform: $PLATFORM" + echo "Valid platforms: darwin-arm64, darwin-x64, linux-x64, linux-arm64" + exit 1 + ;; + esac fi -echo "==> Installing dependencies..." -npm ci - if [[ "$SKIP_DEPS" == "false" ]]; then - echo "==> Installing cross-platform native bindings..." - # npm ci only installs optional deps for the current platform - # We need all platform bindings for bun cross-compilation - # Use --force to bypass platform checks (os/cpu restrictions in package.json) - # Install all in one command to avoid npm removing packages from previous installs - npm install --no-save --force \ - @mariozechner/clipboard-darwin-arm64@0.3.0 \ - @mariozechner/clipboard-darwin-x64@0.3.0 \ - @mariozechner/clipboard-linux-x64-gnu@0.3.0 \ - @mariozechner/clipboard-linux-arm64-gnu@0.3.0 \ - @mariozechner/clipboard-win32-x64-msvc@0.3.0 \ - @img/sharp-darwin-arm64@0.34.5 \ - @img/sharp-darwin-x64@0.34.5 \ - @img/sharp-linux-x64@0.34.5 \ - @img/sharp-linux-arm64@0.34.5 \ - @img/sharp-win32-x64@0.34.5 \ - @img/sharp-libvips-darwin-arm64@1.2.4 \ - @img/sharp-libvips-darwin-x64@1.2.4 \ - @img/sharp-libvips-linux-x64@1.2.4 \ - @img/sharp-libvips-linux-arm64@1.2.4 -else - echo "==> Skipping cross-platform native bindings (--skip-deps)" -fi + echo "==> Installing dependencies for all release platforms (frozen lockfile)..." + bun install --frozen-lockfile --os=* --cpu=* -echo "==> Building all packages..." -npm run build + echo "==> Building all packages..." + bun run build +fi -echo "==> Building binaries..." +echo "==> Compiling binaries..." cd packages/coding-agent # Clean previous builds rm -rf binaries -mkdir -p binaries/{darwin-arm64,darwin-x64,linux-x64,linux-arm64,windows-x64} +mkdir -p binaries # Determine which platforms to build if [[ -n "$PLATFORM" ]]; then - PLATFORMS=("$PLATFORM") + PLATFORMS=("$PLATFORM") else - PLATFORMS=(darwin-arm64 darwin-x64 linux-x64 linux-arm64 windows-x64) + PLATFORMS=(darwin-arm64 darwin-x64 linux-x64 linux-arm64) fi for platform in "${PLATFORMS[@]}"; do - echo "Building for $platform..." - # Externalize koffi to avoid embedding all 18 platform .node files (~74MB) - # into every binary. Koffi is only used on Windows for VT input and the - # call site has a try/catch fallback. For Windows builds, we copy the - # appropriate .node file alongside the binary below. - if [[ "$platform" == "windows-x64" ]]; then - bun build --compile --external koffi --target=bun-$platform ./dist/bun/cli.js --outfile binaries/$platform/pi.exe - else - bun build --compile --external koffi --target=bun-$platform ./dist/bun/cli.js --outfile binaries/$platform/pi - fi + echo "Building for $platform..." + mkdir -p "binaries/$platform" + bun build --compile --external koffi --target="bun-$platform" ./dist/bun/cli.js --outfile "binaries/$platform/pi" done -echo "==> Creating release archives..." - -# Copy shared files to each platform directory -for platform in "${PLATFORMS[@]}"; do - cp package.json binaries/$platform/ - cp README.md binaries/$platform/ - cp CHANGELOG.md binaries/$platform/ - cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm binaries/$platform/ - mkdir -p binaries/$platform/theme - cp dist/modes/interactive/theme/*.json binaries/$platform/theme/ - mkdir -p binaries/$platform/assets - cp dist/modes/interactive/assets/* binaries/$platform/assets/ - cp -r dist/core/export-html binaries/$platform/ - cp -r docs binaries/$platform/ - cp -r examples binaries/$platform/ - cp -r skills binaries/$platform/ - - # Copy koffi native module for Windows (needed for VT input support) - if [[ "$platform" == "windows-x64" ]]; then - mkdir -p binaries/$platform/node_modules/koffi/build/koffi/win32_x64 - cp ../../node_modules/koffi/index.js binaries/$platform/node_modules/koffi/ - cp ../../node_modules/koffi/package.json binaries/$platform/node_modules/koffi/ - cp ../../node_modules/koffi/build/koffi/win32_x64/koffi.node binaries/$platform/node_modules/koffi/build/koffi/win32_x64/ - fi -done +echo "==> Copying sidecar assets..." +bun run copy-binary-assets -# Create archives -cd binaries - -for platform in "${PLATFORMS[@]}"; do - if [[ "$platform" == "windows-x64" ]]; then - # Windows (zip) - echo "Creating pi-$platform.zip..." - (cd $platform && zip -r ../pi-$platform.zip .) - else - # Unix platforms (tar.gz) - use wrapper directory for mise compatibility - echo "Creating pi-$platform.tar.gz..." - mv $platform pi && tar -czf pi-$platform.tar.gz pi && mv pi $platform - fi -done - -# Extract archives for easy local testing -echo "==> Extracting archives for testing..." -for platform in "${PLATFORMS[@]}"; do - rm -rf $platform - if [[ "$platform" == "windows-x64" ]]; then - mkdir -p $platform && (cd $platform && unzip -q ../pi-$platform.zip) - else - tar -xzf pi-$platform.tar.gz && mv pi $platform - fi -done +echo "==> Assembling release archives..." +VERSION=$(bun -e "console.log(require('./package.json').version)") +BASE_URL="${PRIME_AGENT_DOWNLOAD_BASE_URL:-https://releases.pi.ai}" +PACK_PLATFORM_ARGS=() +if [[ -n "$PLATFORM" ]]; then + PACK_PLATFORM_ARGS=(--platform "$PLATFORM") +fi +bun ../../scripts/pack-prime-agent-release.mjs \ + --channel stable \ + --version "$VERSION" \ + --base-url "$BASE_URL" \ + --binary-base-dir "$(pwd)/binaries" \ + --sidecar-dir "$(pwd)/dist" \ + --out-dir "$(pwd)/release" \ + "${PACK_PLATFORM_ARGS[@]}" echo "" echo "==> Build complete!" -echo "Archives available in packages/coding-agent/binaries/" -ls -lh *.tar.gz *.zip 2>/dev/null || true +echo "Platform archives:" +ls -lh "release/artifacts/"*.tar.gz 2>/dev/null || true echo "" -echo "Extracted directories for testing:" -for platform in "${PLATFORMS[@]}"; do - echo " binaries/$platform/pi" -done +echo "Metadata:" +ls -lh "release/artifacts/SHA256SUMS" "release/artifacts/latest.json" "release/artifacts/stable" 2>/dev/null || true diff --git a/scripts/check-browser-smoke.mjs b/scripts/check-browser-smoke.mjs index d590988d62..fe24ff3da5 100644 --- a/scripts/check-browser-smoke.mjs +++ b/scripts/check-browser-smoke.mjs @@ -1,36 +1,26 @@ import { writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { build } from "esbuild"; -const outputPath = join(tmpdir(), "pi-browser-smoke.js"); -const errorLogPath = join(tmpdir(), "pi-browser-smoke-errors.log"); +const outputPath = join(tmpdir(), "prime-agent-browser-smoke.js"); +const errorLogPath = join(tmpdir(), "prime-agent-browser-smoke-errors.log"); try { - await build({ - entryPoints: ["scripts/browser-smoke-entry.ts"], - bundle: true, - platform: "browser", + const result = await Bun.build({ + entrypoints: ["scripts/browser-smoke-entry.ts"], + target: "browser", format: "esm", - logLevel: "silent", - outfile: outputPath, + sourcemap: "none", + write: false, + throw: false, }); - process.exit(0); -} catch (error) { - let detailedErrors = ""; - if (error && typeof error === "object" && "errors" in error && Array.isArray(error.errors)) { - detailedErrors = error.errors - .map((entry) => { - const location = entry.location - ? `${entry.location.file}:${entry.location.line}:${entry.location.column}` - : ""; - return [location, entry.text].filter(Boolean).join(" "); - }) - .join("\n"); + if (!result.success || result.outputs.length !== 1) { + throw new Error(result.logs.map((entry) => entry.message).join("\n") || "Bun browser bundle produced no output"); } - - const baseError = error instanceof Error ? (error.stack ?? error.message) : String(error); - writeFileSync(errorLogPath, [detailedErrors, baseError].filter(Boolean).join("\n\n"), "utf-8"); + await Bun.write(outputPath, result.outputs[0]); +} catch (error) { + const message = error instanceof Error ? (error.stack ?? error.message) : String(error); + writeFileSync(errorLogPath, message, "utf-8"); console.error(`Browser smoke check failed. See ${errorLogPath}`); process.exit(1); } diff --git a/scripts/compiled-artifact-smoke.ts b/scripts/compiled-artifact-smoke.ts new file mode 100644 index 0000000000..c1055f49a3 --- /dev/null +++ b/scripts/compiled-artifact-smoke.ts @@ -0,0 +1,161 @@ +#!/usr/bin/env bun + +import { spawnSync } from "node:child_process"; +import { chmodSync, copyFileSync, cpSync, existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, statSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { basename, dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const defaultBinary = join(rootDir, "packages", "coding-agent", "dist", "pi"); +const defaultDist = dirname(defaultBinary); + +export const REQUIRED_BINARY_SIDECARS = [ + "package.json", + "README.md", + "CHANGELOG.md", + "install.sh", + "prime-agent-runtime", + "skills", + "theme", + "assets", + "export-html", + "docs", + "examples", + "photon_rs_bg.wasm", +] as const; + +type RunResult = { + args: string[]; + exitCode: number; + stdout: string; + stderr: string; +}; + +function run(executable: string, args: string[], cwd: string, path: string): RunResult { + const result = spawnSync(executable, args, { + cwd, + env: { ...process.env, PATH: path }, + encoding: "utf8", + }); + return { + args, + exitCode: result.status ?? 1, + stdout: result.stdout ?? "", + stderr: result.stderr ?? result.error?.message ?? "", + }; +} + +export function inspectNativeExecutable(path: string): "elf" | "mach-o" | "unknown" { + const header = readFileSync(path).subarray(0, 4).toString("hex"); + if (header === "7f454c46") return "elf"; + if ([ + "feedface", "cefaedfe", "feedfacf", "cffaedfe", + "cafebabe", "bebafeca", "cafebabf", "bfbafeca", + ].includes(header)) return "mach-o"; + return "unknown"; +} + +export function runEmptyDiagnostic(binaryPath = defaultBinary) { + if (!existsSync(binaryPath)) throw new Error(`Compiled binary not found: ${binaryPath}`); + const tempDir = mkdtempSync(join(tmpdir(), "prime-agent-binary-empty-")); + try { + const binary = join(tempDir, basename(binaryPath)); + copyFileSync(binaryPath, binary); + chmodSync(binary, 0o755); + const emptyPath = join(tempDir, "empty-path"); + mkdirSync(emptyPath); + const runResult = run(binary, ["--version"], tempDir, emptyPath); + return { + mode: "binary-only-diagnostic" as const, + nativeFormat: inspectNativeExecutable(binary), + run: runResult, + detectedMissingPackageJson: runResult.exitCode !== 0 && runResult.stderr.includes("package.json"), + }; + } finally { + rmSync(tempDir, { recursive: true, force: true }); + } +} + +export function runPackagedSmoke(binaryPath = defaultBinary, sourceDist = defaultDist) { + if (!existsSync(binaryPath)) throw new Error(`Compiled binary not found: ${binaryPath}`); + const missing = REQUIRED_BINARY_SIDECARS.filter((name) => !existsSync(join(sourceDist, name))); + if (missing.length > 0) throw new Error(`Missing compiled-binary sidecars: ${missing.join(", ")}`); + + const tempDir = mkdtempSync(join(tmpdir(), "prime-agent-binary-package-")); + try { + const binary = join(tempDir, basename(binaryPath)); + copyFileSync(binaryPath, binary); + chmodSync(binary, 0o755); + for (const name of REQUIRED_BINARY_SIDECARS) { + cpSync(join(sourceDist, name), join(tempDir, name), { recursive: true, dereference: true }); + } + + const emptyPath = join(tempDir, "empty-path"); + mkdirSync(emptyPath); + let nodeAvailable = false; + let npmAvailable = false; + try { nodeAvailable = run("node", ["--version"], tempDir, emptyPath).exitCode === 0; } catch {} + try { npmAvailable = run("npm", ["--version"], tempDir, emptyPath).exitCode === 0; } catch {} + const runs = [["--version"], ["--help"]].map((args) => run(binary, args, tempDir, emptyPath)); + const passed = + inspectNativeExecutable(binary) !== "unknown" && + !nodeAvailable && + !npmAvailable && + runs.every((result) => result.exitCode === 0 && result.stdout.trim().length > 0); + return { + mode: "packaged-layout-smoke" as const, + nativeFormat: inspectNativeExecutable(binary), + binarySizeBytes: statSync(binary).size, + path: emptyPath, + nodeAvailable, + npmAvailable, + sidecars: [...REQUIRED_BINARY_SIDECARS], + runs, + passed, + }; + } finally { + rmSync(tempDir, { recursive: true, force: true }); + } +} + +function argumentValue(name: string): string | undefined { + const index = process.argv.indexOf(name); + return index >= 0 ? process.argv[index + 1] : undefined; +} + +if (import.meta.main) { + const binary = resolve(argumentValue("--binary") ?? defaultBinary); + const sourceDist = resolve(argumentValue("--dist") ?? dirname(binary)); + try { + const empty = runEmptyDiagnostic(binary); + const packaged = runPackagedSmoke(binary, sourceDist); + console.log(JSON.stringify({ + empty: { + mode: empty.mode, + nativeFormat: empty.nativeFormat, + exitCode: empty.run.exitCode, + detectedMissingPackageJson: empty.detectedMissingPackageJson, + }, + packaged: { + mode: packaged.mode, + nativeFormat: packaged.nativeFormat, + binarySizeBytes: packaged.binarySizeBytes, + nodeAvailable: packaged.nodeAvailable, + npmAvailable: packaged.npmAvailable, + sidecars: packaged.sidecars, + runs: packaged.runs.map((result) => ({ + args: result.args, + exitCode: result.exitCode, + stdoutLength: result.stdout.length, + stderrLength: result.stderr.length, + })), + passed: packaged.passed, + }, + }, null, 2)); + if (empty.nativeFormat === "unknown" || !empty.detectedMissingPackageJson || !packaged.passed) process.exit(1); + } catch (error) { + console.error(error instanceof Error ? error.message : String(error)); + process.exit(1); + } +} diff --git a/scripts/pack-prime-agent-release.mjs b/scripts/pack-prime-agent-release.mjs old mode 100644 new mode 100755 index d264025e11..220105a68a --- a/scripts/pack-prime-agent-release.mjs +++ b/scripts/pack-prime-agent-release.mjs @@ -1,348 +1,166 @@ -#!/usr/bin/env node - -import { spawnSync } from "node:child_process"; -import { createHash } from "node:crypto"; -import { - cpSync, - existsSync, - mkdirSync, - renameSync, - readFileSync, - rmSync, - statSync, - writeFileSync, -} from "node:fs"; -import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; - -const root = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +#!/usr/bin/env bun +/** + * Produce Bun-compiled platform release archives. + * + * This script is the CI entry point for the release artifact lane. It expects + * pre-built Bun-compiled binaries for 4 platforms (darwin-arm64, darwin-x64, + * linux-arm64, linux-x64) and sidecar files, then produces platform-specific + * .tar.gz archives with checksums and channel metadata. + * + * No npm or Node.js is used during artifact assembly. + * + * Usage: + * bun scripts/pack-prime-agent-release.mjs \ + * --base-url \ + * [--channel stable|beta] \ + * [--version x.y.z] \ + * [--out-dir ] \ + * [--binary-base-dir ] \ + * [--sidecar-dir ] + * + * Output: + * /artifacts/ + * prime-agent--.tar.gz + * SHA256SUMS + * + * latest.json|beta.json + */ + +import { existsSync, readFileSync } from "node:fs"; +import { resolve, join } from "node:path"; + +const root = resolve(import.meta.dirname, ".."); const defaultOutputDir = join(root, "packages", "coding-agent", "release"); const defaultBaseUrl = process.env.PRIME_AGENT_DOWNLOAD_BASE_URL; -const publicPackageName = process.env.PRIME_AGENT_PACKAGE_NAME || "prime-agent"; -const publicCommandName = process.env.PRIME_AGENT_CMD || "prime-agent"; const releaseChannels = new Set(["stable", "beta"]); -const releasePackages = [ - { packageDir: "ai", publicName: undefined, artifactName: "prime-agent-ai" }, - { packageDir: "tui", publicName: undefined, artifactName: "prime-agent-tui" }, - { packageDir: "agent", publicName: undefined, artifactName: "prime-agent-core" }, - { packageDir: "coding-agent", publicName: publicPackageName, artifactName: publicPackageName }, -]; - function parseArgs(args) { const parsed = { baseUrl: defaultBaseUrl, channel: "stable", + binaryBaseDir: join(root, "packages", "coding-agent", "binaries"), + sidecarDir: join(root, "packages", "coding-agent", "dist"), outDir: defaultOutputDir, version: undefined, + platforms: [], }; for (let i = 0; i < args.length; i += 1) { const arg = args[i]; switch (arg) { case "--channel": { - const value = args[i + 1]; - if (!value || !releaseChannels.has(value)) { - throw new Error("--channel must be stable or beta"); - } + const value = args[++i]; + if (!value || !releaseChannels.has(value)) throw new Error("--channel must be stable or beta"); parsed.channel = value; - i += 1; break; } case "--base-url": { - const value = args[i + 1]; + const value = args[++i]; if (!value) throw new Error("--base-url requires a value"); parsed.baseUrl = value; - i += 1; + break; + } + case "--version": { + const value = args[++i]; + if (!value) throw new Error("--version requires a value"); + parsed.version = value; break; } case "--out-dir": { - const value = args[i + 1]; + const value = args[++i]; if (!value) throw new Error("--out-dir requires a value"); parsed.outDir = resolve(root, value); - i += 1; break; } - case "--version": { - const value = args[i + 1]; - if (!value) throw new Error("--version requires a value"); - parsed.version = normalizeVersion(value); - i += 1; + case "--binary-base-dir": { + const value = args[++i]; + if (!value) throw new Error("--binary-base-dir requires a value"); + parsed.binaryBaseDir = resolve(root, value); + break; + } + case "--sidecar-dir": { + const value = args[++i]; + if (!value) throw new Error("--sidecar-dir requires a value"); + parsed.sidecarDir = resolve(root, value); + break; + } + case "--platform": { + const value = args[++i]; + if (!value) throw new Error("--platform requires a value"); + parsed.platforms.push(value); break; } case "--help": case "-h": printHelp(); process.exit(0); - break; default: throw new Error(`Unknown argument: ${arg}`); } } - if (!parsed.baseUrl) { - throw new Error("--base-url or PRIME_AGENT_DOWNLOAD_BASE_URL is required"); + if (!parsed.baseUrl) throw new Error("--base-url or PRIME_AGENT_DOWNLOAD_BASE_URL is required"); + parsed.baseUrl = parsed.baseUrl.replace(/\/+$/, ""); + + // Resolve version from coding-agent package.json if not provided. + if (!parsed.version) { + const cliPkg = JSON.parse(readFileSync(join(root, "packages", "coding-agent", "package.json"), "utf8")); + parsed.version = cliPkg.version; } - parsed.baseUrl = parsed.baseUrl.replace(/\/+$/, ""); return parsed; } function printHelp() { - console.log(`Usage: node scripts/pack-prime-agent-release.mjs --base-url url [--channel stable|beta] [--version x.y.z] [--out-dir path] + console.log(`Usage: bun scripts/pack-prime-agent-release.mjs --base-url url [--channel stable|beta] [--version x.y.z] [--out-dir path] [--binary-base-dir path] [--sidecar-dir path] [--platform platform] -Creates private npm tarballs for R2 distribution: +Creates platform release archives: - /artifacts/prime-agent-.tgz - /artifacts/prime-agent-ai-.tgz - /artifacts/prime-agent-core-.tgz - /artifacts/prime-agent-tui-.tgz + /artifacts/prime-agent--.tar.gz /artifacts/SHA256SUMS /artifacts/ /artifacts/latest.json (stable) or beta.json (beta) -`); -} - -function normalizeVersion(version) { - const normalized = version.startsWith("v") ? version.slice(1) : version; - if (!/^[0-9A-Za-z.-]+$/.test(normalized)) { - throw new Error(`Invalid release version: ${version}`); - } - return normalized; -} - -function readJson(path) { - return JSON.parse(readFileSync(path, "utf8")); -} - -function writeJson(path, value) { - writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`); -} - -function packagePath(packageDir) { - return join(root, "packages", packageDir); -} - -function assertSafeOutputDir(outDir) { - const relativeToReleaseRoot = relative(defaultOutputDir, outDir); - if (relativeToReleaseRoot === "" || (!relativeToReleaseRoot.startsWith("..") && !isAbsolute(relativeToReleaseRoot))) { - return; - } - throw new Error(`Refusing to remove output directory outside ${defaultOutputDir}: ${outDir}`); -} - -function packageJsonPath(packageDir) { - return join(packagePath(packageDir), "package.json"); -} - -function requireBuiltPackage(packageDir) { - const dist = join(packagePath(packageDir), "dist"); - if (!existsSync(dist)) { - throw new Error(`Missing ${dist}. Run npm run build before packing a release.`); - } -} - -function copyIfExists(source, target) { - if (existsSync(source)) { - cpSync(source, target, { recursive: true }); - } -} - -function npmTarballName(packageName, version) { - return `${packageName.replace(/^@/, "").replace("/", "-")}-${version}.tgz`; -} -function releaseTarballUrl(baseUrl, version, tarballFile) { - return `${baseUrl}/releases/v${version}/${tarballFile}`; -} - -function rewriteInternalDependencies(dependencies, internalPackageUrls) { - if (!dependencies) return undefined; - const rewritten = {}; - for (const [name, range] of Object.entries(dependencies)) { - rewritten[name] = internalPackageUrls.get(name) || range; - } - return rewritten; -} - -function releaseScripts(sourceScripts) { - if (!sourceScripts?.postinstall) return undefined; - return { - postinstall: sourceScripts.postinstall, - }; -} - -function createReleasePackageJson(sourcePackage, packageName, releaseVersion, internalPackageUrls) { - const packageJson = { - ...sourcePackage, - name: packageName, - version: releaseVersion, - dependencies: rewriteInternalDependencies(sourcePackage.dependencies, internalPackageUrls), - optionalDependencies: rewriteInternalDependencies(sourcePackage.optionalDependencies, internalPackageUrls), - scripts: releaseScripts(sourcePackage.scripts), - }; - - delete packageJson.devDependencies; - delete packageJson.overrides; - delete packageJson.private; - - if (packageName === publicPackageName) { - packageJson.bin = { - [publicCommandName]: "dist/bundle/cli.js", - }; - packageJson.piConfig = { - ...(packageJson.piConfig || {}), - name: publicCommandName, - configDir: ".prime/agent", - }; - } - - return packageJson; -} - -function copyPackageContents(sourceDir, targetDir, packageJson) { - mkdirSync(targetDir, { recursive: true }); - writeJson(join(targetDir, "package.json"), packageJson); - - for (const entry of ["dist", "docs", "examples", "skills", "postinstall.cjs", "README.md", "CHANGELOG.md"]) { - copyIfExists(join(sourceDir, entry), join(targetDir, entry)); - } -} - -function run(command, args, cwd) { - const result = spawnSync(command, args, { - cwd, - stdio: "pipe", - encoding: "utf8", - }); - - if (result.status !== 0) { - if (result.stdout) process.stdout.write(result.stdout); - if (result.stderr) process.stderr.write(result.stderr); - throw new Error(`${command} ${args.join(" ")} failed with exit code ${result.status}`); - } - - if (result.stderr) process.stderr.write(result.stderr); - return result.stdout.trim(); -} - -function sha256File(path) { - const hash = createHash("sha256"); - hash.update(readFileSync(path)); - return hash.digest("hex"); +--binary-base-dir defaults to packages/coding-agent/binaries/ +--sidecar-dir defaults to packages/coding-agent/dist/ +`); } -function main() { +async function main() { const args = parseArgs(process.argv.slice(2)); - const sourcePackages = new Map( - releasePackages.map((releasePackage) => [ - releasePackage.packageDir, - readJson(packageJsonPath(releasePackage.packageDir)), - ]), - ); - const cliPackage = sourcePackages.get("coding-agent"); - const releaseVersion = args.version || normalizeVersion(process.env.PRIME_AGENT_VERSION || cliPackage.version); - for (const releasePackage of releasePackages) { - requireBuiltPackage(releasePackage.packageDir); - } - - // Dependency keys stay on the source package names so existing compiled imports - // keep resolving, while release package names and artifact filenames are branded. - const sourcePackageNames = new Map(); - const packageNames = new Map(); - const artifactFiles = new Map(); - for (const releasePackage of releasePackages) { - const sourcePackage = sourcePackages.get(releasePackage.packageDir); - const packageName = releasePackage.publicName || releasePackage.artifactName || sourcePackage.name; - sourcePackageNames.set(releasePackage.packageDir, sourcePackage.name); - packageNames.set(releasePackage.packageDir, packageName); - artifactFiles.set( - releasePackage.packageDir, - npmTarballName(releasePackage.artifactName || packageName, releaseVersion), + if (!existsSync(args.sidecarDir)) { + throw new Error( + `Sidecar dir not found: ${args.sidecarDir}. Run "bun run build && bun run copy-binary-assets" first.`, ); } - const internalPackageUrls = new Map(); - for (const releasePackage of releasePackages) { - if (releasePackage.packageDir === "coding-agent") continue; - const sourcePackageName = sourcePackageNames.get(releasePackage.packageDir); - const artifactFile = artifactFiles.get(releasePackage.packageDir); - internalPackageUrls.set(sourcePackageName, releaseTarballUrl(args.baseUrl, releaseVersion, artifactFile)); - } - - const stagingRoot = join(args.outDir, "packages"); - const artifactsDir = join(args.outDir, "artifacts"); - assertSafeOutputDir(args.outDir); - rmSync(args.outDir, { force: true, recursive: true }); - mkdirSync(stagingRoot, { recursive: true }); - mkdirSync(artifactsDir, { recursive: true }); - - const tarballs = []; - for (const releasePackage of releasePackages) { - const sourcePackage = sourcePackages.get(releasePackage.packageDir); - const packageName = packageNames.get(releasePackage.packageDir); - const stagingDir = join(stagingRoot, releasePackage.packageDir); - const packageJson = createReleasePackageJson( - sourcePackage, - packageName, - releaseVersion, - internalPackageUrls, - ); - - copyPackageContents(packagePath(releasePackage.packageDir), stagingDir, packageJson); - - const tarballName = run("npm", ["pack", stagingDir, "--pack-destination", artifactsDir, "--silent"], root) - .split("\n") - .at(-1); - if (!tarballName) { - throw new Error(`npm pack did not report a tarball name for ${packageName}`); - } - - const tarballPath = join(artifactsDir, basename(tarballName)); - if (!existsSync(tarballPath) || !statSync(tarballPath).isFile()) { - throw new Error(`npm pack did not create ${tarballPath}`); - } - - const artifactFile = artifactFiles.get(releasePackage.packageDir); - const artifactPath = join(artifactsDir, artifactFile); - if (tarballPath !== artifactPath) { - rmSync(artifactPath, { force: true }); - renameSync(tarballPath, artifactPath); - } - - tarballs.push({ - name: packageName, - file: artifactFile, - sha256: sha256File(artifactPath), - }); + // The assembly script is in the same scripts directory. + const assemblyScript = join(import.meta.dirname, "assemble-release-archives.mjs"); + if (!existsSync(assemblyScript)) { + throw new Error(`Assembly script not found: ${assemblyScript}`); } - tarballs.sort((left, right) => left.file.localeCompare(right.file)); - writeFileSync( - join(artifactsDir, "SHA256SUMS"), - tarballs.map((tarball) => `${tarball.sha256} ${tarball.file}`).join("\n") + "\n", - ); - writeFileSync(join(artifactsDir, args.channel), `v${releaseVersion}\n`); - const manifestName = args.channel === "stable" ? "latest.json" : "beta.json"; - writeJson(join(artifactsDir, manifestName), { - version: `v${releaseVersion}`, - package: publicPackageName, - tarball: `releases/v${releaseVersion}/${artifactFiles.get("coding-agent")}`, - tarballs: tarballs.map((tarball) => ({ - package: tarball.name, - file: tarball.file, - sha256: tarball.sha256, - })), - }); + const { spawnSync } = await import("node:child_process"); + const assemblyArgs = [ + assemblyScript, + "--base-url", args.baseUrl, + "--channel", args.channel, + "--version", args.version, + "--binary-dir", args.binaryBaseDir, + "--sidecar-dir", args.sidecarDir, + "--out-dir", args.outDir, + ]; + for (const platform of args.platforms) assemblyArgs.push("--platform", platform); + const result = spawnSync(process.execPath, assemblyArgs, { stdio: "inherit", encoding: "utf8" }); - for (const tarball of tarballs) { - console.log(`Created ${join(artifactsDir, tarball.file)}`); + if (result.status !== 0) { + throw new Error(`assemble-release-archives.mjs failed with exit code ${result.status}`); } } try { - main(); + await main(); } catch (error) { console.error(error instanceof Error ? error.message : String(error)); process.exit(1); diff --git a/scripts/release.mjs b/scripts/release.mjs index 4eb4c83cba..65adaea803 100755 --- a/scripts/release.mjs +++ b/scripts/release.mjs @@ -1,19 +1,19 @@ -#!/usr/bin/env node +#!/usr/bin/env bun /** - * Release script for pi-mono + * Release script for Prime Agent * * Usage: - * node scripts/release.mjs - * node scripts/release.mjs - * node scripts/release.mjs --dry-run (preview changelog updates only) + * bun scripts/release.mjs + * bun scripts/release.mjs + * bun scripts/release.mjs --dry-run (preview changelog updates only) * * Steps: * 1. Check for uncommitted changes - * 2. Bump version via npm run version:xxx or set an explicit version + * 2. Bump every workspace version and refresh bun.lock * 3. Update CHANGELOG.md files: aggregate .changes/*.md fragments into a * [version] - date section, git rm the consumed fragments * 4. Commit and tag - * 5. Publish to npm + * 5. Publish the npm compatibility packages with Bun */ import { execSync } from "child_process"; @@ -27,7 +27,7 @@ const BUMP_TYPES = new Set(["major", "minor", "patch"]); const SEMVER_RE = /^\d+\.\d+\.\d+$/; if (!RELEASE_TARGET || (!BUMP_TYPES.has(RELEASE_TARGET) && !SEMVER_RE.test(RELEASE_TARGET))) { - console.error("Usage: node scripts/release.mjs [--dry-run]"); + console.error("Usage: bun scripts/release.mjs [--dry-run]"); process.exit(1); } @@ -82,7 +82,7 @@ function bumpOrSetVersion(target) { if (BUMP_TYPES.has(target)) { console.log(`Bumping version (${target})...`); - run(`npm run version:${target}`); + run(`bun run version:${target}`); return getVersion(); } @@ -92,9 +92,7 @@ function bumpOrSetVersion(target) { } console.log(`Setting explicit version (${target})...`); - run( - `npm version ${target} -ws --no-git-tag-version && node scripts/sync-versions.js && npx shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install`, - ); + run(`bun scripts/set-version.ts ${target}`); return getVersion(); } @@ -214,8 +212,8 @@ run(`git commit -m "Release v${version}"`); run(`git tag v${version}`); console.log(); -console.log("Publishing to npm..."); -run("npm run publish"); +console.log("Publishing npm compatibility packages..."); +run("bun run publish"); console.log(); console.log("Pushing to remote..."); From d0e3c63c972af2020a447df6492969e6939667f4 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 17:39:02 -0400 Subject: [PATCH 06/31] ci: run checks and releases with pinned Bun --- .github/dependabot.yml | 2 +- .github/workflows/build-binaries.yml | 119 ++++++++-- .github/workflows/ci.yml | 218 ++++++++++++++++--- .github/workflows/nightly-process-stress.yml | 19 +- 4 files changed, 290 insertions(+), 68 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6742d53aa1..21d8c43a7f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,4 +1,4 @@ -# Dependency update PRs wait out the same 7-day cooldown that .npmrc's +# Dependency update PRs wait out the same 7-day cooldown that bunfig.toml's # min-release-age enforces locally. Security-advisory PRs are exempt # from cooldown by design, so CVE fixes still arrive promptly. version: 2 diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index c140daa67f..af5cd25a98 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -16,7 +16,6 @@ on: concurrency: group: release-prime-agent cancel-in-progress: false - queue: max permissions: contents: read @@ -40,6 +39,11 @@ jobs: fetch-tags: true persist-credentials: false + - name: Setup Bun 1.3.14 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 + with: + bun-version: 1.3.14 + - name: Resolve release context id: context env: @@ -72,7 +76,7 @@ jobs: build_ref="$REF_NAME" publish_production=true else - production_version=$(node -p "require('./package.json').version") + production_version=$(bun -e "console.log(require('./package.json').version)") build_ref="$GITHUB_SHA_VALUE" beta_version="${production_version}-beta.${RUN_NUMBER}.${RUN_ATTEMPT}.${GITHUB_SHA_VALUE::7}" publish_beta=true @@ -80,7 +84,7 @@ jobs: previous_version= if [ -n "$BEFORE_SHA" ] && ! printf '%s\n' "$BEFORE_SHA" | grep -Eq '^0+$' && git cat-file -e "${BEFORE_SHA}:package.json"; then git show "${BEFORE_SHA}:package.json" > /tmp/previous-package.json - previous_version=$(node -p "require('/tmp/previous-package.json').version") + previous_version=$(bun -e "console.log(require('/tmp/previous-package.json').version)") fi if [ -z "$previous_version" ] || [ "$production_version" != "$previous_version" ]; then @@ -133,20 +137,38 @@ jobs: ref: ${{ env.BUILD_REF }} persist-credentials: false - - name: Setup Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - name: Setup Bun 1.3.14 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - node-version: '22' - registry-url: 'https://registry.npmjs.org' + bun-version: 1.3.14 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev - - name: Install dependencies - run: npm ci + - name: Install dependencies for all release platforms + run: bun install --frozen-lockfile --os=* --cpu=* - name: Build - run: npm run build + run: bun run build - name: Check - run: npm run check + run: bun run check + + - name: Compile binaries for all platforms + working-directory: packages/coding-agent + run: | + mkdir -p binaries + for platform in darwin-arm64 darwin-x64 linux-arm64 linux-x64; do + echo "Compiling for $platform..." + mkdir -p "binaries/$platform" + bun build --compile --external koffi --target="bun-$platform" ./dist/bun/cli.js --outfile "binaries/$platform/pi" + done + + - name: Copy binary sidecar assets + working-directory: packages/coding-agent + run: bun run copy-binary-assets - name: Pack production release if: env.PUBLISH_PRODUCTION == 'true' @@ -154,7 +176,7 @@ jobs: PRIME_AGENT_DOWNLOAD_BASE_URL: ${{ vars.R2_PUBLIC_BASE_URL }} run: | test -n "$PRIME_AGENT_DOWNLOAD_BASE_URL" - npm run release:pack -- \ + bun run release:pack -- \ --channel stable \ --version "$PRODUCTION_VERSION" \ --base-url "$PRIME_AGENT_DOWNLOAD_BASE_URL" \ @@ -166,12 +188,65 @@ jobs: PRIME_AGENT_DOWNLOAD_BASE_URL: ${{ vars.R2_PUBLIC_BASE_URL }} run: | test -n "$PRIME_AGENT_DOWNLOAD_BASE_URL" - npm run release:pack -- \ + bun run release:pack -- \ --channel beta \ --version "$BETA_VERSION" \ --base-url "$PRIME_AGENT_DOWNLOAD_BASE_URL" \ --out-dir packages/coding-agent/release/beta + - name: Smoke test host-platform archive + if: env.PUBLISH_PRODUCTION == 'true' || env.PUBLISH_BETA == 'true' + run: | + # Determine which archive to test (prefer production, fall back to beta) + ARTIFACTS_DIR="" + if [ "$PUBLISH_PRODUCTION" = "true" ]; then + ARTIFACTS_DIR="packages/coding-agent/release/production/artifacts" + else + ARTIFACTS_DIR="packages/coding-agent/release/beta/artifacts" + fi + + # Detect host platform + OS=$(uname -s) + ARCH=$(uname -m) + case "$OS" in + Linux) + case "$ARCH" in + x86_64) PLATFORM="linux-x64" ;; + aarch64|arm64) PLATFORM="linux-arm64" ;; + *) echo "Unknown host arch: $ARCH"; exit 1 ;; + esac + ;; + Darwin) + case "$ARCH" in + x86_64) PLATFORM="darwin-x64" ;; + arm64) PLATFORM="darwin-arm64" ;; + *) echo "Unknown host arch: $ARCH"; exit 1 ;; + esac + ;; + *) + echo "Unknown host OS: $OS"; exit 1 ;; + esac + + # Extract host-platform archive and run --version + ARCHIVE=$(ls "$ARTIFACTS_DIR"/*-"${PLATFORM}.tar.gz" 2>/dev/null | head -1) + if [ -z "$ARCHIVE" ]; then + echo "No archive for host platform ${PLATFORM} in ${ARTIFACTS_DIR}" + exit 1 + fi + + SMOKE_DIR=$(mktemp -d) + tar -xzf "$ARCHIVE" -C "$SMOKE_DIR" + chmod +x "$SMOKE_DIR/prime-agent" + if "$SMOKE_DIR/prime-agent" --version >/dev/null 2>&1; then + echo "Smoke test passed: $("$SMOKE_DIR/prime-agent" --version 2>&1)" + else + echo "Smoke test FAILED." + "$SMOKE_DIR/prime-agent" --version 2>&1 || true + rm -rf "$SMOKE_DIR" + exit 1 + fi + rm -rf "$SMOKE_DIR" + - name: Upload production artifacts if: env.PUBLISH_PRODUCTION == 'true' uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 @@ -212,6 +287,11 @@ jobs: ref: ${{ env.BUILD_REF }} persist-credentials: false + - name: Setup Bun 1.3.14 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 + with: + bun-version: 1.3.14 + - name: Download production artifacts if: env.PUBLISH_PRODUCTION == 'true' uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 @@ -232,7 +312,7 @@ jobs: export INSTALL_BASE_URL test -n "$INSTALL_BASE_URL" - node - <<'NODE' + bun -e ' const fs = require("node:fs"); const baseUrl = process.env.INSTALL_BASE_URL; if (!baseUrl) throw new Error("INSTALL_BASE_URL is required"); @@ -242,7 +322,7 @@ jobs: .replaceAll("__PRIME_AGENT_DEFAULT_RELEASE_CHANNEL__", channel); fs.writeFileSync("/tmp/prime-agent-install.sh", renderInstaller("stable")); fs.writeFileSync("/tmp/prime-agent-install-beta.sh", renderInstaller("beta")); - NODE + ' - name: Extract production release notes if: env.PUBLISH_PRODUCTION == 'true' @@ -257,16 +337,14 @@ jobs: run: | PRODUCTION_DIR=release-artifacts/production RELEASE_PREFIX="releases/v${PRODUCTION_VERSION}" - TARBALL="$PRODUCTION_DIR/prime-agent-${PRODUCTION_VERSION}.tgz" - test -f "$TARBALL" test -f "$PRODUCTION_DIR/SHA256SUMS" test -f "$PRODUCTION_DIR/stable" test -f "$PRODUCTION_DIR/latest.json" test -n "$R2_BUCKET" test -n "$R2_ENDPOINT_URL" - for artifact in "$PRODUCTION_DIR"/*.tgz; do + for artifact in "$PRODUCTION_DIR"/*.tar.gz; do aws s3 cp "$artifact" "s3://${R2_BUCKET}/${RELEASE_PREFIX}/$(basename "$artifact")" \ --endpoint-url "$R2_ENDPOINT_URL" \ --content-type application/gzip \ @@ -325,16 +403,14 @@ jobs: run: | BETA_DIR=release-artifacts/beta RELEASE_PREFIX="releases/v${BETA_VERSION}" - TARBALL="$BETA_DIR/prime-agent-${BETA_VERSION}.tgz" - test -f "$TARBALL" test -f "$BETA_DIR/SHA256SUMS" test -f "$BETA_DIR/beta" test -f "$BETA_DIR/beta.json" test -n "$R2_BUCKET" test -n "$R2_ENDPOINT_URL" - for artifact in "$BETA_DIR"/*.tgz; do + for artifact in "$BETA_DIR"/*.tar.gz; do aws s3 cp "$artifact" "s3://${R2_BUCKET}/${RELEASE_PREFIX}/$(basename "$artifact")" \ --endpoint-url "$R2_ENDPOINT_URL" \ --content-type application/gzip \ @@ -359,6 +435,7 @@ jobs: fi BETA_DIR=release-artifacts/beta + aws s3 cp "$BETA_DIR/beta.json" "s3://${R2_BUCKET}/beta.json" \ --endpoint-url "$R2_ENDPOINT_URL" \ --content-type application/json \ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af521a547c..c29c8fa8c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,11 +42,10 @@ jobs: with: persist-credentials: false - - name: Setup Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - name: Setup Bun 1.3.14 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - node-version: 22 - cache: npm + bun-version: 1.3.14 - name: Install system dependencies run: | @@ -54,14 +53,24 @@ jobs: sudo apt-get install -y libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev fd-find ripgrep sudo ln -s $(which fdfind) /usr/local/bin/fd - - name: Install dependencies - run: npm ci + - name: Install dependencies (frozen lockfile) + run: bun install --frozen-lockfile - name: Build - run: npm run build + run: bun run build + + - name: Check model catalog drift + run: | + if ! git diff --exit-code packages/ai/src/models.generated.ts; then + echo "ERROR: Model catalog has drifted from committed state." + echo "Run 'bun run build' in packages/ai to regenerate, then commit the updated models.generated.ts." + echo "Diff:" + git diff packages/ai/src/models.generated.ts + exit 1 + fi - name: Check - run: npm run check + run: bun run check test: name: Test (${{ matrix.name }}) @@ -75,39 +84,27 @@ jobs: include: - name: agent-core package: packages/agent - command: npm test + command: bun run test install_uv: false - name: ai package: packages/ai - command: npm test + command: bun run test install_uv: false - name: tui package: packages/tui - command: npm test + command: bun run test install_uv: false - name: coding-agent 1/3 package: packages/coding-agent - command: npm run test:ci -- --shard=1/3 + command: bun run test:ci -- --shard=1/3 install_uv: true - name: coding-agent 2/3 package: packages/coding-agent - command: npm run test:ci -- --shard=2/3 + command: bun run test:ci -- --shard=2/3 install_uv: true - name: coding-agent 3/3 package: packages/coding-agent - command: npm run test:ci -- --shard=3/3 - install_uv: true - - name: coding-agent process smoke - package: packages/coding-agent - command: npm run test:process - install_uv: true - - name: coding-agent kernel - package: packages/coding-agent - command: npm run test:kernel - install_uv: true - - name: runtime python - package: prime-agent-runtime - command: uv run python -m unittest discover -s test + command: bun run test:ci -- --shard=3/3 install_uv: true steps: - name: Checkout @@ -115,11 +112,10 @@ jobs: with: persist-credentials: false - - name: Setup Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - name: Setup Bun 1.3.14 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - node-version: 22 - cache: npm + bun-version: 1.3.14 - name: Install system dependencies run: | @@ -127,32 +123,182 @@ jobs: sudo apt-get install -y libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev fd-find ripgrep sudo ln -s $(which fdfind) /usr/local/bin/fd - - name: Install dependencies - run: npm ci + - name: Install dependencies (frozen lockfile) + run: bun install --frozen-lockfile - name: Build - run: npm run build + run: bun run build - name: Install uv if: matrix.install_uv run: | - python3 -m pip install --user uv - echo "$HOME/.local/bin" >> "$GITHUB_PATH" + curl -LsSf https://astral.sh/uv/install.sh | sh + echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Test working-directory: ${{ matrix.package }} run: ${{ matrix.command }} + process-stress: + name: Process stress + needs: trust + if: needs.trust.outputs.allowed == 'true' + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Setup Bun 1.3.14 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 + with: + bun-version: 1.3.14 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev fd-find ripgrep + sudo ln -s $(which fdfind) /usr/local/bin/fd + + - name: Install dependencies (frozen lockfile) + run: bun install --frozen-lockfile + + - name: Build + run: bun run build + + - name: Install uv + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + + - name: Run process stress tests + working-directory: packages/coding-agent + env: + PRIME_AGENT_STRESS_WORKERS: "10" + run: bun run test:process-stress + + kernel-heavy: + name: Kernel-heavy + needs: trust + if: needs.trust.outputs.allowed == 'true' + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Setup Bun 1.3.14 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 + with: + bun-version: 1.3.14 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev fd-find ripgrep + sudo ln -s $(which fdfind) /usr/local/bin/fd + + - name: Install dependencies (frozen lockfile) + run: bun install --frozen-lockfile + + - name: Build + run: bun run build + + - name: Install uv + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + + - name: Run kernel-heavy tests + working-directory: packages/coding-agent + run: bun run test:kernel + + runtime-python: + name: Runtime Python + needs: trust + if: needs.trust.outputs.allowed == 'true' + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Setup Bun 1.3.14 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 + with: + bun-version: 1.3.14 + + - name: Install dependencies (frozen lockfile) + run: bun install --frozen-lockfile + + - name: Install uv + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + + - name: Install Python runtime dependencies + working-directory: prime-agent-runtime + run: uv sync + + - name: Run Python runtime tests + working-directory: prime-agent-runtime + run: uv run python -m unittest discover -s test + + artifact-smoke: + name: Artifact smoke + needs: trust + if: needs.trust.outputs.allowed == 'true' + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Setup Bun 1.3.14 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 + with: + bun-version: 1.3.14 + + - name: Install dependencies for all release platforms + run: bun install --frozen-lockfile --os=* --cpu=* + + - name: Build + run: bun run build + + - name: Build binary + working-directory: packages/coding-agent + run: bun run build:binary + + - name: Run artifact smoke test + working-directory: packages/coding-agent + run: bun test test/compiled-artifact-smoke.test.ts + build-check-test: name: build-check-test if: always() && needs.trust.outputs.allowed == 'true' - needs: [trust, build-check, test] + needs: [trust, build-check, test, process-stress, kernel-heavy, runtime-python, artifact-smoke] runs-on: ubuntu-latest steps: - name: Verify CI results env: BUILD_CHECK_RESULT: ${{ needs.build-check.result }} TEST_RESULT: ${{ needs.test.result }} + PROCESS_STRESS_RESULT: ${{ needs.process-stress.result }} + KERNEL_HEAVY_RESULT: ${{ needs.kernel-heavy.result }} + RUNTIME_PYTHON_RESULT: ${{ needs.runtime-python.result }} + ARTIFACT_SMOKE_RESULT: ${{ needs.artifact-smoke.result }} run: | test "$BUILD_CHECK_RESULT" = success test "$TEST_RESULT" = success + test "$PROCESS_STRESS_RESULT" = success + test "$KERNEL_HEAVY_RESULT" = success + test "$RUNTIME_PYTHON_RESULT" = success + test "$ARTIFACT_SMOKE_RESULT" = success diff --git a/.github/workflows/nightly-process-stress.yml b/.github/workflows/nightly-process-stress.yml index e47f42ca85..86b197c330 100644 --- a/.github/workflows/nightly-process-stress.yml +++ b/.github/workflows/nightly-process-stress.yml @@ -23,11 +23,10 @@ jobs: with: persist-credentials: false - - name: Setup Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + - name: Setup Bun 1.3.14 + uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - node-version: 22 - cache: npm + bun-version: 1.3.14 - name: Install system dependencies run: | @@ -35,19 +34,19 @@ jobs: sudo apt-get install -y libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev fd-find ripgrep sudo ln -s $(which fdfind) /usr/local/bin/fd - - name: Install dependencies - run: npm ci + - name: Install dependencies (frozen lockfile) + run: bun install --frozen-lockfile - name: Build - run: npm run build + run: bun run build - name: Install uv run: | - python3 -m pip install --user uv - echo "$HOME/.local/bin" >> "$GITHUB_PATH" + curl -LsSf https://astral.sh/uv/install.sh | sh + echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Run process stress tests working-directory: packages/coding-agent env: PRIME_AGENT_STRESS_WORKERS: "10" - run: npm run test:process-stress + run: bun run test:process-stress From 6edda2e16c1d3db87fdd4713cb077989a1d60ff8 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 17:39:23 -0400 Subject: [PATCH 07/31] chore: finish Bun tooling migration --- packages/ai/src/models.generated.ts | 2 +- .../custom-provider-anthropic/index.ts | 2 +- .../custom-provider-gitlab-duo/test.ts | 8 +++--- .../examples/extensions/sandbox/index.ts | 2 +- .../examples/extensions/with-deps/index.ts | 2 +- .../coding-agent/examples/rpc-extension-ui.ts | 2 +- scripts/bench-attach-bytes.mjs | 4 +-- scripts/bench-daemon-startup.mjs | 4 +-- scripts/cost.ts | 2 +- scripts/edit-tool-stats.mjs | 4 +-- scripts/profile-coding-agent-node.mjs | 27 +++++-------------- scripts/read-tool-stats.mjs | 4 +-- scripts/session-context-stats.mjs | 4 +-- scripts/session-transcripts.ts | 4 +-- scripts/stats.ts | 2 +- scripts/tool-stats.ts | 2 +- 16 files changed, 31 insertions(+), 44 deletions(-) diff --git a/packages/ai/src/models.generated.ts b/packages/ai/src/models.generated.ts index a3945be9a1..6ecbf9e811 100644 --- a/packages/ai/src/models.generated.ts +++ b/packages/ai/src/models.generated.ts @@ -1,5 +1,5 @@ // This file is auto-generated by scripts/generate-models.ts -// Do not edit manually - run 'npm run generate-models' to update +// Do not edit manually - run 'bun run generate-models' to update import type { Model } from "./types.js"; diff --git a/packages/coding-agent/examples/extensions/custom-provider-anthropic/index.ts b/packages/coding-agent/examples/extensions/custom-provider-anthropic/index.ts index 69267f4006..73318cd2b5 100644 --- a/packages/coding-agent/examples/extensions/custom-provider-anthropic/index.ts +++ b/packages/coding-agent/examples/extensions/custom-provider-anthropic/index.ts @@ -10,7 +10,7 @@ * * Usage: * # First install dependencies - * cd packages/coding-agent/examples/extensions/custom-provider && npm install + * cd packages/coding-agent/examples/extensions/custom-provider && bun install * * # With OAuth (run /login custom-anthropic first) * pi -e ./packages/coding-agent/examples/extensions/custom-provider diff --git a/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts b/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts index c796373258..88f8a543e7 100644 --- a/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts +++ b/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts @@ -1,11 +1,11 @@ /** * Test script for GitLab Duo extension - * Run: npx tsx test.ts [model-id] [--thinking] + * Run: bun test.ts [model-id] [--thinking] * * Examples: - * npx tsx test.ts # Test default (claude-sonnet-4-5-20250929) - * npx tsx test.ts gpt-5-codex # Test GPT-5 Codex - * npx tsx test.ts claude-sonnet-4-5-20250929 --thinking + * bun test.ts # Test default (claude-sonnet-4-5-20250929) + * bun test.ts gpt-5-codex # Test GPT-5 Codex + * bun test.ts claude-sonnet-4-5-20250929 --thinking */ import { type Api, type Context, type Model, registerApiProvider, streamSimple } from "@earendil-works/pi-ai"; diff --git a/packages/coding-agent/examples/extensions/sandbox/index.ts b/packages/coding-agent/examples/extensions/sandbox/index.ts index 55524872cc..ebe6dede8a 100644 --- a/packages/coding-agent/examples/extensions/sandbox/index.ts +++ b/packages/coding-agent/examples/extensions/sandbox/index.ts @@ -36,7 +36,7 @@ * * Setup: * 1. Copy sandbox/ directory to ~/.prime/agent/extensions/ - * 2. Run `npm install` in ~/.prime/agent/extensions/sandbox/ + * 2. Run `bun install` in ~/.prime/agent/extensions/sandbox/ * * Linux also requires: bubblewrap, socat, ripgrep */ diff --git a/packages/coding-agent/examples/extensions/with-deps/index.ts b/packages/coding-agent/examples/extensions/with-deps/index.ts index 17be7da048..6008d65e55 100644 --- a/packages/coding-agent/examples/extensions/with-deps/index.ts +++ b/packages/coding-agent/examples/extensions/with-deps/index.ts @@ -2,7 +2,7 @@ * Example extension with its own npm dependencies. * Tests that jiti resolves modules from the extension's own node_modules. * - * Requires: npm install in this directory + * Requires: bun install in this directory */ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; diff --git a/packages/coding-agent/examples/rpc-extension-ui.ts b/packages/coding-agent/examples/rpc-extension-ui.ts index bcbb6ec898..9816e8b2bf 100644 --- a/packages/coding-agent/examples/rpc-extension-ui.ts +++ b/packages/coding-agent/examples/rpc-extension-ui.ts @@ -5,7 +5,7 @@ * Demonstrates how to build a custom UI on top of the RPC protocol, * including handling extension UI requests (select, confirm, input, editor). * - * Usage: npx tsx examples/rpc-extension-ui.ts + * Usage: bun examples/rpc-extension-ui.ts * * Slash commands: * /select - demo select dialog diff --git a/scripts/bench-attach-bytes.mjs b/scripts/bench-attach-bytes.mjs index e64434bc51..52fd02a608 100644 --- a/scripts/bench-attach-bytes.mjs +++ b/scripts/bench-attach-bytes.mjs @@ -1,10 +1,10 @@ -#!/usr/bin/env node +#!/usr/bin/env bun /** * Measures attach payload bytes for legacy vs slim_attach clients against a * daemon session loaded from a given session file. Uses an isolated agent dir * so no test sessions leak into the shared sessions directory. * - * node scripts/bench-attach-bytes.mjs + * bun scripts/bench-attach-bytes.mjs */ import { spawn } from "node:child_process"; import { copyFileSync, mkdtempSync, rmSync } from "node:fs"; diff --git a/scripts/bench-daemon-startup.mjs b/scripts/bench-daemon-startup.mjs index fb8e9e7f3b..25f9dc79c3 100644 --- a/scripts/bench-daemon-startup.mjs +++ b/scripts/bench-daemon-startup.mjs @@ -1,10 +1,10 @@ -#!/usr/bin/env node +#!/usr/bin/env bun /** * Measures daemon cold-start latency: spawn `--mode daemon` and poll the unix * socket until it accepts a connection. This is the readiness gate every * interactive cold start waits on. * - * node scripts/bench-daemon-startup.mjs [--runs N] + * bun scripts/bench-daemon-startup.mjs [--runs N] */ import { spawn } from "node:child_process"; import { mkdtempSync, rmSync } from "node:fs"; diff --git a/scripts/cost.ts b/scripts/cost.ts index 2774b8d87e..06ef039ea5 100755 --- a/scripts/cost.ts +++ b/scripts/cost.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env npx tsx +#!/usr/bin/env bun import * as fs from "fs"; import * as path from "path"; diff --git a/scripts/edit-tool-stats.mjs b/scripts/edit-tool-stats.mjs index 2c2c7ceabc..2e42fe9620 100644 --- a/scripts/edit-tool-stats.mjs +++ b/scripts/edit-tool-stats.mjs @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env bun import { createReadStream } from "node:fs"; import { promises as fs } from "node:fs"; @@ -62,7 +62,7 @@ function parseArgs(argv) { } function printHelp() { - console.log(`Usage: node scripts/edit-tool-stats.mjs [options] + console.log(`Usage: bun scripts/edit-tool-stats.mjs [options] Options: --sessions-dir Sessions directory (default: ~/.pi/agent/sessions) diff --git a/scripts/profile-coding-agent-node.mjs b/scripts/profile-coding-agent-node.mjs index 44ccf86b6c..c646aac9e3 100644 --- a/scripts/profile-coding-agent-node.mjs +++ b/scripts/profile-coding-agent-node.mjs @@ -17,13 +17,11 @@ const startupBenchmarkEnvName = "PI_STARTUP_BENCHMARK"; function printHelp() { console.log(`Usage: - node scripts/profile-coding-agent-node.mjs [options] + bun scripts/profile-coding-agent-node.mjs [options] -Profiles coding-agent startup with the runtime selected below: -- npm run profile:tui -> builds packages/coding-agent and profiles TUI startup with Node -- npm run profile:rpc -> builds packages/coding-agent and profiles RPC startup with Node -- bun run profile:tui -> profiles TUI startup from src/cli.ts directly with Bun -- bun run profile:rpc -> profiles RPC startup from src/cli.ts directly with Bun +Profiles coding-agent startup with the selected runtime. bun run profile:tui +and bun run profile:rpc use Bun by default. Pass --runtime node only for +an explicit Node compatibility comparison. Options: --mode tui or rpc (default: tui) @@ -282,19 +280,8 @@ async function runBuild() { process.stdout.write("Building packages/tui, packages/ai, packages/agent, and packages/coding-agent...\n"); const startedAt = performance.now(); const child = spawn( - "npm", - [ - "run", - "build", - "--workspace", - "packages/tui", - "--workspace", - "packages/ai", - "--workspace", - "packages/agent", - "--workspace", - "packages/coding-agent", - ], + process.execPath, + ["run", "build"], { cwd: repoRoot, env: process.env, @@ -352,7 +339,7 @@ function getRuntimeCommand(runtime, mode, profileDir, profileName, cpuProfile) { } args.push(distCliPath, ...benchmarkArgs); return { - executable: process.execPath, + executable: "node", args, }; } diff --git a/scripts/read-tool-stats.mjs b/scripts/read-tool-stats.mjs index 07bedd8f90..487e11e0c9 100755 --- a/scripts/read-tool-stats.mjs +++ b/scripts/read-tool-stats.mjs @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env bun import { createReadStream } from "node:fs"; import { promises as fs } from "node:fs"; @@ -53,7 +53,7 @@ function parseArgs(argv) { } function printHelp() { - console.log(`Usage: node scripts/read-tool-stats.mjs [options] + console.log(`Usage: bun scripts/read-tool-stats.mjs [options] Options: --sessions-dir Sessions directory (default: ~/.pi/agent/sessions) diff --git a/scripts/session-context-stats.mjs b/scripts/session-context-stats.mjs index e9ae425c30..6f47329c0e 100755 --- a/scripts/session-context-stats.mjs +++ b/scripts/session-context-stats.mjs @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env bun import { createReadStream } from "node:fs"; import { promises as fs } from "node:fs"; @@ -34,7 +34,7 @@ function parseArgs(argv) { } function printHelp() { - console.log(`Usage: node scripts/session-context-stats.mjs [options] + console.log(`Usage: bun scripts/session-context-stats.mjs [options] Options: --sessions-dir Sessions directory (default: ~/.pi/agent/sessions) diff --git a/scripts/session-transcripts.ts b/scripts/session-transcripts.ts index e10dbff9f4..0b5a7410fc 100644 --- a/scripts/session-transcripts.ts +++ b/scripts/session-transcripts.ts @@ -1,9 +1,9 @@ -#!/usr/bin/env npx tsx +#!/usr/bin/env bun /** * Extracts session transcripts for a given cwd, splits into context-sized files, * optionally spawns subagents to analyze patterns. * - * Usage: npx tsx scripts/session-transcripts.ts [--analyze] [--output ] [cwd] + * Usage: bun scripts/session-transcripts.ts [--analyze] [--output ] [cwd] * --analyze Spawn pi subagents to analyze each transcript file * --output Output directory for transcript files (defaults to ./session-transcripts) * cwd Working directory to extract sessions for (defaults to current) diff --git a/scripts/stats.ts b/scripts/stats.ts index 15c353e382..72597ccfaf 100644 --- a/scripts/stats.ts +++ b/scripts/stats.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env npx tsx +#!/usr/bin/env bun import { existsSync, readdirSync, readFileSync } from "node:fs"; import { homedir } from "node:os"; diff --git a/scripts/tool-stats.ts b/scripts/tool-stats.ts index 8d39b8683c..97b59e1872 100755 --- a/scripts/tool-stats.ts +++ b/scripts/tool-stats.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env npx tsx +#!/usr/bin/env bun import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs"; import { homedir, tmpdir } from "node:os"; From 4a65980485b23a348d97e79652500747928a558e Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 17:39:30 -0400 Subject: [PATCH 08/31] docs: make Bun the default workflow --- AGENTS.md | 18 +++++++++--------- packages/agent/README.md | 2 +- packages/ai/README.md | 8 ++++---- packages/coding-agent/docs/daemon.md | 10 +++++----- packages/coding-agent/docs/development.md | 6 +++--- packages/coding-agent/docs/extensions.md | 6 +++--- .../coding-agent/docs/long-running-agents.md | 2 +- packages/coding-agent/docs/quickstart.md | 6 +++--- packages/coding-agent/docs/rlm.md | 2 +- packages/coding-agent/docs/sdk.md | 2 +- packages/coding-agent/docs/skills.md | 4 ++-- packages/coding-agent/docs/termux.md | 2 +- packages/coding-agent/docs/tui.md | 2 +- packages/coding-agent/docs/usage.md | 2 +- .../examples/extensions/plan-mode/README.md | 2 +- packages/coding-agent/examples/sdk/README.md | 2 +- packages/tui/README.md | 10 +++++----- 17 files changed, 43 insertions(+), 43 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 85e64ff351..393fb51cb4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,10 +22,10 @@ ## Commands -- After code changes (not documentation changes): `npm run check` (get full output, no tail). Fix all errors, warnings, and infos before committing. -- Note: `npm run check` does not run tests. -- NEVER run: `npm run dev`, `npm run build`, `npm test` -- Only run specific tests if user instructs: `npx tsx ../../node_modules/vitest/dist/cli.js --run test/specific.test.ts` +- After code changes (not documentation changes): `bun run check` (get full output, no tail). Fix all errors, warnings, and infos before committing. +- Note: `bun run check` does not run tests. +- NEVER run: `bun run dev`, `bun run build`, `bun test` +- Only run specific tests if user instructs: `bun test test/specific.test.ts` - Run tests from the package root, not the repo root. - If you create or modify a test file, you MUST run that test file and iterate until it passes. - When writing tests, run them, identify issues in either the test or implementation, and iterate until fixed. @@ -43,9 +43,9 @@ ## Dependencies -- A 7-day minimum release age applies to all dependency updates: `.npmrc` sets `min-release-age=7` and `.github/dependabot.yml` uses a matching `cooldown`. Never bypass it for routine updates. -- Enforcement requires npm >= 11.10; older npm silently ignores the setting, so use a current npm when updating dependencies. -- For an urgent security patch younger than 7 days, override explicitly: `npm install --min-release-age=0 `. +- A 7-day minimum release age applies to all dependency updates: `bunfig.toml` sets `minimumReleaseAge = 604800` and `.github/dependabot.yml` uses a matching `cooldown`. Never bypass it for routine updates. +- Bun 1.3.14 enforces this setting for dependency updates. +- For an urgent security patch younger than 7 days, override explicitly: `bun add --minimum-release-age=0 `. ## GitHub Workflow @@ -195,8 +195,8 @@ Create provider file exporting: 2. **Run release script**: ```bash - npm run release:patch # Fixes and additions - npm run release:minor # API breaking changes + bun run release:patch # Fixes and additions + bun run release:minor # API breaking changes ``` The script handles: version bump, folding `.changes/` fragments into the release section, commit, tag, and publish. diff --git a/packages/agent/README.md b/packages/agent/README.md index e28f449c89..a451cb49f5 100644 --- a/packages/agent/README.md +++ b/packages/agent/README.md @@ -18,7 +18,7 @@ Release docs use the Prime Agent package names. The source workspace manifests s ## Workspace Package ```bash -npm install prime-agent-core +bun add prime-agent-core ``` ## Quick Start diff --git a/packages/ai/README.md b/packages/ai/README.md index a35c679302..b93a6122f2 100644 --- a/packages/ai/README.md +++ b/packages/ai/README.md @@ -91,7 +91,7 @@ Unified LLM API with automatic model discovery, provider configuration, token an ## Installation ```bash -npm install prime-agent-ai +bun add prime-agent-ai ``` TypeBox exports are re-exported from `prime-agent-ai`: `Type`, `Static`, and `TSchema`. @@ -1150,9 +1150,9 @@ Official docs: [Application Default Credentials](https://cloud.google.com/docs/a The quickest way to authenticate: ```bash -npx prime-agent-ai login # interactive provider selection -npx prime-agent-ai login anthropic # login to specific provider -npx prime-agent-ai list # list available providers +bunx prime-agent-ai login # interactive provider selection +bunx prime-agent-ai login anthropic # login to specific provider +bunx prime-agent-ai list # list available providers ``` Credentials are saved to `auth.json` in the current directory. diff --git a/packages/coding-agent/docs/daemon.md b/packages/coding-agent/docs/daemon.md index 35e4ce9dd9..ba1cce031e 100644 --- a/packages/coding-agent/docs/daemon.md +++ b/packages/coding-agent/docs/daemon.md @@ -156,11 +156,11 @@ If preparation or manifest validation fails, prepared workers are released and a From `packages/coding-agent`: ```sh -npx tsx test/daemon-multiclient-bench.ts -npx tsx test/daemon-multiclient-bench.ts --generated-session-mib 100 -npx tsx test/daemon-multiclient-bench.ts --generated-session-mib 500 -npx tsx test/daemon-multiclient-bench.ts --session-file /path/to/session.jsonl -PRIME_AGENT_STRESS_WORKERS=50 npx tsx ../../node_modules/vitest/dist/cli.js --run test/daemon-supervisor-process.test.ts -t "hosts resident roots" +bun test/daemon-multiclient-bench.ts +bun test/daemon-multiclient-bench.ts --generated-session-mib 100 +bun test/daemon-multiclient-bench.ts --generated-session-mib 500 +bun test/daemon-multiclient-bench.ts --session-file /path/to/session.jsonl +PRIME_AGENT_STRESS_WORKERS=50 PRIME_AGENT_TEST_TAGS=process-stress bun test --isolate test/daemon-supervisor-process.test.ts -t "hosts resident roots" ``` The benchmark compares fanout and attach paths, including serialization count, throughput, elapsed time, and sampled RSS. The stress case starts many resident roots and verifies that their schedules advance independently while sessions are busy. diff --git a/packages/coding-agent/docs/development.md b/packages/coding-agent/docs/development.md index 56aa1a74a4..e3da5b8af9 100644 --- a/packages/coding-agent/docs/development.md +++ b/packages/coding-agent/docs/development.md @@ -9,7 +9,7 @@ Prime Agent requires Node.js 22.8.0 or newer. ```bash git clone https://github.com/PrimeIntellect-ai/prime-agent cd prime-agent -npm ci +bun install --frozen-lockfile ``` Run from source: @@ -68,7 +68,7 @@ prime-agent shutdown After code changes, run the repository check from the root: ```bash -npm run check +bun run check ``` This performs formatting, linting, type checking, installer rendering checks, and the browser smoke check. It does not run the test suite. @@ -77,7 +77,7 @@ Run focused tests from the package root. For example: ```bash cd packages/coding-agent -npx tsx ../../node_modules/vitest/dist/cli.js --run test/specific.test.ts +bun test test/specific.test.ts ``` If you create or modify a test file, run that file and iterate until it passes. Coding-agent suite regressions belong under `test/suite/regressions/` and use the suite harness and faux provider rather than live provider credentials. diff --git a/packages/coding-agent/docs/extensions.md b/packages/coding-agent/docs/extensions.md index 4fd2912808..a16b06bbb5 100644 --- a/packages/coding-agent/docs/extensions.md +++ b/packages/coding-agent/docs/extensions.md @@ -144,7 +144,7 @@ To share extensions via npm or git as Prime Agent packages, see [packages.md](pa | `@earendil-works/pi-ai` | AI utilities (`StringEnum` for Google-compatible enums) | | `@earendil-works/pi-tui` | TUI components for custom rendering | -npm dependencies work too. Add a `package.json` next to your extension (or in a parent directory), run `npm install`, and imports from `node_modules/` are resolved automatically. +npm dependencies work too. Add a `package.json` next to your extension (or in a parent directory), run `bun install`, and imports from `node_modules/` are resolved automatically. For distributed Prime Agent packages installed with `prime-agent package install` (npm or git), runtime dependencies must be in `dependencies`. Package installation uses production installs (`npm install --omit=dev`) by default, so `devDependencies` are not available at runtime; when `npmCommand` is configured, git packages use plain `install` for compatibility with wrappers. @@ -242,7 +242,7 @@ This pattern makes the fetched models available during normal startup and to `pr └── my-extension/ ├── package.json # Declares dependencies and entry points ├── package-lock.json - ├── node_modules/ # After npm install + ├── node_modules/ # After bun install └── src/ └── index.ts ``` @@ -261,7 +261,7 @@ This pattern makes the fetched models available during normal startup and to `pr } ``` -Run `npm install` in the extension directory, then imports from `node_modules/` work automatically. +Run `bun install` in the extension directory, then imports from `node_modules/` work automatically. ## Events diff --git a/packages/coding-agent/docs/long-running-agents.md b/packages/coding-agent/docs/long-running-agents.md index 436a40d447..1ac2f9d1ed 100644 --- a/packages/coding-agent/docs/long-running-agents.md +++ b/packages/coding-agent/docs/long-running-agents.md @@ -213,7 +213,7 @@ Or configure a run from the CLI: ```bash prime-agent \ --autonomous \ - --autonomous-gate "npm run check" \ + --autonomous-gate "bun run check" \ --autonomous-max-turns 20 \ "Implement and verify the requested change" ``` diff --git a/packages/coding-agent/docs/quickstart.md b/packages/coding-agent/docs/quickstart.md index e55a8375b5..bf8db3ec31 100644 --- a/packages/coding-agent/docs/quickstart.md +++ b/packages/coding-agent/docs/quickstart.md @@ -30,7 +30,7 @@ To run a source checkout instead, use Node.js 22.8.0 or newer: ```bash git clone https://github.com/PrimeIntellect-ai/prime-agent cd prime-agent -npm ci +bun install --frozen-lockfile ./prime-agent.sh ``` @@ -94,7 +94,7 @@ Prime Agent loads context files at startup. Add an `AGENTS.md` file to tell it h ```markdown # Project Instructions -- Run `npm run check` after code changes. +- Run `bun run check` after code changes. - Do not run production migrations locally. - Keep responses concise. ``` @@ -124,7 +124,7 @@ Images can be pasted with Ctrl+V (Alt+V on Windows) or dragged into supported te In interactive mode: ```text -!npm run lint +!bun run lint ``` The command output is sent to the model. Use `!!command` to run a command without adding its output to model context. During agent work, the model normally runs project commands from the Python REPL with `bash()`. diff --git a/packages/coding-agent/docs/rlm.md b/packages/coding-agent/docs/rlm.md index 7d558073b4..4be00ec26c 100644 --- a/packages/coding-agent/docs/rlm.md +++ b/packages/coding-agent/docs/rlm.md @@ -44,7 +44,7 @@ large_files = [path for path in config_files if path.stat().st_size > 10_000] Run a project's normal commands through its own environment with `bash()`: ```python -result = await bash("npm run check") +result = await bash("bun run check") print(result.output) ``` diff --git a/packages/coding-agent/docs/sdk.md b/packages/coding-agent/docs/sdk.md index a8ee9aa372..e50f199584 100644 --- a/packages/coding-agent/docs/sdk.md +++ b/packages/coding-agent/docs/sdk.md @@ -40,7 +40,7 @@ await session.prompt("What files are in the current directory?"); ## Installation ```bash -npm install @earendil-works/pi-coding-agent +bun add @earendil-works/pi-coding-agent ``` The SDK is included in the main package. No separate installation needed. diff --git a/packages/coding-agent/docs/skills.md b/packages/coding-agent/docs/skills.md index ef41c05f27..8b156f0b41 100644 --- a/packages/coding-agent/docs/skills.md +++ b/packages/coding-agent/docs/skills.md @@ -278,7 +278,7 @@ description: What this skill does and when to use it. Be specific. Run once before first use: ```bash -cd /path/to/skill && npm install +cd /path/to/skill && bun install ``` ## Usage @@ -369,7 +369,7 @@ description: Web search and content extraction via Brave Search API. Use for sea ## Setup ```bash -cd /path/to/brave-search && npm install +cd /path/to/brave-search && bun install ``` ## Search diff --git a/packages/coding-agent/docs/termux.md b/packages/coding-agent/docs/termux.md index c43eab4122..db3ab9273e 100644 --- a/packages/coding-agent/docs/termux.md +++ b/packages/coding-agent/docs/termux.md @@ -19,7 +19,7 @@ pkg install nodejs termux-api git ripgrep # Clone and install Prime Agent from source git clone https://github.com/PrimeIntellect-ai/prime-agent.git cd prime-agent -npm ci +bun install --frozen-lockfile # Run Prime Agent ./prime-agent.sh diff --git a/packages/coding-agent/docs/tui.md b/packages/coding-agent/docs/tui.md index 5e9c371255..2d25174997 100644 --- a/packages/coding-agent/docs/tui.md +++ b/packages/coding-agent/docs/tui.md @@ -448,7 +448,7 @@ interface MyTheme { Set `PI_TUI_WRITE_LOG` to capture the raw ANSI stream written to stdout. ```bash -PI_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx packages/tui/test/chat-simple.ts +PI_TUI_WRITE_LOG=/tmp/tui-ansi.log bun packages/tui/test/chat-simple.ts ``` ## Performance diff --git a/packages/coding-agent/docs/usage.md b/packages/coding-agent/docs/usage.md index 3d68af75bd..087bbf196a 100644 --- a/packages/coding-agent/docs/usage.md +++ b/packages/coding-agent/docs/usage.md @@ -279,7 +279,7 @@ For example, this noninteractive run uses a locally available model configuratio ```bash prime-agent -p \ --autonomous \ - --autonomous-gate "npm run check" \ + --autonomous-gate "bun run check" \ --autonomous-gate-retries 2 \ --autonomous-gate-timeout-ms 300000 \ --autonomous-max-continuations 3 \ diff --git a/packages/coding-agent/examples/extensions/plan-mode/README.md b/packages/coding-agent/examples/extensions/plan-mode/README.md index 6618c80860..0783559388 100644 --- a/packages/coding-agent/examples/extensions/plan-mode/README.md +++ b/packages/coding-agent/examples/extensions/plan-mode/README.md @@ -60,6 +60,6 @@ Safe commands (allowed): Blocked commands: - File modification: `rm`, `mv`, `cp`, `mkdir`, `touch` - Git write: `git add`, `git commit`, `git push` -- Package install: `npm install`, `yarn add`, `pip install` +- Package install: `bun install`, `npm install`, `yarn add`, `pip install` - System: `sudo`, `kill`, `reboot` - Editors: `vim`, `nano`, `code` diff --git a/packages/coding-agent/examples/sdk/README.md b/packages/coding-agent/examples/sdk/README.md index aac8b4ea6b..21d05192cd 100644 --- a/packages/coding-agent/examples/sdk/README.md +++ b/packages/coding-agent/examples/sdk/README.md @@ -30,7 +30,7 @@ The runtime example shows how to build a recreate function that closes over proc ```bash cd packages/coding-agent -npx tsx examples/sdk/01-minimal.ts +bun examples/sdk/01-minimal.ts ``` ## Quick Reference diff --git a/packages/tui/README.md b/packages/tui/README.md index c28647549b..120606e583 100644 --- a/packages/tui/README.md +++ b/packages/tui/README.md @@ -770,20 +770,20 @@ See `test/chat-simple.ts` for a complete chat interface example with: Run it: ```bash -npx tsx test/chat-simple.ts +bun test/chat-simple.ts ``` ## Development ```bash # Install dependencies (from monorepo root) -npm install +bun install # Run type checking -npm run check +bun run check # Run the demo -npx tsx test/chat-simple.ts +bun test/chat-simple.ts ``` ### Debug logging @@ -791,5 +791,5 @@ npx tsx test/chat-simple.ts Set `PI_TUI_WRITE_LOG` to capture the raw ANSI stream written to stdout. ```bash -PI_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx test/chat-simple.ts +PI_TUI_WRITE_LOG=/tmp/tui-ansi.log bun test/chat-simple.ts ``` From 9791df5a93af873ab9bf28b042e77547b6f56c87 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 17:43:36 -0400 Subject: [PATCH 09/31] docs: add Bun migration changelog fragments --- packages/ai/.changes/bun-primary-runtime.md | 1 + packages/coding-agent/.changes/bun-primary-runtime.md | 1 + 2 files changed, 2 insertions(+) create mode 100644 packages/ai/.changes/bun-primary-runtime.md create mode 100644 packages/coding-agent/.changes/bun-primary-runtime.md diff --git a/packages/ai/.changes/bun-primary-runtime.md b/packages/ai/.changes/bun-primary-runtime.md new file mode 100644 index 0000000000..e0b40ce40f --- /dev/null +++ b/packages/ai/.changes/bun-primary-runtime.md @@ -0,0 +1 @@ +- Made Bun 1.3.14 the primary development and test runtime while preserving Node-compatible package output. diff --git a/packages/coding-agent/.changes/bun-primary-runtime.md b/packages/coding-agent/.changes/bun-primary-runtime.md new file mode 100644 index 0000000000..a2feb62ae6 --- /dev/null +++ b/packages/coding-agent/.changes/bun-primary-runtime.md @@ -0,0 +1 @@ +- Added Bun-primary development, testing, native binary releases, and verified binary-first installation. From 076cd4fca9d1fd2b23fba22ca9713503b952de7e Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 17:49:14 -0400 Subject: [PATCH 10/31] chore(ai): refresh generated model catalog --- packages/ai/src/models.generated.ts | 774 ++++++++++++++++++---------- 1 file changed, 495 insertions(+), 279 deletions(-) diff --git a/packages/ai/src/models.generated.ts b/packages/ai/src/models.generated.ts index 6ecbf9e811..cbc6e14c3b 100644 --- a/packages/ai/src/models.generated.ts +++ b/packages/ai/src/models.generated.ts @@ -91,6 +91,24 @@ export const MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"bedrock-converse-stream">, + "anthropic.claude-fable-5-1": { + id: "anthropic.claude-fable-5-1", + name: "Claude Fable 5.1", + api: "bedrock-converse-stream", + provider: "amazon-bedrock", + baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com", + reasoning: true, + thinkingLevelMap: {"off":null,"xhigh":"xhigh","max":"max"}, + input: ["text", "image"], + cost: { + input: 10, + output: 50, + cacheRead: 0.25, + cacheWrite: 12.5, + }, + contextWindow: 1000000, + maxTokens: 128000, + } satisfies Model<"bedrock-converse-stream">, "anthropic.claude-haiku-4-5-20251001-v1:0": { id: "anthropic.claude-haiku-4-5-20251001-v1:0", name: "Claude Haiku 4.5", @@ -637,6 +655,24 @@ export const MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"bedrock-converse-stream">, + "global.anthropic.claude-fable-5-1": { + id: "global.anthropic.claude-fable-5-1", + name: "Claude Fable 5.1 (Global)", + api: "bedrock-converse-stream", + provider: "amazon-bedrock", + baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com", + reasoning: true, + thinkingLevelMap: {"off":null,"xhigh":"xhigh","max":"max"}, + input: ["text", "image"], + cost: { + input: 10, + output: 50, + cacheRead: 0.25, + cacheWrite: 12.5, + }, + contextWindow: 1000000, + maxTokens: 128000, + } satisfies Model<"bedrock-converse-stream">, "global.anthropic.claude-haiku-4-5-20251001-v1:0": { id: "global.anthropic.claude-haiku-4-5-20251001-v1:0", name: "Claude Haiku 4.5 (Global)", @@ -1728,6 +1764,24 @@ export const MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"bedrock-converse-stream">, + "us.anthropic.claude-fable-5-1": { + id: "us.anthropic.claude-fable-5-1", + name: "Claude Fable 5.1 (US)", + api: "bedrock-converse-stream", + provider: "amazon-bedrock", + baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com", + reasoning: true, + thinkingLevelMap: {"off":null,"xhigh":"xhigh","max":"max"}, + input: ["text", "image"], + cost: { + input: 11, + output: 55, + cacheRead: 0.275, + cacheWrite: 13.75, + }, + contextWindow: 1000000, + maxTokens: 128000, + } satisfies Model<"bedrock-converse-stream">, "us.anthropic.claude-haiku-4-5-20251001-v1:0": { id: "us.anthropic.claude-haiku-4-5-20251001-v1:0", name: "Claude Haiku 4.5 (US)", @@ -2094,6 +2148,24 @@ export const MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"anthropic-messages">, + "claude-fable-5-1": { + id: "claude-fable-5-1", + name: "Claude Fable 5.1", + api: "anthropic-messages", + provider: "anthropic", + baseUrl: "https://api.anthropic.com", + reasoning: true, + thinkingLevelMap: {"off":null,"xhigh":"xhigh","max":"max"}, + input: ["text", "image"], + cost: { + input: 10, + output: 50, + cacheRead: 0.25, + cacheWrite: 12.5, + }, + contextWindow: 1000000, + maxTokens: 128000, + } satisfies Model<"anthropic-messages">, "claude-haiku-4-5": { id: "claude-haiku-4-5", name: "Claude Haiku 4.5 (latest)", @@ -3904,6 +3976,24 @@ export const MODELS = { contextWindow: 262144, maxTokens: 256000, } satisfies Model<"openai-completions">, + "@cf/zai-org/glm-5.3": { + id: "@cf/zai-org/glm-5.3", + name: "Glm 5.3", + api: "openai-completions", + provider: "cloudflare-workers-ai", + baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1", + compat: {"sendSessionAffinityHeaders":true}, + reasoning: true, + input: ["text"], + cost: { + input: 1.4, + output: 4.4, + cacheRead: 0.26, + cacheWrite: 0, + }, + contextWindow: 1310720, + maxTokens: 1310720, + } satisfies Model<"openai-completions">, "@cf/zai-org/glm-5.3-flash": { id: "@cf/zai-org/glm-5.3-flash", name: "Glm 5.3 Flash", @@ -3920,7 +4010,7 @@ export const MODELS = { cacheWrite: 0, }, contextWindow: 1310720, - maxTokens: 1310720, + maxTokens: 1048576, } satisfies Model<"openai-completions">, }, "deepseek": { @@ -3964,23 +4054,6 @@ export const MODELS = { } satisfies Model<"openai-completions">, }, "fireworks": { - "accounts/fireworks/models/deepseek-v4-flash": { - id: "accounts/fireworks/models/deepseek-v4-flash", - name: "DeepSeek V4 Flash", - api: "anthropic-messages", - provider: "fireworks", - baseUrl: "https://api.fireworks.ai/inference", - reasoning: true, - input: ["text"], - cost: { - input: 0.14, - output: 0.28, - cacheRead: 0.028, - cacheWrite: 0, - }, - contextWindow: 1000000, - maxTokens: 384000, - } satisfies Model<"anthropic-messages">, "accounts/fireworks/models/deepseek-v4-flash-0731": { id: "accounts/fireworks/models/deepseek-v4-flash-0731", name: "DeepSeek V4 Flash 0731", @@ -3990,9 +4063,9 @@ export const MODELS = { reasoning: true, input: ["text"], cost: { - input: 0.14, - output: 0.28, - cacheRead: 0.028, + input: 0.22, + output: 0.66, + cacheRead: 0.007, cacheWrite: 0, }, contextWindow: 1000000, @@ -4032,6 +4105,40 @@ export const MODELS = { contextWindow: 1048575, maxTokens: 131072, } satisfies Model<"anthropic-messages">, + "accounts/fireworks/models/glm-5p3": { + id: "accounts/fireworks/models/glm-5p3", + name: "GLM 5.3", + api: "anthropic-messages", + provider: "fireworks", + baseUrl: "https://api.fireworks.ai/inference", + reasoning: true, + input: ["text"], + cost: { + input: 1.4, + output: 4.4, + cacheRead: 0.26, + cacheWrite: 0, + }, + contextWindow: 1000000, + maxTokens: 131072, + } satisfies Model<"anthropic-messages">, + "accounts/fireworks/models/glm-5p3-flash": { + id: "accounts/fireworks/models/glm-5p3-flash", + name: "GLM 5.3 Flash", + api: "anthropic-messages", + provider: "fireworks", + baseUrl: "https://api.fireworks.ai/inference", + reasoning: true, + input: ["text", "image"], + cost: { + input: 0.15, + output: 0.5, + cacheRead: 0.029, + cacheWrite: 0, + }, + contextWindow: 1000000, + maxTokens: 131072, + } satisfies Model<"anthropic-messages">, "accounts/fireworks/models/gpt-oss-120b": { id: "accounts/fireworks/models/gpt-oss-120b", name: "GPT OSS 120B", @@ -5133,23 +5240,6 @@ export const MODELS = { contextWindow: 1048576, maxTokens: 65536, } satisfies Model<"google-generative-ai">, - "gemini-robotics-er-1.6-preview": { - id: "gemini-robotics-er-1.6-preview", - name: "Gemini Robotics-ER 1.6 Preview", - api: "google-generative-ai", - provider: "google", - baseUrl: "https://generativelanguage.googleapis.com/v1beta", - reasoning: true, - input: ["text", "image"], - cost: { - input: 1, - output: 5, - cacheRead: 0, - cacheWrite: 0, - }, - contextWindow: 131072, - maxTokens: 65536, - } satisfies Model<"google-generative-ai">, "gemma-4-26b-a4b-it": { id: "gemma-4-26b-a4b-it", name: "Gemma 4 26B A4B IT", @@ -5517,6 +5607,23 @@ export const MODELS = { contextWindow: 131072, maxTokens: 16384, } satisfies Model<"openai-completions">, + "qwen/qwen3.8-27b": { + id: "qwen/qwen3.8-27b", + name: "Qwen3.8 27B", + api: "openai-completions", + provider: "groq", + baseUrl: "https://api.groq.com/openai/v1", + reasoning: true, + input: ["text", "image"], + cost: { + input: 0.8, + output: 4, + cacheRead: 0, + cacheWrite: 0, + }, + contextWindow: 131042, + maxTokens: 16384, + } satisfies Model<"openai-completions">, }, "huggingface": { "MiniMaxAI/MiniMax-M2": { @@ -6744,6 +6851,24 @@ export const MODELS = { contextWindow: 262144, maxTokens: 131072, } satisfies Model<"openai-completions">, + "zai-org/GLM-5.3": { + id: "zai-org/GLM-5.3", + name: "GLM-5.3", + api: "openai-completions", + provider: "huggingface", + baseUrl: "https://router.huggingface.co/v1", + compat: {"supportsDeveloperRole":false}, + reasoning: true, + input: ["text"], + cost: { + input: 1.4, + output: 4.4, + cacheRead: 0, + cacheWrite: 0, + }, + contextWindow: 1048576, + maxTokens: 131072, + } satisfies Model<"openai-completions">, "zai-org/GLM-5.3-Flash": { id: "zai-org/GLM-5.3-Flash", name: "GLM-5.3-Flash", @@ -6752,7 +6877,7 @@ export const MODELS = { baseUrl: "https://router.huggingface.co/v1", compat: {"supportsDeveloperRole":false}, reasoning: true, - input: ["text"], + input: ["text", "image"], cost: { input: 0.15, output: 0.5, @@ -8816,6 +8941,24 @@ export const MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"anthropic-messages">, + "claude-fable-5-1": { + id: "claude-fable-5-1", + name: "Claude Fable 5.1", + api: "anthropic-messages", + provider: "opencode", + baseUrl: "https://opencode.ai/zen", + reasoning: true, + thinkingLevelMap: {"off":null,"xhigh":"xhigh","max":"max"}, + input: ["text", "image"], + cost: { + input: 10, + output: 50, + cacheRead: 0.25, + cacheWrite: 12.5, + }, + contextWindow: 1000000, + maxTokens: 128000, + } satisfies Model<"anthropic-messages">, "claude-haiku-4-5": { id: "claude-haiku-4-5", name: "Claude Haiku 4.5", @@ -9582,23 +9725,6 @@ export const MODELS = { contextWindow: 256000, maxTokens: 256000, } satisfies Model<"openai-responses">, - "hy3-free": { - id: "hy3-free", - name: "Hy3 Free", - api: "openai-completions", - provider: "opencode", - baseUrl: "https://opencode.ai/zen/v1", - reasoning: true, - input: ["text"], - cost: { - input: 0, - output: 0, - cacheRead: 0, - cacheWrite: 0, - }, - contextWindow: 190000, - maxTokens: 64000, - } satisfies Model<"openai-completions">, "kimi-k2.5": { id: "kimi-k2.5", name: "Kimi K2.5", @@ -9668,6 +9794,23 @@ export const MODELS = { contextWindow: 1048576, maxTokens: 131072, } satisfies Model<"openai-completions">, + "ling-3.0-flash-fin-free": { + id: "ling-3.0-flash-fin-free", + name: "Ling 3.0 Flash Fin Free", + api: "openai-completions", + provider: "opencode", + baseUrl: "https://opencode.ai/zen/v1", + reasoning: true, + input: ["text"], + cost: { + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + }, + contextWindow: 262144, + maxTokens: 32768, + } satisfies Model<"openai-completions">, "mimo-v2.5-free": { id: "mimo-v2.5-free", name: "MiMo V2.5 Free", @@ -10002,21 +10145,38 @@ export const MODELS = { } satisfies Model<"openai-responses">, "hy3": { id: "hy3", - name: "Hy3 (8x usage)", + name: "Hy3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { - input: 0.0175, - output: 0.0725, - cacheRead: 0.004375, + input: 0.14, + output: 0.58, + cacheRead: 0.035, cacheWrite: 0, }, contextWindow: 256000, maxTokens: 64000, } satisfies Model<"openai-completions">, + "hy4-preview": { + id: "hy4-preview", + name: "Hy4 preview", + api: "openai-completions", + provider: "opencode-go", + baseUrl: "https://opencode.ai/zen/go/v1", + reasoning: true, + input: ["text"], + cost: { + input: 0.834, + output: 2.501, + cacheRead: 0.042, + cacheWrite: 0, + }, + contextWindow: 1024000, + maxTokens: 64000, + } satisfies Model<"openai-completions">, "kimi-k2.6": { id: "kimi-k2.6", name: "Kimi K2.6", @@ -10438,6 +10598,24 @@ export const MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"openai-completions">, + "anthropic/claude-fable-5.1": { + id: "anthropic/claude-fable-5.1", + name: "Anthropic: Claude Fable 5.1", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + reasoning: true, + thinkingLevelMap: {"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"}, + input: ["text", "image"], + cost: { + input: 10, + output: 50, + cacheRead: 0.25, + cacheWrite: 12.5, + }, + contextWindow: 1000000, + maxTokens: 128000, + } satisfies Model<"openai-completions">, "anthropic/claude-haiku-4.5": { id: "anthropic/claude-haiku-4.5", name: "Anthropic: Claude Haiku 4.5", @@ -10550,9 +10728,9 @@ export const MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"openai-completions">, - "anthropic/claude-opus-4.7-fast": { - id: "anthropic/claude-opus-4.7-fast", - name: "Anthropic: Claude Opus 4.7 (Fast)", + "anthropic/claude-opus-4.8": { + id: "anthropic/claude-opus-4.8", + name: "Anthropic: Claude Opus 4.8", api: "openai-completions", provider: "openrouter", baseUrl: "https://openrouter.ai/api/v1", @@ -10560,46 +10738,10 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"}, input: ["text", "image"], cost: { - input: 30, - output: 150, - cacheRead: 3, - cacheWrite: 37.5, - }, - contextWindow: 1000000, - maxTokens: 128000, - } satisfies Model<"openai-completions">, - "anthropic/claude-opus-4.8": { - id: "anthropic/claude-opus-4.8", - name: "Anthropic: Claude Opus 4.8", - api: "openai-completions", - provider: "openrouter", - baseUrl: "https://openrouter.ai/api/v1", - reasoning: true, - thinkingLevelMap: {"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"}, - input: ["text", "image"], - cost: { - input: 5, - output: 25, - cacheRead: 0.5, - cacheWrite: 6.25, - }, - contextWindow: 1000000, - maxTokens: 128000, - } satisfies Model<"openai-completions">, - "anthropic/claude-opus-4.8-fast": { - id: "anthropic/claude-opus-4.8-fast", - name: "Anthropic: Claude Opus 4.8 (Fast)", - api: "openai-completions", - provider: "openrouter", - baseUrl: "https://openrouter.ai/api/v1", - reasoning: true, - thinkingLevelMap: {"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"}, - input: ["text", "image"], - cost: { - input: 10, - output: 50, - cacheRead: 1, - cacheWrite: 12.5, + input: 5, + output: 25, + cacheRead: 0.5, + cacheWrite: 6.25, }, contextWindow: 1000000, maxTokens: 128000, @@ -10622,24 +10764,6 @@ export const MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"openai-completions">, - "anthropic/claude-opus-5-fast": { - id: "anthropic/claude-opus-5-fast", - name: "Claude Opus 5 (Fast)", - api: "openai-completions", - provider: "openrouter", - baseUrl: "https://openrouter.ai/api/v1", - reasoning: true, - thinkingLevelMap: {"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"}, - input: ["text", "image"], - cost: { - input: 10, - output: 50, - cacheRead: 1, - cacheWrite: 12.5, - }, - contextWindow: 1000000, - maxTokens: 128000, - } satisfies Model<"openai-completions">, "anthropic/claude-sonnet-4": { id: "anthropic/claude-sonnet-4", name: "Anthropic: Claude Sonnet 4", @@ -10725,30 +10849,13 @@ export const MODELS = { thinkingLevelMap: {"off":null,"minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":null}, input: ["text"], cost: { - input: 0.22, - output: 0.85, + input: 0.25, + output: 0.7999999999999999, cacheRead: 0.06, cacheWrite: 0, }, contextWindow: 262144, - maxTokens: 235929, - } satisfies Model<"openai-completions">, - "arcee-ai/virtuoso-large": { - id: "arcee-ai/virtuoso-large", - name: "Arcee AI: Virtuoso Large", - api: "openai-completions", - provider: "openrouter", - baseUrl: "https://openrouter.ai/api/v1", - reasoning: false, - input: ["text"], - cost: { - input: 0.75, - output: 1.2, - cacheRead: 0, - cacheWrite: 0, - }, - contextWindow: 131072, - maxTokens: 64000, + maxTokens: 80000, } satisfies Model<"openai-completions">, "auto": { id: "auto", @@ -11090,9 +11197,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 0.088606, - output: 0.177212, - cacheRead: 0.017721200000000003, + input: 0.07168000000000001, + output: 0.14336000000000002, + cacheRead: 0.014336, cacheWrite: 0, }, contextWindow: 1048576, @@ -11109,9 +11216,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 0.07, - output: 0.14, - cacheRead: 0.014, + input: 0.065, + output: 0.18, + cacheRead: 0.016, cacheWrite: 0, }, contextWindow: 1310720, @@ -11128,9 +11235,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text", "image"], cost: { - input: 0.44, - output: 1.32, - cacheRead: 0.014, + input: 0.22, + output: 0.66, + cacheRead: 0.007, cacheWrite: 0, }, contextWindow: 1048576, @@ -11147,9 +11254,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 0.87, - output: 1.74, - cacheRead: 0.0725, + input: 1.0241639999999999, + output: 2.0483279999999997, + cacheRead: 0.085347, cacheWrite: 0, }, contextWindow: 1048576, @@ -11166,9 +11273,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 1.32, - output: 3.9600000000000004, - cacheRead: 0.044, + input: 0.66, + output: 1.9800000000000002, + cacheRead: 0.022, cacheWrite: 0, }, contextWindow: 1048576, @@ -11461,10 +11568,10 @@ export const MODELS = { thinkingLevelMap: {"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null}, input: ["text", "image"], cost: { - input: 0.375, - output: 1.875, - cacheRead: 0.0375, - cacheWrite: 0.0208333333333333, + input: 0.75, + output: 3.75, + cacheRead: 0.075, + cacheWrite: 0.0416666666666667, }, contextWindow: 1048576, maxTokens: 65536, @@ -11500,7 +11607,7 @@ export const MODELS = { cacheRead: 0.04, cacheWrite: 0, }, - contextWindow: 262144, + contextWindow: 131072, maxTokens: 117964, } satisfies Model<"openai-completions">, "google/gemma-4-26b-a4b-it": { @@ -11596,6 +11703,24 @@ export const MODELS = { contextWindow: 131072, maxTokens: 117964, } satisfies Model<"openai-completions">, + "ibm-granite/granite-4.2-8b": { + id: "ibm-granite/granite-4.2-8b", + name: "IBM: Granite 4.2 8B", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + reasoning: true, + thinkingLevelMap: {"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":null}, + input: ["text"], + cost: { + input: 0.09999999999999999, + output: 0.15, + cacheRead: 0.049999999999999996, + cacheWrite: 0, + }, + contextWindow: 131072, + maxTokens: 117964, + } satisfies Model<"openai-completions">, "inception/mercury-2": { id: "inception/mercury-2", name: "Inception: Mercury 2", @@ -11614,6 +11739,24 @@ export const MODELS = { contextWindow: 128000, maxTokens: 50000, } satisfies Model<"openai-completions">, + "inception/mercury-2.5-preview": { + id: "inception/mercury-2.5-preview", + name: "Inception: Mercury 2.5 Preview", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + reasoning: true, + thinkingLevelMap: {"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null}, + input: ["text"], + cost: { + input: 0.04, + output: 0.15, + cacheRead: 0.004, + cacheWrite: 0, + }, + contextWindow: 260000, + maxTokens: 65536, + } satisfies Model<"openai-completions">, "inclusionai/ling-3.0-flash": { id: "inclusionai/ling-3.0-flash", name: "Ling-3.0-flash", @@ -11652,23 +11795,6 @@ export const MODELS = { contextWindow: 262144, maxTokens: 32768, } satisfies Model<"openai-completions">, - "kwaipilot/kat-coder-air-v2.5": { - id: "kwaipilot/kat-coder-air-v2.5", - name: "Kwaipilot: KAT-Coder-Air V2.5", - api: "openai-completions", - provider: "openrouter", - baseUrl: "https://openrouter.ai/api/v1", - reasoning: false, - input: ["text"], - cost: { - input: 0.15, - output: 0.6, - cacheRead: 0.03, - cacheWrite: 0, - }, - contextWindow: 256000, - maxTokens: 80000, - } satisfies Model<"openai-completions">, "kwaipilot/kat-coder-pro-v2": { id: "kwaipilot/kat-coder-pro-v2", name: "Kwaipilot: KAT-Coder-Pro V2", @@ -11684,7 +11810,7 @@ export const MODELS = { cacheWrite: 0, }, contextWindow: 262144, - maxTokens: 80000, + maxTokens: 144000, } satisfies Model<"openai-completions">, "kwaipilot/kat-coder-pro-v2.5": { id: "kwaipilot/kat-coder-pro-v2.5", @@ -11701,7 +11827,7 @@ export const MODELS = { cacheWrite: 0, }, contextWindow: 262144, - maxTokens: 80000, + maxTokens: 235929, } satisfies Model<"openai-completions">, "liquid/lfm-2.5-2.6b:free": { id: "liquid/lfm-2.5-2.6b:free", @@ -11802,12 +11928,12 @@ export const MODELS = { input: ["text", "image"], cost: { input: 0.19999999999999998, - output: 0.7999999999999999, + output: 0.696, cacheRead: 0, cacheWrite: 0, }, contextWindow: 1048576, - maxTokens: 16384, + maxTokens: 115200, } satisfies Model<"openai-completions">, "meta-llama/llama-4-scout": { id: "meta-llama/llama-4-scout", @@ -11818,13 +11944,13 @@ export const MODELS = { reasoning: false, input: ["text", "image"], cost: { - input: 0.11, - output: 0.33999999999999997, - cacheRead: 0.055, + input: 0.09999999999999999, + output: 0.3, + cacheRead: 0, cacheWrite: 0, }, contextWindow: 1310720, - maxTokens: 8192, + maxTokens: 16384, } satisfies Model<"openai-completions">, "meta/muse-glimmer-30b": { id: "meta/muse-glimmer-30b", @@ -11836,13 +11962,13 @@ export const MODELS = { thinkingLevelMap: {"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null}, input: ["text", "image"], cost: { - input: 0.35, - output: 1.5, + input: 0.3, + output: 1.2, cacheRead: 0.04, cacheWrite: 0, }, contextWindow: 131072, - maxTokens: 117964, + maxTokens: 16384, } satisfies Model<"openai-completions">, "meta/muse-spark-1.1": { id: "meta/muse-spark-1.1", @@ -12076,9 +12202,9 @@ export const MODELS = { reasoning: false, input: ["text"], cost: { - input: 0.44, - output: 2.2, - cacheRead: 0.044, + input: 0.39999999999999997, + output: 2, + cacheRead: 0.04, cacheWrite: 0, }, contextWindow: 262144, @@ -12338,8 +12464,8 @@ export const MODELS = { cacheRead: 0.01, cacheWrite: 0, }, - contextWindow: 32000, - maxTokens: 25600, + contextWindow: 32768, + maxTokens: 26214, } satisfies Model<"openai-completions">, "moonshotai/kimi-k2": { id: "moonshotai/kimi-k2", @@ -12628,13 +12754,13 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":null}, input: ["text"], cost: { - input: 0.09999999999999999, - output: 0.25, - cacheRead: 0.049999999999999996, + input: 0.08, + output: 0.19999999999999998, + cacheRead: 0.04, cacheWrite: 0, }, contextWindow: 262144, - maxTokens: 235929, + maxTokens: 131072, } satisfies Model<"openai-completions">, "nvidia/nemotron-3.5-lightning:free": { id: "nvidia/nemotron-3.5-lightning:free", @@ -14161,13 +14287,13 @@ export const MODELS = { reasoning: false, input: ["text", "image"], cost: { - input: 0.13, - output: 0.52, + input: 0.15, + output: 0.6, cacheRead: 0, cacheWrite: 0, }, contextWindow: 262144, - maxTokens: 32768, + maxTokens: 16384, } satisfies Model<"openai-completions">, "qwen/qwen3-vl-30b-a3b-thinking": { id: "qwen/qwen3-vl-30b-a3b-thinking", @@ -14252,13 +14378,13 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":null}, input: ["text", "image"], cost: { - input: 0.26, - output: 2.08, + input: 0.29, + output: 2.4, cacheRead: 0, cacheWrite: 0, }, contextWindow: 262144, - maxTokens: 235929, + maxTokens: 81920, } satisfies Model<"openai-completions">, "qwen/qwen3.5-27b": { id: "qwen/qwen3.5-27b", @@ -14752,9 +14878,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":null}, input: ["text"], cost: { - input: 0.13199999999999998, - output: 0.5279999999999999, - cacheRead: 0.032999999999999995, + input: 0.0825, + output: 0.33, + cacheRead: 0.020625, cacheWrite: 0, }, contextWindow: 262144, @@ -14823,13 +14949,13 @@ export const MODELS = { thinkingLevelMap: {"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null,"max":"max"}, input: ["text", "image"], cost: { - input: 0.95, + input: 1, output: 4.05, - cacheRead: 0.16, + cacheRead: 0.16999999999999998, cacheWrite: 0, }, contextWindow: 1048576, - maxTokens: 262144, + maxTokens: 471859, } satisfies Model<"openai-completions">, "thinkingmachines/inkling-small": { id: "thinkingmachines/inkling-small", @@ -15235,13 +15361,13 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":null}, input: ["text"], cost: { - input: 1.26, - output: 3.9600000000000004, - cacheRead: 0.234, + input: 0.966, + output: 3.036, + cacheRead: 0.1794, cacheWrite: 0, }, contextWindow: 204800, - maxTokens: 182476, + maxTokens: 128000, } satisfies Model<"openai-completions">, "z-ai/glm-5.2": { id: "z-ai/glm-5.2", @@ -15294,7 +15420,7 @@ export const MODELS = { cacheRead: 0.26, cacheWrite: 0, }, - contextWindow: 1048576, + contextWindow: 1310720, maxTokens: 131072, } satisfies Model<"openai-completions">, "z-ai/glm-5.3-flash": { @@ -15346,7 +15472,7 @@ export const MODELS = { cost: { input: 10, output: 50, - cacheRead: 1, + cacheRead: 0.25, cacheWrite: 12.5, }, contextWindow: 1000000, @@ -15418,9 +15544,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 0.03, - output: 0.09999999999999999, - cacheRead: 0.007, + input: 0.049980000000000004, + output: 0.09996000000000001, + cacheRead: 0.009996000000000001, cacheWrite: 0, }, contextWindow: 1310720, @@ -15436,10 +15562,10 @@ export const MODELS = { thinkingLevelMap: {"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null}, input: ["text", "image"], cost: { - input: 0.375, - output: 1.875, - cacheRead: 0.0375, - cacheWrite: 0.0208333333333333, + input: 0.75, + output: 3.75, + cacheRead: 0.075, + cacheWrite: 0.0416666666666667, }, contextWindow: 1048576, maxTokens: 65536, @@ -15544,13 +15670,13 @@ export const MODELS = { thinkingLevelMap: {"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":"max"}, input: ["text"], cost: { - input: 1.4, - output: 4.4, - cacheRead: 0.26, + input: 1.17, + output: 3.9600000000000004, + cacheRead: 0.234, cacheWrite: 0, }, - contextWindow: 1048576, - maxTokens: 131072, + contextWindow: 1310720, + maxTokens: 943718, } satisfies Model<"openai-completions">, }, "prime-inference": { @@ -16129,7 +16255,7 @@ export const MODELS = { cacheRead: 0, cacheWrite: 0, }, - contextWindow: 262144, + contextWindow: 131072, maxTokens: 117964, } satisfies Model<"openai-completions">, "meta-llama/Llama-3.2-1B-Instruct": { @@ -16202,7 +16328,26 @@ export const MODELS = { cacheWrite: 0, }, contextWindow: 1048576, - maxTokens: 16384, + maxTokens: 115200, + } satisfies Model<"openai-completions">, + "meta/muse-spark-1.2": { + id: "meta/muse-spark-1.2", + name: "Muse Spark 1.2", + api: "openai-completions", + provider: "prime-inference", + baseUrl: "https://api.pinference.ai/api/v1", + compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","supportsStrictMode":false}, + reasoning: true, + thinkingLevelMap: {"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null}, + input: ["text", "image"], + cost: { + input: 1.25, + output: 4.25, + cacheRead: 0, + cacheWrite: 0, + }, + contextWindow: 1048576, + maxTokens: 943718, } satisfies Model<"openai-completions">, "minimax/minimax-m2.5": { id: "minimax/minimax-m2.5", @@ -16824,8 +16969,8 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"}, input: ["text", "image"], cost: { - input: 1, - output: 6, + input: 0.2, + output: 1.2, cacheRead: 0, cacheWrite: 0, }, @@ -17169,7 +17314,7 @@ export const MODELS = { cacheWrite: 0, }, contextWindow: 262144, - maxTokens: 32768, + maxTokens: 16384, } satisfies Model<"openai-completions">, "qwen/qwen3-vl-8b-instruct": { id: "qwen/qwen3-vl-8b-instruct", @@ -17344,6 +17489,25 @@ export const MODELS = { maxTokens: 30000, featured: true, } satisfies Model<"openai-completions">, + "x-ai/grok-4.6": { + id: "x-ai/grok-4.6", + name: "Grok 4.6", + api: "openai-completions", + provider: "prime-inference", + baseUrl: "https://api.pinference.ai/api/v1", + compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","supportsStrictMode":false}, + reasoning: true, + thinkingLevelMap: {"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null}, + input: ["text", "image"], + cost: { + input: 2, + output: 6, + cacheRead: 0, + cacheWrite: 0, + }, + contextWindow: 500000, + maxTokens: 450000, + } satisfies Model<"openai-completions">, "xiaomi/mimo-v2.5": { id: "xiaomi/mimo-v2.5", name: "Mimo V2.5", @@ -17514,7 +17678,7 @@ export const MODELS = { cacheWrite: 0, }, contextWindow: 204800, - maxTokens: 182476, + maxTokens: 128000, featured: true, } satisfies Model<"openai-completions">, "z-ai/glm-5.2": { @@ -17553,7 +17717,7 @@ export const MODELS = { cacheRead: 0, cacheWrite: 0, }, - contextWindow: 1048576, + contextWindow: 1310720, maxTokens: 131072, } satisfies Model<"openai-completions">, "z-ai/glm-5.3-flash": { @@ -18013,11 +18177,11 @@ export const MODELS = { cost: { input: 2, output: 6, - cacheRead: 0.19999999999999998, + cacheRead: 0.25, cacheWrite: 0, }, contextWindow: 262144, - maxTokens: 131072, + maxTokens: 128000, } satisfies Model<"anthropic-messages">, "alibaba/qwen3.8-27b": { id: "alibaba/qwen3.8-27b", @@ -18028,10 +18192,10 @@ export const MODELS = { reasoning: true, input: ["text", "image"], cost: { - input: 0.55, - output: 3.3000000000000003, - cacheRead: 0.11, - cacheWrite: 0, + input: 0.5, + output: 3, + cacheRead: 0.09999999999999999, + cacheWrite: 0.625, }, contextWindow: 1000000, maxTokens: 131072, @@ -18053,6 +18217,23 @@ export const MODELS = { contextWindow: 991000, maxTokens: 128000, } satisfies Model<"anthropic-messages">, + "alibaba/qwen3.8-flash-next": { + id: "alibaba/qwen3.8-flash-next", + name: "Qwen 3.8 Flash Next", + api: "anthropic-messages", + provider: "vercel-ai-gateway", + baseUrl: "https://ai-gateway.vercel.sh", + reasoning: true, + input: ["text", "image"], + cost: { + input: 0.12, + output: 0.39999999999999997, + cacheRead: 0.01, + cacheWrite: 0, + }, + contextWindow: 1048576, + maxTokens: 1048576, + } satisfies Model<"anthropic-messages">, "alibaba/qwen3.8-max": { id: "alibaba/qwen3.8-max", name: "Qwen 3.8 Max", @@ -18173,6 +18354,24 @@ export const MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"anthropic-messages">, + "anthropic/claude-fable-5.1": { + id: "anthropic/claude-fable-5.1", + name: "Claude Fable 5.1", + api: "anthropic-messages", + provider: "vercel-ai-gateway", + baseUrl: "https://ai-gateway.vercel.sh", + reasoning: true, + thinkingLevelMap: {"off":null,"xhigh":"xhigh","max":"max"}, + input: ["text", "image"], + cost: { + input: 10, + output: 50, + cacheRead: 0.25, + cacheWrite: 12.5, + }, + contextWindow: 1000000, + maxTokens: 128000, + } satisfies Model<"anthropic-messages">, "anthropic/claude-haiku-4.5": { id: "anthropic/claude-haiku-4.5", name: "Claude Haiku 4.5", @@ -18487,23 +18686,6 @@ export const MODELS = { contextWindow: 128000, maxTokens: 8192, } satisfies Model<"anthropic-messages">, - "deepseek/deepseek-v3": { - id: "deepseek/deepseek-v3", - name: "DeepSeek V3 0324", - api: "anthropic-messages", - provider: "vercel-ai-gateway", - baseUrl: "https://ai-gateway.vercel.sh", - reasoning: false, - input: ["text"], - cost: { - input: 0.27, - output: 1.12, - cacheRead: 0.135, - cacheWrite: 0, - }, - contextWindow: 163840, - maxTokens: 163840, - } satisfies Model<"anthropic-messages">, "deepseek/deepseek-v3.1": { id: "deepseek/deepseek-v3.1", name: "DeepSeek V3.1", @@ -18620,8 +18802,8 @@ export const MODELS = { cacheRead: 0.007, cacheWrite: 0, }, - contextWindow: 1000000, - maxTokens: 384000, + contextWindow: 1048576, + maxTokens: 1048576, } satisfies Model<"anthropic-messages">, "deepseek/deepseek-v4-pro": { id: "deepseek/deepseek-v4-pro", @@ -18632,13 +18814,13 @@ export const MODELS = { reasoning: true, input: ["text"], cost: { - input: 1.74, - output: 3.48, - cacheRead: 0.14, + input: 0.66, + output: 1.9800000000000002, + cacheRead: 0.022, cacheWrite: 0, }, - contextWindow: 1048600, - maxTokens: 1048600, + contextWindow: 1000000, + maxTokens: 384000, } satisfies Model<"anthropic-messages">, "deepseek/deepseek-v4-pro-0813": { id: "deepseek/deepseek-v4-pro-0813", @@ -19271,7 +19453,7 @@ export const MODELS = { } satisfies Model<"anthropic-messages">, "minimax/minimax-m2.7": { id: "minimax/minimax-m2.7", - name: "Minimax M2.7", + name: "MiniMax M2.7", api: "anthropic-messages", provider: "vercel-ai-gateway", baseUrl: "https://ai-gateway.vercel.sh", @@ -19288,7 +19470,7 @@ export const MODELS = { } satisfies Model<"anthropic-messages">, "minimax/minimax-m2.7-free": { id: "minimax/minimax-m2.7-free", - name: "Minimax M2.7 (Free)", + name: "MiniMax M2.7 (Free)", api: "anthropic-messages", provider: "vercel-ai-gateway", baseUrl: "https://ai-gateway.vercel.sh", @@ -19334,8 +19516,8 @@ export const MODELS = { cacheRead: 0.06, cacheWrite: 0, }, - contextWindow: 1000000, - maxTokens: 1000000, + contextWindow: 512000, + maxTokens: 512000, } satisfies Model<"anthropic-messages">, "minimax/minimax-m3-free": { id: "minimax/minimax-m3-free", @@ -19637,7 +19819,7 @@ export const MODELS = { cost: { input: 0.95, output: 4, - cacheRead: 0.19, + cacheRead: 0.16, cacheWrite: 0, }, contextWindow: 256000, @@ -19757,8 +19939,8 @@ export const MODELS = { input: ["text"], cost: { input: 0.049999999999999996, - output: 0.15, - cacheRead: 0.049999999999999996, + output: 0.19999999999999998, + cacheRead: 0.01, cacheWrite: 0, }, contextWindow: 262144, @@ -21086,13 +21268,30 @@ export const MODELS = { reasoning: true, input: ["text"], cost: { - input: 0.13199999999999998, - output: 0.5279999999999999, - cacheRead: 0.032999999999999995, + input: 0.14, + output: 0.58, + cacheRead: 0.035, cacheWrite: 0, }, - contextWindow: 256000, - maxTokens: 128000, + contextWindow: 262144, + maxTokens: 262144, + } satisfies Model<"anthropic-messages">, + "tencent/hy4-preview": { + id: "tencent/hy4-preview", + name: "Tencent Hy4 Preview", + api: "anthropic-messages", + provider: "vercel-ai-gateway", + baseUrl: "https://ai-gateway.vercel.sh", + reasoning: true, + input: ["text"], + cost: { + input: 0.834, + output: 2.501, + cacheRead: 0.041999999999999996, + cacheWrite: 0, + }, + contextWindow: 1024000, + maxTokens: 64000, } satisfies Model<"anthropic-messages">, "thinkingmachines/inkling": { id: "thinkingmachines/inkling", @@ -21162,6 +21361,23 @@ export const MODELS = { contextWindow: 1050000, maxTokens: 131000, } satisfies Model<"anthropic-messages">, + "xiaomi/mimo-v2.5-pro-ultraspeed": { + id: "xiaomi/mimo-v2.5-pro-ultraspeed", + name: "MiMo V2.5 Pro UltraSpeed", + api: "anthropic-messages", + provider: "vercel-ai-gateway", + baseUrl: "https://ai-gateway.vercel.sh", + reasoning: true, + input: ["text"], + cost: { + input: 1.305, + output: 2.61, + cacheRead: 0.0108, + cacheWrite: 0, + }, + contextWindow: 1048576, + maxTokens: 131072, + } satisfies Model<"anthropic-messages">, "zai/glm-4.5": { id: "zai/glm-4.5", name: "GLM 4.5", @@ -21377,11 +21593,11 @@ export const MODELS = { cost: { input: 1.4, output: 4.4, - cacheRead: 0.26, + cacheRead: 0.14, cacheWrite: 0, }, contextWindow: 1000000, - maxTokens: 12800, + maxTokens: 1000000, } satisfies Model<"anthropic-messages">, "zai/glm-5.3-flash": { id: "zai/glm-5.3-flash", From b4613f02a91417bae6aab43faaf18a79ffbd2672 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 17:49:14 -0400 Subject: [PATCH 11/31] fix(coding-agent): stabilize Python skill diagnostics --- packages/coding-agent/src/core/skills.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/src/core/skills.ts b/packages/coding-agent/src/core/skills.ts index d8b2bd28cf..85316240fa 100644 --- a/packages/coding-agent/src/core/skills.ts +++ b/packages/coding-agent/src/core/skills.ts @@ -550,9 +550,10 @@ export function loadSkills(options: LoadSkillsOptions): LoadSkillsResult { if (skill.kind === "python") { const existingPythonSkill = pythonImportMap.get(skill.python.importName); if (existingPythonSkill) { + const [firstName, secondName] = [existingPythonSkill.name, skill.name].sort(); pythonImportDiagnostics.push({ type: "warning", - message: `python import name "${skill.python.importName}" is shared by skills "${existingPythonSkill.name}" and "${skill.name}"`, + message: `python import name "${skill.python.importName}" is shared by skills "${firstName}" and "${secondName}"`, path: skill.filePath, }); } else { From b80a52bf621bf534a04a780633d88b2fd6d9e62c Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 18:21:01 -0400 Subject: [PATCH 12/31] fix: harden binary release and installer paths --- .github/workflows/build-binaries.yml | 6 +- install.sh | 40 +++--- packages/coding-agent/docs/quickstart.md | 2 +- packages/coding-agent/docs/termux.md | 2 +- packages/coding-agent/scripts/copy-assets.ts | 4 +- .../coding-agent/src/core/kernel/bootstrap.ts | 10 +- .../test/bun-installer-e2e.test.ts | 54 +++++++- .../test/bun-release-archives.test.ts | 51 ++++++- .../test/compiled-artifact-smoke.test.ts | 4 + .../test/kernel-bootstrap.test.ts | 11 ++ scripts/assemble-release-archives.mjs | 66 ++++++++-- scripts/build-binaries.sh | 5 +- scripts/pack-prime-agent-release.mjs | 124 +++++++++++++++++- 13 files changed, 335 insertions(+), 44 deletions(-) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index af5cd25a98..da13297546 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -344,7 +344,8 @@ jobs: test -n "$R2_BUCKET" test -n "$R2_ENDPOINT_URL" - for artifact in "$PRODUCTION_DIR"/*.tar.gz; do + for artifact in "$PRODUCTION_DIR"/*.tar.gz "$PRODUCTION_DIR"/*.tgz; do + test -f "$artifact" || continue aws s3 cp "$artifact" "s3://${R2_BUCKET}/${RELEASE_PREFIX}/$(basename "$artifact")" \ --endpoint-url "$R2_ENDPOINT_URL" \ --content-type application/gzip \ @@ -410,7 +411,8 @@ jobs: test -n "$R2_BUCKET" test -n "$R2_ENDPOINT_URL" - for artifact in "$BETA_DIR"/*.tar.gz; do + for artifact in "$BETA_DIR"/*.tar.gz "$BETA_DIR"/*.tgz; do + test -f "$artifact" || continue aws s3 cp "$artifact" "s3://${R2_BUCKET}/${RELEASE_PREFIX}/$(basename "$artifact")" \ --endpoint-url "$R2_ENDPOINT_URL" \ --content-type application/gzip \ diff --git a/install.sh b/install.sh index c2bbce253f..450211c37e 100755 --- a/install.sh +++ b/install.sh @@ -1624,17 +1624,21 @@ prime_agent_detect_binary_platform() { case "$_arch" in x86_64|amd64) printf 'darwin-x64' ;; arm64|aarch64) printf 'darwin-arm64' ;; - *) return 1 ;; + *) printf 'error: unsupported macOS architecture for binary install: %s\n' "$_arch" >&2; return 1 ;; esac ;; Linux) + if [ -f /etc/alpine-release ] || { command -v ldd >/dev/null 2>&1 && ldd --version 2>&1 | grep -qi musl; }; then + printf 'error: Prime Agent binaries require glibc Linux; use --method=npm on musl systems.\n' >&2 + return 1 + fi case "$_arch" in x86_64|amd64) printf 'linux-x64' ;; arm64|aarch64) printf 'linux-arm64' ;; - *) return 1 ;; + *) printf 'error: unsupported Linux architecture for binary install: %s\n' "$_arch" >&2; return 1 ;; esac ;; - *) return 1 ;; + *) printf 'error: unsupported platform for binary install: %s %s\n' "$_os" "$_arch" >&2; return 1 ;; esac } @@ -1677,7 +1681,6 @@ prime_agent_binary_fresh_install() { _version="$(resolve_prime_agent_version "$@")" _platform= if ! _platform=$(prime_agent_detect_binary_platform); then - printf 'error: unsupported platform for binary install: %s %s\n' "$(uname -s)" "$(uname -m)" >&2 exit 1 fi _artifact_name="$(prime_agent_binary_artifact_name "$_version" "$_platform")" @@ -1800,7 +1803,6 @@ prime_agent_binary_update() { _platform= if ! _platform=$(prime_agent_detect_binary_platform); then - printf 'error: unsupported platform for binary update: %s %s\n' "$(uname -s)" "$(uname -m)" >&2 exit 1 fi _artifact_name="$(prime_agent_binary_artifact_name "$_update_version" "$_platform")" @@ -1893,8 +1895,20 @@ prime_agent_binary_update() { prime_agent_binary_rollback_version="$_old_version_dir" fi - # Atomically switch the symlink + # Atomically switch the symlink, then verify the activated path. If activation + # fails, restore the previous immutable version before returning an error. prime_agent_binary_atomic_symlink "$_binary_path" "$prime_agent_binary_symlink" + if ! prime_agent_binary_smoke_binary "$prime_agent_binary_symlink"; then + if prime_agent_binary_rollback; then + rm -rf "$_version_dir" + printf 'error: activation failed; restored the previous Prime Agent version.\n' >&2 + else + printf 'error: activation failed and no healthy rollback version was available.\n' >&2 + fi + rm -rf "$_download_dir" + prime_agent_download_dir= + exit 1 + fi rm -rf "$_download_dir" prime_agent_download_dir= @@ -1962,16 +1976,10 @@ prime_agent_configure_binary_path() { fi _bin_dir=$(dirname "$prime_agent_binary_symlink") - case ":$PATH:" in - *":$_bin_dir:"*) - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "Run it with: $prime_agent_cmd" "" - else - printf '\nRun it with: %s\n' "$prime_agent_cmd" - fi - return - ;; - esac + if [ -n "${_existing_path:-}" ] && [ "$_existing_path" != "$prime_agent_binary_symlink" ]; then + printf 'warning: %s at %s currently shadows the new binary at %s.\n' \ + "$prime_agent_cmd" "$_existing_path" "$prime_agent_binary_symlink" >&2 + fi if [ "$prime_agent_screen_enabled" = 1 ]; then prime_agent_screen "Prime Agent installed" "" "PATH update needed for $prime_agent_cmd." "" diff --git a/packages/coding-agent/docs/quickstart.md b/packages/coding-agent/docs/quickstart.md index bf8db3ec31..9bf314d779 100644 --- a/packages/coding-agent/docs/quickstart.md +++ b/packages/coding-agent/docs/quickstart.md @@ -25,7 +25,7 @@ cd /path/to/project prime-agent ``` -To run a source checkout instead, use Node.js 22.8.0 or newer: +To run a source checkout instead, use Bun 1.3.14: ```bash git clone https://github.com/PrimeIntellect-ai/prime-agent diff --git a/packages/coding-agent/docs/termux.md b/packages/coding-agent/docs/termux.md index db3ab9273e..fd127ac056 100644 --- a/packages/coding-agent/docs/termux.md +++ b/packages/coding-agent/docs/termux.md @@ -14,7 +14,7 @@ Prime Agent runs on Android via [Termux](https://termux.dev/), a terminal emulat pkg update && pkg upgrade # Install dependencies -pkg install nodejs termux-api git ripgrep +pkg install bun termux-api git ripgrep # Clone and install Prime Agent from source git clone https://github.com/PrimeIntellect-ai/prime-agent.git diff --git a/packages/coding-agent/scripts/copy-assets.ts b/packages/coding-agent/scripts/copy-assets.ts index a322995b49..0fdee57c1e 100644 --- a/packages/coding-agent/scripts/copy-assets.ts +++ b/packages/coding-agent/scripts/copy-assets.ts @@ -52,7 +52,9 @@ async function copyBinaryAssets(): Promise { await copyFile(join(repoDir, "install.sh"), distDir); await copyFiles(join(packageDir, "src/modes/interactive/theme"), join(distDir, "theme"), ".json"); await copyFiles(join(packageDir, "src/modes/interactive/assets"), join(distDir, "assets"), ".png"); - await copyFile(join(packageDir, "src/core/export-html/template.html"), join(distDir, "export-html")); + for (const name of ["template.html", "template.css", "template.js"]) { + await copyFile(join(packageDir, "src/core/export-html", name), join(distDir, "export-html")); + } await copyFiles(join(packageDir, "src/core/export-html/vendor"), join(distDir, "export-html/vendor"), ".js"); await replaceDirectory(join(packageDir, "docs"), join(distDir, "docs")); await replaceDirectory(join(packageDir, "examples"), join(distDir, "examples")); diff --git a/packages/coding-agent/src/core/kernel/bootstrap.ts b/packages/coding-agent/src/core/kernel/bootstrap.ts index 16f13fac7d..3c33cf8426 100644 --- a/packages/coding-agent/src/core/kernel/bootstrap.ts +++ b/packages/coding-agent/src/core/kernel/bootstrap.ts @@ -649,12 +649,12 @@ async function writeBootstrapVersion( function runtimeCandidateDirs(): string[] { const moduleDir = path.dirname(fileURLToPath(import.meta.url)); - // dist/prime-agent-runtime is listed first deliberately: it is the only path stable - // across every shipped layout (dist/, dist/bundle/, bun), where import.meta.url-relative - // resolution breaks. `bun run build` rebuilds it from live source (copy-assets does - // rm -rf + cp), so the staleness hash still refreshes on every build. The relative - // paths below cover running from source (tsx) where dist/ hasn't been built. + // Compiled binary releases place the runtime beside the executable. npm bundles + // place it under dist/. `bun run build` refreshes both layouts from live source, + // so the staleness hash still changes with runtime code. The relative paths below + // cover direct source execution where dist/ has not been built. return [ + path.join(getPackageDir(), "prime-agent-runtime"), path.join(getPackageDir(), "dist", "prime-agent-runtime"), path.resolve(moduleDir, "..", "..", "prime-agent-runtime"), path.resolve(moduleDir, "..", "..", "..", "..", "..", "prime-agent-runtime"), diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index 298278cb2b..f9654a9430 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -31,7 +31,11 @@ function makeRelease(root: string, version: string, executable: string, checksum writeFileSync(join(releaseDir, "SHA256SUMS"), `${checksum} ${archiveName}\n`); } -function runInstaller(root: string, args: string[]): { exitCode: number; stdout: string; stderr: string } { +function runInstaller( + root: string, + args: string[], + env: Record = {}, +): { exitCode: number; stdout: string; stderr: string } { const home = join(root, "home"); const versions = join(root, "apps", "versions"); const bin = join(root, "bin"); @@ -45,6 +49,7 @@ function runInstaller(root: string, args: string[]): { exitCode: number; stdout: PRIME_AGENT_VERSIONS_DIR: versions, PRIME_AGENT_BIN_DIR: bin, TERM: "dumb", + ...env, }, encoding: "utf8", }); @@ -101,4 +106,51 @@ describe("compiled binary installer", () => { expect(readlinkSync(link)).toBe(oldTarget); expect(readFileSync(join(root, "home", ".prime", "sentinel"), "utf8")).toBe("user data"); }); + + test("rolls back when the activated symlink fails its smoke test", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + expect(runInstaller(root, ["1.2.3"]).exitCode).toBe(0); + const link = join(root, "bin", "prime-agent"); + const oldTarget = readlinkSync(link); + + makeRelease( + root, + "2.0.0", + '#!/bin/sh\ncase "$0" in */bin/prime-agent) exit 1 ;; esac\nif [ "$1" = "--version" ]; then echo "prime-agent 2.0.0"; exit 0; fi\nexit 0\n', + ); + const result = runInstaller(root, ["--update", "2.0.0"]); + expect(result.exitCode).not.toBe(0); + expect(result.stderr).toContain("restored the previous Prime Agent version"); + expect(readlinkSync(link)).toBe(oldTarget); + }); + + test("rejects glibc binaries on musl Linux before downloading", () => { + if (process.platform !== "linux") return; + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + const tools = join(root, "tools"); + mkdirSync(tools); + writeFileSync(join(tools, "ldd"), '#!/bin/sh\necho "musl libc"\n'); + chmodSync(join(tools, "ldd"), 0o755); + const result = runInstaller(root, ["1.2.3"], { PATH: `${tools}:${process.env.PATH}` }); + expect(result.exitCode).not.toBe(0); + expect(result.stderr).toContain("require glibc Linux"); + }); + + test("warns when an older command shadows the installed binary", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + const tools = join(root, "tools"); + mkdirSync(tools); + writeFileSync(join(tools, "prime-agent"), '#!/bin/sh\necho "old"\n'); + chmodSync(join(tools, "prime-agent"), 0o755); + + const result = runInstaller(root, ["1.2.3"], { PATH: `${tools}:${process.env.PATH}` }); + expect(result.exitCode, result.stderr).toBe(0); + expect(result.stderr).toContain("currently shadows the new binary"); + expect(result.stdout).toContain('export PATH="'); + }); }); diff --git a/packages/coding-agent/test/bun-release-archives.test.ts b/packages/coding-agent/test/bun-release-archives.test.ts index d92b6f9af1..6a98610e56 100644 --- a/packages/coding-agent/test/bun-release-archives.test.ts +++ b/packages/coding-agent/test/bun-release-archives.test.ts @@ -9,6 +9,7 @@ import { readdirSync, readFileSync, rmSync, + symlinkSync, writeFileSync, } from "node:fs"; import { tmpdir } from "node:os"; @@ -89,7 +90,23 @@ describe("compiled release archives", () => { const archives = readdirSync(artifacts).filter((name) => name.endsWith(".tar.gz")); expect(archives.sort()).toEqual(platforms.map((platform) => `prime-agent-1.2.3-${platform}.tar.gz`).sort()); expect(readFileSync(join(artifacts, "stable"), "utf8")).toBe("v1.2.3\n"); - expect(readFileSync(join(artifacts, "SHA256SUMS"), "utf8").trim().split("\n")).toHaveLength(4); + expect(readFileSync(join(artifacts, "SHA256SUMS"), "utf8").trim().split("\n")).toHaveLength(8); + for (const tarball of [ + "prime-agent-1.2.3.tgz", + "prime-agent-ai-1.2.3.tgz", + "prime-agent-core-1.2.3.tgz", + "prime-agent-tui-1.2.3.tgz", + ]) { + expect(existsSync(join(artifacts, tarball)), tarball).toBe(true); + } + const npmExtracted = join(f.root, "npm-extracted"); + mkdirSync(npmExtracted); + expect(spawnSync("tar", ["-xzf", join(artifacts, "prime-agent-1.2.3.tgz"), "-C", npmExtracted]).status).toBe(0); + expect(JSON.parse(readFileSync(join(npmExtracted, "package", "package.json"), "utf8"))).toMatchObject({ + name: "prime-agent", + version: "1.2.3", + bin: { "prime-agent": "dist/bundle/cli.js" }, + }); const extracted = join(f.root, "extracted"); mkdirSync(extracted); @@ -147,4 +164,36 @@ describe("compiled release archives", () => { expect(result.status).not.toBe(0); expect(result.stderr).toContain("forbidden dependency or cache directory"); }); + test("rejects shell-active release base URLs", () => { + const f = fixture(); + const result = pack(f, ["--base-url", "https://downloads.example.test/$(touch-danger)"]); + expect(result.status).not.toBe(0); + expect(result.stderr).toContain("unsafe shell characters"); + }); + + test("preserves existing artifacts when preflight validation fails", () => { + const f = fixture(); + const sentinel = join(f.output, "artifacts", "keep.txt"); + mkdirSync(dirname(sentinel), { recursive: true }); + writeFileSync(sentinel, "keep"); + rmSync(join(f.sidecars, "theme"), { recursive: true }); + const result = pack(f); + expect(result.status).not.toBe(0); + expect(readFileSync(sentinel, "utf8")).toBe("keep"); + }); + + test("rejects output paths that traverse a symlink", () => { + const f = fixture(); + const outside = join(f.root, "outside"); + const sentinel = join(outside, "old", "keep.txt"); + mkdirSync(dirname(sentinel), { recursive: true }); + writeFileSync(sentinel, "keep"); + const link = join(releaseRoot, `link-${process.pid}-${Math.random().toString(36).slice(2)}`); + outputDirs.push(link); + symlinkSync(outside, link, "dir"); + const result = pack(f, ["--out-dir", join(link, "old")]); + expect(result.status).not.toBe(0); + expect(result.stderr).toContain("symlinked output path"); + expect(readFileSync(sentinel, "utf8")).toBe("keep"); + }); }); diff --git a/packages/coding-agent/test/compiled-artifact-smoke.test.ts b/packages/coding-agent/test/compiled-artifact-smoke.test.ts index 4215ce290f..5bce3bb746 100644 --- a/packages/coding-agent/test/compiled-artifact-smoke.test.ts +++ b/packages/coding-agent/test/compiled-artifact-smoke.test.ts @@ -41,6 +41,10 @@ describe("compiled Bun artifact", () => { for (const name of REQUIRED_BINARY_SIDECARS) { expect(existsSync(join(distDir, name)), name).toBe(true); } + for (const name of ["template.html", "template.css", "template.js"]) { + expect(existsSync(join(distDir, "export-html", name)), name).toBe(true); + } + expect(existsSync(join(distDir, "prime-agent-runtime", "pyproject.toml"))).toBe(true); }); it("contains no installed dependency or cache directories", () => { diff --git a/packages/coding-agent/test/kernel-bootstrap.test.ts b/packages/coding-agent/test/kernel-bootstrap.test.ts index cda17807c4..0aff453877 100644 --- a/packages/coding-agent/test/kernel-bootstrap.test.ts +++ b/packages/coding-agent/test/kernel-bootstrap.test.ts @@ -173,6 +173,17 @@ describe("kernel bootstrap", () => { expect(getKernelVenvDir()).toBe(venv); }); + it("resolves a runtime sidecar beside a compiled binary", async () => { + const packageDir = join(tempDir, "binary-layout"); + const runtimeDir = join(packageDir, "prime-agent-runtime"); + mkdirSync(join(runtimeDir, "src", "rlm"), { recursive: true }); + writeFileSync(join(runtimeDir, "pyproject.toml"), '[project]\nname = "prime-agent-runtime"\n'); + writeFileSync(join(runtimeDir, "src", "rlm", "__init__.py"), "VALUE = 1\n"); + process.env.PI_PACKAGE_DIR = packageDir; + + expect(await resolveRuntimeIdentity()).toMatch(/^sha256:[0-9a-f]{64}$/); + }); + it("bootstraps a missing venv with uv, prime-agent-runtime, and default extra packages", async () => { const logPath = installFakeUv(); const venv = join(tempDir, "kernel-venv"); diff --git a/scripts/assemble-release-archives.mjs b/scripts/assemble-release-archives.mjs index 3f085a15ff..3e6475905b 100755 --- a/scripts/assemble-release-archives.mjs +++ b/scripts/assemble-release-archives.mjs @@ -36,7 +36,17 @@ */ import { createHash } from "node:crypto"; -import { chmodSync, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; +import { + chmodSync, + cpSync, + existsSync, + lstatSync, + mkdirSync, + readFileSync, + readdirSync, + rmSync, + writeFileSync, +} from "node:fs"; import { spawnSync } from "node:child_process"; import { isAbsolute, join, relative, resolve } from "node:path"; @@ -130,7 +140,7 @@ function parseArgs(args) { parsed.version = normalizeVersion(parsed.version); if (parsed.platforms.length === 0) parsed.platforms = [...PLATFORMS]; - parsed.baseUrl = parsed.baseUrl.replace(/\/+$/, ""); + parsed.baseUrl = normalizeBaseUrl(parsed.baseUrl); return parsed; } @@ -153,11 +163,41 @@ function normalizeVersion(version) { return normalized; } +function normalizeBaseUrl(value) { + if (/[\u0000-\u001f\u007f"'`$\\]/.test(value)) { + throw new Error("Release base URL contains unsafe shell characters"); + } + let parsed; + try { + parsed = new URL(value); + } catch { + throw new Error(`Invalid release base URL: ${value}`); + } + if (!new Set(["https:", "http:"]).has(parsed.protocol) || !parsed.hostname || parsed.username || parsed.password) { + throw new Error(`Invalid release base URL: ${value}`); + } + if (parsed.search || parsed.hash) throw new Error("Release base URL must not contain a query or fragment"); + return parsed.toString().replace(/\/+$/, ""); +} + function assertSafeOutputDir(outDir) { const base = resolve(defaultOutDir); - const pathFromBase = relative(base, resolve(outDir)); - if (pathFromBase === "" || (!pathFromBase.startsWith("..") && !isAbsolute(pathFromBase))) return; - throw new Error(`Refusing to write output outside ${base}: ${outDir}`); + const resolvedOutDir = resolve(outDir); + const pathFromBase = relative(base, resolvedOutDir); + if (pathFromBase !== "" && (pathFromBase.startsWith("..") || isAbsolute(pathFromBase))) { + throw new Error(`Refusing to write output outside ${base}: ${outDir}`); + } + + let current = base; + for (const part of pathFromBase.split(/[\/\\]/).filter(Boolean)) { + if (existsSync(current) && lstatSync(current).isSymbolicLink()) { + throw new Error(`Refusing to write through symlinked output path: ${current}`); + } + current = join(current, part); + } + if (existsSync(current) && lstatSync(current).isSymbolicLink()) { + throw new Error(`Refusing to write through symlinked output path: ${current}`); + } } function sha256File(path) { @@ -222,10 +262,6 @@ function main() { const args = parseArgs(process.argv.slice(2)); const outDir = resolve(args.outDir); assertSafeOutputDir(outDir); - rmSync(outDir, { force: true, recursive: true }); - - const versionDir = join(outDir, "artifacts"); - mkdirSync(versionDir, { recursive: true }); const missing = validateSidecars(args.sidecarDir); if (missing.length > 0) { @@ -239,14 +275,22 @@ function main() { throw new Error(`Release sidecars contain a forbidden dependency or cache directory: ${forbiddenDirectory}`); } - const archives = []; - + const binarySources = new Map(); for (const platform of args.platforms) { const binarySource = join(args.binaryDir, platform, "pi"); if (!existsSync(binarySource)) { throw new Error(`Binary not found for platform ${platform}: ${binarySource}`); } + binarySources.set(platform, binarySource); + } + rmSync(outDir, { force: true, recursive: true }); + const versionDir = join(outDir, "artifacts"); + mkdirSync(versionDir, { recursive: true }); + const archives = []; + + for (const platform of args.platforms) { + const binarySource = binarySources.get(platform); const stagingDir = join(outDir, "staging", platform); mkdirSync(stagingDir, { recursive: true }); diff --git a/scripts/build-binaries.sh b/scripts/build-binaries.sh index b41cf1e3cc..b8951a7e8d 100755 --- a/scripts/build-binaries.sh +++ b/scripts/build-binaries.sh @@ -17,6 +17,7 @@ # # packages/coding-agent/release/artifacts/ # prime-agent--.tar.gz +# prime-agent-.tgz (plus internal workspace tarballs) # SHA256SUMS # stable # latest.json @@ -116,8 +117,8 @@ bun ../../scripts/pack-prime-agent-release.mjs \ echo "" echo "==> Build complete!" -echo "Platform archives:" -ls -lh "release/artifacts/"*.tar.gz 2>/dev/null || true +echo "Release archives:" +ls -lh "release/artifacts/"*.tar.gz "release/artifacts/"*.tgz 2>/dev/null || true echo "" echo "Metadata:" ls -lh "release/artifacts/SHA256SUMS" "release/artifacts/latest.json" "release/artifacts/stable" 2>/dev/null || true diff --git a/scripts/pack-prime-agent-release.mjs b/scripts/pack-prime-agent-release.mjs index 220105a68a..3b795dbfdd 100755 --- a/scripts/pack-prime-agent-release.mjs +++ b/scripts/pack-prime-agent-release.mjs @@ -1,13 +1,13 @@ #!/usr/bin/env bun /** - * Produce Bun-compiled platform release archives. + * Produce Bun-compiled platform archives and npm-compatible tarballs. * * This script is the CI entry point for the release artifact lane. It expects * pre-built Bun-compiled binaries for 4 platforms (darwin-arm64, darwin-x64, * linux-arm64, linux-x64) and sidecar files, then produces platform-specific * .tar.gz archives with checksums and channel metadata. * - * No npm or Node.js is used during artifact assembly. + * Bun creates both native archives and npm-compatible package tarballs. * * Usage: * bun scripts/pack-prime-agent-release.mjs \ @@ -21,18 +21,28 @@ * Output: * /artifacts/ * prime-agent--.tar.gz + * prime-agent-.tgz (plus internal workspace tarballs) * SHA256SUMS * * latest.json|beta.json */ -import { existsSync, readFileSync } from "node:fs"; +import { createHash } from "node:crypto"; +import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { resolve, join } from "node:path"; const root = resolve(import.meta.dirname, ".."); const defaultOutputDir = join(root, "packages", "coding-agent", "release"); const defaultBaseUrl = process.env.PRIME_AGENT_DOWNLOAD_BASE_URL; const releaseChannels = new Set(["stable", "beta"]); +const publicPackageName = "prime-agent"; +const publicCommandName = "prime-agent"; +const releasePackages = [ + { packageDir: "ai", publicName: "prime-agent-ai" }, + { packageDir: "tui", publicName: "prime-agent-tui" }, + { packageDir: "agent", publicName: "prime-agent-core" }, + { packageDir: "coding-agent", publicName: publicPackageName }, +]; function parseArgs(args) { const parsed = { @@ -126,6 +136,113 @@ Creates platform release archives: `); } +function sha256File(path) { + const hash = createHash("sha256"); + hash.update(readFileSync(path)); + return hash.digest("hex"); +} + +function rewriteInternalDependencies(dependencies, internalPackageUrls) { + if (!dependencies) return undefined; + return Object.fromEntries( + Object.entries(dependencies).map(([name, range]) => [name, internalPackageUrls.get(name) || range]), + ); +} + +function createReleasePackageJson(sourcePackage, packageName, version, internalPackageUrls) { + const manifest = { + ...sourcePackage, + name: packageName, + version, + dependencies: rewriteInternalDependencies(sourcePackage.dependencies, internalPackageUrls), + optionalDependencies: rewriteInternalDependencies(sourcePackage.optionalDependencies, internalPackageUrls), + scripts: sourcePackage.scripts?.postinstall ? { postinstall: sourcePackage.scripts.postinstall } : undefined, + }; + delete manifest.devDependencies; + delete manifest.overrides; + delete manifest.private; + if (packageName === publicPackageName) { + manifest.bin = { [publicCommandName]: "dist/bundle/cli.js" }; + manifest.piConfig = { ...(manifest.piConfig || {}), name: publicCommandName, configDir: ".prime/agent" }; + } + return manifest; +} + +function copyPackageContents(sourceDir, targetDir, packageJson) { + mkdirSync(targetDir, { recursive: true }); + writeFileSync(join(targetDir, "package.json"), `${JSON.stringify(packageJson, null, 2)}\n`); + for (const entry of ["dist", "docs", "examples", "skills", "postinstall.cjs", "README.md", "CHANGELOG.md"]) { + const source = join(sourceDir, entry); + if (existsSync(source)) cpSync(source, join(targetDir, entry), { recursive: true }); + } +} + +function packNpmCompatibilityTarballs(args) { + const artifactsDir = join(args.outDir, "artifacts"); + const stagingRoot = join(args.outDir, "npm-packages"); + const packageSources = new Map(); + for (const releasePackage of releasePackages) { + const sourceDir = join(root, "packages", releasePackage.packageDir); + if (!existsSync(join(sourceDir, "dist"))) { + throw new Error(`Missing built package: ${sourceDir}/dist`); + } + packageSources.set(releasePackage.packageDir, JSON.parse(readFileSync(join(sourceDir, "package.json"), "utf8"))); + } + + const artifactFiles = new Map( + releasePackages.map(({ packageDir, publicName }) => [packageDir, `${publicName}-${args.version}.tgz`]), + ); + const internalPackageUrls = new Map(); + for (const { packageDir, publicName } of releasePackages) { + if (packageDir === "coding-agent") continue; + const sourceName = packageSources.get(packageDir).name; + internalPackageUrls.set(sourceName, `${args.baseUrl}/releases/v${args.version}/${artifactFiles.get(packageDir)}`); + } + + const tarballs = []; + try { + rmSync(stagingRoot, { recursive: true, force: true }); + for (const { packageDir, publicName } of releasePackages) { + const stagingDir = join(stagingRoot, packageDir); + copyPackageContents( + join(root, "packages", packageDir), + stagingDir, + createReleasePackageJson(packageSources.get(packageDir), publicName, args.version, internalPackageUrls), + ); + const result = Bun.spawnSync([process.execPath, "pm", "pack", "--destination", artifactsDir], { + cwd: stagingDir, + stdout: "pipe", + stderr: "pipe", + }); + if (result.exitCode !== 0) { + throw new Error(`bun pm pack failed for ${packageDir}: ${result.stderr.toString()}`); + } + const file = artifactFiles.get(packageDir); + const path = join(artifactsDir, file); + if (!existsSync(path)) throw new Error(`bun pm pack did not create ${path}`); + tarballs.push({ package: publicName, file, sha256: sha256File(path) }); + } + } finally { + rmSync(stagingRoot, { recursive: true, force: true }); + } + + const checksumPath = join(artifactsDir, "SHA256SUMS"); + const checksums = readFileSync(checksumPath, "utf8") + .trim() + .split("\n") + .filter(Boolean); + checksums.push(...tarballs.map(({ file, sha256 }) => `${sha256} ${file}`)); + checksums.sort((left, right) => left.split(/\s+/).at(-1).localeCompare(right.split(/\s+/).at(-1))); + writeFileSync(checksumPath, `${checksums.join("\n")}\n`); + + const manifestName = args.channel === "stable" ? "latest.json" : "beta.json"; + const manifestPath = join(artifactsDir, manifestName); + const manifest = JSON.parse(readFileSync(manifestPath, "utf8")); + manifest.tarball = `releases/v${args.version}/${artifactFiles.get("coding-agent")}`; + manifest.tarballs = tarballs; + writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`); +} + async function main() { const args = parseArgs(process.argv.slice(2)); @@ -157,6 +274,7 @@ async function main() { if (result.status !== 0) { throw new Error(`assemble-release-archives.mjs failed with exit code ${result.status}`); } + packNpmCompatibilityTarballs(args); } try { From a688401a3ae69692ac87c2e083b28956f858a145 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 18:21:18 -0400 Subject: [PATCH 13/31] fix: drain daemon sockets before shutdown --- .github/workflows/ci.yml | 32 +++++++++---------- .github/workflows/nightly-process-stress.yml | 8 ++--- .../src/modes/daemon/daemon-mode.ts | 4 +-- .../src/modes/daemon/daemon-socket.ts | 15 ++++++++- .../src/modes/daemon/daemon-supervisor.ts | 4 +-- .../coding-agent/test/daemon-socket.test.ts | 25 +++++++++++++++ 6 files changed, 63 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c29c8fa8c3..6a6fec4ae0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,11 +129,11 @@ jobs: - name: Build run: bun run build - - name: Install uv + - name: Install uv 0.12.4 if: matrix.install_uv - run: | - curl -LsSf https://astral.sh/uv/install.sh | sh - echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 + with: + version: "0.12.4" - name: Test working-directory: ${{ matrix.package }} @@ -168,10 +168,10 @@ jobs: - name: Build run: bun run build - - name: Install uv - run: | - curl -LsSf https://astral.sh/uv/install.sh | sh - echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + - name: Install uv 0.12.4 + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 + with: + version: "0.12.4" - name: Run process stress tests working-directory: packages/coding-agent @@ -208,10 +208,10 @@ jobs: - name: Build run: bun run build - - name: Install uv - run: | - curl -LsSf https://astral.sh/uv/install.sh | sh - echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + - name: Install uv 0.12.4 + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 + with: + version: "0.12.4" - name: Run kernel-heavy tests working-directory: packages/coding-agent @@ -237,10 +237,10 @@ jobs: - name: Install dependencies (frozen lockfile) run: bun install --frozen-lockfile - - name: Install uv - run: | - curl -LsSf https://astral.sh/uv/install.sh | sh - echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + - name: Install uv 0.12.4 + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 + with: + version: "0.12.4" - name: Install Python runtime dependencies working-directory: prime-agent-runtime diff --git a/.github/workflows/nightly-process-stress.yml b/.github/workflows/nightly-process-stress.yml index 86b197c330..8ea0cfb4c5 100644 --- a/.github/workflows/nightly-process-stress.yml +++ b/.github/workflows/nightly-process-stress.yml @@ -40,10 +40,10 @@ jobs: - name: Build run: bun run build - - name: Install uv - run: | - curl -LsSf https://astral.sh/uv/install.sh | sh - echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + - name: Install uv 0.12.4 + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 + with: + version: "0.12.4" - name: Run process stress tests working-directory: packages/coding-agent diff --git a/packages/coding-agent/src/modes/daemon/daemon-mode.ts b/packages/coding-agent/src/modes/daemon/daemon-mode.ts index bcecaba035..e9d0b1f4d3 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-mode.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-mode.ts @@ -183,6 +183,7 @@ import { cleanupDaemonSocketPath, type DaemonSocketIdentity, defaultDaemonSocketPath, + endDaemonSocketAfterFlush, getDaemonSocketIdentity, normalizeSocketPath, prepareDaemonSocketPath, @@ -7313,8 +7314,7 @@ export class AgentDaemon { } for (const client of this.clients) { client.detachInput(); - client.socket.end(); - client.socket.destroy(); + endDaemonSocketAfterFlush(client.socket); } await new Promise((resolveClose) => { if (!this.server) { diff --git a/packages/coding-agent/src/modes/daemon/daemon-socket.ts b/packages/coding-agent/src/modes/daemon/daemon-socket.ts index dd6d5e2cf7..753595265c 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-socket.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-socket.ts @@ -1,5 +1,5 @@ import { chmodSync, existsSync, lstatSync, mkdirSync, unlinkSync } from "node:fs"; -import { createConnection } from "node:net"; +import { createConnection, type Socket } from "node:net"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import lockfile from "proper-lockfile"; @@ -12,6 +12,19 @@ const DAEMON_SOCKET_RELEASE_GRACE_MS = 1000; const DAEMON_SOCKET_RELEASE_POLL_MS = 25; const DAEMON_SOCKET_LOCK_STALE_MS = 5000; const DAEMON_SOCKET_LOCK_UPDATE_MS = 1000; +const DAEMON_SOCKET_FLUSH_TIMEOUT_MS = 1000; + +export function endDaemonSocketAfterFlush(socket: Socket): void { + if (socket.destroyed) return; + const forceCloseTimer = setTimeout(() => socket.destroy(), DAEMON_SOCKET_FLUSH_TIMEOUT_MS); + forceCloseTimer.unref(); + const clearForceClose = () => clearTimeout(forceCloseTimer); + socket.once("close", clearForceClose); + socket.end(() => { + clearForceClose(); + if (!socket.destroyed) socket.destroy(); + }); +} type DaemonSocketCompromiseListener = (error: Error) => void; diff --git a/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts b/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts index bf92424d32..c50c81b8bb 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts @@ -113,6 +113,7 @@ import { type DaemonSocketPathLease, defaultDaemonSocketDir, defaultDaemonSocketPath, + endDaemonSocketAfterFlush, getDaemonSocketIdentity, normalizeSocketPath, prepareDaemonSocketPath, @@ -6554,8 +6555,7 @@ export class DaemonSupervisor { await this.catalog.stop(); for (const client of this.clients) { client.detachInput(); - client.socket.end(); - client.socket.destroy(); + endDaemonSocketAfterFlush(client.socket); } await new Promise((resolveClose) => this.server?.close(() => resolveClose()) ?? resolveClose()); await this.runCleanupStep("daemon socket", () => this.cleanupSocket()); diff --git a/packages/coding-agent/test/daemon-socket.test.ts b/packages/coding-agent/test/daemon-socket.test.ts index 8237d68f23..5288c1f17e 100644 --- a/packages/coding-agent/test/daemon-socket.test.ts +++ b/packages/coding-agent/test/daemon-socket.test.ts @@ -9,11 +9,36 @@ import { cleanupDaemonSocketPath, DaemonSocketPathLease, defaultDaemonSocketPath, + endDaemonSocketAfterFlush, getDaemonSocketIdentity, normalizeSocketPath, prepareDaemonSocketPath, } from "../src/modes/daemon/daemon-socket.js"; +describe("endDaemonSocketAfterFlush", () => { + it("delivers queued bytes before closing the socket", async () => { + const server = createServer((socket) => { + socket.write("daemon_closing\n"); + endDaemonSocketAfterFlush(socket); + }); + await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); + const address = server.address(); + if (!address || typeof address === "string") throw new Error("Expected TCP server address"); + const received = await new Promise((resolve, reject) => { + let data = ""; + const socket = createConnection({ host: "127.0.0.1", port: address.port }); + socket.setEncoding("utf8"); + socket.on("data", (chunk) => { + data += chunk; + }); + socket.on("end", () => resolve(data)); + socket.on("error", reject); + }); + await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve()))); + expect(received).toBe("daemon_closing\n"); + }); +}); + describe("normalizeSocketPath", () => { it("normalizes equivalent Unix spellings", () => { if (process.platform === "win32") return; From 19a52a08f50993263012b945973199eae4688199 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 18:21:25 -0400 Subject: [PATCH 14/31] chore(ai): refresh generated model catalog --- packages/ai/src/models.generated.ts | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/packages/ai/src/models.generated.ts b/packages/ai/src/models.generated.ts index cbc6e14c3b..95bc323c01 100644 --- a/packages/ai/src/models.generated.ts +++ b/packages/ai/src/models.generated.ts @@ -8941,24 +8941,6 @@ export const MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"anthropic-messages">, - "claude-fable-5-1": { - id: "claude-fable-5-1", - name: "Claude Fable 5.1", - api: "anthropic-messages", - provider: "opencode", - baseUrl: "https://opencode.ai/zen", - reasoning: true, - thinkingLevelMap: {"off":null,"xhigh":"xhigh","max":"max"}, - input: ["text", "image"], - cost: { - input: 10, - output: 50, - cacheRead: 0.25, - cacheWrite: 12.5, - }, - contextWindow: 1000000, - maxTokens: 128000, - } satisfies Model<"anthropic-messages">, "claude-haiku-4-5": { id: "claude-haiku-4-5", name: "Claude Haiku 4.5", @@ -11254,9 +11236,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 1.0241639999999999, - output: 2.0483279999999997, - cacheRead: 0.085347, + input: 1.0274699999999999, + output: 2.0549399999999998, + cacheRead: 0.0856225, cacheWrite: 0, }, contextWindow: 1048576, From 424cb85db2ba523ea179582dcc7b620701e924e2 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 18:30:05 -0400 Subject: [PATCH 15/31] fix: normalize release paths and require HTTPS --- install.sh | 2 ++ .../coding-agent/test/bun-installer-e2e.test.ts | 12 ++++++++++++ .../test/bun-release-archives.test.ts | 16 ++++++++++++++++ scripts/assemble-release-archives.mjs | 4 ++-- scripts/pack-prime-agent-release.mjs | 9 ++++++++- 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/install.sh b/install.sh index 450211c37e..56367e1f7c 100755 --- a/install.sh +++ b/install.sh @@ -1665,6 +1665,8 @@ prime_agent_binary_smoke_binary() { prime_agent_binary_atomic_symlink() { _target="$1" _link="$2" + _target_dir=$(cd "$(dirname "$_target")" 2>/dev/null && pwd -P) || return 1 + _target="$_target_dir/$(basename "$_target")" # Create parent dir if needed _link_dir=$(dirname "$_link") if [ ! -d "$_link_dir" ]; then diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index f9654a9430..772b782052 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -42,6 +42,7 @@ function runInstaller( mkdirSync(join(home, ".prime"), { recursive: true }); writeFileSync(join(home, ".prime", "sentinel"), "user data"); const result = spawnSync("sh", [installer, ...args], { + cwd: root, env: { ...process.env, HOME: home, @@ -153,4 +154,15 @@ describe("compiled binary installer", () => { expect(result.stderr).toContain("currently shadows the new binary"); expect(result.stdout).toContain('export PATH="'); }); + test("canonicalizes relative version directories before linking", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + + const result = runInstaller(root, ["1.2.3"], { PRIME_AGENT_VERSIONS_DIR: "relative/versions" }); + expect(result.exitCode, result.stderr).toBe(0); + expect(readlinkSync(join(root, "bin", "prime-agent"))).toBe( + join(root, "relative", "versions", "v1.2.3", "prime-agent"), + ); + }); }); diff --git a/packages/coding-agent/test/bun-release-archives.test.ts b/packages/coding-agent/test/bun-release-archives.test.ts index 6a98610e56..100888e1a5 100644 --- a/packages/coding-agent/test/bun-release-archives.test.ts +++ b/packages/coding-agent/test/bun-release-archives.test.ts @@ -164,6 +164,22 @@ describe("compiled release archives", () => { expect(result.status).not.toBe(0); expect(result.stderr).toContain("forbidden dependency or cache directory"); }); + test("normalizes v-prefixed versions for npm artifact URLs", () => { + const f = fixture(); + const result = pack(f, ["--version", "v1.2.3"]); + expect(result.status, result.stderr).toBe(0); + const manifest = JSON.parse(readFileSync(join(f.output, "artifacts", "latest.json"), "utf8")); + expect(manifest.tarball).toBe("releases/v1.2.3/prime-agent-1.2.3.tgz"); + expect(existsSync(join(f.output, "artifacts", "prime-agent-1.2.3.tgz"))).toBe(true); + }); + + test("rejects insecure release base URLs", () => { + const f = fixture(); + const result = pack(f, ["--base-url", "http://downloads.example.test"]); + expect(result.status).not.toBe(0); + expect(result.stderr).toContain("must use HTTPS"); + }); + test("rejects shell-active release base URLs", () => { const f = fixture(); const result = pack(f, ["--base-url", "https://downloads.example.test/$(touch-danger)"]); diff --git a/scripts/assemble-release-archives.mjs b/scripts/assemble-release-archives.mjs index 3e6475905b..4ac116c054 100755 --- a/scripts/assemble-release-archives.mjs +++ b/scripts/assemble-release-archives.mjs @@ -173,8 +173,8 @@ function normalizeBaseUrl(value) { } catch { throw new Error(`Invalid release base URL: ${value}`); } - if (!new Set(["https:", "http:"]).has(parsed.protocol) || !parsed.hostname || parsed.username || parsed.password) { - throw new Error(`Invalid release base URL: ${value}`); + if (parsed.protocol !== "https:" || !parsed.hostname || parsed.username || parsed.password) { + throw new Error(`Release base URL must use HTTPS without credentials: ${value}`); } if (parsed.search || parsed.hash) throw new Error("Release base URL must not contain a query or fragment"); return parsed.toString().replace(/\/+$/, ""); diff --git a/scripts/pack-prime-agent-release.mjs b/scripts/pack-prime-agent-release.mjs index 3b795dbfdd..e21bdce1e3 100755 --- a/scripts/pack-prime-agent-release.mjs +++ b/scripts/pack-prime-agent-release.mjs @@ -112,15 +112,22 @@ function parseArgs(args) { if (!parsed.baseUrl) throw new Error("--base-url or PRIME_AGENT_DOWNLOAD_BASE_URL is required"); parsed.baseUrl = parsed.baseUrl.replace(/\/+$/, ""); - // Resolve version from coding-agent package.json if not provided. + // Resolve and normalize the version once for archive names and embedded URLs. if (!parsed.version) { const cliPkg = JSON.parse(readFileSync(join(root, "packages", "coding-agent", "package.json"), "utf8")); parsed.version = cliPkg.version; } + parsed.version = normalizeVersion(parsed.version); return parsed; } +function normalizeVersion(version) { + const normalized = version.startsWith("v") ? version.slice(1) : version; + if (!/^[0-9A-Za-z.-]+$/.test(normalized)) throw new Error(`Invalid release version: ${version}`); + return normalized; +} + function printHelp() { console.log(`Usage: bun scripts/pack-prime-agent-release.mjs --base-url url [--channel stable|beta] [--version x.y.z] [--out-dir path] [--binary-base-dir path] [--sidecar-dir path] [--platform platform] From 2399dfb7271cdfd10cd3839cc74e9cb70dc1f3c1 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 18:33:14 -0400 Subject: [PATCH 16/31] fix: keep npm release postinstall Node-compatible --- packages/coding-agent/test/bun-release-archives.test.ts | 1 + scripts/pack-prime-agent-release.mjs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/test/bun-release-archives.test.ts b/packages/coding-agent/test/bun-release-archives.test.ts index 100888e1a5..f987742cc0 100644 --- a/packages/coding-agent/test/bun-release-archives.test.ts +++ b/packages/coding-agent/test/bun-release-archives.test.ts @@ -106,6 +106,7 @@ describe("compiled release archives", () => { name: "prime-agent", version: "1.2.3", bin: { "prime-agent": "dist/bundle/cli.js" }, + scripts: { postinstall: "node postinstall.cjs" }, }); const extracted = join(f.root, "extracted"); diff --git a/scripts/pack-prime-agent-release.mjs b/scripts/pack-prime-agent-release.mjs index e21bdce1e3..347ed27e7c 100755 --- a/scripts/pack-prime-agent-release.mjs +++ b/scripts/pack-prime-agent-release.mjs @@ -163,7 +163,7 @@ function createReleasePackageJson(sourcePackage, packageName, version, internalP version, dependencies: rewriteInternalDependencies(sourcePackage.dependencies, internalPackageUrls), optionalDependencies: rewriteInternalDependencies(sourcePackage.optionalDependencies, internalPackageUrls), - scripts: sourcePackage.scripts?.postinstall ? { postinstall: sourcePackage.scripts.postinstall } : undefined, + scripts: sourcePackage.scripts?.postinstall ? { postinstall: "node postinstall.cjs" } : undefined, }; delete manifest.devDependencies; delete manifest.overrides; From f670360b8294b01961db63d1f929f47a17030699 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 18:36:25 -0400 Subject: [PATCH 17/31] fix: trim release base URLs before packing --- .../test/bun-release-archives.test.ts | 15 +++++++++++++++ scripts/assemble-release-archives.mjs | 1 + scripts/pack-prime-agent-release.mjs | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/test/bun-release-archives.test.ts b/packages/coding-agent/test/bun-release-archives.test.ts index f987742cc0..66e0c68854 100644 --- a/packages/coding-agent/test/bun-release-archives.test.ts +++ b/packages/coding-agent/test/bun-release-archives.test.ts @@ -174,6 +174,21 @@ describe("compiled release archives", () => { expect(existsSync(join(f.output, "artifacts", "prime-agent-1.2.3.tgz"))).toBe(true); }); + test("trims release base URLs before writing npm dependency specs", () => { + const f = fixture(); + const result = pack(f, ["--base-url", " https://downloads.example.test/ "]); + expect(result.status, result.stderr).toBe(0); + const packedManifest = spawnSync( + "tar", + ["-xOzf", join(f.output, "artifacts", "prime-agent-1.2.3.tgz"), "package/package.json"], + { encoding: "utf8" }, + ); + expect(packedManifest.status, packedManifest.stderr).toBe(0); + expect(JSON.parse(packedManifest.stdout).dependencies["@earendil-works/pi-ai"]).toBe( + "https://downloads.example.test/releases/v1.2.3/prime-agent-ai-1.2.3.tgz", + ); + }); + test("rejects insecure release base URLs", () => { const f = fixture(); const result = pack(f, ["--base-url", "http://downloads.example.test"]); diff --git a/scripts/assemble-release-archives.mjs b/scripts/assemble-release-archives.mjs index 4ac116c054..282b5c9061 100755 --- a/scripts/assemble-release-archives.mjs +++ b/scripts/assemble-release-archives.mjs @@ -164,6 +164,7 @@ function normalizeVersion(version) { } function normalizeBaseUrl(value) { + value = value.trim(); if (/[\u0000-\u001f\u007f"'`$\\]/.test(value)) { throw new Error("Release base URL contains unsafe shell characters"); } diff --git a/scripts/pack-prime-agent-release.mjs b/scripts/pack-prime-agent-release.mjs index 347ed27e7c..1f101d683d 100755 --- a/scripts/pack-prime-agent-release.mjs +++ b/scripts/pack-prime-agent-release.mjs @@ -110,7 +110,7 @@ function parseArgs(args) { } if (!parsed.baseUrl) throw new Error("--base-url or PRIME_AGENT_DOWNLOAD_BASE_URL is required"); - parsed.baseUrl = parsed.baseUrl.replace(/\/+$/, ""); + parsed.baseUrl = parsed.baseUrl.trim().replace(/\/+$/, ""); // Resolve and normalize the version once for archive names and embedded URLs. if (!parsed.version) { From 06e57bc31996e99a412ace94036e1d5b9e120458 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 18:54:16 -0400 Subject: [PATCH 18/31] feat!: make compiled Bun binaries the only install path --- .github/workflows/build-binaries.yml | 4 +- install.sh | 914 +----------------- .../.changes/bun-primary-runtime.md | 2 +- packages/coding-agent/README.md | 2 +- packages/coding-agent/docs/development.md | 2 +- .../test/bun-installer-e2e.test.ts | 53 +- .../coding-agent/test/bun-installer.test.ts | 26 +- .../test/bun-release-archives.test.ts | 39 +- scripts/build-binaries.sh | 3 +- scripts/check-installer-render.mjs | 18 +- scripts/pack-prime-agent-release.mjs | 124 +-- scripts/release.mjs | 4 +- 12 files changed, 129 insertions(+), 1062 deletions(-) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index da13297546..c044db863a 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -344,7 +344,7 @@ jobs: test -n "$R2_BUCKET" test -n "$R2_ENDPOINT_URL" - for artifact in "$PRODUCTION_DIR"/*.tar.gz "$PRODUCTION_DIR"/*.tgz; do + for artifact in "$PRODUCTION_DIR"/*.tar.gz; do test -f "$artifact" || continue aws s3 cp "$artifact" "s3://${R2_BUCKET}/${RELEASE_PREFIX}/$(basename "$artifact")" \ --endpoint-url "$R2_ENDPOINT_URL" \ @@ -411,7 +411,7 @@ jobs: test -n "$R2_BUCKET" test -n "$R2_ENDPOINT_URL" - for artifact in "$BETA_DIR"/*.tar.gz "$BETA_DIR"/*.tgz; do + for artifact in "$BETA_DIR"/*.tar.gz; do test -f "$artifact" || continue aws s3 cp "$artifact" "s3://${R2_BUCKET}/${RELEASE_PREFIX}/$(basename "$artifact")" \ --endpoint-url "$R2_ENDPOINT_URL" \ diff --git a/install.sh b/install.sh index 56367e1f7c..41f53e530d 100755 --- a/install.sh +++ b/install.sh @@ -57,7 +57,6 @@ prime_agent_screen_status= prime_agent_screen_detail= prime_agent_screen_question= prime_agent_animation_frame=0 -prime_agent_install_method="${PRIME_AGENT_INSTALL_METHOD:-auto}" prime_agent_binary_versions_dir="${PRIME_AGENT_VERSIONS_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/prime-agent/versions}" prime_agent_binary_symlink="${PRIME_AGENT_BIN_DIR:-${XDG_BIN_HOME:-$HOME/.local/bin}}/prime-agent" prime_agent_binary_rollback_version= @@ -70,25 +69,16 @@ main() { exit 1 fi - # Parse flags before positional args - prime_agent_install_method="${PRIME_AGENT_INSTALL_METHOD:-auto}" prime_agent_is_update=0 _prime_agent_positional= for _prime_agent_arg in "$@"; do case "$_prime_agent_arg" in --method=*) - prime_agent_install_method="${_prime_agent_arg#--method=}" - case "$prime_agent_install_method" in - binary|npm|auto) ;; - *) - printf 'error: invalid install method: %s (must be binary, npm, or auto)\n' "$prime_agent_install_method" >&2 - exit 1 - ;; - esac + printf 'error: --method is no longer supported; Prime Agent installs as a compiled Bun binary.\n' >&2 + exit 1 ;; --update) prime_agent_is_update=1 - prime_agent_install_method=binary ;; *) if [ -z "$_prime_agent_positional" ]; then @@ -113,19 +103,12 @@ main() { return fi - # Default auto and explicit --method=binary both use compiled binary - if [ "$prime_agent_install_method" != npm ]; then - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Installing Prime Agent" "" "" "" - else - printf '\n\033[1m Installing Prime Agent\033[0m\n\033[2m compiled binary\033[0m\n\n' - fi - prime_agent_binary_fresh_install "${_prime_agent_positional:-}" - return + if [ "$prime_agent_screen_enabled" = 1 ]; then + prime_agent_screen "Installing Prime Agent" "" "" "" + else + printf '\n\033[1m Installing Prime Agent\033[0m\n\033[2m compiled Bun binary\033[0m\n\n' fi - - # Explicit --method=npm: original npm install path - prime_agent_npm_install "${_prime_agent_positional:-}" + prime_agent_binary_fresh_install "${_prime_agent_positional:-}" } create_temp_dir() { @@ -632,37 +615,6 @@ prime_agent_print_centered_line() { fi } -prime_agent_place_prompt_cursor() { - max_width=$((prime_agent_screen_cols - 4)) - if [ "$max_width" -lt 1 ]; then - max_width=1 - fi - prompt_text=$(prime_agent_fit_ascii "$(prime_agent_screen_primary_text)" "$max_width") - prompt_width=${#prompt_text} - content_height=$(prime_agent_content_height) - top=$(((prime_agent_screen_rows - content_height) / 2)) - if [ "$top" -lt 0 ]; then - top=0 - fi - prompt_index=0 - if prime_agent_show_logo; then - prompt_index=$((prompt_index + 15)) - fi - row=$((top + prompt_index + 1)) - col=$(((prime_agent_screen_cols - prompt_width) / 2 + prompt_width + 2)) - if [ "$col" -lt 1 ]; then - col=1 - fi - if [ "$col" -gt "$prime_agent_screen_cols" ]; then - col="$prime_agent_screen_cols" - fi - if ( : <>/dev/tty ) 2>/dev/null; then - printf '%s%s%s[%s;%sH' "$prime_agent_reset" "$prime_agent_show_cursor" "$prime_agent_esc" "$row" "$col" >/dev/tty - else - printf '%s%s%s[%s;%sH' "$prime_agent_reset" "$prime_agent_show_cursor" "$prime_agent_esc" "$row" "$col" >&2 - fi -} - prime_agent_pulse() { case $((prime_agent_screen_frame % 4)) in 0) printf '.' ;; @@ -741,15 +693,6 @@ prime_agent_run_quiet_with_animation() { prime_agent_run_quiet_with_animation_command "$title" "$status" "$detail" pulse "$@" } -prime_agent_run_quiet_with_animation_steps() { - title="$1" - status="$2" - details="$3" - shift 3 - - prime_agent_run_quiet_with_animation_command "$title" "$status" "$details" static "$@" -} - prime_agent_run_quiet_with_animation_command() { title="$1" status="$2" @@ -791,122 +734,6 @@ prime_agent_run_quiet_with_animation_command() { return "$command_status" } -prime_agent_prompt_yes_no() { - question="$1" - detail="$2" - input_prompt="$3" - - if ( : <>/dev/tty ) 2>/dev/null; then - prompt_input=tty - exec 3<>/dev/tty - elif [ -t 0 ]; then - prompt_input=stdin - else - return 2 - fi - - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "$question" "" "$detail" "$input_prompt" - prime_agent_place_prompt_cursor "$input_prompt" - else - printf '%s\n' "$detail" - if [ "$prompt_input" = tty ]; then - printf '%s ' "$input_prompt" >&3 - else - printf '%s ' "$input_prompt" >&2 - fi - fi - - if [ "$prompt_input" = tty ]; then - if ! IFS= read -r answer <&3; then - answer= - fi - exec 3>&- - else - if ! IFS= read -r answer; then - answer= - fi - fi - - case "$answer" in - n|N|no|NO) - return 1 - ;; - esac - return 0 -} - -start_preflight_checks() { - preflight_dir=$(create_temp_dir) - preflight_file="$preflight_dir/preflight" - run_preflight_checks >"$preflight_file" & - preflight_pid=$! -} - -finish_preflight_checks() { - if [ "$prime_agent_screen_enabled" = 1 ]; then - while kill -0 "$preflight_pid" 2>/dev/null; do - prime_agent_screen "Checking Node.js and npm$(prime_agent_pulse)" "" "" "" - sleep 0.18 - done - fi - - if wait "$preflight_pid"; then - preflight_status=0 - else - preflight_status=$? - fi - - if [ "$prime_agent_screen_enabled" = 1 ]; then - if [ "$preflight_status" -ne 0 ]; then - preflight_summary=$(sed -n '1p' "$preflight_file") - prime_agent_screen "Node.js 20.6.0 or newer is required" "" "$preflight_summary" "" - sleep 0.4 - elif [ -s "$preflight_file" ]; then - preflight_summary="Existing $prime_agent_cmd command found on PATH." - prime_agent_screen "Environment ready" "" "$preflight_summary" "" - sleep 0.4 - fi - else - cat "$preflight_file" - fi - rm -rf "$preflight_dir" - return "$preflight_status" -} - -run_preflight_checks() { - status=0 - yellow="${prime_agent_esc}[33m" - reset="${prime_agent_esc}[0m" - - if command -v node >/dev/null 2>&1; then - node_version=$(node --version) - if ! node -e 'const [major, minor, patch] = process.versions.node.split(".").map(Number); process.exit(major > 20 || (major === 20 && (minor > 6 || (minor === 6 && patch >= 0))) ? 0 : 1)' >/dev/null; then - printf 'error: Prime Agent requires Node.js 20.6.0 or newer. Found %s.\n' "$node_version" - status=1 - fi - else - printf 'error: Node.js 20.6.0 or newer is required to install Prime Agent.\n' - status=1 - fi - - if ! command -v npm >/dev/null 2>&1; then - printf 'error: npm is required to install Prime Agent.\n' - status=1 - fi - - if [ "$status" -ne 0 ]; then - printf '\n' - fi - - if prime_agent_path=$(command -v "$prime_agent_cmd" 2>/dev/null); then - printf '%sExisting %s found at: %s%s\n' "$yellow" "$prime_agent_cmd" "$prime_agent_path" "$reset" - printf '\n' - fi - - return "$status" -} - resolve_prime_agent_version() { if [ "${1:-}" ]; then case "$1" in @@ -973,387 +800,6 @@ normalize_version() { printf '%s' "$version" } -install_node_npm_interactive() { - method=$(detect_node_install_method) - case "$method" in - homebrew) label="Homebrew" ;; - apt) label="apt" ;; - apk) label="apk" ;; - standalone) label="standalone Node.js" ;; - *) - method=standalone - label="standalone Node.js" - ;; - esac - - if prime_agent_prompt_yes_no \ - "Install Node.js and npm with $label?" \ - "Required before Prime Agent can be installed." \ - "Install? [Y/n]"; then - install_node_npm "$method" "$label" - return - else - prompt_status=$? - fi - if [ "$prompt_status" -eq 2 ]; then - printf 'No terminal detected; install Node.js 20.6.0 or newer and npm, then run this installer again.\n' - else - printf '\nInstall Node.js 20.6.0 or newer and npm, then run this installer again.\n' - fi - return 1 -} - -detect_node_install_method() { - case "$(uname -s)" in - Darwin) - if command -v brew >/dev/null 2>&1; then - printf 'homebrew' - else - printf 'standalone' - fi - ;; - Linux) - if command -v apt-cache >/dev/null 2>&1 && command -v apt-get >/dev/null 2>&1 && apt_node_candidate_is_new_enough; then - printf 'apt' - elif command -v apk >/dev/null 2>&1 && apk_node_candidate_is_new_enough; then - printf 'apk' - else - printf 'standalone' - fi - ;; - *) - printf 'standalone' - ;; - esac -} - -apt_node_candidate_is_new_enough() { - version=$(apt-cache policy nodejs 2>/dev/null | awk '/Candidate:/ { print $2; exit }') - [ -n "$version" ] && [ "$version" != "(none)" ] && node_version_string_is_new_enough "$version" -} - -apk_node_candidate_is_new_enough() { - version=$(apk search -x nodejs 2>/dev/null | awk -F- '/^nodejs-/ { print $2; exit }') - [ -n "$version" ] && node_version_string_is_new_enough "$version" -} - -node_version_string_is_new_enough() { - version="${1#v}" - case "$version" in - [0-9]*) ;; - *) return 1 ;; - esac - version="${version%%[!0-9.]*}" - version_ifs=${IFS- } - IFS=. - set -- $version - IFS=$version_ifs - major="${1:-}" - minor="${2:-0}" - patch="${3:-0}" - case "$major" in ''|*[!0-9]*) return 1 ;; esac - case "$minor" in ''|*[!0-9]*) minor=0 ;; esac - case "$patch" in ''|*[!0-9]*) patch=0 ;; esac - - [ "$major" -gt 20 ] && return 0 - [ "$major" -eq 20 ] && [ "$minor" -gt 6 ] && return 0 - [ "$major" -eq 20 ] && [ "$minor" -eq 6 ] && [ "$patch" -ge 0 ] && return 0 - return 1 -} - -install_node_npm() { - method="$1" - label="$2" - - if [ "$prime_agent_screen_enabled" != 1 ]; then - printf '\nInstalling Node.js and npm with %s...\n\n' "$label" - run_node_install_method "$method" - else - prepare_sudo_for_node_install "$method" - node_install_details="Using $label. -Resolving Node.js packages. -Downloading Node.js runtime. -Installing npm. -Preparing Prime Agent setup." - prime_agent_run_quiet_with_animation_steps \ - "Installing Node.js and npm" \ - "Installing Node.js and npm" \ - "$node_install_details" \ - run_node_install_method "$method" - fi - - if [ "$method" = standalone ]; then - load_standalone_node - PRIME_AGENT_NODE_INSTALLED_STANDALONE=1 - fi - hash -r - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Node.js and npm installed" "" "Continuing Prime Agent setup." "" - else - printf '\nNode.js and npm are installed.\n\n' - fi -} - -node_install_needs_sudo() { - if [ "${EUID:-$(id -u)}" -eq 0 ]; then - return 1 - fi - - case "$1" in - apt|apk) - return 0 - ;; - standalone) - [ "$(uname -s)" = Linux ] || return 1 - command -v xz >/dev/null 2>&1 && return 1 - command -v apt-get >/dev/null 2>&1 || command -v apk >/dev/null 2>&1 - ;; - *) - return 1 - ;; - esac -} - -prepare_sudo_for_node_install() { - method="$1" - if ! node_install_needs_sudo "$method"; then - return 0 - fi - - prime_agent_screen "Preparing Node.js install" "" "This may ask for your sudo password." "" - prime_agent_restore_terminal - printf '\n' - sudo -v -} - -run_node_install_method() { - case "$1" in - homebrew) install_node_with_homebrew ;; - apt) install_node_with_apt ;; - apk) install_node_with_apk ;; - standalone) install_node_standalone ;; - esac -} - -install_node_with_homebrew() { - if brew list node >/dev/null 2>&1; then - brew upgrade node - else - brew install node - fi -} - -install_node_with_apt() { - print_sudo_note - if [ "${EUID:-$(id -u)}" -eq 0 ]; then - apt-get update - apt-get install -y nodejs npm - else - sudo sh -c 'apt-get update && apt-get install -y nodejs npm' - fi -} - -install_node_with_apk() { - print_sudo_note - run_with_sudo apk add --update-cache nodejs npm -} - -install_node_standalone() { - node_platform=$(detect_node_binary_platform) || { - printf 'Unsupported operating system for automatic Node.js install: %s\n' "$(uname -s)" - return 1 - } - node_arch=$(detect_node_binary_arch) || { - printf 'Unsupported CPU architecture for automatic Node.js install: %s\n' "$(uname -m)" - return 1 - } - node_dist_base="https://nodejs.org/dist/latest-v22.x" - node_base_dir=$(node_standalone_base_dir) - node_tmp_dir=$(create_temp_dir) - - mkdir -p "$node_tmp_dir" "$node_base_dir" - - printf 'Resolving Node.js binary for %s-%s\n' "$node_platform" "$node_arch" - curl -fsSL "$node_dist_base/SHASUMS256.txt" -o "$node_tmp_dir/SHASUMS256.txt" - node_file=$(awk -v suffix="-$node_platform-$node_arch.tar.xz" ' - index($2, "node-v") == 1 && length($2) >= length(suffix) && substr($2, length($2) - length(suffix) + 1) == suffix { print $2; exit } - ' "$node_tmp_dir/SHASUMS256.txt") - if [ -z "$node_file" ]; then - printf 'No Node.js binary is available for %s-%s.\n' "$node_platform" "$node_arch" - rm -rf "$node_tmp_dir" - return 1 - fi - case "$node_file" in - */*|*\\*|*..*) - printf 'Unsafe Node.js archive name in checksum manifest: %s\n' "$node_file" - rm -rf "$node_tmp_dir" - return 1 - ;; - node-v*-"$node_platform"-"$node_arch".tar.xz) ;; - *) - printf 'Unexpected Node.js archive name in checksum manifest: %s\n' "$node_file" - rm -rf "$node_tmp_dir" - return 1 - ;; - esac - - printf 'Downloading Node.js %s\n' "${node_file%.tar.xz}" - curl -fsSL "$node_dist_base/$node_file" -o "$node_tmp_dir/$node_file" - verify_node_standalone_download "$node_tmp_dir" "$node_file" - ensure_node_standalone_extract_tools "$node_platform" - - node_dir="$node_base_dir/${node_file%.tar.xz}" - rm -rf "$node_dir" - printf 'Extracting Node.js to %s\n' "$node_dir" - tar -xf "$node_tmp_dir/$node_file" -C "$node_base_dir" - rm -f "$node_base_dir/current" - ln -s "$node_dir" "$node_base_dir/current" - rm -rf "$node_tmp_dir" - printf 'Node.js installed at %s\n' "$node_dir" -} - -verify_node_standalone_download() { - checksum_dir="$1" - checksum_file_name="$2" - awk -v file="$checksum_file_name" '$2 == file { print }' "$checksum_dir/SHASUMS256.txt" >"$checksum_dir/SHASUMS256.selected" - - if command -v sha256sum >/dev/null 2>&1; then - printf 'Verifying Node.js download\n' - (cd "$checksum_dir" && sha256sum -c SHASUMS256.selected) - elif command -v shasum >/dev/null 2>&1; then - printf 'Verifying Node.js download\n' - (cd "$checksum_dir" && shasum -a 256 -c SHASUMS256.selected) - else - printf 'error: sha256sum or shasum is required to verify the Node.js download.\n' - return 1 - fi -} - -ensure_node_standalone_extract_tools() { - extract_platform="$1" - - if [ "$extract_platform" = linux ] && ! command -v xz >/dev/null 2>&1; then - printf 'Installing xz-utils for Node.js archive extraction\n' - print_sudo_note - if command -v apt-get >/dev/null 2>&1; then - run_with_sudo apt-get update - run_with_sudo apt-get install -y xz-utils - elif command -v apk >/dev/null 2>&1; then - run_with_sudo apk add --update-cache xz - else - printf 'xz is required to extract Node.js. Install xz and run this installer again.\n' - return 1 - fi - fi -} - -load_standalone_node() { - PRIME_AGENT_STANDALONE_NODE_BIN="$(node_standalone_base_dir)/current/bin" - PATH="$PRIME_AGENT_STANDALONE_NODE_BIN:$PATH" - export PRIME_AGENT_STANDALONE_NODE_BIN PATH -} - -node_standalone_base_dir() { - if [ -n "${XDG_DATA_HOME:-}" ]; then - printf '%s/prime-agent-node' "$XDG_DATA_HOME" - else - printf '%s/.local/share/prime-agent-node' "$HOME" - fi -} - -detect_node_binary_platform() { - case "$(uname -s)" in - Darwin) printf 'darwin' ;; - Linux) printf 'linux' ;; - *) return 1 ;; - esac -} - -detect_node_binary_arch() { - case "$(uname -m)" in - x86_64|amd64) printf 'x64' ;; - arm64|aarch64) printf 'arm64' ;; - armv7l) printf 'armv7l' ;; - ppc64le) printf 'ppc64le' ;; - s390x) printf 's390x' ;; - *) return 1 ;; - esac -} - -print_sudo_note() { - if [ "${EUID:-$(id -u)}" -ne 0 ]; then - printf 'This may ask for your sudo password.\n\n' - fi -} - -run_with_sudo() { - if [ "${EUID:-$(id -u)}" -eq 0 ]; then - "$@" - else - sudo "$@" - fi -} - -configure_standalone_node_path() { - if original_prime_agent_path=$(resolve_prime_agent_with_original_path); then - case "$original_prime_agent_path" in - "$PRIME_AGENT_STANDALONE_NODE_BIN/"*) - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "Run it with: $prime_agent_cmd" "" - else - printf '\nRun it with: %s\n' "$prime_agent_cmd" - fi - return 0 - ;; - esac - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "PATH update needed for $prime_agent_cmd." "" - else - printf '%s was installed, but your shell is not using that install yet.\n' "$prime_agent_cmd" - printf 'Your shell currently resolves %s to: %s\n' "$prime_agent_cmd" "$original_prime_agent_path" - fi - else - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "PATH update needed for $prime_agent_cmd." "" - else - printf '%s was installed, but your shell is not using that install yet.\n' "$prime_agent_cmd" - fi - fi - - profile=$(detect_shell_profile) || { - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_restore_terminal - printf '\n' - fi - print_standalone_path_manual_instructions - return 0 - } - - if shell_profile_has_standalone_node_path "$profile"; then - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "Run: $(prime_agent_source_profile_command "$profile")" "" - else - printf '%s already contains %s.\n' "$profile" "$PRIME_AGENT_STANDALONE_NODE_BIN" - printf 'Restart your shell or run: %s\n' "$(prime_agent_source_profile_command "$profile")" - fi - return 0 - fi - - prompt_add_standalone_node_path "$profile" -} - -resolve_prime_agent_with_original_path() { - saved_path=$PATH - PATH=$prime_agent_original_path - if command -v "$prime_agent_cmd" 2>/dev/null; then - status=0 - else - status=$? - fi - PATH=$saved_path - return "$status" -} - detect_shell_profile() { if [ -n "${PRIME_AGENT_SHELL_PROFILE:-}" ]; then printf '%s' "$PRIME_AGENT_SHELL_PROFILE" @@ -1384,119 +830,6 @@ detect_shell_profile() { esac } -shell_profile_has_standalone_node_path() { - profile="$1" - [ -f "$profile" ] && grep -F "$PRIME_AGENT_STANDALONE_NODE_BIN" "$profile" >/dev/null 2>&1 -} - -prompt_add_standalone_node_path() { - profile="$1" - path_line=$(standalone_node_path_line) - - if ! prime_agent_prompt_yes_no \ - "Add standalone Node.js to your PATH?" \ - "Updates $profile so future shells can run $prime_agent_cmd." \ - "Update PATH? [Y/n]"; then - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_restore_terminal - printf '\n' - fi - print_standalone_path_manual_instructions - return 0 - fi - - mkdir -p "$(dirname "$profile")" - { - printf '\n# Prime Agent standalone Node.js\n' - printf '%s\n' "$path_line" - } >>"$profile" - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "Run: $(prime_agent_source_profile_command "$profile")" "" - else - printf 'Added %s to %s.\n' "$PRIME_AGENT_STANDALONE_NODE_BIN" "$profile" - printf 'Restart your shell or run: %s\n' "$(prime_agent_source_profile_command "$profile")" - fi -} - -print_standalone_path_manual_instructions() { - printf 'Add this to your shell profile to use %s from new shells:\n\n' "$prime_agent_cmd" - printf ' %s\n' "$(standalone_node_path_line)" - printf '\nThen restart your shell and run: %s\n' "$prime_agent_cmd" -} - -standalone_node_path_line() { - printf 'export PATH="%s:$PATH"' "$PRIME_AGENT_STANDALONE_NODE_BIN" -} - -prime_agent_shell_quote() { - quoted=$(printf '%s' "$1" | sed "s/'/'\\\\''/g") - printf "'%s'" "$quoted" -} - -prime_agent_source_profile_command() { - printf '. %s && %s' "$(prime_agent_shell_quote "$1")" "$prime_agent_cmd" -} - -download_prime_agent_package() { - version="$1" - tarball_url="$2" - tarball_path="$3" - download_dir=$(dirname "$tarball_path") - tarball_name=$(basename "$tarball_path") - checksums_url="$prime_agent_base_url/releases/v$version/SHA256SUMS" - checksums_path="$download_dir/SHA256SUMS" - - if ! command -v curl >/dev/null 2>&1; then - printf 'error: curl is required to download Prime Agent.\n' >&2 - exit 1 - fi - - prime_agent_run_quiet_with_animation \ - "Downloading checksums" \ - "Downloading release checksums" \ - "Prime Agent v$version" \ - curl -fsSL "$checksums_url" -o "$checksums_path" - - prime_agent_run_quiet_with_animation \ - "Downloading Prime Agent" \ - "Downloading Prime Agent v$version" \ - "Fetching the verified package." \ - curl -fsSL "$tarball_url" -o "$tarball_path" - - verify_prime_agent_package_checksum "$checksums_path" "$tarball_path" -} - -verify_prime_agent_package_checksum() { - checksums_path="$1" - tarball_path="$2" - checksum_dir=$(dirname "$tarball_path") - tarball_name=$(basename "$tarball_path") - selected_checksums_path="$checksum_dir/SHA256SUMS.selected" - - if ! awk -v file="$tarball_name" '$2 == file { print; found = 1; exit } END { if (!found) exit 1 }' \ - "$checksums_path" >"$selected_checksums_path"; then - printf 'error: checksum for %s was not found in %s\n' "$tarball_name" "$checksums_path" >&2 - exit 1 - fi - - if command -v sha256sum >/dev/null 2>&1; then - prime_agent_run_quiet_with_animation \ - "Verifying download" \ - "Verifying Prime Agent download" \ - "Checking SHA-256." \ - prime_agent_run_checksum_check "$checksum_dir" "$(basename "$selected_checksums_path")" sha256sum - elif command -v shasum >/dev/null 2>&1; then - prime_agent_run_quiet_with_animation \ - "Verifying download" \ - "Verifying Prime Agent download" \ - "Checking SHA-256." \ - prime_agent_run_checksum_check "$checksum_dir" "$(basename "$selected_checksums_path")" shasum - else - printf 'error: sha256sum or shasum is required to verify the Prime Agent download.\n' >&2 - exit 1 - fi -} - prime_agent_run_checksum_check() { checksum_dir="$1" selected_checksums_name="$2" @@ -1511,111 +844,6 @@ prime_agent_run_checksum_check() { esac } -confirm_install() { - version="$1" - tarball_url="$2" - - if prime_agent_prompt_yes_no \ - "Install Prime Agent v$version globally with npm?" \ - "Downloads the verified release and runs npm install -g." \ - "Install? [Y/n]"; then - return 0 - else - prompt_status=$? - fi - - if [ "$prompt_status" -eq 2 ]; then - printf 'This will download, verify, and install:\n\n %s\n\n' "$tarball_url" - printf 'No terminal detected; continuing without confirmation.\n' - return 0 - fi - - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Installation cancelled" "" "No changes were made." "" - exit 0 - fi - printf '\nInstallation cancelled.\n' - exit 0 -} - -confirm_kernel_runtime_setup() { - case "${PRIME_AGENT_BOOTSTRAP_KERNEL_ON_INSTALL:-}" in - 1) - prime_agent_bootstrap_kernel_on_install=1 - return - ;; - 0) - prime_agent_bootstrap_kernel_on_install=0 - return - ;; - esac - - if prime_agent_prompt_yes_no \ - "Prepare Python runtime now?" \ - "Installs uv, Python 3.11, and the Prime Agent runtime." \ - "Prepare? [Y/n]"; then - prime_agent_bootstrap_kernel_on_install=1 - return - else - prompt_status=$? - fi - - if [ "$prompt_status" -eq 2 ]; then - printf 'No terminal detected; preparing the Python runtime during install.\n' - prime_agent_bootstrap_kernel_on_install=1 - return - fi - - prime_agent_bootstrap_kernel_on_install=0 - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Python setup skipped" "" "The runtime can be prepared on first ipython use." "" - sleep 0.4 - else - printf '\nSkipping Python runtime setup.\n' - fi -} - -install_prime_agent_package() { - tarball_path="$1" - if [ "$prime_agent_bootstrap_kernel_on_install" = 1 ]; then - npm_install_details="Preparing global install. -Linking command binaries. -Installing runtime packages. -Preloading search tools. -Preparing Python kernel. -Finalizing npm install." - prime_agent_run_quiet_with_animation_steps \ - "Installing Prime Agent" \ - "Installing Prime Agent" \ - "$npm_install_details" \ - env PRIME_AGENT_BOOTSTRAP_TOOLS_ON_INSTALL=1 PRIME_AGENT_BOOTSTRAP_KERNEL_ON_INSTALL=1 PRIME_AGENT_INSTALL_UV=1 npm install -g --no-fund --no-audit --loglevel=error --progress=false "$tarball_path" - else - npm_install_details="Preparing global install. -Linking command binaries. -Installing runtime packages. -Preloading search tools. -Finalizing npm install." - prime_agent_run_quiet_with_animation_steps \ - "Installing Prime Agent" \ - "Installing Prime Agent" \ - "$npm_install_details" \ - env PRIME_AGENT_BOOTSTRAP_TOOLS_ON_INSTALL=1 npm install -g --no-fund --no-audit --loglevel=error --progress=false "$tarball_path" - fi -} - - - -# ============================================================================= -# Binary Install Path (Bun-compiled artifact, no Node/npm needed) -# ============================================================================= - -# Architecture: install each release into a versioned directory -# ${XDG_DATA_HOME:-$HOME/.local/share}/prime-agent/versions/v/ -# and point a stable symlink at it from ~/.local/bin/prime-agent. -# On update: download to a fresh version dir, smoke-test the binary there, -# then atomically switch the symlink. Rollback by restoring the old symlink. -# Never copy runtime sidecars into user config dirs (~/.prime/*). - prime_agent_detect_binary_platform() { _os=$(uname -s) _arch=$(uname -m) @@ -1629,7 +857,7 @@ prime_agent_detect_binary_platform() { ;; Linux) if [ -f /etc/alpine-release ] || { command -v ldd >/dev/null 2>&1 && ldd --version 2>&1 | grep -qi musl; }; then - printf 'error: Prime Agent binaries require glibc Linux; use --method=npm on musl systems.\n' >&2 + printf 'error: Prime Agent compiled binaries require glibc Linux and do not support musl systems.\n' >&2 return 1 fi case "$_arch" in @@ -1662,6 +890,31 @@ prime_agent_binary_smoke_binary() { fi } +prime_agent_binary_validate_layout() { + _root="$1" + _binary="$2" + if ! prime_agent_binary_smoke_binary "$_binary"; then + printf 'error: the downloaded Prime Agent binary did not run correctly.\n' >&2 + return 1 + fi + for _relative_path in \ + package.json README.md CHANGELOG.md install.sh photon_rs_bg.wasm \ + prime-agent-runtime/pyproject.toml \ + theme/prime.json theme/dark.json theme/light.json theme/theme-schema.json \ + export-html/template.html export-html/template.css export-html/template.js; do + if [ ! -f "$_root/$_relative_path" ]; then + printf 'error: release archive is missing required sidecar: %s\n' "$_relative_path" >&2 + return 1 + fi + done + for _relative_dir in skills assets docs examples export-html/vendor; do + if [ ! -d "$_root/$_relative_dir" ]; then + printf 'error: release archive is missing required sidecar directory: %s\n' "$_relative_dir" >&2 + return 1 + fi + done +} + prime_agent_binary_atomic_symlink() { _target="$1" _link="$2" @@ -1702,7 +955,7 @@ prime_agent_binary_fresh_install() { if [ ! -x "$_existing_binary" ] && [ -x "$_version_dir/pi" ]; then _existing_binary="$_version_dir/pi" fi - if [ -x "$_existing_binary" ] && prime_agent_binary_smoke_binary "$_existing_binary"; then + if [ -x "$_existing_binary" ] && prime_agent_binary_validate_layout "$_version_dir" "$_existing_binary"; then prime_agent_binary_atomic_symlink "$_existing_binary" "$prime_agent_binary_symlink" prime_agent_configure_binary_path "$_version" return @@ -1754,13 +1007,6 @@ prime_agent_binary_fresh_install() { chmod +x "$_version_dir/install.sh" 2>/dev/null || true fi - if ! "$_binary_path" --version >/dev/null 2>&1; then - printf 'error: the downloaded binary did not run correctly.\n' >&2 - rm -rf "$_version_dir" "$_download_dir" - prime_agent_download_dir= - exit 1 - fi - # If the binary was inside a wrapper dir, move contents up to version_dir _binary_dir=$(dirname "$_binary_path") if [ "$_binary_dir" != "$_version_dir" ]; then @@ -1768,6 +1014,11 @@ prime_agent_binary_fresh_install() { rm -rf "$_binary_dir" _binary_path="$_version_dir/$(basename "$_binary_path")" fi + if ! prime_agent_binary_validate_layout "$_version_dir" "$_binary_path"; then + rm -rf "$_version_dir" "$_download_dir" + prime_agent_download_dir= + exit 1 + fi # Create the stable symlink mkdir -p "$(dirname "$prime_agent_binary_symlink")" @@ -1869,19 +1120,6 @@ prime_agent_binary_update() { chmod +x "$_version_dir/install.sh" 2>/dev/null || true fi - # Smoke-test the new binary BEFORE switching the symlink - if ! "$_binary_path" --version >/dev/null 2>&1; then - # New binary is bad: remove it, keep old symlink - rm -rf "$_version_dir" "$_download_dir" - prime_agent_download_dir= - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Update failed" "" "New binary did not run correctly." "" - else - printf '\nUpdate failed: the new binary did not run correctly.\n' - fi - exit 1 - fi - # If the binary was inside a wrapper dir, move contents up _binary_dir=$(dirname "$_binary_path") if [ "$_binary_dir" != "$_version_dir" ]; then @@ -1889,6 +1127,11 @@ prime_agent_binary_update() { rm -rf "$_binary_dir" _binary_path="$_version_dir/$(basename "$_binary_path")" fi + if ! prime_agent_binary_validate_layout "$_version_dir" "$_binary_path"; then + rm -rf "$_version_dir" "$_download_dir" + prime_agent_download_dir= + exit 1 + fi # Remember old version for rollback if [ -L "$prime_agent_binary_symlink" ]; then @@ -2008,74 +1251,5 @@ prime_agent_configure_binary_path() { # NPM Install Path (extracted from main) # ============================================================================= -prime_agent_npm_install() { - start_preflight_checks - - if finish_preflight_checks; then - check_status=0 - else - check_status=$? - fi - - if [ "$check_status" -ne 0 ]; then - if ! install_node_npm_interactive; then - exit "$check_status" - fi - - start_preflight_checks - if finish_preflight_checks; then - check_status=0 - else - check_status=$? - fi - - if [ "$check_status" -ne 0 ]; then - exit "$check_status" - fi - fi - - version="$(resolve_prime_agent_version "$@")" - tarball_name="$prime_agent_package-$version.tgz" - tarball_url="$prime_agent_base_url/releases/v$version/$tarball_name" - - confirm_install "$version" "$tarball_url" - confirm_kernel_runtime_setup - - download_dir=$(create_temp_dir) - prime_agent_download_dir="$download_dir" - tarball_path="$download_dir/$tarball_name" - - download_prime_agent_package "$version" "$tarball_url" "$tarball_path" - install_prime_agent_package "$tarball_path" - rm -rf "$download_dir" - prime_agent_download_dir= - - if [ "${PRIME_AGENT_NODE_INSTALLED_STANDALONE:-0}" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "Checking your shell PATH." "" - configure_standalone_node_path - elif command -v "$prime_agent_cmd" >/dev/null 2>&1; then - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "Run it with: $prime_agent_cmd" "" - else - printf '\nPrime Agent was installed successfully.\n' - printf '\nRun it with: %s\n' "$prime_agent_cmd" - fi - else - if [ "$prime_agent_screen_enabled" = 1 ]; then - prime_agent_screen "Prime Agent installed" "" "PATH update needed for $prime_agent_cmd." "" - prime_agent_restore_terminal - else - printf '\nPrime Agent was installed successfully.\n' - fi - cat < -Prime Agent began as a hard fork of [pi-mono](https://github.com/badlogic/pi-mono), but it is now developed and distributed independently. This workspace retains inherited `@earendil-works/pi-*` source package identifiers, the `pi` package manifest key, and a source-package `pi` bin entry for internal compatibility. Public releases are currently versioned tarball artifacts installed by the scripts below; release packaging rewrites the application package and command to `prime-agent`. Do not use the inherited npm package as the Prime Agent install path. +Prime Agent began as a hard fork of [pi-mono](https://github.com/badlogic/pi-mono), but it is now developed and distributed independently. This workspace retains inherited `@earendil-works/pi-*` source package identifiers, the `pi` package manifest key, and a source-package `pi` bin entry for internal compatibility. Public releases are compiled Bun binary archives installed by the scripts below; release packaging ships the application and command as `prime-agent`. Do not use the inherited npm package as the Prime Agent install path. ## Table of Contents diff --git a/packages/coding-agent/docs/development.md b/packages/coding-agent/docs/development.md index e3da5b8af9..8a702daea8 100644 --- a/packages/coding-agent/docs/development.md +++ b/packages/coding-agent/docs/development.md @@ -24,7 +24,7 @@ The script can be called from any directory and preserves the caller's working d Prime Agent is the product, public CLI, release artifact, and repository name. The monorepo still retains inherited `@earendil-works/pi-*` npm workspace names, a source-package `pi` bin entry, the `pi` package manifest key, and some `PI_*` compatibility environment variables. These names are source and compatibility details, not a signal that contributors should install or develop against pi-mono. -Public releases are currently versioned tarball artifacts installed by the stable and beta installer scripts. `scripts/pack-prime-agent-release.mjs` rewrites the coding-agent package name, executable, config metadata, and internal dependency URLs for that distribution. Do not document the inherited npm workspace package as the public Prime Agent install path. +Public releases are compiled Bun binary archives installed by the stable and beta installer scripts. `scripts/pack-prime-agent-release.mjs` assembles the platform archives and metadata. Do not document a package-manager install path for the public Prime Agent CLI. ## Local Configuration diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index 772b782052..4f75734fe7 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -13,7 +13,13 @@ afterEach(() => { for (const root of temporaryRoots.splice(0)) rmSync(root, { recursive: true, force: true }); }); -function makeRelease(root: string, version: string, executable: string, checksumIsValid = true): void { +function makeRelease( + root: string, + version: string, + executable: string, + checksumIsValid = true, + omitSidecar?: string, +): void { const platform = `${process.platform === "darwin" ? "darwin" : "linux"}-${process.arch === "arm64" ? "arm64" : "x64"}`; const releaseDir = join(root, "server", "releases", `v${version}`); const stage = join(root, `stage-${version}`); @@ -21,8 +27,34 @@ function makeRelease(root: string, version: string, executable: string, checksum mkdirSync(stage, { recursive: true }); writeFileSync(join(stage, "prime-agent"), executable); chmodSync(join(stage, "prime-agent"), 0o755); - writeFileSync(join(stage, "package.json"), JSON.stringify({ name: "prime-agent", version })); - writeFileSync(join(stage, "install.sh"), "#!/bin/sh\n"); + const requiredFiles = [ + "package.json", + "README.md", + "CHANGELOG.md", + "install.sh", + "photon_rs_bg.wasm", + "prime-agent-runtime/pyproject.toml", + "theme/prime.json", + "theme/dark.json", + "theme/light.json", + "theme/theme-schema.json", + "export-html/template.html", + "export-html/template.css", + "export-html/template.js", + ]; + for (const relative of requiredFiles) { + mkdirSync(dirname(join(stage, relative)), { recursive: true }); + writeFileSync( + join(stage, relative), + relative === "package.json" ? JSON.stringify({ name: "prime-agent", version }) : "fixture", + ); + } + for (const relative of ["skills", "assets", "docs", "examples", "export-html/vendor"]) { + mkdirSync(join(stage, relative), { recursive: true }); + writeFileSync(join(stage, relative, ".keep"), "fixture"); + } + if (omitSidecar) rmSync(join(stage, omitSidecar), { recursive: true, force: true }); + chmodSync(join(stage, "install.sh"), 0o755); const archiveName = `prime-agent-${version}-${platform}.tar.gz`; const archive = join(releaseDir, archiveName); const packed = spawnSync("tar", ["-czf", archive, "-C", stage, "."], { encoding: "utf8" }); @@ -108,6 +140,21 @@ describe("compiled binary installer", () => { expect(readFileSync(join(root, "home", ".prime", "sentinel"), "utf8")).toBe("user data"); }); + test("keeps the previous version when an update is missing a required sidecar", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + expect(runInstaller(root, ["1.2.3"]).exitCode).toBe(0); + const link = join(root, "bin", "prime-agent"); + const oldTarget = readlinkSync(link); + + makeRelease(root, "2.0.0", goodExecutable("2.0.0"), true, "theme/prime.json"); + const result = runInstaller(root, ["--update", "2.0.0"]); + expect(result.exitCode).not.toBe(0); + expect(result.stderr).toContain("missing required sidecar: theme/prime.json"); + expect(readlinkSync(link)).toBe(oldTarget); + }); + test("rolls back when the activated symlink fails its smoke test", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); temporaryRoots.push(root); diff --git a/packages/coding-agent/test/bun-installer.test.ts b/packages/coding-agent/test/bun-installer.test.ts index 12ba085d72..72f2294db0 100644 --- a/packages/coding-agent/test/bun-installer.test.ts +++ b/packages/coding-agent/test/bun-installer.test.ts @@ -40,27 +40,17 @@ describe("install.sh shell syntax", () => { expect(() => execFileSync("sh", ["-n", installer], { stdio: "pipe" })).not.toThrow(); }); - it("contains the npm install function", () => { - expect(installerText).toContain("prime_agent_npm_install"); - }); - - it("supports --method and --update flags", () => { - expect(installerText).toContain("--method=*"); - expect(installerText).toContain("binary|npm|auto"); + it("supports compiled binary installs and updates only", () => { + expect(installerText).toContain("prime_agent_binary_fresh_install"); + expect(installerText).toContain("prime_agent_binary_update"); expect(installerText).toContain("--update"); + expect(installerText).not.toContain("prime_agent_npm_install"); + expect(installerText).not.toContain("install_node_npm"); + expect(installerText).not.toContain("npm install"); }); -}); -// ============================================================================ -describe("default install method (auto) routes to binary", () => { - it("routes auto and binary to binary_fresh_install, never npm", () => { - expect(installerText).toMatch(/\$prime_agent_install_method" != npm/); - }); - - it("uses npm only with explicit --method=npm", () => { - const matches = installerText.match(/\$prime_agent_install_method"\s*!=\s*npm/g); - expect(matches).not.toBeNull(); - expect(matches!.length).toBeGreaterThanOrEqual(1); + it("rejects removed package-manager method flags", () => { + expect(installerText).toContain("--method is no longer supported"); }); }); diff --git a/packages/coding-agent/test/bun-release-archives.test.ts b/packages/coding-agent/test/bun-release-archives.test.ts index 66e0c68854..836c2bc37b 100644 --- a/packages/coding-agent/test/bun-release-archives.test.ts +++ b/packages/coding-agent/test/bun-release-archives.test.ts @@ -90,24 +90,7 @@ describe("compiled release archives", () => { const archives = readdirSync(artifacts).filter((name) => name.endsWith(".tar.gz")); expect(archives.sort()).toEqual(platforms.map((platform) => `prime-agent-1.2.3-${platform}.tar.gz`).sort()); expect(readFileSync(join(artifacts, "stable"), "utf8")).toBe("v1.2.3\n"); - expect(readFileSync(join(artifacts, "SHA256SUMS"), "utf8").trim().split("\n")).toHaveLength(8); - for (const tarball of [ - "prime-agent-1.2.3.tgz", - "prime-agent-ai-1.2.3.tgz", - "prime-agent-core-1.2.3.tgz", - "prime-agent-tui-1.2.3.tgz", - ]) { - expect(existsSync(join(artifacts, tarball)), tarball).toBe(true); - } - const npmExtracted = join(f.root, "npm-extracted"); - mkdirSync(npmExtracted); - expect(spawnSync("tar", ["-xzf", join(artifacts, "prime-agent-1.2.3.tgz"), "-C", npmExtracted]).status).toBe(0); - expect(JSON.parse(readFileSync(join(npmExtracted, "package", "package.json"), "utf8"))).toMatchObject({ - name: "prime-agent", - version: "1.2.3", - bin: { "prime-agent": "dist/bundle/cli.js" }, - scripts: { postinstall: "node postinstall.cjs" }, - }); + expect(readFileSync(join(artifacts, "SHA256SUMS"), "utf8").trim().split("\n")).toHaveLength(4); const extracted = join(f.root, "extracted"); mkdirSync(extracted); @@ -165,28 +148,22 @@ describe("compiled release archives", () => { expect(result.status).not.toBe(0); expect(result.stderr).toContain("forbidden dependency or cache directory"); }); - test("normalizes v-prefixed versions for npm artifact URLs", () => { + test("normalizes v-prefixed versions for binary archive metadata", () => { const f = fixture(); const result = pack(f, ["--version", "v1.2.3"]); expect(result.status, result.stderr).toBe(0); const manifest = JSON.parse(readFileSync(join(f.output, "artifacts", "latest.json"), "utf8")); - expect(manifest.tarball).toBe("releases/v1.2.3/prime-agent-1.2.3.tgz"); - expect(existsSync(join(f.output, "artifacts", "prime-agent-1.2.3.tgz"))).toBe(true); + expect(manifest.version).toBe("v1.2.3"); + expect(manifest.baseUrl).toBe("https://downloads.example.test/releases/v1.2.3"); + expect(existsSync(join(f.output, "artifacts", "prime-agent-1.2.3-darwin-arm64.tar.gz"))).toBe(true); }); - test("trims release base URLs before writing npm dependency specs", () => { + test("trims release base URLs before writing binary metadata", () => { const f = fixture(); const result = pack(f, ["--base-url", " https://downloads.example.test/ "]); expect(result.status, result.stderr).toBe(0); - const packedManifest = spawnSync( - "tar", - ["-xOzf", join(f.output, "artifacts", "prime-agent-1.2.3.tgz"), "package/package.json"], - { encoding: "utf8" }, - ); - expect(packedManifest.status, packedManifest.stderr).toBe(0); - expect(JSON.parse(packedManifest.stdout).dependencies["@earendil-works/pi-ai"]).toBe( - "https://downloads.example.test/releases/v1.2.3/prime-agent-ai-1.2.3.tgz", - ); + const manifest = JSON.parse(readFileSync(join(f.output, "artifacts", "latest.json"), "utf8")); + expect(manifest.baseUrl).toBe("https://downloads.example.test/releases/v1.2.3"); }); test("rejects insecure release base URLs", () => { diff --git a/scripts/build-binaries.sh b/scripts/build-binaries.sh index b8951a7e8d..18a6915e99 100755 --- a/scripts/build-binaries.sh +++ b/scripts/build-binaries.sh @@ -17,7 +17,6 @@ # # packages/coding-agent/release/artifacts/ # prime-agent--.tar.gz -# prime-agent-.tgz (plus internal workspace tarballs) # SHA256SUMS # stable # latest.json @@ -118,7 +117,7 @@ bun ../../scripts/pack-prime-agent-release.mjs \ echo "" echo "==> Build complete!" echo "Release archives:" -ls -lh "release/artifacts/"*.tar.gz "release/artifacts/"*.tgz 2>/dev/null || true +ls -lh "release/artifacts/"*.tar.gz echo "" echo "Metadata:" ls -lh "release/artifacts/SHA256SUMS" "release/artifacts/latest.json" "release/artifacts/stable" 2>/dev/null || true diff --git a/scripts/check-installer-render.mjs b/scripts/check-installer-render.mjs index 835f306bbc..c4b5878080 100644 --- a/scripts/check-installer-render.mjs +++ b/scripts/check-installer-render.mjs @@ -93,9 +93,9 @@ screen_case() { } progress_case() { - progress_details="Preparing global install. -Linking command binaries. -Finalizing npm install." + progress_details="Downloading verified archive. +Extracting compiled binary. +Validating runtime sidecars." for progress_frame in 1 24 25 48 49 200; do prime_agent_animation_frame="$progress_frame" printf '__PROGRESS__ %s\t%s\t%s\\n' "$progress_frame" "$(prime_agent_animation_status "Installing Prime Agent" "$progress_details" static)" "$(prime_agent_animation_detail "$progress_details")" @@ -241,12 +241,12 @@ function assertInstallerProgress(progress) { if (progress.length !== 6) return; const expectedDetails = [ - "Preparing global install.", - "Preparing global install.", - "Linking command binaries.", - "Linking command binaries.", - "Finalizing npm install.", - "Finalizing npm install.", + "Downloading verified archive.", + "Downloading verified archive.", + "Extracting compiled binary.", + "Extracting compiled binary.", + "Validating runtime sidecars.", + "Validating runtime sidecars.", ]; for (const [index, expectedDetail] of expectedDetails.entries()) { check( diff --git a/scripts/pack-prime-agent-release.mjs b/scripts/pack-prime-agent-release.mjs index 1f101d683d..184ac02ab2 100755 --- a/scripts/pack-prime-agent-release.mjs +++ b/scripts/pack-prime-agent-release.mjs @@ -1,14 +1,12 @@ #!/usr/bin/env bun /** - * Produce Bun-compiled platform archives and npm-compatible tarballs. + * Produce Bun-compiled platform archives. * * This script is the CI entry point for the release artifact lane. It expects * pre-built Bun-compiled binaries for 4 platforms (darwin-arm64, darwin-x64, * linux-arm64, linux-x64) and sidecar files, then produces platform-specific * .tar.gz archives with checksums and channel metadata. * - * Bun creates both native archives and npm-compatible package tarballs. - * * Usage: * bun scripts/pack-prime-agent-release.mjs \ * --base-url \ @@ -21,28 +19,18 @@ * Output: * /artifacts/ * prime-agent--.tar.gz - * prime-agent-.tgz (plus internal workspace tarballs) * SHA256SUMS * * latest.json|beta.json */ -import { createHash } from "node:crypto"; -import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { existsSync, readFileSync } from "node:fs"; import { resolve, join } from "node:path"; const root = resolve(import.meta.dirname, ".."); const defaultOutputDir = join(root, "packages", "coding-agent", "release"); const defaultBaseUrl = process.env.PRIME_AGENT_DOWNLOAD_BASE_URL; const releaseChannels = new Set(["stable", "beta"]); -const publicPackageName = "prime-agent"; -const publicCommandName = "prime-agent"; -const releasePackages = [ - { packageDir: "ai", publicName: "prime-agent-ai" }, - { packageDir: "tui", publicName: "prime-agent-tui" }, - { packageDir: "agent", publicName: "prime-agent-core" }, - { packageDir: "coding-agent", publicName: publicPackageName }, -]; function parseArgs(args) { const parsed = { @@ -143,113 +131,6 @@ Creates platform release archives: `); } -function sha256File(path) { - const hash = createHash("sha256"); - hash.update(readFileSync(path)); - return hash.digest("hex"); -} - -function rewriteInternalDependencies(dependencies, internalPackageUrls) { - if (!dependencies) return undefined; - return Object.fromEntries( - Object.entries(dependencies).map(([name, range]) => [name, internalPackageUrls.get(name) || range]), - ); -} - -function createReleasePackageJson(sourcePackage, packageName, version, internalPackageUrls) { - const manifest = { - ...sourcePackage, - name: packageName, - version, - dependencies: rewriteInternalDependencies(sourcePackage.dependencies, internalPackageUrls), - optionalDependencies: rewriteInternalDependencies(sourcePackage.optionalDependencies, internalPackageUrls), - scripts: sourcePackage.scripts?.postinstall ? { postinstall: "node postinstall.cjs" } : undefined, - }; - delete manifest.devDependencies; - delete manifest.overrides; - delete manifest.private; - if (packageName === publicPackageName) { - manifest.bin = { [publicCommandName]: "dist/bundle/cli.js" }; - manifest.piConfig = { ...(manifest.piConfig || {}), name: publicCommandName, configDir: ".prime/agent" }; - } - return manifest; -} - -function copyPackageContents(sourceDir, targetDir, packageJson) { - mkdirSync(targetDir, { recursive: true }); - writeFileSync(join(targetDir, "package.json"), `${JSON.stringify(packageJson, null, 2)}\n`); - for (const entry of ["dist", "docs", "examples", "skills", "postinstall.cjs", "README.md", "CHANGELOG.md"]) { - const source = join(sourceDir, entry); - if (existsSync(source)) cpSync(source, join(targetDir, entry), { recursive: true }); - } -} - -function packNpmCompatibilityTarballs(args) { - const artifactsDir = join(args.outDir, "artifacts"); - const stagingRoot = join(args.outDir, "npm-packages"); - const packageSources = new Map(); - for (const releasePackage of releasePackages) { - const sourceDir = join(root, "packages", releasePackage.packageDir); - if (!existsSync(join(sourceDir, "dist"))) { - throw new Error(`Missing built package: ${sourceDir}/dist`); - } - packageSources.set(releasePackage.packageDir, JSON.parse(readFileSync(join(sourceDir, "package.json"), "utf8"))); - } - - const artifactFiles = new Map( - releasePackages.map(({ packageDir, publicName }) => [packageDir, `${publicName}-${args.version}.tgz`]), - ); - const internalPackageUrls = new Map(); - for (const { packageDir, publicName } of releasePackages) { - if (packageDir === "coding-agent") continue; - const sourceName = packageSources.get(packageDir).name; - internalPackageUrls.set(sourceName, `${args.baseUrl}/releases/v${args.version}/${artifactFiles.get(packageDir)}`); - } - - const tarballs = []; - try { - rmSync(stagingRoot, { recursive: true, force: true }); - for (const { packageDir, publicName } of releasePackages) { - const stagingDir = join(stagingRoot, packageDir); - copyPackageContents( - join(root, "packages", packageDir), - stagingDir, - createReleasePackageJson(packageSources.get(packageDir), publicName, args.version, internalPackageUrls), - ); - const result = Bun.spawnSync([process.execPath, "pm", "pack", "--destination", artifactsDir], { - cwd: stagingDir, - stdout: "pipe", - stderr: "pipe", - }); - if (result.exitCode !== 0) { - throw new Error(`bun pm pack failed for ${packageDir}: ${result.stderr.toString()}`); - } - const file = artifactFiles.get(packageDir); - const path = join(artifactsDir, file); - if (!existsSync(path)) throw new Error(`bun pm pack did not create ${path}`); - tarballs.push({ package: publicName, file, sha256: sha256File(path) }); - } - } finally { - rmSync(stagingRoot, { recursive: true, force: true }); - } - - const checksumPath = join(artifactsDir, "SHA256SUMS"); - const checksums = readFileSync(checksumPath, "utf8") - .trim() - .split("\n") - .filter(Boolean); - checksums.push(...tarballs.map(({ file, sha256 }) => `${sha256} ${file}`)); - checksums.sort((left, right) => left.split(/\s+/).at(-1).localeCompare(right.split(/\s+/).at(-1))); - writeFileSync(checksumPath, `${checksums.join("\n")}\n`); - - const manifestName = args.channel === "stable" ? "latest.json" : "beta.json"; - const manifestPath = join(artifactsDir, manifestName); - const manifest = JSON.parse(readFileSync(manifestPath, "utf8")); - manifest.tarball = `releases/v${args.version}/${artifactFiles.get("coding-agent")}`; - manifest.tarballs = tarballs; - writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`); -} - async function main() { const args = parseArgs(process.argv.slice(2)); @@ -281,7 +162,6 @@ async function main() { if (result.status !== 0) { throw new Error(`assemble-release-archives.mjs failed with exit code ${result.status}`); } - packNpmCompatibilityTarballs(args); } try { diff --git a/scripts/release.mjs b/scripts/release.mjs index 65adaea803..bee63bcf43 100755 --- a/scripts/release.mjs +++ b/scripts/release.mjs @@ -13,7 +13,7 @@ * 3. Update CHANGELOG.md files: aggregate .changes/*.md fragments into a * [version] - date section, git rm the consumed fragments * 4. Commit and tag - * 5. Publish the npm compatibility packages with Bun + * 5. Publish registry packages with Bun */ import { execSync } from "child_process"; @@ -212,7 +212,7 @@ run(`git commit -m "Release v${version}"`); run(`git tag v${version}`); console.log(); -console.log("Publishing npm compatibility packages..."); +console.log("Publishing registry packages with Bun..."); run("bun run publish"); console.log(); From 7deaf892816d7e41514ca421c755d03abe07b860 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 18:59:54 -0400 Subject: [PATCH 19/31] fix: reject ambiguous release URLs --- .../coding-agent/test/bun-installer-e2e.test.ts | 15 ++++++++++++--- .../test/bun-release-archives.test.ts | 9 +++++++++ scripts/assemble-release-archives.mjs | 4 +++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index 4f75734fe7..60327ffc2e 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -1,7 +1,16 @@ import { afterEach, describe, expect, test } from "bun:test"; import { spawnSync } from "node:child_process"; import { createHash } from "node:crypto"; -import { chmodSync, mkdirSync, mkdtempSync, readFileSync, readlinkSync, rmSync, writeFileSync } from "node:fs"; +import { + chmodSync, + mkdirSync, + mkdtempSync, + readFileSync, + readlinkSync, + realpathSync, + rmSync, + writeFileSync, +} from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; @@ -105,7 +114,7 @@ describe("compiled binary installer", () => { const result = runInstaller(root, ["1.2.3"]); expect(result.exitCode, result.stderr).toBe(0); - const target = join(root, "apps", "versions", "v1.2.3", "prime-agent"); + const target = join(realpathSync(root), "apps", "versions", "v1.2.3", "prime-agent"); expect(readlinkSync(join(root, "bin", "prime-agent"))).toBe(target); expect(readFileSync(join(root, "apps", "versions", "v1.2.3", "package.json"), "utf8")).toContain('"1.2.3"'); expect(readFileSync(join(root, "home", ".prime", "sentinel"), "utf8")).toBe("user data"); @@ -209,7 +218,7 @@ describe("compiled binary installer", () => { const result = runInstaller(root, ["1.2.3"], { PRIME_AGENT_VERSIONS_DIR: "relative/versions" }); expect(result.exitCode, result.stderr).toBe(0); expect(readlinkSync(join(root, "bin", "prime-agent"))).toBe( - join(root, "relative", "versions", "v1.2.3", "prime-agent"), + join(realpathSync(root), "relative", "versions", "v1.2.3", "prime-agent"), ); }); }); diff --git a/packages/coding-agent/test/bun-release-archives.test.ts b/packages/coding-agent/test/bun-release-archives.test.ts index 836c2bc37b..8b35dc50ad 100644 --- a/packages/coding-agent/test/bun-release-archives.test.ts +++ b/packages/coding-agent/test/bun-release-archives.test.ts @@ -173,6 +173,15 @@ describe("compiled release archives", () => { expect(result.stderr).toContain("must use HTTPS"); }); + test("rejects empty query and fragment delimiters in release base URLs", () => { + for (const delimiter of ["?", "#"]) { + const f = fixture(); + const result = pack(f, ["--base-url", `https://downloads.example.test/${delimiter}`]); + expect(result.status).not.toBe(0); + expect(result.stderr).toContain("must not contain a query or fragment"); + } + }); + test("rejects shell-active release base URLs", () => { const f = fixture(); const result = pack(f, ["--base-url", "https://downloads.example.test/$(touch-danger)"]); diff --git a/scripts/assemble-release-archives.mjs b/scripts/assemble-release-archives.mjs index 282b5c9061..ca175a50e6 100755 --- a/scripts/assemble-release-archives.mjs +++ b/scripts/assemble-release-archives.mjs @@ -177,7 +177,9 @@ function normalizeBaseUrl(value) { if (parsed.protocol !== "https:" || !parsed.hostname || parsed.username || parsed.password) { throw new Error(`Release base URL must use HTTPS without credentials: ${value}`); } - if (parsed.search || parsed.hash) throw new Error("Release base URL must not contain a query or fragment"); + if (parsed.search || parsed.hash || /[?#]$/.test(parsed.toString())) { + throw new Error("Release base URL must not contain a query or fragment"); + } return parsed.toString().replace(/\/+$/, ""); } From c465c92631a775c1b27478bcfa4e2a968393d36b Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 19:05:11 -0400 Subject: [PATCH 20/31] fix: verify activated binary install paths --- install.sh | 55 ++++++++----------- .../test/bun-installer-e2e.test.ts | 33 +++++++++++ .../coding-agent/test/bun-installer.test.ts | 5 ++ 3 files changed, 60 insertions(+), 33 deletions(-) diff --git a/install.sh b/install.sh index 41f53e530d..1e3ccf6f6b 100755 --- a/install.sh +++ b/install.sh @@ -13,10 +13,8 @@ if [ "$prime_agent_default_release_channel" = "$prime_agent_unconfigured_default prime_agent_default_release_channel=stable fi prime_agent_release_channel="${PRIME_AGENT_RELEASE_CHANNEL:-$prime_agent_default_release_channel}" -prime_agent_package="${PRIME_AGENT_PACKAGE:-prime-agent}" prime_agent_cmd="${PRIME_AGENT_CMD:-prime-agent}" prime_agent_esc=$(printf '\033') -prime_agent_original_path="${PATH:-}" prime_agent_reset="${prime_agent_esc}[0m" prime_agent_bold="${prime_agent_esc}[1m" prime_agent_italic="${prime_agent_esc}[3m" @@ -33,7 +31,7 @@ prime_agent_color_dim="${prime_agent_esc}[38;2;113;113;122m" prime_agent_color_primary="${prime_agent_esc}[38;2;127;91;213m" prime_agent_color_scan="${prime_agent_esc}[38;2;14;165;233m" prime_agent_color_warning="${prime_agent_esc}[38;2;245;158;11m" -readonly prime_agent_unconfigured_base_url prime_agent_unconfigured_default_release_channel prime_agent_base_url prime_agent_default_release_channel prime_agent_release_channel prime_agent_package prime_agent_cmd prime_agent_esc prime_agent_original_path +readonly prime_agent_unconfigured_base_url prime_agent_unconfigured_default_release_channel prime_agent_base_url prime_agent_default_release_channel prime_agent_release_channel prime_agent_cmd prime_agent_esc readonly prime_agent_reset prime_agent_bold prime_agent_italic prime_agent_hide_cursor prime_agent_show_cursor prime_agent_home_cursor prime_agent_clear_screen prime_agent_clear_line readonly prime_agent_sync_start prime_agent_sync_end readonly prime_agent_color_text prime_agent_color_muted prime_agent_color_dim prime_agent_color_primary prime_agent_color_scan prime_agent_color_warning @@ -51,11 +49,9 @@ prime_agent_screen_layout_lab_width=0 prime_agent_screen_render_lab_width=0 prime_agent_screen_compact=0 prime_agent_download_dir= -prime_agent_bootstrap_kernel_on_install=0 prime_agent_screen_title= prime_agent_screen_status= prime_agent_screen_detail= -prime_agent_screen_question= prime_agent_animation_frame=0 prime_agent_binary_versions_dir="${PRIME_AGENT_VERSIONS_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/prime-agent/versions}" prime_agent_binary_symlink="${PRIME_AGENT_BIN_DIR:-${XDG_BIN_HOME:-$HOME/.local/bin}}/prime-agent" @@ -197,7 +193,6 @@ prime_agent_screen() { fi prime_agent_screen_status= prime_agent_screen_detail="${3:-}" - prime_agent_screen_question="${4:-}" prime_agent_screen_frame=$((prime_agent_screen_frame + 1)) prime_agent_read_terminal_size prime_agent_init_screen_layout @@ -341,18 +336,12 @@ prime_agent_content_line() { fi if [ "$index" -eq 0 ]; then - if [ -n "$prime_agent_screen_question" ]; then - prime_agent_set_text_line "$(prime_agent_screen_primary_text)" "$prime_agent_bold$prime_agent_color_text" - else - prime_agent_set_title_line "$prime_agent_screen_title" - fi + prime_agent_set_title_line "$prime_agent_screen_title" return fi if [ "$index" -eq 1 ]; then - if [ -n "$prime_agent_screen_question" ]; then - prime_agent_set_text_line "Press Enter to continue; type n to cancel." "$prime_agent_color_muted" - elif [ -n "$prime_agent_screen_detail" ]; then + if [ -n "$prime_agent_screen_detail" ]; then prime_agent_set_text_line "$prime_agent_screen_detail" "$prime_agent_color_muted" else prime_agent_set_blank_line @@ -361,18 +350,6 @@ prime_agent_content_line() { fi } -prime_agent_screen_primary_text() { - if [ -z "$prime_agent_screen_question" ]; then - printf '%s' "$prime_agent_screen_title" - return - fi - - case "$prime_agent_screen_question" in - *'[Y/n]'*) printf '%s [Y/n] >' "$prime_agent_screen_title" ;; - *) printf '%s %s' "$prime_agent_screen_title" "$prime_agent_screen_question" ;; - esac -} - prime_agent_set_lab_line() { lab_row="$1" prime_agent_lab_width="$prime_agent_screen_render_lab_width" @@ -1020,9 +997,25 @@ prime_agent_binary_fresh_install() { exit 1 fi - # Create the stable symlink + # Create and verify the stable symlink. Restore a healthy prior target if the + # activated command cannot run through its public path. + _old_target= + if [ -L "$prime_agent_binary_symlink" ]; then + _old_target=$(readlink "$prime_agent_binary_symlink" 2>/dev/null || printf '') + fi mkdir -p "$(dirname "$prime_agent_binary_symlink")" prime_agent_binary_atomic_symlink "$_binary_path" "$prime_agent_binary_symlink" + if ! prime_agent_binary_smoke_binary "$prime_agent_binary_symlink"; then + if [ -n "$_old_target" ] && prime_agent_binary_smoke_binary "$_old_target"; then + prime_agent_binary_atomic_symlink "$_old_target" "$prime_agent_binary_symlink" + else + rm -f "$prime_agent_binary_symlink" + fi + rm -rf "$_version_dir" "$_download_dir" + prime_agent_download_dir= + printf 'error: the installed Prime Agent command did not run correctly.\n' >&2 + exit 1 + fi rm -rf "$_download_dir" prime_agent_download_dir= @@ -1045,7 +1038,8 @@ prime_agent_binary_update() { fi fi - if [ -n "$_current_version" ] && [ "$_current_version" = "$_update_version" ]; then + if [ -n "$_current_version" ] && [ "$_current_version" = "$_update_version" ] && + prime_agent_binary_validate_layout "$_pkg_dir" "$prime_agent_binary_symlink"; then if [ "$prime_agent_screen_enabled" = 1 ]; then prime_agent_screen "Prime Agent is up to date" "" "v$_current_version" "" else @@ -1247,9 +1241,4 @@ prime_agent_configure_binary_path() { fi } -# ============================================================================= -# NPM Install Path (extracted from main) -# ============================================================================= - - main "$@" diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index 60327ffc2e..0dc6d18f4f 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -124,6 +124,21 @@ describe("compiled binary installer", () => { expect(readlinkSync(join(root, "bin", "prime-agent"))).toBe(target); }); + test("rejects a fresh install that fails through the activated command symlink", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease( + root, + "1.2.3", + '#!/bin/sh\ncase "$0" in */bin/prime-agent) exit 1 ;; esac\nif [ "$1" = "--version" ]; then exit 0; fi\nexit 0\n', + ); + + const result = runInstaller(root, ["1.2.3"]); + expect(result.exitCode).not.toBe(0); + expect(result.stderr).toContain("installed Prime Agent command did not run correctly"); + expect(() => readlinkSync(join(root, "bin", "prime-agent"))).toThrow(); + }); + test("rejects a bad checksum before changing the active version", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); temporaryRoots.push(root); @@ -134,6 +149,24 @@ describe("compiled binary installer", () => { expect(() => readlinkSync(join(root, "bin", "prime-agent"))).toThrow(); }); + test("repairs a broken active command when updating to the same version", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + expect(runInstaller(root, ["1.2.3"]).exitCode).toBe(0); + const link = join(root, "bin", "prime-agent"); + const target = readlinkSync(link); + writeFileSync(target, "#!/bin/sh\nexit 1\n"); + chmodSync(target, 0o755); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + + const result = runInstaller(root, ["--update", "1.2.3"]); + expect(result.exitCode, result.stderr).toBe(0); + const smoke = spawnSync(link, ["--version"], { encoding: "utf8" }); + expect(smoke.status).toBe(0); + expect(smoke.stdout).toContain("1.2.3"); + }); + test("keeps the previous symlink when an update fails its smoke test", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); temporaryRoots.push(root); diff --git a/packages/coding-agent/test/bun-installer.test.ts b/packages/coding-agent/test/bun-installer.test.ts index 72f2294db0..93f3d2f950 100644 --- a/packages/coding-agent/test/bun-installer.test.ts +++ b/packages/coding-agent/test/bun-installer.test.ts @@ -47,6 +47,11 @@ describe("install.sh shell syntax", () => { expect(installerText).not.toContain("prime_agent_npm_install"); expect(installerText).not.toContain("install_node_npm"); expect(installerText).not.toContain("npm install"); + expect(installerText).not.toContain("NPM Install Path"); + expect(installerText).not.toContain("prime_agent_package"); + expect(installerText).not.toContain("prime_agent_original_path"); + expect(installerText).not.toContain("prime_agent_bootstrap_kernel_on_install"); + expect(installerText).not.toContain("prime_agent_screen_question"); }); it("rejects removed package-manager method flags", () => { From e53576de8b56c15144872a444725ace4c8d656c2 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 19:12:01 -0400 Subject: [PATCH 21/31] fix: serialize binary installer activation --- install.sh | 39 ++++++++++- packages/ai/src/models.generated.ts | 6 +- .../test/bun-installer-e2e.test.ts | 67 +++++++++++++++---- .../coding-agent/test/bun-installer.test.ts | 2 + 4 files changed, 95 insertions(+), 19 deletions(-) diff --git a/install.sh b/install.sh index 1e3ccf6f6b..e39c904769 100755 --- a/install.sh +++ b/install.sh @@ -56,6 +56,7 @@ prime_agent_animation_frame=0 prime_agent_binary_versions_dir="${PRIME_AGENT_VERSIONS_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/prime-agent/versions}" prime_agent_binary_symlink="${PRIME_AGENT_BIN_DIR:-${XDG_BIN_HOME:-$HOME/.local/bin}}/prime-agent" prime_agent_binary_rollback_version= +prime_agent_binary_lock_dir= prime_agent_is_update=0 main() { @@ -130,6 +131,10 @@ prime_agent_cleanup() { if [ -n "${prime_agent_download_dir:-}" ] && [ -d "$prime_agent_download_dir" ]; then rm -rf "$prime_agent_download_dir" fi + if [ -n "${prime_agent_binary_lock_dir:-}" ] && [ -d "$prime_agent_binary_lock_dir" ]; then + rm -rf "$prime_agent_binary_lock_dir" + prime_agent_binary_lock_dir= + fi prime_agent_restore_terminal return "$status" } @@ -892,6 +897,29 @@ prime_agent_binary_validate_layout() { done } +prime_agent_binary_acquire_lock() { + _versions_dir="$1" + _lock_dir="$_versions_dir/.install.lock" + _timeout="${PRIME_AGENT_INSTALL_LOCK_TIMEOUT_SECONDS:-60}" + case "$_timeout" in + ''|*[!0-9]*) + printf 'error: PRIME_AGENT_INSTALL_LOCK_TIMEOUT_SECONDS must be a non-negative integer.\n' >&2 + return 1 + ;; + esac + _waited=0 + while ! mkdir "$_lock_dir" 2>/dev/null; do + if [ "$_waited" -ge "$_timeout" ]; then + printf 'error: timed out waiting for another Prime Agent install or update to finish.\n' >&2 + return 1 + fi + sleep 1 + _waited=$((_waited + 1)) + done + printf '%s\n' "$$" > "$_lock_dir/pid" + prime_agent_binary_lock_dir="$_lock_dir" +} + prime_agent_binary_atomic_symlink() { _target="$1" _link="$2" @@ -902,6 +930,10 @@ prime_agent_binary_atomic_symlink() { if [ ! -d "$_link_dir" ]; then mkdir -p "$_link_dir" fi + if [ -d "$_link" ] && [ ! -L "$_link" ]; then + printf 'error: cannot activate Prime Agent because the command path is a directory: %s\n' "$_link" >&2 + return 1 + fi # Atomic replacement with temp symlink _tmp="${_link}.tmp.$$" ln -sf "$_target" "$_tmp" @@ -925,6 +957,7 @@ prime_agent_binary_fresh_install() { _artifact_path="$_download_dir/$_artifact_name" mkdir -p "$_versions_dir" + prime_agent_binary_acquire_lock "$_versions_dir" # Version directories are immutable. Reuse a healthy existing install instead # of replacing files underneath the active command symlink. @@ -1027,6 +1060,9 @@ prime_agent_binary_fresh_install() { prime_agent_binary_update() { _update_version= _update_version="$(resolve_prime_agent_version "$@")" + _versions_dir="$prime_agent_binary_versions_dir" + mkdir -p "$_versions_dir" + prime_agent_binary_acquire_lock "$_versions_dir" # Read current version from the symlink target's package.json _current_version= @@ -1054,7 +1090,6 @@ prime_agent_binary_update() { fi _artifact_name="$(prime_agent_binary_artifact_name "$_update_version" "$_platform")" _artifact_url="$prime_agent_base_url/releases/v$_update_version/$_artifact_name" - _versions_dir="$prime_agent_binary_versions_dir" _version_dir="$(prime_agent_binary_target_version_dir "$_update_version")" _download_dir=$(create_temp_dir) @@ -1229,7 +1264,7 @@ prime_agent_configure_binary_path() { _profile=$(detect_shell_profile) if [ -n "$_profile" ] && [ -w "$_profile" ] 2>/dev/null; then - if ! grep -q "$_bin_dir" "$_profile" 2>/dev/null; then + if ! grep -F -q -- "$_bin_dir" "$_profile" 2>/dev/null; then printf '\nexport PATH="%s:$PATH"\n' "$_bin_dir" >> "$_profile" printf 'Added %s to %s.\n' "$_bin_dir" "$_profile" fi diff --git a/packages/ai/src/models.generated.ts b/packages/ai/src/models.generated.ts index 95bc323c01..68ab212bdd 100644 --- a/packages/ai/src/models.generated.ts +++ b/packages/ai/src/models.generated.ts @@ -11179,9 +11179,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 0.07168000000000001, - output: 0.14336000000000002, - cacheRead: 0.014336, + input: 0.07014000000000001, + output: 0.14028000000000002, + cacheRead: 0.014028, cacheWrite: 0, }, contextWindow: 1048576, diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index 0dc6d18f4f..c0485a24e9 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -72,27 +72,29 @@ function makeRelease( writeFileSync(join(releaseDir, "SHA256SUMS"), `${checksum} ${archiveName}\n`); } +function installerEnv(root: string, overrides: Record = {}): NodeJS.ProcessEnv { + const home = join(root, "home"); + mkdirSync(join(home, ".prime"), { recursive: true }); + writeFileSync(join(home, ".prime", "sentinel"), "user data"); + return { + ...process.env, + HOME: home, + PRIME_AGENT_DOWNLOAD_BASE_URL: `file://${join(root, "server")}`, + PRIME_AGENT_VERSIONS_DIR: join(root, "apps", "versions"), + PRIME_AGENT_BIN_DIR: join(root, "bin"), + TERM: "dumb", + ...overrides, + }; +} + function runInstaller( root: string, args: string[], env: Record = {}, ): { exitCode: number; stdout: string; stderr: string } { - const home = join(root, "home"); - const versions = join(root, "apps", "versions"); - const bin = join(root, "bin"); - mkdirSync(join(home, ".prime"), { recursive: true }); - writeFileSync(join(home, ".prime", "sentinel"), "user data"); const result = spawnSync("sh", [installer, ...args], { cwd: root, - env: { - ...process.env, - HOME: home, - PRIME_AGENT_DOWNLOAD_BASE_URL: `file://${join(root, "server")}`, - PRIME_AGENT_VERSIONS_DIR: versions, - PRIME_AGENT_BIN_DIR: bin, - TERM: "dumb", - ...env, - }, + env: installerEnv(root, env), encoding: "utf8", }); return { @@ -149,6 +151,19 @@ describe("compiled binary installer", () => { expect(() => readlinkSync(join(root, "bin", "prime-agent"))).toThrow(); }); + test("rejects a pre-existing directory at the command path", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + const commandPath = join(root, "bin", "prime-agent"); + mkdirSync(commandPath, { recursive: true }); + + const result = runInstaller(root, ["1.2.3"]); + expect(result.exitCode).not.toBe(0); + expect(result.stderr).toContain("command path is a directory"); + expect(readFileSync(join(root, "home", ".prime", "sentinel"), "utf8")).toBe("user data"); + }); + test("repairs a broken active command when updating to the same version", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); temporaryRoots.push(root); @@ -182,6 +197,30 @@ describe("compiled binary installer", () => { expect(readFileSync(join(root, "home", ".prime", "sentinel"), "utf8")).toBe("user data"); }); + test("serializes concurrent updates without deleting an activated version", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + expect(runInstaller(root, ["1.2.3"]).exitCode).toBe(0); + makeRelease(root, "2.0.0", goodExecutable("2.0.0").replace("then echo", "then sleep 1; echo")); + + const result = spawnSync( + "sh", + [ + "-c", + 'sh "$1" --update 2.0.0 & first=$!; sh "$1" --update 2.0.0 & second=$!; wait "$first"; a=$?; wait "$second"; b=$?; [ "$a" -eq 0 ] && [ "$b" -eq 0 ]', + "--", + installer, + ], + { cwd: root, env: installerEnv(root), encoding: "utf8", timeout: 20_000 }, + ); + expect(result.status, result.stderr).toBe(0); + const link = join(root, "bin", "prime-agent"); + expect(readlinkSync(link)).toContain("v2.0.0/prime-agent"); + expect(spawnSync(link, ["--version"], { encoding: "utf8" }).status).toBe(0); + expect(() => readFileSync(join(root, "apps", "versions", ".install.lock", "pid"))).toThrow(); + }); + test("keeps the previous version when an update is missing a required sidecar", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); temporaryRoots.push(root); diff --git a/packages/coding-agent/test/bun-installer.test.ts b/packages/coding-agent/test/bun-installer.test.ts index 93f3d2f950..e122d4779d 100644 --- a/packages/coding-agent/test/bun-installer.test.ts +++ b/packages/coding-agent/test/bun-installer.test.ts @@ -52,6 +52,8 @@ describe("install.sh shell syntax", () => { expect(installerText).not.toContain("prime_agent_original_path"); expect(installerText).not.toContain("prime_agent_bootstrap_kernel_on_install"); expect(installerText).not.toContain("prime_agent_screen_question"); + expect(installerText).toContain("prime_agent_binary_acquire_lock"); + expect(installerText).toContain('grep -F -q -- "$_bin_dir"'); }); it("rejects removed package-manager method flags", () => { From 1ced0af6dc6f0a02a6a2bec2bb7a5d7f04430552 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 19:19:10 -0400 Subject: [PATCH 22/31] fix: avoid same-version self-rollback --- install.sh | 27 ++++++++++++------- packages/ai/src/models.generated.ts | 10 +++---- .../test/bun-installer-e2e.test.ts | 20 ++++++++++++++ 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/install.sh b/install.sh index e39c904769..8fa5107074 100755 --- a/install.sh +++ b/install.sh @@ -1039,7 +1039,12 @@ prime_agent_binary_fresh_install() { mkdir -p "$(dirname "$prime_agent_binary_symlink")" prime_agent_binary_atomic_symlink "$_binary_path" "$prime_agent_binary_symlink" if ! prime_agent_binary_smoke_binary "$prime_agent_binary_symlink"; then - if [ -n "$_old_target" ] && prime_agent_binary_smoke_binary "$_old_target"; then + _old_target_dir= + if [ -n "$_old_target" ]; then + _old_target_dir=$(dirname "$_old_target") + fi + if [ -n "$_old_target" ] && [ "$_old_target_dir" != "$_version_dir" ] && + prime_agent_binary_smoke_binary "$_old_target"; then prime_agent_binary_atomic_symlink "$_old_target" "$prime_agent_binary_symlink" else rm -f "$prime_agent_binary_symlink" @@ -1091,6 +1096,14 @@ prime_agent_binary_update() { _artifact_name="$(prime_agent_binary_artifact_name "$_update_version" "$_platform")" _artifact_url="$prime_agent_base_url/releases/v$_update_version/$_artifact_name" _version_dir="$(prime_agent_binary_target_version_dir "$_update_version")" + prime_agent_binary_rollback_version= + if [ -L "$prime_agent_binary_symlink" ]; then + _old_target=$(readlink "$prime_agent_binary_symlink" 2>/dev/null || printf '') + _old_version_dir=$(dirname "$_old_target" 2>/dev/null || printf '') + if [ "$_old_version_dir" != "$_version_dir" ]; then + prime_agent_binary_rollback_version="$_old_version_dir" + fi + fi _download_dir=$(create_temp_dir) prime_agent_download_dir="$_download_dir" @@ -1162,24 +1175,17 @@ prime_agent_binary_update() { exit 1 fi - # Remember old version for rollback - if [ -L "$prime_agent_binary_symlink" ]; then - _old_target=$(readlink "$prime_agent_binary_symlink" 2>/dev/null || printf '') - _old_version_dir=$(dirname "$_old_target" 2>/dev/null || printf '') - prime_agent_binary_rollback_version="$_old_version_dir" - fi - # Atomically switch the symlink, then verify the activated path. If activation # fails, restore the previous immutable version before returning an error. prime_agent_binary_atomic_symlink "$_binary_path" "$prime_agent_binary_symlink" if ! prime_agent_binary_smoke_binary "$prime_agent_binary_symlink"; then if prime_agent_binary_rollback; then - rm -rf "$_version_dir" printf 'error: activation failed; restored the previous Prime Agent version.\n' >&2 else + rm -f "$prime_agent_binary_symlink" printf 'error: activation failed and no healthy rollback version was available.\n' >&2 fi - rm -rf "$_download_dir" + rm -rf "$_version_dir" "$_download_dir" prime_agent_download_dir= exit 1 fi @@ -1210,6 +1216,7 @@ prime_agent_binary_rollback() { return 1 fi prime_agent_binary_atomic_symlink "$_rollback_binary" "$prime_agent_binary_symlink" + prime_agent_binary_smoke_binary "$prime_agent_binary_symlink" } prime_agent_verify_binary_checksum() { diff --git a/packages/ai/src/models.generated.ts b/packages/ai/src/models.generated.ts index 68ab212bdd..2ab1ba6ec9 100644 --- a/packages/ai/src/models.generated.ts +++ b/packages/ai/src/models.generated.ts @@ -11236,9 +11236,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 1.0274699999999999, - output: 2.0549399999999998, - cacheRead: 0.0856225, + input: 1.0241639999999999, + output: 2.0483279999999997, + cacheRead: 0.085347, cacheWrite: 0, }, contextWindow: 1048576, @@ -14665,11 +14665,11 @@ export const MODELS = { cost: { input: 2, output: 6, - cacheRead: 0.25, + cacheRead: 0.19999999999999998, cacheWrite: 0, }, contextWindow: 1048576, - maxTokens: 262144, + maxTokens: 131072, } satisfies Model<"openai-completions">, "qwen/qwen3.8-27b": { id: "qwen/qwen3.8-27b", diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index c0485a24e9..bfb1021fe2 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -182,6 +182,26 @@ describe("compiled binary installer", () => { expect(smoke.stdout).toContain("1.2.3"); }); + test("does not use the repaired version as its own rollback target", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + expect(runInstaller(root, ["1.2.3"]).exitCode).toBe(0); + const link = join(root, "bin", "prime-agent"); + const target = readlinkSync(link); + const publicPathFailure = + '#!/bin/sh\ncase "$0" in */bin/prime-agent) exit 1 ;; esac\nif [ "$1" = "--version" ]; then exit 0; fi\nexit 0\n'; + writeFileSync(target, publicPathFailure); + chmodSync(target, 0o755); + makeRelease(root, "1.2.3", publicPathFailure); + + const result = runInstaller(root, ["--update", "1.2.3"]); + expect(result.exitCode).not.toBe(0); + expect(result.stderr).toContain("no healthy rollback version was available"); + expect(() => readlinkSync(link)).toThrow(); + expect(() => readFileSync(join(root, "apps", "versions", "v1.2.3", "package.json"))).toThrow(); + }); + test("keeps the previous symlink when an update fails its smoke test", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); temporaryRoots.push(root); From 4f366f948b2a21e42bab96a871bd6e80d51356a9 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 19:26:47 -0400 Subject: [PATCH 23/31] fix: persist binary install paths --- install.sh | 62 ++++++++++++++++++- .../test/bun-installer-e2e.test.ts | 48 ++++++++++++++ .../coding-agent/test/bun-installer.test.ts | 16 ++++- 3 files changed, 123 insertions(+), 3 deletions(-) diff --git a/install.sh b/install.sh index 8fa5107074..79225148cc 100755 --- a/install.sh +++ b/install.sh @@ -14,6 +14,23 @@ if [ "$prime_agent_default_release_channel" = "$prime_agent_unconfigured_default fi prime_agent_release_channel="${PRIME_AGENT_RELEASE_CHANNEL:-$prime_agent_default_release_channel}" prime_agent_cmd="${PRIME_AGENT_CMD:-prime-agent}" +prime_agent_persisted_versions_dir= +prime_agent_persisted_symlink= +prime_agent_script_dir=$(CDPATH= cd -P "$(dirname "$0")" 2>/dev/null && pwd) +if [ -f "$prime_agent_script_dir/.install-paths" ]; then + prime_agent_persisted_versions_dir=$(sed -n '1p' "$prime_agent_script_dir/.install-paths") + prime_agent_persisted_symlink=$(sed -n '2p' "$prime_agent_script_dir/.install-paths") +fi +prime_agent_default_data_home="${XDG_DATA_HOME:-${HOME:+$HOME/.local/share}}" +prime_agent_default_bin_home="${XDG_BIN_HOME:-${HOME:+$HOME/.local/bin}}" +prime_agent_binary_versions_dir="${PRIME_AGENT_VERSIONS_DIR:-${prime_agent_persisted_versions_dir:-${prime_agent_default_data_home:+$prime_agent_default_data_home/prime-agent/versions}}}" +if [ -n "${PRIME_AGENT_BIN_DIR:-}" ]; then + prime_agent_binary_symlink="${PRIME_AGENT_BIN_DIR%/}/prime-agent" +elif [ -n "$prime_agent_persisted_symlink" ]; then + prime_agent_binary_symlink="$prime_agent_persisted_symlink" +else + prime_agent_binary_symlink="${prime_agent_default_bin_home:+$prime_agent_default_bin_home/prime-agent}" +fi prime_agent_esc=$(printf '\033') prime_agent_reset="${prime_agent_esc}[0m" prime_agent_bold="${prime_agent_esc}[1m" @@ -53,8 +70,6 @@ prime_agent_screen_title= prime_agent_screen_status= prime_agent_screen_detail= prime_agent_animation_frame=0 -prime_agent_binary_versions_dir="${PRIME_AGENT_VERSIONS_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/prime-agent/versions}" -prime_agent_binary_symlink="${PRIME_AGENT_BIN_DIR:-${XDG_BIN_HOME:-$HOME/.local/bin}}/prime-agent" prime_agent_binary_rollback_version= prime_agent_binary_lock_dir= prime_agent_is_update=0 @@ -65,6 +80,10 @@ main() { printf 'Set PRIME_AGENT_DOWNLOAD_BASE_URL or use the installer published by the release workflow.\n' >&2 exit 1 fi + if [ -z "$prime_agent_binary_versions_dir" ] || [ -z "$prime_agent_binary_symlink" ]; then + printf 'error: HOME is not set; set HOME or explicit PRIME_AGENT_VERSIONS_DIR and PRIME_AGENT_BIN_DIR paths.\n' >&2 + exit 1 + fi prime_agent_is_update=0 _prime_agent_positional= @@ -909,6 +928,34 @@ prime_agent_binary_acquire_lock() { esac _waited=0 while ! mkdir "$_lock_dir" 2>/dev/null; do + _lock_pid= + if [ -f "$_lock_dir/pid" ]; then + _lock_pid=$(sed -n '1p' "$_lock_dir/pid" 2>/dev/null || printf '') + fi + case "$_lock_pid" in + '') + # The owner writes its PID immediately after mkdir. Give that tiny + # publication window one retry before treating the lock as abandoned. + if [ "$_waited" -eq 0 ]; then + sleep 1 + _waited=$((_waited + 1)) + continue + fi + _lock_is_stale=1 + ;; + *[!0-9]*) _lock_is_stale=1 ;; + *) + if kill -0 "$_lock_pid" 2>/dev/null; then + _lock_is_stale=0 + else + _lock_is_stale=1 + fi + ;; + esac + if [ "$_lock_is_stale" = 1 ]; then + rm -rf "$_lock_dir" + continue + fi if [ "$_waited" -ge "$_timeout" ]; then printf 'error: timed out waiting for another Prime Agent install or update to finish.\n' >&2 return 1 @@ -920,6 +967,14 @@ prime_agent_binary_acquire_lock() { prime_agent_binary_lock_dir="$_lock_dir" } +prime_agent_binary_write_install_paths() { + _version_dir="$1" + _state_path="$_version_dir/.install-paths" + _state_tmp="${_state_path}.tmp.$$" + printf '%s\n%s\n' "$prime_agent_binary_versions_dir" "$prime_agent_binary_symlink" > "$_state_tmp" + mv -f "$_state_tmp" "$_state_path" +} + prime_agent_binary_atomic_symlink() { _target="$1" _link="$2" @@ -966,6 +1021,7 @@ prime_agent_binary_fresh_install() { _existing_binary="$_version_dir/pi" fi if [ -x "$_existing_binary" ] && prime_agent_binary_validate_layout "$_version_dir" "$_existing_binary"; then + prime_agent_binary_write_install_paths "$_version_dir" prime_agent_binary_atomic_symlink "$_existing_binary" "$prime_agent_binary_symlink" prime_agent_configure_binary_path "$_version" return @@ -1029,6 +1085,7 @@ prime_agent_binary_fresh_install() { prime_agent_download_dir= exit 1 fi + prime_agent_binary_write_install_paths "$_version_dir" # Create and verify the stable symlink. Restore a healthy prior target if the # activated command cannot run through its public path. @@ -1174,6 +1231,7 @@ prime_agent_binary_update() { prime_agent_download_dir= exit 1 fi + prime_agent_binary_write_install_paths "$_version_dir" # Atomically switch the symlink, then verify the activated path. If activation # fails, restore the previous immutable version before returning an error. diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index bfb1021fe2..39827f073c 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -126,6 +126,36 @@ describe("compiled binary installer", () => { expect(readlinkSync(join(root, "bin", "prime-agent"))).toBe(target); }); + test("self-updates the persisted custom install paths without exported overrides", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + expect(runInstaller(root, ["1.2.3"]).exitCode).toBe(0); + const v1Sidecar = join(root, "apps", "versions", "v1.2.3", "install.sh"); + writeFileSync(v1Sidecar, readFileSync(installer)); + chmodSync(v1Sidecar, 0o755); + makeRelease(root, "2.0.0", goodExecutable("2.0.0")); + const isolatedHome = join(root, "isolated-home"); + mkdirSync(isolatedHome); + const result = spawnSync("sh", [v1Sidecar, "--update", "2.0.0"], { + cwd: root, + env: { + ...process.env, + HOME: isolatedHome, + PRIME_AGENT_DOWNLOAD_BASE_URL: `file://${join(root, "server")}`, + PRIME_AGENT_VERSIONS_DIR: undefined, + PRIME_AGENT_BIN_DIR: undefined, + XDG_DATA_HOME: undefined, + XDG_BIN_HOME: undefined, + TERM: "dumb", + }, + encoding: "utf8", + }); + expect(result.status, result.stderr).toBe(0); + expect(readlinkSync(join(root, "bin", "prime-agent"))).toContain("v2.0.0/prime-agent"); + expect(() => readlinkSync(join(isolatedHome, ".local", "bin", "prime-agent"))).toThrow(); + }); + test("rejects a fresh install that fails through the activated command symlink", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); temporaryRoots.push(root); @@ -241,6 +271,24 @@ describe("compiled binary installer", () => { expect(() => readFileSync(join(root, "apps", "versions", ".install.lock", "pid"))).toThrow(); }); + test("recovers an install lock whose recorded process is gone", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + expect(runInstaller(root, ["1.2.3"]).exitCode).toBe(0); + makeRelease(root, "2.0.0", goodExecutable("2.0.0")); + const lockDir = join(root, "apps", "versions", ".install.lock"); + mkdirSync(lockDir); + writeFileSync(join(lockDir, "pid"), "99999999\n"); + + const result = runInstaller(root, ["--update", "2.0.0"], { + PRIME_AGENT_INSTALL_LOCK_TIMEOUT_SECONDS: "1", + }); + expect(result.exitCode, result.stderr).toBe(0); + expect(readlinkSync(join(root, "bin", "prime-agent"))).toContain("v2.0.0/prime-agent"); + expect(() => readFileSync(join(lockDir, "pid"))).toThrow(); + }); + test("keeps the previous version when an update is missing a required sidecar", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); temporaryRoots.push(root); diff --git a/packages/coding-agent/test/bun-installer.test.ts b/packages/coding-agent/test/bun-installer.test.ts index e122d4779d..cdacafd098 100644 --- a/packages/coding-agent/test/bun-installer.test.ts +++ b/packages/coding-agent/test/bun-installer.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, it } from "bun:test"; -import { execFileSync } from "node:child_process"; +import { execFileSync, spawnSync } from "node:child_process"; import { mkdtempSync, readFileSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; @@ -59,6 +59,20 @@ describe("install.sh shell syntax", () => { it("rejects removed package-manager method flags", () => { expect(installerText).toContain("--method is no longer supported"); }); + + it("reports an actionable error when HOME and explicit install paths are absent", () => { + const result = spawnSync("sh", [installer, "1.2.3"], { + encoding: "utf8", + env: { + PATH: process.env.PATH, + PRIME_AGENT_DOWNLOAD_BASE_URL: "https://downloads.example.test", + TERM: "dumb", + }, + }); + expect(result.status).not.toBe(0); + expect(result.stderr).toContain("HOME is not set"); + expect(result.stderr).not.toContain("parameter not set"); + }); }); // ============================================================================ From faf728096f0a35d65cea5725005308d8bb27bdcb Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 19:37:51 -0400 Subject: [PATCH 24/31] fix: canonicalize binary install roots --- install.sh | 20 ++++++++++++--- .../test/bun-installer-e2e.test.ts | 25 +++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/install.sh b/install.sh index 79225148cc..8bcf40a958 100755 --- a/install.sh +++ b/install.sh @@ -916,6 +916,16 @@ prime_agent_binary_validate_layout() { done } +prime_agent_binary_canonicalize_install_paths() { + mkdir -p "$prime_agent_binary_versions_dir" + prime_agent_binary_versions_dir=$(CDPATH= cd -P "$prime_agent_binary_versions_dir" && pwd) + _link_dir=$(dirname "$prime_agent_binary_symlink") + _link_name=$(basename "$prime_agent_binary_symlink") + mkdir -p "$_link_dir" + _link_dir=$(CDPATH= cd -P "$_link_dir" && pwd) + prime_agent_binary_symlink="$_link_dir/$_link_name" +} + prime_agent_binary_acquire_lock() { _versions_dir="$1" _lock_dir="$_versions_dir/.install.lock" @@ -1004,6 +1014,7 @@ prime_agent_binary_fresh_install() { fi _artifact_name="$(prime_agent_binary_artifact_name "$_version" "$_platform")" _artifact_url="$prime_agent_base_url/releases/v$_version/$_artifact_name" + prime_agent_binary_canonicalize_install_paths _versions_dir="$prime_agent_binary_versions_dir" _version_dir="$(prime_agent_binary_target_version_dir "$_version")" @@ -1011,7 +1022,6 @@ prime_agent_binary_fresh_install() { prime_agent_download_dir="$_download_dir" _artifact_path="$_download_dir/$_artifact_name" - mkdir -p "$_versions_dir" prime_agent_binary_acquire_lock "$_versions_dir" # Version directories are immutable. Reuse a healthy existing install instead @@ -1023,8 +1033,10 @@ prime_agent_binary_fresh_install() { if [ -x "$_existing_binary" ] && prime_agent_binary_validate_layout "$_version_dir" "$_existing_binary"; then prime_agent_binary_write_install_paths "$_version_dir" prime_agent_binary_atomic_symlink "$_existing_binary" "$prime_agent_binary_symlink" - prime_agent_configure_binary_path "$_version" - return + if prime_agent_binary_smoke_binary "$prime_agent_binary_symlink"; then + prime_agent_configure_binary_path "$_version" + return + fi fi prime_agent_run_quiet_with_animation "Downloading Prime Agent v$_version" "Downloading Prime Agent v$_version" "Fetching the compiled binary for $_platform." curl -fsSL "$_artifact_url" -o "$_artifact_path" @@ -1122,8 +1134,8 @@ prime_agent_binary_fresh_install() { prime_agent_binary_update() { _update_version= _update_version="$(resolve_prime_agent_version "$@")" + prime_agent_binary_canonicalize_install_paths _versions_dir="$prime_agent_binary_versions_dir" - mkdir -p "$_versions_dir" prime_agent_binary_acquire_lock "$_versions_dir" # Read current version from the symlink target's package.json diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index 39827f073c..52d1c7442d 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -9,6 +9,7 @@ import { readlinkSync, realpathSync, rmSync, + symlinkSync, writeFileSync, } from "node:fs"; import { tmpdir } from "node:os"; @@ -232,6 +233,30 @@ describe("compiled binary installer", () => { expect(() => readFileSync(join(root, "apps", "versions", "v1.2.3", "package.json"))).toThrow(); }); + test("does not self-rollback through an aliased versions directory", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + const physicalVersions = join(root, "physical-versions"); + const aliasedVersions = join(root, "aliased-versions"); + mkdirSync(physicalVersions); + symlinkSync(physicalVersions, aliasedVersions, "dir"); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + const pathEnv = { PRIME_AGENT_VERSIONS_DIR: aliasedVersions }; + expect(runInstaller(root, ["1.2.3"], pathEnv).exitCode).toBe(0); + const link = join(root, "bin", "prime-agent"); + const target = readlinkSync(link); + writeFileSync(target, "#!/bin/sh\nexit 1\n"); + chmodSync(target, 0o755); + const publicPathFailure = + '#!/bin/sh\ncase "$0" in */bin/prime-agent) exit 1 ;; esac\nif [ "$1" = "--version" ]; then exit 0; fi\nexit 0\n'; + makeRelease(root, "1.2.3", publicPathFailure); + + const result = runInstaller(root, ["1.2.3"], pathEnv); + expect(result.exitCode).not.toBe(0); + expect(() => readlinkSync(link)).toThrow(); + expect(() => readFileSync(join(physicalVersions, "v1.2.3", "package.json"))).toThrow(); + }); + test("keeps the previous symlink when an update fails its smoke test", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); temporaryRoots.push(root); From 69ccb0e47831d87fa7c64875f423b5eaf94790d9 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 19:57:38 -0400 Subject: [PATCH 25/31] fix: harden installer lock ownership --- install.sh | 187 ++++++++++++++---- .../test/bun-installer-e2e.test.ts | 59 +++++- 2 files changed, 198 insertions(+), 48 deletions(-) diff --git a/install.sh b/install.sh index 8bcf40a958..d6b78e5cea 100755 --- a/install.sh +++ b/install.sh @@ -16,20 +16,53 @@ prime_agent_release_channel="${PRIME_AGENT_RELEASE_CHANNEL:-$prime_agent_default prime_agent_cmd="${PRIME_AGENT_CMD:-prime-agent}" prime_agent_persisted_versions_dir= prime_agent_persisted_symlink= -prime_agent_script_dir=$(CDPATH= cd -P "$(dirname "$0")" 2>/dev/null && pwd) -if [ -f "$prime_agent_script_dir/.install-paths" ]; then - prime_agent_persisted_versions_dir=$(sed -n '1p' "$prime_agent_script_dir/.install-paths") - prime_agent_persisted_symlink=$(sed -n '2p' "$prime_agent_script_dir/.install-paths") +prime_agent_persisted_paths_invalid=0 +prime_agent_script_dir= +case "$0" in + */*) + prime_agent_script_dir=$(CDPATH= cd -P "$(dirname "$0")" 2>/dev/null && pwd) + ;; +esac +if [ -n "$prime_agent_script_dir" ] && [ -f "$prime_agent_script_dir/.install-paths" ]; then + _persisted_versions=$(sed -n '1p' "$prime_agent_script_dir/.install-paths") + _persisted_symlink=$(sed -n '2p' "$prime_agent_script_dir/.install-paths") + _persisted_cmd=$(sed -n '3p' "$prime_agent_script_dir/.install-paths") + if [ -z "$_persisted_cmd" ]; then + _persisted_cmd=$(basename "$_persisted_symlink") + fi + _persisted_versions_physical= + _persisted_target_dir= + if [ -d "$_persisted_versions" ]; then + _persisted_versions_physical=$(CDPATH= cd -P "$_persisted_versions" 2>/dev/null && pwd) + fi + if [ -L "$_persisted_symlink" ]; then + _persisted_target=$(readlink "$_persisted_symlink" 2>/dev/null || printf '') + if [ -n "$_persisted_target" ] && [ -d "$(dirname "$_persisted_target")" ]; then + _persisted_target_dir=$(CDPATH= cd -P "$(dirname "$_persisted_target")" 2>/dev/null && pwd) + fi + fi + if [ -n "$_persisted_versions_physical" ] && + [ "$_persisted_versions_physical" = "$(dirname "$prime_agent_script_dir")" ] && + [ "$_persisted_target_dir" = "$prime_agent_script_dir" ] && + [ "$(basename "$_persisted_symlink")" = "$_persisted_cmd" ]; then + prime_agent_persisted_versions_dir="$_persisted_versions_physical" + prime_agent_persisted_symlink="$_persisted_symlink" + if [ -z "${PRIME_AGENT_CMD:-}" ]; then + prime_agent_cmd="$_persisted_cmd" + fi + else + prime_agent_persisted_paths_invalid=1 + fi fi prime_agent_default_data_home="${XDG_DATA_HOME:-${HOME:+$HOME/.local/share}}" prime_agent_default_bin_home="${XDG_BIN_HOME:-${HOME:+$HOME/.local/bin}}" prime_agent_binary_versions_dir="${PRIME_AGENT_VERSIONS_DIR:-${prime_agent_persisted_versions_dir:-${prime_agent_default_data_home:+$prime_agent_default_data_home/prime-agent/versions}}}" if [ -n "${PRIME_AGENT_BIN_DIR:-}" ]; then - prime_agent_binary_symlink="${PRIME_AGENT_BIN_DIR%/}/prime-agent" + prime_agent_binary_symlink="${PRIME_AGENT_BIN_DIR%/}/$prime_agent_cmd" elif [ -n "$prime_agent_persisted_symlink" ]; then prime_agent_binary_symlink="$prime_agent_persisted_symlink" else - prime_agent_binary_symlink="${prime_agent_default_bin_home:+$prime_agent_default_bin_home/prime-agent}" + prime_agent_binary_symlink="${prime_agent_default_bin_home:+$prime_agent_default_bin_home/$prime_agent_cmd}" fi prime_agent_esc=$(printf '\033') prime_agent_reset="${prime_agent_esc}[0m" @@ -72,6 +105,7 @@ prime_agent_screen_detail= prime_agent_animation_frame=0 prime_agent_binary_rollback_version= prime_agent_binary_lock_dir= +prime_agent_binary_lock_root= prime_agent_is_update=0 main() { @@ -80,6 +114,10 @@ main() { printf 'Set PRIME_AGENT_DOWNLOAD_BASE_URL or use the installer published by the release workflow.\n' >&2 exit 1 fi + if [ "$prime_agent_persisted_paths_invalid" = 1 ]; then + printf 'error: installed Prime Agent path metadata does not match this sidecar or active command.\n' >&2 + exit 1 + fi if [ -z "$prime_agent_binary_versions_dir" ] || [ -z "$prime_agent_binary_symlink" ]; then printf 'error: HOME is not set; set HOME or explicit PRIME_AGENT_VERSIONS_DIR and PRIME_AGENT_BIN_DIR paths.\n' >&2 exit 1 @@ -154,6 +192,10 @@ prime_agent_cleanup() { rm -rf "$prime_agent_binary_lock_dir" prime_agent_binary_lock_dir= fi + if [ -n "${prime_agent_binary_lock_root:-}" ] && [ -d "$prime_agent_binary_lock_root" ]; then + rmdir "$prime_agent_binary_lock_root" 2>/dev/null || true + prime_agent_binary_lock_root= + fi prime_agent_restore_terminal return "$status" } @@ -928,7 +970,7 @@ prime_agent_binary_canonicalize_install_paths() { prime_agent_binary_acquire_lock() { _versions_dir="$1" - _lock_dir="$_versions_dir/.install.lock" + _lock_root="$_versions_dir/.install-locks" _timeout="${PRIME_AGENT_INSTALL_LOCK_TIMEOUT_SECONDS:-60}" case "$_timeout" in ''|*[!0-9]*) @@ -936,36 +978,76 @@ prime_agent_binary_acquire_lock() { return 1 ;; esac - _waited=0 - while ! mkdir "$_lock_dir" 2>/dev/null; do - _lock_pid= - if [ -f "$_lock_dir/pid" ]; then - _lock_pid=$(sed -n '1p' "$_lock_dir/pid" 2>/dev/null || printf '') - fi - case "$_lock_pid" in - '') - # The owner writes its PID immediately after mkdir. Give that tiny - # publication window one retry before treating the lock as abandoned. - if [ "$_waited" -eq 0 ]; then - sleep 1 - _waited=$((_waited + 1)) - continue - fi - _lock_is_stale=1 - ;; - *[!0-9]*) _lock_is_stale=1 ;; - *) - if kill -0 "$_lock_pid" 2>/dev/null; then - _lock_is_stale=0 - else - _lock_is_stale=1 - fi - ;; - esac - if [ "$_lock_is_stale" = 1 ]; then - rm -rf "$_lock_dir" + mkdir -p "$_lock_root" + prime_agent_binary_lock_root="$_lock_root" + rm -rf "$_lock_root/choosing-$$" + for _entry in "$_lock_root"/*-"$$"; do + [ -d "$_entry" ] || continue + rm -rf "$_entry" + done + _choosing_dir="$_lock_root/choosing-$$" + mkdir "$_choosing_dir" + prime_agent_binary_lock_dir="$_choosing_dir" + + _max_ticket=0 + for _entry in "$_lock_root"/*-*; do + [ -d "$_entry" ] || continue + _entry_name=$(basename "$_entry") + case "$_entry_name" in choosing-*) continue ;; esac + _entry_ticket=${_entry_name%%-*} + _entry_pid=${_entry_name#*-} + case "$_entry_ticket:$_entry_pid" in *[!0-9:]*|:*) continue ;; esac + if ! kill -0 "$_entry_pid" 2>/dev/null; then + rm -rf "$_entry" continue fi + if [ "$_entry_ticket" -gt "$_max_ticket" ]; then + _max_ticket="$_entry_ticket" + fi + done + _my_ticket=$((_max_ticket + 1)) + while :; do + _my_contender="$_lock_root/$_my_ticket-$$" + if mkdir "$_my_contender" 2>/dev/null; then + break + fi + _my_ticket=$((_my_ticket + 1)) + done + rm -rf "$_choosing_dir" + prime_agent_binary_lock_dir="$_my_contender" + + _waited=0 + while :; do + _blocked=0 + for _entry in "$_lock_root"/choosing-*; do + [ -d "$_entry" ] || continue + _entry_pid=${_entry##*-} + case "$_entry_pid" in ''|*[!0-9]*) rm -rf "$_entry"; continue ;; esac + if kill -0 "$_entry_pid" 2>/dev/null; then + _blocked=1 + else + rm -rf "$_entry" + fi + done + for _entry in "$_lock_root"/*-*; do + [ -d "$_entry" ] || continue + _entry_name=$(basename "$_entry") + case "$_entry_name" in choosing-*|"$_my_ticket-$$") continue ;; esac + _entry_ticket=${_entry_name%%-*} + _entry_pid=${_entry_name#*-} + case "$_entry_ticket:$_entry_pid" in *[!0-9:]*|:*) continue ;; esac + if ! kill -0 "$_entry_pid" 2>/dev/null; then + rm -rf "$_entry" + continue + fi + if [ "$_entry_ticket" -lt "$_my_ticket" ] || + { [ "$_entry_ticket" -eq "$_my_ticket" ] && [ "$_entry_pid" -lt "$$" ]; }; then + _blocked=1 + fi + done + if [ "$_blocked" = 0 ]; then + return 0 + fi if [ "$_waited" -ge "$_timeout" ]; then printf 'error: timed out waiting for another Prime Agent install or update to finish.\n' >&2 return 1 @@ -973,15 +1055,13 @@ prime_agent_binary_acquire_lock() { sleep 1 _waited=$((_waited + 1)) done - printf '%s\n' "$$" > "$_lock_dir/pid" - prime_agent_binary_lock_dir="$_lock_dir" } prime_agent_binary_write_install_paths() { _version_dir="$1" _state_path="$_version_dir/.install-paths" _state_tmp="${_state_path}.tmp.$$" - printf '%s\n%s\n' "$prime_agent_binary_versions_dir" "$prime_agent_binary_symlink" > "$_state_tmp" + printf '%s\n%s\n%s\n' "$prime_agent_binary_versions_dir" "$prime_agent_binary_symlink" "$prime_agent_cmd" > "$_state_tmp" mv -f "$_state_tmp" "$_state_path" } @@ -1030,6 +1110,9 @@ prime_agent_binary_fresh_install() { if [ ! -x "$_existing_binary" ] && [ -x "$_version_dir/pi" ]; then _existing_binary="$_version_dir/pi" fi + if [ ! -x "$_existing_binary" ] && [ -x "$_version_dir/prime-agent" ]; then + _existing_binary="$_version_dir/prime-agent" + fi if [ -x "$_existing_binary" ] && prime_agent_binary_validate_layout "$_version_dir" "$_existing_binary"; then prime_agent_binary_write_install_paths "$_version_dir" prime_agent_binary_atomic_symlink "$_existing_binary" "$prime_agent_binary_symlink" @@ -1059,6 +1142,8 @@ prime_agent_binary_fresh_install() { _binary_path="$_version_dir/pi" elif [ -f "$_version_dir/$prime_agent_cmd" ]; then _binary_path="$_version_dir/$prime_agent_cmd" + elif [ -f "$_version_dir/prime-agent" ]; then + _binary_path="$_version_dir/prime-agent" else for _d in "$_version_dir"/*/; do _d="${_d%/}" @@ -1068,6 +1153,9 @@ prime_agent_binary_fresh_install() { elif [ -f "${_d}/$prime_agent_cmd" ]; then _binary_path="${_d}/$prime_agent_cmd" break + elif [ -f "${_d}/prime-agent" ]; then + _binary_path="${_d}/prime-agent" + break fi done fi @@ -1205,6 +1293,8 @@ prime_agent_binary_update() { _binary_path="$_version_dir/pi" elif [ -f "$_version_dir/$prime_agent_cmd" ]; then _binary_path="$_version_dir/$prime_agent_cmd" + elif [ -f "$_version_dir/prime-agent" ]; then + _binary_path="$_version_dir/prime-agent" else for _d in "$_version_dir"/*/; do _d="${_d%/}" @@ -1214,6 +1304,9 @@ prime_agent_binary_update() { elif [ -f "${_d}/$prime_agent_cmd" ]; then _binary_path="${_d}/$prime_agent_cmd" break + elif [ -f "${_d}/prime-agent" ]; then + _binary_path="${_d}/prime-agent" + break fi done fi @@ -1281,6 +1374,8 @@ prime_agent_binary_rollback() { _rollback_binary="$prime_agent_binary_rollback_version/pi" elif [ -f "$prime_agent_binary_rollback_version/$prime_agent_cmd" ]; then _rollback_binary="$prime_agent_binary_rollback_version/$prime_agent_cmd" + elif [ -f "$prime_agent_binary_rollback_version/prime-agent" ]; then + _rollback_binary="$prime_agent_binary_rollback_version/prime-agent" fi if [ -z "$_rollback_binary" ] || [ ! -x "$_rollback_binary" ]; then return 1 @@ -1311,6 +1406,12 @@ prime_agent_verify_binary_checksum() { fi } +prime_agent_shell_quote() { + printf "'" + printf '%s' "$1" | sed "s/'/'\\\\''/g" + printf "'" +} + prime_agent_configure_binary_path() { _installed_version="${1:-}" @@ -1340,16 +1441,18 @@ prime_agent_configure_binary_path() { fi _profile=$(detect_shell_profile) + _quoted_bin_dir=$(prime_agent_shell_quote "$_bin_dir") + _quoted_cmd=$(prime_agent_shell_quote "$prime_agent_cmd") if [ -n "$_profile" ] && [ -w "$_profile" ] 2>/dev/null; then if ! grep -F -q -- "$_bin_dir" "$_profile" 2>/dev/null; then - printf '\nexport PATH="%s:$PATH"\n' "$_bin_dir" >> "$_profile" + printf '\nexport PATH=%s:"$PATH"\n' "$_quoted_bin_dir" >> "$_profile" printf 'Added %s to %s.\n' "$_bin_dir" "$_profile" fi - printf '\nRestart your shell or run: export PATH="%s:$PATH" && %s\n' "$_bin_dir" "$prime_agent_cmd" + printf '\nRestart your shell or run: export PATH=%s:"$PATH" && %s\n' "$_quoted_bin_dir" "$_quoted_cmd" else printf '\nAdd to your shell profile:\n' - printf ' export PATH="%s:$PATH"\n' "$_bin_dir" - printf '\nThen restart your shell and run: %s\n' "$prime_agent_cmd" + printf ' export PATH=%s:"$PATH"\n' "$_quoted_bin_dir" + printf '\nThen restart your shell and run: %s\n' "$_quoted_cmd" fi } diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index 52d1c7442d..05888a8beb 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -127,6 +127,51 @@ describe("compiled binary installer", () => { expect(readlinkSync(join(root, "bin", "prime-agent"))).toBe(target); }); + test("links a custom command name to the canonical archive executable", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + + const result = runInstaller(root, ["1.2.3"], { PRIME_AGENT_CMD: "pa" }); + expect(result.exitCode, result.stderr).toBe(0); + const command = join(root, "bin", "pa"); + expect(readlinkSync(command)).toContain("v1.2.3/prime-agent"); + expect(spawnSync(command, ["--version"], { encoding: "utf8" }).status).toBe(0); + }); + + test("does not trust install metadata from the working directory in a piped install", () => { + const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); + temporaryRoots.push(root); + makeRelease(root, "1.2.3", goodExecutable("1.2.3")); + const attackerDir = join(root, "attacker"); + mkdirSync(attackerDir); + writeFileSync( + join(attackerDir, ".install-paths"), + `${join(root, "attacker-versions")}\n${join(root, "attacker-bin", "prime-agent")}\nprime-agent\n`, + ); + const home = join(root, "piped-home"); + mkdirSync(home); + + const result = spawnSync("sh", ["-s", "--", "1.2.3"], { + cwd: attackerDir, + input: readFileSync(installer), + env: { + ...process.env, + HOME: home, + PRIME_AGENT_DOWNLOAD_BASE_URL: `file://${join(root, "server")}`, + PRIME_AGENT_VERSIONS_DIR: undefined, + PRIME_AGENT_BIN_DIR: undefined, + XDG_DATA_HOME: undefined, + XDG_BIN_HOME: undefined, + TERM: "dumb", + }, + encoding: "utf8", + }); + expect(result.status, result.stderr).toBe(0); + expect(readlinkSync(join(home, ".local", "bin", "prime-agent"))).toContain("v1.2.3/prime-agent"); + expect(() => readlinkSync(join(root, "attacker-bin", "prime-agent"))).toThrow(); + }); + test("self-updates the persisted custom install paths without exported overrides", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); temporaryRoots.push(root); @@ -278,6 +323,8 @@ describe("compiled binary installer", () => { makeRelease(root, "1.2.3", goodExecutable("1.2.3")); expect(runInstaller(root, ["1.2.3"]).exitCode).toBe(0); makeRelease(root, "2.0.0", goodExecutable("2.0.0").replace("then echo", "then sleep 1; echo")); + const staleRoot = join(root, "apps", "versions", ".install-locks"); + mkdirSync(join(staleRoot, "1-99999991"), { recursive: true }); const result = spawnSync( "sh", @@ -293,7 +340,7 @@ describe("compiled binary installer", () => { const link = join(root, "bin", "prime-agent"); expect(readlinkSync(link)).toContain("v2.0.0/prime-agent"); expect(spawnSync(link, ["--version"], { encoding: "utf8" }).status).toBe(0); - expect(() => readFileSync(join(root, "apps", "versions", ".install.lock", "pid"))).toThrow(); + expect(() => readFileSync(join(staleRoot, "1-99999991", "pid"))).toThrow(); }); test("recovers an install lock whose recorded process is gone", () => { @@ -302,16 +349,16 @@ describe("compiled binary installer", () => { makeRelease(root, "1.2.3", goodExecutable("1.2.3")); expect(runInstaller(root, ["1.2.3"]).exitCode).toBe(0); makeRelease(root, "2.0.0", goodExecutable("2.0.0")); - const lockDir = join(root, "apps", "versions", ".install.lock"); - mkdirSync(lockDir); - writeFileSync(join(lockDir, "pid"), "99999999\n"); + const lockRoot = join(root, "apps", "versions", ".install-locks"); + const staleContender = join(lockRoot, "1-99999999"); + mkdirSync(staleContender, { recursive: true }); const result = runInstaller(root, ["--update", "2.0.0"], { PRIME_AGENT_INSTALL_LOCK_TIMEOUT_SECONDS: "1", }); expect(result.exitCode, result.stderr).toBe(0); expect(readlinkSync(join(root, "bin", "prime-agent"))).toContain("v2.0.0/prime-agent"); - expect(() => readFileSync(join(lockDir, "pid"))).toThrow(); + expect(() => readFileSync(join(staleContender, "pid"))).toThrow(); }); test("keeps the previous version when an update is missing a required sidecar", () => { @@ -373,7 +420,7 @@ describe("compiled binary installer", () => { const result = runInstaller(root, ["1.2.3"], { PATH: `${tools}:${process.env.PATH}` }); expect(result.exitCode, result.stderr).toBe(0); expect(result.stderr).toContain("currently shadows the new binary"); - expect(result.stdout).toContain('export PATH="'); + expect(result.stdout).toContain("export PATH='"); }); test("canonicalizes relative version directories before linking", () => { const root = mkdtempSync(join(tmpdir(), "prime-agent-installer-")); From 0bcc0c2e471eaa839f2468d732730d1d05c47832 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 20:01:28 -0400 Subject: [PATCH 26/31] chore(ai): refresh generated model catalog --- packages/ai/src/models.generated.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/ai/src/models.generated.ts b/packages/ai/src/models.generated.ts index 2ab1ba6ec9..5c7b432e0c 100644 --- a/packages/ai/src/models.generated.ts +++ b/packages/ai/src/models.generated.ts @@ -11179,9 +11179,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 0.07014000000000001, - output: 0.14028000000000002, - cacheRead: 0.014028, + input: 0.088606, + output: 0.177212, + cacheRead: 0.017721200000000003, cacheWrite: 0, }, contextWindow: 1048576, @@ -11236,9 +11236,9 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 1.0241639999999999, - output: 2.0483279999999997, - cacheRead: 0.085347, + input: 1.04226, + output: 2.08452, + cacheRead: 0.086855, cacheWrite: 0, }, contextWindow: 1048576, @@ -15526,13 +15526,13 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max","max":null}, input: ["text"], cost: { - input: 0.049980000000000004, - output: 0.09996000000000001, - cacheRead: 0.009996000000000001, + input: 0.049999999999999996, + output: 0.16, + cacheRead: 0.013000000000000001, cacheWrite: 0, }, contextWindow: 1310720, - maxTokens: 131072, + maxTokens: 393216, } satisfies Model<"openai-completions">, "~google/gemini-flash-latest": { id: "~google/gemini-flash-latest", From 3acc3abc0aea911cbba766bacb34cb73c9f5930e Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 20:09:17 -0400 Subject: [PATCH 27/31] ci: make model catalog builds deterministic --- .github/workflows/ci.yml | 10 ---------- package.json | 1 + packages/ai/README.md | 2 ++ packages/ai/package.json | 2 +- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a6fec4ae0..4228d9137b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,16 +59,6 @@ jobs: - name: Build run: bun run build - - name: Check model catalog drift - run: | - if ! git diff --exit-code packages/ai/src/models.generated.ts; then - echo "ERROR: Model catalog has drifted from committed state." - echo "Run 'bun run build' in packages/ai to regenerate, then commit the updated models.generated.ts." - echo "Diff:" - git diff packages/ai/src/models.generated.ts - exit 1 - fi - - name: Check run: bun run check diff --git a/package.json b/package.json index 5009177fa1..1835df249a 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "build": "bun run --cwd packages/tui build && bun run --cwd packages/ai build && bun run --cwd packages/agent build && bun run --cwd packages/coding-agent build", "dev": "bun scripts/dev.ts", "dev:tsc": "bun run --cwd packages/ai dev:tsc", + "models:refresh": "bun run --cwd packages/ai generate-models", "check": "bun --bun biome check --write --error-on-warnings . && bun run check:type && bun run check:installer && bun run check:browser-smoke", "check:installer": "bun scripts/check-installer-render.mjs", "check:browser-smoke": "bun scripts/check-browser-smoke.mjs", diff --git a/packages/ai/README.md b/packages/ai/README.md index b93a6122f2..25f5197a19 100644 --- a/packages/ai/README.md +++ b/packages/ai/README.md @@ -1272,6 +1272,8 @@ Create a new provider file (for example `amazon-bedrock.ts`) that exports: #### 4. Model Generation (`scripts/generate-models.ts`) +Normal builds compile the committed `src/models.generated.ts` snapshot and do not contact live provider APIs. Refresh the snapshot intentionally from the repository root with `bun run models:refresh`, then review and commit the generated diff. Live catalog changes must not make unrelated pull-request builds nondeterministic. + - Add logic to fetch and parse models from the provider's source (e.g., models.dev API) - Map provider model data to the standardized `Model` interface - Handle provider-specific quirks (pricing format, capability flags, model ID transformations) diff --git a/packages/ai/package.json b/packages/ai/package.json index 73ada05d79..08a5493038 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -65,7 +65,7 @@ "scripts": { "clean": "bun ../../scripts/remove-paths.ts dist", "generate-models": "bun scripts/generate-models.ts", - "build": "bun run generate-models && bun --bun tsgo -p tsconfig.build.json", + "build": "bun --bun tsgo -p tsconfig.build.json", "dev": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", "dev:tsc": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", "test": "bun ../../scripts/run-with-clean-env.ts bun test --isolate --timeout 30000", From 3272cec102d7d00b7e2a080531fcc4acd8e1f47a Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 20:12:51 -0400 Subject: [PATCH 28/31] fix: retain installer lock coordination root --- install.sh | 6 ------ packages/coding-agent/test/bun-installer-e2e.test.ts | 3 ++- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/install.sh b/install.sh index d6b78e5cea..46a4f40693 100755 --- a/install.sh +++ b/install.sh @@ -105,7 +105,6 @@ prime_agent_screen_detail= prime_agent_animation_frame=0 prime_agent_binary_rollback_version= prime_agent_binary_lock_dir= -prime_agent_binary_lock_root= prime_agent_is_update=0 main() { @@ -192,10 +191,6 @@ prime_agent_cleanup() { rm -rf "$prime_agent_binary_lock_dir" prime_agent_binary_lock_dir= fi - if [ -n "${prime_agent_binary_lock_root:-}" ] && [ -d "$prime_agent_binary_lock_root" ]; then - rmdir "$prime_agent_binary_lock_root" 2>/dev/null || true - prime_agent_binary_lock_root= - fi prime_agent_restore_terminal return "$status" } @@ -979,7 +974,6 @@ prime_agent_binary_acquire_lock() { ;; esac mkdir -p "$_lock_root" - prime_agent_binary_lock_root="$_lock_root" rm -rf "$_lock_root/choosing-$$" for _entry in "$_lock_root"/*-"$$"; do [ -d "$_entry" ] || continue diff --git a/packages/coding-agent/test/bun-installer-e2e.test.ts b/packages/coding-agent/test/bun-installer-e2e.test.ts index 05888a8beb..e70ac65d27 100644 --- a/packages/coding-agent/test/bun-installer-e2e.test.ts +++ b/packages/coding-agent/test/bun-installer-e2e.test.ts @@ -5,6 +5,7 @@ import { chmodSync, mkdirSync, mkdtempSync, + readdirSync, readFileSync, readlinkSync, realpathSync, @@ -340,7 +341,7 @@ describe("compiled binary installer", () => { const link = join(root, "bin", "prime-agent"); expect(readlinkSync(link)).toContain("v2.0.0/prime-agent"); expect(spawnSync(link, ["--version"], { encoding: "utf8" }).status).toBe(0); - expect(() => readFileSync(join(staleRoot, "1-99999991", "pid"))).toThrow(); + expect(readdirSync(staleRoot)).toEqual([]); }); test("recovers an install lock whose recorded process is gone", () => { From df849ab3c82b08d87753dc3d2c766e567c0c875e Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 21:45:05 -0400 Subject: [PATCH 29/31] feat: upgrade primary runtime to Bun 1.4.0 --- .bun-version | 2 +- .github/workflows/build-binaries.yml | 21 +++++++--- .github/workflows/ci.yml | 42 +++++++++++++------ .github/workflows/nightly-process-stress.yml | 7 +++- AGENTS.md | 2 +- bun.lock | 8 ++-- package.json | 9 ++-- packages/agent/package.json | 2 +- packages/ai/.changes/bun-primary-runtime.md | 2 +- packages/ai/package.json | 2 +- packages/ai/src/providers/amazon-bedrock.ts | 3 ++ packages/coding-agent/docs/quickstart.md | 2 +- packages/coding-agent/package.json | 2 +- .../test/bun-release-archives.test.ts | 2 +- packages/tui/package.json | 2 +- scripts/assemble-release-archives.mjs | 2 +- scripts/build-binaries.sh | 4 +- scripts/check-bun-version.ts | 12 ++++++ 18 files changed, 85 insertions(+), 41 deletions(-) create mode 100644 scripts/check-bun-version.ts diff --git a/.bun-version b/.bun-version index 085c0f2666..88c5fb891d 100644 --- a/.bun-version +++ b/.bun-version @@ -1 +1 @@ -1.3.14 +1.4.0 diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index c044db863a..86e963be7e 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -39,10 +39,13 @@ jobs: fetch-tags: true persist-credentials: false - - name: Setup Bun 1.3.14 + - name: Setup Bun 1.4.0 uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - bun-version: 1.3.14 + bun-version: 1.4.0 + + - name: Verify Bun 1.4.0 + run: bun run check:bun-version - name: Resolve release context id: context @@ -137,10 +140,13 @@ jobs: ref: ${{ env.BUILD_REF }} persist-credentials: false - - name: Setup Bun 1.3.14 + - name: Setup Bun 1.4.0 uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - bun-version: 1.3.14 + bun-version: 1.4.0 + + - name: Verify Bun 1.4.0 + run: bun run check:bun-version - name: Install system dependencies run: | @@ -287,10 +293,13 @@ jobs: ref: ${{ env.BUILD_REF }} persist-credentials: false - - name: Setup Bun 1.3.14 + - name: Setup Bun 1.4.0 uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - bun-version: 1.3.14 + bun-version: 1.4.0 + + - name: Verify Bun 1.4.0 + run: bun run check:bun-version - name: Download production artifacts if: env.PUBLISH_PRODUCTION == 'true' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4228d9137b..f79c1d0e7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,10 +42,13 @@ jobs: with: persist-credentials: false - - name: Setup Bun 1.3.14 + - name: Setup Bun 1.4.0 uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - bun-version: 1.3.14 + bun-version: 1.4.0 + + - name: Verify Bun 1.4.0 + run: bun run check:bun-version - name: Install system dependencies run: | @@ -102,10 +105,13 @@ jobs: with: persist-credentials: false - - name: Setup Bun 1.3.14 + - name: Setup Bun 1.4.0 uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - bun-version: 1.3.14 + bun-version: 1.4.0 + + - name: Verify Bun 1.4.0 + run: bun run check:bun-version - name: Install system dependencies run: | @@ -141,10 +147,13 @@ jobs: with: persist-credentials: false - - name: Setup Bun 1.3.14 + - name: Setup Bun 1.4.0 uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - bun-version: 1.3.14 + bun-version: 1.4.0 + + - name: Verify Bun 1.4.0 + run: bun run check:bun-version - name: Install system dependencies run: | @@ -181,10 +190,13 @@ jobs: with: persist-credentials: false - - name: Setup Bun 1.3.14 + - name: Setup Bun 1.4.0 uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - bun-version: 1.3.14 + bun-version: 1.4.0 + + - name: Verify Bun 1.4.0 + run: bun run check:bun-version - name: Install system dependencies run: | @@ -219,10 +231,13 @@ jobs: with: persist-credentials: false - - name: Setup Bun 1.3.14 + - name: Setup Bun 1.4.0 uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - bun-version: 1.3.14 + bun-version: 1.4.0 + + - name: Verify Bun 1.4.0 + run: bun run check:bun-version - name: Install dependencies (frozen lockfile) run: bun install --frozen-lockfile @@ -252,10 +267,13 @@ jobs: with: persist-credentials: false - - name: Setup Bun 1.3.14 + - name: Setup Bun 1.4.0 uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - bun-version: 1.3.14 + bun-version: 1.4.0 + + - name: Verify Bun 1.4.0 + run: bun run check:bun-version - name: Install dependencies for all release platforms run: bun install --frozen-lockfile --os=* --cpu=* diff --git a/.github/workflows/nightly-process-stress.yml b/.github/workflows/nightly-process-stress.yml index 8ea0cfb4c5..41d049f8c9 100644 --- a/.github/workflows/nightly-process-stress.yml +++ b/.github/workflows/nightly-process-stress.yml @@ -23,10 +23,13 @@ jobs: with: persist-credentials: false - - name: Setup Bun 1.3.14 + - name: Setup Bun 1.4.0 uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 with: - bun-version: 1.3.14 + bun-version: 1.4.0 + + - name: Verify Bun 1.4.0 + run: bun run check:bun-version - name: Install system dependencies run: | diff --git a/AGENTS.md b/AGENTS.md index 393fb51cb4..c8fe302c1a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -44,7 +44,7 @@ ## Dependencies - A 7-day minimum release age applies to all dependency updates: `bunfig.toml` sets `minimumReleaseAge = 604800` and `.github/dependabot.yml` uses a matching `cooldown`. Never bypass it for routine updates. -- Bun 1.3.14 enforces this setting for dependency updates. +- Bun 1.4.0 enforces this setting for dependency updates. - For an urgent security patch younger than 7 days, override explicitly: `bun add --minimum-release-age=0 `. ## GitHub Workflow diff --git a/bun.lock b/bun.lock index dcae26ccae..c1cfdb646d 100644 --- a/bun.lock +++ b/bun.lock @@ -16,7 +16,7 @@ "@vitest/expect": "4.1.10", "@vitest/runner": "4.1.10", "@vitest/spy": "4.1.10", - "bun-types": "1.3.14", + "bun-types": "1.4.0", "husky": "^9.1.7", "jiti": "^2.7.0", "typescript": "^7.0.2", @@ -417,7 +417,7 @@ "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], - "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + "bun-types": ["bun-types@1.4.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-iIKw23BspnQQYd3prITOBxeUsxBHnwzX6YJfGMuNOZzeNcMmVqzIIVGRm1l69ogaPQmb4wB6BN8mA5bE9YuC5Q=="], "canvas": ["canvas@3.2.3", "", { "dependencies": { "node-addon-api": "^7.0.0", "prebuild-install": "^7.1.3" } }, "sha512-PzE5nJZPz72YUAfo8oTp0u3fqqY7IzlTubneAihqDYAUcBk7ryeCmBbdJBEdaH0bptSOe2VT2Zwcb3UaFyaSWw=="], @@ -665,7 +665,7 @@ "strtok3": ["strtok3@10.3.5", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA=="], - "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "tar-fs": ["tar-fs@2.1.5", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw=="], @@ -769,8 +769,6 @@ "bun-types/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], - "cli-highlight/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "protobufjs/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], diff --git a/package.json b/package.json index 1835df249a..f5dac8ce7d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "prime-agent", "private": true, "type": "module", - "packageManager": "bun@1.3.14", + "packageManager": "bun@1.4.0", "workspaces": [ "packages/*", "packages/coding-agent/examples/extensions/with-deps", @@ -16,7 +16,8 @@ "dev": "bun scripts/dev.ts", "dev:tsc": "bun run --cwd packages/ai dev:tsc", "models:refresh": "bun run --cwd packages/ai generate-models", - "check": "bun --bun biome check --write --error-on-warnings . && bun run check:type && bun run check:installer && bun run check:browser-smoke", + "check:bun-version": "bun scripts/check-bun-version.ts", + "check": "bun run check:bun-version && bun --bun biome check --write --error-on-warnings . && bun run check:type && bun run check:installer && bun run check:browser-smoke", "check:installer": "bun scripts/check-installer-render.mjs", "check:browser-smoke": "bun scripts/check-browser-smoke.mjs", "profile:tui": "bun scripts/profile-coding-agent-node.mjs --mode tui", @@ -46,7 +47,7 @@ "@biomejs/biome": "2.5.5", "@types/node": "^22.10.5", "@typescript/native-preview": "7.0.0-dev.20260120.1", - "bun-types": "1.3.14", + "bun-types": "1.4.0", "husky": "^9.1.7", "jiti": "^2.7.0", "typescript": "^7.0.2", @@ -56,7 +57,7 @@ }, "engines": { "node": ">=22.8.0", - "bun": "1.3.14" + "bun": "1.4.0" }, "version": "0.9.1", "dependencies": { diff --git a/packages/agent/package.json b/packages/agent/package.json index a056fb3609..1a55f80f35 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -36,7 +36,7 @@ }, "engines": { "node": ">=20.0.0", - "bun": "1.3.14" + "bun": "1.4.0" }, "devDependencies": { "@types/node": "^24.3.0", diff --git a/packages/ai/.changes/bun-primary-runtime.md b/packages/ai/.changes/bun-primary-runtime.md index e0b40ce40f..f0b83b5388 100644 --- a/packages/ai/.changes/bun-primary-runtime.md +++ b/packages/ai/.changes/bun-primary-runtime.md @@ -1 +1 @@ -- Made Bun 1.3.14 the primary development and test runtime while preserving Node-compatible package output. +- Made Bun 1.4.0 the primary development and test runtime while preserving Node-compatible package output. diff --git a/packages/ai/package.json b/packages/ai/package.json index 08a5493038..c6a6e323e6 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -103,7 +103,7 @@ }, "engines": { "node": ">=20.0.0", - "bun": "1.3.14" + "bun": "1.4.0" }, "devDependencies": { "@types/node": "^24.3.0", diff --git a/packages/ai/src/providers/amazon-bedrock.ts b/packages/ai/src/providers/amazon-bedrock.ts index 0a540c337e..76eda44a36 100644 --- a/packages/ai/src/providers/amazon-bedrock.ts +++ b/packages/ai/src/providers/amazon-bedrock.ts @@ -208,6 +208,9 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream", BedrockOpt if (nextCommandInput !== undefined) { commandInput = nextCommandInput as typeof commandInput; } + if (options.signal?.aborted) { + throw new Error("Request was aborted"); + } const command = new ConverseStreamCommand(commandInput); const response = await client.send(command, { abortSignal: options.signal }); diff --git a/packages/coding-agent/docs/quickstart.md b/packages/coding-agent/docs/quickstart.md index 9bf314d779..b1e614f654 100644 --- a/packages/coding-agent/docs/quickstart.md +++ b/packages/coding-agent/docs/quickstart.md @@ -25,7 +25,7 @@ cd /path/to/project prime-agent ``` -To run a source checkout instead, use Bun 1.3.14: +To run a source checkout instead, use Bun 1.4.0: ```bash git clone https://github.com/PrimeIntellect-ai/prime-agent diff --git a/packages/coding-agent/package.json b/packages/coding-agent/package.json index 7d2896f277..24212ce924 100644 --- a/packages/coding-agent/package.json +++ b/packages/coding-agent/package.json @@ -102,6 +102,6 @@ }, "engines": { "node": ">=22.8.0", - "bun": "1.3.14" + "bun": "1.4.0" } } diff --git a/packages/coding-agent/test/bun-release-archives.test.ts b/packages/coding-agent/test/bun-release-archives.test.ts index 8b35dc50ad..5bb0c74a13 100644 --- a/packages/coding-agent/test/bun-release-archives.test.ts +++ b/packages/coding-agent/test/bun-release-archives.test.ts @@ -103,7 +103,7 @@ describe("compiled release archives", () => { name: "prime-agent", version: "1.2.3", bin: { "prime-agent": "./prime-agent" }, - packageManager: "bun@1.3.14", + packageManager: "bun@1.4.0", }); for (const name of [ "prime-agent", diff --git a/packages/tui/package.json b/packages/tui/package.json index 9f991b1af8..7f6c2000c2 100644 --- a/packages/tui/package.json +++ b/packages/tui/package.json @@ -33,7 +33,7 @@ }, "engines": { "node": ">=20.0.0", - "bun": "1.3.14" + "bun": "1.4.0" }, "types": "./dist/index.d.ts", "dependencies": { diff --git a/scripts/assemble-release-archives.mjs b/scripts/assemble-release-archives.mjs index ca175a50e6..eba30c05bc 100755 --- a/scripts/assemble-release-archives.mjs +++ b/scripts/assemble-release-archives.mjs @@ -246,7 +246,7 @@ function renderPackageManifest(path, version) { manifest.name = publicPackageName; manifest.version = version; manifest.bin = { [binaryName]: `./${binaryName}` }; - manifest.packageManager = "bun@1.3.14"; + manifest.packageManager = "bun@1.4.0"; writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\n`); } diff --git a/scripts/build-binaries.sh b/scripts/build-binaries.sh index 18a6915e99..a7dc23c0a9 100755 --- a/scripts/build-binaries.sh +++ b/scripts/build-binaries.sh @@ -25,8 +25,8 @@ set -euo pipefail cd "$(dirname "$0")/.." -# Require Bun 1.3.14 -EXPECTED_BUN_VERSION="1.3.14" +# Require Bun 1.4.0 +EXPECTED_BUN_VERSION="1.4.0" ACTUAL_BUN_VERSION=$(bun --version 2>/dev/null || echo "not-found") if [ "$ACTUAL_BUN_VERSION" != "$EXPECTED_BUN_VERSION" ]; then echo "ERROR: Expected Bun ${EXPECTED_BUN_VERSION}, got ${ACTUAL_BUN_VERSION}" diff --git a/scripts/check-bun-version.ts b/scripts/check-bun-version.ts new file mode 100644 index 0000000000..a4c56aa895 --- /dev/null +++ b/scripts/check-bun-version.ts @@ -0,0 +1,12 @@ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; + +const expected = readFileSync(resolve(import.meta.dir, "../.bun-version"), "utf8").trim(); +const actual = Bun.version; + +if (actual !== expected) { + console.error(`Expected Bun ${expected}, got ${actual}.`); + process.exit(1); +} + +console.log(`Validated Bun ${actual} (${process.execPath})`); From cad37bc2a28a25546fa07a3409c01edc647180a8 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 1 Sep 2026 23:18:56 -0400 Subject: [PATCH 30/31] perf: accelerate compiled Bun startup --- .github/workflows/build-binaries.yml | 2 +- .../ai/src/providers/register-builtins.ts | 29 ++++++++++----- packages/ai/test/lazy-module-load.test.ts | 35 +++++++++++++++++++ packages/coding-agent/package.json | 2 +- .../coding-agent/src/bun/register-bedrock.ts | 8 +++-- scripts/build-binaries.sh | 2 +- 6 files changed, 63 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index 86e963be7e..d3429868a4 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -169,7 +169,7 @@ jobs: for platform in darwin-arm64 darwin-x64 linux-arm64 linux-x64; do echo "Compiling for $platform..." mkdir -p "binaries/$platform" - bun build --compile --external koffi --target="bun-$platform" ./dist/bun/cli.js --outfile "binaries/$platform/pi" + bun build --compile --minify --keep-names --bytecode --format=esm --external koffi --target="bun-$platform" ./dist/bun/cli.js --outfile "binaries/$platform/pi" done - name: Copy binary sidecar assets diff --git a/packages/ai/src/providers/register-builtins.ts b/packages/ai/src/providers/register-builtins.ts index 6447568084..5ed356d285 100644 --- a/packages/ai/src/providers/register-builtins.ts +++ b/packages/ai/src/providers/register-builtins.ts @@ -115,17 +115,32 @@ let openAIResponsesProviderModulePromise: let bedrockProviderModuleOverride: | LazyProviderModule<"bedrock-converse-stream", BedrockOptions, SimpleStreamOptions> | undefined; +let bedrockProviderModuleLoaderOverride: (() => Promise) | undefined; let bedrockProviderModulePromise: | Promise> | undefined; -export function setBedrockProviderModule(module: BedrockProviderModule): void { - bedrockProviderModuleOverride = { +function toLazyBedrockProviderModule( + module: BedrockProviderModule, +): LazyProviderModule<"bedrock-converse-stream", BedrockOptions, SimpleStreamOptions> { + return { stream: module.streamBedrock, streamSimple: module.streamSimpleBedrock, }; } +export function setBedrockProviderModule(module: BedrockProviderModule): void { + bedrockProviderModuleLoaderOverride = undefined; + bedrockProviderModulePromise = undefined; + bedrockProviderModuleOverride = toLazyBedrockProviderModule(module); +} + +export function setBedrockProviderModuleLoader(loader: () => Promise): void { + bedrockProviderModuleOverride = undefined; + bedrockProviderModulePromise = undefined; + bedrockProviderModuleLoaderOverride = loader; +} + function forwardStream(target: AssistantMessageEventStream, source: AsyncIterable): void { (async () => { for await (const event of source) { @@ -310,13 +325,9 @@ function loadBedrockProviderModule(): Promise< if (bedrockProviderModuleOverride) { return Promise.resolve(bedrockProviderModuleOverride); } - bedrockProviderModulePromise ||= importNodeOnlyProvider("./amazon-bedrock.js").then((module) => { - const provider = module as BedrockProviderModule; - return { - stream: provider.streamBedrock, - streamSimple: provider.streamSimpleBedrock, - }; - }); + bedrockProviderModulePromise ||= ( + bedrockProviderModuleLoaderOverride?.() ?? importNodeOnlyProvider("./amazon-bedrock.js") + ).then((module) => toLazyBedrockProviderModule(module as BedrockProviderModule)); return bedrockProviderModulePromise; } diff --git a/packages/ai/test/lazy-module-load.test.ts b/packages/ai/test/lazy-module-load.test.ts index 7c707c8684..7b2a3e7db4 100644 --- a/packages/ai/test/lazy-module-load.test.ts +++ b/packages/ai/test/lazy-module-load.test.ts @@ -7,6 +7,7 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const packageRoot = resolve(__dirname, ".."); const aiEntryUrl = new URL("../src/index.ts", import.meta.url).href; +const bedrockProviderEntryUrl = new URL("../src/bedrock-provider.ts", import.meta.url).href; const SDK_SPECIFIERS = [ "@anthropic-ai/sdk", @@ -58,6 +59,40 @@ describe("lazy provider module loading", () => { expect(result.loadedSpecifiers).toEqual([]); }); + it("does not load the Bedrock SDK when registering its compiled-binary loader", () => { + const result = runProbe( + `mod.setBedrockProviderModuleLoader(async () => (await import("${bedrockProviderEntryUrl}")).bedrockProviderModule);`, + ); + expect(result.loadedSpecifiers).toEqual([]); + }); + + it("loads the Bedrock SDK when the registered loader is first used", () => { + const result = runProbe( + [ + `mod.setBedrockProviderModuleLoader(async () => {`, + ` await import("${bedrockProviderEntryUrl}");`, + ` const fail = () => { throw new Error("probe"); };`, + ` return { streamBedrock: fail, streamSimpleBedrock: fail };`, + `});`, + `const model = {`, + ` id: "anthropic.claude-3-5-sonnet-20241022-v2:0",`, + ` api: "bedrock-converse-stream",`, + ` provider: "amazon-bedrock",`, + ` baseUrl: "http://127.0.0.1:9",`, + ` reasoning: false,`, + ` input: ["text"],`, + ` cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },`, + ` contextWindow: 200000,`, + ` maxTokens: 8192,`, + `};`, + `const context = { messages: [{ role: "user", content: "hi", timestamp: Date.now() }] };`, + `try { await mod.streamSimple(model, context).result(); } catch (_e) {}`, + ].join("\n"), + ); + + expect(result.loadedSpecifiers).toEqual(["@aws-sdk/client-bedrock-runtime"]); + }); + it("loads only the Anthropic SDK when calling the root lazy wrapper", () => { const result = runProbe( [ diff --git a/packages/coding-agent/package.json b/packages/coding-agent/package.json index 24212ce924..aee7466abe 100644 --- a/packages/coding-agent/package.json +++ b/packages/coding-agent/package.json @@ -34,7 +34,7 @@ "clean": "bun ../../scripts/remove-paths.ts dist", "dev": "bun --bun tsgo -p tsconfig.build.json --watch --preserveWatchOutput", "build": "bun --bun tsgo -p tsconfig.build.json && bun scripts/copy-assets.ts package && bun run bundle", - "build:binary": "bun run --cwd ../tui build && bun run --cwd ../ai build && bun run --cwd ../agent build && bun run build && bun build --compile ./dist/bun/cli.js --outfile dist/pi && bun scripts/copy-assets.ts binary", + "build:binary": "bun run --cwd ../tui build && bun run --cwd ../ai build && bun run --cwd ../agent build && bun run build && bun build --compile --minify --keep-names --bytecode --format=esm ./dist/bun/cli.js --outfile dist/pi && bun scripts/copy-assets.ts binary", "copy-assets": "bun scripts/copy-assets.ts package", "copy-binary-assets": "bun scripts/copy-assets.ts binary", "test": "bun ../../scripts/run-with-clean-env.ts bun scripts/run-tests.ts", diff --git a/packages/coding-agent/src/bun/register-bedrock.ts b/packages/coding-agent/src/bun/register-bedrock.ts index 92af0dde28..839cbcdb2b 100644 --- a/packages/coding-agent/src/bun/register-bedrock.ts +++ b/packages/coding-agent/src/bun/register-bedrock.ts @@ -1,4 +1,6 @@ -import { setBedrockProviderModule } from "@earendil-works/pi-ai"; -import { bedrockProviderModule } from "@earendil-works/pi-ai/bedrock-provider"; +import { setBedrockProviderModuleLoader } from "@earendil-works/pi-ai"; -setBedrockProviderModule(bedrockProviderModule); +setBedrockProviderModuleLoader(async () => { + const { bedrockProviderModule } = await import("@earendil-works/pi-ai/bedrock-provider"); + return bedrockProviderModule; +}); diff --git a/scripts/build-binaries.sh b/scripts/build-binaries.sh index a7dc23c0a9..b02ef9bc62 100755 --- a/scripts/build-binaries.sh +++ b/scripts/build-binaries.sh @@ -92,7 +92,7 @@ fi for platform in "${PLATFORMS[@]}"; do echo "Building for $platform..." mkdir -p "binaries/$platform" - bun build --compile --external koffi --target="bun-$platform" ./dist/bun/cli.js --outfile "binaries/$platform/pi" + bun build --compile --minify --keep-names --bytecode --format=esm --external koffi --target="bun-$platform" ./dist/bun/cli.js --outfile "binaries/$platform/pi" done echo "==> Copying sidecar assets..." From 97795bf5f913fe943051bd24f85b3feff72b58de Mon Sep 17 00:00:00 2001 From: Seth Date: Wed, 2 Sep 2026 02:27:18 -0400 Subject: [PATCH 31/31] build: prepare Prime Intellect Bun packages --- README.md | 10 +++- bun.lock | 40 ++++++------- package.json | 2 +- .../agent/.changes/prime-intellect-package.md | 1 + packages/agent/package.json | 7 ++- packages/agent/src/agent-loop.ts | 2 +- packages/agent/src/agent.ts | 2 +- packages/agent/src/proxy.ts | 2 +- packages/agent/src/types.ts | 4 +- .../ai/.changes/prime-intellect-package.md | 1 + packages/ai/package.json | 5 +- packages/ai/src/cli.ts | 12 ++-- .../.changes/prime-intellect-package.md | 1 + packages/coding-agent/README.md | 14 ++++- packages/coding-agent/docs/compaction.md | 4 +- packages/coding-agent/docs/custom-provider.md | 8 +-- packages/coding-agent/docs/development.md | 2 +- packages/coding-agent/docs/extensions.md | 56 +++++++++---------- packages/coding-agent/docs/index.md | 6 +- packages/coding-agent/docs/packages.md | 2 +- packages/coding-agent/docs/quickstart.md | 12 ++-- packages/coding-agent/docs/rpc.md | 2 +- packages/coding-agent/docs/sdk.md | 48 ++++++++-------- packages/coding-agent/docs/session-format.md | 2 +- packages/coding-agent/docs/tui.md | 38 ++++++------- .../examples/extensions/README.md | 6 +- .../extensions/auto-commit-on-exit.ts | 2 +- .../examples/extensions/bash-spawn-hook.ts | 4 +- .../examples/extensions/bookmark.ts | 2 +- .../extensions/border-status-editor.ts | 6 +- .../extensions/built-in-tool-renderer.ts | 6 +- .../examples/extensions/claude-rules.ts | 2 +- .../examples/extensions/commands.ts | 2 +- .../extensions/confirm-destructive.ts | 2 +- .../examples/extensions/custom-compaction.ts | 6 +- .../examples/extensions/custom-footer.ts | 6 +- .../examples/extensions/custom-header.ts | 4 +- .../custom-provider-anthropic/index.ts | 4 +- .../custom-provider-gitlab-duo/index.ts | 4 +- .../custom-provider-gitlab-duo/test.ts | 2 +- .../examples/extensions/custom-refinement.ts | 4 +- .../examples/extensions/dirty-repo-guard.ts | 2 +- .../extensions/doom-overlay/doom-component.ts | 4 +- .../extensions/doom-overlay/doom-keys.ts | 2 +- .../examples/extensions/doom-overlay/index.ts | 2 +- .../extensions/dynamic-resources/index.ts | 2 +- .../examples/extensions/dynamic-tools.ts | 2 +- .../examples/extensions/event-bus.ts | 2 +- .../examples/extensions/file-trigger.ts | 2 +- .../examples/extensions/git-checkpoint.ts | 2 +- .../extensions/github-issue-autocomplete.ts | 4 +- .../examples/extensions/handoff.ts | 8 +-- .../coding-agent/examples/extensions/hello.ts | 4 +- .../extensions/hidden-thinking-label.ts | 2 +- .../examples/extensions/inline-bash.ts | 2 +- .../examples/extensions/input-transform.ts | 2 +- .../examples/extensions/interactive-shell.ts | 2 +- .../examples/extensions/mac-system-theme.ts | 2 +- .../examples/extensions/message-renderer.ts | 4 +- .../examples/extensions/minimal-mode.ts | 6 +- .../examples/extensions/modal-editor.ts | 4 +- .../examples/extensions/model-status.ts | 2 +- .../examples/extensions/notify.ts | 2 +- .../examples/extensions/overlay-qa-tests.ts | 6 +- .../examples/extensions/overlay-test.ts | 4 +- .../examples/extensions/permission-gate.ts | 2 +- .../examples/extensions/pirate.ts | 2 +- .../examples/extensions/plan-mode/index.ts | 8 +-- .../examples/extensions/preset.ts | 8 +-- .../examples/extensions/prompt-customizer.ts | 2 +- .../examples/extensions/protected-paths.ts | 2 +- .../examples/extensions/provider-payload.ts | 2 +- .../coding-agent/examples/extensions/qna.ts | 6 +- .../examples/extensions/question.ts | 4 +- .../examples/extensions/questionnaire.ts | 4 +- .../examples/extensions/rainbow-editor.ts | 2 +- .../examples/extensions/reload-runtime.ts | 2 +- .../examples/extensions/rpc-demo.ts | 2 +- .../examples/extensions/sandbox/index.ts | 4 +- .../examples/extensions/send-user-message.ts | 2 +- .../examples/extensions/session-name.ts | 2 +- .../examples/extensions/shutdown-command.ts | 2 +- .../coding-agent/examples/extensions/snake.ts | 4 +- .../examples/extensions/space-invaders.ts | 4 +- .../coding-agent/examples/extensions/ssh.ts | 9 +-- .../examples/extensions/status-line.ts | 2 +- .../examples/extensions/structured-output.ts | 4 +- .../examples/extensions/subagent/agents.ts | 2 +- .../examples/extensions/subagent/index.ts | 10 ++-- .../examples/extensions/summarize.ts | 8 +-- .../extensions/system-prompt-header.ts | 2 +- .../examples/extensions/tic-tac-toe.ts | 6 +- .../examples/extensions/timed-confirm.ts | 2 +- .../examples/extensions/titlebar-spinner.ts | 2 +- .../coding-agent/examples/extensions/todo.ts | 6 +- .../examples/extensions/tool-override.ts | 4 +- .../coding-agent/examples/extensions/tools.ts | 6 +- .../examples/extensions/trigger-compact.ts | 2 +- .../examples/extensions/truncated-tool.ts | 6 +- .../examples/extensions/widget-placement.ts | 2 +- .../examples/extensions/with-deps/index.ts | 2 +- .../examples/extensions/working-indicator.ts | 2 +- .../extensions/working-message-test.ts | 2 +- .../coding-agent/examples/rpc-extension-ui.ts | 10 +++- .../coding-agent/examples/sdk/01-minimal.ts | 2 +- .../examples/sdk/02-custom-model.ts | 4 +- .../examples/sdk/03-custom-prompt.ts | 7 +-- .../coding-agent/examples/sdk/04-skills.ts | 2 +- .../coding-agent/examples/sdk/05-tools.ts | 2 +- .../examples/sdk/06-extensions.ts | 9 +-- .../examples/sdk/07-context-files.ts | 7 +-- .../examples/sdk/08-prompt-templates.ts | 2 +- .../examples/sdk/09-api-keys-and-oauth.ts | 2 +- .../coding-agent/examples/sdk/10-settings.ts | 2 +- .../coding-agent/examples/sdk/11-sessions.ts | 2 +- .../examples/sdk/12-full-control.ts | 4 +- .../examples/sdk/13-session-runtime.ts | 2 +- packages/coding-agent/examples/sdk/README.md | 6 +- packages/coding-agent/package.json | 13 +++-- packages/coding-agent/scripts/bundle.mjs | 8 +-- .../coding-agent/src/bun/register-bedrock.ts | 4 +- packages/coding-agent/src/cli/args.ts | 2 +- .../coding-agent/src/cli/config-selector.ts | 2 +- .../coding-agent/src/cli/daemon-command.ts | 2 +- .../coding-agent/src/cli/file-processor.ts | 2 +- .../coding-agent/src/cli/initial-message.ts | 2 +- packages/coding-agent/src/cli/list-models.ts | 4 +- packages/coding-agent/src/config.ts | 2 +- .../coding-agent/src/core/agent-messages.ts | 2 +- .../coding-agent/src/core/agent-observe.ts | 2 +- .../src/core/agent-session-config.ts | 2 +- .../src/core/agent-session-services.ts | 4 +- .../coding-agent/src/core/agent-session.ts | 28 +++++----- .../coding-agent/src/core/auth-storage.ts | 4 +- packages/coding-agent/src/core/autonomous.ts | 2 +- .../core/compaction/branch-summarization.ts | 6 +- .../src/core/compaction/compaction.ts | 6 +- .../coding-agent/src/core/compaction/utils.ts | 4 +- .../coding-agent/src/core/context-tree.ts | 2 +- packages/coding-agent/src/core/defaults.ts | 2 +- .../src/core/export-html/index.ts | 2 +- .../src/core/export-html/tool-renderer.ts | 4 +- .../src/core/extensions/bundled-modules.ts | 15 +++-- .../src/core/extensions/loader.ts | 15 +++-- .../src/core/extensions/runner.ts | 6 +- .../coding-agent/src/core/extensions/types.ts | 22 ++++---- .../src/core/extensions/wrapper.ts | 2 +- packages/coding-agent/src/core/goals.ts | 2 +- .../coding-agent/src/core/kernel/shared.ts | 2 +- packages/coding-agent/src/core/keybindings.ts | 4 +- packages/coding-agent/src/core/logging.ts | 2 +- .../coding-agent/src/core/mcp/mcp-command.ts | 2 +- .../coding-agent/src/core/mcp/mcp-manager.ts | 4 +- packages/coding-agent/src/core/messages.ts | 6 +- .../coding-agent/src/core/model-registry.ts | 6 +- .../coding-agent/src/core/model-resolver.ts | 4 +- .../src/core/prime-inference-auth.ts | 2 +- .../core/prime-inference-model-selection.ts | 2 +- .../src/core/prime-inference-models.ts | 2 +- .../src/core/refinement/refinement.ts | 6 +- packages/coding-agent/src/core/rlm-runtime.ts | 4 +- packages/coding-agent/src/core/sdk.ts | 12 +++- .../src/core/session-action-store.ts | 4 +- .../coding-agent/src/core/session-manager.ts | 11 +++- .../coding-agent/src/core/settings-manager.ts | 2 +- .../coding-agent/src/core/side-question.ts | 4 +- packages/coding-agent/src/core/skills.ts | 2 +- packages/coding-agent/src/core/telemetry.ts | 2 +- .../coding-agent/src/core/thinking-levels.ts | 2 +- packages/coding-agent/src/core/timings.ts | 2 +- packages/coding-agent/src/core/tools/bash.ts | 4 +- packages/coding-agent/src/core/tools/edit.ts | 4 +- packages/coding-agent/src/core/tools/index.ts | 2 +- .../coding-agent/src/core/tools/ipython.ts | 4 +- .../src/core/tools/render-utils.ts | 4 +- .../src/core/tools/tool-definition-wrapper.ts | 2 +- packages/coding-agent/src/core/usage.ts | 2 +- packages/coding-agent/src/main.ts | 6 +- .../coding-agent/src/modes/acp/acp-events.ts | 2 +- .../coding-agent/src/modes/acp/acp-mode.ts | 4 +- .../daemon-agent-connection.ts | 4 +- .../in-process-agent-connection.ts | 4 +- .../src/modes/agent-connection/snapshot.ts | 2 +- .../src/modes/agent-connection/types.ts | 12 +++- .../src/modes/agents-view/agents-view-mode.ts | 2 +- .../modes/agents-view/session-view-search.ts | 2 +- .../modes/daemon/compact-session-stream.ts | 2 +- .../src/modes/daemon/daemon-mode.ts | 2 +- .../src/modes/daemon/daemon-protocol.ts | 4 +- .../src/modes/daemon/daemon-session-list.ts | 4 +- .../modes/daemon/daemon-session-summarizer.ts | 6 +- .../src/modes/daemon/daemon-supervisor.ts | 2 +- .../modes/daemon/snapshot-transcript-cache.ts | 2 +- .../src/modes/headless-completion.ts | 4 +- .../src/modes/interactive/auth-flows.ts | 4 +- .../interactive/components/agent-message.ts | 2 +- .../src/modes/interactive/components/armin.ts | 2 +- .../components/assistant-message.ts | 4 +- .../interactive/components/bash-execution.ts | 2 +- .../interactive/components/bordered-loader.ts | 2 +- .../components/branch-summary-message.ts | 2 +- .../components/centered-overlay.ts | 2 +- .../components/collapsible-error.ts | 2 +- .../components/compaction-outcome-message.ts | 2 +- .../components/compaction-summary-message.ts | 2 +- .../interactive/components/config-selector.ts | 2 +- .../components/configuration-menu.ts | 4 +- .../components/context-tree-format.ts | 4 +- .../components/conversation-components.ts | 4 +- .../interactive/components/countdown-timer.ts | 2 +- .../interactive/components/custom-editor.ts | 2 +- .../interactive/components/custom-message.ts | 6 +- .../modes/interactive/components/daxnuts.ts | 2 +- .../src/modes/interactive/components/diff.ts | 2 +- .../interactive/components/dynamic-border.ts | 2 +- .../components/earendil-announcement.ts | 2 +- .../interactive/components/edit-summary.ts | 6 +- .../components/expandable-custom-message.ts | 2 +- .../components/extension-editor.ts | 2 +- .../interactive/components/extension-input.ts | 10 +++- .../components/extension-selector.ts | 2 +- .../interactive/components/feature-hint.ts | 2 +- .../modes/interactive/components/footer.ts | 2 +- .../components/heartbeat-manager.ts | 8 ++- .../components/injected-prompt-message.ts | 4 +- .../interactive/components/ipython-cell.ts | 2 +- .../components/keybinding-hints.ts | 2 +- .../interactive/components/login-dialog.ts | 4 +- .../interactive/components/menu-panel.ts | 2 +- .../interactive/components/modal-back.ts | 2 +- .../interactive/components/model-selector.ts | 4 +- .../interactive/components/oauth-selector.ts | 2 +- .../components/prime-onboarding-splash.ts | 2 +- .../components/prime-team-selector.ts | 9 ++- .../components/refinement-outcome-message.ts | 2 +- .../components/scoped-models-selector.ts | 4 +- .../components/settings-selector.ts | 6 +- .../components/show-images-selector.ts | 2 +- .../interactive/components/side-question.ts | 2 +- .../components/skill-invocation-message.ts | 2 +- .../components/slash-command-message.ts | 2 +- .../slash-command-result-message.ts | 2 +- .../components/subagent-summary-line.ts | 8 ++- .../interactive/components/theme-selector.ts | 2 +- .../components/thinking-selector.ts | 4 +- .../interactive/components/tool-execution.ts | 4 +- .../interactive/components/tool-panel.ts | 2 +- .../interactive/components/tree-selector.ts | 2 +- .../components/user-message-selector.ts | 9 ++- .../interactive/components/user-message.ts | 9 ++- .../interactive/components/visual-truncate.ts | 2 +- .../src/modes/interactive/interactive-mode.ts | 10 ++-- .../src/modes/interactive/onboarding.ts | 2 +- .../modes/interactive/prompt-stash-state.ts | 4 +- .../src/modes/interactive/theme/theme.ts | 6 +- .../src/modes/model-autocomplete.ts | 4 +- packages/coding-agent/src/modes/print-mode.ts | 2 +- .../coding-agent/src/modes/rpc/rpc-client.ts | 4 +- .../coding-agent/src/modes/rpc/rpc-types.ts | 4 +- .../coding-agent/src/package-manager-cli.ts | 2 +- .../coding-agent/src/utils/image-resize.ts | 2 +- packages/coding-agent/test/config.test.ts | 54 +++++++++--------- packages/coding-agent/tsconfig.examples.json | 8 +-- .../tui/.changes/prime-intellect-package.md | 1 + packages/tui/package.json | 5 +- scripts/browser-smoke-entry.ts | 2 +- tsconfig.json | 13 ++++- 267 files changed, 693 insertions(+), 590 deletions(-) create mode 100644 packages/agent/.changes/prime-intellect-package.md create mode 100644 packages/ai/.changes/prime-intellect-package.md create mode 100644 packages/coding-agent/.changes/prime-intellect-package.md create mode 100644 packages/tui/.changes/prime-intellect-package.md diff --git a/README.md b/README.md index e4b77ad79f..dcdcda3d07 100644 --- a/README.md +++ b/README.md @@ -53,13 +53,17 @@ Prime Agent combines a persistent Python control environment with durable harnes ## Getting Started -Install the latest stable release on macOS or Linux: +Install the latest stable release with [Bun](https://bun.sh/docs/installation): ```bash -curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh +bun install -g @prime-intellect/prime-agent ``` -The installer downloads a versioned release, verifies its SHA-256 checksum, installs the `prime-agent` command, and can prepare the Python runtime used by the agent. +The package installs the `prime-agent` command. On macOS and Linux, the standalone release installer remains available as an alternative: + +```bash +curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh +``` Start Prime Agent from the repository or directory you want it to work in: diff --git a/bun.lock b/bun.lock index c1cfdb646d..dee2073c04 100644 --- a/bun.lock +++ b/bun.lock @@ -5,7 +5,7 @@ "": { "name": "prime-agent", "dependencies": { - "@earendil-works/pi-coding-agent": "^0.9.1", + "@prime-intellect/prime-agent": "^0.9.1", "get-east-asian-width": "^1.6.0", }, "devDependencies": { @@ -23,10 +23,10 @@ }, }, "packages/agent": { - "name": "@earendil-works/pi-agent-core", + "name": "@prime-intellect/prime-agent-core", "version": "0.9.1", "dependencies": { - "@earendil-works/pi-ai": "^0.9.1", + "@prime-intellect/prime-agent-ai": "^0.9.1", "typebox": "^1.3.9", }, "devDependencies": { @@ -35,7 +35,7 @@ }, }, "packages/ai": { - "name": "@earendil-works/pi-ai", + "name": "@prime-intellect/prime-agent-ai", "version": "0.9.1", "bin": { "pi-ai": "./dist/cli.js", @@ -59,16 +59,16 @@ }, }, "packages/coding-agent": { - "name": "@earendil-works/pi-coding-agent", + "name": "@prime-intellect/prime-agent", "version": "0.9.1", "bin": { - "pi": "dist/bundle/cli.js", + "prime-agent": "dist/bundle/cli.js", }, "dependencies": { "@agentclientprotocol/sdk": "^1.3.0", - "@earendil-works/pi-agent-core": "^0.9.1", - "@earendil-works/pi-ai": "^0.9.1", - "@earendil-works/pi-tui": "^0.9.1", + "@prime-intellect/prime-agent-core": "^0.9.1", + "@prime-intellect/prime-agent-ai": "^0.9.1", + "@prime-intellect/prime-agent-tui": "^0.9.1", "@silvia-odwyer/photon-node": "^0.3.4", "chalk": "^5.5.0", "cli-highlight": "^2.1.11", @@ -130,7 +130,7 @@ }, }, "packages/tui": { - "name": "@earendil-works/pi-tui", + "name": "@prime-intellect/prime-agent-tui", "version": "0.9.1", "dependencies": { "@types/mime-types": "^3.0.1", @@ -219,13 +219,13 @@ "@borewit/text-codec": ["@borewit/text-codec@0.2.2", "", {}, "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ=="], - "@earendil-works/pi-agent-core": ["@earendil-works/pi-agent-core@workspace:packages/agent"], + "@prime-intellect/prime-agent-core": ["@prime-intellect/prime-agent-core@workspace:packages/agent"], - "@earendil-works/pi-ai": ["@earendil-works/pi-ai@workspace:packages/ai"], + "@prime-intellect/prime-agent-ai": ["@prime-intellect/prime-agent-ai@workspace:packages/ai"], - "@earendil-works/pi-coding-agent": ["@earendil-works/pi-coding-agent@workspace:packages/coding-agent"], + "@prime-intellect/prime-agent": ["@prime-intellect/prime-agent@workspace:packages/coding-agent"], - "@earendil-works/pi-tui": ["@earendil-works/pi-tui@workspace:packages/tui"], + "@prime-intellect/prime-agent-tui": ["@prime-intellect/prime-agent-tui@workspace:packages/tui"], "@google/genai": ["@google/genai@1.52.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q=="], @@ -723,11 +723,11 @@ "@aws-sdk/credential-provider-sso/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1116.0", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-ygIivKqh8aHzNkucOCXHyIBgBpLPfrSI0mCqXF+vLBsPTUKqj0VSqAY0GFPe7lQl4HntjOcQ+KSyS7oUV2C54Q=="], - "@earendil-works/pi-agent-core/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], + "@prime-intellect/prime-agent-core/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], - "@earendil-works/pi-ai/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], + "@prime-intellect/prime-agent-ai/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], - "@earendil-works/pi-coding-agent/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], + "@prime-intellect/prime-agent/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="], "@mistralai/mistralai/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], @@ -759,11 +759,11 @@ "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "@earendil-works/pi-agent-core/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + "@prime-intellect/prime-agent-core/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], - "@earendil-works/pi-ai/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + "@prime-intellect/prime-agent-ai/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], - "@earendil-works/pi-coding-agent/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + "@prime-intellect/prime-agent/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], "@types/yauzl/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], diff --git a/package.json b/package.json index f5dac8ce7d..51f294e230 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ }, "version": "0.9.1", "dependencies": { - "@earendil-works/pi-coding-agent": "^0.9.1", + "@prime-intellect/prime-agent": "^0.9.1", "get-east-asian-width": "^1.6.0" }, "overrides": { diff --git a/packages/agent/.changes/prime-intellect-package.md b/packages/agent/.changes/prime-intellect-package.md new file mode 100644 index 0000000000..455a3a4812 --- /dev/null +++ b/packages/agent/.changes/prime-intellect-package.md @@ -0,0 +1 @@ +- Moved the agent core package to `@prime-intellect/prime-agent-core`. diff --git a/packages/agent/package.json b/packages/agent/package.json index 1a55f80f35..1797886eee 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -1,5 +1,5 @@ { - "name": "@earendil-works/pi-agent-core", + "name": "@prime-intellect/prime-agent-core", "version": "0.9.1", "description": "General-purpose agent with transport abstraction, state management, and attachment support", "type": "module", @@ -17,7 +17,7 @@ "prepublishOnly": "bun run clean && bun run build" }, "dependencies": { - "@earendil-works/pi-ai": "^0.9.1", + "@prime-intellect/prime-agent-ai": "^0.9.1", "typebox": "^1.3.9" }, "keywords": [ @@ -41,5 +41,8 @@ "devDependencies": { "@types/node": "^24.3.0", "typescript": "^7.0.2" + }, + "publishConfig": { + "access": "public" } } diff --git a/packages/agent/src/agent-loop.ts b/packages/agent/src/agent-loop.ts index 31b3a15ccc..bf79e9e2ec 100644 --- a/packages/agent/src/agent-loop.ts +++ b/packages/agent/src/agent-loop.ts @@ -11,7 +11,7 @@ import { streamSimple, type ToolResultMessage, validateToolArguments, -} from "@earendil-works/pi-ai"; +} from "@prime-intellect/prime-agent-ai"; import type { AgentContext, AgentEvent, diff --git a/packages/agent/src/agent.ts b/packages/agent/src/agent.ts index 0b7b5ae774..0e99e3305a 100644 --- a/packages/agent/src/agent.ts +++ b/packages/agent/src/agent.ts @@ -8,7 +8,7 @@ import { type TextContent, type ThinkingBudgets, type Transport, -} from "@earendil-works/pi-ai"; +} from "@prime-intellect/prime-agent-ai"; import { runAgentLoop, runAgentLoopContinue } from "./agent-loop.js"; import type { AfterToolCallContext, diff --git a/packages/agent/src/proxy.ts b/packages/agent/src/proxy.ts index 69920ce033..964fa67cc4 100644 --- a/packages/agent/src/proxy.ts +++ b/packages/agent/src/proxy.ts @@ -8,7 +8,7 @@ import { type SimpleStreamOptions, type StopReason, type ToolCall, -} from "@earendil-works/pi-ai"; +} from "@prime-intellect/prime-agent-ai"; class ProxyMessageEventStream extends EventStream { constructor() { diff --git a/packages/agent/src/types.ts b/packages/agent/src/types.ts index f29074abe0..3c5a050f72 100644 --- a/packages/agent/src/types.ts +++ b/packages/agent/src/types.ts @@ -10,7 +10,7 @@ import type { TextContent, Tool, ToolResultMessage, -} from "@earendil-works/pi-ai"; +} from "@prime-intellect/prime-agent-ai"; import type { Static, TSchema } from "typebox"; /** @@ -275,7 +275,7 @@ export interface AgentLoopConfig extends SimpleStreamOptions { /** * Thinking/reasoning level for models that support it. * Note: "xhigh" and "max" are only supported by selected model families. Use model - * thinking-level metadata from @earendil-works/pi-ai to detect support for a concrete model. + * thinking-level metadata from @prime-intellect/prime-agent-ai to detect support for a concrete model. */ export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max"; diff --git a/packages/ai/.changes/prime-intellect-package.md b/packages/ai/.changes/prime-intellect-package.md new file mode 100644 index 0000000000..17dbc6dbb7 --- /dev/null +++ b/packages/ai/.changes/prime-intellect-package.md @@ -0,0 +1 @@ +- Moved the AI package to `@prime-intellect/prime-agent-ai`. diff --git a/packages/ai/package.json b/packages/ai/package.json index c6a6e323e6..59f43e0705 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,5 +1,5 @@ { - "name": "@earendil-works/pi-ai", + "name": "@prime-intellect/prime-agent-ai", "version": "0.9.1", "description": "Unified LLM API with automatic model discovery and provider configuration", "type": "module", @@ -108,5 +108,8 @@ "devDependencies": { "@types/node": "^24.3.0", "canvas": "^3.2.0" + }, + "publishConfig": { + "access": "public" } } diff --git a/packages/ai/src/cli.ts b/packages/ai/src/cli.ts index a378141c64..655be44d13 100644 --- a/packages/ai/src/cli.ts +++ b/packages/ai/src/cli.ts @@ -64,7 +64,7 @@ async function main(): Promise { if (!command || command === "help" || command === "--help" || command === "-h") { const providerList = PROVIDERS.map((p) => ` ${p.id.padEnd(20)} ${p.name}`).join("\n"); - console.log(`Usage: bunx @earendil-works/pi-ai [provider] + console.log(`Usage: bunx @prime-intellect/prime-agent-ai [provider] Commands: login [provider] Login to an OAuth provider @@ -74,9 +74,9 @@ Providers: ${providerList} Examples: - bunx @earendil-works/pi-ai login # interactive provider selection - bunx @earendil-works/pi-ai login anthropic # login to specific provider - bunx @earendil-works/pi-ai list # list providers + bunx @prime-intellect/prime-agent-ai login # interactive provider selection + bunx @prime-intellect/prime-agent-ai login anthropic # login to specific provider + bunx @prime-intellect/prime-agent-ai list # list providers `); return; } @@ -113,7 +113,7 @@ Examples: if (!PROVIDERS.some((p) => p.id === provider)) { console.error(`Unknown provider: ${provider}`); - console.error(`Use 'bunx @earendil-works/pi-ai list' to see available providers`); + console.error(`Use 'bunx @prime-intellect/prime-agent-ai list' to see available providers`); process.exit(1); } @@ -123,7 +123,7 @@ Examples: } console.error(`Unknown command: ${command}`); - console.error(`Use 'bunx @earendil-works/pi-ai --help' for usage`); + console.error(`Use 'bunx @prime-intellect/prime-agent-ai --help' for usage`); process.exit(1); } diff --git a/packages/coding-agent/.changes/prime-intellect-package.md b/packages/coding-agent/.changes/prime-intellect-package.md new file mode 100644 index 0000000000..06370a2b00 --- /dev/null +++ b/packages/coding-agent/.changes/prime-intellect-package.md @@ -0,0 +1 @@ +- Changed the public CLI package to `@prime-intellect/prime-agent` and made Bun global installation the preferred install path. diff --git a/packages/coding-agent/README.md b/packages/coding-agent/README.md index 21af060ac1..f34ec95a17 100644 --- a/packages/coding-agent/README.md +++ b/packages/coding-agent/README.md @@ -13,7 +13,7 @@ RLM-native terminal coding and research harness.

-Prime Agent began as a hard fork of [pi-mono](https://github.com/badlogic/pi-mono), but it is now developed and distributed independently. This workspace retains inherited `@earendil-works/pi-*` source package identifiers, the `pi` package manifest key, and a source-package `pi` bin entry for internal compatibility. Public releases are compiled Bun binary archives installed by the scripts below; release packaging ships the application and command as `prime-agent`. Do not use the inherited npm package as the Prime Agent install path. +Prime Agent began as a hard fork of [pi-mono](https://github.com/badlogic/pi-mono), but it is now developed and distributed independently under the `@prime-intellect` npm scope. The public CLI package is `@prime-intellect/prime-agent`, and it installs the `prime-agent` command. ## Table of Contents @@ -43,13 +43,21 @@ Prime Agent began as a hard fork of [pi-mono](https://github.com/badlogic/pi-mon ## Quick Start ```bash -curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh +bun install -g @prime-intellect/prime-agent ``` +The global `prime-agent` command runs on Bun. The package's TypeScript SDK exports remain compatible with Node.js 22.8 and newer. + To install the beta built from the latest commit on `main`: ```bash -curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh -s -- beta +bun install -g @prime-intellect/prime-agent@beta +``` + +On macOS and Linux, the standalone release installer remains available as an alternative: + +```bash +curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh ``` Authenticate with an API key: diff --git a/packages/coding-agent/docs/compaction.md b/packages/coding-agent/docs/compaction.md index 11f2837cfe..7e520dc699 100644 --- a/packages/coding-agent/docs/compaction.md +++ b/packages/coding-agent/docs/compaction.md @@ -9,7 +9,7 @@ LLMs have limited context windows. When conversations grow too long, Prime Agent - [`session-manager.ts`](../src/core/session-manager.ts) - Entry types (`CompactionEntry`, `BranchSummaryEntry`) - [`extensions/types.ts`](../src/core/extensions/types.ts) - Extension event types -For TypeScript definitions in your project, inspect `node_modules/@earendil-works/pi-coding-agent/dist/`. +For TypeScript definitions in your project, inspect `node_modules/@prime-intellect/prime-agent/dist/`. ## Overview @@ -310,7 +310,7 @@ pi.on("session_before_compact", async (event, ctx) => { To generate a summary with your own model, convert messages to text using `serializeConversation`: ```typescript -import { convertToLlm, serializeConversation } from "@earendil-works/pi-coding-agent"; +import { convertToLlm, serializeConversation } from "@prime-intellect/prime-agent"; pi.on("session_before_compact", async (event, ctx) => { const { preparation } = event; diff --git a/packages/coding-agent/docs/custom-provider.md b/packages/coding-agent/docs/custom-provider.md index 979f7d685c..986e9c4bbd 100644 --- a/packages/coding-agent/docs/custom-provider.md +++ b/packages/coding-agent/docs/custom-provider.md @@ -30,7 +30,7 @@ See these complete provider examples: ## Quick Reference ```typescript -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { // Override baseUrl for existing provider @@ -96,7 +96,7 @@ To add a completely new provider, specify `models` along with the required confi If the model list comes from a remote endpoint, use an async extension factory: ```typescript -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default async function (pi: ExtensionAPI) { const response = await fetch("http://localhost:1234/v1/models"); @@ -252,7 +252,7 @@ pi.registerProvider("custom-api", { Add OAuth/SSO authentication that integrates with `/login`: ```typescript -import type { OAuthCredentials, OAuthLoginCallbacks } from "@earendil-works/pi-ai"; +import type { OAuthCredentials, OAuthLoginCallbacks } from "@prime-intellect/prime-agent-ai"; pi.registerProvider("corporate-ai", { baseUrl: "https://ai.corp.com/v1", @@ -365,7 +365,7 @@ import { type SimpleStreamOptions, calculateCost, createAssistantMessageEventStream, -} from "@earendil-works/pi-ai"; +} from "@prime-intellect/prime-agent-ai"; function streamMyProvider( model: Model, diff --git a/packages/coding-agent/docs/development.md b/packages/coding-agent/docs/development.md index 8a702daea8..7d1bf3aad3 100644 --- a/packages/coding-agent/docs/development.md +++ b/packages/coding-agent/docs/development.md @@ -22,7 +22,7 @@ The script can be called from any directory and preserves the caller's working d ## Product and Source Names -Prime Agent is the product, public CLI, release artifact, and repository name. The monorepo still retains inherited `@earendil-works/pi-*` npm workspace names, a source-package `pi` bin entry, the `pi` package manifest key, and some `PI_*` compatibility environment variables. These names are source and compatibility details, not a signal that contributors should install or develop against pi-mono. +Prime Agent is the product, public CLI, release artifact, and repository name. The monorepo publishes its workspaces under the `@prime-intellect` npm scope and retains the inherited `pi` package manifest key and some `PI_*` compatibility environment variables. Public releases are compiled Bun binary archives installed by the stable and beta installer scripts. `scripts/pack-prime-agent-release.mjs` assembles the platform archives and metadata. Do not document a package-manager install path for the public Prime Agent CLI. diff --git a/packages/coding-agent/docs/extensions.md b/packages/coding-agent/docs/extensions.md index a16b06bbb5..320ea9e703 100644 --- a/packages/coding-agent/docs/extensions.md +++ b/packages/coding-agent/docs/extensions.md @@ -57,7 +57,7 @@ See [examples/extensions/](../examples/extensions/) for working implementations. Create `~/.prime/agent/extensions/my-extension.ts`: ```typescript -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { Type } from "typebox"; export default function (pi: ExtensionAPI) { @@ -139,10 +139,10 @@ To share extensions via npm or git as Prime Agent packages, see [packages.md](pa | Package | Purpose | |---------|---------| -| `@earendil-works/pi-coding-agent` | Extension types (`ExtensionAPI`, `ExtensionContext`, events) | +| `@prime-intellect/prime-agent` | Extension types (`ExtensionAPI`, `ExtensionContext`, events) | | `typebox` | Schema definitions for tool parameters | -| `@earendil-works/pi-ai` | AI utilities (`StringEnum` for Google-compatible enums) | -| `@earendil-works/pi-tui` | TUI components for custom rendering | +| `@prime-intellect/prime-agent-ai` | AI utilities (`StringEnum` for Google-compatible enums) | +| `@prime-intellect/prime-agent-tui` | TUI components for custom rendering | npm dependencies work too. Add a `package.json` next to your extension (or in a parent directory), run `bun install`, and imports from `node_modules/` are resolved automatically. @@ -155,7 +155,7 @@ Node.js built-ins (`node:fs`, `node:path`, etc.) are also available. An extension exports a default factory function that receives `ExtensionAPI`. The factory can be synchronous or asynchronous: ```typescript -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { // Subscribe to events @@ -184,7 +184,7 @@ If the factory returns a `Promise`, Prime Agent awaits it before continuing star Use an async factory for one-time startup work such as fetching remote configuration or dynamically discovering available models. ```typescript -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default async function (pi: ExtensionAPI) { const response = await fetch("http://localhost:1234/v1/models"); @@ -722,7 +722,7 @@ Behavior guarantees: - Return values from `tool_call` only control blocking via `{ block: true, reason?: string }` ```typescript -import { isToolCallEventType } from "@earendil-works/pi-coding-agent"; +import { isToolCallEventType } from "@prime-intellect/prime-agent"; pi.on("tool_call", async (event, ctx) => { // event.toolName - "ipython", "bash", "edit", etc. @@ -758,7 +758,7 @@ export type MyToolInput = Static; Use `isToolCallEventType` with explicit type parameters: ```typescript -import { isToolCallEventType } from "@earendil-works/pi-coding-agent"; +import { isToolCallEventType } from "@prime-intellect/prime-agent"; import type { MyToolInput } from "my-extension"; pi.on("tool_call", (event) => { @@ -782,7 +782,7 @@ In parallel tool mode, `tool_result` and `tool_execution_end` may interleave in Use `ctx.signal` for nested async work inside the handler. This lets Esc cancel model calls, `fetch()`, and other abort-aware operations started by the extension. ```typescript -import { isBashToolResult } from "@earendil-works/pi-coding-agent"; +import { isBashToolResult } from "@prime-intellect/prime-agent"; pi.on("tool_result", async (event, ctx) => { // event.toolName, event.toolCallId, event.input @@ -810,7 +810,7 @@ pi.on("tool_result", async (event, ctx) => { Fired when user executes `!` or `!!` commands. **Can intercept.** ```typescript -import { createLocalBashOperations } from "@earendil-works/pi-coding-agent"; +import { createLocalBashOperations } from "@prime-intellect/prime-agent"; pi.on("user_bash", (event, ctx) => { // event.command - the bash command @@ -1121,7 +1121,7 @@ Options: To discover available sessions, use the static `SessionManager.list()` or `SessionManager.listAll()` methods: ```typescript -import { SessionManager } from "@earendil-works/pi-coding-agent"; +import { SessionManager } from "@prime-intellect/prime-agent"; pi.registerCommand("switch", { description: "Switch to another session", @@ -1215,7 +1215,7 @@ Tools run with `ExtensionContext`, so they cannot call `ctx.reload()` directly. Example tool the LLM can call to trigger reload: ```typescript -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { Type } from "typebox"; export default function (pi: ExtensionAPI) { @@ -1265,7 +1265,7 @@ See [dynamic-tools.ts](../examples/extensions/dynamic-tools.ts) for a full examp ```typescript import { Type } from "typebox"; -import { StringEnum } from "@earendil-works/pi-ai"; +import { StringEnum } from "@prime-intellect/prime-agent-ai"; pi.registerTool({ name: "my_tool", @@ -1423,7 +1423,7 @@ pi.registerCommand("stats", { Optional: add argument auto-completion for `/command ...`: ```typescript -import type { AutocompleteItem } from "@earendil-works/pi-tui"; +import type { AutocompleteItem } from "@prime-intellect/prime-agent-tui"; pi.registerCommand("deploy", { description: "Deploy to an environment", @@ -1713,7 +1713,7 @@ Pass the real target file path to `withFileMutationQueue()`, not the raw user ar Queue the entire mutation window on that target path. That includes read-modify-write logic, not just the final write. ```typescript -import { withFileMutationQueue } from "@earendil-works/pi-coding-agent"; +import { withFileMutationQueue } from "@prime-intellect/prime-agent"; import { mkdir, readFile, writeFile } from "node:fs/promises"; import { dirname, resolve } from "node:path"; @@ -1738,8 +1738,8 @@ async execute(_toolCallId, params, _signal, _onUpdate, ctx) { ```typescript import { Type } from "typebox"; -import { StringEnum } from "@earendil-works/pi-ai"; -import { Text } from "@earendil-works/pi-tui"; +import { StringEnum } from "@prime-intellect/prime-agent-ai"; +import { Text } from "@prime-intellect/prime-agent-tui"; pi.registerTool({ name: "my_tool", @@ -1807,7 +1807,7 @@ async execute(toolCallId, params) { } ``` -**Important:** Use `StringEnum` from `@earendil-works/pi-ai` for string enums. `Type.Union`/`Type.Literal` doesn't work with Google's API. +**Important:** Use `StringEnum` from `@prime-intellect/prime-agent-ai` for string enums. `Type.Union`/`Type.Literal` doesn't work with Google's API. **Argument preparation:** `prepareArguments(args)` is optional. If defined, it runs before schema validation and before `execute()`. Use it to mimic an older accepted input shape when Prime Agent resumes an older session whose stored tool call arguments no longer match the current schema. Return the object you want validated against `parameters`. Keep the public schema strict. Do not add deprecated compatibility fields to `parameters` just to keep old resumed sessions working. @@ -1889,7 +1889,7 @@ Built-in tool implementations: The `bash` and `edit` tools support pluggable operations for delegating to remote systems (SSH, containers, etc.): ```typescript -import { createBashTool, type BashOperations } from "@earendil-works/pi-coding-agent"; +import { createBashTool, type BashOperations } from "@prime-intellect/prime-agent"; // Create tool with custom operations const remoteBash = createBashTool(cwd, { @@ -1917,7 +1917,7 @@ For `user_bash`, extensions can reuse Prime Agent's local shell backend via `cre The bash tool also supports a spawn hook to adjust the command, cwd, or env before execution: ```typescript -import { createBashTool } from "@earendil-works/pi-coding-agent"; +import { createBashTool } from "@prime-intellect/prime-agent"; const bashTool = createBashTool(cwd, { spawnHook: ({ command, cwd, env }) => ({ @@ -1947,7 +1947,7 @@ import { formatSize, // Human-readable size (e.g., "50KB", "1.5MB") DEFAULT_MAX_BYTES, // 50KB DEFAULT_MAX_LINES, // 2000 -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; async execute(toolCallId, params, signal, onUpdate, ctx) { const output = await runCommand(); @@ -2038,7 +2038,7 @@ Use `context.state` for cross-slot shared state. Keep slot-local caches on the r Renders the tool call or header: ```typescript -import { Text } from "@earendil-works/pi-tui"; +import { Text } from "@prime-intellect/prime-agent-tui"; renderCall(args, theme, context) { const text = (context.lastComponent as Text | undefined) ?? new Text("", 0, 0); @@ -2083,7 +2083,7 @@ If a slot intentionally has no visible content, return an empty `Component` such Use `keyHint()` to display keybinding hints that respect the active keybinding configuration: ```typescript -import { keyHint } from "@earendil-works/pi-coding-agent"; +import { keyHint } from "@prime-intellect/prime-agent"; renderResult(result, { expanded }, theme, context) { let text = theme.fg("success", "✓ Done"); @@ -2356,7 +2356,7 @@ See [github-issue-autocomplete.ts](../examples/extensions/github-issue-autocompl For complex UI, use `ctx.ui.custom()`. This temporarily replaces the editor with your component until `done()` is called: ```typescript -import { Text, Component } from "@earendil-works/pi-tui"; +import { Text, Component } from "@prime-intellect/prime-agent-tui"; const result = await ctx.ui.custom((tui, theme, keybindings, done) => { const text = new Text("Press Enter to confirm, Escape to cancel", 1, 1); @@ -2414,8 +2414,8 @@ See [tui.md](tui.md) for the full `OverlayOptions` API and [overlay-qa-tests.ts] Replace the main input editor with a custom implementation (vim mode, emacs mode, etc.): ```typescript -import { CustomEditor, type ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { matchesKey } from "@earendil-works/pi-tui"; +import { CustomEditor, type ExtensionAPI } from "@prime-intellect/prime-agent"; +import { matchesKey } from "@prime-intellect/prime-agent-tui"; class VimEditor extends CustomEditor { private mode: "normal" | "insert" = "insert"; @@ -2465,7 +2465,7 @@ See [tui.md](tui.md) Pattern 7 for a complete example with mode indicator. Register a custom renderer for messages with your `customType`: ```typescript -import { Text } from "@earendil-works/pi-tui"; +import { Text } from "@prime-intellect/prime-agent-tui"; pi.registerMessageRenderer("my-extension", (message, options, theme) => { const { expanded } = options; @@ -2514,7 +2514,7 @@ theme.strikethrough(text) For syntax highlighting in custom tool renderers: ```typescript -import { highlightCode, getLanguageFromPath } from "@earendil-works/pi-coding-agent"; +import { highlightCode, getLanguageFromPath } from "@prime-intellect/prime-agent"; // Highlight code with explicit language const highlighted = highlightCode("const x = 1;", "typescript", theme); diff --git a/packages/coding-agent/docs/index.md b/packages/coding-agent/docs/index.md index 96fb32160e..e776d8bd7b 100644 --- a/packages/coding-agent/docs/index.md +++ b/packages/coding-agent/docs/index.md @@ -4,10 +4,10 @@ Prime Agent is an RLM-native coding and research harness built around a persiste ## Quick Start -Install the latest stable release on Linux or macOS: +Install the latest stable release with Bun: ```bash -curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh +bun install -g @prime-intellect/prime-agent ``` Then run it in a project directory: @@ -19,7 +19,7 @@ prime-agent Authenticate with `/login` for subscription or stored API-key providers, or set an environment variable such as `ANTHROPIC_API_KEY` before launch. See the [Quickstart](quickstart.md) for the complete first-run flow. -Public releases are currently installed from versioned release artifacts. The inherited npm workspace names in the source tree are implementation details, not the public install path. +The public package installs the `prime-agent` command. Versioned standalone release artifacts remain available as an alternative on macOS and Linux. ## Start Here diff --git a/packages/coding-agent/docs/packages.md b/packages/coding-agent/docs/packages.md index e5fc166b21..323cb75363 100644 --- a/packages/coding-agent/docs/packages.md +++ b/packages/coding-agent/docs/packages.md @@ -161,7 +161,7 @@ If no `pi` manifest is present, Prime Agent auto-discovers resources from these Third party runtime dependencies belong in `dependencies` in `package.json`. Dependencies that do not register extensions, skills, prompt templates, or themes also belong in `dependencies`. When Prime Agent installs a package from npm or git, it runs `npm install`, so those dependencies are installed automatically. -Prime Agent bundles core packages for extensions and skills. The workspace still publishes these inherited package names; if you import any of them, list them in `peerDependencies` with a `"*"` range and do not bundle them: `@earendil-works/pi-ai`, `@earendil-works/pi-agent-core`, `@earendil-works/pi-coding-agent`, `@earendil-works/pi-tui`, `typebox`. +Prime Agent bundles core packages for extensions and skills. The workspace publishes these packages under the `@prime-intellect` scope; if you import any of them, list them in `peerDependencies` with a `"*"` range and do not bundle them: `@prime-intellect/prime-agent-ai`, `@prime-intellect/prime-agent-core`, `@prime-intellect/prime-agent`, `@prime-intellect/prime-agent-tui`, `typebox`. Other resource packages must be bundled in your tarball. Add them to `dependencies` and `bundledDependencies`, then reference their resources through `node_modules/` paths. Prime Agent loads packages with separate module roots, so separate installs do not collide or share modules. diff --git a/packages/coding-agent/docs/quickstart.md b/packages/coding-agent/docs/quickstart.md index b1e614f654..144a5ac475 100644 --- a/packages/coding-agent/docs/quickstart.md +++ b/packages/coding-agent/docs/quickstart.md @@ -4,19 +4,23 @@ This page gets you from install to a useful first Prime Agent session. ## Install -Install the latest stable release on Linux or macOS: +Install the latest stable release with Bun: ```bash -curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh +bun install -g @prime-intellect/prime-agent ``` To try the latest beta built from `main`: ```bash -curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh -s -- beta +bun install -g @prime-intellect/prime-agent@beta ``` -Both commands fetch versioned Prime Agent release artifacts and install the `prime-agent` command. The inherited npm workspace identifiers in the source tree are not the public install path. +Both commands install the `prime-agent` command. On macOS and Linux, the standalone release installer remains available as an alternative: + +```bash +curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh +``` Then start Prime Agent in the project directory you want it to work on: diff --git a/packages/coding-agent/docs/rpc.md b/packages/coding-agent/docs/rpc.md index 51ae0bd7b7..ae56c8147a 100644 --- a/packages/coding-agent/docs/rpc.md +++ b/packages/coding-agent/docs/rpc.md @@ -2,7 +2,7 @@ RPC mode enables headless operation of the coding agent via a JSON protocol over stdin/stdout. This is useful for embedding the agent in other applications, IDEs, or custom UIs. -**Note for Node.js/TypeScript users**: If you're building a Node.js application, consider using `AgentSession` directly from `@earendil-works/pi-coding-agent` instead of spawning a subprocess. See [`src/core/agent-session.ts`](../src/core/agent-session.ts) for the API. For a subprocess-based TypeScript client, see [`src/modes/rpc/rpc-client.ts`](../src/modes/rpc/rpc-client.ts). +**Note for Node.js/TypeScript users**: If you're building a Node.js application, consider using `AgentSession` directly from `@prime-intellect/prime-agent` instead of spawning a subprocess. See [`src/core/agent-session.ts`](../src/core/agent-session.ts) for the API. For a subprocess-based TypeScript client, see [`src/modes/rpc/rpc-client.ts`](../src/modes/rpc/rpc-client.ts). ## Starting RPC Mode diff --git a/packages/coding-agent/docs/sdk.md b/packages/coding-agent/docs/sdk.md index e50f199584..296dddd26a 100644 --- a/packages/coding-agent/docs/sdk.md +++ b/packages/coding-agent/docs/sdk.md @@ -16,7 +16,7 @@ See [examples/sdk/](../examples/sdk/) for working examples from minimal to full ## Quick Start ```typescript -import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@earendil-works/pi-coding-agent"; +import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@prime-intellect/prime-agent"; // Set up credential storage and model registry const authStorage = AuthStorage.create(); @@ -40,7 +40,7 @@ await session.prompt("What files are in the current directory?"); ## Installation ```bash -bun add @earendil-works/pi-coding-agent +bun add @prime-intellect/prime-agent ``` The SDK is included in the main package. No separate installation needed. @@ -54,7 +54,7 @@ The main factory function for a single `AgentSession`. `createAgentSession()` uses a `ResourceLoader` to supply extensions, skills, prompt templates, themes, and context files. If you do not provide one, it uses `DefaultResourceLoader` with standard discovery. ```typescript -import { createAgentSession } from "@earendil-works/pi-coding-agent"; +import { createAgentSession } from "@prime-intellect/prime-agent"; // Minimal: defaults with DefaultResourceLoader const { session } = await createAgentSession(); @@ -132,7 +132,7 @@ import { createAgentSessionServices, getAgentDir, SessionManager, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => { const services = await createAgentSessionServices({ cwd }); @@ -239,7 +239,7 @@ Both `steer()` and `followUp()` expand file-based prompt templates but error on ### Agent and AgentState -The `Agent` class (from `@earendil-works/pi-agent-core`) handles the core LLM interaction. Access it via `session.agent`. +The `Agent` class (from `@prime-intellect/prime-agent-core`) handles the core LLM interaction. Access it via `session.agent`. ```typescript // Access current state @@ -368,8 +368,8 @@ When you pass a custom `ResourceLoader`, `cwd` and `agentDir` no longer control ### Model ```typescript -import { getModel } from "@earendil-works/pi-ai"; -import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent"; +import { getModel } from "@prime-intellect/prime-agent-ai"; +import { AuthStorage, ModelRegistry } from "@prime-intellect/prime-agent"; const authStorage = AuthStorage.create(); const modelRegistry = ModelRegistry.create(authStorage); @@ -416,7 +416,7 @@ API key resolution priority (handled by AuthStorage): 4. Fallback resolver (for custom provider keys from `models.json`) ```typescript -import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent"; +import { AuthStorage, ModelRegistry } from "@prime-intellect/prime-agent"; // Default: uses ~/.prime/agent/auth.json and ~/.prime/agent/models.json const authStorage = AuthStorage.create(); @@ -452,7 +452,7 @@ const simpleRegistry = ModelRegistry.inMemory(authStorage); Use a `ResourceLoader` to override the system prompt: ```typescript -import { createAgentSession, DefaultResourceLoader } from "@earendil-works/pi-coding-agent"; +import { createAgentSession, DefaultResourceLoader } from "@prime-intellect/prime-agent"; const loader = new DefaultResourceLoader({ systemPromptOverride: () => "You are a helpful assistant.", @@ -487,7 +487,7 @@ import { createIpythonToolDefinition, createBashToolDefinition, createEditToolDefinition, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; const cwd = "/path/to/project"; @@ -514,7 +514,7 @@ const { session } = await createAgentSession({ ```typescript import { Type } from "typebox"; -import { createAgentSession, defineTool } from "@earendil-works/pi-coding-agent"; +import { createAgentSession, defineTool } from "@prime-intellect/prime-agent"; // Inline custom tool const myTool = defineTool({ @@ -547,7 +547,7 @@ Custom tools passed via `customTools` are combined with extension-registered too Extensions are loaded by the `ResourceLoader`. `DefaultResourceLoader` discovers extensions from `~/.prime/agent/extensions/`, `.prime/agent/extensions/`, and `settings.json` extension sources. ```typescript -import { createAgentSession, DefaultResourceLoader } from "@earendil-works/pi-coding-agent"; +import { createAgentSession, DefaultResourceLoader } from "@prime-intellect/prime-agent"; const loader = new DefaultResourceLoader({ additionalExtensionPaths: ["/path/to/my-extension.ts"], @@ -569,7 +569,7 @@ Extensions can register tools, subscribe to events, add commands, and more. See **Event Bus:** Extensions can communicate via `pi.events`. Pass a shared `eventBus` to `DefaultResourceLoader` if you need to emit or listen from outside: ```typescript -import { createEventBus, DefaultResourceLoader } from "@earendil-works/pi-coding-agent"; +import { createEventBus, DefaultResourceLoader } from "@prime-intellect/prime-agent"; const eventBus = createEventBus(); const loader = new DefaultResourceLoader({ @@ -589,7 +589,7 @@ import { createAgentSession, DefaultResourceLoader, type Skill, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; const customSkill: Skill = { name: "my-skill", @@ -615,7 +615,7 @@ const { session } = await createAgentSession({ resourceLoader: loader }); ### Context Files ```typescript -import { createAgentSession, DefaultResourceLoader } from "@earendil-works/pi-coding-agent"; +import { createAgentSession, DefaultResourceLoader } from "@prime-intellect/prime-agent"; const loader = new DefaultResourceLoader({ agentsFilesOverride: (current) => ({ @@ -639,7 +639,7 @@ import { createAgentSession, DefaultResourceLoader, type PromptTemplate, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; const customCommand: PromptTemplate = { name: "deploy", @@ -674,7 +674,7 @@ import { createAgentSessionServices, getAgentDir, SessionManager, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; // In-memory (no persistence) const { session } = await createAgentSession({ @@ -768,7 +768,7 @@ sm.createBranchedSession(leafId); // Extract path to new file ### Settings Management ```typescript -import { createAgentSession, SettingsManager, SessionManager } from "@earendil-works/pi-coding-agent"; +import { createAgentSession, SettingsManager, SessionManager } from "@prime-intellect/prime-agent"; // Default: loads from files (global + project merged) const { session } = await createAgentSession({ @@ -824,7 +824,7 @@ Use `DefaultResourceLoader` to discover extensions, skills, prompts, themes, and import { DefaultResourceLoader, getAgentDir, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; const loader = new DefaultResourceLoader({ cwd, @@ -865,7 +865,7 @@ interface LoadExtensionsResult { ## Complete Example ```typescript -import { getModel } from "@earendil-works/pi-ai"; +import { getModel } from "@prime-intellect/prime-agent-ai"; import { Type } from "typebox"; import { AuthStorage, @@ -875,7 +875,7 @@ import { ModelRegistry, SessionManager, SettingsManager, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; // Set up auth storage (custom location) const authStorage = AuthStorage.create("/custom/agent/auth.json"); @@ -960,7 +960,7 @@ import { getAgentDir, InteractiveMode, SessionManager, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => { const services = await createAgentSessionServices({ cwd }); @@ -1000,7 +1000,7 @@ import { getAgentDir, runPrintMode, SessionManager, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => { const services = await createAgentSessionServices({ cwd }); @@ -1037,7 +1037,7 @@ import { getAgentDir, runRpcMode, SessionManager, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => { const services = await createAgentSessionServices({ cwd }); diff --git a/packages/coding-agent/docs/session-format.md b/packages/coding-agent/docs/session-format.md index 7437e65acb..27593879a7 100644 --- a/packages/coding-agent/docs/session-format.md +++ b/packages/coding-agent/docs/session-format.md @@ -33,7 +33,7 @@ Existing sessions are automatically migrated to the current version (v3) when lo - [`packages/ai/src/types.ts`](../../ai/src/types.ts) - Base message types (`UserMessage`, `AssistantMessage`, `ToolResultMessage`) - [`packages/agent/src/types.ts`](../../agent/src/types.ts) - `AgentMessage` union type -For TypeScript definitions in your project, inspect `node_modules/@earendil-works/pi-coding-agent/dist/` and `node_modules/@earendil-works/pi-ai/dist/`. +For TypeScript definitions in your project, inspect `node_modules/@prime-intellect/prime-agent/dist/` and `node_modules/@prime-intellect/prime-agent-ai/dist/`. ## Message Types diff --git a/packages/coding-agent/docs/tui.md b/packages/coding-agent/docs/tui.md index 2d25174997..1d871107c8 100644 --- a/packages/coding-agent/docs/tui.md +++ b/packages/coding-agent/docs/tui.md @@ -33,7 +33,7 @@ The TUI appends a full SGR reset and OSC 8 reset at the end of each rendered lin Components that display a text cursor and need IME (Input Method Editor) support should implement the `Focusable` interface: ```typescript -import { CURSOR_MARKER, type Component, type Focusable } from "@earendil-works/pi-tui"; +import { CURSOR_MARKER, type Component, type Focusable } from "@prime-intellect/prime-agent-tui"; class MyInput implements Component, Focusable { focused: boolean = false; // Set by TUI when focus changes @@ -59,7 +59,7 @@ This enables IME candidate windows to appear at the correct position for CJK inp When a container component (dialog, selector, etc.) contains an `Input` or `Editor` child, the container must implement `Focusable` and propagate the focus state to the child. Otherwise, the hardware cursor won't be positioned correctly for IME input. ```typescript -import { Container, type Focusable, Input } from "@earendil-works/pi-tui"; +import { Container, type Focusable, Input } from "@prime-intellect/prime-agent-tui"; class SearchDialog extends Container implements Focusable { private searchInput: Input; @@ -179,10 +179,10 @@ See [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts) for compre ## Built-in Components -Import from `@earendil-works/pi-tui`: +Import from `@prime-intellect/prime-agent-tui`: ```typescript -import { Text, Box, Container, Spacer, Markdown } from "@earendil-works/pi-tui"; +import { Text, Box, Container, Spacer, Markdown } from "@prime-intellect/prime-agent-tui"; ``` ### Text @@ -264,7 +264,7 @@ const image = new Image( Use `matchesKey()` for key detection: ```typescript -import { matchesKey, Key } from "@earendil-works/pi-tui"; +import { matchesKey, Key } from "@prime-intellect/prime-agent-tui"; handleInput(data: string) { if (matchesKey(data, Key.up)) { @@ -290,7 +290,7 @@ handleInput(data: string) { **Critical:** Each line from `render()` must not exceed the `width` parameter. ```typescript -import { visibleWidth, truncateToWidth } from "@earendil-works/pi-tui"; +import { visibleWidth, truncateToWidth } from "@prime-intellect/prime-agent-tui"; render(width: number): string[] { // Truncate long lines @@ -311,7 +311,7 @@ Example: Interactive selector import { matchesKey, Key, truncateToWidth, visibleWidth -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; class MySelector { private items: string[]; @@ -425,8 +425,8 @@ renderResult(result, options, theme, context) { **For Markdown**, use `getMarkdownTheme()`: ```typescript -import { getMarkdownTheme } from "@earendil-works/pi-coding-agent"; -import { Markdown } from "@earendil-works/pi-tui"; +import { getMarkdownTheme } from "@prime-intellect/prime-agent"; +import { Markdown } from "@prime-intellect/prime-agent-tui"; renderResult(result, options, theme, context) { const mdTheme = getMarkdownTheme(); @@ -587,12 +587,12 @@ These patterns cover the most common UI needs in extensions. **Copy these patter ### Pattern 1: Selection Dialog (SelectList) -For letting users pick from a list of options. Use `SelectList` from `@earendil-works/pi-tui` with `DynamicBorder` for framing. +For letting users pick from a list of options. Use `SelectList` from `@prime-intellect/prime-agent-tui` with `DynamicBorder` for framing. ```typescript -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { DynamicBorder } from "@earendil-works/pi-coding-agent"; -import { Container, type SelectItem, SelectList, Text } from "@earendil-works/pi-tui"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { DynamicBorder } from "@prime-intellect/prime-agent"; +import { Container, type SelectItem, SelectList, Text } from "@prime-intellect/prime-agent-tui"; pi.registerCommand("pick", { handler: async (_args, ctx) => { @@ -650,7 +650,7 @@ pi.registerCommand("pick", { For operations that take time and should be cancellable. `BorderedLoader` shows a spinner and handles escape to cancel. ```typescript -import { BorderedLoader } from "@earendil-works/pi-coding-agent"; +import { BorderedLoader } from "@prime-intellect/prime-agent"; pi.registerCommand("fetch", { handler: async (_args, ctx) => { @@ -679,11 +679,11 @@ pi.registerCommand("fetch", { ### Pattern 3: Settings/Toggles (SettingsList) -For toggling multiple settings. Use `SettingsList` from `@earendil-works/pi-tui` with `getSettingsListTheme()`. +For toggling multiple settings. Use `SettingsList` from `@prime-intellect/prime-agent-tui` with `getSettingsListTheme()`. ```typescript -import { getSettingsListTheme } from "@earendil-works/pi-coding-agent"; -import { Container, type SettingItem, SettingsList, Text } from "@earendil-works/pi-tui"; +import { getSettingsListTheme } from "@prime-intellect/prime-agent"; +import { Container, type SettingItem, SettingsList, Text } from "@prime-intellect/prime-agent-tui"; pi.registerCommand("settings", { handler: async (_args, ctx) => { @@ -822,8 +822,8 @@ Token stats available via `ctx.sessionManager.getBranch()` and `ctx.model`. Replace the main input editor with a custom implementation. Useful for modal editing (vim), different keybindings (emacs), or specialized input handling. ```typescript -import { CustomEditor, type ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { matchesKey, truncateToWidth } from "@earendil-works/pi-tui"; +import { CustomEditor, type ExtensionAPI } from "@prime-intellect/prime-agent"; +import { matchesKey, truncateToWidth } from "@prime-intellect/prime-agent-tui"; type Mode = "normal" | "insert"; diff --git a/packages/coding-agent/examples/extensions/README.md b/packages/coding-agent/examples/extensions/README.md index 3caef7deec..a87b5367bf 100644 --- a/packages/coding-agent/examples/extensions/README.md +++ b/packages/coding-agent/examples/extensions/README.md @@ -123,7 +123,7 @@ cp permission-gate.ts ~/.prime/agent/extensions/ | Extension | Description | |-----------|-------------| | `custom-provider-anthropic/` | Custom Anthropic provider with OAuth support and custom streaming implementation | -| `custom-provider-gitlab-duo/` | GitLab Duo provider using the inherited `@earendil-works/pi-ai` streaming API through a proxy | +| `custom-provider-gitlab-duo/` | GitLab Duo provider using the inherited `@prime-intellect/prime-agent-ai` streaming API through a proxy | ### External Dependencies @@ -137,7 +137,7 @@ cp permission-gate.ts ~/.prime/agent/extensions/ See [docs/extensions.md](../../docs/extensions.md) for full documentation. ```typescript -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { Type } from "typebox"; export default function (pi: ExtensionAPI) { @@ -179,7 +179,7 @@ export default function (pi: ExtensionAPI) { **Use StringEnum for string parameters** (required for Google API compatibility): ```typescript -import { StringEnum } from "@earendil-works/pi-ai"; +import { StringEnum } from "@prime-intellect/prime-agent-ai"; // Good action: StringEnum(["list", "add"] as const) diff --git a/packages/coding-agent/examples/extensions/auto-commit-on-exit.ts b/packages/coding-agent/examples/extensions/auto-commit-on-exit.ts index 39447204ff..46b652f254 100644 --- a/packages/coding-agent/examples/extensions/auto-commit-on-exit.ts +++ b/packages/coding-agent/examples/extensions/auto-commit-on-exit.ts @@ -5,7 +5,7 @@ * Uses the last assistant message to generate a commit message. */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { pi.on("session_shutdown", async (_event, ctx) => { diff --git a/packages/coding-agent/examples/extensions/bash-spawn-hook.ts b/packages/coding-agent/examples/extensions/bash-spawn-hook.ts index e4a1d02280..500488e46a 100644 --- a/packages/coding-agent/examples/extensions/bash-spawn-hook.ts +++ b/packages/coding-agent/examples/extensions/bash-spawn-hook.ts @@ -7,8 +7,8 @@ * pi -e ./bash-spawn-hook.ts */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { createBashTool } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { createBashTool } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { const cwd = process.cwd(); diff --git a/packages/coding-agent/examples/extensions/bookmark.ts b/packages/coding-agent/examples/extensions/bookmark.ts index 302d133d93..925694c906 100644 --- a/packages/coding-agent/examples/extensions/bookmark.ts +++ b/packages/coding-agent/examples/extensions/bookmark.ts @@ -7,7 +7,7 @@ * Usage: /bookmark [label] - bookmark the last assistant message */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { pi.registerCommand("bookmark", { diff --git a/packages/coding-agent/examples/extensions/border-status-editor.ts b/packages/coding-agent/examples/extensions/border-status-editor.ts index dce9e59596..b18b362afd 100644 --- a/packages/coding-agent/examples/extensions/border-status-editor.ts +++ b/packages/coding-agent/examples/extensions/border-status-editor.ts @@ -3,9 +3,9 @@ import { type ExtensionAPI, type ExtensionContext, type KeybindingsManager, -} from "@earendil-works/pi-coding-agent"; -import type { Component, EditorTheme, TUI } from "@earendil-works/pi-tui"; -import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent"; +import type { Component, EditorTheme, TUI } from "@prime-intellect/prime-agent-tui"; +import { truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; function fitBorder( left: string, diff --git a/packages/coding-agent/examples/extensions/built-in-tool-renderer.ts b/packages/coding-agent/examples/extensions/built-in-tool-renderer.ts index 8da34ab8b4..c58cee7fbe 100644 --- a/packages/coding-agent/examples/extensions/built-in-tool-renderer.ts +++ b/packages/coding-agent/examples/extensions/built-in-tool-renderer.ts @@ -25,9 +25,9 @@ * pi -e ./built-in-tool-renderer.ts */ -import type { BashToolDetails, EditToolDetails, ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { createBashTool, createEditTool } from "@earendil-works/pi-coding-agent"; -import { Text } from "@earendil-works/pi-tui"; +import type { BashToolDetails, EditToolDetails, ExtensionAPI } from "@prime-intellect/prime-agent"; +import { createBashTool, createEditTool } from "@prime-intellect/prime-agent"; +import { Text } from "@prime-intellect/prime-agent-tui"; export default function (pi: ExtensionAPI) { const cwd = process.cwd(); diff --git a/packages/coding-agent/examples/extensions/claude-rules.ts b/packages/coding-agent/examples/extensions/claude-rules.ts index d8d55f778d..c038cf4d17 100644 --- a/packages/coding-agent/examples/extensions/claude-rules.ts +++ b/packages/coding-agent/examples/extensions/claude-rules.ts @@ -19,7 +19,7 @@ import * as fs from "node:fs"; import * as path from "node:path"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; /** * Recursively find all .md files in a directory diff --git a/packages/coding-agent/examples/extensions/commands.ts b/packages/coding-agent/examples/extensions/commands.ts index 346c5f21ea..6101827e6b 100644 --- a/packages/coding-agent/examples/extensions/commands.ts +++ b/packages/coding-agent/examples/extensions/commands.ts @@ -10,7 +10,7 @@ * 3. Use /commands extensions to filter by source */ -import type { ExtensionAPI, SlashCommandInfo } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, SlashCommandInfo } from "@prime-intellect/prime-agent"; export default function commandsExtension(pi: ExtensionAPI) { pi.registerCommand("commands", { diff --git a/packages/coding-agent/examples/extensions/confirm-destructive.ts b/packages/coding-agent/examples/extensions/confirm-destructive.ts index 7d4201f758..1dd6728da2 100644 --- a/packages/coding-agent/examples/extensions/confirm-destructive.ts +++ b/packages/coding-agent/examples/extensions/confirm-destructive.ts @@ -5,7 +5,7 @@ * Demonstrates how to cancel session events using the before_* events. */ -import type { ExtensionAPI, SessionBeforeSwitchEvent, SessionMessageEntry } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, SessionBeforeSwitchEvent, SessionMessageEntry } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { pi.on("session_before_switch", async (event: SessionBeforeSwitchEvent, ctx) => { diff --git a/packages/coding-agent/examples/extensions/custom-compaction.ts b/packages/coding-agent/examples/extensions/custom-compaction.ts index 02c6ceb3a8..7030c9f4d9 100644 --- a/packages/coding-agent/examples/extensions/custom-compaction.ts +++ b/packages/coding-agent/examples/extensions/custom-compaction.ts @@ -13,9 +13,9 @@ * pi --extension examples/extensions/custom-compaction.ts */ -import { complete } from "@earendil-works/pi-ai"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { convertToLlm, serializeConversation } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { convertToLlm, serializeConversation } from "@prime-intellect/prime-agent"; +import { complete } from "@prime-intellect/prime-agent-ai"; export default function (pi: ExtensionAPI) { pi.on("session_before_compact", async (event, ctx) => { diff --git a/packages/coding-agent/examples/extensions/custom-footer.ts b/packages/coding-agent/examples/extensions/custom-footer.ts index 15e41e06f0..78dba899cb 100644 --- a/packages/coding-agent/examples/extensions/custom-footer.ts +++ b/packages/coding-agent/examples/extensions/custom-footer.ts @@ -8,9 +8,9 @@ * Token stats come from ctx.sessionManager/ctx.model (already accessible). */ -import type { AssistantMessage } from "@earendil-works/pi-ai"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import type { AssistantMessage } from "@prime-intellect/prime-agent-ai"; +import { truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; export default function (pi: ExtensionAPI) { let enabled = false; diff --git a/packages/coding-agent/examples/extensions/custom-header.ts b/packages/coding-agent/examples/extensions/custom-header.ts index e3aeb65616..a5d49aabc3 100644 --- a/packages/coding-agent/examples/extensions/custom-header.ts +++ b/packages/coding-agent/examples/extensions/custom-header.ts @@ -5,8 +5,8 @@ * (logo + keybinding hints) with a custom component showing the pi mascot. */ -import type { ExtensionAPI, Theme } from "@earendil-works/pi-coding-agent"; -import { VERSION } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, Theme } from "@prime-intellect/prime-agent"; +import { VERSION } from "@prime-intellect/prime-agent"; // --- PI MASCOT --- // Based on pi_mascot.ts - the pi agent character diff --git a/packages/coding-agent/examples/extensions/custom-provider-anthropic/index.ts b/packages/coding-agent/examples/extensions/custom-provider-anthropic/index.ts index 73318cd2b5..9eddd9040a 100644 --- a/packages/coding-agent/examples/extensions/custom-provider-anthropic/index.ts +++ b/packages/coding-agent/examples/extensions/custom-provider-anthropic/index.ts @@ -23,6 +23,7 @@ import Anthropic from "@anthropic-ai/sdk"; import type { ContentBlockParam, MessageCreateParamsStreaming } from "@anthropic-ai/sdk/resources/messages.js"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { type Api, type AssistantMessage, @@ -42,8 +43,7 @@ import { type Tool, type ToolCall, type ToolResultMessage, -} from "@earendil-works/pi-ai"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent-ai"; // ============================================================================= // OAuth Implementation (copied from packages/ai/src/utils/oauth/anthropic.ts) diff --git a/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/index.ts b/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/index.ts index 23d0a40a68..765baaea46 100644 --- a/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/index.ts +++ b/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/index.ts @@ -9,6 +9,7 @@ * # Then /login gitlab-duo, or set GITLAB_TOKEN=glpat-... */ +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { type Api, type AssistantMessageEventStream, @@ -20,8 +21,7 @@ import { type SimpleStreamOptions, streamSimpleAnthropic, streamSimpleOpenAIResponses, -} from "@earendil-works/pi-ai"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent-ai"; // ============================================================================= // Constants diff --git a/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts b/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts index 88f8a543e7..250a8291ee 100644 --- a/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts +++ b/packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts @@ -8,7 +8,7 @@ * bun test.ts claude-sonnet-4-5-20250929 --thinking */ -import { type Api, type Context, type Model, registerApiProvider, streamSimple } from "@earendil-works/pi-ai"; +import { type Api, type Context, type Model, registerApiProvider, streamSimple } from "@prime-intellect/prime-agent-ai"; import { readFileSync } from "fs"; import { getAgentDir } from "packages/coding-agent/src/config.js"; import { join } from "path"; diff --git a/packages/coding-agent/examples/extensions/custom-refinement.ts b/packages/coding-agent/examples/extensions/custom-refinement.ts index 5e83287e48..1a99122750 100644 --- a/packages/coding-agent/examples/extensions/custom-refinement.ts +++ b/packages/coding-agent/examples/extensions/custom-refinement.ts @@ -14,8 +14,8 @@ * prime-agent -e examples/extensions/custom-refinement.ts */ -import { complete } from "@earendil-works/pi-ai"; -import type { ExtensionAPI, RefinementProposal } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, RefinementProposal } from "@prime-intellect/prime-agent"; +import { complete } from "@prime-intellect/prime-agent-ai"; export default function (pi: ExtensionAPI) { pi.on("session_before_refine", async (event, ctx) => { diff --git a/packages/coding-agent/examples/extensions/dirty-repo-guard.ts b/packages/coding-agent/examples/extensions/dirty-repo-guard.ts index 86874afdac..db1519869b 100644 --- a/packages/coding-agent/examples/extensions/dirty-repo-guard.ts +++ b/packages/coding-agent/examples/extensions/dirty-repo-guard.ts @@ -5,7 +5,7 @@ * Useful to ensure work is committed before switching context. */ -import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, ExtensionContext } from "@prime-intellect/prime-agent"; async function checkDirtyRepo( pi: ExtensionAPI, diff --git a/packages/coding-agent/examples/extensions/doom-overlay/doom-component.ts b/packages/coding-agent/examples/extensions/doom-overlay/doom-component.ts index dbc795b914..8562568267 100644 --- a/packages/coding-agent/examples/extensions/doom-overlay/doom-component.ts +++ b/packages/coding-agent/examples/extensions/doom-overlay/doom-component.ts @@ -5,8 +5,8 @@ * Height is calculated from width to maintain DOOM's aspect ratio. */ -import type { Component } from "@earendil-works/pi-tui"; -import { isKeyRelease, type TUI } from "@earendil-works/pi-tui"; +import type { Component } from "@prime-intellect/prime-agent-tui"; +import { isKeyRelease, type TUI } from "@prime-intellect/prime-agent-tui"; import type { DoomEngine } from "./doom-engine.js"; import { DoomKeys, mapKeyToDoom } from "./doom-keys.js"; diff --git a/packages/coding-agent/examples/extensions/doom-overlay/doom-keys.ts b/packages/coding-agent/examples/extensions/doom-overlay/doom-keys.ts index cb71a44d81..9fb7fa6674 100644 --- a/packages/coding-agent/examples/extensions/doom-overlay/doom-keys.ts +++ b/packages/coding-agent/examples/extensions/doom-overlay/doom-keys.ts @@ -34,7 +34,7 @@ export const DoomKeys = { KEY_RALT: 0x80 + 0x38, } as const; -import { Key, matchesKey, parseKey } from "@earendil-works/pi-tui"; +import { Key, matchesKey, parseKey } from "@prime-intellect/prime-agent-tui"; /** * Map terminal key input to DOOM key codes diff --git a/packages/coding-agent/examples/extensions/doom-overlay/index.ts b/packages/coding-agent/examples/extensions/doom-overlay/index.ts index 434f0be1b4..53027cb145 100644 --- a/packages/coding-agent/examples/extensions/doom-overlay/index.ts +++ b/packages/coding-agent/examples/extensions/doom-overlay/index.ts @@ -9,7 +9,7 @@ * This demonstrates that overlays can handle real-time game rendering at 35 FPS. */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { DoomOverlayComponent } from "./doom-component.js"; import { DoomEngine } from "./doom-engine.js"; import { ensureWadFile } from "./wad-finder.js"; diff --git a/packages/coding-agent/examples/extensions/dynamic-resources/index.ts b/packages/coding-agent/examples/extensions/dynamic-resources/index.ts index 2f89f93e30..8c70eaac1b 100644 --- a/packages/coding-agent/examples/extensions/dynamic-resources/index.ts +++ b/packages/coding-agent/examples/extensions/dynamic-resources/index.ts @@ -1,6 +1,6 @@ import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; const baseDir = dirname(fileURLToPath(import.meta.url)); diff --git a/packages/coding-agent/examples/extensions/dynamic-tools.ts b/packages/coding-agent/examples/extensions/dynamic-tools.ts index 54ad13b42a..1d03bfeda5 100644 --- a/packages/coding-agent/examples/extensions/dynamic-tools.ts +++ b/packages/coding-agent/examples/extensions/dynamic-tools.ts @@ -7,7 +7,7 @@ * - Registers additional tools at runtime via /add-echo-tool */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { Type } from "typebox"; const ECHO_PARAMS = Type.Object({ diff --git a/packages/coding-agent/examples/extensions/event-bus.ts b/packages/coding-agent/examples/extensions/event-bus.ts index e63caa5132..0f11f1eba7 100644 --- a/packages/coding-agent/examples/extensions/event-bus.ts +++ b/packages/coding-agent/examples/extensions/event-bus.ts @@ -7,7 +7,7 @@ * Usage: /emit [event-name] [data] - emit an event on the bus */ -import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, ExtensionContext } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { // Store ctx for use in event handler diff --git a/packages/coding-agent/examples/extensions/file-trigger.ts b/packages/coding-agent/examples/extensions/file-trigger.ts index 8b9894c534..97adeca352 100644 --- a/packages/coding-agent/examples/extensions/file-trigger.ts +++ b/packages/coding-agent/examples/extensions/file-trigger.ts @@ -9,7 +9,7 @@ */ import * as fs from "node:fs"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { pi.on("session_start", async (_event, ctx) => { diff --git a/packages/coding-agent/examples/extensions/git-checkpoint.ts b/packages/coding-agent/examples/extensions/git-checkpoint.ts index 7ee5e6af88..bc91f671a7 100644 --- a/packages/coding-agent/examples/extensions/git-checkpoint.ts +++ b/packages/coding-agent/examples/extensions/git-checkpoint.ts @@ -5,7 +5,7 @@ * When forking, offers to restore code to that point in history. */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { const checkpoints = new Map(); diff --git a/packages/coding-agent/examples/extensions/github-issue-autocomplete.ts b/packages/coding-agent/examples/extensions/github-issue-autocomplete.ts index 0fd1b7be40..ec1634ef6a 100644 --- a/packages/coding-agent/examples/extensions/github-issue-autocomplete.ts +++ b/packages/coding-agent/examples/extensions/github-issue-autocomplete.ts @@ -1,13 +1,13 @@ // Requires GitHub CLI (`gh`) and a GitHub repository checkout. // Preloads the latest open issues once per session, then filters them locally for fast `#...` completion. -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { type AutocompleteItem, type AutocompleteProvider, type AutocompleteSuggestions, fuzzyFilter, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; type GitHubIssue = { number: number; diff --git a/packages/coding-agent/examples/extensions/handoff.ts b/packages/coding-agent/examples/extensions/handoff.ts index 10581dc6e9..03a24ac6a8 100644 --- a/packages/coding-agent/examples/extensions/handoff.ts +++ b/packages/coding-agent/examples/extensions/handoff.ts @@ -12,10 +12,10 @@ * The generated prompt appears as a draft in the editor for review/editing. */ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import { complete, type Message } from "@earendil-works/pi-ai"; -import type { ExtensionAPI, SessionEntry } from "@earendil-works/pi-coding-agent"; -import { BorderedLoader, convertToLlm, serializeConversation } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, SessionEntry } from "@prime-intellect/prime-agent"; +import { BorderedLoader, convertToLlm, serializeConversation } from "@prime-intellect/prime-agent"; +import { complete, type Message } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; const SYSTEM_PROMPT = `You are a context transfer assistant. Given a conversation history and the user's goal for a new thread, generate a focused prompt that: diff --git a/packages/coding-agent/examples/extensions/hello.ts b/packages/coding-agent/examples/extensions/hello.ts index 52da3910bd..708faba2a7 100644 --- a/packages/coding-agent/examples/extensions/hello.ts +++ b/packages/coding-agent/examples/extensions/hello.ts @@ -2,8 +2,8 @@ * Hello Tool - Minimal custom tool example */ -import { Type } from "@earendil-works/pi-ai"; -import { defineTool, type ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import { defineTool, type ExtensionAPI } from "@prime-intellect/prime-agent"; +import { Type } from "@prime-intellect/prime-agent-ai"; const helloTool = defineTool({ name: "hello", diff --git a/packages/coding-agent/examples/extensions/hidden-thinking-label.ts b/packages/coding-agent/examples/extensions/hidden-thinking-label.ts index bcdaab66aa..38e63a1f36 100644 --- a/packages/coding-agent/examples/extensions/hidden-thinking-label.ts +++ b/packages/coding-agent/examples/extensions/hidden-thinking-label.ts @@ -18,7 +18,7 @@ * /thinking-label Reset to the default label */ -import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, ExtensionContext } from "@prime-intellect/prime-agent"; const DEFAULT_LABEL = "Pondering..."; diff --git a/packages/coding-agent/examples/extensions/inline-bash.ts b/packages/coding-agent/examples/extensions/inline-bash.ts index 11849696d1..18a022b7cb 100644 --- a/packages/coding-agent/examples/extensions/inline-bash.ts +++ b/packages/coding-agent/examples/extensions/inline-bash.ts @@ -14,7 +14,7 @@ * * Note: Regular !command syntax (whole-line bash) is preserved and works as before. */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { const PATTERN = /!\{([^}]+)\}/g; diff --git a/packages/coding-agent/examples/extensions/input-transform.ts b/packages/coding-agent/examples/extensions/input-transform.ts index e47c1af5d7..c185d5587e 100644 --- a/packages/coding-agent/examples/extensions/input-transform.ts +++ b/packages/coding-agent/examples/extensions/input-transform.ts @@ -9,7 +9,7 @@ * ping → "pong" (instant, no LLM) * time → current time (instant, no LLM) */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { pi.on("input", async (event, ctx) => { diff --git a/packages/coding-agent/examples/extensions/interactive-shell.ts b/packages/coding-agent/examples/extensions/interactive-shell.ts index 99a7f9632f..d758b1f7ba 100644 --- a/packages/coding-agent/examples/extensions/interactive-shell.ts +++ b/packages/coding-agent/examples/extensions/interactive-shell.ts @@ -21,7 +21,7 @@ */ import { spawnSync } from "node:child_process"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; // Default interactive commands - editors, pagers, git ops, TUIs const DEFAULT_INTERACTIVE_COMMANDS = [ diff --git a/packages/coding-agent/examples/extensions/mac-system-theme.ts b/packages/coding-agent/examples/extensions/mac-system-theme.ts index c2095cf78f..11c22bf6e1 100644 --- a/packages/coding-agent/examples/extensions/mac-system-theme.ts +++ b/packages/coding-agent/examples/extensions/mac-system-theme.ts @@ -7,7 +7,7 @@ import { exec } from "node:child_process"; import { promisify } from "node:util"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; const execAsync = promisify(exec); diff --git a/packages/coding-agent/examples/extensions/message-renderer.ts b/packages/coding-agent/examples/extensions/message-renderer.ts index b5e0b08ace..39f4cccc78 100644 --- a/packages/coding-agent/examples/extensions/message-renderer.ts +++ b/packages/coding-agent/examples/extensions/message-renderer.ts @@ -7,8 +7,8 @@ * Usage: /status [message] - sends a status message with custom rendering */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { Box, Text } from "@earendil-works/pi-tui"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { Box, Text } from "@prime-intellect/prime-agent-tui"; export default function (pi: ExtensionAPI) { pi.registerMessageRenderer("status-update", (message, { expanded }, theme) => { diff --git a/packages/coding-agent/examples/extensions/minimal-mode.ts b/packages/coding-agent/examples/extensions/minimal-mode.ts index 1303876844..a5e21b440c 100644 --- a/packages/coding-agent/examples/extensions/minimal-mode.ts +++ b/packages/coding-agent/examples/extensions/minimal-mode.ts @@ -16,9 +16,9 @@ * Then use ctrl+o to toggle between minimal (collapsed) and full (expanded) views. */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { createBashTool, createEditTool } from "@earendil-works/pi-coding-agent"; -import { Text } from "@earendil-works/pi-tui"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { createBashTool, createEditTool } from "@prime-intellect/prime-agent"; +import { Text } from "@prime-intellect/prime-agent-tui"; import { homedir } from "os"; /** diff --git a/packages/coding-agent/examples/extensions/modal-editor.ts b/packages/coding-agent/examples/extensions/modal-editor.ts index 01959dd39a..85ca50d544 100644 --- a/packages/coding-agent/examples/extensions/modal-editor.ts +++ b/packages/coding-agent/examples/extensions/modal-editor.ts @@ -9,8 +9,8 @@ * - ctrl+c, ctrl+d, etc. work in both modes */ -import { CustomEditor, type ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import { CustomEditor, type ExtensionAPI } from "@prime-intellect/prime-agent"; +import { matchesKey, truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; // Normal mode key mappings: key -> escape sequence (or null for mode switch) const NORMAL_KEYS: Record = { diff --git a/packages/coding-agent/examples/extensions/model-status.ts b/packages/coding-agent/examples/extensions/model-status.ts index 27fa2f8b2e..23d2b3b151 100644 --- a/packages/coding-agent/examples/extensions/model-status.ts +++ b/packages/coding-agent/examples/extensions/model-status.ts @@ -7,7 +7,7 @@ * Usage: pi -e ./model-status.ts */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { pi.on("model_select", async (event, ctx) => { diff --git a/packages/coding-agent/examples/extensions/notify.ts b/packages/coding-agent/examples/extensions/notify.ts index f7b1f819ad..e10d6f0ae6 100644 --- a/packages/coding-agent/examples/extensions/notify.ts +++ b/packages/coding-agent/examples/extensions/notify.ts @@ -8,7 +8,7 @@ * - Windows toast: Windows Terminal (WSL) */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; function windowsToastScript(title: string, body: string): string { const type = "Windows.UI.Notifications"; diff --git a/packages/coding-agent/examples/extensions/overlay-qa-tests.ts b/packages/coding-agent/examples/extensions/overlay-qa-tests.ts index b13f43a9fe..bdb47838fd 100644 --- a/packages/coding-agent/examples/extensions/overlay-qa-tests.ts +++ b/packages/coding-agent/examples/extensions/overlay-qa-tests.ts @@ -19,9 +19,9 @@ * /overlay-streaming - Multiple input panels with simulated streaming (Tab to cycle focus) */ -import type { ExtensionAPI, ExtensionCommandContext, Theme } from "@earendil-works/pi-coding-agent"; -import type { Component, OverlayAnchor, OverlayHandle, OverlayOptions, TUI } from "@earendil-works/pi-tui"; -import { matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import type { ExtensionAPI, ExtensionCommandContext, Theme } from "@prime-intellect/prime-agent"; +import type { Component, OverlayAnchor, OverlayHandle, OverlayOptions, TUI } from "@prime-intellect/prime-agent-tui"; +import { matchesKey, truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; import { spawn } from "child_process"; // Global handle for toggle demo (in real code, use a more elegant pattern) diff --git a/packages/coding-agent/examples/extensions/overlay-test.ts b/packages/coding-agent/examples/extensions/overlay-test.ts index 02f8204b1a..eb829d1d46 100644 --- a/packages/coding-agent/examples/extensions/overlay-test.ts +++ b/packages/coding-agent/examples/extensions/overlay-test.ts @@ -8,8 +8,8 @@ * - Edge case tests (wide chars, styled text, emoji) */ -import type { ExtensionAPI, ExtensionCommandContext, Theme } from "@earendil-works/pi-coding-agent"; -import { CURSOR_MARKER, type Focusable, matchesKey, visibleWidth } from "@earendil-works/pi-tui"; +import type { ExtensionAPI, ExtensionCommandContext, Theme } from "@prime-intellect/prime-agent"; +import { CURSOR_MARKER, type Focusable, matchesKey, visibleWidth } from "@prime-intellect/prime-agent-tui"; export default function (pi: ExtensionAPI) { pi.registerCommand("overlay-test", { diff --git a/packages/coding-agent/examples/extensions/permission-gate.ts b/packages/coding-agent/examples/extensions/permission-gate.ts index ce29f7eb5c..18fc4f424a 100644 --- a/packages/coding-agent/examples/extensions/permission-gate.ts +++ b/packages/coding-agent/examples/extensions/permission-gate.ts @@ -5,7 +5,7 @@ * Patterns checked: rm -rf, sudo, chmod/chown 777 */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { const dangerousPatterns = [/\brm\s+(-rf?|--recursive)/i, /\bsudo\b/i, /\b(chmod|chown)\b.*777/i]; diff --git a/packages/coding-agent/examples/extensions/pirate.ts b/packages/coding-agent/examples/extensions/pirate.ts index abde601db6..4db9320874 100644 --- a/packages/coding-agent/examples/extensions/pirate.ts +++ b/packages/coding-agent/examples/extensions/pirate.ts @@ -10,7 +10,7 @@ * 3. When enabled, the agent will respond like a pirate */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function pirateExtension(pi: ExtensionAPI) { let pirateMode = false; diff --git a/packages/coding-agent/examples/extensions/plan-mode/index.ts b/packages/coding-agent/examples/extensions/plan-mode/index.ts index 20b3a6267d..1c52bc32ab 100644 --- a/packages/coding-agent/examples/extensions/plan-mode/index.ts +++ b/packages/coding-agent/examples/extensions/plan-mode/index.ts @@ -12,10 +12,10 @@ * - Progress tracking widget during execution */ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { AssistantMessage, TextContent } from "@earendil-works/pi-ai"; -import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; -import { Key } from "@earendil-works/pi-tui"; +import type { ExtensionAPI, ExtensionContext } from "@prime-intellect/prime-agent"; +import type { AssistantMessage, TextContent } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; +import { Key } from "@prime-intellect/prime-agent-tui"; import { extractTodoItems, isSafeCommand, markCompletedSteps, type TodoItem } from "./utils.js"; // Tools diff --git a/packages/coding-agent/examples/extensions/preset.ts b/packages/coding-agent/examples/extensions/preset.ts index 849f82d699..6651aa4345 100644 --- a/packages/coding-agent/examples/extensions/preset.ts +++ b/packages/coding-agent/examples/extensions/preset.ts @@ -40,10 +40,10 @@ import { existsSync, readFileSync } from "node:fs"; import { join } from "node:path"; -import type { Api, Model } from "@earendil-works/pi-ai"; -import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; -import { DynamicBorder, getAgentDir } from "@earendil-works/pi-coding-agent"; -import { Container, Key, type SelectItem, SelectList, Text } from "@earendil-works/pi-tui"; +import type { ExtensionAPI, ExtensionContext } from "@prime-intellect/prime-agent"; +import { DynamicBorder, getAgentDir } from "@prime-intellect/prime-agent"; +import type { Api, Model } from "@prime-intellect/prime-agent-ai"; +import { Container, Key, type SelectItem, SelectList, Text } from "@prime-intellect/prime-agent-tui"; // Preset configuration interface Preset { diff --git a/packages/coding-agent/examples/extensions/prompt-customizer.ts b/packages/coding-agent/examples/extensions/prompt-customizer.ts index 9c98088c78..fe53a6e7d0 100644 --- a/packages/coding-agent/examples/extensions/prompt-customizer.ts +++ b/packages/coding-agent/examples/extensions/prompt-customizer.ts @@ -12,7 +12,7 @@ * 2. Use the extension — it automatically adapts to your active tools and skills */ -import type { BuildSystemPromptOptions, ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { BuildSystemPromptOptions, ExtensionAPI } from "@prime-intellect/prime-agent"; /** * Adds tool-specific guidance that adapts to the active tool set. diff --git a/packages/coding-agent/examples/extensions/protected-paths.ts b/packages/coding-agent/examples/extensions/protected-paths.ts index 0242fdfd27..85a6a9d93e 100644 --- a/packages/coding-agent/examples/extensions/protected-paths.ts +++ b/packages/coding-agent/examples/extensions/protected-paths.ts @@ -5,7 +5,7 @@ * Useful for preventing accidental modifications to sensitive files. */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { const protectedPaths = [".env", ".git/", "node_modules/"]; diff --git a/packages/coding-agent/examples/extensions/provider-payload.ts b/packages/coding-agent/examples/extensions/provider-payload.ts index abf06e9365..81067d4107 100644 --- a/packages/coding-agent/examples/extensions/provider-payload.ts +++ b/packages/coding-agent/examples/extensions/provider-payload.ts @@ -1,6 +1,6 @@ import { appendFileSync } from "node:fs"; import { join } from "node:path"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { const logFile = join(process.cwd(), ".prime", "agent", "provider-payload.log"); diff --git a/packages/coding-agent/examples/extensions/qna.ts b/packages/coding-agent/examples/extensions/qna.ts index 2675b5d762..1d80dbd4c9 100644 --- a/packages/coding-agent/examples/extensions/qna.ts +++ b/packages/coding-agent/examples/extensions/qna.ts @@ -7,9 +7,9 @@ * 3. Loads the result into the editor for user to fill in answers */ -import { complete, type UserMessage } from "@earendil-works/pi-ai"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { BorderedLoader } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { BorderedLoader } from "@prime-intellect/prime-agent"; +import { complete, type UserMessage } from "@prime-intellect/prime-agent-ai"; const SYSTEM_PROMPT = `You are a question extractor. Given text from a conversation, extract any questions that need answering and format them for the user to fill in. diff --git a/packages/coding-agent/examples/extensions/question.ts b/packages/coding-agent/examples/extensions/question.ts index 7aba1d7098..192aab948e 100644 --- a/packages/coding-agent/examples/extensions/question.ts +++ b/packages/coding-agent/examples/extensions/question.ts @@ -4,8 +4,8 @@ * Escape in editor returns to options, Escape in options cancels */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { Editor, type EditorTheme, Key, matchesKey, Text, truncateToWidth } from "@earendil-works/pi-tui"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { Editor, type EditorTheme, Key, matchesKey, Text, truncateToWidth } from "@prime-intellect/prime-agent-tui"; import { Type } from "typebox"; interface OptionWithDesc { diff --git a/packages/coding-agent/examples/extensions/questionnaire.ts b/packages/coding-agent/examples/extensions/questionnaire.ts index 34fb666c15..252e669ff9 100644 --- a/packages/coding-agent/examples/extensions/questionnaire.ts +++ b/packages/coding-agent/examples/extensions/questionnaire.ts @@ -5,8 +5,8 @@ * Multiple questions: tab bar navigation between questions */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { Editor, type EditorTheme, Key, matchesKey, Text, truncateToWidth } from "@earendil-works/pi-tui"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { Editor, type EditorTheme, Key, matchesKey, Text, truncateToWidth } from "@prime-intellect/prime-agent-tui"; import { Type } from "typebox"; // Types diff --git a/packages/coding-agent/examples/extensions/rainbow-editor.ts b/packages/coding-agent/examples/extensions/rainbow-editor.ts index 20b7437c91..c54da3c67e 100644 --- a/packages/coding-agent/examples/extensions/rainbow-editor.ts +++ b/packages/coding-agent/examples/extensions/rainbow-editor.ts @@ -4,7 +4,7 @@ * Usage: pi --extension ./examples/extensions/rainbow-editor.ts */ -import { CustomEditor, type ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import { CustomEditor, type ExtensionAPI } from "@prime-intellect/prime-agent"; // Base colors (coral → yellow → green → teal → blue → purple → pink) const COLORS: [number, number, number][] = [ diff --git a/packages/coding-agent/examples/extensions/reload-runtime.ts b/packages/coding-agent/examples/extensions/reload-runtime.ts index be46410f22..69104e590d 100644 --- a/packages/coding-agent/examples/extensions/reload-runtime.ts +++ b/packages/coding-agent/examples/extensions/reload-runtime.ts @@ -5,7 +5,7 @@ * tool that queues a follow-up command to trigger reload. */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { Type } from "typebox"; export default function (pi: ExtensionAPI) { diff --git a/packages/coding-agent/examples/extensions/rpc-demo.ts b/packages/coding-agent/examples/extensions/rpc-demo.ts index 78789a13ee..96cfd42644 100644 --- a/packages/coding-agent/examples/extensions/rpc-demo.ts +++ b/packages/coding-agent/examples/extensions/rpc-demo.ts @@ -17,7 +17,7 @@ * - setEditorText() - via /rpc-prefill command */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { let turnCount = 0; diff --git a/packages/coding-agent/examples/extensions/sandbox/index.ts b/packages/coding-agent/examples/extensions/sandbox/index.ts index ebe6dede8a..3878d00a82 100644 --- a/packages/coding-agent/examples/extensions/sandbox/index.ts +++ b/packages/coding-agent/examples/extensions/sandbox/index.ts @@ -45,8 +45,8 @@ import { spawn } from "node:child_process"; import { existsSync, readFileSync } from "node:fs"; import { join } from "node:path"; import { SandboxManager, type SandboxRuntimeConfig } from "@anthropic-ai/sandbox-runtime"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { type BashOperations, createBashTool, getAgentDir } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { type BashOperations, createBashTool, getAgentDir } from "@prime-intellect/prime-agent"; interface SandboxConfig extends SandboxRuntimeConfig { enabled?: boolean; diff --git a/packages/coding-agent/examples/extensions/send-user-message.ts b/packages/coding-agent/examples/extensions/send-user-message.ts index cf4eb138c7..b9f654afd5 100644 --- a/packages/coding-agent/examples/extensions/send-user-message.ts +++ b/packages/coding-agent/examples/extensions/send-user-message.ts @@ -11,7 +11,7 @@ * /followup And then? - Sends while streaming with followUp delivery */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { // Simple command that sends a user message diff --git a/packages/coding-agent/examples/extensions/session-name.ts b/packages/coding-agent/examples/extensions/session-name.ts index 48203dea92..b6139b5978 100644 --- a/packages/coding-agent/examples/extensions/session-name.ts +++ b/packages/coding-agent/examples/extensions/session-name.ts @@ -7,7 +7,7 @@ * Usage: /session-name [name] - set or show session name */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { pi.registerCommand("session-name", { diff --git a/packages/coding-agent/examples/extensions/shutdown-command.ts b/packages/coding-agent/examples/extensions/shutdown-command.ts index 743f8807da..95e42174f3 100644 --- a/packages/coding-agent/examples/extensions/shutdown-command.ts +++ b/packages/coding-agent/examples/extensions/shutdown-command.ts @@ -5,7 +5,7 @@ * Demonstrates how extensions can use ctx.shutdown() to exit pi cleanly. */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { Type } from "typebox"; export default function (pi: ExtensionAPI) { diff --git a/packages/coding-agent/examples/extensions/snake.ts b/packages/coding-agent/examples/extensions/snake.ts index 29995b36cc..d6da06bcbd 100644 --- a/packages/coding-agent/examples/extensions/snake.ts +++ b/packages/coding-agent/examples/extensions/snake.ts @@ -2,8 +2,8 @@ * Snake game extension - play snake with /snake command */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { matchesKey, visibleWidth } from "@earendil-works/pi-tui"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { matchesKey, visibleWidth } from "@prime-intellect/prime-agent-tui"; const GAME_WIDTH = 40; const GAME_HEIGHT = 15; diff --git a/packages/coding-agent/examples/extensions/space-invaders.ts b/packages/coding-agent/examples/extensions/space-invaders.ts index c91071b880..ac3723669a 100644 --- a/packages/coding-agent/examples/extensions/space-invaders.ts +++ b/packages/coding-agent/examples/extensions/space-invaders.ts @@ -3,8 +3,8 @@ * Uses Kitty keyboard protocol for smooth movement (press/release detection) */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { isKeyRelease, Key, matchesKey, visibleWidth } from "@earendil-works/pi-tui"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { isKeyRelease, Key, matchesKey, visibleWidth } from "@prime-intellect/prime-agent-tui"; const GAME_WIDTH = 60; const GAME_HEIGHT = 24; diff --git a/packages/coding-agent/examples/extensions/ssh.ts b/packages/coding-agent/examples/extensions/ssh.ts index ddf83a0654..65a41b6ad9 100644 --- a/packages/coding-agent/examples/extensions/ssh.ts +++ b/packages/coding-agent/examples/extensions/ssh.ts @@ -14,13 +14,8 @@ */ import { spawn } from "node:child_process"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { - type BashOperations, - createBashTool, - createEditTool, - type EditOperations, -} from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; +import { type BashOperations, createBashTool, createEditTool, type EditOperations } from "@prime-intellect/prime-agent"; function sshExec(remote: string, command: string): Promise { return new Promise((resolve, reject) => { diff --git a/packages/coding-agent/examples/extensions/status-line.ts b/packages/coding-agent/examples/extensions/status-line.ts index 6c4a3a477c..172ffc9375 100644 --- a/packages/coding-agent/examples/extensions/status-line.ts +++ b/packages/coding-agent/examples/extensions/status-line.ts @@ -5,7 +5,7 @@ * Shows turn progress with themed colors. */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { let turnCount = 0; diff --git a/packages/coding-agent/examples/extensions/structured-output.ts b/packages/coding-agent/examples/extensions/structured-output.ts index 13331377fe..6e72f7f850 100644 --- a/packages/coding-agent/examples/extensions/structured-output.ts +++ b/packages/coding-agent/examples/extensions/structured-output.ts @@ -5,8 +5,8 @@ * without paying for an extra follow-up LLM turn. */ -import { defineTool, type ExtensionAPI } from "@earendil-works/pi-coding-agent"; -import { Text } from "@earendil-works/pi-tui"; +import { defineTool, type ExtensionAPI } from "@prime-intellect/prime-agent"; +import { Text } from "@prime-intellect/prime-agent-tui"; import { Type } from "typebox"; interface StructuredOutputDetails { diff --git a/packages/coding-agent/examples/extensions/subagent/agents.ts b/packages/coding-agent/examples/extensions/subagent/agents.ts index bfd88e2057..35117af155 100644 --- a/packages/coding-agent/examples/extensions/subagent/agents.ts +++ b/packages/coding-agent/examples/extensions/subagent/agents.ts @@ -4,7 +4,7 @@ import * as fs from "node:fs"; import * as path from "node:path"; -import { getAgentDir, parseFrontmatter } from "@earendil-works/pi-coding-agent"; +import { getAgentDir, parseFrontmatter } from "@prime-intellect/prime-agent"; export type AgentScope = "user" | "project" | "both"; diff --git a/packages/coding-agent/examples/extensions/subagent/index.ts b/packages/coding-agent/examples/extensions/subagent/index.ts index 2ccd606f76..84d3bd3fb8 100644 --- a/packages/coding-agent/examples/extensions/subagent/index.ts +++ b/packages/coding-agent/examples/extensions/subagent/index.ts @@ -16,11 +16,11 @@ import { spawn } from "node:child_process"; import * as fs from "node:fs"; import * as os from "node:os"; import * as path from "node:path"; -import type { AgentToolResult } from "@earendil-works/pi-agent-core"; -import type { Message } from "@earendil-works/pi-ai"; -import { StringEnum } from "@earendil-works/pi-ai"; -import { type ExtensionAPI, getMarkdownTheme, withFileMutationQueue } from "@earendil-works/pi-coding-agent"; -import { Container, Markdown, Spacer, Text } from "@earendil-works/pi-tui"; +import { type ExtensionAPI, getMarkdownTheme, withFileMutationQueue } from "@prime-intellect/prime-agent"; +import type { Message } from "@prime-intellect/prime-agent-ai"; +import { StringEnum } from "@prime-intellect/prime-agent-ai"; +import type { AgentToolResult } from "@prime-intellect/prime-agent-core"; +import { Container, Markdown, Spacer, Text } from "@prime-intellect/prime-agent-tui"; import { Type } from "typebox"; import { type AgentConfig, type AgentScope, discoverAgents } from "./agents.js"; diff --git a/packages/coding-agent/examples/extensions/summarize.ts b/packages/coding-agent/examples/extensions/summarize.ts index dd30c35046..295bb9120d 100644 --- a/packages/coding-agent/examples/extensions/summarize.ts +++ b/packages/coding-agent/examples/extensions/summarize.ts @@ -1,7 +1,7 @@ -import { complete, getModel } from "@earendil-works/pi-ai"; -import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent"; -import { DynamicBorder, getMarkdownTheme } from "@earendil-works/pi-coding-agent"; -import { Container, Markdown, matchesKey, Text } from "@earendil-works/pi-tui"; +import type { ExtensionAPI, ExtensionCommandContext } from "@prime-intellect/prime-agent"; +import { DynamicBorder, getMarkdownTheme } from "@prime-intellect/prime-agent"; +import { complete, getModel } from "@prime-intellect/prime-agent-ai"; +import { Container, Markdown, matchesKey, Text } from "@prime-intellect/prime-agent-tui"; type ContentBlock = { type?: string; diff --git a/packages/coding-agent/examples/extensions/system-prompt-header.ts b/packages/coding-agent/examples/extensions/system-prompt-header.ts index c6845b2bcc..e2b232c2bc 100644 --- a/packages/coding-agent/examples/extensions/system-prompt-header.ts +++ b/packages/coding-agent/examples/extensions/system-prompt-header.ts @@ -3,7 +3,7 @@ * * Demonstrates ctx.getSystemPrompt() for accessing the effective system prompt. */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { pi.on("agent_start", (_event, ctx) => { diff --git a/packages/coding-agent/examples/extensions/tic-tac-toe.ts b/packages/coding-agent/examples/extensions/tic-tac-toe.ts index 8cbfdeabbf..9e40a21c7d 100644 --- a/packages/coding-agent/examples/extensions/tic-tac-toe.ts +++ b/packages/coding-agent/examples/extensions/tic-tac-toe.ts @@ -17,9 +17,9 @@ * separate variables. Only the agent cursor is ever exposed to the agent. */ -import { StringEnum } from "@earendil-works/pi-ai"; -import type { ExtensionAPI, ExtensionContext, Theme, ToolExecutionMode } from "@earendil-works/pi-coding-agent"; -import { type Component, matchesKey, Text, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import type { ExtensionAPI, ExtensionContext, Theme, ToolExecutionMode } from "@prime-intellect/prime-agent"; +import { StringEnum } from "@prime-intellect/prime-agent-ai"; +import { type Component, matchesKey, Text, truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; import { Type } from "typebox"; // Thrown from the tool on illegal actions. The agent runtime surfaces thrown diff --git a/packages/coding-agent/examples/extensions/timed-confirm.ts b/packages/coding-agent/examples/extensions/timed-confirm.ts index 1ab86e55b2..35a08bdc10 100644 --- a/packages/coding-agent/examples/extensions/timed-confirm.ts +++ b/packages/coding-agent/examples/extensions/timed-confirm.ts @@ -7,7 +7,7 @@ * - /timed-signal - Shows confirm using AbortSignal (manual approach) */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { // Simple approach: use timeout option (recommended) diff --git a/packages/coding-agent/examples/extensions/titlebar-spinner.ts b/packages/coding-agent/examples/extensions/titlebar-spinner.ts index 51467acb6d..552b5701bf 100644 --- a/packages/coding-agent/examples/extensions/titlebar-spinner.ts +++ b/packages/coding-agent/examples/extensions/titlebar-spinner.ts @@ -9,7 +9,7 @@ */ import path from "node:path"; -import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, ExtensionContext } from "@prime-intellect/prime-agent"; const BRAILLE_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; diff --git a/packages/coding-agent/examples/extensions/todo.ts b/packages/coding-agent/examples/extensions/todo.ts index 89b147c84d..b9c3a702aa 100644 --- a/packages/coding-agent/examples/extensions/todo.ts +++ b/packages/coding-agent/examples/extensions/todo.ts @@ -10,9 +10,9 @@ * correct for that point in history. */ -import { StringEnum } from "@earendil-works/pi-ai"; -import type { ExtensionAPI, ExtensionContext, Theme } from "@earendil-works/pi-coding-agent"; -import { matchesKey, Text, truncateToWidth } from "@earendil-works/pi-tui"; +import type { ExtensionAPI, ExtensionContext, Theme } from "@prime-intellect/prime-agent"; +import { StringEnum } from "@prime-intellect/prime-agent-ai"; +import { matchesKey, Text, truncateToWidth } from "@prime-intellect/prime-agent-tui"; import { Type } from "typebox"; interface Todo { diff --git a/packages/coding-agent/examples/extensions/tool-override.ts b/packages/coding-agent/examples/extensions/tool-override.ts index 55b1455613..e3bc11a070 100644 --- a/packages/coding-agent/examples/extensions/tool-override.ts +++ b/packages/coding-agent/examples/extensions/tool-override.ts @@ -16,8 +16,8 @@ * pi -e ./tool-override.ts */ -import type { TextContent } from "@earendil-works/pi-ai"; -import { type ExtensionAPI, getAgentDir, withFileMutationQueue } from "@earendil-works/pi-coding-agent"; +import { type ExtensionAPI, getAgentDir, withFileMutationQueue } from "@prime-intellect/prime-agent"; +import type { TextContent } from "@prime-intellect/prime-agent-ai"; import { constants, readFileSync } from "fs"; import { access, appendFile, readFile } from "fs/promises"; import { join, resolve } from "path"; diff --git a/packages/coding-agent/examples/extensions/tools.ts b/packages/coding-agent/examples/extensions/tools.ts index 5e617ab36a..51a8328e00 100644 --- a/packages/coding-agent/examples/extensions/tools.ts +++ b/packages/coding-agent/examples/extensions/tools.ts @@ -9,9 +9,9 @@ * 2. Use /tools to open the tool selector */ -import type { ExtensionAPI, ExtensionContext, ToolInfo } from "@earendil-works/pi-coding-agent"; -import { getSettingsListTheme } from "@earendil-works/pi-coding-agent"; -import { Container, type SettingItem, SettingsList } from "@earendil-works/pi-tui"; +import type { ExtensionAPI, ExtensionContext, ToolInfo } from "@prime-intellect/prime-agent"; +import { getSettingsListTheme } from "@prime-intellect/prime-agent"; +import { Container, type SettingItem, SettingsList } from "@prime-intellect/prime-agent-tui"; // State persisted to session interface ToolsState { diff --git a/packages/coding-agent/examples/extensions/trigger-compact.ts b/packages/coding-agent/examples/extensions/trigger-compact.ts index fed578110c..b75091a7be 100644 --- a/packages/coding-agent/examples/extensions/trigger-compact.ts +++ b/packages/coding-agent/examples/extensions/trigger-compact.ts @@ -1,4 +1,4 @@ -import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, ExtensionContext } from "@prime-intellect/prime-agent"; const COMPACT_THRESHOLD_TOKENS = 100_000; diff --git a/packages/coding-agent/examples/extensions/truncated-tool.ts b/packages/coding-agent/examples/extensions/truncated-tool.ts index a59b3e79b6..f7c80bb864 100644 --- a/packages/coding-agent/examples/extensions/truncated-tool.ts +++ b/packages/coding-agent/examples/extensions/truncated-tool.ts @@ -14,7 +14,7 @@ */ import { mkdtemp, writeFile } from "node:fs/promises"; -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, @@ -22,8 +22,8 @@ import { type TruncationResult, truncateHead, withFileMutationQueue, -} from "@earendil-works/pi-coding-agent"; -import { Text } from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent"; +import { Text } from "@prime-intellect/prime-agent-tui"; import { execSync } from "child_process"; import { tmpdir } from "os"; import { join } from "path"; diff --git a/packages/coding-agent/examples/extensions/widget-placement.ts b/packages/coding-agent/examples/extensions/widget-placement.ts index 44bf5b6044..c07ac2016f 100644 --- a/packages/coding-agent/examples/extensions/widget-placement.ts +++ b/packages/coding-agent/examples/extensions/widget-placement.ts @@ -1,4 +1,4 @@ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function widgetPlacementExtension(pi: ExtensionAPI) { pi.on("session_start", (_event, ctx) => { diff --git a/packages/coding-agent/examples/extensions/with-deps/index.ts b/packages/coding-agent/examples/extensions/with-deps/index.ts index 6008d65e55..ff9dc8c9f9 100644 --- a/packages/coding-agent/examples/extensions/with-deps/index.ts +++ b/packages/coding-agent/examples/extensions/with-deps/index.ts @@ -5,7 +5,7 @@ * Requires: bun install in this directory */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; import ms from "ms"; import { Type } from "typebox"; diff --git a/packages/coding-agent/examples/extensions/working-indicator.ts b/packages/coding-agent/examples/extensions/working-indicator.ts index 1fb3dbd714..fb6d615f38 100644 --- a/packages/coding-agent/examples/extensions/working-indicator.ts +++ b/packages/coding-agent/examples/extensions/working-indicator.ts @@ -16,7 +16,7 @@ * /working-indicator reset Restore pi's default spinner */ -import type { ExtensionAPI, ExtensionContext, WorkingIndicatorOptions } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI, ExtensionContext, WorkingIndicatorOptions } from "@prime-intellect/prime-agent"; type WorkingIndicatorMode = "dot" | "none" | "pulse" | "spinner" | "default"; diff --git a/packages/coding-agent/examples/extensions/working-message-test.ts b/packages/coding-agent/examples/extensions/working-message-test.ts index 7c5a32f9ef..8def36b599 100644 --- a/packages/coding-agent/examples/extensions/working-message-test.ts +++ b/packages/coding-agent/examples/extensions/working-message-test.ts @@ -12,7 +12,7 @@ * loader appears, not revert to the default gray "Working...". */ -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; const CUSTOM_MESSAGE = "\x1b[38;2;155;86;63mWorking... (custom)\x1b[39m"; const CUSTOM_INDICATOR = { frames: ["\x1b[38;2;155;86;63m●\x1b[39m"] }; diff --git a/packages/coding-agent/examples/rpc-extension-ui.ts b/packages/coding-agent/examples/rpc-extension-ui.ts index 9816e8b2bf..8830d60db5 100644 --- a/packages/coding-agent/examples/rpc-extension-ui.ts +++ b/packages/coding-agent/examples/rpc-extension-ui.ts @@ -18,7 +18,15 @@ import { spawn } from "node:child_process"; import { dirname, join } from "node:path"; import * as readline from "node:readline"; import { fileURLToPath } from "node:url"; -import { type Component, Container, Input, matchesKey, ProcessTerminal, SelectList, TUI } from "@earendil-works/pi-tui"; +import { + type Component, + Container, + Input, + matchesKey, + ProcessTerminal, + SelectList, + TUI, +} from "@prime-intellect/prime-agent-tui"; const __dirname = dirname(fileURLToPath(import.meta.url)); diff --git a/packages/coding-agent/examples/sdk/01-minimal.ts b/packages/coding-agent/examples/sdk/01-minimal.ts index be35bab2b0..fc5f2fdb79 100644 --- a/packages/coding-agent/examples/sdk/01-minimal.ts +++ b/packages/coding-agent/examples/sdk/01-minimal.ts @@ -5,7 +5,7 @@ * from cwd and ~/.pi/agent. Model chosen from settings or first available. */ -import { createAgentSession } from "@earendil-works/pi-coding-agent"; +import { createAgentSession } from "@prime-intellect/prime-agent"; const { session } = await createAgentSession(); diff --git a/packages/coding-agent/examples/sdk/02-custom-model.ts b/packages/coding-agent/examples/sdk/02-custom-model.ts index ff1b428788..3c79a58996 100644 --- a/packages/coding-agent/examples/sdk/02-custom-model.ts +++ b/packages/coding-agent/examples/sdk/02-custom-model.ts @@ -4,8 +4,8 @@ * Shows how to select a specific model and thinking level. */ -import { getModel } from "@earendil-works/pi-ai"; -import { AuthStorage, createAgentSession, ModelRegistry } from "@earendil-works/pi-coding-agent"; +import { AuthStorage, createAgentSession, ModelRegistry } from "@prime-intellect/prime-agent"; +import { getModel } from "@prime-intellect/prime-agent-ai"; // Set up auth storage and model registry const authStorage = AuthStorage.create(); diff --git a/packages/coding-agent/examples/sdk/03-custom-prompt.ts b/packages/coding-agent/examples/sdk/03-custom-prompt.ts index 7c3ea5ffa6..2991bad036 100644 --- a/packages/coding-agent/examples/sdk/03-custom-prompt.ts +++ b/packages/coding-agent/examples/sdk/03-custom-prompt.ts @@ -4,12 +4,7 @@ * Shows how to replace or modify the default system prompt. */ -import { - createAgentSession, - DefaultResourceLoader, - getAgentDir, - SessionManager, -} from "@earendil-works/pi-coding-agent"; +import { createAgentSession, DefaultResourceLoader, getAgentDir, SessionManager } from "@prime-intellect/prime-agent"; const cwd = process.cwd(); const agentDir = getAgentDir(); diff --git a/packages/coding-agent/examples/sdk/04-skills.ts b/packages/coding-agent/examples/sdk/04-skills.ts index 806f51ab15..8f08a3fd6a 100644 --- a/packages/coding-agent/examples/sdk/04-skills.ts +++ b/packages/coding-agent/examples/sdk/04-skills.ts @@ -12,7 +12,7 @@ import { getAgentDir, SessionManager, type Skill, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; // Or define custom skills inline const customSkill: Skill = { diff --git a/packages/coding-agent/examples/sdk/05-tools.ts b/packages/coding-agent/examples/sdk/05-tools.ts index a223ca24ac..9f1ac9dca4 100644 --- a/packages/coding-agent/examples/sdk/05-tools.ts +++ b/packages/coding-agent/examples/sdk/05-tools.ts @@ -10,7 +10,7 @@ * extensions system using pi.registerTool(). */ -import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent"; +import { createAgentSession, SessionManager } from "@prime-intellect/prime-agent"; // Default tool surface await createAgentSession({ diff --git a/packages/coding-agent/examples/sdk/06-extensions.ts b/packages/coding-agent/examples/sdk/06-extensions.ts index 8e55a80ab0..94f44e1787 100644 --- a/packages/coding-agent/examples/sdk/06-extensions.ts +++ b/packages/coding-agent/examples/sdk/06-extensions.ts @@ -13,12 +13,7 @@ * export default function (pi: ExtensionAPI) { ... } */ -import { - createAgentSession, - DefaultResourceLoader, - getAgentDir, - SessionManager, -} from "@earendil-works/pi-coding-agent"; +import { createAgentSession, DefaultResourceLoader, getAgentDir, SessionManager } from "@prime-intellect/prime-agent"; // Extensions are discovered automatically from standard locations. // You can also add paths via settings.json or DefaultResourceLoader options. @@ -53,7 +48,7 @@ console.log(); // Example extension file (./my-logging-extension.ts): /* -import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; +import type { ExtensionAPI } from "@prime-intellect/prime-agent"; export default function (pi: ExtensionAPI) { pi.on("agent_start", async () => { diff --git a/packages/coding-agent/examples/sdk/07-context-files.ts b/packages/coding-agent/examples/sdk/07-context-files.ts index c8ce77a1f7..24d1ba4729 100644 --- a/packages/coding-agent/examples/sdk/07-context-files.ts +++ b/packages/coding-agent/examples/sdk/07-context-files.ts @@ -4,12 +4,7 @@ * Context files provide project-specific instructions loaded into the system prompt. */ -import { - createAgentSession, - DefaultResourceLoader, - getAgentDir, - SessionManager, -} from "@earendil-works/pi-coding-agent"; +import { createAgentSession, DefaultResourceLoader, getAgentDir, SessionManager } from "@prime-intellect/prime-agent"; // Disable context files entirely by returning an empty list in agentsFilesOverride. const loader = new DefaultResourceLoader({ diff --git a/packages/coding-agent/examples/sdk/08-prompt-templates.ts b/packages/coding-agent/examples/sdk/08-prompt-templates.ts index 814e32306a..85f4d5c6c3 100644 --- a/packages/coding-agent/examples/sdk/08-prompt-templates.ts +++ b/packages/coding-agent/examples/sdk/08-prompt-templates.ts @@ -11,7 +11,7 @@ import { getAgentDir, type PromptTemplate, SessionManager, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; // Define custom templates const deployTemplate: PromptTemplate = { diff --git a/packages/coding-agent/examples/sdk/09-api-keys-and-oauth.ts b/packages/coding-agent/examples/sdk/09-api-keys-and-oauth.ts index 127e5933e6..6e7f142027 100644 --- a/packages/coding-agent/examples/sdk/09-api-keys-and-oauth.ts +++ b/packages/coding-agent/examples/sdk/09-api-keys-and-oauth.ts @@ -4,7 +4,7 @@ * Configure API key resolution via AuthStorage and ModelRegistry. */ -import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@earendil-works/pi-coding-agent"; +import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@prime-intellect/prime-agent"; // Default: AuthStorage uses ~/.pi/agent/auth.json // ModelRegistry loads built-in + custom models from ~/.pi/agent/models.json diff --git a/packages/coding-agent/examples/sdk/10-settings.ts b/packages/coding-agent/examples/sdk/10-settings.ts index 9b6f93d8cf..23b00f7e12 100644 --- a/packages/coding-agent/examples/sdk/10-settings.ts +++ b/packages/coding-agent/examples/sdk/10-settings.ts @@ -4,7 +4,7 @@ * Override settings using SettingsManager. */ -import { createAgentSession, SessionManager, SettingsManager } from "@earendil-works/pi-coding-agent"; +import { createAgentSession, SessionManager, SettingsManager } from "@prime-intellect/prime-agent"; const cwd = process.cwd(); diff --git a/packages/coding-agent/examples/sdk/11-sessions.ts b/packages/coding-agent/examples/sdk/11-sessions.ts index 414db8b636..45995009f5 100644 --- a/packages/coding-agent/examples/sdk/11-sessions.ts +++ b/packages/coding-agent/examples/sdk/11-sessions.ts @@ -4,7 +4,7 @@ * Control session persistence: in-memory, new file, continue, or open specific. */ -import { createAgentSession, SessionManager } from "@earendil-works/pi-coding-agent"; +import { createAgentSession, SessionManager } from "@prime-intellect/prime-agent"; // In-memory (no persistence) const { session: inMemory } = await createAgentSession({ diff --git a/packages/coding-agent/examples/sdk/12-full-control.ts b/packages/coding-agent/examples/sdk/12-full-control.ts index 9cb55623e7..8aeb0cc2b4 100644 --- a/packages/coding-agent/examples/sdk/12-full-control.ts +++ b/packages/coding-agent/examples/sdk/12-full-control.ts @@ -4,7 +4,6 @@ * Replace everything - no discovery, explicit configuration. */ -import { getModel } from "@earendil-works/pi-ai"; import { AuthStorage, createAgentSession, @@ -13,7 +12,8 @@ import { type ResourceLoader, SessionManager, SettingsManager, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; +import { getModel } from "@prime-intellect/prime-agent-ai"; // Custom auth storage location const authStorage = AuthStorage.create("/tmp/my-agent/auth.json"); diff --git a/packages/coding-agent/examples/sdk/13-session-runtime.ts b/packages/coding-agent/examples/sdk/13-session-runtime.ts index a49d71ab09..0cc4e6ac6c 100644 --- a/packages/coding-agent/examples/sdk/13-session-runtime.ts +++ b/packages/coding-agent/examples/sdk/13-session-runtime.ts @@ -15,7 +15,7 @@ import { createAgentSessionServices, getAgentDir, SessionManager, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; const createRuntime: CreateAgentSessionRuntimeFactory = async ({ cwd, sessionManager, sessionStartEvent }) => { const services = await createAgentSessionServices({ cwd }); diff --git a/packages/coding-agent/examples/sdk/README.md b/packages/coding-agent/examples/sdk/README.md index 21d05192cd..562eaf81b3 100644 --- a/packages/coding-agent/examples/sdk/README.md +++ b/packages/coding-agent/examples/sdk/README.md @@ -2,7 +2,7 @@ Programmatic usage of the Prime Agent SDK via `createAgentSession()` and `createAgentSessionRuntime()`. -The published TypeScript packages still use inherited `@earendil-works/pi-*` +The published TypeScript packages use the `@prime-intellect/prime-agent*` namespace identifiers. Those identifiers are API names, not a dependency on the upstream Pi monorepo. @@ -36,7 +36,7 @@ bun examples/sdk/01-minimal.ts ## Quick Reference ```typescript -import { getModel } from "@earendil-works/pi-ai"; +import { getModel } from "@prime-intellect/prime-agent-ai"; import { AuthStorage, createAgentSession, @@ -44,7 +44,7 @@ import { ModelRegistry, SessionManager, SettingsManager, -} from "@earendil-works/pi-coding-agent"; +} from "@prime-intellect/prime-agent"; // Auth and models setup const authStorage = AuthStorage.create(); diff --git a/packages/coding-agent/package.json b/packages/coding-agent/package.json index aee7466abe..5a69bd34cb 100644 --- a/packages/coding-agent/package.json +++ b/packages/coding-agent/package.json @@ -1,5 +1,5 @@ { - "name": "@earendil-works/pi-coding-agent", + "name": "@prime-intellect/prime-agent", "version": "0.9.1", "description": "Coding agent CLI with a persistent Python REPL kernel and session management", "type": "module", @@ -8,7 +8,7 @@ "configDir": ".prime/agent" }, "bin": { - "pi": "dist/bundle/cli.js" + "prime-agent": "dist/bundle/cli.js" }, "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -48,9 +48,9 @@ }, "dependencies": { "@agentclientprotocol/sdk": "^1.3.0", - "@earendil-works/pi-agent-core": "^0.9.1", - "@earendil-works/pi-ai": "^0.9.1", - "@earendil-works/pi-tui": "^0.9.1", + "@prime-intellect/prime-agent-core": "^0.9.1", + "@prime-intellect/prime-agent-ai": "^0.9.1", + "@prime-intellect/prime-agent-tui": "^0.9.1", "@silvia-odwyer/photon-node": "^0.3.4", "chalk": "^5.5.0", "cli-highlight": "^2.1.11", @@ -103,5 +103,8 @@ "engines": { "node": ">=22.8.0", "bun": "1.4.0" + }, + "publishConfig": { + "access": "public" } } diff --git a/packages/coding-agent/scripts/bundle.mjs b/packages/coding-agent/scripts/bundle.mjs index ae780849c5..458d2ef20c 100644 --- a/packages/coding-agent/scripts/bundle.mjs +++ b/packages/coding-agent/scripts/bundle.mjs @@ -1,6 +1,6 @@ #!/usr/bin/env bun /** - * Bundles the compiled CLI entry (dist/cli.js) into dist/bundle/ with Bun. + * Bundles the Bun CLI entry (dist/bun/cli.js) into dist/bundle/. * * Why: the unbundled module graph is ~2,500 files; resolving and reading them * dominates startup (~1.5s on slow filesystems). The bundle loads the same code @@ -31,11 +31,11 @@ try { rmSync(outdir, { recursive: true, force: true }); const result = await Bun.build({ - entrypoints: [join(packageDir, "dist", "cli.js")], + entrypoints: [join(packageDir, "dist", "bun", "cli.js")], outdir, splitting: true, format: "esm", - target: "node", + target: "bun", sourcemap: "linked", // Native or interop-sensitive packages stay external; they resolve from // node_modules at runtime (and are loaded via createRequire/lazily anyway). @@ -60,4 +60,4 @@ if (!result.success) { } chmodSync(join(outdir, "cli.js"), 0o755); -console.log("bundled dist/cli.js -> dist/bundle/"); +console.log("bundled dist/bun/cli.js -> dist/bundle/"); diff --git a/packages/coding-agent/src/bun/register-bedrock.ts b/packages/coding-agent/src/bun/register-bedrock.ts index 839cbcdb2b..923ef85101 100644 --- a/packages/coding-agent/src/bun/register-bedrock.ts +++ b/packages/coding-agent/src/bun/register-bedrock.ts @@ -1,6 +1,6 @@ -import { setBedrockProviderModuleLoader } from "@earendil-works/pi-ai"; +import { setBedrockProviderModuleLoader } from "@prime-intellect/prime-agent-ai"; setBedrockProviderModuleLoader(async () => { - const { bedrockProviderModule } = await import("@earendil-works/pi-ai/bedrock-provider"); + const { bedrockProviderModule } = await import("@prime-intellect/prime-agent-ai/bedrock-provider"); return bedrockProviderModule; }); diff --git a/packages/coding-agent/src/cli/args.ts b/packages/coding-agent/src/cli/args.ts index fed99107ef..20be686c3f 100644 --- a/packages/coding-agent/src/cli/args.ts +++ b/packages/coding-agent/src/cli/args.ts @@ -2,7 +2,7 @@ * CLI argument parsing and help display */ -import type { ThinkingLevel } from "@earendil-works/pi-agent-core"; +import type { ThinkingLevel } from "@prime-intellect/prime-agent-core"; import { APP_NAME } from "../config.js"; import { THINKING_LEVELS } from "../core/thinking-levels.js"; diff --git a/packages/coding-agent/src/cli/config-selector.ts b/packages/coding-agent/src/cli/config-selector.ts index f7bc30ae47..774b3566e6 100644 --- a/packages/coding-agent/src/cli/config-selector.ts +++ b/packages/coding-agent/src/cli/config-selector.ts @@ -1,4 +1,4 @@ -import { ProcessTerminal, TUI } from "@earendil-works/pi-tui"; +import { ProcessTerminal, TUI } from "@prime-intellect/prime-agent-tui"; import type { ResolvedPaths } from "../core/package-manager.js"; import type { SettingsManager } from "../core/settings-manager.js"; import { ConfigSelectorComponent } from "../modes/interactive/components/config-selector.js"; diff --git a/packages/coding-agent/src/cli/daemon-command.ts b/packages/coding-agent/src/cli/daemon-command.ts index 4fd655ef95..6f49b9eab6 100644 --- a/packages/coding-agent/src/cli/daemon-command.ts +++ b/packages/coding-agent/src/cli/daemon-command.ts @@ -1,7 +1,7 @@ import { resolve } from "node:path"; import { clearLine, createInterface, cursorTo, type Interface } from "node:readline"; import { setTimeout as delay } from "node:timers/promises"; -import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; import chalk from "chalk"; import { spawn } from "child_process"; import { expandTildePath } from "../config.js"; diff --git a/packages/coding-agent/src/cli/file-processor.ts b/packages/coding-agent/src/cli/file-processor.ts index 418ad173cd..d8f95e6d45 100644 --- a/packages/coding-agent/src/cli/file-processor.ts +++ b/packages/coding-agent/src/cli/file-processor.ts @@ -1,5 +1,5 @@ import { access, readFile, stat } from "node:fs/promises"; -import type { ImageContent } from "@earendil-works/pi-ai"; +import type { ImageContent } from "@prime-intellect/prime-agent-ai"; import chalk from "chalk"; import { resolve } from "path"; import { resolveReadPath } from "../core/tools/path-utils.js"; diff --git a/packages/coding-agent/src/cli/initial-message.ts b/packages/coding-agent/src/cli/initial-message.ts index a3a7f1b756..9a7261aadf 100644 --- a/packages/coding-agent/src/cli/initial-message.ts +++ b/packages/coding-agent/src/cli/initial-message.ts @@ -1,4 +1,4 @@ -import type { ImageContent } from "@earendil-works/pi-ai"; +import type { ImageContent } from "@prime-intellect/prime-agent-ai"; import type { Args } from "./args.js"; export interface InitialMessageInput { diff --git a/packages/coding-agent/src/cli/list-models.ts b/packages/coding-agent/src/cli/list-models.ts index 6228a0e10e..b28fd4438e 100644 --- a/packages/coding-agent/src/cli/list-models.ts +++ b/packages/coding-agent/src/cli/list-models.ts @@ -1,5 +1,5 @@ -import type { Api, Model } from "@earendil-works/pi-ai"; -import { fuzzyFilter } from "@earendil-works/pi-tui"; +import type { Api, Model } from "@prime-intellect/prime-agent-ai"; +import { fuzzyFilter } from "@prime-intellect/prime-agent-tui"; import chalk from "chalk"; import { formatNoModelsAvailableMessage } from "../core/auth-guidance.js"; import type { ModelRegistry } from "../core/model-registry.js"; diff --git a/packages/coding-agent/src/config.ts b/packages/coding-agent/src/config.ts index 1d6fbbc8c7..004bc2cc0c 100644 --- a/packages/coding-agent/src/config.ts +++ b/packages/coding-agent/src/config.ts @@ -514,7 +514,7 @@ const envPrefix = .toUpperCase() .replace(/[^A-Z0-9]+/g, "_") .replace(/^_+|_+$/g, "") || "PI"; -export const PACKAGE_NAME: string = pkg.name || "@earendil-works/pi-coding-agent"; +export const PACKAGE_NAME: string = pkg.name || "@prime-intellect/prime-agent"; export const APP_NAME: string = piConfigName || "pi"; export const APP_TITLE: string = piConfigName ? APP_NAME : "π"; export const CONFIG_DIR_NAME: string = pkg.piConfig?.configDir || ".prime/agent"; diff --git a/packages/coding-agent/src/core/agent-messages.ts b/packages/coding-agent/src/core/agent-messages.ts index 0599c003c9..d7931fd3aa 100644 --- a/packages/coding-agent/src/core/agent-messages.ts +++ b/packages/coding-agent/src/core/agent-messages.ts @@ -1,5 +1,5 @@ import { randomUUID } from "node:crypto"; -import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; import type { HostRequestHandler } from "./kernel/index.js"; import type { CustomMessage } from "./messages.js"; import { HEARTBEAT_PROMPT_CUSTOM_TYPE } from "./messages.js"; diff --git a/packages/coding-agent/src/core/agent-observe.ts b/packages/coding-agent/src/core/agent-observe.ts index 045be77572..dbc8370e57 100644 --- a/packages/coding-agent/src/core/agent-observe.ts +++ b/packages/coding-agent/src/core/agent-observe.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; export const AGENT_OBSERVE_SKILL_NAME = "agent-observe"; export const AGENT_OBSERVE_IMPORT_NAME = "agent_observe"; diff --git a/packages/coding-agent/src/core/agent-session-config.ts b/packages/coding-agent/src/core/agent-session-config.ts index f855f4c075..1007af2559 100644 --- a/packages/coding-agent/src/core/agent-session-config.ts +++ b/packages/coding-agent/src/core/agent-session-config.ts @@ -1,4 +1,4 @@ -import type { ThinkingLevel } from "@earendil-works/pi-agent-core"; +import type { ThinkingLevel } from "@prime-intellect/prime-agent-core"; import type { AgentAutonomousConfig } from "./autonomous.js"; export type AgentExecutionMode = "interactive" | "print" | "json" | "rpc" | "acp"; diff --git a/packages/coding-agent/src/core/agent-session-services.ts b/packages/coding-agent/src/core/agent-session-services.ts index e1622530b9..fd52712635 100644 --- a/packages/coding-agent/src/core/agent-session-services.ts +++ b/packages/coding-agent/src/core/agent-session-services.ts @@ -1,6 +1,6 @@ import { join } from "node:path"; -import type { ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { Model, ServiceTier } from "@earendil-works/pi-ai"; +import type { Model, ServiceTier } from "@prime-intellect/prime-agent-ai"; +import type { ThinkingLevel } from "@prime-intellect/prime-agent-core"; import { getAgentDir } from "../config.js"; import type { AgentSessionMessageController } from "./agent-messages.js"; import type { AgentObserveController } from "./agent-observe.js"; diff --git a/packages/coding-agent/src/core/agent-session.ts b/packages/coding-agent/src/core/agent-session.ts index 39dab65732..81c407da8e 100644 --- a/packages/coding-agent/src/core/agent-session.ts +++ b/packages/coding-agent/src/core/agent-session.ts @@ -3,18 +3,6 @@ import { randomUUID } from "node:crypto"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { basename, dirname, join, resolve } from "node:path"; -import { - Agent, - type AgentContext, - AgentContinueError, - type AgentEvent, - type AgentMessage, - type AgentState, - type AgentTool, - type GetContinuationMessagesContext, - type ShouldStopAfterTurnContext, - type ThinkingLevel, -} from "@earendil-works/pi-agent-core"; import type { Api, AssistantMessage, @@ -24,7 +12,7 @@ import type { TextContent, Usage, UserMessage, -} from "@earendil-works/pi-ai"; +} from "@prime-intellect/prime-agent-ai"; import { clampThinkingLevel, cleanupSessionResources, @@ -33,7 +21,19 @@ import { modelsAreEqual, resetApiProviders, supportsFastMode, -} from "@earendil-works/pi-ai"; +} from "@prime-intellect/prime-agent-ai"; +import { + Agent, + type AgentContext, + AgentContinueError, + type AgentEvent, + type AgentMessage, + type AgentState, + type AgentTool, + type GetContinuationMessagesContext, + type ShouldStopAfterTurnContext, + type ThinkingLevel, +} from "@prime-intellect/prime-agent-core"; import { theme } from "../modes/interactive/theme/theme.js"; import { stripFrontmatter } from "../utils/frontmatter.js"; import { sleep } from "../utils/sleep.js"; diff --git a/packages/coding-agent/src/core/auth-storage.ts b/packages/coding-agent/src/core/auth-storage.ts index 389bc64f85..3bae0d1f10 100644 --- a/packages/coding-agent/src/core/auth-storage.ts +++ b/packages/coding-agent/src/core/auth-storage.ts @@ -13,8 +13,8 @@ import { type OAuthCredentials, type OAuthLoginCallbacks, type OAuthProviderId, -} from "@earendil-works/pi-ai"; -import { getOAuthApiKey, getOAuthProvider, getOAuthProviders } from "@earendil-works/pi-ai/oauth"; +} from "@prime-intellect/prime-agent-ai"; +import { getOAuthApiKey, getOAuthProvider, getOAuthProviders } from "@prime-intellect/prime-agent-ai/oauth"; import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs"; import { dirname, join } from "path"; import lockfile from "proper-lockfile"; diff --git a/packages/coding-agent/src/core/autonomous.ts b/packages/coding-agent/src/core/autonomous.ts index 75930d415c..67d7989909 100644 --- a/packages/coding-agent/src/core/autonomous.ts +++ b/packages/coding-agent/src/core/autonomous.ts @@ -3,7 +3,7 @@ import { createHash } from "node:crypto"; import { createReadStream } from "node:fs"; import { lstat, readlink } from "node:fs/promises"; import { resolve } from "node:path"; -import type { AssistantMessage, Usage, UserMessage } from "@earendil-works/pi-ai"; +import type { AssistantMessage, Usage, UserMessage } from "@prime-intellect/prime-agent-ai"; import { waitForChildProcess } from "../utils/child-process.js"; import { killProcessTree, trackDetachedChildPid, untrackDetachedChildPid } from "../utils/shell.js"; diff --git a/packages/coding-agent/src/core/compaction/branch-summarization.ts b/packages/coding-agent/src/core/compaction/branch-summarization.ts index a23f825f05..c62c71e0c5 100644 --- a/packages/coding-agent/src/core/compaction/branch-summarization.ts +++ b/packages/coding-agent/src/core/compaction/branch-summarization.ts @@ -5,9 +5,9 @@ * a summary of the branch being left so context isn't lost. */ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { Model } from "@earendil-works/pi-ai"; -import { completeSimple } from "@earendil-works/pi-ai"; +import type { Model } from "@prime-intellect/prime-agent-ai"; +import { completeSimple } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; import { convertToLlm, createBranchSummaryMessage, diff --git a/packages/coding-agent/src/core/compaction/compaction.ts b/packages/coding-agent/src/core/compaction/compaction.ts index cdda5ed080..f387601ef0 100644 --- a/packages/coding-agent/src/core/compaction/compaction.ts +++ b/packages/coding-agent/src/core/compaction/compaction.ts @@ -5,9 +5,9 @@ * and after compaction the session is reloaded. */ -import type { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { AssistantMessage, Model, Usage } from "@earendil-works/pi-ai"; -import { completeSimple } from "@earendil-works/pi-ai"; +import type { AssistantMessage, Model, Usage } from "@prime-intellect/prime-agent-ai"; +import { completeSimple } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage, ThinkingLevel } from "@prime-intellect/prime-agent-core"; import { convertToLlm, createBranchSummaryMessage, diff --git a/packages/coding-agent/src/core/compaction/utils.ts b/packages/coding-agent/src/core/compaction/utils.ts index 72a764566d..412b767e12 100644 --- a/packages/coding-agent/src/core/compaction/utils.ts +++ b/packages/coding-agent/src/core/compaction/utils.ts @@ -2,8 +2,8 @@ * Shared utilities for compaction and branch summarization. */ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { Message } from "@earendil-works/pi-ai"; +import type { Message } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; export interface FileOperations { read: Set; written: Set; diff --git a/packages/coding-agent/src/core/context-tree.ts b/packages/coding-agent/src/core/context-tree.ts index 6e744b9929..670ab50f39 100644 --- a/packages/coding-agent/src/core/context-tree.ts +++ b/packages/coding-agent/src/core/context-tree.ts @@ -1,6 +1,6 @@ import { existsSync, readdirSync, statSync } from "node:fs"; import { basename, join } from "node:path"; -import type { AssistantMessage, Usage } from "@earendil-works/pi-ai"; +import type { AssistantMessage, Usage } from "@prime-intellect/prime-agent-ai"; import type { RlmChildAgentStatus } from "./agent-session.js"; import { calculateContextTokens, estimateContextTokens } from "./compaction/index.js"; import type { ContextUsage } from "./extensions/index.js"; diff --git a/packages/coding-agent/src/core/defaults.ts b/packages/coding-agent/src/core/defaults.ts index fddc7d14f9..026749fea0 100644 --- a/packages/coding-agent/src/core/defaults.ts +++ b/packages/coding-agent/src/core/defaults.ts @@ -1,3 +1,3 @@ -import type { ThinkingLevel } from "@earendil-works/pi-agent-core"; +import type { ThinkingLevel } from "@prime-intellect/prime-agent-core"; export const DEFAULT_THINKING_LEVEL: ThinkingLevel = "medium"; diff --git a/packages/coding-agent/src/core/export-html/index.ts b/packages/coding-agent/src/core/export-html/index.ts index a6733fe9ac..8d89c328eb 100644 --- a/packages/coding-agent/src/core/export-html/index.ts +++ b/packages/coding-agent/src/core/export-html/index.ts @@ -1,4 +1,4 @@ -import type { AgentState } from "@earendil-works/pi-agent-core"; +import type { AgentState } from "@prime-intellect/prime-agent-core"; import { existsSync, readFileSync, writeFileSync } from "fs"; import { basename, join } from "path"; import { APP_NAME, getExportTemplateDir } from "../../config.js"; diff --git a/packages/coding-agent/src/core/export-html/tool-renderer.ts b/packages/coding-agent/src/core/export-html/tool-renderer.ts index 7ba99a1410..67a342d64f 100644 --- a/packages/coding-agent/src/core/export-html/tool-renderer.ts +++ b/packages/coding-agent/src/core/export-html/tool-renderer.ts @@ -5,8 +5,8 @@ * and converting the ANSI output to HTML. */ -import type { ImageContent, TextContent } from "@earendil-works/pi-ai"; -import type { Component } from "@earendil-works/pi-tui"; +import type { ImageContent, TextContent } from "@prime-intellect/prime-agent-ai"; +import type { Component } from "@prime-intellect/prime-agent-tui"; import type { Theme } from "../../modes/interactive/theme/theme.js"; import type { ToolDefinition, ToolRenderContext } from "../extensions/types.js"; import { ansiLinesToHtml } from "./ansi-to-html.js"; diff --git a/packages/coding-agent/src/core/extensions/bundled-modules.ts b/packages/coding-agent/src/core/extensions/bundled-modules.ts index 678387e1cb..05171b6d8b 100644 --- a/packages/coding-agent/src/core/extensions/bundled-modules.ts +++ b/packages/coding-agent/src/core/extensions/bundled-modules.ts @@ -8,15 +8,15 @@ * not pull in the entire package graph at startup. */ -import * as _bundledPiAgentCore from "@earendil-works/pi-agent-core"; -import * as _bundledPiAi from "@earendil-works/pi-ai"; -import * as _bundledPiAiOauth from "@earendil-works/pi-ai/oauth"; -import * as _bundledPiTui from "@earendil-works/pi-tui"; +import * as _bundledPiAi from "@prime-intellect/prime-agent-ai"; +import * as _bundledPiAiOauth from "@prime-intellect/prime-agent-ai/oauth"; +import * as _bundledPiAgentCore from "@prime-intellect/prime-agent-core"; +import * as _bundledPiTui from "@prime-intellect/prime-agent-tui"; import * as _bundledTypebox from "typebox"; import * as _bundledTypeboxCompile from "typebox/compile"; import * as _bundledTypeboxValue from "typebox/value"; // NOTE: This import works because loader.ts exports are NOT re-exported from index.ts, -// avoiding a circular dependency. Extensions can import from @earendil-works/pi-coding-agent. +// avoiding a circular dependency. Extensions can import from @prime-intellect/prime-agent. import * as _bundledPiCodingAgent from "../../index.js"; export const VIRTUAL_MODULES: Record = { @@ -26,6 +26,11 @@ export const VIRTUAL_MODULES: Record = { "@sinclair/typebox": _bundledTypebox, "@sinclair/typebox/compile": _bundledTypeboxCompile, "@sinclair/typebox/value": _bundledTypeboxValue, + "@prime-intellect/prime-agent-core": _bundledPiAgentCore, + "@prime-intellect/prime-agent-tui": _bundledPiTui, + "@prime-intellect/prime-agent-ai": _bundledPiAi, + "@prime-intellect/prime-agent-ai/oauth": _bundledPiAiOauth, + "@prime-intellect/prime-agent": _bundledPiCodingAgent, "@earendil-works/pi-agent-core": _bundledPiAgentCore, "@earendil-works/pi-tui": _bundledPiTui, "@earendil-works/pi-ai": _bundledPiAi, diff --git a/packages/coding-agent/src/core/extensions/loader.ts b/packages/coding-agent/src/core/extensions/loader.ts index ff978c8e8c..7ee79a6a00 100644 --- a/packages/coding-agent/src/core/extensions/loader.ts +++ b/packages/coding-agent/src/core/extensions/loader.ts @@ -8,7 +8,7 @@ import { createRequire } from "node:module"; import * as os from "node:os"; import * as path from "node:path"; import { fileURLToPath } from "node:url"; -import type { KeyId } from "@earendil-works/pi-tui"; +import type { KeyId } from "@prime-intellect/prime-agent-tui"; import { CONFIG_DIR_NAME, getAgentDir, isBunBinary } from "../../config.js"; import { createEventBus, type EventBus } from "../event-bus.js"; import type { ExecOptions } from "../exec.js"; @@ -54,12 +54,17 @@ function getAliases(): Record { }; const piCodingAgentEntry = packageIndex; - const piAgentCoreEntry = resolveWorkspaceOrImport("agent/dist/index.js", "@earendil-works/pi-agent-core"); - const piTuiEntry = resolveWorkspaceOrImport("tui/dist/index.js", "@earendil-works/pi-tui"); - const piAiEntry = resolveWorkspaceOrImport("ai/dist/index.js", "@earendil-works/pi-ai"); - const piAiOauthEntry = resolveWorkspaceOrImport("ai/dist/oauth.js", "@earendil-works/pi-ai/oauth"); + const piAgentCoreEntry = resolveWorkspaceOrImport("agent/dist/index.js", "@prime-intellect/prime-agent-core"); + const piTuiEntry = resolveWorkspaceOrImport("tui/dist/index.js", "@prime-intellect/prime-agent-tui"); + const piAiEntry = resolveWorkspaceOrImport("ai/dist/index.js", "@prime-intellect/prime-agent-ai"); + const piAiOauthEntry = resolveWorkspaceOrImport("ai/dist/oauth.js", "@prime-intellect/prime-agent-ai/oauth"); _aliases = { + "@prime-intellect/prime-agent": piCodingAgentEntry, + "@prime-intellect/prime-agent-core": piAgentCoreEntry, + "@prime-intellect/prime-agent-tui": piTuiEntry, + "@prime-intellect/prime-agent-ai": piAiEntry, + "@prime-intellect/prime-agent-ai/oauth": piAiOauthEntry, "@earendil-works/pi-coding-agent": piCodingAgentEntry, "@earendil-works/pi-agent-core": piAgentCoreEntry, "@earendil-works/pi-tui": piTuiEntry, diff --git a/packages/coding-agent/src/core/extensions/runner.ts b/packages/coding-agent/src/core/extensions/runner.ts index 172f725003..c13dbd15d1 100644 --- a/packages/coding-agent/src/core/extensions/runner.ts +++ b/packages/coding-agent/src/core/extensions/runner.ts @@ -2,9 +2,9 @@ * Extension runner - executes extensions and manages their lifecycle. */ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { ImageContent, Model } from "@earendil-works/pi-ai"; -import type { KeyId } from "@earendil-works/pi-tui"; +import type { ImageContent, Model } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; +import type { KeyId } from "@prime-intellect/prime-agent-tui"; import { type Theme, theme } from "../../modes/interactive/theme/theme.js"; import type { ResourceDiagnostic } from "../diagnostics.js"; import type { KeybindingsConfig } from "../keybindings.js"; diff --git a/packages/coding-agent/src/core/extensions/types.ts b/packages/coding-agent/src/core/extensions/types.ts index 4ff321fdfd..f6f32a408d 100644 --- a/packages/coding-agent/src/core/extensions/types.ts +++ b/packages/coding-agent/src/core/extensions/types.ts @@ -8,13 +8,6 @@ * - Interact with the user via UI primitives */ -import type { - AgentMessage, - AgentToolResult, - AgentToolUpdateCallback, - ThinkingLevel, - ToolExecutionMode, -} from "@earendil-works/pi-agent-core"; import type { Api, AssistantMessageEvent, @@ -27,7 +20,14 @@ import type { SimpleStreamOptions, TextContent, ToolResultMessage, -} from "@earendil-works/pi-ai"; +} from "@prime-intellect/prime-agent-ai"; +import type { + AgentMessage, + AgentToolResult, + AgentToolUpdateCallback, + ThinkingLevel, + ToolExecutionMode, +} from "@prime-intellect/prime-agent-core"; import type { AutocompleteItem, AutocompleteProvider, @@ -38,7 +38,7 @@ import type { OverlayHandle, OverlayOptions, TUI, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import type { Static, TSchema } from "typebox"; import type { Theme } from "../../modes/interactive/theme/theme.js"; import type { BashResult } from "../bash-executor.js"; @@ -215,12 +215,12 @@ export interface ExtensionUIContext { * - `keybindings`: KeybindingsManager for app-level keybindings * * For full app keybinding support (escape, ctrl+d, model switching, etc.), - * extend `CustomEditor` from `@earendil-works/pi-coding-agent` and call + * extend `CustomEditor` from `@prime-intellect/prime-agent` and call * `super.handleInput(data)` for keys you don't handle. * * @example * ```ts - * import { CustomEditor } from "@earendil-works/pi-coding-agent"; + * import { CustomEditor } from "@prime-intellect/prime-agent"; * * class VimEditor extends CustomEditor { * private mode: "normal" | "insert" = "insert"; diff --git a/packages/coding-agent/src/core/extensions/wrapper.ts b/packages/coding-agent/src/core/extensions/wrapper.ts index 3a852f0e97..cfc737fc27 100644 --- a/packages/coding-agent/src/core/extensions/wrapper.ts +++ b/packages/coding-agent/src/core/extensions/wrapper.ts @@ -5,7 +5,7 @@ * Tool call and tool result interception is handled by AgentSession via agent-core hooks. */ -import type { AgentTool } from "@earendil-works/pi-agent-core"; +import type { AgentTool } from "@prime-intellect/prime-agent-core"; import { wrapToolDefinition, wrapToolDefinitions } from "../tools/tool-definition-wrapper.js"; import type { ExtensionRunner } from "./runner.js"; import type { RegisteredTool } from "./types.js"; diff --git a/packages/coding-agent/src/core/goals.ts b/packages/coding-agent/src/core/goals.ts index 339775de9f..7f44b3bfdb 100644 --- a/packages/coding-agent/src/core/goals.ts +++ b/packages/coding-agent/src/core/goals.ts @@ -1,4 +1,4 @@ -import type { ImageContent, TextContent } from "@earendil-works/pi-ai"; +import type { ImageContent, TextContent } from "@prime-intellect/prime-agent-ai"; import type { CustomMessage } from "./messages.js"; export const GOAL_STATE_CUSTOM_TYPE = "thread_goal_state"; diff --git a/packages/coding-agent/src/core/kernel/shared.ts b/packages/coding-agent/src/core/kernel/shared.ts index 25d43b9178..af65348cf8 100644 --- a/packages/coding-agent/src/core/kernel/shared.ts +++ b/packages/coding-agent/src/core/kernel/shared.ts @@ -1,4 +1,4 @@ -import { registerSessionResourceCleanup } from "@earendil-works/pi-ai"; +import { registerSessionResourceCleanup } from "@prime-intellect/prime-agent-ai"; import type { KernelBootstrapProgressHandler, KernelPythonSkill } from "./bootstrap.js"; import type { RestoreResult, SnapshotResult } from "./state-snapshot.js"; diff --git a/packages/coding-agent/src/core/keybindings.ts b/packages/coding-agent/src/core/keybindings.ts index 6c451d53e6..e2bcbcd9df 100644 --- a/packages/coding-agent/src/core/keybindings.ts +++ b/packages/coding-agent/src/core/keybindings.ts @@ -5,7 +5,7 @@ import { type KeyId, TUI_KEYBINDINGS, KeybindingsManager as TuiKeybindingsManager, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { existsSync, readFileSync } from "fs"; import { join } from "path"; import { getAgentDir } from "../config.js"; @@ -69,7 +69,7 @@ export interface AppKeybindings { export type AppKeybinding = keyof AppKeybindings; -declare module "@earendil-works/pi-tui" { +declare module "@prime-intellect/prime-agent-tui" { interface Keybindings extends AppKeybindings {} } diff --git a/packages/coding-agent/src/core/logging.ts b/packages/coding-agent/src/core/logging.ts index 44ed72f13e..5478593ab4 100644 --- a/packages/coding-agent/src/core/logging.ts +++ b/packages/coding-agent/src/core/logging.ts @@ -1,4 +1,4 @@ -import { type LogEntry, setLogSink, stringifyLogEntry } from "@earendil-works/pi-ai"; +import { type LogEntry, setLogSink, stringifyLogEntry } from "@prime-intellect/prime-agent-ai"; import { appendRotatingLog, getAgentLogPath } from "../config.js"; const AGENT_LOG_MAX_BYTES = 20 * 1024 * 1024; diff --git a/packages/coding-agent/src/core/mcp/mcp-command.ts b/packages/coding-agent/src/core/mcp/mcp-command.ts index 51c2d88e37..5483d1ef85 100644 --- a/packages/coding-agent/src/core/mcp/mcp-command.ts +++ b/packages/coding-agent/src/core/mcp/mcp-command.ts @@ -1,4 +1,4 @@ -import { getCatalogEntry } from "@earendil-works/pi-ai/mcp"; +import { getCatalogEntry } from "@prime-intellect/prime-agent-ai/mcp"; import type { McpServerConfig, SettingsManager } from "../settings-manager.js"; export type McpManagementAction = "add" | "list" | "get" | "remove"; diff --git a/packages/coding-agent/src/core/mcp/mcp-manager.ts b/packages/coding-agent/src/core/mcp/mcp-manager.ts index 6031651078..4d27c6d445 100644 --- a/packages/coding-agent/src/core/mcp/mcp-manager.ts +++ b/packages/coding-agent/src/core/mcp/mcp-manager.ts @@ -6,8 +6,8 @@ import { createMcpOAuthProvider, getCatalogEntry, registerBuiltinMcpOAuthProviders, -} from "@earendil-works/pi-ai/mcp"; -import { registerOAuthProvider, unregisterOAuthProvider } from "@earendil-works/pi-ai/oauth"; +} from "@prime-intellect/prime-agent-ai/mcp"; +import { registerOAuthProvider, unregisterOAuthProvider } from "@prime-intellect/prime-agent-ai/oauth"; import type { AuthStorage } from "../auth-storage.js"; import type { McpServerConfig } from "../settings-manager.js"; import type { AcpMcpServerConfig } from "./acp-mcp-types.js"; diff --git a/packages/coding-agent/src/core/messages.ts b/packages/coding-agent/src/core/messages.ts index 81a77117f4..93b6cf76a7 100644 --- a/packages/coding-agent/src/core/messages.ts +++ b/packages/coding-agent/src/core/messages.ts @@ -5,8 +5,8 @@ * and provides a transformer to convert them to LLM-compatible messages. */ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { ImageContent, Message, TextContent } from "@earendil-works/pi-ai"; +import type { ImageContent, Message, TextContent } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; import type { AgentCronJob } from "./cron-jobs.js"; import type { AppliedRefinementEdit, HarnessScope, RefinementResult } from "./refinement/refinement.js"; import { isSessionSlashCommandName, parseSessionSlashCommand, type SessionSlashCommand } from "./slash-commands.js"; @@ -201,7 +201,7 @@ export interface CompactionSummaryMessage { timestamp: number; } -declare module "@earendil-works/pi-agent-core" { +declare module "@prime-intellect/prime-agent-core" { interface CustomAgentMessages { bashExecution: BashExecutionMessage; custom: CustomMessage; diff --git a/packages/coding-agent/src/core/model-registry.ts b/packages/coding-agent/src/core/model-registry.ts index 4ebf6c3b8d..7c985e29d0 100644 --- a/packages/coding-agent/src/core/model-registry.ts +++ b/packages/coding-agent/src/core/model-registry.ts @@ -19,9 +19,9 @@ import { registerApiProvider, resetApiProviders, type SimpleStreamOptions, -} from "@earendil-works/pi-ai"; -import { registerBuiltinMcpOAuthProviders } from "@earendil-works/pi-ai/mcp"; -import { registerOAuthProvider, resetOAuthProviders } from "@earendil-works/pi-ai/oauth"; +} from "@prime-intellect/prime-agent-ai"; +import { registerBuiltinMcpOAuthProviders } from "@prime-intellect/prime-agent-ai/mcp"; +import { registerOAuthProvider, resetOAuthProviders } from "@prime-intellect/prime-agent-ai/oauth"; import { existsSync, readFileSync, renameSync, writeFileSync } from "fs"; import { dirname, join } from "path"; import { type Static, type TProperties, Type } from "typebox"; diff --git a/packages/coding-agent/src/core/model-resolver.ts b/packages/coding-agent/src/core/model-resolver.ts index 950020e703..cd0b0bf557 100644 --- a/packages/coding-agent/src/core/model-resolver.ts +++ b/packages/coding-agent/src/core/model-resolver.ts @@ -2,8 +2,8 @@ * Model resolution, scoping, and initial selection */ -import type { ThinkingLevel } from "@earendil-works/pi-agent-core"; -import { type Api, getLogger, type KnownProvider, type Model, modelsAreEqual } from "@earendil-works/pi-ai"; +import { type Api, getLogger, type KnownProvider, type Model, modelsAreEqual } from "@prime-intellect/prime-agent-ai"; +import type { ThinkingLevel } from "@prime-intellect/prime-agent-core"; import chalk from "chalk"; import { minimatch } from "minimatch"; import { isValidThinkingLevel } from "../cli/args.js"; diff --git a/packages/coding-agent/src/core/prime-inference-auth.ts b/packages/coding-agent/src/core/prime-inference-auth.ts index f761489ec6..83f96be74e 100644 --- a/packages/coding-agent/src/core/prime-inference-auth.ts +++ b/packages/coding-agent/src/core/prime-inference-auth.ts @@ -13,7 +13,7 @@ import { } from "node:fs"; import { homedir } from "node:os"; import { basename, dirname, join } from "node:path"; -import type { OAuthAuthInfo } from "@earendil-works/pi-ai"; +import type { OAuthAuthInfo } from "@prime-intellect/prime-agent-ai"; export const PRIME_INFERENCE_PROVIDER_ID = "prime-inference"; export const PRIME_INFERENCE_PROVIDER_NAME = "Prime Inference"; diff --git a/packages/coding-agent/src/core/prime-inference-model-selection.ts b/packages/coding-agent/src/core/prime-inference-model-selection.ts index 7e3351786e..3e49f96b35 100644 --- a/packages/coding-agent/src/core/prime-inference-model-selection.ts +++ b/packages/coding-agent/src/core/prime-inference-model-selection.ts @@ -1,4 +1,4 @@ -import type { Api, Model } from "@earendil-works/pi-ai"; +import type { Api, Model } from "@prime-intellect/prime-agent-ai"; import type { ModelRegistry } from "./model-registry.js"; import { PRIME_INFERENCE_DEFAULT_MODEL_ID } from "./model-resolver.js"; import { PRIME_INFERENCE_PROVIDER_ID } from "./prime-inference-auth.js"; diff --git a/packages/coding-agent/src/core/prime-inference-models.ts b/packages/coding-agent/src/core/prime-inference-models.ts index c9af39adfa..87eaf2edb2 100644 --- a/packages/coding-agent/src/core/prime-inference-models.ts +++ b/packages/coding-agent/src/core/prime-inference-models.ts @@ -1,4 +1,4 @@ -import type { Model } from "@earendil-works/pi-ai"; +import type { Model } from "@prime-intellect/prime-agent-ai"; export const PRIME_INFERENCE_BASE_URL = "https://api.pinference.ai/api/v1"; const PRIVATE_MODEL_REFRESH_TIMEOUT_MS = 10_000; diff --git a/packages/coding-agent/src/core/refinement/refinement.ts b/packages/coding-agent/src/core/refinement/refinement.ts index 76cc701556..ea07abfc36 100644 --- a/packages/coding-agent/src/core/refinement/refinement.ts +++ b/packages/coding-agent/src/core/refinement/refinement.ts @@ -10,9 +10,9 @@ import { writeFileSync, } from "node:fs"; import { join } from "node:path"; -import type { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { Model } from "@earendil-works/pi-ai"; -import { completeSimple } from "@earendil-works/pi-ai"; +import type { Model } from "@prime-intellect/prime-agent-ai"; +import { completeSimple } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage, ThinkingLevel } from "@prime-intellect/prime-agent-core"; import { getAgentDir } from "../../config.js"; import { serializeConversation } from "../compaction/utils.js"; import { convertToLlm } from "../messages.js"; diff --git a/packages/coding-agent/src/core/rlm-runtime.ts b/packages/coding-agent/src/core/rlm-runtime.ts index 976b7b040d..5fcdfde2b2 100644 --- a/packages/coding-agent/src/core/rlm-runtime.ts +++ b/packages/coding-agent/src/core/rlm-runtime.ts @@ -1,5 +1,5 @@ -import type { ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { Api, Model, ServiceTier } from "@earendil-works/pi-ai"; +import type { Api, Model, ServiceTier } from "@prime-intellect/prime-agent-ai"; +import type { ThinkingLevel } from "@prime-intellect/prime-agent-core"; import type { AgentSession } from "./agent-session.js"; import type { ToolDefinition } from "./extensions/index.js"; import type { HostRequestHandler } from "./kernel/index.js"; diff --git a/packages/coding-agent/src/core/sdk.ts b/packages/coding-agent/src/core/sdk.ts index 72b740e980..c785fccf53 100644 --- a/packages/coding-agent/src/core/sdk.ts +++ b/packages/coding-agent/src/core/sdk.ts @@ -1,6 +1,12 @@ import { join } from "node:path"; -import { Agent, type AgentMessage, type ThinkingLevel } from "@earendil-works/pi-agent-core"; -import { clampThinkingLevel, type Message, type Model, streamSimple, supportsFastMode } from "@earendil-works/pi-ai"; +import { + clampThinkingLevel, + type Message, + type Model, + streamSimple, + supportsFastMode, +} from "@prime-intellect/prime-agent-ai"; +import { Agent, type AgentMessage, type ThinkingLevel } from "@prime-intellect/prime-agent-core"; import { getAgentDir } from "../config.js"; import { AgentSession } from "./agent-session.js"; import type { AgentSessionCreationOptions } from "./agent-session-services.js"; @@ -116,7 +122,7 @@ function getDefaultAgentDir(): string { * const { session } = await createAgentSession(); * * // With explicit model - * import { getModel } from '@earendil-works/pi-ai'; + * import { getModel } from '@prime-intellect/prime-agent-ai'; * const { session } = await createAgentSession({ * model: getModel('anthropic', 'claude-opus-4-5'), * thinkingLevel: 'high', diff --git a/packages/coding-agent/src/core/session-action-store.ts b/packages/coding-agent/src/core/session-action-store.ts index 312479986f..2e9dd25bb0 100644 --- a/packages/coding-agent/src/core/session-action-store.ts +++ b/packages/coding-agent/src/core/session-action-store.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { ImageContent, UserMessage } from "@earendil-works/pi-ai"; +import type { ImageContent, UserMessage } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; import type { InputSource } from "./extensions/index.js"; import type { CustomMessage } from "./messages.js"; import type { SessionSlashCommand } from "./slash-commands.js"; diff --git a/packages/coding-agent/src/core/session-manager.ts b/packages/coding-agent/src/core/session-manager.ts index cd6e486deb..d3a4b2f75d 100644 --- a/packages/coding-agent/src/core/session-manager.ts +++ b/packages/coding-agent/src/core/session-manager.ts @@ -1,5 +1,12 @@ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { AssistantMessage, ImageContent, Message, ServiceTier, TextContent, Usage } from "@earendil-works/pi-ai"; +import type { + AssistantMessage, + ImageContent, + Message, + ServiceTier, + TextContent, + Usage, +} from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; import { randomUUID } from "crypto"; import { appendFileSync, diff --git a/packages/coding-agent/src/core/settings-manager.ts b/packages/coding-agent/src/core/settings-manager.ts index e2b7ee8e77..d0e293bfd6 100644 --- a/packages/coding-agent/src/core/settings-manager.ts +++ b/packages/coding-agent/src/core/settings-manager.ts @@ -1,4 +1,4 @@ -import type { ServiceTier, Transport } from "@earendil-works/pi-ai"; +import type { ServiceTier, Transport } from "@prime-intellect/prime-agent-ai"; import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "fs"; import { homedir } from "os"; import { dirname, join } from "path"; diff --git a/packages/coding-agent/src/core/side-question.ts b/packages/coding-agent/src/core/side-question.ts index 02d970cd8c..d88926f037 100644 --- a/packages/coding-agent/src/core/side-question.ts +++ b/packages/coding-agent/src/core/side-question.ts @@ -1,5 +1,5 @@ -import { Agent, type AgentMessage } from "@earendil-works/pi-agent-core"; -import type { AssistantMessage, UserMessage } from "@earendil-works/pi-ai"; +import type { AssistantMessage, UserMessage } from "@prime-intellect/prime-agent-ai"; +import { Agent, type AgentMessage } from "@prime-intellect/prime-agent-core"; export type SideQuestionStatus = "running" | "complete" | "cancelled" | "error"; diff --git a/packages/coding-agent/src/core/skills.ts b/packages/coding-agent/src/core/skills.ts index 85316240fa..15e5ee0ae1 100644 --- a/packages/coding-agent/src/core/skills.ts +++ b/packages/coding-agent/src/core/skills.ts @@ -1,4 +1,4 @@ -import { getLogger } from "@earendil-works/pi-ai"; +import { getLogger } from "@prime-intellect/prime-agent-ai"; import { existsSync, readdirSync, readFileSync, statSync } from "fs"; import ignore from "ignore"; import { homedir } from "os"; diff --git a/packages/coding-agent/src/core/telemetry.ts b/packages/coding-agent/src/core/telemetry.ts index bb32bce5fd..f6a36c2fe1 100644 --- a/packages/coding-agent/src/core/telemetry.ts +++ b/packages/coding-agent/src/core/telemetry.ts @@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto"; import { lstatSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs"; import { arch, platform } from "node:os"; import { join } from "node:path"; -import type { AssistantMessage, Usage } from "@earendil-works/pi-ai"; +import type { AssistantMessage, Usage } from "@prime-intellect/prime-agent-ai"; import { detectInstallMethod, VERSION } from "../config.js"; import type { AgentSession, AgentSessionEvent } from "./agent-session.js"; import type { AgentExecutionMode } from "./agent-session-config.js"; diff --git a/packages/coding-agent/src/core/thinking-levels.ts b/packages/coding-agent/src/core/thinking-levels.ts index e7c76805f5..a35ec837ea 100644 --- a/packages/coding-agent/src/core/thinking-levels.ts +++ b/packages/coding-agent/src/core/thinking-levels.ts @@ -1,3 +1,3 @@ -import type { ThinkingLevel } from "@earendil-works/pi-agent-core"; +import type { ThinkingLevel } from "@prime-intellect/prime-agent-core"; export const THINKING_LEVELS: ThinkingLevel[] = ["off", "minimal", "low", "medium", "high", "xhigh", "max"]; diff --git a/packages/coding-agent/src/core/timings.ts b/packages/coding-agent/src/core/timings.ts index 677f0d8868..e2bff60506 100644 --- a/packages/coding-agent/src/core/timings.ts +++ b/packages/coding-agent/src/core/timings.ts @@ -3,7 +3,7 @@ * Enable with PI_TIMING=1 environment variable. */ -import { getLogger } from "@earendil-works/pi-ai"; +import { getLogger } from "@prime-intellect/prime-agent-ai"; const log = getLogger("coding-agent.timings"); const ENABLED = process.env.PI_TIMING === "1"; diff --git a/packages/coding-agent/src/core/tools/bash.ts b/packages/coding-agent/src/core/tools/bash.ts index 1541063491..c86acc1c5f 100644 --- a/packages/coding-agent/src/core/tools/bash.ts +++ b/packages/coding-agent/src/core/tools/bash.ts @@ -1,6 +1,6 @@ import { existsSync } from "node:fs"; -import type { AgentTool } from "@earendil-works/pi-agent-core"; -import { Container, Text, truncateToWidth } from "@earendil-works/pi-tui"; +import type { AgentTool } from "@prime-intellect/prime-agent-core"; +import { Container, Text, truncateToWidth } from "@prime-intellect/prime-agent-tui"; import { spawn } from "child_process"; import { type Static, Type } from "typebox"; import { expandCollapseHint } from "../../modes/interactive/components/keybinding-hints.js"; diff --git a/packages/coding-agent/src/core/tools/edit.ts b/packages/coding-agent/src/core/tools/edit.ts index df71f893f4..4ea2a31f5c 100644 --- a/packages/coding-agent/src/core/tools/edit.ts +++ b/packages/coding-agent/src/core/tools/edit.ts @@ -1,5 +1,5 @@ -import type { AgentTool } from "@earendil-works/pi-agent-core"; -import { Box, type Component, Container, Spacer, Text, wrapTextWithAnsi } from "@earendil-works/pi-tui"; +import type { AgentTool } from "@prime-intellect/prime-agent-core"; +import { Box, type Component, Container, Spacer, Text, wrapTextWithAnsi } from "@prime-intellect/prime-agent-tui"; import { constants } from "fs"; import { access as fsAccess, readFile as fsReadFile, writeFile as fsWriteFile } from "fs/promises"; import { type Static, Type } from "typebox"; diff --git a/packages/coding-agent/src/core/tools/index.ts b/packages/coding-agent/src/core/tools/index.ts index f846d0bf68..de0d3091b4 100644 --- a/packages/coding-agent/src/core/tools/index.ts +++ b/packages/coding-agent/src/core/tools/index.ts @@ -37,7 +37,7 @@ export { truncateTail, } from "./truncate.js"; -import type { AgentTool } from "@earendil-works/pi-agent-core"; +import type { AgentTool } from "@prime-intellect/prime-agent-core"; import type { ToolDefinition } from "../extensions/types.js"; import { createIpythonToolDefinition, type IpythonToolOptions } from "./ipython.js"; diff --git a/packages/coding-agent/src/core/tools/ipython.ts b/packages/coding-agent/src/core/tools/ipython.ts index 6c8501b928..0c130602d7 100644 --- a/packages/coding-agent/src/core/tools/ipython.ts +++ b/packages/coding-agent/src/core/tools/ipython.ts @@ -1,6 +1,6 @@ import { existsSync } from "node:fs"; -import type { AgentTool } from "@earendil-works/pi-agent-core"; -import type { ImageContent, TextContent } from "@earendil-works/pi-ai"; +import type { ImageContent, TextContent } from "@prime-intellect/prime-agent-ai"; +import type { AgentTool } from "@prime-intellect/prime-agent-core"; import { type Static, Type } from "typebox"; import { IMAGE_MIME_TYPES } from "../../utils/mime.js"; import { resolveKernelBashShell } from "../../utils/shell.js"; diff --git a/packages/coding-agent/src/core/tools/render-utils.ts b/packages/coding-agent/src/core/tools/render-utils.ts index 19893aa50e..01416ec17b 100644 --- a/packages/coding-agent/src/core/tools/render-utils.ts +++ b/packages/coding-agent/src/core/tools/render-utils.ts @@ -1,6 +1,6 @@ import * as os from "node:os"; -import type { ImageContent, TextContent } from "@earendil-works/pi-ai"; -import { getImageDimensions, imageFallback } from "@earendil-works/pi-tui"; +import type { ImageContent, TextContent } from "@prime-intellect/prime-agent-ai"; +import { getImageDimensions, imageFallback } from "@prime-intellect/prime-agent-tui"; import stripAnsi from "strip-ansi"; import { sanitizeBinaryOutput } from "../../utils/shell.js"; diff --git a/packages/coding-agent/src/core/tools/tool-definition-wrapper.ts b/packages/coding-agent/src/core/tools/tool-definition-wrapper.ts index 1aca3f309a..32bff669d5 100644 --- a/packages/coding-agent/src/core/tools/tool-definition-wrapper.ts +++ b/packages/coding-agent/src/core/tools/tool-definition-wrapper.ts @@ -1,4 +1,4 @@ -import type { AgentTool } from "@earendil-works/pi-agent-core"; +import type { AgentTool } from "@prime-intellect/prime-agent-core"; import type { ExtensionContext, ToolDefinition } from "../extensions/types.js"; /** Wrap a ToolDefinition into an AgentTool for the core runtime. */ diff --git a/packages/coding-agent/src/core/usage.ts b/packages/coding-agent/src/core/usage.ts index 469edbc6d9..6d5ae1cb7d 100644 --- a/packages/coding-agent/src/core/usage.ts +++ b/packages/coding-agent/src/core/usage.ts @@ -1,4 +1,4 @@ -import type { Usage } from "@earendil-works/pi-ai"; +import type { Usage } from "@prime-intellect/prime-agent-ai"; export function emptyUsage(): Usage { return { diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index b4968d66c2..b74acc88e3 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -7,9 +7,9 @@ import { join, resolve } from "node:path"; import { createInterface } from "node:readline"; -import { type Api, type ImageContent, type Model, modelsAreEqual } from "@earendil-works/pi-ai"; -import { registerBuiltinMcpOAuthProviders } from "@earendil-works/pi-ai/mcp"; -import { ProcessTerminal, setKeybindings, TUI } from "@earendil-works/pi-tui"; +import { type Api, type ImageContent, type Model, modelsAreEqual } from "@prime-intellect/prime-agent-ai"; +import { registerBuiltinMcpOAuthProviders } from "@prime-intellect/prime-agent-ai/mcp"; +import { ProcessTerminal, setKeybindings, TUI } from "@prime-intellect/prime-agent-tui"; import chalk from "chalk"; import { type Args, type Mode, parseArgs } from "./cli/args.js"; import { formatTopLevelHelp } from "./cli/command-registry.js"; diff --git a/packages/coding-agent/src/modes/acp/acp-events.ts b/packages/coding-agent/src/modes/acp/acp-events.ts index e48374c381..8b4170a3e4 100644 --- a/packages/coding-agent/src/modes/acp/acp-events.ts +++ b/packages/coding-agent/src/modes/acp/acp-events.ts @@ -1,4 +1,4 @@ -import type { AssistantMessageEvent } from "@earendil-works/pi-ai"; +import type { AssistantMessageEvent } from "@prime-intellect/prime-agent-ai"; import type { AgentConnectionSessionEvent } from "../agent-connection/types.js"; import type { PrimeAgentIpythonMeta, PrimeAgentSessionMeta } from "./acp-meta.js"; import { primeAgentMeta } from "./acp-meta.js"; diff --git a/packages/coding-agent/src/modes/acp/acp-mode.ts b/packages/coding-agent/src/modes/acp/acp-mode.ts index db1087f76c..b3883ec3fc 100644 --- a/packages/coding-agent/src/modes/acp/acp-mode.ts +++ b/packages/coding-agent/src/modes/acp/acp-mode.ts @@ -3,8 +3,8 @@ import { realpathSync, statSync } from "node:fs"; import { resolve } from "node:path"; import { Readable } from "node:stream"; import * as acp from "@agentclientprotocol/sdk"; -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { ImageContent } from "@earendil-works/pi-ai"; +import type { ImageContent } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; import { VERSION } from "../../config.js"; import type { AgentSessionRuntime } from "../../core/agent-session-runtime.js"; import type { AgentAutonomousStatus } from "../../core/autonomous.js"; diff --git a/packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts b/packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts index 722c2895be..aaad3c226d 100644 --- a/packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts +++ b/packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts @@ -1,6 +1,6 @@ import { randomUUID } from "node:crypto"; -import type { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { ImageContent, ServiceTier, Transport } from "@earendil-works/pi-ai"; +import type { ImageContent, ServiceTier, Transport } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage, ThinkingLevel } from "@prime-intellect/prime-agent-core"; import { appendRotatingLog, getAgentLogPath, getDaemonLogPath } from "../../config.js"; import type { AgentSessionMessageReceipt, AgentSessionMessageSafetyStatus } from "../../core/agent-messages.js"; import type { AgentSessionEvent } from "../../core/agent-session.js"; diff --git a/packages/coding-agent/src/modes/agent-connection/in-process-agent-connection.ts b/packages/coding-agent/src/modes/agent-connection/in-process-agent-connection.ts index 9fc5851d1e..db156f59b4 100644 --- a/packages/coding-agent/src/modes/agent-connection/in-process-agent-connection.ts +++ b/packages/coding-agent/src/modes/agent-connection/in-process-agent-connection.ts @@ -1,6 +1,6 @@ import { resolve } from "node:path"; -import type { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { ImageContent, ServiceTier, Transport } from "@earendil-works/pi-ai"; +import type { ImageContent, ServiceTier, Transport } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage, ThinkingLevel } from "@prime-intellect/prime-agent-core"; import type { AgentSessionMessageReceipt, AgentSessionMessageSafetyStatus } from "../../core/agent-messages.js"; import type { AgentSessionRuntime } from "../../core/agent-session-runtime.js"; import { flushAllPendingAgentTraceUploads } from "../../core/agent-traces.js"; diff --git a/packages/coding-agent/src/modes/agent-connection/snapshot.ts b/packages/coding-agent/src/modes/agent-connection/snapshot.ts index 3b08cc4cda..c9a85a6cba 100644 --- a/packages/coding-agent/src/modes/agent-connection/snapshot.ts +++ b/packages/coding-agent/src/modes/agent-connection/snapshot.ts @@ -1,6 +1,6 @@ import { createHash } from "node:crypto"; import { basename, isAbsolute, relative, resolve, sep } from "node:path"; -import type { Api, Model } from "@earendil-works/pi-ai"; +import type { Api, Model } from "@prime-intellect/prime-agent-ai"; import type { AgentSession } from "../../core/agent-session.js"; import type { AgentSessionRuntime } from "../../core/agent-session-runtime.js"; import type { diff --git a/packages/coding-agent/src/modes/agent-connection/types.ts b/packages/coding-agent/src/modes/agent-connection/types.ts index 67408cd347..43f8c7a953 100644 --- a/packages/coding-agent/src/modes/agent-connection/types.ts +++ b/packages/coding-agent/src/modes/agent-connection/types.ts @@ -1,5 +1,13 @@ -import type { AgentEvent, AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { Api, ImageContent, Model, ServiceTier, TextContent, Transport, Usage } from "@earendil-works/pi-ai"; +import type { + Api, + ImageContent, + Model, + ServiceTier, + TextContent, + Transport, + Usage, +} from "@prime-intellect/prime-agent-ai"; +import type { AgentEvent, AgentMessage, ThinkingLevel } from "@prime-intellect/prime-agent-core"; import type { AgentSessionMessageReceipt, AgentSessionMessageSafetyStatus } from "../../core/agent-messages.js"; import type { AuthSourceToken } from "../../core/auth-storage.js"; import type { AgentAutonomousStatus } from "../../core/autonomous.js"; diff --git a/packages/coding-agent/src/modes/agents-view/agents-view-mode.ts b/packages/coding-agent/src/modes/agents-view/agents-view-mode.ts index d674c86d7f..b7848d2c3e 100644 --- a/packages/coding-agent/src/modes/agents-view/agents-view-mode.ts +++ b/packages/coding-agent/src/modes/agents-view/agents-view-mode.ts @@ -12,7 +12,7 @@ import { truncateToWidth, visibleWidth, wrapTextWithAnsi, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { APP_TITLE, appendRotatingLog, getAgentDir, getClientErrorLogPath, VERSION } from "../../config.js"; import type { AgentSessionRuntimeConfig } from "../../core/agent-session-config.js"; import { KeybindingsManager } from "../../core/keybindings.js"; diff --git a/packages/coding-agent/src/modes/agents-view/session-view-search.ts b/packages/coding-agent/src/modes/agents-view/session-view-search.ts index ef36814b1f..c3c5bae17d 100644 --- a/packages/coding-agent/src/modes/agents-view/session-view-search.ts +++ b/packages/coding-agent/src/modes/agents-view/session-view-search.ts @@ -1,4 +1,4 @@ -import { fuzzyMatch } from "@earendil-works/pi-tui"; +import { fuzzyMatch } from "@prime-intellect/prime-agent-tui"; export interface ParsedSearchQuery { mode: "tokens" | "regex"; tokens: { kind: "fuzzy" | "phrase"; value: string }[]; diff --git a/packages/coding-agent/src/modes/daemon/compact-session-stream.ts b/packages/coding-agent/src/modes/daemon/compact-session-stream.ts index d8e5cb2b86..4b7fb72f05 100644 --- a/packages/coding-agent/src/modes/daemon/compact-session-stream.ts +++ b/packages/coding-agent/src/modes/daemon/compact-session-stream.ts @@ -1,4 +1,4 @@ -import { type AssistantMessage, type AssistantMessageEvent, parseStreamingJson } from "@earendil-works/pi-ai"; +import { type AssistantMessage, type AssistantMessageEvent, parseStreamingJson } from "@prime-intellect/prime-agent-ai"; import type { DaemonEventMeta, DaemonOutbound } from "./daemon-protocol.js"; type SessionEvent = Extract["event"]; diff --git a/packages/coding-agent/src/modes/daemon/daemon-mode.ts b/packages/coding-agent/src/modes/daemon/daemon-mode.ts index e9d0b1f4d3..0df748beec 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-mode.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-mode.ts @@ -12,7 +12,7 @@ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync import { stat } from "node:fs/promises"; import { createConnection, createServer, type Server, type Socket } from "node:net"; import { basename, dirname, isAbsolute, join, resolve } from "node:path"; -import { type Api, getLogger, type Model } from "@earendil-works/pi-ai"; +import { type Api, getLogger, type Model } from "@prime-intellect/prime-agent-ai"; import { createCliSubprocessEnv, createCliSubprocessLaunchSpec } from "../../cli/subprocess-launch.js"; import { appendRotatingLog, diff --git a/packages/coding-agent/src/modes/daemon/daemon-protocol.ts b/packages/coding-agent/src/modes/daemon/daemon-protocol.ts index 707009989f..b134426d5e 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-protocol.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-protocol.ts @@ -1,5 +1,5 @@ -import type { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { ImageContent, ServiceTier, TextContent, Transport } from "@earendil-works/pi-ai"; +import type { ImageContent, ServiceTier, TextContent, Transport } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage, ThinkingLevel } from "@prime-intellect/prime-agent-core"; import type { AgentSessionMessageDeliveryMode, AgentSessionMessageReceipt, diff --git a/packages/coding-agent/src/modes/daemon/daemon-session-list.ts b/packages/coding-agent/src/modes/daemon/daemon-session-list.ts index 6155d703f6..993a91945f 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-session-list.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-session-list.ts @@ -1,7 +1,7 @@ import { statSync } from "node:fs"; import { resolve } from "node:path"; -import type { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { Api, Model } from "@earendil-works/pi-ai"; +import type { Api, Model } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage, ThinkingLevel } from "@prime-intellect/prime-agent-core"; import { compactRlmText } from "../../core/agent-session.js"; import type { AgentSessionRuntimeDiagnostic } from "../../core/agent-session-services.js"; import { type AgentCronJob, isHeartbeatCronJob } from "../../core/cron-jobs.js"; diff --git a/packages/coding-agent/src/modes/daemon/daemon-session-summarizer.ts b/packages/coding-agent/src/modes/daemon/daemon-session-summarizer.ts index 1af8a1cbd6..6106a5af1b 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-session-summarizer.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-session-summarizer.ts @@ -1,6 +1,6 @@ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { Api, Model } from "@earendil-works/pi-ai"; -import { completeSimple } from "@earendil-works/pi-ai"; +import type { Api, Model } from "@prime-intellect/prime-agent-ai"; +import { completeSimple } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; import type { ModelRegistry } from "../../core/model-registry.js"; import type { AgentStatus, AgentTaskState } from "../../core/session-manager.js"; import type { ActiveSessionState } from "./active-session-state.js"; diff --git a/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts b/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts index c50c81b8bb..8e95fa76ed 100644 --- a/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts +++ b/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts @@ -4,7 +4,7 @@ import { chmodSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, wr import { createServer, type Server, type Socket } from "node:net"; import { basename, dirname, join, resolve } from "node:path"; import { Writable } from "node:stream"; -import { getLogger } from "@earendil-works/pi-ai"; +import { getLogger } from "@prime-intellect/prime-agent-ai"; import { createCliSubprocessEnv, createCliSubprocessLaunchSpec } from "../../cli/subprocess-launch.js"; import { appendRotatingLog, diff --git a/packages/coding-agent/src/modes/daemon/snapshot-transcript-cache.ts b/packages/coding-agent/src/modes/daemon/snapshot-transcript-cache.ts index 874c5632e7..0c56e43e3f 100644 --- a/packages/coding-agent/src/modes/daemon/snapshot-transcript-cache.ts +++ b/packages/coding-agent/src/modes/daemon/snapshot-transcript-cache.ts @@ -1,6 +1,6 @@ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; export const SNAPSHOT_TARGET_CHUNK_BYTES = 512 * 1024; export const SNAPSHOT_MEMORY_CACHE_BYTES = 4 * 1024 * 1024; diff --git a/packages/coding-agent/src/modes/headless-completion.ts b/packages/coding-agent/src/modes/headless-completion.ts index e6524d314e..8469f4fb65 100644 --- a/packages/coding-agent/src/modes/headless-completion.ts +++ b/packages/coding-agent/src/modes/headless-completion.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { AssistantMessage } from "@earendil-works/pi-ai"; +import type { AssistantMessage } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; import type { AgentSession } from "../core/agent-session.js"; import { type AgentAutonomousStatus, diff --git a/packages/coding-agent/src/modes/interactive/auth-flows.ts b/packages/coding-agent/src/modes/interactive/auth-flows.ts index 80e7b2378e..e600f6fde7 100644 --- a/packages/coding-agent/src/modes/interactive/auth-flows.ts +++ b/packages/coding-agent/src/modes/interactive/auth-flows.ts @@ -1,6 +1,6 @@ import * as path from "node:path"; -import { getProviders, type OAuthProviderId, type OAuthSelectPrompt } from "@earendil-works/pi-ai"; -import type { OverlayHandle, TUI } from "@earendil-works/pi-tui"; +import { getProviders, type OAuthProviderId, type OAuthSelectPrompt } from "@prime-intellect/prime-agent-ai"; +import type { OverlayHandle, TUI } from "@prime-intellect/prime-agent-tui"; import { getAuthPath, getDocsPath } from "../../config.js"; import type { ModelRegistry } from "../../core/model-registry.js"; import { diff --git a/packages/coding-agent/src/modes/interactive/components/agent-message.ts b/packages/coding-agent/src/modes/interactive/components/agent-message.ts index cf6845a495..9f617da1df 100644 --- a/packages/coding-agent/src/modes/interactive/components/agent-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/agent-message.ts @@ -7,7 +7,7 @@ import { truncateToWidth, visibleWidth, wrapTextWithAnsi, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { type AgentSessionMessage, formatAgentMessageParticipant } from "../../../core/agent-messages.js"; import { getMarkdownTheme, theme } from "../theme/theme.js"; import { expandCollapseHint } from "./keybinding-hints.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/armin.ts b/packages/coding-agent/src/modes/interactive/components/armin.ts index 794e5562ab..0cc1567630 100644 --- a/packages/coding-agent/src/modes/interactive/components/armin.ts +++ b/packages/coding-agent/src/modes/interactive/components/armin.ts @@ -2,7 +2,7 @@ * Armin says hi! A fun easter egg with animated XBM art. */ -import type { Component, TUI } from "@earendil-works/pi-tui"; +import type { Component, TUI } from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; // XBM image: 31x36 pixels, LSB first, 1=background, 0=foreground diff --git a/packages/coding-agent/src/modes/interactive/components/assistant-message.ts b/packages/coding-agent/src/modes/interactive/components/assistant-message.ts index a39279bfe5..42a4d26255 100644 --- a/packages/coding-agent/src/modes/interactive/components/assistant-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/assistant-message.ts @@ -1,4 +1,4 @@ -import type { AssistantMessage } from "@earendil-works/pi-ai"; +import type { AssistantMessage } from "@prime-intellect/prime-agent-ai"; import { type Component, Container, @@ -8,7 +8,7 @@ import { Text, truncateToWidth, visibleWidth, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { LOGIN_RECOVERY_MESSAGE } from "../../../core/auth-guidance.js"; import { getMarkdownTheme, theme } from "../theme/theme.js"; import { diff --git a/packages/coding-agent/src/modes/interactive/components/bash-execution.ts b/packages/coding-agent/src/modes/interactive/components/bash-execution.ts index 2026e3fec9..b4ca25c26f 100644 --- a/packages/coding-agent/src/modes/interactive/components/bash-execution.ts +++ b/packages/coding-agent/src/modes/interactive/components/bash-execution.ts @@ -1,4 +1,4 @@ -import { Container, Loader, Spacer, Text, type TUI } from "@earendil-works/pi-tui"; +import { Container, Loader, Spacer, Text, type TUI } from "@prime-intellect/prime-agent-tui"; import stripAnsi from "strip-ansi"; import { DEFAULT_MAX_BYTES, diff --git a/packages/coding-agent/src/modes/interactive/components/bordered-loader.ts b/packages/coding-agent/src/modes/interactive/components/bordered-loader.ts index 916e4af5d2..4f05bc36c9 100644 --- a/packages/coding-agent/src/modes/interactive/components/bordered-loader.ts +++ b/packages/coding-agent/src/modes/interactive/components/bordered-loader.ts @@ -1,4 +1,4 @@ -import { CancellableLoader, Container, Loader, Spacer, Text, type TUI } from "@earendil-works/pi-tui"; +import { CancellableLoader, Container, Loader, Spacer, Text, type TUI } from "@prime-intellect/prime-agent-tui"; import type { Theme } from "../theme/theme.js"; import { DynamicBorder } from "./dynamic-border.js"; import { keyHint } from "./keybinding-hints.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/branch-summary-message.ts b/packages/coding-agent/src/modes/interactive/components/branch-summary-message.ts index 1aa49bb7a8..86dbd54ccb 100644 --- a/packages/coding-agent/src/modes/interactive/components/branch-summary-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/branch-summary-message.ts @@ -1,4 +1,4 @@ -import { Box, Markdown, type MarkdownTheme, Spacer, Text } from "@earendil-works/pi-tui"; +import { Box, Markdown, type MarkdownTheme, Spacer, Text } from "@prime-intellect/prime-agent-tui"; import type { BranchSummaryMessage } from "../../../core/messages.js"; import { getMarkdownTheme, theme } from "../theme/theme.js"; import { expandCollapseHint } from "./keybinding-hints.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/centered-overlay.ts b/packages/coding-agent/src/modes/interactive/components/centered-overlay.ts index 9f66f05c70..4b701f640d 100644 --- a/packages/coding-agent/src/modes/interactive/components/centered-overlay.ts +++ b/packages/coding-agent/src/modes/interactive/components/centered-overlay.ts @@ -7,7 +7,7 @@ import { type TUI, truncateToWidth, visibleWidth, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; interface CenteredOverlayOptions { getRows: () => number; diff --git a/packages/coding-agent/src/modes/interactive/components/collapsible-error.ts b/packages/coding-agent/src/modes/interactive/components/collapsible-error.ts index 247b260e5f..e28a931207 100644 --- a/packages/coding-agent/src/modes/interactive/components/collapsible-error.ts +++ b/packages/coding-agent/src/modes/interactive/components/collapsible-error.ts @@ -1,4 +1,4 @@ -import { type Component, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui"; +import { type Component, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@prime-intellect/prime-agent-tui"; import stripAnsi from "strip-ansi"; import { theme } from "../theme/theme.js"; import { expandCollapseHint } from "./keybinding-hints.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/compaction-outcome-message.ts b/packages/coding-agent/src/modes/interactive/components/compaction-outcome-message.ts index 8772901833..38ae2eaa5f 100644 --- a/packages/coding-agent/src/modes/interactive/components/compaction-outcome-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/compaction-outcome-message.ts @@ -1,4 +1,4 @@ -import { Box, Container, Text } from "@earendil-works/pi-tui"; +import { Box, Container, Text } from "@prime-intellect/prime-agent-tui"; import type { CompactionOutcomeMessage } from "../../../core/messages.js"; import { theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/compaction-summary-message.ts b/packages/coding-agent/src/modes/interactive/components/compaction-summary-message.ts index 653dbfa22b..4bb95060f8 100644 --- a/packages/coding-agent/src/modes/interactive/components/compaction-summary-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/compaction-summary-message.ts @@ -1,4 +1,4 @@ -import { Markdown, type MarkdownTheme, Spacer, Text } from "@earendil-works/pi-tui"; +import { Markdown, type MarkdownTheme, Spacer, Text } from "@prime-intellect/prime-agent-tui"; import type { CompactionSummaryMessage } from "../../../core/messages.js"; import { getMarkdownTheme, theme } from "../theme/theme.js"; import { customMessageLabel, ExpandableCustomMessageBox } from "./expandable-custom-message.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/config-selector.ts b/packages/coding-agent/src/modes/interactive/components/config-selector.ts index 208456f9bd..041d69d10e 100644 --- a/packages/coding-agent/src/modes/interactive/components/config-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/config-selector.ts @@ -13,7 +13,7 @@ import { Spacer, truncateToWidth, visibleWidth, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { CONFIG_DIR_NAME } from "../../../config.js"; import type { PathMetadata, ResolvedPaths, ResolvedResource } from "../../../core/package-manager.js"; import type { PackageSource, SettingsManager } from "../../../core/settings-manager.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/configuration-menu.ts b/packages/coding-agent/src/modes/interactive/components/configuration-menu.ts index ce269c7634..51184a1a83 100644 --- a/packages/coding-agent/src/modes/interactive/components/configuration-menu.ts +++ b/packages/coding-agent/src/modes/interactive/components/configuration-menu.ts @@ -1,4 +1,4 @@ -import type { Api, Model } from "@earendil-works/pi-ai"; +import type { Api, Model } from "@prime-intellect/prime-agent-ai"; import { type Component, Container, @@ -7,7 +7,7 @@ import { type TUI, visibleWidth, wrapTextWithAnsi, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import type { AuthStorage } from "../../../core/auth-storage.js"; import type { ModelRegistry } from "../../../core/model-registry.js"; import { theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/context-tree-format.ts b/packages/coding-agent/src/modes/interactive/components/context-tree-format.ts index fd0129cf70..747fccd657 100644 --- a/packages/coding-agent/src/modes/interactive/components/context-tree-format.ts +++ b/packages/coding-agent/src/modes/interactive/components/context-tree-format.ts @@ -1,5 +1,5 @@ -import type { Usage } from "@earendil-works/pi-ai"; -import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import type { Usage } from "@prime-intellect/prime-agent-ai"; +import { truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; import type { ContextTreeNode } from "../../../core/context-tree.js"; import type { ContextUsage } from "../../../core/extensions/index.js"; import { addAssistantUsage, emptyUsage } from "../../../core/usage.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/conversation-components.ts b/packages/coding-agent/src/modes/interactive/components/conversation-components.ts index 8e06264658..2b3ad6b4b6 100644 --- a/packages/coding-agent/src/modes/interactive/components/conversation-components.ts +++ b/packages/coding-agent/src/modes/interactive/components/conversation-components.ts @@ -1,5 +1,5 @@ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { Component, MarkdownTheme, TUI } from "@earendil-works/pi-tui"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; +import type { Component, MarkdownTheme, TUI } from "@prime-intellect/prime-agent-tui"; import { isAgentSessionMessage } from "../../../core/agent-messages.js"; import { COMPACTION_OUTCOME_CUSTOM_TYPE, diff --git a/packages/coding-agent/src/modes/interactive/components/countdown-timer.ts b/packages/coding-agent/src/modes/interactive/components/countdown-timer.ts index 43d07f3116..a8c59e53c9 100644 --- a/packages/coding-agent/src/modes/interactive/components/countdown-timer.ts +++ b/packages/coding-agent/src/modes/interactive/components/countdown-timer.ts @@ -1,4 +1,4 @@ -import type { TUI } from "@earendil-works/pi-tui"; +import type { TUI } from "@prime-intellect/prime-agent-tui"; export class CountdownTimer { private intervalId: ReturnType | undefined; diff --git a/packages/coding-agent/src/modes/interactive/components/custom-editor.ts b/packages/coding-agent/src/modes/interactive/components/custom-editor.ts index 058e4076be..b881521f6d 100644 --- a/packages/coding-agent/src/modes/interactive/components/custom-editor.ts +++ b/packages/coding-agent/src/modes/interactive/components/custom-editor.ts @@ -6,7 +6,7 @@ import { type TUI, truncateToWidth, visibleWidth, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import type { AppKeybinding, KeybindingsManager } from "../../../core/keybindings.js"; export interface CustomEditorOptions extends EditorOptions { diff --git a/packages/coding-agent/src/modes/interactive/components/custom-message.ts b/packages/coding-agent/src/modes/interactive/components/custom-message.ts index a6840c347b..3274971215 100644 --- a/packages/coding-agent/src/modes/interactive/components/custom-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/custom-message.ts @@ -1,6 +1,6 @@ -import type { TextContent } from "@earendil-works/pi-ai"; -import type { Component } from "@earendil-works/pi-tui"; -import { Box, Container, Markdown, type MarkdownTheme, Spacer, Text } from "@earendil-works/pi-tui"; +import type { TextContent } from "@prime-intellect/prime-agent-ai"; +import type { Component } from "@prime-intellect/prime-agent-tui"; +import { Box, Container, Markdown, type MarkdownTheme, Spacer, Text } from "@prime-intellect/prime-agent-tui"; import type { MessageRenderer } from "../../../core/extensions/types.js"; import type { CustomMessage } from "../../../core/messages.js"; import { getMarkdownTheme, theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/daxnuts.ts b/packages/coding-agent/src/modes/interactive/components/daxnuts.ts index bfc4dbaa20..60da1be5aa 100644 --- a/packages/coding-agent/src/modes/interactive/components/daxnuts.ts +++ b/packages/coding-agent/src/modes/interactive/components/daxnuts.ts @@ -4,7 +4,7 @@ * A heartfelt tribute to dax (@thdxr) for providing free Kimi K2.5 access via OpenCode. */ -import type { Component, TUI } from "@earendil-works/pi-tui"; +import type { Component, TUI } from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; // 32x32 RGB image of dax, hex encoded (3 bytes per pixel) diff --git a/packages/coding-agent/src/modes/interactive/components/diff.ts b/packages/coding-agent/src/modes/interactive/components/diff.ts index 36f939b318..29717fe023 100644 --- a/packages/coding-agent/src/modes/interactive/components/diff.ts +++ b/packages/coding-agent/src/modes/interactive/components/diff.ts @@ -1,4 +1,4 @@ -import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui"; +import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@prime-intellect/prime-agent-tui"; import * as Diff from "diff"; import { highlightCode, theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/dynamic-border.ts b/packages/coding-agent/src/modes/interactive/components/dynamic-border.ts index d4fa67c401..6a278a6bf6 100644 --- a/packages/coding-agent/src/modes/interactive/components/dynamic-border.ts +++ b/packages/coding-agent/src/modes/interactive/components/dynamic-border.ts @@ -1,4 +1,4 @@ -import type { Component } from "@earendil-works/pi-tui"; +import type { Component } from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; /** diff --git a/packages/coding-agent/src/modes/interactive/components/earendil-announcement.ts b/packages/coding-agent/src/modes/interactive/components/earendil-announcement.ts index 6f5a0bde5c..e1b1c8e2c3 100644 --- a/packages/coding-agent/src/modes/interactive/components/earendil-announcement.ts +++ b/packages/coding-agent/src/modes/interactive/components/earendil-announcement.ts @@ -1,5 +1,5 @@ import * as fs from "node:fs"; -import { Container, Image, Spacer, Text } from "@earendil-works/pi-tui"; +import { Container, Image, Spacer, Text } from "@prime-intellect/prime-agent-tui"; import { getBundledInteractiveAssetPath } from "../../../config.js"; import { theme } from "../theme/theme.js"; import { DynamicBorder } from "./dynamic-border.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/edit-summary.ts b/packages/coding-agent/src/modes/interactive/components/edit-summary.ts index dacf64e261..3df57f1082 100644 --- a/packages/coding-agent/src/modes/interactive/components/edit-summary.ts +++ b/packages/coding-agent/src/modes/interactive/components/edit-summary.ts @@ -1,7 +1,7 @@ import { isAbsolute } from "node:path"; -import type { AgentMessage } from "@earendil-works/pi-agent-core"; -import type { ToolResultMessage } from "@earendil-works/pi-ai"; -import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import type { ToolResultMessage } from "@prime-intellect/prime-agent-ai"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; +import { truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; import type { EditToolDetails } from "../../../core/tools/edit.js"; import { generateDiffString } from "../../../core/tools/edit-diff.js"; import type { IpythonToolDetails } from "../../../core/tools/ipython.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/expandable-custom-message.ts b/packages/coding-agent/src/modes/interactive/components/expandable-custom-message.ts index c397a51b08..3cf00f2a49 100644 --- a/packages/coding-agent/src/modes/interactive/components/expandable-custom-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/expandable-custom-message.ts @@ -1,4 +1,4 @@ -import { Box } from "@earendil-works/pi-tui"; +import { Box } from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; /** diff --git a/packages/coding-agent/src/modes/interactive/components/extension-editor.ts b/packages/coding-agent/src/modes/interactive/components/extension-editor.ts index e0cf071db3..fbdd20e684 100644 --- a/packages/coding-agent/src/modes/interactive/components/extension-editor.ts +++ b/packages/coding-agent/src/modes/interactive/components/extension-editor.ts @@ -11,7 +11,7 @@ import { Spacer, Text, type TUI, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import type { KeybindingsManager } from "../../../core/keybindings.js"; import { getEditorTheme, theme } from "../theme/theme.js"; import { DynamicBorder } from "./dynamic-border.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/extension-input.ts b/packages/coding-agent/src/modes/interactive/components/extension-input.ts index 39f44f0fc6..f96059eb1b 100644 --- a/packages/coding-agent/src/modes/interactive/components/extension-input.ts +++ b/packages/coding-agent/src/modes/interactive/components/extension-input.ts @@ -2,7 +2,15 @@ * Simple text input component for extensions. */ -import { Container, type Focusable, getKeybindings, Input, Spacer, Text, type TUI } from "@earendil-works/pi-tui"; +import { + Container, + type Focusable, + getKeybindings, + Input, + Spacer, + Text, + type TUI, +} from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; import { CountdownTimer } from "./countdown-timer.js"; import { DynamicBorder } from "./dynamic-border.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/extension-selector.ts b/packages/coding-agent/src/modes/interactive/components/extension-selector.ts index c9dec2cd11..ca65d3b0ab 100644 --- a/packages/coding-agent/src/modes/interactive/components/extension-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/extension-selector.ts @@ -3,7 +3,7 @@ * Displays a list of string options with keyboard navigation. */ -import { Container, getKeybindings, Spacer, Text, type TUI } from "@earendil-works/pi-tui"; +import { Container, getKeybindings, Spacer, Text, type TUI } from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; import { CountdownTimer } from "./countdown-timer.js"; import { keyHint, rawKeyHint } from "./keybinding-hints.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/feature-hint.ts b/packages/coding-agent/src/modes/interactive/components/feature-hint.ts index acbe3aa420..7c155973ea 100644 --- a/packages/coding-agent/src/modes/interactive/components/feature-hint.ts +++ b/packages/coding-agent/src/modes/interactive/components/feature-hint.ts @@ -1,4 +1,4 @@ -import { type Component, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import { type Component, truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; const LABEL = "Hint:"; diff --git a/packages/coding-agent/src/modes/interactive/components/footer.ts b/packages/coding-agent/src/modes/interactive/components/footer.ts index a8afd00ebe..2798a58667 100644 --- a/packages/coding-agent/src/modes/interactive/components/footer.ts +++ b/packages/coding-agent/src/modes/interactive/components/footer.ts @@ -1,4 +1,4 @@ -import type { Component } from "@earendil-works/pi-tui"; +import type { Component } from "@prime-intellect/prime-agent-tui"; import type { ReadonlyFooterDataProvider } from "../../../core/footer-data-provider.js"; /** diff --git a/packages/coding-agent/src/modes/interactive/components/heartbeat-manager.ts b/packages/coding-agent/src/modes/interactive/components/heartbeat-manager.ts index 28e9344ec7..1044bf8422 100644 --- a/packages/coding-agent/src/modes/interactive/components/heartbeat-manager.ts +++ b/packages/coding-agent/src/modes/interactive/components/heartbeat-manager.ts @@ -1,4 +1,10 @@ -import { type Component, type Focusable, getKeybindings, Spacer, TruncatedText } from "@earendil-works/pi-tui"; +import { + type Component, + type Focusable, + getKeybindings, + Spacer, + TruncatedText, +} from "@prime-intellect/prime-agent-tui"; import type { AgentHeartbeatManagementAction } from "../../../core/cron-jobs.js"; import type { AgentConnectionHeartbeat } from "../../agent-connection/types.js"; import { theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/injected-prompt-message.ts b/packages/coding-agent/src/modes/interactive/components/injected-prompt-message.ts index 6893496870..6abed9e3bc 100644 --- a/packages/coding-agent/src/modes/interactive/components/injected-prompt-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/injected-prompt-message.ts @@ -1,4 +1,4 @@ -import type { AgentMessage } from "@earendil-works/pi-agent-core"; +import type { AgentMessage } from "@prime-intellect/prime-agent-core"; import { Container, Markdown, @@ -7,7 +7,7 @@ import { Text, truncateToWidth, visibleWidth, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { GOAL_CONTEXT_CUSTOM_TYPE, type GoalContextDetails } from "../../../core/goals.js"; import { type CustomMessage, diff --git a/packages/coding-agent/src/modes/interactive/components/ipython-cell.ts b/packages/coding-agent/src/modes/interactive/components/ipython-cell.ts index 97be0c4c11..49e3d38d2e 100644 --- a/packages/coding-agent/src/modes/interactive/components/ipython-cell.ts +++ b/packages/coding-agent/src/modes/interactive/components/ipython-cell.ts @@ -4,7 +4,7 @@ import { VersionedRenderCache, visibleWidth, wrapTextWithAnsi, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { formatAgentMessageParticipant } from "../../../core/agent-messages.js"; import { previewIpythonCode } from "../../../core/tools/code-preview.js"; import { generateDiffString } from "../../../core/tools/edit-diff.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/keybinding-hints.ts b/packages/coding-agent/src/modes/interactive/components/keybinding-hints.ts index 22d681d7c1..ad76bd7346 100644 --- a/packages/coding-agent/src/modes/interactive/components/keybinding-hints.ts +++ b/packages/coding-agent/src/modes/interactive/components/keybinding-hints.ts @@ -2,7 +2,7 @@ * Utilities for formatting keybinding hints in the UI. */ -import { getKeybindings, type Keybinding, type KeyId } from "@earendil-works/pi-tui"; +import { getKeybindings, type Keybinding, type KeyId } from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; export interface KeyTextOptions { diff --git a/packages/coding-agent/src/modes/interactive/components/login-dialog.ts b/packages/coding-agent/src/modes/interactive/components/login-dialog.ts index be41de0a3b..faf309b43b 100644 --- a/packages/coding-agent/src/modes/interactive/components/login-dialog.ts +++ b/packages/coding-agent/src/modes/interactive/components/login-dialog.ts @@ -1,5 +1,5 @@ import { win32 } from "node:path"; -import { getOAuthProviders } from "@earendil-works/pi-ai/oauth"; +import { getOAuthProviders } from "@prime-intellect/prime-agent-ai/oauth"; import { type Component, Container, @@ -11,7 +11,7 @@ import { type TUI, truncateToWidth, visibleWidth, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { execFile } from "child_process"; import { PRIME_BUTTERFLY_LOGO } from "../../../themes/prime-logo.js"; import { copyToClipboard } from "../../../utils/clipboard.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/menu-panel.ts b/packages/coding-agent/src/modes/interactive/components/menu-panel.ts index f9e6899d2c..ad5bd28e1d 100644 --- a/packages/coding-agent/src/modes/interactive/components/menu-panel.ts +++ b/packages/coding-agent/src/modes/interactive/components/menu-panel.ts @@ -6,7 +6,7 @@ import { truncateToWidth, visibleWidth, wrapTextWithAnsi, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; interface MenuPanelOptions { diff --git a/packages/coding-agent/src/modes/interactive/components/modal-back.ts b/packages/coding-agent/src/modes/interactive/components/modal-back.ts index 7a04a98560..04e34c29bb 100644 --- a/packages/coding-agent/src/modes/interactive/components/modal-back.ts +++ b/packages/coding-agent/src/modes/interactive/components/modal-back.ts @@ -9,7 +9,7 @@ * existing `onAgentsBack` guard so behaviour stays consistent across the app. */ -import { getKeybindings } from "@earendil-works/pi-tui"; +import { getKeybindings } from "@prime-intellect/prime-agent-tui"; /** A text input whose cursor position can be inspected. */ export interface BackGuardInput { diff --git a/packages/coding-agent/src/modes/interactive/components/model-selector.ts b/packages/coding-agent/src/modes/interactive/components/model-selector.ts index 58a08eb319..942bda42ed 100644 --- a/packages/coding-agent/src/modes/interactive/components/model-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/model-selector.ts @@ -1,4 +1,4 @@ -import { type Model, modelsAreEqual } from "@earendil-works/pi-ai"; +import { type Model, modelsAreEqual } from "@prime-intellect/prime-agent-ai"; import { type Component, Container, @@ -8,7 +8,7 @@ import { Spacer, Text, type TUI, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import type { ModelRegistry } from "../../../core/model-registry.js"; import { theme } from "../theme/theme.js"; import { keyHint } from "./keybinding-hints.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/oauth-selector.ts b/packages/coding-agent/src/modes/interactive/components/oauth-selector.ts index 7ea9ec50aa..d111453f40 100644 --- a/packages/coding-agent/src/modes/interactive/components/oauth-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/oauth-selector.ts @@ -6,7 +6,7 @@ import { getKeybindings, Spacer, TruncatedText, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import type { AuthStatus, AuthStorage } from "../../../core/auth-storage.js"; import { PRIME_INFERENCE_PROVIDER_ID } from "../../../core/prime-inference-auth.js"; import { theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/prime-onboarding-splash.ts b/packages/coding-agent/src/modes/interactive/components/prime-onboarding-splash.ts index 5cc7dfe945..605d3e172a 100644 --- a/packages/coding-agent/src/modes/interactive/components/prime-onboarding-splash.ts +++ b/packages/coding-agent/src/modes/interactive/components/prime-onboarding-splash.ts @@ -1,4 +1,4 @@ -import { type Component, getKeybindings, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import { type Component, getKeybindings, truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; import { PRIME_BUTTERFLY_LOGO } from "../../../themes/prime-logo.js"; import { type ThemeColor, theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/prime-team-selector.ts b/packages/coding-agent/src/modes/interactive/components/prime-team-selector.ts index 62b438815d..274ff22b39 100644 --- a/packages/coding-agent/src/modes/interactive/components/prime-team-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/prime-team-selector.ts @@ -1,4 +1,11 @@ -import { Container, type Focusable, fuzzyFilter, getKeybindings, Spacer, TruncatedText } from "@earendil-works/pi-tui"; +import { + Container, + type Focusable, + fuzzyFilter, + getKeybindings, + Spacer, + TruncatedText, +} from "@prime-intellect/prime-agent-tui"; import type { PrimeTeam } from "../../../core/prime-inference-auth.js"; import { theme } from "../theme/theme.js"; import { diff --git a/packages/coding-agent/src/modes/interactive/components/refinement-outcome-message.ts b/packages/coding-agent/src/modes/interactive/components/refinement-outcome-message.ts index 8b65e1bf02..3c11a6e6d2 100644 --- a/packages/coding-agent/src/modes/interactive/components/refinement-outcome-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/refinement-outcome-message.ts @@ -1,4 +1,4 @@ -import { type Component, Spacer, Text, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import { type Component, Spacer, Text, truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; import type { RefinementOutcomeMessage } from "../../../core/messages.js"; import type { AppliedRefinementEdit, HarnessEntry } from "../../../core/refinement/refinement.js"; import { generateDiffString } from "../../../core/tools/edit-diff.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/scoped-models-selector.ts b/packages/coding-agent/src/modes/interactive/components/scoped-models-selector.ts index 0a08f669ab..9e9272ad46 100644 --- a/packages/coding-agent/src/modes/interactive/components/scoped-models-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/scoped-models-selector.ts @@ -1,4 +1,4 @@ -import type { Model } from "@earendil-works/pi-ai"; +import type { Model } from "@prime-intellect/prime-agent-ai"; import { Container, type Focusable, @@ -9,7 +9,7 @@ import { matchesKey, Spacer, Text, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; import { DynamicBorder } from "./dynamic-border.js"; import { keyText } from "./keybinding-hints.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/settings-selector.ts b/packages/coding-agent/src/modes/interactive/components/settings-selector.ts index 8f2b6bd8f9..b734648b32 100644 --- a/packages/coding-agent/src/modes/interactive/components/settings-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/settings-selector.ts @@ -1,5 +1,5 @@ -import type { ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { Transport } from "@earendil-works/pi-ai"; +import type { Transport } from "@prime-intellect/prime-agent-ai"; +import type { ThinkingLevel } from "@prime-intellect/prime-agent-core"; import { Container, type SelectItem, @@ -9,7 +9,7 @@ import { SettingsList, Spacer, Text, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import type { IdleEvictionMinutes } from "../../../core/session-action-store.js"; import type { MermaidRenderingMode, WarningSettings } from "../../../core/settings-manager.js"; import { getSelectListTheme, getSettingsListTheme, theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/show-images-selector.ts b/packages/coding-agent/src/modes/interactive/components/show-images-selector.ts index f7c1c03358..2bdb2c6395 100644 --- a/packages/coding-agent/src/modes/interactive/components/show-images-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/show-images-selector.ts @@ -1,4 +1,4 @@ -import { Container, type SelectItem, SelectList, type SelectListLayoutOptions } from "@earendil-works/pi-tui"; +import { Container, type SelectItem, SelectList, type SelectListLayoutOptions } from "@prime-intellect/prime-agent-tui"; import { getSelectListTheme } from "../theme/theme.js"; import { DynamicBorder } from "./dynamic-border.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/side-question.ts b/packages/coding-agent/src/modes/interactive/components/side-question.ts index 3cf901cb57..a07a8cdbd7 100644 --- a/packages/coding-agent/src/modes/interactive/components/side-question.ts +++ b/packages/coding-agent/src/modes/interactive/components/side-question.ts @@ -1,4 +1,4 @@ -import { Box, type Component, Markdown, Text, visibleWidth } from "@earendil-works/pi-tui"; +import { Box, type Component, Markdown, Text, visibleWidth } from "@prime-intellect/prime-agent-tui"; import type { AgentConnectionSideQuestionEvent } from "../../agent-connection/types.js"; import { getMarkdownTheme, theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/skill-invocation-message.ts b/packages/coding-agent/src/modes/interactive/components/skill-invocation-message.ts index fab70367ec..39a1d529a3 100644 --- a/packages/coding-agent/src/modes/interactive/components/skill-invocation-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/skill-invocation-message.ts @@ -1,4 +1,4 @@ -import { Markdown, type MarkdownTheme, Text } from "@earendil-works/pi-tui"; +import { Markdown, type MarkdownTheme, Text } from "@prime-intellect/prime-agent-tui"; import type { ParsedSkillBlock } from "../../../core/skill-blocks.js"; import { getMarkdownTheme, theme } from "../theme/theme.js"; import { customMessageLabel, ExpandableCustomMessageBox } from "./expandable-custom-message.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/slash-command-message.ts b/packages/coding-agent/src/modes/interactive/components/slash-command-message.ts index d977028edd..beb2e88d7d 100644 --- a/packages/coding-agent/src/modes/interactive/components/slash-command-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/slash-command-message.ts @@ -1,4 +1,4 @@ -import { Box, Container, Text } from "@earendil-works/pi-tui"; +import { Box, Container, Text } from "@prime-intellect/prime-agent-tui"; import { parseSlashCommand } from "../../../core/slash-commands.js"; import { theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/slash-command-result-message.ts b/packages/coding-agent/src/modes/interactive/components/slash-command-result-message.ts index 9b91bc4a14..b2e0042c69 100644 --- a/packages/coding-agent/src/modes/interactive/components/slash-command-result-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/slash-command-result-message.ts @@ -1,4 +1,4 @@ -import { Box, Container, Text } from "@earendil-works/pi-tui"; +import { Box, Container, Text } from "@prime-intellect/prime-agent-tui"; import type { SessionSlashCommandResultMessage } from "../../../core/messages.js"; import { theme } from "../theme/theme.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/subagent-summary-line.ts b/packages/coding-agent/src/modes/interactive/components/subagent-summary-line.ts index 0d8b7b44b0..c21a00f24f 100644 --- a/packages/coding-agent/src/modes/interactive/components/subagent-summary-line.ts +++ b/packages/coding-agent/src/modes/interactive/components/subagent-summary-line.ts @@ -1,4 +1,10 @@ -import { type Component, type Focusable, getKeybindings, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import { + type Component, + type Focusable, + getKeybindings, + truncateToWidth, + visibleWidth, +} from "@prime-intellect/prime-agent-tui"; import type { AgentConnectionRlmChildAgentSnapshot } from "../../agent-connection/index.js"; import { isDirectAgentChild } from "../../agents-view/agents-view-state.js"; import { type AgentRosterStatus, classifyAgentStatus } from "../../daemon/agent-roster.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/theme-selector.ts b/packages/coding-agent/src/modes/interactive/components/theme-selector.ts index 6b5fcedd1b..5620f41ee6 100644 --- a/packages/coding-agent/src/modes/interactive/components/theme-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/theme-selector.ts @@ -1,4 +1,4 @@ -import { Container, type SelectItem, SelectList, type SelectListLayoutOptions } from "@earendil-works/pi-tui"; +import { Container, type SelectItem, SelectList, type SelectListLayoutOptions } from "@prime-intellect/prime-agent-tui"; import { getAvailableThemes, getSelectListTheme } from "../theme/theme.js"; import { DynamicBorder } from "./dynamic-border.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/thinking-selector.ts b/packages/coding-agent/src/modes/interactive/components/thinking-selector.ts index bcc5701011..d70abf57a4 100644 --- a/packages/coding-agent/src/modes/interactive/components/thinking-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/thinking-selector.ts @@ -1,5 +1,5 @@ -import type { ThinkingLevel } from "@earendil-works/pi-agent-core"; -import { Container, type SelectItem, SelectList, type SelectListLayoutOptions } from "@earendil-works/pi-tui"; +import type { ThinkingLevel } from "@prime-intellect/prime-agent-core"; +import { Container, type SelectItem, SelectList, type SelectListLayoutOptions } from "@prime-intellect/prime-agent-tui"; import { getSelectListTheme } from "../theme/theme.js"; import { DynamicBorder } from "./dynamic-border.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/tool-execution.ts b/packages/coding-agent/src/modes/interactive/components/tool-execution.ts index 3785b4c64d..f7bf6bb54a 100644 --- a/packages/coding-agent/src/modes/interactive/components/tool-execution.ts +++ b/packages/coding-agent/src/modes/interactive/components/tool-execution.ts @@ -1,5 +1,5 @@ -import type { AgentToolResult } from "@earendil-works/pi-agent-core"; -import { type Component, Container, Image, Text, type TUI } from "@earendil-works/pi-tui"; +import type { AgentToolResult } from "@prime-intellect/prime-agent-core"; +import { type Component, Container, Image, Text, type TUI } from "@prime-intellect/prime-agent-tui"; import type { ToolDefinition, ToolRenderContext, ToolRenderResultOptions } from "../../../core/extensions/types.js"; import type { KernelSentAgentMessage } from "../../../core/kernel/index.js"; import { createBashToolDefinition } from "../../../core/tools/bash.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/tool-panel.ts b/packages/coding-agent/src/modes/interactive/components/tool-panel.ts index 1a120e8a94..c1db478c37 100644 --- a/packages/coding-agent/src/modes/interactive/components/tool-panel.ts +++ b/packages/coding-agent/src/modes/interactive/components/tool-panel.ts @@ -1,4 +1,4 @@ -import { type Component, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui"; +import { type Component, truncateToWidth, visibleWidth } from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; export const TOOL_PANEL_PADDING_X = 2; diff --git a/packages/coding-agent/src/modes/interactive/components/tree-selector.ts b/packages/coding-agent/src/modes/interactive/components/tree-selector.ts index e01bdfb79d..6dcbb30cb4 100644 --- a/packages/coding-agent/src/modes/interactive/components/tree-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/tree-selector.ts @@ -8,7 +8,7 @@ import { Text, TruncatedText, truncateToWidth, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import type { AgentConnectionSessionTreeNode } from "../../agent-connection/index.js"; import { theme } from "../theme/theme.js"; import { DynamicBorder } from "./dynamic-border.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/user-message-selector.ts b/packages/coding-agent/src/modes/interactive/components/user-message-selector.ts index 999d830344..c5cdcac1e2 100644 --- a/packages/coding-agent/src/modes/interactive/components/user-message-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/user-message-selector.ts @@ -1,4 +1,11 @@ -import { type Component, Container, getKeybindings, Spacer, Text, truncateToWidth } from "@earendil-works/pi-tui"; +import { + type Component, + Container, + getKeybindings, + Spacer, + Text, + truncateToWidth, +} from "@prime-intellect/prime-agent-tui"; import { theme } from "../theme/theme.js"; import { DynamicBorder } from "./dynamic-border.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/user-message.ts b/packages/coding-agent/src/modes/interactive/components/user-message.ts index 58b8766378..ee17cf9879 100644 --- a/packages/coding-agent/src/modes/interactive/components/user-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/user-message.ts @@ -1,4 +1,11 @@ -import { Box, type Component, Container, Markdown, type MarkdownTheme, visibleWidth } from "@earendil-works/pi-tui"; +import { + Box, + type Component, + Container, + Markdown, + type MarkdownTheme, + visibleWidth, +} from "@prime-intellect/prime-agent-tui"; import { parseSlashCommand } from "../../../core/slash-commands.js"; import { getMarkdownTheme, theme } from "../theme/theme.js"; import { isLeadingSlashCommand } from "./slash-command-message.js"; diff --git a/packages/coding-agent/src/modes/interactive/components/visual-truncate.ts b/packages/coding-agent/src/modes/interactive/components/visual-truncate.ts index 827230416b..dcfa5efb58 100644 --- a/packages/coding-agent/src/modes/interactive/components/visual-truncate.ts +++ b/packages/coding-agent/src/modes/interactive/components/visual-truncate.ts @@ -3,7 +3,7 @@ * Used by both tool-execution.ts and bash-execution.ts for consistent behavior. */ -import { Text } from "@earendil-works/pi-tui"; +import { Text } from "@prime-intellect/prime-agent-tui"; export interface VisualTruncateResult { /** The visual lines to display */ diff --git a/packages/coding-agent/src/modes/interactive/interactive-mode.ts b/packages/coding-agent/src/modes/interactive/interactive-mode.ts index 9c81ae25e8..64fd96d3eb 100644 --- a/packages/coding-agent/src/modes/interactive/interactive-mode.ts +++ b/packages/coding-agent/src/modes/interactive/interactive-mode.ts @@ -2,7 +2,6 @@ import { randomUUID } from "node:crypto"; import * as fs from "node:fs"; import * as os from "node:os"; import * as path from "node:path"; -import type { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; import { type Api, type AssistantMessage, @@ -12,8 +11,9 @@ import { type ServiceTier, supportsFastMode, type ToolCall, -} from "@earendil-works/pi-ai"; -import { BUILTIN_MCP_CATALOG } from "@earendil-works/pi-ai/mcp"; +} from "@prime-intellect/prime-agent-ai"; +import { BUILTIN_MCP_CATALOG } from "@prime-intellect/prime-agent-ai/mcp"; +import type { AgentMessage, ThinkingLevel } from "@prime-intellect/prime-agent-core"; import type { AutocompleteItem, AutocompleteProvider, @@ -24,7 +24,7 @@ import type { OverlayHandle, OverlayOptions, SlashCommand, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { CombinedAutocompleteProvider, type Component, @@ -41,7 +41,7 @@ import { TUI, truncateToWidth, visibleWidth, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import { spawn, spawnSync } from "child_process"; import { buildDaemonUpdateRestartReport, diff --git a/packages/coding-agent/src/modes/interactive/onboarding.ts b/packages/coding-agent/src/modes/interactive/onboarding.ts index ed8ebb1167..607745315a 100644 --- a/packages/coding-agent/src/modes/interactive/onboarding.ts +++ b/packages/coding-agent/src/modes/interactive/onboarding.ts @@ -1,4 +1,4 @@ -import type { Api, Model } from "@earendil-works/pi-ai"; +import type { Api, Model } from "@prime-intellect/prime-agent-ai"; import type { AuthStatus } from "../../core/auth-storage.js"; import { PRIME_INFERENCE_PROVIDER_ID } from "../../core/prime-inference-auth.js"; diff --git a/packages/coding-agent/src/modes/interactive/prompt-stash-state.ts b/packages/coding-agent/src/modes/interactive/prompt-stash-state.ts index ff4b5b9a70..1282cf2b60 100644 --- a/packages/coding-agent/src/modes/interactive/prompt-stash-state.ts +++ b/packages/coding-agent/src/modes/interactive/prompt-stash-state.ts @@ -1,5 +1,5 @@ -import type { ImageContent } from "@earendil-works/pi-ai"; -import type { EditorPasteSnapshot } from "@earendil-works/pi-tui"; +import type { ImageContent } from "@prime-intellect/prime-agent-ai"; +import type { EditorPasteSnapshot } from "@prime-intellect/prime-agent-tui"; export interface PromptStash { text: string; diff --git a/packages/coding-agent/src/modes/interactive/theme/theme.ts b/packages/coding-agent/src/modes/interactive/theme/theme.ts index 40424a81aa..1628ec76b1 100644 --- a/packages/coding-agent/src/modes/interactive/theme/theme.ts +++ b/packages/coding-agent/src/modes/interactive/theme/theme.ts @@ -12,7 +12,7 @@ import { type Rgb, rgbTo256, type SelectListTheme, -} from "@earendil-works/pi-tui"; +} from "@prime-intellect/prime-agent-tui"; import chalk from "chalk"; import { type Static, type TProperties, Type } from "typebox"; import type { Validator } from "typebox/compile"; @@ -821,7 +821,7 @@ function getDefaultTheme(): string { // ============================================================================ // Use globalThis to share theme across module loaders (direct Bun source execution + jiti in dev mode) -const THEME_KEY = Symbol.for("@earendil-works/pi-coding-agent:theme"); +const THEME_KEY = Symbol.for("@prime-intellect/prime-agent:theme"); // Export theme as a getter that reads from globalThis // This ensures all module instances (tsx, jiti) see the same theme @@ -1358,7 +1358,7 @@ export function getEditorTheme(): EditorTheme { }; } -export function getSettingsListTheme(): import("@earendil-works/pi-tui").SettingsListTheme { +export function getSettingsListTheme(): import("@prime-intellect/prime-agent-tui").SettingsListTheme { return { label: (text: string, selected: boolean) => (selected ? theme.fg("accent", text) : text), value: (text: string, selected: boolean) => (selected ? theme.fg("accent", text) : theme.fg("muted", text)), diff --git a/packages/coding-agent/src/modes/model-autocomplete.ts b/packages/coding-agent/src/modes/model-autocomplete.ts index cbe5814a8d..2da2918ef0 100644 --- a/packages/coding-agent/src/modes/model-autocomplete.ts +++ b/packages/coding-agent/src/modes/model-autocomplete.ts @@ -1,5 +1,5 @@ -import type { AutocompleteItem } from "@earendil-works/pi-tui"; -import { fuzzyFilter } from "@earendil-works/pi-tui"; +import type { AutocompleteItem } from "@prime-intellect/prime-agent-tui"; +import { fuzzyFilter } from "@prime-intellect/prime-agent-tui"; export interface ModelAutocompleteCandidate { id: string; diff --git a/packages/coding-agent/src/modes/print-mode.ts b/packages/coding-agent/src/modes/print-mode.ts index c586de9cb0..6ca13598b4 100644 --- a/packages/coding-agent/src/modes/print-mode.ts +++ b/packages/coding-agent/src/modes/print-mode.ts @@ -6,7 +6,7 @@ * - `pi --mode json "prompt"` - JSON event stream */ -import type { ImageContent } from "@earendil-works/pi-ai"; +import type { ImageContent } from "@prime-intellect/prime-agent-ai"; import type { AgentSessionRuntime } from "../core/agent-session-runtime.js"; import { type AgentAutonomousStatus, type AutonomousLimitReason, autonomousLimitReason } from "../core/autonomous.js"; import { flushRawStdout, writeRawStdout } from "../core/output-guard.js"; diff --git a/packages/coding-agent/src/modes/rpc/rpc-client.ts b/packages/coding-agent/src/modes/rpc/rpc-client.ts index 7c32788164..7b672e321c 100644 --- a/packages/coding-agent/src/modes/rpc/rpc-client.ts +++ b/packages/coding-agent/src/modes/rpc/rpc-client.ts @@ -5,8 +5,8 @@ */ import { type ChildProcess, spawn } from "node:child_process"; -import type { AgentEvent, AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { ImageContent } from "@earendil-works/pi-ai"; +import type { ImageContent } from "@prime-intellect/prime-agent-ai"; +import type { AgentEvent, AgentMessage, ThinkingLevel } from "@prime-intellect/prime-agent-core"; import type { AgentSessionMessageReceipt, AgentSessionMessageSafetyStatus } from "../../core/agent-messages.js"; import type { BashResult } from "../../core/bash-executor.js"; import type { CompactionResult } from "../../core/compaction/index.js"; diff --git a/packages/coding-agent/src/modes/rpc/rpc-types.ts b/packages/coding-agent/src/modes/rpc/rpc-types.ts index 7cba4f8a9b..9119937cb1 100644 --- a/packages/coding-agent/src/modes/rpc/rpc-types.ts +++ b/packages/coding-agent/src/modes/rpc/rpc-types.ts @@ -5,8 +5,8 @@ * Responses and events are emitted as JSON lines on stdout. */ -import type { AgentEvent, AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; -import type { ImageContent, Model } from "@earendil-works/pi-ai"; +import type { ImageContent, Model } from "@prime-intellect/prime-agent-ai"; +import type { AgentEvent, AgentMessage, ThinkingLevel } from "@prime-intellect/prime-agent-core"; import type { AgentSessionMessageReceipt, AgentSessionMessageSafetyStatus } from "../../core/agent-messages.js"; import type { BashResult } from "../../core/bash-executor.js"; import type { CompactionResult } from "../../core/compaction/index.js"; diff --git a/packages/coding-agent/src/package-manager-cli.ts b/packages/coding-agent/src/package-manager-cli.ts index adec93e9ae..fae7047079 100644 --- a/packages/coding-agent/src/package-manager-cli.ts +++ b/packages/coding-agent/src/package-manager-cli.ts @@ -1,4 +1,4 @@ -import type { ImageContent, TextContent, UserMessage } from "@earendil-works/pi-ai"; +import type { ImageContent, TextContent, UserMessage } from "@prime-intellect/prime-agent-ai"; import chalk from "chalk"; import { spawn } from "child_process"; import { readFileSync, rmSync, statSync } from "fs"; diff --git a/packages/coding-agent/src/utils/image-resize.ts b/packages/coding-agent/src/utils/image-resize.ts index 84b4ac331c..5b0fa58cfc 100644 --- a/packages/coding-agent/src/utils/image-resize.ts +++ b/packages/coding-agent/src/utils/image-resize.ts @@ -1,4 +1,4 @@ -import type { ImageContent } from "@earendil-works/pi-ai"; +import type { ImageContent } from "@prime-intellect/prime-agent-ai"; import { applyExifOrientation } from "./exif-orientation.js"; import { loadPhoton } from "./photon.js"; diff --git a/packages/coding-agent/test/config.test.ts b/packages/coding-agent/test/config.test.ts index a84400709b..2b59002588 100644 --- a/packages/coding-agent/test/config.test.ts +++ b/packages/coding-agent/test/config.test.ts @@ -173,8 +173,8 @@ describe("detectInstallMethod", () => { ); expect(detectInstallMethod()).toBe("pnpm"); - expect(getUpdateInstruction("@earendil-works/pi-coding-agent")).toBe( - "Run: pnpm install -g @earendil-works/pi-coding-agent", + expect(getUpdateInstruction("@prime-intellect/prime-agent")).toBe( + "Run: pnpm install -g @prime-intellect/prime-agent", ); }); @@ -182,9 +182,9 @@ describe("detectInstallMethod", () => { setExecPath("/usr/local/bin/node"); expect(detectInstallMethod()).toBe("unknown"); - expect(getSelfUpdateCommand("@earendil-works/pi-coding-agent")).toBeUndefined(); - expect(getUpdateInstruction("@earendil-works/pi-coding-agent")).toBe( - "Update @earendil-works/pi-coding-agent using the package manager, wrapper, or source checkout that provides this installation.", + expect(getSelfUpdateCommand("@prime-intellect/prime-agent")).toBeUndefined(); + expect(getUpdateInstruction("@prime-intellect/prime-agent")).toBe( + "Update @prime-intellect/prime-agent using the package manager, wrapper, or source checkout that provides this installation.", ); }); @@ -200,13 +200,13 @@ describe("detectInstallMethod", () => { test("self-updates npm installs from custom prefixes", () => { const { prefix } = createNpmPrefixInstall(); - const command = getSelfUpdateCommand("@earendil-works/pi-coding-agent"); + const command = getSelfUpdateCommand("@prime-intellect/prime-agent"); expect(detectInstallMethod()).toBe("npm"); expect(command).toEqual({ command: "npm", - args: ["--prefix", prefix, "install", "-g", "@earendil-works/pi-coding-agent"], - display: `npm --prefix ${prefix} install -g @earendil-works/pi-coding-agent`, + args: ["--prefix", prefix, "install", "-g", "@prime-intellect/prime-agent"], + display: `npm --prefix ${prefix} install -g @prime-intellect/prime-agent`, }); }); @@ -238,7 +238,7 @@ describe("detectInstallMethod", () => { const { prefix } = createNpmPrefixInstall(); const tarballUrl = "https://downloads.example.test/prime-agent/prime-agent-0.73.0.tgz"; - const command = getSelfUpdateCommand("@earendil-works/pi-coding-agent", undefined, tarballUrl); + const command = getSelfUpdateCommand("@prime-intellect/prime-agent", undefined, tarballUrl); expect(command).toEqual({ command: "npm", @@ -251,12 +251,12 @@ describe("detectInstallMethod", () => { const { prefix } = createNpmPrefixInstall(); const tarballUrl = "https://downloads.example.test/prime-agent/prime-agent-0.73.0.tgz"; - const command = getSelfUpdateCommand("@earendil-works/pi-coding-agent", undefined, tarballUrl, "prime-agent"); + const command = getSelfUpdateCommand("@prime-intellect/prime-agent", undefined, tarballUrl, "prime-agent"); expect(command).toEqual({ command: "npm", args: ["--prefix", prefix, "install", "-g", tarballUrl], - display: `npm --prefix ${prefix} install -g ${tarballUrl} && npm --prefix ${prefix} uninstall -g @earendil-works/pi-coding-agent`, + display: `npm --prefix ${prefix} install -g ${tarballUrl} && npm --prefix ${prefix} uninstall -g @prime-intellect/prime-agent`, steps: [ { command: "npm", @@ -265,8 +265,8 @@ describe("detectInstallMethod", () => { }, { command: "npm", - args: ["--prefix", prefix, "uninstall", "-g", "@earendil-works/pi-coding-agent"], - display: `npm --prefix ${prefix} uninstall -g @earendil-works/pi-coding-agent`, + args: ["--prefix", prefix, "uninstall", "-g", "@prime-intellect/prime-agent"], + display: `npm --prefix ${prefix} uninstall -g @prime-intellect/prime-agent`, }, ], }); @@ -275,29 +275,29 @@ describe("detectInstallMethod", () => { test("self-update respects configured npmCommand", () => { const { prefix } = createNpmPrefixInstall(); - const command = getSelfUpdateCommand("@earendil-works/pi-coding-agent", ["npm", "--prefix", prefix]); + const command = getSelfUpdateCommand("@prime-intellect/prime-agent", ["npm", "--prefix", prefix]); expect(command).toEqual({ command: "npm", - args: ["--prefix", prefix, "install", "-g", "@earendil-works/pi-coding-agent"], - display: `npm --prefix ${prefix} install -g @earendil-works/pi-coding-agent`, + args: ["--prefix", prefix, "install", "-g", "@prime-intellect/prime-agent"], + display: `npm --prefix ${prefix} install -g @prime-intellect/prime-agent`, }); }); test("self-update treats empty npmCommand as unset", () => { const { prefix } = createNpmPrefixInstall(); - const command = getSelfUpdateCommand("@earendil-works/pi-coding-agent", []); + const command = getSelfUpdateCommand("@prime-intellect/prime-agent", []); - expect(command?.args).toEqual(["--prefix", prefix, "install", "-g", "@earendil-works/pi-coding-agent"]); + expect(command?.args).toEqual(["--prefix", prefix, "install", "-g", "@prime-intellect/prime-agent"]); }); test("quotes npm self-update display paths", () => { const { prefix } = createNpmPrefixInstall("pi prefix "); - const command = getSelfUpdateCommand("@earendil-works/pi-coding-agent"); + const command = getSelfUpdateCommand("@prime-intellect/prime-agent"); - expect(command?.display).toBe(`npm --prefix "${prefix}" install -g @earendil-works/pi-coding-agent`); + expect(command?.display).toBe(`npm --prefix "${prefix}" install -g @prime-intellect/prime-agent`); }); test("does not infer Windows npm custom prefixes from package paths", () => { @@ -306,21 +306,21 @@ describe("detectInstallMethod", () => { setExecPath(`${packageDir}\\dist\\cli.js`); expect(detectInstallMethod()).toBe("npm"); - expect(getUpdateInstruction("@earendil-works/pi-coding-agent")).toBe( - "Run: npm install -g @earendil-works/pi-coding-agent", + expect(getUpdateInstruction("@prime-intellect/prime-agent")).toBe( + "Run: npm install -g @prime-intellect/prime-agent", ); }); test("self-updates bun global installs from bun pm bin", () => { createBunGlobalInstall(); - const command = getSelfUpdateCommand("@earendil-works/pi-coding-agent"); + const command = getSelfUpdateCommand("@prime-intellect/prime-agent"); expect(detectInstallMethod()).toBe("bun"); expect(command).toEqual({ command: "bun", - args: ["install", "-g", "@earendil-works/pi-coding-agent"], - display: "bun install -g @earendil-works/pi-coding-agent", + args: ["install", "-g", "@prime-intellect/prime-agent"], + display: "bun install -g @prime-intellect/prime-agent", }); }); @@ -403,8 +403,8 @@ describe("detectInstallMethod", () => { const { packageDir } = createNpmPrefixInstall(); chmodSync(packageDir, 0o500); - expect(getSelfUpdateCommand("@earendil-works/pi-coding-agent")).toBeUndefined(); - expect(getSelfUpdateUnavailableInstruction("@earendil-works/pi-coding-agent")).toContain( + expect(getSelfUpdateCommand("@prime-intellect/prime-agent")).toBeUndefined(); + expect(getSelfUpdateUnavailableInstruction("@prime-intellect/prime-agent")).toContain( "the install path is not writable", ); }); diff --git a/packages/coding-agent/tsconfig.examples.json b/packages/coding-agent/tsconfig.examples.json index a313c7c2ed..95462dd7d1 100644 --- a/packages/coding-agent/tsconfig.examples.json +++ b/packages/coding-agent/tsconfig.examples.json @@ -3,10 +3,10 @@ "compilerOptions": { "noEmit": true, "paths": { - "@earendil-works/pi-coding-agent": ["./src/index.ts"], - "@earendil-works/pi-coding-agent/hooks": ["./src/core/hooks/index.ts"], - "@earendil-works/pi-tui": ["../tui/src/index.ts"], - "@earendil-works/pi-ai": ["../ai/src/index.ts"], + "@prime-intellect/prime-agent": ["./src/index.ts"], + "@prime-intellect/prime-agent/hooks": ["./src/core/hooks/index.ts"], + "@prime-intellect/prime-agent-tui": ["../tui/src/index.ts"], + "@prime-intellect/prime-agent-ai": ["../ai/src/index.ts"], "typebox": ["../../node_modules/typebox"] }, "skipLibCheck": true diff --git a/packages/tui/.changes/prime-intellect-package.md b/packages/tui/.changes/prime-intellect-package.md new file mode 100644 index 0000000000..69e25304c7 --- /dev/null +++ b/packages/tui/.changes/prime-intellect-package.md @@ -0,0 +1 @@ +- Moved the TUI package to `@prime-intellect/prime-agent-tui`. diff --git a/packages/tui/package.json b/packages/tui/package.json index 7f6c2000c2..76243c731d 100644 --- a/packages/tui/package.json +++ b/packages/tui/package.json @@ -1,5 +1,5 @@ { - "name": "@earendil-works/pi-tui", + "name": "@prime-intellect/prime-agent-tui", "version": "0.9.1", "description": "Terminal User Interface library with differential rendering for efficient text-based applications", "type": "module", @@ -49,5 +49,8 @@ "devDependencies": { "@xterm/headless": "^6.0.0", "@xterm/xterm": "^6.0.0" + }, + "publishConfig": { + "access": "public" } } diff --git a/scripts/browser-smoke-entry.ts b/scripts/browser-smoke-entry.ts index a4057c9301..24c1194fd0 100644 --- a/scripts/browser-smoke-entry.ts +++ b/scripts/browser-smoke-entry.ts @@ -1,4 +1,4 @@ -import { complete, getModel } from "@earendil-works/pi-ai"; +import { complete, getModel } from "@prime-intellect/prime-agent-ai"; const model = getModel("google", "gemini-2.5-flash"); console.log(model.id, typeof complete); diff --git a/tsconfig.json b/tsconfig.json index a54d87e145..70c915e9c2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,18 @@ "noEmit": true, "paths": { "*": ["./*"], + "@prime-intellect/prime-agent-ai": ["./packages/ai/src/index.ts"], + "@prime-intellect/prime-agent-ai/oauth": ["./packages/ai/src/oauth.ts"], + "@prime-intellect/prime-agent-ai/*": ["./packages/ai/src/*.ts", "./packages/ai/src/providers/*.ts"], + "@prime-intellect/prime-agent-ai/dist/*": ["./packages/ai/src/*"], + "@prime-intellect/prime-agent-core": ["./packages/agent/src/index.ts"], + "@prime-intellect/prime-agent-core/*": ["./packages/agent/src/*"], + "@prime-intellect/prime-agent": ["./packages/coding-agent/src/index.ts"], + "@prime-intellect/prime-agent/hooks": ["./packages/coding-agent/src/core/hooks/index.ts"], + "@prime-intellect/prime-agent/*": ["./packages/coding-agent/src/*"], + "typebox": ["./node_modules/typebox"], + "@prime-intellect/prime-agent-tui": ["./packages/tui/src/index.ts"], + "@prime-intellect/prime-agent-tui/*": ["./packages/tui/src/*"], "@earendil-works/pi-ai": ["./packages/ai/src/index.ts"], "@earendil-works/pi-ai/oauth": ["./packages/ai/src/oauth.ts"], "@earendil-works/pi-ai/*": ["./packages/ai/src/*.ts", "./packages/ai/src/providers/*.ts"], @@ -13,7 +25,6 @@ "@earendil-works/pi-coding-agent": ["./packages/coding-agent/src/index.ts"], "@earendil-works/pi-coding-agent/hooks": ["./packages/coding-agent/src/core/hooks/index.ts"], "@earendil-works/pi-coding-agent/*": ["./packages/coding-agent/src/*"], - "typebox": ["./node_modules/typebox"], "@earendil-works/pi-tui": ["./packages/tui/src/index.ts"], "@earendil-works/pi-tui/*": ["./packages/tui/src/*"], "@earendil-works/pi-agent-old": ["./packages/agent-old/src/index.ts"],