Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 56 additions & 2 deletions extensions-web/src/jan-provider-web/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import {
import { janApiClient, JanChatMessage } from './api'
import { janProviderStore } from './store'

// Jan models support tools via MCP
const JAN_MODEL_CAPABILITIES = ['tools'] as const

export default class JanProviderWeb extends AIEngine {
readonly provider = 'jan'
private activeSessions: Map<string, SessionInfo> = new Map()
Expand All @@ -24,6 +27,9 @@ export default class JanProviderWeb extends AIEngine {
console.log('Loading Jan Provider Extension...')

try {
// Check and clear invalid Jan models (capabilities mismatch)
this.validateJanModelsLocalStorage()

// Initialize authentication and fetch models
await janApiClient.initialize()
console.log('Jan Provider Extension loaded successfully')
Expand All @@ -35,6 +41,54 @@ export default class JanProviderWeb extends AIEngine {
super.onLoad()
}

// Verify Jan models capabilities in localStorage
private validateJanModelsLocalStorage() {
try {
console.log("Validating Jan models in localStorage...")
const storageKey = 'model-provider'
const data = localStorage.getItem(storageKey)
if (!data) return

const parsed = JSON.parse(data)
if (!parsed?.state?.providers) return

// Check if any Jan model has incorrect capabilities
let hasInvalidModel = false

for (const provider of parsed.state.providers) {
if (provider.provider === 'jan' && provider.models) {
for (const model of provider.models) {
console.log(`Checking Jan model: ${model.id}`, model.capabilities)
if (JSON.stringify(model.capabilities) !== JSON.stringify(JAN_MODEL_CAPABILITIES)) {
hasInvalidModel = true
console.log(`Found invalid Jan model: ${model.id}, clearing localStorage`)
break
}
}
}
if (hasInvalidModel) break
}

// If any invalid model found, just clear the storage
if (hasInvalidModel) {
// Force clear the storage
localStorage.removeItem(storageKey)
// Verify it's actually removed
const afterRemoval = localStorage.getItem(storageKey)
// If still present, try setting to empty state
if (afterRemoval) {
// Try alternative clearing method
localStorage.setItem(storageKey, JSON.stringify({ state: { providers: [] }, version: parsed.version || 3 }))
}
console.log('Cleared model-provider from localStorage due to invalid Jan capabilities')
// Force a page reload to ensure clean state
window.location.reload()
}
} catch (error) {
console.error('Failed to check Jan models:', error)
}
}

override async onUnload() {
console.log('Unloading Jan Provider Extension...')

Expand Down Expand Up @@ -64,7 +118,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
capabilities: [...JAN_MODEL_CAPABILITIES],
}
: undefined
)
Expand All @@ -85,7 +139,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
capabilities: [...JAN_MODEL_CAPABILITIES],
}))
} catch (error) {
console.error('Failed to list Jan models:', error)
Expand Down
12 changes: 12 additions & 0 deletions extensions-web/src/shared/auth/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ export class JanAuthService {
* Called on app load to check existing session
*/
async initialize(): Promise<void> {
// Ensure refreshtoken is valid (in case of expired session or secret change)
try {
await refreshToken()
} catch (error) {
console.log('Failed to refresh token on init:', error)
// If refresh fails, logout to clear any invalid state
console.log('Logging out and clearing auth state to clear invalid session...')
await logoutUser()
this.clearAuthState()
this.authBroadcast.broadcastLogout()
}
// Authentication state check
try {
if (!this.isAuthenticated()) {
// Not authenticated - ensure guest access
Expand Down