From f07e43cfe01bc96054053512852148ed8ae3a80b Mon Sep 17 00:00:00 2001 From: Dinh Long Nguyen Date: Fri, 24 Oct 2025 09:01:31 +0700 Subject: [PATCH] fix: conversation items (#6815) --- .github/workflows/jan-server-web-ci-dev.yml | 4 +- .github/workflows/jan-server-web-ci-prod.yml | 4 +- .github/workflows/jan-server-web-ci-stag.yml | 4 +- Dockerfile | 4 +- extensions-web/src/conversational-web/api.ts | 12 +- .../src/conversational-web/types.ts | 36 ++- .../src/conversational-web/utils.ts | 301 ++++++++++++------ extensions-web/src/jan-provider-web/api.ts | 8 +- extensions-web/src/mcp-web/index.ts | 6 +- extensions-web/src/shared/auth/api.ts | 8 +- .../src/shared/auth/providers/api.ts | 6 +- extensions-web/src/shared/auth/service.ts | 4 +- extensions-web/src/types/global.d.ts | 2 +- extensions-web/vite.config.ts | 2 +- 14 files changed, 274 insertions(+), 127 deletions(-) diff --git a/.github/workflows/jan-server-web-ci-dev.yml b/.github/workflows/jan-server-web-ci-dev.yml index 59515f443..be2243864 100644 --- a/.github/workflows/jan-server-web-ci-dev.yml +++ b/.github/workflows/jan-server-web-ci-dev.yml @@ -12,7 +12,7 @@ jobs: build-and-preview: runs-on: [ubuntu-24-04-docker] env: - JAN_API_BASE: "https://api-dev.menlo.ai/v1" + MENLO_PLATFORM_BASE_URL: "https://api-dev.menlo.ai/v1" permissions: pull-requests: write contents: write @@ -52,7 +52,7 @@ jobs: - name: Build docker image run: | - docker build --build-arg JAN_API_BASE=${{ env.JAN_API_BASE }} -t ${{ steps.vars.outputs.FULL_IMAGE }} . + docker build --build-arg MENLO_PLATFORM_BASE_URL=${{ env.MENLO_PLATFORM_BASE_URL }} -t ${{ steps.vars.outputs.FULL_IMAGE }} . - name: Push docker image if: github.event_name == 'push' diff --git a/.github/workflows/jan-server-web-ci-prod.yml b/.github/workflows/jan-server-web-ci-prod.yml index 1477fea32..cb5b597b7 100644 --- a/.github/workflows/jan-server-web-ci-prod.yml +++ b/.github/workflows/jan-server-web-ci-prod.yml @@ -13,7 +13,7 @@ jobs: deployments: write pull-requests: write env: - JAN_API_BASE: "https://api.menlo.ai/v1" + MENLO_PLATFORM_BASE_URL: "https://api.menlo.ai/v1" GA_MEASUREMENT_ID: "G-YK53MX8M8M" CLOUDFLARE_PROJECT_NAME: "jan-server-web" steps: @@ -43,7 +43,7 @@ jobs: - name: Install dependencies run: make config-yarn && yarn install && yarn build:core && make build-web-app env: - JAN_API_BASE: ${{ env.JAN_API_BASE }} + MENLO_PLATFORM_BASE_URL: ${{ env.MENLO_PLATFORM_BASE_URL }} GA_MEASUREMENT_ID: ${{ env.GA_MEASUREMENT_ID }} - name: Publish to Cloudflare Pages Production diff --git a/.github/workflows/jan-server-web-ci-stag.yml b/.github/workflows/jan-server-web-ci-stag.yml index b1851ebdd..3c2581952 100644 --- a/.github/workflows/jan-server-web-ci-stag.yml +++ b/.github/workflows/jan-server-web-ci-stag.yml @@ -12,7 +12,7 @@ jobs: build-and-preview: runs-on: [ubuntu-24-04-docker] env: - JAN_API_BASE: "https://api-stag.menlo.ai/v1" + MENLO_PLATFORM_BASE_URL: "https://api-stag.menlo.ai/v1" permissions: pull-requests: write contents: write @@ -52,7 +52,7 @@ jobs: - name: Build docker image run: | - docker build --build-arg JAN_API_BASE=${{ env.JAN_API_BASE }} -t ${{ steps.vars.outputs.FULL_IMAGE }} . + docker build --build-arg MENLO_PLATFORM_BASE_URL=${{ env.MENLO_PLATFORM_BASE_URL }} -t ${{ steps.vars.outputs.FULL_IMAGE }} . - name: Push docker image if: github.event_name == 'push' diff --git a/Dockerfile b/Dockerfile index 236aa583c..ad14af852 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ # Stage 1: Build stage with Node.js and Yarn v4 FROM node:20-alpine AS builder -ARG JAN_API_BASE=https://api-dev.jan.ai/v1 -ENV JAN_API_BASE=$JAN_API_BASE +ARG MENLO_PLATFORM_BASE_URL=https://api-dev.menlo.ai/v1 +ENV MENLO_PLATFORM_BASE_URL=$MENLO_PLATFORM_BASE_URL # Install build dependencies RUN apk add --no-cache \ diff --git a/extensions-web/src/conversational-web/api.ts b/extensions-web/src/conversational-web/api.ts index 0e398eb05..4fdbd6c69 100644 --- a/extensions-web/src/conversational-web/api.ts +++ b/extensions-web/src/conversational-web/api.ts @@ -16,7 +16,7 @@ import { ListConversationItemsResponse } from './types' -declare const JAN_API_BASE: string +declare const MENLO_PLATFORM_BASE_URL: string export class RemoteApi { private authService: JanAuthService @@ -28,7 +28,7 @@ export class RemoteApi { async createConversation( data: Conversation ): Promise { - const url = `${JAN_API_BASE}${CONVERSATION_API_ROUTES.CONVERSATIONS}` + const url = `${MENLO_PLATFORM_BASE_URL}${CONVERSATION_API_ROUTES.CONVERSATIONS}` return this.authService.makeAuthenticatedRequest( url, @@ -43,7 +43,7 @@ export class RemoteApi { conversationId: string, data: Conversation ): Promise { - const url = `${JAN_API_BASE}${CONVERSATION_API_ROUTES.CONVERSATION_BY_ID(conversationId)}` + const url = `${MENLO_PLATFORM_BASE_URL}${CONVERSATION_API_ROUTES.CONVERSATION_BY_ID(conversationId)}` return this.authService.makeAuthenticatedRequest( url, @@ -70,7 +70,7 @@ export class RemoteApi { } const queryString = queryParams.toString() - const url = `${JAN_API_BASE}${CONVERSATION_API_ROUTES.CONVERSATIONS}${queryString ? `?${queryString}` : ''}` + const url = `${MENLO_PLATFORM_BASE_URL}${CONVERSATION_API_ROUTES.CONVERSATIONS}${queryString ? `?${queryString}` : ''}` return this.authService.makeAuthenticatedRequest( url, @@ -114,7 +114,7 @@ export class RemoteApi { } async deleteConversation(conversationId: string): Promise { - const url = `${JAN_API_BASE}${CONVERSATION_API_ROUTES.CONVERSATION_BY_ID(conversationId)}` + const url = `${MENLO_PLATFORM_BASE_URL}${CONVERSATION_API_ROUTES.CONVERSATION_BY_ID(conversationId)}` await this.authService.makeAuthenticatedRequest( url, @@ -141,7 +141,7 @@ export class RemoteApi { } const queryString = queryParams.toString() - const url = `${JAN_API_BASE}${CONVERSATION_API_ROUTES.CONVERSATION_ITEMS(conversationId)}${queryString ? `?${queryString}` : ''}` + const url = `${MENLO_PLATFORM_BASE_URL}${CONVERSATION_API_ROUTES.CONVERSATION_ITEMS(conversationId)}${queryString ? `?${queryString}` : ''}` return this.authService.makeAuthenticatedRequest( url, diff --git a/extensions-web/src/conversational-web/types.ts b/extensions-web/src/conversational-web/types.ts index a6057da5d..ceb994808 100644 --- a/extensions-web/src/conversational-web/types.ts +++ b/extensions-web/src/conversational-web/types.ts @@ -31,7 +31,7 @@ export interface ConversationResponse { id: string object: 'conversation' title?: string - created_at: number + created_at: number | string metadata: ConversationMetadata } @@ -50,6 +50,7 @@ export interface ConversationItemAnnotation { } export interface ConversationItemContent { + type?: string file?: { file_id?: string mime_type?: string @@ -62,23 +63,50 @@ export interface ConversationItemContent { file_id?: string url?: string } + image_file?: { + file_id?: string + mime_type?: string + } input_text?: string output_text?: { annotations?: ConversationItemAnnotation[] text?: string } - reasoning_content?: string text?: { value?: string + text?: string } - type?: string + reasoning_content?: string + tool_calls?: Array<{ + id?: string + type?: string + function?: { + name?: string + arguments?: string + } + }> + tool_call_id?: string + tool_result?: { + content?: Array<{ + type?: string + text?: string + output_text?: { + text?: string + } + }> + output_text?: { + text?: string + } + } + text_result?: string } export interface ConversationItem { content?: ConversationItemContent[] - created_at: number + created_at: number | string id: string object: string + metadata?: Record role: string status?: string type?: string diff --git a/extensions-web/src/conversational-web/utils.ts b/extensions-web/src/conversational-web/utils.ts index 6448d9f4d..ad2f6fde9 100644 --- a/extensions-web/src/conversational-web/utils.ts +++ b/extensions-web/src/conversational-web/utils.ts @@ -1,5 +1,5 @@ import { Thread, ThreadAssistantInfo, ThreadMessage, ContentType } from '@janhq/core' -import { Conversation, ConversationResponse, ConversationItem } from './types' +import { Conversation, ConversationResponse, ConversationItem, ConversationItemContent, ConversationMetadata } from './types' import { DEFAULT_ASSISTANT } from './const' export class ObjectParser { @@ -7,7 +7,7 @@ export class ObjectParser { const modelName = thread.assistants?.[0]?.model?.id || undefined const modelProvider = thread.assistants?.[0]?.model?.engine || undefined const isFavorite = thread.metadata?.is_favorite?.toString() || 'false' - let metadata = {} + let metadata: ConversationMetadata = {} if (modelName && modelProvider) { metadata = { model_id: modelName, @@ -23,15 +23,14 @@ export class ObjectParser { static conversationToThread(conversation: ConversationResponse): Thread { const assistants: ThreadAssistantInfo[] = [] - if ( - conversation.metadata?.model_id && - conversation.metadata?.model_provider - ) { + const metadata: ConversationMetadata = conversation.metadata || {} + + if (metadata.model_id && metadata.model_provider) { assistants.push({ ...DEFAULT_ASSISTANT, model: { - id: conversation.metadata.model_id, - engine: conversation.metadata.model_provider, + id: metadata.model_id, + engine: metadata.model_provider, }, }) } else { @@ -44,16 +43,18 @@ export class ObjectParser { }) } - const isFavorite = conversation.metadata?.is_favorite === 'true' + const isFavorite = metadata.is_favorite === 'true' + const createdAtMs = parseTimestamp(conversation.created_at) + return { id: conversation.id, title: conversation.title || '', assistants, - created: conversation.created_at, - updated: conversation.created_at, + created: createdAtMs, + updated: createdAtMs, model: { - id: conversation.metadata.model_id, - provider: conversation.metadata.model_provider, + id: metadata.model_id, + provider: metadata.model_provider, }, isFavorite, metadata: { is_favorite: isFavorite }, @@ -65,74 +66,70 @@ export class ObjectParser { threadId: string ): ThreadMessage { // Extract text content and metadata from the item - let textContent = '' - let reasoningContent = '' + const textSegments: string[] = [] + const reasoningSegments: string[] = [] const imageUrls: string[] = [] let toolCalls: any[] = [] - let finishReason = '' if (item.content && item.content.length > 0) { for (const content of item.content) { - // Handle text content - if (content.text?.value) { - textContent = content.text.value - } - // Handle output_text for assistant messages - if (content.output_text?.text) { - textContent = content.output_text.text - } - // Handle reasoning content - if (content.reasoning_content) { - reasoningContent = content.reasoning_content - } - // Handle image content - if (content.image?.url) { - imageUrls.push(content.image.url) - } - // Extract finish_reason - if (content.finish_reason) { - finishReason = content.finish_reason - } - } - } - - // Handle tool calls parsing for assistant messages - if (item.role === 'assistant' && finishReason === 'tool_calls') { - try { - // Tool calls are embedded as JSON string in textContent - const toolCallMatch = textContent.match(/\[.*\]/) - if (toolCallMatch) { - const toolCallsData = JSON.parse(toolCallMatch[0]) - toolCalls = toolCallsData.map((toolCall: any) => ({ - tool: { - id: toolCall.id || 'unknown', - function: { - name: toolCall.function?.name || 'unknown', - arguments: toolCall.function?.arguments || '{}' - }, - type: toolCall.type || 'function' - }, - response: { - error: '', - content: [] - }, - state: 'ready' - })) - // Remove tool calls JSON from text content, keep only reasoning - textContent = '' - } - } catch (error) { - console.error('Failed to parse tool calls:', error) + extractContentByType(content, { + onText: (value) => { + if (value) { + textSegments.push(value) + } + }, + onReasoning: (value) => { + if (value) { + reasoningSegments.push(value) + } + }, + onImage: (url) => { + if (url) { + imageUrls.push(url) + } + }, + onToolCalls: (calls) => { + toolCalls = calls.map((toolCall) => { + const callId = toolCall.id || 'unknown' + const rawArgs = toolCall.function?.arguments + const normalizedArgs = + typeof rawArgs === 'string' + ? rawArgs + : JSON.stringify(rawArgs ?? {}) + return { + id: callId, + tool_call_id: callId, + tool: { + id: callId, + function: { + name: toolCall.function?.name || 'unknown', + arguments: normalizedArgs, + }, + type: toolCall.type || 'function', + }, + response: { + error: '', + content: [], + }, + state: 'pending', + } + }) + }, + }) } } // Format final content with reasoning if present let finalTextValue = '' - if (reasoningContent) { - finalTextValue = `${reasoningContent}` + if (reasoningSegments.length > 0) { + finalTextValue += `${reasoningSegments.join('\n')}` } - if (textContent) { - finalTextValue += textContent + if (textSegments.length > 0) { + if (finalTextValue) { + finalTextValue += '\n' + } + finalTextValue += textSegments.join('\n') } // Build content array for ThreadMessage @@ -157,22 +154,26 @@ export class ObjectParser { } // Build metadata - const metadata: any = {} + const metadata: any = { ...(item.metadata || {}) } if (toolCalls.length > 0) { metadata.tool_calls = toolCalls } + const createdAtMs = parseTimestamp(item.created_at) + // Map status from server format to frontend format const mappedStatus = item.status === 'completed' ? 'ready' : item.status || 'ready' + const role = item.role === 'user' || item.role === 'assistant' ? item.role : 'assistant' + return { type: 'text', id: item.id, object: 'thread.message', thread_id: threadId, - role: item.role as 'user' | 'assistant', + role, content: messageContent, - created_at: item.created_at * 1000, // Convert to milliseconds + created_at: createdAtMs, completed_at: 0, status: mappedStatus, metadata, @@ -201,25 +202,46 @@ export const combineConversationItemsToMessages = ( ): ThreadMessage[] => { const messages: ThreadMessage[] = [] const toolResponseMap = new Map() + const sortedItems = [...items].sort( + (a, b) => parseTimestamp(a.created_at) - parseTimestamp(b.created_at) + ) // First pass: collect tool responses - for (const item of items) { + for (const item of sortedItems) { if (item.role === 'tool') { - const toolContent = item.content?.[0]?.text?.value || '' - toolResponseMap.set(item.id, { - error: '', - content: [ - { - type: 'text', - text: toolContent - } - ] - }) + for (const content of item.content ?? []) { + const toolCallId = content.tool_call_id || item.id + const toolResultText = + content.tool_result?.output_text?.text || + (Array.isArray(content.tool_result?.content) + ? content.tool_result?.content + ?.map((entry) => entry.text || entry.output_text?.text) + .filter((text): text is string => Boolean(text)) + .join('\n') + : undefined) + const toolContent = + content.text?.text || + content.text?.value || + content.output_text?.text || + content.input_text || + content.text_result || + toolResultText || + '' + toolResponseMap.set(toolCallId, { + error: '', + content: [ + { + type: 'text', + text: toolContent, + }, + ], + }) + } } } // Second pass: build messages and merge tool responses - for (const item of items) { + for (const item of sortedItems) { // Skip tool messages as they will be merged into assistant messages if (item.role === 'tool') { continue @@ -228,14 +250,35 @@ export const combineConversationItemsToMessages = ( const message = ObjectParser.conversationItemToThreadMessage(item, threadId) // If this is an assistant message with tool calls, merge tool responses - if (message.role === 'assistant' && message.metadata?.tool_calls && Array.isArray(message.metadata.tool_calls)) { + if ( + message.role === 'assistant' && + message.metadata?.tool_calls && + Array.isArray(message.metadata.tool_calls) + ) { const toolCalls = message.metadata.tool_calls as any[] - let toolResponseIndex = 0 - for (const [responseId, responseData] of toolResponseMap.entries()) { - if (toolResponseIndex < toolCalls.length) { - toolCalls[toolResponseIndex].response = responseData - toolResponseIndex++ + for (const toolCall of toolCalls) { + const callId = toolCall.tool_call_id || toolCall.id || toolCall.tool?.id + let responseKey: string | undefined + let response: any = null + + if (callId && toolResponseMap.has(callId)) { + responseKey = callId + response = toolResponseMap.get(callId) + } else { + const iterator = toolResponseMap.entries().next() + if (!iterator.done) { + responseKey = iterator.value[0] + response = iterator.value[1] + } + } + + if (response) { + toolCall.response = response + toolCall.state = 'succeeded' + if (responseKey) { + toolResponseMap.delete(responseKey) + } } } } @@ -245,3 +288,79 @@ export const combineConversationItemsToMessages = ( return messages } + +const parseTimestamp = (value: number | string | undefined): number => { + if (typeof value === 'number') { + // Distinguish between seconds and milliseconds + return value > 1e12 ? value : value * 1000 + } + if (typeof value === 'string') { + const parsed = Date.parse(value) + return Number.isNaN(parsed) ? Date.now() : parsed + } + return Date.now() +} + +const extractContentByType = ( + content: ConversationItemContent, + handlers: { + onText: (value: string) => void + onReasoning: (value: string) => void + onImage: (url: string) => void + onToolCalls: (calls: NonNullable) => void + } +) => { + const type = content.type || '' + + switch (type) { + case 'input_text': + handlers.onText(content.input_text || '') + break + case 'text': + handlers.onText(content.text?.text || content.text?.value || '') + break + case 'output_text': + handlers.onText(content.output_text?.text || '') + break + case 'reasoning_content': + handlers.onReasoning(content.reasoning_content || '') + break + case 'image': + case 'image_url': + if (content.image?.url) { + handlers.onImage(content.image.url) + } + break + case 'tool_calls': + if (content.tool_calls && Array.isArray(content.tool_calls)) { + handlers.onToolCalls(content.tool_calls) + } + break + case 'tool_result': + if (content.tool_result?.output_text?.text) { + handlers.onText(content.tool_result.output_text.text) + } + break + default: + // Fallback for legacy fields without explicit type + if (content.text?.value || content.text?.text) { + handlers.onText(content.text.value || content.text.text || '') + } + if (content.text_result) { + handlers.onText(content.text_result) + } + if (content.output_text?.text) { + handlers.onText(content.output_text.text) + } + if (content.reasoning_content) { + handlers.onReasoning(content.reasoning_content) + } + if (content.image?.url) { + handlers.onImage(content.image.url) + } + if (content.tool_calls && Array.isArray(content.tool_calls)) { + handlers.onToolCalls(content.tool_calls) + } + break + } +} diff --git a/extensions-web/src/jan-provider-web/api.ts b/extensions-web/src/jan-provider-web/api.ts index 1d15c31b9..ded8f3214 100644 --- a/extensions-web/src/jan-provider-web/api.ts +++ b/extensions-web/src/jan-provider-web/api.ts @@ -8,7 +8,7 @@ import { ApiError } from '../shared/types/errors' import { JAN_API_ROUTES } from './const' import { JanModel, janProviderStore } from './store' -// JAN_API_BASE is defined in vite.config.ts +// MENLO_PLATFORM_BASE_URL is defined in vite.config.ts // Constants const TEMPORARY_CHAT_ID = 'temporary-chat' @@ -20,7 +20,7 @@ const TEMPORARY_CHAT_ID = 'temporary-chat' */ function getChatCompletionConfig(request: JanChatCompletionRequest, stream: boolean = false) { const isTemporaryChat = request.conversation_id === TEMPORARY_CHAT_ID - const endpoint = `${JAN_API_BASE}${JAN_API_ROUTES.CHAT_COMPLETIONS}` + const endpoint = `${MENLO_PLATFORM_BASE_URL}${JAN_API_ROUTES.CHAT_COMPLETIONS}` const payload = { ...request, @@ -162,7 +162,7 @@ export class JanApiClient { this.modelsFetchPromise = (async () => { const response = await this.authService.makeAuthenticatedRequest( - `${JAN_API_BASE}${JAN_API_ROUTES.MODELS}` + `${MENLO_PLATFORM_BASE_URL}${JAN_API_ROUTES.MODELS}` ) const summaries = response.data || [] @@ -327,7 +327,7 @@ export class JanApiClient { private async fetchSupportedParameters(modelId: string): Promise { try { - const endpoint = `${JAN_API_BASE}${JAN_API_ROUTES.MODEL_CATALOGS}/${this.encodeModelIdForCatalog(modelId)}` + const endpoint = `${MENLO_PLATFORM_BASE_URL}${JAN_API_ROUTES.MODEL_CATALOGS}/${this.encodeModelIdForCatalog(modelId)}` const catalog = await this.authService.makeAuthenticatedRequest(endpoint) return this.extractSupportedParameters(catalog) } catch (error) { diff --git a/extensions-web/src/mcp-web/index.ts b/extensions-web/src/mcp-web/index.ts index 3d588753f..6545fd426 100644 --- a/extensions-web/src/mcp-web/index.ts +++ b/extensions-web/src/mcp-web/index.ts @@ -12,8 +12,8 @@ import { JanMCPOAuthProvider } from './oauth-provider' import { WebSearchButton } from './components' import type { ComponentType } from 'react' -// JAN_API_BASE is defined in vite.config.ts (defaults to 'https://api-dev.jan.ai/jan/v1') -declare const JAN_API_BASE: string +// MENLO_PLATFORM_BASE_URL is defined in vite.config.ts (defaults to 'https://api-dev.menlo.ai/jan/v1') +declare const MENLO_PLATFORM_BASE_URL: string export default class MCPExtensionWeb extends MCPExtension { private mcpEndpoint = '/mcp' @@ -77,7 +77,7 @@ export default class MCPExtensionWeb extends MCPExtension { // Create transport with OAuth provider (handles token refresh automatically) const transport = new StreamableHTTPClientTransport( - new URL(`${JAN_API_BASE}${this.mcpEndpoint}`), + new URL(`${MENLO_PLATFORM_BASE_URL}${this.mcpEndpoint}`), { authProvider: this.oauthProvider // No sessionId needed - server will generate one automatically diff --git a/extensions-web/src/shared/auth/api.ts b/extensions-web/src/shared/auth/api.ts index 61163984b..a14617190 100644 --- a/extensions-web/src/shared/auth/api.ts +++ b/extensions-web/src/shared/auth/api.ts @@ -6,13 +6,13 @@ import { AuthTokens } from './types' import { AUTH_ENDPOINTS } from './const' -declare const JAN_API_BASE: string +declare const MENLO_PLATFORM_BASE_URL: string /** * Logout user on server */ export async function logoutUser(): Promise { - const response = await fetch(`${JAN_API_BASE}${AUTH_ENDPOINTS.LOGOUT}`, { + const response = await fetch(`${MENLO_PLATFORM_BASE_URL}${AUTH_ENDPOINTS.LOGOUT}`, { method: 'GET', credentials: 'include', headers: { @@ -29,7 +29,7 @@ export async function logoutUser(): Promise { * Guest login */ export async function guestLogin(): Promise { - const response = await fetch(`${JAN_API_BASE}${AUTH_ENDPOINTS.GUEST_LOGIN}`, { + const response = await fetch(`${MENLO_PLATFORM_BASE_URL}${AUTH_ENDPOINTS.GUEST_LOGIN}`, { method: 'POST', credentials: 'include', headers: { @@ -51,7 +51,7 @@ export async function guestLogin(): Promise { */ export async function refreshToken(): Promise { const response = await fetch( - `${JAN_API_BASE}${AUTH_ENDPOINTS.REFRESH_TOKEN}`, + `${MENLO_PLATFORM_BASE_URL}${AUTH_ENDPOINTS.REFRESH_TOKEN}`, { method: 'GET', credentials: 'include', diff --git a/extensions-web/src/shared/auth/providers/api.ts b/extensions-web/src/shared/auth/providers/api.ts index f2830e911..f63b5a915 100644 --- a/extensions-web/src/shared/auth/providers/api.ts +++ b/extensions-web/src/shared/auth/providers/api.ts @@ -5,10 +5,10 @@ import { AuthTokens, LoginUrlResponse } from './types' -declare const JAN_API_BASE: string +declare const MENLO_PLATFORM_BASE_URL: string export async function getLoginUrl(endpoint: string): Promise { - const response: Response = await fetch(`${JAN_API_BASE}${endpoint}`, { + const response: Response = await fetch(`${MENLO_PLATFORM_BASE_URL}${endpoint}`, { method: 'GET', credentials: 'include', headers: { @@ -30,7 +30,7 @@ export async function handleOAuthCallback( code: string, state?: string ): Promise { - const response: Response = await fetch(`${JAN_API_BASE}${endpoint}`, { + const response: Response = await fetch(`${MENLO_PLATFORM_BASE_URL}${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/extensions-web/src/shared/auth/service.ts b/extensions-web/src/shared/auth/service.ts index 55371a940..fc12b5ffd 100644 --- a/extensions-web/src/shared/auth/service.ts +++ b/extensions-web/src/shared/auth/service.ts @@ -3,7 +3,7 @@ * Handles authentication flows for any OAuth provider */ -declare const JAN_API_BASE: string +declare const MENLO_PLATFORM_BASE_URL: string import { User, AuthState, AuthBroadcastMessage, AuthTokens } from './types' import { @@ -429,7 +429,7 @@ export class JanAuthService { private async fetchUserProfile(): Promise { try { return await this.makeAuthenticatedRequest( - `${JAN_API_BASE}${AUTH_ENDPOINTS.ME}` + `${MENLO_PLATFORM_BASE_URL}${AUTH_ENDPOINTS.ME}` ) } catch (error) { console.error('Failed to fetch user profile:', error) diff --git a/extensions-web/src/types/global.d.ts b/extensions-web/src/types/global.d.ts index 8d70d398b..22dea22d0 100644 --- a/extensions-web/src/types/global.d.ts +++ b/extensions-web/src/types/global.d.ts @@ -1,5 +1,5 @@ export {} declare global { - declare const JAN_API_BASE: string + declare const MENLO_PLATFORM_BASE_URL: string } diff --git a/extensions-web/vite.config.ts b/extensions-web/vite.config.ts index 8c144b0ab..b68fc4d5a 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/v1'), + MENLO_PLATFORM_BASE_URL: JSON.stringify(process.env.MENLO_PLATFORM_BASE_URL || 'https://api-dev.menlo.ai/v1'), } })