pi-meta-oauth 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +69 -0
- package/bun.lock +296 -0
- package/extensions/meta.ts +373 -0
- package/package.json +34 -0
- package/preview.png +0 -0
- package/tests/meta.test.ts +102 -0
- package/tsconfig.json +12 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BlockedPath
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# pi-meta-oauth
|
|
2
|
+
|
|
3
|
+
Meta Model API OAuth provider for [pi](https://pi.dev) — use **Muse Spark** (`muse-spark-1.2`, `muse-spark-1.2-contributor`, `muse-spark-1.1`) via `openai-responses` inside pi.
|
|
4
|
+
|
|
5
|
+
- Device authorization (same client as Muse Code) against `https://auth.meta.com`
|
|
6
|
+
- Mints a Model API key via `POST https://api.meta.ai/muse-code/key`
|
|
7
|
+
- Stores OAuth `refresh = identity token` + `access = Model API key` in `~/.pi/agent/auth.json` under provider `meta`
|
|
8
|
+
- Refresh re-mints the Model API key daily
|
|
9
|
+
- Model catalog from `GET https://api.meta.ai/v1/models` with thinking levels `minimal/low/medium/high/xhigh`
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# local path (no publish needed)
|
|
15
|
+
pi install ./pi-meta-provider
|
|
16
|
+
# or npm (after publish)
|
|
17
|
+
pi install npm:pi-meta-oauth
|
|
18
|
+
|
|
19
|
+
pi --list-models meta
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Login
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pi
|
|
26
|
+
/login meta
|
|
27
|
+
# shows device code -> approve in browser -> mints Model API key automatically
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Stored credential shape:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{ "meta": { "type": "oauth", "refresh": "<identity>", "access": "<MODEL_API_KEY>", "expires": 123 } }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Models
|
|
37
|
+
|
|
38
|
+
All three share 1,048,576 context, 256K output, `supportsReasoningEffort: true`, and `input: ["text","image"]`:
|
|
39
|
+
|
|
40
|
+
| id | pricing (input/output/cached) $/M |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `muse-spark-1.2` | 1.25 / 4.25 / 0.15 |
|
|
43
|
+
| `muse-spark-1.2-contributor` | 0.10 / 0.20 / 0.002 |
|
|
44
|
+
| `muse-spark-1.1` | 1.25 / 4.25 / 0.15 |
|
|
45
|
+
|
|
46
|
+
Add to `enabledModels` in `~/.pi/agent/settings.json`:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{ "enabledModels": ["meta/*"] }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Verify
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pi --list-models meta
|
|
56
|
+
pi -p --provider meta --model muse-spark-1.2 "Reply exactly: META_OK"
|
|
57
|
+
bun test extensions/meta.test.ts
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Publish to pi.dev
|
|
61
|
+
|
|
62
|
+
`pi-package` keyword makes it appear at https://pi.dev/packages
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm publish --access public
|
|
66
|
+
# users then run: pi install npm:pi-meta-oauth
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
See `extensions/meta.ts` for the `registerProvider` / `refreshModels` / `oauth` implementation reused from Muse Code's launcher flow.
|
package/bun.lock
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"configVersion": 1,
|
|
4
|
+
"workspaces": {
|
|
5
|
+
"": {
|
|
6
|
+
"name": "pi-meta-oauth",
|
|
7
|
+
"devDependencies": {
|
|
8
|
+
"@earendil-works/pi-ai": "0.83.0",
|
|
9
|
+
"@earendil-works/pi-coding-agent": "0.83.0",
|
|
10
|
+
"bun-types": "latest",
|
|
11
|
+
"typescript": "^5.9.0",
|
|
12
|
+
},
|
|
13
|
+
"peerDependencies": {
|
|
14
|
+
"@earendil-works/pi-ai": ">=0.83.0 <0.84.0",
|
|
15
|
+
"@earendil-works/pi-coding-agent": ">=0.83.0 <0.84.0",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
"packages": {
|
|
20
|
+
"@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.91.1", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw=="],
|
|
21
|
+
|
|
22
|
+
"@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="],
|
|
23
|
+
|
|
24
|
+
"@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="],
|
|
25
|
+
|
|
26
|
+
"@aws-crypto/supports-web-crypto": ["@aws-crypto/supports-web-crypto@5.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg=="],
|
|
27
|
+
|
|
28
|
+
"@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="],
|
|
29
|
+
|
|
30
|
+
"@aws-sdk/client-bedrock-runtime": ["@aws-sdk/client-bedrock-runtime@3.1048.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.11", "@aws-sdk/credential-provider-node": "^3.972.42", "@aws-sdk/eventstream-handler-node": "^3.972.16", "@aws-sdk/middleware-eventstream": "^3.972.12", "@aws-sdk/middleware-websocket": "^3.972.19", "@aws-sdk/token-providers": "3.1048.0", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/fetch-http-handler": "^5.4.2", "@smithy/node-http-handler": "^4.7.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ=="],
|
|
31
|
+
|
|
32
|
+
"@aws-sdk/core": ["@aws-sdk/core@3.977.6", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@aws-sdk/xml-builder": "^3.972.37", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.31.1", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.16.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-QiaJV4/zDrB4ZY2mfeSXSzSTc36W16sZXcGz+SPFk0CJ26gziO0cS+4LjJUMAbdeeBOvS0k0Aq1cZpfGdUXxSw=="],
|
|
33
|
+
|
|
34
|
+
"@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.67", "", { "dependencies": { "@aws-sdk/core": "^3.977.6", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-rcIpk5kxUqDaaNa6Xk23pQ6ViY7jlqzmfFWCahQcBT97ddXaXYYwzCen9Tz1Jvo6aJft6wDl5bN44/Jw5B4oLA=="],
|
|
35
|
+
|
|
36
|
+
"@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.69", "", { "dependencies": { "@aws-sdk/core": "^3.977.6", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/fetch-http-handler": "^5.6.13", "@smithy/node-http-handler": "^4.9.13", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-nggwJtZ4eeNsUw5IeWBMXsi1ryct5idi0K+/SCRF3kybLubOMaNTb3XCihXpWMiVpyzyPeIrl0zTkzhBH9porA=="],
|
|
37
|
+
|
|
38
|
+
"@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.973.12", "", { "dependencies": { "@aws-sdk/core": "^3.977.6", "@aws-sdk/credential-provider-env": "^3.972.67", "@aws-sdk/credential-provider-http": "^3.972.69", "@aws-sdk/credential-provider-login": "^3.972.74", "@aws-sdk/credential-provider-process": "^3.972.67", "@aws-sdk/credential-provider-sso": "^3.973.11", "@aws-sdk/credential-provider-web-identity": "^3.972.73", "@aws-sdk/nested-clients": "^3.997.41", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/credential-provider-imds": "^4.4.16", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-pNEf/OeyN5X3VmLKlgSO6TqaWmW10CvI3TfwL1XhsuhYjSLT2VDaxFnCPHnOeQXSaFisMX4jNhpETriqN8DOmg=="],
|
|
39
|
+
|
|
40
|
+
"@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.74", "", { "dependencies": { "@aws-sdk/core": "^3.977.6", "@aws-sdk/nested-clients": "^3.997.41", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-0AQfDcf99TNmqVKv0owHrw/TQs6i4ZE5t9qmz6NvO53bE/sA/tpXhXL9AAcEP1qHc6Zzjd1UMb69+/9zdhvY3g=="],
|
|
41
|
+
|
|
42
|
+
"@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.78", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.67", "@aws-sdk/credential-provider-http": "^3.972.69", "@aws-sdk/credential-provider-ini": "^3.973.12", "@aws-sdk/credential-provider-process": "^3.972.67", "@aws-sdk/credential-provider-sso": "^3.973.11", "@aws-sdk/credential-provider-web-identity": "^3.972.73", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/credential-provider-imds": "^4.4.16", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-OgPAnfvbGAMWac6yvxJ1ihslrvDpPVwR68D2csospdNCCyPvHk9JLzYKwz48SNiS1T2znDwHauywRKRFfpyYng=="],
|
|
43
|
+
|
|
44
|
+
"@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.67", "", { "dependencies": { "@aws-sdk/core": "^3.977.6", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-IlUEejorGTWKb4/Dm7K5Yw4QxUmXLThLhrvBmzVBqZFTbW72cv9LTcITmo1dsnYriALE4h68mOq4LB99x6sQ7Q=="],
|
|
45
|
+
|
|
46
|
+
"@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.973.11", "", { "dependencies": { "@aws-sdk/core": "^3.977.6", "@aws-sdk/nested-clients": "^3.997.41", "@aws-sdk/token-providers": "3.1103.0", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-gAQBkBZxUB84d71+pPcI9L+jh2ujhuAVxc/4FgGiWFDjkPBlMKxzd5XDtkSXTFX8Ro7ansnT88+XadasxMeCRw=="],
|
|
47
|
+
|
|
48
|
+
"@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.73", "", { "dependencies": { "@aws-sdk/core": "^3.977.6", "@aws-sdk/nested-clients": "^3.997.41", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-SnlEmQa6SjOgs6iOPLUQl1Eyq4AKiAdPQlkOhFhqNfDtDCwibMGvL6QlkSmf3o6vAUSImzdPCxowT5dfQUZP1A=="],
|
|
49
|
+
|
|
50
|
+
"@aws-sdk/eventstream-handler-node": ["@aws-sdk/eventstream-handler-node@3.972.31", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-/BRzvkp46mF6eXBL/l9WKPQQfifLlUPaWli6n9/T/WDLUg8he7TCyuNFnk6RvHP5j5W/kMj5Gxw7W778LJaXDA=="],
|
|
51
|
+
|
|
52
|
+
"@aws-sdk/middleware-eventstream": ["@aws-sdk/middleware-eventstream@3.972.26", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-2eIvouTZoxPu5ClHY6ij13De1yhY8Rmllt0dlGeBNXX3wmR7fU1pvMCGb50fKm1GxcuntWK0t1T0cMjTyDoUQA=="],
|
|
53
|
+
|
|
54
|
+
"@aws-sdk/middleware-websocket": ["@aws-sdk/middleware-websocket@3.972.49", "", { "dependencies": { "@aws-sdk/core": "^3.977.6", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/fetch-http-handler": "^5.6.13", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-wGYJvu1/stdWuzGcNyh44u8aY7ArU8XFrMesBlzIYn70HWVCRBNEngQexDuPIMu0NEgsKGKmTc0uvnS/bF7KWw=="],
|
|
55
|
+
|
|
56
|
+
"@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.41", "", { "dependencies": { "@aws-sdk/core": "^3.977.6", "@aws-sdk/signature-v4-multi-region": "^3.996.43", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/fetch-http-handler": "^5.6.13", "@smithy/node-http-handler": "^4.9.13", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-RDHqPGQWlF6tatA/Tp3rg6oIwtgN9IVderxE+9av2Y93Dfyu+mO1hZ5Bu2jpfZg2rwdNbsssnwM+sLafIczMlQ=="],
|
|
57
|
+
|
|
58
|
+
"@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.43", "", { "dependencies": { "@aws-sdk/types": "^3.974.2", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-lKekx8bLBXSv4O+cslk9Zfnw2XKSkWBs3uWL5QGhH2ZAQfNS7FE0vcSSN2vD/AhxX54ZTywWxR4STThoeOXlBA=="],
|
|
59
|
+
|
|
60
|
+
"@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1048.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.11", "@aws-sdk/nested-clients": "^3.997.9", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA=="],
|
|
61
|
+
|
|
62
|
+
"@aws-sdk/types": ["@aws-sdk/types@3.974.2", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA=="],
|
|
63
|
+
|
|
64
|
+
"@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.8", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g=="],
|
|
65
|
+
|
|
66
|
+
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.37", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-zKq4HQum8JwDyEuyfuI4bbiAcU0KxP6qy+9PR/IsR92IyE/DaBAikzAS50tjxip4bqIIANpCcG+Yyj6CVhXupg=="],
|
|
67
|
+
|
|
68
|
+
"@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="],
|
|
69
|
+
|
|
70
|
+
"@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="],
|
|
71
|
+
|
|
72
|
+
"@earendil-works/pi-agent-core": ["@earendil-works/pi-agent-core@0.83.0", "", { "dependencies": { "@earendil-works/pi-ai": "^0.83.0", "diff": "8.0.4", "ignore": "7.0.5", "typebox": "1.3.7", "yaml": "2.9.0" } }, "sha512-RorGp9OH5l3ElpuC5a5ZQ2eWcchZGXflXRzVGkV99y3y6tT+LLNyxoYIdVKvTKWEObwhExeQbTH0fI2tE4iX4g=="],
|
|
73
|
+
|
|
74
|
+
"@earendil-works/pi-ai": ["@earendil-works/pi-ai@0.83.0", "", { "dependencies": { "@anthropic-ai/sdk": "0.91.1", "@aws-sdk/client-bedrock-runtime": "3.1048.0", "@google/genai": "1.52.0", "@mistralai/mistralai": "2.2.6", "@opentelemetry/api": "1.9.0", "@smithy/node-http-handler": "4.7.3", "http-proxy-agent": "7.0.2", "https-proxy-agent": "7.0.6", "openai": "6.26.0", "partial-json": "0.1.7", "typebox": "1.3.7" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-m3IZD4g3er0V8TC9+Vpgw/sjTKqcJlkcIBy/JvsgRubuuik3tAVzyugUg4rVrShIkkOT69mEd34NEqKUIsl6JQ=="],
|
|
75
|
+
|
|
76
|
+
"@earendil-works/pi-coding-agent": ["@earendil-works/pi-coding-agent@0.83.0", "", { "dependencies": { "@earendil-works/pi-agent-core": "^0.83.0", "@earendil-works/pi-ai": "^0.83.0", "@earendil-works/pi-tui": "^0.83.0", "@silvia-odwyer/photon-node": "0.3.4", "chalk": "5.6.2", "cross-spawn": "7.0.6", "diff": "8.0.4", "glob": "13.0.6", "highlight.js": "10.7.3", "hosted-git-info": "9.0.3", "ignore": "7.0.5", "jiti": "2.7.0", "minimatch": "10.2.5", "proper-lockfile": "4.1.2", "semver": "7.8.0", "typebox": "1.3.7", "undici": "8.5.0", "yaml": "2.9.0" }, "optionalDependencies": { "@mariozechner/clipboard": "0.3.9" }, "bin": { "pi": "dist/cli.js" } }, "sha512-uYhF+FsZxogoSX/AxBcUdiY+ZklubwaXyAoEGA2eQwsHcyEAhUYIKh/WLXe/a8+k8eTCmxb+ZN2Zo9mzQtzbWw=="],
|
|
77
|
+
|
|
78
|
+
"@earendil-works/pi-tui": ["@earendil-works/pi-tui@0.83.0", "", { "dependencies": { "get-east-asian-width": "1.6.0", "marked": "18.0.5" } }, "sha512-IoYrb0rORjELmEpNtoCA/U8je3KopMkRAVJRdSzvXRvgb+Huo1gNh8Q5CSZvNOiYtDxJdj2tYZZHZ4B3+IN3hA=="],
|
|
79
|
+
|
|
80
|
+
"@google/genai": ["@google/genai@1.52.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q=="],
|
|
81
|
+
|
|
82
|
+
"@mariozechner/clipboard": ["@mariozechner/clipboard@0.3.9", "", { "optionalDependencies": { "@mariozechner/clipboard-darwin-arm64": "0.3.9", "@mariozechner/clipboard-darwin-universal": "0.3.9", "@mariozechner/clipboard-darwin-x64": "0.3.9", "@mariozechner/clipboard-linux-arm64-gnu": "0.3.9", "@mariozechner/clipboard-linux-arm64-musl": "0.3.9", "@mariozechner/clipboard-linux-riscv64-gnu": "0.3.9", "@mariozechner/clipboard-linux-x64-gnu": "0.3.9", "@mariozechner/clipboard-linux-x64-musl": "0.3.9", "@mariozechner/clipboard-win32-arm64-msvc": "0.3.9", "@mariozechner/clipboard-win32-x64-msvc": "0.3.9" } }, "sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA=="],
|
|
83
|
+
|
|
84
|
+
"@mariozechner/clipboard-darwin-arm64": ["@mariozechner/clipboard-darwin-arm64@0.3.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BfgV7vCEWZwJwZJw03r6bP5+tf0iI/ANuQYCxi9RNn7FrWB3yzGuMKCrNLRl6V761vXRdL8+OqZ0wd4TqlsNOQ=="],
|
|
85
|
+
|
|
86
|
+
"@mariozechner/clipboard-darwin-universal": ["@mariozechner/clipboard-darwin-universal@0.3.9", "", { "os": "darwin" }, "sha512-BGGR4iA9Z2shAjI65eI5xtyb3LYNlDW9X3gxKxDbqtbnREohsrqznov6zpKoIrsRWpzlYVEdKphS7ksJ0/ndSQ=="],
|
|
87
|
+
|
|
88
|
+
"@mariozechner/clipboard-darwin-x64": ["@mariozechner/clipboard-darwin-x64@0.3.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-4kURmCbS6nt8uYhtmWpUcJWyPHfmAr5dTpXD1nO3pIfa+TSQ9DbrGOYCKH+aEFW47XhQ4Vp8ZTszie+wfFvDKg=="],
|
|
89
|
+
|
|
90
|
+
"@mariozechner/clipboard-linux-arm64-gnu": ["@mariozechner/clipboard-linux-arm64-gnu@0.3.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-g59OkUGP2DDfCOIKypHeYgv2M55u/cKvXa5dSxFbEJ34XvIQMdcVmpKCkGUro3ZgefXiGVdwguvTMQGpHWzIXw=="],
|
|
91
|
+
|
|
92
|
+
"@mariozechner/clipboard-linux-arm64-musl": ["@mariozechner/clipboard-linux-arm64-musl@0.3.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-AGuJdgKsmJdm4Pych7kv3sqe591ERRaAHW3xjLooiFzn8J+PxUyof++7YZrB5Y5tpnTO+K18Og3taj2NpluCRQ=="],
|
|
93
|
+
|
|
94
|
+
"@mariozechner/clipboard-linux-riscv64-gnu": ["@mariozechner/clipboard-linux-riscv64-gnu@0.3.9", "", { "os": "linux", "cpu": "none" }, "sha512-DXBEAiuMpk7dhS1a9NzNxVAFi1vaKoPu7rQNgY8LIDLGrK3lnIp3nT10DUum+PKVJoJppIP+NAA8IZe4DMNDPw=="],
|
|
95
|
+
|
|
96
|
+
"@mariozechner/clipboard-linux-x64-gnu": ["@mariozechner/clipboard-linux-x64-gnu@0.3.9", "", { "os": "linux", "cpu": "x64" }, "sha512-WORrMLd6EpElEME7JRKfSaY34nW1P5LbdgK5YNCS1ncG2LqmITsSMEJ8nh2mpvxb3TxqbOOKgY7k9eMJYlW9Mw=="],
|
|
97
|
+
|
|
98
|
+
"@mariozechner/clipboard-linux-x64-musl": ["@mariozechner/clipboard-linux-x64-musl@0.3.9", "", { "os": "linux", "cpu": "x64" }, "sha512-/DHn+1DrfL6oRaPPWXaOKvonFFrni666fxd+zFqiQEfvBH0tsHVWjq9iqBk0oDp0qaPA72lIMy5BptxISBEhZQ=="],
|
|
99
|
+
|
|
100
|
+
"@mariozechner/clipboard-win32-arm64-msvc": ["@mariozechner/clipboard-win32-arm64-msvc@0.3.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-O5FHD3ErkMwMhNzAfu3ggy0ug4z7btZuoQgwwxlzPrwV2bxlD6WDpqBY4NCgICAgZdDKdp+loUEKVAVt8aYnhQ=="],
|
|
101
|
+
|
|
102
|
+
"@mariozechner/clipboard-win32-x64-msvc": ["@mariozechner/clipboard-win32-x64-msvc@0.3.9", "", { "os": "win32", "cpu": "x64" }, "sha512-ihQC3EufqEY81vhXBgVBtK4prL+wc62zJsSvxrgz7K1hsdt6OObz6v9p3Rn1OG3GJksTTKMJF0u/guMISHPhSA=="],
|
|
103
|
+
|
|
104
|
+
"@mistralai/mistralai": ["@mistralai/mistralai@2.2.6", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.40.0", "ws": "^8.18.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.25.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0" }, "optionalPeers": ["@opentelemetry/api"] }, "sha512-W8pX7zHxjJvMIpw8JMxeJEleapXX0Q9NPszdNzqkM3MIEoIGPObdodujj+WHteXEvGfaP/AMwlNyRfEzSY6dQQ=="],
|
|
105
|
+
|
|
106
|
+
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
|
107
|
+
|
|
108
|
+
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.43.0", "", {}, "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg=="],
|
|
109
|
+
|
|
110
|
+
"@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="],
|
|
111
|
+
|
|
112
|
+
"@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="],
|
|
113
|
+
|
|
114
|
+
"@protobufjs/codegen": ["@protobufjs/codegen@2.0.5", "", {}, "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g=="],
|
|
115
|
+
|
|
116
|
+
"@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.1", "", {}, "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg=="],
|
|
117
|
+
|
|
118
|
+
"@protobufjs/fetch": ["@protobufjs/fetch@1.1.1", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1" } }, "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw=="],
|
|
119
|
+
|
|
120
|
+
"@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="],
|
|
121
|
+
|
|
122
|
+
"@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="],
|
|
123
|
+
|
|
124
|
+
"@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="],
|
|
125
|
+
|
|
126
|
+
"@protobufjs/utf8": ["@protobufjs/utf8@1.1.2", "", {}, "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug=="],
|
|
127
|
+
|
|
128
|
+
"@silvia-odwyer/photon-node": ["@silvia-odwyer/photon-node@0.3.4", "", {}, "sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA=="],
|
|
129
|
+
|
|
130
|
+
"@smithy/core": ["@smithy/core@3.31.1", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-CyogUINxvi7C7LDsh8Syo6hVJOT9ckz4rG8dRZfTJ8r91HkMY59PnNooaj7WcHyxEkxPfBAmbgztZU+xTo76lg=="],
|
|
131
|
+
|
|
132
|
+
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.4.16", "", { "dependencies": { "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-QfuLWAkLzptffFW980AFeHZFdqds2B64rpEd3uJ6lgs3xVn9QegGMUgUcj+4d7dRrAsya3r58ZKpku97WcFb4w=="],
|
|
133
|
+
|
|
134
|
+
"@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.6.13", "", { "dependencies": { "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-4fW86pEUOMbrD5nkbyl/tTvPHHWJFbuB2odl6ps9lWfHoXf9HWh3Q/Smh59qH1g7+c/BSZghX6bbUk4gsiMs8A=="],
|
|
135
|
+
|
|
136
|
+
"@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
|
137
|
+
|
|
138
|
+
"@smithy/node-http-handler": ["@smithy/node-http-handler@4.7.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA=="],
|
|
139
|
+
|
|
140
|
+
"@smithy/signature-v4": ["@smithy/signature-v4@5.6.12", "", { "dependencies": { "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-I6KLtq3H0qqSuV9vLglfi8puHqzygzWHOnI4z/Rdoo+q50vvo18vBRdPAvvEtcaKROz7Zn6qnPa14kRfPH6PcQ=="],
|
|
141
|
+
|
|
142
|
+
"@smithy/types": ["@smithy/types@4.16.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg=="],
|
|
143
|
+
|
|
144
|
+
"@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
|
145
|
+
|
|
146
|
+
"@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
|
147
|
+
|
|
148
|
+
"@types/node": ["@types/node@26.1.2", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg=="],
|
|
149
|
+
|
|
150
|
+
"@types/retry": ["@types/retry@0.12.0", "", {}, "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="],
|
|
151
|
+
|
|
152
|
+
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
|
153
|
+
|
|
154
|
+
"balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
|
155
|
+
|
|
156
|
+
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
|
157
|
+
|
|
158
|
+
"bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
|
|
159
|
+
|
|
160
|
+
"bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="],
|
|
161
|
+
|
|
162
|
+
"brace-expansion": ["brace-expansion@5.0.9", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg=="],
|
|
163
|
+
|
|
164
|
+
"buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
|
|
165
|
+
|
|
166
|
+
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
|
167
|
+
|
|
168
|
+
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
|
169
|
+
|
|
170
|
+
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
171
|
+
|
|
172
|
+
"data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="],
|
|
173
|
+
|
|
174
|
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
|
175
|
+
|
|
176
|
+
"diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
|
|
177
|
+
|
|
178
|
+
"ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
|
|
179
|
+
|
|
180
|
+
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
|
|
181
|
+
|
|
182
|
+
"fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
|
|
183
|
+
|
|
184
|
+
"formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
|
|
185
|
+
|
|
186
|
+
"gaxios": ["gaxios@7.3.0", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA=="],
|
|
187
|
+
|
|
188
|
+
"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=="],
|
|
189
|
+
|
|
190
|
+
"get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="],
|
|
191
|
+
|
|
192
|
+
"glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
|
|
193
|
+
|
|
194
|
+
"google-auth-library": ["google-auth-library@10.9.1", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw=="],
|
|
195
|
+
|
|
196
|
+
"google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="],
|
|
197
|
+
|
|
198
|
+
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
|
199
|
+
|
|
200
|
+
"highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="],
|
|
201
|
+
|
|
202
|
+
"hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="],
|
|
203
|
+
|
|
204
|
+
"http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
|
|
205
|
+
|
|
206
|
+
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
|
207
|
+
|
|
208
|
+
"ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
|
209
|
+
|
|
210
|
+
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
|
211
|
+
|
|
212
|
+
"jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="],
|
|
213
|
+
|
|
214
|
+
"json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
|
|
215
|
+
|
|
216
|
+
"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=="],
|
|
217
|
+
|
|
218
|
+
"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=="],
|
|
219
|
+
|
|
220
|
+
"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=="],
|
|
221
|
+
|
|
222
|
+
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
|
223
|
+
|
|
224
|
+
"lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="],
|
|
225
|
+
|
|
226
|
+
"marked": ["marked@18.0.5", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w=="],
|
|
227
|
+
|
|
228
|
+
"minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
|
|
229
|
+
|
|
230
|
+
"minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
|
231
|
+
|
|
232
|
+
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
233
|
+
|
|
234
|
+
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
|
|
235
|
+
|
|
236
|
+
"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=="],
|
|
237
|
+
|
|
238
|
+
"openai": ["openai@6.26.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA=="],
|
|
239
|
+
|
|
240
|
+
"p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="],
|
|
241
|
+
|
|
242
|
+
"partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="],
|
|
243
|
+
|
|
244
|
+
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
|
245
|
+
|
|
246
|
+
"path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
|
247
|
+
|
|
248
|
+
"proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="],
|
|
249
|
+
|
|
250
|
+
"protobufjs": ["protobufjs@7.6.5", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw=="],
|
|
251
|
+
|
|
252
|
+
"retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="],
|
|
253
|
+
|
|
254
|
+
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
|
255
|
+
|
|
256
|
+
"semver": ["semver@7.8.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="],
|
|
257
|
+
|
|
258
|
+
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
|
259
|
+
|
|
260
|
+
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
|
261
|
+
|
|
262
|
+
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
|
263
|
+
|
|
264
|
+
"ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="],
|
|
265
|
+
|
|
266
|
+
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
267
|
+
|
|
268
|
+
"typebox": ["typebox@1.3.7", "", {}, "sha512-meKuifc33Pccx0O6PdIzYMq3Og8zvP4TIi/a+Bw3AEMZMxOD0+RHGQvpglEe6Zdy3wZ8nqn/j95h8LUZLk/6Hg=="],
|
|
269
|
+
|
|
270
|
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
271
|
+
|
|
272
|
+
"undici": ["undici@8.5.0", "", {}, "sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg=="],
|
|
273
|
+
|
|
274
|
+
"undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
|
|
275
|
+
|
|
276
|
+
"web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
|
|
277
|
+
|
|
278
|
+
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
|
279
|
+
|
|
280
|
+
"ws": ["ws@8.21.2", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-54dMVAo4WIe6SKy3vBgN+9bJZqqQ8IMRevAkOLQALhi49qkkQDQfWdAZ8KQlXiEabw88ARXXdUrlvtbKQX+aKw=="],
|
|
281
|
+
|
|
282
|
+
"yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="],
|
|
283
|
+
|
|
284
|
+
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
|
285
|
+
|
|
286
|
+
"zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="],
|
|
287
|
+
|
|
288
|
+
"@aws-sdk/credential-provider-http/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.13", "", { "dependencies": { "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-Nmd/Nl35zfYrd+a6OO2cDJb3GPh9bgTjIUhcM+JFfjpp8/osCgboDV5nCT1I01Pv6R13eSKDKLSoVa5ZB6Zsfw=="],
|
|
289
|
+
|
|
290
|
+
"@aws-sdk/credential-provider-sso/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1103.0", "", { "dependencies": { "@aws-sdk/core": "^3.977.6", "@aws-sdk/nested-clients": "^3.997.41", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-N4wy26MNn31ItGVHYHPrEuCIFY4MBBjC+C5v1lJKqIUSA7OZBdhleCY53zCCrXn27hsk7YNOaTuhQu807S4AfQ=="],
|
|
291
|
+
|
|
292
|
+
"@aws-sdk/nested-clients/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.13", "", { "dependencies": { "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-Nmd/Nl35zfYrd+a6OO2cDJb3GPh9bgTjIUhcM+JFfjpp8/osCgboDV5nCT1I01Pv6R13eSKDKLSoVa5ZB6Zsfw=="],
|
|
293
|
+
|
|
294
|
+
"p-retry/retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="],
|
|
295
|
+
}
|
|
296
|
+
}
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
OAuthCredentials,
|
|
3
|
+
OAuthLoginCallbacks,
|
|
4
|
+
RefreshModelsContext,
|
|
5
|
+
} from "@earendil-works/pi-ai";
|
|
6
|
+
import type { ExtensionAPI, ProviderConfig } from "@earendil-works/pi-coding-agent";
|
|
7
|
+
|
|
8
|
+
export const META_PROVIDER_ID = "meta";
|
|
9
|
+
export const META_API_BASE_URL = "https://api.meta.ai/v1";
|
|
10
|
+
export const META_MODEL_CATALOG_URL = "https://api.meta.ai/v1/models";
|
|
11
|
+
export const META_AUTH_BASE_URL = "https://auth.meta.com";
|
|
12
|
+
export const META_CLIENT_ID = "1031625952748946";
|
|
13
|
+
|
|
14
|
+
const DEVICE_AUTHORIZATION_URL = `${META_AUTH_BASE_URL}/oidc/device/authorization/`;
|
|
15
|
+
const DEVICE_TOKEN_URL = `${META_AUTH_BASE_URL}/oidc/device/token/`;
|
|
16
|
+
const API_KEY_MINT_URL = "https://api.meta.ai/muse-code/key";
|
|
17
|
+
const DEVICE_CODE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
18
|
+
const API_KEY_REFRESH_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
19
|
+
|
|
20
|
+
export type MetaProviderModel = NonNullable<ProviderConfig["models"]>[number];
|
|
21
|
+
type Fetch = typeof fetch;
|
|
22
|
+
type Sleep = (milliseconds: number) => Promise<void>;
|
|
23
|
+
|
|
24
|
+
interface DeviceAuthorization {
|
|
25
|
+
device_code: string;
|
|
26
|
+
user_code: string;
|
|
27
|
+
verification_uri: string;
|
|
28
|
+
verification_uri_complete?: string;
|
|
29
|
+
expires_in?: number;
|
|
30
|
+
interval?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface DeviceTokenGrant {
|
|
34
|
+
access_token: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface OAuthError {
|
|
38
|
+
error?: string;
|
|
39
|
+
error_description?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface MintResponse {
|
|
43
|
+
api_key?: string;
|
|
44
|
+
base_url?: string;
|
|
45
|
+
require_payment?: boolean;
|
|
46
|
+
action_url?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface CatalogResponse {
|
|
50
|
+
data?: MetaCatalogModel[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface MetaCatalogModel {
|
|
54
|
+
id?: string;
|
|
55
|
+
metadata?: {
|
|
56
|
+
"muse-code"?: {
|
|
57
|
+
name?: string;
|
|
58
|
+
is_hidden?: boolean;
|
|
59
|
+
reasoning?: boolean;
|
|
60
|
+
modalities?: { input?: string[] };
|
|
61
|
+
limit?: { context?: number; output?: number };
|
|
62
|
+
variants?: Record<string, { reasoningEffort?: string }>;
|
|
63
|
+
cost?: { input?: string | number; output?: string | number; cached?: string | number };
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const FALLBACK_MODELS: MetaProviderModel[] = [
|
|
69
|
+
{
|
|
70
|
+
id: "muse-spark-1.2",
|
|
71
|
+
name: "Muse Spark 1.2",
|
|
72
|
+
reasoning: true,
|
|
73
|
+
thinkingLevelMap: {
|
|
74
|
+
off: null,
|
|
75
|
+
minimal: "minimal",
|
|
76
|
+
low: "low",
|
|
77
|
+
medium: "medium",
|
|
78
|
+
high: "high",
|
|
79
|
+
xhigh: "xhigh",
|
|
80
|
+
max: null,
|
|
81
|
+
},
|
|
82
|
+
input: ["text", "image"],
|
|
83
|
+
cost: { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 },
|
|
84
|
+
contextWindow: 1_048_576,
|
|
85
|
+
maxTokens: 256_000,
|
|
86
|
+
compat: { supportsReasoningEffort: true },
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: "muse-spark-1.2-contributor",
|
|
90
|
+
name: "Muse Spark 1.2 Contributor",
|
|
91
|
+
reasoning: true,
|
|
92
|
+
thinkingLevelMap: {
|
|
93
|
+
off: null,
|
|
94
|
+
minimal: "minimal",
|
|
95
|
+
low: "low",
|
|
96
|
+
medium: "medium",
|
|
97
|
+
high: "high",
|
|
98
|
+
xhigh: "xhigh",
|
|
99
|
+
max: null,
|
|
100
|
+
},
|
|
101
|
+
input: ["text", "image"],
|
|
102
|
+
cost: { input: 0.1, output: 0.2, cacheRead: 0.002, cacheWrite: 0 },
|
|
103
|
+
contextWindow: 1_048_576,
|
|
104
|
+
maxTokens: 256_000,
|
|
105
|
+
compat: { supportsReasoningEffort: true },
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: "muse-spark-1.1",
|
|
109
|
+
name: "Muse Spark 1.1",
|
|
110
|
+
reasoning: true,
|
|
111
|
+
thinkingLevelMap: {
|
|
112
|
+
off: null,
|
|
113
|
+
minimal: "minimal",
|
|
114
|
+
low: "low",
|
|
115
|
+
medium: "medium",
|
|
116
|
+
high: "high",
|
|
117
|
+
xhigh: "xhigh",
|
|
118
|
+
max: null,
|
|
119
|
+
},
|
|
120
|
+
input: ["text", "image"],
|
|
121
|
+
cost: { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 },
|
|
122
|
+
contextWindow: 1_048_576,
|
|
123
|
+
maxTokens: 256_000,
|
|
124
|
+
compat: { supportsReasoningEffort: true },
|
|
125
|
+
},
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
function delay(milliseconds: number): Promise<void> {
|
|
129
|
+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function responseBody(response: Response): Promise<Record<string, unknown>> {
|
|
133
|
+
const text = await response.text();
|
|
134
|
+
if (!text) return {};
|
|
135
|
+
try {
|
|
136
|
+
const value = JSON.parse(text) as unknown;
|
|
137
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
138
|
+
? (value as Record<string, unknown>)
|
|
139
|
+
: {};
|
|
140
|
+
} catch {
|
|
141
|
+
return {};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function errorDetail(body: Record<string, unknown>): string | undefined {
|
|
146
|
+
for (const key of ["error_description", "detail", "message", "error"]) {
|
|
147
|
+
const value = body[key];
|
|
148
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
149
|
+
}
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function postForm<T>(
|
|
154
|
+
url: string,
|
|
155
|
+
fields: Record<string, string>,
|
|
156
|
+
fetchImpl: Fetch,
|
|
157
|
+
): Promise<{ response: Response; body: T & Record<string, unknown> }> {
|
|
158
|
+
const response = await fetchImpl(url, {
|
|
159
|
+
method: "POST",
|
|
160
|
+
headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded" },
|
|
161
|
+
body: new URLSearchParams(fields),
|
|
162
|
+
redirect: "manual",
|
|
163
|
+
});
|
|
164
|
+
return { response, body: (await responseBody(response)) as T & Record<string, unknown> };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export async function mintMetaApiKey(identityToken: string, fetchImpl: Fetch = fetch): Promise<string> {
|
|
168
|
+
const response = await fetchImpl(API_KEY_MINT_URL, {
|
|
169
|
+
method: "POST",
|
|
170
|
+
headers: {
|
|
171
|
+
Accept: "application/json",
|
|
172
|
+
Authorization: `Bearer ${identityToken}`,
|
|
173
|
+
"Content-Type": "application/json",
|
|
174
|
+
"x-api-version": "1.0.0",
|
|
175
|
+
},
|
|
176
|
+
body: "{}",
|
|
177
|
+
});
|
|
178
|
+
const body = (await responseBody(response)) as MintResponse & Record<string, unknown>;
|
|
179
|
+
if (!response.ok) {
|
|
180
|
+
throw new Error(`Meta API-key mint failed (HTTP ${response.status})${errorDetail(body) ? `: ${errorDetail(body)}` : ""}`);
|
|
181
|
+
}
|
|
182
|
+
if (typeof body.api_key !== "string" || !body.api_key) {
|
|
183
|
+
const setup = typeof body.action_url === "string" && body.action_url ? ` Complete setup at ${body.action_url}.` : "";
|
|
184
|
+
throw new Error(`Meta did not issue an API key.${setup}`);
|
|
185
|
+
}
|
|
186
|
+
return body.api_key;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export async function loginMeta(
|
|
190
|
+
callbacks: OAuthLoginCallbacks,
|
|
191
|
+
fetchImpl: Fetch = fetch,
|
|
192
|
+
sleep: Sleep = delay,
|
|
193
|
+
): Promise<OAuthCredentials> {
|
|
194
|
+
callbacks.onProgress?.("Starting Meta device authorization…");
|
|
195
|
+
const authorization = await postForm<DeviceAuthorization>(
|
|
196
|
+
DEVICE_AUTHORIZATION_URL,
|
|
197
|
+
{ client_id: META_CLIENT_ID },
|
|
198
|
+
fetchImpl,
|
|
199
|
+
);
|
|
200
|
+
if (!authorization.response.ok) {
|
|
201
|
+
throw new Error(
|
|
202
|
+
`Meta login could not be started (HTTP ${authorization.response.status})${errorDetail(authorization.body) ? `: ${errorDetail(authorization.body)}` : ""}`,
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
const device = authorization.body;
|
|
206
|
+
if (!device.device_code || !device.user_code || !device.verification_uri) {
|
|
207
|
+
throw new Error("Meta device authorization returned an incomplete response");
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
let intervalSeconds = Number.isFinite(device.interval) && Number(device.interval) > 0 ? Number(device.interval) : 5;
|
|
211
|
+
const expiresInSeconds = Number.isFinite(device.expires_in) && Number(device.expires_in) > 0
|
|
212
|
+
? Number(device.expires_in)
|
|
213
|
+
: 900;
|
|
214
|
+
const deadline = Date.now() + expiresInSeconds * 1000;
|
|
215
|
+
callbacks.onDeviceCode({
|
|
216
|
+
userCode: device.user_code,
|
|
217
|
+
verificationUri: device.verification_uri_complete || device.verification_uri,
|
|
218
|
+
intervalSeconds,
|
|
219
|
+
expiresInSeconds,
|
|
220
|
+
});
|
|
221
|
+
callbacks.onProgress?.("Waiting for Meta login approval…");
|
|
222
|
+
|
|
223
|
+
let identityToken: string | undefined;
|
|
224
|
+
while (Date.now() < deadline) {
|
|
225
|
+
await sleep(intervalSeconds * 1000);
|
|
226
|
+
const grant = await postForm<DeviceTokenGrant & OAuthError>(
|
|
227
|
+
DEVICE_TOKEN_URL,
|
|
228
|
+
{
|
|
229
|
+
grant_type: DEVICE_CODE_GRANT,
|
|
230
|
+
device_code: device.device_code,
|
|
231
|
+
client_id: META_CLIENT_ID,
|
|
232
|
+
},
|
|
233
|
+
fetchImpl,
|
|
234
|
+
);
|
|
235
|
+
if (grant.response.ok && grant.body.access_token) {
|
|
236
|
+
identityToken = grant.body.access_token;
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
switch (grant.body.error) {
|
|
240
|
+
case "authorization_pending":
|
|
241
|
+
continue;
|
|
242
|
+
case "slow_down":
|
|
243
|
+
intervalSeconds += 5;
|
|
244
|
+
continue;
|
|
245
|
+
case "access_denied":
|
|
246
|
+
throw new Error("Meta login was denied");
|
|
247
|
+
case "expired_token":
|
|
248
|
+
throw new Error("Meta login request expired");
|
|
249
|
+
default:
|
|
250
|
+
throw new Error(
|
|
251
|
+
`Meta login failed (HTTP ${grant.response.status})${errorDetail(grant.body) ? `: ${errorDetail(grant.body)}` : ""}`,
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (!identityToken) throw new Error("Meta login request expired");
|
|
256
|
+
|
|
257
|
+
callbacks.onProgress?.("Enabling Meta Model API access…");
|
|
258
|
+
const apiKey = await mintMetaApiKey(identityToken, fetchImpl);
|
|
259
|
+
return {
|
|
260
|
+
refresh: identityToken,
|
|
261
|
+
access: apiKey,
|
|
262
|
+
expires: Date.now() + API_KEY_REFRESH_INTERVAL_MS,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export async function refreshMetaToken(
|
|
267
|
+
credentials: OAuthCredentials,
|
|
268
|
+
fetchImpl: Fetch = fetch,
|
|
269
|
+
): Promise<OAuthCredentials> {
|
|
270
|
+
if (!credentials.refresh) throw new Error("Meta login is missing its identity token; run /login meta again");
|
|
271
|
+
return {
|
|
272
|
+
...credentials,
|
|
273
|
+
access: await mintMetaApiKey(credentials.refresh, fetchImpl),
|
|
274
|
+
expires: Date.now() + API_KEY_REFRESH_INTERVAL_MS,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function finitePositive(value: unknown, fallback: number): number {
|
|
279
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function numericCost(value: unknown, fallback: number): number {
|
|
283
|
+
const number = typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN;
|
|
284
|
+
return Number.isFinite(number) && number >= 0 ? number : fallback;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function displayName(id: string): string {
|
|
288
|
+
return id
|
|
289
|
+
.split("-")
|
|
290
|
+
.map((part) => part ? part[0].toUpperCase() + part.slice(1) : part)
|
|
291
|
+
.join(" ");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function toProviderModels(catalog: CatalogResponse): MetaProviderModel[] {
|
|
295
|
+
return (catalog.data ?? []).flatMap((entry) => {
|
|
296
|
+
if (typeof entry.id !== "string" || !entry.id) return [];
|
|
297
|
+
const metadata = entry.metadata?.["muse-code"];
|
|
298
|
+
if (metadata?.is_hidden) return [];
|
|
299
|
+
const fallback = FALLBACK_MODELS.find((model) => model.id === entry.id);
|
|
300
|
+
const catalogName = metadata?.name === entry.id ? undefined : metadata?.name;
|
|
301
|
+
const variants = metadata?.variants ?? {};
|
|
302
|
+
const thinkingLevelMap: NonNullable<MetaProviderModel["thinkingLevelMap"]> = {
|
|
303
|
+
off: null,
|
|
304
|
+
minimal: variants.minimal?.reasoningEffort ?? "minimal",
|
|
305
|
+
low: variants.low?.reasoningEffort ?? "low",
|
|
306
|
+
medium: variants.medium?.reasoningEffort ?? "medium",
|
|
307
|
+
high: variants.high?.reasoningEffort ?? "high",
|
|
308
|
+
xhigh: variants.xhigh?.reasoningEffort ?? "xhigh",
|
|
309
|
+
max: null,
|
|
310
|
+
};
|
|
311
|
+
return [{
|
|
312
|
+
id: entry.id,
|
|
313
|
+
name: catalogName || fallback?.name || displayName(entry.id),
|
|
314
|
+
reasoning: metadata?.reasoning ?? fallback?.reasoning ?? true,
|
|
315
|
+
thinkingLevelMap,
|
|
316
|
+
input: metadata
|
|
317
|
+
? (metadata.modalities?.input?.includes("image") ? ["text", "image"] : ["text"])
|
|
318
|
+
: (fallback?.input ?? ["text"]),
|
|
319
|
+
cost: {
|
|
320
|
+
input: numericCost(metadata?.cost?.input, fallback?.cost.input ?? 0),
|
|
321
|
+
output: numericCost(metadata?.cost?.output, fallback?.cost.output ?? 0),
|
|
322
|
+
cacheRead: numericCost(metadata?.cost?.cached, fallback?.cost.cacheRead ?? 0),
|
|
323
|
+
cacheWrite: 0,
|
|
324
|
+
},
|
|
325
|
+
contextWindow: finitePositive(metadata?.limit?.context, fallback?.contextWindow ?? 1_048_576),
|
|
326
|
+
maxTokens: finitePositive(metadata?.limit?.output, fallback?.maxTokens ?? 256_000),
|
|
327
|
+
compat: { supportsReasoningEffort: true },
|
|
328
|
+
} satisfies MetaProviderModel];
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export async function refreshMetaModels(
|
|
333
|
+
context: RefreshModelsContext,
|
|
334
|
+
fetchImpl: Fetch = fetch,
|
|
335
|
+
): Promise<MetaProviderModel[]> {
|
|
336
|
+
if (!context.allowNetwork || context.signal?.aborted) return [...FALLBACK_MODELS];
|
|
337
|
+
const apiKey = context.credential?.type === "oauth"
|
|
338
|
+
? context.credential.access
|
|
339
|
+
: context.credential?.type === "api_key"
|
|
340
|
+
? context.credential.key
|
|
341
|
+
: undefined;
|
|
342
|
+
if (!apiKey) return [...FALLBACK_MODELS];
|
|
343
|
+
|
|
344
|
+
const response = await fetchImpl(META_MODEL_CATALOG_URL, {
|
|
345
|
+
headers: { Accept: "application/json", Authorization: `Bearer ${apiKey}`, "x-api-version": "1.0.0" },
|
|
346
|
+
signal: context.signal,
|
|
347
|
+
});
|
|
348
|
+
const body = (await responseBody(response)) as CatalogResponse & Record<string, unknown>;
|
|
349
|
+
if (!response.ok) {
|
|
350
|
+
throw new Error(`Meta model catalog failed (HTTP ${response.status})${errorDetail(body) ? `: ${errorDetail(body)}` : ""}`);
|
|
351
|
+
}
|
|
352
|
+
return toProviderModels(body);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export function createMetaProviderConfig(): ProviderConfig {
|
|
356
|
+
return {
|
|
357
|
+
name: "Meta Model API",
|
|
358
|
+
baseUrl: META_API_BASE_URL,
|
|
359
|
+
api: "openai-responses",
|
|
360
|
+
models: [...FALLBACK_MODELS],
|
|
361
|
+
refreshModels: refreshMetaModels,
|
|
362
|
+
oauth: {
|
|
363
|
+
name: "Meta Model API (browser login)",
|
|
364
|
+
login: loginMeta,
|
|
365
|
+
refreshToken: refreshMetaToken,
|
|
366
|
+
getApiKey: (credentials: { access: string }) => credentials.access,
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export default function metaOAuthProvider(pi: ExtensionAPI): void {
|
|
372
|
+
pi.registerProvider(META_PROVIDER_ID, createMetaProviderConfig());
|
|
373
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-meta-oauth",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Meta Model API OAuth provider for pi — device login, API-key minting, and Muse Spark model catalog for pi.dev",
|
|
5
|
+
"keywords": ["pi-package", "meta", "muse-spark", "oauth", "provider"],
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/BlockedPath/pi-meta-oauth"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/BlockedPath/pi-meta-oauth#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/BlockedPath/pi-meta-oauth/issues"
|
|
15
|
+
},
|
|
16
|
+
"pi": {
|
|
17
|
+
"extensions": ["./extensions/meta.ts"],
|
|
18
|
+
"image": "https://raw.githubusercontent.com/BlockedPath/pi-meta-oauth/main/preview.png"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@earendil-works/pi-ai": ">=0.83.0 <0.84.0",
|
|
22
|
+
"@earendil-works/pi-coding-agent": ">=0.83.0 <0.84.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@earendil-works/pi-ai": "0.83.0",
|
|
26
|
+
"@earendil-works/pi-coding-agent": "0.83.0",
|
|
27
|
+
"bun-types": "latest",
|
|
28
|
+
"typescript": "^5.9.0"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"test": "bun test tests/meta.test.ts"
|
|
33
|
+
}
|
|
34
|
+
}
|
package/preview.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import {
|
|
3
|
+
loginMeta,
|
|
4
|
+
mintMetaApiKey,
|
|
5
|
+
toProviderModels,
|
|
6
|
+
} from "../extensions/meta.ts";
|
|
7
|
+
|
|
8
|
+
function jsonResponse(body: unknown, status = 200): Response {
|
|
9
|
+
return new Response(JSON.stringify(body), {
|
|
10
|
+
status,
|
|
11
|
+
headers: { "Content-Type": "application/json" },
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
describe("Meta OAuth provider", () => {
|
|
16
|
+
test("maps the Muse catalog into Pi model metadata", () => {
|
|
17
|
+
const models = toProviderModels({
|
|
18
|
+
data: [
|
|
19
|
+
{
|
|
20
|
+
id: "muse-spark-test",
|
|
21
|
+
metadata: {
|
|
22
|
+
"muse-code": {
|
|
23
|
+
name: "Muse Spark Test",
|
|
24
|
+
reasoning: true,
|
|
25
|
+
modalities: { input: ["text", "image"] },
|
|
26
|
+
limit: { context: 123_000, output: 45_000 },
|
|
27
|
+
variants: { high: { reasoningEffort: "deep" } },
|
|
28
|
+
cost: { input: "1.25", output: "4.25", cached: "0.15" },
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{ id: "hidden", metadata: { "muse-code": { is_hidden: true } } },
|
|
33
|
+
],
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(models).toHaveLength(1);
|
|
37
|
+
expect(models[0]).toMatchObject({
|
|
38
|
+
id: "muse-spark-test",
|
|
39
|
+
name: "Muse Spark Test",
|
|
40
|
+
input: ["text", "image"],
|
|
41
|
+
contextWindow: 123_000,
|
|
42
|
+
maxTokens: 45_000,
|
|
43
|
+
cost: { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 },
|
|
44
|
+
thinkingLevelMap: { off: null, high: "deep", max: null },
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("runs device login, polls, and mints a Model API key", async () => {
|
|
49
|
+
const requests: Array<{ url: string; authorization?: string }> = [];
|
|
50
|
+
const responses = [
|
|
51
|
+
jsonResponse({
|
|
52
|
+
device_code: "device-token",
|
|
53
|
+
user_code: "ABCD-1234",
|
|
54
|
+
verification_uri: "https://auth.meta.com/device",
|
|
55
|
+
verification_uri_complete: "https://auth.meta.com/device?code=ABCD-1234",
|
|
56
|
+
expires_in: 900,
|
|
57
|
+
interval: 1,
|
|
58
|
+
}),
|
|
59
|
+
jsonResponse({ error: "authorization_pending" }, 400),
|
|
60
|
+
jsonResponse({ access_token: "identity-token" }),
|
|
61
|
+
jsonResponse({ api_key: "model-api-key", base_url: "https://api.meta.ai/v1" }),
|
|
62
|
+
];
|
|
63
|
+
const fetchMock = (async (input: string | URL | Request, init?: RequestInit) => {
|
|
64
|
+
const headers = new Headers(init?.headers);
|
|
65
|
+
requests.push({ url: String(input), authorization: headers.get("Authorization") ?? undefined });
|
|
66
|
+
const response = responses.shift();
|
|
67
|
+
if (!response) throw new Error("Unexpected request");
|
|
68
|
+
return response;
|
|
69
|
+
}) as unknown as typeof fetch;
|
|
70
|
+
const deviceCodes: unknown[] = [];
|
|
71
|
+
const credentials = await loginMeta(
|
|
72
|
+
{
|
|
73
|
+
onAuth() {},
|
|
74
|
+
onDeviceCode(value: unknown) { deviceCodes.push(value); },
|
|
75
|
+
onPrompt: async () => "",
|
|
76
|
+
onSelect: async () => undefined,
|
|
77
|
+
},
|
|
78
|
+
fetchMock,
|
|
79
|
+
async () => {},
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
expect(deviceCodes).toEqual([{
|
|
83
|
+
userCode: "ABCD-1234",
|
|
84
|
+
verificationUri: "https://auth.meta.com/device?code=ABCD-1234",
|
|
85
|
+
intervalSeconds: 1,
|
|
86
|
+
expiresInSeconds: 900,
|
|
87
|
+
}]);
|
|
88
|
+
expect(credentials.refresh).toBe("identity-token");
|
|
89
|
+
expect(credentials.access).toBe("model-api-key");
|
|
90
|
+
expect(requests.at(-1)?.authorization).toBe("Bearer identity-token");
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("reports account setup when minting yields no API key", async () => {
|
|
94
|
+
const fetchMock = (async () => jsonResponse({
|
|
95
|
+
require_payment: true,
|
|
96
|
+
action_url: "https://dev.meta.ai/billing",
|
|
97
|
+
})) as unknown as typeof fetch;
|
|
98
|
+
await expect(mintMetaApiKey("identity-token", fetchMock)).rejects.toThrow(
|
|
99
|
+
"Complete setup at https://dev.meta.ai/billing",
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
});
|
package/tsconfig.json
ADDED