@gitpagedocs/cli 1.1.62 → 1.1.63

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 (59) hide show
  1. package/README.md +193 -193
  2. package/ai/application/ai-command.ts +24 -24
  3. package/ai/application/ai-provider-factory.ts +22 -22
  4. package/ai/application/docs-pattern.ts +68 -68
  5. package/ai/application/run-ai-cli-command.ts +167 -167
  6. package/ai/config.ts +50 -50
  7. package/ai/core/models/ai-cli-config.ts +33 -33
  8. package/ai/core/models/parse-ai-cli-config.ts +78 -78
  9. package/ai/core/ports/illm-provider.ts +32 -32
  10. package/ai/infrastructure/ai-config-file.ts +101 -101
  11. package/ai/infrastructure/file-system-adapter.ts +85 -85
  12. package/ai/infrastructure/llm/tools-llm-provider.ts +54 -54
  13. package/ai/infrastructure/version-docs-writer.ts +143 -143
  14. package/ai/presentation/ai-prompts.ts +239 -239
  15. package/application/ports/cli-runtime-ports.ts +91 -91
  16. package/application/report/config-only-reporter.mjs +64 -64
  17. package/application/use-cases/dispatch-mode.ts +18 -18
  18. package/builders/config-orchestrator.mjs +34 -34
  19. package/builders/project-links.mjs +50 -50
  20. package/builders/root-config-builder.mjs +61 -61
  21. package/builders/route-builders.mjs +136 -136
  22. package/builders/theme-template.mjs +76 -76
  23. package/builders/version-config-builder.mjs +186 -186
  24. package/content/docs-en.mjs +549 -549
  25. package/content/docs-es.mjs +462 -462
  26. package/content/docs-pt.mjs +462 -462
  27. package/contracts/doc-versions.mjs +3 -3
  28. package/data/default-site-config.mjs +321 -321
  29. package/data/i18n-langmenu.mjs +347 -347
  30. package/data/layouts.mjs +436 -436
  31. package/data/path-mappings.mjs +26 -26
  32. package/data/route-metas.mjs +93 -93
  33. package/data/theme-colors.mjs +443 -443
  34. package/data/urls.mjs +12 -12
  35. package/domain/models/cli-options.ts +33 -33
  36. package/home/constants.mjs +4 -4
  37. package/index.mjs +37 -37
  38. package/infrastructure/gitpagedocs-config-file.ts +47 -47
  39. package/infrastructure/home/runtime.mjs +37 -37
  40. package/package.json +3 -3
  41. package/presentation/commands/ai-info.ts +57 -57
  42. package/presentation/commands/config-clear.ts +23 -23
  43. package/presentation/commands/config-info.ts +24 -24
  44. package/presentation/commands/diagnostics.ts +164 -164
  45. package/presentation/commands/docs.ts +37 -37
  46. package/presentation/commands/mcp.ts +20 -20
  47. package/presentation/commands/pages.ts +101 -101
  48. package/presentation/commands/password.ts +62 -62
  49. package/presentation/commands/run-command.ts +70 -70
  50. package/presentation/index.ts +124 -124
  51. package/presentation/options/parser.ts +119 -119
  52. package/presentation/options/resolver.ts +46 -46
  53. package/presentation/ui/clack.ts +91 -91
  54. package/presentation/ui/prompts.ts +146 -146
  55. package/runtime/git-ops.mjs +110 -110
  56. package/runtime/output.mjs +159 -159
  57. package/runtime/workflow.mjs +129 -129
  58. package/start.mjs +12 -12
  59. package/ui/logger.mjs +9 -9
