@easysociable/cli 0.1.9 → 0.1.11
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 +1 -0
- package/dist/easysociable.js +170 -3
- package/dist/easysociable.js.map +1 -1
- package/package.json +1 -1
- package/skills/easysociable-content/SKILL.md +5 -5
- package/skills/easysociable-slideshow/SKILL.md +20 -7
- package/skills/easysociable-slideshow/references/GATEWAY.md +9 -0
- package/skills/easysociable-slideshow/workflows/CREATE_RUN.md +28 -13
package/README.md
CHANGED
|
@@ -53,6 +53,7 @@ unless you pass `--sync-workbench` (pulls from the public core checkout /
|
|
|
53
53
|
| Command | Purpose |
|
|
54
54
|
|---------|---------|
|
|
55
55
|
| `easysociable engine init [--root] [--yes] [--serve]` | Clone public core into `Content Engine/` (no overwrite) |
|
|
56
|
+
| `easysociable engine update [--engine] [--yes]` | Sync core rules from the public template; preview first, apply with `--yes`. Never touches vault data |
|
|
56
57
|
| `easysociable engine serve [--engine] [--no-open] [--sync-workbench]` | Rebuild + start on `:8765` |
|
|
57
58
|
| `easysociable engine build [--engine] [--sync-workbench]` | Rebuild `workbench/index.html` |
|
|
58
59
|
| `easysociable engine detect` | Find engines under search roots |
|
package/dist/easysociable.js
CHANGED
|
@@ -32645,7 +32645,8 @@ import {
|
|
|
32645
32645
|
readdirSync,
|
|
32646
32646
|
readFileSync as readFileSync2,
|
|
32647
32647
|
rmSync,
|
|
32648
|
-
statSync
|
|
32648
|
+
statSync,
|
|
32649
|
+
writeFileSync as writeFileSync2
|
|
32649
32650
|
} from "fs";
|
|
32650
32651
|
import net from "net";
|
|
32651
32652
|
import { homedir as homedir2 } from "os";
|
|
@@ -32654,7 +32655,18 @@ var ENGINE_ROOT_NAME = "Content Engine";
|
|
|
32654
32655
|
var WORKBENCH_PORT = 8765;
|
|
32655
32656
|
var WORKBENCH_URL = `http://127.0.0.1:${WORKBENCH_PORT}/workbench/`;
|
|
32656
32657
|
var CONTENT_ENGINE_REPO = "https://github.com/murphywuwu/content-engine.git";
|
|
32657
|
-
var WORKBENCH_FILES = [
|
|
32658
|
+
var WORKBENCH_FILES = [
|
|
32659
|
+
"template.html",
|
|
32660
|
+
"build.py",
|
|
32661
|
+
"serve.py",
|
|
32662
|
+
"roots.py",
|
|
32663
|
+
"README.md",
|
|
32664
|
+
"easysociable-mark.svg",
|
|
32665
|
+
"css/workbench.css",
|
|
32666
|
+
"js/i18n.js",
|
|
32667
|
+
"js/utils.js",
|
|
32668
|
+
"js/app.js"
|
|
32669
|
+
];
|
|
32658
32670
|
var REQUIRED_RELATIVE = [
|
|
32659
32671
|
"CLAUDE.md",
|
|
32660
32672
|
"engine.json",
|
|
@@ -32874,6 +32886,7 @@ function ensureWorkbench(engine, _moduleUrl, { update = false } = {}) {
|
|
|
32874
32886
|
if (!existsSync3(from))
|
|
32875
32887
|
throw new Error(`Missing ${name} in Content Engine core checkout`);
|
|
32876
32888
|
const existed = existsSync3(dest);
|
|
32889
|
+
mkdirSync2(dirname3(dest), { recursive: true });
|
|
32877
32890
|
copyFileSync(from, dest);
|
|
32878
32891
|
if (existed)
|
|
32879
32892
|
updated.push(name);
|
|
@@ -33002,6 +33015,133 @@ async function initEngine(rootOrEngine, moduleUrl, {
|
|
|
33002
33015
|
source: contentEngineRepoUrl()
|
|
33003
33016
|
};
|
|
33004
33017
|
}
|
|
33018
|
+
var CORE_REFRESH_FILES = /* @__PURE__ */ new Set(["CLAUDE.md", "LAYOUT.md", "topics/scoring.md"]);
|
|
33019
|
+
var CORE_ADD_ONLY_FILES = /* @__PURE__ */ new Set([
|
|
33020
|
+
"media/_index.md",
|
|
33021
|
+
"media/README.md",
|
|
33022
|
+
"profiles/default/brand.md",
|
|
33023
|
+
"wiki/_index.md",
|
|
33024
|
+
"wiki/_unfiled.md",
|
|
33025
|
+
"wiki/README.md",
|
|
33026
|
+
"wiki/_template.md",
|
|
33027
|
+
"library/README.md",
|
|
33028
|
+
"library/swipe/_index.md",
|
|
33029
|
+
"library/atoms/_index.md",
|
|
33030
|
+
"library/claims/_index.md"
|
|
33031
|
+
]);
|
|
33032
|
+
function classifyCoreFile(rel) {
|
|
33033
|
+
const parts = rel.split("/");
|
|
33034
|
+
if (parts[0] === ".git")
|
|
33035
|
+
return "skip";
|
|
33036
|
+
if (CORE_ADD_ONLY_FILES.has(rel))
|
|
33037
|
+
return "add";
|
|
33038
|
+
if (CORE_REFRESH_FILES.has(rel))
|
|
33039
|
+
return "refresh";
|
|
33040
|
+
if (parts[0] === "workbench")
|
|
33041
|
+
return "refresh";
|
|
33042
|
+
if (parts[0] === "platforms" && rel.endsWith(".md"))
|
|
33043
|
+
return "refresh";
|
|
33044
|
+
if (basename(rel) === "_template.md" || parts.includes("_template"))
|
|
33045
|
+
return "refresh";
|
|
33046
|
+
return "skip";
|
|
33047
|
+
}
|
|
33048
|
+
function walkCoreFiles(core, relDir = "") {
|
|
33049
|
+
const out = [];
|
|
33050
|
+
const absDir = join3(core, relDir);
|
|
33051
|
+
if (!isDir(absDir))
|
|
33052
|
+
return out;
|
|
33053
|
+
for (const name of readdirSync(absDir)) {
|
|
33054
|
+
if (name === ".git" || name === ".DS_Store")
|
|
33055
|
+
continue;
|
|
33056
|
+
const rel = relDir ? `${relDir}/${name}` : name;
|
|
33057
|
+
if (isDir(join3(core, rel)))
|
|
33058
|
+
out.push(...walkCoreFiles(core, rel));
|
|
33059
|
+
else
|
|
33060
|
+
out.push(rel);
|
|
33061
|
+
}
|
|
33062
|
+
return out;
|
|
33063
|
+
}
|
|
33064
|
+
function mergeEngineJson(engine, core) {
|
|
33065
|
+
const engPath = join3(engine, "engine.json");
|
|
33066
|
+
const corePath = join3(core, "engine.json");
|
|
33067
|
+
if (!existsSync3(engPath) || !existsSync3(corePath))
|
|
33068
|
+
return [];
|
|
33069
|
+
let eng;
|
|
33070
|
+
let cor;
|
|
33071
|
+
try {
|
|
33072
|
+
eng = JSON.parse(readFileSync2(engPath, "utf8"));
|
|
33073
|
+
cor = JSON.parse(readFileSync2(corePath, "utf8"));
|
|
33074
|
+
} catch {
|
|
33075
|
+
return [];
|
|
33076
|
+
}
|
|
33077
|
+
const engPaths = eng.paths ?? (eng.paths = {});
|
|
33078
|
+
const corPaths = cor.paths ?? {};
|
|
33079
|
+
const added = [];
|
|
33080
|
+
for (const [key, value] of Object.entries(corPaths)) {
|
|
33081
|
+
if (!(key in engPaths)) {
|
|
33082
|
+
engPaths[key] = value;
|
|
33083
|
+
added.push(`paths.${key}`);
|
|
33084
|
+
}
|
|
33085
|
+
}
|
|
33086
|
+
if (added.length)
|
|
33087
|
+
writeFileSync2(engPath, `${JSON.stringify(eng, null, 2)}
|
|
33088
|
+
`);
|
|
33089
|
+
return added;
|
|
33090
|
+
}
|
|
33091
|
+
function updateEngine(rootOrEngine, moduleUrl, { yes = false } = {}) {
|
|
33092
|
+
const engine = resolveEngine(rootOrEngine);
|
|
33093
|
+
if (!isEngine(engine)) {
|
|
33094
|
+
return {
|
|
33095
|
+
engine,
|
|
33096
|
+
action: "preview",
|
|
33097
|
+
valid: false,
|
|
33098
|
+
code: "NOT_AN_ENGINE",
|
|
33099
|
+
errors: [`${engine} is not a Content Engine. Run engine init first, or pass --engine <path>.`]
|
|
33100
|
+
};
|
|
33101
|
+
}
|
|
33102
|
+
const core = ensureCoreCheckout({ update: true });
|
|
33103
|
+
const refresh = [];
|
|
33104
|
+
const add = [];
|
|
33105
|
+
for (const rel of walkCoreFiles(core)) {
|
|
33106
|
+
const cls = classifyCoreFile(rel);
|
|
33107
|
+
if (cls === "refresh")
|
|
33108
|
+
refresh.push(rel);
|
|
33109
|
+
else if (cls === "add" && !existsSync3(join3(engine, rel)))
|
|
33110
|
+
add.push(rel);
|
|
33111
|
+
}
|
|
33112
|
+
if (!yes) {
|
|
33113
|
+
return {
|
|
33114
|
+
engine,
|
|
33115
|
+
action: "preview",
|
|
33116
|
+
source: contentEngineRepoUrl(),
|
|
33117
|
+
willRefresh: refresh,
|
|
33118
|
+
willAdd: add,
|
|
33119
|
+
next: "Re-run with --yes to apply. Vault data (profiles, needs, runs, media files) is never touched."
|
|
33120
|
+
};
|
|
33121
|
+
}
|
|
33122
|
+
const copy = (list) => {
|
|
33123
|
+
for (const rel of list) {
|
|
33124
|
+
const dest = join3(engine, rel);
|
|
33125
|
+
mkdirSync2(dirname3(dest), { recursive: true });
|
|
33126
|
+
copyFileSync(join3(core, rel), dest);
|
|
33127
|
+
}
|
|
33128
|
+
return list;
|
|
33129
|
+
};
|
|
33130
|
+
const refreshed = copy(refresh);
|
|
33131
|
+
const added = copy(add);
|
|
33132
|
+
const enginePaths = mergeEngineJson(engine, core);
|
|
33133
|
+
const workbenchBuild = buildWorkbench(engine);
|
|
33134
|
+
return {
|
|
33135
|
+
...validateEngine(engine, moduleUrl),
|
|
33136
|
+
engine,
|
|
33137
|
+
action: "applied",
|
|
33138
|
+
source: contentEngineRepoUrl(),
|
|
33139
|
+
refreshed,
|
|
33140
|
+
added,
|
|
33141
|
+
enginePaths,
|
|
33142
|
+
workbenchBuild
|
|
33143
|
+
};
|
|
33144
|
+
}
|
|
33005
33145
|
function detectEngines() {
|
|
33006
33146
|
const extra = (process.env.EASYSOCIABLE_ENGINE_SEARCH_ROOTS || "").split(process.platform === "win32" ? ";" : ":").map((item) => item.trim()).filter(Boolean);
|
|
33007
33147
|
const home = homedir2();
|
|
@@ -33048,6 +33188,21 @@ function validateRun(moduleUrl, args) {
|
|
|
33048
33188
|
};
|
|
33049
33189
|
}
|
|
33050
33190
|
|
|
33191
|
+
// src/studioIdentity.ts
|
|
33192
|
+
var FIXTURE_WORKSPACE_IDS = /* @__PURE__ */ new Set(["workspace_local"]);
|
|
33193
|
+
var IDENTITY_CHAIN_HINT = "Studio login \u2192 Dashboard create API key \u2192 easysociable auth login --api-key <key> \u2192 create Run \u2192 open studioUrl as the same account. See docs/operations/studio-identity-chain.md";
|
|
33194
|
+
async function assertHumanStudioIdentity(client, options = {}) {
|
|
33195
|
+
if (options.allowLocalFixture === true || process.env.EASYSOCIABLE_ALLOW_LOCAL_FIXTURE === "1")
|
|
33196
|
+
return;
|
|
33197
|
+
const envelope = await client.requestJson("GET", "/v1/commercial/me");
|
|
33198
|
+
const workspaceId = envelope.data?.principal?.workspaceId ?? envelope.principal?.workspaceId ?? null;
|
|
33199
|
+
if (typeof workspaceId === "string" && FIXTURE_WORKSPACE_IDS.has(workspaceId)) {
|
|
33200
|
+
throw new Error(
|
|
33201
|
+
`This CLI is using fixture workspace "${workspaceId}". ${IDENTITY_CHAIN_HINT}`
|
|
33202
|
+
);
|
|
33203
|
+
}
|
|
33204
|
+
}
|
|
33205
|
+
|
|
33051
33206
|
// src/v1-cli.ts
|
|
33052
33207
|
var CLI_MODULE_URL = import.meta.url;
|
|
33053
33208
|
function readCliVersion() {
|
|
@@ -33310,6 +33465,15 @@ function buildV1Cli() {
|
|
|
33310
33465
|
if (!built.ok)
|
|
33311
33466
|
throw new Error(built.message);
|
|
33312
33467
|
});
|
|
33468
|
+
jsonOption(engine.command("update").description("Sync core rules from the template (CLAUDE.md, workbench, platforms, templates) and add new scaffolds; never touches your vault data. Preview first; apply with --yes.").option("--engine <path>", "Content Engine path or parent", defaultEngineRoot()).option("--yes", "Apply the update (default is a dry-run preview)")).action((...args) => {
|
|
33469
|
+
const command = args.at(-1);
|
|
33470
|
+
const opts = command.opts();
|
|
33471
|
+
const result = updateEngine(String(opts.engine), CLI_MODULE_URL, { yes: opts.yes === true });
|
|
33472
|
+
print(result, commandWantsJson(command));
|
|
33473
|
+
const code = result.code;
|
|
33474
|
+
if (code)
|
|
33475
|
+
throw new Error(result.errors?.[0] ?? code);
|
|
33476
|
+
});
|
|
33313
33477
|
const auth = program.command("auth").description("Manage the shared EasySociable credential");
|
|
33314
33478
|
jsonOption(auth.command("status").description("Show authentication status")).action(async (...args) => {
|
|
33315
33479
|
const command = args.at(-1);
|
|
@@ -33367,7 +33531,10 @@ function buildV1Cli() {
|
|
|
33367
33531
|
contentSlug: opts.contentSlug ? String(opts.contentSlug) : void 0,
|
|
33368
33532
|
status: opts.status ? String(opts.status) : void 0
|
|
33369
33533
|
})));
|
|
33370
|
-
jsonOption(slideshows.command("create").requiredOption("--file <path>")).action(withClient(async (client, opts) =>
|
|
33534
|
+
jsonOption(slideshows.command("create").requiredOption("--file <path>").option("--allow-local-fixture", "Allow workspace_local fixture keys (dev only)")).action(withClient(async (client, opts) => {
|
|
33535
|
+
await assertHumanStudioIdentity(client, { allowLocalFixture: opts.allowLocalFixture === true });
|
|
33536
|
+
return client.createSlideshowRun({ pack: JSON.parse(await readFile(String(opts.file), "utf8")) });
|
|
33537
|
+
}));
|
|
33371
33538
|
jsonOption(slideshows.command("get").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.getSlideshowRun(String(opts.id))));
|
|
33372
33539
|
jsonOption(slideshows.command("update").requiredOption("--id <id>").requiredOption("--file <path>")).action(withClient(async (client, opts) => client.updateSlideshowRun(String(opts.id), JSON.parse(await readFile(String(opts.file), "utf8")))));
|
|
33373
33540
|
jsonOption(slideshows.command("archive").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.archiveSlideshowRun(String(opts.id))));
|