The open source codebase powering HuggingChat
This report summarizes scanner evidence for huggingface/chat-ui, a TypeScript project with 11,009 GitHub stars. SynthScan examined 184,459 lines of code across 1000 source files, recording 132 pattern matches distributed across 9 syntactic categories. The legacy adjusted pattern signal is 1.1 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 100 finding(s).
Are imports declared and package/API names verified? 5 finding(s).
Are wrappers, guards, and repeated structures necessary? 90 finding(s).
Which changes need focused human review? 132 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 132 distinct pattern matches across 9 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/fixtures.ts | 62 | // ── Test database ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/fixtures.ts | 85 | // ── Session helpers ─────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/fixtures.ts | 135 | // ── Conversation seeding ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/fixtures.ts | 208 | // ── Mock control clients ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/fixtures.ts | 271 | // ── Direct HTTP helpers ─────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/fixtures.ts | 355 | // ── Fixtures ────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/mock-openai.ts | 205 | // ── Control plane ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/mock-openai.ts | 233 | // ── Model list — the app hard-requires this at boot ────────────────────── | COMMENT |
| MEDIUM | tests/mock-openai.ts | 239 | // ── Legacy completions (endpointOai.ts:150) ────────────────────────────── | COMMENT |
| MEDIUM | tests/mock-openai.ts | 261 | // ── Chat completions ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/mock-openai.ts | 293 | // ── Non-streaming: title generation and tool-call id recovery ────────── | COMMENT |
| MEDIUM | tests/mock-openai.ts | 324 | // ── Streaming ────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | tests/mock-openai.ts | 406 | // ── CLI mode: `vite-node e2e/mock-openai.ts` ───────────────────────────────── | COMMENT |
| MEDIUM | tests/mock-mcp.ts | 156 | // ── CLI mode: `node --experimental-strip-types e2e/mock-mcp.ts` ────────────── | COMMENT |
| MEDIUM | src/lib/stores/mcpServers.spec.ts | 46 | // ─── tests ─────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …erver/textGeneration/__tests__/replayRoundTrip.spec.ts | 37 | // ── Scripted edges ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …erver/textGeneration/__tests__/replayRoundTrip.spec.ts | 127 | // ── Driving a turn ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …erver/textGeneration/__tests__/replayRoundTrip.spec.ts | 298 | // ── Setup ───────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …erver/textGeneration/__tests__/replayRoundTrip.spec.ts | 365 | // ── The round trip ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …erver/textGeneration/__tests__/replayRoundTrip.spec.ts | 468 | // ── Turns that ended badly ──────────────────────────────────────────────────── | COMMENT |
| MEDIUM | …erver/textGeneration/__tests__/replayRoundTrip.spec.ts | 621 | // ── Reasoning: attribution and gating ───────────────────────────────────────── | COMMENT |
| MEDIUM | …erver/textGeneration/__tests__/replayRoundTrip.spec.ts | 749 | // ── Producer gating across a model switch ───────────────────────────────────── | COMMENT |
| MEDIUM | …erver/textGeneration/__tests__/replayRoundTrip.spec.ts | 958 | // ── Budget and storage growth ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | …erver/textGeneration/__tests__/replayRoundTrip.spec.ts | 1370 | // ── Tool results that carry no text ─────────────────────────────────────────── | COMMENT |
| MEDIUM | …erver/textGeneration/__tests__/replayRoundTrip.spec.ts | 1447 | // ── Data written before this feature existed ────────────────────────────────── | COMMENT |
| MEDIUM | src/lib/utils/haptics.ts | 34 | // ── Internals ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | src/lib/utils/haptics.ts | 44 | // ── Semantic haptic actions ────────────────────────────────────────── | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/lib/stores/mcpServers.ts | 470 | export async function reconcileOAuthConnections(): Promise<void> { | CODE |
| LOW | src/lib/stores/mcpServers.ts | 573 | async function consumeOAuthRedirectIfAny() { | CODE |
| LOW | src/lib/stores/activeGenerations.svelte.ts | 99 | export function createActiveGenerationsStore(): ActiveGenerationsStore { | CODE |
| LOW | src/lib/stores/activeGenerations.svelte.ts | 105 | export function useActiveGenerationsStore(): ActiveGenerationsStore { | CODE |
| LOW | src/lib/server/mlAssistantPrompt.ts | 246 | export function mlAssistantSessionContext({ | CODE |
| LOW | src/lib/server/mlAssistantPrompt.ts | 429 | export function mlAssistantToolDoctrineBlocks( | CODE |
| LOW | src/lib/server/conversationSettings.ts | 38 | export async function applyConversationSettings( | CODE |
| LOW | src/lib/server/billingOrganizations.ts | 36 | export async function fetchBillableOrganizations( | CODE |
| LOW | src/lib/server/billingOrganizations.ts | 70 | export async function assertBillableOrganization( | CODE |
| LOW | src/lib/server/conversation.ts | 12 | export async function createConversationFromShare( | CODE |
| LOW | src/lib/server/mlAssistant.ts | 65 | export function isMlAssistantConversation(conv: Pick<Conversation, "mlAssistant">): boolean { | CODE |
| LOW | src/lib/server/mlAssistant.ts | 98 | export function mlAssistantBillingNamespace( | CODE |
| LOW | src/lib/server/settingsValidation.ts | 55 | export async function assertBillingTargetChange( | CODE |
| LOW | src/lib/server/auth.ts | 379 | export async function validateAndParseCsrfToken( | CODE |
| LOW | src/lib/server/auth.ts | 379 | export async function validateAndParseCsrfToken( | CODE |
| LOW | src/lib/server/reasoningPolicy.ts | 44 | export function preservesReasoningByDefault(modelId: string | undefined): boolean { | CODE |
| LOW | src/lib/server/mlBudget/guard.ts | 203 | export function withRequiredDiscriminators( | CODE |
| LOW | src/lib/server/mlBudget/pricing.ts | 99 | export async function getFlavorPriceMicroUsdPerMinute(flavor: string): Promise<number | undefined> { | CODE |
| LOW | src/lib/server/mlFiles/expand.ts | 132 | export function createVirtualFileExpander(conversationId: ObjectId): VirtualFileExpander { | CODE |
| LOW | src/lib/server/endpoints/preprocessMessages.ts | 48 | function stripEmptyInitialSystemMessage(messages: EndpointMessage[]): EndpointMessage[] { | CODE |
| LOW | src/lib/server/endpoints/openai/providerFallback.ts | 6 | export async function fetchWithProviderFallback( | CODE |
| LOW | src/lib/server/textGeneration/reasoning.ts | 4 | export async function generateSummaryOfReasoning( | CODE |
| LOW | …lib/server/textGeneration/builtinTools/researchTool.ts | 213 | function availableResearchToolNames( | CODE |
| LOW | …b/server/textGeneration/builtinTools/researchPrompt.ts | 31 | export function buildResearchSystemPrompt(availableTools: ReadonlySet<string>): string { | CODE |
| LOW | src/lib/server/textGeneration/utils/routing.ts | 11 | export function stripReasoningFromMessageForRouting(message: EndpointMessage): EndpointMessage { | CODE |
| LOW | src/lib/server/textGeneration/utils/harnessEvent.ts | 10 | export function withHarnessEventOnLastTool( | CODE |
| LOW | src/lib/server/mcp/preflightGuard.ts | 55 | export function createSchemaPreflightGuard(mapping: Record<string, McpToolMapping>): ToolCallGuard { | CODE |
| LOW | src/lib/server/mcp/elicitationSchema.ts | 181 | export function normalizeElicitationRequest(params: unknown): NormalizeResult { | CODE |
| LOW | src/lib/server/mcp/elicitationSchema.ts | 269 | export function validateElicitationContent( | CODE |
| LOW | src/lib/server/mcp/oauth/validation.ts | 37 | export function parseAuthorizationServerMetadata(input: unknown): AuthorizationServerMetadata { | CODE |
| LOW | src/lib/server/mcp/oauth/validation.ts | 113 | export function assertAuthorizationResponseIssuer( | CODE |
| LOW | src/lib/server/mcp/oauth/validation.ts | 148 | export function assertProtectedResourceMatches( | CODE |
| LOW | src/lib/server/mcp/oauth/connections.ts | 145 | export async function migrateOAuthConnectionsToUser( | CODE |
| LOW | src/lib/server/mcp/oauth/connections.ts | 442 | export async function captureInsufficientScopeResponse( | CODE |
| LOW | src/lib/server/mcp/oauth/discover.ts | 41 | export function buildClientMetadataDocumentClient( | CODE |
| LOW | src/lib/server/mlRegistry/events.ts | 136 | export async function conversationsAwaitingEvents(): Promise<ObjectId[]> { | CODE |
| LOW | src/lib/server/mlRegistry/events.ts | 169 | export async function markServiceEventsReported( | CODE |
| LOW | src/lib/server/mlRegistry/midTurn.ts | 57 | export async function markHarnessEventDelivered( | CODE |
| LOW | src/lib/server/slack/readOnly.ts | 16 | export async function isSlackConversationMutation( | CODE |
| LOW | src/lib/server/slack/store.ts | 11 | export async function getOrCreateThread( | CODE |
| LOW | src/lib/server/generation/messageShape.ts | 156 | export function messageRoundsShapeEnabled(): boolean { | CODE |
| LOW | src/lib/server/generation/compressUpdates.ts | 69 | export function compressUpdatesForStorage(updates: Message["updates"]): Message["updates"] { | CODE |
| LOW | src/lib/server/generation/finalize.ts | 27 | export async function markGenerationInterrupted( | CODE |
| LOW | src/lib/server/generation/conversationRequest.ts | 57 | export async function generateConversationResponse({ | CODE |
| LOW | src/lib/server/router/endpoint.ts | 101 | function stripReasoningFromMessage(message: EndpointMessage): EndpointMessage { | CODE |
| LOW | src/lib/server/router/multimodal.ts | 9 | export function findConfiguredMultimodalModel( | CODE |
| LOW | src/lib/server/router/multimodal.ts | 23 | export function getConfiguredMultimodalModelId( | CODE |
| LOW | src/lib/server/router/toolsRoute.ts | 14 | export function isRouterToolsBypassEnabled(): boolean { | CODE |
| LOW | src/lib/utils/marked.ts | 349 | function sanitizeHtmlForMultimedia(html: string): string { | CODE |
| LOW | src/lib/utils/parseBlocks.ts | 60 | function countNonSelfClosingOpenTags(block: string, tagName: string): number { | CODE |
| LOW | src/lib/utils/linkParams.ts | 108 | export function linkPromptNeedsConfirmation(request: LinkPromptRequest): boolean { | CODE |
| LOW | src/lib/utils/trackio.ts | 167 | export function trackioDashboardsFromToolUpdates(updates: MessageToolUpdate[]): TrackioDashboard[] { | CODE |
| LOW | src/lib/utils/artifactCapture.ts | 65 | export function captureArtifactScreenshot( | CODE |
| LOW | src/lib/utils/pendingPlaceholder.ts | 8 | export function shouldShowPendingPlaceholder({ | CODE |
| LOW | src/lib/utils/mcpOAuth.ts | 105 | export async function disconnectOAuthConnection( | CODE |
| LOW | src/lib/utils/mcpOAuth.ts | 126 | export async function fetchOAuthConnectionState( | CODE |
| LOW | src/lib/utils/generationState.ts | 74 | export function isAssistantGenerationTerminal(message?: Message): boolean { | CODE |
| LOW | src/lib/utils/generationState.ts | 84 | export function isConversationGenerationActive(messages: Message[]): boolean { | CODE |
| LOW | src/lib/utils/messageBlocks.ts | 106 | function collapseConsecutiveArtifactOps(input: MessageBlock[]): MessageBlock[] { | CODE |
| LOW | src/lib/utils/tree/convertLegacyConversation.ts | 5 | export function convertLegacyConversation( | CODE |
| 3 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | server.js | 1 | import process from "node:process"; | COMMENT |
| LOW | src/lib/stores/queuedInputs.svelte.ts | 21 | COMMENT | |
| LOW | src/lib/server/mlAssistantPrompt.spec.ts | 441 | COMMENT | |
| LOW | src/lib/server/mlAssistantPrompt.spec.ts | 461 | // Raised deliberately each time, and the reasons are the point of keeping it: | COMMENT |
| LOW | src/lib/server/mlAssistantPrompt.spec.ts | 481 | // sandbox, which cannot surface an OOM or a steps-per-second worth | COMMENT |
| LOW | src/lib/server/mlAssistantPrompt.spec.ts | 501 | // | COMMENT |
| LOW | src/lib/server/endpoints/openai/endpointOai.ts | 201 | // reply allowance this request will actually ask for. | COMMENT |
| LOW | src/lib/server/textGeneration/utils/prepareFiles.ts | 161 | // in chronological order. Rounds whose Call update persisted its own | COMMENT |
| LOW | src/lib/server/textGeneration/utils/prepareFiles.ts | 181 | remainingParts.splice(0, 1); | COMMENT |
| LOW | src/lib/server/textGeneration/utils/prepareFiles.ts | 281 | COMMENT | |
| LOW | src/lib/server/textGeneration/utils/prepareFiles.ts | 621 | // The newest replayable turn is the one a continuation resumes INTO: its | COMMENT |
| LOW | src/lib/server/textGeneration/mcp/runMcpFlow.ts | 141 | // ML Assistant runs jobs, and the round budget is what it spends grounding ids, | COMMENT |
| LOW | src/lib/server/textGeneration/mcp/runMcpFlow.ts | 581 | // In the mode, gated tools advertise their routing discriminator as | COMMENT |
| LOW | src/lib/server/textGeneration/mcp/runMcpFlow.ts | 1441 | continue; | COMMENT |
| LOW | src/lib/server/mcp/elicitation.ts | 461 | let validated: Record<string, ElicitationValue> | undefined; | COMMENT |
| LOW | src/lib/utils/pendingConversation.ts | 21 | mlAssistant?: boolean; | COMMENT |
| LOW | src/lib/utils/markdownWorkerPool.ts | 41 | // every worker's JS VM, so the pool is deliberately tiny: a couple of workers shared | COMMENT |
| LOW | src/lib/utils/scroll/chatScroll.svelte.ts | 261 | // The anchored position no longer exists (a branch switch onto a | COMMENT |
| LOW | src/lib/components/chat/ArtifactPanel.svelte | 201 | // position leaks into the next one (e.g. a version that streamed pinned to | COMMENT |
| LOW | src/lib/components/chat/ChatWindow.svelte | 501 | COMMENT | |
| LOW | src/routes/conversation/[id]/+page.svelte | 81 | // non-terminal, flipping $loading back on. Keying the tombstone by | COMMENT |
| LOW | src/routes/conversation/[id]/+page.svelte | 481 | // so the abort marker is durably written before we poll for the | COMMENT |
| LOW | src/routes/conversation/[id]/+page.svelte | 821 | // changes (sidebar navigation) or the load data itself was refreshed | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docs/source/ml-intern/local-development.md | 21 | ## Step 1: Create a Hugging Face OAuth app | COMMENT |
| LOW | docs/source/ml-intern/local-development.md | 38 | ## Step 2: Configure `.env.local` | COMMENT |
| LOW | docs/source/ml-intern/local-development.md | 75 | ## Step 3: Run it | COMMENT |
| LOW⚡ | docs/source/ml-intern/getting-started.md | 18 | ## Step 1: Open HuggingChat and switch on ML Intern | COMMENT |
| LOW⚡ | docs/source/ml-intern/getting-started.md | 27 | ## Step 2: Enable the Hub tools ML Intern uses | COMMENT |
| LOW⚡ | docs/source/ml-intern/getting-started.md | 33 | ## Step 3: Choose who pays | COMMENT |
| LOW⚡ | docs/source/ml-intern/getting-started.md | 43 | ## Step 4: Describe your task | COMMENT |
| LOW | docs/source/ml-intern/getting-started.md | 55 | ## Step 5: Set a compute budget | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | src/lib/server/textGeneration/mcp/routerResolution.ts | 81 | // the bypass flag so disabling tools keeps the agentic route off the heuristic path | COMMENT |
| MEDIUM | …c/lib/utils/scroll/__tests__/chatScroll.svelte.test.ts | 593 | // which in a one-turn agentic conversation is the top of the page. | COMMENT |
| MEDIUM | src/lib/components/chat/ChatWindow.svelte | 668 | // Resume beats Retry for a failed agentic turn: retry re-runs the whole turn | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/scroll-anchoring.spec.ts | 21 | const TALL_REPLY = `${"lorem ipsum dolor sit amet ".repeat(30)}\n\n`.repeat(8); | CODE |
| LOW | tests/scroll-anchoring.spec.ts | 21 | const TALL_REPLY = `${"lorem ipsum dolor sit amet ".repeat(30)}\n\n`.repeat(8); | CODE |
| LOW | docs/source/configuration/open-id.md | 27 | ALLOWED_USER_EMAILS=["user@example.com", "admin@example.com"] | CODE |
| LOW | docs/source/configuration/open-id.md | 27 | ALLOWED_USER_EMAILS=["user@example.com", "admin@example.com"] | CODE |
| LOW | …c/lib/server/shareThumbnail/shareThumbnail.ssr.test.ts | 67 | "lorem ipsum ".repeat(40), | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | .github/workflows/lint-and-test.yml | 102 | # The harness starts its own MongoMemoryServer (see startTestDatabase in | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/lib/server/auth.ts | 555 | // TODO: Handle errors if provider is not responding | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/lib/server/hooks/handle.ts | 31 | export async function handleRequest({ event, resolve }: HandleInput): Promise<Response> { | CODE |