Skip to content
61 linesCodeBlameRaw
1import { pluginRef } from "@g1t/contracts/claude-plugin";
2import { connectorPath, connectorsFor } from "@g1t/contracts/connectors";
3import { CUSTOMIZE, type CustomizeSection, customizePath } from "@g1t/contracts/customize";
4import { FIRST_PARTY_EXTENSIONS } from "@g1t/contracts/marketplace";
5import { 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
17export 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
29export 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
61export { CUSTOMIZE, customizePath, type CustomizeSection };