From 0771b998a591531497b02f829d69d850758067a2 Mon Sep 17 00:00:00 2001 From: Dinh Long Nguyen Date: Mon, 15 Sep 2025 09:08:30 +0700 Subject: [PATCH 1/2] Fix: Web Services Improvement Fix: Web Services Improvement --- extensions-web/src/jan-provider-web/api.ts | 7 ++-- extensions-web/src/mcp-web/index.ts | 6 ++-- extensions-web/src/shared/auth.ts | 37 +++++++++++----------- extensions-web/src/shared/index.ts | 2 +- web-app/src/lib/completion.ts | 8 +++-- web-app/src/routes/__root.tsx | 2 +- 6 files changed, 29 insertions(+), 33 deletions(-) diff --git a/extensions-web/src/jan-provider-web/api.ts b/extensions-web/src/jan-provider-web/api.ts index 3ea083f5d..16c4dc70e 100644 --- a/extensions-web/src/jan-provider-web/api.ts +++ b/extensions-web/src/jan-provider-web/api.ts @@ -3,7 +3,7 @@ * Handles API requests to Jan backend for models and chat completions */ -import { JanAuthService } from '../shared/auth' +import { getSharedAuthService, JanAuthService } from '../shared' import { JanModel, janProviderStore } from './store' // JAN_API_BASE is defined in vite.config.ts @@ -77,7 +77,7 @@ export class JanApiClient { private authService: JanAuthService private constructor() { - this.authService = JanAuthService.getInstance() + this.authService = getSharedAuthService() } static getInstance(): JanApiClient { @@ -216,12 +216,9 @@ export class JanApiClient { async initialize(): Promise { try { - await this.authService.initialize() janProviderStore.setAuthenticated(true) - // Fetch initial models await this.getModels() - console.log('Jan API client initialized successfully') } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Failed to initialize API client' diff --git a/extensions-web/src/mcp-web/index.ts b/extensions-web/src/mcp-web/index.ts index 5b55643d4..5e13846a7 100644 --- a/extensions-web/src/mcp-web/index.ts +++ b/extensions-web/src/mcp-web/index.ts @@ -5,7 +5,7 @@ */ import { MCPExtension, MCPTool, MCPToolCallResult } from '@janhq/core' -import { JanAuthService } from '../shared/auth' +import { getSharedAuthService, JanAuthService } from '../shared' import { Client } from '@modelcontextprotocol/sdk/client/index.js' import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js' import { JanMCPOAuthProvider } from './oauth-provider' @@ -30,14 +30,12 @@ export default class MCPExtensionWeb extends MCPExtension { version?: string ) { super(url, name, productName, active, description, version) - this.authService = JanAuthService.getInstance() + this.authService = getSharedAuthService() this.oauthProvider = new JanMCPOAuthProvider(this.authService) } async onLoad(): Promise { try { - // Initialize authentication first - await this.authService.initialize() // Initialize MCP client with OAuth await this.initializeMCPClient() // Then fetch tools diff --git a/extensions-web/src/shared/auth.ts b/extensions-web/src/shared/auth.ts index 3e7a3869b..8b44ed714 100644 --- a/extensions-web/src/shared/auth.ts +++ b/extensions-web/src/shared/auth.ts @@ -20,21 +20,13 @@ const AUTH_STORAGE_KEY = 'jan_auth_tokens' const TOKEN_EXPIRY_BUFFER = 60 * 1000 // 1 minute buffer before actual expiry export class JanAuthService { - private static instance: JanAuthService private tokens: AuthTokens | null = null private tokenExpiryTime: number = 0 - private constructor() { + constructor() { this.loadTokensFromStorage() } - static getInstance(): JanAuthService { - if (!JanAuthService.instance) { - JanAuthService.instance = new JanAuthService() - } - return JanAuthService.instance - } - private loadTokensFromStorage(): void { try { const storedTokens = localStorage.getItem(AUTH_STORAGE_KEY) @@ -169,16 +161,6 @@ export class JanAuthService { return this.tokens.access_token } - async initialize(): Promise { - try { - await this.getValidAccessToken() - console.log('Jan auth service initialized successfully') - } catch (error) { - console.error('Failed to initialize Jan auth service:', error) - throw error - } - } - async getAuthHeader(): Promise<{ Authorization: string }> { const token = await this.getValidAccessToken() return { @@ -217,4 +199,21 @@ export class JanAuthService { logout(): void { this.clearTokens() } +} + +declare global { + interface Window { + janAuthService?: JanAuthService + } +} + +/** + * Gets or creates the shared JanAuthService instance on the window object + * This ensures all extensions use the same auth service instance + */ +export function getSharedAuthService(): JanAuthService { + if (!window.janAuthService) { + window.janAuthService = new JanAuthService() + } + return window.janAuthService } \ No newline at end of file diff --git a/extensions-web/src/shared/index.ts b/extensions-web/src/shared/index.ts index d97ca4161..92399c75f 100644 --- a/extensions-web/src/shared/index.ts +++ b/extensions-web/src/shared/index.ts @@ -1,3 +1,3 @@ export { getSharedDB } from './db' -export { JanAuthService } from './auth' +export { JanAuthService, getSharedAuthService } from './auth' export type { AuthTokens, AuthResponse } from './auth' \ No newline at end of file diff --git a/web-app/src/lib/completion.ts b/web-app/src/lib/completion.ts index 4d30f0750..023c39481 100644 --- a/web-app/src/lib/completion.ts +++ b/web-app/src/lib/completion.ts @@ -193,6 +193,7 @@ export const sendCompletion = async ( if ( thread.model.id && + models[providerName]?.models !== true && // Skip if provider accepts any model (models: true) !Object.values(models[providerName]).flat().includes(thread.model.id) && !tokenJS.extendedModelExist(providerName as any, thread.model.id) && provider.provider !== 'llamacpp' @@ -396,9 +397,12 @@ export const postMessageProcessing = async ( let toolParameters = {} if (toolCall.function.arguments.length) { try { + console.log('Raw tool arguments:', toolCall.function.arguments) toolParameters = JSON.parse(toolCall.function.arguments) + console.log('Parsed tool parameters:', toolParameters) } catch (error) { console.error('Failed to parse tool arguments:', error) + console.error('Raw arguments that failed:', toolCall.function.arguments) } } const approved = @@ -414,9 +418,7 @@ export const postMessageProcessing = async ( const { promise, cancel } = getServiceHub().mcp().callToolWithCancellation({ toolName: toolCall.function.name, - arguments: toolCall.function.arguments.length - ? JSON.parse(toolCall.function.arguments) - : {}, + arguments: toolCall.function.arguments.length ? toolParameters : {}, }) useAppState.getState().setCancelToolCall(cancel) diff --git a/web-app/src/routes/__root.tsx b/web-app/src/routes/__root.tsx index f97e0c96d..710de4399 100644 --- a/web-app/src/routes/__root.tsx +++ b/web-app/src/routes/__root.tsx @@ -114,7 +114,7 @@ const AppLayout = () => { {/* Fake absolute panel top to enable window drag */}
- + {PlatformFeatures[PlatformFeature.LOCAL_INFERENCE] && } {/* Use ResizablePanelGroup only on larger screens */} {!isSmallScreen && isLeftPanelOpen ? ( From 1d36a4ad6e100e659ed8fa7d8d68c47836a31c51 Mon Sep 17 00:00:00 2001 From: Louis Date: Mon, 15 Sep 2025 10:27:07 +0700 Subject: [PATCH 2/2] refactor: clean up empty folders (#6454) --- .gitignore | 1 + pre-install/.gitkeep | 0 scripts/download-bin.mjs | 5 ----- 3 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 pre-install/.gitkeep diff --git a/.gitignore b/.gitignore index e087b3b66..6b51867ef 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ core/lib/** .yarnrc *.tsbuildinfo test_results.html +pre-install # docs docs/yarn.lock diff --git a/pre-install/.gitkeep b/pre-install/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/scripts/download-bin.mjs b/scripts/download-bin.mjs index a1884d940..36e17b3f0 100644 --- a/scripts/download-bin.mjs +++ b/scripts/download-bin.mjs @@ -231,11 +231,6 @@ async function main() { console.log('Downloads completed.') } -// Ensure the downloads directory exists -if (!fs.existsSync('downloads')) { - fs.mkdirSync('downloads') -} - main().catch((err) => { console.error('Error:', err) process.exit(1)