codex-marketplace 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +25 -0
  2. package/dist/banner.d.ts +4 -0
  3. package/dist/banner.d.ts.map +1 -0
  4. package/dist/banner.js +20 -0
  5. package/dist/banner.js.map +1 -0
  6. package/dist/config.d.ts +2 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +83 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/filesystem.d.ts +2 -0
  11. package/dist/filesystem.d.ts.map +1 -0
  12. package/dist/filesystem.js +45 -0
  13. package/dist/filesystem.js.map +1 -0
  14. package/dist/git.d.ts +3 -0
  15. package/dist/git.d.ts.map +1 -0
  16. package/dist/git.js +48 -0
  17. package/dist/git.js.map +1 -0
  18. package/dist/github.d.ts +3 -0
  19. package/dist/github.d.ts.map +1 -0
  20. package/dist/github.js +29 -0
  21. package/dist/github.js.map +1 -0
  22. package/dist/index.d.ts +3 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +124 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/install.d.ts +16 -0
  27. package/dist/install.d.ts.map +1 -0
  28. package/dist/install.js +77 -0
  29. package/dist/install.js.map +1 -0
  30. package/dist/manifest.d.ts +4 -0
  31. package/dist/manifest.d.ts.map +1 -0
  32. package/dist/manifest.js +146 -0
  33. package/dist/manifest.js.map +1 -0
  34. package/dist/marketplace.d.ts +6 -0
  35. package/dist/marketplace.d.ts.map +1 -0
  36. package/dist/marketplace.js +100 -0
  37. package/dist/marketplace.js.map +1 -0
  38. package/dist/repository.d.ts +3 -0
  39. package/dist/repository.d.ts.map +1 -0
  40. package/dist/repository.js +44 -0
  41. package/dist/repository.js.map +1 -0
  42. package/dist/schema.d.ts +360 -0
  43. package/dist/schema.d.ts.map +1 -0
  44. package/dist/schema.js +59 -0
  45. package/dist/schema.js.map +1 -0
  46. package/dist/types.d.ts +117 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +2 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/utils.d.ts +7 -0
  51. package/dist/utils.d.ts.map +1 -0
  52. package/dist/utils.js +32 -0
  53. package/dist/utils.js.map +1 -0
  54. package/package.json +38 -0
@@ -0,0 +1,146 @@
1
+ import path from "node:path";
2
+ import { readFile, stat } from "node:fs/promises";
3
+ import { marketplaceConfigSchema, pluginManifestSchema } from "./schema.js";
4
+ import { isSubpath } from "./utils.js";
5
+ const ALLOWED_CATEGORIES = new Set([
6
+ "Coding",
7
+ "Development",
8
+ "Design",
9
+ "Productivity",
10
+ "Communication",
11
+ "DevOps",
12
+ "Data",
13
+ "Finance",
14
+ "Writing",
15
+ "AI & Agents",
16
+ "Utilities",
17
+ ]);
18
+ async function fileExists(targetPath) {
19
+ try {
20
+ await stat(targetPath);
21
+ return true;
22
+ }
23
+ catch {
24
+ return false;
25
+ }
26
+ }
27
+ export async function loadPluginManifest(pluginRoot) {
28
+ const manifestPath = path.join(pluginRoot, ".codex-plugin", "plugin.json");
29
+ if (!(await fileExists(manifestPath))) {
30
+ throw new Error(`Missing plugin manifest at ${manifestPath}`);
31
+ }
32
+ let raw;
33
+ try {
34
+ raw = JSON.parse(await readFile(manifestPath, "utf8"));
35
+ }
36
+ catch (error) {
37
+ throw new Error(`Failed to parse plugin manifest at ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`);
38
+ }
39
+ return pluginManifestSchema.parse(raw);
40
+ }
41
+ function normalizeCategory(category) {
42
+ if (!category)
43
+ return undefined;
44
+ if (ALLOWED_CATEGORIES.has(category)) {
45
+ return category;
46
+ }
47
+ return undefined;
48
+ }
49
+ function inferCategory(manifest) {
50
+ const direct = normalizeCategory(manifest.interface?.category);
51
+ if (direct) {
52
+ return direct;
53
+ }
54
+ const keywords = [
55
+ manifest.name,
56
+ manifest.description,
57
+ ...(manifest.keywords ?? []),
58
+ ]
59
+ .join(" ")
60
+ .toLowerCase();
61
+ if (/(figma|design|canva)/.test(keywords))
62
+ return "Design";
63
+ if (/(github|git|review|lint|test|deploy|vercel|cloudflare|ios|android|web)/.test(keywords)) {
64
+ return "Coding";
65
+ }
66
+ if (/(linear|notion|calendar|drive|teams|slack|gmail|outlook|sharepoint|box)/.test(keywords)) {
67
+ return "Productivity";
68
+ }
69
+ if (/(data|analytics|model|hugging|dataset)/.test(keywords))
70
+ return "Data";
71
+ if (/(agent|ai|workflow|orchestr)/.test(keywords))
72
+ return "AI & Agents";
73
+ return "Utilities";
74
+ }
75
+ function defaultPolicy() {
76
+ return {
77
+ installation: "AVAILABLE",
78
+ authentication: "ON_INSTALL",
79
+ };
80
+ }
81
+ async function loadMarketplaceConfig(checkoutRoot) {
82
+ const marketplacePath = path.join(checkoutRoot, ".agents", "plugins", "marketplace.json");
83
+ if (!(await fileExists(marketplacePath))) {
84
+ return null;
85
+ }
86
+ let raw;
87
+ try {
88
+ raw = JSON.parse(await readFile(marketplacePath, "utf8"));
89
+ }
90
+ catch (error) {
91
+ throw new Error(`Failed to parse marketplace file at ${marketplacePath}: ${error instanceof Error ? error.message : String(error)}`);
92
+ }
93
+ return marketplaceConfigSchema.parse(raw);
94
+ }
95
+ function resolveMarketplacePluginPath(checkoutRoot, relativePath) {
96
+ const resolved = path.resolve(checkoutRoot, relativePath);
97
+ if (!isSubpath(checkoutRoot, resolved)) {
98
+ throw new Error(`Marketplace entry points outside the repository: ${relativePath}`);
99
+ }
100
+ return resolved;
101
+ }
102
+ export async function discoverPluginSources(checkoutRoot, pluginName) {
103
+ const marketplace = await loadMarketplaceConfig(checkoutRoot);
104
+ if (marketplace) {
105
+ const pluginEntries = pluginName
106
+ ? marketplace.plugins.filter((plugin) => plugin.name === pluginName)
107
+ : marketplace.plugins;
108
+ if (pluginName && pluginEntries.length === 0) {
109
+ throw new Error(`Marketplace repository does not expose a plugin named ${pluginName}.`);
110
+ }
111
+ const discovered = [];
112
+ for (const plugin of pluginEntries) {
113
+ if (plugin.source.source !== "local") {
114
+ throw new Error(`Unsupported marketplace source for ${plugin.name}. Only local sources are supported.`);
115
+ }
116
+ const sourcePath = resolveMarketplacePluginPath(checkoutRoot, plugin.source.path);
117
+ const manifest = await loadPluginManifest(sourcePath);
118
+ if (manifest.name !== plugin.name) {
119
+ throw new Error(`Marketplace entry ${plugin.name} points to a plugin manifest named ${manifest.name}.`);
120
+ }
121
+ discovered.push({
122
+ manifest,
123
+ sourcePath,
124
+ category: normalizeCategory(plugin.category) ?? inferCategory(manifest),
125
+ policy: plugin.policy ?? defaultPolicy(),
126
+ });
127
+ }
128
+ if (discovered.length === 0) {
129
+ throw new Error("Marketplace repository does not contain any installable plugins.");
130
+ }
131
+ return discovered;
132
+ }
133
+ const manifest = await loadPluginManifest(checkoutRoot);
134
+ if (pluginName && manifest.name !== pluginName) {
135
+ throw new Error(`Repository root plugin is named ${manifest.name}, not ${pluginName}.`);
136
+ }
137
+ return [
138
+ {
139
+ manifest,
140
+ sourcePath: checkoutRoot,
141
+ category: inferCategory(manifest),
142
+ policy: defaultPolicy(),
143
+ },
144
+ ];
145
+ }
146
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { InstallScope, MarketplaceConfig, MarketplacePlugin, MutableMarketplace, ScopeLayout } from "./types.js";
2
+ export declare function resolveScopeLayout(scope: InstallScope, cwd: string, homeDir: string): ScopeLayout;
3
+ export declare function loadMarketplace(layout: ScopeLayout): Promise<MutableMarketplace>;
4
+ export declare function upsertMarketplacePlugin(config: MarketplaceConfig, pluginName: string, sourcePath: string, marketplaceRoot: string, category?: string, policy?: MarketplacePlugin["policy"]): MarketplaceConfig;
5
+ export declare function writeMarketplace(layout: ScopeLayout, config: MarketplaceConfig): Promise<void>;
6
+ //# sourceMappingURL=marketplace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplace.d.ts","sourceRoot":"","sources":["../src/marketplace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAqBjH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAsBjG;AAYD,wBAAsB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyBtF;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,EACvB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,GACnC,iBAAiB,CAuBnB;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpG"}
@@ -0,0 +1,100 @@
1
+ import path from "node:path";
2
+ import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
3
+ import { marketplaceConfigSchema } from "./schema.js";
4
+ import { relativePathForMarketplace, sanitizeSegment, stableHash } from "./utils.js";
5
+ async function fileExists(targetPath) {
6
+ try {
7
+ await stat(targetPath);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ function validateMarketplaceName(name) {
15
+ if (!/^[A-Za-z0-9_-]+$/.test(name)) {
16
+ throw new Error(`Marketplace name \`${name}\` is invalid. Only ASCII letters, digits, \`_\`, and \`-\` are allowed.`);
17
+ }
18
+ return name;
19
+ }
20
+ export function resolveScopeLayout(scope, cwd, homeDir) {
21
+ if (scope === "global") {
22
+ return {
23
+ scope,
24
+ marketplaceRoot: homeDir,
25
+ marketplacePath: path.join(homeDir, ".agents", "plugins", "marketplace.json"),
26
+ pluginSourceRoot: path.join(homeDir, ".codex", "plugins"),
27
+ defaultMarketplaceName: "codex-marketplace-global",
28
+ defaultMarketplaceDisplayName: "Codex Plugins (Global)",
29
+ };
30
+ }
31
+ const projectName = sanitizeSegment(path.basename(cwd), "project");
32
+ const projectHash = stableHash(path.resolve(cwd));
33
+ return {
34
+ scope,
35
+ marketplaceRoot: cwd,
36
+ marketplacePath: path.join(cwd, ".agents", "plugins", "marketplace.json"),
37
+ pluginSourceRoot: path.join(cwd, "plugins"),
38
+ defaultMarketplaceName: `codex-marketplace-${projectName}-${projectHash}`,
39
+ defaultMarketplaceDisplayName: `Codex Plugins (${path.basename(cwd) || "Project"})`,
40
+ };
41
+ }
42
+ function createDefaultMarketplace(layout) {
43
+ return {
44
+ name: layout.defaultMarketplaceName,
45
+ interface: {
46
+ displayName: layout.defaultMarketplaceDisplayName,
47
+ },
48
+ plugins: [],
49
+ };
50
+ }
51
+ export async function loadMarketplace(layout) {
52
+ if (!(await fileExists(layout.marketplacePath))) {
53
+ return {
54
+ config: createDefaultMarketplace(layout),
55
+ existed: false,
56
+ };
57
+ }
58
+ let raw;
59
+ try {
60
+ raw = JSON.parse(await readFile(layout.marketplacePath, "utf8"));
61
+ }
62
+ catch (error) {
63
+ throw new Error(`Failed to parse marketplace file at ${layout.marketplacePath}: ${error instanceof Error ? error.message : String(error)}`);
64
+ }
65
+ const config = marketplaceConfigSchema.parse(raw);
66
+ validateMarketplaceName(config.name);
67
+ return {
68
+ config,
69
+ existed: true,
70
+ };
71
+ }
72
+ export function upsertMarketplacePlugin(config, pluginName, sourcePath, marketplaceRoot, category, policy) {
73
+ const entry = {
74
+ name: pluginName,
75
+ source: {
76
+ source: "local",
77
+ path: relativePathForMarketplace(marketplaceRoot, sourcePath),
78
+ },
79
+ policy,
80
+ category,
81
+ };
82
+ const existingIndex = config.plugins.findIndex((plugin) => plugin.name === pluginName);
83
+ const plugins = [...config.plugins];
84
+ if (existingIndex >= 0) {
85
+ plugins.splice(existingIndex, 1, entry);
86
+ }
87
+ else {
88
+ plugins.push(entry);
89
+ }
90
+ return {
91
+ ...config,
92
+ plugins,
93
+ };
94
+ }
95
+ export async function writeMarketplace(layout, config) {
96
+ validateMarketplaceName(config.name);
97
+ await mkdir(path.dirname(layout.marketplacePath), { recursive: true });
98
+ await writeFile(layout.marketplacePath, JSON.stringify(config, null, 2) + "\n", "utf8");
99
+ }
100
+ //# sourceMappingURL=marketplace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplace.js","sourceRoot":"","sources":["../src/marketplace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { GitHubRepoSpec } from "./types.js";
2
+ export declare function parseRepositoryInput(input: string): GitHubRepoSpec;
3
+ //# sourceMappingURL=repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5C,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CA8ClE"}
@@ -0,0 +1,44 @@
1
+ const REPO_PATTERN = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
2
+ export function parseRepositoryInput(input) {
3
+ const trimmed = input.trim();
4
+ if (!trimmed) {
5
+ throw new Error("Repository is required. Use `owner/repo` or a GitHub repository URL.");
6
+ }
7
+ if (REPO_PATTERN.test(trimmed)) {
8
+ const [owner, repo] = trimmed.split("/");
9
+ return {
10
+ owner,
11
+ repo,
12
+ fullName: `${owner}/${repo}`,
13
+ url: `https://github.com/${owner}/${repo}`,
14
+ };
15
+ }
16
+ try {
17
+ const url = new URL(trimmed);
18
+ if (url.hostname !== "github.com") {
19
+ throw new Error("Only github.com repositories are supported.");
20
+ }
21
+ const parts = url.pathname.replace(/\/+$/, "").split("/").filter(Boolean);
22
+ if (parts.length !== 2) {
23
+ throw new Error("GitHub repository URLs must look like https://github.com/owner/repo.");
24
+ }
25
+ const [owner, rawRepo] = parts;
26
+ const repo = rawRepo.endsWith(".git") ? rawRepo.slice(0, -4) : rawRepo;
27
+ if (!REPO_PATTERN.test(`${owner}/${repo}`)) {
28
+ throw new Error("Repository must look like `owner/repo`.");
29
+ }
30
+ return {
31
+ owner,
32
+ repo,
33
+ fullName: `${owner}/${repo}`,
34
+ url: `https://github.com/${owner}/${repo}`,
35
+ };
36
+ }
37
+ catch (error) {
38
+ if (error instanceof TypeError) {
39
+ throw new Error("Repository must look like `owner/repo` or a GitHub URL.");
40
+ }
41
+ throw error;
42
+ }
43
+ }
44
+ //# sourceMappingURL=repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAG,oCAAoC,CAAC;AAE1D,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAC1F,CAAC;IAED,IAAI,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,OAAO;YACL,KAAK;YACL,IAAI;YACJ,QAAQ,EAAE,GAAG,KAAK,IAAI,IAAI,EAAE;YAC5B,GAAG,EAAE,sBAAsB,KAAK,IAAI,IAAI,EAAE;SAC3C,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAC7B,IAAI,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAC1F,CAAC;QAED,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QACvE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO;YACL,KAAK;YACL,IAAI;YACJ,QAAQ,EAAE,GAAG,KAAK,IAAI,IAAI,EAAE;YAC5B,GAAG,EAAE,sBAAsB,KAAK,IAAI,IAAI,EAAE;SAC3C,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}