@gitpagedocs/cli 1.1.61 → 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 (72) hide show
  1. package/README.md +193 -191
  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/config-only/handler.mjs +2 -0
  16. package/application/home/handler.mjs +2 -0
  17. package/application/ports/cli-runtime-ports.ts +91 -87
  18. package/application/report/config-only-reporter.mjs +64 -63
  19. package/application/use-cases/dispatch-mode.ts +18 -18
  20. package/builders/config-orchestrator.mjs +34 -34
  21. package/builders/project-links.mjs +50 -26
  22. package/builders/root-config-builder.d.mts +16 -0
  23. package/builders/root-config-builder.mjs +61 -53
  24. package/builders/route-builders.mjs +136 -136
  25. package/builders/theme-template.mjs +76 -76
  26. package/builders/version-config-builder.mjs +186 -186
  27. package/content/docs-en.mjs +549 -545
  28. package/content/docs-es.mjs +462 -460
  29. package/content/docs-pt.mjs +462 -460
  30. package/contracts/doc-versions.mjs +3 -3
  31. package/contracts/index.mjs +10 -0
  32. package/contracts/layouts-paths.d.mts +17 -0
  33. package/contracts/layouts-paths.mjs +68 -0
  34. package/data/default-site-config.mjs +321 -321
  35. package/data/i18n-langmenu.mjs +347 -347
  36. package/data/layouts.mjs +436 -436
  37. package/data/path-mappings.mjs +26 -26
  38. package/data/route-metas.mjs +93 -93
  39. package/data/theme-colors.mjs +443 -443
  40. package/data/urls.mjs +12 -12
  41. package/domain/models/cli-options.ts +33 -18
  42. package/domain/services/layouts-migration.d.mts +15 -0
  43. package/domain/services/layouts-migration.mjs +60 -0
  44. package/home/constants.mjs +4 -4
  45. package/index.mjs +37 -37
  46. package/infrastructure/gitpagedocs-config-file.ts +47 -47
  47. package/infrastructure/home/runtime.mjs +37 -37
  48. package/package.json +3 -3
  49. package/presentation/commands/ai-info.ts +57 -57
  50. package/presentation/commands/config-clear.ts +23 -23
  51. package/presentation/commands/config-info.ts +24 -24
  52. package/presentation/commands/diagnostics.ts +164 -164
  53. package/presentation/commands/docs.ts +37 -37
  54. package/presentation/commands/mcp.ts +20 -20
  55. package/presentation/commands/pages.ts +101 -101
  56. package/presentation/commands/password.ts +62 -62
  57. package/presentation/commands/run-command.ts +70 -70
  58. package/presentation/index.ts +124 -116
  59. package/presentation/options/parser.ts +119 -104
  60. package/presentation/options/resolver.ts +46 -48
  61. package/presentation/options/schema.ts +4 -0
  62. package/presentation/ui/clack.ts +91 -91
  63. package/presentation/ui/layouts-prompts.ts +124 -0
  64. package/presentation/ui/prompts.ts +146 -138
  65. package/presentation/ui/tty.ts +37 -0
  66. package/runtime/git-ops.mjs +110 -110
  67. package/runtime/layouts-migrator.d.mts +11 -0
  68. package/runtime/layouts-migrator.mjs +103 -0
  69. package/runtime/output.mjs +159 -146
  70. package/runtime/workflow.mjs +129 -129
  71. package/start.mjs +12 -12
  72. package/ui/logger.mjs +9 -9
