Adding transportType to API
This commit is contained in:
parent
ef08e97a5f
commit
b326e36ccc
6 changed files with 106 additions and 17 deletions
|
|
@ -1,3 +1,5 @@
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
*.md
|
*.md
|
||||||
examples
|
.wrangler
|
||||||
|
.vscode
|
||||||
|
test-results
|
||||||
|
|
|
||||||
4
AGENT.md
4
AGENT.md
|
|
@ -27,6 +27,10 @@
|
||||||
- Log errors with appropriate levels (debug, info, warn, error)
|
- Log errors with appropriate levels (debug, info, warn, error)
|
||||||
- Defensive error handling with specific error types when available
|
- Defensive error handling with specific error types when available
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
- **Commit changes frequently** after each logical change or debugging step
|
||||||
|
- Use descriptive commit messages that explain what was changed and why
|
||||||
|
|
||||||
### React Patterns
|
### React Patterns
|
||||||
- Use React hooks with useRef for mutable values
|
- Use React hooks with useRef for mutable values
|
||||||
- Stable callbacks with useCallback and appropriate dependencies
|
- Stable callbacks with useCallback and appropriate dependencies
|
||||||
|
|
@ -24,16 +24,17 @@
|
||||||
"dev": "tsup --watch",
|
"dev": "tsup --watch",
|
||||||
"build": "tsup",
|
"build": "tsup",
|
||||||
"check": "prettier --check . && tsc",
|
"check": "prettier --check . && tsc",
|
||||||
|
"prettier:fix": "prettier --write .",
|
||||||
"fix:oranda": "sed -i 's/```tsx/```ts/g' README.md",
|
"fix:oranda": "sed -i 's/```tsx/```ts/g' README.md",
|
||||||
"build:site": "npx @axodotdev/oranda build",
|
"build:site": "npx @axodotdev/oranda build",
|
||||||
"deploy:site": "npx wrangler deploy"
|
"deploy:site": "npx wrangler deploy"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "^1.11.0",
|
|
||||||
"strict-url-sanitise": "^0.0.1"
|
"strict-url-sanitise": "^0.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@axodotdev/oranda": "^0.6.5",
|
"@axodotdev/oranda": "^0.6.5",
|
||||||
|
"@modelcontextprotocol/sdk": "^1.13.1",
|
||||||
"@types/react": "^19.0.12",
|
"@types/react": "^19.0.12",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
|
|
|
||||||
42
pnpm-lock.yaml
generated
42
pnpm-lock.yaml
generated
|
|
@ -18,6 +18,9 @@ importers:
|
||||||
'@axodotdev/oranda':
|
'@axodotdev/oranda':
|
||||||
specifier: ^0.6.5
|
specifier: ^0.6.5
|
||||||
version: 0.6.5
|
version: 0.6.5
|
||||||
|
'@modelcontextprotocol/sdk':
|
||||||
|
specifier: ^1.13.1
|
||||||
|
version: 1.13.1
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^19.0.12
|
specifier: ^19.0.12
|
||||||
version: 19.0.12
|
version: 19.0.12
|
||||||
|
|
@ -535,8 +538,8 @@ packages:
|
||||||
'@jridgewell/trace-mapping@0.3.9':
|
'@jridgewell/trace-mapping@0.3.9':
|
||||||
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.11.0':
|
'@modelcontextprotocol/sdk@1.13.1':
|
||||||
resolution: {integrity: sha512-k/1pb70eD638anoi0e8wUGAlbMJXyvdV4p62Ko+EZ7eBe1xMx8Uhak1R5DgfoofsK5IBBnRwsYGTaLZl+6/+RQ==}
|
resolution: {integrity: sha512-8q6+9aF0yA39/qWT/uaIj6zTpC+Qu07DnN/lb9mjoquCJsAh6l3HyYqc9O3t2j7GilseOQOQimLg7W3By6jqvg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
'@pkgjs/parseargs@0.11.0':
|
'@pkgjs/parseargs@0.11.0':
|
||||||
|
|
@ -657,6 +660,9 @@ packages:
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
ajv@6.12.6:
|
||||||
|
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
||||||
|
|
||||||
ansi-regex@5.0.1:
|
ansi-regex@5.0.1:
|
||||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
@ -916,6 +922,12 @@ packages:
|
||||||
exsolve@1.0.5:
|
exsolve@1.0.5:
|
||||||
resolution: {integrity: sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==}
|
resolution: {integrity: sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==}
|
||||||
|
|
||||||
|
fast-deep-equal@3.1.3:
|
||||||
|
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||||
|
|
||||||
|
fast-json-stable-stringify@2.1.0:
|
||||||
|
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
|
||||||
|
|
||||||
fdir@6.4.3:
|
fdir@6.4.3:
|
||||||
resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==}
|
resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -1041,6 +1053,9 @@ packages:
|
||||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
json-schema-traverse@0.4.1:
|
||||||
|
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
|
||||||
|
|
||||||
lilconfig@3.1.3:
|
lilconfig@3.1.3:
|
||||||
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
|
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|
@ -1459,6 +1474,9 @@ packages:
|
||||||
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
uri-js@4.4.1:
|
||||||
|
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||||
|
|
||||||
utils-merge@1.0.1:
|
utils-merge@1.0.1:
|
||||||
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
||||||
engines: {node: '>= 0.4.0'}
|
engines: {node: '>= 0.4.0'}
|
||||||
|
|
@ -1846,8 +1864,9 @@ snapshots:
|
||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.0
|
'@jridgewell/sourcemap-codec': 1.5.0
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.11.0':
|
'@modelcontextprotocol/sdk@1.13.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
ajv: 6.12.6
|
||||||
content-type: 1.0.5
|
content-type: 1.0.5
|
||||||
cors: 2.8.5
|
cors: 2.8.5
|
||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
|
|
@ -1936,6 +1955,13 @@ snapshots:
|
||||||
|
|
||||||
acorn@8.14.0: {}
|
acorn@8.14.0: {}
|
||||||
|
|
||||||
|
ajv@6.12.6:
|
||||||
|
dependencies:
|
||||||
|
fast-deep-equal: 3.1.3
|
||||||
|
fast-json-stable-stringify: 2.1.0
|
||||||
|
json-schema-traverse: 0.4.1
|
||||||
|
uri-js: 4.4.1
|
||||||
|
|
||||||
ansi-regex@5.0.1: {}
|
ansi-regex@5.0.1: {}
|
||||||
|
|
||||||
ansi-regex@6.1.0: {}
|
ansi-regex@6.1.0: {}
|
||||||
|
|
@ -2238,6 +2264,10 @@ snapshots:
|
||||||
|
|
||||||
exsolve@1.0.5: {}
|
exsolve@1.0.5: {}
|
||||||
|
|
||||||
|
fast-deep-equal@3.1.3: {}
|
||||||
|
|
||||||
|
fast-json-stable-stringify@2.1.0: {}
|
||||||
|
|
||||||
fdir@6.4.3(picomatch@4.0.2):
|
fdir@6.4.3(picomatch@4.0.2):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
picomatch: 4.0.2
|
picomatch: 4.0.2
|
||||||
|
|
@ -2365,6 +2395,8 @@ snapshots:
|
||||||
|
|
||||||
joycon@3.1.1: {}
|
joycon@3.1.1: {}
|
||||||
|
|
||||||
|
json-schema-traverse@0.4.1: {}
|
||||||
|
|
||||||
lilconfig@3.1.3: {}
|
lilconfig@3.1.3: {}
|
||||||
|
|
||||||
lines-and-columns@1.2.4: {}
|
lines-and-columns@1.2.4: {}
|
||||||
|
|
@ -2802,6 +2834,10 @@ snapshots:
|
||||||
|
|
||||||
unpipe@1.0.0: {}
|
unpipe@1.0.0: {}
|
||||||
|
|
||||||
|
uri-js@4.4.1:
|
||||||
|
dependencies:
|
||||||
|
punycode: 2.3.1
|
||||||
|
|
||||||
utils-merge@1.0.1: {}
|
utils-merge@1.0.1: {}
|
||||||
|
|
||||||
vary@1.1.2: {}
|
vary@1.1.2: {}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ export type UseMcpOptions = {
|
||||||
autoReconnect?: boolean | number
|
autoReconnect?: boolean | number
|
||||||
/** Popup window features string (dimensions and behavior) for OAuth */
|
/** Popup window features string (dimensions and behavior) for OAuth */
|
||||||
popupFeatures?: string
|
popupFeatures?: string
|
||||||
|
/** Transport type preference: 'auto' (HTTP with SSE fallback), 'http' (HTTP only), 'sse' (SSE only) */
|
||||||
|
transportType?: 'auto' | 'http' | 'sse'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UseMcpResult = {
|
export type UseMcpResult = {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
|
||||||
debug = false,
|
debug = false,
|
||||||
autoRetry = false,
|
autoRetry = false,
|
||||||
autoReconnect = DEFAULT_RECONNECT_DELAY,
|
autoReconnect = DEFAULT_RECONNECT_DELAY,
|
||||||
|
transportType = 'auto',
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
const [state, setState] = useState<UseMcpResult['state']>('discovering')
|
const [state, setState] = useState<UseMcpResult['state']>('discovering')
|
||||||
|
|
@ -190,20 +191,36 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
|
||||||
|
|
||||||
const commonOptions: SSEClientTransportOptions = {
|
const commonOptions: SSEClientTransportOptions = {
|
||||||
authProvider: authProviderRef.current,
|
authProvider: authProviderRef.current,
|
||||||
requestInit: { headers: customHeaders },
|
requestInit: {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json, text/event-stream',
|
||||||
|
...customHeaders,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// Sanitize the URL to prevent XSS attacks from malicious server URLs
|
// Sanitize the URL to prevent XSS attacks from malicious server URLs
|
||||||
const sanitizedUrl = sanitizeUrl(url)
|
const sanitizedUrl = sanitizeUrl(url)
|
||||||
const targetUrl = new URL(sanitizedUrl)
|
const targetUrl = new URL(sanitizedUrl)
|
||||||
|
|
||||||
|
addLog('debug', `Creating ${transportType.toUpperCase()} transport for URL: ${targetUrl.toString()}`)
|
||||||
|
addLog('debug', `Transport options:`, {
|
||||||
|
authProvider: !!authProviderRef.current,
|
||||||
|
headers: customHeaders,
|
||||||
|
url: targetUrl.toString(),
|
||||||
|
})
|
||||||
|
|
||||||
if (transportType === 'http') {
|
if (transportType === 'http') {
|
||||||
|
addLog('debug', 'Creating StreamableHTTPClientTransport...')
|
||||||
transportInstance = new StreamableHTTPClientTransport(targetUrl, commonOptions)
|
transportInstance = new StreamableHTTPClientTransport(targetUrl, commonOptions)
|
||||||
|
addLog('debug', 'StreamableHTTPClientTransport created successfully')
|
||||||
} else {
|
} else {
|
||||||
// sse
|
// sse
|
||||||
|
addLog('debug', 'Creating SSEClientTransport...')
|
||||||
transportInstance = new SSEClientTransport(targetUrl, commonOptions)
|
transportInstance = new SSEClientTransport(targetUrl, commonOptions)
|
||||||
|
addLog('debug', 'SSEClientTransport created successfully')
|
||||||
}
|
}
|
||||||
transportRef.current = transportInstance // Assign to ref immediately
|
transportRef.current = transportInstance // Assign to ref immediately
|
||||||
addLog('debug', `${transportType.toUpperCase()} transport created.`)
|
addLog('debug', `${transportType.toUpperCase()} transport created and assigned to ref.`)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Use stable failConnection
|
// Use stable failConnection
|
||||||
failConnection(
|
failConnection(
|
||||||
|
|
@ -222,6 +239,13 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
|
||||||
}
|
}
|
||||||
transportInstance.onerror = (err: Error) => {
|
transportInstance.onerror = (err: Error) => {
|
||||||
// Transport errors usually mean connection is lost/failed definitively for this transport
|
// Transport errors usually mean connection is lost/failed definitively for this transport
|
||||||
|
addLog('warn', `Transport error event (${transportType.toUpperCase()}):`, err)
|
||||||
|
addLog('debug', `Error details:`, {
|
||||||
|
message: err.message,
|
||||||
|
stack: err.stack,
|
||||||
|
name: err.name,
|
||||||
|
cause: err.cause,
|
||||||
|
})
|
||||||
// Use stable failConnection
|
// Use stable failConnection
|
||||||
failConnection(`Transport error (${transportType.toUpperCase()}): ${err.message}`, err)
|
failConnection(`Transport error (${transportType.toUpperCase()}): ${err.message}`, err)
|
||||||
// Should we return 'failed' here? failConnection sets state, maybe that's enough.
|
// Should we return 'failed' here? failConnection sets state, maybe that's enough.
|
||||||
|
|
@ -252,6 +276,9 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
|
||||||
// 3. Attempt client.connect()
|
// 3. Attempt client.connect()
|
||||||
try {
|
try {
|
||||||
addLog('info', `Connecting client via ${transportType.toUpperCase()}...`)
|
addLog('info', `Connecting client via ${transportType.toUpperCase()}...`)
|
||||||
|
addLog('debug', `About to call client.connect() with transport instance`)
|
||||||
|
addLog('debug', `Transport instance type: ${transportInstance.constructor.name}`)
|
||||||
|
|
||||||
await clientRef.current!.connect(transportInstance)
|
await clientRef.current!.connect(transportInstance)
|
||||||
|
|
||||||
// --- Success Path ---
|
// --- Success Path ---
|
||||||
|
|
@ -275,6 +302,12 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
|
||||||
} catch (connectErr) {
|
} catch (connectErr) {
|
||||||
// --- Error Handling Path ---
|
// --- Error Handling Path ---
|
||||||
addLog('debug', `Client connect error via ${transportType.toUpperCase()}:`, connectErr)
|
addLog('debug', `Client connect error via ${transportType.toUpperCase()}:`, connectErr)
|
||||||
|
addLog('debug', `Connect error details:`, {
|
||||||
|
message: connectErr instanceof Error ? connectErr.message : String(connectErr),
|
||||||
|
stack: connectErr instanceof Error ? connectErr.stack : 'N/A',
|
||||||
|
name: connectErr instanceof Error ? connectErr.name : 'Unknown',
|
||||||
|
cause: connectErr instanceof Error ? connectErr.cause : undefined,
|
||||||
|
})
|
||||||
const errorInstance = connectErr instanceof Error ? connectErr : new Error(String(connectErr))
|
const errorInstance = connectErr instanceof Error ? connectErr : new Error(String(connectErr))
|
||||||
|
|
||||||
// Check for 404/405 specifically for HTTP transport
|
// Check for 404/405 specifically for HTTP transport
|
||||||
|
|
@ -287,7 +320,7 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
|
||||||
errorMessage === 'Load failed' /* Safari */
|
errorMessage === 'Load failed' /* Safari */
|
||||||
|
|
||||||
if (transportType === 'http' && (is404 || is405 || isLikelyCors)) {
|
if (transportType === 'http' && (is404 || is405 || isLikelyCors)) {
|
||||||
addLog('warn', `HTTP transport failed (${isLikelyCors ? 'CORS' : is404 ? '404' : '405'}). Will attempt fallback to SSE.`)
|
addLog('warn', `HTTP transport failed (${isLikelyCors ? 'CORS' : is404 ? '404' : '405'}).`)
|
||||||
return 'fallback' // Signal that fallback should be attempted
|
return 'fallback' // Signal that fallback should be attempted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -344,7 +377,7 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
|
||||||
// Don't call failConnection here for HTTP transport - let orchestration handle it
|
// Don't call failConnection here for HTTP transport - let orchestration handle it
|
||||||
// so that SSE fallback can still be attempted
|
// so that SSE fallback can still be attempted
|
||||||
if (transportType === 'http') {
|
if (transportType === 'http') {
|
||||||
addLog('warn', `HTTP transport failed: ${errorMessage}. Will attempt fallback to SSE.`)
|
addLog('warn', `HTTP transport failed: ${errorMessage}.`)
|
||||||
return 'fallback'
|
return 'fallback'
|
||||||
} else {
|
} else {
|
||||||
// For SSE transport, we can fail immediately since there's no further fallback
|
// For SSE transport, we can fail immediately since there's no further fallback
|
||||||
|
|
@ -357,15 +390,26 @@ export function useMcp(options: UseMcpOptions): UseMcpResult {
|
||||||
// --- Orchestrate Connection Attempts ---
|
// --- Orchestrate Connection Attempts ---
|
||||||
let finalStatus: 'success' | 'auth_redirect' | 'failed' | 'fallback' = 'failed' // Default to failed
|
let finalStatus: 'success' | 'auth_redirect' | 'failed' | 'fallback' = 'failed' // Default to failed
|
||||||
|
|
||||||
// 1. Try HTTP
|
if (transportType === 'sse') {
|
||||||
const httpResult = await tryConnectWithTransport('http')
|
// SSE only - skip HTTP entirely
|
||||||
|
addLog('debug', 'Using SSE-only transport mode')
|
||||||
// 2. Try SSE only if HTTP requested fallback and we haven't redirected
|
finalStatus = await tryConnectWithTransport('sse')
|
||||||
if (httpResult === 'fallback' && isMountedRef.current && stateRef.current !== 'authenticating') {
|
} else if (transportType === 'http') {
|
||||||
const sseResult = await tryConnectWithTransport('sse')
|
// HTTP only - no fallback
|
||||||
finalStatus = sseResult // Use SSE result as final status
|
addLog('debug', 'Using HTTP-only transport mode')
|
||||||
|
finalStatus = await tryConnectWithTransport('http')
|
||||||
} else {
|
} else {
|
||||||
finalStatus = httpResult // Use HTTP result if no fallback was needed/possible
|
// Auto mode - try HTTP first, fallback to SSE
|
||||||
|
addLog('debug', 'Using auto transport mode (HTTP with SSE fallback)')
|
||||||
|
const httpResult = await tryConnectWithTransport('http')
|
||||||
|
|
||||||
|
// Try SSE only if HTTP requested fallback and we haven't redirected
|
||||||
|
if (httpResult === 'fallback' && isMountedRef.current && stateRef.current !== 'authenticating') {
|
||||||
|
const sseResult = await tryConnectWithTransport('sse')
|
||||||
|
finalStatus = sseResult // Use SSE result as final status
|
||||||
|
} else {
|
||||||
|
finalStatus = httpResult // Use HTTP result if no fallback was needed/possible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we still have 'fallback' status, convert to 'failed' since no more transports to try
|
// If we still have 'fallback' status, convert to 'failed' since no more transports to try
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue