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
6 changes: 3 additions & 3 deletions entrypoints/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { registerDeclarativeNetRequestRule } from '@/utils/web-request'
import { BackgroundDatabaseManager } from './database'
import { BackgroundCacheServiceManager } from './services/cache-service'
import { BackgroundChatHistoryServiceManager } from './services/chat-history-service'
import { waitForSidepanelLoaded } from './utils'
import { waitUntilSidepanelLoaded } from './utils'

export default defineBackground(() => {
if (import.meta.env.CHROME) {
Expand Down Expand Up @@ -122,11 +122,11 @@ export default defineBackground(() => {
if (typeof info.menuItemId === 'string' && ['quick-actions', 'add-image-to-chat'].some((id) => info.menuItemId.toString().includes(id))) {
if (browser.sidePanel) {
await browser.sidePanel.open({ windowId: tab.windowId })
await waitForSidepanelLoaded().catch((err) => logger.error(err))
await waitUntilSidepanelLoaded().catch((err) => logger.error(err))
}
else if (browser.sidebarAction) {
await browser.sidebarAction.open()
await waitForSidepanelLoaded().catch((err) => logger.error(err))
await waitUntilSidepanelLoaded().catch((err) => logger.error(err))
}
await b2sRpc.emit('contextMenuClicked', { ...info, menuItemId: info.menuItemId as ContextMenuId, tabInfo: tabToTabInfo(tab) })
}
Expand Down
6 changes: 3 additions & 3 deletions entrypoints/background/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const checkSidepanelLoaded = async () => {
try {
const r = await Promise.race([
b2sRpc.getSidepanelStatus().then((status) => !!status),
sleep(2000).then(() => false),
sleep(1000).then(() => false),
])
return r
}
Expand All @@ -14,10 +14,10 @@ const checkSidepanelLoaded = async () => {
}
}

export async function waitForSidepanelLoaded() {
export async function waitUntilSidepanelLoaded() {
const start = Date.now()
while (!(await checkSidepanelLoaded())) {
if (Date.now() - start > 5000) {
if (Date.now() - start > 3000) {
throw new Error('Timeout waiting for sidepanel to load')
}
await sleep(500)
Expand Down
6 changes: 3 additions & 3 deletions entrypoints/settings/components/GeneralSettings/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ import { MIN_CONTEXT_WINDOW_SIZE, OLLAMA_HOMEPAGE_URL, OLLAMA_SEARCH_URL, OLLAMA
import { useI18n } from '@/utils/i18n/index'
import logger from '@/utils/logger'
import { useOllamaStatusStore } from '@/utils/pinia-store/store'
import { settings2bRpc } from '@/utils/rpc'
import { getUserConfig } from '@/utils/user-config'

import { useSettingsInitialQuery } from '../../composables/useQuery'
Expand Down Expand Up @@ -303,9 +304,8 @@ const testConnection = async () => {
try {
await reScanOllama()
const success = await ollamaStatusStore.updateConnectionStatus()
if (success) {
await ollamaStatusStore.updateModelList()
}
success ? (await ollamaStatusStore.updateModelList()) : ollamaStatusStore.clearModelList()
settings2bRpc.updateSidepanelModelList()
return success
}
catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
color="primary"
class="grow-0 shrink-0"
>
<IconTick class="w-4 h-4 inline-block mr-2" />
<IconTick class="size-4 shrink-0 inline-block mr-2" />
</Text>
<Text color="secondary">
{{ t('onboarding.guide.features.1') }}
Expand All @@ -34,7 +34,7 @@
color="primary"
class="grow-0 shrink-0"
>
<IconTick class="w-4 h-4 inline-block mr-2" />
<IconTick class="size-4 shrink-0 inline-block mr-2" />
</Text>
<Text color="secondary">
{{ t('onboarding.guide.features.2') }}
Expand All @@ -45,7 +45,7 @@
color="primary"
class="grow-0 shrink-0"
>
<IconTick class="w-4 h-4 inline-block mr-2" />
<IconTick class="size-4 shrink-0 inline-block mr-2" />
</Text>
<Text color="secondary">
{{ t('onboarding.guide.features.3') }}
Expand Down
4 changes: 2 additions & 2 deletions entrypoints/sidepanel/components/Onboarding/SloganCard.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="flex flex-col items-center justify-start bg-gradient-to-b from-[#D5F4E1] to-[#FFFFFF] to-40% rounded-lg overflow-hidden pb-4">
<div class="text-center">
<ImageElements />
<div class="text-center max-w-full">
<ImageElements class="max-w-full h-auto" />
<div class="font-semibold text-sm mt-5">
{{ t('onboarding.banner.title') }}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</Modal>
<Button
variant="secondary"
class="shrink-0 grow-0 flex mt-1 items-center justify-center rounded-md gap-2 font-bold cursor-pointer h-7"
class="shrink-0 grow-0 flex mt-1 items-center justify-center rounded-md gap-2 font-bold cursor-pointer min-h-7"
:disabled="!supportWebLLM.supported"
@click="initWebLLM"
>
Expand Down
3 changes: 1 addition & 2 deletions entrypoints/sidepanel/utils/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,7 @@ export class Agent<T extends PromptBasedToolName> {
if (tool) {
const params = chunk.params
this.log.debug('Tool call start', chunk)
const abortController = new AbortController()
this.abortControllers.push(abortController)
const abortController = this.createAbortController()
try {
const executedResults = await tool.execute({
params,
Expand Down
8 changes: 2 additions & 6 deletions entrypoints/sidepanel/utils/search.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { s2bRpc } from '@/utils/rpc'
import { searchWebsites } from '@/utils/search'
export interface SearchOptions {
resultLimit?: number
abortSignal?: AbortSignal
Expand All @@ -7,11 +7,7 @@ export interface SearchOptions {

export class SearchScraper {
async searchWebsites(query: string, options?: SearchOptions) {
const links = await s2bRpc.searchWebsites(query, options)
const links = await searchWebsites(query, options)
return links
}

async fetchUrlsContent(links: string[]) {
return s2bRpc.openAndFetchUrlsContent(links)
}
}
4 changes: 2 additions & 2 deletions utils/abort-controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AbortError } from './error'
import { AbortError, AppError } from './error'

export function makeAbortable<T>(promise: Promise<T>, signal: AbortSignal, abortErrorFactory: () => Error = () => new AbortError('Operation aborted')): Promise<T> {
export function makeAbortable<T>(promise: Promise<T>, signal: AbortSignal, abortErrorFactory: () => AppError = () => new AbortError('Operation aborted')): Promise<T> {
return new Promise((resolve, reject) => {
if (signal.aborted) {
return reject(abortErrorFactory())
Expand Down
13 changes: 10 additions & 3 deletions utils/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@ import { useGlobalI18n } from './i18n'

export type ErrorCode = 'unknown' | 'requestError' | 'requestTimeout' | 'abortError' | 'timeoutError' | 'modelNotFound' | 'createTabStreamCaptureError' | 'translateError' | 'unsupportedEndpointType' | 'fetchError' | 'parseFunctionCallError' | 'aiSDKError' | 'generateObjectSchemaError'

export abstract class AppError<Code extends ErrorCode> extends Error {
private _appError = true
// we use a base AppError class instead of extending the native Error class directly because of Firefox compatibility issues of error instance transform in postMessage
export abstract class AppError<Code extends ErrorCode = ErrorCode> {
private _appError = true // this is a symbol to identify AppError instances
name?: string
message: string
private nativeError: Error
static isAppError(error: unknown): error is AppError<ErrorCode> {
// can not check instanceof AppError directly because it may be from another context (e.g. from background script to content script)
return (typeof error === 'object' && error !== null && '_appError' in error && error._appError === true)
}

constructor(public code: Code, message?: string) {
super(message)
this.nativeError = new Error(message)
this.message = message ?? ''
}

async toLocaleMessage(_locale?: string): Promise<string> {
return this.message
}

get stack(): string | undefined {
return this.nativeError.stack
}
}

export class FetchError extends AppError<'fetchError'> {
Expand Down
4 changes: 4 additions & 0 deletions utils/pinia-store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export const useOllamaStatusStore = defineStore('ollama-status', () => {
return []
}
}
const clearModelList = () => {
modelList.value = []
}

const connectionStatusLoading = ref(false)
const updateConnectionStatus = async () => {
Expand Down Expand Up @@ -99,6 +102,7 @@ export const useOllamaStatusStore = defineStore('ollama-status', () => {
initDefaultModel,
unloadModel,
updateModelList,
clearModelList,
updateConnectionStatus,
checkCurrentModelSupportVision,
checkModelSupportThinking,
Expand Down
3 changes: 2 additions & 1 deletion utils/rpc/background-fns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,12 @@ const makeLoadingModelListener = (port: Browser.runtime.Port) => (ev: ModelLoadi
}

const normalizeError = (_error: unknown) => {
const networkErrorMessages = ['NetworkError', 'Failed to fetch']
let error
if (_error instanceof AppError) {
error = _error
}
else if (_error instanceof Error && _error.message.includes('Failed to fetch')) {
else if (_error instanceof Error && networkErrorMessages.some((msg) => _error.message.includes(msg))) {
error = new ModelRequestError(_error.message)
}
else if (AISDKError.isInstance(_error)) {
Expand Down
3 changes: 1 addition & 2 deletions utils/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,7 @@ export type SearchingMessage =
}

export async function searchWebsites(query: string, options?: SearchByGoogleOptions) {
const { abortSignal, ...restOptions } = options || {}
const links = await _searchByGoogle(query, restOptions)
const links = await _searchByGoogle(query, options)
return links
}

Expand Down
Loading