@easysociable/cli 0.1.8 → 0.1.9
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 +29 -9
- package/dist/easysociable.js +111 -100
- package/dist/easysociable.js.map +1 -1
- package/package.json +2 -2
- package/scripts/engine/migrate-split-vault.py +75 -0
- package/skills/ONBOARDING.md +19 -4
- package/skills/easysociable-content/SKILL.md +25 -9
- package/content-engine/scripts/fixture.test.mjs +0 -24
- package/content-engine/scripts/starter.mjs +0 -58
- package/content-engine/scripts/validate.test.mjs +0 -101
- package/content-engine/scripts/workbench.mjs +0 -140
- package/content-engine/starter/CLAUDE.md +0 -908
- package/content-engine/starter/accounts/README.md +0 -9
- package/content-engine/starter/accounts/_index.md +0 -31
- package/content-engine/starter/accounts/overrides/README.md +0 -3
- package/content-engine/starter/engine.json +0 -23
- package/content-engine/starter/exports/README.md +0 -28
- package/content-engine/starter/hits/README.md +0 -5
- package/content-engine/starter/hits/_index.md +0 -30
- package/content-engine/starter/hits/_template.md +0 -46
- package/content-engine/starter/hits/entries/README.md +0 -3
- package/content-engine/starter/inbox/README.md +0 -9
- package/content-engine/starter/inbox/_index.md +0 -24
- package/content-engine/starter/inbox/entries/README.md +0 -3
- package/content-engine/starter/needs/README.md +0 -38
- package/content-engine/starter/needs/_index.md +0 -31
- package/content-engine/starter/needs/_template.md +0 -24
- package/content-engine/starter/needs/entries/README.md +0 -5
- package/content-engine/starter/platforms/README.md +0 -19
- package/content-engine/starter/platforms/ig.md +0 -69
- package/content-engine/starter/platforms/instagram.md +0 -5
- package/content-engine/starter/platforms/linkedin.md +0 -72
- package/content-engine/starter/platforms/threads.md +0 -69
- package/content-engine/starter/platforms/tiktok.md +0 -71
- package/content-engine/starter/platforms/x.md +0 -78
- package/content-engine/starter/platforms/xiaohongshu.md +0 -19
- package/content-engine/starter/products/README.md +0 -38
- package/content-engine/starter/products/_index.md +0 -25
- package/content-engine/starter/products/_template.md +0 -56
- package/content-engine/starter/products/entries/P-001-easysociable.md +0 -150
- package/content-engine/starter/products/entries/P-002-content-engine.md +0 -136
- package/content-engine/starter/profiles/_index.md +0 -16
- package/content-engine/starter/profiles/default/README.md +0 -17
- package/content-engine/starter/profiles/default/audience.md +0 -38
- package/content-engine/starter/profiles/default/boundaries.md +0 -14
- package/content-engine/starter/profiles/default/expression.md +0 -18
- package/content-engine/starter/profiles/default/handles.md +0 -8
- package/content-engine/starter/profiles/default/keywords.md +0 -31
- package/content-engine/starter/profiles/default/lanes.md +0 -12
- package/content-engine/starter/profiles/default/pillars.md +0 -33
- package/content-engine/starter/profiles/default/stories.md +0 -15
- package/content-engine/starter/profiles/default/voice.md +0 -38
- package/content-engine/starter/published/_index.md +0 -20
- package/content-engine/starter/raw/README.md +0 -4
- package/content-engine/starter/raw/_index.md +0 -12
- package/content-engine/starter/recommendations/README.md +0 -21
- package/content-engine/starter/recommendations/_index.md +0 -21
- package/content-engine/starter/recommendations/_template.md +0 -44
- package/content-engine/starter/runs/README.md +0 -22
- package/content-engine/starter/runs/_index.md +0 -41
- package/content-engine/starter/runs/_template/brief.md +0 -76
- package/content-engine/starter/runs/_template/draft.md +0 -11
- package/content-engine/starter/runs/_template/editor.md +0 -18
- package/content-engine/starter/runs/_template/feedback.md +0 -15
- package/content-engine/starter/runs/_template/idea.md +0 -27
- package/content-engine/starter/runs/_template/pack.md +0 -55
- package/content-engine/starter/runs/_template/packet.md +0 -31
- package/content-engine/starter/runs/_template/rubric.md +0 -19
- package/content-engine/starter/swipe/_index.md +0 -27
- package/content-engine/starter/swipe/_template.md +0 -36
- package/content-engine/starter/topics/README.md +0 -21
- package/content-engine/starter/topics/_index.md +0 -51
- package/content-engine/starter/topics/_template-item.md +0 -106
- package/content-engine/starter/topics/items/README.md +0 -4
- package/content-engine/starter/topics/scoring.md +0 -255
- package/content-engine/starter/wiki/README.md +0 -13
- package/content-engine/starter/wiki/atoms/_index.md +0 -23
- package/content-engine/starter/wiki/atoms/_template.md +0 -31
- package/content-engine/starter/wiki/claims/_index.md +0 -26
- package/content-engine/starter/wiki/claims/_template.md +0 -38
- package/content-engine/starter/workbench/README.md +0 -17
- package/content-engine/workbench/__pycache__/build.cpython-310.pyc +0 -0
- package/content-engine/workbench/build.py +0 -1467
- package/content-engine/workbench/serve.py +0 -53
- package/content-engine/workbench/template.html +0 -2683
- /package/{content-engine/scripts → scripts/engine}/contracts.mjs +0 -0
- /package/{content-engine/scripts → scripts/engine}/export-contracts.mjs +0 -0
- /package/{content-engine → scripts/engine}/fixtures/golden-run-en/draft.md +0 -0
- /package/{content-engine → scripts/engine}/fixtures/golden-run-en/idea.md +0 -0
- /package/{content-engine → scripts/engine}/fixtures/golden-run-en/pack-tiktok.json +0 -0
- /package/{content-engine/scripts → scripts/engine}/validate-export.mjs +0 -0
- /package/{content-engine/scripts → scripts/engine}/validate-pack.mjs +0 -0
- /package/{content-engine/scripts → scripts/engine}/validate-run.mjs +0 -0
package/README.md
CHANGED
|
@@ -21,27 +21,47 @@ Default install does **not** include `easysociable-content`. Add it when you wan
|
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
23
|
easysociable install --skills content,template,slideshow --yes
|
|
24
|
-
easysociable engine init --root /workspace --yes
|
|
25
|
-
easysociable engine serve --engine /workspace/Content Engine --no-open
|
|
26
24
|
```
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
**Preferred:** clone the public core:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/murphywuwu/content-engine.git
|
|
30
|
+
cd content-engine
|
|
31
|
+
python3 workbench/build.py
|
|
32
|
+
python3 workbench/serve.py --no-open
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
See https://github.com/murphywuwu/content-engine (LAYOUT.md, migrate-split-vault.py).
|
|
36
|
+
|
|
37
|
+
**Optional:** `easysociable engine init --root … --yes` clones that repo into
|
|
38
|
+
`Content Engine/` (never overwrites an existing engine).
|
|
39
|
+
|
|
40
|
+
Then tell the Agent to follow `CLAUDE.md`. The core includes separate
|
|
41
|
+
`products/` (owned offers) and `recommendations/` (third-party review subjects);
|
|
42
|
+
neither is a substitute for `needs/`.
|
|
31
43
|
|
|
32
44
|
Lazy-auth guidance lives in the package at `skills/ONBOARDING.md`.
|
|
33
45
|
|
|
34
46
|
## Content Engine
|
|
35
47
|
|
|
48
|
+
Core methodology lives in the **public GitHub repo**, not inside this CLI
|
|
49
|
+
tarball. `engine serve` / `build` do **not** overwrite local workbench files
|
|
50
|
+
unless you pass `--sync-workbench` (pulls from the public core checkout /
|
|
51
|
+
`CONTENT_ENGINE_CORE`).
|
|
52
|
+
|
|
36
53
|
| Command | Purpose |
|
|
37
54
|
|---------|---------|
|
|
38
|
-
| `easysociable engine init [--root] [--yes] [--serve]` |
|
|
39
|
-
| `easysociable engine serve [--engine] [--no-open]` |
|
|
40
|
-
| `easysociable engine build [--engine]` |
|
|
55
|
+
| `easysociable engine init [--root] [--yes] [--serve]` | Clone public core into `Content Engine/` (no overwrite) |
|
|
56
|
+
| `easysociable engine serve [--engine] [--no-open] [--sync-workbench]` | Rebuild + start on `:8765` |
|
|
57
|
+
| `easysociable engine build [--engine] [--sync-workbench]` | Rebuild `workbench/index.html` |
|
|
41
58
|
| `easysociable engine detect` | Find engines under search roots |
|
|
42
|
-
| `easysociable engine validate --root …` |
|
|
59
|
+
| `easysociable engine validate --root …` | Core marker completeness |
|
|
43
60
|
| `easysociable engine validate --run …` | Run / pack checks before render |
|
|
44
61
|
|
|
62
|
+
Optional `engine.json` field `vault_root` (default `"."`) points data at a
|
|
63
|
+
separate vault; see the public LAYOUT.md.
|
|
64
|
+
|
|
45
65
|
The Workbench exposes Products and Recommendations as separate read-only
|
|
46
66
|
indexes. Topics can cite either one without forcing a product connection.
|
|
47
67
|
|
package/dist/easysociable.js
CHANGED
|
@@ -32639,12 +32639,13 @@ function resolveDefaultSkillsSource(moduleUrl) {
|
|
|
32639
32639
|
import { spawn, spawnSync } from "child_process";
|
|
32640
32640
|
import {
|
|
32641
32641
|
copyFileSync,
|
|
32642
|
+
cpSync,
|
|
32642
32643
|
existsSync as existsSync3,
|
|
32643
32644
|
mkdirSync as mkdirSync2,
|
|
32644
32645
|
readdirSync,
|
|
32645
32646
|
readFileSync as readFileSync2,
|
|
32646
|
-
|
|
32647
|
-
|
|
32647
|
+
rmSync,
|
|
32648
|
+
statSync
|
|
32648
32649
|
} from "fs";
|
|
32649
32650
|
import net from "net";
|
|
32650
32651
|
import { homedir as homedir2 } from "os";
|
|
@@ -32652,29 +32653,61 @@ import { basename, dirname as dirname3, join as join3, resolve } from "path";
|
|
|
32652
32653
|
var ENGINE_ROOT_NAME = "Content Engine";
|
|
32653
32654
|
var WORKBENCH_PORT = 8765;
|
|
32654
32655
|
var WORKBENCH_URL = `http://127.0.0.1:${WORKBENCH_PORT}/workbench/`;
|
|
32655
|
-
var
|
|
32656
|
-
|
|
32657
|
-
|
|
32658
|
-
|
|
32659
|
-
|
|
32660
|
-
|
|
32661
|
-
|
|
32662
|
-
|
|
32663
|
-
|
|
32664
|
-
|
|
32665
|
-
|
|
32666
|
-
|
|
32667
|
-
|
|
32668
|
-
|
|
32669
|
-
|
|
32670
|
-
return join3(contentEnginePackageRoot(moduleUrl), "workbench");
|
|
32671
|
-
}
|
|
32672
|
-
function scriptsDir(moduleUrl) {
|
|
32673
|
-
return join3(contentEnginePackageRoot(moduleUrl), "scripts");
|
|
32674
|
-
}
|
|
32656
|
+
var CONTENT_ENGINE_REPO = "https://github.com/murphywuwu/content-engine.git";
|
|
32657
|
+
var WORKBENCH_FILES = ["template.html", "build.py", "serve.py", "roots.py"];
|
|
32658
|
+
var REQUIRED_RELATIVE = [
|
|
32659
|
+
"CLAUDE.md",
|
|
32660
|
+
"engine.json",
|
|
32661
|
+
"LAYOUT.md",
|
|
32662
|
+
"workbench/build.py",
|
|
32663
|
+
"workbench/serve.py",
|
|
32664
|
+
"workbench/template.html",
|
|
32665
|
+
"workbench/roots.py",
|
|
32666
|
+
"needs/_index.md",
|
|
32667
|
+
"topics/_index.md",
|
|
32668
|
+
"runs/_index.md",
|
|
32669
|
+
"profiles/_index.md"
|
|
32670
|
+
];
|
|
32675
32671
|
function isDir(path) {
|
|
32676
32672
|
return existsSync3(path) && statSync(path).isDirectory();
|
|
32677
32673
|
}
|
|
32674
|
+
function scriptsDir(moduleUrl) {
|
|
32675
|
+
return join3(cliPackageRoot(moduleUrl), "scripts", "engine");
|
|
32676
|
+
}
|
|
32677
|
+
function contentEngineRepoUrl() {
|
|
32678
|
+
return (process.env.CONTENT_ENGINE_REPO || CONTENT_ENGINE_REPO).trim() || CONTENT_ENGINE_REPO;
|
|
32679
|
+
}
|
|
32680
|
+
function ensureCoreCheckout({ update = false } = {}) {
|
|
32681
|
+
const local = (process.env.CONTENT_ENGINE_CORE || "").trim();
|
|
32682
|
+
if (local) {
|
|
32683
|
+
const abs = resolve(local);
|
|
32684
|
+
if (!existsSync3(join3(abs, "CLAUDE.md")))
|
|
32685
|
+
throw new Error(`CONTENT_ENGINE_CORE=${abs} is missing CLAUDE.md`);
|
|
32686
|
+
return abs;
|
|
32687
|
+
}
|
|
32688
|
+
const cache = join3(homedir2(), ".cache", "easysociable", "content-engine");
|
|
32689
|
+
const marker = join3(cache, "CLAUDE.md");
|
|
32690
|
+
if (existsSync3(marker) && !update)
|
|
32691
|
+
return cache;
|
|
32692
|
+
mkdirSync2(dirname3(cache), { recursive: true });
|
|
32693
|
+
if (existsSync3(marker) && update) {
|
|
32694
|
+
const pull = spawnSync("git", ["-C", cache, "pull", "--ff-only"], { encoding: "utf8" });
|
|
32695
|
+
if (pull.status !== 0) {
|
|
32696
|
+
rmSync(cache, { recursive: true, force: true });
|
|
32697
|
+
} else {
|
|
32698
|
+
return cache;
|
|
32699
|
+
}
|
|
32700
|
+
}
|
|
32701
|
+
if (existsSync3(cache))
|
|
32702
|
+
rmSync(cache, { recursive: true, force: true });
|
|
32703
|
+
const clone3 = spawnSync("git", ["clone", "--depth", "1", contentEngineRepoUrl(), cache], { encoding: "utf8" });
|
|
32704
|
+
if (clone3.status !== 0 || !existsSync3(marker)) {
|
|
32705
|
+
throw new Error(
|
|
32706
|
+
`Failed to clone Content Engine core from ${contentEngineRepoUrl()}. ${clone3.stderr || clone3.stdout || ""}`.trim()
|
|
32707
|
+
);
|
|
32708
|
+
}
|
|
32709
|
+
return cache;
|
|
32710
|
+
}
|
|
32678
32711
|
function isEngine(path) {
|
|
32679
32712
|
return isDir(path) && existsSync3(join3(path, "CLAUDE.md")) && isDir(join3(path, "runs"));
|
|
32680
32713
|
}
|
|
@@ -32684,62 +32717,10 @@ function resolveEngine(rootOrEngine) {
|
|
|
32684
32717
|
return absolute;
|
|
32685
32718
|
return join3(absolute, ENGINE_ROOT_NAME);
|
|
32686
32719
|
}
|
|
32687
|
-
function
|
|
32688
|
-
const out = [];
|
|
32689
|
-
if (!existsSync3(dir))
|
|
32690
|
-
return out;
|
|
32691
|
-
for (const name of readdirSync(dir)) {
|
|
32692
|
-
if (name === ".DS_Store")
|
|
32693
|
-
continue;
|
|
32694
|
-
const path = join3(dir, name);
|
|
32695
|
-
if (statSync(path).isDirectory())
|
|
32696
|
-
out.push(...walkFiles(path));
|
|
32697
|
-
else
|
|
32698
|
-
out.push(path);
|
|
32699
|
-
}
|
|
32700
|
-
return out;
|
|
32701
|
-
}
|
|
32702
|
-
function engineJson() {
|
|
32703
|
-
return `${JSON.stringify({
|
|
32704
|
-
schemaVersion: "content-engine.v1",
|
|
32705
|
-
locale: "en",
|
|
32706
|
-
root: ENGINE_ROOT_NAME,
|
|
32707
|
-
paths: {
|
|
32708
|
-
runs: "runs",
|
|
32709
|
-
exports: "exports",
|
|
32710
|
-
topics: "topics",
|
|
32711
|
-
needs: "needs",
|
|
32712
|
-
hits: "hits",
|
|
32713
|
-
products: "products",
|
|
32714
|
-
recommendations: "recommendations",
|
|
32715
|
-
swipe: "swipe",
|
|
32716
|
-
profiles: "profiles",
|
|
32717
|
-
inbox: "inbox",
|
|
32718
|
-
accounts: "accounts",
|
|
32719
|
-
raw: "raw",
|
|
32720
|
-
published: "published",
|
|
32721
|
-
wiki: "wiki",
|
|
32722
|
-
platforms: "platforms",
|
|
32723
|
-
workbench: "workbench"
|
|
32724
|
-
}
|
|
32725
|
-
}, null, 2)}
|
|
32726
|
-
`;
|
|
32727
|
-
}
|
|
32728
|
-
function starterFiles(moduleUrl) {
|
|
32729
|
-
const root = starterDir(moduleUrl);
|
|
32730
|
-
const files = {};
|
|
32731
|
-
for (const path of walkFiles(root)) {
|
|
32732
|
-
const relativePath = path.slice(root.length + 1).split("\\").join("/");
|
|
32733
|
-
files[relativePath] = readFileSync2(path, "utf8");
|
|
32734
|
-
}
|
|
32735
|
-
files["engine.json"] = engineJson();
|
|
32736
|
-
return files;
|
|
32737
|
-
}
|
|
32738
|
-
function inventory(engine, moduleUrl) {
|
|
32739
|
-
const files = starterFiles(moduleUrl);
|
|
32720
|
+
function inventory(engine, _moduleUrl) {
|
|
32740
32721
|
const missing = [];
|
|
32741
32722
|
const existing = [];
|
|
32742
|
-
for (const relative of
|
|
32723
|
+
for (const relative of REQUIRED_RELATIVE) {
|
|
32743
32724
|
const path = join3(engine, relative);
|
|
32744
32725
|
(existsSync3(path) ? existing : missing).push(relative);
|
|
32745
32726
|
}
|
|
@@ -32747,6 +32728,7 @@ function inventory(engine, moduleUrl) {
|
|
|
32747
32728
|
engine,
|
|
32748
32729
|
engineExists: isDir(engine),
|
|
32749
32730
|
rootName: ENGINE_ROOT_NAME,
|
|
32731
|
+
repo: contentEngineRepoUrl(),
|
|
32750
32732
|
missing,
|
|
32751
32733
|
existing,
|
|
32752
32734
|
starterComplete: missing.length === 0
|
|
@@ -32855,7 +32837,7 @@ function validateEngine(rootOrEngine, moduleUrl, { strict = false, requireKnowle
|
|
|
32855
32837
|
if (!result.engineExists)
|
|
32856
32838
|
errors.push("Content Engine/ folder does not exist");
|
|
32857
32839
|
else if (result.missing.length > 0)
|
|
32858
|
-
errors.push(`
|
|
32840
|
+
errors.push(`Engine incomplete: ${result.missing.length} file(s) missing (clone ${contentEngineRepoUrl()} or run engine init --yes)`);
|
|
32859
32841
|
}
|
|
32860
32842
|
const knowledge = requireKnowledge ? checkKnowledge(engine) : void 0;
|
|
32861
32843
|
if (knowledge && !knowledge.valid)
|
|
@@ -32866,20 +32848,31 @@ function python3Bin() {
|
|
|
32866
32848
|
const result = spawnSync("python3", ["--version"], { encoding: "utf8" });
|
|
32867
32849
|
return result.status === 0 ? "python3" : "";
|
|
32868
32850
|
}
|
|
32869
|
-
function
|
|
32851
|
+
function wantWorkbenchSync(explicit) {
|
|
32852
|
+
if (explicit === true)
|
|
32853
|
+
return true;
|
|
32854
|
+
if (explicit === false)
|
|
32855
|
+
return false;
|
|
32856
|
+
const env = (process.env.EASYSOCIABLE_SYNC_WORKBENCH || "").trim().toLowerCase();
|
|
32857
|
+
return env === "1" || env === "true" || env === "yes";
|
|
32858
|
+
}
|
|
32859
|
+
function ensureWorkbench(engine, _moduleUrl, { update = false } = {}) {
|
|
32870
32860
|
const destDir = join3(engine, "workbench");
|
|
32871
32861
|
mkdirSync2(destDir, { recursive: true });
|
|
32872
32862
|
const copied = [];
|
|
32873
32863
|
const updated = [];
|
|
32874
32864
|
const skipped = [];
|
|
32875
|
-
const
|
|
32865
|
+
const needFetch = update || WORKBENCH_FILES.some((name) => !existsSync3(join3(destDir, name)));
|
|
32866
|
+
const srcRoot = needFetch ? join3(ensureCoreCheckout({ update }), "workbench") : "";
|
|
32876
32867
|
for (const name of WORKBENCH_FILES) {
|
|
32877
32868
|
const dest = join3(destDir, name);
|
|
32878
|
-
const from = join3(src, name);
|
|
32879
32869
|
if (existsSync3(dest) && !update) {
|
|
32880
32870
|
skipped.push(name);
|
|
32881
32871
|
continue;
|
|
32882
32872
|
}
|
|
32873
|
+
const from = join3(srcRoot, name);
|
|
32874
|
+
if (!existsSync3(from))
|
|
32875
|
+
throw new Error(`Missing ${name} in Content Engine core checkout`);
|
|
32883
32876
|
const existed = existsSync3(dest);
|
|
32884
32877
|
copyFileSync(from, dest);
|
|
32885
32878
|
if (existed)
|
|
@@ -32895,7 +32888,7 @@ function buildWorkbench(engine) {
|
|
|
32895
32888
|
return { ok: false, code: "PYTHON3_REQUIRED", message: "python3 is required for the workbench. Install Python 3 and retry." };
|
|
32896
32889
|
const script = join3(engine, "workbench", "build.py");
|
|
32897
32890
|
if (!existsSync3(script))
|
|
32898
|
-
return { ok: false, code: "WORKBENCH_MISSING", message:
|
|
32891
|
+
return { ok: false, code: "WORKBENCH_MISSING", message: `workbench/build.py is missing. Clone ${contentEngineRepoUrl()} or run engine init --yes.` };
|
|
32899
32892
|
const result = spawnSync(python, [script], { encoding: "utf8", cwd: engine });
|
|
32900
32893
|
if (result.status !== 0)
|
|
32901
32894
|
return { ok: false, code: "WORKBENCH_BUILD_FAILED", message: result.stderr.trim() || result.stdout.trim() || "workbench build failed" };
|
|
@@ -32915,11 +32908,15 @@ function openUrl(url2) {
|
|
|
32915
32908
|
const args = process.platform === "win32" ? ["/c", "start", url2] : [url2];
|
|
32916
32909
|
spawn(command, args, { stdio: "ignore", detached: true }).unref();
|
|
32917
32910
|
}
|
|
32918
|
-
async function startWorkbench(engine, moduleUrl, {
|
|
32911
|
+
async function startWorkbench(engine, moduleUrl, {
|
|
32912
|
+
noOpen = false,
|
|
32913
|
+
syncWorkbench = false
|
|
32914
|
+
} = {}) {
|
|
32919
32915
|
const python = python3Bin();
|
|
32920
32916
|
if (!python)
|
|
32921
32917
|
return { ok: false, code: "PYTHON3_REQUIRED", message: "python3 is required for the workbench. Install Python 3 and retry." };
|
|
32922
|
-
|
|
32918
|
+
const sync = wantWorkbenchSync(syncWorkbench || void 0);
|
|
32919
|
+
ensureWorkbench(engine, moduleUrl, { update: sync });
|
|
32923
32920
|
const built = buildWorkbench(engine);
|
|
32924
32921
|
if (!built.ok)
|
|
32925
32922
|
return built;
|
|
@@ -32947,7 +32944,7 @@ async function initEngine(rootOrEngine, moduleUrl, {
|
|
|
32947
32944
|
return {
|
|
32948
32945
|
...preview,
|
|
32949
32946
|
action: "preview",
|
|
32950
|
-
next: "
|
|
32947
|
+
next: isEngine(engine) ? "Engine already present; nothing to do" : `Re-run with --yes to git clone ${contentEngineRepoUrl()} into this path (or clone manually)`
|
|
32951
32948
|
};
|
|
32952
32949
|
}
|
|
32953
32950
|
const parent = resolve(engine, "..");
|
|
@@ -32961,15 +32958,24 @@ async function initEngine(rootOrEngine, moduleUrl, {
|
|
|
32961
32958
|
created: []
|
|
32962
32959
|
};
|
|
32963
32960
|
}
|
|
32964
|
-
mkdirSync2(engine, { recursive: true });
|
|
32965
|
-
const report = inventory(engine, moduleUrl);
|
|
32966
32961
|
const created = [];
|
|
32967
|
-
|
|
32968
|
-
|
|
32969
|
-
|
|
32970
|
-
|
|
32971
|
-
|
|
32972
|
-
|
|
32962
|
+
if (isEngine(engine)) {
|
|
32963
|
+
} else if (existsSync3(engine) && readdirSync(engine).filter((n) => n !== ".DS_Store").length > 0) {
|
|
32964
|
+
return {
|
|
32965
|
+
...validateEngine(engine, moduleUrl),
|
|
32966
|
+
created,
|
|
32967
|
+
action: "applied",
|
|
32968
|
+
valid: false,
|
|
32969
|
+
code: "ENGINE_DIR_DIRTY",
|
|
32970
|
+
errors: [`${engine} exists but is not a Content Engine. Remove it or clone ${contentEngineRepoUrl()} into an empty path.`]
|
|
32971
|
+
};
|
|
32972
|
+
} else {
|
|
32973
|
+
const core = ensureCoreCheckout();
|
|
32974
|
+
if (existsSync3(engine))
|
|
32975
|
+
rmSync(engine, { recursive: true, force: true });
|
|
32976
|
+
cpSync(core, engine, { recursive: true });
|
|
32977
|
+
rmSync(join3(engine, ".git"), { recursive: true, force: true });
|
|
32978
|
+
created.push("CLAUDE.md", "engine.json", "workbench/", "(cloned public core)");
|
|
32973
32979
|
}
|
|
32974
32980
|
const workbench = ensureWorkbench(engine, moduleUrl);
|
|
32975
32981
|
const python = python3Bin();
|
|
@@ -32981,7 +32987,7 @@ async function initEngine(rootOrEngine, moduleUrl, {
|
|
|
32981
32987
|
action: "applied",
|
|
32982
32988
|
valid: false,
|
|
32983
32989
|
code: "PYTHON3_REQUIRED",
|
|
32984
|
-
errors: ["python3 is required for the workbench. Install Python 3 and retry.
|
|
32990
|
+
errors: ["python3 is required for the workbench. Install Python 3 and retry."]
|
|
32985
32991
|
};
|
|
32986
32992
|
}
|
|
32987
32993
|
const built = buildWorkbench(engine);
|
|
@@ -32992,7 +32998,8 @@ async function initEngine(rootOrEngine, moduleUrl, {
|
|
|
32992
32998
|
workbench,
|
|
32993
32999
|
workbenchBuild: built,
|
|
32994
33000
|
workbenchStart: started,
|
|
32995
|
-
action: "applied"
|
|
33001
|
+
action: "applied",
|
|
33002
|
+
source: contentEngineRepoUrl()
|
|
32996
33003
|
};
|
|
32997
33004
|
}
|
|
32998
33005
|
function detectEngines() {
|
|
@@ -33230,7 +33237,7 @@ function buildV1Cli() {
|
|
|
33230
33237
|
const command = args.at(-1);
|
|
33231
33238
|
print({ action: "detect", engines: detectEngines() }, commandWantsJson(command));
|
|
33232
33239
|
});
|
|
33233
|
-
jsonOption(engine.command("init").description("
|
|
33240
|
+
jsonOption(engine.command("init").description("Clone public Content Engine core into Content Engine/ (never overwrites an existing engine). Prefer: git clone https://github.com/murphywuwu/content-engine.git").option("--root <path>", "Parent directory or Content Engine path", defaultEngineRoot()).option("--yes", "Clone core into place").option("--serve", "Also start the workbench server").option("--no-open", "Do not open a browser when starting the workbench")).action(async (...args) => {
|
|
33234
33241
|
const command = args.at(-1);
|
|
33235
33242
|
const opts = command.opts();
|
|
33236
33243
|
const result = await initEngine(String(opts.root), CLI_MODULE_URL, {
|
|
@@ -33280,22 +33287,26 @@ function buildV1Cli() {
|
|
|
33280
33287
|
if (!report.valid)
|
|
33281
33288
|
throw new Error(report.errors[0] ?? "engine validate failed");
|
|
33282
33289
|
});
|
|
33283
|
-
jsonOption(engine.command("serve").description("
|
|
33290
|
+
jsonOption(engine.command("serve").description("Rebuild workbench and start on :8765 (does not overwrite local workbench unless --sync-workbench)").option("--engine <path>", "Content Engine path or parent", defaultEngineRoot()).option("--no-open", "Do not open a browser").option("--sync-workbench", "Refresh workbench runtime files from the CLI package")).action(async (...args) => {
|
|
33284
33291
|
const command = args.at(-1);
|
|
33285
33292
|
const opts = command.opts();
|
|
33286
33293
|
const enginePath = resolveEngine(String(opts.engine));
|
|
33287
|
-
const started = await startWorkbench(enginePath, CLI_MODULE_URL, {
|
|
33294
|
+
const started = await startWorkbench(enginePath, CLI_MODULE_URL, {
|
|
33295
|
+
noOpen: opts.noOpen === true,
|
|
33296
|
+
syncWorkbench: opts.syncWorkbench === true
|
|
33297
|
+
});
|
|
33288
33298
|
print({ action: "serve", engine: enginePath, ...started }, commandWantsJson(command));
|
|
33289
33299
|
if (!started.ok)
|
|
33290
33300
|
throw new Error("message" in started ? String(started.message) : "engine serve failed");
|
|
33291
33301
|
});
|
|
33292
|
-
jsonOption(engine.command("build").description("
|
|
33302
|
+
jsonOption(engine.command("build").description("Rebuild workbench/index.html (does not overwrite local workbench unless --sync-workbench)").option("--engine <path>", "Content Engine path or parent", defaultEngineRoot()).option("--sync-workbench", "Refresh workbench runtime files from the CLI package")).action((...args) => {
|
|
33293
33303
|
const command = args.at(-1);
|
|
33294
33304
|
const opts = command.opts();
|
|
33295
33305
|
const enginePath = resolveEngine(String(opts.engine));
|
|
33296
|
-
const
|
|
33306
|
+
const sync = wantWorkbenchSync(opts.syncWorkbench === true ? true : void 0);
|
|
33307
|
+
const workbench = ensureWorkbench(enginePath, CLI_MODULE_URL, { update: sync });
|
|
33297
33308
|
const built = buildWorkbench(enginePath);
|
|
33298
|
-
print({ action: "build", engine: enginePath, workbench, ...built }, commandWantsJson(command));
|
|
33309
|
+
print({ action: "build", engine: enginePath, workbench, syncWorkbench: sync, ...built }, commandWantsJson(command));
|
|
33299
33310
|
if (!built.ok)
|
|
33300
33311
|
throw new Error(built.message);
|
|
33301
33312
|
});
|