From 7a78c5603a3a3023f9e46d49dc75751952c15266 Mon Sep 17 00:00:00 2001 From: Dinh Long Nguyen Date: Thu, 11 Sep 2025 10:26:40 +0700 Subject: [PATCH 1/5] add mcp for web --- core/src/browser/extension.ts | 1 + core/src/browser/extensions/index.ts | 5 + core/src/browser/extensions/mcp.test.ts | 99 ++++++ core/src/browser/extensions/mcp.ts | 21 ++ core/src/types/index.ts | 1 + core/src/types/mcp/index.ts | 2 + core/src/types/mcp/mcpEntity.ts | 24 ++ core/src/types/mcp/mcpInterface.ts | 32 ++ extensions-web/package.json | 3 + extensions-web/src/index.ts | 5 +- extensions-web/src/jan-provider-web/api.ts | 38 +-- .../src/jan-provider-web/provider.ts | 12 +- extensions-web/src/mcp-web/index.ts | 299 ++++++++++++++++++ extensions-web/src/mcp-web/types.ts | 12 + .../src/{jan-provider-web => shared}/auth.ts | 42 ++- extensions-web/src/shared/index.ts | 3 + extensions-web/src/types.ts | 9 +- web-app/src/lib/platform/const.ts | 2 +- web-app/src/routes/settings/mcp-servers.tsx | 112 ++++++- web-app/src/services/index.ts | 3 + web-app/src/services/mcp/default.ts | 6 +- web-app/src/services/mcp/types.ts | 11 +- web-app/src/services/mcp/web.ts | 279 ++++++++++++++++ 23 files changed, 968 insertions(+), 53 deletions(-) create mode 100644 core/src/browser/extensions/mcp.test.ts create mode 100644 core/src/browser/extensions/mcp.ts create mode 100644 core/src/types/mcp/index.ts create mode 100644 core/src/types/mcp/mcpEntity.ts create mode 100644 core/src/types/mcp/mcpInterface.ts create mode 100644 extensions-web/src/mcp-web/index.ts create mode 100644 extensions-web/src/mcp-web/types.ts rename extensions-web/src/{jan-provider-web => shared}/auth.ts (83%) create mode 100644 extensions-web/src/shared/index.ts create mode 100644 web-app/src/services/mcp/web.ts diff --git a/core/src/browser/extension.ts b/core/src/browser/extension.ts index 7fc9136381..159d4ac68b 100644 --- a/core/src/browser/extension.ts +++ b/core/src/browser/extension.ts @@ -7,6 +7,7 @@ export enum ExtensionTypeEnum { Inference = 'inference', Model = 'model', SystemMonitoring = 'systemMonitoring', + MCP = 'mcp', HuggingFace = 'huggingFace', Engine = 'engine', Hardware = 'hardware', diff --git a/core/src/browser/extensions/index.ts b/core/src/browser/extensions/index.ts index 6ee3baff7a..30c7de2162 100644 --- a/core/src/browser/extensions/index.ts +++ b/core/src/browser/extensions/index.ts @@ -14,6 +14,11 @@ export { InferenceExtension } from './inference' */ export { AssistantExtension } from './assistant' +/** + * MCP extension for managing tools and server communication. + */ +export { MCPExtension } from './mcp' + /** * Base AI Engines. */ diff --git a/core/src/browser/extensions/mcp.test.ts b/core/src/browser/extensions/mcp.test.ts new file mode 100644 index 0000000000..ece9718099 --- /dev/null +++ b/core/src/browser/extensions/mcp.test.ts @@ -0,0 +1,99 @@ +import { describe, it, expect, beforeEach } from 'vitest' +import { MCPExtension } from './mcp' +import { ExtensionTypeEnum } from '../extension' +import { MCPTool, MCPToolCallResult } from '../../types' + +class TestMCPExtension extends MCPExtension { + constructor() { + super('test://mcp', 'test-mcp') + } + + async getTools(): Promise { + return [ + { + name: 'test_tool', + description: 'A test tool', + inputSchema: { type: 'object' }, + server: 'test-server' + } + ] + } + + async callTool(toolName: string, args: Record): Promise { + return { + error: '', + content: [{ type: 'text', text: `Called ${toolName} with ${JSON.stringify(args)}` }] + } + } + + async getConnectedServers(): Promise { + return ['test-server'] + } + + async refreshTools(): Promise { + // Mock implementation + } + + async isHealthy(): Promise { + return true + } + + async onLoad(): Promise { + // Mock implementation + } + + onUnload(): void { + // Mock implementation + } +} + +describe('MCPExtension', () => { + let mcpExtension: TestMCPExtension + + beforeEach(() => { + mcpExtension = new TestMCPExtension() + }) + + describe('type', () => { + it('should return MCP extension type', () => { + expect(mcpExtension.type()).toBe(ExtensionTypeEnum.MCP) + }) + }) + + describe('getTools', () => { + it('should return array of MCP tools', async () => { + const tools = await mcpExtension.getTools() + expect(tools).toHaveLength(1) + expect(tools[0]).toEqual({ + name: 'test_tool', + description: 'A test tool', + inputSchema: { type: 'object' }, + server: 'test-server' + }) + }) + }) + + describe('callTool', () => { + it('should call tool and return result', async () => { + const result = await mcpExtension.callTool('test_tool', { param: 'value' }) + expect(result).toEqual({ + error: '', + content: [{ type: 'text', text: 'Called test_tool with {"param":"value"}' }] + }) + }) + }) + + describe('getConnectedServers', () => { + it('should return list of connected servers', async () => { + const servers = await mcpExtension.getConnectedServers() + expect(servers).toEqual(['test-server']) + }) + }) + + describe('isHealthy', () => { + it('should return health status', async () => { + const healthy = await mcpExtension.isHealthy() + expect(healthy).toBe(true) + }) + }) +}) \ No newline at end of file diff --git a/core/src/browser/extensions/mcp.ts b/core/src/browser/extensions/mcp.ts new file mode 100644 index 0000000000..7f30a54284 --- /dev/null +++ b/core/src/browser/extensions/mcp.ts @@ -0,0 +1,21 @@ +import { MCPInterface, MCPTool, MCPToolCallResult } from '../../types' +import { BaseExtension, ExtensionTypeEnum } from '../extension' + +/** + * MCP (Model Context Protocol) extension for managing tools and server communication. + * @extends BaseExtension + */ +export abstract class MCPExtension extends BaseExtension implements MCPInterface { + /** + * MCP extension type. + */ + type(): ExtensionTypeEnum | undefined { + return ExtensionTypeEnum.MCP + } + + abstract getTools(): Promise + abstract callTool(toolName: string, args: Record): Promise + abstract getConnectedServers(): Promise + abstract refreshTools(): Promise + abstract isHealthy(): Promise +} \ No newline at end of file diff --git a/core/src/types/index.ts b/core/src/types/index.ts index 54cb9f41e0..2f165b7b9d 100644 --- a/core/src/types/index.ts +++ b/core/src/types/index.ts @@ -10,3 +10,4 @@ export * from './api' export * from './setting' export * from './engine' export * from './hardware' +export * from './mcp' diff --git a/core/src/types/mcp/index.ts b/core/src/types/mcp/index.ts new file mode 100644 index 0000000000..4ffd501fc2 --- /dev/null +++ b/core/src/types/mcp/index.ts @@ -0,0 +1,2 @@ +export * from './mcpEntity' +export * from './mcpInterface' \ No newline at end of file diff --git a/core/src/types/mcp/mcpEntity.ts b/core/src/types/mcp/mcpEntity.ts new file mode 100644 index 0000000000..a2259e52ed --- /dev/null +++ b/core/src/types/mcp/mcpEntity.ts @@ -0,0 +1,24 @@ +/** + * MCP (Model Context Protocol) entities + */ + +export interface MCPTool { + name: string + description: string + inputSchema: Record + server: string +} + +export interface MCPToolCallResult { + error: string + content: Array<{ + type?: string + text: string + }> +} + +export interface MCPServerInfo { + name: string + connected: boolean + tools?: MCPTool[] +} \ No newline at end of file diff --git a/core/src/types/mcp/mcpInterface.ts b/core/src/types/mcp/mcpInterface.ts new file mode 100644 index 0000000000..15152a83be --- /dev/null +++ b/core/src/types/mcp/mcpInterface.ts @@ -0,0 +1,32 @@ +/** + * MCP (Model Context Protocol) interface + */ + +import { MCPTool, MCPToolCallResult } from './mcpEntity' + +export interface MCPInterface { + /** + * Get all available MCP tools + */ + getTools(): Promise + + /** + * Call a specific MCP tool + */ + callTool(toolName: string, args: Record): Promise + + /** + * Get list of connected MCP servers + */ + getConnectedServers(): Promise + + /** + * Refresh the list of available tools + */ + refreshTools(): Promise + + /** + * Check if MCP service is healthy + */ + isHealthy(): Promise +} \ No newline at end of file diff --git a/extensions-web/package.json b/extensions-web/package.json index 8d54443fed..c6517bde05 100644 --- a/extensions-web/package.json +++ b/extensions-web/package.json @@ -30,5 +30,8 @@ "peerDependencies": { "@janhq/core": "*", "zustand": "^5.0.0" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.17.5" } } diff --git a/extensions-web/src/index.ts b/extensions-web/src/index.ts index aa53e37e10..e45c2d71cd 100644 --- a/extensions-web/src/index.ts +++ b/extensions-web/src/index.ts @@ -8,6 +8,7 @@ import type { WebExtensionRegistry } from './types' export { default as AssistantExtensionWeb } from './assistant-web' export { default as ConversationalExtensionWeb } from './conversational-web' export { default as JanProviderWeb } from './jan-provider-web' +export { default as MCPExtensionWeb } from './mcp-web' // Re-export types export type { @@ -17,7 +18,8 @@ export type { WebExtensionLoader, AssistantWebModule, ConversationalWebModule, - JanProviderWebModule + JanProviderWebModule, + MCPWebModule } from './types' // Extension registry for dynamic loading @@ -25,4 +27,5 @@ export const WEB_EXTENSIONS: WebExtensionRegistry = { 'assistant-web': () => import('./assistant-web'), 'conversational-web': () => import('./conversational-web'), 'jan-provider-web': () => import('./jan-provider-web'), + 'mcp-web': () => import('./mcp-web'), } \ No newline at end of file diff --git a/extensions-web/src/jan-provider-web/api.ts b/extensions-web/src/jan-provider-web/api.ts index 68dd6cb77d..3ea083f5de 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 './auth' +import { JanAuthService } from '../shared/auth' import { JanModel, janProviderStore } from './store' // JAN_API_BASE is defined in vite.config.ts @@ -18,6 +18,7 @@ export interface JanChatMessage { content: string reasoning?: string reasoning_content?: string + tool_calls?: any[] } export interface JanChatCompletionRequest { @@ -30,6 +31,8 @@ export interface JanChatCompletionRequest { presence_penalty?: number stream?: boolean stop?: string | string[] + tools?: any[] + tool_choice?: any } export interface JanChatCompletionChoice { @@ -63,6 +66,7 @@ export interface JanChatCompletionChunk { content?: string reasoning?: string reasoning_content?: string + tool_calls?: any[] } finish_reason: string | null }> @@ -83,40 +87,12 @@ export class JanApiClient { return JanApiClient.instance } - private async makeAuthenticatedRequest( - url: string, - options: RequestInit = {} - ): Promise { - try { - const authHeader = await this.authService.getAuthHeader() - - const response = await fetch(url, { - ...options, - headers: { - 'Content-Type': 'application/json', - ...authHeader, - ...options.headers, - }, - }) - - if (!response.ok) { - const errorText = await response.text() - throw new Error(`API request failed: ${response.status} ${response.statusText} - ${errorText}`) - } - - return response.json() - } catch (error) { - console.error('API request failed:', error) - throw error - } - } - async getModels(): Promise { try { janProviderStore.setLoadingModels(true) janProviderStore.clearError() - const response = await this.makeAuthenticatedRequest( + const response = await this.authService.makeAuthenticatedRequest( `${JAN_API_BASE}/models` ) @@ -138,7 +114,7 @@ export class JanApiClient { try { janProviderStore.clearError() - return await this.makeAuthenticatedRequest( + return await this.authService.makeAuthenticatedRequest( `${JAN_API_BASE}/chat/completions`, { method: 'POST', diff --git a/extensions-web/src/jan-provider-web/provider.ts b/extensions-web/src/jan-provider-web/provider.ts index dbe39bebab..5c829ed34f 100644 --- a/extensions-web/src/jan-provider-web/provider.ts +++ b/extensions-web/src/jan-provider-web/provider.ts @@ -62,6 +62,7 @@ export default class JanProviderWeb extends AIEngine { path: undefined, // Remote model, no local path owned_by: model.owned_by, object: model.object, + capabilities: ['tools'], // Jan models support both tools via MCP })) } catch (error) { console.error('Failed to list Jan models:', error) @@ -150,6 +151,8 @@ export default class JanProviderWeb extends AIEngine { presence_penalty: opts.presence_penalty ?? undefined, stream: opts.stream ?? false, stop: opts.stop ?? undefined, + tools: opts.tools ?? undefined, + tool_choice: opts.tool_choice ?? undefined, } if (opts.stream) { @@ -176,6 +179,7 @@ export default class JanProviderWeb extends AIEngine { content: choice.message.content, reasoning: choice.message.reasoning, reasoning_content: choice.message.reasoning_content, + tool_calls: choice.message.tool_calls, }, finish_reason: (choice.finish_reason || 'stop') as 'stop' | 'length' | 'tool_calls' | 'content_filter' | 'function_call', })), @@ -233,6 +237,7 @@ export default class JanProviderWeb extends AIEngine { content: choice.delta.content, reasoning: choice.delta.reasoning, reasoning_content: choice.delta.reasoning_content, + tool_calls: choice.delta.tool_calls, }, finish_reason: choice.finish_reason, })), @@ -300,8 +305,9 @@ export default class JanProviderWeb extends AIEngine { return Array.from(this.activeSessions.values()).map(session => session.model_id) } - async isToolSupported(): Promise { - // Tools are not yet supported - return false + async isToolSupported(modelId: string): Promise { + // Jan models support tool calls via MCP + console.log(`Checking tool support for Jan model ${modelId}: supported`); + return true; } } \ No newline at end of file diff --git a/extensions-web/src/mcp-web/index.ts b/extensions-web/src/mcp-web/index.ts new file mode 100644 index 0000000000..205c1042a1 --- /dev/null +++ b/extensions-web/src/mcp-web/index.ts @@ -0,0 +1,299 @@ +/** + * MCP Web Extension + * Provides Model Context Protocol functionality for web platform + * Uses official MCP TypeScript SDK with proper session handling + */ + +import { MCPExtension, MCPTool, MCPToolCallResult } from '@janhq/core' +import { JanAuthService } from '../shared/auth' +import { Client } from '@modelcontextprotocol/sdk/client/index.js' +import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js' + +// JAN_API_BASE is defined in vite.config.ts (defaults to 'https://api-dev.jan.ai/jan/v1') +declare const JAN_API_BASE: string + +export default class MCPExtensionWeb extends MCPExtension { + private mcpEndpoint = '/mcp' + private tools: MCPTool[] = [] + private initialized = false + private authService: JanAuthService + private mcpClient: Client | null = null + private tokenUpdateListener: (() => void) | null = null + + constructor( + url: string, + name: string, + productName?: string, + active?: boolean, + description?: string, + version?: string + ) { + super(url, name, productName, active, description, version) + this.authService = JanAuthService.getInstance() + } + + async onLoad(): Promise { + try { + // Initialize authentication first + await this.authService.initialize() + // Initialize MCP client + await this.initializeMCPClient() + // Set up localStorage monitoring for token changes + this.setupTokenMonitoring() + // Then fetch tools + await this.initializeTools() + } catch (error) { + console.warn('Failed to initialize MCP extension:', error) + this.tools = [] + } + } + + async onUnload(): Promise { + this.tools = [] + this.initialized = false + + // Remove token update event listener + if (this.tokenUpdateListener) { + window.removeEventListener('jan-auth-token-updated', this.tokenUpdateListener as EventListener) + this.tokenUpdateListener = null + } + + // Properly close MCP client to avoid session errors + if (this.mcpClient) { + try { + await this.mcpClient.close() + } catch (error) { + console.warn('Error closing MCP client:', error) + } + this.mcpClient = null + } + } + + private async initializeMCPClient(): Promise { + try { + // Close existing client if any + if (this.mcpClient) { + try { + await this.mcpClient.close() + } catch (error) { + // Ignore close errors + } + this.mcpClient = null + } + + // Get fresh authentication token + const token = await this.authService.getValidAccessToken() + + // Create StreamableHTTP transport with authentication and session management + const transport = new StreamableHTTPClientTransport( + new URL(`${JAN_API_BASE}${this.mcpEndpoint}`), + { + requestInit: { + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json', + 'mcp-protocol-version': '2025-06-18' + } + } + } + ) + + // Create MCP client + this.mcpClient = new Client( + { + name: 'jan-web-client', + version: '1.0.0' + }, + { + capabilities: { + tools: {}, + resources: {}, + prompts: {}, + logging: {} + } + } + ) + + // Connect to MCP server + await this.mcpClient.connect(transport) + console.log('MCP client connected successfully') + } catch (error) { + console.error('Failed to initialize MCP client:', error) + throw error + } + } + + private setupTokenMonitoring(): void { + // Listen for token update events from the auth service + this.tokenUpdateListener = () => { + // Simply reinitialize the MCP client when any token update occurs + this.initializeMCPClient().catch(error => { + console.error('Failed to reinitialize MCP client after token update:', error) + }) + } + + window.addEventListener('jan-auth-token-updated', this.tokenUpdateListener as EventListener) + } + + private async initializeTools(): Promise { + if (this.initialized || !this.mcpClient) { + return + } + + try { + // Use MCP SDK to list tools + const result = await this.mcpClient.listTools() + console.log('MCP tools/list response:', result) + + if (result.tools && Array.isArray(result.tools)) { + this.tools = result.tools.map((tool) => ({ + name: tool.name, + description: tool.description || '', + inputSchema: (tool.inputSchema || {}) as Record, + server: 'Jan MCP Server' + })) + } else { + console.warn('No tools found in MCP server response') + this.tools = [] + } + + this.initialized = true + console.log(`Initialized MCP extension with ${this.tools.length} tools:`, this.tools.map(t => t.name)) + } catch (error) { + console.error('Failed to fetch MCP tools:', error) + this.tools = [] + this.initialized = false + throw error + } + } + + async getTools(): Promise { + if (!this.initialized) { + await this.initializeTools() + } + return this.tools + } + + async callTool(toolName: string, args: Record): Promise { + if (!this.mcpClient) { + return { + error: 'MCP client not initialized', + content: [{ type: 'text', text: 'MCP client not initialized' }] + } + } + + try { + // Use MCP SDK to call tool + const result = await this.mcpClient.callTool({ + name: toolName, + arguments: args + }) + + console.log(`MCP tool call result for ${toolName}:`, result) + + // Handle tool call result + if (result.isError) { + const errorText = Array.isArray(result.content) && result.content.length > 0 + ? (result.content[0].type === 'text' ? (result.content[0] as any).text : 'Tool call failed') + : 'Tool call failed' + + return { + error: errorText, + content: [{ type: 'text', text: errorText }] + } + } + + // Convert MCP content to Jan's format + const content = Array.isArray(result.content) + ? result.content.map(item => { + if (item.type === 'text') { + return { type: 'text' as const, text: (item as any).text } + } else { + // For non-text types, convert to text representation + return { type: 'text' as const, text: JSON.stringify(item) } + } + }) + : [{ type: 'text' as const, text: 'No content returned' }] + + return { + error: '', + content + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error) + console.error(`Failed to call MCP tool ${toolName}:`, error) + + // If it's a session error, try to reconnect + if (errorMessage.includes('session') || errorMessage.includes('connection')) { + console.log('Detected session error, attempting to reconnect...') + try { + await this.initializeMCPClient() + // Retry the tool call once after reconnection + const retryResult = await this.mcpClient!.callTool({ + name: toolName, + arguments: args + }) + + if (retryResult.isError) { + const errorText = Array.isArray(retryResult.content) && retryResult.content.length > 0 + ? (retryResult.content[0].type === 'text' ? (retryResult.content[0] as any).text : 'Tool call failed after retry') + : 'Tool call failed after retry' + return { + error: errorText, + content: [{ type: 'text', text: errorText }] + } + } + + const content = Array.isArray(retryResult.content) + ? retryResult.content.map(item => { + if (item.type === 'text') { + return { type: 'text' as const, text: (item as any).text } + } else { + return { type: 'text' as const, text: JSON.stringify(item) } + } + }) + : [{ type: 'text' as const, text: 'No content returned' }] + + return { error: '', content } + } catch (retryError) { + console.error('Retry after reconnection failed:', retryError) + } + } + + return { + error: errorMessage, + content: [{ type: 'text', text: errorMessage }] + } + } + } + + async isHealthy(): Promise { + if (!this.mcpClient) { + return false + } + + try { + // Try to list tools as health check (ping might not be available) + await this.mcpClient.listTools() + return true + } catch (error) { + console.warn('MCP health check failed:', error) + return false + } + } + + async getConnectedServers(): Promise { + // Return servers based on MCP client connection status + return this.mcpClient && this.initialized ? ['Jan MCP Server'] : [] + } + + async refreshTools(): Promise { + this.initialized = false + try { + await this.initializeTools() + } catch (error) { + console.error('Failed to refresh tools:', error) + throw error + } + } +} \ No newline at end of file diff --git a/extensions-web/src/mcp-web/types.ts b/extensions-web/src/mcp-web/types.ts new file mode 100644 index 0000000000..4a8b44e986 --- /dev/null +++ b/extensions-web/src/mcp-web/types.ts @@ -0,0 +1,12 @@ +/** + * MCP Web Extension Types + */ + +export interface MCPApiResponse { + content?: Array<{ + type?: string + text?: string + }> + result?: string | object +} + diff --git a/extensions-web/src/jan-provider-web/auth.ts b/extensions-web/src/shared/auth.ts similarity index 83% rename from extensions-web/src/jan-provider-web/auth.ts rename to extensions-web/src/shared/auth.ts index be830c0d0f..8659628a8c 100644 --- a/extensions-web/src/jan-provider-web/auth.ts +++ b/extensions-web/src/shared/auth.ts @@ -1,8 +1,11 @@ /** - * Jan Provider Authentication Service + * Shared Authentication Service * Handles guest login and token refresh for Jan API */ +// JAN_API_BASE is defined in vite.config.ts +declare const JAN_API_BASE: string + export interface AuthTokens { access_token: string expires_in: number @@ -13,7 +16,6 @@ export interface AuthResponse { expires_in: number } -// JAN_API_BASE is defined in vite.config.ts const AUTH_STORAGE_KEY = 'jan_auth_tokens' const TOKEN_EXPIRY_BUFFER = 60 * 1000 // 1 minute buffer before actual expiry @@ -54,6 +56,14 @@ export class JanAuthService { tokens: this.tokens, expiryTime: this.tokenExpiryTime })) + + // Dispatch custom event when tokens are updated + window.dispatchEvent(new CustomEvent('jan-auth-token-updated', { + detail: { + access_token: this.tokens.access_token, + expires_in: this.tokens.expires_in + } + })) } catch (error) { console.error('Failed to save tokens to storage:', error) } @@ -184,6 +194,34 @@ export class JanAuthService { } } + async makeAuthenticatedRequest( + url: string, + options: RequestInit = {} + ): Promise { + try { + const authHeader = await this.getAuthHeader() + + const response = await fetch(url, { + ...options, + headers: { + 'Content-Type': 'application/json', + ...authHeader, + ...options.headers, + }, + }) + + if (!response.ok) { + const errorText = await response.text() + throw new Error(`API request failed: ${response.status} ${response.statusText} - ${errorText}`) + } + + return response.json() + } catch (error) { + console.error('API request failed:', error) + throw error + } + } + logout(): void { this.clearTokens() } diff --git a/extensions-web/src/shared/index.ts b/extensions-web/src/shared/index.ts new file mode 100644 index 0000000000..d97ca4161a --- /dev/null +++ b/extensions-web/src/shared/index.ts @@ -0,0 +1,3 @@ +export { getSharedDB } from './db' +export { JanAuthService } from './auth' +export type { AuthTokens, AuthResponse } from './auth' \ No newline at end of file diff --git a/extensions-web/src/types.ts b/extensions-web/src/types.ts index 4b2ba583e4..f98d761cc5 100644 --- a/extensions-web/src/types.ts +++ b/extensions-web/src/types.ts @@ -2,7 +2,7 @@ * Web Extension Types */ -import type { AssistantExtension, ConversationalExtension, BaseExtension, AIEngine } from '@janhq/core' +import type { AssistantExtension, ConversationalExtension, BaseExtension, AIEngine, MCPExtension } from '@janhq/core' type ExtensionConstructorParams = ConstructorParameters @@ -18,12 +18,17 @@ export interface JanProviderWebModule { default: new (...args: ExtensionConstructorParams) => AIEngine } -export type WebExtensionModule = AssistantWebModule | ConversationalWebModule | JanProviderWebModule +export interface MCPWebModule { + default: new (...args: ExtensionConstructorParams) => MCPExtension +} + +export type WebExtensionModule = AssistantWebModule | ConversationalWebModule | JanProviderWebModule | MCPWebModule export interface WebExtensionRegistry { 'assistant-web': () => Promise 'conversational-web': () => Promise 'jan-provider-web': () => Promise + 'mcp-web': () => Promise } export type WebExtensionName = keyof WebExtensionRegistry diff --git a/web-app/src/lib/platform/const.ts b/web-app/src/lib/platform/const.ts index e2aabb1093..f761b30f1f 100644 --- a/web-app/src/lib/platform/const.ts +++ b/web-app/src/lib/platform/const.ts @@ -21,7 +21,7 @@ export const PlatformFeatures: Record = { [PlatformFeature.LOCAL_INFERENCE]: isPlatformTauri(), // MCP (Model Context Protocol) servers - [PlatformFeature.MCP_SERVERS]: isPlatformTauri(), + [PlatformFeature.MCP_SERVERS]: true, // Local API server [PlatformFeature.LOCAL_API_SERVER]: isPlatformTauri(), diff --git a/web-app/src/routes/settings/mcp-servers.tsx b/web-app/src/routes/settings/mcp-servers.tsx index 3eb20dd3ad..0eaa616963 100644 --- a/web-app/src/routes/settings/mcp-servers.tsx +++ b/web-app/src/routes/settings/mcp-servers.tsx @@ -23,6 +23,8 @@ import { useTranslation } from '@/i18n/react-i18next-compat' import { useAppState } from '@/hooks/useAppState' import { PlatformGuard } from '@/lib/platform/PlatformGuard' import { PlatformFeature } from '@/lib/platform' +import { isPlatformTauri } from '@/lib/platform/utils' +import { MCPTool } from '@janhq/core' // Function to mask sensitive values const maskSensitiveValue = (value: string) => { @@ -91,12 +93,118 @@ export const Route = createFileRoute(route.settings.mcp_servers as any)({ function MCPServers() { return ( - + {isPlatformTauri() ? : } ) } -function MCPServersContent() { +// Web version of MCP servers - simpler UI without server management +function MCPServersWeb() { + const { t } = useTranslation() + const serviceHub = useServiceHub() + const { allowAllMCPPermissions, setAllowAllMCPPermissions } = useToolApproval() + + const [webMcpTools, setWebMcpTools] = useState([]) + const [webMcpServers, setWebMcpServers] = useState([]) + const [webMcpLoading, setWebMcpLoading] = useState(true) + + useEffect(() => { + async function loadWebMcpData() { + setWebMcpLoading(true) + try { + const [tools, servers] = await Promise.all([ + serviceHub.mcp().getTools(), + serviceHub.mcp().getConnectedServers(), + ]) + setWebMcpTools(tools) + setWebMcpServers(servers) + } catch (error) { + console.error('Failed to load web MCP data:', error) + setWebMcpTools([]) + setWebMcpServers([]) + } finally { + setWebMcpLoading(false) + } + } + loadWebMcpData() + }, [serviceHub]) + + return ( +
+ +

{t('common:settings')}

+
+
+ +
+
+ +

+ {t('mcp-servers:title')} +

+

+ MCP tools are automatically available in your chat sessions +

+
+ } + > + + +
+ } + /> + + + + 0 + ? `Connected to ${webMcpServers.join(', ')}. ${webMcpTools.length} tools available.` + : "MCP service not connected" + } + descriptionOutside={ + webMcpTools.length > 0 && !webMcpLoading && ( +
+

Available Tools:

+
+ {webMcpTools.map((tool) => ( +
+
+
{tool.name}
+
{tool.description}
+ {tool.server && ( +
Server: {tool.server}
+ )} +
+
+ ))} +
+
+ ) + } + /> +
+
+
+ + + ) +} + +// Desktop version of MCP servers - full server management capabilities +function MCPServersDesktop() { const { t } = useTranslation() const serviceHub = useServiceHub() const { diff --git a/web-app/src/services/index.ts b/web-app/src/services/index.ts index 88c9765ff5..1217421773 100644 --- a/web-app/src/services/index.ts +++ b/web-app/src/services/index.ts @@ -157,6 +157,7 @@ class PlatformServiceHub implements ServiceHub { windowModule, deepLinkModule, providersModule, + mcpModule, ] = await Promise.all([ import('./theme/web'), import('./app/web'), @@ -167,6 +168,7 @@ class PlatformServiceHub implements ServiceHub { import('./window/web'), import('./deeplink/web'), import('./providers/web'), + import('./mcp/web'), ]) this.themeService = new themeModule.WebThemeService() @@ -178,6 +180,7 @@ class PlatformServiceHub implements ServiceHub { this.windowService = new windowModule.WebWindowService() this.deepLinkService = new deepLinkModule.WebDeepLinkService() this.providersService = new providersModule.WebProvidersService() + this.mcpService = new mcpModule.WebMCPService() } this.initialized = true diff --git a/web-app/src/services/mcp/default.ts b/web-app/src/services/mcp/default.ts index 801bbd60df..1bcce285ad 100644 --- a/web-app/src/services/mcp/default.ts +++ b/web-app/src/services/mcp/default.ts @@ -2,9 +2,9 @@ * Default MCP Service - Generic implementation with minimal returns */ -import { MCPTool } from '@/types/completion' +import { MCPTool, MCPToolCallResult } from '@janhq/core' import type { MCPServerConfig } from '@/hooks/useMCPServers' -import type { MCPService, MCPConfig, ToolCallResult, ToolCallWithCancellationResult } from './types' +import type { MCPService, MCPConfig, ToolCallWithCancellationResult } from './types' export class DefaultMCPService implements MCPService { async updateMCPConfig(configs: string): Promise { @@ -28,7 +28,7 @@ export class DefaultMCPService implements MCPService { return [] } - async callTool(args: { toolName: string; arguments: object }): Promise { + async callTool(args: { toolName: string; arguments: object }): Promise { console.log('callTool called with args:', args) return { error: '', diff --git a/web-app/src/services/mcp/types.ts b/web-app/src/services/mcp/types.ts index f68668d2cc..c551c61c5a 100644 --- a/web-app/src/services/mcp/types.ts +++ b/web-app/src/services/mcp/types.ts @@ -2,20 +2,15 @@ * MCP Service Types */ -import { MCPTool } from '@/types/completion' +import { MCPTool, MCPToolCallResult } from '@janhq/core' import type { MCPServerConfig, MCPServers } from '@/hooks/useMCPServers' export interface MCPConfig { mcpServers?: MCPServers } -export interface ToolCallResult { - error: string - content: { text: string }[] -} - export interface ToolCallWithCancellationResult { - promise: Promise + promise: Promise cancel: () => Promise token: string } @@ -26,7 +21,7 @@ export interface MCPService { getMCPConfig(): Promise getTools(): Promise getConnectedServers(): Promise - callTool(args: { toolName: string; arguments: object }): Promise + callTool(args: { toolName: string; arguments: object }): Promise callToolWithCancellation(args: { toolName: string arguments: object diff --git a/web-app/src/services/mcp/web.ts b/web-app/src/services/mcp/web.ts new file mode 100644 index 0000000000..124de93fd4 --- /dev/null +++ b/web-app/src/services/mcp/web.ts @@ -0,0 +1,279 @@ +/** + * Web MCP Service - Implementation for web platform + * Uses the MCP extension through ExtensionManager + * Follows OpenAI function calling standards + */ + +import type { MCPServerConfig } from '@/hooks/useMCPServers' +import type { MCPService, MCPConfig, ToolCallWithCancellationResult } from './types' +import { ExtensionManager } from '@/lib/extension' +import { ExtensionTypeEnum, MCPExtension, MCPTool, MCPToolCallResult } from '@janhq/core' + +export class WebMCPService implements MCPService { + private abortControllers: Map = new Map() + private extensionCache: MCPExtension | null = null + private cacheTimestamp = 0 + private readonly CACHE_TTL = 5000 // 5 seconds + + private getMCPExtension(): MCPExtension | null { + const now = Date.now() + if (this.extensionCache && (now - this.cacheTimestamp) < this.CACHE_TTL) { + return this.extensionCache + } + + this.extensionCache = ExtensionManager.getInstance().get( + ExtensionTypeEnum.MCP + ) || null + + this.cacheTimestamp = now + return this.extensionCache + } + + private invalidateCache(): void { + this.extensionCache = null + this.cacheTimestamp = 0 + } + + async updateMCPConfig(configs: string): Promise { + if (!configs || typeof configs !== 'string') { + throw new Error('Invalid MCP configuration provided') + } + // For web platform, configuration is handled by the remote API server + // Invalidate cache to ensure fresh extension retrieval + this.invalidateCache() + } + + async restartMCPServers(): Promise { + // For web platform, servers are managed remotely + // This triggers a refresh of available tools + this.invalidateCache() + const extension = this.getMCPExtension() + if (extension) { + try { + await extension.refreshTools() + } catch (error) { + throw new Error(`Failed to restart MCP servers: ${error instanceof Error ? error.message : String(error)}`) + } + } + } + + async getMCPConfig(): Promise { + // Return empty config since web platform doesn't manage local MCP servers + return {} + } + + async getTools(): Promise { + const extension = this.getMCPExtension() + if (!extension) { + return [] + } + + try { + return await extension.getTools() + } catch (error) { + console.error('Failed to get MCP tools:', error) + return [] + } + } + + async getConnectedServers(): Promise { + const extension = this.getMCPExtension() + if (!extension) { + return [] + } + + try { + return await extension.getConnectedServers() + } catch (error) { + console.error('Failed to get connected servers:', error) + return [] + } + } + + async callTool(args: { toolName: string; arguments: object }): Promise { + // Validate input parameters + if (!args.toolName || typeof args.toolName !== 'string') { + return { + error: 'Invalid tool name provided', + content: [{ type: 'text', text: 'Tool name must be a non-empty string' }] + } + } + + const extension = this.getMCPExtension() + if (!extension) { + return { + error: 'MCP extension not available', + content: [{ type: 'text', text: 'MCP service is not available' }] + } + } + + try { + const result = await extension.callTool(args.toolName, args.arguments as Record) + + // Ensure OpenAI-compliant response format + if (!result.content || !Array.isArray(result.content)) { + return { + error: 'Invalid tool response format', + content: [{ type: 'text', text: 'Tool returned invalid response format' }] + } + } + + return { + error: result.error || '', + content: result.content.map(item => ({ + type: item.type || 'text', + text: item.text || JSON.stringify(item) + })) + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error) + return { + error: errorMessage, + content: [{ type: 'text', text: `Tool execution failed: ${errorMessage}` }] + } + } + } + + callToolWithCancellation(args: { + toolName: string + arguments: object + cancellationToken?: string + }): ToolCallWithCancellationResult { + // Validate input parameters + if (!args.toolName || typeof args.toolName !== 'string') { + const errorResult: MCPToolCallResult = { + error: 'Invalid tool name provided', + content: [{ type: 'text', text: 'Tool name must be a non-empty string' }] + } + return { + promise: Promise.resolve(errorResult), + cancel: async () => {}, // No-op for failed validation + token: 'invalid' + } + } + + const token = args.cancellationToken || this.generateCancellationToken() + const abortController = new AbortController() + this.abortControllers.set(token, abortController) + + const promise = this.callToolWithAbort(args, abortController.signal) + .finally(() => { + this.abortControllers.delete(token) + }) + + return { + promise, + cancel: async () => { + const controller = this.abortControllers.get(token) + if (controller && !controller.signal.aborted) { + controller.abort() + } + this.abortControllers.delete(token) + }, + token + } + } + + private async callToolWithAbort( + args: { toolName: string; arguments: object }, + signal: AbortSignal + ): Promise { + // Check if already aborted + if (signal.aborted) { + return { + error: 'Tool call was cancelled', + content: [{ type: 'text', text: 'Tool call was cancelled by user' }] + } + } + + const extension = this.getMCPExtension() + if (!extension) { + return { + error: 'MCP extension not available', + content: [{ type: 'text', text: 'MCP service is not available' }] + } + } + + return new Promise((resolve) => { + const abortHandler = () => { + resolve({ + error: 'Tool call was cancelled', + content: [{ type: 'text', text: 'Tool call was cancelled by user' }] + }) + } + signal.addEventListener('abort', abortHandler, { once: true }) + + extension.callTool(args.toolName, args.arguments as Record) + .then(result => { + if (!signal.aborted) { + if (!result.content || !Array.isArray(result.content)) { + resolve({ + error: 'Invalid tool response format', + content: [{ type: 'text', text: 'Tool returned invalid response format' }] + }) + return + } + + resolve({ + error: result.error || '', + content: result.content.map(item => ({ + type: item.type || 'text', + text: item.text || JSON.stringify(item) + })) + }) + } + }) + .catch(error => { + if (!signal.aborted) { + const errorMessage = error instanceof Error ? error.message : String(error) + resolve({ + error: errorMessage, + content: [{ type: 'text', text: `Tool execution failed: ${errorMessage}` }] + }) + } + }) + .finally(() => { + signal.removeEventListener('abort', abortHandler) + }) + }) + } + + async cancelToolCall(cancellationToken: string): Promise { + const controller = this.abortControllers.get(cancellationToken) + if (controller) { + controller.abort() + this.abortControllers.delete(cancellationToken) + } + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async activateMCPServer(name: string, _config: MCPServerConfig): Promise { + // For web platform, server activation is handled remotely + this.invalidateCache() + const extension = this.getMCPExtension() + if (extension) { + try { + await extension.refreshTools() + } catch (error) { + throw new Error(`Failed to activate MCP server ${name}: ${error instanceof Error ? error.message : String(error)}`) + } + } + } + + async deactivateMCPServer(name: string): Promise { + // For web platform, server deactivation is handled remotely + this.invalidateCache() + const extension = this.getMCPExtension() + if (extension) { + try { + await extension.refreshTools() + } catch (error) { + throw new Error(`Failed to deactivate MCP server ${name}: ${error instanceof Error ? error.message : String(error)}`) + } + } + } + + private generateCancellationToken(): string { + return `mcp_cancel_${Date.now()}_${Math.random().toString(36).substring(2, 11)}` + } +} \ No newline at end of file From ebf66a2735a5b04783d942087f7375ba105b7e52 Mon Sep 17 00:00:00 2001 From: Dinh Long Nguyen Date: Thu, 11 Sep 2025 12:16:02 +0700 Subject: [PATCH 2/5] update /jan/v1 endpoint to /v1 --- extensions-web/vite.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions-web/vite.config.ts b/extensions-web/vite.config.ts index 8d9147c79f..89cfb7d0eb 100644 --- a/extensions-web/vite.config.ts +++ b/extensions-web/vite.config.ts @@ -14,6 +14,6 @@ export default defineConfig({ emptyOutDir: false // Don't clean the output directory }, define: { - JAN_API_BASE: JSON.stringify(process.env.JAN_API_BASE || 'https://api-dev.jan.ai/jan/v1'), + JAN_API_BASE: JSON.stringify(process.env.JAN_API_BASE || 'https://api-dev.jan.ai/v1'), } }) \ No newline at end of file From fb2e214c5a28be64afbd4eecaf9b4b1c92182a4a Mon Sep 17 00:00:00 2001 From: Dinh Long Nguyen Date: Thu, 11 Sep 2025 17:25:01 +0700 Subject: [PATCH 3/5] update mise and makefile --- Makefile | 2 ++ mise.toml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 457f314ef0..d10b26fd93 100644 --- a/Makefile +++ b/Makefile @@ -40,9 +40,11 @@ install-web-app: config-yarn yarn install dev-web-app: install-web-app + yarn build:core yarn dev:web-app build-web-app: install-web-app + yarn build:core yarn build:web-app serve-web-app: diff --git a/mise.toml b/mise.toml index e30b8ba415..85d87aade7 100644 --- a/mise.toml +++ b/mise.toml @@ -82,12 +82,12 @@ run = [ [tasks.dev-web-app] description = "Start web application development server (matches Makefile)" -depends = ["install"] +depends = ["build-core"] run = "yarn dev:web-app" [tasks.build-web-app] description = "Build web application (matches Makefile)" -depends = ["install"] +depends = ["build-core"] run = "yarn build:web-app" [tasks.serve-web-app] From 60e39fa6e6b0ec37cf408cc1be0ba062e6d3a30b Mon Sep 17 00:00:00 2001 From: Dinh Long Nguyen Date: Thu, 11 Sep 2025 20:08:43 +0700 Subject: [PATCH 4/5] update yarn lock --- extensions/yarn.lock | 16 +- src-tauri/plugins/yarn.lock | 1238 +++++++++++++++++++++++++++++++++++ yarn.lock | 471 ++++++++++++- 3 files changed, 1707 insertions(+), 18 deletions(-) diff --git a/extensions/yarn.lock b/extensions/yarn.lock index 5f87d96d65..12b1ddaaf0 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -517,41 +517,41 @@ __metadata: "@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension": version: 0.1.10 - resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=9fbce2&locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension" + resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=c5357d&locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension" dependencies: rxjs: "npm:^7.8.1" ulidx: "npm:^2.3.0" - checksum: 10c0/e59c11201e0e95ea4ed567e3a34921c7fd2901cf32d07d13bdc8254992b6a4b51de7c1e3be633a3c2f558fe533065fa69455b065230dac87f31cb9b86649e932 + checksum: 10c0/95e2ec1f1213d604730f5c9c381c80840402b00a9649039d1a9754ee3efa13e224e4ca39ea094aab5751f3f2ace1860c7640769e66b191b8c56998fd5f2ba5b9 languageName: node linkType: hard "@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension": version: 0.1.10 - resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=9fbce2&locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension" + resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=c5357d&locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension" dependencies: rxjs: "npm:^7.8.1" ulidx: "npm:^2.3.0" - checksum: 10c0/e59c11201e0e95ea4ed567e3a34921c7fd2901cf32d07d13bdc8254992b6a4b51de7c1e3be633a3c2f558fe533065fa69455b065230dac87f31cb9b86649e932 + checksum: 10c0/95e2ec1f1213d604730f5c9c381c80840402b00a9649039d1a9754ee3efa13e224e4ca39ea094aab5751f3f2ace1860c7640769e66b191b8c56998fd5f2ba5b9 languageName: node linkType: hard "@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fdownload-extension%40workspace%3Adownload-extension": version: 0.1.10 - resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=9fbce2&locator=%40janhq%2Fdownload-extension%40workspace%3Adownload-extension" + resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=c5357d&locator=%40janhq%2Fdownload-extension%40workspace%3Adownload-extension" dependencies: rxjs: "npm:^7.8.1" ulidx: "npm:^2.3.0" - checksum: 10c0/e59c11201e0e95ea4ed567e3a34921c7fd2901cf32d07d13bdc8254992b6a4b51de7c1e3be633a3c2f558fe533065fa69455b065230dac87f31cb9b86649e932 + checksum: 10c0/95e2ec1f1213d604730f5c9c381c80840402b00a9649039d1a9754ee3efa13e224e4ca39ea094aab5751f3f2ace1860c7640769e66b191b8c56998fd5f2ba5b9 languageName: node linkType: hard "@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fllamacpp-extension%40workspace%3Allamacpp-extension": version: 0.1.10 - resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=9fbce2&locator=%40janhq%2Fllamacpp-extension%40workspace%3Allamacpp-extension" + resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=c5357d&locator=%40janhq%2Fllamacpp-extension%40workspace%3Allamacpp-extension" dependencies: rxjs: "npm:^7.8.1" ulidx: "npm:^2.3.0" - checksum: 10c0/e59c11201e0e95ea4ed567e3a34921c7fd2901cf32d07d13bdc8254992b6a4b51de7c1e3be633a3c2f558fe533065fa69455b065230dac87f31cb9b86649e932 + checksum: 10c0/95e2ec1f1213d604730f5c9c381c80840402b00a9649039d1a9754ee3efa13e224e4ca39ea094aab5751f3f2ace1860c7640769e66b191b8c56998fd5f2ba5b9 languageName: node linkType: hard diff --git a/src-tauri/plugins/yarn.lock b/src-tauri/plugins/yarn.lock index e69de29bb2..3fba44fdc1 100644 --- a/src-tauri/plugins/yarn.lock +++ b/src-tauri/plugins/yarn.lock @@ -0,0 +1,1238 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: "npm:^5.1.2" + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: "npm:^7.0.1" + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: "npm:^8.1.0" + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e + languageName: node + linkType: hard + +"@isaacs/fs-minipass@npm:^4.0.0": + version: 4.0.1 + resolution: "@isaacs/fs-minipass@npm:4.0.1" + dependencies: + minipass: "npm:^7.0.4" + checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 + languageName: node + linkType: hard + +"@janhq/tauri-plugin-hardware-api@workspace:tauri-plugin-hardware": + version: 0.0.0-use.local + resolution: "@janhq/tauri-plugin-hardware-api@workspace:tauri-plugin-hardware" + dependencies: + "@rollup/plugin-typescript": "npm:^12.0.0" + "@tauri-apps/api": "npm:>=2.0.0-beta.6" + rollup: "npm:^4.9.6" + tslib: "npm:^2.6.2" + typescript: "npm:^5.3.3" + languageName: unknown + linkType: soft + +"@janhq/tauri-plugin-llamacpp-api@workspace:tauri-plugin-llamacpp": + version: 0.0.0-use.local + resolution: "@janhq/tauri-plugin-llamacpp-api@workspace:tauri-plugin-llamacpp" + dependencies: + "@rollup/plugin-typescript": "npm:^12.0.0" + "@tauri-apps/api": "npm:>=2.0.0-beta.6" + rollup: "npm:^4.9.6" + tslib: "npm:^2.6.2" + typescript: "npm:^5.3.3" + languageName: unknown + linkType: soft + +"@npmcli/agent@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/agent@npm:3.0.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/fs@npm:4.0.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd + languageName: node + linkType: hard + +"@rollup/plugin-typescript@npm:^12.0.0": + version: 12.1.4 + resolution: "@rollup/plugin-typescript@npm:12.1.4" + dependencies: + "@rollup/pluginutils": "npm:^5.1.0" + resolve: "npm:^1.22.1" + peerDependencies: + rollup: ^2.14.0||^3.0.0||^4.0.0 + tslib: "*" + typescript: ">=3.7.0" + peerDependenciesMeta: + rollup: + optional: true + tslib: + optional: true + checksum: 10c0/b5bf7f54794d0b33ae5441c5aa202a95beb7068c206f40102f94997e888756c06c2bfe00517eb74a58771078432f94e8a34e99f5c6dbf89a22b49431b83c4798 + languageName: node + linkType: hard + +"@rollup/pluginutils@npm:^5.1.0": + version: 5.3.0 + resolution: "@rollup/pluginutils@npm:5.3.0" + dependencies: + "@types/estree": "npm:^1.0.0" + estree-walker: "npm:^2.0.2" + picomatch: "npm:^4.0.2" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/001834bf62d7cf5bac424d2617c113f7f7d3b2bf3c1778cbcccb72cdc957b68989f8e7747c782c2b911f1dde8257f56f8ac1e779e29e74e638e3f1e2cac2bcd0 + languageName: node + linkType: hard + +"@rollup/rollup-android-arm-eabi@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.50.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-android-arm64@npm:4.50.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-darwin-arm64@npm:4.50.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-darwin-x64@npm:4.50.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-freebsd-arm64@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.50.1" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-freebsd-x64@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-freebsd-x64@npm:4.50.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.50.1" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-musleabihf@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.50.1" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.50.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.50.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-loongarch64-gnu@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.50.1" + conditions: os=linux & cpu=loong64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-ppc64-gnu@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.50.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.50.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-musl@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.50.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-s390x-gnu@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.50.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.50.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.50.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-openharmony-arm64@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-openharmony-arm64@npm:4.50.1" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.50.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.50.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.50.1": + version: 4.50.1 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.50.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@tauri-apps/api@npm:>=2.0.0-beta.6": + version: 2.8.0 + resolution: "@tauri-apps/api@npm:2.8.0" + checksum: 10c0/fb111e4d7572372997b440ebe6879543fa8c4765151878e3fddfbfe809b18da29eed142ce83061d14a9ca6d896b3266dc8a4927c642d71cdc0b4277dc7e3aabf + languageName: node + linkType: hard + +"@types/estree@npm:1.0.8, @types/estree@npm:^1.0.0": + version: 1.0.8 + resolution: "@types/estree@npm:1.0.8" + checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 + languageName: node + linkType: hard + +"abbrev@npm:^3.0.0": + version: 3.0.1 + resolution: "abbrev@npm:3.0.1" + checksum: 10c0/21ba8f574ea57a3106d6d35623f2c4a9111d9ee3e9a5be47baed46ec2457d2eac46e07a5c4a60186f88cb98abbe3e24f2d4cca70bc2b12f1692523e2209a9ccf + languageName: node + linkType: hard + +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": + version: 7.1.4 + resolution: "agent-base@npm:7.1.4" + checksum: 10c0/c2c9ab7599692d594b6a161559ada307b7a624fa4c7b03e3afdb5a5e31cd0e53269115b620fcab024c5ac6a6f37fa5eb2e004f076ad30f5f7e6b8b671f7b35fe + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 10c0/05d4acb1d2f59ab2cf4b794339c7b168890d44dda4bf0ce01152a8da0213aca207802f930442ce8cd22d7a92f44907664aac6508904e75e038fa944d2601b30f + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: "npm:^2.0.1" + checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.3 + resolution: "ansi-styles@npm:6.2.3" + checksum: 10c0/23b8a4ce14e18fb854693b95351e286b771d23d8844057ed2e7d083cd3e708376c3323707ec6a24365f7d7eda3ca00327fe04092e29e551499ec4c8b7bfac868 + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.2 + resolution: "brace-expansion@npm:2.0.2" + dependencies: + balanced-match: "npm:^1.0.0" + checksum: 10c0/6d117a4c793488af86b83172deb6af143e94c17bc53b0b3cec259733923b4ca84679d506ac261f4ba3c7ed37c46018e2ff442f9ce453af8643ecd64f4a54e6cf + languageName: node + linkType: hard + +"cacache@npm:^19.0.1": + version: 19.0.1 + resolution: "cacache@npm:19.0.1" + dependencies: + "@npmcli/fs": "npm:^4.0.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^7.0.2" + ssri: "npm:^12.0.0" + tar: "npm:^7.4.3" + unique-filename: "npm:^4.0.0" + checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c + languageName: node + linkType: hard + +"chownr@npm:^3.0.0": + version: 3.0.0 + resolution: "chownr@npm:3.0.0" + checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: "npm:~1.1.4" + checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.6": + version: 7.0.6 + resolution: "cross-spawn@npm:7.0.6" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.3.4": + version: 4.4.1 + resolution: "debug@npm:4.4.1" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/d2b44bc1afd912b49bb7ebb0d50a860dc93a4dd7d946e8de94abc957bb63726b7dd5aa48c18c2386c379ec024c46692e15ed3ed97d481729f929201e671fcd55 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: "npm:^0.6.2" + checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 + languageName: node + linkType: hard + +"estree-walker@npm:^2.0.2": + version: 2.0.2 + resolution: "estree-walker@npm:2.0.2" + checksum: 10c0/53a6c54e2019b8c914dc395890153ffdc2322781acf4bd7d1a32d7aedc1710807bdcd866ac133903d5629ec601fbb50abe8c2e5553c7f5a0afdd9b6af6c945af + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.2 + resolution: "exponential-backoff@npm:3.1.2" + checksum: 10c0/d9d3e1eafa21b78464297df91f1776f7fbaa3d5e3f7f0995648ca5b89c069d17055033817348d9f4a43d1c20b0eab84f75af6991751e839df53e4dfd6f22e844 + languageName: node + linkType: hard + +"fdir@npm:^6.5.0": + version: 6.5.0 + resolution: "fdir@npm:6.5.0" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10c0/e345083c4306b3aed6cb8ec551e26c36bab5c511e99ea4576a16750ddc8d3240e63826cc624f5ae17ad4dc82e68a253213b60d556c11bfad064b7607847ed07f + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.3.1 + resolution: "foreground-child@npm:3.3.1" + dependencies: + cross-spawn: "npm:^7.0.6" + signal-exit: "npm:^4.0.1" + checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 + languageName: node + linkType: hard + +"fsevents@npm:~2.3.2": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 + languageName: node + linkType: hard + +"glob@npm:^10.2.2": + version: 10.4.5 + resolution: "glob@npm:10.4.5" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e + languageName: node + linkType: hard + +"graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 + languageName: node + linkType: hard + +"hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" + dependencies: + function-bind: "npm:^1.1.2" + checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.2.0 + resolution: "http-cache-semantics@npm:4.2.0" + checksum: 10c0/45b66a945cf13ec2d1f29432277201313babf4a01d9e52f44b31ca923434083afeca03f18417f599c9ab3d0e7b618ceb21257542338b57c54b710463b4a53e37 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" + dependencies: + agent-base: "npm:^7.1.2" + debug: "npm:4" + checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 + languageName: node + linkType: hard + +"ip-address@npm:^10.0.1": + version: 10.0.1 + resolution: "ip-address@npm:10.0.1" + checksum: 10c0/1634d79dae18394004775cb6d699dc46b7c23df6d2083164025a2b15240c1164fccde53d0e08bd5ee4fc53913d033ab6b5e395a809ad4b956a940c446e948843 + languageName: node + linkType: hard + +"is-core-module@npm:^2.16.0": + version: 2.16.1 + resolution: "is-core-module@npm:2.16.1" + dependencies: + hasown: "npm:^2.0.2" + checksum: 10c0/898443c14780a577e807618aaae2b6f745c8538eca5c7bc11388a3f2dc6de82b9902bcc7eb74f07be672b11bbe82dd6a6edded44a00cb3d8f933d0459905eedd + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 + languageName: node + linkType: hard + +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb + languageName: node + linkType: hard + +"make-fetch-happen@npm:^14.0.3": + version: 14.0.3 + resolution: "make-fetch-happen@npm:14.0.3" + dependencies: + "@npmcli/agent": "npm:^3.0.0" + cacache: "npm:^19.0.1" + http-cache-semantics: "npm:^4.1.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^4.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^1.0.0" + proc-log: "npm:^5.0.0" + promise-retry: "npm:^2.0.1" + ssri: "npm:^12.0.0" + checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.4": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e + languageName: node + linkType: hard + +"minipass-fetch@npm:^4.0.0": + version: 4.0.1 + resolution: "minipass-fetch@npm:4.0.1" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^3.0.1" + dependenciesMeta: + encoding: + optional: true + checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 + languageName: node + linkType: hard + +"minizlib@npm:^3.0.1": + version: 3.0.2 + resolution: "minizlib@npm:3.0.2" + dependencies: + minipass: "npm:^7.1.2" + checksum: 10c0/9f3bd35e41d40d02469cb30470c55ccc21cae0db40e08d1d0b1dff01cc8cc89a6f78e9c5d2b7c844e485ec0a8abc2238111213fdc5b2038e6d1012eacf316f78 + languageName: node + linkType: hard + +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d + languageName: node + linkType: hard + +"ms@npm:^2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 + languageName: node + linkType: hard + +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 11.4.2 + resolution: "node-gyp@npm:11.4.2" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^14.0.3" + nopt: "npm:^8.0.0" + proc-log: "npm:^5.0.0" + semver: "npm:^7.3.5" + tar: "npm:^7.4.3" + tinyglobby: "npm:^0.2.12" + which: "npm:^5.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10c0/0bfd3e96770ed70f07798d881dd37b4267708966d868a0e585986baac487d9cf5831285579fd629a83dc4e434f53e6416ce301097f2ee464cb74d377e4d8bdbe + languageName: node + linkType: hard + +"nopt@npm:^8.0.0": + version: 8.1.0 + resolution: "nopt@npm:8.1.0" + dependencies: + abbrev: "npm:^3.0.0" + bin: + nopt: bin/nopt.js + checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef + languageName: node + linkType: hard + +"p-map@npm:^7.0.2": + version: 7.0.3 + resolution: "p-map@npm:7.0.3" + checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c + languageName: node + linkType: hard + +"package-json-from-dist@npm:^1.0.0": + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c + languageName: node + linkType: hard + +"path-parse@npm:^1.0.7": + version: 1.0.7 + resolution: "path-parse@npm:1.0.7" + checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: "npm:^10.2.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d + languageName: node + linkType: hard + +"picomatch@npm:^4.0.2, picomatch@npm:^4.0.3": + version: 4.0.3 + resolution: "picomatch@npm:4.0.3" + checksum: 10c0/9582c951e95eebee5434f59e426cddd228a7b97a0161a375aed4be244bd3fe8e3a31b846808ea14ef2c8a2527a6eeab7b3946a67d5979e81694654f939473ae2 + languageName: node + linkType: hard + +"proc-log@npm:^5.0.0": + version: 5.0.0 + resolution: "proc-log@npm:5.0.0" + checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: "npm:^2.0.2" + retry: "npm:^0.12.0" + checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 + languageName: node + linkType: hard + +"resolve@npm:^1.22.1": + version: 1.22.10 + resolution: "resolve@npm:1.22.10" + dependencies: + is-core-module: "npm:^2.16.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/8967e1f4e2cc40f79b7e080b4582b9a8c5ee36ffb46041dccb20e6461161adf69f843b43067b4a375de926a2cd669157e29a29578191def399dd5ef89a1b5203 + languageName: node + linkType: hard + +"resolve@patch:resolve@npm%3A^1.22.1#optional!builtin": + version: 1.22.10 + resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.16.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/52a4e505bbfc7925ac8f4cd91fd8c4e096b6a89728b9f46861d3b405ac9a1ccf4dcbf8befb4e89a2e11370dacd0160918163885cbc669369590f2f31f4c58939 + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe + languageName: node + linkType: hard + +"rollup@npm:^4.9.6": + version: 4.50.1 + resolution: "rollup@npm:4.50.1" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.50.1" + "@rollup/rollup-android-arm64": "npm:4.50.1" + "@rollup/rollup-darwin-arm64": "npm:4.50.1" + "@rollup/rollup-darwin-x64": "npm:4.50.1" + "@rollup/rollup-freebsd-arm64": "npm:4.50.1" + "@rollup/rollup-freebsd-x64": "npm:4.50.1" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.50.1" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.50.1" + "@rollup/rollup-linux-arm64-gnu": "npm:4.50.1" + "@rollup/rollup-linux-arm64-musl": "npm:4.50.1" + "@rollup/rollup-linux-loongarch64-gnu": "npm:4.50.1" + "@rollup/rollup-linux-ppc64-gnu": "npm:4.50.1" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.50.1" + "@rollup/rollup-linux-riscv64-musl": "npm:4.50.1" + "@rollup/rollup-linux-s390x-gnu": "npm:4.50.1" + "@rollup/rollup-linux-x64-gnu": "npm:4.50.1" + "@rollup/rollup-linux-x64-musl": "npm:4.50.1" + "@rollup/rollup-openharmony-arm64": "npm:4.50.1" + "@rollup/rollup-win32-arm64-msvc": "npm:4.50.1" + "@rollup/rollup-win32-ia32-msvc": "npm:4.50.1" + "@rollup/rollup-win32-x64-msvc": "npm:4.50.1" + "@types/estree": "npm:1.0.8" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-freebsd-arm64": + optional: true + "@rollup/rollup-freebsd-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-loongarch64-gnu": + optional: true + "@rollup/rollup-linux-ppc64-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-riscv64-musl": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-openharmony-arm64": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 10c0/2029282826d5fb4e308be261b2c28329a4d2bd34304cc3960da69fd21d5acccd0267d6770b1656ffc8f166203ef7e865b4583d5f842a519c8ef059ac71854205 + languageName: node + linkType: hard + +"root-workspace-0b6124@workspace:.": + version: 0.0.0-use.local + resolution: "root-workspace-0b6124@workspace:." + languageName: unknown + linkType: soft + +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"semver@npm:^7.3.5": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.5 + resolution: "socks-proxy-agent@npm:8.0.5" + dependencies: + agent-base: "npm:^7.1.2" + debug: "npm:^4.3.4" + socks: "npm:^2.8.3" + checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 + languageName: node + linkType: hard + +"socks@npm:^2.8.3": + version: 2.8.7 + resolution: "socks@npm:2.8.7" + dependencies: + ip-address: "npm:^10.0.1" + smart-buffer: "npm:^4.2.0" + checksum: 10c0/2805a43a1c4bcf9ebf6e018268d87b32b32b06fbbc1f9282573583acc155860dc361500f89c73bfbb157caa1b4ac78059eac0ef15d1811eb0ca75e0bdadbc9d2 + languageName: node + linkType: hard + +"ssri@npm:^12.0.0": + version: 12.0.0 + resolution: "ssri@npm:12.0.0" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: "npm:^8.0.0" + is-fullwidth-code-point: "npm:^3.0.0" + strip-ansi: "npm:^6.0.1" + checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: "npm:^0.2.0" + emoji-regex: "npm:^9.2.2" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: "npm:^5.0.1" + checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.2 + resolution: "strip-ansi@npm:7.1.2" + dependencies: + ansi-regex: "npm:^6.0.1" + checksum: 10c0/0d6d7a023de33368fd042aab0bf48f4f4077abdfd60e5393e73c7c411e85e1b3a83507c11af2e656188511475776215df9ca589b4da2295c9455cc399ce1858b + languageName: node + linkType: hard + +"supports-preserve-symlinks-flag@npm:^1.0.0": + version: 1.0.0 + resolution: "supports-preserve-symlinks-flag@npm:1.0.0" + checksum: 10c0/6c4032340701a9950865f7ae8ef38578d8d7053f5e10518076e6554a9381fa91bd9c6850193695c141f32b21f979c985db07265a758867bac95de05f7d8aeb39 + languageName: node + linkType: hard + +"tar@npm:^7.4.3": + version: 7.4.3 + resolution: "tar@npm:7.4.3" + dependencies: + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^7.1.2" + minizlib: "npm:^3.0.1" + mkdirp: "npm:^3.0.1" + yallist: "npm:^5.0.0" + checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d + languageName: node + linkType: hard + +"tinyglobby@npm:^0.2.12": + version: 0.2.15 + resolution: "tinyglobby@npm:0.2.15" + dependencies: + fdir: "npm:^6.5.0" + picomatch: "npm:^4.0.3" + checksum: 10c0/869c31490d0d88eedb8305d178d4c75e7463e820df5a9b9d388291daf93e8b1eb5de1dad1c1e139767e4269fe75f3b10d5009b2cc14db96ff98986920a186844 + languageName: node + linkType: hard + +"tslib@npm:^2.6.2": + version: 2.8.1 + resolution: "tslib@npm:2.8.1" + checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 + languageName: node + linkType: hard + +"typescript@npm:^5.3.3": + version: 5.9.2 + resolution: "typescript@npm:5.9.2" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/cd635d50f02d6cf98ed42de2f76289701c1ec587a363369255f01ed15aaf22be0813226bff3c53e99d971f9b540e0b3cc7583dbe05faded49b1b0bed2f638a18 + languageName: node + linkType: hard + +"typescript@patch:typescript@npm%3A^5.3.3#optional!builtin": + version: 5.9.2 + resolution: "typescript@patch:typescript@npm%3A5.9.2#optional!builtin::version=5.9.2&hash=5786d5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/34d2a8e23eb8e0d1875072064d5e1d9c102e0bdce56a10a25c0b917b8aa9001a9cf5c225df12497e99da107dc379360bc138163c66b55b95f5b105b50578067e + languageName: node + linkType: hard + +"unique-filename@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-filename@npm:4.0.0" + dependencies: + unique-slug: "npm:^5.0.0" + checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc + languageName: node + linkType: hard + +"unique-slug@npm:^5.0.0": + version: 5.0.0 + resolution: "unique-slug@npm:5.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293 + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f + languageName: node + linkType: hard + +"which@npm:^5.0.0": + version: 5.0.0 + resolution: "which@npm:5.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: "npm:^6.1.0" + string-width: "npm:^5.0.1" + strip-ansi: "npm:^7.0.1" + checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a + languageName: node + linkType: hard + +"yallist@npm:^5.0.0": + version: 5.0.0 + resolution: "yallist@npm:5.0.0" + checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 + languageName: node + linkType: hard diff --git a/yarn.lock b/yarn.lock index b0b2ce70ce..b66b7f4183 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3464,6 +3464,7 @@ __metadata: resolution: "@jan/extensions-web@workspace:extensions-web" dependencies: "@janhq/core": "workspace:*" + "@modelcontextprotocol/sdk": "npm:^1.17.5" typescript: "npm:^5.3.3" vite: "npm:^5.0.0" vitest: "npm:^2.0.0" @@ -3590,6 +3591,7 @@ __metadata: react-textarea-autosize: "npm:^8.5.9" rehype-katex: "npm:^7.0.1" rehype-raw: "npm:^7.0.0" + remark-breaks: "npm:^4.0.0" remark-emoji: "npm:^5.0.1" remark-gfm: "npm:^4.0.1" remark-math: "npm:^6.0.0" @@ -3721,6 +3723,26 @@ __metadata: languageName: node linkType: hard +"@modelcontextprotocol/sdk@npm:^1.17.5": + version: 1.17.5 + resolution: "@modelcontextprotocol/sdk@npm:1.17.5" + dependencies: + ajv: "npm:^6.12.6" + content-type: "npm:^1.0.5" + cors: "npm:^2.8.5" + cross-spawn: "npm:^7.0.5" + eventsource: "npm:^3.0.2" + eventsource-parser: "npm:^3.0.0" + express: "npm:^5.0.1" + express-rate-limit: "npm:^7.5.0" + pkce-challenge: "npm:^5.0.0" + raw-body: "npm:^3.0.0" + zod: "npm:^3.23.8" + zod-to-json-schema: "npm:^3.24.1" + checksum: 10c0/182b92b5e7c07da428fd23c6de22021c4f9a91f799c02a8ef15def07e4f9361d0fc22303548658fec2a700623535fd44a9dc4d010fb5d803a8f80e3c6c64a45e + languageName: node + linkType: hard + "@napi-rs/wasm-runtime@npm:^0.2.4": version: 0.2.7 resolution: "@napi-rs/wasm-runtime@npm:0.2.7" @@ -8356,6 +8378,16 @@ __metadata: languageName: node linkType: hard +"accepts@npm:^2.0.0": + version: 2.0.0 + resolution: "accepts@npm:2.0.0" + dependencies: + mime-types: "npm:^3.0.0" + negotiator: "npm:^1.0.0" + checksum: 10c0/98374742097e140891546076215f90c32644feacf652db48412329de4c2a529178a81aa500fbb13dd3e6cbf6e68d829037b123ac037fc9a08bcec4b87b358eef + languageName: node + linkType: hard + "acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -8430,7 +8462,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.12.3, ajv@npm:^6.12.4": +"ajv@npm:^6.12.3, ajv@npm:^6.12.4, ajv@npm:^6.12.6": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -8967,6 +8999,23 @@ __metadata: languageName: node linkType: hard +"body-parser@npm:^2.2.0": + version: 2.2.0 + resolution: "body-parser@npm:2.2.0" + dependencies: + bytes: "npm:^3.1.2" + content-type: "npm:^1.0.5" + debug: "npm:^4.4.0" + http-errors: "npm:^2.0.0" + iconv-lite: "npm:^0.6.3" + on-finished: "npm:^2.4.1" + qs: "npm:^6.14.0" + raw-body: "npm:^3.0.0" + type-is: "npm:^2.0.0" + checksum: 10c0/a9ded39e71ac9668e2211afa72e82ff86cc5ef94de1250b7d1ba9cc299e4150408aaa5f1e8b03dd4578472a3ce6d1caa2a23b27a6c18e526e48b4595174c116c + languageName: node + linkType: hard + "bowser@npm:^2.11.0": version: 2.11.0 resolution: "bowser@npm:2.11.0" @@ -9221,7 +9270,7 @@ __metadata: languageName: node linkType: hard -"bytes@npm:3.1.2": +"bytes@npm:3.1.2, bytes@npm:^3.1.2": version: 3.1.2 resolution: "bytes@npm:3.1.2" checksum: 10c0/76d1c43cbd602794ad8ad2ae94095cddeb1de78c5dddaa7005c51af10b0176c69971a6d88e805a90c2b6550d76636e43c40d8427a808b8645ede885de4a0358e @@ -9798,6 +9847,22 @@ __metadata: languageName: node linkType: hard +"content-disposition@npm:^1.0.0": + version: 1.0.0 + resolution: "content-disposition@npm:1.0.0" + dependencies: + safe-buffer: "npm:5.2.1" + checksum: 10c0/c7b1ba0cea2829da0352ebc1b7f14787c73884bc707c8bc2271d9e3bf447b372270d09f5d3980dc5037c749ceef56b9a13fccd0b0001c87c3f12579967e4dd27 + languageName: node + linkType: hard + +"content-type@npm:^1.0.5": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af + languageName: node + linkType: hard + "convert-source-map@npm:^2.0.0": version: 2.0.0 resolution: "convert-source-map@npm:2.0.0" @@ -9805,6 +9870,20 @@ __metadata: languageName: node linkType: hard +"cookie-signature@npm:^1.2.1": + version: 1.2.2 + resolution: "cookie-signature@npm:1.2.2" + checksum: 10c0/54e05df1a293b3ce81589b27dddc445f462f6fa6812147c033350cd3561a42bc14481674e05ed14c7bd0ce1e8bb3dc0e40851bad75415733711294ddce0b7bc6 + languageName: node + linkType: hard + +"cookie@npm:^0.7.1": + version: 0.7.2 + resolution: "cookie@npm:0.7.2" + checksum: 10c0/9596e8ccdbf1a3a88ae02cf5ee80c1c50959423e1022e4e60b91dd87c622af1da309253d8abdb258fb5e3eacb4f08e579dc58b4897b8087574eee0fd35dfa5d2 + languageName: node + linkType: hard + "copy-descriptor@npm:^0.1.0": version: 0.1.1 resolution: "copy-descriptor@npm:0.1.1" @@ -9849,6 +9928,16 @@ __metadata: languageName: node linkType: hard +"cors@npm:^2.8.5": + version: 2.8.5 + resolution: "cors@npm:2.8.5" + dependencies: + object-assign: "npm:^4" + vary: "npm:^1" + checksum: 10c0/373702b7999409922da80de4a61938aabba6929aea5b6fd9096fefb9e8342f626c0ebd7507b0e8b0b311380744cc985f27edebc0a26e0ddb784b54e1085de761 + languageName: node + linkType: hard + "cpx@npm:^1.5.0": version: 1.5.0 resolution: "cpx@npm:1.5.0" @@ -9938,7 +10027,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6": +"cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.5, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -10089,7 +10178,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:^4.3.7, debug@npm:^4.4.1": +"debug@npm:^4.3.5, debug@npm:^4.3.7, debug@npm:^4.4.0, debug@npm:^4.4.1": version: 4.4.1 resolution: "debug@npm:4.4.1" dependencies: @@ -10225,6 +10314,13 @@ __metadata: languageName: node linkType: hard +"depd@npm:2.0.0, depd@npm:^2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: 10c0/58bd06ec20e19529b06f7ad07ddab60e504d9e0faca4bd23079fac2d279c3594334d736508dc350e06e510aba5e22e4594483b3a6562ce7c17dd797f4cc4ad2c + languageName: node + linkType: hard + "dequal@npm:^2.0.0, dequal@npm:^2.0.3": version: 2.0.3 resolution: "dequal@npm:2.0.3" @@ -10376,6 +10472,13 @@ __metadata: languageName: node linkType: hard +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 10c0/b5bb125ee93161bc16bfe6e56c6b04de5ad2aa44234d8f644813cc95d861a6910903132b05093706de2b706599367c4130eb6d170f6b46895686b95f87d017b7 + languageName: node + linkType: hard + "ejs@npm:^3.1.6": version: 3.1.10 resolution: "ejs@npm:3.1.10" @@ -10455,6 +10558,13 @@ __metadata: languageName: node linkType: hard +"encodeurl@npm:^2.0.0": + version: 2.0.0 + resolution: "encodeurl@npm:2.0.0" + checksum: 10c0/5d317306acb13e6590e28e27924c754163946a2480de11865c991a3a7eed4315cd3fba378b543ca145829569eefe9b899f3d84bb09870f675ae60bc924b01ceb + languageName: node + linkType: hard + "encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -10790,6 +10900,13 @@ __metadata: languageName: node linkType: hard +"escape-html@npm:^1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 10c0/524c739d776b36c3d29fa08a22e03e8824e3b2fd57500e5e44ecf3cc4707c34c60f9ca0781c0e33d191f2991161504c295e98f68c78fe7baa6e57081ec6ac0a3 + languageName: node + linkType: hard + "escape-string-regexp@npm:^4.0.0": version: 4.0.0 resolution: "escape-string-regexp@npm:4.0.0" @@ -11048,6 +11165,13 @@ __metadata: languageName: node linkType: hard +"etag@npm:^1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 10c0/12be11ef62fb9817314d790089a0a49fae4e1b50594135dcb8076312b7d7e470884b5100d249b28c18581b7fd52f8b485689ffae22a11ed9ec17377a33a08f84 + languageName: node + linkType: hard + "event-target-shim@npm:^5.0.0": version: 5.0.1 resolution: "event-target-shim@npm:5.0.1" @@ -11062,6 +11186,22 @@ __metadata: languageName: node linkType: hard +"eventsource-parser@npm:^3.0.0, eventsource-parser@npm:^3.0.1": + version: 3.0.6 + resolution: "eventsource-parser@npm:3.0.6" + checksum: 10c0/70b8ccec7dac767ef2eca43f355e0979e70415701691382a042a2df8d6a68da6c2fca35363669821f3da876d29c02abe9b232964637c1b6635c940df05ada78a + languageName: node + linkType: hard + +"eventsource@npm:^3.0.2": + version: 3.0.7 + resolution: "eventsource@npm:3.0.7" + dependencies: + eventsource-parser: "npm:^3.0.1" + checksum: 10c0/c48a73c38f300e33e9f11375d4ee969f25cbb0519608a12378a38068055ae8b55b6e0e8a49c3f91c784068434efe1d9f01eb49b6315b04b0da9157879ce2f67d + languageName: node + linkType: hard + "evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": version: 1.0.3 resolution: "evp_bytestokey@npm:1.0.3" @@ -11144,6 +11284,50 @@ __metadata: languageName: node linkType: hard +"express-rate-limit@npm:^7.5.0": + version: 7.5.1 + resolution: "express-rate-limit@npm:7.5.1" + peerDependencies: + express: ">= 4.11" + checksum: 10c0/b07de84d700a2c07c4bf2f040e7558ed5a1f660f03ed5f30bf8ff7b51e98ba7a85215640e70fc48cbbb9151066ea51239d9a1b41febc9b84d98c7915b0186161 + languageName: node + linkType: hard + +"express@npm:^5.0.1": + version: 5.1.0 + resolution: "express@npm:5.1.0" + dependencies: + accepts: "npm:^2.0.0" + body-parser: "npm:^2.2.0" + content-disposition: "npm:^1.0.0" + content-type: "npm:^1.0.5" + cookie: "npm:^0.7.1" + cookie-signature: "npm:^1.2.1" + debug: "npm:^4.4.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + etag: "npm:^1.8.1" + finalhandler: "npm:^2.1.0" + fresh: "npm:^2.0.0" + http-errors: "npm:^2.0.0" + merge-descriptors: "npm:^2.0.0" + mime-types: "npm:^3.0.0" + on-finished: "npm:^2.4.1" + once: "npm:^1.4.0" + parseurl: "npm:^1.3.3" + proxy-addr: "npm:^2.0.7" + qs: "npm:^6.14.0" + range-parser: "npm:^1.2.1" + router: "npm:^2.2.0" + send: "npm:^1.1.0" + serve-static: "npm:^2.2.0" + statuses: "npm:^2.0.1" + type-is: "npm:^2.0.1" + vary: "npm:^1.1.2" + checksum: 10c0/80ce7c53c5f56887d759b94c3f2283e2e51066c98d4b72a4cc1338e832b77f1e54f30d0239cc10815a0f849bdb753e6a284d2fa48d4ab56faf9c501f55d751d6 + languageName: node + linkType: hard + "extend-shallow@npm:^2.0.1": version: 2.0.1 resolution: "extend-shallow@npm:2.0.1" @@ -11425,6 +11609,20 @@ __metadata: languageName: node linkType: hard +"finalhandler@npm:^2.1.0": + version: 2.1.0 + resolution: "finalhandler@npm:2.1.0" + dependencies: + debug: "npm:^4.4.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + on-finished: "npm:^2.4.1" + parseurl: "npm:^1.3.3" + statuses: "npm:^2.0.1" + checksum: 10c0/da0bbca6d03873472ee890564eb2183f4ed377f25f3628a0fc9d16dac40bed7b150a0d82ebb77356e4c6d97d2796ad2dba22948b951dddee2c8768b0d1b9fb1f + languageName: node + linkType: hard + "find-index@npm:^0.1.1": version: 0.1.1 resolution: "find-index@npm:0.1.1" @@ -11591,6 +11789,13 @@ __metadata: languageName: node linkType: hard +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: 10c0/9b67c3fac86acdbc9ae47ba1ddd5f2f81526fa4c8226863ede5600a3f7c7416ef451f6f1e240a3cc32d0fd79fcfe6beb08fd0da454f360032bde70bf80afbb33 + languageName: node + linkType: hard + "fragment-cache@npm:^0.2.1": version: 0.2.1 resolution: "fragment-cache@npm:0.2.1" @@ -11644,6 +11849,13 @@ __metadata: languageName: node linkType: hard +"fresh@npm:^2.0.0": + version: 2.0.0 + resolution: "fresh@npm:2.0.0" + checksum: 10c0/0557548194cb9a809a435bf92bcfbc20c89e8b5eb38861b73ced36750437251e39a111fc3a18b98531be9dd91fe1411e4969f229dc579ec0251ce6c5d4900bbc + languageName: node + linkType: hard + "fs-extra@npm:^11.2.0": version: 11.3.0 resolution: "fs-extra@npm:11.3.0" @@ -12593,6 +12805,19 @@ __metadata: languageName: node linkType: hard +"http-errors@npm:2.0.0, http-errors@npm:^2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: "npm:2.0.0" + inherits: "npm:2.0.4" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + toidentifier: "npm:1.0.1" + checksum: 10c0/fc6f2715fe188d091274b5ffc8b3657bd85c63e969daa68ccb77afb05b071a4b62841acb7a21e417b5539014dff2ebf9550f0b14a9ff126f2734a7c1387f8e19 + languageName: node + linkType: hard + "http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.2": version: 7.0.2 resolution: "http-proxy-agent@npm:7.0.2" @@ -12670,7 +12895,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": +"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" dependencies: @@ -12679,6 +12904,15 @@ __metadata: languageName: node linkType: hard +"iconv-lite@npm:0.7.0": + version: 0.7.0 + resolution: "iconv-lite@npm:0.7.0" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/2382400469071c55b6746c531eed5fa4d033e5db6690b7331fb2a5f59a30d7a9782932e92253db26df33c1cf46fa200a3fbe524a2a7c62037c762283f188ec2f + languageName: node + linkType: hard + "idb@npm:^7.0.1": version: 7.1.1 resolution: "idb@npm:7.1.1" @@ -12752,7 +12986,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -12808,6 +13042,13 @@ __metadata: languageName: node linkType: hard +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: 10c0/0486e775047971d3fdb5fb4f063829bac45af299ae0b82dcf3afa2145338e08290563a2a70f34b732d795ecc8311902e541a8530eeb30d75860a78ff4e94ce2a + languageName: node + linkType: hard + "is-accessor-descriptor@npm:^1.0.1": version: 1.0.1 resolution: "is-accessor-descriptor@npm:1.0.1" @@ -13276,6 +13517,13 @@ __metadata: languageName: node linkType: hard +"is-promise@npm:^4.0.0": + version: 4.0.0 + resolution: "is-promise@npm:4.0.0" + checksum: 10c0/ebd5c672d73db781ab33ccb155fb9969d6028e37414d609b115cc534654c91ccd061821d5b987eefaa97cf4c62f0b909bb2f04db88306de26e91bfe8ddc01503 + languageName: node + linkType: hard + "is-regex@npm:^1.2.1": version: 1.2.1 resolution: "is-regex@npm:1.2.1" @@ -13625,6 +13873,7 @@ __metadata: cpx: "npm:^1.5.0" cross-env: "npm:^7.0.3" husky: "npm:^9.1.5" + jsdom: "npm:^26.1.0" rimraf: "npm:^3.0.2" run-script-os: "npm:^1.1.6" tar: "npm:^4.4.19" @@ -14549,6 +14798,16 @@ __metadata: languageName: node linkType: hard +"mdast-util-newline-to-break@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-newline-to-break@npm:2.0.0" + dependencies: + "@types/mdast": "npm:^4.0.0" + mdast-util-find-and-replace: "npm:^3.0.0" + checksum: 10c0/756a5660b0a821e0d6d6a0b2d9b13ac32e41cc028c485a91bccf6300977e2557236c6cc93dbd55c68b785f1ed6eae69209a4ffe182533cd1cdfda369021bebd2 + languageName: node + linkType: hard + "mdast-util-phrasing@npm:^4.0.0": version: 4.1.0 resolution: "mdast-util-phrasing@npm:4.1.0" @@ -14602,6 +14861,20 @@ __metadata: languageName: node linkType: hard +"media-typer@npm:^1.1.0": + version: 1.1.0 + resolution: "media-typer@npm:1.1.0" + checksum: 10c0/7b4baa40b25964bb90e2121ee489ec38642127e48d0cc2b6baa442688d3fde6262bfdca86d6bbf6ba708784afcac168c06840c71facac70e390f5f759ac121b9 + languageName: node + linkType: hard + +"merge-descriptors@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-descriptors@npm:2.0.0" + checksum: 10c0/95389b7ced3f9b36fbdcf32eb946dc3dd1774c2fdf164609e55b18d03aa499b12bd3aae3a76c1c7185b96279e9803525550d3eb292b5224866060a288f335cb3 + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -15031,7 +15304,7 @@ __metadata: languageName: node linkType: hard -"mime-db@npm:>= 1.43.0 < 2": +"mime-db@npm:>= 1.43.0 < 2, mime-db@npm:^1.54.0": version: 1.54.0 resolution: "mime-db@npm:1.54.0" checksum: 10c0/8d907917bc2a90fa2df842cdf5dfeaf509adc15fe0531e07bb2f6ab15992416479015828d6a74200041c492e42cce3ebf78e5ce714388a0a538ea9c53eece284 @@ -15063,6 +15336,15 @@ __metadata: languageName: node linkType: hard +"mime-types@npm:^3.0.0, mime-types@npm:^3.0.1": + version: 3.0.1 + resolution: "mime-types@npm:3.0.1" + dependencies: + mime-db: "npm:^1.54.0" + checksum: 10c0/bd8c20d3694548089cf229016124f8f40e6a60bbb600161ae13e45f793a2d5bb40f96bbc61f275836696179c77c1d6bf4967b2a75e0a8ad40fe31f4ed5be4da5 + languageName: node + linkType: hard + "mimic-fn@npm:^2.1.0": version: 2.1.0 resolution: "mimic-fn@npm:2.1.0" @@ -15803,7 +16085,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.1.1": +"object-assign@npm:^4, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 @@ -15887,6 +16169,15 @@ __metadata: languageName: node linkType: hard +"on-finished@npm:^2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: "npm:1.1.1" + checksum: 10c0/46fb11b9063782f2d9968863d9cbba33d77aa13c17f895f56129c274318b86500b22af3a160fe9995aa41317efcd22941b6eba747f718ced08d9a73afdb087b4 + languageName: node + linkType: hard + "on-headers@npm:~1.1.0": version: 1.1.0 resolution: "on-headers@npm:1.1.0" @@ -16171,6 +16462,13 @@ __metadata: languageName: node linkType: hard +"parseurl@npm:^1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 10c0/90dd4760d6f6174adb9f20cf0965ae12e23879b5f5464f38e92fce8073354341e4b3b76fa3d878351efe7d01e617121955284cfd002ab087fba1a0726ec0b4f5 + languageName: node + linkType: hard + "pascalcase@npm:^0.1.1": version: 0.1.1 resolution: "pascalcase@npm:0.1.1" @@ -16247,6 +16545,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:^8.0.0": + version: 8.3.0 + resolution: "path-to-regexp@npm:8.3.0" + checksum: 10c0/ee1544a73a3f294a97a4c663b0ce71bbf1621d732d80c9c9ed201b3e911a86cb628ebad691b9d40f40a3742fe22011e5a059d8eed2cf63ec2cb94f6fb4efe67c + languageName: node + linkType: hard + "pathe@npm:^1.1.2": version: 1.1.2 resolution: "pathe@npm:1.1.2" @@ -16324,6 +16629,13 @@ __metadata: languageName: node linkType: hard +"pkce-challenge@npm:^5.0.0": + version: 5.0.0 + resolution: "pkce-challenge@npm:5.0.0" + checksum: 10c0/c6706d627fdbb6f22bf8cc5d60d96d6b6a7bb481399b336a3d3f4e9bfba3e167a2c32f8ec0b5e74be686a0ba3bcc9894865d4c2dd1b91cea4c05dba1f28602c3 + languageName: node + linkType: hard + "pkg-dir@npm:^5.0.0": version: 5.0.0 resolution: "pkg-dir@npm:5.0.0" @@ -16575,6 +16887,16 @@ __metadata: languageName: node linkType: hard +"proxy-addr@npm:^2.0.7": + version: 2.0.7 + resolution: "proxy-addr@npm:2.0.7" + dependencies: + forwarded: "npm:0.2.0" + ipaddr.js: "npm:1.9.1" + checksum: 10c0/c3eed999781a35f7fd935f398b6d8920b6fb00bbc14287bc6de78128ccc1a02c89b95b56742bf7cf0362cc333c61d138532049c7dedc7a328ef13343eff81210 + languageName: node + linkType: hard + "psl@npm:^1.1.28": version: 1.15.0 resolution: "psl@npm:1.15.0" @@ -16621,7 +16943,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.12.3": +"qs@npm:^6.12.3, qs@npm:^6.14.0": version: 6.14.0 resolution: "qs@npm:6.14.0" dependencies: @@ -16688,6 +17010,25 @@ __metadata: languageName: node linkType: hard +"range-parser@npm:^1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 10c0/96c032ac2475c8027b7a4e9fe22dc0dfe0f6d90b85e496e0f016fbdb99d6d066de0112e680805075bd989905e2123b3b3d002765149294dce0c1f7f01fcc2ea0 + languageName: node + linkType: hard + +"raw-body@npm:^3.0.0": + version: 3.0.1 + resolution: "raw-body@npm:3.0.1" + dependencies: + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.7.0" + unpipe: "npm:1.0.0" + checksum: 10c0/892f4fbd21ecab7e2fed0f045f7af9e16df7e8050879639d4e482784a2f4640aaaa33d916a0e98013f23acb82e09c2e3c57f84ab97104449f728d22f65a7d79a + languageName: node + linkType: hard + "rc@npm:^1.0.1, rc@npm:^1.1.6": version: 1.2.8 resolution: "rc@npm:1.2.8" @@ -17295,6 +17636,17 @@ __metadata: languageName: node linkType: hard +"remark-breaks@npm:^4.0.0": + version: 4.0.0 + resolution: "remark-breaks@npm:4.0.0" + dependencies: + "@types/mdast": "npm:^4.0.0" + mdast-util-newline-to-break: "npm:^2.0.0" + unified: "npm:^11.0.0" + checksum: 10c0/d7b319a7993b54c5d574e9255080c5de68cfa24f993873b0ee296af13f478521c41d4b7ae0fc14b4607ea70c8f6967e998ab7a467de13139141e66a1a34cb6be + languageName: node + linkType: hard + "remark-emoji@npm:^5.0.1": version: 5.0.1 resolution: "remark-emoji@npm:5.0.1" @@ -17863,6 +18215,19 @@ __metadata: languageName: node linkType: hard +"router@npm:^2.2.0": + version: 2.2.0 + resolution: "router@npm:2.2.0" + dependencies: + debug: "npm:^4.4.0" + depd: "npm:^2.0.0" + is-promise: "npm:^4.0.0" + parseurl: "npm:^1.3.3" + path-to-regexp: "npm:^8.0.0" + checksum: 10c0/3279de7450c8eae2f6e095e9edacbdeec0abb5cb7249c6e719faa0db2dba43574b4fff5892d9220631c9abaff52dd3cad648cfea2aaace845e1a071915ac8867 + languageName: node + linkType: hard + "rrweb-cssom@npm:^0.8.0": version: 0.8.0 resolution: "rrweb-cssom@npm:0.8.0" @@ -18019,6 +18384,25 @@ __metadata: languageName: node linkType: hard +"send@npm:^1.1.0, send@npm:^1.2.0": + version: 1.2.0 + resolution: "send@npm:1.2.0" + dependencies: + debug: "npm:^4.3.5" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + etag: "npm:^1.8.1" + fresh: "npm:^2.0.0" + http-errors: "npm:^2.0.0" + mime-types: "npm:^3.0.1" + ms: "npm:^2.1.3" + on-finished: "npm:^2.4.1" + range-parser: "npm:^1.2.1" + statuses: "npm:^2.0.1" + checksum: 10c0/531bcfb5616948d3468d95a1fd0adaeb0c20818ba4a500f439b800ca2117971489e02074ce32796fd64a6772ea3e7235fe0583d8241dbd37a053dc3378eff9a5 + languageName: node + linkType: hard + "serialize-javascript@npm:^6.0.1": version: 6.0.2 resolution: "serialize-javascript@npm:6.0.2" @@ -18059,6 +18443,18 @@ __metadata: languageName: node linkType: hard +"serve-static@npm:^2.2.0": + version: 2.2.0 + resolution: "serve-static@npm:2.2.0" + dependencies: + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + parseurl: "npm:^1.3.3" + send: "npm:^1.2.0" + checksum: 10c0/30e2ed1dbff1984836cfd0c65abf5d3f3f83bcd696c99d2d3c97edbd4e2a3ff4d3f87108a7d713640d290a7b6fe6c15ddcbc61165ab2eaad48ea8d3b52c7f913 + languageName: node + linkType: hard + "serve@npm:^14.2.4": version: 14.2.5 resolution: "serve@npm:14.2.5" @@ -18136,6 +18532,13 @@ __metadata: languageName: node linkType: hard +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: 10c0/68733173026766fa0d9ecaeb07f0483f4c2dc70ca376b3b7c40b7cda909f94b0918f6c5ad5ce27a9160bdfb475efaa9d5e705a11d8eaae18f9835d20976028bc + languageName: node + linkType: hard + "sha.js@npm:^2.4.0, sha.js@npm:^2.4.11, sha.js@npm:^2.4.8": version: 2.4.11 resolution: "sha.js@npm:2.4.11" @@ -18574,6 +18977,20 @@ __metadata: languageName: node linkType: hard +"statuses@npm:2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 10c0/34378b207a1620a24804ce8b5d230fea0c279f00b18a7209646d5d47e419d1cc23e7cbf33a25a1e51ac38973dc2ac2e1e9c647a8e481ef365f77668d72becfd0 + languageName: node + linkType: hard + +"statuses@npm:^2.0.1": + version: 2.0.2 + resolution: "statuses@npm:2.0.2" + checksum: 10c0/a9947d98ad60d01f6b26727570f3bcceb6c8fa789da64fe6889908fe2e294d57503b14bf2b5af7605c2d36647259e856635cd4c49eab41667658ec9d0080ec3f + languageName: node + linkType: hard + "std-env@npm:^3.8.0, std-env@npm:^3.9.0": version: 3.9.0 resolution: "std-env@npm:3.9.0" @@ -19154,6 +19571,13 @@ __metadata: languageName: node linkType: hard +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 10c0/93937279934bd66cc3270016dd8d0afec14fb7c94a05c72dc57321f8bd1fa97e5bea6d1f7c89e728d077ca31ea125b78320a616a6c6cd0e6b9cb94cb864381c1 + languageName: node + linkType: hard + "token.js@npm:token.js-fork@0.7.23": version: 0.7.23 resolution: "token.js-fork@npm:0.7.23" @@ -19391,6 +19815,17 @@ __metadata: languageName: node linkType: hard +"type-is@npm:^2.0.0, type-is@npm:^2.0.1": + version: 2.0.1 + resolution: "type-is@npm:2.0.1" + dependencies: + content-type: "npm:^1.0.5" + media-typer: "npm:^1.1.0" + mime-types: "npm:^3.0.0" + checksum: 10c0/7f7ec0a060b16880bdad36824ab37c26019454b67d73e8a465ed5a3587440fbe158bc765f0da68344498235c877e7dbbb1600beccc94628ed05599d667951b99 + languageName: node + linkType: hard + "typed-array-buffer@npm:^1.0.3": version: 1.0.3 resolution: "typed-array-buffer@npm:1.0.3" @@ -19736,6 +20171,13 @@ __metadata: languageName: node linkType: hard +"unpipe@npm:1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c + languageName: node + linkType: hard + "unplugin@npm:^2.1.2": version: 2.3.2 resolution: "unplugin@npm:2.3.2" @@ -20004,7 +20446,7 @@ __metadata: languageName: node linkType: hard -"vary@npm:~1.1.2": +"vary@npm:^1, vary@npm:^1.1.2, vary@npm:~1.1.2": version: 1.1.2 resolution: "vary@npm:1.1.2" checksum: 10c0/f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f @@ -20941,6 +21383,15 @@ __metadata: languageName: node linkType: hard +"zod-to-json-schema@npm:^3.24.1": + version: 3.24.6 + resolution: "zod-to-json-schema@npm:3.24.6" + peerDependencies: + zod: ^3.24.1 + checksum: 10c0/b907ab6d057100bd25a37e5545bf5f0efa5902cd84d3c3ec05c2e51541431a47bd9bf1e5e151a244273409b45f5986d55b26e5d207f98abc5200702f733eb368 + languageName: node + linkType: hard + "zod@npm:^3.23.8": version: 3.24.2 resolution: "zod@npm:3.24.2" From 651ac308c262a29250b2bfd67a792ca62fd85e11 Mon Sep 17 00:00:00 2001 From: Dinh Long Nguyen Date: Fri, 12 Sep 2025 10:14:30 +0700 Subject: [PATCH 5/5] use mcp oauth properly --- extensions-web/src/mcp-web/index.ts | 88 +++----------------- extensions-web/src/mcp-web/oauth-provider.ts | 60 +++++++++++++ extensions-web/src/shared/auth.ts | 8 -- 3 files changed, 73 insertions(+), 83 deletions(-) create mode 100644 extensions-web/src/mcp-web/oauth-provider.ts diff --git a/extensions-web/src/mcp-web/index.ts b/extensions-web/src/mcp-web/index.ts index 205c1042a1..5b55643d4c 100644 --- a/extensions-web/src/mcp-web/index.ts +++ b/extensions-web/src/mcp-web/index.ts @@ -8,6 +8,7 @@ import { MCPExtension, MCPTool, MCPToolCallResult } from '@janhq/core' import { JanAuthService } from '../shared/auth' import { Client } from '@modelcontextprotocol/sdk/client/index.js' import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js' +import { JanMCPOAuthProvider } from './oauth-provider' // JAN_API_BASE is defined in vite.config.ts (defaults to 'https://api-dev.jan.ai/jan/v1') declare const JAN_API_BASE: string @@ -18,7 +19,7 @@ export default class MCPExtensionWeb extends MCPExtension { private initialized = false private authService: JanAuthService private mcpClient: Client | null = null - private tokenUpdateListener: (() => void) | null = null + private oauthProvider: JanMCPOAuthProvider constructor( url: string, @@ -30,16 +31,15 @@ export default class MCPExtensionWeb extends MCPExtension { ) { super(url, name, productName, active, description, version) this.authService = JanAuthService.getInstance() + this.oauthProvider = new JanMCPOAuthProvider(this.authService) } async onLoad(): Promise { try { // Initialize authentication first await this.authService.initialize() - // Initialize MCP client + // Initialize MCP client with OAuth await this.initializeMCPClient() - // Set up localStorage monitoring for token changes - this.setupTokenMonitoring() // Then fetch tools await this.initializeTools() } catch (error) { @@ -52,13 +52,7 @@ export default class MCPExtensionWeb extends MCPExtension { this.tools = [] this.initialized = false - // Remove token update event listener - if (this.tokenUpdateListener) { - window.removeEventListener('jan-auth-token-updated', this.tokenUpdateListener as EventListener) - this.tokenUpdateListener = null - } - - // Properly close MCP client to avoid session errors + // Close MCP client if (this.mcpClient) { try { await this.mcpClient.close() @@ -81,20 +75,12 @@ export default class MCPExtensionWeb extends MCPExtension { this.mcpClient = null } - // Get fresh authentication token - const token = await this.authService.getValidAccessToken() - - // Create StreamableHTTP transport with authentication and session management + // Create transport with OAuth provider (handles token refresh automatically) const transport = new StreamableHTTPClientTransport( new URL(`${JAN_API_BASE}${this.mcpEndpoint}`), { - requestInit: { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json', - 'mcp-protocol-version': '2025-06-18' - } - } + authProvider: this.oauthProvider + // No sessionId needed - server will generate one automatically } ) @@ -114,27 +100,16 @@ export default class MCPExtensionWeb extends MCPExtension { } ) - // Connect to MCP server + // Connect to MCP server (OAuth provider handles auth automatically) await this.mcpClient.connect(transport) - console.log('MCP client connected successfully') + + console.log('MCP client connected successfully, session ID:', transport.sessionId) } catch (error) { console.error('Failed to initialize MCP client:', error) throw error } } - private setupTokenMonitoring(): void { - // Listen for token update events from the auth service - this.tokenUpdateListener = () => { - // Simply reinitialize the MCP client when any token update occurs - this.initializeMCPClient().catch(error => { - console.error('Failed to reinitialize MCP client after token update:', error) - }) - } - - window.addEventListener('jan-auth-token-updated', this.tokenUpdateListener as EventListener) - } - private async initializeTools(): Promise { if (this.initialized || !this.mcpClient) { return @@ -183,7 +158,7 @@ export default class MCPExtensionWeb extends MCPExtension { } try { - // Use MCP SDK to call tool + // Use MCP SDK to call tool (OAuth provider handles auth automatically) const result = await this.mcpClient.callTool({ name: toolName, arguments: args @@ -223,43 +198,6 @@ export default class MCPExtensionWeb extends MCPExtension { const errorMessage = error instanceof Error ? error.message : String(error) console.error(`Failed to call MCP tool ${toolName}:`, error) - // If it's a session error, try to reconnect - if (errorMessage.includes('session') || errorMessage.includes('connection')) { - console.log('Detected session error, attempting to reconnect...') - try { - await this.initializeMCPClient() - // Retry the tool call once after reconnection - const retryResult = await this.mcpClient!.callTool({ - name: toolName, - arguments: args - }) - - if (retryResult.isError) { - const errorText = Array.isArray(retryResult.content) && retryResult.content.length > 0 - ? (retryResult.content[0].type === 'text' ? (retryResult.content[0] as any).text : 'Tool call failed after retry') - : 'Tool call failed after retry' - return { - error: errorText, - content: [{ type: 'text', text: errorText }] - } - } - - const content = Array.isArray(retryResult.content) - ? retryResult.content.map(item => { - if (item.type === 'text') { - return { type: 'text' as const, text: (item as any).text } - } else { - return { type: 'text' as const, text: JSON.stringify(item) } - } - }) - : [{ type: 'text' as const, text: 'No content returned' }] - - return { error: '', content } - } catch (retryError) { - console.error('Retry after reconnection failed:', retryError) - } - } - return { error: errorMessage, content: [{ type: 'text', text: errorMessage }] @@ -273,7 +211,7 @@ export default class MCPExtensionWeb extends MCPExtension { } try { - // Try to list tools as health check (ping might not be available) + // Try to list tools as health check (OAuth provider handles auth) await this.mcpClient.listTools() return true } catch (error) { diff --git a/extensions-web/src/mcp-web/oauth-provider.ts b/extensions-web/src/mcp-web/oauth-provider.ts new file mode 100644 index 0000000000..fd37c3ecea --- /dev/null +++ b/extensions-web/src/mcp-web/oauth-provider.ts @@ -0,0 +1,60 @@ +import { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js' +import { OAuthTokens, OAuthClientInformation, OAuthClientMetadata } from '@modelcontextprotocol/sdk/shared/auth.js' +import { JanAuthService } from '../shared/auth' + +/** + * MCP OAuth provider that integrates with Jan Auth Service + * Just provides tokens, no storage or validation needed + */ +export class JanMCPOAuthProvider implements OAuthClientProvider { + private authService: JanAuthService + + constructor(authService: JanAuthService) { + this.authService = authService + } + + get redirectUrl(): string { + return '' + } + + get clientMetadata(): OAuthClientMetadata { + return { + redirect_uris: [] // Not used, but required by interface + } + } + + async clientInformation(): Promise { + return undefined + } + + async tokens(): Promise { + try { + const accessToken = await this.authService.getValidAccessToken() + if (accessToken) { + return { + access_token: accessToken, + token_type: 'Bearer' + } + } + } catch (error) { + console.warn('Failed to get tokens from auth service:', error) + } + return undefined + } + + async saveTokens(): Promise { + // No-op: Jan auth service handles token storage + } + + redirectToAuthorization(): void { + // No-op: Not handling authorization flow + } + + async saveCodeVerifier(): Promise { + // No-op: Not handling authorization flow + } + + async codeVerifier(): Promise { + throw new Error('Code verifier not supported') + } +} \ No newline at end of file diff --git a/extensions-web/src/shared/auth.ts b/extensions-web/src/shared/auth.ts index 8659628a8c..3e7a3869bf 100644 --- a/extensions-web/src/shared/auth.ts +++ b/extensions-web/src/shared/auth.ts @@ -56,14 +56,6 @@ export class JanAuthService { tokens: this.tokens, expiryTime: this.tokenExpiryTime })) - - // Dispatch custom event when tokens are updated - window.dispatchEvent(new CustomEvent('jan-auth-token-updated', { - detail: { - access_token: this.tokens.access_token, - expires_in: this.tokens.expires_in - } - })) } catch (error) { console.error('Failed to save tokens to storage:', error) }