From 856925bd72b50a699f6119846479b01aa1b3c097 Mon Sep 17 00:00:00 2001 From: Jamie Turner Date: Wed, 28 Jan 2026 10:02:30 -0800 Subject: [PATCH 1/6] A few fixes for search. * Focus the search box when you click "search" in the header * There were some bad codegen things -- trying to access ctx.db inside an action. --- convex/httpApiV1.ts | 2 +- convex/search.ts | 18 +++++++++++++----- src/components/Header.tsx | 36 ++++++++++++++++++++++++++++++++---- src/routeTree.gen.ts | 30 +++++++++++++++--------------- src/routes/index.tsx | 23 +++++++++++++++++++---- src/routes/skills/index.tsx | 15 +++++++++++++-- src/routes/souls/index.tsx | 12 ++++++++++++ 7 files changed, 105 insertions(+), 31 deletions(-) diff --git a/convex/httpApiV1.ts b/convex/httpApiV1.ts index 5590e67..f58d59c 100644 --- a/convex/httpApiV1.ts +++ b/convex/httpApiV1.ts @@ -59,7 +59,7 @@ type GetBySlugResult = { updatedAt: number } | null latestVersion: Doc<'skillVersions'> | null - owner: { handle?: string; displayName?: string; image?: string } | null + owner: { _id: Id<'users'>; handle?: string; displayName?: string; image?: string } | null } | null type ListVersionsResult = { diff --git a/convex/search.ts b/convex/search.ts index bb7ce38..21952cf 100644 --- a/convex/search.ts +++ b/convex/search.ts @@ -2,8 +2,8 @@ import { v } from 'convex/values' import { internal } from './_generated/api' import type { Doc, Id } from './_generated/dataModel' import { action, internalQuery } from './_generated/server' +import { getSkillBadgeMaps, isSkillHighlighted, type SkillBadgeMap } from './lib/badges' import { generateEmbedding } from './lib/embeddings' -import { getSkillBadgeMaps, isSkillHighlighted } from './lib/badges' import { matchesExactTokens, tokenize } from './lib/searchText' type HydratedEntry = { @@ -61,10 +61,10 @@ export const searchSkills: ReturnType = action({ results.map((result) => [result._id, result._score]), ) - const badgeMapBySkillId = await getSkillBadgeMaps( - ctx, - hydrated.map((entry) => entry.skill._id), - ) + const badgeEntries = (await ctx.runQuery(internal.search.getBadgeMapsForSkills, { + skillIds: hydrated.map((entry) => entry.skill._id), + })) as Array<[Id<'skills'>, SkillBadgeMap]> + const badgeMapBySkillId = new Map(badgeEntries) const hydratedWithBadges = hydrated.map((entry) => ({ ...entry, skill: { ...entry.skill, badges: badgeMapBySkillId.get(entry.skill._id) ?? {} }, @@ -101,6 +101,14 @@ export const searchSkills: ReturnType = action({ }, }) +export const getBadgeMapsForSkills = internalQuery({ + args: { skillIds: v.array(v.id('skills')) }, + handler: async (ctx, args): Promise, SkillBadgeMap]>> => { + const badgeMap = await getSkillBadgeMaps(ctx, args.skillIds) + return Array.from(badgeMap.entries()) + }, +}) + export const hydrateResults = internalQuery({ args: { embeddingIds: v.array(v.id('skillEmbeddings')) }, handler: async (ctx, args): Promise => { diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 76cab5c..37c0b73 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -63,7 +63,13 @@ export default function Header() { {isSoulMode ? ( Souls @@ -76,6 +82,7 @@ export default function Header() { dir: undefined, highlighted: undefined, view: undefined, + focus: undefined, }} > Skills @@ -89,13 +96,20 @@ export default function Header() { to={isSoulMode ? '/souls' : '/skills'} search={ isSoulMode - ? { q: undefined, sort: undefined, dir: undefined, view: undefined } + ? { + q: undefined, + sort: undefined, + dir: undefined, + view: undefined, + focus: 'search', + } : { q: undefined, sort: undefined, dir: undefined, highlighted: undefined, view: undefined, + focus: 'search', } } > @@ -126,7 +140,13 @@ export default function Header() { {isSoulMode ? ( Souls @@ -139,6 +159,7 @@ export default function Header() { dir: undefined, highlighted: undefined, view: undefined, + focus: undefined, }} > Skills @@ -160,13 +181,20 @@ export default function Header() { to={isSoulMode ? '/souls' : '/skills'} search={ isSoulMode - ? { q: undefined, sort: undefined, dir: undefined, view: undefined } + ? { + q: undefined, + sort: undefined, + dir: undefined, + view: undefined, + focus: 'search', + } : { q: undefined, sort: undefined, dir: undefined, highlighted: undefined, view: undefined, + focus: 'search', } } > diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index 84702e8..bc0e5b6 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -12,10 +12,10 @@ import { Route as rootRouteImport } from './routes/__root' import { Route as UploadRouteImport } from './routes/upload' import { Route as StarsRouteImport } from './routes/stars' import { Route as SettingsRouteImport } from './routes/settings' +import { Route as ManagementRouteImport } from './routes/management' import { Route as ImportRouteImport } from './routes/import' import { Route as DashboardRouteImport } from './routes/dashboard' import { Route as AdminRouteImport } from './routes/admin' -import { Route as ManagementRouteImport } from './routes/management' import { Route as IndexRouteImport } from './routes/index' import { Route as SoulsIndexRouteImport } from './routes/souls/index' import { Route as SkillsIndexRouteImport } from './routes/skills/index' @@ -39,6 +39,11 @@ const SettingsRoute = SettingsRouteImport.update({ path: '/settings', getParentRoute: () => rootRouteImport, } as any) +const ManagementRoute = ManagementRouteImport.update({ + id: '/management', + path: '/management', + getParentRoute: () => rootRouteImport, +} as any) const ImportRoute = ImportRouteImport.update({ id: '/import', path: '/import', @@ -54,11 +59,6 @@ const AdminRoute = AdminRouteImport.update({ path: '/admin', getParentRoute: () => rootRouteImport, } as any) -const ManagementRoute = ManagementRouteImport.update({ - id: '/management', - path: '/management', - getParentRoute: () => rootRouteImport, -} as any) const IndexRoute = IndexRouteImport.update({ id: '/', path: '/', @@ -198,9 +198,9 @@ export interface FileRouteTypes { export interface RootRouteChildren { IndexRoute: typeof IndexRoute AdminRoute: typeof AdminRoute - ManagementRoute: typeof ManagementRoute DashboardRoute: typeof DashboardRoute ImportRoute: typeof ImportRoute + ManagementRoute: typeof ManagementRoute SettingsRoute: typeof SettingsRoute StarsRoute: typeof StarsRoute UploadRoute: typeof UploadRoute @@ -235,6 +235,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof SettingsRouteImport parentRoute: typeof rootRouteImport } + '/management': { + id: '/management' + path: '/management' + fullPath: '/management' + preLoaderRoute: typeof ManagementRouteImport + parentRoute: typeof rootRouteImport + } '/import': { id: '/import' path: '/import' @@ -256,13 +263,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AdminRouteImport parentRoute: typeof rootRouteImport } - '/management': { - id: '/management' - path: '/management' - fullPath: '/management' - preLoaderRoute: typeof ManagementRouteImport - parentRoute: typeof rootRouteImport - } '/': { id: '/' path: '/' @@ -318,9 +318,9 @@ declare module '@tanstack/react-router' { const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, AdminRoute: AdminRoute, - ManagementRoute: ManagementRoute, DashboardRoute: DashboardRoute, ImportRoute: ImportRoute, + ManagementRoute: ManagementRoute, SettingsRoute: SettingsRoute, StarsRoute: StarsRoute, UploadRoute: UploadRoute, diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 714482e..bba982d 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -46,10 +46,11 @@ function SkillsHome() { dir: undefined, highlighted: undefined, view: undefined, + focus: undefined, }} className="btn" > - Browse skills + See all skills @@ -118,10 +119,11 @@ function SkillsHome() { dir: undefined, highlighted: undefined, view: undefined, + focus: undefined, }} className="btn" > - See all skills + Browse skills @@ -160,7 +162,13 @@ function OnlyCrabsHome() { Browse souls @@ -179,6 +187,7 @@ function OnlyCrabsHome() { sort: undefined, dir: undefined, view: undefined, + focus: undefined, }, }) }} @@ -222,7 +231,13 @@ function OnlyCrabsHome() {
See all souls diff --git a/src/routes/skills/index.tsx b/src/routes/skills/index.tsx index 22707e0..b2ff0f4 100644 --- a/src/routes/skills/index.tsx +++ b/src/routes/skills/index.tsx @@ -52,6 +52,7 @@ export const Route = createFileRoute('/skills/')({ ? true : undefined, view: search.view === 'cards' || search.view === 'list' ? search.view : undefined, + focus: search.focus === 'search' ? 'search' : undefined, } }, component: SkillsIndex, @@ -72,6 +73,7 @@ export function SkillsIndex() { const searchRequest = useRef(0) const loadMoreRef = useRef(null) + const searchInputRef = useRef(null) const trimmedQuery = useMemo(() => query.trim(), [query]) const hasQuery = trimmedQuery.length > 0 const searchKey = trimmedQuery ? `${trimmedQuery}::${highlightedOnly ? '1' : '0'}` : '' @@ -95,6 +97,15 @@ export function SkillsIndex() { setQuery(search.q ?? '') }, [search.q]) + // Auto-focus search input when focus=search param is present + useEffect(() => { + if (search.focus === 'search' && searchInputRef.current) { + searchInputRef.current.focus() + // Clear the focus param from URL to avoid re-focusing on navigation + void navigate({ search: (prev) => ({ ...prev, focus: undefined }), replace: true }) + } + }, [search.focus, navigate]) + useEffect(() => { if (!searchKey) { setSearchResults([]) @@ -144,8 +155,7 @@ export function SkillsIndex() { }, [hasQuery, paginatedResults, searchResults]) const filtered = useMemo( - () => - baseItems.filter((entry) => (highlightedOnly ? isSkillHighlighted(entry.skill) : true)), + () => baseItems.filter((entry) => (highlightedOnly ? isSkillHighlighted(entry.skill) : true)), [baseItems, highlightedOnly], ) @@ -225,6 +235,7 @@ export function SkillsIndex() {
{ diff --git a/src/routes/souls/index.tsx b/src/routes/souls/index.tsx index 6b33f7c..cf5094b 100644 --- a/src/routes/souls/index.tsx +++ b/src/routes/souls/index.tsx @@ -27,6 +27,7 @@ export const Route = createFileRoute('/souls/')({ sort: typeof search.sort === 'string' ? parseSort(search.sort) : undefined, dir: search.dir === 'asc' || search.dir === 'desc' ? search.dir : undefined, view: search.view === 'cards' || search.view === 'list' ? search.view : undefined, + focus: search.focus === 'search' ? 'search' : undefined, } }, component: SoulsIndex, @@ -43,12 +44,22 @@ function SoulsIndex() { const souls = useQuery(api.souls.list, { limit: 500 }) as Doc<'souls'>[] | undefined const ensureSoulSeeds = useAction(api.seed.ensureSoulSeeds) const seedEnsuredRef = useRef(false) + const searchInputRef = useRef(null) const isLoadingSouls = souls === undefined useEffect(() => { setQuery(search.q ?? '') }, [search.q]) + // Auto-focus search input when focus=search param is present + useEffect(() => { + if (search.focus === 'search' && searchInputRef.current) { + searchInputRef.current.focus() + // Clear the focus param from URL to avoid re-focusing on navigation + void navigate({ search: (prev) => ({ ...prev, focus: undefined }), replace: true }) + } + }, [search.focus, navigate]) + useEffect(() => { if (seedEnsuredRef.current) return seedEnsuredRef.current = true @@ -108,6 +119,7 @@ function SoulsIndex() {
{ From dcdc87e83e53aab14b4d1d8528a1614966d9fe4c Mon Sep 17 00:00:00 2001 From: Jamie Turner Date: Wed, 28 Jan 2026 10:10:17 -0800 Subject: [PATCH 2/6] Uh swap these labels back thx. --- src/routes/index.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/routes/index.tsx b/src/routes/index.tsx index bba982d..d960765 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -20,7 +20,10 @@ function Home() { function SkillsHome() { const highlighted = - (useQuery(api.skills.list, { batch: 'highlighted', limit: 6 }) as Doc<'skills'>[]) ?? [] + (useQuery(api.skills.list, { + batch: 'highlighted', + limit: 6, + }) as Doc<'skills'>[]) ?? [] const latest = (useQuery(api.skills.list, { limit: 12 }) as Doc<'skills'>[]) ?? [] return ( @@ -50,7 +53,7 @@ function SkillsHome() { }} className="btn" > - See all skills + Browse skills
@@ -123,7 +126,7 @@ function SkillsHome() { }} className="btn" > - Browse skills + See all skills
From 476cf4957b42afd1f54221c536cdc605459f3fbb Mon Sep 17 00:00:00 2001 From: Jamie Turner Date: Wed, 28 Jan 2026 10:50:05 -0800 Subject: [PATCH 3/6] Lint. --- convex/devSeed.ts | 2 +- convex/devSeedExtra.ts | 2 +- convex/http.ts | 2 +- convex/lib/badges.ts | 4 +-- convex/lib/githubImport.ts | 2 +- convex/lib/skillBackfill.ts | 2 +- convex/lib/skillPublish.ts | 4 +-- convex/lib/skills.test.ts | 2 +- convex/lib/skills.ts | 2 +- convex/maintenance.ts | 29 +++++++++-------- convex/skills.ts | 13 +++++--- e2e/molthub.e2e.test.ts | 2 +- packages/molthub/src/cli.ts | 2 +- src/components/SkillDetailPage.tsx | 6 ++-- src/components/SoulDetailPage.tsx | 4 +-- src/lib/uploadFiles.ts | 2 +- src/routes/management.tsx | 50 +++++++++++++++++++----------- 17 files changed, 70 insertions(+), 60 deletions(-) diff --git a/convex/devSeed.ts b/convex/devSeed.ts index 1919052..c3446c2 100644 --- a/convex/devSeed.ts +++ b/convex/devSeed.ts @@ -3,7 +3,7 @@ import { internal } from './_generated/api' import type { ActionCtx } from './_generated/server' import { internalAction, internalMutation } from './_generated/server' import { EMBEDDING_DIMENSIONS } from './lib/embeddings' -import { parseMoltbotMetadata, parseFrontmatter } from './lib/skills' +import { parseFrontmatter, parseMoltbotMetadata } from './lib/skills' type SeedSkillSpec = { slug: string diff --git a/convex/devSeedExtra.ts b/convex/devSeedExtra.ts index d33eb6e..4f202ab 100644 --- a/convex/devSeedExtra.ts +++ b/convex/devSeedExtra.ts @@ -11,7 +11,7 @@ import { internal } from './_generated/api' import type { Id } from './_generated/dataModel' import type { ActionCtx } from './_generated/server' import { internalAction, internalMutation } from './_generated/server' -import { parseMoltbotMetadata, parseFrontmatter } from './lib/skills' +import { parseFrontmatter, parseMoltbotMetadata } from './lib/skills' type SeedSkillSpec = { slug: string diff --git a/convex/http.ts b/convex/http.ts index d09ba07..3a27c2a 100644 --- a/convex/http.ts +++ b/convex/http.ts @@ -1,5 +1,5 @@ -import { ApiRoutes, LegacyApiRoutes } from 'molthub-schema' import { httpRouter } from 'convex/server' +import { ApiRoutes, LegacyApiRoutes } from 'molthub-schema' import { auth } from './auth' import { downloadZip } from './downloads' import { diff --git a/convex/lib/badges.ts b/convex/lib/badges.ts index 2d1c4eb..37a899f 100644 --- a/convex/lib/badges.ts +++ b/convex/lib/badges.ts @@ -3,9 +3,7 @@ import type { QueryCtx } from '../_generated/server' type BadgeKind = Doc<'skillBadges'>['kind'] -export type SkillBadgeMap = Partial< - Record; at: number }> -> +export type SkillBadgeMap = Partial; at: number }>> export type SkillBadgeSource = { badges?: SkillBadgeMap | null } diff --git a/convex/lib/githubImport.ts b/convex/lib/githubImport.ts index 9d71256..5282e74 100644 --- a/convex/lib/githubImport.ts +++ b/convex/lib/githubImport.ts @@ -1,5 +1,5 @@ -import { TEXT_FILE_EXTENSION_SET } from 'molthub-schema' import { zipSync } from 'fflate' +import { TEXT_FILE_EXTENSION_SET } from 'molthub-schema' import semver from 'semver' import { parseFrontmatter } from './skills' diff --git a/convex/lib/skillBackfill.ts b/convex/lib/skillBackfill.ts index 99ab322..c911a4b 100644 --- a/convex/lib/skillBackfill.ts +++ b/convex/lib/skillBackfill.ts @@ -2,8 +2,8 @@ import { getFrontmatterMetadata, getFrontmatterValue, type ParsedSkillFrontmatter, - parseMoltbotMetadata, parseFrontmatter, + parseMoltbotMetadata, } from './skills' export type ParsedSkillData = { diff --git a/convex/lib/skillPublish.ts b/convex/lib/skillPublish.ts index 7395f2b..7501cfa 100644 --- a/convex/lib/skillPublish.ts +++ b/convex/lib/skillPublish.ts @@ -3,16 +3,16 @@ import semver from 'semver' import { api, internal } from '../_generated/api' import type { Doc, Id } from '../_generated/dataModel' import type { ActionCtx, MutationCtx } from '../_generated/server' +import { getSkillBadgeMap, isSkillHighlighted } from './badges' import { generateChangelogForPublish } from './changelog' import { generateEmbedding } from './embeddings' -import { getSkillBadgeMap, isSkillHighlighted } from './badges' import { buildEmbeddingText, getFrontmatterMetadata, hashSkillFiles, isTextFile, - parseMoltbotMetadata, parseFrontmatter, + parseMoltbotMetadata, sanitizePath, } from './skills' import type { WebhookSkillPayload } from './webhooks' diff --git a/convex/lib/skills.test.ts b/convex/lib/skills.test.ts index 3d99947..f8254f4 100644 --- a/convex/lib/skills.test.ts +++ b/convex/lib/skills.test.ts @@ -5,8 +5,8 @@ import { getFrontmatterValue, hashSkillFiles, isTextFile, - parseMoltbotMetadata, parseFrontmatter, + parseMoltbotMetadata, sanitizePath, } from './skills' diff --git a/convex/lib/skills.ts b/convex/lib/skills.ts index 55b9336..2dfe60c 100644 --- a/convex/lib/skills.ts +++ b/convex/lib/skills.ts @@ -1,8 +1,8 @@ import { + isTextContentType, type MoltbotConfigSpec, type MoltbotSkillMetadata, MoltbotSkillMetadataSchema, - isTextContentType, type NixPluginSpec, parseArk, type SkillInstallSpec, diff --git a/convex/maintenance.ts b/convex/maintenance.ts index 7bc4227..7f048c5 100644 --- a/convex/maintenance.ts +++ b/convex/maintenance.ts @@ -672,9 +672,10 @@ export const backfillSkillBadges: ReturnType = action({ handler: async (ctx, args): Promise => { const { user } = await requireUserFromAction(ctx) assertRole(user, ['admin']) - return ctx.runAction(internal.maintenance.backfillSkillBadgesInternal, args) as Promise< - BadgeBackfillActionResult - > + return ctx.runAction( + internal.maintenance.backfillSkillBadgesInternal, + args, + ) as Promise }, }) @@ -771,15 +772,12 @@ export async function backfillSkillBadgeTableInternalHandler( if (dryRun) continue for (const entry of entries) { - const result = await ctx.runMutation( - internal.maintenance.upsertSkillBadgeRecordInternal, - { - skillId: item.skillId, - kind: entry.kind, - byUserId: entry.byUserId, - at: entry.at, - }, - ) + const result = await ctx.runMutation(internal.maintenance.upsertSkillBadgeRecordInternal, { + skillId: item.skillId, + kind: entry.kind, + byUserId: entry.byUserId, + at: entry.at, + }) if (result.inserted) { totals.recordsInserted++ } @@ -814,9 +812,10 @@ export const backfillSkillBadgeTable: ReturnType = action({ handler: async (ctx, args): Promise => { const { user } = await requireUserFromAction(ctx) assertRole(user, ['admin']) - return ctx.runAction(internal.maintenance.backfillSkillBadgeTableInternal, args) as Promise< - SkillBadgeTableBackfillActionResult - > + return ctx.runAction( + internal.maintenance.backfillSkillBadgeTableInternal, + args, + ) as Promise }, }) diff --git a/convex/skills.ts b/convex/skills.ts index 684d609..62a5b99 100644 --- a/convex/skills.ts +++ b/convex/skills.ts @@ -301,8 +301,7 @@ export const listWithLatest = query({ const ordered = args.batch === 'highlighted' ? [...withBadges].sort( - (a, b) => - (b.badges?.highlighted?.at ?? 0) - (a.badges?.highlighted?.at ?? 0), + (a, b) => (b.badges?.highlighted?.at ?? 0) - (a.badges?.highlighted?.at ?? 0), ) : withBadges const limited = ordered.slice(0, limit) @@ -327,8 +326,9 @@ export const listForManagement = query({ const limit = clampInt(args.limit ?? 50, 1, MAX_LIST_BULK_LIMIT) const takeLimit = Math.min(limit * 5, MAX_LIST_TAKE) const entries = await ctx.db.query('skills').order('desc').take(takeLimit) - const filtered = (args.includeDeleted ? entries : entries.filter((skill) => !skill.softDeletedAt)) - .slice(0, limit) + const filtered = ( + args.includeDeleted ? entries : entries.filter((skill) => !skill.softDeletedAt) + ).slice(0, limit) return buildManagementSkillEntries(ctx, filtered) }, }) @@ -339,7 +339,10 @@ export const listRecentVersions = query({ const { user } = await requireUser(ctx) assertModerator(user) const limit = clampInt(args.limit ?? 20, 1, MAX_LIST_BULK_LIMIT) - const versions = await ctx.db.query('skillVersions').order('desc').take(limit * 2) + const versions = await ctx.db + .query('skillVersions') + .order('desc') + .take(limit * 2) const entries = versions.filter((version) => !version.softDeletedAt).slice(0, limit) const results: Array<{ diff --git a/e2e/molthub.e2e.test.ts b/e2e/molthub.e2e.test.ts index dd2db59..4a111df 100644 --- a/e2e/molthub.e2e.test.ts +++ b/e2e/molthub.e2e.test.ts @@ -4,13 +4,13 @@ import { spawnSync } from 'node:child_process' import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' +import { unzipSync } from 'fflate' import { ApiRoutes, ApiV1SearchResponseSchema, ApiV1WhoamiResponseSchema, parseArk, } from 'molthub-schema' -import { unzipSync } from 'fflate' import { Agent, setGlobalDispatcher } from 'undici' import { describe, expect, it } from 'vitest' import { readGlobalConfig } from '../packages/molthub/src/config' diff --git a/packages/molthub/src/cli.ts b/packages/molthub/src/cli.ts index 4cbdd42..3db7f55 100644 --- a/packages/molthub/src/cli.ts +++ b/packages/molthub/src/cli.ts @@ -3,7 +3,6 @@ import { stat } from 'node:fs/promises' import { join, resolve } from 'node:path' import { Command } from 'commander' import { getCliBuildLabel, getCliVersion } from './cli/buildInfo.js' -import { resolveMoltbotDefaultWorkspace } from './cli/moltbotConfig.js' import { cmdLoginFlow, cmdLogout, cmdWhoami } from './cli/commands/auth.js' import { cmdDeleteSkill, cmdUndeleteSkill } from './cli/commands/delete.js' import { cmdPublish } from './cli/commands/publish.js' @@ -12,6 +11,7 @@ import { cmdStarSkill } from './cli/commands/star.js' import { cmdSync } from './cli/commands/sync.js' import { cmdUnstarSkill } from './cli/commands/unstar.js' import { configureCommanderHelp, styleEnvBlock, styleTitle } from './cli/helpStyle.js' +import { resolveMoltbotDefaultWorkspace } from './cli/moltbotConfig.js' import { DEFAULT_REGISTRY, DEFAULT_SITE } from './cli/registry.js' import type { GlobalOpts } from './cli/types.js' import { fail } from './cli/ui.js' diff --git a/src/components/SkillDetailPage.tsx b/src/components/SkillDetailPage.tsx index 29caf05..4417d54 100644 --- a/src/components/SkillDetailPage.tsx +++ b/src/components/SkillDetailPage.tsx @@ -1,6 +1,6 @@ import { Link, useNavigate } from '@tanstack/react-router' -import type { MoltbotSkillMetadata, SkillInstallSpec } from 'molthub-schema' import { useAction, useMutation, useQuery } from 'convex/react' +import type { MoltbotSkillMetadata, SkillInstallSpec } from 'molthub-schema' import { useEffect, useMemo, useState } from 'react' import ReactMarkdown from 'react-markdown' import remarkGfm from 'remark-gfm' @@ -649,9 +649,7 @@ export function SkillDetailPage({ @{entry.user?.handle ?? entry.user?.name ?? 'user'}
{entry.comment.body}
- {isAuthenticated && - me && - (me._id === entry.comment.userId || isModerator(me)) ? ( + {isAuthenticated && me && (me._id === entry.comment.userId || isModerator(me)) ? (
- {isAuthenticated && - me && - (me._id === entry.comment.userId || isModerator(me)) ? ( + {isAuthenticated && me && (me._id === entry.comment.userId || isModerator(me)) ? (