@@ -1,62 +1,62 @@
1
- import { NodeCryptoService, deriveDocAccessKeys } from "@gitpagedocs/tools";
2
- import type { CommandContext } from "./run-command";
3
- import { askPassword, note, outro } from "../ui/clack";
4
- import { interactivePromptsAvailable } from "../ui/prompts";
5
- import { GitPageDocsConfigRepository } from "../../infrastructure/gitpagedocs-config-file";
6
-
7
- const MIN_PASSWORD_LENGTH = 4;
8
-
9
- /**
10
- * `gitpagedocs password` — interactively set a documentation access password.
11
- *
12
- * Type + confirm a password, derive the double-hash key pair, write the PUBLIC
13
- * key into gitpagedocs/config.json (which makes the frontend gate the docs), and
14
- * print the PRIVATE key for the user to copy. The password itself is never stored.
15
- */
16
- export async function runPassword(ctx: CommandContext): Promise<void> {
17
- if (!interactivePromptsAvailable()) {
18
- // eslint-disable-next-line no-console
19
- console.log("\n `gitpagedocs password` is interactive — run it in a terminal (TTY).\n");
20
- return;
21
- }
22
-
23
- const password = await askPassword({
24
- message: "Documentation password:",
25
- validate: (v) =>
26
- v && v.trim().length >= MIN_PASSWORD_LENGTH
27
- ? undefined
28
- : `Use at least ${MIN_PASSWORD_LENGTH} characters.`,
29
- });
30
- const confirmation = await askPassword({
31
- message: "Confirm password:",
32
- validate: (v) => (v ? undefined : "Required."),
33
- });
34
-
35
- if (password !== confirmation) {
36
- note("Passwords do not match. Nothing was changed.", "Aborted");
37
- return;
38
- }
39
-
40
- const { privateKey, publicKey } = await deriveDocAccessKeys(password, new NodeCryptoService());
41
-
42
- let configPath: string;
43
- try {
44
- configPath = await new GitPageDocsConfigRepository(ctx.cwd).patchDocsAccess(publicKey);
45
- } catch (error) {
46
- note(error instanceof Error ? error.message : String(error), "Could not save");
47
- return;
48
- }
49
-
50
- note(
51
- `Public key saved to ${configPath}\nThe documentation is now password-protected.`,
52
- "Saved",
53
- );
54
- // eslint-disable-next-line no-console
55
- console.log(
56
- "\n PRIVATE KEY (copy & keep it safe — it also unlocks the docs):\n\n" +
57
- ` ${privateKey}\n\n` +
58
- " Readers can unlock with the password OR this private key.\n" +
59
- " To remove protection, set site.docsAccess.enabled to false in config.json.\n",
60
- );
61
- outro("Done.");
62
- }
1
+ import { NodeCryptoService, deriveDocAccessKeys } from "@gitpagedocs/tools";
2
+ import type { CommandContext } from "./run-command";
3
+ import { askPassword, note, outro } from "../ui/clack";
4
+ import { interactivePromptsAvailable } from "../ui/prompts";
5
+ import { GitPageDocsConfigRepository } from "../../infrastructure/gitpagedocs-config-file";
6
+
7
+ const MIN_PASSWORD_LENGTH = 4;
8
+
9
+ /**
10
+ * `gitpagedocs password` — interactively set a documentation access password.
11
+ *
12
+ * Type + confirm a password, derive the double-hash key pair, write the PUBLIC
13
+ * key into gitpagedocs/config.json (which makes the frontend gate the docs), and
14
+ * print the PRIVATE key for the user to copy. The password itself is never stored.
15
+ */
16
+ export async function runPassword(ctx: CommandContext): Promise<void> {
17
+ if (!interactivePromptsAvailable()) {
18
+ // eslint-disable-next-line no-console
19
+ console.log("\n `gitpagedocs password` is interactive — run it in a terminal (TTY).\n");
20
+ return;
21
+ }
22
+
23
+ const password = await askPassword({
24
+ message: "Documentation password:",
25
+ validate: (v) =>
26
+ v && v.trim().length >= MIN_PASSWORD_LENGTH
27
+ ? undefined
28
+ : `Use at least ${MIN_PASSWORD_LENGTH} characters.`,
29
+ });
30
+ const confirmation = await askPassword({
31
+ message: "Confirm password:",
32
+ validate: (v) => (v ? undefined : "Required."),
33
+ });
34
+
35
+ if (password !== confirmation) {
36
+ note("Passwords do not match. Nothing was changed.", "Aborted");
37
+ return;
38
+ }
39
+
40
+ const { privateKey, publicKey } = await deriveDocAccessKeys(password, new NodeCryptoService());
41
+
42
+ let configPath: string;
43
+ try {
44
+ configPath = await new GitPageDocsConfigRepository(ctx.cwd).patchDocsAccess(publicKey);
45
+ } catch (error) {
46
+ note(error instanceof Error ? error.message : String(error), "Could not save");
47
+ return;
48
+ }
49
+
50
+ note(
51
+ `Public key saved to ${configPath}\nThe documentation is now password-protected.`,
52
+ "Saved",
53
+ );
54
+ // eslint-disable-next-line no-console
55
+ console.log(
56
+ "\n PRIVATE KEY (copy & keep it safe — it also unlocks the docs):\n\n" +
57
+ ` ${privateKey}\n\n` +
58
+ " Readers can unlock with the password OR this private key.\n" +
59
+ " To remove protection, set site.docsAccess.enabled to false in config.json.\n",
60
+ );
61
+ outro("Done.");
62
+ }
@@ -1,70 +1,70 @@
1
- /**
2
- * New-verb command layer (Phase 6). Intercepts the informational/utility
3
- * commands that are NOT part of the legacy flag flow (version, doctor, provider,
4
- * models, config, mcp, update) and routes them to thin handlers that consume
5
- * @gitpagedocs/tools. Alias verbs (init, document, deploy, pages) are mapped in
6
- * the parser and fall through to the legacy dispatch, so this returns false for
7
- * them.
8
- */
9
- export interface CommandContext {
10
- argv: string[];
11
- args: string[];
12
- pkgRoot: string;
13
- cwd: string;
14
- }
15
-
16
- export type CommandHandler = (ctx: CommandContext) => Promise<void>;
17
-
18
- import { runVersion, runDoctor, runUpdate } from "./diagnostics";
19
- import { runProvider, runModels } from "./ai-info";
20
- import { runConfig } from "./config-info";
21
- import { runConfigClear } from "./config-clear";
22
- import { runMcp } from "./mcp";
23
- import { runDocs } from "./docs";
24
- import { runPagesActions, runPagesDeploy } from "./pages";
25
- import { runPassword } from "./password";
26
-
27
- const REGISTRY: Record<string, CommandHandler> = {
28
- version: runVersion,
29
- "--version": runVersion,
30
- "-v": runVersion,
31
- doctor: runDoctor,
32
- update: runUpdate,
33
- provider: runProvider,
34
- providers: runProvider,
35
- models: runModels,
36
- config: runConfig,
37
- mcp: runMcp,
38
- docs: runDocs,
39
- password: runPassword,
40
- };
41
-
42
- /** Returns true if a new command handled the invocation (skip legacy flow). */
43
- export async function runNewCommand(argv: string[], pkgRoot: string): Promise<boolean> {
44
- const args = argv.slice(2);
45
- const ctx: CommandContext = { argv, args, pkgRoot, cwd: process.cwd() };
46
-
47
- // Configure-only Pages→Actions: `--pages-actions` flag or `pages actions` verb.
48
- if (args.includes("--pages-actions") || (args[0] === "pages" && args[1] === "actions")) {
49
- await runPagesActions(ctx);
50
- return true;
51
- }
52
- // Full deploy: `pages deploy` (detect owner/repo, confirm, run the proven
53
- // push flow, print URL). Bare `pages`/`deploy` still fall through to legacy.
54
- if (args[0] === "pages" && args[1] === "deploy") {
55
- await runPagesDeploy(ctx);
56
- return true;
57
- }
58
- // Wipe the stored AI credentials config: `config clear`.
59
- if (args[0] === "config" && args[1] === "clear") {
60
- await runConfigClear(ctx);
61
- return true;
62
- }
63
-
64
- const handler = REGISTRY[args[0] ?? ""];
65
- if (!handler) return false;
66
- await handler(ctx);
67
- return true;
68
- }
69
-
70
- export const NEW_COMMAND_NAMES = Object.keys(REGISTRY).filter((n) => !n.startsWith("-"));
1
+ /**
2
+ * New-verb command layer (Phase 6). Intercepts the informational/utility
3
+ * commands that are NOT part of the legacy flag flow (version, doctor, provider,
4
+ * models, config, mcp, update) and routes them to thin handlers that consume
5
+ * @gitpagedocs/tools. Alias verbs (init, document, deploy, pages) are mapped in
6
+ * the parser and fall through to the legacy dispatch, so this returns false for
7
+ * them.
8
+ */
9
+ export interface CommandContext {
10
+ argv: string[];
11
+ args: string[];
12
+ pkgRoot: string;
13
+ cwd: string;
14
+ }
15
+
16
+ export type CommandHandler = (ctx: CommandContext) => Promise<void>;
17
+
18
+ import { runVersion, runDoctor, runUpdate } from "./diagnostics";
19
+ import { runProvider, runModels } from "./ai-info";
20
+ import { runConfig } from "./config-info";
21
+ import { runConfigClear } from "./config-clear";
22
+ import { runMcp } from "./mcp";
23
+ import { runDocs } from "./docs";
24
+ import { runPagesActions, runPagesDeploy } from "./pages";
25
+ import { runPassword } from "./password";
26
+
27
+ const REGISTRY: Record<string, CommandHandler> = {
28
+ version: runVersion,
29
+ "--version": runVersion,
30
+ "-v": runVersion,
31
+ doctor: runDoctor,
32
+ update: runUpdate,
33
+ provider: runProvider,
34
+ providers: runProvider,
35
+ models: runModels,
36
+ config: runConfig,
37
+ mcp: runMcp,
38
+ docs: runDocs,
39
+ password: runPassword,
40
+ };
41
+
42
+ /** Returns true if a new command handled the invocation (skip legacy flow). */
43
+ export async function runNewCommand(argv: string[], pkgRoot: string): Promise<boolean> {
44
+ const args = argv.slice(2);
45
+ const ctx: CommandContext = { argv, args, pkgRoot, cwd: process.cwd() };
46
+
47
+ // Configure-only Pages→Actions: `--pages-actions` flag or `pages actions` verb.
48
+ if (args.includes("--pages-actions") || (args[0] === "pages" && args[1] === "actions")) {
49
+ await runPagesActions(ctx);
50
+ return true;
51
+ }
52
+ // Full deploy: `pages deploy` (detect owner/repo, confirm, run the proven
53
+ // push flow, print URL). Bare `pages`/`deploy` still fall through to legacy.
54
+ if (args[0] === "pages" && args[1] === "deploy") {
55
+ await runPagesDeploy(ctx);
56
+ return true;
57
+ }
58
+ // Wipe the stored AI credentials config: `config clear`.
59
+ if (args[0] === "config" && args[1] === "clear") {
60
+ await runConfigClear(ctx);
61
+ return true;
62
+ }
63
+
64
+ const handler = REGISTRY[args[0] ?? ""];
65
+ if (!handler) return false;
66
+ await handler(ctx);
67
+ return true;
68
+ }
69
+
70
+ export const NEW_COMMAND_NAMES = Object.keys(REGISTRY).filter((n) => !n.startsWith("-"));
@@ -1,124 +1,124 @@
1
- #!/usr/bin/env node
2
-
3
- import path from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- import { printBanner, printCredits } from "./ui/banner";
6
- import { resolveOptions } from "./options/resolver";
7
- import { migrateLegacyLayoutsInteractive } from "./ui/layouts-prompts";
8
- import { runNewCommand } from "./commands/run-command";
9
- import { dispatchMode } from "../application/use-cases/dispatch-mode";
10
- import type {
11
- CliRuntimeParams,
12
- ConfigOnlyRuntimePort,
13
- HomeRuntimePort,
14
- } from "../application/ports/cli-runtime-ports";
15
- // @ts-expect-error .mjs modules are runtime-only in this package.
16
- import { buildConfigArtifacts } from "../builders/config-orchestrator.mjs";
17
- // @ts-expect-error .mjs modules are runtime-only in this package.
18
- import { createThemeTemplate } from "../builders/theme-template.mjs";
19
- // @ts-expect-error .mjs modules are runtime-only in this package.
20
- import { LAYOUTS } from "../data/layouts.mjs";
21
- // @ts-expect-error .mjs modules are runtime-only in this package.
22
- import { executeConfigOnly } from "../application/config-only/handler.mjs";
23
- // @ts-expect-error .mjs modules are runtime-only in this package.
24
- import { executeHome } from "../application/home/handler.mjs";
25
- // @ts-expect-error .mjs modules are runtime-only in this package.
26
- import { createConfigOnlyRuntime } from "../infrastructure/config-only/runtime.mjs";
27
- // @ts-expect-error .mjs modules are runtime-only in this package.
28
- import { createHomeRuntime } from "../infrastructure/home/runtime.mjs";
29
-
30
- const scriptDir = path.dirname(fileURLToPath(import.meta.url));
31
- const root = process.cwd();
32
- // cli/ is the published package root (bin = cli/index.mjs). scriptDir is
33
- // cli/presentation, so pkgRoot = cli/ and the bundled prebuilt/ ships at
34
- // cli/prebuilt — works identically in-repo and when installed via npm.
35
- const pkgRoot = path.join(scriptDir, "..");
36
- const prebuiltDir = path.join(pkgRoot, "prebuilt");
37
-
38
- const params: CliRuntimeParams = {
39
- root,
40
- pkgRoot,
41
- prebuiltDir,
42
- buildConfigArtifacts,
43
- createThemeTemplate,
44
- layouts: LAYOUTS,
45
- };
46
-
47
- async function main(): Promise<void> {
48
- // `mcp start` owns stdout (the MCP stdio channel) — no banner/credits there.
49
- const stdoutOwnedByCommand = process.argv[2] === "mcp";
50
- if (!stdoutOwnedByCommand) printBanner();
51
-
52
- // New informational/utility commands (version, doctor, provider, models,
53
- // config, mcp, update) are handled before the legacy flag flow. Alias verbs
54
- // (init, document, deploy, pages) are mapped in the parser and fall through.
55
- if (await runNewCommand(process.argv, pkgRoot)) {
56
- if (!stdoutOwnedByCommand) printCredits();
57
- return;
58
- }
59
-
60
- const options = await resolveOptions(process.argv, process.env);
61
-
62
- // Layouts moved out of <outputDir>/layouts/. Offer to relocate anything left
63
- // behind before generating, so the config written next points at one folder.
64
- if (options.mode === "config-only") {
65
- await migrateLegacyLayoutsInteractive(root, options);
66
- }
67
-
68
- const configOnlyRuntime = createConfigOnlyRuntime() as ConfigOnlyRuntimePort;
69
- const homeRuntime = createHomeRuntime() as HomeRuntimePort;
70
- await dispatchMode(options, params, {
71
- runConfigOnly: async (context) => {
72
- const safePrebuiltDir =
73
- typeof context.prebuiltDir === "string"
74
- ? context.prebuiltDir
75
- : path.join(String(context.pkgRoot ?? process.cwd()), "prebuilt");
76
- await executeConfigOnly(
77
- {
78
- ...context,
79
- prebuiltDir: safePrebuiltDir,
80
- },
81
- configOnlyRuntime,
82
- );
83
- },
84
- runHome: async (context) => {
85
- await executeHome(context, homeRuntime);
86
- },
87
- runAi: async (context) => {
88
- console.log("[gitpagedocs] Iniciando Módulo de IA na CLI...");
89
- const safePrebuiltDir =
90
- typeof context.prebuiltDir === "string"
91
- ? context.prebuiltDir
92
- : path.join(String(context.pkgRoot ?? process.cwd()), "prebuilt");
93
- // @ts-ignore
94
- const { runAiCliCommand } = await import("../ai/application/run-ai-cli-command.ts");
95
- const result = await runAiCliCommand({
96
- cwd: process.cwd(),
97
- onInfo: (message: string) => console.log(message),
98
- // Scaffold the base gitpagedocs/ structure before AI pages are wired in.
99
- onScaffold: async () => {
100
- await executeConfigOnly({ ...context, prebuiltDir: safePrebuiltDir }, configOnlyRuntime);
101
- },
102
- });
103
-
104
- if (result.summary.scannedFilesCount === 0) {
105
- console.log("[gitpagedocs:ai] Nenhum arquivo elegível foi encontrado nos paths informados.");
106
- return;
107
- }
108
-
109
- const pages = result.summary.pages ?? [];
110
- console.log(
111
- `\nProcesso completo. Páginas no padrão gitpagedocs: ${pages.join(", ") || "(nenhuma)"}`,
112
- );
113
- console.log(
114
- `[gitpagedocs:ai] ${result.summary.outputs.length} arquivos markdown gerados e conectados ao config.json da versão mais recente.`,
115
- );
116
- },
117
- });
118
- printCredits();
119
- }
120
-
121
- main().catch((err: unknown) => {
122
- console.error("Failed to create Git Page Docs scaffold.", err);
123
- process.exitCode = 1;
124
- });
1
+ #!/usr/bin/env node
2
+
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { printBanner, printCredits } from "./ui/banner";
6
+ import { resolveOptions } from "./options/resolver";
7
+ import { migrateLegacyLayoutsInteractive } from "./ui/layouts-prompts";
8
+ import { runNewCommand } from "./commands/run-command";
9
+ import { dispatchMode } from "../application/use-cases/dispatch-mode";
10
+ import type {
11
+ CliRuntimeParams,
12
+ ConfigOnlyRuntimePort,
13
+ HomeRuntimePort,
14
+ } from "../application/ports/cli-runtime-ports";
15
+ // @ts-expect-error .mjs modules are runtime-only in this package.
16
+ import { buildConfigArtifacts } from "../builders/config-orchestrator.mjs";
17
+ // @ts-expect-error .mjs modules are runtime-only in this package.
18
+ import { createThemeTemplate } from "../builders/theme-template.mjs";
19
+ // @ts-expect-error .mjs modules are runtime-only in this package.
20
+ import { LAYOUTS } from "../data/layouts.mjs";
21
+ // @ts-expect-error .mjs modules are runtime-only in this package.
22
+ import { executeConfigOnly } from "../application/config-only/handler.mjs";
23
+ // @ts-expect-error .mjs modules are runtime-only in this package.
24
+ import { executeHome } from "../application/home/handler.mjs";
25
+ // @ts-expect-error .mjs modules are runtime-only in this package.
26
+ import { createConfigOnlyRuntime } from "../infrastructure/config-only/runtime.mjs";
27
+ // @ts-expect-error .mjs modules are runtime-only in this package.
28
+ import { createHomeRuntime } from "../infrastructure/home/runtime.mjs";
29
+
30
+ const scriptDir = path.dirname(fileURLToPath(import.meta.url));
31
+ const root = process.cwd();
32
+ // cli/ is the published package root (bin = cli/index.mjs). scriptDir is
33
+ // cli/presentation, so pkgRoot = cli/ and the bundled prebuilt/ ships at
34
+ // cli/prebuilt — works identically in-repo and when installed via npm.
35
+ const pkgRoot = path.join(scriptDir, "..");
36
+ const prebuiltDir = path.join(pkgRoot, "prebuilt");
37
+
38
+ const params: CliRuntimeParams = {
39
+ root,
40
+ pkgRoot,
41
+ prebuiltDir,
42
+ buildConfigArtifacts,
43
+ createThemeTemplate,
44
+ layouts: LAYOUTS,
45
+ };
46
+
47
+ async function main(): Promise<void> {
48
+ // `mcp start` owns stdout (the MCP stdio channel) — no banner/credits there.
49
+ const stdoutOwnedByCommand = process.argv[2] === "mcp";
50
+ if (!stdoutOwnedByCommand) printBanner();
51
+
52
+ // New informational/utility commands (version, doctor, provider, models,
53
+ // config, mcp, update) are handled before the legacy flag flow. Alias verbs
54
+ // (init, document, deploy, pages) are mapped in the parser and fall through.
55
+ if (await runNewCommand(process.argv, pkgRoot)) {
56
+ if (!stdoutOwnedByCommand) printCredits();
57
+ return;
58
+ }
59
+
60
+ const options = await resolveOptions(process.argv, process.env);
61
+
62
+ // Layouts moved out of <outputDir>/layouts/. Offer to relocate anything left
63
+ // behind before generating, so the config written next points at one folder.
64
+ if (options.mode === "config-only") {
65
+ await migrateLegacyLayoutsInteractive(root, options);
66
+ }
67
+
68
+ const configOnlyRuntime = createConfigOnlyRuntime() as ConfigOnlyRuntimePort;
69
+ const homeRuntime = createHomeRuntime() as HomeRuntimePort;
70
+ await dispatchMode(options, params, {
71
+ runConfigOnly: async (context) => {
72
+ const safePrebuiltDir =
73
+ typeof context.prebuiltDir === "string"
74
+ ? context.prebuiltDir
75
+ : path.join(String(context.pkgRoot ?? process.cwd()), "prebuilt");
76
+ await executeConfigOnly(
77
+ {
78
+ ...context,
79
+ prebuiltDir: safePrebuiltDir,
80
+ },
81
+ configOnlyRuntime,
82
+ );
83
+ },
84
+ runHome: async (context) => {
85
+ await executeHome(context, homeRuntime);
86
+ },
87
+ runAi: async (context) => {
88
+ console.log("[gitpagedocs] Iniciando Módulo de IA na CLI...");
89
+ const safePrebuiltDir =
90
+ typeof context.prebuiltDir === "string"
91
+ ? context.prebuiltDir
92
+ : path.join(String(context.pkgRoot ?? process.cwd()), "prebuilt");
93
+ // @ts-ignore
94
+ const { runAiCliCommand } = await import("../ai/application/run-ai-cli-command.ts");
95
+ const result = await runAiCliCommand({
96
+ cwd: process.cwd(),
97
+ onInfo: (message: string) => console.log(message),
98
+ // Scaffold the base gitpagedocs/ structure before AI pages are wired in.
99
+ onScaffold: async () => {
100
+ await executeConfigOnly({ ...context, prebuiltDir: safePrebuiltDir }, configOnlyRuntime);
101
+ },
102
+ });
103
+
104
+ if (result.summary.scannedFilesCount === 0) {
105
+ console.log("[gitpagedocs:ai] Nenhum arquivo elegível foi encontrado nos paths informados.");
106
+ return;
107
+ }
108
+
109
+ const pages = result.summary.pages ?? [];
110
+ console.log(
111
+ `\nProcesso completo. Páginas no padrão gitpagedocs: ${pages.join(", ") || "(nenhuma)"}`,
112
+ );
113
+ console.log(
114
+ `[gitpagedocs:ai] ${result.summary.outputs.length} arquivos markdown gerados e conectados ao config.json da versão mais recente.`,
115
+ );
116
+ },
117
+ });
118
+ printCredits();
119
+ }
120
+
121
+ main().catch((err: unknown) => {
122
+ console.error("Failed to create Git Page Docs scaffold.", err);
123
+ process.exitCode = 1;
124
+ });