sub-bridge 1.0.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/.cursor/commands/mcp-only.md +1 -0
- package/.github/workflows/npm-publish.yml +33 -0
- package/.github/workflows/pages.yml +40 -0
- package/.github/workflows/release-please.yml +21 -0
- package/.release-please-manifest.json +3 -0
- package/CHANGELOG.md +8 -0
- package/DEVELOPMENT.md +31 -0
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/api/index.ts +12 -0
- package/bun.lock +102 -0
- package/dist/auth/oauth-flow.d.ts +24 -0
- package/dist/auth/oauth-flow.d.ts.map +1 -0
- package/dist/auth/oauth-flow.js +184 -0
- package/dist/auth/oauth-flow.js.map +1 -0
- package/dist/auth/oauth-manager.d.ts +13 -0
- package/dist/auth/oauth-manager.d.ts.map +1 -0
- package/dist/auth/oauth-manager.js +25 -0
- package/dist/auth/oauth-manager.js.map +1 -0
- package/dist/auth/provider.d.ts +42 -0
- package/dist/auth/provider.d.ts.map +1 -0
- package/dist/auth/provider.js +270 -0
- package/dist/auth/provider.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +91 -0
- package/dist/cli.js.map +1 -0
- package/dist/mcp/proxy.d.ts +16 -0
- package/dist/mcp/proxy.d.ts.map +1 -0
- package/dist/mcp/proxy.js +85 -0
- package/dist/mcp/proxy.js.map +1 -0
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +50 -0
- package/dist/mcp.js.map +1 -0
- package/dist/routes/auth.d.ts +6 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +149 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/chat.d.ts +6 -0
- package/dist/routes/chat.d.ts.map +1 -0
- package/dist/routes/chat.js +808 -0
- package/dist/routes/chat.js.map +1 -0
- package/dist/routes/tunnels.d.ts +7 -0
- package/dist/routes/tunnels.d.ts.map +1 -0
- package/dist/routes/tunnels.js +44 -0
- package/dist/routes/tunnels.js.map +1 -0
- package/dist/server.d.ts +25 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +157 -0
- package/dist/server.js.map +1 -0
- package/dist/tunnel/providers/cloudflare.d.ts +9 -0
- package/dist/tunnel/providers/cloudflare.d.ts.map +1 -0
- package/dist/tunnel/providers/cloudflare.js +47 -0
- package/dist/tunnel/providers/cloudflare.js.map +1 -0
- package/dist/tunnel/providers/index.d.ts +4 -0
- package/dist/tunnel/providers/index.d.ts.map +1 -0
- package/dist/tunnel/providers/index.js +13 -0
- package/dist/tunnel/providers/index.js.map +1 -0
- package/dist/tunnel/providers/ngrok.d.ts +10 -0
- package/dist/tunnel/providers/ngrok.d.ts.map +1 -0
- package/dist/tunnel/providers/ngrok.js +52 -0
- package/dist/tunnel/providers/ngrok.js.map +1 -0
- package/dist/tunnel/providers/tailscale.d.ts +10 -0
- package/dist/tunnel/providers/tailscale.d.ts.map +1 -0
- package/dist/tunnel/providers/tailscale.js +48 -0
- package/dist/tunnel/providers/tailscale.js.map +1 -0
- package/dist/tunnel/registry.d.ts +14 -0
- package/dist/tunnel/registry.d.ts.map +1 -0
- package/dist/tunnel/registry.js +86 -0
- package/dist/tunnel/registry.js.map +1 -0
- package/dist/tunnel/types.d.ts +26 -0
- package/dist/tunnel/types.d.ts.map +1 -0
- package/dist/tunnel/types.js +6 -0
- package/dist/tunnel/types.js.map +1 -0
- package/dist/tunnel/utils.d.ts +18 -0
- package/dist/tunnel/utils.d.ts.map +1 -0
- package/dist/tunnel/utils.js +57 -0
- package/dist/tunnel/utils.js.map +1 -0
- package/dist/types.d.ts +52 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/anthropic-to-openai-converter.d.ts +103 -0
- package/dist/utils/anthropic-to-openai-converter.d.ts.map +1 -0
- package/dist/utils/anthropic-to-openai-converter.js +376 -0
- package/dist/utils/anthropic-to-openai-converter.js.map +1 -0
- package/dist/utils/chat-to-responses.d.ts +59 -0
- package/dist/utils/chat-to-responses.d.ts.map +1 -0
- package/dist/utils/chat-to-responses.js +395 -0
- package/dist/utils/chat-to-responses.js.map +1 -0
- package/dist/utils/chatgpt-instructions.d.ts +3 -0
- package/dist/utils/chatgpt-instructions.d.ts.map +1 -0
- package/dist/utils/chatgpt-instructions.js +12 -0
- package/dist/utils/chatgpt-instructions.js.map +1 -0
- package/dist/utils/cli-args.d.ts +3 -0
- package/dist/utils/cli-args.d.ts.map +1 -0
- package/dist/utils/cli-args.js +10 -0
- package/dist/utils/cli-args.js.map +1 -0
- package/dist/utils/cors-bypass.d.ts +4 -0
- package/dist/utils/cors-bypass.d.ts.map +1 -0
- package/dist/utils/cors-bypass.js +30 -0
- package/dist/utils/cors-bypass.js.map +1 -0
- package/dist/utils/cursor-byok-bypass.d.ts +37 -0
- package/dist/utils/cursor-byok-bypass.d.ts.map +1 -0
- package/dist/utils/cursor-byok-bypass.js +53 -0
- package/dist/utils/cursor-byok-bypass.js.map +1 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +192 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/port.d.ts +27 -0
- package/dist/utils/port.d.ts.map +1 -0
- package/dist/utils/port.js +78 -0
- package/dist/utils/port.js.map +1 -0
- package/dist/utils/setup-instructions.d.ts +10 -0
- package/dist/utils/setup-instructions.d.ts.map +1 -0
- package/dist/utils/setup-instructions.js +49 -0
- package/dist/utils/setup-instructions.js.map +1 -0
- package/env.example +25 -0
- package/index.html +992 -0
- package/package.json +57 -0
- package/public/.nojekyll +0 -0
- package/public/assets/chat.png +0 -0
- package/public/assets/demo.gif +0 -0
- package/public/assets/demo.mp4 +0 -0
- package/public/assets/setup.png +0 -0
- package/public/assets/ui.png +0 -0
- package/public/index.html +292 -0
- package/release-please-config.json +10 -0
- package/src/auth/provider.ts +412 -0
- package/src/cli.ts +97 -0
- package/src/mcp/proxy.ts +64 -0
- package/src/mcp.ts +56 -0
- package/src/oauth/authorize.ts +270 -0
- package/src/oauth/crypto.ts +198 -0
- package/src/oauth/dcr.ts +129 -0
- package/src/oauth/metadata.ts +40 -0
- package/src/oauth/token.ts +173 -0
- package/src/routes/auth.ts +149 -0
- package/src/routes/chat.ts +983 -0
- package/src/routes/oauth.ts +220 -0
- package/src/routes/tunnels.ts +45 -0
- package/src/server.ts +204 -0
- package/src/tunnel/providers/cloudflare.ts +50 -0
- package/src/tunnel/providers/index.ts +7 -0
- package/src/tunnel/providers/ngrok.ts +56 -0
- package/src/tunnel/providers/tailscale.ts +50 -0
- package/src/tunnel/registry.ts +96 -0
- package/src/tunnel/types.ts +32 -0
- package/src/tunnel/utils.ts +59 -0
- package/src/types.ts +55 -0
- package/src/utils/anthropic-to-openai-converter.ts +578 -0
- package/src/utils/chat-to-responses.ts +512 -0
- package/src/utils/chatgpt-instructions.ts +7 -0
- package/src/utils/cli-args.ts +8 -0
- package/src/utils/cors-bypass.ts +39 -0
- package/src/utils/cursor-byok-bypass.ts +56 -0
- package/src/utils/logger.ts +174 -0
- package/src/utils/port.ts +99 -0
- package/src/utils/setup-instructions.ts +59 -0
- package/tsconfig.json +22 -0
- package/vercel.json +20 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Tunnel Registry - Manages providers and active tunnel
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import type { TunnelProvider, TunnelInstance, TunnelStatus, ProviderInfo } from './types'
|
|
6
|
+
import {
|
|
7
|
+
CloudflareTunnelProvider,
|
|
8
|
+
NgrokTunnelProvider,
|
|
9
|
+
TailscaleTunnelProvider,
|
|
10
|
+
} from './providers'
|
|
11
|
+
|
|
12
|
+
export class TunnelRegistry {
|
|
13
|
+
private providers: Map<string, TunnelProvider> = new Map()
|
|
14
|
+
private activeTunnel: TunnelInstance | null = null
|
|
15
|
+
private startedAt: string | null = null
|
|
16
|
+
private lastError: string | null = null
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
const allProviders: TunnelProvider[] = [
|
|
20
|
+
new CloudflareTunnelProvider(),
|
|
21
|
+
new NgrokTunnelProvider(),
|
|
22
|
+
new TailscaleTunnelProvider(),
|
|
23
|
+
]
|
|
24
|
+
for (const provider of allProviders) {
|
|
25
|
+
this.providers.set(provider.id, provider)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async getProviders(): Promise<ProviderInfo[]> {
|
|
30
|
+
const results: ProviderInfo[] = []
|
|
31
|
+
for (const [id, provider] of this.providers) {
|
|
32
|
+
results.push({
|
|
33
|
+
id,
|
|
34
|
+
name: provider.name,
|
|
35
|
+
available: await provider.isAvailable(),
|
|
36
|
+
supportsNamedTunnels: provider.supportsNamedTunnels,
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
return results
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getStatus(): TunnelStatus {
|
|
43
|
+
if (this.activeTunnel) {
|
|
44
|
+
return {
|
|
45
|
+
active: true,
|
|
46
|
+
providerId: this.activeTunnel.providerId,
|
|
47
|
+
publicUrl: this.activeTunnel.publicUrl,
|
|
48
|
+
startedAt: this.startedAt || undefined,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
active: false,
|
|
53
|
+
error: this.lastError || undefined,
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async start(providerId: string, localPort: number, namedUrl?: string): Promise<TunnelStatus> {
|
|
58
|
+
// Stop existing tunnel if any
|
|
59
|
+
if (this.activeTunnel) {
|
|
60
|
+
this.activeTunnel.stop()
|
|
61
|
+
this.activeTunnel = null
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const provider = this.providers.get(providerId)
|
|
65
|
+
if (!provider) {
|
|
66
|
+
throw new Error(`Unknown tunnel provider: ${providerId}`)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!await provider.isAvailable()) {
|
|
70
|
+
throw new Error(`Tunnel provider ${provider.name} is not available`)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
this.lastError = null
|
|
75
|
+
this.activeTunnel = await provider.start(localPort, namedUrl)
|
|
76
|
+
this.startedAt = new Date().toISOString()
|
|
77
|
+
return this.getStatus()
|
|
78
|
+
} catch (error) {
|
|
79
|
+
this.lastError = error instanceof Error ? error.message : String(error)
|
|
80
|
+
throw error
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
stop(): TunnelStatus {
|
|
85
|
+
if (this.activeTunnel) {
|
|
86
|
+
this.activeTunnel.stop()
|
|
87
|
+
this.activeTunnel = null
|
|
88
|
+
this.startedAt = null
|
|
89
|
+
}
|
|
90
|
+
return this.getStatus()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getPublicUrl(): string | null {
|
|
94
|
+
return this.activeTunnel?.publicUrl || null
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Tunnel Types
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
export interface TunnelProvider {
|
|
6
|
+
id: string
|
|
7
|
+
name: string
|
|
8
|
+
supportsNamedTunnels: boolean
|
|
9
|
+
isAvailable(): Promise<boolean>
|
|
10
|
+
start(localPort: number, namedUrl?: string): Promise<TunnelInstance>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface TunnelInstance {
|
|
14
|
+
providerId: string
|
|
15
|
+
publicUrl: string
|
|
16
|
+
stop(): void
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface TunnelStatus {
|
|
20
|
+
active: boolean
|
|
21
|
+
providerId?: string
|
|
22
|
+
publicUrl?: string
|
|
23
|
+
startedAt?: string
|
|
24
|
+
error?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ProviderInfo {
|
|
28
|
+
id: string
|
|
29
|
+
name: string
|
|
30
|
+
available: boolean
|
|
31
|
+
supportsNamedTunnels: boolean
|
|
32
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Tunnel Utilities
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { exec, spawn, ChildProcess } from 'child_process'
|
|
6
|
+
import { promisify } from 'util'
|
|
7
|
+
|
|
8
|
+
const execAsync = promisify(exec)
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Check if a binary exists in PATH
|
|
12
|
+
*/
|
|
13
|
+
export async function binaryExists(binary: string): Promise<boolean> {
|
|
14
|
+
try {
|
|
15
|
+
const cmd = process.platform === 'win32' ? `where ${binary}` : `which ${binary}`
|
|
16
|
+
await execAsync(cmd)
|
|
17
|
+
return true
|
|
18
|
+
} catch {
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Spawn a tunnel process with standard configuration
|
|
25
|
+
*/
|
|
26
|
+
export function spawnTunnelProcess(command: string, args: string[]): ChildProcess {
|
|
27
|
+
return spawn(command, args, { stdio: ['ignore', 'pipe', 'pipe'] })
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Poll a function until it returns a value or times out
|
|
32
|
+
*/
|
|
33
|
+
export async function pollUntil<T>(
|
|
34
|
+
fn: () => Promise<T | null>,
|
|
35
|
+
timeout: number = 30000,
|
|
36
|
+
interval: number = 500
|
|
37
|
+
): Promise<T> {
|
|
38
|
+
const start = Date.now()
|
|
39
|
+
|
|
40
|
+
while (Date.now() - start < timeout) {
|
|
41
|
+
try {
|
|
42
|
+
const result = await fn()
|
|
43
|
+
if (result !== null) return result
|
|
44
|
+
} catch {
|
|
45
|
+
// Continue polling on error
|
|
46
|
+
}
|
|
47
|
+
await new Promise(r => setTimeout(r, interval))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
throw new Error('Polling timeout')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Execute shell command and return parsed JSON output
|
|
55
|
+
*/
|
|
56
|
+
export async function execJson<T = any>(command: string): Promise<T> {
|
|
57
|
+
const { stdout } = await execAsync(command)
|
|
58
|
+
return JSON.parse(stdout)
|
|
59
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Shared type definitions
|
|
2
|
+
|
|
3
|
+
export interface AnthropicRequestBody {
|
|
4
|
+
system?: Array<{ type: string; text: string }>
|
|
5
|
+
messages?: Array<any>
|
|
6
|
+
metadata?: {
|
|
7
|
+
user_id?: string
|
|
8
|
+
}
|
|
9
|
+
stream?: boolean
|
|
10
|
+
model: string
|
|
11
|
+
[key: string]: unknown
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface AnthropicResponse {
|
|
15
|
+
id?: string
|
|
16
|
+
model?: string
|
|
17
|
+
stop_reason?: string | null
|
|
18
|
+
content?: Array<{
|
|
19
|
+
type: 'text' | 'tool_use'
|
|
20
|
+
text?: string
|
|
21
|
+
id?: string
|
|
22
|
+
name?: string
|
|
23
|
+
input?: unknown
|
|
24
|
+
}>
|
|
25
|
+
usage?: {
|
|
26
|
+
input_tokens: number
|
|
27
|
+
output_tokens: number
|
|
28
|
+
cache_creation_input_tokens?: number
|
|
29
|
+
cache_read_input_tokens?: number
|
|
30
|
+
}
|
|
31
|
+
[key: string]: unknown
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ErrorResponse {
|
|
35
|
+
error: string
|
|
36
|
+
message?: string
|
|
37
|
+
details?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SuccessResponse {
|
|
41
|
+
success: boolean
|
|
42
|
+
message: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ModelInfo {
|
|
46
|
+
id: string
|
|
47
|
+
object: 'model'
|
|
48
|
+
created: number
|
|
49
|
+
owned_by: string
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ModelsListResponse {
|
|
53
|
+
object: 'list'
|
|
54
|
+
data: ModelInfo[]
|
|
55
|
+
}
|