@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.
Files changed (3) hide show
  1. package/README.md +25 -0
  2. package/package.json +50 -0
  3. 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
+ }