@doxbrix/doxloop 0.1.3 → 0.1.4
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 +31 -0
- package/README.md +96 -41
- package/assets/doxbrix-preview.css +8 -0
- package/dist/agents.d.ts +4 -0
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +9 -0
- package/dist/agents.js.map +1 -1
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +2 -1
- package/dist/args.js.map +1 -1
- package/dist/auth.js +47 -4
- package/dist/auth.js.map +1 -1
- package/dist/author.d.ts +3 -5
- package/dist/author.d.ts.map +1 -1
- package/dist/author.js +7 -4
- package/dist/author.js.map +1 -1
- package/dist/cli.js +346 -72
- package/dist/cli.js.map +1 -1
- package/dist/doxbrix-markdown.js +39 -1
- package/dist/doxbrix-markdown.js.map +1 -1
- package/dist/interactive.d.ts +17 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +345 -0
- package/dist/interactive.js.map +1 -0
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +194 -0
- package/dist/preview.js.map +1 -1
- package/dist/project.d.ts +8 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +124 -11
- package/dist/project.js.map +1 -1
- package/dist/prompts.d.ts +41 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +290 -0
- package/dist/prompts.js.map +1 -0
- package/dist/settings.d.ts +6 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +519 -0
- package/dist/settings.js.map +1 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +46 -0
- package/dist/sync.js.map +1 -1
- package/dist/types.d.ts +18 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/ci-and-automation.md +10 -0
- package/docs/doxbrix-http-api.md +2 -1
- package/docs/project-format.md +13 -1
- package/docs/security-model.md +4 -2
- package/package.json +1 -1
- package/skills/doxloop-authoring/references/project-format.md +20 -0
- package/dist/public-deploy-confirmation.d.ts +0 -5
- package/dist/public-deploy-confirmation.d.ts.map +0 -1
- package/dist/public-deploy-confirmation.js +0 -22
- package/dist/public-deploy-confirmation.js.map +0 -1
package/dist/author.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"author.js","sourceRoot":"","sources":["../src/author.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,KAAK,MAAM,aAAa,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AACtF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"author.js","sourceRoot":"","sources":["../src/author.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { mkdir, readFile } from 'node:fs/promises';
|
|
3
|
+
import { join, relative, resolve } from 'node:path';
|
|
3
4
|
import { assertAllowedFlags, booleanFlag, flag, flags, numberFlag, parseArgs, } from './args.js';
|
|
4
|
-
import {
|
|
5
|
-
import { login, logout, whoami } from './auth.js';
|
|
5
|
+
import { installSkill, parseAgent, skillStatus } from './agents.js';
|
|
6
|
+
import { loadUserConfig, login, logout, whoami } from './auth.js';
|
|
6
7
|
import { parseReasoning, resolveScreenshotIntent, runAuthor, } from './author.js';
|
|
7
8
|
import { capture } from './capture.js';
|
|
8
9
|
import { deploy } from './deploy.js';
|
|
9
10
|
import { formatDoctorReport, runDoctor } from './doctor.js';
|
|
10
11
|
import { DoxloopError, UsageError } from './errors.js';
|
|
11
12
|
import { addGenerator, diagnoseGenerator, formatGeneratorInfo, formatGeneratorList, removeGenerator, } from './generator-manager.js';
|
|
12
|
-
import { GENERATOR_CATALOG, parseGenerator } from './generators.js';
|
|
13
|
-
import {
|
|
13
|
+
import { GENERATOR_CATALOG, generatorCatalogEntry, parseGenerator, resolveGeneratorPackage, } from './generators.js';
|
|
14
|
+
import { formatInitPlan, promptForRequest, replayInitCommand, runCreateRescueWizard, runInitWizard, selectAgentInteractive, } from './interactive.js';
|
|
15
|
+
import { addDesignReferences, assertNewProjectDirectory, findProjectRoot, isSpecUrl, loadProject, parseDesignReference, parseSource, parseSpec, resolveSeparateProjectLayout, saveDefaultAgent, scaffoldProject, validateProjectSourceBoundaries, } from './project.js';
|
|
16
|
+
import { isInteractive, promptConfirm } from './prompts.js';
|
|
14
17
|
import { startPreview } from './preview.js';
|
|
15
|
-
import {
|
|
18
|
+
import { effectiveDeployment, formatProjectSettings, runSettingsWizard, } from './settings.js';
|
|
19
|
+
import { collectSourceChanges, formatSourceChanges } from './sync.js';
|
|
16
20
|
import { formatValidation, validateProject } from './validation.js';
|
|
17
21
|
import { VERSION } from './version.js';
|
|
18
22
|
async function main() {
|
|
@@ -48,7 +52,9 @@ async function main() {
|
|
|
48
52
|
return report.ready ? 0 : 1;
|
|
49
53
|
}
|
|
50
54
|
case 'create':
|
|
51
|
-
if (flag(args, 'source') !== undefined ||
|
|
55
|
+
if (flag(args, 'source') !== undefined ||
|
|
56
|
+
flag(args, 'output') !== undefined ||
|
|
57
|
+
flags(args, 'spec').length > 0) {
|
|
52
58
|
return createProjectCommand(args, cwd);
|
|
53
59
|
}
|
|
54
60
|
return authorCommand(args, cwd, 'create');
|
|
@@ -73,6 +79,15 @@ async function main() {
|
|
|
73
79
|
}
|
|
74
80
|
case 'status':
|
|
75
81
|
return statusCommand(cwd, outputFormat(flag(args, 'format')));
|
|
82
|
+
case 'settings': {
|
|
83
|
+
const root = await findProjectRoot(cwd);
|
|
84
|
+
if (!isInteractive(args)) {
|
|
85
|
+
process.stdout.write(`${formatProjectSettings(root, await loadProject(root))}\n`);
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
await runSettingsWizard(root, cwd, promptIo());
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
76
91
|
case 'preview': {
|
|
77
92
|
const root = await findProjectRoot(cwd);
|
|
78
93
|
await startPreview({
|
|
@@ -102,21 +117,54 @@ async function main() {
|
|
|
102
117
|
return 0;
|
|
103
118
|
case 'deploy': {
|
|
104
119
|
const root = await findProjectRoot(cwd);
|
|
105
|
-
const
|
|
106
|
-
const
|
|
107
|
-
const
|
|
120
|
+
const project = await loadProject(root);
|
|
121
|
+
const userConfig = await loadUserConfig();
|
|
122
|
+
const savedDeployment = effectiveDeployment(project, userConfig.apiUrl);
|
|
123
|
+
const name = flag(args, 'name') ?? savedDeployment.name;
|
|
124
|
+
const slug = flag(args, 'slug') ?? savedDeployment.slug;
|
|
125
|
+
const apiOverride = flag(args, 'api-url') ?? savedDeployment.apiUrl;
|
|
108
126
|
const dryRun = booleanFlag(args, 'dry-run');
|
|
109
|
-
const publicSite =
|
|
110
|
-
|
|
111
|
-
|
|
127
|
+
const publicSite = flag(args, 'public') !== undefined
|
|
128
|
+
? booleanFlag(args, 'public')
|
|
129
|
+
: savedDeployment.visibility === 'public';
|
|
130
|
+
if (isInteractive(args) && !dryRun) {
|
|
131
|
+
const validation = await validateProject(root);
|
|
132
|
+
if (validation.errors > 0) {
|
|
133
|
+
throw new DoxloopError(`Deployment stopped because documentation has ${validation.errors} validation error${validation.errors === 1 ? '' : 's'}. Run \`doxloop test\`.`);
|
|
134
|
+
}
|
|
135
|
+
process.stdout.write(`\nDeployment summary\n\n Project: ${name}\n Slug: ${slug}\n Destination: ${apiOverride}\n Visibility: ${publicSite ? 'PUBLIC' : 'Private'}\n Pages: ${validation.pages.length}\n Warnings: ${validation.warnings}\n Product files: 0\n\n`);
|
|
136
|
+
if (publicSite) {
|
|
137
|
+
process.stdout.write('Anyone on the internet will be able to access this documentation.\n\n');
|
|
138
|
+
}
|
|
139
|
+
const proceed = await promptConfirm({
|
|
140
|
+
message: publicSite ? 'Deploy publicly?' : 'Deploy now?',
|
|
141
|
+
initial: !publicSite,
|
|
142
|
+
});
|
|
143
|
+
if (!proceed) {
|
|
144
|
+
process.stdout.write('Deployment canceled. No data was uploaded.\n');
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
147
|
+
const token = userConfig.token ?? process.env.DOXLOOP_TOKEN ?? process.env.DOXBRIX_TOKEN;
|
|
148
|
+
if (!token) {
|
|
149
|
+
process.stdout.write('You are not signed in to Doxbrix.\n');
|
|
150
|
+
const signIn = await promptConfirm({
|
|
151
|
+
message: 'Sign in now?',
|
|
152
|
+
initial: true,
|
|
153
|
+
});
|
|
154
|
+
if (!signIn) {
|
|
155
|
+
process.stdout.write('Deployment canceled. No data was uploaded.\n');
|
|
156
|
+
return 0;
|
|
157
|
+
}
|
|
158
|
+
await login({ apiUrl: apiOverride });
|
|
159
|
+
}
|
|
112
160
|
}
|
|
113
161
|
await deploy({
|
|
114
162
|
root,
|
|
115
|
-
|
|
116
|
-
|
|
163
|
+
name,
|
|
164
|
+
slug,
|
|
117
165
|
dryRun,
|
|
118
166
|
public: publicSite,
|
|
119
|
-
|
|
167
|
+
apiUrl: apiOverride,
|
|
120
168
|
});
|
|
121
169
|
return 0;
|
|
122
170
|
}
|
|
@@ -125,100 +173,248 @@ async function main() {
|
|
|
125
173
|
}
|
|
126
174
|
}
|
|
127
175
|
async function initCommand(args, cwd) {
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
176
|
+
const providedDirectory = args.positionals[0];
|
|
177
|
+
let sources = [
|
|
178
|
+
...flags(args, 'source').map(parseSource),
|
|
179
|
+
...flags(args, 'spec').map(parseSpec),
|
|
180
|
+
];
|
|
181
|
+
let title = flag(args, 'title');
|
|
182
|
+
let generator = parseGenerator(flag(args, 'generator'));
|
|
183
|
+
let fromWizard = false;
|
|
184
|
+
let directory = providedDirectory;
|
|
185
|
+
if (!providedDirectory) {
|
|
186
|
+
if (!isInteractive(args)) {
|
|
187
|
+
throw new UsageError('Guided setup requires an interactive terminal. For automation, use `doxloop init <directory>` with optional --source or --spec values.');
|
|
188
|
+
}
|
|
189
|
+
const plan = await runInitWizard(cwd);
|
|
190
|
+
directory = plan.directory;
|
|
191
|
+
if (sources.length === 0)
|
|
192
|
+
sources = plan.sources;
|
|
193
|
+
title = title ?? plan.title;
|
|
194
|
+
generator = generator ?? plan.generator;
|
|
195
|
+
fromWizard = true;
|
|
196
|
+
}
|
|
131
197
|
if (args.positionals.length > 1) {
|
|
132
198
|
throw new UsageError('The init command accepts one destination directory.');
|
|
133
199
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
const projectRoot = resolve(cwd, directory);
|
|
139
|
-
await validateProjectSourceBoundaries(projectRoot, sources);
|
|
140
|
-
const root = await scaffoldProject({
|
|
141
|
-
directory: projectRoot,
|
|
200
|
+
if (!directory)
|
|
201
|
+
throw new UsageError('A documentation project directory is required.');
|
|
202
|
+
const plan = {
|
|
203
|
+
directory,
|
|
142
204
|
...(title ? { title } : {}),
|
|
143
205
|
sources,
|
|
206
|
+
generator: generator ?? 'doxbrix',
|
|
207
|
+
};
|
|
208
|
+
if (fromWizard && !(await confirmInitPlan(cwd, plan))) {
|
|
209
|
+
process.stdout.write('Setup canceled. No project was created.\n');
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
const root = await initializeProject(args, cwd, plan, flags(args, 'reference').map(parseDesignReference));
|
|
213
|
+
if (fromWizard) {
|
|
214
|
+
process.stdout.write(`\nRerun this setup non-interactively:\n ${replayInitCommand(plan)}\n`);
|
|
215
|
+
}
|
|
216
|
+
process.stdout.write(`\nNext:\n cd ${directory}\n doxloop create\n doxloop preview --open\n doxloop test\n`);
|
|
217
|
+
return 0;
|
|
218
|
+
}
|
|
219
|
+
async function confirmInitPlan(cwd, plan) {
|
|
220
|
+
process.stdout.write(`\n${formatInitPlan(cwd, plan)}\n\n`);
|
|
221
|
+
return promptConfirm({ message: 'Create this project?', initial: true });
|
|
222
|
+
}
|
|
223
|
+
async function initializeProject(args, cwd, plan, designReferences = []) {
|
|
224
|
+
const projectRoot = resolve(cwd, plan.directory);
|
|
225
|
+
await validateProjectSourceBoundaries(projectRoot, plan.sources);
|
|
226
|
+
if (plan.generator !== 'doxbrix') {
|
|
227
|
+
await ensureGeneratorAvailable(args, projectRoot, plan.generator);
|
|
228
|
+
}
|
|
229
|
+
const root = await scaffoldProject({
|
|
230
|
+
directory: projectRoot,
|
|
231
|
+
...(plan.title ? { title: plan.title } : {}),
|
|
232
|
+
sources: plan.sources,
|
|
144
233
|
designReferences,
|
|
145
|
-
|
|
234
|
+
generator: plan.generator,
|
|
146
235
|
});
|
|
147
236
|
const installs = await installSkill({ root });
|
|
148
237
|
process.stdout.write(`Created Doxloop project at ${root}\n`);
|
|
149
238
|
for (const install of installs) {
|
|
150
239
|
process.stdout.write(`${install.action}: ${install.path}\n`);
|
|
151
240
|
}
|
|
152
|
-
|
|
153
|
-
|
|
241
|
+
return root;
|
|
242
|
+
}
|
|
243
|
+
async function ensureGeneratorAvailable(args, projectRoot, generator) {
|
|
244
|
+
const entry = generatorCatalogEntry(generator);
|
|
245
|
+
if (!entry?.packageName)
|
|
246
|
+
return;
|
|
247
|
+
if (resolveGeneratorPackage(projectRoot, entry.packageName))
|
|
248
|
+
return;
|
|
249
|
+
if (isInteractive(args)) {
|
|
250
|
+
const install = await promptConfirm({
|
|
251
|
+
message: `${entry.displayName} support needs ${entry.packageName}. Install it into the new project now?`,
|
|
252
|
+
initial: true,
|
|
253
|
+
});
|
|
254
|
+
if (!install) {
|
|
255
|
+
throw new DoxloopError(`${entry.displayName} support is not installed. Install it with \`doxloop generator add ${generator}\` inside the documentation project.`, 2);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
await mkdir(projectRoot, { recursive: true });
|
|
259
|
+
await addGenerator(projectRoot, generator);
|
|
154
260
|
}
|
|
155
261
|
async function createProjectCommand(args, cwd) {
|
|
156
262
|
const source = flag(args, 'source');
|
|
157
263
|
const output = flag(args, 'output');
|
|
158
|
-
|
|
159
|
-
|
|
264
|
+
const specs = flags(args, 'spec').map(parseSpec);
|
|
265
|
+
if (!output || (!source && specs.length === 0)) {
|
|
266
|
+
throw new UsageError('Creating a new documentation project requires `--output <documentation-directory>` plus `--source <product-directory>`, `--spec <openapi-file-or-url>`, or both.');
|
|
160
267
|
}
|
|
161
268
|
if (flags(args, 'source').length > 1 || flags(args, 'output').length > 1) {
|
|
162
269
|
throw new UsageError('The first-run create command accepts one source and one output directory.');
|
|
163
270
|
}
|
|
164
|
-
const layout =
|
|
165
|
-
|
|
271
|
+
const layout = source
|
|
272
|
+
? await resolveSeparateProjectLayout({ cwd, source, output })
|
|
273
|
+
: undefined;
|
|
274
|
+
const projectRoot = layout?.projectRoot ?? resolve(cwd, output);
|
|
275
|
+
const sources = [
|
|
276
|
+
...(layout ? [layout.sourceBinding] : []),
|
|
277
|
+
...specs.map((spec) => projectRelativeSpec(spec, cwd, projectRoot)),
|
|
278
|
+
];
|
|
166
279
|
const print = booleanFlag(args, 'print');
|
|
167
|
-
const selectedAgent = print ? requestedAgent : (await chooseAgent(requestedAgent)).name;
|
|
168
280
|
const designReferences = flags(args, 'reference').map(parseDesignReference);
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
281
|
+
if (!layout)
|
|
282
|
+
await assertNewProjectDirectory(projectRoot);
|
|
283
|
+
await validateProjectSourceBoundaries(projectRoot, sources);
|
|
284
|
+
const sourceText = layout
|
|
285
|
+
? `Product source:\n ${layout.sourceRoot}\n Read-only — product files will not be changed or deployed.\n\n`
|
|
286
|
+
: specs.length > 0
|
|
287
|
+
? `API specification${specs.length === 1 ? '' : 's'}:\n${specs.map((spec) => ` ${spec.path}`).join('\n')}\n Read-only API evidence.\n\n`
|
|
288
|
+
: '';
|
|
289
|
+
process.stdout.write(`Welcome to Doxloop\n\n${sourceText}Documentation project:\n ${projectRoot}\n Only this project can be previewed or deployed.\n\n`);
|
|
176
290
|
const root = await scaffoldProject({
|
|
177
|
-
directory:
|
|
178
|
-
sources
|
|
291
|
+
directory: projectRoot,
|
|
292
|
+
sources,
|
|
179
293
|
designReferences,
|
|
180
294
|
});
|
|
181
295
|
if (print) {
|
|
296
|
+
const requestedAgent = parseAgent(flag(args, 'agent'));
|
|
182
297
|
await installSkill({
|
|
183
298
|
root,
|
|
184
|
-
...(
|
|
299
|
+
...(requestedAgent ? { agent: requestedAgent } : {}),
|
|
185
300
|
});
|
|
186
301
|
}
|
|
187
|
-
const result = await
|
|
188
|
-
root,
|
|
189
|
-
mode: 'create',
|
|
190
|
-
...(selectedAgent ? { agent: selectedAgent } : {}),
|
|
191
|
-
...(model ? { model } : {}),
|
|
192
|
-
...(reasoning ? { reasoning } : {}),
|
|
193
|
-
screenshots,
|
|
194
|
-
print,
|
|
195
|
-
...(args.positionals.length > 0
|
|
196
|
-
? { request: args.positionals.join(' ') }
|
|
197
|
-
: {}),
|
|
198
|
-
});
|
|
199
|
-
if (result === 0 && !print) {
|
|
200
|
-
const validation = await validateProject(root);
|
|
201
|
-
process.stdout.write(`\nDocumentation created successfully.\n\nPages created: ${validation.pages.length}\nDocumentation project: ${root}\nProduct source files included in deployment: 0\n\nPreview the documentation:\n cd ${root}\n doxloop preview --open\n\nWhen the product changes:\n cd ${root}\n doxloop update\n`);
|
|
202
|
-
}
|
|
302
|
+
const result = await authorCommand(args, root, 'create');
|
|
203
303
|
return result;
|
|
204
304
|
}
|
|
205
305
|
async function authorCommand(args, cwd, mode) {
|
|
206
|
-
const
|
|
306
|
+
const interactive = isInteractive(args);
|
|
307
|
+
const print = booleanFlag(args, 'print');
|
|
308
|
+
let root;
|
|
309
|
+
try {
|
|
310
|
+
root = await findProjectRoot(cwd);
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
if (mode === 'create' && interactive && !print) {
|
|
314
|
+
const plan = await runCreateRescueWizard(cwd, promptIo());
|
|
315
|
+
if (plan) {
|
|
316
|
+
if (!(await confirmInitPlan(cwd, plan))) {
|
|
317
|
+
process.stdout.write('Setup canceled. No project was created.\n');
|
|
318
|
+
return 0;
|
|
319
|
+
}
|
|
320
|
+
root = await initializeProject(args, cwd, plan);
|
|
321
|
+
process.stdout.write('\nSetup complete. Tell Doxloop what documentation to create.\n\n');
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
throw error;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
throw error;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
const project = await loadProject(root);
|
|
207
332
|
if (mode !== 'review') {
|
|
208
|
-
const project = await loadProject(root);
|
|
209
333
|
await validateProjectSourceBoundaries(root, project.sources);
|
|
210
334
|
}
|
|
211
|
-
|
|
212
|
-
|
|
335
|
+
let selectedAgent = parseAgent(flag(args, 'agent')) ?? project.defaultAgent;
|
|
336
|
+
let request = args.positionals.join(' ') || undefined;
|
|
337
|
+
let changeSummary;
|
|
338
|
+
let requestedInteractively = false;
|
|
339
|
+
let offerToRememberAgent = false;
|
|
340
|
+
if (mode === 'update') {
|
|
341
|
+
if (interactive && !print && !(await hasCompletedAuthoringRun(root))) {
|
|
342
|
+
process.stdout.write('This project has not completed its first documentation run yet.\n\nNext:\n doxloop create\n');
|
|
343
|
+
return 0;
|
|
344
|
+
}
|
|
345
|
+
if (project.sources.length === 0) {
|
|
346
|
+
if (interactive && !print) {
|
|
347
|
+
process.stdout.write('No product source or API specification is configured.\nUse `doxloop settings` to add evidence, or describe a documentation-only change below.\n\n');
|
|
348
|
+
if (!request) {
|
|
349
|
+
request = await promptForRequest('update', promptIo(), false);
|
|
350
|
+
requestedInteractively = true;
|
|
351
|
+
if (!request) {
|
|
352
|
+
process.stdout.write('No documentation change requested.\n');
|
|
353
|
+
return 0;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
const changes = await collectSourceChanges(root, project.sources);
|
|
360
|
+
changeSummary = formatSourceChanges(changes);
|
|
361
|
+
if (interactive && !print) {
|
|
362
|
+
process.stdout.write(`${formatSourceChangeOverview(changes)}\n\n`);
|
|
363
|
+
if (!hasPendingSourceChanges(changes) && !request) {
|
|
364
|
+
const proceed = await promptConfirm({
|
|
365
|
+
message: 'Documentation is synchronized. Make a documentation-only change?',
|
|
366
|
+
initial: false,
|
|
367
|
+
});
|
|
368
|
+
if (!proceed) {
|
|
369
|
+
process.stdout.write('Documentation is synchronized with the recorded source baseline.\n');
|
|
370
|
+
return 0;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (interactive &&
|
|
377
|
+
!print &&
|
|
378
|
+
!request &&
|
|
379
|
+
!requestedInteractively &&
|
|
380
|
+
(mode === 'create' || mode === 'update')) {
|
|
381
|
+
request = await promptForRequest(mode, promptIo(), project.sources.length > 0);
|
|
382
|
+
}
|
|
383
|
+
if (interactive && !print && !selectedAgent) {
|
|
384
|
+
selectedAgent = await selectAgentInteractive(promptIo());
|
|
385
|
+
if (selectedAgent && mode !== 'review' && !project.defaultAgent) {
|
|
386
|
+
offerToRememberAgent = true;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
if (interactive && !print && mode === 'create') {
|
|
390
|
+
process.stdout.write(`\nAuthoring summary\n\n Project: ${project.title}\n Evidence: ${project.sources.length === 0 ? 'None yet' : `${project.sources.length} configured source${project.sources.length === 1 ? '' : 's'}`}\n Generator: ${project.generator}\n Agent: ${selectedAgent ?? 'Automatically detected'}\n Request: ${request ?? 'Let the agent propose a documentation plan'}\n\n`);
|
|
391
|
+
const proceed = await promptConfirm({
|
|
392
|
+
message: 'Start creating documentation?',
|
|
393
|
+
initial: true,
|
|
394
|
+
});
|
|
395
|
+
if (!proceed) {
|
|
396
|
+
process.stdout.write('Authoring canceled. Project settings were preserved.\n');
|
|
397
|
+
return 0;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (offerToRememberAgent && selectedAgent) {
|
|
401
|
+
const remember = await promptConfirm({
|
|
402
|
+
message: `Remember ${selectedAgent} as this project's default agent?`,
|
|
403
|
+
initial: true,
|
|
404
|
+
});
|
|
405
|
+
if (remember)
|
|
406
|
+
await saveDefaultAgent(root, selectedAgent);
|
|
407
|
+
}
|
|
213
408
|
const designReferences = flags(args, 'reference').map(parseDesignReference);
|
|
214
409
|
if (mode !== 'review')
|
|
215
410
|
await addDesignReferences(root, designReferences);
|
|
216
411
|
const model = flag(args, 'model');
|
|
217
412
|
const reasoning = parseReasoning(flag(args, 'reasoning'));
|
|
218
413
|
const screenshots = screenshotIntent(args);
|
|
219
|
-
|
|
414
|
+
const result = await runAuthor({
|
|
220
415
|
root,
|
|
221
416
|
mode,
|
|
417
|
+
...(changeSummary !== undefined ? { changeSummary } : {}),
|
|
222
418
|
...(selectedAgent ? { agent: selectedAgent } : {}),
|
|
223
419
|
...(model ? { model } : {}),
|
|
224
420
|
...(reasoning ? { reasoning } : {}),
|
|
@@ -237,6 +433,11 @@ async function authorCommand(args, cwd, mode) {
|
|
|
237
433
|
}
|
|
238
434
|
: {}),
|
|
239
435
|
});
|
|
436
|
+
if (result === 0 && !print && mode === 'create') {
|
|
437
|
+
const validation = await validateProject(root);
|
|
438
|
+
process.stdout.write(`\nDocumentation created successfully.\n\nPages created: ${validation.pages.length}\nDocumentation project: ${root}\nProduct source files included in deployment: 0\n\nNext:\n cd ${root}\n doxloop preview --open\n doxloop test\n\nWhen the product changes:\n doxloop update\n`);
|
|
439
|
+
}
|
|
440
|
+
return result;
|
|
240
441
|
}
|
|
241
442
|
async function agentCommand(args, cwd) {
|
|
242
443
|
const action = args.positionals[0];
|
|
@@ -294,6 +495,7 @@ async function generatorCommand(args, cwd) {
|
|
|
294
495
|
async function statusCommand(cwd, format) {
|
|
295
496
|
const root = await findProjectRoot(cwd);
|
|
296
497
|
const project = await loadProject(root);
|
|
498
|
+
const deployment = effectiveDeployment(project);
|
|
297
499
|
const result = await validateProject(root);
|
|
298
500
|
if (format === 'json') {
|
|
299
501
|
process.stdout.write(`${JSON.stringify({
|
|
@@ -304,12 +506,13 @@ async function statusCommand(cwd, format) {
|
|
|
304
506
|
sources: project.sources,
|
|
305
507
|
designReferences: project.designReferences,
|
|
306
508
|
...(project.application ? { application: project.application } : {}),
|
|
509
|
+
deployment,
|
|
307
510
|
errors: result.errors,
|
|
308
511
|
warnings: result.warnings,
|
|
309
512
|
}, null, 2)}\n`);
|
|
310
513
|
}
|
|
311
514
|
else {
|
|
312
|
-
process.stdout.write(`${project.title}\nRoot: ${root}\nGenerator: ${project.generator}\nPages: ${result.pages.length}\nSources: ${project.sources.length}\nDesign references: ${project.designReferences.length}\nApplication screenshots: ${project.application ? `${project.application.screenshots?.policy ?? 'requested'} (${project.application.baseUrl})` : 'not configured'}\nErrors: ${result.errors}\nWarnings: ${result.warnings}\n`);
|
|
515
|
+
process.stdout.write(`${project.title}\nRoot: ${root}\nGenerator: ${project.generator}\nPages: ${result.pages.length}\nSources: ${project.sources.length}\nDesign references: ${project.designReferences.length}\nApplication screenshots: ${project.application ? `${project.application.screenshots?.policy ?? 'requested'} (${project.application.baseUrl})` : 'not configured'}\nDeployment: ${deployment.slug} (${deployment.visibility}) → ${deployment.apiUrl}\nErrors: ${result.errors}\nWarnings: ${result.warnings}\n`);
|
|
313
516
|
for (const source of project.sources) {
|
|
314
517
|
process.stdout.write(`source ${source.name}: ${source.path}\n`);
|
|
315
518
|
}
|
|
@@ -318,16 +521,17 @@ async function statusCommand(cwd, format) {
|
|
|
318
521
|
}
|
|
319
522
|
function validateCommandArguments(args) {
|
|
320
523
|
const allowed = {
|
|
321
|
-
init: ['title', 'source', 'reference', 'generator'],
|
|
524
|
+
init: ['title', 'source', 'spec', 'reference', 'generator'],
|
|
322
525
|
agent: ['agent'],
|
|
323
526
|
generator: [],
|
|
324
527
|
doctor: ['source', 'output', 'agent'],
|
|
325
|
-
create: ['agent', 'model', 'reasoning', 'reference', 'print', 'screenshots', 'no-screenshots', 'source', 'output'],
|
|
528
|
+
create: ['agent', 'model', 'reasoning', 'reference', 'print', 'screenshots', 'no-screenshots', 'source', 'spec', 'output'],
|
|
326
529
|
update: ['agent', 'model', 'reasoning', 'reference', 'print', 'screenshots', 'no-screenshots'],
|
|
327
530
|
review: ['agent', 'model', 'reasoning', 'reference', 'print'],
|
|
328
531
|
capture: [],
|
|
329
532
|
test: ['format'],
|
|
330
533
|
status: ['format'],
|
|
534
|
+
settings: [],
|
|
331
535
|
preview: ['host', 'port', 'open'],
|
|
332
536
|
login: ['api-url', 'token'],
|
|
333
537
|
logout: [],
|
|
@@ -347,6 +551,49 @@ function validateCommandArguments(args) {
|
|
|
347
551
|
throw new UsageError(`The ${args.command} command does not accept arguments.`);
|
|
348
552
|
}
|
|
349
553
|
}
|
|
554
|
+
function promptIo() {
|
|
555
|
+
return { input: process.stdin, output: process.stdout };
|
|
556
|
+
}
|
|
557
|
+
function hasPendingSourceChanges(changes) {
|
|
558
|
+
return changes.some((change) => change.kind !== 'unchanged' && change.kind !== 'spec-unchanged');
|
|
559
|
+
}
|
|
560
|
+
function formatSourceChangeOverview(changes) {
|
|
561
|
+
const pending = changes.filter((change) => change.kind !== 'unchanged' && change.kind !== 'spec-unchanged');
|
|
562
|
+
const committedFiles = changes.reduce((total, change) => total + (change.kind === 'changed' ? change.changedFiles.length : 0), 0);
|
|
563
|
+
const workingTreeFiles = changes.reduce((total, change) => total +
|
|
564
|
+
('uncommittedFiles' in change ? change.uncommittedFiles.length : 0), 0);
|
|
565
|
+
const status = pending.length === 0
|
|
566
|
+
? 'Synchronized'
|
|
567
|
+
: `${pending.length} source${pending.length === 1 ? '' : 's'} need inspection`;
|
|
568
|
+
return `Source check\n\n Sources checked: ${changes.length}\n Status: ${status}\n Committed files: ${committedFiles}\n Working-tree files: ${workingTreeFiles}`;
|
|
569
|
+
}
|
|
570
|
+
async function hasCompletedAuthoringRun(root) {
|
|
571
|
+
try {
|
|
572
|
+
const receipt = JSON.parse(await readFile(join(root, '.doxloop', 'last-run.json'), 'utf8'));
|
|
573
|
+
return ((receipt.mode === 'create' || receipt.mode === 'update') &&
|
|
574
|
+
typeof receipt.completedAt === 'string');
|
|
575
|
+
}
|
|
576
|
+
catch {
|
|
577
|
+
try {
|
|
578
|
+
const syncState = JSON.parse(await readFile(join(root, '.doxloop', 'sync-state.json'), 'utf8'));
|
|
579
|
+
return (syncState.schemaVersion === 1 &&
|
|
580
|
+
syncState.sources !== null &&
|
|
581
|
+
typeof syncState.sources === 'object' &&
|
|
582
|
+
!Array.isArray(syncState.sources));
|
|
583
|
+
}
|
|
584
|
+
catch {
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
function projectRelativeSpec(spec, cwd, projectRoot) {
|
|
590
|
+
if (isSpecUrl(spec.path))
|
|
591
|
+
return spec;
|
|
592
|
+
return {
|
|
593
|
+
...spec,
|
|
594
|
+
path: relative(projectRoot, resolve(cwd, spec.path)).split('\\').join('/'),
|
|
595
|
+
};
|
|
596
|
+
}
|
|
350
597
|
function screenshotIntent(args) {
|
|
351
598
|
if (args.command === 'review')
|
|
352
599
|
return 'disabled';
|
|
@@ -361,16 +608,24 @@ function outputFormat(value) {
|
|
|
361
608
|
}
|
|
362
609
|
function help(command) {
|
|
363
610
|
if (command === 'init') {
|
|
364
|
-
return `Usage: doxloop init
|
|
611
|
+
return `Usage: doxloop init [directory] [options]
|
|
365
612
|
|
|
366
613
|
Create a local documentation project and install the authoring and format skills.
|
|
614
|
+
Run without arguments in a terminal to answer a short set of setup questions.
|
|
367
615
|
|
|
368
616
|
Options:
|
|
369
617
|
--title <title> Documentation site title
|
|
370
618
|
--source <name=path> Add a local product source; may be repeated
|
|
619
|
+
--spec <name=file|url> Add an OpenAPI specification as API evidence; may be repeated
|
|
371
620
|
--reference <url> Add a documentation design reference; may be repeated
|
|
372
621
|
--generator <name> Generator: ${GENERATOR_CATALOG.map((entry) => entry.id).join(', ')}
|
|
622
|
+
--yes Never prompt; fail instead of asking
|
|
373
623
|
--cwd <directory> Resolve paths from this directory
|
|
624
|
+
|
|
625
|
+
Examples:
|
|
626
|
+
doxloop init
|
|
627
|
+
doxloop init my-docs --source product=../my-app
|
|
628
|
+
doxloop init api-docs --spec https://example.com/openapi.json
|
|
374
629
|
`;
|
|
375
630
|
}
|
|
376
631
|
if (command === 'agent') {
|
|
@@ -421,10 +676,10 @@ Options:
|
|
|
421
676
|
--no-screenshots Do not capture application screenshots
|
|
422
677
|
`;
|
|
423
678
|
const createUsage = command === 'create'
|
|
424
|
-
? `\
|
|
679
|
+
? `\nRun inside a Doxloop project to answer a short set of authoring questions.\nWhen run inside a detected product repository, Doxloop offers the complete setup\nwizard first. No flags are required for interactive use.\n\nOptional automation form:\n doxloop create --source <product-directory> --output <documentation-directory> [request]\n doxloop create --spec <openapi-file-or-url> --output <documentation-directory> [request]\n`
|
|
425
680
|
: '';
|
|
426
681
|
const createOptions = command === 'create'
|
|
427
|
-
? ` --source <directory> Read-only product source for a new documentation project\n --output <directory> New, separate documentation project directory\n`
|
|
682
|
+
? ` --source <directory> Read-only product source for a new documentation project\n --spec <name=file|url> OpenAPI specification used as read-only API evidence\n --output <directory> New, separate documentation project directory\n`
|
|
428
683
|
: '';
|
|
429
684
|
return `Usage: doxloop ${command} [request] [options]
|
|
430
685
|
${createUsage}
|
|
@@ -473,6 +728,17 @@ ${command === 'test' ? 'Validate documentation structure and content.' : 'Summar
|
|
|
473
728
|
Options:
|
|
474
729
|
--format <text|json> Output format (default: text)
|
|
475
730
|
--cwd <directory> Run from this project directory
|
|
731
|
+
`;
|
|
732
|
+
}
|
|
733
|
+
if (command === 'settings') {
|
|
734
|
+
return `Usage: doxloop settings
|
|
735
|
+
|
|
736
|
+
View or interactively change the current project's evidence, identity, default
|
|
737
|
+
agent, documentation preferences, design references, screenshots, and
|
|
738
|
+
deployment settings. When output is not a terminal, prints the saved settings.
|
|
739
|
+
|
|
740
|
+
Options:
|
|
741
|
+
--cwd <directory> Run from this project directory
|
|
476
742
|
`;
|
|
477
743
|
}
|
|
478
744
|
if (command === 'login') {
|
|
@@ -511,6 +777,7 @@ Options:
|
|
|
511
777
|
--name <name> Hosted project name
|
|
512
778
|
--slug <slug> Hosted project slug
|
|
513
779
|
--api-url <url> Override the Doxbrix API base URL
|
|
780
|
+
--yes Use saved settings without prompting
|
|
514
781
|
--cwd <directory> Run from this project directory
|
|
515
782
|
`;
|
|
516
783
|
}
|
|
@@ -533,6 +800,7 @@ Author:
|
|
|
533
800
|
Verify:
|
|
534
801
|
doctor Check runtime, source, agent, generator, skills, and documentation
|
|
535
802
|
status Summarize the documentation project
|
|
803
|
+
settings View or change project settings
|
|
536
804
|
test Validate pages, navigation, links, and code fences
|
|
537
805
|
preview Run a beautiful local preview
|
|
538
806
|
|
|
@@ -544,9 +812,15 @@ Publish:
|
|
|
544
812
|
|
|
545
813
|
Global options:
|
|
546
814
|
--cwd <directory> Run as if started in this directory
|
|
815
|
+
--yes Never prompt; accept safe defaults or fail instead of asking
|
|
547
816
|
-h, --help Show help
|
|
548
817
|
-v, --version Show version
|
|
549
818
|
|
|
819
|
+
Get started:
|
|
820
|
+
doxloop init Answer a few questions interactively
|
|
821
|
+
doxloop create Create docs from saved project settings
|
|
822
|
+
doxloop settings View or change project settings
|
|
823
|
+
|
|
550
824
|
Run \`doxloop <command> --help\` for command details.
|
|
551
825
|
`;
|
|
552
826
|
}
|