| 1 | import { pluginRef } from "@g1t/contracts/claude-plugin"; |
| 2 | import { connectorPath, connectorsFor } from "@g1t/contracts/connectors"; |
| 3 | import { CUSTOMIZE, type CustomizeSection, customizePath } from "@g1t/contracts/customize"; |
| 4 | import { FIRST_PARTY_EXTENSIONS } from "@g1t/contracts/marketplace"; |
| 5 | import { FOUNDATIONAL_SKILLS } from "@g1t/contracts/skills"; |
| 6 | |
| 7 | /** |
| 8 | * Customize on the phone: Skills, Connectors and Plugins |
| 9 | * (packages/contracts/src/customize.ts). What is listed comes from the |
| 10 | * catalogs every g1t ships with; a workspace's own library, connections |
| 11 | * and installs are read on the site for now, and added here once the API |
| 12 | * serves them. Every item opens where the site shows it: a connector on |
| 13 | * Connectors' Discover (an MCP server on its connect page), g1t's own |
| 14 | * announced plugins on their pages in the `g1t` marketplace. |
| 15 | */ |
| 16 | |
| 17 | export type CustomizeItem = { |
| 18 | id: string; |
| 19 | name: string; |
| 20 | description: string; |
| 21 | /** Available, Soon, or what else a listing says about itself. */ |
| 22 | status: "available" | "soon" | "built-in"; |
| 23 | /** A group to list it under. */ |
| 24 | group: string; |
| 25 | /** The site page that sets it up, for this workspace. */ |
| 26 | sitePath: string; |
| 27 | }; |
| 28 | |
| 29 | export function customizeItems(section: CustomizeSection, workspace: string): CustomizeItem[] { |
| 30 | const fallback = customizePath(section, workspace); |
| 31 | if (section === "skills") { |
| 32 | return FOUNDATIONAL_SKILLS.map((skill) => ({ |
| 33 | id: skill.id, |
| 34 | name: skill.name, |
| 35 | description: skill.description, |
| 36 | status: "built-in" as const, |
| 37 | group: "In every agent", |
| 38 | sitePath: fallback, |
| 39 | })); |
| 40 | } |
| 41 | if (section === "connectors") { |
| 42 | return connectorsFor("workspace").map((connector) => ({ |
| 43 | id: connector.id, |
| 44 | name: connector.name, |
| 45 | description: connector.description, |
| 46 | status: connector.status, |
| 47 | group: connector.status === "available" ? "Connect now" : "Coming", |
| 48 | sitePath: connector.href ? connectorPath(connector.href, workspace) : `${fallback}?view=discover&directory=${encodeURIComponent(connector.id)}`, |
| 49 | })); |
| 50 | } |
| 51 | return FIRST_PARTY_EXTENSIONS.map((extension) => ({ |
| 52 | id: extension.id, |
| 53 | name: extension.name, |
| 54 | description: extension.tagline, |
| 55 | status: extension.status, |
| 56 | group: `${extension.publisher.name} · ${extension.category}`, |
| 57 | sitePath: customizePath("plugins", workspace, encodeURIComponent(pluginRef(extension.id, "g1t"))), |
| 58 | })); |
| 59 | } |
| 60 | |
| 61 | export { CUSTOMIZE, customizePath, type CustomizeSection }; |