sub-bridge 1.0.0 ā 1.0.3
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/.github/workflows/npm-publish.yml +3 -2
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +16 -0
- package/dist/auth/provider.d.ts +1 -0
- package/dist/auth/provider.d.ts.map +1 -1
- package/dist/auth/provider.js +22 -0
- package/dist/auth/provider.js.map +1 -1
- package/dist/cli.js +0 -14
- package/dist/cli.js.map +1 -1
- package/dist/oauth/authorize.d.ts +73 -0
- package/dist/oauth/authorize.d.ts.map +1 -0
- package/dist/oauth/authorize.js +197 -0
- package/dist/oauth/authorize.js.map +1 -0
- package/dist/oauth/crypto.d.ts +58 -0
- package/dist/oauth/crypto.d.ts.map +1 -0
- package/dist/oauth/crypto.js +170 -0
- package/dist/oauth/crypto.js.map +1 -0
- package/dist/oauth/dcr.d.ts +44 -0
- package/dist/oauth/dcr.d.ts.map +1 -0
- package/dist/oauth/dcr.js +84 -0
- package/dist/oauth/dcr.js.map +1 -0
- package/dist/oauth/metadata.d.ts +23 -0
- package/dist/oauth/metadata.d.ts.map +1 -0
- package/dist/oauth/metadata.js +29 -0
- package/dist/oauth/metadata.js.map +1 -0
- package/dist/oauth/token.d.ts +29 -0
- package/dist/oauth/token.d.ts.map +1 -0
- package/dist/oauth/token.js +117 -0
- package/dist/oauth/token.js.map +1 -0
- package/dist/routes/chat.d.ts.map +1 -1
- package/dist/routes/chat.js +128 -15
- package/dist/routes/chat.js.map +1 -1
- package/dist/routes/oauth.d.ts +13 -0
- package/dist/routes/oauth.d.ts.map +1 -0
- package/dist/routes/oauth.js +174 -0
- package/dist/routes/oauth.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +14 -6
- package/dist/server.js.map +1 -1
- package/dist/tunnel/providers/cloudflare.d.ts.map +1 -1
- package/dist/tunnel/providers/cloudflare.js +19 -5
- package/dist/tunnel/providers/cloudflare.js.map +1 -1
- package/dist/tunnel/registry.d.ts.map +1 -1
- package/dist/tunnel/registry.js +75 -9
- package/dist/tunnel/registry.js.map +1 -1
- package/dist/utils/cloudflared-config.d.ts +2 -0
- package/dist/utils/cloudflared-config.d.ts.map +1 -0
- package/dist/utils/cloudflared-config.js +116 -0
- package/dist/utils/cloudflared-config.js.map +1 -0
- package/dist/utils/setup-instructions.d.ts.map +1 -1
- package/dist/utils/setup-instructions.js +6 -9
- package/dist/utils/setup-instructions.js.map +1 -1
- package/index.html +268 -281
- package/package.json +6 -2
- package/src/cli.ts +0 -14
- package/src/routes/chat.ts +3 -0
- package/src/server.ts +10 -6
- package/src/tunnel/providers/cloudflare.ts +18 -5
- package/src/tunnel/registry.ts +79 -8
- package/src/utils/cloudflared-config.ts +121 -0
- package/src/utils/setup-instructions.ts +6 -9
- package/dist/auth/oauth-flow.d.ts +0 -24
- package/dist/auth/oauth-flow.d.ts.map +0 -1
- package/dist/auth/oauth-flow.js +0 -184
- package/dist/auth/oauth-flow.js.map +0 -1
- package/dist/auth/oauth-manager.d.ts +0 -13
- package/dist/auth/oauth-manager.d.ts.map +0 -1
- package/dist/auth/oauth-manager.js +0 -25
- package/dist/auth/oauth-manager.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sub-bridge",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "MCP bridge to use ChatGPT Pro, Claude Max, etc. in Cursor via an OpenAI-compatible proxy",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"dev": "tsx src/cli.ts --verbose",
|
|
12
12
|
"dev:server": "tsx watch src/server.ts",
|
|
13
13
|
"dev:mcp": "tsx src/mcp.ts",
|
|
14
|
-
"dev:tmux": "tmux attach -t sub-bridge || tmux new -s sub-bridge \"set -a; source ./.env; set +a; npm run dev:server\"",
|
|
14
|
+
"dev:tmux": "tmux attach -t sub-bridge 2>/dev/null || tmux new -s sub-bridge \"set -a; source ./.env; set +a; npm run dev:server || sleep 10\"",
|
|
15
15
|
"start": "node dist/cli.js",
|
|
16
16
|
"start:server": "tsx src/server.ts",
|
|
17
17
|
"start:mcp": "tsx src/mcp.ts",
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
],
|
|
35
35
|
"author": "Maol-1997",
|
|
36
36
|
"license": "MIT",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/buremba/sub-bridge"
|
|
40
|
+
},
|
|
37
41
|
"dependencies": {
|
|
38
42
|
"@hono/node-server": "^1.19.7",
|
|
39
43
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
package/src/cli.ts
CHANGED
|
@@ -69,23 +69,9 @@ async function main() {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
function printSetupInstructions(publicUrl: string) {
|
|
72
|
-
log()
|
|
73
|
-
log(chalk.bold.yellow(' Setup in Cursor:'))
|
|
74
|
-
log(chalk.dim(' āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'))
|
|
75
|
-
log()
|
|
76
|
-
log(chalk.dim(' 1. Command Palette (Cmd+Shift+P / Ctrl+Shift+P)'))
|
|
77
|
-
log(chalk.dim(' 2. Search "Cursor Settings" ā Open'))
|
|
78
|
-
log(chalk.dim(' 3. Navigate: Models ā API Keys (expand)'))
|
|
79
|
-
log(chalk.dim(' 4. Enable "OpenAI API Key" toggle'))
|
|
80
|
-
log(chalk.dim(' 5. Set API key with routing:'))
|
|
81
|
-
log(chalk.dim(' '), chalk.cyan('o3=opus-4.5,o3-mini=sonnet-4.5:sk-ant-xxx'))
|
|
82
|
-
log(chalk.dim(' 6. Enable "Override OpenAI Base URL" toggle'))
|
|
83
|
-
log(chalk.dim(' 7. Set Base URL:'), chalk.cyan.bold(`${publicUrl}/v1`))
|
|
84
72
|
log()
|
|
85
73
|
log(chalk.dim(' Getting API keys:'))
|
|
86
74
|
log(chalk.dim(' ⢠Open'), chalk.cyan(publicUrl), chalk.dim('in your external browser and click Login buttons'))
|
|
87
|
-
log(chalk.dim(' ⢠Or use Claude Code CLI:'), chalk.cyan('claude setup-token'))
|
|
88
|
-
log(chalk.dim(' ⢠Or use Codex CLI:'), chalk.cyan('codex login'))
|
|
89
75
|
log()
|
|
90
76
|
log(chalk.dim(' Use MCP tool: "get_status" to get URL anytime'))
|
|
91
77
|
log()
|
package/src/routes/chat.ts
CHANGED
|
@@ -961,6 +961,9 @@ Examples:
|
|
|
961
961
|
export function createChatRoutes() {
|
|
962
962
|
const app = new Hono()
|
|
963
963
|
|
|
964
|
+
// Base route for quick health checks
|
|
965
|
+
app.get('/', (c) => c.json({ status: 'ok' }))
|
|
966
|
+
|
|
964
967
|
// Models endpoint
|
|
965
968
|
app.get('/models', async (c) => {
|
|
966
969
|
const response = await fetch('https://models.dev/api.json')
|
package/src/server.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { createChatRoutes } from './routes/chat'
|
|
|
23
23
|
import { createOAuthRoutes } from './routes/oauth'
|
|
24
24
|
import { addSharedOptions } from './utils/cli-args'
|
|
25
25
|
import { buildStatusText } from './utils/setup-instructions'
|
|
26
|
+
import { getCloudflaredHostnames } from './utils/cloudflared-config'
|
|
26
27
|
|
|
27
28
|
// ============================================================================
|
|
28
29
|
// CONFIGURATION
|
|
@@ -86,10 +87,14 @@ export function createServerApp(config: ServerConfig, getPublicUrl: () => string
|
|
|
86
87
|
}))
|
|
87
88
|
|
|
88
89
|
// API config for frontend
|
|
89
|
-
app.get('/api/config', (c) =>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
app.get('/api/config', async (c) => {
|
|
91
|
+
const cloudflaredHostnames = await getCloudflaredHostnames(localPort.value)
|
|
92
|
+
return c.json({
|
|
93
|
+
publicUrl: getPublicUrl(),
|
|
94
|
+
port: localPort.value,
|
|
95
|
+
cloudflaredHostnames,
|
|
96
|
+
})
|
|
97
|
+
})
|
|
93
98
|
|
|
94
99
|
// MCP tool forwarding endpoint
|
|
95
100
|
app.post('/mcp/tools/:name', async (c) => {
|
|
@@ -156,14 +161,13 @@ export async function startServer(config: ServerConfig): Promise<StartedServer>
|
|
|
156
161
|
: `http://localhost:${info.port}`
|
|
157
162
|
|
|
158
163
|
log()
|
|
159
|
-
log(chalk.bold.cyan(' Sub Bridge
|
|
164
|
+
log(chalk.bold.cyan(' Sub Bridge OpenAI API Gateway and MCP Server'))
|
|
160
165
|
log(chalk.dim(' āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'))
|
|
161
166
|
log()
|
|
162
167
|
log(' ', chalk.green(publicUrl))
|
|
163
168
|
log(chalk.dim(` Port: ${info.port}`))
|
|
164
169
|
log()
|
|
165
170
|
log(chalk.dim(' API key format: o3=opus-4.5,o3-mini=sonnet-4.5:sk-ant-xxx'))
|
|
166
|
-
log()
|
|
167
171
|
|
|
168
172
|
resolve({
|
|
169
173
|
port: info.port,
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
// ============================================================================
|
|
4
4
|
|
|
5
5
|
import { Tunnel } from 'cloudflared'
|
|
6
|
+
import fs from 'node:fs/promises'
|
|
7
|
+
import os from 'node:os'
|
|
8
|
+
import path from 'node:path'
|
|
6
9
|
import type { TunnelProvider, TunnelInstance } from '../types'
|
|
7
10
|
|
|
8
11
|
export class CloudflareTunnelProvider implements TunnelProvider {
|
|
@@ -27,14 +30,21 @@ export class CloudflareTunnelProvider implements TunnelProvider {
|
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
// Anonymous tunnel using cloudflared npm package
|
|
30
|
-
const
|
|
33
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'sub-bridge-cloudflared-'))
|
|
34
|
+
const configPath = path.join(tmpDir, 'config.yml')
|
|
35
|
+
await fs.writeFile(configPath, 'no-autoupdate: true\n')
|
|
36
|
+
// Use HTTP/2 protocol for more reliable connections
|
|
37
|
+
const tunnel = Tunnel.quick(`http://localhost:${localPort}`, { '--config': configPath, '--protocol': 'http2' })
|
|
31
38
|
|
|
39
|
+
// Wait for URL event - the tunnel is usable once we have the URL
|
|
32
40
|
const url = await new Promise<string>((resolve, reject) => {
|
|
33
|
-
const timeout = setTimeout(() => reject(new Error('Tunnel timeout (
|
|
34
|
-
|
|
41
|
+
const timeout = setTimeout(() => reject(new Error('Tunnel timeout (60s)')), 60000)
|
|
42
|
+
|
|
43
|
+
tunnel.once('url', (url: string) => {
|
|
35
44
|
clearTimeout(timeout)
|
|
36
|
-
resolve(
|
|
45
|
+
resolve(url)
|
|
37
46
|
})
|
|
47
|
+
|
|
38
48
|
tunnel.once('error', (err: Error) => {
|
|
39
49
|
clearTimeout(timeout)
|
|
40
50
|
reject(err)
|
|
@@ -44,7 +54,10 @@ export class CloudflareTunnelProvider implements TunnelProvider {
|
|
|
44
54
|
return {
|
|
45
55
|
providerId: this.id,
|
|
46
56
|
publicUrl: url,
|
|
47
|
-
stop: () =>
|
|
57
|
+
stop: () => {
|
|
58
|
+
tunnel.stop()
|
|
59
|
+
void fs.rm(tmpDir, { recursive: true, force: true })
|
|
60
|
+
}
|
|
48
61
|
}
|
|
49
62
|
}
|
|
50
63
|
}
|
package/src/tunnel/registry.ts
CHANGED
|
@@ -3,6 +3,54 @@
|
|
|
3
3
|
// ============================================================================
|
|
4
4
|
|
|
5
5
|
import type { TunnelProvider, TunnelInstance, TunnelStatus, ProviderInfo } from './types'
|
|
6
|
+
import { SERVICE_IDENTIFIER } from '../utils/port'
|
|
7
|
+
|
|
8
|
+
function sleep(ms: number): Promise<void> {
|
|
9
|
+
return new Promise((resolve) => setTimeout(resolve, ms))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function verifyTunnelHealth(publicUrl: string, expectedPort: number): Promise<void> {
|
|
13
|
+
const baseUrl = publicUrl.replace(/\/$/, '')
|
|
14
|
+
const healthUrl = `${baseUrl}/health`
|
|
15
|
+
const maxAttempts = 12
|
|
16
|
+
let lastError: Error | null = null
|
|
17
|
+
|
|
18
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
19
|
+
const controller = new AbortController()
|
|
20
|
+
const timeout = setTimeout(() => controller.abort(), 3000)
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const response = await fetch(healthUrl, { signal: controller.signal })
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
throw new Error(`Tunnel check failed (HTTP ${response.status})`)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const data = await response.json() as { service?: string; port?: number }
|
|
29
|
+
if (data.service !== SERVICE_IDENTIFIER) {
|
|
30
|
+
throw new Error('Tunnel check failed (unexpected service)')
|
|
31
|
+
}
|
|
32
|
+
if (typeof data.port === 'number' && data.port !== expectedPort) {
|
|
33
|
+
throw new Error(`Tunnel check failed (unexpected port ${data.port})`)
|
|
34
|
+
}
|
|
35
|
+
return
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
38
|
+
lastError = new Error('Tunnel check timed out')
|
|
39
|
+
} else if (error instanceof Error) {
|
|
40
|
+
lastError = error
|
|
41
|
+
} else {
|
|
42
|
+
lastError = new Error(String(error))
|
|
43
|
+
}
|
|
44
|
+
if (attempt < maxAttempts) {
|
|
45
|
+
await sleep(400)
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`Tunnel check failed: ${lastError.message} (${healthUrl})`)
|
|
49
|
+
} finally {
|
|
50
|
+
clearTimeout(timeout)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
6
54
|
import {
|
|
7
55
|
CloudflareTunnelProvider,
|
|
8
56
|
NgrokTunnelProvider,
|
|
@@ -70,15 +118,38 @@ export class TunnelRegistry {
|
|
|
70
118
|
throw new Error(`Tunnel provider ${provider.name} is not available`)
|
|
71
119
|
}
|
|
72
120
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
121
|
+
const isQuickCloudflare = providerId === 'cloudflare' && !namedUrl
|
|
122
|
+
const maxAttempts = isQuickCloudflare ? 4 : 1
|
|
123
|
+
let lastError: Error | null = null
|
|
124
|
+
|
|
125
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
126
|
+
try {
|
|
127
|
+
this.lastError = null
|
|
128
|
+
this.activeTunnel = await provider.start(localPort, namedUrl)
|
|
129
|
+
this.startedAt = new Date().toISOString()
|
|
130
|
+
await verifyTunnelHealth(this.activeTunnel.publicUrl, localPort)
|
|
131
|
+
return this.getStatus()
|
|
132
|
+
} catch (error) {
|
|
133
|
+
lastError = error instanceof Error ? error : new Error(String(error))
|
|
134
|
+
this.lastError = lastError.message
|
|
135
|
+
if (this.activeTunnel) {
|
|
136
|
+
this.activeTunnel.stop()
|
|
137
|
+
this.activeTunnel = null
|
|
138
|
+
this.startedAt = null
|
|
139
|
+
}
|
|
140
|
+
if (attempt < maxAttempts) {
|
|
141
|
+
await sleep(600)
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
}
|
|
81
145
|
}
|
|
146
|
+
|
|
147
|
+
const message = lastError?.message || 'Unknown error'
|
|
148
|
+
throw new Error(
|
|
149
|
+
maxAttempts > 1
|
|
150
|
+
? `Failed to start tunnel after ${maxAttempts} attempts: ${message}`
|
|
151
|
+
: message
|
|
152
|
+
)
|
|
82
153
|
}
|
|
83
154
|
|
|
84
155
|
stop(): TunnelStatus {
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import fs from 'node:fs/promises'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
interface IngressRule {
|
|
6
|
+
hostname?: string
|
|
7
|
+
service?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function stripQuotes(value: string): string {
|
|
11
|
+
const trimmed = value.trim()
|
|
12
|
+
if (
|
|
13
|
+
(trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
14
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'"))
|
|
15
|
+
) {
|
|
16
|
+
return trimmed.slice(1, -1)
|
|
17
|
+
}
|
|
18
|
+
return trimmed
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function normalizeHostname(hostname: string): string {
|
|
22
|
+
return hostname.replace(/^https?:\/\//, '').split('/')[0]?.trim() || ''
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function parseIngressRules(content: string): IngressRule[] {
|
|
26
|
+
const entries: IngressRule[] = []
|
|
27
|
+
const lines = content.split(/\r?\n/)
|
|
28
|
+
let inIngress = false
|
|
29
|
+
let current: IngressRule | null = null
|
|
30
|
+
|
|
31
|
+
for (const rawLine of lines) {
|
|
32
|
+
const line = rawLine.replace(/\t/g, ' ')
|
|
33
|
+
const trimmed = line.trim()
|
|
34
|
+
if (!trimmed || trimmed.startsWith('#')) continue
|
|
35
|
+
|
|
36
|
+
if (!inIngress) {
|
|
37
|
+
if (trimmed === 'ingress:' || trimmed.startsWith('ingress:')) {
|
|
38
|
+
inIngress = true
|
|
39
|
+
}
|
|
40
|
+
continue
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const indent = line.match(/^\s*/)?.[0].length ?? 0
|
|
44
|
+
if (indent === 0 && !trimmed.startsWith('-')) {
|
|
45
|
+
break
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (trimmed.startsWith('-')) {
|
|
49
|
+
if (current && (current.hostname || current.service)) entries.push(current)
|
|
50
|
+
current = {}
|
|
51
|
+
const afterDash = trimmed.slice(1).trim()
|
|
52
|
+
if (afterDash.startsWith('hostname:')) {
|
|
53
|
+
current.hostname = stripQuotes(afterDash.slice('hostname:'.length))
|
|
54
|
+
} else if (afterDash.startsWith('service:')) {
|
|
55
|
+
current.service = stripQuotes(afterDash.slice('service:'.length))
|
|
56
|
+
}
|
|
57
|
+
continue
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!current) continue
|
|
61
|
+
|
|
62
|
+
if (trimmed.startsWith('hostname:')) {
|
|
63
|
+
current.hostname = stripQuotes(trimmed.slice('hostname:'.length))
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
if (trimmed.startsWith('service:')) {
|
|
67
|
+
current.service = stripQuotes(trimmed.slice('service:'.length))
|
|
68
|
+
continue
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (current && (current.hostname || current.service)) entries.push(current)
|
|
73
|
+
return entries
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function serviceMatchesPort(service: string, port: number): boolean {
|
|
77
|
+
if (!service || service.startsWith('http_status:')) return false
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const url = new URL(service)
|
|
81
|
+
const protocol = url.protocol
|
|
82
|
+
if (protocol !== 'http:' && protocol !== 'https:') return false
|
|
83
|
+
|
|
84
|
+
const resolvedPort = url.port
|
|
85
|
+
? Number(url.port)
|
|
86
|
+
: (protocol === 'https:' ? 443 : 80)
|
|
87
|
+
if (resolvedPort !== port) return false
|
|
88
|
+
|
|
89
|
+
const host = url.hostname
|
|
90
|
+
return host === 'localhost' || host === '127.0.0.1' || host === '0.0.0.0' || host === '::1'
|
|
91
|
+
} catch {
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function getCloudflaredHostnames(port: number): Promise<string[]> {
|
|
97
|
+
const home = os.homedir()
|
|
98
|
+
const configPaths = [
|
|
99
|
+
path.join(home, '.cloudflared', 'config.yml'),
|
|
100
|
+
path.join(home, '.cloudflared', 'config.yaml'),
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
const hostnames = new Set<string>()
|
|
104
|
+
|
|
105
|
+
for (const configPath of configPaths) {
|
|
106
|
+
try {
|
|
107
|
+
const content = await fs.readFile(configPath, 'utf8')
|
|
108
|
+
const rules = parseIngressRules(content)
|
|
109
|
+
for (const rule of rules) {
|
|
110
|
+
if (!rule.hostname || !rule.service) continue
|
|
111
|
+
if (!serviceMatchesPort(rule.service, port)) continue
|
|
112
|
+
const normalized = normalizeHostname(rule.hostname)
|
|
113
|
+
if (normalized) hostnames.add(normalized)
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return Array.from(hostnames)
|
|
121
|
+
}
|
|
@@ -21,15 +21,15 @@ export function buildStatusText(options: StatusTextOptions): string {
|
|
|
21
21
|
const lines = [
|
|
22
22
|
'Sub Bridge is running.',
|
|
23
23
|
'',
|
|
24
|
-
`Setup URL: ${baseUrl}`,
|
|
24
|
+
`Setup URL: ${baseUrl}?to=cursor`,
|
|
25
25
|
"Open this URL in your browser where you're logged into ChatGPT or Claude.",
|
|
26
26
|
'',
|
|
27
27
|
'To configure Cursor:',
|
|
28
28
|
'1. Authenticate with ChatGPT or Claude in the web UI',
|
|
29
29
|
'2. Copy the generated API key',
|
|
30
|
-
'3. In Cursor
|
|
31
|
-
' - Paste the API key',
|
|
32
|
-
` - Set Base URL
|
|
30
|
+
'3. In Cursor Settings ā Models ā API Keys',
|
|
31
|
+
' - Paste the API key from the web UI',
|
|
32
|
+
` - Set Base URL from the web UI`,
|
|
33
33
|
'',
|
|
34
34
|
...MODEL_MAPPING_LINES,
|
|
35
35
|
]
|
|
@@ -46,14 +46,11 @@ export function buildStatusText(options: StatusTextOptions): string {
|
|
|
46
46
|
'Sub Bridge server not reachable.',
|
|
47
47
|
'',
|
|
48
48
|
'To set up:',
|
|
49
|
-
`1. Open ${baseUrl} in your browser where you're logged into ChatGPT or Claude`,
|
|
49
|
+
`1. Open ${baseUrl}?to=cursor in your browser where you're logged into ChatGPT or Claude`,
|
|
50
50
|
'2. Authenticate and copy the generated API key',
|
|
51
|
-
`3. In Cursor: Settings ā Models ā API Keys, paste the key and set Base URL
|
|
51
|
+
`3. In Cursor: Settings ā Models ā API Keys, paste the key and set Base URL from the web UI`,
|
|
52
52
|
'',
|
|
53
53
|
...MODEL_MAPPING_LINES,
|
|
54
|
-
'',
|
|
55
|
-
'If you need a public URL, enable a tunnel in the web UI.',
|
|
56
|
-
'',
|
|
57
54
|
`Setup screenshot: ${baseUrl}/assets/setup.png`,
|
|
58
55
|
].join('\n')
|
|
59
56
|
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
interface PKCE {
|
|
2
|
-
verifier: string;
|
|
3
|
-
challenge: string;
|
|
4
|
-
}
|
|
5
|
-
interface TokenResponse {
|
|
6
|
-
access_token: string;
|
|
7
|
-
refresh_token: string;
|
|
8
|
-
expires_in: number;
|
|
9
|
-
}
|
|
10
|
-
interface ExchangeOptions {
|
|
11
|
-
persist?: boolean;
|
|
12
|
-
log?: boolean;
|
|
13
|
-
}
|
|
14
|
-
export declare function getAuthorizationUrl(pkce: PKCE): string;
|
|
15
|
-
export declare function exchangeCodeForTokens(code: string, verifier: string, options?: ExchangeOptions): Promise<TokenResponse>;
|
|
16
|
-
export declare function generateAuthSession(): Promise<{
|
|
17
|
-
authUrl: string;
|
|
18
|
-
sessionId: string;
|
|
19
|
-
}>;
|
|
20
|
-
export declare function handleOAuthCallback(code: string, sessionId: string): Promise<TokenResponse>;
|
|
21
|
-
export declare function login(): Promise<boolean>;
|
|
22
|
-
export declare function logout(): Promise<boolean>;
|
|
23
|
-
export {};
|
|
24
|
-
//# sourceMappingURL=oauth-flow.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-flow.d.ts","sourceRoot":"","sources":["../../src/auth/oauth-flow.ts"],"names":[],"mappings":"AAQA,UAAU,IAAI;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,UAAU,aAAa;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,UAAU,eAAe;IACvB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AAiBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAetD;AAuCD,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC,CAuCxB;AAGD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC;IACnD,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB,CAAC,CASD;AAGD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,CAAC,CAMxB;AAED,wBAAsB,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAgB9C;AAED,wBAAsB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAS/C"}
|
package/dist/auth/oauth-flow.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.getAuthorizationUrl = getAuthorizationUrl;
|
|
40
|
-
exports.exchangeCodeForTokens = exchangeCodeForTokens;
|
|
41
|
-
exports.generateAuthSession = generateAuthSession;
|
|
42
|
-
exports.handleOAuthCallback = handleOAuthCallback;
|
|
43
|
-
exports.login = login;
|
|
44
|
-
exports.logout = logout;
|
|
45
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
46
|
-
const authManager = __importStar(require("./oauth-manager"));
|
|
47
|
-
const CLIENT_ID = process.env.ANTHROPIC_OAUTH_CLIENT_ID ||
|
|
48
|
-
'9d1c250a-e61b-44d9-88ed-5944d1962f5e';
|
|
49
|
-
const REDIRECT_URI = 'https://console.anthropic.com/oauth/code/callback';
|
|
50
|
-
function splitCodeState(code) {
|
|
51
|
-
const splits = code.split('#');
|
|
52
|
-
return { code: splits[0], state: splits[1] || undefined };
|
|
53
|
-
}
|
|
54
|
-
function generatePKCE() {
|
|
55
|
-
const verifier = crypto_1.default.randomBytes(32).toString('base64url');
|
|
56
|
-
const challenge = crypto_1.default
|
|
57
|
-
.createHash('sha256')
|
|
58
|
-
.update(verifier)
|
|
59
|
-
.digest('base64url');
|
|
60
|
-
return { verifier, challenge };
|
|
61
|
-
}
|
|
62
|
-
function getAuthorizationUrl(pkce) {
|
|
63
|
-
const authUrl = new URL('https://claude.ai/oauth/authorize');
|
|
64
|
-
authUrl.searchParams.set('code', 'true');
|
|
65
|
-
authUrl.searchParams.set('client_id', CLIENT_ID);
|
|
66
|
-
authUrl.searchParams.set('response_type', 'code');
|
|
67
|
-
authUrl.searchParams.set('redirect_uri', REDIRECT_URI);
|
|
68
|
-
authUrl.searchParams.set('scope', 'org:create_api_key user:profile user:inference');
|
|
69
|
-
authUrl.searchParams.set('code_challenge', pkce.challenge);
|
|
70
|
-
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
71
|
-
authUrl.searchParams.set('state', pkce.verifier);
|
|
72
|
-
return authUrl.toString();
|
|
73
|
-
}
|
|
74
|
-
async function startAuthFlow() {
|
|
75
|
-
const pkce = generatePKCE();
|
|
76
|
-
const authUrl = getAuthorizationUrl(pkce);
|
|
77
|
-
console.log('\nš OAuth Authentication Required');
|
|
78
|
-
console.log('Please visit the following URL to authenticate:');
|
|
79
|
-
console.log(`\n${authUrl}\n`);
|
|
80
|
-
console.log('After authentication, you will get a code.');
|
|
81
|
-
console.log('Please paste the entire code here and press Enter:\n');
|
|
82
|
-
// Read code from stdin
|
|
83
|
-
const code = await readCodeFromStdin();
|
|
84
|
-
if (!code) {
|
|
85
|
-
throw new Error('No code provided');
|
|
86
|
-
}
|
|
87
|
-
// Exchange code for tokens
|
|
88
|
-
return await exchangeCodeForTokens(code, pkce.verifier);
|
|
89
|
-
}
|
|
90
|
-
async function readCodeFromStdin() {
|
|
91
|
-
return new Promise((resolve) => {
|
|
92
|
-
let code = '';
|
|
93
|
-
process.stdin.setEncoding('utf8');
|
|
94
|
-
process.stdin.resume();
|
|
95
|
-
process.stdin.on('data', (chunk) => {
|
|
96
|
-
code += chunk;
|
|
97
|
-
if (code.includes('\n')) {
|
|
98
|
-
process.stdin.pause();
|
|
99
|
-
resolve(code.trim());
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
async function exchangeCodeForTokens(code, verifier, options = {}) {
|
|
105
|
-
const { code: authCode, state } = splitCodeState(code);
|
|
106
|
-
const response = await fetch('https://console.anthropic.com/v1/oauth/token', {
|
|
107
|
-
method: 'POST',
|
|
108
|
-
headers: {
|
|
109
|
-
'Content-Type': 'application/json',
|
|
110
|
-
},
|
|
111
|
-
body: JSON.stringify({
|
|
112
|
-
code: authCode,
|
|
113
|
-
state: state || verifier,
|
|
114
|
-
grant_type: 'authorization_code',
|
|
115
|
-
client_id: CLIENT_ID,
|
|
116
|
-
redirect_uri: REDIRECT_URI,
|
|
117
|
-
code_verifier: verifier,
|
|
118
|
-
}),
|
|
119
|
-
});
|
|
120
|
-
if (!response.ok) {
|
|
121
|
-
const error = await response.text();
|
|
122
|
-
throw new Error(`Failed to exchange code: ${error}`);
|
|
123
|
-
}
|
|
124
|
-
const data = (await response.json());
|
|
125
|
-
const shouldPersist = options.persist ?? true;
|
|
126
|
-
const shouldLog = options.log ?? true;
|
|
127
|
-
if (shouldPersist) {
|
|
128
|
-
await authManager.set({
|
|
129
|
-
type: 'oauth',
|
|
130
|
-
refresh: data.refresh_token,
|
|
131
|
-
access: data.access_token,
|
|
132
|
-
expires: Date.now() + data.expires_in * 1000,
|
|
133
|
-
});
|
|
134
|
-
if (shouldLog) {
|
|
135
|
-
console.log('ā
OAuth tokens saved successfully!');
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return data;
|
|
139
|
-
}
|
|
140
|
-
// New function to generate auth URL and store PKCE verifier
|
|
141
|
-
async function generateAuthSession() {
|
|
142
|
-
const pkce = generatePKCE();
|
|
143
|
-
const authUrl = getAuthorizationUrl(pkce);
|
|
144
|
-
// Store PKCE verifier temporarily (in production, use a proper session store)
|
|
145
|
-
// For now, we'll use the verifier as the session ID
|
|
146
|
-
const sessionId = pkce.verifier;
|
|
147
|
-
return { authUrl, sessionId };
|
|
148
|
-
}
|
|
149
|
-
// New function to handle OAuth callback
|
|
150
|
-
async function handleOAuthCallback(code, sessionId) {
|
|
151
|
-
// In production, retrieve the verifier from session store
|
|
152
|
-
// For now, we use the sessionId as the verifier
|
|
153
|
-
const verifier = sessionId;
|
|
154
|
-
return await exchangeCodeForTokens(code, verifier);
|
|
155
|
-
}
|
|
156
|
-
async function login() {
|
|
157
|
-
try {
|
|
158
|
-
// Check if we already have valid credentials
|
|
159
|
-
const existing = await authManager.get();
|
|
160
|
-
if (existing && existing.access && existing.expires > Date.now()) {
|
|
161
|
-
console.log('ā
Valid OAuth credentials already exist');
|
|
162
|
-
return true;
|
|
163
|
-
}
|
|
164
|
-
// Start OAuth flow
|
|
165
|
-
await startAuthFlow();
|
|
166
|
-
return true;
|
|
167
|
-
}
|
|
168
|
-
catch (error) {
|
|
169
|
-
console.error('OAuth login failed:', error);
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
async function logout() {
|
|
174
|
-
try {
|
|
175
|
-
await authManager.remove();
|
|
176
|
-
console.log('ā
OAuth credentials removed');
|
|
177
|
-
return true;
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
console.error('Logout failed:', error);
|
|
181
|
-
return false;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
//# sourceMappingURL=oauth-flow.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-flow.js","sourceRoot":"","sources":["../../src/auth/oauth-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
interface OAuthCredentials {
|
|
2
|
-
type: 'oauth';
|
|
3
|
-
refresh: string;
|
|
4
|
-
access: string;
|
|
5
|
-
expires: number;
|
|
6
|
-
}
|
|
7
|
-
declare function get(): Promise<OAuthCredentials | null>;
|
|
8
|
-
declare function set(credentials: OAuthCredentials): Promise<boolean>;
|
|
9
|
-
declare function remove(): Promise<boolean>;
|
|
10
|
-
declare function getAll(): Promise<Record<string, OAuthCredentials>>;
|
|
11
|
-
declare function getAccessToken(): Promise<string | null>;
|
|
12
|
-
export { get, set, remove, getAll, getAccessToken };
|
|
13
|
-
//# sourceMappingURL=oauth-manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-manager.d.ts","sourceRoot":"","sources":["../../src/auth/oauth-manager.ts"],"names":[],"mappings":"AAAA,UAAU,gBAAgB;IACxB,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,iBAAe,GAAG,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAErD;AAED,iBAAe,GAAG,CAAC,WAAW,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAElE;AAED,iBAAe,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAExC;AAED,iBAAe,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAEjE;AAED,iBAAe,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAItD;AAED,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA"}
|