@x12i/made-easy-cli 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +54 -2
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +4 -0
- package/dist/bin.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +659 -0
- package/dist/index.js.map +1 -0
- package/dist/remote.d.ts +62 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +126 -0
- package/dist/remote.js.map +1 -0
- package/package.json +58 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 x12i
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,55 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @x12i/made-easy-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Command line for **Made Easy**: two guides from one bundle, one for people (the human guide) and one for the AI agent that works for them. Works on a local bundle, or against a hosted server with `--server`.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install -g @x12i/made-easy-cli
|
|
7
|
+
made-easy recipes
|
|
8
|
+
made-easy init --recipe sdk.quickstart --subject "ms" --out ./guide
|
|
9
|
+
made-easy validate ./guide
|
|
10
|
+
made-easy validate ./guide --mode release --audience public
|
|
11
|
+
made-easy build ./guide --out ./out --mode release --audience public
|
|
12
|
+
made-easy build ./guide --out ./out-md --mode release --audience public --format md # pure Markdown only, no browser
|
|
13
|
+
made-easy journey ./guide --out journey.svg
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The spec-style prefix also works: `made-easy guide validate ./guide`.
|
|
17
|
+
|
|
18
|
+
## Commands
|
|
19
|
+
|
|
20
|
+
| Command | What it does |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| `recipes [list]`, `recipes show <id>` | List recipes, or show one recipe's section roles |
|
|
23
|
+
| `init` | Scaffold a bundle from a recipe |
|
|
24
|
+
| `validate <path\|zip>` | Located diagnostics; `--mode draft\|release`, `--audience private\|public`, `--json` |
|
|
25
|
+
| `preview <path\|zip>` | Render one guide (`--track human\|agent`, `--format html\|markdown\|json`); the older track names `operator` and `brief` still mean `agent` |
|
|
26
|
+
| `build <path\|zip>` | `guide.pdf`, `index.html`, `agent/index.html`, `guide.md`, `agent-guide.md`, `brief.json`, manifest and ZIP into `--out`; `--format html,pdf,md` chooses (default `html,pdf`; `md` alone is a complete edition without a browser) |
|
|
27
|
+
| `journey <path>` | The whole job as one diagram: `--format svg\|mermaid\|md` (default `svg`), `--track human\|agent`, `--job-map <id>`, `--out <file>` |
|
|
28
|
+
| `pin <path>` | Record AI agent guide digests in `brief.yaml` (`--check` to verify only) |
|
|
29
|
+
| `review <path>` | Record a named human's review of AI-drafted text: `--by <party>` with `--claim <id>`, `--entry <id>` or `--all` (an attestation by name, not proof of identity) |
|
|
30
|
+
| `check-return <path> <file>` | Check an AI agent's return against the brief's return schema |
|
|
31
|
+
| `anchors <path>` | Add explicit `{#anchor}` to headings that lack one |
|
|
32
|
+
| `verify <path> --allow-exec` | Run executable examples and record the results |
|
|
33
|
+
| `resolve-npm <package>` | Resolve an exact npm version and integrity |
|
|
34
|
+
| `draft <path>` | Propose section text from a source snapshot (`--apply` to write it) |
|
|
35
|
+
| `job show\|cancel\|download <id>` | Work with build and draft jobs on a server |
|
|
36
|
+
| `serve`, `mcp` | Start the hosted server or the MCP stdio server (install the matching package) |
|
|
37
|
+
|
|
38
|
+
Exit codes: `0` success, `1` validation or build failed, `2` usage error, `3` internal or transport error. A partial build (for example HTML without a PDF) is private and exits `1` unless you pass `--allow-partial`. A Markdown-only build is complete and exits `0`.
|
|
39
|
+
|
|
40
|
+
## Remote mode
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
export MADE_EASY_URL=https://guides.example.com
|
|
44
|
+
export MADE_EASY_TOKEN=... # prefer the environment to --token
|
|
45
|
+
made-easy validate ./guide --mode release # runs on the server
|
|
46
|
+
made-easy build ./guide --out ./out --mode release --audience public
|
|
47
|
+
made-easy job show job-1234
|
|
48
|
+
made-easy job download job-1234 --out ./out
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`build` uploads the bundle, waits for the job and downloads the artifacts, checking every file against the digest the server reported. Add `--no-wait` to return the job instead. Use `--guide <id>` to build a guide already stored on the server.
|
|
52
|
+
|
|
53
|
+
Builds never read secrets, and bundles must not contain any: `SECRET_DETECTED` stops a release.
|
|
54
|
+
|
|
55
|
+
MIT © x12i · [Repository](https://github.com/x12i/made-easy)
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
|
package/dist/bin.js
ADDED
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,CAAC,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface CliIo {
|
|
2
|
+
out(text: string): void;
|
|
3
|
+
err(text: string): void;
|
|
4
|
+
cwd: string;
|
|
5
|
+
env: NodeJS.ProcessEnv;
|
|
6
|
+
}
|
|
7
|
+
export declare const defaultIo: CliIo;
|
|
8
|
+
/** Run the CLI. Returns the process exit code and never calls process.exit, so it is testable. */
|
|
9
|
+
export declare function run(argv: string[], io?: CliIo): Promise<number>;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,KAAK;IACpB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,eAAO,MAAM,SAAS,EAAE,KAKvB,CAAC;AAgiBF,kGAAkG;AAClG,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,KAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoChF"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { parseArgs } from 'node:util';
|
|
4
|
+
import { RemoteClient, RemoteError, readLocalBundle } from './remote.js';
|
|
5
|
+
import { VERSION, applyDraftProposal, buildGuide, createChatCompletionsAdapter, createGuide, createTemplateDraftAdapter, draftGuide, journeyGuide, listGuideRecipes, loadGuide, pinGuide, previewGuide, resolveNpmPackage, reviewGuide, stabilizeAnchors, validateAgentReturn, validateGuide, verifyExamples, writeBundle, MadeEasyError, SourceSnapshotSchema, getGuideRecipe, } from '@x12i/made-easy';
|
|
6
|
+
export const defaultIo = {
|
|
7
|
+
out: (t) => process.stdout.write(t),
|
|
8
|
+
err: (t) => process.stderr.write(t),
|
|
9
|
+
cwd: process.cwd(),
|
|
10
|
+
env: process.env,
|
|
11
|
+
};
|
|
12
|
+
const EXIT_OK = 0;
|
|
13
|
+
const EXIT_FAILED = 1;
|
|
14
|
+
const EXIT_USAGE = 2;
|
|
15
|
+
const EXIT_INTERNAL = 3;
|
|
16
|
+
class UsageError extends Error {
|
|
17
|
+
}
|
|
18
|
+
const HELP = `made-easy ${VERSION}
|
|
19
|
+
|
|
20
|
+
Two guides from one source bundle: a human guide for the people who decide and act, and an AI agent
|
|
21
|
+
guide written for the agent that does the work. Both can be built as pure Markdown (no browser needed).
|
|
22
|
+
|
|
23
|
+
Usage: made-easy <command> [options] (the spec-style form "made-easy guide <command>" also works)
|
|
24
|
+
|
|
25
|
+
Commands:
|
|
26
|
+
recipes [list] List recipes (profile.preset)
|
|
27
|
+
recipes show <id> Show one recipe: its section roles and requirements
|
|
28
|
+
init Scaffold a guide bundle: --recipe <id> --subject <name> --out <dir> [--recipe-version <v>]
|
|
29
|
+
validate <path|zip> Validate a bundle: [--mode draft|release] [--audience private|public] [--json]
|
|
30
|
+
preview <path|zip> Render one guide: [--track human|agent] [--format html|markdown|json] [--out <file>]
|
|
31
|
+
journey <path> Draw the job as a journey [--format svg|mermaid|md] [--track human|agent] [--job-map <id>] [--out <file>]
|
|
32
|
+
build <path|zip> Build outputs: --out <dir> [--mode] [--audience] [--format html,pdf,md] [--paper A4,Letter]
|
|
33
|
+
[--no-zip] [--allow-partial] [--overwrite] [--json]
|
|
34
|
+
(--format md builds only guide.md and agent-guide.md: no browser, complete)
|
|
35
|
+
pin <path> Record the AI agent guide's digests in brief.yaml [--all] [--check]
|
|
36
|
+
review <path> Record that a human read AI-drafted content --by <party> (--claim <id> | --entry <id> | --all)
|
|
37
|
+
check-return <path> <file> Check an agent's JSON return against the brief [--no-revision]
|
|
38
|
+
anchors <path> Add explicit {#anchor} to headings that lack one
|
|
39
|
+
verify <path> Run executable examples and record results --allow-exec [--only <id>]
|
|
40
|
+
resolve-npm <package> Resolve an exact npm version and integrity [--range <range>] [--registry <url>]
|
|
41
|
+
draft <path> Propose section text from a source snapshot --snapshot <file> --section <track:entry> [--apply]
|
|
42
|
+
job show <id> Show a build or draft job on a server [--json]
|
|
43
|
+
job cancel <id> Cancel a queued or running job
|
|
44
|
+
job download <id> Download a succeeded job's artifacts --out <dir>
|
|
45
|
+
serve Start the hosted service and Studio (needs @x12i/made-easy-server)
|
|
46
|
+
mcp Start the MCP server on stdio (needs @x12i/made-easy-mcp)
|
|
47
|
+
|
|
48
|
+
Remote mode (recipes, validate, preview, build, job):
|
|
49
|
+
--server <url> Use a hosted Made Easy server instead of local code (env MADE_EASY_URL)
|
|
50
|
+
--token <token> Bearer token; prefer the environment variable (env MADE_EASY_TOKEN)
|
|
51
|
+
--guide <id> Use a guide stored on the server instead of a local path [--revision <rev>]
|
|
52
|
+
build --server uploads the bundle, waits for the job and downloads the artifacts to --out
|
|
53
|
+
(add --no-wait to print the job and return).
|
|
54
|
+
|
|
55
|
+
Common options:
|
|
56
|
+
--json Machine-readable output (the same result shape the API and MCP tools return)
|
|
57
|
+
--help Show help for a command
|
|
58
|
+
--version Print the version
|
|
59
|
+
|
|
60
|
+
Exit codes: 0 success, 1 validation or build failed, 2 usage error, 3 internal error.
|
|
61
|
+
`;
|
|
62
|
+
function formatDiagnostic(d) {
|
|
63
|
+
const loc = d.line ? `${d.path}:${d.line}${d.column ? `:${d.column}` : ''}` : d.path;
|
|
64
|
+
const block = d.blockId ? ` [${d.blockId}]` : '';
|
|
65
|
+
const hint = d.hint ? `\n hint: ${d.hint}` : '';
|
|
66
|
+
return `${loc} ${d.severity.padEnd(7)} ${d.code}${block} ${d.message}${hint}`;
|
|
67
|
+
}
|
|
68
|
+
function printDiagnostics(io, diagnostics, showInfo) {
|
|
69
|
+
for (const d of diagnostics) {
|
|
70
|
+
if (d.severity === 'info' && !showInfo)
|
|
71
|
+
continue;
|
|
72
|
+
(d.severity === 'error' ? io.err : io.out)(`${formatDiagnostic(d)}\n`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function summaryLine(s) {
|
|
76
|
+
return `${s.errors} error(s), ${s.warnings} warning(s), ${s.infos} note(s)`;
|
|
77
|
+
}
|
|
78
|
+
const csv = (v) => (v ? v.split(',').map((x) => x.trim()).filter(Boolean) : undefined);
|
|
79
|
+
function mode(v) {
|
|
80
|
+
if (v === undefined)
|
|
81
|
+
return 'draft';
|
|
82
|
+
if (v !== 'draft' && v !== 'release')
|
|
83
|
+
throw new UsageError(`--mode must be "draft" or "release", not "${v}".`);
|
|
84
|
+
return v;
|
|
85
|
+
}
|
|
86
|
+
function audience(v) {
|
|
87
|
+
if (v === undefined)
|
|
88
|
+
return undefined;
|
|
89
|
+
if (v !== 'private' && v !== 'public')
|
|
90
|
+
throw new UsageError(`--audience must be "private" or "public", not "${v}".`);
|
|
91
|
+
return v;
|
|
92
|
+
}
|
|
93
|
+
const REMOTE_OPTIONS = {
|
|
94
|
+
server: { type: 'string' },
|
|
95
|
+
token: { type: 'string' },
|
|
96
|
+
guide: { type: 'string' },
|
|
97
|
+
revision: { type: 'string' },
|
|
98
|
+
};
|
|
99
|
+
/** A client when --server (or MADE_EASY_URL) is set, otherwise undefined and the command runs locally. */
|
|
100
|
+
function remoteOf(io, values) {
|
|
101
|
+
const server = values.server ?? io.env.MADE_EASY_URL;
|
|
102
|
+
if (!server)
|
|
103
|
+
return undefined;
|
|
104
|
+
return new RemoteClient({ server, token: values.token ?? io.env.MADE_EASY_TOKEN });
|
|
105
|
+
}
|
|
106
|
+
async function remoteSource(io, positional, values) {
|
|
107
|
+
if (values.guide)
|
|
108
|
+
return { kind: 'guide', guideId: values.guide, ...(values.revision ? { revision: values.revision } : {}) };
|
|
109
|
+
const p = positional[0];
|
|
110
|
+
if (!p)
|
|
111
|
+
throw new UsageError('Give a bundle path (a directory or .zip), or --guide <id> for a guide stored on the server.');
|
|
112
|
+
const abs = resolve(io.cwd, p);
|
|
113
|
+
if (abs.toLowerCase().endsWith('.zip'))
|
|
114
|
+
return { kind: 'zip', base64: (await readFile(abs)).toString('base64') };
|
|
115
|
+
return { kind: 'files', files: await readLocalBundle(abs) };
|
|
116
|
+
}
|
|
117
|
+
function input(io, positional) {
|
|
118
|
+
const p = positional[0];
|
|
119
|
+
if (!p)
|
|
120
|
+
throw new UsageError('A bundle path (a directory or .zip) is required.');
|
|
121
|
+
return resolve(io.cwd, p);
|
|
122
|
+
}
|
|
123
|
+
async function dispatch(command, args, io) {
|
|
124
|
+
const shared = { json: { type: 'boolean' }, help: { type: 'boolean' } };
|
|
125
|
+
const parse = (options) => {
|
|
126
|
+
try {
|
|
127
|
+
return parseArgs({ args, options: { ...shared, ...options }, allowPositionals: true, strict: true });
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
throw new UsageError(e.message);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
const emitJson = (v) => io.out(`${JSON.stringify(v, null, 2)}\n`);
|
|
134
|
+
switch (command) {
|
|
135
|
+
case 'recipes': {
|
|
136
|
+
const { values, positionals } = parse({ ...REMOTE_OPTIONS });
|
|
137
|
+
const client = remoteOf(io, values);
|
|
138
|
+
const sub = positionals[0] ?? 'list';
|
|
139
|
+
if (sub === 'show') {
|
|
140
|
+
const id = positionals[1];
|
|
141
|
+
if (!id)
|
|
142
|
+
throw new UsageError('recipes show needs a recipe id, for example sdk.handbook.');
|
|
143
|
+
const recipe = (client ? await client.recipe(id) : getGuideRecipe(id));
|
|
144
|
+
if (values.json)
|
|
145
|
+
emitJson(recipe);
|
|
146
|
+
else {
|
|
147
|
+
io.out(`${recipe.id}${recipe.title ? ` — ${recipe.title}` : ''}\n${recipe.description ?? ''}\n\nHuman guide:\n`);
|
|
148
|
+
for (const r of recipe.roleDetails ?? [])
|
|
149
|
+
io.out(` ${r.role.padEnd(18)} ${r.purpose ?? r.title ?? ''}\n`);
|
|
150
|
+
io.out('\nAI agent guide:\n');
|
|
151
|
+
for (const r of recipe.agentRoles ?? recipe.operatorRoles ?? [])
|
|
152
|
+
io.out(` ${r.role.padEnd(18)} ${r.purpose ?? r.title ?? ''}\n`);
|
|
153
|
+
}
|
|
154
|
+
return EXIT_OK;
|
|
155
|
+
}
|
|
156
|
+
if (sub !== 'list')
|
|
157
|
+
throw new UsageError(`Unknown recipes command "${sub}". Use "recipes list" or "recipes show <id>".`);
|
|
158
|
+
const recipes = (client ? await client.recipes() : listGuideRecipes());
|
|
159
|
+
if (values.json)
|
|
160
|
+
emitJson(recipes);
|
|
161
|
+
else
|
|
162
|
+
for (const r of recipes)
|
|
163
|
+
io.out(`${r.id.padEnd(22)} ${r.title} — ${r.description}\n`);
|
|
164
|
+
return EXIT_OK;
|
|
165
|
+
}
|
|
166
|
+
case 'init': {
|
|
167
|
+
const { values } = parse({
|
|
168
|
+
recipe: { type: 'string' },
|
|
169
|
+
'recipe-version': { type: 'string' },
|
|
170
|
+
subject: { type: 'string' },
|
|
171
|
+
subtitle: { type: 'string' },
|
|
172
|
+
scope: { type: 'string' },
|
|
173
|
+
'guide-id': { type: 'string' },
|
|
174
|
+
'job-id': { type: 'string' },
|
|
175
|
+
locale: { type: 'string' },
|
|
176
|
+
out: { type: 'string' },
|
|
177
|
+
overwrite: { type: 'boolean' },
|
|
178
|
+
});
|
|
179
|
+
if (!values.recipe || !values.subject || !values.out) {
|
|
180
|
+
throw new UsageError('init needs --recipe <id>, --subject <name> and --out <dir>. Run "made-easy recipes" to see recipe IDs.');
|
|
181
|
+
}
|
|
182
|
+
const created = await createGuide({
|
|
183
|
+
recipe: values.recipe,
|
|
184
|
+
recipeVersion: values['recipe-version'],
|
|
185
|
+
subject: { name: values.subject, subtitle: values.subtitle, scope: values.scope },
|
|
186
|
+
guideId: values['guide-id'],
|
|
187
|
+
jobId: values['job-id'],
|
|
188
|
+
locale: values.locale,
|
|
189
|
+
});
|
|
190
|
+
const written = await writeBundle(created.files, resolve(io.cwd, values.out), { overwrite: values.overwrite });
|
|
191
|
+
if (values.json)
|
|
192
|
+
emitJson({ ok: true, guideId: created.guideId, revision: created.revision, out: resolve(io.cwd, values.out), files: written });
|
|
193
|
+
else {
|
|
194
|
+
io.out(`Created ${written.length} files in ${values.out} (${values.recipe}).\n`);
|
|
195
|
+
io.out(`Every [[TODO: ...]] placeholder is a warning in draft mode and an error in release mode.\n`);
|
|
196
|
+
io.out(`Next: made-easy validate ${values.out}\n`);
|
|
197
|
+
}
|
|
198
|
+
return EXIT_OK;
|
|
199
|
+
}
|
|
200
|
+
case 'validate': {
|
|
201
|
+
const { values, positionals } = parse({ mode: { type: 'string' }, audience: { type: 'string' }, quiet: { type: 'boolean' }, ...REMOTE_OPTIONS });
|
|
202
|
+
const client = remoteOf(io, values);
|
|
203
|
+
const result = client
|
|
204
|
+
? (await client.validate({ source: await remoteSource(io, positionals, values), mode: mode(values.mode), audience: audience(values.audience) }))
|
|
205
|
+
: await validateGuide(input(io, positionals), { mode: mode(values.mode), audience: audience(values.audience) });
|
|
206
|
+
if (values.json)
|
|
207
|
+
emitJson(result);
|
|
208
|
+
else {
|
|
209
|
+
printDiagnostics(io, result.diagnostics, !values.quiet);
|
|
210
|
+
io.out(`${result.ok ? 'OK' : 'FAILED'} (${result.mode}): ${summaryLine(result.summary)}${result.revision ? `\nrevision ${result.revision}` : ''}\n`);
|
|
211
|
+
}
|
|
212
|
+
return result.ok ? EXIT_OK : EXIT_FAILED;
|
|
213
|
+
}
|
|
214
|
+
case 'preview': {
|
|
215
|
+
const { values, positionals } = parse({
|
|
216
|
+
track: { type: 'string' },
|
|
217
|
+
format: { type: 'string' },
|
|
218
|
+
mode: { type: 'string' },
|
|
219
|
+
audience: { type: 'string' },
|
|
220
|
+
out: { type: 'string' },
|
|
221
|
+
...REMOTE_OPTIONS,
|
|
222
|
+
});
|
|
223
|
+
const track = (values.track ?? 'human');
|
|
224
|
+
const format = (values.format ?? 'html');
|
|
225
|
+
if (!['human', 'agent', 'operator', 'brief'].includes(track))
|
|
226
|
+
throw new UsageError('--track must be human or agent.');
|
|
227
|
+
if (!['html', 'markdown', 'json'].includes(format))
|
|
228
|
+
throw new UsageError('--format must be html, markdown or json.');
|
|
229
|
+
const client = remoteOf(io, values);
|
|
230
|
+
const result = client
|
|
231
|
+
? (await client.preview({ source: await remoteSource(io, positionals, values), track, format, mode: mode(values.mode), audience: audience(values.audience) }))
|
|
232
|
+
: await previewGuide(input(io, positionals), { track, format, mode: mode(values.mode), audience: audience(values.audience) });
|
|
233
|
+
if (values.json)
|
|
234
|
+
emitJson(result);
|
|
235
|
+
else if (values.out && result.content !== undefined) {
|
|
236
|
+
const target = resolve(io.cwd, values.out);
|
|
237
|
+
await mkdir(dirname(target), { recursive: true });
|
|
238
|
+
await writeFile(target, result.content);
|
|
239
|
+
io.out(`Wrote ${values.out}\n`);
|
|
240
|
+
}
|
|
241
|
+
else if (result.content !== undefined)
|
|
242
|
+
io.out(result.content);
|
|
243
|
+
if (!result.content || !values.json)
|
|
244
|
+
printDiagnostics(io, result.diagnostics.filter((d) => d.severity === 'error'), false);
|
|
245
|
+
return result.content === undefined ? EXIT_FAILED : EXIT_OK;
|
|
246
|
+
}
|
|
247
|
+
case 'journey': {
|
|
248
|
+
const { values, positionals } = parse({
|
|
249
|
+
format: { type: 'string' },
|
|
250
|
+
track: { type: 'string' },
|
|
251
|
+
'job-map': { type: 'string' },
|
|
252
|
+
out: { type: 'string' },
|
|
253
|
+
});
|
|
254
|
+
const picked = (values.format ?? 'svg') === 'md' ? 'markdown' : (values.format ?? 'svg');
|
|
255
|
+
if (!['svg', 'mermaid', 'markdown'].includes(picked))
|
|
256
|
+
throw new UsageError('--format must be svg, mermaid or md.');
|
|
257
|
+
const track = values.track ?? 'human';
|
|
258
|
+
if (!['human', 'agent'].includes(track))
|
|
259
|
+
throw new UsageError('--track must be human or agent.');
|
|
260
|
+
const result = await journeyGuide(input(io, positionals), { format: picked, track: track, jobMap: values['job-map'] });
|
|
261
|
+
if (values.json)
|
|
262
|
+
emitJson(result);
|
|
263
|
+
else if (values.out && result.content !== undefined) {
|
|
264
|
+
const target = resolve(io.cwd, values.out);
|
|
265
|
+
await mkdir(dirname(target), { recursive: true });
|
|
266
|
+
await writeFile(target, result.content);
|
|
267
|
+
io.out(`Wrote ${values.out}\n`);
|
|
268
|
+
}
|
|
269
|
+
else if (result.content !== undefined)
|
|
270
|
+
io.out(result.content.endsWith('\n') ? result.content : `${result.content}\n`);
|
|
271
|
+
if (!result.content || !values.json)
|
|
272
|
+
printDiagnostics(io, result.diagnostics.filter((d) => d.severity === 'error'), false);
|
|
273
|
+
return result.content === undefined ? EXIT_FAILED : EXIT_OK;
|
|
274
|
+
}
|
|
275
|
+
case 'build': {
|
|
276
|
+
const { values, positionals } = parse({
|
|
277
|
+
out: { type: 'string' },
|
|
278
|
+
mode: { type: 'string' },
|
|
279
|
+
audience: { type: 'string' },
|
|
280
|
+
format: { type: 'string' },
|
|
281
|
+
paper: { type: 'string' },
|
|
282
|
+
'no-zip': { type: 'boolean' },
|
|
283
|
+
'allow-partial': { type: 'boolean' },
|
|
284
|
+
overwrite: { type: 'boolean' },
|
|
285
|
+
browser: { type: 'string' },
|
|
286
|
+
'no-wait': { type: 'boolean' },
|
|
287
|
+
...REMOTE_OPTIONS,
|
|
288
|
+
});
|
|
289
|
+
const formats = csv(values.format);
|
|
290
|
+
if (formats?.some((f) => !['html', 'pdf', 'md'].includes(f)))
|
|
291
|
+
throw new UsageError('--format takes html, pdf and md, comma separated. "md" alone builds the pure-Markdown guides without a browser.');
|
|
292
|
+
const paper = csv(values.paper);
|
|
293
|
+
const client = remoteOf(io, values);
|
|
294
|
+
if (client) {
|
|
295
|
+
if (!values.out && !values['no-wait'])
|
|
296
|
+
throw new UsageError('build needs --out <dir> (or --no-wait to only start the job).');
|
|
297
|
+
let job = await client.startBuild({
|
|
298
|
+
source: await remoteSource(io, positionals, values),
|
|
299
|
+
mode: mode(values.mode),
|
|
300
|
+
audience: audience(values.audience),
|
|
301
|
+
formats,
|
|
302
|
+
paper,
|
|
303
|
+
zip: !values['no-zip'],
|
|
304
|
+
allowPartial: values['allow-partial'],
|
|
305
|
+
});
|
|
306
|
+
if (!values['no-wait']) {
|
|
307
|
+
job = await client.wait(job.id, { onStatus: (s) => !values.json && io.err(`job ${job.id}: ${s}\n`) });
|
|
308
|
+
if (job.status === 'succeeded')
|
|
309
|
+
await client.download(job, resolve(io.cwd, values.out));
|
|
310
|
+
}
|
|
311
|
+
if (values.json)
|
|
312
|
+
emitJson(job);
|
|
313
|
+
else if (job.status === 'failed' || job.status === 'cancelled') {
|
|
314
|
+
const diags = job.result?.diagnostics;
|
|
315
|
+
if (diags)
|
|
316
|
+
printDiagnostics(io, diags, false);
|
|
317
|
+
io.out(`${job.status === 'failed' ? 'BUILD FAILED' : 'CANCELLED'}${job.error ? ` (${job.error.code}): ${job.error.message}` : ''}. Nothing was published.\n`);
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
io.out(`${job.status === 'succeeded' ? 'BUILT' : `Started ${job.id}`} (${job.status}) on the server.\n`);
|
|
321
|
+
for (const a of job.artifacts)
|
|
322
|
+
io.out(` ${a.path} ${a.size} bytes\n`);
|
|
323
|
+
if (job.status === 'succeeded')
|
|
324
|
+
io.out(`Output: ${resolve(io.cwd, values.out)}\n`);
|
|
325
|
+
else
|
|
326
|
+
io.out(`Check it with: made-easy job show ${job.id}\n`);
|
|
327
|
+
}
|
|
328
|
+
return job.status === 'failed' || job.status === 'cancelled' ? EXIT_FAILED : EXIT_OK;
|
|
329
|
+
}
|
|
330
|
+
if (!values.out)
|
|
331
|
+
throw new UsageError('build needs --out <dir>.');
|
|
332
|
+
const result = await buildGuide(input(io, positionals), {
|
|
333
|
+
mode: mode(values.mode),
|
|
334
|
+
audience: audience(values.audience),
|
|
335
|
+
formats,
|
|
336
|
+
paper,
|
|
337
|
+
zip: !values['no-zip'],
|
|
338
|
+
allowPartial: values['allow-partial'],
|
|
339
|
+
out: resolve(io.cwd, values.out),
|
|
340
|
+
overwrite: values.overwrite,
|
|
341
|
+
browserPath: values.browser ?? io.env.MADE_EASY_BROWSER,
|
|
342
|
+
});
|
|
343
|
+
if (values.json)
|
|
344
|
+
emitJson(result);
|
|
345
|
+
else {
|
|
346
|
+
printDiagnostics(io, result.diagnostics, false);
|
|
347
|
+
if (result.status === 'failed')
|
|
348
|
+
io.out(`BUILD FAILED: ${summaryLine(result.summary)}. Nothing was published.\n`);
|
|
349
|
+
else {
|
|
350
|
+
io.out(`${result.status === 'partial' ? 'PARTIAL' : 'BUILT'} (${result.mode}, ${result.visibility})${result.complete ? '' : ' — incomplete, private'}: ${summaryLine(result.summary)}\n`);
|
|
351
|
+
for (const a of result.artifacts)
|
|
352
|
+
io.out(` ${a.path} ${a.size} bytes\n`);
|
|
353
|
+
io.out(`Output: ${result.outDir}\n`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return result.status === 'succeeded' || (result.status === 'partial' && values['allow-partial']) ? EXIT_OK : EXIT_FAILED;
|
|
357
|
+
}
|
|
358
|
+
case 'pin': {
|
|
359
|
+
const { values, positionals } = parse({ all: { type: 'boolean' }, check: { type: 'boolean' } });
|
|
360
|
+
const dir = positionals[0] ? resolve(io.cwd, positionals[0]) : undefined;
|
|
361
|
+
if (!dir)
|
|
362
|
+
throw new UsageError('pin needs a bundle directory.');
|
|
363
|
+
const result = await pinGuide(dir, { all: values.all });
|
|
364
|
+
const changed = result.entries.filter((e) => e.changed);
|
|
365
|
+
if (values.check) {
|
|
366
|
+
if (values.json)
|
|
367
|
+
emitJson({ ok: changed.length === 0, entries: result.entries });
|
|
368
|
+
else
|
|
369
|
+
io.out(changed.length ? `Stale pins: ${changed.map((e) => e.id).join(', ')}\n` : 'All pins are current.\n');
|
|
370
|
+
return changed.length ? EXIT_FAILED : EXIT_OK;
|
|
371
|
+
}
|
|
372
|
+
if (result.brief)
|
|
373
|
+
await writeFile(resolve(dir, 'brief.yaml'), result.brief);
|
|
374
|
+
if (values.json)
|
|
375
|
+
emitJson({ ok: true, written: Boolean(result.brief), entries: result.entries });
|
|
376
|
+
else
|
|
377
|
+
io.out(result.brief ? `Updated brief.yaml: ${changed.map((e) => e.id).join(', ')}\n` : 'brief.yaml already has current pins.\n');
|
|
378
|
+
return EXIT_OK;
|
|
379
|
+
}
|
|
380
|
+
case 'review': {
|
|
381
|
+
const { values, positionals } = parse({
|
|
382
|
+
by: { type: 'string' },
|
|
383
|
+
claim: { type: 'string', multiple: true },
|
|
384
|
+
entry: { type: 'string', multiple: true },
|
|
385
|
+
all: { type: 'boolean' },
|
|
386
|
+
at: { type: 'string' },
|
|
387
|
+
});
|
|
388
|
+
const dir = positionals[0] ? resolve(io.cwd, positionals[0]) : undefined;
|
|
389
|
+
if (!dir)
|
|
390
|
+
throw new UsageError('review needs a bundle directory.');
|
|
391
|
+
if (!values.by)
|
|
392
|
+
throw new UsageError('review needs --by <party>: the human who read the content (a human party id or name from brief.yaml). It is never assumed.');
|
|
393
|
+
if (!values.all && !values.claim?.length && !values.entry?.length) {
|
|
394
|
+
throw new UsageError('Say what you reviewed: --claim <id>, --entry <id>, or --all.');
|
|
395
|
+
}
|
|
396
|
+
let result;
|
|
397
|
+
try {
|
|
398
|
+
result = await reviewGuide(dir, { by: values.by, claims: values.claim, entries: values.entry, all: values.all, at: values.at });
|
|
399
|
+
}
|
|
400
|
+
catch (e) {
|
|
401
|
+
if (e instanceof MadeEasyError)
|
|
402
|
+
throw new UsageError(e.message);
|
|
403
|
+
throw e;
|
|
404
|
+
}
|
|
405
|
+
if (result.sources)
|
|
406
|
+
await writeFile(resolve(dir, 'sources.yaml'), result.sources);
|
|
407
|
+
if (values.json)
|
|
408
|
+
emitJson({ ok: true, written: Boolean(result.sources), reviewed: result.reviewed });
|
|
409
|
+
else {
|
|
410
|
+
io.out(result.reviewed.length ? `Recorded ${values.by}'s review of ${result.reviewed.map((r) => `${r.kind} ${r.id}`).join(', ')} in sources.yaml.\n` : 'Nothing needed review.\n');
|
|
411
|
+
if (result.reviewed.length)
|
|
412
|
+
io.out('Review binds to the text as it is now; any later edit makes it stale.\n');
|
|
413
|
+
}
|
|
414
|
+
return EXIT_OK;
|
|
415
|
+
}
|
|
416
|
+
case 'check-return': {
|
|
417
|
+
const { values, positionals } = parse({ 'no-revision': { type: 'boolean' } });
|
|
418
|
+
const dir = positionals[0] ? resolve(io.cwd, positionals[0]) : undefined;
|
|
419
|
+
const file = positionals[1] ? resolve(io.cwd, positionals[1]) : undefined;
|
|
420
|
+
if (!dir || !file)
|
|
421
|
+
throw new UsageError('check-return needs a bundle directory and the agent return file (JSON).');
|
|
422
|
+
let value;
|
|
423
|
+
try {
|
|
424
|
+
value = JSON.parse(await readFile(file, 'utf8'));
|
|
425
|
+
}
|
|
426
|
+
catch (e) {
|
|
427
|
+
throw new UsageError(`Cannot read ${file} as JSON: ${e.message}`);
|
|
428
|
+
}
|
|
429
|
+
const model = await loadGuide(dir);
|
|
430
|
+
const result = validateAgentReturn(model, value, values['no-revision'] ? { checkRevision: false } : {});
|
|
431
|
+
if (values.json)
|
|
432
|
+
emitJson(result);
|
|
433
|
+
else {
|
|
434
|
+
printDiagnostics(io, result.diagnostics, false);
|
|
435
|
+
io.out(result.ok ? 'The return matches the brief.\n' : `The return does not match the brief: ${result.diagnostics.length} problem(s).\n`);
|
|
436
|
+
}
|
|
437
|
+
return result.ok ? EXIT_OK : EXIT_FAILED;
|
|
438
|
+
}
|
|
439
|
+
case 'anchors': {
|
|
440
|
+
const { values, positionals } = parse({ check: { type: 'boolean' } });
|
|
441
|
+
const dir = positionals[0] ? resolve(io.cwd, positionals[0]) : undefined;
|
|
442
|
+
if (!dir)
|
|
443
|
+
throw new UsageError('anchors needs a bundle directory.');
|
|
444
|
+
const changed = await stabilizeAnchors(dir);
|
|
445
|
+
const files = Object.keys(changed);
|
|
446
|
+
if (!values.check)
|
|
447
|
+
for (const [rel, text] of Object.entries(changed))
|
|
448
|
+
await writeFile(resolve(dir, ...rel.split('/')), text);
|
|
449
|
+
if (values.json)
|
|
450
|
+
emitJson({ ok: values.check ? files.length === 0 : true, files });
|
|
451
|
+
else
|
|
452
|
+
io.out(files.length ? `${values.check ? 'Would update' : 'Updated'}: ${files.join(', ')}\n` : 'Every heading already has an explicit anchor.\n');
|
|
453
|
+
return values.check && files.length ? EXIT_FAILED : EXIT_OK;
|
|
454
|
+
}
|
|
455
|
+
case 'verify': {
|
|
456
|
+
const { values, positionals } = parse({ 'allow-exec': { type: 'boolean' }, only: { type: 'string', multiple: true }, 'no-write': { type: 'boolean' }, timeout: { type: 'string' } });
|
|
457
|
+
const dir = positionals[0] ? resolve(io.cwd, positionals[0]) : undefined;
|
|
458
|
+
if (!dir)
|
|
459
|
+
throw new UsageError('verify needs a bundle directory.');
|
|
460
|
+
if (!values['allow-exec']) {
|
|
461
|
+
throw new UsageError('verify runs the commands listed in executable examples. Re-run with --allow-exec once you trust this bundle (prefer CI or a container).');
|
|
462
|
+
}
|
|
463
|
+
const result = await verifyExamples(dir, { allowExec: true, only: values.only, timeoutMs: values.timeout ? Number(values.timeout) * 1000 : undefined });
|
|
464
|
+
if (!values['no-write'] && result.outcomes.length) {
|
|
465
|
+
const file = resolve(dir, ...result.verificationPath.split('/'));
|
|
466
|
+
await mkdir(dirname(file), { recursive: true });
|
|
467
|
+
await writeFile(file, result.verificationYaml);
|
|
468
|
+
}
|
|
469
|
+
if (values.json)
|
|
470
|
+
emitJson({ ok: result.ok, outcomes: result.outcomes.map((o) => ({ example: o.example, ok: o.ok, error: o.error, record: o.record })) });
|
|
471
|
+
else {
|
|
472
|
+
for (const o of result.outcomes)
|
|
473
|
+
io.out(`${o.ok ? 'pass' : 'FAIL'} ${o.example}${o.error ? `\n${o.error}\n` : ''}\n`);
|
|
474
|
+
if (!result.outcomes.length)
|
|
475
|
+
io.out('No executable examples found.\n');
|
|
476
|
+
else if (!values['no-write'])
|
|
477
|
+
io.out(`Recorded results in ${result.verificationPath}\n`);
|
|
478
|
+
}
|
|
479
|
+
return result.ok ? EXIT_OK : EXIT_FAILED;
|
|
480
|
+
}
|
|
481
|
+
case 'resolve-npm': {
|
|
482
|
+
const { values, positionals } = parse({ range: { type: 'string' }, registry: { type: 'string' } });
|
|
483
|
+
const name = positionals[0];
|
|
484
|
+
if (!name)
|
|
485
|
+
throw new UsageError('resolve-npm needs a package name.');
|
|
486
|
+
const resolved = await resolveNpmPackage(name, values.range ?? 'latest', { registry: values.registry });
|
|
487
|
+
if (values.json)
|
|
488
|
+
emitJson(resolved);
|
|
489
|
+
else {
|
|
490
|
+
io.out(`${resolved.name}@${resolved.version}\n`);
|
|
491
|
+
io.out(` requested ${resolved.requested}\n integrity ${resolved.integrity ?? '(none published)'}\n registry ${resolved.registry}\n`);
|
|
492
|
+
if (resolved.deprecated)
|
|
493
|
+
io.out(` deprecated ${resolved.deprecated}\n`);
|
|
494
|
+
}
|
|
495
|
+
return EXIT_OK;
|
|
496
|
+
}
|
|
497
|
+
case 'draft': {
|
|
498
|
+
const { values, positionals } = parse({
|
|
499
|
+
snapshot: { type: 'string' },
|
|
500
|
+
section: { type: 'string', multiple: true },
|
|
501
|
+
adapter: { type: 'string' },
|
|
502
|
+
endpoint: { type: 'string' },
|
|
503
|
+
model: { type: 'string' },
|
|
504
|
+
out: { type: 'string' },
|
|
505
|
+
apply: { type: 'boolean' },
|
|
506
|
+
});
|
|
507
|
+
const dir = positionals[0] ? resolve(io.cwd, positionals[0]) : undefined;
|
|
508
|
+
if (!dir || !values.snapshot || !values.section?.length) {
|
|
509
|
+
throw new UsageError('draft needs a bundle directory, --snapshot <file.json> and one or more --section <track:entry> (for example human:decision).');
|
|
510
|
+
}
|
|
511
|
+
const snapshot = SourceSnapshotSchema.parse(JSON.parse(await readFile(resolve(io.cwd, values.snapshot), 'utf8')));
|
|
512
|
+
const sections = values.section.map((s) => {
|
|
513
|
+
const [a, b] = s.includes(':') ? s.split(':') : ['human', s];
|
|
514
|
+
return { track: a, entry: b };
|
|
515
|
+
});
|
|
516
|
+
let adapter;
|
|
517
|
+
if ((values.adapter ?? 'template') === 'template')
|
|
518
|
+
adapter = createTemplateDraftAdapter();
|
|
519
|
+
else if (values.adapter === 'chat-completions') {
|
|
520
|
+
if (!values.endpoint || !values.model)
|
|
521
|
+
throw new UsageError('chat-completions needs --endpoint <url> and --model <name>. The API key is read from MADE_EASY_DRAFT_API_KEY.');
|
|
522
|
+
adapter = createChatCompletionsAdapter({ endpoint: values.endpoint, model: values.model, apiKey: io.env.MADE_EASY_DRAFT_API_KEY });
|
|
523
|
+
}
|
|
524
|
+
else
|
|
525
|
+
throw new UsageError('--adapter must be "template" or "chat-completions".');
|
|
526
|
+
const validated = await validateGuide(dir);
|
|
527
|
+
const drafted = await draftGuide(dir, { sections, snapshot, adapter, expectedRevision: validated.revision });
|
|
528
|
+
if (!drafted.ok || !drafted.proposal) {
|
|
529
|
+
if (values.json)
|
|
530
|
+
emitJson(drafted);
|
|
531
|
+
else
|
|
532
|
+
printDiagnostics(io, drafted.diagnostics, true);
|
|
533
|
+
return EXIT_FAILED;
|
|
534
|
+
}
|
|
535
|
+
if (values.apply) {
|
|
536
|
+
const applied = await applyDraftProposal(dir, drafted.proposal, { expectedRevision: validated.revision, snapshot });
|
|
537
|
+
if (!applied.ok) {
|
|
538
|
+
if (values.json)
|
|
539
|
+
emitJson(applied);
|
|
540
|
+
else
|
|
541
|
+
printDiagnostics(io, applied.diagnostics, true);
|
|
542
|
+
return EXIT_FAILED;
|
|
543
|
+
}
|
|
544
|
+
for (const [rel, text] of Object.entries(applied.files))
|
|
545
|
+
await writeFile(resolve(dir, ...rel.split('/')), text);
|
|
546
|
+
if (values.json)
|
|
547
|
+
emitJson({ ok: true, changed: Object.keys(applied.files), revision: applied.revision });
|
|
548
|
+
else
|
|
549
|
+
io.out(`Applied draft to: ${Object.keys(applied.files).join(', ')}\nReview the unresolved items and replace every [[TODO]] before release.\n`);
|
|
550
|
+
return EXIT_OK;
|
|
551
|
+
}
|
|
552
|
+
const text = `${JSON.stringify(drafted.proposal, null, 2)}\n`;
|
|
553
|
+
if (values.out) {
|
|
554
|
+
await writeFile(resolve(io.cwd, values.out), text);
|
|
555
|
+
io.out(`Wrote proposal to ${values.out}. Nothing in the bundle changed.\n`);
|
|
556
|
+
}
|
|
557
|
+
else
|
|
558
|
+
io.out(text);
|
|
559
|
+
return EXIT_OK;
|
|
560
|
+
}
|
|
561
|
+
case 'job': {
|
|
562
|
+
const { values, positionals } = parse({ out: { type: 'string' }, wait: { type: 'boolean' }, ...REMOTE_OPTIONS });
|
|
563
|
+
const [sub, id] = positionals;
|
|
564
|
+
if (!sub || !['show', 'cancel', 'download'].includes(sub))
|
|
565
|
+
throw new UsageError('Use "job show <id>", "job cancel <id>" or "job download <id> --out <dir>".');
|
|
566
|
+
if (!id)
|
|
567
|
+
throw new UsageError(`job ${sub} needs a job id.`);
|
|
568
|
+
const client = remoteOf(io, values);
|
|
569
|
+
if (!client)
|
|
570
|
+
throw new UsageError('job commands talk to a server: pass --server <url> or set MADE_EASY_URL (and MADE_EASY_TOKEN).');
|
|
571
|
+
let job = sub === 'cancel' ? await client.cancel(id) : await client.job(id);
|
|
572
|
+
if (sub !== 'cancel' && values.wait)
|
|
573
|
+
job = await client.wait(id);
|
|
574
|
+
if (sub === 'download') {
|
|
575
|
+
if (!values.out)
|
|
576
|
+
throw new UsageError('job download needs --out <dir>.');
|
|
577
|
+
if (job.status !== 'succeeded') {
|
|
578
|
+
io.err(`Job ${id} is ${job.status}; only a succeeded job has artifacts to download.\n`);
|
|
579
|
+
return EXIT_FAILED;
|
|
580
|
+
}
|
|
581
|
+
const written = await client.download(job, resolve(io.cwd, values.out));
|
|
582
|
+
if (values.json)
|
|
583
|
+
emitJson({ ok: true, out: resolve(io.cwd, values.out), files: written });
|
|
584
|
+
else
|
|
585
|
+
io.out(`Downloaded ${written.length} file(s) to ${values.out}\n`);
|
|
586
|
+
return EXIT_OK;
|
|
587
|
+
}
|
|
588
|
+
if (values.json)
|
|
589
|
+
emitJson(job);
|
|
590
|
+
else {
|
|
591
|
+
io.out(`${job.id} ${job.kind} ${job.status}${job.guideId ? ` guide ${job.guideId}` : ''}${job.revision ? ` ${job.revision.slice(0, 19)}` : ''}\n`);
|
|
592
|
+
if (job.error)
|
|
593
|
+
io.out(` ${job.error.code}: ${job.error.message}\n`);
|
|
594
|
+
for (const a of job.artifacts)
|
|
595
|
+
io.out(` ${a.path} ${a.size} bytes\n`);
|
|
596
|
+
}
|
|
597
|
+
return job.status === 'failed' ? EXIT_FAILED : EXIT_OK;
|
|
598
|
+
}
|
|
599
|
+
case 'serve': {
|
|
600
|
+
const mod = await import('@x12i/made-easy-server').catch(() => undefined);
|
|
601
|
+
if (!mod?.startFromArgs)
|
|
602
|
+
throw new UsageError('serve needs @x12i/made-easy-server. Install it with: npm i -g @x12i/made-easy-server');
|
|
603
|
+
return (await mod.startFromArgs(args, io)) ?? EXIT_OK;
|
|
604
|
+
}
|
|
605
|
+
case 'mcp': {
|
|
606
|
+
const mod = await import('@x12i/made-easy-mcp').catch(() => undefined);
|
|
607
|
+
if (!mod?.startStdioFromArgs)
|
|
608
|
+
throw new UsageError('mcp needs @x12i/made-easy-mcp. Install it with: npm i -g @x12i/made-easy-mcp');
|
|
609
|
+
return (await mod.startStdioFromArgs(args, io)) ?? EXIT_OK;
|
|
610
|
+
}
|
|
611
|
+
default:
|
|
612
|
+
throw new UsageError(`Unknown command "${command}". Run "made-easy --help".`);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
/** Run the CLI. Returns the process exit code and never calls process.exit, so it is testable. */
|
|
616
|
+
export async function run(argv, io = defaultIo) {
|
|
617
|
+
const args = [...argv];
|
|
618
|
+
if (args[0] === 'guide')
|
|
619
|
+
args.shift();
|
|
620
|
+
const command = args.shift();
|
|
621
|
+
if (!command || command === '--help' || command === '-h' || command === 'help') {
|
|
622
|
+
io.out(HELP);
|
|
623
|
+
return command ? EXIT_OK : EXIT_USAGE;
|
|
624
|
+
}
|
|
625
|
+
if (command === '--version' || command === '-v' || command === 'version') {
|
|
626
|
+
io.out(`${VERSION}\n`);
|
|
627
|
+
return EXIT_OK;
|
|
628
|
+
}
|
|
629
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
630
|
+
io.out(HELP);
|
|
631
|
+
return EXIT_OK;
|
|
632
|
+
}
|
|
633
|
+
try {
|
|
634
|
+
return await dispatch(command, args, io);
|
|
635
|
+
}
|
|
636
|
+
catch (e) {
|
|
637
|
+
if (e instanceof UsageError) {
|
|
638
|
+
io.err(`error: ${e.message}\n`);
|
|
639
|
+
return EXIT_USAGE;
|
|
640
|
+
}
|
|
641
|
+
if (e instanceof RemoteError) {
|
|
642
|
+
if (args.includes('--json'))
|
|
643
|
+
io.out(`${JSON.stringify({ ok: false, error: { code: e.code, message: e.message, status: e.status, diagnostics: e.diagnostics } }, null, 2)}\n`);
|
|
644
|
+
else
|
|
645
|
+
io.err(`error: ${e.code}: ${e.message}\n`);
|
|
646
|
+
return e.status >= 400 && e.status < 500 ? EXIT_FAILED : EXIT_INTERNAL;
|
|
647
|
+
}
|
|
648
|
+
if (e instanceof MadeEasyError) {
|
|
649
|
+
if (args.includes('--json'))
|
|
650
|
+
io.out(`${JSON.stringify({ ok: false, diagnostics: e.diagnostics }, null, 2)}\n`);
|
|
651
|
+
else
|
|
652
|
+
printDiagnostics(io, e.diagnostics, true);
|
|
653
|
+
return EXIT_FAILED;
|
|
654
|
+
}
|
|
655
|
+
io.err(`error: ${e.message}\n`);
|
|
656
|
+
return EXIT_INTERNAL;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/remote.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type FileContent } from '@x12i/made-easy';
|
|
2
|
+
/** A problem returned by a Made Easy server, or a transport failure. */
|
|
3
|
+
export declare class RemoteError extends Error {
|
|
4
|
+
readonly status: number;
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly diagnostics?: unknown | undefined;
|
|
7
|
+
constructor(status: number, code: string, message: string, diagnostics?: unknown | undefined);
|
|
8
|
+
}
|
|
9
|
+
export interface RemoteOptions {
|
|
10
|
+
/** Server root, for example https://guides.example.com (the /v1 prefix is added). */
|
|
11
|
+
server: string;
|
|
12
|
+
token?: string;
|
|
13
|
+
fetch?: typeof fetch;
|
|
14
|
+
}
|
|
15
|
+
export interface RemoteJob {
|
|
16
|
+
id: string;
|
|
17
|
+
kind: string;
|
|
18
|
+
status: 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled';
|
|
19
|
+
guideId?: string;
|
|
20
|
+
revision?: string;
|
|
21
|
+
artifacts: {
|
|
22
|
+
id: string;
|
|
23
|
+
path: string;
|
|
24
|
+
size: number;
|
|
25
|
+
sha256: string;
|
|
26
|
+
mediaType: string;
|
|
27
|
+
url: string;
|
|
28
|
+
}[];
|
|
29
|
+
error?: {
|
|
30
|
+
code: string;
|
|
31
|
+
message: string;
|
|
32
|
+
};
|
|
33
|
+
result?: unknown;
|
|
34
|
+
statusUrl: string;
|
|
35
|
+
}
|
|
36
|
+
/** Read a local bundle directory into the inline `files` form the API accepts. Symlinks are refused. */
|
|
37
|
+
export declare function readLocalBundle(dir: string): Promise<Record<string, FileContent>>;
|
|
38
|
+
export declare class RemoteClient {
|
|
39
|
+
private readonly o;
|
|
40
|
+
private readonly base;
|
|
41
|
+
private readonly doFetch;
|
|
42
|
+
constructor(o: RemoteOptions);
|
|
43
|
+
private headers;
|
|
44
|
+
private request;
|
|
45
|
+
private json;
|
|
46
|
+
recipes: () => Promise<unknown[]>;
|
|
47
|
+
recipe: (id: string) => Promise<Record<string, unknown>>;
|
|
48
|
+
validate: (body: unknown) => Promise<Record<string, unknown>>;
|
|
49
|
+
preview: (body: unknown) => Promise<Record<string, unknown>>;
|
|
50
|
+
startBuild: (body: unknown, idempotencyKey?: string) => Promise<RemoteJob>;
|
|
51
|
+
job: (id: string) => Promise<RemoteJob>;
|
|
52
|
+
cancel: (id: string) => Promise<RemoteJob>;
|
|
53
|
+
/** Poll until the job is terminal. */
|
|
54
|
+
wait(id: string, options?: {
|
|
55
|
+
intervalMs?: number;
|
|
56
|
+
timeoutMs?: number;
|
|
57
|
+
onStatus?: (status: string) => void;
|
|
58
|
+
}): Promise<RemoteJob>;
|
|
59
|
+
/** Download every artifact of a job into a directory, refusing any path that would escape it. */
|
|
60
|
+
download(job: RemoteJob, outDir: string): Promise<string[]>;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=remote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAErF,wEAAwE;AACxE,qBAAa,WAAY,SAAQ,KAAK;IAElC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAErB,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO;gBAHrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACN,WAAW,CAAC,EAAE,OAAO,YAAA;CAIjC;AAED,MAAM,WAAW,aAAa;IAC5B,qFAAqF;IACrF,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACxG,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,wGAAwG;AACxG,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CASvF;AAED,qBAAa,YAAY;IAIX,OAAO,CAAC,QAAQ,CAAC,CAAC;IAH9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;gBAEV,CAAC,EAAE,aAAa;IAa7C,OAAO,CAAC,OAAO;YAID,OAAO;YAuBP,IAAI;IAIlB,OAAO,2BAA0F;IACjG,MAAM,GAAI,IAAI,MAAM,sCAA2F;IAC/G,QAAQ,GAAI,MAAM,OAAO,sCAA0E;IACnG,OAAO,GAAI,MAAM,OAAO,sCAAyE;IACjG,UAAU,GAAI,MAAM,OAAO,EAAE,iBAAgB,MAAqB,wBAAoG;IACtK,GAAG,GAAI,IAAI,MAAM,wBAA0E;IAC3F,MAAM,GAAI,IAAI,MAAM,wBAA6E;IAEjG,sCAAsC;IAChC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;KAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAe1I,iGAAiG;IAC3F,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAkBlE"}
|
package/dist/remote.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, resolve, sep } from 'node:path';
|
|
3
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
4
|
+
import { checkBundlePath, directorySource } from '@x12i/made-easy';
|
|
5
|
+
/** A problem returned by a Made Easy server, or a transport failure. */
|
|
6
|
+
export class RemoteError extends Error {
|
|
7
|
+
status;
|
|
8
|
+
code;
|
|
9
|
+
diagnostics;
|
|
10
|
+
constructor(status, code, message, diagnostics) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.diagnostics = diagnostics;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const TEXT = /\.(md|markdown|ya?ml|json|txt|css|html?|svg|js|mjs|ts|csv)$/i;
|
|
18
|
+
/** Read a local bundle directory into the inline `files` form the API accepts. Symlinks are refused. */
|
|
19
|
+
export async function readLocalBundle(dir) {
|
|
20
|
+
const src = directorySource(dir);
|
|
21
|
+
const files = {};
|
|
22
|
+
for (const name of await src.list()) {
|
|
23
|
+
if (name.startsWith('\u0000symlink:'))
|
|
24
|
+
throw new Error(`Symbolic links are not allowed in a bundle: ${name.slice(9)}`);
|
|
25
|
+
const bytes = await src.read(name);
|
|
26
|
+
files[name] = TEXT.test(name) ? Buffer.from(bytes).toString('utf8') : { encoding: 'base64', content: Buffer.from(bytes).toString('base64') };
|
|
27
|
+
}
|
|
28
|
+
return files;
|
|
29
|
+
}
|
|
30
|
+
export class RemoteClient {
|
|
31
|
+
o;
|
|
32
|
+
base;
|
|
33
|
+
doFetch;
|
|
34
|
+
constructor(o) {
|
|
35
|
+
this.o = o;
|
|
36
|
+
let url;
|
|
37
|
+
try {
|
|
38
|
+
url = new URL(o.server);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
throw new RemoteError(0, 'INVALID_SERVER', `"${o.server}" is not a valid server URL. Use, for example, --server https://guides.example.com.`);
|
|
42
|
+
}
|
|
43
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:')
|
|
44
|
+
throw new RemoteError(0, 'INVALID_SERVER', 'The server URL must be http or https.');
|
|
45
|
+
const root = url.toString().replace(/\/+$/, '');
|
|
46
|
+
this.base = /\/v1$/.test(root) ? root : `${root}/v1`;
|
|
47
|
+
this.doFetch = o.fetch ?? fetch;
|
|
48
|
+
}
|
|
49
|
+
headers(extra = {}) {
|
|
50
|
+
return { accept: 'application/json', ...(this.o.token ? { authorization: `Bearer ${this.o.token}` } : {}), ...extra };
|
|
51
|
+
}
|
|
52
|
+
async request(method, path, body, extra = {}) {
|
|
53
|
+
let res;
|
|
54
|
+
try {
|
|
55
|
+
res = await this.doFetch(`${this.base}${path}`, {
|
|
56
|
+
method,
|
|
57
|
+
headers: this.headers(body === undefined ? extra : { 'content-type': 'application/json', ...extra }),
|
|
58
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
throw new RemoteError(0, 'SERVER_UNREACHABLE', `Could not reach ${this.base}: ${e.message}`);
|
|
63
|
+
}
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
let problem = {};
|
|
66
|
+
try {
|
|
67
|
+
problem = (await res.json());
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
/* not JSON */
|
|
71
|
+
}
|
|
72
|
+
throw new RemoteError(res.status, problem.error?.code ?? `HTTP_${res.status}`, problem.error?.message ?? `The server answered ${res.status} ${res.statusText}.`, problem.error?.diagnostics);
|
|
73
|
+
}
|
|
74
|
+
return res;
|
|
75
|
+
}
|
|
76
|
+
async json(method, path, body, extra) {
|
|
77
|
+
return (await (await this.request(method, path, body, extra)).json());
|
|
78
|
+
}
|
|
79
|
+
recipes = async () => (await this.json('GET', '/guide-recipes')).recipes;
|
|
80
|
+
recipe = (id) => this.json('GET', `/guide-recipes/${encodeURIComponent(id)}`);
|
|
81
|
+
validate = (body) => this.json('POST', '/guides/validate', body);
|
|
82
|
+
preview = (body) => this.json('POST', '/guides/preview', body);
|
|
83
|
+
startBuild = (body, idempotencyKey = randomUUID()) => this.json('POST', '/guide-build-jobs', body, { 'idempotency-key': idempotencyKey });
|
|
84
|
+
job = (id) => this.json('GET', `/guide-jobs/${encodeURIComponent(id)}`);
|
|
85
|
+
cancel = (id) => this.json('DELETE', `/guide-jobs/${encodeURIComponent(id)}`);
|
|
86
|
+
/** Poll until the job is terminal. */
|
|
87
|
+
async wait(id, options = {}) {
|
|
88
|
+
const deadline = Date.now() + (options.timeoutMs ?? 10 * 60_000);
|
|
89
|
+
let last = '';
|
|
90
|
+
for (;;) {
|
|
91
|
+
const job = await this.job(id);
|
|
92
|
+
if (job.status !== last) {
|
|
93
|
+
last = job.status;
|
|
94
|
+
options.onStatus?.(job.status);
|
|
95
|
+
}
|
|
96
|
+
if (['succeeded', 'failed', 'cancelled'].includes(job.status))
|
|
97
|
+
return job;
|
|
98
|
+
if (Date.now() > deadline)
|
|
99
|
+
throw new RemoteError(0, 'WAIT_TIMEOUT', `Job ${id} did not finish in time. It is still ${job.status}; check it with "made-easy job show ${id}".`);
|
|
100
|
+
await new Promise((r) => setTimeout(r, options.intervalMs ?? 500));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Download every artifact of a job into a directory, refusing any path that would escape it. */
|
|
104
|
+
async download(job, outDir) {
|
|
105
|
+
const root = resolve(outDir);
|
|
106
|
+
const written = [];
|
|
107
|
+
for (const a of job.artifacts) {
|
|
108
|
+
const check = checkBundlePath(a.path);
|
|
109
|
+
if (!check.ok)
|
|
110
|
+
throw new RemoteError(0, 'UNSAFE_ARTIFACT_PATH', `The server returned an unsafe artifact path "${a.path}": ${check.reason}`);
|
|
111
|
+
const target = resolve(root, check.path);
|
|
112
|
+
if (target !== root && !target.startsWith(root + sep))
|
|
113
|
+
throw new RemoteError(0, 'UNSAFE_ARTIFACT_PATH', `Artifact path escapes the output directory: ${a.path}`);
|
|
114
|
+
const res = await this.request('GET', `/guide-jobs/${encodeURIComponent(job.id)}/artifacts/${encodeURIComponent(a.id)}`, undefined, { accept: '*/*' });
|
|
115
|
+
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
116
|
+
const digest = createHash('sha256').update(bytes).digest('hex');
|
|
117
|
+
if (a.sha256 && digest !== a.sha256.replace(/^sha256:/, ''))
|
|
118
|
+
throw new RemoteError(0, 'ARTIFACT_DIGEST_MISMATCH', `${a.path} does not match the digest the server reported; it was not written.`);
|
|
119
|
+
await mkdir(dirname(target), { recursive: true });
|
|
120
|
+
await writeFile(target, bytes);
|
|
121
|
+
written.push(check.path);
|
|
122
|
+
}
|
|
123
|
+
return written;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=remote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote.js","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@x12i/made-easy-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Command line for Made Easy: init, validate, preview, build, journey, pin, verify and draft the human guide and the AI agent guide. Same diagnostics and outputs as the SDK, API and MCP tools.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"made-easy",
|
|
8
|
+
"cli",
|
|
9
|
+
"guide",
|
|
10
|
+
"ebook",
|
|
11
|
+
"ai-agent",
|
|
12
|
+
"markdown",
|
|
13
|
+
"x12i"
|
|
14
|
+
],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": "x12i",
|
|
17
|
+
"homepage": "https://github.com/x12i/made-easy#readme",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/x12i/made-easy.git",
|
|
21
|
+
"directory": "packages/cli"
|
|
22
|
+
},
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/x12i/made-easy/issues"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=22"
|
|
28
|
+
},
|
|
29
|
+
"bin": {
|
|
30
|
+
"made-easy": "dist/bin.js"
|
|
31
|
+
},
|
|
32
|
+
"main": "./dist/index.js",
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"import": "./dist/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"README.md",
|
|
44
|
+
"LICENSE"
|
|
45
|
+
],
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@x12i/made-easy": "^0.2.0"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"playwright-core": "^1.50.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"playwright-core": {
|
|
57
|
+
"optional": true
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|