@easysociable/cli 0.1.10 → 0.1.12
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 +2 -1
- package/dist/easysociable.js +116 -14
- 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 +29 -7
- package/skills/easysociable-slideshow/references/GATEWAY.md +9 -0
- package/skills/easysociable-slideshow/workflows/CREATE_RUN.md +30 -13
package/README.md
CHANGED
|
@@ -83,9 +83,10 @@ easysociable mcp serve --transport stdio
|
|
|
83
83
|
|---------|---------|
|
|
84
84
|
| `easysociable install [--yes] [--skills list]` | Install Skills + MCP |
|
|
85
85
|
| `easysociable update [--yes] [--skills list]` | Update Skills + MCP |
|
|
86
|
-
| `easysociable templates …` | Page Template drafts / catalog |
|
|
86
|
+
| `easysociable templates …` | Page Template drafts / catalog (`list --platform <p> --all` for a full platform catalog) |
|
|
87
87
|
| `easysociable brands …` | Workspace Brands |
|
|
88
88
|
| `easysociable slideshows …` | Slideshow Runs |
|
|
89
|
+
| `easysociable slideshows recommend --file contracts.json --seed <slug>` | Per-page template shortlist from Page Contracts (recent families demoted, gaps reported) |
|
|
89
90
|
| `easysociable renders …` | Single-page final render jobs |
|
|
90
91
|
| `easysociable mcp serve --transport stdio` | Unified MCP server |
|
|
91
92
|
|
package/dist/easysociable.js
CHANGED
|
@@ -16297,11 +16297,13 @@ function isRetryableStatus(status) {
|
|
|
16297
16297
|
function sleep(ms) {
|
|
16298
16298
|
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
16299
16299
|
}
|
|
16300
|
-
var TemplateGatewayError, TemplateGatewayClient;
|
|
16300
|
+
var DEFAULT_TEMPLATE_PAGE_SIZE, MAX_TEMPLATE_PAGE_SIZE, TemplateGatewayError, TemplateGatewayClient;
|
|
16301
16301
|
var init_client = __esm({
|
|
16302
16302
|
"../../packages/template-gateway-client/src/client.ts"() {
|
|
16303
16303
|
"use strict";
|
|
16304
16304
|
init_src();
|
|
16305
|
+
DEFAULT_TEMPLATE_PAGE_SIZE = 20;
|
|
16306
|
+
MAX_TEMPLATE_PAGE_SIZE = 50;
|
|
16305
16307
|
TemplateGatewayError = class extends Error {
|
|
16306
16308
|
code;
|
|
16307
16309
|
retryable;
|
|
@@ -16347,6 +16349,13 @@ var init_client = __esm({
|
|
|
16347
16349
|
return response.json;
|
|
16348
16350
|
}
|
|
16349
16351
|
async listTemplates(query) {
|
|
16352
|
+
return (await this.listTemplatesPage(query)).templates;
|
|
16353
|
+
}
|
|
16354
|
+
/**
|
|
16355
|
+
* Same as listTemplates plus `nextCursor` so Agents know the catalog is paged.
|
|
16356
|
+
* Derived client-side (full page ⇒ maybe more) to keep the strict v1 envelope.
|
|
16357
|
+
*/
|
|
16358
|
+
async listTemplatesPage(query) {
|
|
16350
16359
|
const parsed = parseListTemplatesQuery(query ?? {});
|
|
16351
16360
|
const params = new URLSearchParams();
|
|
16352
16361
|
const appendList = (key, values) => {
|
|
@@ -16375,7 +16384,23 @@ var init_client = __esm({
|
|
|
16375
16384
|
const qs = params.toString();
|
|
16376
16385
|
const response = await this.request("GET", qs ? `/v1/templates?${qs}` : "/v1/templates");
|
|
16377
16386
|
this.throwIfError(response.status, response.json);
|
|
16378
|
-
|
|
16387
|
+
const templates = parseTemplateSummaryList(response.json);
|
|
16388
|
+
const limit = parsed.limit ?? DEFAULT_TEMPLATE_PAGE_SIZE;
|
|
16389
|
+
const offset = Number.parseInt(parsed.cursor ?? "0", 10) || 0;
|
|
16390
|
+
return { templates, nextCursor: templates.length >= limit ? String(offset + limit) : null };
|
|
16391
|
+
}
|
|
16392
|
+
/** Drain every page for a filtered query (platform catalogs are tens of templates). */
|
|
16393
|
+
async listAllTemplates(query) {
|
|
16394
|
+
const all = [];
|
|
16395
|
+
let cursor;
|
|
16396
|
+
for (let page = 0; page < 40; page += 1) {
|
|
16397
|
+
const result = await this.listTemplatesPage({ ...query, limit: MAX_TEMPLATE_PAGE_SIZE, cursor });
|
|
16398
|
+
all.push(...result.templates);
|
|
16399
|
+
if (!result.nextCursor)
|
|
16400
|
+
return all;
|
|
16401
|
+
cursor = result.nextCursor;
|
|
16402
|
+
}
|
|
16403
|
+
return all;
|
|
16379
16404
|
}
|
|
16380
16405
|
async getTemplate(templateId) {
|
|
16381
16406
|
const response = await this.request("GET", `/v1/templates/${encodeURIComponent(templateId)}`);
|
|
@@ -16543,6 +16568,12 @@ var init_client = __esm({
|
|
|
16543
16568
|
this.throwIfError(response.status, response.json);
|
|
16544
16569
|
return parseSlideshowRun(response.json);
|
|
16545
16570
|
}
|
|
16571
|
+
/** Per-page shortlist (hard filter → fit score → recent-family penalty → explore slot). Agent still picks. */
|
|
16572
|
+
async recommendSlideshowTemplates(input) {
|
|
16573
|
+
const response = await this.request("POST", "/v1/slideshow/template-recommendations", input);
|
|
16574
|
+
this.throwIfError(response.status, response.json);
|
|
16575
|
+
return response.json.data;
|
|
16576
|
+
}
|
|
16546
16577
|
async listSlideshowRuns(query = {}) {
|
|
16547
16578
|
const input = listSlideshowRunsQuerySchema.parse(query);
|
|
16548
16579
|
const params = new URLSearchParams();
|
|
@@ -31720,7 +31751,7 @@ var init_src4 = __esm({
|
|
|
31720
31751
|
{
|
|
31721
31752
|
name: "list_templates",
|
|
31722
31753
|
title: "List templates",
|
|
31723
|
-
description: "List public template catalog summaries from Gateway (filterable; no AST)",
|
|
31754
|
+
description: "List public template catalog summaries from Gateway (filterable; no AST). Paged: follow nextCursor, or pass all=true with platforms to get the whole platform catalog before choosing. For Slideshow page choice prefer recommend_slideshow_templates.",
|
|
31724
31755
|
effect: "read-only",
|
|
31725
31756
|
inputSchema: {
|
|
31726
31757
|
type: "object",
|
|
@@ -31734,11 +31765,13 @@ var init_src4 = __esm({
|
|
|
31734
31765
|
requiresImage: { type: "boolean" },
|
|
31735
31766
|
locale: { type: "string" },
|
|
31736
31767
|
q: { type: "string" },
|
|
31737
|
-
limit: { type: "number" }
|
|
31768
|
+
limit: { type: "number" },
|
|
31769
|
+
cursor: { type: "string" },
|
|
31770
|
+
all: { type: "boolean" }
|
|
31738
31771
|
},
|
|
31739
31772
|
additionalProperties: false
|
|
31740
31773
|
},
|
|
31741
|
-
outputSchema: { type: "object", properties: { templates: { type: "array" } } }
|
|
31774
|
+
outputSchema: { type: "object", properties: { templates: { type: "array" }, nextCursor: { type: ["string", "null"] } } }
|
|
31742
31775
|
},
|
|
31743
31776
|
{
|
|
31744
31777
|
name: "get_template",
|
|
@@ -32057,7 +32090,7 @@ var init_src4 = __esm({
|
|
|
32057
32090
|
};
|
|
32058
32091
|
try {
|
|
32059
32092
|
if (toolName === "list_templates") {
|
|
32060
|
-
const
|
|
32093
|
+
const query = {
|
|
32061
32094
|
platforms: args.platforms,
|
|
32062
32095
|
roles: args.roles,
|
|
32063
32096
|
contentFamily: args.contentFamily,
|
|
@@ -32066,10 +32099,16 @@ var init_src4 = __esm({
|
|
|
32066
32099
|
canvasPreset: args.canvasPreset,
|
|
32067
32100
|
requiresImage: typeof args.requiresImage === "boolean" ? args.requiresImage : void 0,
|
|
32068
32101
|
locale: args.locale,
|
|
32069
|
-
q: typeof args.q === "string" ? args.q : void 0
|
|
32070
|
-
|
|
32102
|
+
q: typeof args.q === "string" ? args.q : void 0
|
|
32103
|
+
};
|
|
32104
|
+
if (args.all === true)
|
|
32105
|
+
return { ok: true, data: { templates: await this.client.listAllTemplates(query), nextCursor: null }, meta: meta4 };
|
|
32106
|
+
const page = await this.client.listTemplatesPage({
|
|
32107
|
+
...query,
|
|
32108
|
+
limit: typeof args.limit === "number" ? args.limit : void 0,
|
|
32109
|
+
cursor: typeof args.cursor === "string" ? args.cursor : void 0
|
|
32071
32110
|
});
|
|
32072
|
-
return { ok: true, data:
|
|
32111
|
+
return { ok: true, data: page, meta: meta4 };
|
|
32073
32112
|
}
|
|
32074
32113
|
if (toolName === "get_template") {
|
|
32075
32114
|
const template = await this.client.getTemplate(String(args.templateId));
|
|
@@ -32277,6 +32316,7 @@ var init_src5 = __esm({
|
|
|
32277
32316
|
objectSchema = { type: "object", properties: {}, additionalProperties: true };
|
|
32278
32317
|
slideshowToolRegistry = [
|
|
32279
32318
|
{ name: "list_runs", title: "List slideshow runs", description: "List owner-scoped Slideshow Runs with optional filters.", effect: "read-only", inputSchema: { ...objectSchema, properties: { q: { type: "string" }, platform: { type: "string" }, profileId: { type: "string" }, brandProfileId: { type: "string" }, contentSlug: { type: "string" }, status: { type: "string" } } }, outputSchema: objectSchema },
|
|
32319
|
+
{ name: "recommend_templates", title: "Recommend slideshow page templates", description: "Before create_run: send the Page Contracts (role, density, slotSummary per page) and get a shortlist per page with reasons. Recently used Layout Families are demoted and one unused family is always kept. Pick one templateId per page yourself; gaps list pages needing more templates.", effect: "read-only", inputSchema: { ...objectSchema, properties: { platform: { type: "string" }, canvasPreset: { type: "string" }, pages: { type: "array", items: { type: "object", properties: { role: { type: "string" }, density: { type: "string" }, slotSummary: { type: "object" }, requiresImage: { type: "boolean" } }, required: ["role"] } }, k: { type: "integer", minimum: 2, maximum: 5 }, seed: { type: "string" } }, required: ["platform", "pages"] }, outputSchema: objectSchema },
|
|
32280
32320
|
{ name: "create_run", title: "Create slideshow run", description: "Create an ADR-0026 Slideshow Run from a ContentPack.", effect: "local-write-job", inputSchema: { ...objectSchema, properties: { pack: { type: "object" }, brandId: { type: "string" }, brandProfileId: { type: "string" }, contentSlug: { type: "string" } }, required: ["pack"] }, outputSchema: objectSchema },
|
|
32281
32321
|
{ name: "get_run", title: "Get slideshow run", description: "Get an owner-scoped Slideshow Run.", effect: "read-only", inputSchema: { ...objectSchema, properties: { runId: { type: "string" } }, required: ["runId"] }, outputSchema: objectSchema },
|
|
32282
32322
|
{ name: "update_run", title: "Update slideshow run", description: "Edit page-instance slots/layout/style/decorations or presentation preference with optimistic revision.", effect: "local-write-job", inputSchema: { ...objectSchema, properties: { runId: { type: "string" }, pack: { type: "object" }, brandId: { type: "string" }, brandProfileId: { type: "string" }, contentSlug: { type: "string" }, baseRevision: { type: "integer", minimum: 1 }, pageIndex: { type: "integer", minimum: 0 }, slots: { type: "object" }, layout: { type: "object" }, style: { type: "object" }, decorations: { type: "array" } }, required: ["runId"] }, outputSchema: objectSchema },
|
|
@@ -32305,6 +32345,8 @@ var init_src5 = __esm({
|
|
|
32305
32345
|
contentSlug: args.contentSlug,
|
|
32306
32346
|
status: args.status
|
|
32307
32347
|
}), meta: m };
|
|
32348
|
+
case "recommend_templates":
|
|
32349
|
+
return { ok: true, data: await this.client.recommendSlideshowTemplates({ platform: String(args.platform), pages: args.pages, canvasPreset: args.canvasPreset, k: args.k, seed: args.seed }), meta: m };
|
|
32308
32350
|
case "create_run":
|
|
32309
32351
|
return { ok: true, data: await this.client.createSlideshowRun({ pack: args.pack, brandId: args.brandId, brandProfileId: args.brandProfileId, contentSlug: args.contentSlug }), meta: m };
|
|
32310
32352
|
case "get_run":
|
|
@@ -32376,6 +32418,7 @@ var init_src6 = __esm({
|
|
|
32376
32418
|
};
|
|
32377
32419
|
slideshowNames = {
|
|
32378
32420
|
list_runs: "list_slideshow_runs",
|
|
32421
|
+
recommend_templates: "recommend_slideshow_templates",
|
|
32379
32422
|
create_run: "create_slideshow_run",
|
|
32380
32423
|
get_run: "get_slideshow_run",
|
|
32381
32424
|
update_run: "update_slideshow_run",
|
|
@@ -32655,7 +32698,18 @@ var ENGINE_ROOT_NAME = "Content Engine";
|
|
|
32655
32698
|
var WORKBENCH_PORT = 8765;
|
|
32656
32699
|
var WORKBENCH_URL = `http://127.0.0.1:${WORKBENCH_PORT}/workbench/`;
|
|
32657
32700
|
var CONTENT_ENGINE_REPO = "https://github.com/murphywuwu/content-engine.git";
|
|
32658
|
-
var WORKBENCH_FILES = [
|
|
32701
|
+
var WORKBENCH_FILES = [
|
|
32702
|
+
"template.html",
|
|
32703
|
+
"build.py",
|
|
32704
|
+
"serve.py",
|
|
32705
|
+
"roots.py",
|
|
32706
|
+
"README.md",
|
|
32707
|
+
"easysociable-mark.svg",
|
|
32708
|
+
"css/workbench.css",
|
|
32709
|
+
"js/i18n.js",
|
|
32710
|
+
"js/utils.js",
|
|
32711
|
+
"js/app.js"
|
|
32712
|
+
];
|
|
32659
32713
|
var REQUIRED_RELATIVE = [
|
|
32660
32714
|
"CLAUDE.md",
|
|
32661
32715
|
"engine.json",
|
|
@@ -32875,6 +32929,7 @@ function ensureWorkbench(engine, _moduleUrl, { update = false } = {}) {
|
|
|
32875
32929
|
if (!existsSync3(from))
|
|
32876
32930
|
throw new Error(`Missing ${name} in Content Engine core checkout`);
|
|
32877
32931
|
const existed = existsSync3(dest);
|
|
32932
|
+
mkdirSync2(dirname3(dest), { recursive: true });
|
|
32878
32933
|
copyFileSync(from, dest);
|
|
32879
32934
|
if (existed)
|
|
32880
32935
|
updated.push(name);
|
|
@@ -33004,7 +33059,19 @@ async function initEngine(rootOrEngine, moduleUrl, {
|
|
|
33004
33059
|
};
|
|
33005
33060
|
}
|
|
33006
33061
|
var CORE_REFRESH_FILES = /* @__PURE__ */ new Set(["CLAUDE.md", "LAYOUT.md", "topics/scoring.md"]);
|
|
33007
|
-
var CORE_ADD_ONLY_FILES = /* @__PURE__ */ new Set([
|
|
33062
|
+
var CORE_ADD_ONLY_FILES = /* @__PURE__ */ new Set([
|
|
33063
|
+
"media/_index.md",
|
|
33064
|
+
"media/README.md",
|
|
33065
|
+
"profiles/default/brand.md",
|
|
33066
|
+
"wiki/_index.md",
|
|
33067
|
+
"wiki/_unfiled.md",
|
|
33068
|
+
"wiki/README.md",
|
|
33069
|
+
"wiki/_template.md",
|
|
33070
|
+
"library/README.md",
|
|
33071
|
+
"library/swipe/_index.md",
|
|
33072
|
+
"library/atoms/_index.md",
|
|
33073
|
+
"library/claims/_index.md"
|
|
33074
|
+
]);
|
|
33008
33075
|
function classifyCoreFile(rel) {
|
|
33009
33076
|
const parts = rel.split("/");
|
|
33010
33077
|
if (parts[0] === ".git")
|
|
@@ -33164,6 +33231,21 @@ function validateRun(moduleUrl, args) {
|
|
|
33164
33231
|
};
|
|
33165
33232
|
}
|
|
33166
33233
|
|
|
33234
|
+
// src/studioIdentity.ts
|
|
33235
|
+
var FIXTURE_WORKSPACE_IDS = /* @__PURE__ */ new Set(["workspace_local"]);
|
|
33236
|
+
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";
|
|
33237
|
+
async function assertHumanStudioIdentity(client, options = {}) {
|
|
33238
|
+
if (options.allowLocalFixture === true || process.env.EASYSOCIABLE_ALLOW_LOCAL_FIXTURE === "1")
|
|
33239
|
+
return;
|
|
33240
|
+
const envelope = await client.requestJson("GET", "/v1/commercial/me");
|
|
33241
|
+
const workspaceId = envelope.data?.principal?.workspaceId ?? envelope.principal?.workspaceId ?? null;
|
|
33242
|
+
if (typeof workspaceId === "string" && FIXTURE_WORKSPACE_IDS.has(workspaceId)) {
|
|
33243
|
+
throw new Error(
|
|
33244
|
+
`This CLI is using fixture workspace "${workspaceId}". ${IDENTITY_CHAIN_HINT}`
|
|
33245
|
+
);
|
|
33246
|
+
}
|
|
33247
|
+
}
|
|
33248
|
+
|
|
33167
33249
|
// src/v1-cli.ts
|
|
33168
33250
|
var CLI_MODULE_URL = import.meta.url;
|
|
33169
33251
|
function readCliVersion() {
|
|
@@ -33464,7 +33546,20 @@ function buildV1Cli() {
|
|
|
33464
33546
|
jsonOption(images.command("search").requiredOption("--q <query>")).action(withClient(async (client, opts) => client.requestJson("GET", `/v1/images?q=${encodeURIComponent(String(opts.q))}`)));
|
|
33465
33547
|
jsonOption(images.command("attest").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.requestJson("POST", `/v1/images/${opts.id}/attest`, { accepted: true })));
|
|
33466
33548
|
const templates = program.command("templates").description("Create and manage Page Template drafts");
|
|
33467
|
-
jsonOption(templates.command("list")).action(withClient(async (client) =>
|
|
33549
|
+
jsonOption(templates.command("list").option("--platform <platform>", "tiktok | instagram | linkedin | threads | xiaohongshu").option("--canvas <preset>", "Canvas preset e.g. 9:16, 4:5").option("--role <role>", "Page role filter (weak tag)").option("--limit <n>", "Page size (max 50)").option("--cursor <cursor>", "Offset cursor from a previous page").option("--all", "Return every matching template (drains pages)")).action(withClient(async (client, opts) => {
|
|
33550
|
+
const query = {
|
|
33551
|
+
platforms: opts.platform ? [String(opts.platform)] : void 0,
|
|
33552
|
+
canvasPreset: opts.canvas ? String(opts.canvas) : void 0,
|
|
33553
|
+
roles: opts.role ? [String(opts.role)] : void 0
|
|
33554
|
+
};
|
|
33555
|
+
if (opts.all === true)
|
|
33556
|
+
return client.listAllTemplates(query);
|
|
33557
|
+
const page = await client.listTemplatesPage({ ...query, limit: opts.limit ? Number(opts.limit) : void 0, cursor: opts.cursor ? String(opts.cursor) : void 0 });
|
|
33558
|
+
if (page.nextCursor)
|
|
33559
|
+
process.stderr.write(`More templates: --cursor ${page.nextCursor} or --all
|
|
33560
|
+
`);
|
|
33561
|
+
return page.templates;
|
|
33562
|
+
}));
|
|
33468
33563
|
jsonOption(templates.command("get").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.getTemplate(String(opts.id))));
|
|
33469
33564
|
jsonOption(templates.command("create-draft").requiredOption("--file <path>")).action(withClient(async (client, opts) => client.createDraft(JSON.parse(await readFile(String(opts.file), "utf8")))));
|
|
33470
33565
|
jsonOption(templates.command("update-draft").requiredOption("--id <id>").requiredOption("--file <path>")).action(withClient(async (client, opts) => client.updateDraft(String(opts.id), JSON.parse(await readFile(String(opts.file), "utf8")))));
|
|
@@ -33492,7 +33587,14 @@ function buildV1Cli() {
|
|
|
33492
33587
|
contentSlug: opts.contentSlug ? String(opts.contentSlug) : void 0,
|
|
33493
33588
|
status: opts.status ? String(opts.status) : void 0
|
|
33494
33589
|
})));
|
|
33495
|
-
jsonOption(slideshows.command("
|
|
33590
|
+
jsonOption(slideshows.command("recommend").description("Shortlist Page Templates per page from Page Contracts JSON ({ platform, pages: [{ role, density?, slotSummary? }], seed? })").requiredOption("--file <path>").option("--seed <seed>", "Tie-break seed, e.g. the content slug")).action(withClient(async (client, opts) => {
|
|
33591
|
+
const input = JSON.parse(await readFile(String(opts.file), "utf8"));
|
|
33592
|
+
return client.recommendSlideshowTemplates(opts.seed ? { ...input, seed: String(opts.seed) } : input);
|
|
33593
|
+
}));
|
|
33594
|
+
jsonOption(slideshows.command("create").requiredOption("--file <path>").option("--allow-local-fixture", "Allow workspace_local fixture keys (dev only)")).action(withClient(async (client, opts) => {
|
|
33595
|
+
await assertHumanStudioIdentity(client, { allowLocalFixture: opts.allowLocalFixture === true });
|
|
33596
|
+
return client.createSlideshowRun({ pack: JSON.parse(await readFile(String(opts.file), "utf8")) });
|
|
33597
|
+
}));
|
|
33496
33598
|
jsonOption(slideshows.command("get").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.getSlideshowRun(String(opts.id))));
|
|
33497
33599
|
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")))));
|
|
33498
33600
|
jsonOption(slideshows.command("archive").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.archiveSlideshowRun(String(opts.id))));
|
|
@@ -33556,5 +33658,5 @@ async function runV1Cli(argv = process.argv) {
|
|
|
33556
33658
|
|
|
33557
33659
|
// src/bin.ts
|
|
33558
33660
|
var exitCode = await runV1Cli();
|
|
33559
|
-
process.exit(exitCode);
|
|
33661
|
+
process.stdout.write("", () => process.exit(exitCode));
|
|
33560
33662
|
//# sourceMappingURL=easysociable.js.map
|