@takazudo/zudo-doc 5.7.0 → 5.9.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.
- package/CHANGELOG.md +35 -0
- package/README.md +17 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.js +1 -0
- package/dist/eject/index.js +9 -0
- package/dist/i18n-defaults/index.js +3 -0
- package/dist/plugins/codex-resources.d.ts +4 -0
- package/dist/plugins/codex-resources.js +31 -0
- package/dist/plugins/internal/claude-resources/generate.js +20 -291
- package/dist/plugins/internal/codex-resources/agents-md.d.ts +6 -0
- package/dist/plugins/internal/codex-resources/agents-md.js +70 -0
- package/dist/plugins/internal/codex-resources/agents.d.ts +7 -0
- package/dist/plugins/internal/codex-resources/agents.js +104 -0
- package/dist/plugins/internal/codex-resources/config.d.ts +6 -0
- package/dist/plugins/internal/codex-resources/config.js +111 -0
- package/dist/plugins/internal/codex-resources/generate.d.ts +20 -0
- package/dist/plugins/internal/codex-resources/generate.js +34 -0
- package/dist/plugins/internal/codex-resources/hooks.d.ts +6 -0
- package/dist/plugins/internal/codex-resources/hooks.js +174 -0
- package/dist/plugins/internal/codex-resources/index.d.ts +24 -0
- package/dist/plugins/internal/codex-resources/index.js +21 -0
- package/dist/plugins/internal/codex-resources/overview.d.ts +10 -0
- package/dist/plugins/internal/codex-resources/overview.js +33 -0
- package/dist/plugins/internal/codex-resources/rules.d.ts +6 -0
- package/dist/plugins/internal/codex-resources/rules.js +255 -0
- package/dist/plugins/internal/codex-resources/skills.d.ts +2 -0
- package/dist/plugins/internal/codex-resources/skills.js +84 -0
- package/dist/plugins/internal/codex-resources/utils.d.ts +14 -0
- package/dist/plugins/internal/codex-resources/utils.js +80 -0
- package/dist/plugins/internal/resource-docs-shared/fs.d.ts +3 -0
- package/dist/plugins/internal/resource-docs-shared/fs.js +19 -0
- package/dist/plugins/internal/resource-docs-shared/index.d.ts +7 -0
- package/dist/plugins/internal/resource-docs-shared/index.js +44 -0
- package/dist/plugins/internal/resource-docs-shared/links.d.ts +22 -0
- package/dist/plugins/internal/resource-docs-shared/links.js +44 -0
- package/dist/plugins/internal/resource-docs-shared/markdown-structure.d.ts +9 -0
- package/dist/plugins/internal/resource-docs-shared/markdown-structure.js +22 -0
- package/dist/plugins/internal/resource-docs-shared/mdx.d.ts +23 -0
- package/dist/plugins/internal/resource-docs-shared/mdx.js +63 -0
- package/dist/plugins/internal/resource-docs-shared/skills.d.ts +37 -0
- package/dist/plugins/internal/resource-docs-shared/skills.js +318 -0
- package/dist/plugins/internal/resource-docs-shared/walk.d.ts +20 -0
- package/dist/plugins/internal/resource-docs-shared/walk.js +41 -0
- package/dist/preset.d.ts +8 -0
- package/dist/preset.js +11 -0
- package/dist/safelist.css +1 -1
- package/dist/settings.d.ts +5 -0
- package/dist/transitions/nested-island-props-refresh.js +9 -3
- package/eject/header/gen-nav-overflow-script.mjs +771 -0
- package/eject/header/header.tsx +2 -0
- package/eject/header/nav-overflow-script.ts +11 -8
- package/package.json +9 -4
- /package/dist/plugins/internal/{claude-resources → resource-docs-shared}/escape-for-mdx.d.ts +0 -0
- /package/dist/plugins/internal/{claude-resources → resource-docs-shared}/escape-for-mdx.js +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { parse } from "smol-toml";
|
|
4
|
+
import {
|
|
5
|
+
formatFrontmatterString,
|
|
6
|
+
cleanDir,
|
|
7
|
+
ensureDir,
|
|
8
|
+
escapeForMdx,
|
|
9
|
+
escapeMarkdownTableCell,
|
|
10
|
+
renderCodeFence,
|
|
11
|
+
writeCategoryIndex
|
|
12
|
+
} from "../resource-docs-shared/index.js";
|
|
13
|
+
import {
|
|
14
|
+
assertUniqueSlug,
|
|
15
|
+
filenameSlug,
|
|
16
|
+
isRecord,
|
|
17
|
+
warn,
|
|
18
|
+
writeGeneratedPage
|
|
19
|
+
} from "./utils.js";
|
|
20
|
+
function optionalString(record, field, filePath) {
|
|
21
|
+
const value = record[field];
|
|
22
|
+
if (value === void 0) return void 0;
|
|
23
|
+
if (typeof value === "string") return value;
|
|
24
|
+
warn(filePath, `${field} must be a string; omitting it`);
|
|
25
|
+
return void 0;
|
|
26
|
+
}
|
|
27
|
+
function generateAgentsCategory(config) {
|
|
28
|
+
const agentsDir = path.join(config.codexDir, "agents");
|
|
29
|
+
const outputDir = path.join(config.docsDir, "codex-agents");
|
|
30
|
+
cleanDir(outputDir);
|
|
31
|
+
if (!fs.existsSync(agentsDir)) return [];
|
|
32
|
+
let files;
|
|
33
|
+
try {
|
|
34
|
+
files = fs.readdirSync(agentsDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".toml")).map((entry) => entry.name).sort();
|
|
35
|
+
} catch (error) {
|
|
36
|
+
warn(agentsDir, `unable to read agents directory: ${String(error)}`);
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
if (files.length === 0) return [];
|
|
40
|
+
ensureDir(outputDir);
|
|
41
|
+
const items = [];
|
|
42
|
+
const emitted = /* @__PURE__ */ new Map();
|
|
43
|
+
for (const filename of files) {
|
|
44
|
+
const filePath = path.join(agentsDir, filename);
|
|
45
|
+
let source;
|
|
46
|
+
let parsed;
|
|
47
|
+
try {
|
|
48
|
+
source = fs.readFileSync(filePath, "utf8");
|
|
49
|
+
parsed = parse(source);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
warn(filePath, `unable to parse TOML, skipping file: ${String(error)}`);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (!isRecord(parsed)) {
|
|
55
|
+
warn(filePath, "parsed TOML root was not an object, skipping file");
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const slug = filenameSlug(filename.replace(/\.toml$/, ""));
|
|
59
|
+
assertUniqueSlug("agent", slug, filename, emitted);
|
|
60
|
+
const name = optionalString(parsed, "name", filePath) ?? slug;
|
|
61
|
+
const description = optionalString(parsed, "description", filePath) ?? "";
|
|
62
|
+
const model = optionalString(parsed, "model", filePath);
|
|
63
|
+
const reasoning = optionalString(parsed, "model_reasoning_effort", filePath);
|
|
64
|
+
const sandbox = optionalString(parsed, "sandbox_mode", filePath);
|
|
65
|
+
const instructions = optionalString(parsed, "developer_instructions", filePath);
|
|
66
|
+
const badges = [
|
|
67
|
+
model ? `**Model:** ${escapeMarkdownTableCell(model)}` : "",
|
|
68
|
+
reasoning ? `**Reasoning effort:** ${escapeMarkdownTableCell(reasoning)}` : "",
|
|
69
|
+
sandbox ? `**Sandbox:** ${escapeMarkdownTableCell(sandbox)}` : ""
|
|
70
|
+
].filter(Boolean);
|
|
71
|
+
const sections = [badges.join("\n")];
|
|
72
|
+
if (instructions !== void 0) {
|
|
73
|
+
sections.push(
|
|
74
|
+
`## Developer instructions
|
|
75
|
+
|
|
76
|
+
${escapeForMdx(instructions.trim())}`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
sections.push(`## Source
|
|
80
|
+
|
|
81
|
+
${renderCodeFence(source, "toml")}`);
|
|
82
|
+
writeGeneratedPage({
|
|
83
|
+
outputPath: path.join(outputDir, `${slug}.mdx`),
|
|
84
|
+
title: name,
|
|
85
|
+
description,
|
|
86
|
+
sidebarLabel: name,
|
|
87
|
+
body: sections.filter(Boolean).join("\n\n")
|
|
88
|
+
});
|
|
89
|
+
items.push({ filename, slug, name });
|
|
90
|
+
}
|
|
91
|
+
if (items.length > 0) {
|
|
92
|
+
writeCategoryIndex(
|
|
93
|
+
outputDir,
|
|
94
|
+
"Agents",
|
|
95
|
+
907,
|
|
96
|
+
"Custom subagents",
|
|
97
|
+
formatFrontmatterString
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return items;
|
|
101
|
+
}
|
|
102
|
+
export {
|
|
103
|
+
generateAgentsCategory
|
|
104
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { parse, TomlDate } from "smol-toml";
|
|
4
|
+
import {
|
|
5
|
+
formatFrontmatterString,
|
|
6
|
+
cleanDir,
|
|
7
|
+
ensureDir,
|
|
8
|
+
escapeMarkdownTableCell,
|
|
9
|
+
renderCodeFence,
|
|
10
|
+
writeCategoryIndex
|
|
11
|
+
} from "../resource-docs-shared/index.js";
|
|
12
|
+
import {
|
|
13
|
+
assertUniqueSlug,
|
|
14
|
+
filenameSlug,
|
|
15
|
+
isRecord,
|
|
16
|
+
renderTableRow,
|
|
17
|
+
warn,
|
|
18
|
+
writeGeneratedPage
|
|
19
|
+
} from "./utils.js";
|
|
20
|
+
function configFiles(codexDir) {
|
|
21
|
+
try {
|
|
22
|
+
return fs.readdirSync(codexDir, { withFileTypes: true }).filter(
|
|
23
|
+
(entry) => entry.isFile() && (entry.name === "config.toml" || entry.name === "config.toml.example" || entry.name.endsWith(".config.toml"))
|
|
24
|
+
).map((entry) => entry.name).sort((a, b) => {
|
|
25
|
+
if (a === "config.toml") return -1;
|
|
26
|
+
if (b === "config.toml") return 1;
|
|
27
|
+
return a.localeCompare(b);
|
|
28
|
+
});
|
|
29
|
+
} catch (error) {
|
|
30
|
+
warn(codexDir, `unable to read config files: ${String(error)}`);
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function renderValue(value) {
|
|
35
|
+
if (typeof value === "string") return value;
|
|
36
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
37
|
+
return String(value);
|
|
38
|
+
}
|
|
39
|
+
if (Array.isArray(value)) return JSON.stringify(value);
|
|
40
|
+
if (value instanceof TomlDate) return value.toISOString();
|
|
41
|
+
return String(value);
|
|
42
|
+
}
|
|
43
|
+
function generateConfigCategory(config) {
|
|
44
|
+
const outputDir = path.join(config.docsDir, "codex-config");
|
|
45
|
+
cleanDir(outputDir);
|
|
46
|
+
if (!fs.existsSync(config.codexDir)) return [];
|
|
47
|
+
const files = configFiles(config.codexDir);
|
|
48
|
+
if (files.length === 0) return [];
|
|
49
|
+
ensureDir(outputDir);
|
|
50
|
+
const items = [];
|
|
51
|
+
const emitted = /* @__PURE__ */ new Map();
|
|
52
|
+
for (const filename of files) {
|
|
53
|
+
const filePath = path.join(config.codexDir, filename);
|
|
54
|
+
let source;
|
|
55
|
+
let parsed;
|
|
56
|
+
try {
|
|
57
|
+
source = fs.readFileSync(filePath, "utf8");
|
|
58
|
+
parsed = parse(source);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
warn(filePath, `unable to parse TOML, skipping file: ${String(error)}`);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (!isRecord(parsed)) {
|
|
64
|
+
warn(filePath, "parsed TOML root was not an object, skipping file");
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const slug = filenameSlug(filename);
|
|
68
|
+
assertUniqueSlug("config", slug, filename, emitted);
|
|
69
|
+
const settings = Object.entries(parsed).filter(([, value]) => !isRecord(value) || value instanceof TomlDate).map(([key, value]) => renderTableRow([key, renderValue(value)]));
|
|
70
|
+
const sections = source.match(/^\s*\[\[?[^\]]+\]\]?/gm) ?? [];
|
|
71
|
+
const sectionList = sections.length === 0 ? "\u2014" : sections.map(
|
|
72
|
+
(section) => `- ${escapeMarkdownTableCell(section.trim())}`
|
|
73
|
+
).join("\n");
|
|
74
|
+
const body = [
|
|
75
|
+
"## Settings",
|
|
76
|
+
"",
|
|
77
|
+
"| Key | Value |",
|
|
78
|
+
"| --- | --- |",
|
|
79
|
+
...settings.length > 0 ? settings : [renderTableRow([void 0, void 0])],
|
|
80
|
+
"",
|
|
81
|
+
"## Sections",
|
|
82
|
+
"",
|
|
83
|
+
sectionList,
|
|
84
|
+
"",
|
|
85
|
+
"## Source",
|
|
86
|
+
"",
|
|
87
|
+
renderCodeFence(source, "toml")
|
|
88
|
+
].join("\n");
|
|
89
|
+
writeGeneratedPage({
|
|
90
|
+
outputPath: path.join(outputDir, `${slug}.mdx`),
|
|
91
|
+
title: filename,
|
|
92
|
+
description: `Codex configuration from ${filename}`,
|
|
93
|
+
sidebarLabel: filename,
|
|
94
|
+
body
|
|
95
|
+
});
|
|
96
|
+
items.push({ filename, slug });
|
|
97
|
+
}
|
|
98
|
+
if (items.length > 0) {
|
|
99
|
+
writeCategoryIndex(
|
|
100
|
+
outputDir,
|
|
101
|
+
"Config",
|
|
102
|
+
906,
|
|
103
|
+
"config.toml and profiles",
|
|
104
|
+
formatFrontmatterString
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return items;
|
|
108
|
+
}
|
|
109
|
+
export {
|
|
110
|
+
generateConfigCategory
|
|
111
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface CodexResourcesConfig {
|
|
2
|
+
codexDir: string;
|
|
3
|
+
/** The doc site's own root and the default value of `scanRoot`. */
|
|
4
|
+
projectRoot?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Repo-wide discovery root for both the AGENTS.md walk and the repo-level
|
|
7
|
+
* `.agents/skills/` root. Also serves as the relative-path base for the
|
|
8
|
+
* generated AGENTS.md titles and slugs. Defaults to `projectRoot`.
|
|
9
|
+
*/
|
|
10
|
+
scanRoot?: string;
|
|
11
|
+
docsDir: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function generateCodexResourcesDocs(config: CodexResourcesConfig): {
|
|
14
|
+
agentsMd: number;
|
|
15
|
+
config: number;
|
|
16
|
+
agents: number;
|
|
17
|
+
hooks: number;
|
|
18
|
+
rules: number;
|
|
19
|
+
skills: number;
|
|
20
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { generateAgentsMdCategory } from "./agents-md.js";
|
|
2
|
+
import { generateAgentsCategory } from "./agents.js";
|
|
3
|
+
import { generateConfigCategory } from "./config.js";
|
|
4
|
+
import { generateHooksCategory } from "./hooks.js";
|
|
5
|
+
import { generateOverview } from "./overview.js";
|
|
6
|
+
import { generateRulesCategory } from "./rules.js";
|
|
7
|
+
import { generateSkillsCategoryDocs } from "./skills.js";
|
|
8
|
+
function generateCodexResourcesDocs(config) {
|
|
9
|
+
const agentsMd = generateAgentsMdCategory(config);
|
|
10
|
+
const configItems = generateConfigCategory(config);
|
|
11
|
+
const agents = generateAgentsCategory(config);
|
|
12
|
+
const hooks = generateHooksCategory(config);
|
|
13
|
+
const rules = generateRulesCategory(config);
|
|
14
|
+
const skills = generateSkillsCategoryDocs(config);
|
|
15
|
+
generateOverview(config, {
|
|
16
|
+
agentsMd: agentsMd.length > 0,
|
|
17
|
+
config: configItems.length > 0,
|
|
18
|
+
agents: agents.length > 0,
|
|
19
|
+
hooks: hooks.length > 0,
|
|
20
|
+
rules: rules.length > 0,
|
|
21
|
+
skills: skills.length > 0
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
agentsMd: agentsMd.length,
|
|
25
|
+
config: configItems.length,
|
|
26
|
+
agents: agents.length,
|
|
27
|
+
hooks: hooks.length,
|
|
28
|
+
rules: rules.length,
|
|
29
|
+
skills: skills.length
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
generateCodexResourcesDocs
|
|
34
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
formatFrontmatterString,
|
|
5
|
+
cleanDir,
|
|
6
|
+
ensureDir,
|
|
7
|
+
getScriptDescription,
|
|
8
|
+
renderCodeFence,
|
|
9
|
+
writeCategoryIndex
|
|
10
|
+
} from "../resource-docs-shared/index.js";
|
|
11
|
+
import {
|
|
12
|
+
assertUniqueSlug,
|
|
13
|
+
filenameSlug,
|
|
14
|
+
isRecord,
|
|
15
|
+
languageForFilename,
|
|
16
|
+
renderTableRow,
|
|
17
|
+
warn,
|
|
18
|
+
writeGeneratedPage
|
|
19
|
+
} from "./utils.js";
|
|
20
|
+
function readHookRows(filePath, source) {
|
|
21
|
+
let parsed;
|
|
22
|
+
try {
|
|
23
|
+
parsed = JSON.parse(source);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
warn(filePath, `unable to parse JSON, skipping hooks.json page: ${String(error)}`);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (!isRecord(parsed) || !isRecord(parsed.hooks)) {
|
|
29
|
+
warn(filePath, "hooks.hooks must be a non-null object; skipping hooks.json page");
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const rows = [];
|
|
33
|
+
for (const [event, groups] of Object.entries(parsed.hooks)) {
|
|
34
|
+
if (!Array.isArray(groups)) {
|
|
35
|
+
warn(filePath, `hooks.${event} must be an array; skipping event`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
for (const [groupIndex, group] of groups.entries()) {
|
|
39
|
+
if (!isRecord(group) || !Array.isArray(group.hooks)) {
|
|
40
|
+
warn(
|
|
41
|
+
filePath,
|
|
42
|
+
`hooks.${event}[${groupIndex}].hooks must be an array; skipping group`
|
|
43
|
+
);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
for (const [handlerIndex, handler] of group.hooks.entries()) {
|
|
47
|
+
if (!isRecord(handler) || typeof handler.command !== "string") {
|
|
48
|
+
warn(
|
|
49
|
+
filePath,
|
|
50
|
+
`hooks.${event}[${groupIndex}].hooks[${handlerIndex}] must be an object with a string command; skipping row`
|
|
51
|
+
);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
rows.push({
|
|
55
|
+
event,
|
|
56
|
+
matcher: group.matcher,
|
|
57
|
+
type: handler.type,
|
|
58
|
+
command: handler.command,
|
|
59
|
+
timeout: handler.timeout,
|
|
60
|
+
async: handler.async
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return rows;
|
|
66
|
+
}
|
|
67
|
+
function generateHooksJson(config, outputDir, emitted) {
|
|
68
|
+
const filePath = path.join(config.codexDir, "hooks.json");
|
|
69
|
+
if (!fs.existsSync(filePath)) return null;
|
|
70
|
+
let source;
|
|
71
|
+
try {
|
|
72
|
+
source = fs.readFileSync(filePath, "utf8");
|
|
73
|
+
} catch (error) {
|
|
74
|
+
warn(filePath, `unable to read hooks.json, skipping page: ${String(error)}`);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const rows = readHookRows(filePath, source);
|
|
78
|
+
if (rows === null) return null;
|
|
79
|
+
const slug = "hooks-json";
|
|
80
|
+
assertUniqueSlug("hook", slug, "hooks.json", emitted);
|
|
81
|
+
const tableRows = rows.map((row) => renderTableRow([
|
|
82
|
+
row.event,
|
|
83
|
+
row.matcher,
|
|
84
|
+
row.type,
|
|
85
|
+
row.command,
|
|
86
|
+
row.timeout,
|
|
87
|
+
row.async
|
|
88
|
+
]));
|
|
89
|
+
const body = [
|
|
90
|
+
"| Event | Matcher | Type | Command | Timeout | Async |",
|
|
91
|
+
"| --- | --- | --- | --- | --- | --- |",
|
|
92
|
+
...tableRows.length > 0 ? tableRows : [renderTableRow(Array.from({ length: 6 }))],
|
|
93
|
+
"",
|
|
94
|
+
"## Source",
|
|
95
|
+
"",
|
|
96
|
+
renderCodeFence(source, "json")
|
|
97
|
+
].join("\n");
|
|
98
|
+
writeGeneratedPage({
|
|
99
|
+
outputPath: path.join(outputDir, `${slug}.mdx`),
|
|
100
|
+
title: "hooks.json",
|
|
101
|
+
description: "Codex lifecycle hook configuration",
|
|
102
|
+
sidebarLabel: "hooks.json",
|
|
103
|
+
body
|
|
104
|
+
});
|
|
105
|
+
return { filename: "hooks.json", slug };
|
|
106
|
+
}
|
|
107
|
+
function generateHookScripts(config, outputDir, emitted) {
|
|
108
|
+
const hooksDir = path.join(config.codexDir, "hooks");
|
|
109
|
+
if (!fs.existsSync(hooksDir)) return [];
|
|
110
|
+
let entries;
|
|
111
|
+
try {
|
|
112
|
+
entries = fs.readdirSync(hooksDir, { withFileTypes: true });
|
|
113
|
+
} catch (error) {
|
|
114
|
+
warn(hooksDir, `unable to read hooks directory: ${String(error)}`);
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
const items = [];
|
|
118
|
+
for (const entry of entries.filter((item) => item.isFile()).sort(
|
|
119
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
120
|
+
)) {
|
|
121
|
+
const filePath = path.join(hooksDir, entry.name);
|
|
122
|
+
const slug = filenameSlug(entry.name);
|
|
123
|
+
assertUniqueSlug("hook", slug, filePath, emitted);
|
|
124
|
+
let source;
|
|
125
|
+
try {
|
|
126
|
+
source = fs.readFileSync(filePath, "utf8");
|
|
127
|
+
} catch (error) {
|
|
128
|
+
warn(filePath, `unable to read hook script, skipping file: ${String(error)}`);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const scriptDescription = getScriptDescription(filePath).replace(/^ — /, "");
|
|
132
|
+
writeGeneratedPage({
|
|
133
|
+
outputPath: path.join(outputDir, `${slug}.mdx`),
|
|
134
|
+
title: entry.name,
|
|
135
|
+
description: scriptDescription,
|
|
136
|
+
sidebarLabel: entry.name,
|
|
137
|
+
body: `## Source
|
|
138
|
+
|
|
139
|
+
${renderCodeFence(
|
|
140
|
+
source,
|
|
141
|
+
languageForFilename(entry.name)
|
|
142
|
+
)}`
|
|
143
|
+
});
|
|
144
|
+
items.push({ filename: entry.name, slug });
|
|
145
|
+
}
|
|
146
|
+
return items;
|
|
147
|
+
}
|
|
148
|
+
function generateHooksCategory(config) {
|
|
149
|
+
const outputDir = path.join(config.docsDir, "codex-hooks");
|
|
150
|
+
cleanDir(outputDir);
|
|
151
|
+
const hasJson = fs.existsSync(path.join(config.codexDir, "hooks.json"));
|
|
152
|
+
const hasScripts = fs.existsSync(path.join(config.codexDir, "hooks"));
|
|
153
|
+
if (!hasJson && !hasScripts) return [];
|
|
154
|
+
ensureDir(outputDir);
|
|
155
|
+
const emitted = /* @__PURE__ */ new Map();
|
|
156
|
+
const jsonItem = generateHooksJson(config, outputDir, emitted);
|
|
157
|
+
const items = [
|
|
158
|
+
...jsonItem ? [jsonItem] : [],
|
|
159
|
+
...generateHookScripts(config, outputDir, emitted)
|
|
160
|
+
];
|
|
161
|
+
if (items.length > 0) {
|
|
162
|
+
writeCategoryIndex(
|
|
163
|
+
outputDir,
|
|
164
|
+
"Hooks",
|
|
165
|
+
908,
|
|
166
|
+
"Lifecycle hooks",
|
|
167
|
+
formatFrontmatterString
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return items;
|
|
171
|
+
}
|
|
172
|
+
export {
|
|
173
|
+
generateHooksCategory
|
|
174
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { generateCodexResourcesDocs, type CodexResourcesConfig } from "./generate.js";
|
|
2
|
+
export interface CodexResourcesPluginOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Path to the project's `.codex/` directory. Resolved against
|
|
5
|
+
* `projectRoot` when relative.
|
|
6
|
+
*/
|
|
7
|
+
codexDir: string;
|
|
8
|
+
/**
|
|
9
|
+
* Anchor for `codexDir`, `docsDir`, and relative `scanRoot` paths, and the
|
|
10
|
+
* default value of `scanRoot`. Defaults to `process.cwd()`.
|
|
11
|
+
*/
|
|
12
|
+
projectRoot?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Repo-wide discovery root, defaulting to `projectRoot`. It governs both the
|
|
15
|
+
* `AGENTS.md` / `AGENTS.override.md` walk (including relative titles/slugs)
|
|
16
|
+
* and the repo-level `.agents/skills/` root. `codexDir` and `docsDir` remain
|
|
17
|
+
* anchored to `projectRoot`.
|
|
18
|
+
*/
|
|
19
|
+
scanRoot?: string;
|
|
20
|
+
/** Output directory, anchored to `projectRoot` when relative. */
|
|
21
|
+
docsDir?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function runCodexResourcesPreStep(options: CodexResourcesPluginOptions): ReturnType<typeof generateCodexResourcesDocs>;
|
|
24
|
+
export { generateCodexResourcesDocs, type CodexResourcesConfig };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import {
|
|
3
|
+
generateCodexResourcesDocs
|
|
4
|
+
} from "./generate.js";
|
|
5
|
+
function runCodexResourcesPreStep(options) {
|
|
6
|
+
const projectRoot = path.resolve(options.projectRoot ?? process.cwd());
|
|
7
|
+
const codexDir = path.isAbsolute(options.codexDir) ? options.codexDir : path.resolve(projectRoot, options.codexDir);
|
|
8
|
+
const scanRoot = options.scanRoot === void 0 ? projectRoot : path.isAbsolute(options.scanRoot) ? options.scanRoot : path.resolve(projectRoot, options.scanRoot);
|
|
9
|
+
const docsDirInput = options.docsDir ?? "src/content/docs";
|
|
10
|
+
const docsDir = path.isAbsolute(docsDirInput) ? docsDirInput : path.resolve(projectRoot, docsDirInput);
|
|
11
|
+
return generateCodexResourcesDocs({
|
|
12
|
+
codexDir,
|
|
13
|
+
projectRoot,
|
|
14
|
+
scanRoot,
|
|
15
|
+
docsDir
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
generateCodexResourcesDocs,
|
|
20
|
+
runCodexResourcesPreStep
|
|
21
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CodexResourcesConfig } from "./generate.js";
|
|
2
|
+
export interface CodexCategoryPresence {
|
|
3
|
+
agentsMd: boolean;
|
|
4
|
+
config: boolean;
|
|
5
|
+
agents: boolean;
|
|
6
|
+
hooks: boolean;
|
|
7
|
+
rules: boolean;
|
|
8
|
+
skills: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function generateOverview(config: CodexResourcesConfig, presence: CodexCategoryPresence): void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { formatFrontmatterString } from "../resource-docs-shared/index.js";
|
|
4
|
+
import { cleanDir, ensureDir } from "../resource-docs-shared/index.js";
|
|
5
|
+
function generateOverview(config, presence) {
|
|
6
|
+
const outputDir = path.join(config.docsDir, "codex");
|
|
7
|
+
cleanDir(outputDir);
|
|
8
|
+
ensureDir(outputDir);
|
|
9
|
+
const slugs = [];
|
|
10
|
+
if (presence.agentsMd) slugs.push("codex-agents-md");
|
|
11
|
+
if (presence.config) slugs.push("codex-config");
|
|
12
|
+
if (presence.agents) slugs.push("codex-agents");
|
|
13
|
+
if (presence.hooks) slugs.push("codex-hooks");
|
|
14
|
+
if (presence.rules) slugs.push("codex-rules");
|
|
15
|
+
if (presence.skills) slugs.push("codex-skills");
|
|
16
|
+
fs.writeFileSync(
|
|
17
|
+
path.join(outputDir, "index.mdx"),
|
|
18
|
+
`---
|
|
19
|
+
title: ${formatFrontmatterString("Codex")}
|
|
20
|
+
description: ${formatFrontmatterString("OpenAI Codex configuration reference.")}
|
|
21
|
+
sidebar_position: 904
|
|
22
|
+
generated: true
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Resources
|
|
26
|
+
|
|
27
|
+
<CategoryNav categories={${JSON.stringify(slugs)}} />
|
|
28
|
+
`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
generateOverview
|
|
33
|
+
};
|