Skip to content
Draft
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
825 changes: 825 additions & 0 deletions .cursor/plans/add_skills_tab_to_marketplace_644a4c6e.plan.md

Large diffs are not rendered by default.

106 changes: 90 additions & 16 deletions apps/storybook/src/mockData/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,72 @@ export const mockMarketplaceItems = [
content:
"slug: debug\nname: Debug\nmodel: anthropic/claude-sonnet-4\nprompt: |\n You are a debugging specialist.",
},
{
id: "translate-skill",
name: "Translate Skill",
description: "Translate and localize applications with support for multiple languages and formats.",
author: "Kilocode",
tags: ["i18n", "translation", "localization"],
type: "skill" as const,
category: "Developer Tools",
repository: {
fullName: "kilocode/translate-skill",
stars: 1250,
forks: 89,
url: "https://github.com/kilocode/translate-skill",
pushedAt: "2024-01-15T10:30:00Z",
},
skillFile: "SKILL.md",
marketplaceJson: {
name: "Translate Skill",
version: "1.0.0",
installCommand: "npm install @kilocode/translate-skill",
description: "Translation and localization for your apps",
},
content: "# Translate Skill\n\nThis skill provides translation and localization capabilities...",
},
{
id: "test-skill",
name: "Test Skill",
description: "Comprehensive testing utilities for writing and managing test suites.",
author: "TestingTeam",
tags: ["testing", "quality", "automation"],
type: "skill" as const,
category: "Quality Assurance",
repository: {
fullName: "community/test-skill",
stars: 567,
forks: 45,
url: "https://github.com/community/test-skill",
pushedAt: "2024-01-14T15:45:00Z",
},
skillFile: "SKILL.md",
marketplaceJson: {
name: "Test Skill",
version: "2.1.0",
installCommand: "npm install @community/test-skill",
description: "Testing utilities for any project",
},
content: "# Test Skill\n\nComprehensive testing utilities...",
},
{
id: "refactor-skill",
name: "Refactor Skill",
description: "Automated code refactoring and improvement suggestions.",
author: "RefactorKing",
tags: ["refactoring", "code-quality", "improvements"],
type: "skill" as const,
category: "Code Quality",
repository: {
fullName: "community/refactor-skill",
stars: 892,
forks: 67,
url: "https://github.com/community/refactor-skill",
pushedAt: "2024-01-13T09:20:00Z",
},
skillFile: "SKILL.md",
content: "# Refactor Skill\n\nAutomated code refactoring...",
},
]

export const mockModes = [
Expand All @@ -68,22 +134,30 @@ export const mockModes = [
},
]

export const createMockMarketplaceStateManager = (activeTab: "mcp" | "mode" = "mcp") => ({
getState: () => ({
allItems: mockMarketplaceItems,
organizationMcps: [],
displayItems: mockMarketplaceItems,
displayOrganizationMcps: [],
isFetching: false,
activeTab,
filters: {
type: "",
search: "",
tags: [],
installed: "all" as const,
},
installedMetadata: { global: {}, project: {} },
}),
export const createMockMarketplaceStateManager = (activeTab: "mcp" | "mode" | "skill" = "mcp") => ({
getState: () => {
const items =
activeTab === "mcp"
? mockMarketplaceItems.filter((i) => i.type === "mcp")
: activeTab === "mode"
? mockMarketplaceItems.filter((i) => i.type === "mode")
: mockMarketplaceItems.filter((i) => i.type === "skill")
return {
allItems: mockMarketplaceItems,
organizationMcps: [],
displayItems: items,
displayOrganizationMcps: [],
isFetching: false,
activeTab,
filters: {
type: "",
search: "",
tags: [],
installed: "all" as const,
},
installedMetadata: { global: {}, project: {} },
}
},
transition: () => Promise.resolve(),
onStateChange: () => () => {},
cleanup: () => {},
Expand Down
2 changes: 1 addition & 1 deletion apps/storybook/stories/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { fn } from "storybook/test"
import { Button } from "@/components/ui/button"
import { createTableStory } from "../src/utils/createTableStory"

const BUTTON_VARIANTS = ["default", "destructive", "outline", "secondary", "ghost", "link"] as const
const BUTTON_VARIANTS = ["primary", "secondary", "destructive", "outline", "ghost", "link", "combobox"] as const
const BUTTON_SIZES = ["default", "sm", "lg", "icon"] as const
const STORY_TABLE_SIZES = ["default", "sm", "lg"] as const

Expand Down
2 changes: 1 addition & 1 deletion apps/storybook/stories/ChatRow.Ask.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const meta = {
editable: false,
hasCheckpoint: false,
},
} satisfies Meta<typeof ChatRow>
} as Meta<typeof ChatRow>

export default meta
type Story = StoryObj<typeof meta>
Expand Down
2 changes: 1 addition & 1 deletion apps/storybook/stories/ChatRow.Say.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const meta = {
editable: false,
hasCheckpoint: false,
},
} satisfies Meta<typeof ChatRow>
} as Meta<typeof ChatRow>

