@cloudflare/aig-pi-extension 2026.9.18
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/README.md +25 -0
- package/package.json +50 -0
- package/src/index.ts +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Cloudflare AI Gateway extension for Pi
|
|
2
|
+
|
|
3
|
+
Adds the `cloudflare/auto` Smart Router model to Pi through Cloudflare's internal AI gateway. It records routing diagnostics silently and shows the latest decision on demand through `/aig-show`, without occupying persistent UI space. It registers an isolated provider without replacing Pi's built-in provider or model catalog.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- `cloudflared`
|
|
8
|
+
- Cloudflare Access entitlement to `opencode.cloudflare.dev`
|
|
9
|
+
- Pi 0.84.4
|
|
10
|
+
|
|
11
|
+
Authentication uses the same pinned `cloudflared access login` flow as `pi-cf-internal-gateway`. Tokens remain in memory and are not written to Pi's credential store.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pi install ./packages/aig-pi-extension
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Select `cloudflare-auto/cloudflare/auto` with `/model` or start Pi with:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pi --model cloudflare-auto/cloudflare/auto
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Pi estimates cost using the internal catalog's `cloudflare/auto` rate. AI Gateway billing and logs report the concrete routed model and actual cost.
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cloudflare/aig-pi-extension",
|
|
3
|
+
"version": "2026.9.18",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Cloudflare AI Gateway Smart Router support and routing diagnostics for Pi",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"pi-package",
|
|
8
|
+
"cloudflare",
|
|
9
|
+
"ai-gateway",
|
|
10
|
+
"smart-router"
|
|
11
|
+
],
|
|
12
|
+
"sideEffects": true,
|
|
13
|
+
"type": "module",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": "./src/index.ts"
|
|
16
|
+
},
|
|
17
|
+
"main": "src/index.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"src",
|
|
20
|
+
"README.md",
|
|
21
|
+
"!**/*.spec.ts"
|
|
22
|
+
],
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@earendil-works/pi-ai": "0.84.4",
|
|
25
|
+
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
26
|
+
"vitest": "4.1.10",
|
|
27
|
+
"@repo/tools": "0.0.0",
|
|
28
|
+
"@repo/eslint-config": "0.0.0",
|
|
29
|
+
"@repo/typescript-config": "0.0.0"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@earendil-works/pi-ai": "0.84.4",
|
|
33
|
+
"@earendil-works/pi-coding-agent": "0.84.4"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public",
|
|
37
|
+
"registry": "https://registry.npmjs.org/"
|
|
38
|
+
},
|
|
39
|
+
"pi": {
|
|
40
|
+
"extensions": [
|
|
41
|
+
"./src/index.ts"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"check:lint": "run-biome && run-eslint",
|
|
46
|
+
"check:types": "run-tsc",
|
|
47
|
+
"test": "run-vitest",
|
|
48
|
+
"test:ci": "run-vitest-ci"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { ExtensionAPI } from '@earendil-works/pi-coding-agent'
|
|
2
|
+
|
|
3
|
+
interface RoutingResult {
|
|
4
|
+
requestedModel: string
|
|
5
|
+
routedModel: string
|
|
6
|
+
reason: string
|
|
7
|
+
decisionId: string
|
|
8
|
+
requestId: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default function aigPiExtension(pi: ExtensionAPI): void {
|
|
12
|
+
let latest: RoutingResult | undefined
|
|
13
|
+
|
|
14
|
+
pi.registerProvider('cloudflare-auto', {
|
|
15
|
+
name: 'Cloudflare Auto (CF Internal Gateway)',
|
|
16
|
+
api: 'openai-completions',
|
|
17
|
+
baseUrl: 'https://gateway.opencode.cloudflare.dev/compat',
|
|
18
|
+
apiKey: 'cf-internal-gateway',
|
|
19
|
+
headers: {
|
|
20
|
+
'cf-access-token':
|
|
21
|
+
'!cloudflared access login --no-verbose -app=https://opencode.cloudflare.dev',
|
|
22
|
+
'X-Requested-With': 'xmlhttprequest',
|
|
23
|
+
},
|
|
24
|
+
models: [
|
|
25
|
+
{
|
|
26
|
+
id: 'cloudflare/auto',
|
|
27
|
+
name: 'Cloudflare Auto (dynamic pricing)',
|
|
28
|
+
reasoning: false,
|
|
29
|
+
input: ['text', 'image'],
|
|
30
|
+
cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.5 },
|
|
31
|
+
contextWindow: 1_000_000,
|
|
32
|
+
maxTokens: 128_000,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
pi.on('after_provider_response', (event, ctx) => {
|
|
38
|
+
const headers = event.headers
|
|
39
|
+
if (
|
|
40
|
+
!headers['cf-aig-routed-model'] &&
|
|
41
|
+
!headers['cf-aig-routing-reason'] &&
|
|
42
|
+
!headers['cf-aig-routing-decision-id']
|
|
43
|
+
)
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
latest = {
|
|
47
|
+
requestedModel: ctx.model?.id ?? 'unknown',
|
|
48
|
+
routedModel: headers['cf-aig-routed-model'] ?? 'unknown',
|
|
49
|
+
reason: headers['cf-aig-routing-reason'] ?? 'unknown',
|
|
50
|
+
decisionId: headers['cf-aig-routing-decision-id'] ?? 'unknown',
|
|
51
|
+
requestId: headers['cf-aig-request-id'] ?? 'unknown',
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
pi.registerCommand('aig-show', {
|
|
56
|
+
description: 'Show the latest AI Gateway Smart Router decision',
|
|
57
|
+
handler: async (_args, ctx) => {
|
|
58
|
+
const message = latest
|
|
59
|
+
? [
|
|
60
|
+
`requested: ${latest.requestedModel}`,
|
|
61
|
+
`routed: ${latest.routedModel}`,
|
|
62
|
+
`reason: ${latest.reason}`,
|
|
63
|
+
`decision: ${latest.decisionId}`,
|
|
64
|
+
`request: ${latest.requestId}`,
|
|
65
|
+
].join('\n')
|
|
66
|
+
: 'No AI Gateway routing result captured yet.'
|
|
67
|
+
ctx.ui.notify(message, 'info')
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
}
|