diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..99f762b
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,31 @@
+name: Release
+
+on:
+ workflow_dispatch:
+
+jobs:
+ mac:
+ runs-on: macos-latest
+ permissions:
+ contents: write
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
+ SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
+ SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
+ SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
+ APPLE_ID: ${{ secrets.APPLE_ID }}
+ APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
+ APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: pnpm/action-setup@v4
+ with:
+ version: 10.29.2
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 22
+ cache: pnpm
+ - run: pnpm install --frozen-lockfile
+ - run: pnpm check
+ - run: pnpm build:release --publish always
diff --git a/README.md b/README.md
index afc531d..e9e8b49 100644
--- a/README.md
+++ b/README.md
@@ -72,6 +72,8 @@ pnpm build
API keys for embedding providers can be configured in **Settings** (Cmd+,). Keys are stored encrypted at rest.
+Error reporting is enabled by default and can be disabled from **Settings > Privacy**. See `docs/TELEMETRY.md` for release configuration and privacy rules.
+
### Feedback Collection
The in-app feedback form posts directly to Forminit form `742yqqcnm5o`. To
diff --git a/docs/TELEMETRY.md b/docs/TELEMETRY.md
new file mode 100644
index 0000000..8494cc7
--- /dev/null
+++ b/docs/TELEMETRY.md
@@ -0,0 +1,91 @@
+# Telemetry
+
+Chroma Explorer keeps product analytics and error reporting separate.
+
+## Product Analytics
+
+`electron/analytics.ts` owns Aptabase event tracking. Analytics is disabled unless
+`APTABASE_APP_KEY` is provided at build time.
+
+Only coarse product events should be tracked. Do not include user document
+contents, collection data, embeddings, metadata values, connection URLs, API
+keys, auth tokens, or provider credentials in event names or properties.
+
+## Error Reporting
+
+`electron/error-monitoring.ts` owns Sentry initialization for the Electron main
+process. `src/error-monitoring.ts` owns renderer initialization.
+
+Error reporting is enabled by default and can be disabled from
+**Settings > Privacy**. The setting is stored as `errorReportingEnabled` in
+`electron/settings-store.ts` and exposed through the canonical IPC contract in
+`electron/ipc-contract.ts`.
+
+Release builds must provide a public DSN at build time:
+
+```bash
+SENTRY_DSN=https://public-key@o0.ingest.sentry.io/project-id pnpm build:release
+```
+
+`vite.config.js` embeds `SENTRY_DSN` for the main process and renderer bridge.
+Renderer events are forwarded through the Electron SDK preload integration once
+the renderer initializes.
+
+Sentry releases use `chroma-explorer@` by default. Set
+`SENTRY_RELEASE` only when the Sentry upload release and runtime
+`Sentry.init({ release })` value need to be overridden together.
+
+Readable production stack traces require source map upload. Release builds
+generate hidden source maps when a DSN is present. They upload maps only when all
+of these build-time values are present:
+
+```bash
+SENTRY_AUTH_TOKEN=sntrys_...
+SENTRY_ORG=your-org-slug
+SENTRY_PROJECT=your-project-slug
+```
+
+The manual GitHub Actions release workflow (`.github/workflows/release.yml`)
+passes those secrets into `pnpm build:release --publish always`. Configure the
+same repository secrets there, along with the existing Apple notarization
+secrets, before publishing production artifacts.
+
+If you do not have source-map upload credentials yet, run Sentry's wizard and use
+the auth token it configures:
+
+```bash
+npx @sentry/wizard@latest -i sourcemaps --saas --org arsent --project electron
+```
+
+## Production Validation
+
+Before shipping a release:
+
+1. Run the manual `Release` workflow from GitHub Actions.
+2. Install the produced app artifact.
+3. Confirm **Settings > Privacy > Error reporting** is enabled.
+4. Trigger a known renderer and main-process failure in a test build.
+5. Confirm Sentry receives events under the expected
+ `chroma-explorer@` release with readable stack traces.
+
+## Privacy Rules
+
+Sentry events are scrubbed before sending:
+
+- URL-like values are replaced with `[redacted-url]`.
+- Long token-like strings are replaced with `[redacted-token]`.
+- Keys containing API key, token, secret, password, credential, authorization,
+ document, metadata, embedding, query, or URL are replaced with `[redacted]`.
+- Event `request` and `user` fields are removed.
+
+Do not add manual Sentry context that contains:
+
+- document text;
+- metadata values;
+- embeddings;
+- collection names when they may reveal user data;
+- connection URLs;
+- auth headers, tokens, credentials, or API keys.
+
+Prefer tags with stable categories such as window type, operation category,
+platform, packaged status, and app version.
diff --git a/electron/error-monitoring.ts b/electron/error-monitoring.ts
new file mode 100644
index 0000000..56bf0f5
--- /dev/null
+++ b/electron/error-monitoring.ts
@@ -0,0 +1,141 @@
+import { app } from 'electron'
+import * as Sentry from '@sentry/electron/main'
+
+const SENSITIVE_KEY_PATTERN = /(api[-_]?key|token|secret|password|credential|authorization|document|metadata|embedding|query|url)/i
+const URL_PATTERN = /\bhttps?:\/\/[^\s"'<>]+/gi
+const LONG_TOKEN_PATTERN = /\b[A-Za-z0-9_-]{32,}\b/g
+const MAX_STRING_LENGTH = 500
+const MAX_DEBUG_STRING_LENGTH = 10_000
+const MAX_SANITIZE_DEPTH = 12
+const DEBUG_STRING_KEY_PATTERN = /^(message|stack|componentStack|exception|value|type)$/i
+
+let initialized = false
+
+function redactString(value: string, maxLength = MAX_STRING_LENGTH): string {
+ const redacted = value
+ .replace(URL_PATTERN, '[redacted-url]')
+ .replace(LONG_TOKEN_PATTERN, '[redacted-token]')
+
+ return redacted.length > maxLength ? redacted.slice(0, maxLength) : redacted
+}
+
+function sanitizeValue(
+ value: unknown,
+ key = '',
+ depth = 0,
+ seen = new WeakSet()
+): unknown {
+ if (depth >= MAX_SANITIZE_DEPTH) {
+ return '[max-depth-exceeded]'
+ }
+
+ if (SENSITIVE_KEY_PATTERN.test(key)) {
+ return '[redacted]'
+ }
+
+ if (typeof value === 'string') {
+ const maxLength = DEBUG_STRING_KEY_PATTERN.test(key) ? MAX_DEBUG_STRING_LENGTH : MAX_STRING_LENGTH
+ return redactString(value, maxLength)
+ }
+
+ if (Array.isArray(value)) {
+ if (seen.has(value)) {
+ return '[circular]'
+ }
+ seen.add(value)
+ return value.slice(0, 10).map((item) => sanitizeValue(item, '', depth + 1, seen))
+ }
+
+ if (value && typeof value === 'object') {
+ if (seen.has(value)) {
+ return '[circular]'
+ }
+ seen.add(value)
+ const entries = Object.entries(value as Record).slice(0, 30)
+ return Object.fromEntries(entries.map(([entryKey, entryValue]) => [
+ entryKey,
+ sanitizeValue(entryValue, entryKey, depth + 1, seen),
+ ]))
+ }
+
+ return value
+}
+
+function getSentryDsn(): string {
+ return process.env.SENTRY_DSN || process.env.VITE_SENTRY_DSN || ''
+}
+
+function getSentryRelease(): string {
+ return process.env.SENTRY_RELEASE || `chroma-explorer@${app.getVersion()}`
+}
+
+export function initErrorMonitoring(enabled: boolean): void {
+ if (initialized || Sentry.isInitialized()) {
+ initialized = true
+ return
+ }
+
+ const dsn = getSentryDsn()
+ if (!enabled || !dsn) {
+ if (!dsn) {
+ console.log('[ErrorMonitoring] SENTRY_DSN not configured, error reporting disabled')
+ }
+ return
+ }
+
+ Sentry.init({
+ dsn,
+ environment: app.isPackaged ? 'production' : 'development',
+ release: getSentryRelease(),
+ sendDefaultPii: false,
+ tracesSampleRate: 0,
+ beforeBreadcrumb(breadcrumb) {
+ return sanitizeValue(breadcrumb) as Sentry.Breadcrumb
+ },
+ beforeSend(event) {
+ const sanitized = sanitizeValue(event) as Sentry.ErrorEvent
+ delete sanitized.request
+ delete sanitized.user
+ return sanitized
+ },
+ })
+
+ Sentry.setTags({
+ packaged: String(app.isPackaged),
+ platform: process.platform,
+ arch: process.arch,
+ electron: process.versions.electron || 'unknown',
+ })
+
+ initialized = true
+ console.log('[ErrorMonitoring] Initialized successfully')
+}
+
+export function setErrorMonitoringEnabled(enabled: boolean): void {
+ if (enabled) {
+ initErrorMonitoring(true)
+ return
+ }
+
+ if (initialized || Sentry.isInitialized()) {
+ void Sentry.close(2000).finally(() => {
+ initialized = false
+ console.log('[ErrorMonitoring] Disabled')
+ })
+ }
+}
+
+export function captureMainError(error: unknown, context?: Record): void {
+ if (!initialized && !Sentry.isInitialized()) {
+ return
+ }
+
+ Sentry.withScope((scope) => {
+ if (context) {
+ scope.setTags(Object.fromEntries(
+ Object.entries(context).map(([key, value]) => [key, String(value)])
+ ))
+ }
+ Sentry.captureException(error)
+ })
+}
diff --git a/electron/ipc-contract.ts b/electron/ipc-contract.ts
index cf8997a..fb9fc02 100644
--- a/electron/ipc-contract.ts
+++ b/electron/ipc-contract.ts
@@ -237,6 +237,9 @@ export interface ElectronAPI {
setApiKeys: (apiKeys: Record) => Promise
getTheme: () => Promise<'light' | 'dark' | 'system'>
setTheme: (theme: 'light' | 'dark' | 'system') => Promise
+ getErrorReportingEnabled: () => Promise
+ setErrorReportingEnabled: (enabled: boolean) => Promise
+ onErrorReportingChange: (callback: (enabled: boolean) => void) => () => void
onThemeChange: (callback: (theme: string) => void) => () => void
openWindow: () => Promise
onSwitchTab: (callback: (tab: string) => void) => () => void
@@ -483,6 +486,11 @@ export function parseTheme(value: unknown): 'light' | 'dark' | 'system' {
return parseEnum(value, 'theme', ['light', 'dark', 'system'])
}
+export function parseErrorReportingEnabled(value: unknown): boolean {
+ if (typeof value !== 'boolean') throw new Error('errorReportingEnabled must be a boolean')
+ return value
+}
+
export function validateExternalUrl(value: unknown): string {
const url = parseString(value, 'url')
const parsed = new URL(url)
diff --git a/electron/main.ts b/electron/main.ts
index dbf2e2f..888e2d1 100644
--- a/electron/main.ts
+++ b/electron/main.ts
@@ -26,6 +26,7 @@ import {
parseCreateDocumentsBatchParams,
parseDeleteDocumentsParams,
parseEmbeddingOverride,
+ parseErrorReportingEnabled,
parseProfileId,
parseSearchDocumentsParams,
parseTheme,
@@ -35,10 +36,12 @@ import { openValidatedExternalUrl } from './external-url'
import { initAutoUpdater, checkForUpdates } from './auto-updater'
import { initAnalytics, track } from './analytics'
import { configureTransformersCache } from './transformers-cache'
+import { captureMainError, initErrorMonitoring, setErrorMonitoringEnabled } from './error-monitoring'
// Inject stored API keys into process.env at startup
configureTransformersCache()
settingsStore.injectIntoProcessEnv()
+initErrorMonitoring(settingsStore.isErrorReportingEnabled())
// Track active copy operations per profile for cancellation
const activeCopyOperations: Map = new Map()
@@ -50,6 +53,12 @@ process.env.VITE_PUBLIC = app.isPackaged
? process.env.DIST
: path.join(process.env.DIST, '../public')
+function reportIpcError(error: unknown, operation: string, fallbackMessage: string) {
+ captureMainError(error, { operation })
+ const message = error instanceof Error ? error.message : fallbackMessage
+ return { success: false, error: message }
+}
+
// Set up IPC handlers
ipcMain.handle('chromadb:connect', async (_event, rawProfileId: unknown, rawProfile: unknown) => {
try {
@@ -59,8 +68,7 @@ ipcMain.handle('chromadb:connect', async (_event, rawProfileId: unknown, rawProf
track('chroma_connected')
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to connect to ChromaDB'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.connect', 'Failed to connect to ChromaDB')
}
})
@@ -74,8 +82,7 @@ ipcMain.handle('chromadb:listCollections', async (_event, rawProfileId: unknown)
const collections = await service.listCollections()
return { success: true, data: collections }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to fetch collections'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.listCollections', 'Failed to fetch collections')
}
})
@@ -90,8 +97,7 @@ ipcMain.handle('chromadb:getDocuments', async (_event, rawProfileId: unknown, ra
const documents = await service.getCollectionDocuments(collectionName)
return { success: true, data: documents }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to fetch documents'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.getDocuments', 'Failed to fetch documents')
}
})
@@ -108,8 +114,7 @@ ipcMain.handle('chromadb:searchDocuments', async (_event, rawProfileId: unknown,
const documents = await service.searchDocuments(params, embeddingOverride)
return { success: true, data: documents }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to search documents'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.searchDocuments', 'Failed to search documents')
}
})
@@ -127,8 +132,7 @@ ipcMain.handle('chromadb:updateDocument', async (_event, rawProfileId: unknown,
track('document_updated')
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to update document'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.updateDocument', 'Failed to update document')
}
})
@@ -146,8 +150,7 @@ ipcMain.handle('chromadb:createDocument', async (_event, rawProfileId: unknown,
track('document_created')
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to create document'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.createDocument', 'Failed to create document')
}
})
@@ -165,8 +168,7 @@ ipcMain.handle('chromadb:deleteDocuments', async (_event, rawProfileId: unknown,
})
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to delete documents'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.deleteDocuments', 'Failed to delete documents')
}
})
@@ -186,8 +188,7 @@ ipcMain.handle('chromadb:createDocumentsBatch', async (_event, rawProfileId: unk
})
return { success: true, data: result }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to create documents'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.createDocumentsBatch', 'Failed to create documents')
}
})
@@ -206,8 +207,7 @@ ipcMain.handle('chromadb:createCollection', async (_event, rawProfileId: unknown
})
return { success: true, data: collection }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to create collection'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.createCollection', 'Failed to create collection')
}
})
@@ -223,8 +223,7 @@ ipcMain.handle('chromadb:deleteCollection', async (_event, rawProfileId: unknown
track('collection_deleted')
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to delete collection'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.deleteCollection', 'Failed to delete collection')
}
})
@@ -264,8 +263,7 @@ ipcMain.handle('chromadb:copyCollection', async (event, rawProfileId: unknown, r
return { success: result.success, data: result, error: result.error }
} catch (error) {
activeCopyOperations.delete(profileId)
- const message = error instanceof Error ? error.message : 'Failed to copy collection'
- return { success: false, error: message }
+ return reportIpcError(error, 'chromadb.copyCollection', 'Failed to copy collection')
}
})
@@ -390,8 +388,7 @@ ipcMain.handle('profiles:getAll', async () => {
const profiles = connectionStore.getProfiles()
return { success: true, data: profiles }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to fetch profiles'
- return { success: false, error: message }
+ return reportIpcError(error, 'profiles.getAll', 'Failed to fetch profiles')
}
})
@@ -401,8 +398,7 @@ ipcMain.handle('profiles:save', async (_event, rawProfile: unknown) => {
connectionStore.saveProfile(profile)
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to save profile'
- return { success: false, error: message }
+ return reportIpcError(error, 'profiles.save', 'Failed to save profile')
}
})
@@ -412,8 +408,7 @@ ipcMain.handle('profiles:delete', async (_event, rawId: unknown) => {
connectionStore.deleteProfile(id)
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to delete profile'
- return { success: false, error: message }
+ return reportIpcError(error, 'profiles.delete', 'Failed to delete profile')
}
})
@@ -422,8 +417,7 @@ ipcMain.handle('profiles:getLastActive', async () => {
const id = connectionStore.getLastActiveProfileId()
return { success: true, data: id }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to fetch last active profile'
- return { success: false, error: message }
+ return reportIpcError(error, 'profiles.getLastActive', 'Failed to fetch last active profile')
}
})
@@ -433,8 +427,7 @@ ipcMain.handle('profiles:setLastActive', async (_event, rawId: unknown) => {
connectionStore.setLastActiveProfileId(id)
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to set last active profile'
- return { success: false, error: message }
+ return reportIpcError(error, 'profiles.setLastActive', 'Failed to set last active profile')
}
})
@@ -445,8 +438,7 @@ ipcMain.handle('profiles:getEmbeddingOverride', async (_event, rawProfileId: unk
const override = connectionStore.getEmbeddingOverride(profileId, collectionName)
return { success: true, data: override }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to get embedding override'
- return { success: false, error: message }
+ return reportIpcError(error, 'profiles.getEmbeddingOverride', 'Failed to get embedding override')
}
})
@@ -458,8 +450,7 @@ ipcMain.handle('profiles:setEmbeddingOverride', async (_event, rawProfileId: unk
connectionStore.setEmbeddingOverride(profileId, collectionName, override)
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to set embedding override'
- return { success: false, error: message }
+ return reportIpcError(error, 'profiles.setEmbeddingOverride', 'Failed to set embedding override')
}
})
@@ -470,8 +461,7 @@ ipcMain.handle('profiles:clearEmbeddingOverride', async (_event, rawProfileId: u
connectionStore.clearEmbeddingOverride(profileId, collectionName)
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to clear embedding override'
- return { success: false, error: message }
+ return reportIpcError(error, 'profiles.clearEmbeddingOverride', 'Failed to clear embedding override')
}
})
@@ -482,8 +472,7 @@ ipcMain.handle('window:create-connection', async (_event, rawProfile: unknown) =
const { window: win, windowId } = windowManager.createConnectionWindow(profile)
return { success: true, data: { windowId } }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to create connection window'
- return { success: false, error: message }
+ return reportIpcError(error, 'window.createConnection', 'Failed to create connection window')
}
})
@@ -523,8 +512,7 @@ ipcMain.handle('window:get-info', async (event) => {
return { success: false, error: 'Window type unknown' }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to get window info'
- return { success: false, error: message }
+ return reportIpcError(error, 'window.getInfo', 'Failed to get window info')
}
})
@@ -540,8 +528,7 @@ ipcMain.handle('window:close-current', async (event) => {
win.close()
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to close window'
- return { success: false, error: message }
+ return reportIpcError(error, 'window.closeCurrent', 'Failed to close window')
}
})
@@ -564,8 +551,7 @@ ipcMain.handle('window:get-profile', async (_event, rawProfileId: unknown) => {
return { success: true, data: profile }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to get profile'
- return { success: false, error: message }
+ return reportIpcError(error, 'window.getProfile', 'Failed to get profile')
}
})
@@ -585,8 +571,7 @@ ipcMain.handle('settings:getApiKeys', async () => {
const apiKeys = settingsStore.getApiKeys()
return { success: true, data: apiKeys }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to get API keys'
- return { success: false, error: message }
+ return reportIpcError(error, 'settings.getApiKeys', 'Failed to get API keys')
}
})
@@ -596,8 +581,7 @@ ipcMain.handle('settings:setApiKeys', async (_event, rawApiKeys: unknown) => {
settingsStore.setApiKeys(apiKeys)
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to save API keys'
- return { success: false, error: message }
+ return reportIpcError(error, 'settings.setApiKeys', 'Failed to save API keys')
}
})
@@ -606,8 +590,7 @@ ipcMain.handle('settings:getTheme', async () => {
const theme = settingsStore.getTheme()
return { success: true, data: theme }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to get theme'
- return { success: false, error: message }
+ return reportIpcError(error, 'settings.getTheme', 'Failed to get theme')
}
})
@@ -626,8 +609,34 @@ ipcMain.handle('settings:setTheme', async (event, rawTheme: unknown) => {
updateThemeMenu()
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to set theme'
- return { success: false, error: message }
+ return reportIpcError(error, 'settings.setTheme', 'Failed to set theme')
+ }
+})
+
+ipcMain.handle('settings:getErrorReportingEnabled', async () => {
+ try {
+ return { success: true, data: settingsStore.isErrorReportingEnabled() }
+ } catch (error) {
+ return reportIpcError(error, 'settings.getErrorReportingEnabled', 'Failed to get error reporting setting')
+ }
+})
+
+ipcMain.handle('settings:setErrorReportingEnabled', async (event, rawEnabled: unknown) => {
+ try {
+ const enabled = parseErrorReportingEnabled(rawEnabled)
+ settingsStore.setErrorReportingEnabled(enabled)
+ setErrorMonitoringEnabled(enabled)
+
+ const senderWindow = BrowserWindow.fromWebContents(event.sender)
+ BrowserWindow.getAllWindows().forEach(win => {
+ if (win !== senderWindow) {
+ win.webContents.send('settings:error-reporting-changed', enabled)
+ }
+ })
+
+ return { success: true }
+ } catch (error) {
+ return reportIpcError(error, 'settings.setErrorReportingEnabled', 'Failed to set error reporting setting')
}
})
@@ -636,8 +645,7 @@ ipcMain.handle('settings:openWindow', async () => {
windowManager.createSettingsWindow()
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to open settings'
- return { success: false, error: message }
+ return reportIpcError(error, 'settings.openWindow', 'Failed to open settings')
}
})
@@ -647,8 +655,7 @@ ipcMain.handle('shell:openExternal', async (_event, rawUrl: unknown) => {
await openValidatedExternalUrl(rawUrl)
return { success: true }
} catch (error) {
- const message = error instanceof Error ? error.message : 'Failed to open URL'
- return { success: false, error: message }
+ return reportIpcError(error, 'shell.openExternal', 'Failed to open URL')
}
})
diff --git a/electron/preload.ts b/electron/preload.ts
index 5678624..5b37ff1 100644
--- a/electron/preload.ts
+++ b/electron/preload.ts
@@ -1,3 +1,4 @@
+import '@sentry/electron/preload'
import { contextBridge, ipcRenderer } from 'electron'
import type {
ConnectionProfile,
@@ -248,6 +249,24 @@ contextBridge.exposeInMainWorld('electronAPI', {
throw new Error(result.error)
}
},
+ getErrorReportingEnabled: async (): Promise => {
+ const result = await ipcRenderer.invoke('settings:getErrorReportingEnabled')
+ if (!result.success) {
+ throw new Error(result.error)
+ }
+ return result.data
+ },
+ setErrorReportingEnabled: async (enabled: boolean): Promise => {
+ const result = await ipcRenderer.invoke('settings:setErrorReportingEnabled', enabled)
+ if (!result.success) {
+ throw new Error(result.error)
+ }
+ },
+ onErrorReportingChange: (callback: (enabled: boolean) => void): (() => void) => {
+ const handler = (_event: any, enabled: boolean) => callback(enabled)
+ ipcRenderer.on('settings:error-reporting-changed', handler)
+ return () => ipcRenderer.removeListener('settings:error-reporting-changed', handler)
+ },
onThemeChange: (callback: (theme: string) => void): (() => void) => {
const handler = (_event: any, theme: string) => callback(theme)
ipcRenderer.on('settings:theme-changed', handler)
diff --git a/electron/settings-store.ts b/electron/settings-store.ts
index 3791f4c..f5a3ce1 100644
--- a/electron/settings-store.ts
+++ b/electron/settings-store.ts
@@ -23,6 +23,7 @@ export type Theme = 'light' | 'dark' | 'system'
interface SettingsSchema {
apiKeys: ApiKeys
theme: Theme
+ errorReportingEnabled: boolean
}
// Legacy store schema (v1 - before theme was added)
@@ -75,6 +76,7 @@ function getStore(): Store {
defaults: {
apiKeys: {},
theme: 'system',
+ errorReportingEnabled: true,
},
encryptionKey: getEncryptionKey(),
clearInvalidConfig: true,
@@ -100,6 +102,7 @@ function getStore(): Store {
defaults: {
apiKeys: {},
theme: 'system',
+ errorReportingEnabled: true,
},
encryptionKey: getEncryptionKey(),
clearInvalidConfig: true,
@@ -147,6 +150,14 @@ export class SettingsStore {
setTheme(theme: Theme): void {
getStore().set('theme', theme)
}
+
+ isErrorReportingEnabled(): boolean {
+ return getStore().get('errorReportingEnabled', true)
+ }
+
+ setErrorReportingEnabled(enabled: boolean): void {
+ getStore().set('errorReportingEnabled', enabled)
+ }
}
export const settingsStore = new SettingsStore()
diff --git a/package.json b/package.json
index faa9f0f..4f5dac7 100644
--- a/package.json
+++ b/package.json
@@ -57,6 +57,7 @@
"license": "MIT",
"devDependencies": {
"@playwright/test": "^1.60.0",
+ "@sentry/vite-plugin": "^5.3.0",
"@tailwindcss/postcss": "^4.1.18",
"@types/node": "^25.0.3",
"@types/react": "^19.2.7",
@@ -96,6 +97,7 @@
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.4",
+ "@sentry/electron": "^7.13.0",
"@tanstack/react-query": "^5.90.16",
"@tanstack/react-table": "^8.21.3",
"bufferutil": "^4.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index de87fc8..eeb9cd2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -74,6 +74,9 @@ importers:
'@radix-ui/react-slot':
specifier: ^1.2.4
version: 1.2.4(@types/react@19.2.7)(react@19.2.3)
+ '@sentry/electron':
+ specifier: ^7.13.0
+ version: 7.13.0
'@tanstack/react-query':
specifier: ^5.90.16
version: 5.90.16(react@19.2.3)
@@ -132,6 +135,9 @@ importers:
'@playwright/test':
specifier: ^1.60.0
version: 1.60.0
+ '@sentry/vite-plugin':
+ specifier: ^5.3.0
+ version: 5.3.0(encoding@0.1.13)(rollup@4.54.0)
'@tailwindcss/postcss':
specifier: ^4.1.18
version: 4.1.18
@@ -176,7 +182,7 @@ importers:
version: 0.14.6
vitest:
specifier: ^4.1.7
- version: 4.1.7(@types/node@25.0.3)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))
+ version: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))
packages:
@@ -321,6 +327,73 @@ packages:
resolution: {integrity: sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw==}
engines: {node: '>=18.0.0'}
+ '@babel/code-frame@7.29.7':
+ resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.29.7':
+ resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.29.7':
+ resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.29.7':
+ resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.29.7':
+ resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-globals@7.29.7':
+ resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.29.7':
+ resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.29.7':
+ resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-string-parser@7.29.7':
+ resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.29.7':
+ resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.29.7':
+ resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.29.7':
+ resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.29.7':
+ resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/template@7.29.7':
+ resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.29.7':
+ resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.29.7':
+ resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==}
+ engines: {node: '>=6.9.0'}
+
'@balena/dockerignore@1.0.2':
resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==}
@@ -624,6 +697,11 @@ packages:
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
engines: {node: '>=14'}
+ '@fastify/otel@0.18.0':
+ resolution: {integrity: sha512-3TASCATfw+ctICSb4ymrv7iCm0qJ0N9CarB+CZ7zIJ7KqNbwI5JjyDL1/sxoC0ccTO1Zyd1iQ+oqncPg5FJXaA==}
+ peerDependencies:
+ '@opentelemetry/api': ^1.9.0
+
'@floating-ui/core@1.7.3':
resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
@@ -875,6 +953,198 @@ packages:
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
deprecated: This functionality has been moved to @npmcli/fs
+ '@opentelemetry/api-logs@0.207.0':
+ resolution: {integrity: sha512-lAb0jQRVyleQQGiuuvCOTDVspc14nx6XJjP4FspJ1sNARo3Regq4ZZbrc3rN4b1TYSuUCvgH+UXUPug4SLOqEQ==}
+ engines: {node: '>=8.0.0'}
+
+ '@opentelemetry/api-logs@0.212.0':
+ resolution: {integrity: sha512-TEEVrLbNROUkYY51sBJGk7lO/OLjuepch8+hmpM6ffMJQ2z/KVCjdHuCFX6fJj8OkJP2zckPjrJzQtXU3IAsFg==}
+ engines: {node: '>=8.0.0'}
+
+ '@opentelemetry/api-logs@0.214.0':
+ resolution: {integrity: sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA==}
+ engines: {node: '>=8.0.0'}
+
+ '@opentelemetry/api@1.9.1':
+ resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==}
+ engines: {node: '>=8.0.0'}
+
+ '@opentelemetry/core@2.6.1':
+ resolution: {integrity: sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': '>=1.0.0 <1.10.0'
+
+ '@opentelemetry/core@2.7.1':
+ resolution: {integrity: sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': '>=1.0.0 <1.10.0'
+
+ '@opentelemetry/instrumentation-amqplib@0.61.0':
+ resolution: {integrity: sha512-mCKoyTGfRNisge4br0NpOFSy2Z1NnEW8hbCJdUDdJFHrPqVzc4IIBPA/vX0U+LUcQqrQvJX+HMIU0dbDRe0i0Q==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-connect@0.57.0':
+ resolution: {integrity: sha512-FMEBChnI4FLN5TE9DHwfH7QpNir1JzXno1uz/TAucVdLCyrG0jTrKIcNHt/i30A0M2AunNBCkcd8Ei26dIPKdg==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-dataloader@0.31.0':
+ resolution: {integrity: sha512-f654tZFQXS5YeLDNb9KySrwtg7SnqZN119FauD7acBoTzuLduaiGTNz88ixcVSOOMGZ+EjJu/RFtx5klObC95g==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-fs@0.33.0':
+ resolution: {integrity: sha512-sCZWXGalQ01wr3tAhSR9ucqFJ0phidpAle6/17HVjD6gN8FLmZMK/8sKxdXYHy3PbnlV1P4zeiSVFNKpbFMNLA==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-generic-pool@0.57.0':
+ resolution: {integrity: sha512-orhmlaK+ZIW9hKU+nHTbXrCSXZcH83AescTqmpamHRobRmYSQwRbD0a1odc0yAzuzOtxYiHiXAnpnIpaSSY7Ow==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-graphql@0.62.0':
+ resolution: {integrity: sha512-3YNuLVPUxafXkH1jBAbGsKNsP3XVzcFDhCDCE3OqBwCwShlqQbLMRMFh1T/d5jaVZiGVmSsfof+ICKD2iOV8xg==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-hapi@0.60.0':
+ resolution: {integrity: sha512-aNljZKYrEa7obLAxd1bCEDxF7kzCLGXTuTJZ8lMR9rIVEjmuKBXN1gfqpm/OB//Zc2zP4iIve1jBp7sr3mQV6w==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-http@0.214.0':
+ resolution: {integrity: sha512-FlkDhZDRjDJDcO2LcSCtjRpkal1NJ8y0fBqBhTvfAR3JSYY2jAIj1kSS5IjmEBt4c3aWv+u/lqLuoCDrrKCSKg==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-ioredis@0.62.0':
+ resolution: {integrity: sha512-ZYt//zcPve8qklaZX+5Z4MkU7UpEkFRrxsf2cnaKYBitqDnsCN69CPAuuMOX6NYdW2rG9sFy7V/QWtBlP5XiNQ==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-kafkajs@0.23.0':
+ resolution: {integrity: sha512-4K+nVo+zI+aDz0Z85SObwbdixIbzS9moIuKJaYsdlzcHYnKOPtB7ya8r8Ezivy/GVIBHiKJVq4tv+BEkgOMLaQ==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-knex@0.58.0':
+ resolution: {integrity: sha512-Hc/o8fSsaWxZ8r1Yw4rNDLwTpUopTf4X32y4W6UhlHmW8Wizz8wfhgOKIelSeqFVTKBBPIDUOsQWuIMxBmu8Bw==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-koa@0.62.0':
+ resolution: {integrity: sha512-uVip0VuGUQXZ+vFxkKxAUNq8qNl+VFlyHDh/U6IQ8COOEDfbEchdaHnpFrMYF3psZRUuoSIgb7xOeXj00RdwDA==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.9.0
+
+ '@opentelemetry/instrumentation-lru-memoizer@0.58.0':
+ resolution: {integrity: sha512-6grM3TdMyHzlGY1cUA+mwoPueB1F3dYKgKtZIH6jOFXqfHAByyLTc+6PFjGM9tKh52CFBJaDwodNlL/Td39z7Q==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-mongodb@0.67.0':
+ resolution: {integrity: sha512-1WJp5N1lYfHq2IhECOTewFs5Tf2NfUOwQRqs/rZdXKTezArMlucxgzAaqcgp3A3YREXopXTpXHsxZTGHjNhMdQ==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-mongoose@0.60.0':
+ resolution: {integrity: sha512-8BahAZpKsOoc+lrZGb7Ofn4g3z8qtp5IxDfvAVpKXsEheQN7ONMH5djT5ihy6yf8yyeQJGS0gXFfpEAEeEHqQg==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-mysql2@0.60.0':
+ resolution: {integrity: sha512-m/5d3bxQALllCzezYDk/6vajh0tj5OijMMvOZGr+qN1NMXm1dzMNwyJ0gNZW7Fo3YFRyj/jJMxIw+W7d525dlw==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-mysql@0.60.0':
+ resolution: {integrity: sha512-08pO8GFPEIz2zquKDGteBZDNmwketdgH8hTe9rVYgW9kCJXq1Psj3wPQGx+VaX4ZJKCfPeoLMYup9+cxHvZyVQ==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-pg@0.66.0':
+ resolution: {integrity: sha512-KxfLGXBb7k2ueaPJfq2GXBDXBly8P+SpR/4Mj410hhNgmQF3sCqwXvUBQxZQkDAmsdBAoenM+yV1LhtsMRamcA==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-redis@0.62.0':
+ resolution: {integrity: sha512-y3pPpot7WzR/8JtHcYlTYsyY8g+pbFhAqbwAuG5bLPnR6v6pt1rQc0DpH0OlGP/9CZbWBP+Zhwp9yFoygf/ZXQ==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation-tedious@0.33.0':
+ resolution: {integrity: sha512-Q6WQwAD01MMTub31GlejoiFACYNw26J426wyjvU7by7fDIr2nZXNW4vhTGs7i7F0TnXBO3xN688g1tdUgYwJ5w==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation@0.207.0':
+ resolution: {integrity: sha512-y6eeli9+TLKnznrR8AZlQMSJT7wILpXH+6EYq5Vf/4Ao+huI7EedxQHwRgVUOMLFbe7VFDvHJrX9/f4lcwnJsA==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation@0.212.0':
+ resolution: {integrity: sha512-IyXmpNnifNouMOe0I/gX7ENfv2ZCNdYTF0FpCsoBcpbIHzk81Ww9rQTYTnvghszCg7qGrIhNvWC8dhEifgX9Jg==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/instrumentation@0.214.0':
+ resolution: {integrity: sha512-MHqEX5Dk59cqVah5LiARMACku7jXSVk9iVDWOea4x3cr7VfdByeDCURK6o1lntT1JS/Tsovw01UJrBhN3/uC5w==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.3.0
+
+ '@opentelemetry/redis-common@0.38.3':
+ resolution: {integrity: sha512-VCghU1JYs/4gP6Gqf/xro9MEsZ7LrMv2uONVsaESKL38ZOB9BqnI98FfS23wjMnHlpuE+TTaWSoAVNpTwYXzjw==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+
+ '@opentelemetry/resources@2.7.1':
+ resolution: {integrity: sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': '>=1.3.0 <1.10.0'
+
+ '@opentelemetry/sdk-trace-base@2.7.1':
+ resolution: {integrity: sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': '>=1.3.0 <1.10.0'
+
+ '@opentelemetry/semantic-conventions@1.41.1':
+ resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==}
+ engines: {node: '>=14'}
+
+ '@opentelemetry/sql-common@0.41.2':
+ resolution: {integrity: sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==}
+ engines: {node: ^18.19.0 || >=20.6.0}
+ peerDependencies:
+ '@opentelemetry/api': ^1.1.0
+
'@pkgjs/parseargs@0.11.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
@@ -884,6 +1154,11 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ '@prisma/instrumentation@7.6.0':
+ resolution: {integrity: sha512-ZPW2gRiwpPzEfgeZgaekhqXrbW+Y2RJKHVqUmlhZhKzRNCcvR6DykzylDrynpArKKRQtLxoZy36fK7U0p3pdgQ==}
+ peerDependencies:
+ '@opentelemetry/api': ^1.8
+
'@protobufjs/aspromise@1.1.2':
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
@@ -1374,6 +1649,148 @@ packages:
cpu: [x64]
os: [win32]
+ '@sentry-internal/browser-utils@10.50.0':
+ resolution: {integrity: sha512-42bxyRTxnCmYlWnvz4CxikuQNanw8UNma2WJrtxJ0f1MAJV2GhQGSHDLnA+lvFlmiz6qct3pfen/NXGyOTegTA==}
+ engines: {node: '>=18'}
+
+ '@sentry-internal/feedback@10.50.0':
+ resolution: {integrity: sha512-0k9XZF0wn86f77mIO2U3gNNyDZooy139CnEanRzHinrN106vVzvBZ6TUEQoHtoO1fqQxr+nWWVrqV/PXUqk47w==}
+ engines: {node: '>=18'}
+
+ '@sentry-internal/replay-canvas@10.50.0':
+ resolution: {integrity: sha512-jx6RKBmcJSWdI92qDGS/sBv1w+7Cww879Z/moX7bw7ipHa/Ts3iDcB3rgZwvhmi17U+mvYsbJeL2DXkPo3TjPw==}
+ engines: {node: '>=18'}
+
+ '@sentry-internal/replay@10.50.0':
+ resolution: {integrity: sha512-51FYNfnvVLAWw1rrEWPFfwHuMRb9mkVCFGA4J9/un7SpeGBsQDziGB0Di4fsCxI7+EdSBpfLHPF0csKtCCw0oQ==}
+ engines: {node: '>=18'}
+
+ '@sentry/babel-plugin-component-annotate@5.3.0':
+ resolution: {integrity: sha512-p4q8gn8wcFqZGP/s2MnJCAAd8fTikaU6A0mM97RDHQgStcrYiaS0Sc5zUNfb1V+UOLPuvdEdL6MwyxfzjYJQTA==}
+ engines: {node: '>= 18'}
+
+ '@sentry/browser@10.50.0':
+ resolution: {integrity: sha512-1f6rAvET6myiTaSeYqvaaBwvq1LfxqWjAPIoAW/NVC9bPMkeEcuvgDajHrnZMrBeWoJ81NMyoLkyX+iOc7MoFA==}
+ engines: {node: '>=18'}
+
+ '@sentry/bundler-plugin-core@5.3.0':
+ resolution: {integrity: sha512-L5T60sWdAI3qWwdg3Ptwek/0TY59PERrxyqp4XMUkroayQvGd9r5dIW9Q1kSeXX9iJ442nXbFZKAOyCKV4Z13Q==}
+ engines: {node: '>= 18'}
+
+ '@sentry/cli-darwin@2.58.6':
+ resolution: {integrity: sha512-udAVvcyfNa0R+95GvPz/+43/N3TC0TYKdkQ7D7jhPSzbcMc7l2fxRNN5yB3UpCA5fWFnW4toeaqwDBhb/Wh3LA==}
+ engines: {node: '>=10'}
+ os: [darwin]
+
+ '@sentry/cli-linux-arm64@2.58.6':
+ resolution: {integrity: sha512-q8mEcNNmeXMy5i+jWT30TVpH7LcP4HD21CD5XRSPAd/a912HF6EpK0ybf/1USO14WOhoXbAGi9txwaWabSe33g==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [linux, freebsd, android]
+
+ '@sentry/cli-linux-arm@2.58.6':
+ resolution: {integrity: sha512-pD0LAt5PcUzAinBwvDqc66x9+2CabHEv486yP0gRjWO7SakbaxmfVq/EXd8VLq/Tzi39LAu422UYK1lpW3MILw==}
+ engines: {node: '>=10'}
+ cpu: [arm]
+ os: [linux, freebsd, android]
+
+ '@sentry/cli-linux-i686@2.58.6':
+ resolution: {integrity: sha512-q8vNJi1eOV/4vxAFWBsEwLHoSYapaZHIf4j76KJGJXFKTkEbsjCOOsKbwUIBTQQhRgV4DFWh3ryfsPS/que4Kg==}
+ engines: {node: '>=10'}
+ cpu: [x86, ia32]
+ os: [linux, freebsd, android]
+
+ '@sentry/cli-linux-x64@2.58.6':
+ resolution: {integrity: sha512-DZu956Mhi3ZRjTBe1WdbGV46ldVbA8d2rgp/fh51GsI25zjBHah4wZnPTSzpc+YqxU6pJpg579B/r3jrIK530Q==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [linux, freebsd, android]
+
+ '@sentry/cli-win32-arm64@2.58.6':
+ resolution: {integrity: sha512-nj0Ff/kmAB73EPDhR8B4O9r+NUHK5GkPCkGWC+kXVemqAJWL5jcJ5KdxG0l/S0z6RoEoltID8/43/B+TaMlT7A==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@sentry/cli-win32-i686@2.58.6':
+ resolution: {integrity: sha512-WNZiDzPbgsEMQWq4avsQ391v/xWKJDIWWWo9GYl+N/w5qcYKkoDW7wQG7T9FasI6ENn68phChTOAPXXxbfAdOg==}
+ engines: {node: '>=10'}
+ cpu: [x86, ia32]
+ os: [win32]
+
+ '@sentry/cli-win32-x64@2.58.6':
+ resolution: {integrity: sha512-R35WJ17oF4D2eqI1DR2sQQqr0fjRTt5xoP16WrTu91XM2lndRMFsnjh+/GttbxapLCBNlrjzia99MJ0PZHZpgA==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@sentry/cli@2.58.6':
+ resolution: {integrity: sha512-baBcNPLLfUi9WuL+Tpri9BFaAdvugZIKelC5X0tt0Zdy+K0K+PCVSrnNmwMWU/HyaF/SEv6b6UHnXIdqanBlcg==}
+ engines: {node: '>= 10'}
+ hasBin: true
+
+ '@sentry/core@10.50.0':
+ resolution: {integrity: sha512-J4A+vzUO3adl0TkFCjaN1+4miamrjHiEIYuLHiuu1lmAjq5WIVw32ObvAh4yMwNtxyaEMosTrrh5M6f12XSJFg==}
+ engines: {node: '>=18'}
+
+ '@sentry/electron@7.13.0':
+ resolution: {integrity: sha512-zW/1c9fKafCZsvhRRp9mIDH9bSvzBiIUwoN087zDDHc0vatVsqqai8nUk0bUewwYZY4Inia7r5w+kPWi8LXZzg==}
+ peerDependencies:
+ '@sentry/node-native': 10.50.0
+ peerDependenciesMeta:
+ '@sentry/node-native':
+ optional: true
+
+ '@sentry/node-core@10.50.0':
+ resolution: {integrity: sha512-Eb1BYf4Lc7ZYmdX3acKP6SgyGikrBA370gbGHaWI5jRu7G7vig8sIu1ghPmY5AlvqBPOetado7GniXr6fAXbTw==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@opentelemetry/api': ^1.9.0
+ '@opentelemetry/core': ^1.30.1 || ^2.1.0
+ '@opentelemetry/exporter-trace-otlp-http': '>=0.57.0 <1'
+ '@opentelemetry/instrumentation': '>=0.57.1 <1'
+ '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0
+ '@opentelemetry/semantic-conventions': ^1.39.0
+ peerDependenciesMeta:
+ '@opentelemetry/api':
+ optional: true
+ '@opentelemetry/core':
+ optional: true
+ '@opentelemetry/exporter-trace-otlp-http':
+ optional: true
+ '@opentelemetry/instrumentation':
+ optional: true
+ '@opentelemetry/sdk-trace-base':
+ optional: true
+ '@opentelemetry/semantic-conventions':
+ optional: true
+
+ '@sentry/node@10.50.0':
+ resolution: {integrity: sha512-TvwzFQu8MGKzMQ2/tqxcNzFA8UG2kKTB+GDmA4uOzx3+GT849YZRRSJzEXCmYhk1teVd2fbmgqyYY2nyLF5a+Q==}
+ engines: {node: '>=18'}
+
+ '@sentry/opentelemetry@10.50.0':
+ resolution: {integrity: sha512-axn3pgDPveGdaMUC0abMCmFN7ux2pA5ebPufCef4lMIsyg7BBQvaEJ+vE19wjstMaBCAJGsdZlL3eeP2rtgRMw==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@opentelemetry/api': ^1.9.0
+ '@opentelemetry/core': ^1.30.1 || ^2.1.0
+ '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0
+ '@opentelemetry/semantic-conventions': ^1.39.0
+
+ '@sentry/rollup-plugin@5.3.0':
+ resolution: {integrity: sha512-hgPGPYdQJ/G1cGYOxAb7d4z3V+/k/E5/P/5TFPEEBLuIbFFk+JG0CISUDJdzXJjO382Lb99PBJuXGbueBmO79w==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ rollup: '>=3.2.0'
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@sentry/vite-plugin@5.3.0':
+ resolution: {integrity: sha512-qcoSzo4n2MulVQ70UUPLq6dTleb2a2HwL2wuwvAgWhPChrYTuk6A6mDg6aQb9fairPAwFPiU9PzOANpoDJcz1A==}
+ engines: {node: '>= 18'}
+
'@sindresorhus/is@4.6.0':
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
engines: {node: '>=10'}
@@ -1682,6 +2099,9 @@ packages:
'@types/chai@5.2.3':
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
+ '@types/connect@3.4.38':
+ resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
+
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
@@ -1709,6 +2129,9 @@ packages:
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+ '@types/mysql@2.15.27':
+ resolution: {integrity: sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==}
+
'@types/node-fetch@2.6.13':
resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==}
@@ -1727,6 +2150,12 @@ packages:
'@types/parquetjs@0.10.6':
resolution: {integrity: sha512-ZCsD6j97YD0mGU8/VnVs3NjORXa7zeHvqlpJpCqy4jU8a1O21dalL+MFn9QNbdEfy8rszR1N7NHeT7/LdtHf+A==}
+ '@types/pg-pool@2.0.7':
+ resolution: {integrity: sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng==}
+
+ '@types/pg@8.15.6':
+ resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==}
+
'@types/plist@3.0.5':
resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==}
@@ -1753,6 +2182,9 @@ packages:
'@types/ssh2@1.15.5':
resolution: {integrity: sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ==}
+ '@types/tedious@4.0.14':
+ resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==}
+
'@types/verror@1.10.11':
resolution: {integrity: sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==}
@@ -1799,6 +2231,16 @@ packages:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'}
+ acorn-import-attributes@1.9.5:
+ resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==}
+ peerDependencies:
+ acorn: ^8
+
+ acorn@8.16.0:
+ resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
agent-base@6.0.2:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'}
@@ -1931,6 +2373,10 @@ packages:
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ balanced-match@4.0.4:
+ resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
+ engines: {node: 18 || 20 || >=22}
+
bare-events@2.8.2:
resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==}
peerDependencies:
@@ -2001,6 +2447,10 @@ packages:
brace-expansion@2.0.2:
resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
+ brace-expansion@5.0.6:
+ resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==}
+ engines: {node: 18 || 20 || >=22}
+
brotli@1.3.3:
resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==}
@@ -2141,6 +2591,9 @@ packages:
resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
engines: {node: '>=8'}
+ cjs-module-lexer@2.2.0:
+ resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==}
+
class-variance-authority@0.7.1:
resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
@@ -2513,6 +2966,10 @@ packages:
filelist@1.0.4:
resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
+ find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+
flatbuffers@25.9.23:
resolution: {integrity: sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==}
@@ -2548,6 +3005,9 @@ packages:
resolution: {integrity: sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg==}
engines: {node: '>= 18'}
+ forwarded-parse@2.1.2:
+ resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==}
+
fraction.js@5.3.4:
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
@@ -2602,6 +3062,10 @@ packages:
resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==}
engines: {node: '>=14'}
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
@@ -2630,6 +3094,10 @@ packages:
resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==}
hasBin: true
+ glob@13.0.6:
+ resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
+ engines: {node: 18 || 20 || >=22}
+
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
@@ -2734,6 +3202,13 @@ packages:
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+ import-in-the-middle@2.0.6:
+ resolution: {integrity: sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw==}
+
+ import-in-the-middle@3.0.1:
+ resolution: {integrity: sha512-pYkiyXVL2Mf3pozdlDGV6NAObxQx13Ae8knZk1UJRJ6uRW/ZRmTGHlQYtrsSl7ubuE5F8CD1z+s1n4RHNuTtuA==}
+ engines: {node: '>=18'}
+
imurmurhash@0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
@@ -2811,10 +3286,18 @@ packages:
js-base64@3.7.2:
resolution: {integrity: sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==}
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
js-yaml@4.1.1:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
json-bigint@1.0.0:
resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==}
@@ -2934,6 +3417,10 @@ packages:
resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
engines: {node: '>= 12.0.0'}
+ locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+
lodash.camelcase@4.3.0:
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
@@ -2964,6 +3451,13 @@ packages:
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+ lru-cache@11.5.1:
+ resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==}
+ engines: {node: 20 || >=22}
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
@@ -3028,6 +3522,10 @@ packages:
resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
engines: {node: 20 || >=22}
+ minimatch@10.2.5:
+ resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==}
+ engines: {node: 18 || 20 || >=22}
+
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -3074,6 +3572,10 @@ packages:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
+ minipass@7.1.3:
+ resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
minizlib@2.1.2:
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
engines: {node: '>= 8'}
@@ -3094,6 +3596,9 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ module-details-from-path@1.0.4:
+ resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==}
+
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -3218,6 +3723,10 @@ packages:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
+ p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+
p-map@4.0.0:
resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
engines: {node: '>=10'}
@@ -3229,6 +3738,10 @@ packages:
resolution: {integrity: sha512-Y6FOc3Oi2AxY4TzJPz7fhICCR8tQNL3p+2xGQoUAMbmlJBR7+JJmMrwuyMjIpDiM7G8Wj/8oqOH4UDUmu4I5ZA==}
engines: {node: '>=7.6'}
+ path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+
path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
@@ -3241,6 +3754,10 @@ packages:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
+ path-scurry@2.0.2:
+ resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
+ engines: {node: 18 || 20 || >=22}
+
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
@@ -3251,6 +3768,17 @@ packages:
pend@1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
+ pg-int8@1.0.1:
+ resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
+ engines: {node: '>=4.0.0'}
+
+ pg-protocol@1.14.0:
+ resolution: {integrity: sha512-n5taZ1kO3s9ngDTVxsEznOqCyToTgz0FLuPq0B33COy5pPpuWJpY3/2oRBVETuOgzdqRXfWpM9HIhp2LBBT1BA==}
+
+ pg-types@2.2.0:
+ resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
+ engines: {node: '>=4'}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -3282,6 +3810,22 @@ packages:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
+ postgres-array@2.0.0:
+ resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
+ engines: {node: '>=4'}
+
+ postgres-bytea@1.0.1:
+ resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==}
+ engines: {node: '>=0.10.0'}
+
+ postgres-date@1.0.7:
+ resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
+ engines: {node: '>=0.10.0'}
+
+ postgres-interval@1.2.0:
+ resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
+ engines: {node: '>=0.10.0'}
+
postject@1.0.0-alpha.6:
resolution: {integrity: sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==}
engines: {node: '>=14.0.0'}
@@ -3425,6 +3969,10 @@ packages:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
+ require-in-the-middle@8.0.1:
+ resolution: {integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==}
+ engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'}
+
resedit@1.7.2:
resolution: {integrity: sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==}
engines: {node: '>=12', npm: '>=6'}
@@ -4010,6 +4558,9 @@ packages:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
@@ -4510,37 +5061,137 @@ snapshots:
'@aws/lambda-invoke-store@0.2.3': {}
- '@balena/dockerignore@1.0.2': {}
+ '@babel/code-frame@7.29.7':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.29.7
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
- '@chroma-core/ai-embeddings-common@0.1.9':
+ '@babel/compat-data@7.29.7': {}
+
+ '@babel/core@7.29.7':
dependencies:
- ajv: 8.17.1
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/helpers': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/template': 7.29.7
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.3
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
- '@chroma-core/chroma-cloud-qwen@0.1.10(chromadb@3.2.0)':
+ '@babel/generator@7.29.7':
dependencies:
- '@chroma-core/ai-embeddings-common': 0.1.9
- chromadb: 3.2.0
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
- '@chroma-core/cloudflare-worker-ai@0.1.8(chromadb@3.2.0)':
+ '@babel/helper-compilation-targets@7.29.7':
dependencies:
- '@chroma-core/ai-embeddings-common': 0.1.9
- chromadb: 3.2.0
+ '@babel/compat-data': 7.29.7
+ '@babel/helper-validator-option': 7.29.7
+ browserslist: 4.28.1
+ lru-cache: 5.1.1
+ semver: 6.3.1
- '@chroma-core/cohere@0.1.8(chromadb@3.2.0)':
+ '@babel/helper-globals@7.29.7': {}
+
+ '@babel/helper-module-imports@7.29.7':
dependencies:
- '@chroma-core/ai-embeddings-common': 0.1.9
- chromadb: 3.2.0
- cohere-ai: 7.20.0
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
transitivePeerDependencies:
- - aws-crt
+ - supports-color
- '@chroma-core/default-embed@0.1.9':
+ '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)':
dependencies:
- '@chroma-core/ai-embeddings-common': 0.1.9
- '@huggingface/transformers': 3.8.1
+ '@babel/core': 7.29.7
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
- '@chroma-core/google-gemini@0.1.8(bufferutil@4.1.0)(chromadb@3.2.0)(encoding@0.1.13)(utf-8-validate@6.0.6)':
- dependencies:
+ '@babel/helper-string-parser@7.29.7': {}
+
+ '@babel/helper-validator-identifier@7.29.7': {}
+
+ '@babel/helper-validator-option@7.29.7': {}
+
+ '@babel/helpers@7.29.7':
+ dependencies:
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
+
+ '@babel/parser@7.29.7':
+ dependencies:
+ '@babel/types': 7.29.7
+
+ '@babel/template@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+
+ '@babel/traverse@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.7
+ '@babel/helper-globals': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.29.7':
+ dependencies:
+ '@babel/helper-string-parser': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+
+ '@balena/dockerignore@1.0.2': {}
+
+ '@chroma-core/ai-embeddings-common@0.1.9':
+ dependencies:
+ ajv: 8.17.1
+
+ '@chroma-core/chroma-cloud-qwen@0.1.10(chromadb@3.2.0)':
+ dependencies:
+ '@chroma-core/ai-embeddings-common': 0.1.9
+ chromadb: 3.2.0
+
+ '@chroma-core/cloudflare-worker-ai@0.1.8(chromadb@3.2.0)':
+ dependencies:
+ '@chroma-core/ai-embeddings-common': 0.1.9
+ chromadb: 3.2.0
+
+ '@chroma-core/cohere@0.1.8(chromadb@3.2.0)':
+ dependencies:
+ '@chroma-core/ai-embeddings-common': 0.1.9
+ chromadb: 3.2.0
+ cohere-ai: 7.20.0
+ transitivePeerDependencies:
+ - aws-crt
+
+ '@chroma-core/default-embed@0.1.9':
+ dependencies:
+ '@chroma-core/ai-embeddings-common': 0.1.9
+ '@huggingface/transformers': 3.8.1
+
+ '@chroma-core/google-gemini@0.1.8(bufferutil@4.1.0)(chromadb@3.2.0)(encoding@0.1.13)(utf-8-validate@6.0.6)':
+ dependencies:
'@chroma-core/ai-embeddings-common': 0.1.9
'@google/genai': 0.14.1(bufferutil@4.1.0)(encoding@0.1.13)(utf-8-validate@6.0.6)
chromadb: 3.2.0
@@ -4823,6 +5474,16 @@ snapshots:
'@fastify/busboy@2.1.1': {}
+ '@fastify/otel@0.18.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.212.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ minimatch: 10.2.5
+ transitivePeerDependencies:
+ - supports-color
+
'@floating-ui/core@1.7.3':
dependencies:
'@floating-ui/utils': 0.2.10
@@ -5046,6 +5707,252 @@ snapshots:
mkdirp: 1.0.4
rimraf: 3.0.2
+ '@opentelemetry/api-logs@0.207.0':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+
+ '@opentelemetry/api-logs@0.212.0':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+
+ '@opentelemetry/api-logs@0.214.0':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+
+ '@opentelemetry/api@1.9.1': {}
+
+ '@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/semantic-conventions': 1.41.1
+
+ '@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/semantic-conventions': 1.41.1
+
+ '@opentelemetry/instrumentation-amqplib@0.61.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-connect@0.57.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ '@types/connect': 3.4.38
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-dataloader@0.31.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-fs@0.33.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-generic-pool@0.57.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-graphql@0.62.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-hapi@0.60.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-http@0.214.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ forwarded-parse: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-ioredis@0.62.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/redis-common': 0.38.3
+ '@opentelemetry/semantic-conventions': 1.41.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-kafkajs@0.23.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-knex@0.58.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-koa@0.62.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-lru-memoizer@0.58.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-mongodb@0.67.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-mongoose@0.60.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-mysql2@0.60.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.1)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-mysql@0.60.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ '@types/mysql': 2.15.27
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-pg@0.66.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.1)
+ '@types/pg': 8.15.6
+ '@types/pg-pool': 2.0.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-redis@0.62.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/redis-common': 0.38.3
+ '@opentelemetry/semantic-conventions': 1.41.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation-tedious@0.33.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ '@types/tedious': 4.0.14
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation@0.207.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/api-logs': 0.207.0
+ import-in-the-middle: 2.0.6
+ require-in-the-middle: 8.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation@0.212.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/api-logs': 0.212.0
+ import-in-the-middle: 2.0.6
+ require-in-the-middle: 8.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/api-logs': 0.214.0
+ import-in-the-middle: 3.0.1
+ require-in-the-middle: 8.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@opentelemetry/redis-common@0.38.3': {}
+
+ '@opentelemetry/resources@2.7.1(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+
+ '@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+
+ '@opentelemetry/semantic-conventions@1.41.1': {}
+
+ '@opentelemetry/sql-common@0.41.2(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+
'@pkgjs/parseargs@0.11.0':
optional: true
@@ -5053,6 +5960,13 @@ snapshots:
dependencies:
playwright: 1.60.0
+ '@prisma/instrumentation@7.6.0(@opentelemetry/api@1.9.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/instrumentation': 0.207.0(@opentelemetry/api@1.9.1)
+ transitivePeerDependencies:
+ - supports-color
+
'@protobufjs/aspromise@1.1.2': {}
'@protobufjs/base64@1.1.2': {}
@@ -5456,6 +6370,178 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.54.0':
optional: true
+ '@sentry-internal/browser-utils@10.50.0':
+ dependencies:
+ '@sentry/core': 10.50.0
+
+ '@sentry-internal/feedback@10.50.0':
+ dependencies:
+ '@sentry/core': 10.50.0
+
+ '@sentry-internal/replay-canvas@10.50.0':
+ dependencies:
+ '@sentry-internal/replay': 10.50.0
+ '@sentry/core': 10.50.0
+
+ '@sentry-internal/replay@10.50.0':
+ dependencies:
+ '@sentry-internal/browser-utils': 10.50.0
+ '@sentry/core': 10.50.0
+
+ '@sentry/babel-plugin-component-annotate@5.3.0': {}
+
+ '@sentry/browser@10.50.0':
+ dependencies:
+ '@sentry-internal/browser-utils': 10.50.0
+ '@sentry-internal/feedback': 10.50.0
+ '@sentry-internal/replay': 10.50.0
+ '@sentry-internal/replay-canvas': 10.50.0
+ '@sentry/core': 10.50.0
+
+ '@sentry/bundler-plugin-core@5.3.0(encoding@0.1.13)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@sentry/babel-plugin-component-annotate': 5.3.0
+ '@sentry/cli': 2.58.6(encoding@0.1.13)
+ dotenv: 16.6.1
+ find-up: 5.0.0
+ glob: 13.0.6
+ magic-string: 0.30.21
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+
+ '@sentry/cli-darwin@2.58.6':
+ optional: true
+
+ '@sentry/cli-linux-arm64@2.58.6':
+ optional: true
+
+ '@sentry/cli-linux-arm@2.58.6':
+ optional: true
+
+ '@sentry/cli-linux-i686@2.58.6':
+ optional: true
+
+ '@sentry/cli-linux-x64@2.58.6':
+ optional: true
+
+ '@sentry/cli-win32-arm64@2.58.6':
+ optional: true
+
+ '@sentry/cli-win32-i686@2.58.6':
+ optional: true
+
+ '@sentry/cli-win32-x64@2.58.6':
+ optional: true
+
+ '@sentry/cli@2.58.6(encoding@0.1.13)':
+ dependencies:
+ https-proxy-agent: 5.0.1
+ node-fetch: 2.7.0(encoding@0.1.13)
+ progress: 2.0.3
+ proxy-from-env: 1.1.0
+ which: 2.0.2
+ optionalDependencies:
+ '@sentry/cli-darwin': 2.58.6
+ '@sentry/cli-linux-arm': 2.58.6
+ '@sentry/cli-linux-arm64': 2.58.6
+ '@sentry/cli-linux-i686': 2.58.6
+ '@sentry/cli-linux-x64': 2.58.6
+ '@sentry/cli-win32-arm64': 2.58.6
+ '@sentry/cli-win32-i686': 2.58.6
+ '@sentry/cli-win32-x64': 2.58.6
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+
+ '@sentry/core@10.50.0': {}
+
+ '@sentry/electron@7.13.0':
+ dependencies:
+ '@sentry/browser': 10.50.0
+ '@sentry/core': 10.50.0
+ '@sentry/node': 10.50.0
+ transitivePeerDependencies:
+ - '@opentelemetry/exporter-trace-otlp-http'
+ - supports-color
+
+ '@sentry/node-core@10.50.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.41.1)':
+ dependencies:
+ '@sentry/core': 10.50.0
+ '@sentry/opentelemetry': 10.50.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.41.1)
+ import-in-the-middle: 3.0.1
+ optionalDependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+
+ '@sentry/node@10.50.0':
+ dependencies:
+ '@fastify/otel': 0.18.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-amqplib': 0.61.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-connect': 0.57.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-dataloader': 0.31.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-fs': 0.33.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-generic-pool': 0.57.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-graphql': 0.62.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-hapi': 0.60.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-http': 0.214.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-ioredis': 0.62.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-kafkajs': 0.23.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-knex': 0.58.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-koa': 0.62.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-lru-memoizer': 0.58.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-mongodb': 0.67.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-mongoose': 0.60.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-mysql': 0.60.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-mysql2': 0.60.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-pg': 0.66.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-redis': 0.62.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/instrumentation-tedious': 0.33.0(@opentelemetry/api@1.9.1)
+ '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ '@prisma/instrumentation': 7.6.0(@opentelemetry/api@1.9.1)
+ '@sentry/core': 10.50.0
+ '@sentry/node-core': 10.50.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.41.1)
+ '@sentry/opentelemetry': 10.50.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.41.1)
+ import-in-the-middle: 3.0.1
+ transitivePeerDependencies:
+ - '@opentelemetry/exporter-trace-otlp-http'
+ - supports-color
+
+ '@sentry/opentelemetry@10.50.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.41.1)':
+ dependencies:
+ '@opentelemetry/api': 1.9.1
+ '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1)
+ '@opentelemetry/semantic-conventions': 1.41.1
+ '@sentry/core': 10.50.0
+
+ '@sentry/rollup-plugin@5.3.0(encoding@0.1.13)(rollup@4.54.0)':
+ dependencies:
+ '@sentry/bundler-plugin-core': 5.3.0(encoding@0.1.13)
+ magic-string: 0.30.21
+ optionalDependencies:
+ rollup: 4.54.0
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+
+ '@sentry/vite-plugin@5.3.0(encoding@0.1.13)(rollup@4.54.0)':
+ dependencies:
+ '@sentry/bundler-plugin-core': 5.3.0(encoding@0.1.13)
+ '@sentry/rollup-plugin': 5.3.0(encoding@0.1.13)(rollup@4.54.0)
+ transitivePeerDependencies:
+ - encoding
+ - rollup
+ - supports-color
+
'@sindresorhus/is@4.6.0': {}
'@smithy/abort-controller@4.2.7':
@@ -5842,6 +6928,10 @@ snapshots:
'@types/deep-eql': 4.0.2
assertion-error: 2.0.1
+ '@types/connect@3.4.38':
+ dependencies:
+ '@types/node': 25.0.3
+
'@types/debug@4.1.12':
dependencies:
'@types/ms': 2.1.0
@@ -5873,6 +6963,10 @@ snapshots:
'@types/ms@2.1.0': {}
+ '@types/mysql@2.15.27':
+ dependencies:
+ '@types/node': 25.0.3
+
'@types/node-fetch@2.6.13':
dependencies:
'@types/node': 25.0.3
@@ -5898,6 +6992,16 @@ snapshots:
dependencies:
'@types/node-int64': 0.4.32
+ '@types/pg-pool@2.0.7':
+ dependencies:
+ '@types/pg': 8.15.6
+
+ '@types/pg@8.15.6':
+ dependencies:
+ '@types/node': 25.0.3
+ pg-protocol: 1.14.0
+ pg-types: 2.2.0
+
'@types/plist@3.0.5':
dependencies:
'@types/node': 25.0.3
@@ -5933,6 +7037,10 @@ snapshots:
dependencies:
'@types/node': 18.19.130
+ '@types/tedious@4.0.14':
+ dependencies:
+ '@types/node': 25.0.3
+
'@types/verror@1.10.11':
optional: true
@@ -5990,6 +7098,12 @@ snapshots:
dependencies:
event-target-shim: 5.0.1
+ acorn-import-attributes@1.9.5(acorn@8.16.0):
+ dependencies:
+ acorn: 8.16.0
+
+ acorn@8.16.0: {}
+
agent-base@6.0.2:
dependencies:
debug: 4.4.3
@@ -6159,6 +7273,8 @@ snapshots:
balanced-match@1.0.2: {}
+ balanced-match@4.0.4: {}
+
bare-events@2.8.2: {}
bare-fs@4.5.2:
@@ -6228,6 +7344,10 @@ snapshots:
dependencies:
balanced-match: 1.0.2
+ brace-expansion@5.0.6:
+ dependencies:
+ balanced-match: 4.0.4
+
brotli@1.3.3:
dependencies:
base64-js: 1.5.1
@@ -6394,6 +7514,8 @@ snapshots:
ci-info@3.9.0: {}
+ cjs-module-lexer@2.2.0: {}
+
class-variance-authority@0.7.1:
dependencies:
clsx: 2.1.1
@@ -6861,6 +7983,11 @@ snapshots:
dependencies:
minimatch: 5.1.6
+ find-up@5.0.0:
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+
flatbuffers@25.9.23: {}
follow-redirects@1.15.11: {}
@@ -6889,6 +8016,8 @@ snapshots:
formdata-node@6.0.3: {}
+ forwarded-parse@2.1.2: {}
+
fraction.js@5.3.4: {}
fs-constants@1.0.0: {}
@@ -6958,6 +8087,8 @@ snapshots:
- encoding
- supports-color
+ gensync@1.0.0-beta.2: {}
+
get-caller-file@2.0.5: {}
get-intrinsic@1.3.0:
@@ -6995,6 +8126,12 @@ snapshots:
package-json-from-dist: 1.0.1
path-scurry: 1.11.1
+ glob@13.0.6:
+ dependencies:
+ minimatch: 10.2.5
+ minipass: 7.1.3
+ path-scurry: 2.0.2
+
glob@7.2.3:
dependencies:
fs.realpath: 1.0.0
@@ -7140,6 +8277,20 @@ snapshots:
ieee754@1.2.1: {}
+ import-in-the-middle@2.0.6:
+ dependencies:
+ acorn: 8.16.0
+ acorn-import-attributes: 1.9.5(acorn@8.16.0)
+ cjs-module-lexer: 2.2.0
+ module-details-from-path: 1.0.4
+
+ import-in-the-middle@3.0.1:
+ dependencies:
+ acorn: 8.16.0
+ acorn-import-attributes: 1.9.5(acorn@8.16.0)
+ cjs-module-lexer: 2.2.0
+ module-details-from-path: 1.0.4
+
imurmurhash@0.1.4: {}
indent-string@4.0.0: {}
@@ -7195,10 +8346,14 @@ snapshots:
js-base64@3.7.2: {}
+ js-tokens@4.0.0: {}
+
js-yaml@4.1.1:
dependencies:
argparse: 2.0.1
+ jsesc@3.1.0: {}
+
json-bigint@1.0.0:
dependencies:
bignumber.js: 9.3.1
@@ -7295,6 +8450,10 @@ snapshots:
lightningcss-win32-arm64-msvc: 1.30.2
lightningcss-win32-x64-msvc: 1.30.2
+ locate-path@6.0.0:
+ dependencies:
+ p-locate: 5.0.0
+
lodash.camelcase@4.3.0: {}
lodash.clonedeep@4.5.0: {}
@@ -7316,6 +8475,12 @@ snapshots:
lru-cache@10.4.3: {}
+ lru-cache@11.5.1: {}
+
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
lru-cache@6.0.0:
dependencies:
yallist: 4.0.0
@@ -7383,6 +8548,10 @@ snapshots:
dependencies:
'@isaacs/brace-expansion': 5.0.0
+ minimatch@10.2.5:
+ dependencies:
+ brace-expansion: 5.0.6
+
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
@@ -7429,6 +8598,8 @@ snapshots:
minipass@7.1.2: {}
+ minipass@7.1.3: {}
+
minizlib@2.1.2:
dependencies:
minipass: 3.3.6
@@ -7446,6 +8617,8 @@ snapshots:
mkdirp@1.0.4: {}
+ module-details-from-path@1.0.4: {}
+
ms@2.1.3: {}
nan@2.24.0:
@@ -7560,6 +8733,10 @@ snapshots:
dependencies:
yocto-queue: 0.1.0
+ p-locate@5.0.0:
+ dependencies:
+ p-limit: 3.1.0
+
p-map@4.0.0:
dependencies:
aggregate-error: 3.1.0
@@ -7581,6 +8758,8 @@ snapshots:
- bufferutil
- utf-8-validate
+ path-exists@4.0.0: {}
+
path-is-absolute@1.0.1: {}
path-key@3.1.1: {}
@@ -7590,12 +8769,29 @@ snapshots:
lru-cache: 10.4.3
minipass: 7.1.2
+ path-scurry@2.0.2:
+ dependencies:
+ lru-cache: 11.5.1
+ minipass: 7.1.3
+
pathe@2.0.3: {}
pe-library@0.4.1: {}
pend@1.2.0: {}
+ pg-int8@1.0.1: {}
+
+ pg-protocol@1.14.0: {}
+
+ pg-types@2.2.0:
+ dependencies:
+ pg-int8: 1.0.1
+ postgres-array: 2.0.0
+ postgres-bytea: 1.0.1
+ postgres-date: 1.0.7
+ postgres-interval: 1.2.0
+
picocolors@1.1.1: {}
picomatch@4.0.3: {}
@@ -7624,6 +8820,16 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ postgres-array@2.0.0: {}
+
+ postgres-bytea@1.0.1: {}
+
+ postgres-date@1.0.7: {}
+
+ postgres-interval@1.2.0:
+ dependencies:
+ xtend: 4.0.2
+
postject@1.0.0-alpha.6:
dependencies:
commander: 9.5.0
@@ -7768,6 +8974,13 @@ snapshots:
require-from-string@2.0.2: {}
+ require-in-the-middle@8.0.1:
+ dependencies:
+ debug: 4.4.3
+ module-details-from-path: 1.0.4
+ transitivePeerDependencies:
+ - supports-color
+
resedit@1.7.2:
dependencies:
pe-library: 0.4.1
@@ -8320,7 +9533,7 @@ snapshots:
lightningcss: 1.30.2
yaml: 2.8.2
- vitest@4.1.7(@types/node@25.0.3)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)):
+ vitest@4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)):
dependencies:
'@vitest/expect': 4.1.7
'@vitest/mocker': 4.1.7(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))
@@ -8343,6 +9556,7 @@ snapshots:
vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)
why-is-node-running: 2.3.0
optionalDependencies:
+ '@opentelemetry/api': 1.9.1
'@types/node': 25.0.3
transitivePeerDependencies:
- msw
@@ -8410,6 +9624,8 @@ snapshots:
y18n@5.0.8: {}
+ yallist@3.1.1: {}
+
yallist@4.0.0: {}
yallist@5.0.0: {}
diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx
new file mode 100644
index 0000000..51a893d
--- /dev/null
+++ b/src/components/ErrorBoundary.tsx
@@ -0,0 +1,39 @@
+import React from 'react'
+import { captureRendererError } from '../error-monitoring'
+
+interface ErrorBoundaryState {
+ error: Error | null
+}
+
+export class ErrorBoundary extends React.Component {
+ state: ErrorBoundaryState = {
+ error: null,
+ }
+
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState {
+ return { error }
+ }
+
+ componentDidCatch(error: Error, info: React.ErrorInfo): void {
+ captureRendererError(error, {
+ componentStack: info.componentStack || 'missing',
+ })
+ }
+
+ render() {
+ if (this.state.error) {
+ return (
+
+
+
Something went wrong
+
+ Restart Chroma Explorer and try the action again.
+
+
+
+ )
+ }
+
+ return this.props.children
+ }
+}
diff --git a/src/error-monitoring.ts b/src/error-monitoring.ts
new file mode 100644
index 0000000..28550d1
--- /dev/null
+++ b/src/error-monitoring.ts
@@ -0,0 +1,49 @@
+import * as Sentry from '@sentry/electron/renderer'
+
+let initialized = false
+
+export async function initRendererErrorMonitoring(): Promise {
+ try {
+ const enabled = await window.electronAPI.settings.getErrorReportingEnabled()
+ setRendererErrorMonitoringEnabled(enabled)
+
+ window.electronAPI.settings.onErrorReportingChange((nextEnabled) => {
+ setRendererErrorMonitoringEnabled(nextEnabled)
+ })
+ } catch (error) {
+ console.warn('[ErrorMonitoring] Failed to read renderer setting:', error)
+ }
+}
+
+export function setRendererErrorMonitoringEnabled(enabled: boolean): void {
+ const dsn = import.meta.env.VITE_SENTRY_DSN
+
+ if (enabled && dsn && !initialized && !Sentry.isInitialized()) {
+ Sentry.init({
+ dsn,
+ release: import.meta.env.VITE_SENTRY_RELEASE,
+ })
+ initialized = true
+ return
+ }
+
+ if (!enabled && (initialized || Sentry.isInitialized())) {
+ const client = Sentry.getClient()
+ void Promise.resolve(client?.close(2000)).finally(() => {
+ initialized = false
+ })
+ }
+}
+
+export function captureRendererError(error: unknown, context?: Record): void {
+ if (!initialized && !Sentry.isInitialized()) {
+ return
+ }
+
+ Sentry.withScope((scope) => {
+ if (context) {
+ scope.setContext('renderer', context)
+ }
+ Sentry.captureException(error)
+ })
+}
diff --git a/src/main.tsx b/src/main.tsx
index aa08c8e..c94350a 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -3,6 +3,8 @@ import ReactDOM from 'react-dom/client'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ThemeProvider } from './context/ThemeContext'
import App from './App'
+import { ErrorBoundary } from './components/ErrorBoundary'
+import { initRendererErrorMonitoring } from './error-monitoring'
import './index.css'
// Create a client
@@ -22,12 +24,16 @@ if (!root) {
throw new Error('Root element not found')
}
+void initRendererErrorMonitoring()
+
ReactDOM.createRoot(root).render(
-
-
-
-
-
+
+
+
+
+
+
+
)
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
index 2c6e9d8..e76b8df 100644
--- a/src/vite-env.d.ts
+++ b/src/vite-env.d.ts
@@ -2,6 +2,8 @@
interface ImportMetaEnv {
readonly VITE_FORMINIT_FORM_ID?: string
+ readonly VITE_SENTRY_DSN?: string
+ readonly VITE_SENTRY_RELEASE?: string
}
interface ImportMeta {
diff --git a/src/windows/SettingsWindow.tsx b/src/windows/SettingsWindow.tsx
index b201379..8bbbca6 100644
--- a/src/windows/SettingsWindow.tsx
+++ b/src/windows/SettingsWindow.tsx
@@ -2,23 +2,29 @@ import { useState, useEffect, useMemo } from 'react'
import { API_KEY_PROVIDERS } from '../constants/api-key-providers'
import { getShortcutsByCategory } from '../constants/keyboard-shortcuts'
import { useTheme, Theme } from '../context/ThemeContext'
-import { ExternalLink, Check, Eye, EyeOff, KeyRound, Keyboard, Palette, Sun, Moon, Monitor } from 'lucide-react'
+import { Checkbox } from '../components/ui/checkbox'
+import { ExternalLink, Check, Eye, EyeOff, KeyRound, Keyboard, Palette, Sun, Moon, Monitor, ShieldCheck } from 'lucide-react'
const inputClassName = "flex-1 h-7 text-[12px] px-2.5 rounded bg-black/[0.06] dark:bg-white/[0.08] text-foreground placeholder:text-foreground/30 focus:outline-none focus:bg-black/[0.08] dark:focus:bg-white/[0.12] transition-colors border-0 font-mono"
-type TabId = 'api-keys' | 'shortcuts' | 'appearance'
+type TabId = 'api-keys' | 'shortcuts' | 'appearance' | 'privacy'
const TABS: { id: TabId; label: string; icon: typeof KeyRound }[] = [
{ id: 'api-keys', label: 'API Keys', icon: KeyRound },
{ id: 'shortcuts', label: 'Shortcuts', icon: Keyboard },
{ id: 'appearance', label: 'Appearance', icon: Palette },
+ { id: 'privacy', label: 'Privacy', icon: ShieldCheck },
]
+function isTabId(value: string | null): value is TabId {
+ return TABS.some(tab => tab.id === value)
+}
+
// Get initial tab from URL params
function getInitialTab(): TabId {
const params = new URLSearchParams(window.location.search)
const tab = params.get('tab')
- if (tab === 'shortcuts' || tab === 'api-keys' || tab === 'appearance') {
+ if (isTabId(tab)) {
return tab
}
return 'api-keys'
@@ -30,6 +36,8 @@ export function SettingsWindow() {
const [apiKeys, setApiKeys] = useState>({})
const [saving, setSaving] = useState(false)
const [saved, setSaved] = useState(false)
+ const [errorReportingEnabled, setErrorReportingEnabled] = useState(true)
+ const [savingErrorReporting, setSavingErrorReporting] = useState(false)
const [visibleKeys, setVisibleKeys] = useState>(new Set())
// Make body transparent for vibrancy effect
@@ -45,7 +53,7 @@ export function SettingsWindow() {
// Listen for tab switch messages from main process
useEffect(() => {
const unsubscribe = window.electronAPI.settings.onSwitchTab((tab) => {
- if (tab === 'shortcuts' || tab === 'api-keys' || tab === 'appearance') {
+ if (isTabId(tab)) {
setActiveTab(tab)
}
})
@@ -59,9 +67,11 @@ export function SettingsWindow() {
const loadSettings = async () => {
try {
const keys = await window.electronAPI.settings.getApiKeys()
+ const reportingEnabled = await window.electronAPI.settings.getErrorReportingEnabled()
setApiKeys(keys)
+ setErrorReportingEnabled(reportingEnabled)
} catch (error) {
- console.error('Failed to load API keys:', error)
+ console.error('Failed to load settings:', error)
}
}
@@ -102,6 +112,19 @@ export function SettingsWindow() {
})
}
+ const handleErrorReportingChange = async (checked: boolean) => {
+ setErrorReportingEnabled(checked)
+ setSavingErrorReporting(true)
+ try {
+ await window.electronAPI.settings.setErrorReportingEnabled(checked)
+ } catch (error) {
+ setErrorReportingEnabled(!checked)
+ console.error('Failed to save error reporting setting:', error)
+ } finally {
+ setSavingErrorReporting(false)
+ }
+ }
+
// Compute theme-aware styles
const isDark = resolvedTheme === 'dark'
@@ -322,6 +345,35 @@ export function SettingsWindow() {
>
)}
+
+ {activeTab === 'privacy' && (
+ <>
+
+
+
+ handleErrorReportingChange(checked === true)}
+ className="mt-0.5"
+ />
+
+
+ Error reporting
+
+
+ Send sanitized crash reports and error details.
+
+
+
+
+
+
+
+ Enabled by default. Database contents, API keys, connection URLs, tokens, metadata, documents, and embeddings are redacted.
+
+ >
+ )}
{/* Footer - only show Save button for API Keys tab */}
diff --git a/vite.config.js b/vite.config.js
index 9d97b5c..53a2521 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -1,5 +1,6 @@
import { defineConfig, loadEnv } from 'vite'
import electron from 'vite-plugin-electron/simple'
+import { sentryVitePlugin } from '@sentry/vite-plugin'
import path from 'path'
import { fileURLToPath } from 'url'
@@ -7,6 +8,10 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url))
// Load .env file for build-time environment variables
const env = loadEnv('', process.cwd(), '')
+const sentryDsn = env.SENTRY_DSN || env.VITE_SENTRY_DSN || ''
+const sentryRelease = env.SENTRY_RELEASE || `chroma-explorer@${process.env.npm_package_version || '0.0.0'}`
+const shouldBuildSourceMaps = Boolean(env.SENTRY_DSN || env.VITE_SENTRY_DSN)
+const shouldUploadSourceMaps = Boolean(env.SENTRY_AUTH_TOKEN && env.SENTRY_ORG && env.SENTRY_PROJECT)
export default defineConfig({
@@ -19,6 +24,7 @@ export default defineConfig({
exclude: ['chromadb']
},
build: {
+ sourcemap: shouldBuildSourceMaps ? 'hidden' : false,
commonjsOptions: {
include: [/chromadb/, /node_modules/]
}
@@ -34,9 +40,13 @@ export default defineConfig({
vite: {
define: {
'process.env.APTABASE_APP_KEY': JSON.stringify(env.APTABASE_APP_KEY || ''),
+ 'process.env.SENTRY_DSN': JSON.stringify(sentryDsn),
+ 'process.env.VITE_SENTRY_DSN': JSON.stringify(sentryDsn),
+ 'process.env.SENTRY_RELEASE': JSON.stringify(sentryRelease),
'process.env.CHROMA_EXPLORER_RELEASE': JSON.stringify(env.CHROMA_EXPLORER_RELEASE || ''),
},
build: {
+ sourcemap: shouldBuildSourceMaps ? 'hidden' : false,
rollupOptions: {
external: [
'@chroma-core/sentence-transformer',
@@ -50,7 +60,27 @@ export default defineConfig({
preload: {
input: 'electron/preload.ts',
},
- renderer: {},
+ renderer: {
+ vite: {
+ define: {
+ 'import.meta.env.VITE_SENTRY_DSN': JSON.stringify(sentryDsn),
+ 'import.meta.env.VITE_SENTRY_RELEASE': JSON.stringify(sentryRelease),
+ },
+ },
+ },
+ }),
+ shouldUploadSourceMaps && sentryVitePlugin({
+ authToken: env.SENTRY_AUTH_TOKEN,
+ org: env.SENTRY_ORG,
+ project: env.SENTRY_PROJECT,
+ release: {
+ name: sentryRelease,
+ },
+ sourcemaps: {
+ assets: ['./dist/**/*', './dist-electron/**/*'],
+ ignore: ['**/node_modules/**'],
+ filesToDeleteAfterUpload: ['./dist/**/*.map', './dist-electron/**/*.map'],
+ },
}),
],
})