Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
23f9b0e
Update schema to support the foundation for skills, both personal and…
jsourcebot Jun 9, 2026
05ae0bd
Add initial UI and actions to support personal skills
jsourcebot Jun 9, 2026
fdc083b
support unsaved changes loss guard, work in progress
jsourcebot Jun 13, 2026
d92be1b
Add Ask command suggestions for personal skills
jsourcebot Jun 15, 2026
bf25c64
feat: add slash command argument substitution
jsourcebot Jun 16, 2026
99cd4ea
refactor: model agent skill scope explicitly
jsourcebot Jun 17, 2026
344255a
Add org skill adoption commands
jsourcebot Jun 17, 2026
a2031b7
Add org skill settings UI
jsourcebot Jun 17, 2026
c91ba89
Add workspace skill management UI
jsourcebot Jun 18, 2026
b1263e9
Add file mentions to skill instructions
jsourcebot Jun 20, 2026
aa0676a
feat(web): auto-invoke agent skills in Ask via load_skill tool
jsourcebot Jun 23, 2026
1945a3c
feat(web): render load_skill tool calls and harden auto-invocation
jsourcebot Jun 24, 2026
0a76bbe
refactor(web): force skill auto-invocation, drop arguments, org-scope…
jsourcebot Jun 25, 2026
fe48eba
refactor(web): move Ask Sourcebot skills into a standalone Skills page
jsourcebot Jun 25, 2026
40cf743
update on skills editing ux
jsourcebot Jun 25, 2026
3d5a1e3
refactor(web): UI improvements for the Ask skills page
jsourcebot Jun 26, 2026
2533ae9
refactor(web): remove the featured skills concept
jsourcebot Jun 26, 2026
7907830
fix(web): only show search mode tooltips when the dropdown is open
jsourcebot Jun 27, 2026
c79ee2b
feat(web): import skills from markdown on the Skills page
jsourcebot Jun 27, 2026
5579e08
feat(web): import skills from an indexed repository
jsourcebot Jun 27, 2026
8fdfc92
feat(web): repo-synced agent skills with org sharing and access gating
jsourcebot Jun 28, 2026
8550993
feat(web): overhaul shared-skills admin table and sharing UX
jsourcebot Jul 1, 2026
0da351b
refactor(web): drop dead skill toggle and redundant delete guard
jsourcebot Jul 1, 2026
6bd7aea
Add changelog entry for Ask skills
jsourcebot Jul 2, 2026
20f5b03
chore: regenerate OpenAPI spec
github-actions[bot] Jul 2, 2026
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [EE] Added DPoP sender-constrained OAuth tokens for MCP clients. [#1395](https://github.com/sourcebot-dev/sourcebot/pull/1395)
- [EE] Added text file attachments to Ask Sourcebot, letting users attach text/code/config files to a chat message via the paperclip button, drag-and-drop, or paste, with large pastes auto-converted to attachments. [#1374](https://github.com/sourcebot-dev/sourcebot/pull/1374)
- [EE] Added image attachments to Ask Sourcebot, letting users attach images to a chat message when the selected model supports image input. [#1375](https://github.com/sourcebot-dev/sourcebot/pull/1375)
- [EE] Added Ask Sourcebot skills, letting users create, import, share, sync, and auto-invoke reusable chat instructions across personal and workspace scopes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add missing PR link to changelog entry.

This is the only [Unreleased] entry without a trailing PR link; every sibling entry (lines 16-22) ends with [#<id>](<url>).

📝 Proposed fix
-- [EE] Added Ask Sourcebot skills, letting users create, import, share, sync, and auto-invoke reusable chat instructions across personal and workspace scopes.
+- [EE] Added Ask Sourcebot skills, letting users create, import, share, sync, and auto-invoke reusable chat instructions across personal and workspace scopes. [#<PR>](https://github.com/sourcebot-dev/sourcebot/pull/<PR>)

As per path instructions, "Update CHANGELOG.md with an entry under [Unreleased] linking to the new PR" and "entries must include the GitHub pull request id at the end of the line, formatted as [#<id>](<url>)".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- [EE] Added Ask Sourcebot skills, letting users create, import, share, sync, and auto-invoke reusable chat instructions across personal and workspace scopes.
[EE] Added Ask Sourcebot skills, letting users create, import, share, sync, and auto-invoke reusable chat instructions across personal and workspace scopes. [#<PR>](https://github.com/sourcebot-dev/sourcebot/pull/<PR>)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` at line 23, The Unreleased changelog item for the Ask Sourcebot
skills entry is missing the trailing GitHub PR link, unlike the other sibling
entries. Update the `CHANGELOG.md` Unreleased entry so the line ends with the
pull request reference in the required `[#<id>](<url>)` format, matching the
existing pattern used by the nearby changelog items.

Source: Path instructions


### Fixed
- Send anonymous server-side PostHog events as personless so unauthenticated requests don't inflate person counts. [#1367](https://github.com/sourcebot-dev/sourcebot/pull/1367)
Expand Down
3 changes: 3 additions & 0 deletions docs/api-reference/sourcebot-public.openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,9 @@
},
"externalWebUrl": {
"type": "string"
},
"blobSha": {
"type": "string"
}
},
"required": [
Expand Down

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we compress into a single migration?

Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
-- CreateEnum
CREATE TYPE "AgentSkillVisibility" AS ENUM ('PERSONAL', 'SHARED');

-- CreateTable
CREATE TABLE "AgentSkill" (
"id" TEXT NOT NULL,
"visibility" "AgentSkillVisibility" NOT NULL,
"scopeId" TEXT NOT NULL,
"slug" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT NOT NULL,
"instructions" TEXT NOT NULL,
"createdById" TEXT NOT NULL,
"updatedById" TEXT,
"orgId" INTEGER NOT NULL,
"enabled" BOOLEAN NOT NULL DEFAULT true,
"featured" BOOLEAN NOT NULL DEFAULT false,
"autoEnrolled" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "AgentSkill_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "AgentSkillAdoption" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"orgId" INTEGER NOT NULL,
"agentSkillId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"removedAt" TIMESTAMP(3),

CONSTRAINT "AgentSkillAdoption_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE INDEX "AgentSkill_createdById_idx" ON "AgentSkill"("createdById");

-- CreateIndex
CREATE INDEX "AgentSkill_updatedById_idx" ON "AgentSkill"("updatedById");

-- CreateIndex
CREATE INDEX "AgentSkill_orgId_idx" ON "AgentSkill"("orgId");

-- CreateIndex
CREATE INDEX "AgentSkill_orgId_visibility_scopeId_idx" ON "AgentSkill"("orgId", "visibility", "scopeId");

-- CreateIndex
CREATE INDEX "AgentSkill_shared_catalog_idx" ON "AgentSkill"("orgId", "visibility", "scopeId", "enabled", "featured" DESC, "updatedAt" DESC, "name");

-- CreateIndex
CREATE UNIQUE INDEX "AgentSkill_orgId_visibility_scopeId_slug_key" ON "AgentSkill"("orgId", "visibility", "scopeId", "slug");

-- CreateIndex
CREATE INDEX "AgentSkillAdoption_userId_orgId_removedAt_idx" ON "AgentSkillAdoption"("userId", "orgId", "removedAt");

-- CreateIndex
CREATE INDEX "AgentSkillAdoption_agentSkillId_idx" ON "AgentSkillAdoption"("agentSkillId");

-- CreateIndex
CREATE INDEX "AgentSkillAdoption_orgId_idx" ON "AgentSkillAdoption"("orgId");

-- CreateIndex
CREATE UNIQUE INDEX "AgentSkillAdoption_orgId_userId_agentSkillId_key" ON "AgentSkillAdoption"("orgId", "userId", "agentSkillId");

-- AddForeignKey
ALTER TABLE "AgentSkill" ADD CONSTRAINT "AgentSkill_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AgentSkill" ADD CONSTRAINT "AgentSkill_updatedById_fkey" FOREIGN KEY ("updatedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AgentSkill" ADD CONSTRAINT "AgentSkill_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "Org"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AgentSkillAdoption" ADD CONSTRAINT "AgentSkillAdoption_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AgentSkillAdoption" ADD CONSTRAINT "AgentSkillAdoption_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "Org"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "AgentSkillAdoption" ADD CONSTRAINT "AgentSkillAdoption_agentSkillId_fkey" FOREIGN KEY ("agentSkillId") REFERENCES "AgentSkill"("id") ON DELETE CASCADE ON UPDATE CASCADE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- DropIndex
DROP INDEX "AgentSkill_shared_catalog_idx";

-- AlterTable
ALTER TABLE "AgentSkill" DROP COLUMN "featured";

-- CreateIndex
CREATE INDEX "AgentSkill_shared_catalog_idx" ON "AgentSkill"("orgId", "visibility", "scopeId", "enabled", "updatedAt" DESC, "name");
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- AlterTable
ALTER TABLE "AgentSkill" ADD COLUMN "sourceBlobSha" TEXT,
ADD COLUMN "sourceFilePath" TEXT,
ADD COLUMN "sourceImportedAt" TIMESTAMP(3),
ADD COLUMN "sourceRepoName" TEXT,
ADD COLUMN "sourceRevision" TEXT;
92 changes: 92 additions & 0 deletions packages/db/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,8 @@ model Org {
repoVisits RepoVisit[]

mcpServers McpServer[]
agentSkills AgentSkill[]
agentSkillAdoptions AgentSkillAdoption[]

license License?
servicePingEvents ServicePingEvent[]
Expand Down Expand Up @@ -519,6 +521,9 @@ model User {
sessionVersion Int @default(0)

userMcpServers UserMcpServer[]
createdAgentSkills AgentSkill[] @relation("AgentSkillCreatedBy")
updatedAgentSkills AgentSkill[] @relation("AgentSkillUpdatedBy")
agentSkillAdoptions AgentSkillAdoption[]

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
Expand Down Expand Up @@ -741,6 +746,93 @@ model ChatAccess {
@@unique([chatId, userId])
}

enum AgentSkillVisibility {
PERSONAL
SHARED
}

model AgentSkill {
id String @id @default(cuid())

// Namespace identity for slash-command uniqueness and lookup.
// This is not a foreign key and should not be used as an authorization check by itself.
//
// Every skill belongs to an org (orgId is always set).
// PERSONAL: scopeId is the user id; the skill is private to that user within the org.
// SHARED: scopeId is String(orgId); the skill is visible to the whole org (opt-in via adoptions).
//
// Future sharing/grants should treat this as the skill's home namespace, not as the ACL.
visibility AgentSkillVisibility
scopeId String
slug String

name String
description String
instructions String

// The user who authored the skill. This is audit metadata, separate from
// the namespace that owns the slash-command slug.
createdBy User @relation("AgentSkillCreatedBy", fields: [createdById], references: [id], onDelete: Cascade)
createdById String

updatedBy User? @relation("AgentSkillUpdatedBy", fields: [updatedById], references: [id], onDelete: SetNull)
updatedById String?

Comment on lines +773 to +780

@coderabbitai coderabbitai Bot Jul 2, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

createdBy cascade delete can silently wipe shared/org skills.

createdBy uses onDelete: Cascade (Line 775) while updatedBy uses onDelete: SetNull (Line 778) for what the comment (Lines 773-774) calls audit metadata, "separate from the namespace that owns the slash-command slug." For PERSONAL skills this is harmless since scopeId == createdById anyway. But for SHARED skills, deleting the creator's User row (e.g., offboarding an employee) cascades to delete the entire org-wide shared skill — along with every other user's AgentSkillAdoption rows for it — even though the skill is meant to persist as an org resource independent of its original author.

This contradicts the stated intent and risks unexpected data loss on a routine admin action (user removal).

🛠️ Suggested fix
-  createdBy   User   `@relation`("AgentSkillCreatedBy", fields: [createdById], references: [id], onDelete: Cascade)
-  createdById String
+  createdBy   User?   `@relation`("AgentSkillCreatedBy", fields: [createdById], references: [id], onDelete: SetNull)
+  createdById String?

Note: this requires updating all createdById: userId call sites and Pick<AgentSkill, ... "createdById" ...> mapping code (e.g. toSharedAgentSkillCatalogItem in types.ts) to tolerate null.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// The user who authored the skill. This is audit metadata, separate from
// the namespace that owns the slash-command slug.
createdBy User @relation("AgentSkillCreatedBy", fields: [createdById], references: [id], onDelete: Cascade)
createdById String
updatedBy User? @relation("AgentSkillUpdatedBy", fields: [updatedById], references: [id], onDelete: SetNull)
updatedById String?
// The user who authored the skill. This is audit metadata, separate from
// the namespace that owns the slash-command slug.
createdBy User? `@relation`("AgentSkillCreatedBy", fields: [createdById], references: [id], onDelete: SetNull)
createdById String?
updatedBy User? `@relation`("AgentSkillUpdatedBy", fields: [updatedById], references: [id], onDelete: SetNull)
updatedById String?
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/db/prisma/schema.prisma` around lines 773 - 780, The AgentSkill
audit relation is too destructive: `createdBy` currently cascades on user
deletion, which can delete shared/org skills and their adopters. Update the
`AgentSkill` model’s `createdBy`/`createdById` relation in the Prisma schema to
stop using cascade delete and allow the creator reference to be cleared instead,
matching the intent of audit metadata. Then update any `createdById` callers and
mappings that assume a required user, including `toSharedAgentSkillCatalogItem`
and any `Pick<AgentSkill, ... "createdById" ...>` usages, so they handle a
nullable creator.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As of current this was actually intentional, but it's unclear if it should be this way or if a shared skill truly becomes an org resource (but then it's weird that the creator is the sole person who can then remove everybodies access to it).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jsourcebot Thanks for the context — that's a fair tension to flag. A few ways I'd think about resolving the ambiguity, depending on which mental model you want for SHARED skills:

  1. Skill is an org resource, ownership decoupled from a single user — switch createdBy/createdById to SetNull (matching updatedBy), and introduce an explicit notion of "current owner/maintainer" that's independent from the original author (e.g., allow any org OWNER to delete/manage a SHARED skill, not just the creator). This is the cleanest mental model for "shared skills survive offboarding," but requires updating the delete/update authorization logic (currently gated to the creator in actions.ts) plus making createdById nullable everywhere it's consumed (e.g., toSharedAgentSkillCatalogItem).
  2. Keep cascade, but guard the destructive path — leave the schema as-is, but before deleting a User, check for SHARED skills they authored and either block the deletion or prompt to reassign/transfer ownership first. This avoids a schema/type migration but adds friction to user offboarding flows.
  3. Status quo — accept that removing a user prunes their shared skills too, treating "shared" as more like "shared while the author remains a member" rather than a durable org asset. Simplest, but as you noted, has surprising blast radius (also deletes all AgentSkillAdoption rows for every other member who adopted it).

Given this is a genuine product/design decision rather than a clear-cut bug, I'll leave it to you and the team to decide the intended semantics. If you'd like, I can open a follow-up issue to track "clarify/rework AgentSkill ownership semantics for org offboarding" so it doesn't get lost — just let me know.


✏️ Learnings added
Learnt from: jsourcebot
Repo: sourcebot-dev/sourcebot PR: 1410
File: packages/db/prisma/schema.prisma:773-780
Timestamp: 2026-07-02T02:23:27.352Z
Learning: In Sourcebot's Prisma schema (packages/db/prisma/schema.prisma), the `AgentSkill.createdBy` relation intentionally uses `onDelete: Cascade` (as of PR `#1410`), meaning deleting a `User` who authored a `SHARED` (org-wide) skill also deletes that skill and all associated `AgentSkillAdoption` rows for every other user who adopted it. The team (jsourcebot) has acknowledged this is a known tradeoff/open design question — it's unclear whether shared skills should become independent org resources decoupled from their creator (which would require reworking ownership/authorization, e.g., allowing any org owner to manage a shared skill) or whether the current author-tied-deletion behavior is intended. Do not flag this as a definitive bug in future reviews unless the schema or stated intent changes; treat it as an open question already known to the maintainers.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: fatmcgav
Repo: sourcebot-dev/sourcebot PR: 1143
File: packages/db/prisma/schema.prisma:640-660
Timestamp: 2026-04-22T07:09:48.693Z
Learning: In Sourcebot’s Prisma schema, treat junction/relationship tables (e.g., AgentConfigToRepo, AgentConfigToConnection) as single-tenant and do not require a denormalized `orgId` column for tenant isolation. Tenant isolation is enforced by foreign keys/cascades from `AgentConfig` (which contains `orgId`). When reviewing queries/relations involving these junction tables, avoid raising multi-tenant isolation concerns as long as access is gated through `AgentConfig` filtered by `orgId`.

// The owning org. Both PERSONAL and SHARED skills are scoped to an org, so a
// user's personal skills change when they switch orgs.
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
orgId Int

enabled Boolean @default(true)
autoEnrolled Boolean @default(false)

// Provenance for skills imported from an indexed repository file. All null for
// skills created manually or imported from a local file. When set, the skill's
// content is a read-only mirror of the source file: edits happen in the repo and
// are pulled in via "Update from source". sourceBlobSha (the git blob OID at
// import) is the comparison key used to detect when the indexed file has changed.
// Sync is personal-only; publishing to shared snapshots the content and drops
// these fields.
sourceRepoName String?
sourceFilePath String?
sourceRevision String?
sourceBlobSha String?
sourceImportedAt DateTime?

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

adoptions AgentSkillAdoption[]

@@unique([orgId, visibility, scopeId, slug])
@@index([createdById])
@@index([updatedById])
@@index([orgId])
@@index([orgId, visibility, scopeId])
@@index([orgId, visibility, scopeId, enabled, updatedAt(sort: Desc), name], map: "AgentSkill_shared_catalog_idx")
}

model AgentSkillAdoption {
id String @id @default(cuid())

user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String

org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
orgId Int

agentSkill AgentSkill @relation(fields: [agentSkillId], references: [id], onDelete: Cascade)
agentSkillId String

createdAt DateTime @default(now())
removedAt DateTime?

@@unique([orgId, userId, agentSkillId])
@@index([userId, orgId, removedAt])
@@index([agentSkillId])
@@index([orgId])
}

// OAuth2 Authorization Server models
// @see: https://datatracker.ietf.org/doc/html/rfc6749

Expand Down
63 changes: 61 additions & 2 deletions packages/db/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,62 @@
import type { User, Account } from ".prisma/client";
import type { Account, Prisma, User } from ".prisma/client";
export type UserWithAccounts = User & { accounts: Account[] };
export * from ".prisma/client";
export * from ".prisma/client";

// Personal skills are scoped to the (user, org) pair: a user's personal skills
// change when they switch orgs. scopeId is the userId; orgId binds it to the org.
export const personalAgentSkillScope = (userId: string, orgId: number) => ({
visibility: "PERSONAL" as const,
scopeId: userId,
orgId,
});

// Shared skills are visible to the whole org. scopeId is String(orgId) so every
// shared skill in an org occupies one slug-uniqueness namespace.
export const sharedAgentSkillScope = (orgId: number) => ({
visibility: "SHARED" as const,
scopeId: String(orgId),
orgId,
});

export const personalAgentSkillAuthScope = (userId: string, orgId: number) => ({
...personalAgentSkillScope(userId, orgId),
createdById: userId,
});

export const sharedAgentSkillAuthScope = (orgId: number) => ({
...sharedAgentSkillScope(orgId),
});

export const sharedAgentSkillVisibleToUserWhere = (userId: string, orgId: number) => ({
...sharedAgentSkillAuthScope(orgId),
enabled: true,
AND: [
{
OR: [
{ autoEnrolled: true },
{
adoptions: {
some: {
userId,
orgId,
removedAt: null,
},
},
},
],
},
{
NOT: {
adoptions: {
some: {
userId,
orgId,
removedAt: {
not: null,
},
},
},
},
},
],
}) satisfies Prisma.AgentSkillWhereInput;
2 changes: 2 additions & 0 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@
"usehooks-ts": "^3.1.0",
"uuid": "^14.0.0",
"vscode-icons-js": "^11.6.1",
"yaml": "^2.8.3",
"zod": "^3.25.76",
"zod-to-json-schema": "^3.24.5"
},
Expand All @@ -213,6 +214,7 @@
"@eslint/eslintrc": "^3",
"@react-email/ui": "6.1.4",
"@react-grab/mcp": "^0.1.23",
"@tailwindcss/container-queries": "^0.1.1",
"@tanstack/eslint-plugin-query": "^5.74.7",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
ServerIcon,
Settings2Icon,
ShieldIcon,
SparklesIcon,
UserIcon,
UsersIcon,
} from "lucide-react";
Expand All @@ -44,6 +45,7 @@ const iconMap = {
"user": UserIcon,
"mcp": VscMcp,
"bot": BotIcon,
"sparkles": SparklesIcon,
} satisfies Record<string, LucideIcon | IconType>;

export type NavIconName = keyof typeof iconMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import { DISABLED_MCP_SERVER_IDS_LOCAL_STORAGE_KEY } from "@/features/chat/const
import { getRepoImageSrc } from '@/lib/utils';
import { useMemo, useRef, useState } from "react";
import { useLocalStorage } from "usehooks-ts";
import type { AskCommandDefinition } from '@/features/chat/commands/types';

interface LandingPageProps {
languageModels: LanguageModelInfo[];
repoName: string;
repoDisplayName?: string;
imageUrl?: string | null;
repoId: number;
askCommands: AskCommandDefinition[];
isAuthenticated: boolean;
maxImageBytes: number;
}
Expand All @@ -30,6 +32,7 @@ export const LandingPage = ({
repoDisplayName,
imageUrl,
repoId,
askCommands,
isAuthenticated,
maxImageBytes,
}: LandingPageProps) => {
Expand Down Expand Up @@ -86,6 +89,7 @@ export const LandingPage = ({
isRedirecting={isLoading}
selectedSearchScopes={selectedSearchScopes}
searchContexts={[]}
askCommands={askCommands}
isDisabled={isChatBoxDisabled}
isAuthenticated={isAuthenticated}
isLoginWallEnabled={true}
Expand Down
5 changes: 5 additions & 0 deletions packages/web/src/app/(app)/askgh/[owner]/[repo]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { auth } from "@/auth";
import { hasEntitlement } from "@/lib/entitlements";
import { ChatEntitlementMessage } from "@/features/chat/components/chatEntitlementMessage";
import { env } from "@sourcebot/shared";
import { listAgentSkillCommandsOrEmpty } from "@/ee/features/chat/skills/commands.server";

interface PageProps {
params: Promise<{ owner: string; repo: string }>;
Expand Down Expand Up @@ -54,6 +55,9 @@ export default async function GitHubRepoPage(props: PageProps) {

const repoInfo = await getRepoInfo(repoId)
const languageModels = await getConfiguredLanguageModelsInfo()
const askCommands = session?.user
? await listAgentSkillCommandsOrEmpty()
: [];

if (isServiceError(repoInfo)) {
throw new ServiceErrorException(repoInfo);
Expand All @@ -68,6 +72,7 @@ export default async function GitHubRepoPage(props: PageProps) {
repoDisplayName={repoInfo.displayName ?? undefined}
imageUrl={repoInfo.imageUrl ?? undefined}
repoId={repoInfo.id}
askCommands={askCommands}
isAuthenticated={!!session?.user}
maxImageBytes={env.SOURCEBOT_CHAT_ATTACHMENT_MAX_IMAGE_BYTES}
/>
Expand Down
Loading