mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-25 19:15:18 +02:00
Merge pull request #1276 from MODSetter/dev_mod
Some checks are pending
Build and Push Docker Images / tag_release (push) Waiting to run
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (backend, surfsense-backend) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (web, surfsense-web) (push) Blocked by required conditions
Some checks are pending
Build and Push Docker Images / tag_release (push) Waiting to run
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (backend, surfsense-backend) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (web, surfsense-web) (push) Blocked by required conditions
feat: add startup for desktop app
This commit is contained in:
commit
1919150523
23 changed files with 1176 additions and 107 deletions
|
|
@ -340,5 +340,85 @@ export const AUTO_INDEX_DEFAULTS: Record<string, AutoIndexConfig> = {
|
|||
|
||||
export const AUTO_INDEX_CONNECTOR_TYPES = new Set<string>(Object.keys(AUTO_INDEX_DEFAULTS));
|
||||
|
||||
// ============================================================================
|
||||
// CONNECTOR TELEMETRY REGISTRY
|
||||
// ----------------------------------------------------------------------------
|
||||
// Single source of truth for "what does this connector_type look like in
|
||||
// analytics?". Any connector added to the lists above is automatically
|
||||
// picked up here, so adding a new integration does NOT require touching
|
||||
// `lib/posthog/events.ts` or per-connector tracking code.
|
||||
// ============================================================================
|
||||
|
||||
export type ConnectorTelemetryGroup =
|
||||
| "oauth"
|
||||
| "composio"
|
||||
| "crawler"
|
||||
| "other"
|
||||
| "unknown";
|
||||
|
||||
export interface ConnectorTelemetryMeta {
|
||||
connector_type: string;
|
||||
connector_title: string;
|
||||
connector_group: ConnectorTelemetryGroup;
|
||||
is_oauth: boolean;
|
||||
}
|
||||
|
||||
const CONNECTOR_TELEMETRY_REGISTRY: ReadonlyMap<string, ConnectorTelemetryMeta> =
|
||||
(() => {
|
||||
const map = new Map<string, ConnectorTelemetryMeta>();
|
||||
|
||||
for (const c of OAUTH_CONNECTORS) {
|
||||
map.set(c.connectorType, {
|
||||
connector_type: c.connectorType,
|
||||
connector_title: c.title,
|
||||
connector_group: "oauth",
|
||||
is_oauth: true,
|
||||
});
|
||||
}
|
||||
for (const c of COMPOSIO_CONNECTORS) {
|
||||
map.set(c.connectorType, {
|
||||
connector_type: c.connectorType,
|
||||
connector_title: c.title,
|
||||
connector_group: "composio",
|
||||
is_oauth: true,
|
||||
});
|
||||
}
|
||||
for (const c of CRAWLERS) {
|
||||
map.set(c.connectorType, {
|
||||
connector_type: c.connectorType,
|
||||
connector_title: c.title,
|
||||
connector_group: "crawler",
|
||||
is_oauth: false,
|
||||
});
|
||||
}
|
||||
for (const c of OTHER_CONNECTORS) {
|
||||
map.set(c.connectorType, {
|
||||
connector_type: c.connectorType,
|
||||
connector_title: c.title,
|
||||
connector_group: "other",
|
||||
is_oauth: false,
|
||||
});
|
||||
}
|
||||
|
||||
return map;
|
||||
})();
|
||||
|
||||
/**
|
||||
* Returns telemetry metadata for a connector_type, or a minimal "unknown"
|
||||
* record so tracking never no-ops for connectors that exist in the backend
|
||||
* but were forgotten in the UI registry.
|
||||
*/
|
||||
export function getConnectorTelemetryMeta(connectorType: string): ConnectorTelemetryMeta {
|
||||
const hit = CONNECTOR_TELEMETRY_REGISTRY.get(connectorType);
|
||||
if (hit) return hit;
|
||||
|
||||
return {
|
||||
connector_type: connectorType,
|
||||
connector_title: connectorType,
|
||||
connector_group: "unknown",
|
||||
is_oauth: false,
|
||||
};
|
||||
}
|
||||
|
||||
// Re-export IndexingConfigState from schemas for backward compatibility
|
||||
export type { IndexingConfigState } from "./connector-popup.schemas";
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ import { isSelfHosted } from "@/lib/env-config";
|
|||
import {
|
||||
trackConnectorConnected,
|
||||
trackConnectorDeleted,
|
||||
trackConnectorSetupFailure,
|
||||
trackConnectorSetupStarted,
|
||||
trackIndexWithDateRangeOpened,
|
||||
trackIndexWithDateRangeStarted,
|
||||
trackPeriodicIndexingStarted,
|
||||
|
|
@ -232,10 +234,20 @@ export const useConnectorDialog = () => {
|
|||
|
||||
if (result.error) {
|
||||
const oauthConnector = result.connector
|
||||
? OAUTH_CONNECTORS.find((c) => c.id === result.connector)
|
||||
? OAUTH_CONNECTORS.find((c) => c.id === result.connector) ||
|
||||
COMPOSIO_CONNECTORS.find((c) => c.id === result.connector)
|
||||
: null;
|
||||
const name = oauthConnector?.title || "connector";
|
||||
|
||||
if (oauthConnector) {
|
||||
trackConnectorSetupFailure(
|
||||
Number(searchSpaceId),
|
||||
oauthConnector.connectorType,
|
||||
result.error,
|
||||
"oauth_callback"
|
||||
);
|
||||
}
|
||||
|
||||
if (result.error === "duplicate_account") {
|
||||
toast.error(`This ${name} account is already connected`, {
|
||||
description: "Please use a different account or manage the existing connection.",
|
||||
|
|
@ -348,6 +360,12 @@ export const useConnectorDialog = () => {
|
|||
// Set connecting state immediately to disable button and show spinner
|
||||
setConnectingId(connector.id);
|
||||
|
||||
trackConnectorSetupStarted(
|
||||
Number(searchSpaceId),
|
||||
connector.connectorType,
|
||||
"oauth_click"
|
||||
);
|
||||
|
||||
try {
|
||||
// Check if authEndpoint already has query parameters
|
||||
const separator = connector.authEndpoint.includes("?") ? "&" : "?";
|
||||
|
|
@ -369,6 +387,12 @@ export const useConnectorDialog = () => {
|
|||
window.location.href = validatedData.auth_url;
|
||||
} catch (error) {
|
||||
console.error(`Error connecting to ${connector.title}:`, error);
|
||||
trackConnectorSetupFailure(
|
||||
Number(searchSpaceId),
|
||||
connector.connectorType,
|
||||
error instanceof Error ? error.message : "oauth_initiation_failed",
|
||||
"oauth_init"
|
||||
);
|
||||
if (error instanceof Error && error.message.includes("Invalid auth URL")) {
|
||||
toast.error(`Invalid response from ${connector.title} OAuth endpoint`);
|
||||
} else {
|
||||
|
|
@ -392,6 +416,11 @@ export const useConnectorDialog = () => {
|
|||
if (!searchSpaceId) return;
|
||||
|
||||
setConnectingId("webcrawler-connector");
|
||||
trackConnectorSetupStarted(
|
||||
Number(searchSpaceId),
|
||||
EnumConnectorName.WEBCRAWLER_CONNECTOR,
|
||||
"webcrawler_quick_add"
|
||||
);
|
||||
try {
|
||||
await createConnector({
|
||||
data: {
|
||||
|
|
@ -441,6 +470,12 @@ export const useConnectorDialog = () => {
|
|||
}
|
||||
} catch (error) {
|
||||
console.error("Error creating webcrawler connector:", error);
|
||||
trackConnectorSetupFailure(
|
||||
Number(searchSpaceId),
|
||||
EnumConnectorName.WEBCRAWLER_CONNECTOR,
|
||||
error instanceof Error ? error.message : "webcrawler_create_failed",
|
||||
"webcrawler_quick_add"
|
||||
);
|
||||
toast.error("Failed to create web crawler connector");
|
||||
} finally {
|
||||
setConnectingId(null);
|
||||
|
|
@ -452,6 +487,12 @@ export const useConnectorDialog = () => {
|
|||
(connectorType: string) => {
|
||||
if (!searchSpaceId) return;
|
||||
|
||||
trackConnectorSetupStarted(
|
||||
Number(searchSpaceId),
|
||||
connectorType,
|
||||
"non_oauth_click"
|
||||
);
|
||||
|
||||
// Handle Obsidian specifically on Desktop & Cloud
|
||||
if (connectorType === EnumConnectorName.OBSIDIAN_CONNECTOR && !selfHosted && isDesktop) {
|
||||
setIsOpen(false);
|
||||
|
|
@ -680,6 +721,12 @@ export const useConnectorDialog = () => {
|
|||
}
|
||||
} catch (error) {
|
||||
console.error("Error creating connector:", error);
|
||||
trackConnectorSetupFailure(
|
||||
Number(searchSpaceId),
|
||||
connectingConnectorType ?? formData.connector_type,
|
||||
error instanceof Error ? error.message : "connector_create_failed",
|
||||
"non_oauth_form"
|
||||
);
|
||||
toast.error(error instanceof Error ? error.message : "Failed to create connector");
|
||||
} finally {
|
||||
isCreatingConnectorRef.current = false;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|||
import type { AnonModel, AnonQuotaResponse } from "@/contracts/types/anonymous-chat.types";
|
||||
import { anonymousChatApiService } from "@/lib/apis/anonymous-chat-api.service";
|
||||
import { readSSEStream } from "@/lib/chat/streaming-state";
|
||||
import { trackAnonymousChatMessageSent } from "@/lib/posthog/events";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { QuotaBar } from "./quota-bar";
|
||||
import { QuotaWarningBanner } from "./quota-warning-banner";
|
||||
|
|
@ -61,6 +62,12 @@ export function AnonymousChat({ model }: AnonymousChatProps) {
|
|||
textareaRef.current.style.height = "auto";
|
||||
}
|
||||
|
||||
trackAnonymousChatMessageSent({
|
||||
modelSlug: model.seo_slug,
|
||||
messageLength: trimmed.length,
|
||||
surface: "free_model_page",
|
||||
});
|
||||
|
||||
const controller = new AbortController();
|
||||
abortRef.current = controller;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import {
|
|||
updateToolCall,
|
||||
} from "@/lib/chat/streaming-state";
|
||||
import { BACKEND_URL } from "@/lib/env-config";
|
||||
import { trackAnonymousChatMessageSent } from "@/lib/posthog/events";
|
||||
import { FreeModelSelector } from "./free-model-selector";
|
||||
import { FreeThread } from "./free-thread";
|
||||
|
||||
|
|
@ -206,6 +207,14 @@ export function FreeChatPage() {
|
|||
}
|
||||
if (!userQuery.trim()) return;
|
||||
|
||||
trackAnonymousChatMessageSent({
|
||||
modelSlug,
|
||||
messageLength: userQuery.trim().length,
|
||||
hasUploadedDoc:
|
||||
anonMode.isAnonymous && anonMode.uploadedDoc !== null ? true : false,
|
||||
surface: "free_chat_page",
|
||||
});
|
||||
|
||||
const userMsgId = `msg-user-${Date.now()}`;
|
||||
setMessages((prev) => [
|
||||
...prev,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue