contentrain 0.4.4 → 0.5.1
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/README.md +112 -34
- package/dist/{activity-CbkxcfDf.mjs → activity-B8j9gfsK.mjs} +3 -3
- package/dist/{branches-D2UWex1N.mjs → branches-CvpFbyrJ.mjs} +3 -3
- package/dist/{cdn-build-BzC2QPNi.mjs → cdn-build-DS9FprWU.mjs} +3 -3
- package/dist/{cdn-init-CsmqJIaQ.mjs → cdn-init-Bm4dpEJn.mjs} +3 -3
- package/dist/{connect-DJo9PSiw.mjs → connect-Bb0BrZsx.mjs} +3 -3
- package/dist/describe-DJ5H9Cxm.mjs +106 -0
- package/dist/describe-format-CUAqB0C4.mjs +50 -0
- package/dist/{diff--halNUpG.mjs → diff-ov1j9bAb.mjs} +67 -59
- package/dist/doctor-MOf_LQEL.mjs +95 -0
- package/dist/{generate-DrUojrk8.mjs → generate-ByscV5SN.mjs} +26 -9
- package/dist/index.mjs +50 -12
- package/dist/{init-CqoDCSV5.mjs → init-540qiNQJ.mjs} +6 -6
- package/dist/{login-DCXkOrQV.mjs → login-xvzL-UvR.mjs} +3 -3
- package/dist/{logout-nPt2UAeQ.mjs → logout-DzspSatR.mjs} +2 -2
- package/dist/mcp-client-DVWTex2i.mjs +44 -0
- package/dist/merge-DdPRttF-.mjs +82 -0
- package/dist/{resolve-context-Cg6JoVZt.mjs → resolve-context-hKVYPniC.mjs} +1 -1
- package/dist/scaffold-iuvrMh78.mjs +115 -0
- package/dist/{serve-CNeFIQ1i.mjs → serve-CxA2pKbp.mjs} +58 -5
- package/dist/serve-ui/assets/{AgentPromptGroup.vue_vue_type_script_setup_true_lang-Ulb-9Tr3.js → AgentPromptGroup.vue_vue_type_script_setup_true_lang-Bftt9tx_.js} +1 -1
- package/dist/serve-ui/assets/AppLayout-B-fbrfMk.js +21 -0
- package/dist/serve-ui/assets/BranchDetailPage-B3PL9PGp.js +17 -0
- package/dist/serve-ui/assets/{BranchesPage-CSwikNkd.js → BranchesPage-4YpE_szf.js} +2 -2
- package/dist/serve-ui/assets/CardContent.vue_vue_type_script_setup_true_lang-D1L2MnBU.js +1 -0
- package/dist/serve-ui/assets/CollapsibleTrigger.vue_vue_type_script_setup_true_lang-B4uDtllm.js +1 -0
- package/dist/serve-ui/assets/{Collection-DTB4xCCE.js → Collection-9URFko-Y.js} +2 -2
- package/dist/serve-ui/assets/ConfigProvider-CwkmRpT5.js +1 -0
- package/dist/serve-ui/assets/{ContentListPage-DF-LjAaS.js → ContentListPage-BMfSfg8x.js} +2 -2
- package/dist/serve-ui/assets/ContentPage-BXUnNJlB.js +1 -0
- package/dist/serve-ui/assets/DashboardPage-1UyYgg5J.js +21 -0
- package/dist/serve-ui/assets/{DialogTitle.vue_vue_type_script_setup_true_lang-2sQAJn_Y.js → DialogTitle.vue_vue_type_script_setup_true_lang-M4LOzTva.js} +1 -1
- package/dist/serve-ui/assets/DoctorPage-WnQ8xYWy.js +1 -0
- package/dist/serve-ui/assets/FormatReferencePage-DoKEaawl.js +1 -0
- package/dist/serve-ui/assets/{Input.vue_vue_type_script_setup_true_lang-BveqfZsR.js → Input.vue_vue_type_script_setup_true_lang-tW0hgReH.js} +2 -2
- package/dist/serve-ui/assets/{ModelDetailPage-_TIV9itx.js → ModelDetailPage-BysqN8IL.js} +3 -3
- package/dist/serve-ui/assets/ModelsPage-DFZrdBIi.js +1 -0
- package/dist/serve-ui/assets/{NormalizePage-Cde8vdk2.js → NormalizePage-4f5Ib_ES.js} +2 -2
- package/dist/serve-ui/assets/{PageHeader.vue_vue_type_script_setup_true_lang-CEnjONvd.js → PageHeader.vue_vue_type_script_setup_true_lang-Bln1czg7.js} +1 -1
- package/dist/serve-ui/assets/Presence-CA3xTrht.js +3 -0
- package/dist/serve-ui/assets/{Separator.vue_vue_type_script_setup_true_lang-1pFZ2PR2.js → Separator.vue_vue_type_script_setup_true_lang-PECBq3nc.js} +1 -1
- package/dist/serve-ui/assets/{StudioHint.vue_vue_type_script_setup_true_lang-C6JN5tPq.js → StudioHint.vue_vue_type_script_setup_true_lang-DYTEoyjw.js} +1 -1
- package/dist/serve-ui/assets/{TrustBadge.vue_vue_type_script_setup_true_lang-KRiTnLVk.js → TrustBadge.vue_vue_type_script_setup_true_lang-BRXWvOYU.js} +2 -2
- package/dist/serve-ui/assets/ValidatePage-BMTpV2KL.js +16 -0
- package/dist/serve-ui/assets/{arrow-down-BAJwpryD.js → arrow-down-IJu6H7Es.js} +1 -1
- package/dist/serve-ui/assets/{arrow-left-DANf_wrK.js → arrow-left-D8ZjVYAI.js} +1 -1
- package/dist/serve-ui/assets/{book-marked-DS8FXgjz.js → book-marked-BNyyZrq3.js} +1 -1
- package/dist/serve-ui/assets/{book-open-DnH5T78M.js → book-open-Dw1fQtSI.js} +1 -1
- package/dist/serve-ui/assets/{box-UJk5SvJJ.js → box-BoGMZDZR.js} +1 -1
- package/dist/serve-ui/assets/{chevron-down-C1nYx5Eu.js → chevron-down-UcXxhyyY.js} +1 -1
- package/dist/serve-ui/assets/{chevron-right-XnJVrezx.js → chevron-right-SpdM5LBc.js} +1 -1
- package/dist/serve-ui/assets/circle-alert-CEwKJpYl.js +6 -0
- package/dist/serve-ui/assets/{content-Ctqretwl.js → content-BQEzysvq.js} +1 -1
- package/dist/serve-ui/assets/{database-Wd_i2bM1.js → database-U6JU8oc9.js} +1 -1
- package/dist/serve-ui/assets/{file-code-ScWZN40B.js → file-code-_sq1QHQo.js} +1 -1
- package/dist/serve-ui/assets/{file-text-J3Wzwieh.js → file-text-BiMGJckO.js} +1 -1
- package/dist/serve-ui/assets/{git-branch-DqEFTZDt.js → git-branch-CdZMOuSP.js} +1 -1
- package/dist/serve-ui/assets/{git-merge-Bmz-MVBm.js → git-merge-D8Y-BwIh.js} +1 -1
- package/dist/serve-ui/assets/{hash-pCwLSzjB.js → hash-CrXakbCy.js} +1 -1
- package/dist/serve-ui/assets/index-DL_dw3XX.js +80 -0
- package/dist/serve-ui/assets/index-KZ2rT4mJ.css +1 -0
- package/dist/serve-ui/assets/{languages-CQqNMim-.js → languages-DvyMGPwy.js} +1 -1
- package/dist/serve-ui/assets/{plus-Cw1OnTR2.js → plus-Ddujj7Qx.js} +1 -1
- package/dist/serve-ui/assets/project-Dg2BVay_.js +1 -0
- package/dist/serve-ui/assets/{scan-search-UJ-_oiOR.js → scan-search-CsPYGmEs.js} +1 -1
- package/dist/serve-ui/assets/{settings-Dnm4yTIj.js → settings-IQvevsKM.js} +1 -1
- package/dist/serve-ui/assets/{shield-check-B67ELGUT.js → shield-check-BmSBU8Ai.js} +1 -1
- package/dist/serve-ui/assets/stethoscope-DgCa_7BL.js +6 -0
- package/dist/serve-ui/assets/{trash-2-B1QgZW1G.js → trash-2-CNTkluuz.js} +1 -1
- package/dist/serve-ui/assets/useDirection-DfPL7a9d.js +1 -0
- package/dist/serve-ui/assets/{useId-CPFWZ4Bo.js → useId-B-RTM02R.js} +1 -1
- package/dist/serve-ui/assets/{useNonce-BffIzuhE.js → useNonce-DR6M3tLq.js} +1 -1
- package/dist/serve-ui/assets/useWatch-D4Y-epQR.js +1 -0
- package/dist/serve-ui/index.html +2 -2
- package/dist/{server-DTdmutjb.mjs → server-B1PSjXbu.mjs} +313 -112
- package/dist/{setup-Y1LFQ9rZ.mjs → setup-BMqKibZt.mjs} +3 -3
- package/dist/{skills-Cp8KF1af.mjs → skills-CZ54F-97.mjs} +3 -3
- package/dist/{status-Cyv-jo1y.mjs → status-BJ6Lu3J4.mjs} +3 -3
- package/dist/{status-CoHgz6HN.mjs → status-Bmjfrk-B.mjs} +24 -11
- package/dist/studio-DPVJ-2oG.mjs +24 -0
- package/dist/{submissions-bIG-MWvv.mjs → submissions-zH_S7JIQ.mjs} +3 -3
- package/dist/{usage-B2xuc2DT.mjs → usage-z6eyT64a.mjs} +3 -3
- package/dist/{validate-B10L7RL7.mjs → validate-BG0X5g09.mjs} +102 -4
- package/dist/{webhooks-Dq3zFLP7.mjs → webhooks-CBG2Bs9P.mjs} +3 -3
- package/dist/{whoami-Ub5RznbU.mjs → whoami-CXVfvo7x.mjs} +2 -2
- package/package.json +7 -6
- package/dist/doctor-DyKjAIKH.mjs +0 -187
- package/dist/serve-ui/assets/AppLayout-C91DN08z.js +0 -21
- package/dist/serve-ui/assets/BranchDetailPage-BokOnhE7.js +0 -17
- package/dist/serve-ui/assets/CollapsibleTrigger.vue_vue_type_script_setup_true_lang-BRzXVXDG.js +0 -1
- package/dist/serve-ui/assets/ConfigProvider-Dvd7YoEV.js +0 -1
- package/dist/serve-ui/assets/ContentPage-BABg8pgn.js +0 -1
- package/dist/serve-ui/assets/DashboardPage-BFLFEJNZ.js +0 -21
- package/dist/serve-ui/assets/ModelsPage-DrQemHQ-.js +0 -1
- package/dist/serve-ui/assets/Presence-BXKCIfUk.js +0 -3
- package/dist/serve-ui/assets/ValidatePage-DRFAySNR.js +0 -21
- package/dist/serve-ui/assets/index-CG5NtNtt.css +0 -1
- package/dist/serve-ui/assets/index-De_z0714.js +0 -1
- package/dist/serve-ui/assets/index-RDdffBTh.js +0 -80
- package/dist/serve-ui/assets/project-BlZcHJw6.js +0 -1
- package/dist/serve-ui/assets/useDirection-B4S5kPsI.js +0 -1
- package/dist/serve-ui/assets/useWatch-B2FLRWr8.js +0 -1
- package/dist/studio-CJUGiIMd.mjs +0 -24
- package/dist/{client-C400qHcL.mjs → client-C9E9D4mb.mjs} +1 -1
- package/dist/{context-An3xrvcP.mjs → context-OskMGy8y.mjs} +1 -1
- package/dist/{demo-DcBt6fw8.mjs → demo-BOUcAoFZ.mjs} +3 -3
- package/dist/{ide-_C2gUPbQ.mjs → ide-DPDVYiaq.mjs} +1 -1
- package/dist/{oauth-server-Beppljfz.mjs → oauth-server-smSxDoH5.mjs} +1 -1
- /package/dist/{ui-B5mXontH.mjs → ui-B8l_LC36.mjs} +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { i as pc, o as statusIcon } from "./ui-B8l_LC36.mjs";
|
|
2
|
+
import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
import { intro, log, outro, spinner } from "@clack/prompts";
|
|
5
|
+
import { runDoctor } from "@contentrain/mcp/core/doctor";
|
|
6
|
+
//#region src/commands/doctor.ts
|
|
7
|
+
/**
|
|
8
|
+
* Thin CLI wrapper over the shared `runDoctor()` from `@contentrain/mcp`.
|
|
9
|
+
*
|
|
10
|
+
* All health-check logic lives in the MCP core so the same report
|
|
11
|
+
* drives three consumers: this command, the `contentrain_doctor` MCP
|
|
12
|
+
* tool, and the Serve UI's `/api/doctor` route. Behaviour in the
|
|
13
|
+
* default (non-`--json`) mode is unchanged — same check labels, same
|
|
14
|
+
* details, same grouped usage output.
|
|
15
|
+
*/
|
|
16
|
+
var doctor_default = defineCommand({
|
|
17
|
+
meta: {
|
|
18
|
+
name: "doctor",
|
|
19
|
+
description: "Check project health and environment"
|
|
20
|
+
},
|
|
21
|
+
args: {
|
|
22
|
+
root: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Project root path",
|
|
25
|
+
required: false
|
|
26
|
+
},
|
|
27
|
+
usage: {
|
|
28
|
+
type: "boolean",
|
|
29
|
+
description: "Analyze content key usage in source files",
|
|
30
|
+
required: false
|
|
31
|
+
},
|
|
32
|
+
json: {
|
|
33
|
+
type: "boolean",
|
|
34
|
+
description: "Emit the raw DoctorReport JSON",
|
|
35
|
+
required: false
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
async run({ args }) {
|
|
39
|
+
const projectRoot = await resolveProjectRoot(args.root);
|
|
40
|
+
if (Boolean(args.json)) {
|
|
41
|
+
const report = await runDoctor(projectRoot, { usage: Boolean(args.usage) });
|
|
42
|
+
process.stdout.write(JSON.stringify(report, null, 2));
|
|
43
|
+
if (report.summary.failed > 0) process.exitCode = 1;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
intro(pc.bold("contentrain doctor"));
|
|
47
|
+
const s = spinner();
|
|
48
|
+
s.start("Running health checks...");
|
|
49
|
+
if (args.usage) s.message("Analyzing content key usage...");
|
|
50
|
+
const report = await runDoctor(projectRoot, { usage: Boolean(args.usage) });
|
|
51
|
+
s.stop("Health checks complete");
|
|
52
|
+
for (const check of report.checks) log.message(`${statusIcon(check.pass)} ${pc.bold(check.name)}: ${check.detail}`);
|
|
53
|
+
if (report.usage?.unusedKeys.length) {
|
|
54
|
+
log.message("");
|
|
55
|
+
log.message(pc.bold(" Unused keys:"));
|
|
56
|
+
const grouped = groupBy(report.usage.unusedKeys, (e) => e.model);
|
|
57
|
+
for (const [model, entries] of Object.entries(grouped)) {
|
|
58
|
+
const keyList = entries.length <= 5 ? entries.map((e) => e.key).join(", ") : `${entries.slice(0, 5).map((e) => e.key).join(", ")} (+${entries.length - 5} more)`;
|
|
59
|
+
log.message(` ${pc.dim(model)}: ${pc.yellow(keyList)}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (report.usage?.duplicateValues.length) {
|
|
63
|
+
log.message("");
|
|
64
|
+
log.message(pc.bold(" Duplicate values:"));
|
|
65
|
+
for (const dv of report.usage.duplicateValues.slice(0, 10)) {
|
|
66
|
+
const truncated = dv.value.length > 30 ? `${dv.value.slice(0, 30)}...` : dv.value;
|
|
67
|
+
log.message(` ${pc.dim(`${dv.model}/${dv.locale}`)}: ${pc.yellow(`"${truncated}"`)} → [${dv.keys.join(", ")}]`);
|
|
68
|
+
}
|
|
69
|
+
if (report.usage.duplicateValues.length > 10) log.message(` ... and ${report.usage.duplicateValues.length - 10} more`);
|
|
70
|
+
}
|
|
71
|
+
if (report.usage?.missingLocaleKeys.length) {
|
|
72
|
+
log.message("");
|
|
73
|
+
log.message(pc.bold(" Missing translations:"));
|
|
74
|
+
const grouped = groupBy(report.usage.missingLocaleKeys, (e) => `${e.model}/${e.missingIn}`);
|
|
75
|
+
for (const [label, entries] of Object.entries(grouped)) log.message(` ${pc.dim(label)}: ${pc.yellow(`${entries.length} key(s)`)}`);
|
|
76
|
+
}
|
|
77
|
+
const { passed, failed } = report.summary;
|
|
78
|
+
if (failed === 0) outro(pc.green(`All ${passed} checks passed!`));
|
|
79
|
+
else {
|
|
80
|
+
outro(pc.yellow(`${passed} passed, ${failed} failed`));
|
|
81
|
+
process.exitCode = 1;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
function groupBy(arr, keyFn) {
|
|
86
|
+
const result = {};
|
|
87
|
+
for (const item of arr) {
|
|
88
|
+
const key = keyFn(item);
|
|
89
|
+
if (!result[key]) result[key] = [];
|
|
90
|
+
result[key].push(item);
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { doctor_default as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { i as pc } from "./ui-B8l_LC36.mjs";
|
|
2
|
+
import { n as requireInitialized, r as resolveProjectRoot, t as loadProjectContext } from "./context-OskMGy8y.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { intro, log, outro, spinner } from "@clack/prompts";
|
|
5
5
|
import { join } from "node:path";
|
|
@@ -24,18 +24,33 @@ var generate_default = defineCommand({
|
|
|
24
24
|
type: "boolean",
|
|
25
25
|
description: "Watch for changes and regenerate",
|
|
26
26
|
required: false
|
|
27
|
+
},
|
|
28
|
+
json: {
|
|
29
|
+
type: "boolean",
|
|
30
|
+
description: "Emit the generate result as JSON (silences pretty output)",
|
|
31
|
+
required: false
|
|
27
32
|
}
|
|
28
33
|
},
|
|
29
34
|
async run({ args }) {
|
|
30
35
|
const projectRoot = await resolveProjectRoot(args.root);
|
|
31
36
|
requireInitialized(await loadProjectContext(projectRoot));
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
s
|
|
37
|
+
const useJson = Boolean(args.json);
|
|
38
|
+
if (!useJson) intro(pc.bold("contentrain generate"));
|
|
39
|
+
const s = useJson ? null : spinner();
|
|
40
|
+
s?.start("Generating SDK client...");
|
|
35
41
|
try {
|
|
36
42
|
const { generate } = await import("@contentrain/query/generate");
|
|
37
43
|
const result = await generate({ projectRoot });
|
|
38
|
-
s
|
|
44
|
+
s?.stop("SDK client generated");
|
|
45
|
+
if (useJson) {
|
|
46
|
+
process.stdout.write(JSON.stringify({
|
|
47
|
+
generatedFiles: result.generatedFiles,
|
|
48
|
+
typesCount: result.typesCount,
|
|
49
|
+
dataModulesCount: result.dataModulesCount,
|
|
50
|
+
packageJsonUpdated: Boolean(result.packageJsonUpdated)
|
|
51
|
+
}, null, 2));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
39
54
|
log.success(`Output: ${pc.cyan(".contentrain/client/")}`);
|
|
40
55
|
log.message(` Files: ${result.generatedFiles.length}`);
|
|
41
56
|
log.message(` Types: ${result.typesCount}`);
|
|
@@ -66,11 +81,13 @@ var generate_default = defineCommand({
|
|
|
66
81
|
await new Promise(() => {});
|
|
67
82
|
}
|
|
68
83
|
} catch (error) {
|
|
69
|
-
s
|
|
70
|
-
|
|
84
|
+
s?.stop("Generation failed");
|
|
85
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
86
|
+
if (useJson) process.stdout.write(JSON.stringify({ error: message }, null, 2));
|
|
87
|
+
else log.error(message);
|
|
71
88
|
process.exitCode = 1;
|
|
72
89
|
}
|
|
73
|
-
outro("");
|
|
90
|
+
if (!useJson) outro("");
|
|
74
91
|
}
|
|
75
92
|
});
|
|
76
93
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -1,25 +1,63 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { i as pc } from "./ui-B8l_LC36.mjs";
|
|
2
3
|
import { defineCommand, runMain } from "citty";
|
|
4
|
+
//#region package.json
|
|
5
|
+
var version = "0.5.1";
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/utils/debug.ts
|
|
8
|
+
/**
|
|
9
|
+
* Debug logging — silent by default, enabled by either the
|
|
10
|
+
* `--debug` flag (recognised per-command) or the
|
|
11
|
+
* `CONTENTRAIN_DEBUG=1` env var. Intended for diagnosing
|
|
12
|
+
* git transactions, MCP calls, and file writes when the
|
|
13
|
+
* user-facing output isn't enough.
|
|
14
|
+
*
|
|
15
|
+
* The tiny helper here is deliberately local — we do not want
|
|
16
|
+
* to ship a logging dependency for something this small.
|
|
17
|
+
* Everything routes through stderr so `--json` stdout payloads
|
|
18
|
+
* stay clean and CI can still capture diagnostic output.
|
|
19
|
+
*/
|
|
20
|
+
let enabled = Boolean(process.env["CONTENTRAIN_DEBUG"]);
|
|
21
|
+
/** Turn debug on for the rest of the process. Command runners call
|
|
22
|
+
* this when `--debug` is passed. Once on, stays on. */
|
|
23
|
+
function enableDebug() {
|
|
24
|
+
enabled = true;
|
|
25
|
+
}
|
|
26
|
+
/** Opening banner for a debug block. `context` is a short label — the
|
|
27
|
+
* command name or helper — that lets the reader grep the noise. */
|
|
28
|
+
function debug(context, message) {
|
|
29
|
+
if (!enabled) return;
|
|
30
|
+
process.stderr.write(`${pc.dim(`[debug:${context}]`)} ${message}\n`);
|
|
31
|
+
}
|
|
3
32
|
//#endregion
|
|
4
33
|
//#region src/index.ts
|
|
34
|
+
const debugIndex = process.argv.findIndex((a) => a === "--debug");
|
|
35
|
+
if (debugIndex !== -1) {
|
|
36
|
+
enableDebug();
|
|
37
|
+
process.argv.splice(debugIndex, 1);
|
|
38
|
+
}
|
|
5
39
|
runMain(defineCommand({
|
|
6
40
|
meta: {
|
|
7
41
|
name: "contentrain",
|
|
8
|
-
version
|
|
42
|
+
version,
|
|
9
43
|
description: "Contentrain CLI — AI content governance infrastructure"
|
|
10
44
|
},
|
|
11
45
|
subCommands: {
|
|
12
|
-
init: () => import("./init-
|
|
13
|
-
status: () => import("./status-
|
|
14
|
-
doctor: () => import("./doctor-
|
|
15
|
-
validate: () => import("./validate-
|
|
16
|
-
serve: () => import("./serve-
|
|
17
|
-
generate: () => import("./generate-
|
|
18
|
-
diff: () => import("./diff
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
46
|
+
init: () => import("./init-540qiNQJ.mjs").then((m) => m.default),
|
|
47
|
+
status: () => import("./status-Bmjfrk-B.mjs").then((m) => m.default),
|
|
48
|
+
doctor: () => import("./doctor-MOf_LQEL.mjs").then((m) => m.default),
|
|
49
|
+
validate: () => import("./validate-BG0X5g09.mjs").then((m) => m.default),
|
|
50
|
+
serve: () => import("./serve-CxA2pKbp.mjs").then((m) => m.default),
|
|
51
|
+
generate: () => import("./generate-ByscV5SN.mjs").then((m) => m.default),
|
|
52
|
+
diff: () => import("./diff-ov1j9bAb.mjs").then((m) => m.default),
|
|
53
|
+
merge: () => import("./merge-DdPRttF-.mjs").then((m) => m.default),
|
|
54
|
+
describe: () => import("./describe-DJ5H9Cxm.mjs").then((m) => m.default),
|
|
55
|
+
"describe-format": () => import("./describe-format-CUAqB0C4.mjs").then((m) => m.default),
|
|
56
|
+
scaffold: () => import("./scaffold-iuvrMh78.mjs").then((m) => m.default),
|
|
57
|
+
setup: () => import("./setup-BMqKibZt.mjs").then((m) => m.default),
|
|
58
|
+
skills: () => import("./skills-CZ54F-97.mjs").then((m) => m.default),
|
|
59
|
+
studio: () => import("./studio-DPVJ-2oG.mjs").then((m) => m.default)
|
|
22
60
|
}
|
|
23
61
|
}));
|
|
24
62
|
//#endregion
|
|
25
|
-
export {};
|
|
63
|
+
export { debug as t };
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { a as createPackageResolver, c as writeMcpConfig, i as addClaudeMdReference, n as IDE_CONFIGS, o as detectIdes, s as installIdeRulesAndSkills } from "./ide-
|
|
1
|
+
import { i as pc } from "./ui-B8l_LC36.mjs";
|
|
2
|
+
import { r as resolveProjectRoot, t as loadProjectContext } from "./context-OskMGy8y.mjs";
|
|
3
|
+
import { a as createPackageResolver, c as writeMcpConfig, i as addClaudeMdReference, n as IDE_CONFIGS, o as detectIdes, s as installIdeRulesAndSkills } from "./ide-DPDVYiaq.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { confirm, intro, isCancel, log, multiselect, outro, select, spinner } from "@clack/prompts";
|
|
6
|
-
import { simpleGit } from "simple-git";
|
|
7
6
|
import { join } from "node:path";
|
|
8
7
|
import { writeModel } from "@contentrain/mcp/core/model-manager";
|
|
9
8
|
import { ensureDir, pathExists, writeJson } from "@contentrain/mcp/util/fs";
|
|
10
|
-
import {
|
|
9
|
+
import { simpleGit } from "simple-git";
|
|
10
|
+
import { buildBranchName, createTransaction } from "@contentrain/mcp/git/transaction";
|
|
11
11
|
import { detectStackInfo } from "@contentrain/mcp/util/detect";
|
|
12
12
|
import { getTemplate, listTemplates } from "@contentrain/mcp/templates";
|
|
13
|
-
import { buildBranchName, createTransaction } from "@contentrain/mcp/git/transaction";
|
|
14
13
|
import { scanSummary } from "@contentrain/mcp/core/scanner";
|
|
14
|
+
import { appendFile, readFile, writeFile } from "node:fs/promises";
|
|
15
15
|
//#region src/commands/init.ts
|
|
16
16
|
const COMMON_LOCALES = [
|
|
17
17
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as pc } from "./ui-
|
|
2
|
-
import { i as checkPermissions, o as loadCredentials, s as saveCredentials, t as StudioApiClient } from "./client-
|
|
3
|
-
import { n as openBrowser, t as startOAuthServer } from "./oauth-server-
|
|
1
|
+
import { i as pc } from "./ui-B8l_LC36.mjs";
|
|
2
|
+
import { i as checkPermissions, o as loadCredentials, s as saveCredentials, t as StudioApiClient } from "./client-C9E9D4mb.mjs";
|
|
3
|
+
import { n as openBrowser, t as startOAuthServer } from "./oauth-server-smSxDoH5.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { confirm, intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
|
|
6
6
|
//#region src/studio/commands/login.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as pc } from "./ui-
|
|
2
|
-
import { a as clearCredentials, o as loadCredentials, t as StudioApiClient } from "./client-
|
|
1
|
+
import { i as pc } from "./ui-B8l_LC36.mjs";
|
|
2
|
+
import { a as clearCredentials, o as loadCredentials, t as StudioApiClient } from "./client-C9E9D4mb.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { intro, log, outro } from "@clack/prompts";
|
|
5
5
|
//#region src/studio/commands/logout.ts
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createServer } from "@contentrain/mcp/server";
|
|
2
|
+
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
3
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
4
|
+
//#region src/utils/mcp-client.ts
|
|
5
|
+
/**
|
|
6
|
+
* Start an in-memory MCP session against a local project root. Always
|
|
7
|
+
* `await session.close()` — typically in a `finally` block — so the
|
|
8
|
+
* underlying transports release cleanly.
|
|
9
|
+
*/
|
|
10
|
+
async function openMcpSession(projectRoot) {
|
|
11
|
+
const server = createServer(projectRoot);
|
|
12
|
+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
13
|
+
const client = new Client({
|
|
14
|
+
name: "contentrain-cli",
|
|
15
|
+
version: "1.0.0"
|
|
16
|
+
});
|
|
17
|
+
await Promise.all([client.connect(clientTransport), server.connect(serverTransport)]);
|
|
18
|
+
return {
|
|
19
|
+
async call(name, args = {}, options = {}) {
|
|
20
|
+
const result = await client.callTool({
|
|
21
|
+
name,
|
|
22
|
+
arguments: args
|
|
23
|
+
});
|
|
24
|
+
const textContent = (result.content ?? []).find((c) => c.type === "text");
|
|
25
|
+
if (!textContent || typeof textContent.text !== "string") throw new Error(`Tool ${name} returned no text content`);
|
|
26
|
+
let parsed;
|
|
27
|
+
try {
|
|
28
|
+
parsed = JSON.parse(textContent.text);
|
|
29
|
+
} catch {
|
|
30
|
+
parsed = textContent.text;
|
|
31
|
+
}
|
|
32
|
+
if (result.isError && options.throwOnError !== false) {
|
|
33
|
+
const msg = typeof parsed === "object" && parsed !== null && "error" in parsed ? String(parsed.error) : textContent.text;
|
|
34
|
+
throw new Error(msg);
|
|
35
|
+
}
|
|
36
|
+
return parsed;
|
|
37
|
+
},
|
|
38
|
+
async close() {
|
|
39
|
+
await Promise.all([client.close().catch(() => {}), server.close().catch(() => {})]);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { openMcpSession as t };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { i as pc } from "./ui-B8l_LC36.mjs";
|
|
2
|
+
import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
import { confirm, intro, isCancel, log, outro } from "@clack/prompts";
|
|
5
|
+
import { simpleGit } from "simple-git";
|
|
6
|
+
import { CONTENTRAIN_BRANCH } from "@contentrain/types";
|
|
7
|
+
import { mergeBranch } from "@contentrain/mcp/git/transaction";
|
|
8
|
+
//#region src/commands/merge.ts
|
|
9
|
+
/**
|
|
10
|
+
* One-shot merge of a single contentrain feature branch.
|
|
11
|
+
*
|
|
12
|
+
* `contentrain diff` drives an interactive review over every pending
|
|
13
|
+
* branch; this command is the scriptable, one-branch sibling —
|
|
14
|
+
* shell-friendly for agents, CI, and manual triage. It reuses the exact
|
|
15
|
+
* same MCP helper (`mergeBranch`) that the interactive command
|
|
16
|
+
* delegates to, so the worktree transaction + selective-sync + dirty-
|
|
17
|
+
* file protections stay on one code path.
|
|
18
|
+
*/
|
|
19
|
+
var merge_default = defineCommand({
|
|
20
|
+
meta: {
|
|
21
|
+
name: "merge",
|
|
22
|
+
description: "Merge one contentrain feature branch into the content branch"
|
|
23
|
+
},
|
|
24
|
+
args: {
|
|
25
|
+
branch: {
|
|
26
|
+
type: "positional",
|
|
27
|
+
description: "Feature branch name (e.g. cr/content/blog/...)",
|
|
28
|
+
required: true
|
|
29
|
+
},
|
|
30
|
+
root: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "Project root path",
|
|
33
|
+
required: false
|
|
34
|
+
},
|
|
35
|
+
yes: {
|
|
36
|
+
type: "boolean",
|
|
37
|
+
description: "Skip confirmation prompt",
|
|
38
|
+
required: false
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
async run({ args }) {
|
|
42
|
+
const projectRoot = await resolveProjectRoot(args.root);
|
|
43
|
+
const branch = String(args.branch);
|
|
44
|
+
intro(pc.bold("contentrain merge"));
|
|
45
|
+
if (branch === CONTENTRAIN_BRANCH) {
|
|
46
|
+
log.error(`Cannot merge the content-tracking branch (${CONTENTRAIN_BRANCH}) into itself.`);
|
|
47
|
+
outro("");
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (!(await simpleGit(projectRoot).branchLocal()).all.includes(branch)) {
|
|
52
|
+
log.error(`Branch "${branch}" does not exist locally.`);
|
|
53
|
+
outro("");
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (!args.yes) {
|
|
58
|
+
const ok = await confirm({ message: `Merge ${branch} into ${CONTENTRAIN_BRANCH} and fast-forward the base branch?` });
|
|
59
|
+
if (isCancel(ok) || !ok) {
|
|
60
|
+
outro("");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const result = await mergeBranch(projectRoot, branch);
|
|
66
|
+
log.success(`Merged ${branch} (commit ${result.commit.slice(0, 8)})`);
|
|
67
|
+
if (result.sync?.synced?.length) log.message(pc.dim(` Synced ${result.sync.synced.length} file(s) to working tree.`));
|
|
68
|
+
if (result.sync?.skipped?.length) {
|
|
69
|
+
log.warning(`${result.sync.skipped.length} file(s) skipped during sync — you have uncommitted changes:`);
|
|
70
|
+
for (const f of result.sync.skipped) log.message(pc.dim(` ${f}`));
|
|
71
|
+
if (result.sync.warning) log.message(pc.dim(` ${result.sync.warning}`));
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
log.error(`Merge failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
75
|
+
process.exitCode = 1;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
outro("");
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
//#endregion
|
|
82
|
+
export { merge_default as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as saveDefaults, o as loadCredentials } from "./client-
|
|
1
|
+
import { c as saveDefaults, o as loadCredentials } from "./client-C9E9D4mb.mjs";
|
|
2
2
|
import { confirm, isCancel, select } from "@clack/prompts";
|
|
3
3
|
//#region src/studio/resolve-context.ts
|
|
4
4
|
/**
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { i as pc } from "./ui-B8l_LC36.mjs";
|
|
2
|
+
import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
|
|
3
|
+
import { t as openMcpSession } from "./mcp-client-DVWTex2i.mjs";
|
|
4
|
+
import { defineCommand } from "citty";
|
|
5
|
+
import { intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
|
|
6
|
+
//#region src/commands/scaffold.ts
|
|
7
|
+
const KNOWN_TEMPLATES = [
|
|
8
|
+
"blog",
|
|
9
|
+
"landing",
|
|
10
|
+
"docs",
|
|
11
|
+
"ecommerce",
|
|
12
|
+
"saas",
|
|
13
|
+
"i18n",
|
|
14
|
+
"mobile"
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* Template-based project seeding, wrapping `contentrain_scaffold`.
|
|
18
|
+
*
|
|
19
|
+
* Agents normally drive scaffolding through the MCP tool directly; this
|
|
20
|
+
* command gives humans the same entry point with an interactive
|
|
21
|
+
* template picker and a bit more actionable next-step output.
|
|
22
|
+
*/
|
|
23
|
+
var scaffold_default = defineCommand({
|
|
24
|
+
meta: {
|
|
25
|
+
name: "scaffold",
|
|
26
|
+
description: "Apply a Contentrain template (models + sample content + vocabulary)"
|
|
27
|
+
},
|
|
28
|
+
args: {
|
|
29
|
+
root: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Project root path",
|
|
32
|
+
required: false
|
|
33
|
+
},
|
|
34
|
+
template: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: `Template ID (${KNOWN_TEMPLATES.join(", ")})`,
|
|
37
|
+
required: false
|
|
38
|
+
},
|
|
39
|
+
locales: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description: "Comma-separated locale override (e.g. \"en,tr,de\")",
|
|
42
|
+
required: false
|
|
43
|
+
},
|
|
44
|
+
"no-sample": {
|
|
45
|
+
type: "boolean",
|
|
46
|
+
description: "Skip sample content",
|
|
47
|
+
required: false
|
|
48
|
+
},
|
|
49
|
+
json: {
|
|
50
|
+
type: "boolean",
|
|
51
|
+
description: "Emit raw JSON for scripts",
|
|
52
|
+
required: false
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
async run({ args }) {
|
|
56
|
+
const projectRoot = await resolveProjectRoot(args.root);
|
|
57
|
+
let templateId = args.template ? String(args.template) : void 0;
|
|
58
|
+
if (!templateId && !args.json) {
|
|
59
|
+
intro(pc.bold("contentrain scaffold"));
|
|
60
|
+
const pick = await select({
|
|
61
|
+
message: "Choose a template",
|
|
62
|
+
options: KNOWN_TEMPLATES.map((t) => ({
|
|
63
|
+
value: t,
|
|
64
|
+
label: t
|
|
65
|
+
}))
|
|
66
|
+
});
|
|
67
|
+
if (isCancel(pick)) {
|
|
68
|
+
outro("");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
templateId = pick;
|
|
72
|
+
}
|
|
73
|
+
if (!templateId) {
|
|
74
|
+
log.error("Template is required. Pass --template <id> or run interactively.");
|
|
75
|
+
process.exitCode = 1;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const locales = args.locales ? String(args.locales).split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
79
|
+
const session = await openMcpSession(projectRoot);
|
|
80
|
+
const s = args.json ? null : spinner();
|
|
81
|
+
s?.start(`Applying template "${templateId}"...`);
|
|
82
|
+
try {
|
|
83
|
+
const result = await session.call("contentrain_scaffold", {
|
|
84
|
+
template: templateId,
|
|
85
|
+
...locales ? { locales } : {},
|
|
86
|
+
with_sample_content: !args["no-sample"]
|
|
87
|
+
});
|
|
88
|
+
s?.stop(`Template "${templateId}" applied.`);
|
|
89
|
+
if (args.json) {
|
|
90
|
+
process.stdout.write(JSON.stringify(result, null, 2));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const git = result["git"];
|
|
94
|
+
log.success(`Scaffolded ${pc.bold(templateId)} on ${pc.cyan(git?.branch ?? "(branch)")} (${git?.action ?? "committed"})`);
|
|
95
|
+
const models = result["models_created"];
|
|
96
|
+
if (models?.length) log.message(` Models: ${models.map((m) => m.id).join(", ")}`);
|
|
97
|
+
if (typeof result["content_created"] === "number") log.message(` Sample entries: ${result["content_created"]}`);
|
|
98
|
+
if (typeof result["vocabulary_terms_added"] === "number" && result["vocabulary_terms_added"]) log.message(` Vocabulary terms added: ${result["vocabulary_terms_added"]}`);
|
|
99
|
+
const next = result["next_steps"];
|
|
100
|
+
if (next?.length) {
|
|
101
|
+
log.info(pc.bold("\nNext steps"));
|
|
102
|
+
for (const step of next) log.message(` • ${step}`);
|
|
103
|
+
}
|
|
104
|
+
outro("");
|
|
105
|
+
} catch (error) {
|
|
106
|
+
s?.stop("Scaffold failed.");
|
|
107
|
+
log.error(error instanceof Error ? error.message : String(error));
|
|
108
|
+
process.exitCode = 1;
|
|
109
|
+
} finally {
|
|
110
|
+
await session.close();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
//#endregion
|
|
115
|
+
export { scaffold_default as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as resolveProjectRoot } from "./context-
|
|
1
|
+
import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
|
|
2
2
|
import { defineCommand } from "citty";
|
|
3
3
|
import { createServer } from "@contentrain/mcp/server";
|
|
4
4
|
import consola from "consola";
|
|
@@ -6,7 +6,7 @@ import consola from "consola";
|
|
|
6
6
|
var serve_default = defineCommand({
|
|
7
7
|
meta: {
|
|
8
8
|
name: "serve",
|
|
9
|
-
description: "Start local content viewer or MCP stdio
|
|
9
|
+
description: "Start the local content viewer or the MCP server (stdio for IDE agents, --mcpHttp for Studio / CI / remote drivers)"
|
|
10
10
|
},
|
|
11
11
|
args: {
|
|
12
12
|
root: {
|
|
@@ -19,6 +19,16 @@ var serve_default = defineCommand({
|
|
|
19
19
|
description: "Use stdio MCP transport for IDE integration (env: CONTENTRAIN_STDIO=true)",
|
|
20
20
|
required: false
|
|
21
21
|
},
|
|
22
|
+
mcpHttp: {
|
|
23
|
+
type: "boolean",
|
|
24
|
+
description: "Use HTTP MCP transport (serves tool calls at POST /mcp)",
|
|
25
|
+
required: false
|
|
26
|
+
},
|
|
27
|
+
authToken: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Bearer token required for HTTP MCP requests (env: CONTENTRAIN_AUTH_TOKEN)",
|
|
30
|
+
required: false
|
|
31
|
+
},
|
|
22
32
|
port: {
|
|
23
33
|
type: "string",
|
|
24
34
|
description: "HTTP server port, default: 3333 (env: CONTENTRAIN_PORT)",
|
|
@@ -44,7 +54,7 @@ var serve_default = defineCommand({
|
|
|
44
54
|
let projectRoot = await resolveProjectRoot(args.root);
|
|
45
55
|
let demoDir;
|
|
46
56
|
if (args.demo) {
|
|
47
|
-
const { createDemoProject, cleanupDemoProject } = await import("./demo-
|
|
57
|
+
const { createDemoProject, cleanupDemoProject } = await import("./demo-BOUcAoFZ.mjs");
|
|
48
58
|
demoDir = await createDemoProject();
|
|
49
59
|
projectRoot = demoDir;
|
|
50
60
|
consola.info(`Demo project created at ${demoDir}`);
|
|
@@ -76,6 +86,50 @@ var serve_default = defineCommand({
|
|
|
76
86
|
}
|
|
77
87
|
const port = Number(args.port) || Number(process.env["CONTENTRAIN_PORT"]) || 3333;
|
|
78
88
|
const host = args.host ?? process.env["CONTENTRAIN_HOST"] ?? "localhost";
|
|
89
|
+
const authToken = args.authToken ?? process.env["CONTENTRAIN_AUTH_TOKEN"];
|
|
90
|
+
if (args.mcpHttp || process.env["CONTENTRAIN_MCP_HTTP"] === "true" || process.env["CONTENTRAIN_MCP_HTTP"] === "1") {
|
|
91
|
+
const { startHttpMcpServer } = await import("@contentrain/mcp/server/http");
|
|
92
|
+
const handle = await startHttpMcpServer({
|
|
93
|
+
projectRoot,
|
|
94
|
+
host,
|
|
95
|
+
port,
|
|
96
|
+
authToken
|
|
97
|
+
});
|
|
98
|
+
consola.box({
|
|
99
|
+
title: "Contentrain MCP (HTTP)",
|
|
100
|
+
message: [
|
|
101
|
+
`Endpoint: ${handle.url}`,
|
|
102
|
+
`Root: ${projectRoot}`,
|
|
103
|
+
authToken ? "Auth: Bearer token required" : "Auth: none (local-only server)",
|
|
104
|
+
"",
|
|
105
|
+
"Press Ctrl+C to stop"
|
|
106
|
+
].join("\n")
|
|
107
|
+
});
|
|
108
|
+
if (host === "0.0.0.0" && !authToken) consola.warn("HTTP MCP server is accessible from the network with no Bearer token. Set --auth-token or CONTENTRAIN_AUTH_TOKEN.");
|
|
109
|
+
process.on("SIGINT", () => {
|
|
110
|
+
handle.close().finally(() => process.exit(0));
|
|
111
|
+
});
|
|
112
|
+
process.on("SIGTERM", () => {
|
|
113
|
+
handle.close().finally(() => process.exit(0));
|
|
114
|
+
});
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (host !== "localhost" && host !== "127.0.0.1" && !authToken) {
|
|
118
|
+
consola.error([
|
|
119
|
+
`Refusing to start serve UI on ${host} without a Bearer token.`,
|
|
120
|
+
"",
|
|
121
|
+
" The serve UI exposes the full .contentrain/ write surface to any",
|
|
122
|
+
" reachable host. Either bind to localhost:",
|
|
123
|
+
"",
|
|
124
|
+
" contentrain serve --host localhost",
|
|
125
|
+
"",
|
|
126
|
+
" Or pass an auth token (coming soon — today, use stdio MCP for remote agents):",
|
|
127
|
+
"",
|
|
128
|
+
" contentrain serve --mcpHttp --host 0.0.0.0 --authToken $(openssl rand -hex 32)"
|
|
129
|
+
].join("\n"));
|
|
130
|
+
process.exitCode = 1;
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
79
133
|
const shouldOpen = args.open !== false && process.env["CONTENTRAIN_NO_OPEN"] !== "true";
|
|
80
134
|
const { join, dirname } = await import("node:path");
|
|
81
135
|
const { existsSync } = await import("node:fs");
|
|
@@ -85,7 +139,7 @@ var serve_default = defineCommand({
|
|
|
85
139
|
consola.warn("Serve UI not found. Running in API-only mode.");
|
|
86
140
|
consola.info("UI will be available after building: cd packages/cli/src/serve-ui && pnpm build");
|
|
87
141
|
}
|
|
88
|
-
const { createServeApp } = await import("./server-
|
|
142
|
+
const { createServeApp } = await import("./server-B1PSjXbu.mjs");
|
|
89
143
|
const { app, handleUpgrade } = await createServeApp({
|
|
90
144
|
projectRoot,
|
|
91
145
|
port,
|
|
@@ -123,7 +177,6 @@ var serve_default = defineCommand({
|
|
|
123
177
|
exec(`${process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open"} ${url}`);
|
|
124
178
|
});
|
|
125
179
|
});
|
|
126
|
-
if (host === "0.0.0.0") consola.warn("Server is accessible from the network. No authentication is configured.");
|
|
127
180
|
}
|
|
128
181
|
});
|
|
129
182
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as i,a as p,o as t,p as o,q as s,j as u,u as a,B as n,g as m,b as l,r as x,
|
|
1
|
+
import{c as i,a as p,o as t,p as o,q as s,j as u,u as a,B as n,g as m,b as l,r as x,G as d,f as g}from"./index-DL_dw3XX.js";/**
|
|
2
2
|
* @license lucide-vue-next v0.474.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|