export default meta
type Story = StoryObj<typeof meta>
Expand Down
41 changes: 40 additions & 1 deletion apps/storybook/stories/MarketplaceView.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const meta = {
argTypes: {
targetTab: {
control: { type: "select" },
options: ["mcp", "mode"],
options: ["mcp", "mode", "skill"],
description: "Which tab should be active initially",
},
hideHeader: {
Expand Down Expand Up @@ -66,3 +66,42 @@ export const ModeTab: Story = {
targetTab: "mode",
},
}

export const SkillTab: Story = {
args: {
stateManager: createMockMarketplaceStateManager("skill") as any,
targetTab: "skill",
},
}

export const AllTabsWithItems: Story = {
args: {
stateManager: createMockMarketplaceStateManager("mcp") as any,
targetTab: "mcp",
},
parameters: {
extensionState: createExtensionStateMock({
organizationAllowList: {
allowAll: true,
providers: {},
},
apiConfiguration: {
apiProvider: "anthropic",
apiModelId: "claude-3-5-sonnet-20241022",
apiKey: "mock-key",
},
marketplaceInstalledMetadata: {
global: {
"filesystem-mcp": { type: "mcp" },
"architect-mode": { type: "mode" },
},
project: {
"database-mcp": { type: "mcp" },
},
},
mcpServers: [],
mode: "code",
customModes: [],
}),
},
}
29 changes: 0 additions & 29 deletions apps/storybook/stories/TabbedCodeIndexPopover.stories.tsx

This file was deleted.

32 changes: 31 additions & 1 deletion packages/types/src/marketplace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type McpInstallationMethod = z.infer<typeof mcpInstallationMethodSchema>
/**
* Component type validation
*/
export const marketplaceItemTypeSchema = z.enum(["mode", "mcp"] as const)
export const marketplaceItemTypeSchema = z.enum(["mode", "mcp", "skill"] as const)

export type MarketplaceItemType = z.infer<typeof marketplaceItemTypeSchema>

Expand Down Expand Up @@ -61,6 +61,32 @@ export const mcpMarketplaceItemSchema = baseMarketplaceItemSchema.extend({

export type McpMarketplaceItem = z.infer<typeof mcpMarketplaceItemSchema>

export const skillMarketplaceItemSchema = baseMarketplaceItemSchema.extend({
repository: z
.object({
fullName: z.string(),
stars: z.number(),
forks: z.number(),
url: z.string().url(),
pushedAt: z.string(),
})
.optional(),
category: z.string().optional(),
hasInstallCommand: z.boolean().optional(),
skillFile: z.string().optional(),
marketplaceJson: z
.object({
name: z.string(),
version: z.string().optional(),
installCommand: z.string().optional(),
description: z.string().optional(),
})
.optional(),
content: z.string().optional(), // Optional content for skill (SKILL.md content)
})

export type SkillMarketplaceItem = z.infer<typeof skillMarketplaceItemSchema>

/**
* Unified marketplace item schema using discriminated union
*/
Expand All @@ -73,6 +99,10 @@ export const marketplaceItemSchema = z.discriminatedUnion("type", [
mcpMarketplaceItemSchema.extend({
type: z.literal("mcp"),
}),
// Skill marketplace item
skillMarketplaceItemSchema.extend({
type: z.literal("skill"),
}),
])

export type MarketplaceItem = z.infer<typeof marketplaceItemSchema>
Expand Down
Loading
Loading