package/README.md CHANGED
@@ -1,191 +1,193 @@
1
- # @gitpagedocs/cli
2
-
3
- The **published npm package** of the [Git Page Docs](../README.md) monorepo (the command it installs is `gitpagedocs`). It scaffolds the `gitpagedocs/` docs contract, generates docs with AI, configures GitHub Pages, and runs the MCP server.
4
-
5
- ```bash
6
- npm install -g @gitpagedocs/cli # global (installs the `gitpagedocs` command)
7
- gitpagedocs # generate gitpagedocs/ config (config-only)
8
-
9
- # or one-off, no install:
10
- npx @gitpagedocs/cli
11
- ```
12
-
13
- > This package ships its TypeScript sources and runs them via `tsx`; it depends on the workspace packages `@gitpagedocs/tools` and `@gitpagedocs/mcp` (published alongside it).
14
-
15
- ## Commands
16
-
17
- | Command | Description |
18
- |---|---|
19
- | `gitpagedocs` | Generate `gitpagedocs/` config + versioned docs (config-only) |
20
- | `gitpagedocs --layoutconfig` | Also emit local layout templates in `gitpagedocs/layouts/` |
21
- | `gitpagedocs --push --owner <o> --repo <r> [--path <sub>]` | Generate, configure Pages, create workflow, commit + push |
22
- | `gitpagedocs --home` | Standalone distribution (`gitpagedocshome/`: static site + .env + Dockerfile) |
23
- | `gitpagedocs -i` / `--interactive` | Interactive prompts |
24
- | `gitpagedocs ai` | Interactive AI documentation generator — writes pages in the gitpagedocs pattern (see below) |
25
- | `gitpagedocs provider [id]` · `models [provider]` | List AI providers / catalog models |
26
- | `gitpagedocs document[:repo\|:file\|:folder]` | Generate documentation with AI in the gitpagedocs pattern |
27
- | `gitpagedocs password` | Set a documentation access password (writes the public key to `config.json`, prints the private key) |
28
- | `gitpagedocs deploy` / `pages [actions\|deploy]` | Configure GitHub Pages via Actions + push |
29
- | `gitpagedocs docs` | Refresh managed regions of README/CONTRIBUTING/SECURITY |
30
- | `gitpagedocs config clear` | Delete the stored `.gitpagedocsconfig` (wipes saved AI credentials) |
31
- | `gitpagedocs doctor` · `version` · `update` | Diagnostics / version / registry update check |
32
- | `gitpagedocs mcp start` | Start the MCP server over stdio |
33
-
34
- The AI-CLI implementation lives in `cli/ai/` (relocated from the frontend so the published package is self-contained).
35
-
36
- # CLI Architecture (Clean Architecture + SOLID)
37
-
38
- ## Layer Overview
39
-
40
- ```
41
- cli/
42
- |-- index.mjs # Node entry (bootstraps TS presentation via tsx)
43
- |-- package.json # the published `gitpagedocs` package
44
- |-- ai/ # AI documentation CLI (provider/model/paths → markdown)
45
- |-- contracts/ # Stable contracts for external tooling
46
- | `-- doc-versions.mjs
47
- |
48
- |-- presentation/ # Interface/composition root
49
- | |-- index.ts
50
- | |-- options/
51
- | `-- ui/
52
- |
53
- |-- application/ # Use-cases and ports
54
- | |-- config-only/handler.mjs
55
- | |-- home/handler.mjs
56
- | |-- report/config-only-reporter.mjs
57
- | |-- use-cases/dispatch-mode.ts
58
- | `-- ports/cli-runtime-ports.ts
59
- |
60
- |-- domain/ # Business rules
61
- | `-- services/sanitize-segment.mjs
62
- |
63
- |-- infrastructure/ # Side effects and adapters
64
- | |-- config-only/runtime.mjs
65
- | `-- home/runtime.mjs
66
- |
67
- |-- builders/ # Pure config builders
68
- |-- data/ # Constants and metadata
69
- |-- content/ # Static docs content
70
- |-- runtime/ # Low-level runtime helpers
71
- `-- home/ # Home templates/files
72
- ```
73
-
74
- ## SOLID Principles
75
-
76
- | Principle | Application |
77
- |-----------|-------------|
78
- | **SRP** | `application/report` only formats messages; handlers only orchestrate |
79
- | **OCP** | New runtime implementations can be injected through ports |
80
- | **LSP** | `dispatch-mode` works with any runner implementing `CliCommandRunner` |
81
- | **ISP** | Split runtime contracts (`ConfigOnlyRuntimePort`, `HomeRuntimePort`) |
82
- | **DIP** | Use-cases depend on `application/ports`, not concrete fs/git/exec |
83
-
84
- ## Clean Architecture
85
-
86
- - **Interfaces/Presentation**: parse CLI args, resolve mode, wire dependencies in `presentation/index.ts`
87
- - **Application**: orchestrate flows with explicit ports, without direct fs/git/exec imports
88
- - **Domain**: sanitize and core rules with no infrastructure dependencies
89
- - **Infrastructure**: concrete adapters for runtime side effects
90
- - **Contracts**: `tools/smoke` consumes `cli/contracts` instead of internal CLI modules
91
-
92
- ## Authorized Routes Pipeline
93
-
94
- The CLI now generates authorized-route docs and config entries in PT/EN/ES.
95
-
96
- - Source content: `cli/content/docs.mjs` (`authorizedRoutes` key per language)
97
- - Route metadata: `cli/data/route-metas.mjs` (`ROUTE_META_ID6`)
98
- - Route path mapping: `cli/data/path-mappings.mjs` (`authorized-routes.md`)
99
- - Version config composition: `cli/builders/version-config-builder.mjs`
100
- - Doc key resolution: `cli/runtime/doc-path-resolver.mjs`
101
-
102
- Generated artifacts include:
103
-
104
- - `gitpagedocs/docs/versions/<version>/config.json` with `auth` and route `authorization`
105
- - `gitpagedocs/docs/versions/<version>/{pt,en,es}/authorized-routes.md`
106
- - `menus-header-md` entry dedicated to Authorized Routes
107
-
108
- ## GitHub Pages Push Paths
109
-
110
- - Default project-site publish (`--push` without `--path`) targets `/<repo>/`.
111
- - Custom project subpath publish (`--push --path <segment>`) targets `/<repo>/<segment>/`.
112
- - `--path` accepts a single sanitized segment (letters, numbers, `.`, `_`, `-`).
113
-
114
- Example:
115
-
116
- ```bash
117
- npx @gitpagedocs/cli --owner vidigal-code --repo energy-bill-ai-parser --path git-docs --push
118
- ```
119
-
120
- Expected URL after deployment:
121
-
122
- ```text
123
- https://vidigal-code.github.io/energy-bill-ai-parser/git-docs/
124
- ```
125
-
126
- ## AI CLI (interactive + config file)
127
-
128
- The CLI now includes a dedicated interactive AI mode:
129
-
130
- ```bash
131
- npx @gitpagedocs/cli ai
132
- ```
133
-
134
- ### What it does
135
-
136
- - asks provider (`openai`, `claude`, `gemini`, `ollama`)
137
- - asks API key or Ollama URL
138
- - asks paths to scan (supports one or many paths, including other repositories)
139
- - generates documentation in `pt`, `en`, `es` **in the gitpagedocs pattern**
140
- - optionally persists config in `.gitpagedocsconfig`
141
-
142
- ### gitpagedocs pattern output
143
-
144
- The model is given a gitpagedocs-aware system prompt and returns documentation split into
145
- pages (delimited by `=== PAGE: <slug> | <Title> ===`). The CLI scaffolds the base
146
- `gitpagedocs/` structure first, then writes each page to
147
- `gitpagedocs/docs/versions/<latest>/<lang>/<slug>.md` for every language and **wires it into
148
- that version's `config.json`** (`routes-md` + `menus-header-md`) so the pages render in the
149
- viewer menu. Entries are tagged `aiGenerated` and idempotent (re-running replaces them). A
150
- later plain `gitpagedocs` rebuild drops the wiring — re-run `gitpagedocs ai` to restore.
151
-
152
- ### `.gitpagedocsconfig` (manual mode)
153
-
154
- The file lives in the per-user OS config directory (never inside the repository, so
155
- the API key cannot be committed by accident) and is written with owner-only
156
- permissions on POSIX systems:
157
-
158
- - Windows: `%APPDATA%\gitpagedocs\.gitpagedocsconfig`
159
- - macOS: `~/Library/Application Support/gitpagedocs/.gitpagedocsconfig`
160
- - Linux: `$XDG_CONFIG_HOME/gitpagedocs/.gitpagedocsconfig` (or `~/.config/gitpagedocs/.gitpagedocsconfig`)
161
-
162
- Set `GITPAGEDOCS_CONFIG_DIR` to override the directory; delete the stored file
163
- and its credentials with `gitpagedocs config clear`; a legacy
164
- `.gitpagedocsconfig` in the repository root is migrated automatically on the next
165
- run. You can create/edit this file manually and then run `npx @gitpagedocs/cli ai`:
166
-
167
- ```json
168
- {
169
- "version": 1,
170
- "ai": {
171
- "provider": "openai",
172
- "model": "gpt-4o-mini",
173
- "apiKey": "<YOUR_API_KEY>",
174
- "paths": ["src", "cli", "../another-repo/src"],
175
- "languages": ["pt", "en", "es"],
176
- "outputDir": "gitpagedocs/docs",
177
- "filePrefix": "ai-generated",
178
- "contextPrompt": "Você é um redator técnico sênior..."
179
- }
180
- }
181
- ```
182
-
183
- For Ollama, use `baseUrl` instead of `apiKey`.
184
-
185
- ### Interactive fallback
186
-
187
- If a directory is not found, CLI offers fallback choices:
188
-
189
- - fix paths and retry
190
- - skip missing paths and continue
191
- - abort safely
1
+ # @gitpagedocs/cli
2
+
3
+ The **published npm package** of the [Git Page Docs](../README.md) monorepo (the command it installs is `gitpagedocs`). It scaffolds the `gitpagedocs/` docs contract, generates docs with AI, configures GitHub Pages, and runs the MCP server.
4
+
5
+ ```bash
6
+ npm install -g @gitpagedocs/cli # global (installs the `gitpagedocs` command)
7
+ gitpagedocs # generate gitpagedocs/ config (config-only)
8
+
9
+ # or one-off, no install:
10
+ npx @gitpagedocs/cli
11
+ ```
12
+
13
+ > This package ships its TypeScript sources and runs them via `tsx`; it depends on the workspace packages `@gitpagedocs/tools` and `@gitpagedocs/mcp` (published alongside it).
14
+
15
+ ## Commands
16
+
17
+ | Command | Description |
18
+ |---|---|
19
+ | `gitpagedocs` | Generate `gitpagedocs/` config + versioned docs (config-only) |
20
+ | `gitpagedocs --layoutconfig` | Also emit local layout templates in `gitpagelayouts/` |
21
+ | `gitpagedocs --layouts-dir <dir>` | Folder for local layouts (default: `gitpagelayouts`) |
22
+ | `gitpagedocs --no-interactive` / `-y` | Never prompt; use flags and defaults |
23
+ | `gitpagedocs --push --owner <o> --repo <r> [--path <sub>]` | Generate, configure Pages, create workflow, commit + push |
24
+ | `gitpagedocs --home` | Standalone distribution (`gitpagedocshome/`: static site + .env + Dockerfile) |
25
+ | `gitpagedocs -i` / `--interactive` | Interactive prompts |
26
+ | `gitpagedocs ai` | Interactive AI documentation generator — writes pages in the gitpagedocs pattern (see below) |
27
+ | `gitpagedocs provider [id]` · `models [provider]` | List AI providers / catalog models |
28
+ | `gitpagedocs document[:repo\|:file\|:folder]` | Generate documentation with AI in the gitpagedocs pattern |
29
+ | `gitpagedocs password` | Set a documentation access password (writes the public key to `config.json`, prints the private key) |
30
+ | `gitpagedocs deploy` / `pages [actions\|deploy]` | Configure GitHub Pages via Actions + push |
31
+ | `gitpagedocs docs` | Refresh managed regions of README/CONTRIBUTING/SECURITY |
32
+ | `gitpagedocs config clear` | Delete the stored `.gitpagedocsconfig` (wipes saved AI credentials) |
33
+ | `gitpagedocs doctor` · `version` · `update` | Diagnostics / version / registry update check |
34
+ | `gitpagedocs mcp start` | Start the MCP server over stdio |
35
+
36
+ The AI-CLI implementation lives in `cli/ai/` (relocated from the frontend so the published package is self-contained).
37
+
38
+ # CLI Architecture (Clean Architecture + SOLID)
39
+
40
+ ## Layer Overview
41
+
42
+ ```
43
+ cli/
44
+ |-- index.mjs # Node entry (bootstraps TS presentation via tsx)
45
+ |-- package.json # the published `gitpagedocs` package
46
+ |-- ai/ # AI documentation CLI (provider/model/paths → markdown)
47
+ |-- contracts/ # Stable contracts for external tooling
48
+ | `-- doc-versions.mjs
49
+ |
50
+ |-- presentation/ # Interface/composition root
51
+ | |-- index.ts
52
+ | |-- options/
53
+ | `-- ui/
54
+ |
55
+ |-- application/ # Use-cases and ports
56
+ | |-- config-only/handler.mjs
57
+ | |-- home/handler.mjs
58
+ | |-- report/config-only-reporter.mjs
59
+ | |-- use-cases/dispatch-mode.ts
60
+ | `-- ports/cli-runtime-ports.ts
61
+ |
62
+ |-- domain/ # Business rules
63
+ | `-- services/sanitize-segment.mjs
64
+ |
65
+ |-- infrastructure/ # Side effects and adapters
66
+ | |-- config-only/runtime.mjs
67
+ | `-- home/runtime.mjs
68
+ |
69
+ |-- builders/ # Pure config builders
70
+ |-- data/ # Constants and metadata
71
+ |-- content/ # Static docs content
72
+ |-- runtime/ # Low-level runtime helpers
73
+ `-- home/ # Home templates/files
74
+ ```
75
+
76
+ ## SOLID Principles
77
+
78
+ | Principle | Application |
79
+ |-----------|-------------|
80
+ | **SRP** | `application/report` only formats messages; handlers only orchestrate |
81
+ | **OCP** | New runtime implementations can be injected through ports |
82
+ | **LSP** | `dispatch-mode` works with any runner implementing `CliCommandRunner` |
83
+ | **ISP** | Split runtime contracts (`ConfigOnlyRuntimePort`, `HomeRuntimePort`) |
84
+ | **DIP** | Use-cases depend on `application/ports`, not concrete fs/git/exec |
85
+
86
+ ## Clean Architecture
87
+
88
+ - **Interfaces/Presentation**: parse CLI args, resolve mode, wire dependencies in `presentation/index.ts`
89
+ - **Application**: orchestrate flows with explicit ports, without direct fs/git/exec imports
90
+ - **Domain**: sanitize and core rules with no infrastructure dependencies
91
+ - **Infrastructure**: concrete adapters for runtime side effects
92
+ - **Contracts**: `tools/smoke` consumes `cli/contracts` instead of internal CLI modules
93
+
94
+ ## Authorized Routes Pipeline
95
+
96
+ The CLI now generates authorized-route docs and config entries in PT/EN/ES.
97
+
98
+ - Source content: `cli/content/docs.mjs` (`authorizedRoutes` key per language)
99
+ - Route metadata: `cli/data/route-metas.mjs` (`ROUTE_META_ID6`)
100
+ - Route path mapping: `cli/data/path-mappings.mjs` (`authorized-routes.md`)
101
+ - Version config composition: `cli/builders/version-config-builder.mjs`
102
+ - Doc key resolution: `cli/runtime/doc-path-resolver.mjs`
103
+
104
+ Generated artifacts include:
105
+
106
+ - `gitpagedocs/docs/versions/<version>/config.json` with `auth` and route `authorization`
107
+ - `gitpagedocs/docs/versions/<version>/{pt,en,es}/authorized-routes.md`
108
+ - `menus-header-md` entry dedicated to Authorized Routes
109
+
110
+ ## GitHub Pages Push Paths
111
+
112
+ - Default project-site publish (`--push` without `--path`) targets `/<repo>/`.
113
+ - Custom project subpath publish (`--push --path <segment>`) targets `/<repo>/<segment>/`.
114
+ - `--path` accepts a single sanitized segment (letters, numbers, `.`, `_`, `-`).
115
+
116
+ Example:
117
+
118
+ ```bash
119
+ npx @gitpagedocs/cli --owner vidigal-code --repo energy-bill-ai-parser --path git-docs --push
120
+ ```
121
+
122
+ Expected URL after deployment:
123
+
124
+ ```text
125
+ https://vidigal-code.github.io/energy-bill-ai-parser/git-docs/
126
+ ```
127
+
128
+ ## AI CLI (interactive + config file)
129
+
130
+ The CLI now includes a dedicated interactive AI mode:
131
+
132
+ ```bash
133
+ npx @gitpagedocs/cli ai
134
+ ```
135
+
136
+ ### What it does
137
+
138
+ - asks provider (`openai`, `claude`, `gemini`, `ollama`)
139
+ - asks API key or Ollama URL
140
+ - asks paths to scan (supports one or many paths, including other repositories)
141
+ - generates documentation in `pt`, `en`, `es` **in the gitpagedocs pattern**
142
+ - optionally persists config in `.gitpagedocsconfig`
143
+
144
+ ### gitpagedocs pattern output
145
+
146
+ The model is given a gitpagedocs-aware system prompt and returns documentation split into
147
+ pages (delimited by `=== PAGE: <slug> | <Title> ===`). The CLI scaffolds the base
148
+ `gitpagedocs/` structure first, then writes each page to
149
+ `gitpagedocs/docs/versions/<latest>/<lang>/<slug>.md` for every language and **wires it into
150
+ that version's `config.json`** (`routes-md` + `menus-header-md`) so the pages render in the
151
+ viewer menu. Entries are tagged `aiGenerated` and idempotent (re-running replaces them). A
152
+ later plain `gitpagedocs` rebuild drops the wiring — re-run `gitpagedocs ai` to restore.
153
+
154
+ ### `.gitpagedocsconfig` (manual mode)
155
+
156
+ The file lives in the per-user OS config directory (never inside the repository, so
157
+ the API key cannot be committed by accident) and is written with owner-only
158
+ permissions on POSIX systems:
159
+
160
+ - Windows: `%APPDATA%\gitpagedocs\.gitpagedocsconfig`
161
+ - macOS: `~/Library/Application Support/gitpagedocs/.gitpagedocsconfig`
162
+ - Linux: `$XDG_CONFIG_HOME/gitpagedocs/.gitpagedocsconfig` (or `~/.config/gitpagedocs/.gitpagedocsconfig`)
163
+
164
+ Set `GITPAGEDOCS_CONFIG_DIR` to override the directory; delete the stored file
165
+ and its credentials with `gitpagedocs config clear`; a legacy
166
+ `.gitpagedocsconfig` in the repository root is migrated automatically on the next
167
+ run. You can create/edit this file manually and then run `npx @gitpagedocs/cli ai`:
168
+
169
+ ```json
170
+ {
171
+ "version": 1,
172
+ "ai": {
173
+ "provider": "openai",
174
+ "model": "gpt-4o-mini",
175
+ "apiKey": "<YOUR_API_KEY>",
176
+ "paths": ["src", "cli", "../another-repo/src"],
177
+ "languages": ["pt", "en", "es"],
178
+ "outputDir": "gitpagedocs/docs",
179
+ "filePrefix": "ai-generated",
180
+ "contextPrompt": "Você é um redator técnico sênior..."
181
+ }
182
+ }
183
+ ```
184
+
185
+ For Ollama, use `baseUrl` instead of `apiKey`.
186
+
187
+ ### Interactive fallback
188
+
189
+ If a directory is not found, CLI offers fallback choices:
190
+
191
+ - fix paths and retry
192
+ - skip missing paths and continue
193
+ - abort safely
@@ -1,24 +1,24 @@
1
- /**
2
- * @file ai-command.ts
3
- * @description Application service for running AI commands. Decoupled from concrete LLMs.
4
- */
5
- import { ILLMProvider } from '../core/ports/illm-provider';
6
-
7
- export class AiCommandService {
8
- constructor(private provider: ILLMProvider) { }
9
-
10
- /**
11
- * Executes the AI Documentation Generation for a specific content
12
- */
13
- async runGeneration(content: string, contextPrompt?: string): Promise<string> {
14
- return await this.provider.generateDocumentation(content, contextPrompt);
15
- }
16
-
17
- /**
18
- * Executes a CLI chat prompt
19
- */
20
- async runChat(prompt: string): Promise<string> {
21
- const messages = [{ role: 'user' as const, content: prompt }];
22
- return await this.provider.chat(messages);
23
- }
24
- }
1
+ /**
2
+ * @file ai-command.ts
3
+ * @description Application service for running AI commands. Decoupled from concrete LLMs.
4
+ */
5
+ import { ILLMProvider } from '../core/ports/illm-provider';
6
+
7
+ export class AiCommandService {
8
+ constructor(private provider: ILLMProvider) { }
9
+
10
+ /**
11
+ * Executes the AI Documentation Generation for a specific content
12
+ */
13
+ async runGeneration(content: string, contextPrompt?: string): Promise<string> {
14
+ return await this.provider.generateDocumentation(content, contextPrompt);
15
+ }
16
+
17
+ /**
18
+ * Executes a CLI chat prompt
19
+ */
20
+ async runChat(prompt: string): Promise<string> {
21
+ const messages = [{ role: 'user' as const, content: prompt }];
22
+ return await this.provider.chat(messages);
23
+ }
24
+ }
@@ -1,22 +1,22 @@
1
- import type { AiProviderId } from "../config";
2
- import type { ILLMProvider } from "../core/ports/illm-provider";
3
- import { ToolsLlmProvider } from "../infrastructure/llm/tools-llm-provider";
4
-
5
- /**
6
- * Creates the CLI LLM provider. Backed by the shared @gitpagedocs/tools AI core
7
- * (one registry-driven implementation for every provider) — no per-provider
8
- * switch. The legacy provider id (openai/claude/gemini/ollama) is mapped to the
9
- * catalog inside ToolsLlmProvider.
10
- */
11
- export function createAiProvider(input: {
12
- provider: AiProviderId;
13
- model: string;
14
- apiKey?: string;
15
- baseUrl?: string;
16
- }): ILLMProvider {
17
- return new ToolsLlmProvider(input.provider, {
18
- model: input.model,
19
- apiKey: input.apiKey,
20
- baseUrl: input.baseUrl,
21
- });
22
- }
1
+ import type { AiProviderId } from "../config";
2
+ import type { ILLMProvider } from "../core/ports/illm-provider";
3
+ import { ToolsLlmProvider } from "../infrastructure/llm/tools-llm-provider";
4
+
5
+ /**
6
+ * Creates the CLI LLM provider. Backed by the shared @gitpagedocs/tools AI core
7
+ * (one registry-driven implementation for every provider) — no per-provider
8
+ * switch. The legacy provider id (openai/claude/gemini/ollama) is mapped to the
9
+ * catalog inside ToolsLlmProvider.
10
+ */
11
+ export function createAiProvider(input: {
12
+ provider: AiProviderId;
13
+ model: string;
14
+ apiKey?: string;
15
+ baseUrl?: string;
16
+ }): ILLMProvider {
17
+ return new ToolsLlmProvider(input.provider, {
18
+ model: input.model,
19
+ apiKey: input.apiKey,
20
+ baseUrl: input.baseUrl,
21
+ });
22
+ }
@@ -1,68 +1,68 @@
1
- /**
2
- * Parse an AI documentation response into gitpagedocs pages.
3
- *
4
- * The model is instructed (see GITPAGEDOCS_DOC_SYSTEM_PROMPT) to delimit each
5
- * page with a line `=== PAGE: <slug> | <Title> ===`. This splits that response
6
- * into individual pages. If the model ignored the format, the whole response is
7
- * returned as a single "ai-overview" page so content is never lost.
8
- */
9
-
10
- export interface AiDocPage {
11
- /** lowercase-kebab, English, identical across languages (used as the filename) */
12
- slug: string;
13
- title: string;
14
- body: string;
15
- }
16
-
17
- const PAGE_DELIMITER = /^===\s*PAGE:\s*(.+?)\s*\|\s*(.*?)\s*===\s*$/;
18
-
19
- /** Turn an arbitrary heading into a safe lowercase-kebab slug. */
20
- export function slugify(raw: string): string {
21
- const slug = (raw ?? "")
22
- .toLowerCase()
23
- .normalize("NFKD")
24
- .replace(/[^a-z0-9]+/g, "-")
25
- .replace(/^-+|-+$/g, "")
26
- .slice(0, 60);
27
- return slug || "page";
28
- }
29
-
30
- export function parseAiPages(markdown: string): AiDocPage[] {
31
- const text = (markdown ?? "").replace(/\r\n/g, "\n").trim();
32
- if (!text) return [];
33
-
34
- const pages: AiDocPage[] = [];
35
- let current: { slug: string; title: string; body: string[] } | null = null;
36
-
37
- const flush = () => {
38
- if (current) {
39
- pages.push({ slug: current.slug, title: current.title, body: current.body.join("\n").trim() });
40
- }
41
- };
42
-
43
- for (const line of text.split("\n")) {
44
- const match = line.match(PAGE_DELIMITER);
45
- if (match) {
46
- flush();
47
- const rawSlug = match[1].trim();
48
- const title = match[2].trim() || rawSlug;
49
- current = { slug: slugify(rawSlug), title, body: [] };
50
- } else if (current) {
51
- current.body.push(line);
52
- }
53
- }
54
- flush();
55
-
56
- const withBody = pages.filter((page) => page.body.length > 0);
57
- if (withBody.length === 0) {
58
- return [{ slug: "ai-overview", title: "Overview", body: text }];
59
- }
60
-
61
- // De-duplicate slugs within a single response (suffix later collisions).
62
- const seen = new Map<string, number>();
63
- return withBody.map((page) => {
64
- const count = seen.get(page.slug) ?? 0;
65
- seen.set(page.slug, count + 1);
66
- return count === 0 ? page : { ...page, slug: `${page.slug}-${count + 1}` };
67
- });
68
- }
1
+ /**
2
+ * Parse an AI documentation response into gitpagedocs pages.
3
+ *
4
+ * The model is instructed (see GITPAGEDOCS_DOC_SYSTEM_PROMPT) to delimit each
5
+ * page with a line `=== PAGE: <slug> | <Title> ===`. This splits that response
6
+ * into individual pages. If the model ignored the format, the whole response is
7
+ * returned as a single "ai-overview" page so content is never lost.
8
+ */
9
+
10
+ export interface AiDocPage {
11
+ /** lowercase-kebab, English, identical across languages (used as the filename) */
12
+ slug: string;
13
+ title: string;
14
+ body: string;
15
+ }
16
+
17
+ const PAGE_DELIMITER = /^===\s*PAGE:\s*(.+?)\s*\|\s*(.*?)\s*===\s*$/;
18
+
19
+ /** Turn an arbitrary heading into a safe lowercase-kebab slug. */
20
+ export function slugify(raw: string): string {
21
+ const slug = (raw ?? "")
22
+ .toLowerCase()
23
+ .normalize("NFKD")
24
+ .replace(/[^a-z0-9]+/g, "-")
25
+ .replace(/^-+|-+$/g, "")
26
+ .slice(0, 60);
27
+ return slug || "page";
28
+ }
29
+
30
+ export function parseAiPages(markdown: string): AiDocPage[] {
31
+ const text = (markdown ?? "").replace(/\r\n/g, "\n").trim();
32
+ if (!text) return [];
33
+
34
+ const pages: AiDocPage[] = [];
35
+ let current: { slug: string; title: string; body: string[] } | null = null;
36
+
37
+ const flush = () => {
38
+ if (current) {
39
+ pages.push({ slug: current.slug, title: current.title, body: current.body.join("\n").trim() });
40
+ }
41
+ };
42
+
43
+ for (const line of text.split("\n")) {
44
+ const match = line.match(PAGE_DELIMITER);
45
+ if (match) {
46
+ flush();
47
+ const rawSlug = match[1].trim();
48
+ const title = match[2].trim() || rawSlug;
49
+ current = { slug: slugify(rawSlug), title, body: [] };
50
+ } else if (current) {
51
+ current.body.push(line);
52
+ }
53
+ }
54
+ flush();
55
+
56
+ const withBody = pages.filter((page) => page.body.length > 0);
57
+ if (withBody.length === 0) {
58
+ return [{ slug: "ai-overview", title: "Overview", body: text }];
59
+ }
60
+
61
+ // De-duplicate slugs within a single response (suffix later collisions).
62
+ const seen = new Map<string, number>();
63
+ return withBody.map((page) => {
64
+ const count = seen.get(page.slug) ?? 0;
65
+ seen.set(page.slug, count + 1);
66
+ return count === 0 ? page : { ...page, slug: `${page.slug}-${count + 1}` };
67
+ });
68
+ }