History

Use MCP for agent-executor communication instead of custom REST

Agent is now a pure MCP client — connects to executor's /mcp endpoint, gets tools via tools/list (run_code description includes sandbox tool inventory), executes code via tools/call. Removes hardcoded run_code tool definition, POST /api/tasks/run endpoint, and Eden Treaty adapter dependency from the agent path. Model accepts tools dynamically.

Rhys Sullivan committed 9 months ago

Commit c479a7d1 parent c1282e913 files · +585 −345Browse files

Unified · Split

13 files
  1. assistant/bun.lock +159 −6
  2. assistant/packages/core/package.json +3 −3
  3. assistant/packages/core/src/agent.test.ts +66 −52
  4. assistant/packages/core/src/agent.ts +138 −120
  5. assistant/packages/core/src/index.ts +2 −2
  6. assistant/packages/core/src/model.ts +20 −14
  7. assistant/packages/server/package.json +0 −1
  8. assistant/packages/server/src/index.ts +19 −10
  9. assistant/packages/server/src/routes.ts +10 −11
  10. bun.lock +1 −3
  11. executor/apps/server/src/index.ts +26 −51
  12. executor/apps/server/src/mcp-server.test.ts +7 −1
  13. executor/apps/server/src/mcp-server.ts +134 −71
assistant/bun.lock+159−6
@@ -37,7 +37,6 @@ · 36 unmodified lines
37 "packages/bot": {37 "packages/bot": {
38 "name": "@assistant/bot",38 "name": "@assistant/bot",
39 "dependencies": {39 "dependencies": {
40 "@assistant/agent-executor-adapter": "workspace:*",
41 "@assistant/core": "workspace:*",40 "@assistant/core": "workspace:*",
42 "@assistant/server": "workspace:*",41 "@assistant/server": "workspace:*",
43 "@elysiajs/eden": "latest",42 "@elysiajs/eden": "latest",
@@ -55,21 +54,21 @@ · 11 unmodified lines
55 "packages/core": {54 "packages/core": {
56 "name": "@assistant/core",55 "name": "@assistant/core",
57 "dependencies": {56 "dependencies": {
58 "@assistant/agent-executor-adapter": "workspace:*",
59 "@mariozechner/pi-ai": "^0.52.6",57 "@mariozechner/pi-ai": "^0.52.6",
60 "@sinclair/typebox": "^0.34.48",58 "@modelcontextprotocol/sdk": "^1.26.0",
61 },59 },
62 "devDependencies": {60 "devDependencies": {
63 "@elysiajs/eden": "^1.4.6",61 "@elysiajs/eden": "^1.4.6",
64 "elysia": "^1.4.22",62 "elysia": "^1.4.22",
63 "zod": "^4.3.6",
65 },64 },
66 },65 },
67 "packages/server": {66 "packages/server": {
68 "name": "@assistant/server",67 "name": "@assistant/server",
69 "dependencies": {68 "dependencies": {
70 "@assistant/agent-executor-adapter": "workspace:*",
71 "@assistant/core": "workspace:*",69 "@assistant/core": "workspace:*",
72 "@elysiajs/eden": "latest",70 "@elysiajs/eden": "latest",
71 "convex": "^1.31.7",
73 "elysia": "latest",72 "elysia": "latest",
74 },73 },
75 "devDependencies": {74 "devDependencies": {
@@ -238,12 +237,16 @@ · 162 unmodified lines
238 237
239 "@google/genai": ["@google/genai@1.40.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-fhIww8smT0QYRX78qWOiz/nIQhHMF5wXOrlXvj33HBrz3vKDBb+wibLcEmTA+L9dmPD4KmfNr7UF3LDQVTXNjA=="],238 "@google/genai": ["@google/genai@1.40.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-fhIww8smT0QYRX78qWOiz/nIQhHMF5wXOrlXvj33HBrz3vKDBb+wibLcEmTA+L9dmPD4KmfNr7UF3LDQVTXNjA=="],
240 239
240 "@hono/node-server": ["@hono/node-server@1.19.9", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw=="],
241
241 "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],242 "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
242 243
243 "@mariozechner/pi-ai": ["@mariozechner/pi-ai@0.52.8", "", { "dependencies": { "@anthropic-ai/sdk": "^0.73.0", "@aws-sdk/client-bedrock-runtime": "^3.983.0", "@google/genai": "^1.40.0", "@mistralai/mistralai": "1.10.0", "@sinclair/typebox": "^0.34.41", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "chalk": "^5.6.2", "openai": "6.10.0", "partial-json": "^0.1.7", "proxy-agent": "^6.5.0", "undici": "^7.19.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-+aFCUbKJcskDJhr9wPcMBTy0x/xWio5v1dkxRYXUBPWp+Zt9DSdT5Kmd/IIQ+a0TOZDF4ajt4GY/oAw37X7XTw=="],244 "@mariozechner/pi-ai": ["@mariozechner/pi-ai@0.52.8", "", { "dependencies": { "@anthropic-ai/sdk": "^0.73.0", "@aws-sdk/client-bedrock-runtime": "^3.983.0", "@google/genai": "^1.40.0", "@mistralai/mistralai": "1.10.0", "@sinclair/typebox": "^0.34.41", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "chalk": "^5.6.2", "openai": "6.10.0", "partial-json": "^0.1.7", "proxy-agent": "^6.5.0", "undici": "^7.19.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-+aFCUbKJcskDJhr9wPcMBTy0x/xWio5v1dkxRYXUBPWp+Zt9DSdT5Kmd/IIQ+a0TOZDF4ajt4GY/oAw37X7XTw=="],
244 245
245 "@mistralai/mistralai": ["@mistralai/mistralai@1.10.0", "", { "dependencies": { "zod": "^3.20.0", "zod-to-json-schema": "^3.24.1" } }, "sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg=="],246 "@mistralai/mistralai": ["@mistralai/mistralai@1.10.0", "", { "dependencies": { "zod": "^3.20.0", "zod-to-json-schema": "^3.24.1" } }, "sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg=="],
246 247
248 "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.26.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg=="],
249
247 "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="],250 "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="],
248 251
249 "@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw=="],252 "@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw=="],
@@ -398,6 +401,8 @@ · 148 unmodified lines
398 401
399 "@vladfrangu/async_event_emitter": ["@vladfrangu/async_event_emitter@2.4.7", "", {}, "sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g=="],402 "@vladfrangu/async_event_emitter": ["@vladfrangu/async_event_emitter@2.4.7", "", {}, "sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g=="],
400 403
404 "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
405
401 "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],406 "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
402 407
403 "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],408 "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
@@ -418,6 +423,8 @@ · 14 unmodified lines
418 423
419 "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],424 "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
420 425
426 "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
427
421 "bowser": ["bowser@2.13.1", "", {}, "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw=="],428 "bowser": ["bowser@2.13.1", "", {}, "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw=="],
422 429
423 "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],430 "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
@@ -426,16 +433,30 @@ · 2 unmodified lines
426 433
427 "bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="],434 "bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="],
428 435
436 "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
437
438 "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
439
440 "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
441
429 "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],442 "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
430 443
431 "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],444 "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
432 445
433 "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],446 "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
434 447
448 "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="],
449
450 "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
451
435 "convex": ["convex@1.31.7", "", { "dependencies": { "esbuild": "0.27.0", "prettier": "^3.0.0" }, "peerDependencies": { "@auth0/auth0-react": "^2.0.1", "@clerk/clerk-react": "^4.12.8 || ^5.0.0", "react": "^18.0.0 || ^19.0.0-0 || ^19.0.0" }, "optionalPeers": ["@auth0/auth0-react", "@clerk/clerk-react", "react"], "bin": { "convex": "bin/main.js" } }, "sha512-PtNMe1mAIOvA8Yz100QTOaIdgt2rIuWqencVXrb4McdhxBHZ8IJ1eXTnrgCC9HydyilGT1pOn+KNqT14mqn9fQ=="],452 "convex": ["convex@1.31.7", "", { "dependencies": { "esbuild": "0.27.0", "prettier": "^3.0.0" }, "peerDependencies": { "@auth0/auth0-react": "^2.0.1", "@clerk/clerk-react": "^4.12.8 || ^5.0.0", "react": "^18.0.0 || ^19.0.0-0 || ^19.0.0" }, "optionalPeers": ["@auth0/auth0-react", "@clerk/clerk-react", "react"], "bin": { "convex": "bin/main.js" } }, "sha512-PtNMe1mAIOvA8Yz100QTOaIdgt2rIuWqencVXrb4McdhxBHZ8IJ1eXTnrgCC9HydyilGT1pOn+KNqT14mqn9fQ=="],
436 453
437 "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],454 "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
438 455
456 "cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
457
458 "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="],
459
439 "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],460 "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
440 461
441 "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],462 "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
@@ -446,24 +467,40 @@ · 4 unmodified lines
446 467
447 "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=="],468 "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=="],
448 469
470 "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
471
449 "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],472 "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
450 473
451 "discord-api-types": ["discord-api-types@0.38.38", "", {}, "sha512-7qcM5IeZrfb+LXW07HvoI5L+j4PQeMZXEkSm1htHAHh4Y9JSMXBWjy/r7zmUCOj4F7zNjMcm7IMWr131MT2h0Q=="],474 "discord-api-types": ["discord-api-types@0.38.38", "", {}, "sha512-7qcM5IeZrfb+LXW07HvoI5L+j4PQeMZXEkSm1htHAHh4Y9JSMXBWjy/r7zmUCOj4F7zNjMcm7IMWr131MT2h0Q=="],
452 475
453 "discord.js": ["discord.js@14.25.1", "", { "dependencies": { "@discordjs/builders": "^1.13.0", "@discordjs/collection": "1.5.3", "@discordjs/formatters": "^0.6.2", "@discordjs/rest": "^2.6.0", "@discordjs/util": "^1.2.0", "@discordjs/ws": "^1.2.3", "@sapphire/snowflake": "3.5.3", "discord-api-types": "^0.38.33", "fast-deep-equal": "3.1.3", "lodash.snakecase": "4.1.1", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.3" } }, "sha512-2l0gsPOLPs5t6GFZfQZKnL1OJNYFcuC/ETWsW4VtKVD/tg4ICa9x+jb9bkPffkMdRpRpuUaO/fKkHCBeiCKh8g=="],476 "discord.js": ["discord.js@14.25.1", "", { "dependencies": { "@discordjs/builders": "^1.13.0", "@discordjs/collection": "1.5.3", "@discordjs/formatters": "^0.6.2", "@discordjs/rest": "^2.6.0", "@discordjs/util": "^1.2.0", "@discordjs/ws": "^1.2.3", "@sapphire/snowflake": "3.5.3", "discord-api-types": "^0.38.33", "fast-deep-equal": "3.1.3", "lodash.snakecase": "4.1.1", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.3" } }, "sha512-2l0gsPOLPs5t6GFZfQZKnL1OJNYFcuC/ETWsW4VtKVD/tg4ICa9x+jb9bkPffkMdRpRpuUaO/fKkHCBeiCKh8g=="],
454 477
478 "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
479
455 "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],480 "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
456 481
457 "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],482 "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
458 483
484 "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
485
459 "effect": ["effect@3.19.16", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-7+XC3vGrbAhCHd8LTFHvnZjRpZKZ8YHRZqJTkpNoxcJ2mCyNs2SwI+6VkV/ij8Y3YW7wfBN4EbU06/F5+m/wkQ=="],486 "effect": ["effect@3.19.16", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-7+XC3vGrbAhCHd8LTFHvnZjRpZKZ8YHRZqJTkpNoxcJ2mCyNs2SwI+6VkV/ij8Y3YW7wfBN4EbU06/F5+m/wkQ=="],
460 487
461 "elysia": ["elysia@1.4.22", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.6", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-Q90VCb1RVFxnFaRV0FDoSylESQQLWgLHFmWciQJdX9h3b2cSasji9KWEUvaJuy/L9ciAGg4RAhUVfsXHg5K2RQ=="],488 "elysia": ["elysia@1.4.22", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.6", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-Q90VCb1RVFxnFaRV0FDoSylESQQLWgLHFmWciQJdX9h3b2cSasji9KWEUvaJuy/L9ciAGg4RAhUVfsXHg5K2RQ=="],
462 489
463 "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],490 "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
464 491
492 "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
493
494 "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
495
496 "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
497
498 "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
499
465 "esbuild": ["esbuild@0.27.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.0", "@esbuild/android-arm": "0.27.0", "@esbuild/android-arm64": "0.27.0", "@esbuild/android-x64": "0.27.0", "@esbuild/darwin-arm64": "0.27.0", "@esbuild/darwin-x64": "0.27.0", "@esbuild/freebsd-arm64": "0.27.0", "@esbuild/freebsd-x64": "0.27.0", "@esbuild/linux-arm": "0.27.0", "@esbuild/linux-arm64": "0.27.0", "@esbuild/linux-ia32": "0.27.0", "@esbuild/linux-loong64": "0.27.0", "@esbuild/linux-mips64el": "0.27.0", "@esbuild/linux-ppc64": "0.27.0", "@esbuild/linux-riscv64": "0.27.0", "@esbuild/linux-s390x": "0.27.0", "@esbuild/linux-x64": "0.27.0", "@esbuild/netbsd-arm64": "0.27.0", "@esbuild/netbsd-x64": "0.27.0", "@esbuild/openbsd-arm64": "0.27.0", "@esbuild/openbsd-x64": "0.27.0", "@esbuild/openharmony-arm64": "0.27.0", "@esbuild/sunos-x64": "0.27.0", "@esbuild/win32-arm64": "0.27.0", "@esbuild/win32-ia32": "0.27.0", "@esbuild/win32-x64": "0.27.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA=="],500 "esbuild": ["esbuild@0.27.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.0", "@esbuild/android-arm": "0.27.0", "@esbuild/android-arm64": "0.27.0", "@esbuild/android-x64": "0.27.0", "@esbuild/darwin-arm64": "0.27.0", "@esbuild/darwin-x64": "0.27.0", "@esbuild/freebsd-arm64": "0.27.0", "@esbuild/freebsd-x64": "0.27.0", "@esbuild/linux-arm": "0.27.0", "@esbuild/linux-arm64": "0.27.0", "@esbuild/linux-ia32": "0.27.0", "@esbuild/linux-loong64": "0.27.0", "@esbuild/linux-mips64el": "0.27.0", "@esbuild/linux-ppc64": "0.27.0", "@esbuild/linux-riscv64": "0.27.0", "@esbuild/linux-s390x": "0.27.0", "@esbuild/linux-x64": "0.27.0", "@esbuild/netbsd-arm64": "0.27.0", "@esbuild/netbsd-x64": "0.27.0", "@esbuild/openbsd-arm64": "0.27.0", "@esbuild/openbsd-x64": "0.27.0", "@esbuild/openharmony-arm64": "0.27.0", "@esbuild/sunos-x64": "0.27.0", "@esbuild/win32-arm64": "0.27.0", "@esbuild/win32-ia32": "0.27.0", "@esbuild/win32-x64": "0.27.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA=="],
466 501
502 "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
503
467 "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=="],504 "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=="],
468 505
469 "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],506 "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
@@ -472,8 +509,18 @@ · 2 unmodified lines
472 509
473 "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],510 "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
474 511
512 "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
513
514 "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
515
516 "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="],
517
475 "exact-mirror": ["exact-mirror@0.2.6", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-7s059UIx9/tnOKSySzUk5cPGkoILhTE4p6ncf6uIPaQ+9aRBQzQjc9+q85l51+oZ+P6aBxh084pD0CzBQPcFUA=="],518 "exact-mirror": ["exact-mirror@0.2.6", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-7s059UIx9/tnOKSySzUk5cPGkoILhTE4p6ncf6uIPaQ+9aRBQzQjc9+q85l51+oZ+P6aBxh084pD0CzBQPcFUA=="],
476 519
520 "express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
521
522 "express-rate-limit": ["express-rate-limit@8.2.1", "", { "dependencies": { "ip-address": "10.0.1" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g=="],
523
477 "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],524 "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
478 525
479 "fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="],526 "fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="],
@@ -490,16 +537,28 @@ · 10 unmodified lines
490 537
491 "file-type": ["file-type@21.3.0", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA=="],538 "file-type": ["file-type@21.3.0", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA=="],
492 539
540 "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="],
541
493 "find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="],542 "find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="],
494 543
495 "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],544 "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
496 545
497 "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],546 "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
498 547
548 "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
549
550 "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
551
552 "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
553
499 "gaxios": ["gaxios@7.1.3", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "rimraf": "^5.0.1" } }, "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ=="],554 "gaxios": ["gaxios@7.1.3", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "rimraf": "^5.0.1" } }, "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ=="],
500 555
501 "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=="],556 "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=="],
502 557
558 "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
559
560 "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
561
503 "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=="],562 "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=="],
504 563
505 "glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],564 "glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
@@ -508,28 +567,50 @@ · 2 unmodified lines
508 567
509 "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="],568 "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="],
510 569
570 "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
571
511 "gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="],572 "gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="],
512 573
574 "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
575
576 "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
577
578 "hono": ["hono@4.11.8", "", {}, "sha512-eVkB/CYCCei7K2WElZW9yYQFWssG0DhaDhVvr7wy5jJ22K+ck8fWW0EsLpB0sITUTvPnc97+rrbQqIr5iqiy9Q=="],
579
580 "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
581
513 "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],582 "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
514 583
515 "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],584 "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
516 585
586 "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
587
517 "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],588 "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
518 589
519 "ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],590 "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
591
592 "ip-address": ["ip-address@10.0.1", "", {}, "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA=="],
593
594 "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
520 595
521 "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],596 "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
522 597
598 "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],
599
523 "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],600 "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
524 601
525 "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],602 "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
526 603
604 "jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="],
605
527 "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],606 "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
528 607
529 "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=="],608 "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=="],
530 609
531 "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],610 "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
532 611
612 "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],
613
533 "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=="],614 "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=="],
534 615
535 "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=="],616 "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=="],
@@ -544,8 +625,18 @@ · 8 unmodified lines
544 625
545 "magic-bytes.js": ["magic-bytes.js@1.13.0", "", {}, "sha512-afO2mnxW7GDTXMm5/AoN1WuOcdoKhtgXjIvHmobqTD1grNplhGdv3PFOyjCVmrnOZBIT/gD/koDKpYG+0mvHcg=="],626 "magic-bytes.js": ["magic-bytes.js@1.13.0", "", {}, "sha512-afO2mnxW7GDTXMm5/AoN1WuOcdoKhtgXjIvHmobqTD1grNplhGdv3PFOyjCVmrnOZBIT/gD/koDKpYG+0mvHcg=="],
546 627
628 "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
629
630 "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
631
547 "memoirist": ["memoirist@0.4.0", "", {}, "sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg=="],632 "memoirist": ["memoirist@0.4.0", "", {}, "sha512-zxTgA0mSYELa66DimuNQDvyLq36AwDlTuVRbnQtB+VuTcKWm5Qc4z3WkSpgsFWHNhexqkIooqpv4hdcqrX5Nmg=="],
548 633
634 "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
635
636 "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
637
638 "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
639
549 "minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],640 "minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
550 641
551 "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],642 "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
@@ -558,6 +649,8 @@ · 6 unmodified lines
558 649
559 "multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="],650 "multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="],
560 651
652 "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
653
561 "netmask": ["netmask@2.0.2", "", {}, "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="],654 "netmask": ["netmask@2.0.2", "", {}, "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="],
562 655
563 "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],656 "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
@@ -566,6 +659,14 @@ · 2 unmodified lines
566 659
567 "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="],660 "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="],
568 661
662 "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
663
664 "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
665
666 "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
667
668 "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
669
569 "openai": ["openai@6.10.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-ITxOGo7rO3XRMiKA5l7tQ43iNNu+iXGFAcf2t+aWVzzqRaS0i7m1K2BhxNdaveB+5eENhO0VY1FkiZzhBk4v3A=="],670 "openai": ["openai@6.10.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-ITxOGo7rO3XRMiKA5l7tQ43iNNu+iXGFAcf2t+aWVzzqRaS0i7m1K2BhxNdaveB+5eENhO0VY1FkiZzhBk4v3A=="],
570 671
571 "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],672 "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
@@ -576,22 +677,36 @@ · 4 unmodified lines
576 677
577 "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],678 "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
578 679
680 "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
681
579 "partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="],682 "partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="],
580 683
581 "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],684 "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
582 685
583 "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],686 "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
584 687
688 "path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="],
689
690 "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="],
691
585 "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],692 "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
586 693
587 "protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],694 "protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="],
588 695
696 "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
697
589 "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=="],698 "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=="],
590 699
591 "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],700 "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
592 701
593 "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],702 "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
594 703
704 "qs": ["qs@6.14.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ=="],
705
706 "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
707
708 "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
709
595 "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],710 "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
596 711
597 "react-reconciler": ["react-reconciler@0.31.0", "", { "dependencies": { "scheduler": "^0.25.0" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ=="],712 "react-reconciler": ["react-reconciler@0.31.0", "", { "dependencies": { "scheduler": "^0.25.0" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ=="],
@@ -600,14 +715,32 @@ · 2 unmodified lines
600 715
601 "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="],716 "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="],
602 717
718 "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
719
603 "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],720 "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
604 721
722 "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
723
605 "scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="],724 "scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="],
606 725
726 "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
727
728 "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="],
729
730 "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
731
607 "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],732 "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
608 733
609 "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],734 "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
610 735
736 "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
737
738 "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
739
740 "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
741
742 "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
743
611 "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],744 "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
612 745
613 "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],746 "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
@@ -618,6 +751,8 @@ · 4 unmodified lines
618 751
619 "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],752 "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
620 753
754 "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
755
621 "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],756 "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
622 757
623 "string-width-cjs": ["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=="],758 "string-width-cjs": ["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=="],
@@ -630,6 +765,8 @@ · 6 unmodified lines
630 765
631 "strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],766 "strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
632 767
768 "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
769
633 "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=="],770 "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=="],
634 771
635 "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="],772 "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="],
@@ -638,6 +775,8 @@ · 2 unmodified lines
638 775
639 "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],776 "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
640 777
778 "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
779
641 "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],780 "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
642 781
643 "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="],782 "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="],
@@ -646,8 +785,12 @@ · 2 unmodified lines
646 785
647 "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],786 "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
648 787
788 "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
789
649 "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],790 "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
650 791
792 "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
793
651 "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],794 "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
652 795
653 "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],796 "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
@@ -656,9 +799,11 @@ · 2 unmodified lines
656 799
657 "wrap-ansi-cjs": ["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=="],800 "wrap-ansi-cjs": ["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=="],
658 801
802 "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
803
659 "ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],804 "ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],
660 805
661 "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],806 "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
662 807
663 "zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],808 "zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
664 809
@@ -672,10 +817,18 @@ · 7 unmodified lines
672 817
673 "@mariozechner/pi-ai/undici": ["undici@7.21.0", "", {}, "sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg=="],818 "@mariozechner/pi-ai/undici": ["undici@7.21.0", "", {}, "sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg=="],
674 819
820 "@mistralai/mistralai/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
821
822 "@modelcontextprotocol/sdk/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
823
824 "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
825
675 "node-fetch/data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="],826 "node-fetch/data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="],
676 827
677 "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],828 "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
678 829
830 "socks/ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],
831
679 "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],832 "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
680 833
681 "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],834 "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
assistant/packages/core/package.json+3−3
@@ -6,12 +6,12 @@ · 5 unmodified lines
6 ".": "./src/index.ts"6 ".": "./src/index.ts"
7 },7 },
8 "dependencies": {8 "dependencies": {
9 "@assistant/agent-executor-adapter": "workspace:*",
10 "@mariozechner/pi-ai": "^0.52.6",9 "@mariozechner/pi-ai": "^0.52.6",
11 "@sinclair/typebox": "^0.34.48"10 "@modelcontextprotocol/sdk": "^1.26.0"
12 },11 },
13 "devDependencies": {12 "devDependencies": {
14 "@elysiajs/eden": "^1.4.6",13 "@elysiajs/eden": "^1.4.6",
15 "elysia": "^1.4.22"14 "elysia": "^1.4.22",
15 "zod": "^4.3.6"
16 }16 }
17}17}
assistant/packages/core/src/agent.test.ts+66−52
@@ -1,62 +1,72 @@
1import { test, expect } from "bun:test";1import { test, expect } from "bun:test";
2import { Elysia, t } from "elysia";2import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3import { treaty } from "@elysiajs/eden";3import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
4import { z } from "zod";
4import { createAgent } from "./agent";5import { createAgent } from "./agent";
5import type { Message, GenerateResult } from "./model";6import type { Message, GenerateResult, ToolDef } from "./model";
6 7
7/**8/**
8 * Minimal mock executor with sync /api/tasks/run endpoint.9 * Create a mock MCP server that exposes run_code.
10 * Returns the Bun HTTP server so we can get the port.
9 */11 */
10function createMockExecutor() {12function createMockMcpServer() {
11 return new Elysia()13 const server = Bun.serve({
12 .get("/api/tools", ({ query }) => {14 port: 0,
13 return [15 async fetch(request) {
16 const transport = new WebStandardStreamableHTTPServerTransport({
17 sessionIdGenerator: undefined,
18 enableJsonResponse: true,
19 });
20
21 const mcp = new McpServer(
22 { name: "mock-executor", version: "0.1.0" },
23 { capabilities: { tools: {} } },
24 );
25
26 mcp.registerTool(
27 "run_code",
14 {28 {
15 path: "utils.get_time",29 description: "Execute TypeScript code in a sandbox.\n\nAvailable tools in the sandbox:\n - tools.utils.get_time({}): { iso: string; unix: number } — Get the current time",
16 description: "Get the current time",30 inputSchema: {
17 approval: "auto" as const,31 code: z.string(),
18 source: "local",32 },
19 argsType: "{}",
20 returnsType: "{ iso: string; unix: number }",
21 },33 },
22 ];34 async (input) => {
23 }, {35 return {
24 query: t.Object({36 content: [{ type: "text" as const, text: `taskId: task_123\nstatus: completed\nruntimeId: local-bun\n\n\`\`\`text\nresult: {"iso":"2026-02-07T00:00:00Z","unix":1770422400000}\n\`\`\`` }],
25 workspaceId: t.String(),37 };
26 actorId: t.Optional(t.String()),38 },
27 clientId: t.Optional(t.String()),39 );
28 }),40
29 })41 try {
30 .post("/api/tasks/run", ({ body }) => {42 await mcp.connect(transport);
31 return {43 return await transport.handleRequest(request);
32 taskId: `task_${Date.now()}`,44 } finally {
33 status: "completed" as const,45 await transport.close().catch(() => {});
34 stdout: 'result: {"iso":"2026-02-07T00:00:00Z","unix":1770422400000}',46 await mcp.close().catch(() => {});
35 stderr: "",47 }
36 exitCode: 0,48 },
37 };49 });
38 }, {50
39 body: t.Object({51 return server;
40 code: t.String(),
41 workspaceId: t.String(),
42 actorId: t.String(),
43 clientId: t.Optional(t.String()),
44 timeoutMs: t.Optional(t.Number()),
45 }),
46 })
47 .listen(0);
48}52}
49 53
50test("agent calls model, sends code to executor, returns result", async () => {54test("agent connects via MCP, calls run_code, returns result", async () => {
51 const server = createMockExecutor();55 const server = createMockMcpServer();
52 const executor = treaty<typeof server>(`http://127.0.0.1:${server.server!.port}`);56 const port = server.port;
53 57
54 let callCount = 0;58 let callCount = 0;
55 const events: string[] = [];59 const events: string[] = [];
56 60
57 const mockGenerate = async (messages: Message[]): Promise<GenerateResult> => {61 const mockGenerate = async (messages: Message[], tools?: ToolDef[]): Promise<GenerateResult> => {
58 callCount++;62 callCount++;
63
64 // First call: verify tools were passed from MCP
59 if (callCount === 1) {65 if (callCount === 1) {
66 expect(tools).toBeDefined();
67 expect(tools!.length).toBeGreaterThan(0);
68 expect(tools![0].name).toBe("run_code");
69
60 return {70 return {
61 toolCalls: [{71 toolCalls: [{
62 id: "call_1",72 id: "call_1",
@@ -65,11 +75,13 @@ test("agent calls model, sends code to executor, returns result", async () => { · 2 unmodified lines
65 }],75 }],
66 };76 };
67 }77 }
78
79 // Second call: return final text
68 return { text: "The current time is 2026-02-07." };80 return { text: "The current time is 2026-02-07." };
69 };81 };
70 82
71 const agent = createAgent({83 const agent = createAgent({
72 executor: executor as any,84 executorUrl: `http://127.0.0.1:${port}`,
73 generate: mockGenerate,85 generate: mockGenerate,
74 workspaceId: "ws_test",86 workspaceId: "ws_test",
75 actorId: "actor_test",87 actorId: "actor_test",
@@ -80,7 +92,7 @@ test("agent calls model, sends code to executor, returns result", async () => { · 4 unmodified lines
80 });92 });
81 93
82 expect(result.text).toBe("The current time is 2026-02-07.");94 expect(result.text).toBe("The current time is 2026-02-07.");
83 expect(result.codeRuns).toBe(1);95 expect(result.toolCalls).toBe(1);
84 expect(callCount).toBe(2);96 expect(callCount).toBe(2);
85 expect(events).toContain("status");97 expect(events).toContain("status");
86 expect(events).toContain("code_generated");98 expect(events).toContain("code_generated");
@@ -91,16 +103,18 @@ test("agent calls model, sends code to executor, returns result", async () => { · 4 unmodified lines
91 server.stop(true);103 server.stop(true);
92});104});
93 105
94test("agent handles model returning text immediately (no code)", async () => {106test("agent handles model returning text immediately (no tool calls)", async () => {
95 const server = createMockExecutor();107 const server = createMockMcpServer();
96 const executor = treaty<typeof server>(`http://127.0.0.1:${server.server!.port}`);108 const port = server.port;
97 109
98 const mockGenerate = async (): Promise<GenerateResult> => {110 const mockGenerate = async (_messages: Message[], tools?: ToolDef[]): Promise<GenerateResult> => {
111 // Tools should still be available even if we don't use them
112 expect(tools).toBeDefined();
99 return { text: "I don't need to run any code for that. Hello!" };113 return { text: "I don't need to run any code for that. Hello!" };
100 };114 };
101 115
102 const agent = createAgent({116 const agent = createAgent({
103 executor: executor as any,117 executorUrl: `http://127.0.0.1:${port}`,
104 generate: mockGenerate,118 generate: mockGenerate,
105 workspaceId: "ws_test",119 workspaceId: "ws_test",
106 actorId: "actor_test",120 actorId: "actor_test",
@@ -109,7 +123,7 @@ test("agent handles model returning text immediately (no code)", async () => { · 2 unmodified lines
109 const result = await agent.run("Say hello");123 const result = await agent.run("Say hello");
110 124
111 expect(result.text).toBe("I don't need to run any code for that. Hello!");125 expect(result.text).toBe("I don't need to run any code for that. Hello!");
112 expect(result.codeRuns).toBe(0);126 expect(result.toolCalls).toBe(0);
113 127
114 server.stop(true);128 server.stop(true);
115});129});
assistant/packages/core/src/agent.ts+138−120
@@ -1,75 +1,61 @@
1/**1/**
2 * Agent loop — orchestrates Claude + executor.2 * Agent loop — orchestrates Claude + executor via MCP.
3 *3 *
4 * 1. Fetch tool inventory from executor4 * 1. Connect to executor MCP server
5 * 2. Build system prompt with tool descriptions5 * 2. List tools (gets run_code with sandbox tool inventory in description)
6 * 3. Call Claude → get run_code({ code }) tool call6 * 3. Call Claude → get run_code({ code }) tool call
7 * 4. Send code to executor via sync endpoint (blocks until done)7 * 4. Forward to executor via MCP tools/call (blocks until done)
8 * 5. Feed result back to Claude8 * 5. Feed result back to Claude
9 * 6. Loop until Claude responds with text9 * 6. Loop until Claude responds with text
10 */10 */
11 11
12import type { ExecutorClient } from "@assistant/agent-executor-adapter";12import { Client } from "@modelcontextprotocol/sdk/client/index.js";
13import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
13import type { TaskEvent } from "./events";14import type { TaskEvent } from "./events";
14import type { Message, GenerateResult } from "./model";15import type { Message, GenerateResult, ToolCall, ToolDef } from "./model";
15 16
16// ---------------------------------------------------------------------------17// ---------------------------------------------------------------------------
17// Types18// Types
18// ---------------------------------------------------------------------------19// ---------------------------------------------------------------------------
19 20
20export interface ToolDescriptor {21export interface McpTool {
21 path: string;22 name: string;
22 description: string;23 description?: string;
23 approval: "auto" | "required";24 inputSchema?: Record<string, unknown>;
24 source?: string;
25 argsType?: string;
26 returnsType?: string;
27}25}
28 26
29export interface AgentOptions {27export interface AgentOptions {
30 readonly executor: ExecutorClient;28 readonly executorUrl: string;
31 readonly generate: (messages: Message[]) => Promise<GenerateResult>;29 readonly generate: (messages: Message[], tools?: ToolDef[]) => Promise<GenerateResult>;
32 readonly workspaceId: string;30 readonly workspaceId: string;
33 readonly actorId: string;31 readonly actorId: string;
34 readonly clientId?: string;32 readonly clientId?: string;
35 readonly context?: string;33 readonly context?: string;
36 readonly maxCodeRuns?: number;34 readonly maxToolCalls?: number;
37 readonly timeoutMs?: number;
38}35}
39 36
40export interface AgentResult {37export interface AgentResult {
41 readonly text: string;38 readonly text: string;
42 readonly codeRuns: number;39 readonly toolCalls: number;
43}40}
44 41
45// ---------------------------------------------------------------------------42// ---------------------------------------------------------------------------
46// System prompt43// System prompt
47// ---------------------------------------------------------------------------44// ---------------------------------------------------------------------------
48 45
49function buildSystemPrompt(tools: ToolDescriptor[], context?: string): string {46function buildSystemPrompt(tools: McpTool[], context?: string): string {
50 const toolGuidance = tools47 const toolSection = tools
51 .map((t) => {48 .map((t) => `### ${t.name}\n${t.description ?? "No description."}`)
52 const args = t.argsType ?? "unknown";49 .join("\n\n");
53 const returns = t.returnsType ?? "unknown";
54 const approval = t.approval === "required" ? " (approval required)" : "";
55 return `- tools.${t.path}(${args}): Promise<${returns}>${approval} — ${t.description}`;
56 })
57 .join("\n");
58
59 const discoveryNote = tools.some((t) => t.path === "discover")
60 ? `\n\n## Tool Discovery\n\nUse \`tools.discover({ query })\` to search for tools by keyword when you need to find specific capabilities.\n`
61 : "";
62 50
63 const contextSection = context ? `\n## Context\n\n${context}\n` : "";51 const contextSection = context ? `\n## Context\n\n${context}\n` : "";
64 52
65 return `You are an AI assistant that executes tasks by generating TypeScript code.53 return `You are an AI assistant that executes tasks by writing TypeScript code.
66
67You have access to tools via the \`tools\` object. Generate TypeScript code that calls these tools to accomplish the user's task.
68${contextSection}54${contextSection}
69## Available Tools55## Available Tools
70 56
71${toolGuidance}57${toolSection}
72${discoveryNote}58
73## Instructions59## Instructions
74 60
75- Use the \`run_code\` tool to execute TypeScript code61- Use the \`run_code\` tool to execute TypeScript code
@@ -80,124 +66,156 @@ ${discoveryNote} · 4 unmodified lines
80- Be concise and accurate — base your response on actual tool results`;66- Be concise and accurate — base your response on actual tool results`;
81}67}
82 68
69// ---------------------------------------------------------------------------
70// MCP client helpers
71// ---------------------------------------------------------------------------
72
73async function connectMcp(executorUrl: string, workspaceId: string, actorId: string, clientId?: string): Promise<Client> {
74 const url = new URL(`${executorUrl}/mcp`);
75 url.searchParams.set("workspaceId", workspaceId);
76 url.searchParams.set("actorId", actorId);
77 if (clientId) url.searchParams.set("clientId", clientId);
78
79 const transport = new StreamableHTTPClientTransport(url);
80 const client = new Client({ name: "assistant-agent", version: "0.1.0" });
81 await client.connect(transport);
82 return client;
83}
84
85async function listMcpTools(client: Client): Promise<McpTool[]> {
86 const result = await client.listTools();
87 return result.tools.map((t) => ({
88 name: t.name,
89 description: t.description,
90 inputSchema: t.inputSchema as Record<string, unknown> | undefined,
91 }));
92}
93
94async function callMcpTool(client: Client, name: string, args: Record<string, unknown>): Promise<{
95 content: string;
96 isError: boolean;
97}> {
98 const result = await client.callTool({ name, arguments: args });
99 const text = (result.content as Array<{ type: string; text?: string }>)
100 .filter((c) => c.type === "text" && c.text)
101 .map((c) => c.text!)
102 .join("\n");
103 return { content: text, isError: result.isError === true };
104}
105
83// ---------------------------------------------------------------------------106// ---------------------------------------------------------------------------
84// Agent107// Agent
85// ---------------------------------------------------------------------------108// ---------------------------------------------------------------------------
86 109
87export function createAgent(options: Omit<AgentOptions, "onEvent">) {110export function createAgent(options: AgentOptions) {
88 return {111 return {
89 async run(prompt: string, onEvent?: (event: TaskEvent) => void): Promise<AgentResult> {112 async run(prompt: string, onEvent?: (event: TaskEvent) => void): Promise<AgentResult> {
90 const {113 const {
91 executor,114 executorUrl,
92 generate,115 generate,
93 workspaceId,116 workspaceId,
94 actorId,117 actorId,
95 clientId,118 clientId,
96 context,119 context,
97 maxCodeRuns = 20,120 maxToolCalls = 20,
98 timeoutMs = 30_000,
99 } = options;121 } = options;
100 122
101 function emit(event: TaskEvent): void {123 function emit(event: TaskEvent): void {
102 onEvent?.(event);124 onEvent?.(event);
103 }125 }
104 126
105 // 1. Fetch tool inventory127 // 1. Connect to executor MCP
106 emit({ type: "status", message: "Loading tools..." });128 emit({ type: "status", message: "Connecting..." });
107 const { data: tools, error: toolsError } = await executor.api.tools.get({129 let mcp: Client;
108 query: { workspaceId, actorId, clientId },130 try {
109 });131 mcp = await connectMcp(executorUrl, workspaceId, actorId, clientId);
110 132 } catch (err) {
111 if (toolsError || !tools) {133 const msg = `Failed to connect to executor MCP: ${err instanceof Error ? err.message : String(err)}`;
112 const msg = "Failed to load tools from executor";
113 emit({ type: "error", error: msg });134 emit({ type: "error", error: msg });
114 emit({ type: "completed" });135 emit({ type: "completed" });
115 return { text: msg, codeRuns: 0 };136 return { text: msg, toolCalls: 0 };
116 }137 }
117 138
118 // 2. Build system prompt + messages139 try {
119 const systemPrompt = buildSystemPrompt(tools as ToolDescriptor[], context);140 // 2. List tools (run_code description includes sandbox tool inventory)
120 const messages: Message[] = [141 emit({ type: "status", message: "Loading tools..." });
121 { role: "system", content: systemPrompt },142 const tools = await listMcpTools(mcp);
122 { role: "user", content: prompt },
123 ];
124
125 emit({ type: "status", message: "Thinking..." });
126 143
127 let codeRunCount = 0;144 if (tools.length === 0) {
128 145 const msg = "No tools available from executor";
129 // 3. Agent loop146 emit({ type: "error", error: msg });
130 while (codeRunCount < maxCodeRuns) {
131 const response = await generate(messages);
132
133 // No tool calls → done
134 if (!response.toolCalls || response.toolCalls.length === 0) {
135 const text = response.text ?? "";
136 emit({ type: "agent_message", text });
137 emit({ type: "completed" });147 emit({ type: "completed" });
138 return { text, codeRuns: codeRunCount };148 return { text: msg, toolCalls: 0 };
139 }149 }
140 150
141 for (const toolCall of response.toolCalls) {151 // 3. Build system prompt + messages
142 if (toolCall.name !== "run_code") {152 const systemPrompt = buildSystemPrompt(tools, context);
153 const messages: Message[] = [
154 { role: "system", content: systemPrompt },
155 { role: "user", content: prompt },
156 ];
157
158 // Convert MCP tools to model tool defs
159 const toolDefs: ToolDef[] = tools.map((t) => ({
160 name: t.name,
161 description: t.description,
162 inputSchema: t.inputSchema,
163 }));
164
165 emit({ type: "status", message: "Thinking..." });
166
167 let toolCallCount = 0;
168
169 // 4. Agent loop
170 while (toolCallCount < maxToolCalls) {
171 const response = await generate(messages, toolDefs);
172
173 // No tool calls → done
174 if (!response.toolCalls || response.toolCalls.length === 0) {
175 const text = response.text ?? "";
176 emit({ type: "agent_message", text });
177 emit({ type: "completed" });
178 return { text, toolCalls: toolCallCount };
179 }
180
181 for (const toolCall of response.toolCalls) {
182 toolCallCount++;
183
184 // Emit events
185 if (toolCall.name === "run_code" && toolCall.args["code"]) {
186 emit({ type: "code_generated", code: String(toolCall.args["code"]) });
187 }
188 emit({ type: "status", message: `Running ${toolCall.name}...` });
189
190 // 5. Forward to executor via MCP
191 const result = await callMcpTool(mcp, toolCall.name, toolCall.args);
192
193 // Emit result
194 emit({
195 type: "code_result",
196 taskId: "",
197 status: result.isError ? "failed" : "completed",
198 stdout: result.isError ? undefined : result.content,
199 error: result.isError ? result.content : undefined,
200 });
201
202 // 6. Feed result back to model
143 messages.push({ role: "assistant", content: "", toolCalls: [toolCall] });203 messages.push({ role: "assistant", content: "", toolCalls: [toolCall] });
144 messages.push({204 messages.push({
145 role: "tool",205 role: "tool",
146 toolCallId: toolCall.id,206 toolCallId: toolCall.id,
147 content: `Error: Unknown tool "${toolCall.name}". Use run_code to execute TypeScript code.`,207 content: result.content,
148 });208 });
149 continue;
150 }
151
152 const code = String(toolCall.args["code"] ?? "");
153 codeRunCount++;
154
155 emit({ type: "code_generated", code });
156 emit({ type: "status", message: "Running code..." });
157
158 // 4. Sync call to executor — blocks until task completes
159 const { data: result, error: runError } = await executor.api.tasks.run.post({
160 code,
161 workspaceId,
162 actorId,
163 clientId,
164 timeoutMs,
165 });
166
167 if (runError || !result) {
168 const errMsg = "Failed to execute code on executor";
169 messages.push({ role: "assistant", content: "", toolCalls: [toolCall] });
170 messages.push({ role: "tool", toolCallId: toolCall.id, content: `Error: ${errMsg}` });
171 continue;
172 }209 }
173
174 const r = result as { taskId?: string; status: string; stdout?: string; stderr?: string; error?: string; exitCode?: number };
175
176 // 5. Emit result event
177 emit({
178 type: "code_result",
179 taskId: r.taskId ?? "",
180 status: r.status,
181 exitCode: r.exitCode,
182 stdout: r.stdout,
183 stderr: r.stderr,
184 error: r.error,
185 });
186
187 // 6. Feed result back to model
188 const resultContent = r.status === "completed"
189 ? `Code executed successfully.\n${r.stdout ? `\nOutput:\n${r.stdout}` : ""}${r.stderr ? `\nStderr:\n${r.stderr}` : ""}`
190 : `Code execution failed (${r.status}).\n${r.error ? `Error: ${r.error}` : ""}${r.stderr ? `\nStderr:\n${r.stderr}` : ""}`;
191
192 messages.push({ role: "assistant", content: "", toolCalls: [toolCall] });
193 messages.push({ role: "tool", toolCallId: toolCall.id, content: resultContent });
194 }210 }
195 }
196 211
197 const text = "Reached maximum number of code executions.";212 const text = "Reached maximum number of tool calls.";
198 emit({ type: "agent_message", text });213 emit({ type: "agent_message", text });
199 emit({ type: "completed" });214 emit({ type: "completed" });
200 return { text, codeRuns: codeRunCount };215 return { text, toolCalls: toolCallCount };
216 } finally {
217 await mcp.close().catch(() => {});
218 }
201 },219 },
202 };220 };
203}221}
assistant/packages/core/src/index.ts+2−2
@@ -1,5 +1,5 @@
1export { createAgent } from "./agent";1export { createAgent } from "./agent";
2export type { AgentOptions, AgentResult, ToolDescriptor } from "./agent";2export type { AgentOptions, AgentResult, McpTool } from "./agent";
3export type { TaskEvent, TaskStatusEvent, TaskCodeGeneratedEvent, TaskCodeResultEvent, TaskAgentMessageEvent, TaskErrorEvent, TaskCompletedEvent } from "./events";3export type { TaskEvent, TaskStatusEvent, TaskCodeGeneratedEvent, TaskCodeResultEvent, TaskAgentMessageEvent, TaskErrorEvent, TaskCompletedEvent } from "./events";
4export { createModel } from "./model";4export { createModel } from "./model";
5export type { Message, ToolCall, GenerateResult, ModelOptions } from "./model";5export type { Message, ToolCall, ToolDef, GenerateResult, ModelOptions } from "./model";
assistant/packages/core/src/model.ts+20−14
@@ -1,5 +1,7 @@
1/**1/**
2 * LLM adapter — wraps pi-ai to implement a simple generate interface.2 * LLM adapter — wraps pi-ai to implement a simple generate interface.
3 *
4 * Tools are passed dynamically per call (from MCP tools/list).
3 */5 */
4 6
5import {7import {
@@ -15,7 +17,6 @@ import { · 9 unmodified lines
15 type TextContent,17 type TextContent,
16 type ToolCall as PiToolCall,18 type ToolCall as PiToolCall,
17} from "@mariozechner/pi-ai";19} from "@mariozechner/pi-ai";
18import { Type } from "@sinclair/typebox";
19 20
20// ---------------------------------------------------------------------------21// ---------------------------------------------------------------------------
21// Types22// Types
@@ -34,6 +35,12 @@ export interface ToolCall { · 12 unmodified lines
34 args: Record<string, unknown>;35 args: Record<string, unknown>;
35}36}
36 37
38export interface ToolDef {
39 name: string;
40 description?: string;
41 inputSchema?: Record<string, unknown>;
42}
43
37export interface GenerateResult {44export interface GenerateResult {
38 text?: string;45 text?: string;
39 toolCalls?: ToolCall[];46 toolCalls?: ToolCall[];
@@ -48,19 +55,16 @@ export interface ModelOptions { · 8 unmodified lines
48}55}
49 56
50// ---------------------------------------------------------------------------57// ---------------------------------------------------------------------------
51// run_code tool (the only tool the model can call)58// Tool conversion (MCP → pi-ai)
52// ---------------------------------------------------------------------------59// ---------------------------------------------------------------------------
53 60
54const RUN_CODE_TOOL: PiTool = {61function convertTool(tool: ToolDef): PiTool {
55 name: "run_code",62 return {
56 description:63 name: tool.name,
57 "Execute TypeScript code in a sandboxed environment. The code has access to a `tools` object with typed methods for interacting with external services. Use `return` to return a value.",64 description: tool.description ?? "",
58 parameters: Type.Object({65 parameters: (tool.inputSchema ?? { type: "object", properties: {} }) as PiTool["parameters"],
59 code: Type.String({66 };
60 description: "TypeScript code to execute. Use `await tools.<namespace>.<method>(input)` to call tools. Use `return` to return a value.",67}
61 }),
62 }),
63};
64 68
65// ---------------------------------------------------------------------------69// ---------------------------------------------------------------------------
66// Message conversion70// Message conversion
@@ -178,12 +182,14 @@ export function createModel(options: ModelOptions = {}) { · 111 unmodified lines
178 const model = getModel(provider as Parameters<typeof getModel>[0], modelId as never);182 const model = getModel(provider as Parameters<typeof getModel>[0], modelId as never);
179 183
180 return {184 return {
181 async generate(messages: Message[]): Promise<GenerateResult> {185 async generate(messages: Message[], tools?: ToolDef[]): Promise<GenerateResult> {
182 const { systemPrompt, piMessages } = convertMessages(messages);186 const { systemPrompt, piMessages } = convertMessages(messages);
183 187
188 const piTools: PiTool[] = tools?.map(convertTool) ?? [];
189
184 const context: PiContext = {190 const context: PiContext = {
185 messages: piMessages,191 messages: piMessages,
186 tools: [RUN_CODE_TOOL],192 tools: piTools,
187 };193 };
188 if (systemPrompt !== undefined) {194 if (systemPrompt !== undefined) {
189 context.systemPrompt = systemPrompt;195 context.systemPrompt = systemPrompt;
assistant/packages/server/package.json+0−1
@@ -12,7 +12,6 @@ · 11 unmodified lines
12 },12 },
13 "dependencies": {13 "dependencies": {
14 "@assistant/core": "workspace:*",14 "@assistant/core": "workspace:*",
15 "@assistant/agent-executor-adapter": "workspace:*",
16 "convex": "^1.31.7",15 "convex": "^1.31.7",
17 "elysia": "latest",16 "elysia": "latest",
18 "@elysiajs/eden": "latest"17 "@elysiajs/eden": "latest"
assistant/packages/server/src/index.ts+19−10
@@ -1,13 +1,13 @@
1/**1/**
2 * Assistant Server entry point.2 * Assistant Server entry point.
3 *3 *
4 * Connects to the executor, sets up the agent, and serves the API.4 * Bootstraps executor context, sets up the agent, and serves the API.
5 * The agent connects to the executor via MCP — no Eden Treaty needed here.
5 */6 */
6 7
7import { readFileSync } from "node:fs";8import { readFileSync } from "node:fs";
8import { createApp } from "./routes";9import { createApp } from "./routes";
9import { createModel } from "@assistant/core";10import { createModel } from "@assistant/core";
10import { createExecutorClient } from "@assistant/agent-executor-adapter";
11 11
12// ---------------------------------------------------------------------------12// ---------------------------------------------------------------------------
13// API key resolution13// API key resolution
@@ -38,6 +38,7 @@ function getAnthropicApiKey(): string | undefined { · 24 unmodified lines
38 38
39const PORT = Number(Bun.env.PORT ?? 3000);39const PORT = Number(Bun.env.PORT ?? 3000);
40const EXECUTOR_URL = Bun.env.EXECUTOR_URL ?? "http://localhost:4001";40const EXECUTOR_URL = Bun.env.EXECUTOR_URL ?? "http://localhost:4001";
41const CONVEX_URL = Bun.env.CONVEX_URL ?? "http://127.0.0.1:3210";
41 42
42const apiKey = getAnthropicApiKey();43const apiKey = getAnthropicApiKey();
43if (!apiKey) {44if (!apiKey) {
@@ -48,16 +49,26 @@ if (!apiKey) { · 4 unmodified lines
48// Boot49// Boot
49// ---------------------------------------------------------------------------50// ---------------------------------------------------------------------------
50 51
51const executor = createExecutorClient(EXECUTOR_URL);
52const model = createModel({ apiKey });52const model = createModel({ apiKey });
53 53
54// Bootstrap an anonymous context on the executor for this server instance54// Bootstrap an anonymous context on the executor
55const { data: anonCtx, error: bootstrapError } = await executor.api.auth.anonymous.bootstrap.post({});55const bootstrapResp = await fetch(`${EXECUTOR_URL}/api/auth/anonymous/bootstrap`, {
56if (bootstrapError || !anonCtx) {56 method: "POST",
57 headers: { "content-type": "application/json" },
58 body: JSON.stringify({}),
59});
60
61if (!bootstrapResp.ok) {
57 console.error("Failed to bootstrap executor context. Is the executor running at", EXECUTOR_URL, "?");62 console.error("Failed to bootstrap executor context. Is the executor running at", EXECUTOR_URL, "?");
58 process.exit(1);63 process.exit(1);
59}64}
60 65
66const anonCtx = await bootstrapResp.json() as {
67 workspaceId: string;
68 actorId: string;
69 clientId: string;
70};
71
61console.log(`[assistant] executor context: workspace=${anonCtx.workspaceId} actor=${anonCtx.actorId}`);72console.log(`[assistant] executor context: workspace=${anonCtx.workspaceId} actor=${anonCtx.actorId}`);
62 73
63// Build context string74// Build context string
@@ -66,11 +77,9 @@ if (Bun.env.POSTHOG_PROJECT_ID) { · 2 unmodified lines
66 contextLines.push(`- PostHog project ID: ${Bun.env.POSTHOG_PROJECT_ID}`);77 contextLines.push(`- PostHog project ID: ${Bun.env.POSTHOG_PROJECT_ID}`);
67}78}
68 79
69const CONVEX_URL = Bun.env.CONVEX_URL ?? "http://127.0.0.1:3210";
70
71const app = createApp({80const app = createApp({
72 executor,81 executorUrl: EXECUTOR_URL,
73 generate: (messages) => model.generate(messages),82 generate: (messages, tools) => model.generate(messages, tools),
74 workspaceId: anonCtx.workspaceId,83 workspaceId: anonCtx.workspaceId,
75 actorId: anonCtx.actorId,84 actorId: anonCtx.actorId,
76 clientId: anonCtx.clientId,85 clientId: anonCtx.clientId,
assistant/packages/server/src/routes.ts+10−11
@@ -7,8 +7,7 @@ · 6 unmodified lines
7 7
8import { Elysia, t } from "elysia";8import { Elysia, t } from "elysia";
9import { createAgent } from "@assistant/core";9import { createAgent } from "@assistant/core";
10import type { ExecutorClient } from "@assistant/agent-executor-adapter";10import type { GenerateResult, Message, ToolDef, TaskEvent } from "@assistant/core";
11import type { GenerateResult, Message, TaskEvent } from "@assistant/core";
12import { ConvexHttpClient } from "convex/browser";11import { ConvexHttpClient } from "convex/browser";
13import { api } from "@executor/convex/_generated/api";12import { api } from "@executor/convex/_generated/api";
14 13
@@ -17,8 +16,8 @@ import { api } from "@executor/convex/_generated/api"; · 2 unmodified lines
17// ---------------------------------------------------------------------------16// ---------------------------------------------------------------------------
18 17
19export interface ServerOptions {18export interface ServerOptions {
20 readonly executor: ExecutorClient;19 readonly executorUrl: string;
21 readonly generate: (messages: Message[]) => Promise<GenerateResult>;20 readonly generate: (messages: Message[], tools?: ToolDef[]) => Promise<GenerateResult>;
22 readonly workspaceId: string;21 readonly workspaceId: string;
23 readonly actorId: string;22 readonly actorId: string;
24 readonly clientId?: string;23 readonly clientId?: string;
@@ -32,7 +31,7 @@ export interface ServerOptions { · 7 unmodified lines
32 31
33export function createApp(options: ServerOptions) {32export function createApp(options: ServerOptions) {
34 const agent = createAgent({33 const agent = createAgent({
35 executor: options.executor,34 executorUrl: options.executorUrl,
36 generate: options.generate,35 generate: options.generate,
37 workspaceId: options.workspaceId,36 workspaceId: options.workspaceId,
38 actorId: options.actorId,37 actorId: options.actorId,
@@ -68,18 +67,18 @@ export function createApp(options: ServerOptions) { · 29 unmodified lines
68 });67 });
69 68
70 // Fire and forget — agent runs, writes results to Convex69 // Fire and forget — agent runs, writes results to Convex
71 let codeRuns = 0;70 let toolCalls = 0;
72 71
73 agent.run(body.prompt, (event: TaskEvent) => {72 agent.run(body.prompt, (event: TaskEvent) => {
74 if (event.type === "code_result") {73 if (event.type === "code_result") {
75 codeRuns++;74 toolCalls++;
76 }75 }
77 76
78 if (event.type === "agent_message") {77 if (event.type === "agent_message") {
79 convex.mutation(api.database.updateAgentTask, {78 convex.mutation(api.database.updateAgentTask, {
80 agentTaskId,79 agentTaskId,
81 resultText: event.text,80 resultText: event.text,
82 codeRuns,81 codeRuns: toolCalls,
83 }).catch((err) => console.error(`[agent task ${agentTaskId}] convex write error:`, err));82 }).catch((err) => console.error(`[agent task ${agentTaskId}] convex write error:`, err));
84 }83 }
85 84
@@ -87,7 +86,7 @@ export function createApp(options: ServerOptions) { · 1 unmodified line
87 convex.mutation(api.database.updateAgentTask, {86 convex.mutation(api.database.updateAgentTask, {
88 agentTaskId,87 agentTaskId,
89 status: "completed",88 status: "completed",
90 codeRuns,89 codeRuns: toolCalls,
91 }).catch((err) => console.error(`[agent task ${agentTaskId}] convex write error:`, err));90 }).catch((err) => console.error(`[agent task ${agentTaskId}] convex write error:`, err));
92 }91 }
93 92
@@ -96,7 +95,7 @@ export function createApp(options: ServerOptions) { · 2 unmodified lines
96 agentTaskId,95 agentTaskId,
97 status: "failed",96 status: "failed",
98 error: event.error,97 error: event.error,
99 codeRuns,98 codeRuns: toolCalls,
100 }).catch((err) => console.error(`[agent task ${agentTaskId}] convex write error:`, err));99 }).catch((err) => console.error(`[agent task ${agentTaskId}] convex write error:`, err));
101 }100 }
102 }).catch((err) => {101 }).catch((err) => {
@@ -105,7 +104,7 @@ export function createApp(options: ServerOptions) { · 2 unmodified lines
105 agentTaskId,104 agentTaskId,
106 status: "failed",105 status: "failed",
107 error: err instanceof Error ? err.message : String(err),106 error: err instanceof Error ? err.message : String(err),
108 codeRuns,107 codeRuns: toolCalls,
109 }).catch((err2) => console.error(`[agent task ${agentTaskId}] convex write error:`, err2));108 }).catch((err2) => console.error(`[agent task ${agentTaskId}] convex write error:`, err2));
110 });109 });
111 110
bun.lock+1−3
@@ -50,9 +50,8 @@ · 49 unmodified lines
50 "assistant/packages/core": {50 "assistant/packages/core": {
51 "name": "@assistant/core",51 "name": "@assistant/core",
52 "dependencies": {52 "dependencies": {
53 "@assistant/agent-executor-adapter": "workspace:*",
54 "@mariozechner/pi-ai": "^0.52.6",53 "@mariozechner/pi-ai": "^0.52.6",
55 "@sinclair/typebox": "^0.34.48",54 "@modelcontextprotocol/sdk": "^1.26.0",
56 },55 },
57 "devDependencies": {56 "devDependencies": {
58 "@elysiajs/eden": "^1.4.6",57 "@elysiajs/eden": "^1.4.6",
@@ -62,7 +61,6 @@ · 3 unmodified lines
62 "assistant/packages/server": {61 "assistant/packages/server": {
63 "name": "@assistant/server",62 "name": "@assistant/server",
64 "dependencies": {63 "dependencies": {
65 "@assistant/agent-executor-adapter": "workspace:*",
66 "@assistant/core": "workspace:*",64 "@assistant/core": "workspace:*",
67 "@elysiajs/eden": "latest",65 "@elysiajs/eden": "latest",
68 "convex": "^1.31.7",66 "convex": "^1.31.7",
executor/apps/server/src/index.ts+26−51
@@ -1,7 +1,7 @@
1import { Elysia, t } from "elysia";1import { Elysia, t } from "elysia";
2import { ExecutorDatabase } from "./database";2import { ExecutorDatabase } from "./database";
3import { TaskEventHub } from "./events";3import { TaskEventHub } from "./events";
4import { handleMcpRequest } from "./mcp-server";4import { handleMcpRequest, type McpWorkspaceContext } from "./mcp-server";
5import { LocalBunRuntime } from "./runtimes/local-bun-runtime";5import { LocalBunRuntime } from "./runtimes/local-bun-runtime";
6import { VercelSandboxRuntime } from "./runtimes/vercel-sandbox-runtime";6import { VercelSandboxRuntime } from "./runtimes/vercel-sandbox-runtime";
7import { ExecutorService, getTaskTerminalState } from "./service";7import { ExecutorService, getTaskTerminalState } from "./service";
@@ -151,6 +151,14 @@ function isInternalAuthorized(request: Request): boolean { · 143 unmodified lines
151 return header.slice("Bearer ".length) === internalToken;151 return header.slice("Bearer ".length) === internalToken;
152}152}
153 153
154function parseMcpContext(url: URL): McpWorkspaceContext | undefined {
155 const workspaceId = url.searchParams.get("workspaceId");
156 const actorId = url.searchParams.get("actorId");
157 if (!workspaceId || !actorId) return undefined;
158 const clientId = url.searchParams.get("clientId") ?? undefined;
159 return { workspaceId, actorId, clientId };
160}
161
154// ── Elysia app ──162// ── Elysia app ──
155 163
156const app = new Elysia()164const app = new Elysia()
@@ -163,9 +171,23 @@ const app = new Elysia() · 6 unmodified lines
163 .options("/*", () => new Response(null, { status: 204 }))171 .options("/*", () => new Response(null, { status: 204 }))
164 172
165 // ── MCP (raw protocol passthrough) ──173 // ── MCP (raw protocol passthrough) ──
166 .post("/mcp", async ({ request }) => await handleMcpRequest(service, request))174 // Optional query params: ?workspaceId=...&actorId=... to bind workspace context.
167 .get("/mcp", async ({ request }) => await handleMcpRequest(service, request))175 // When bound, run_code description includes sandbox tool inventory and input is simplified.
168 .delete("/mcp", async ({ request }) => await handleMcpRequest(service, request))176 .post("/mcp", async ({ request }) => {
177 const url = new URL(request.url);
178 const context = parseMcpContext(url);
179 return await handleMcpRequest(service, request, context);
180 })
181 .get("/mcp", async ({ request }) => {
182 const url = new URL(request.url);
183 const context = parseMcpContext(url);
184 return await handleMcpRequest(service, request, context);
185 })
186 .delete("/mcp", async ({ request }) => {
187 const url = new URL(request.url);
188 const context = parseMcpContext(url);
189 return await handleMcpRequest(service, request, context);
190 })
169 191
170 // ── Health ──192 // ── Health ──
171 .get("/api/health", () => ({193 .get("/api/health", () => ({
@@ -262,53 +284,6 @@ const app = new Elysia() · 90 unmodified lines
262 query: t.Object({ workspaceId: t.String() }),284 query: t.Object({ workspaceId: t.String() }),
263 })285 })
264 286
265 // ── Sync run (blocks until task completes, returns result inline) ──
266 .post("/api/tasks/run", async ({ body, set }) => {
267 try {
268 const { task } = await service.createTask(body);
269 // createTask fires executeTask in background when autoExecute is on.
270 // We need to wait for it to finish.
271 const deadline = Date.now() + (body.timeoutMs ?? 30_000) + 15_000;
272
273 while (Date.now() < deadline) {
274 const current = await service.getTask(task.id);
275 if (!current) break;
276
277 if (current.status === "completed" || current.status === "failed" || current.status === "timed_out" || current.status === "denied") {
278 return {
279 taskId: current.id,
280 status: current.status,
281 stdout: current.stdout,
282 stderr: current.stderr,
283 exitCode: current.exitCode,
284 error: current.error,
285 };
286 }
287
288 await Bun.sleep(200);
289 }
290
291 return {
292 taskId: task.id,
293 status: "timed_out" as const,
294 error: "Task did not complete within deadline",
295 };
296 } catch (cause) {
297 set.status = 400;
298 return { error: cause instanceof Error ? cause.message : String(cause) };
299 }
300 }, {
301 body: t.Object({
302 code: t.String(),
303 timeoutMs: t.Optional(t.Number()),
304 runtimeId: t.Optional(t.String()),
305 metadata: t.Optional(t.Record(t.String(), t.Unknown())),
306 workspaceId: t.String(),
307 actorId: t.String(),
308 clientId: t.Optional(t.String()),
309 }),
310 })
311
312 // ── Tasks ──287 // ── Tasks ──
313 .get("/api/tasks", async ({ query, set }) => {288 .get("/api/tasks", async ({ query, set }) => {
314 if (!query.workspaceId) {289 if (!query.workspaceId) {
executor/apps/server/src/mcp-server.test.ts+7−1
@@ -2,7 +2,7 @@ import { expect, test } from "bun:test"; · 1 unmodified line
2import { Client } from "@modelcontextprotocol/sdk/client/index.js";2import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";3import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4import { handleMcpRequest } from "./mcp-server";4import { handleMcpRequest } from "./mcp-server";
5import type { AnonymousContext, CreateTaskInput, TaskRecord } from "./types";5import type { AnonymousContext, CreateTaskInput, TaskRecord, ToolDescriptor } from "./types";
6 6
7class FakeMcpService {7class FakeMcpService {
8 private readonly tasks = new Map<string, TaskRecord>();8 private readonly tasks = new Map<string, TaskRecord>();
@@ -71,6 +71,12 @@ class FakeMcpService { · 62 unmodified lines
71 this.sessions.set(context.sessionId, context);71 this.sessions.set(context.sessionId, context);
72 return context;72 return context;
73 }73 }
74
75 async listTools(_context?: { workspaceId: string; actorId?: string; clientId?: string }): Promise<ToolDescriptor[]> {
76 return [
77 { path: "utils.get_time", description: "Get the current time", approval: "auto" },
78 ];
79 }
74}80}
75 81
76async function withMcpClient<T>(82async function withMcpClient<T>(
executor/apps/server/src/mcp-server.ts+134−71
@@ -2,39 +2,32 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; · 1 unmodified line
2import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";2import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
3import { z } from "zod";3import { z } from "zod";
4import { getTaskTerminalState } from "./service";4import { getTaskTerminalState } from "./service";
5import type { AnonymousContext, CreateTaskInput, TaskRecord } from "./types";5import type { AnonymousContext, CreateTaskInput, TaskRecord, ToolDescriptor } from "./types";
6
7// ---------------------------------------------------------------------------
8// Service interface
9// ---------------------------------------------------------------------------
6 10
7interface McpExecutorService {11interface McpExecutorService {
8 createTask(input: CreateTaskInput): Promise<{ task: TaskRecord }>;12 createTask(input: CreateTaskInput): Promise<{ task: TaskRecord }>;
9 getTask(taskId: string, workspaceId?: string): Promise<TaskRecord | null>;13 getTask(taskId: string, workspaceId?: string): Promise<TaskRecord | null>;
10 bootstrapAnonymousContext(sessionId?: string): Promise<AnonymousContext>;14 bootstrapAnonymousContext(sessionId?: string): Promise<AnonymousContext>;
15 listTools(context?: { workspaceId: string; actorId?: string; clientId?: string }): Promise<ToolDescriptor[]>;
11}16}
12 17
13const RUN_CODE_INPUT = {18// ---------------------------------------------------------------------------
14 code: z.string().min(1),19// Workspace context (optional, from query params)
15 timeoutMs: z.number().int().min(1).max(600_000).optional(),20// ---------------------------------------------------------------------------
16 runtimeId: z.string().optional(),
17 metadata: z.record(z.string(), z.any()).optional(),
18 workspaceId: z.string().optional(),
19 actorId: z.string().optional(),
20 clientId: z.string().optional(),
21 sessionId: z.string().optional(),
22 waitForResult: z.boolean().optional(),
23 resultTimeoutMs: z.number().int().min(100).max(900_000).optional(),
24} as const;
25 21
26type RunCodeInput = {22export interface McpWorkspaceContext {
27 code: string;23 workspaceId: string;
28 timeoutMs?: number;24 actorId: string;
29 runtimeId?: string;
30 metadata?: Record<string, unknown>;
31 workspaceId?: string;
32 actorId?: string;
33 clientId?: string;25 clientId?: string;
34 sessionId?: string;26}
35 waitForResult?: boolean;27
36 resultTimeoutMs?: number;28// ---------------------------------------------------------------------------
37};29// Helpers
30// ---------------------------------------------------------------------------
38 31
39function asCodeBlock(language: string, value: string): string {32function asCodeBlock(language: string, value: string): string {
40 return `\n\n\`\`\`${language}\n${value}\n\`\`\``;33 return `\n\n\`\`\`${language}\n${value}\n\`\`\``;
@@ -78,54 +71,82 @@ async function waitForTerminalTask( · 37 unmodified lines
78 const deadline = Date.now() + waitTimeoutMs;71 const deadline = Date.now() + waitTimeoutMs;
79 while (Date.now() < deadline) {72 while (Date.now() < deadline) {
80 const task = await service.getTask(taskId, workspaceId);73 const task = await service.getTask(taskId, workspaceId);
81 if (!task) {74 if (!task) return null;
82 return null;75 if (getTaskTerminalState(task.status)) return task;
83 }
84 if (getTaskTerminalState(task.status)) {
85 return task;
86 }
87 await Bun.sleep(300);76 await Bun.sleep(300);
88 }77 }
89 return await service.getTask(taskId, workspaceId);78 return await service.getTask(taskId, workspaceId);
90}79}
91 80
92async function resolveExecutionContext(81// ---------------------------------------------------------------------------
93 service: McpExecutorService,82// Build run_code description with sandbox tool inventory
94 input: RunCodeInput,83// ---------------------------------------------------------------------------
95 mcpSessionId?: string,
96): Promise<{ workspaceId: string; actorId: string; clientId?: string; sessionId?: string }> {
97 if (input.workspaceId || input.actorId) {
98 if (!input.workspaceId || !input.actorId) {
99 throw new Error("workspaceId and actorId must be provided together");
100 }
101 return {
102 workspaceId: input.workspaceId,
103 actorId: input.actorId,
104 clientId: input.clientId,
105 sessionId: input.sessionId,
106 };
107 }
108 84
109 const seededSessionId = input.sessionId ?? (mcpSessionId ? `mcp_${mcpSessionId}` : undefined);85function buildRunCodeDescription(tools?: ToolDescriptor[]): string {
110 const anonymous = await service.bootstrapAnonymousContext(seededSessionId);86 const base =
111 return {87 "Execute TypeScript code in a sandboxed runtime. The code has access to a `tools` object with typed methods for calling external services. Use `return` to return a value. Waits for completion and returns stdout/stderr.";
112 workspaceId: anonymous.workspaceId,88
113 actorId: anonymous.actorId,89 if (!tools || tools.length === 0) return base;
114 clientId: input.clientId ?? anonymous.clientId,90
115 sessionId: anonymous.sessionId,91 const toolLines = tools.map((t) => {
116 };92 const args = t.argsType ?? "unknown";
93 const returns = t.returnsType ?? "unknown";
94 const approval = t.approval === "required" ? " [approval required]" : "";
95 return ` - tools.${t.path}(${args}): ${returns}${approval} — ${t.description}`;
96 });
97
98 return `${base}\n\nAvailable tools in the sandbox:\n${toolLines.join("\n")}`;
117}99}
118 100
119function createRunCodeTool(service: McpExecutorService) {101// ---------------------------------------------------------------------------
102// run_code tool handler
103// ---------------------------------------------------------------------------
104
105function createRunCodeTool(
106 service: McpExecutorService,
107 boundContext?: McpWorkspaceContext,
108) {
120 return async (109 return async (
121 input: RunCodeInput,110 input: {
111 code: string;
112 timeoutMs?: number;
113 runtimeId?: string;
114 metadata?: Record<string, unknown>;
115 workspaceId?: string;
116 actorId?: string;
117 clientId?: string;
118 sessionId?: string;
119 waitForResult?: boolean;
120 resultTimeoutMs?: number;
121 },
122 extra: { sessionId?: string },122 extra: { sessionId?: string },
123 ): Promise<{123 ): Promise<{
124 content: Array<{ type: "text"; text: string }>;124 content: Array<{ type: "text"; text: string }>;
125 structuredContent?: Record<string, unknown>;125 structuredContent?: Record<string, unknown>;
126 isError?: boolean;126 isError?: boolean;
127 }> => {127 }> => {
128 const context = await resolveExecutionContext(service, input, extra.sessionId);128 // Resolve context: bound context takes priority, then input, then anonymous
129 let context: { workspaceId: string; actorId: string; clientId?: string; sessionId?: string };
130
131 if (boundContext) {
132 context = { ...boundContext, sessionId: input.sessionId };
133 } else if (input.workspaceId && input.actorId) {
134 context = {
135 workspaceId: input.workspaceId,
136 actorId: input.actorId,
137 clientId: input.clientId,
138 sessionId: input.sessionId,
139 };
140 } else {
141 const seededSessionId = input.sessionId ?? (extra.sessionId ? `mcp_${extra.sessionId}` : undefined);
142 const anonymous = await service.bootstrapAnonymousContext(seededSessionId);
143 context = {
144 workspaceId: anonymous.workspaceId,
145 actorId: anonymous.actorId,
146 clientId: input.clientId ?? anonymous.clientId,
147 sessionId: anonymous.sessionId,
148 };
149 }
129 150
130 const created = await service.createTask({151 const created = await service.createTask({
131 code: input.code,152 code: input.code,
@@ -164,13 +185,7 @@ function createRunCodeTool(service: McpExecutorService) { · 32 unmodified lines
164 if (!getTaskTerminalState(task.status)) {185 if (!getTaskTerminalState(task.status)) {
165 return {186 return {
166 content: [textContent(`Task ${task.id} is still ${task.status}`)],187 content: [textContent(`Task ${task.id} is still ${task.status}`)],
167 structuredContent: {188 structuredContent: { taskId: task.id, status: task.status, workspaceId: context.workspaceId, actorId: context.actorId, sessionId: context.sessionId },
168 taskId: task.id,
169 status: task.status,
170 workspaceId: context.workspaceId,
171 actorId: context.actorId,
172 sessionId: context.sessionId,
173 },
174 };189 };
175 }190 }
176 191
@@ -194,31 +209,79 @@ function createRunCodeTool(service: McpExecutorService) { · 17 unmodified lines
194 };209 };
195}210}
196 211
197function createMcpServer(service: McpExecutorService): McpServer {212// ---------------------------------------------------------------------------
213// Input schema — when context is bound, workspace fields aren't needed
214// ---------------------------------------------------------------------------
215
216const FULL_INPUT = {
217 code: z.string().min(1),
218 timeoutMs: z.number().int().min(1).max(600_000).optional(),
219 runtimeId: z.string().optional(),
220 metadata: z.record(z.string(), z.any()).optional(),
221 workspaceId: z.string().optional(),
222 actorId: z.string().optional(),
223 clientId: z.string().optional(),
224 sessionId: z.string().optional(),
225 waitForResult: z.boolean().optional(),
226 resultTimeoutMs: z.number().int().min(100).max(900_000).optional(),
227} as const;
228
229const BOUND_INPUT = {
230 code: z.string().min(1),
231 timeoutMs: z.number().int().min(1).max(600_000).optional(),
232 runtimeId: z.string().optional(),
233 metadata: z.record(z.string(), z.any()).optional(),
234} as const;
235
236// ---------------------------------------------------------------------------
237// MCP server factory
238// ---------------------------------------------------------------------------
239
240async function createMcpServer(
241 service: McpExecutorService,
242 context?: McpWorkspaceContext,
243): Promise<McpServer> {
198 const mcp = new McpServer(244 const mcp = new McpServer(
199 { name: "executor", version: "0.1.0" },245 { name: "executor", version: "0.1.0" },
200 { capabilities: { tools: {} } },246 { capabilities: { tools: {} } },
201 );247 );
202 248
249 // If workspace context is provided, fetch tool inventory for richer description
250 let tools: ToolDescriptor[] | undefined;
251 if (context) {
252 tools = await service.listTools({
253 workspaceId: context.workspaceId,
254 actorId: context.actorId,
255 clientId: context.clientId,
256 });
257 }
258
203 mcp.registerTool(259 mcp.registerTool(
204 "run_code",260 "run_code",
205 {261 {
206 description:262 description: buildRunCodeDescription(tools),
207 "Run JavaScript/TypeScript code in the executor runtime. Defaults to waiting for terminal result and returns stdout/stderr.",263 inputSchema: context ? BOUND_INPUT : FULL_INPUT,
208 inputSchema: RUN_CODE_INPUT,
209 },264 },
210 createRunCodeTool(service),265 createRunCodeTool(service, context),
211 );266 );
212 267
213 return mcp;268 return mcp;
214}269}
215 270
216export async function handleMcpRequest(service: McpExecutorService, request: Request): Promise<Response> {271// ---------------------------------------------------------------------------
272// Request handler
273// ---------------------------------------------------------------------------
274
275export async function handleMcpRequest(
276 service: McpExecutorService,
277 request: Request,
278 context?: McpWorkspaceContext,
279): Promise<Response> {
217 const transport = new WebStandardStreamableHTTPServerTransport({280 const transport = new WebStandardStreamableHTTPServerTransport({
218 sessionIdGenerator: undefined,281 sessionIdGenerator: undefined,
219 enableJsonResponse: true,282 enableJsonResponse: true,
220 });283 });
221 const mcp = createMcpServer(service);284 const mcp = await createMcpServer(service, context);
222 285
223 try {286 try {
224 await mcp.connect(transport);287 await mcp.connect(transport);