From 1a99b17656407e0cd6470b248bb0262afe96ea37 Mon Sep 17 00:00:00 2001 From: Jeff Haynie Date: Thu, 7 May 2026 06:47:43 -0500 Subject: [PATCH 1/4] Split Pi AI Gateway plugin into package --- README.md | 1 + bun.lock | 57 ++++++++++++------- package.json | 4 +- packages/coder-tui/package.json | 3 +- packages/coder-tui/src/index.ts | 2 +- packages/coder-tui/tsconfig.json | 6 +- packages/pi-aigateway/README.md | 3 + packages/pi-aigateway/package.json | 41 +++++++++++++ .../src/index.ts} | 6 +- packages/pi-aigateway/tsconfig.json | 16 ++++++ tsconfig.json | 1 + 11 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 packages/pi-aigateway/README.md create mode 100644 packages/pi-aigateway/package.json rename packages/{coder-tui/src/aigateway.ts => pi-aigateway/src/index.ts} (99%) create mode 100644 packages/pi-aigateway/tsconfig.json diff --git a/README.md b/README.md index 42d87c398..06c4464a3 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ The structure of this mono repository: - `packages/frontend` - Reusable code for web frontends including WebRTC peer connections - `packages/keyvalue` - Key-value storage service client - `packages/opencode` - Opencode agent plugins for Agentuity +- `packages/pi-aigateway` - Pi coding agent provider plugin for Agentuity AI Gateway models - `packages/postgres` - Resilient PostgreSQL client with automatic reconnection - `packages/queue` - Queue service client for publishing messages to queues - `packages/react` - React package for the Browser including WebRTC hooks diff --git a/bun.lock b/bun.lock index 2624bb576..9a6f93fad 100644 --- a/bun.lock +++ b/bun.lock @@ -535,8 +535,7 @@ "name": "@agentuity/coder-tui", "version": "2.0.15", "dependencies": { - "@agentuity/core": "workspace:*", - "@agentuity/server": "workspace:*", + "@agentuity/pi-aigateway": "workspace:*", "@mariozechner/pi-coding-agent": "^0.72.1", "@mariozechner/pi-tui": "^0.72.1", "@sinclair/typebox": "^0.34.49", @@ -685,6 +684,20 @@ "typescript": "^5.9.0", }, }, + "packages/pi-aigateway": { + "name": "@agentuity/pi-aigateway", + "version": "2.0.15", + "dependencies": { + "@agentuity/core": "workspace:*", + "@agentuity/server": "workspace:*", + "@mariozechner/pi-coding-agent": "^0.72.1", + }, + "devDependencies": { + "@types/bun": "^1.3.9", + "bun-types": "^1.3.9", + "typescript": "^5.9.0", + }, + }, "packages/postgres": { "name": "@agentuity/postgres", "version": "2.0.15", @@ -1014,6 +1027,8 @@ "@agentuity/opencode": ["@agentuity/opencode@workspace:packages/opencode"], + "@agentuity/pi-aigateway": ["@agentuity/pi-aigateway@workspace:packages/pi-aigateway"], + "@agentuity/postgres": ["@agentuity/postgres@workspace:packages/postgres"], "@agentuity/queue": ["@agentuity/queue@workspace:packages/queue"], @@ -3020,7 +3035,7 @@ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - "gaxios": ["gaxios@7.1.4", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA=="], + "gaxios": ["gaxios@6.7.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", "uuid": "^9.0.1" } }, "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ=="], "gcp-metadata": ["gcp-metadata@6.1.1", "", { "dependencies": { "gaxios": "^6.1.1", "google-logging-utils": "^0.0.2", "json-bigint": "^1.0.0" } }, "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A=="], @@ -3066,7 +3081,7 @@ "google-auth-library": ["google-auth-library@10.6.2", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw=="], - "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], + "google-logging-utils": ["google-logging-utils@0.0.2", "", {}, "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ=="], "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], @@ -3148,7 +3163,7 @@ "husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="], - "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], @@ -3572,7 +3587,7 @@ "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], - "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], "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=="], @@ -4564,6 +4579,8 @@ "cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="], + "d3-dsv/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + "d3-sankey/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="], "d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="], @@ -4588,6 +4605,8 @@ "effect/uuid": ["uuid@13.0.2", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw=="], + "encoding-sniffer/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + "escodegen/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "extract-zip/yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="], @@ -4596,12 +4615,14 @@ "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "gcp-metadata/gaxios": ["gaxios@6.7.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", "uuid": "^9.0.1" } }, "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ=="], + "gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], - "gcp-metadata/google-logging-utils": ["google-logging-utils@0.0.2", "", {}, "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ=="], + "google-auth-library/gaxios": ["gaxios@7.1.4", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA=="], "google-auth-library/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=="], + "google-auth-library/google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], + "happy-dom/whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="], "hast-util-from-html/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], @@ -4636,13 +4657,11 @@ "mongodb-connection-string-url/whatwg-url": ["whatwg-url@14.2.0", "", { "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" } }, "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw=="], - "mysql2/iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], - "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], "nextjs-app-agentuity/@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], - "node-fetch/data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], + "node-fetch/whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], "normalize-package-data/hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="], @@ -4726,6 +4745,8 @@ "webrtc-test/@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], + "whatwg-encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + "wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], @@ -4886,9 +4907,7 @@ "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "gcp-metadata/gaxios/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], - - "gcp-metadata/gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + "google-auth-library/gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], "hast-util-from-html/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], @@ -4912,6 +4931,10 @@ "nextjs-app-agentuity/@vitejs/plugin-react/react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], + "node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + "normalize-package-data/hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "oauth/@vitejs/plugin-react/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], @@ -5124,7 +5147,7 @@ "docs/ai/@ai-sdk/gateway/@vercel/oidc": ["@vercel/oidc@3.1.0", "", {}, "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w=="], - "gcp-metadata/gaxios/node-fetch/whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + "google-auth-library/gaxios/node-fetch/data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], "prebuild-install/tar-fs/tar-stream/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], @@ -5142,10 +5165,6 @@ "create-agentuity/@agentuity/cli/@agentuity/auth/@agentuity/drizzle/drizzle-orm": ["drizzle-orm@0.45.2", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-kY0BSaTNYWnoDMVoyY8uxmyHjpJW1geOmBMdSSicKo9CIIWkSxMIj2rkeSR51b8KAPB7m+qysjuHme5nKP+E5Q=="], - "gcp-metadata/gaxios/node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], - - "gcp-metadata/gaxios/node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], - "archiver-utils/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "archiver-utils/glob/jackspeak/@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], diff --git a/package.json b/package.json index e94c7a6cf..11c22e627 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ ], "scripts": { "prepare": "husky", - "build": "bunx tsc --build && bun run --filter='./packages/core' build && bun run --filter='./packages/schema' build && bun run --filter='./packages/frontend' build && bun run --filter='./packages/server' build && bun run --filter='./packages/react' build && bun run --filter='./packages/postgres' build && bun run --filter='./packages/drizzle' build && bun run --filter='./packages/auth' build && bun run --filter='./packages/aigateway' build && bun run --filter='./packages/evals' build && bun run --filter='./packages/workbench' build && bun run --filter='./packages/runtime' build && bun packages/frontend/scripts/build-beacon.ts && bun run --filter='./packages/cli' build && bun run --filter='./packages/opencode' build && bun run --filter='./apps/testing/integration-suite' build && bun run --filter='./apps/testing/cloud-deployment' build && bun run --filter='./apps/testing/e2e-web' build && bun run --filter='./apps/testing/svelte-web' build", - "build:packages": "bunx tsc --build && bun run --filter='./packages/core' build && bun run --filter='./packages/schema' build && bun run --filter='./packages/frontend' build && bun run --filter='./packages/server' build && bun run --filter='./packages/react' build && bun run --filter='./packages/postgres' build && bun run --filter='./packages/drizzle' build && bun run --filter='./packages/auth' build && bun run --filter='./packages/aigateway' build && bun run --filter='./packages/evals' build && bun run --filter='./packages/workbench' build && bun run --filter='./packages/runtime' build && bun packages/frontend/scripts/build-beacon.ts && bun run --filter='./packages/cli' build && bun run --filter='./packages/opencode' build", + "build": "bunx tsc --build && bun run --filter='./packages/core' build && bun run --filter='./packages/schema' build && bun run --filter='./packages/frontend' build && bun run --filter='./packages/server' build && bun run --filter='./packages/pi-aigateway' build && bun run --filter='./packages/react' build && bun run --filter='./packages/postgres' build && bun run --filter='./packages/drizzle' build && bun run --filter='./packages/auth' build && bun run --filter='./packages/aigateway' build && bun run --filter='./packages/evals' build && bun run --filter='./packages/workbench' build && bun run --filter='./packages/runtime' build && bun packages/frontend/scripts/build-beacon.ts && bun run --filter='./packages/cli' build && bun run --filter='./packages/opencode' build && bun run --filter='./apps/testing/integration-suite' build && bun run --filter='./apps/testing/cloud-deployment' build && bun run --filter='./apps/testing/e2e-web' build && bun run --filter='./apps/testing/svelte-web' build", + "build:packages": "bunx tsc --build && bun run --filter='./packages/core' build && bun run --filter='./packages/schema' build && bun run --filter='./packages/frontend' build && bun run --filter='./packages/server' build && bun run --filter='./packages/pi-aigateway' build && bun run --filter='./packages/react' build && bun run --filter='./packages/postgres' build && bun run --filter='./packages/drizzle' build && bun run --filter='./packages/auth' build && bun run --filter='./packages/aigateway' build && bun run --filter='./packages/evals' build && bun run --filter='./packages/workbench' build && bun run --filter='./packages/runtime' build && bun packages/frontend/scripts/build-beacon.ts && bun run --filter='./packages/cli' build && bun run --filter='./packages/opencode' build", "dev:workbench": "concurrently \"cd packages/workbench && bun run dev:app\" \"cd apps/testing/integration-suite && bun run dev\" --names \"workbench,integration-suite\" --prefix-colors \"blue,green\"", "test": "bun test:packages && cd packages/cli && bun run test && cd ../.. && bun test:templates && bun test:pkginstall && bun test:create", "test:packages": "cd packages/core && bun test && cd ../schema && bun test && cd ../frontend && bun test && cd ../server && bun test && cd ../react && bun test && cd ../postgres && bun test && cd ../drizzle && bun test && cd ../auth && bun test && cd ../runtime && bun test --max-concurrency=1 && cd ../opencode && bun test", diff --git a/packages/coder-tui/package.json b/packages/coder-tui/package.json index 742a62f79..a6f4e098f 100644 --- a/packages/coder-tui/package.json +++ b/packages/coder-tui/package.json @@ -25,8 +25,7 @@ "prepublishOnly": "bun run clean && bun run build" }, "dependencies": { - "@agentuity/core": "workspace:*", - "@agentuity/server": "workspace:*", + "@agentuity/pi-aigateway": "workspace:*", "@mariozechner/pi-coding-agent": "^0.72.1", "@mariozechner/pi-tui": "^0.72.1", "@sinclair/typebox": "^0.34.49" diff --git a/packages/coder-tui/src/index.ts b/packages/coder-tui/src/index.ts index 384116df9..203d4140e 100644 --- a/packages/coder-tui/src/index.ts +++ b/packages/coder-tui/src/index.ts @@ -25,7 +25,7 @@ import { handleRemoteUiRequest } from './remote-ui-handler.ts'; import { buildInboundRpcPromptText, getInboundRpcDeliverAs } from './inbound-rpc.ts'; import { applyCoderAuthHeaders, getCoderAuthCurlArgs } from './auth.ts'; import { formatToolDisplay } from './agentuity-cli.ts'; -import { setupAIGateway } from './aigateway.ts'; +import { setupAIGateway } from '@agentuity/pi-aigateway'; import { adaptInitMessageForLocalTui } from './local-init-filter.ts'; import { selectSubAgentToolNames } from './subagent-tool-selection.ts'; import type { diff --git a/packages/coder-tui/tsconfig.json b/packages/coder-tui/tsconfig.json index 5156d1abb..a6defc5e0 100644 --- a/packages/coder-tui/tsconfig.json +++ b/packages/coder-tui/tsconfig.json @@ -6,12 +6,10 @@ "rootDir": "./src", "rewriteRelativeImportExtensions": true, "paths": { - "@agentuity/core": ["../core/src"], - "@agentuity/core/*": ["../core/src/services/*"], - "@agentuity/server": ["../server/src"] + "@agentuity/pi-aigateway": ["../pi-aigateway/src"] } }, "include": ["src/**/*"], "exclude": ["test/**/*"], - "references": [{ "path": "../core" }, { "path": "../server" }] + "references": [{ "path": "../pi-aigateway" }] } diff --git a/packages/pi-aigateway/README.md b/packages/pi-aigateway/README.md new file mode 100644 index 000000000..419a39e39 --- /dev/null +++ b/packages/pi-aigateway/README.md @@ -0,0 +1,3 @@ +# @agentuity/pi-aigateway + +Agentuity AI Gateway provider plugin for the Pi coding agent. diff --git a/packages/pi-aigateway/package.json b/packages/pi-aigateway/package.json new file mode 100644 index 000000000..89dd37016 --- /dev/null +++ b/packages/pi-aigateway/package.json @@ -0,0 +1,41 @@ +{ + "name": "@agentuity/pi-aigateway", + "version": "2.0.15", + "description": "Agentuity AI Gateway provider plugin for Pi coding agent", + "license": "Apache-2.0", + "author": "Agentuity employees and contributors", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "README.md", + "src", + "dist" + ], + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "scripts": { + "clean": "rm -rf dist tsconfig.tsbuildinfo", + "build": "bunx tsc --build", + "typecheck": "bunx tsc --noEmit", + "prepublishOnly": "bun run clean && bun run build" + }, + "dependencies": { + "@agentuity/core": "workspace:*", + "@agentuity/server": "workspace:*", + "@mariozechner/pi-coding-agent": "^0.72.1" + }, + "devDependencies": { + "@types/bun": "^1.3.9", + "bun-types": "^1.3.9", + "typescript": "^5.9.0" + }, + "publishConfig": { + "access": "public" + }, + "sideEffects": false +} diff --git a/packages/coder-tui/src/aigateway.ts b/packages/pi-aigateway/src/index.ts similarity index 99% rename from packages/coder-tui/src/aigateway.ts rename to packages/pi-aigateway/src/index.ts index 22a8f5fff..48bad0b69 100644 --- a/packages/coder-tui/src/aigateway.ts +++ b/packages/pi-aigateway/src/index.ts @@ -7,9 +7,9 @@ * Usage: * Use /model to switch to aigateway models */ -import { delimiter, join } from 'node:path'; -import { existsSync } from 'node:fs'; import { execFileSync } from 'node:child_process'; +import { existsSync } from 'node:fs'; +import { delimiter, join } from 'node:path'; import { createMinimalLogger, StructuredError } from '@agentuity/core'; import { AIGatewayService, @@ -199,7 +199,7 @@ export async function setupAIGateway(pi: ExtensionAPI) { for (const m of allModels) { const apiType = m.api; if (!isKnownApi(apiType)) { - continue; // THIS SHOULD NEVER HAPPEN BUT JUST IN CASE + continue; } const existing = modelsByApi.get(apiType) ?? []; existing.push(toPiModel(m)); diff --git a/packages/pi-aigateway/tsconfig.json b/packages/pi-aigateway/tsconfig.json new file mode 100644 index 000000000..192f7101c --- /dev/null +++ b/packages/pi-aigateway/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./dist", + "rootDir": "./src", + "paths": { + "@agentuity/core": ["../core/src"], + "@agentuity/core/*": ["../core/src/services/*"], + "@agentuity/server": ["../server/src"] + } + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"], + "references": [{ "path": "../core" }, { "path": "../server" }] +} diff --git a/tsconfig.json b/tsconfig.json index abec9854f..dadf059cb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,6 +17,7 @@ { "path": "./packages/migrate" }, { "path": "./packages/opencode" }, { "path": "./packages/postgres" }, + { "path": "./packages/pi-aigateway" }, { "path": "./packages/queue" }, { "path": "./packages/react" }, { "path": "./packages/runtime" }, From 3bf6ce30e3355891ee7f3bf95579ea9d60b0f4e3 Mon Sep 17 00:00:00 2001 From: Jeff Haynie Date: Thu, 7 May 2026 06:49:22 -0500 Subject: [PATCH 2/4] Mark Pi coding agent as peer dependency --- bun.lock | 5 ++++- packages/pi-aigateway/package.json | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/bun.lock b/bun.lock index 9a6f93fad..6cdc2560c 100644 --- a/bun.lock +++ b/bun.lock @@ -690,13 +690,16 @@ "dependencies": { "@agentuity/core": "workspace:*", "@agentuity/server": "workspace:*", - "@mariozechner/pi-coding-agent": "^0.72.1", }, "devDependencies": { + "@mariozechner/pi-coding-agent": "^0.72.1", "@types/bun": "^1.3.9", "bun-types": "^1.3.9", "typescript": "^5.9.0", }, + "peerDependencies": { + "@mariozechner/pi-coding-agent": "^0.72.1", + }, }, "packages/postgres": { "name": "@agentuity/postgres", diff --git a/packages/pi-aigateway/package.json b/packages/pi-aigateway/package.json index 89dd37016..76f3eb4f5 100644 --- a/packages/pi-aigateway/package.json +++ b/packages/pi-aigateway/package.json @@ -26,10 +26,13 @@ }, "dependencies": { "@agentuity/core": "workspace:*", - "@agentuity/server": "workspace:*", + "@agentuity/server": "workspace:*" + }, + "peerDependencies": { "@mariozechner/pi-coding-agent": "^0.72.1" }, "devDependencies": { + "@mariozechner/pi-coding-agent": "^0.72.1", "@types/bun": "^1.3.9", "bun-types": "^1.3.9", "typescript": "^5.9.0" From 52eed67670794a2b777eb5a632ca81db9b4cd558 Mon Sep 17 00:00:00 2001 From: Jeff Haynie Date: Thu, 7 May 2026 06:55:46 -0500 Subject: [PATCH 3/4] Rename Pi plugin package --- README.md | 2 +- bun.lock | 8 ++++---- package.json | 4 ++-- packages/coder-tui/package.json | 2 +- packages/coder-tui/src/index.ts | 2 +- packages/coder-tui/tsconfig.json | 4 ++-- packages/{pi-aigateway => pi}/README.md | 2 +- packages/{pi-aigateway => pi}/package.json | 2 +- packages/{pi-aigateway => pi}/src/index.ts | 0 packages/{pi-aigateway => pi}/tsconfig.json | 0 tsconfig.json | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) rename packages/{pi-aigateway => pi}/README.md (70%) rename packages/{pi-aigateway => pi}/package.json (96%) rename packages/{pi-aigateway => pi}/src/index.ts (100%) rename packages/{pi-aigateway => pi}/tsconfig.json (100%) diff --git a/README.md b/README.md index 06c4464a3..c063795d3 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ The structure of this mono repository: - `packages/frontend` - Reusable code for web frontends including WebRTC peer connections - `packages/keyvalue` - Key-value storage service client - `packages/opencode` - Opencode agent plugins for Agentuity -- `packages/pi-aigateway` - Pi coding agent provider plugin for Agentuity AI Gateway models +- `packages/pi` - Pi coding agent provider plugin for Agentuity AI Gateway models - `packages/postgres` - Resilient PostgreSQL client with automatic reconnection - `packages/queue` - Queue service client for publishing messages to queues - `packages/react` - React package for the Browser including WebRTC hooks diff --git a/bun.lock b/bun.lock index 6cdc2560c..9de0e0b6b 100644 --- a/bun.lock +++ b/bun.lock @@ -535,7 +535,7 @@ "name": "@agentuity/coder-tui", "version": "2.0.15", "dependencies": { - "@agentuity/pi-aigateway": "workspace:*", + "@agentuity/pi": "workspace:*", "@mariozechner/pi-coding-agent": "^0.72.1", "@mariozechner/pi-tui": "^0.72.1", "@sinclair/typebox": "^0.34.49", @@ -684,8 +684,8 @@ "typescript": "^5.9.0", }, }, - "packages/pi-aigateway": { - "name": "@agentuity/pi-aigateway", + "packages/pi": { + "name": "@agentuity/pi", "version": "2.0.15", "dependencies": { "@agentuity/core": "workspace:*", @@ -1030,7 +1030,7 @@ "@agentuity/opencode": ["@agentuity/opencode@workspace:packages/opencode"], - "@agentuity/pi-aigateway": ["@agentuity/pi-aigateway@workspace:packages/pi-aigateway"], + "@agentuity/pi": ["@agentuity/pi@workspace:packages/pi"], "@agentuity/postgres": ["@agentuity/postgres@workspace:packages/postgres"], diff --git a/package.json b/package.json index 11c22e627..458aadb95 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ ], "scripts": { "prepare": "husky", - "build": "bunx tsc --build && bun run --filter='./packages/core' build && bun run --filter='./packages/schema' build && bun run --filter='./packages/frontend' build && bun run --filter='./packages/server' build && bun run --filter='./packages/pi-aigateway' build && bun run --filter='./packages/react' build && bun run --filter='./packages/postgres' build && bun run --filter='./packages/drizzle' build && bun run --filter='./packages/auth' build && bun run --filter='./packages/aigateway' build && bun run --filter='./packages/evals' build && bun run --filter='./packages/workbench' build && bun run --filter='./packages/runtime' build && bun packages/frontend/scripts/build-beacon.ts && bun run --filter='./packages/cli' build && bun run --filter='./packages/opencode' build && bun run --filter='./apps/testing/integration-suite' build && bun run --filter='./apps/testing/cloud-deployment' build && bun run --filter='./apps/testing/e2e-web' build && bun run --filter='./apps/testing/svelte-web' build", - "build:packages": "bunx tsc --build && bun run --filter='./packages/core' build && bun run --filter='./packages/schema' build && bun run --filter='./packages/frontend' build && bun run --filter='./packages/server' build && bun run --filter='./packages/pi-aigateway' build && bun run --filter='./packages/react' build && bun run --filter='./packages/postgres' build && bun run --filter='./packages/drizzle' build && bun run --filter='./packages/auth' build && bun run --filter='./packages/aigateway' build && bun run --filter='./packages/evals' build && bun run --filter='./packages/workbench' build && bun run --filter='./packages/runtime' build && bun packages/frontend/scripts/build-beacon.ts && bun run --filter='./packages/cli' build && bun run --filter='./packages/opencode' build", + "build": "bunx tsc --build && bun run --filter='./packages/core' build && bun run --filter='./packages/schema' build && bun run --filter='./packages/frontend' build && bun run --filter='./packages/server' build && bun run --filter='./packages/pi' build && bun run --filter='./packages/react' build && bun run --filter='./packages/postgres' build && bun run --filter='./packages/drizzle' build && bun run --filter='./packages/auth' build && bun run --filter='./packages/aigateway' build && bun run --filter='./packages/evals' build && bun run --filter='./packages/workbench' build && bun run --filter='./packages/runtime' build && bun packages/frontend/scripts/build-beacon.ts && bun run --filter='./packages/cli' build && bun run --filter='./packages/opencode' build && bun run --filter='./apps/testing/integration-suite' build && bun run --filter='./apps/testing/cloud-deployment' build && bun run --filter='./apps/testing/e2e-web' build && bun run --filter='./apps/testing/svelte-web' build", + "build:packages": "bunx tsc --build && bun run --filter='./packages/core' build && bun run --filter='./packages/schema' build && bun run --filter='./packages/frontend' build && bun run --filter='./packages/server' build && bun run --filter='./packages/pi' build && bun run --filter='./packages/react' build && bun run --filter='./packages/postgres' build && bun run --filter='./packages/drizzle' build && bun run --filter='./packages/auth' build && bun run --filter='./packages/aigateway' build && bun run --filter='./packages/evals' build && bun run --filter='./packages/workbench' build && bun run --filter='./packages/runtime' build && bun packages/frontend/scripts/build-beacon.ts && bun run --filter='./packages/cli' build && bun run --filter='./packages/opencode' build", "dev:workbench": "concurrently \"cd packages/workbench && bun run dev:app\" \"cd apps/testing/integration-suite && bun run dev\" --names \"workbench,integration-suite\" --prefix-colors \"blue,green\"", "test": "bun test:packages && cd packages/cli && bun run test && cd ../.. && bun test:templates && bun test:pkginstall && bun test:create", "test:packages": "cd packages/core && bun test && cd ../schema && bun test && cd ../frontend && bun test && cd ../server && bun test && cd ../react && bun test && cd ../postgres && bun test && cd ../drizzle && bun test && cd ../auth && bun test && cd ../runtime && bun test --max-concurrency=1 && cd ../opencode && bun test", diff --git a/packages/coder-tui/package.json b/packages/coder-tui/package.json index a6f4e098f..e779f6322 100644 --- a/packages/coder-tui/package.json +++ b/packages/coder-tui/package.json @@ -25,7 +25,7 @@ "prepublishOnly": "bun run clean && bun run build" }, "dependencies": { - "@agentuity/pi-aigateway": "workspace:*", + "@agentuity/pi": "workspace:*", "@mariozechner/pi-coding-agent": "^0.72.1", "@mariozechner/pi-tui": "^0.72.1", "@sinclair/typebox": "^0.34.49" diff --git a/packages/coder-tui/src/index.ts b/packages/coder-tui/src/index.ts index 203d4140e..804301a78 100644 --- a/packages/coder-tui/src/index.ts +++ b/packages/coder-tui/src/index.ts @@ -25,7 +25,7 @@ import { handleRemoteUiRequest } from './remote-ui-handler.ts'; import { buildInboundRpcPromptText, getInboundRpcDeliverAs } from './inbound-rpc.ts'; import { applyCoderAuthHeaders, getCoderAuthCurlArgs } from './auth.ts'; import { formatToolDisplay } from './agentuity-cli.ts'; -import { setupAIGateway } from '@agentuity/pi-aigateway'; +import { setupAIGateway } from '@agentuity/pi'; import { adaptInitMessageForLocalTui } from './local-init-filter.ts'; import { selectSubAgentToolNames } from './subagent-tool-selection.ts'; import type { diff --git a/packages/coder-tui/tsconfig.json b/packages/coder-tui/tsconfig.json index a6defc5e0..2511e52c5 100644 --- a/packages/coder-tui/tsconfig.json +++ b/packages/coder-tui/tsconfig.json @@ -6,10 +6,10 @@ "rootDir": "./src", "rewriteRelativeImportExtensions": true, "paths": { - "@agentuity/pi-aigateway": ["../pi-aigateway/src"] + "@agentuity/pi": ["../pi/src"] } }, "include": ["src/**/*"], "exclude": ["test/**/*"], - "references": [{ "path": "../pi-aigateway" }] + "references": [{ "path": "../pi" }] } diff --git a/packages/pi-aigateway/README.md b/packages/pi/README.md similarity index 70% rename from packages/pi-aigateway/README.md rename to packages/pi/README.md index 419a39e39..c4b2da640 100644 --- a/packages/pi-aigateway/README.md +++ b/packages/pi/README.md @@ -1,3 +1,3 @@ -# @agentuity/pi-aigateway +# @agentuity/pi Agentuity AI Gateway provider plugin for the Pi coding agent. diff --git a/packages/pi-aigateway/package.json b/packages/pi/package.json similarity index 96% rename from packages/pi-aigateway/package.json rename to packages/pi/package.json index 76f3eb4f5..e6e3241b4 100644 --- a/packages/pi-aigateway/package.json +++ b/packages/pi/package.json @@ -1,5 +1,5 @@ { - "name": "@agentuity/pi-aigateway", + "name": "@agentuity/pi", "version": "2.0.15", "description": "Agentuity AI Gateway provider plugin for Pi coding agent", "license": "Apache-2.0", diff --git a/packages/pi-aigateway/src/index.ts b/packages/pi/src/index.ts similarity index 100% rename from packages/pi-aigateway/src/index.ts rename to packages/pi/src/index.ts diff --git a/packages/pi-aigateway/tsconfig.json b/packages/pi/tsconfig.json similarity index 100% rename from packages/pi-aigateway/tsconfig.json rename to packages/pi/tsconfig.json diff --git a/tsconfig.json b/tsconfig.json index dadf059cb..5e81d9de1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,7 @@ { "path": "./packages/migrate" }, { "path": "./packages/opencode" }, { "path": "./packages/postgres" }, - { "path": "./packages/pi-aigateway" }, + { "path": "./packages/pi" }, { "path": "./packages/queue" }, { "path": "./packages/react" }, { "path": "./packages/runtime" }, From 66e9fa279aa0de370c8f530e5c45d9001f189816 Mon Sep 17 00:00:00 2001 From: Jeff Haynie Date: Thu, 7 May 2026 07:26:01 -0500 Subject: [PATCH 4/4] Add Pi organization and region selectors --- packages/pi/src/index.ts | 290 +++++++++++++++++++++++++++++++++++---- 1 file changed, 264 insertions(+), 26 deletions(-) diff --git a/packages/pi/src/index.ts b/packages/pi/src/index.ts index 48bad0b69..dbf807a6b 100644 --- a/packages/pi/src/index.ts +++ b/packages/pi/src/index.ts @@ -17,7 +17,11 @@ import { type AIGatewayModels, } from '@agentuity/core/aigateway'; import { createServerFetchAdapter } from '@agentuity/server'; -import type { ExtensionAPI, ProviderModelConfig } from '@mariozechner/pi-coding-agent'; +import type { + ExtensionAPI, + ExtensionCommandContext, + ProviderModelConfig, +} from '@mariozechner/pi-coding-agent'; export type KnownApi = | 'openai-completions' @@ -48,6 +52,68 @@ const AIGatewayModelFetchError = StructuredError('AIGatewayModelFetchError')<{ cause?: unknown; }>(); +type AgentuityOrganization = { + id: string; + name: string; +}; + +type AgentuityWhoami = { + organizations?: AgentuityOrganization[]; +}; + +type AgentuityRegion = { + region: string; + description: string; + default?: boolean; +}; + +function parseFirstJsonObject(value: string): unknown { + const start = value.indexOf('{'); + if (start === -1) { + throw new SyntaxError('No JSON object found'); + } + + let depth = 0; + let inString = false; + let escaped = false; + for (let i = start; i < value.length; i++) { + const char = value[i]; + if (escaped) { + escaped = false; + continue; + } + if (char === '\\') { + escaped = true; + continue; + } + if (char === '"') { + inString = !inString; + continue; + } + if (inString) { + continue; + } + if (char === '{') { + depth++; + } else if (char === '}') { + depth--; + if (depth === 0) { + return JSON.parse(value.slice(start, i + 1)); + } + } + } + + throw new SyntaxError('Unterminated JSON object'); +} + +function parseJson(value: string): unknown { + const trimmed = value.trim(); + if (trimmed.startsWith('[')) { + return JSON.parse(trimmed); + } + return parseFirstJsonObject(trimmed); +} + function getEnv(...keys: string[]): string | undefined { for (const key of keys) { if (process.env[key]) { @@ -77,6 +143,61 @@ function getBaseUrl(): string { return `https://aigateway-${region}.agentuity.cloud`; } +function getAgentuityCliPath(): string | undefined { + const path = process.env.PATH?.split(delimiter) ?? []; + for (const dir of path) { + const fn = join(dir, 'agentuity'); + if (existsSync(fn)) { + return fn; + } + } +} + +function fetchOrganizations(): AgentuityOrganization[] { + const agentuity = getAgentuityCliPath(); + if (!agentuity) { + return []; + } + + const res = execFileSync(agentuity, ['auth', 'whoami', '--json']); + const whoami = parseJson(res.toString()) as AgentuityWhoami; + return (whoami.organizations ?? []).filter( + (org): org is AgentuityOrganization => + typeof org?.id === 'string' && + org.id.length > 0 && + typeof org?.name === 'string' && + org.name.length > 0 + ); +} + +function fetchRegions(): AgentuityRegion[] { + const agentuity = getAgentuityCliPath(); + if (!agentuity) { + return []; + } + + const res = execFileSync(agentuity, ['cloud', 'region', 'list', '--json']); + const regions = parseJson(res.toString()) as AgentuityRegion[]; + return (Array.isArray(regions) ? regions : []).filter( + (region): region is AgentuityRegion => + typeof region?.region === 'string' && + region.region.length > 0 && + typeof region?.description === 'string' && + region.description.length > 0 + ); +} + +function getCurrentOrgId(): string | undefined { + return normalizeCredential( + getEnv( + 'AGENTUITY_AIGATEWAY_ORGID', + 'AGENTUITY_ORGID', + 'AGENTUITY_CLOUD_ORG_ID', + 'AGENTUITY_ORG_ID' + ) + ); +} + async function fetchModels(): Promise { const baseUrl = getBaseUrl(); let apiKey = normalizeCredential( @@ -93,37 +214,30 @@ async function fetchModels(): Promise { if (!apiKey) { let found = false; - const path = process.env.PATH?.split(delimiter) ?? []; - for (const dir of path) { - const fn = join(dir, 'agentuity'); - if (existsSync(fn)) { - try { - const res = execFileSync(fn, ['auth', 'apikey', '--json']); - const apiKeyResult = JSON.parse(res.toString()) as { apiKey: string }; - apiKey = normalizeCredential(apiKeyResult.apiKey); - found = true; + const fn = getAgentuityCliPath(); + if (fn) { + try { + const res = execFileSync(fn, ['auth', 'apikey', '--json']); + const apiKeyResult = parseJson(res.toString()) as { apiKey: string }; + apiKey = normalizeCredential(apiKeyResult.apiKey); + found = true; + if (!orgId) { + const ores = execFileSync(fn, ['auth', 'org', 'current']); + orgId = normalizeCredential(ores); if (!orgId) { - const ores = execFileSync(fn, ['auth', 'org', 'current']); - orgId = normalizeCredential(ores); - if (!orgId) { - console.warn( - 'Cannot determine the org id. Use `agentuity auth org select` to select a default organization' - ); - return {}; - } + return {}; } - break; - } catch (error) { - throw new AIGatewayModelFetchError({ - message: 'Failed to fetch models from AI Gateway', - cause: error, - }); } + } catch (error) { + throw new AIGatewayModelFetchError({ + message: 'Failed to fetch models from AI Gateway', + cause: error, + }); } } if (!found) { console.warn( - 'AGENTUITY_SDK_KEY, AGENTUITY_CLI_API_KEY or AGENTUITY_CLI_KEY not set and cannot find the agentuit cli, cannot fetch models from AI Gateway' + 'AGENTUITY_SDK_KEY, AGENTUITY_CLI_API_KEY or AGENTUITY_CLI_KEY not set and cannot find the agentuity cli, cannot fetch models from AI Gateway' ); return {}; } @@ -180,7 +294,7 @@ function toPiModel(m: AIGatewayModel): ProviderModelConfig { }; } -export async function setupAIGateway(pi: ExtensionAPI) { +async function registerAIGatewayProviders(pi: ExtensionAPI) { const models = await fetchModels(); const baseUrl = getBaseUrl(); @@ -225,3 +339,127 @@ export async function setupAIGateway(pi: ExtensionAPI) { }); } } + +function registerRegionCommand(pi: ExtensionAPI): void { + pi.registerCommand('region', { + description: 'Select active Agentuity region', + handler: async (_args: string, ctx: ExtensionCommandContext) => { + if (!ctx.hasUI) { + return; + } + + let regions: AgentuityRegion[]; + try { + regions = fetchRegions(); + } catch (error) { + ctx.ui.notify(`Failed to load Agentuity regions: ${String(error)}`, 'error'); + return; + } + + if (regions.length === 0) { + ctx.ui.notify('No Agentuity regions found.', 'warning'); + return; + } + + const currentRegion = getRegion(); + const labels = regions.map((region) => { + const marker = region.region === currentRegion ? '* ' : ''; + const defaultLabel = region.default ? ' default' : ''; + return `${marker}${region.description} (${region.region})${defaultLabel}`; + }); + const selected = await ctx.ui.select('Select Agentuity Region', labels); + if (!selected) { + return; + } + + const selectedIndex = labels.indexOf(selected); + const region = regions[selectedIndex]; + if (!region) { + return; + } + + process.env.AGENTUITY_REGION = region.region; + ctx.ui.notify(`Using Agentuity region: ${region.description}`, 'info'); + + try { + await registerAIGatewayProviders(pi); + ctx.ui.notify('Agentuity AI Gateway models refreshed.', 'info'); + } catch (error) { + ctx.ui.notify(`Failed to refresh AI Gateway models: ${String(error)}`, 'error'); + } + }, + }); +} + +function registerOrganizationCommand(pi: ExtensionAPI): void { + pi.registerCommand('organization', { + description: 'Select active Agentuity organization', + handler: async (_args: string, ctx: ExtensionCommandContext) => { + if (!ctx.hasUI) { + return; + } + + let organizations: AgentuityOrganization[]; + try { + organizations = fetchOrganizations(); + } catch (error) { + ctx.ui.notify(`Failed to load Agentuity organizations: ${String(error)}`, 'error'); + return; + } + + if (organizations.length === 0) { + ctx.ui.notify('No Agentuity organizations found for the current CLI login.', 'warning'); + return; + } + + const currentOrgId = getCurrentOrgId(); + const labels = organizations.map((org) => { + const marker = org.id === currentOrgId ? '* ' : ''; + return `${marker}${org.name} (${org.id})`; + }); + const selected = await ctx.ui.select('Select Agentuity Organization', labels); + if (!selected) { + return; + } + + const selectedIndex = labels.indexOf(selected); + const organization = organizations[selectedIndex]; + if (!organization) { + return; + } + + process.env.AGENTUITY_AIGATEWAY_ORGID = organization.id; + process.env.AGENTUITY_ORGID = organization.id; + process.env.AGENTUITY_CLOUD_ORG_ID = organization.id; + process.env.AGENTUITY_ORG_ID = organization.id; + + ctx.ui.notify(`Using Agentuity organization: ${organization.name}`, 'info'); + + try { + await registerAIGatewayProviders(pi); + ctx.ui.notify('Agentuity AI Gateway models refreshed.', 'info'); + } catch (error) { + ctx.ui.notify(`Failed to refresh AI Gateway models: ${String(error)}`, 'error'); + } + }, + }); +} + +export async function setupAIGateway(pi: ExtensionAPI) { + registerOrganizationCommand(pi); + registerRegionCommand(pi); + let showedOrganizationPrompt = false; + pi.on('session_start', (_event, ctx) => { + if (showedOrganizationPrompt || !ctx.hasUI || getCurrentOrgId()) { + return; + } + showedOrganizationPrompt = true; + ctx.ui.notify( + 'Use /organization to select an Agentuity organization for AI Gateway models.', + 'info' + ); + }); + await registerAIGatewayProviders(pi); +} + +export default setupAIGateway;