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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions scripts/check-code-health.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ const baselines = {
unlisted: 0,
unresolved: 0,
},
complexity: { violations: 35, maxCcn: 56, maxLength: 397, maxParams: 17 },
complexity: { violations: 34, maxCcn: 56, maxLength: 397, maxParams: 17 },
duplication: {
clones: 34,
duplicatedLines: 532,
percentage: 2.698452954603094,
clones: 27,
duplicatedLines: 369,
percentage: 1.8774,
},
suppressions: 8,
dependencies: { critical: 0, highIds: 0, highFindings: 0 },
Expand Down
19 changes: 2 additions & 17 deletions scripts/seed-popular.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import type { DbClient as Client, InStatement } from '../src/db/client';
import { createD1RestClientFromEnv } from '../src/db/rest-client';

import { isRetryableDbError } from '../src/lib/db-retry';
import { buildRepoEmbeddingText, generateEmbeddings, textHash } from '../src/lib/embeddings';
import { buildEmbeddingFromRow, generateEmbeddings } from '../src/lib/embeddings';
import {
enumeratePopularCatalog,
GITHUB_SEARCH_PAGE_SIZE,
Expand Down Expand Up @@ -277,22 +277,7 @@ async function embedPending(db: Client, limit: number): Promise<number> {

const toEmbed: { id: number; text: string; hash: string }[] = [];
for (const row of pending.rows) {
const text = buildRepoEmbeddingText({
full_name: row.full_name as string,
description: row.description as string | null,
language: row.language as string | null,
topics: row.topics as string,
ai: row.summary
? {
summary: row.summary as string,
category: row.category as string,
subcategories: row.subcategories as string,
use_cases: row.use_cases as string,
keywords: row.keywords as string,
}
: null,
});
const hash = textHash(text);
const { text, hash } = buildEmbeddingFromRow(row);
if (row.text_hash !== hash) {
toEmbed.push({ id: row.id as number, text, hash });
}
Expand Down
19 changes: 2 additions & 17 deletions src/app/api/internal/embed-pending/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { InStatement } from '@/db/client';
import { NextResponse } from 'next/server';

import { db } from '@/db';
import { buildRepoEmbeddingText, generateEmbeddings, textHash } from '@/lib/embeddings';
import { buildEmbeddingFromRow, generateEmbeddings } from '@/lib/embeddings';
import { hasValidOperatorToken } from '@/lib/operator-auth';
import { repoVectors } from '@/lib/repo-vectors';

Expand Down Expand Up @@ -77,22 +77,7 @@ export async function POST(request: Request) {

const pending: { id: number; text: string; hash: string }[] = [];
for (const row of repos.rows) {
const text = buildRepoEmbeddingText({
full_name: row.full_name as string,
description: row.description as string | null,
language: row.language as string | null,
topics: row.topics as string,
ai: row.summary
? {
summary: row.summary as string,
category: row.category as string,
subcategories: row.subcategories as string,
use_cases: row.use_cases as string,
keywords: row.keywords as string,
}
: null,
});
const hash = textHash(text);
const { text, hash } = buildEmbeddingFromRow(row);
if (row.text_hash !== hash) {
pending.push({ id: row.id as number, text, hash });
}
Expand Down
45 changes: 2 additions & 43 deletions src/app/api/repos/[repoId]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,7 @@ import { type NextRequest, NextResponse } from 'next/server';

import { db } from '@/db';

import { resolveRepoId } from '../resolve';

interface GitHubRepoResponse {
id: number;
name: string;
full_name: string;
owner: { login: string; avatar_url: string };
html_url: string;
description: string | null;
language: string | null;
stargazers_count: number;
archived?: boolean;
topics?: string[];
created_at: string;
updated_at: string;
}
import { type GitHubRepoResponse, resolveRepoId, upsertRepoFromGitHub } from '../resolve';

export async function GET(
request: NextRequest,
Expand Down Expand Up @@ -82,33 +67,7 @@ export async function GET(

const gh = (await ghRes.json()) as GitHubRepoResponse;

await db.execute({
sql: `INSERT INTO repos (id, name, full_name, owner_login, owner_avatar, html_url,
description, language, stargazers_count, archived, topics, repo_created_at, repo_updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
name = excluded.name, full_name = excluded.full_name,
owner_login = excluded.owner_login, owner_avatar = excluded.owner_avatar,
html_url = excluded.html_url, description = excluded.description,
language = excluded.language, stargazers_count = excluded.stargazers_count,
archived = excluded.archived, topics = excluded.topics, repo_created_at = excluded.repo_created_at,
repo_updated_at = excluded.repo_updated_at`,
args: [
gh.id,
gh.name,
gh.full_name,
gh.owner.login,
gh.owner.avatar_url,
gh.html_url,
gh.description ?? null,
gh.language ?? null,
gh.stargazers_count,
gh.archived ? 1 : 0,
JSON.stringify(gh.topics ?? []),
gh.created_at,
gh.updated_at,
],
});
await upsertRepoFromGitHub(gh);

repoResult = await db.execute({
sql: 'SELECT * FROM repos WHERE id = ?',
Expand Down
66 changes: 38 additions & 28 deletions src/app/api/repos/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { db } from '@/db';

interface GitHubRepoResponse {
export interface GitHubRepoResponse {
id: number;
name: string;
full_name: string;
Expand All @@ -15,6 +15,42 @@ interface GitHubRepoResponse {
updated_at: string;
}

const REPO_UPSERT_SQL = `INSERT INTO repos (id, name, full_name, owner_login, owner_avatar, html_url,
description, language, stargazers_count, archived, topics, repo_created_at, repo_updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
name = excluded.name, full_name = excluded.full_name,
owner_login = excluded.owner_login, owner_avatar = excluded.owner_avatar,
html_url = excluded.html_url, description = excluded.description,
language = excluded.language, stargazers_count = excluded.stargazers_count,
archived = excluded.archived, topics = excluded.topics, repo_created_at = excluded.repo_created_at,
repo_updated_at = excluded.repo_updated_at`;

/**
* Upsert a GitHub repo row into D1. Shared by resolveRepoId and the
* [repoId] GET route so the INSERT/ON CONFLICT shape stays in one place.
*/
export async function upsertRepoFromGitHub(gh: GitHubRepoResponse): Promise<void> {
await db.execute({
sql: REPO_UPSERT_SQL,
args: [
gh.id,
gh.name,
gh.full_name,
gh.owner.login,
gh.owner.avatar_url,
gh.html_url,
gh.description ?? null,
gh.language ?? null,
gh.stargazers_count,
gh.archived ? 1 : 0,
JSON.stringify(gh.topics ?? []),
gh.created_at,
gh.updated_at,
],
});
}

/**
* Resolve owner/repo slug to a numeric repo ID.
* If the repo isn't in our DB yet, fetches from GitHub and inserts it.
Expand Down Expand Up @@ -42,33 +78,7 @@ export async function resolveRepoId(owner: string, repo: string): Promise<number

const gh = (await ghRes.json()) as GitHubRepoResponse;

await db.execute({
sql: `INSERT INTO repos (id, name, full_name, owner_login, owner_avatar, html_url,
description, language, stargazers_count, archived, topics, repo_created_at, repo_updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
name = excluded.name, full_name = excluded.full_name,
owner_login = excluded.owner_login, owner_avatar = excluded.owner_avatar,
html_url = excluded.html_url, description = excluded.description,
language = excluded.language, stargazers_count = excluded.stargazers_count,
archived = excluded.archived, topics = excluded.topics, repo_created_at = excluded.repo_created_at,
repo_updated_at = excluded.repo_updated_at`,
args: [
gh.id,
gh.name,
gh.full_name,
gh.owner.login,
gh.owner.avatar_url,
gh.html_url,
gh.description ?? null,
gh.language ?? null,
gh.stargazers_count,
gh.archived ? 1 : 0,
JSON.stringify(gh.topics ?? []),
gh.created_at,
gh.updated_at,
],
});
await upsertRepoFromGitHub(gh);

return gh.id as number;
}
60 changes: 1 addition & 59 deletions src/app/discover/discover-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { useSession } from 'next-auth/react';
import { parseAsArrayOf, parseAsString, parseAsStringLiteral, useQueryState } from 'nuqs';
import { Suspense, useCallback, useEffect, useState } from 'react';

import { PageSkeleton } from '@/components/page-skeleton';
import { RepoGrid } from '@/components/repo-grid';
import { Sidebar } from '@/components/sidebar';
import { TopBar } from '@/components/top-bar';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Sheet, SheetContent, SheetDescription, SheetTitle } from '@/components/ui/sheet';
import { Skeleton } from '@/components/ui/skeleton';
import { useDiscoverRepos } from '@/hooks/use-discover-repos';
import type { DiscoverResponse } from '@/hooks/use-discover-repos';
import { useLists } from '@/hooks/use-lists';
Expand All @@ -22,64 +22,6 @@ const sortOptions = [
'name-az',
] as const;

function PageSkeleton() {
return (
<>
<header className="sticky top-0 z-30 flex items-center gap-3 border-b bg-background/80 px-4 py-3 backdrop-blur-sm md:px-6">
<Skeleton className="h-9 flex-1 rounded-md" />
<Skeleton className="hidden h-8 w-36 rounded-md sm:block" />
<Skeleton className="hidden h-8 w-20 rounded-md sm:block" />
<Skeleton className="size-8 rounded-full" />
</header>

<div className="flex min-h-0 flex-1">
<aside className="hidden w-[280px] shrink-0 border-r md:block">
<div className="flex flex-col gap-1 p-4">
{Array.from({ length: 3 }).map((_, section) => (
<div key={section}>
<div className="flex items-center gap-2 px-2 py-1">
<Skeleton className="size-4" />
<Skeleton className="h-3 w-20" />
</div>
<div className="mt-1 flex flex-col gap-0.5">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="flex items-center gap-2.5 px-2 py-1.5">
<Skeleton className="h-3 flex-1" />
<Skeleton className="h-3 w-6" />
</div>
))}
</div>
{section < 2 && <div className="my-3 h-px bg-border" />}
</div>
))}
</div>
</aside>

<div className="flex-1 p-4 md:p-6">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{Array.from({ length: 6 }).map((_, i) => (
<div key={i} className="flex flex-col rounded-lg border bg-card p-4">
<div className="flex items-start gap-3">
<Skeleton className="size-6 rounded-full" />
<Skeleton className="h-4 w-36" />
</div>
<Skeleton className="mt-3 h-3 w-full" />
<Skeleton className="mt-1.5 h-3 w-3/4" />
<div className="mt-auto pt-4">
<div className="flex items-center gap-3">
<Skeleton className="h-3 w-16" />
<Skeleton className="h-3 w-10" />
</div>
</div>
</div>
))}
</div>
</div>
</div>
</>
);
}

export default function DiscoverClient({
initialData,
initialUrl,
Expand Down
14 changes: 2 additions & 12 deletions src/app/discover/error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useEffect } from 'react';

import { ErrorActions } from '@/components/error-actions';
import { captureError } from '@/lib/foundry-monitoring';

export default function DiscoverError({
Expand All @@ -23,18 +24,7 @@ export default function DiscoverError({
<p className="text-sm opacity-70 mb-6">
Something went wrong while loading the discover feed — try again.
</p>
<div className="flex gap-3 justify-center">
<button onClick={reset} className="px-4 py-2 rounded border hover:opacity-80">
Try again
</button>
<button
onClick={() => window.location.replace('/')}
className="px-4 py-2 rounded border hover:opacity-80"
>
Home
</button>
</div>
{error.digest ? <p className="mt-6 text-xs opacity-40">Reference: {error.digest}</p> : null}
<ErrorActions error={error} reset={reset} />
</div>
</div>
);
Expand Down
14 changes: 2 additions & 12 deletions src/app/error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useEffect } from 'react';

import { ErrorActions } from '@/components/error-actions';
import { captureError } from '@/lib/foundry-monitoring';

export default function Error({
Expand All @@ -25,18 +26,7 @@ export default function Error({
An unexpected error occurred on our end. Your data is safe — try again, and if it keeps
happening, come back in a few minutes.
</p>
<div className="flex gap-3 justify-center">
<button onClick={reset} className="px-4 py-2 rounded border hover:opacity-80">
Try again
</button>
<button
onClick={() => window.location.replace('/')}
className="px-4 py-2 rounded border hover:opacity-80"
>
Home
</button>
</div>
{error.digest ? <p className="mt-6 text-xs opacity-40">Reference: {error.digest}</p> : null}
<ErrorActions error={error} reset={reset} />
</div>
</div>
);
Expand Down
3 changes: 2 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ export default function RootLayout({
{/* fleet-jsonld:start (generated by apply-agent-surfaces; edit registry, not this) */}
<script
type="application/ld+json"
// biome-ignore lint/security/noDangerouslySetInnerHtml: fleet-generated JSON-LD
dangerouslySetInnerHTML={{
__html: `{"@context":"https://schema.org","@graph":[{"@type":"Person","@id":"https://sarthakagrawal.dev/#person","name":"Sarthak Agrawal","jobTitle":"AI Infrastructure & Product Engineer","url":"https://sarthakagrawal.dev","image":"https://avatars.githubusercontent.com/u/43884471?v=4","sameAs":["https://sarthakagrawal.dev","https://www.linkedin.com/in/sarthakagrawal927","https://github.com/sarthakagrawal927","https://x.com/sarthakcodes","https://huggingface.co/sarthakagrawal927"],"knowsAbout":["AI infrastructure","Local-first software","Post-training language models","AI code review","Cloudflare Workers","TypeScript","Rust"],"affiliation":{"@type":"Organization","@id":"https://sassmaker.com/#app","name":"SaaS Maker","url":"https://sassmaker.com"}},{"@type":"WebSite","@id":"https://starboard.codevetter.com/#app","name":"Starboard","url":"https://starboard.codevetter.com","description":"GitHub stars organizer with semantic search — sub-product of CodeVetter for repo intelligence.","publisher":{"@id":"https://sarthakagrawal.dev/#person"},"sameAs":["https://github.com/Codevetter/starboard"]}]}`,
__html: `{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://sassmaker.com/#org","name":"SaaS Maker (Foundry)","url":"https://sassmaker.com","sameAs":["https://sassmaker.com","https://github.com/Codevetter/starboard"]},{"@type":"SoftwareApplication","@id":"https://starboard.codevetter.com/#app","name":"Starboard","url":"https://starboard.codevetter.com","description":"GitHub stars organizer with semantic search — sub-product of CodeVetter for repo intelligence.","publisher":{"@id":"https://sassmaker.com/#org"}}]}`,
}}
/>
{/* fleet-jsonld:end */}
Expand Down
Loading
Loading