@easysociable/cli 0.1.2 → 0.1.4
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 +32 -21
- package/{skills/easysociable-content → content-engine}/scripts/starter.mjs +3 -1
- package/{skills/easysociable-content → content-engine}/scripts/workbench.mjs +13 -8
- package/{skills/easysociable-content → content-engine}/starter/CLAUDE.md +217 -128
- package/{skills/easysociable-content → content-engine}/starter/engine.json +3 -0
- package/content-engine/starter/needs/README.md +38 -0
- package/content-engine/starter/needs/_index.md +31 -0
- package/content-engine/starter/needs/_template.md +24 -0
- package/content-engine/starter/needs/entries/README.md +5 -0
- package/content-engine/starter/products/README.md +38 -0
- package/content-engine/starter/products/_index.md +24 -0
- package/content-engine/starter/products/_template.md +56 -0
- package/content-engine/starter/products/entries/P-001-easysociable.md +150 -0
- package/content-engine/starter/profiles/_index.md +16 -0
- package/{skills/easysociable-content → content-engine}/starter/profiles/default/README.md +4 -1
- package/content-engine/starter/profiles/default/boundaries.md +14 -0
- package/content-engine/starter/profiles/default/expression.md +18 -0
- package/content-engine/starter/profiles/default/lanes.md +12 -0
- package/content-engine/starter/profiles/default/stories.md +15 -0
- package/{skills/easysociable-content → content-engine}/starter/profiles/default/voice.md +14 -0
- package/content-engine/starter/recommendations/README.md +21 -0
- package/content-engine/starter/recommendations/_index.md +21 -0
- package/content-engine/starter/recommendations/_template.md +44 -0
- package/{skills/easysociable-content → content-engine}/starter/runs/_template/brief.md +1 -1
- package/{skills/easysociable-content → content-engine}/starter/runs/_template/pack.md +15 -7
- package/{skills/easysociable-content → content-engine}/starter/runs/_template/packet.md +6 -0
- package/{skills/easysociable-content → content-engine}/starter/swipe/_template.md +3 -1
- package/content-engine/starter/topics/README.md +21 -0
- package/{skills/easysociable-content → content-engine}/starter/topics/_index.md +12 -5
- package/content-engine/starter/topics/_template-item.md +103 -0
- package/{skills/easysociable-content → content-engine}/starter/topics/scoring.md +55 -4
- package/content-engine/workbench/__pycache__/build.cpython-310.pyc +0 -0
- package/{skills/easysociable-content → content-engine}/workbench/build.py +306 -97
- package/{skills/easysociable-content → content-engine}/workbench/serve.py +0 -0
- package/{skills/easysociable-content → content-engine}/workbench/template.html +173 -27
- package/dist/easysociable.js +629 -142
- package/dist/easysociable.js.map +1 -1
- package/package.json +15 -15
- package/skills/ONBOARDING.md +21 -18
- package/skills/easysociable-content/SKILL.md +104 -98
- package/skills/easysociable-content/workflows/INTERVIEW.md +70 -0
- package/skills/easysociable-content/workflows/NEEDS.md +82 -0
- package/skills/easysociable-slideshow/SKILL.md +79 -44
- package/skills/easysociable-slideshow/references/ARC.md +44 -0
- package/skills/easysociable-slideshow/references/CONTENT_PACK.md +34 -6
- package/skills/easysociable-slideshow/workflows/CREATE_RUN.md +24 -5
- package/skills/easysociable-slideshow/workflows/OUT_OF_SCOPE.md +3 -0
- package/skills/easysociable-template/SKILL.md +29 -30
- package/skills/easysociable-template/references/CATALOG_METADATA.md +23 -20
- package/skills/easysociable-template/references/DESIGN_V2_1.md +53 -2
- package/skills/easysociable-template/references/GATEWAY.md +7 -2
- package/skills/easysociable-template/references/PLATFORM_SPECS.md +11 -3
- package/skills/easysociable-template/references/THEME_TOKENS.md +1 -1
- package/skills/easysociable-template/references/fixtures/image-reference.design-plan.json +74 -0
- package/skills/easysociable-template/references/fixtures/image-reference.visual-qa.json +28 -0
- package/skills/easysociable-template/scripts/generate-theme-from-hex.mjs +0 -0
- package/skills/easysociable-template/scripts/validate-design-v2.mjs +97 -0
- package/skills/easysociable-template/workflows/ASSET_PLAN.md +2 -1
- package/skills/easysociable-template/workflows/AUTHORING_FROM_BRIEF.md +4 -4
- package/skills/easysociable-template/workflows/AUTHORING_FROM_IMAGE.md +66 -16
- package/skills/easysociable-template/workflows/AUTHORING_STUDIO.md +28 -15
- package/skills/easysociable-template/workflows/DESIGN_BRIEF.md +4 -3
- package/skills/easysociable-template/workflows/FILL_AND_RENDER.md +4 -83
- package/skills/easysociable-template/workflows/MULTI_PLATFORM_FAMILY.md +81 -0
- package/skills/easysociable-template/workflows/OUT_OF_SCOPE.md +3 -2
- package/skills/easysociable-template/workflows/PUBLISH_FROM_DRAFT.md +1 -1
- package/skills/easysociable-template/workflows/VISUAL_QA.md +10 -0
- package/skills/easysociable-content/INSTALL.md +0 -60
- package/skills/easysociable-content/platforms/claude.md +0 -4
- package/skills/easysociable-content/platforms/codex.md +0 -4
- package/skills/easysociable-content/platforms/hermes.md +0 -4
- package/skills/easysociable-content/platforms/openclaw.md +0 -4
- package/skills/easysociable-content/references/CLI.md +0 -40
- package/skills/easysociable-content/references/CONTRACT_SYNC.md +0 -42
- package/skills/easysociable-content/references/MCP.md +0 -15
- package/skills/easysociable-content/references/PAGE_PACK.md +0 -129
- package/skills/easysociable-content/references/PLATFORM_GUIDE.md +0 -36
- package/skills/easysociable-content/references/RUN_LAYOUT.md +0 -73
- package/skills/easysociable-content/references/TROUBLESHOOTING.md +0 -13
- package/skills/easysociable-content/references/VAULT.md +0 -40
- package/skills/easysociable-content/references/VOICE.md +0 -16
- package/skills/easysociable-content/scripts/package-skill.mjs +0 -49
- package/skills/easysociable-content/scripts/setup.mjs +0 -200
- package/skills/easysociable-content/scripts/setup.test.mjs +0 -82
- package/skills/easysociable-content/starter/discovery/README.md +0 -18
- package/skills/easysociable-content/starter/discovery/_index.md +0 -27
- package/skills/easysociable-content/starter/discovery/_template.md +0 -41
- package/skills/easysociable-content/starter/profiles/_index.md +0 -13
- package/skills/easysociable-content/starter/topics/README.md +0 -25
- package/skills/easysociable-content/starter/topics/WATCHLIST.md +0 -65
- package/skills/easysociable-content/starter/topics/_template-item.md +0 -90
- package/skills/easysociable-content/starter/topics/watchlists/README.md +0 -10
- package/skills/easysociable-content/starter/topics/watchlists/_shared.md +0 -14
- package/skills/easysociable-content/starter/topics/watchlists/default.md +0 -6
- package/skills/easysociable-content/workflows/ANALYSIS_AND_COVERAGE.md +0 -17
- package/skills/easysociable-content/workflows/CONTENT_EXPORT.md +0 -24
- package/skills/easysociable-content/workflows/GETTING_STARTED.md +0 -40
- package/skills/easysociable-content/workflows/MCP_FIRST.md +0 -5
- package/skills/easysociable-content/workflows/OUT_OF_SCOPE.md +0 -18
- package/skills/easysociable-content/workflows/PACK_AUTHORING.md +0 -42
- package/skills/easysociable-content/workflows/SWIPE_CAPTURE.md +0 -18
- package/skills/easysociable-content/workflows/TOPIC_DRAFT.md +0 -29
- package/skills/easysociable-content/workflows/WORKING_DRAFT.md +0 -19
- /package/{skills/easysociable-content → content-engine}/fixtures/golden-run-en/draft.md +0 -0
- /package/{skills/easysociable-content → content-engine}/fixtures/golden-run-en/idea.md +0 -0
- /package/{skills/easysociable-content → content-engine}/fixtures/golden-run-en/pack-tiktok.json +0 -0
- /package/{skills/easysociable-content → content-engine}/scripts/contracts.mjs +0 -0
- /package/{skills/easysociable-content → content-engine}/scripts/export-contracts.mjs +0 -0
- /package/{skills/easysociable-content → content-engine}/scripts/fixture.test.mjs +0 -0
- /package/{skills/easysociable-content → content-engine}/scripts/validate-export.mjs +0 -0
- /package/{skills/easysociable-content → content-engine}/scripts/validate-pack.mjs +0 -0
- /package/{skills/easysociable-content → content-engine}/scripts/validate-run.mjs +0 -0
- /package/{skills/easysociable-content → content-engine}/scripts/validate.test.mjs +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/accounts/README.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/accounts/_index.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/accounts/overrides/README.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/exports/README.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/inbox/README.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/inbox/_index.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/inbox/entries/README.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/platforms/README.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/platforms/ig.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/platforms/instagram.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/platforms/linkedin.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/platforms/threads.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/platforms/tiktok.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/platforms/x.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/platforms/xiaohongshu.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/profiles/default/audience.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/profiles/default/pillars.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/published/_index.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/raw/README.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/raw/_index.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/runs/README.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/runs/_index.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/runs/_template/draft.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/runs/_template/editor.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/runs/_template/feedback.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/runs/_template/idea.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/runs/_template/rubric.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/swipe/_index.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/topics/items/README.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/wiki/README.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/wiki/atoms/_index.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/wiki/atoms/_template.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/wiki/claims/_index.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/wiki/claims/_template.md +0 -0
- /package/{skills/easysociable-content → content-engine}/starter/workbench/README.md +0 -0
package/dist/easysociable.js
CHANGED
|
@@ -15351,13 +15351,17 @@ function parseSlideshowRunSummaryList(payload) {
|
|
|
15351
15351
|
assertNoPrivateTemplateFields(payload);
|
|
15352
15352
|
return parseDataEnvelope(payload, external_exports.array(slideshowRunSummarySchema));
|
|
15353
15353
|
}
|
|
15354
|
+
function parseSlideshowRunSummary(payload) {
|
|
15355
|
+
assertNoPrivateTemplateFields(payload);
|
|
15356
|
+
return parseDataEnvelope(payload, slideshowRunSummarySchema);
|
|
15357
|
+
}
|
|
15354
15358
|
function parseBrand(payload) {
|
|
15355
15359
|
return parseDataEnvelope(payload, brandSchema);
|
|
15356
15360
|
}
|
|
15357
15361
|
function parseBrandList(payload) {
|
|
15358
15362
|
return parseDataEnvelope(payload, external_exports.array(brandSchema));
|
|
15359
15363
|
}
|
|
15360
|
-
var FORBIDDEN_PUBLIC_KEYS, templatePlatformSchema, canvasPresetSchema, pageRoleSchema, contentFamilySchema, contentArchetypeSchema, densityLevelSchema, visualStyleSchema, imageRoleSchema, slotSummarySchema, selectionMetadataSchema, selectionMetadataDraftSchema, listTemplatesQuerySchema, templateSummarySchema, publicTemplateSlotTypeSchema, publicTemplateSlotSchema, templateDetailSchema, templateSelectionSchema, presentationIntentSchema, renderSlotValueSchema, renderJobRequestSchema, legacyRenderJobRequestSchema, renderJobStatusSchema, renderCaptureHintSchema, renderJobViewSchema, renderPreviewMaterializationSchema, renderSelectionSummarySchema, renderManifestSchema, templateAuthoringCanvasSchema, templateAuthoringProvenanceSchema, templateImageModeSchema, templateImageNodeSchema, authoringImageNodeSchema, authoringIconNodeSchema, templateAuthoringSourceSchema, themeContrastEntrySchema, themePaletteSchema, themeTokensSchema, themeSummarySchema, themeDetailSchema, gradientTextSafeZoneSchema, gradientStopSchema, gradientSummarySchema, gradientDetailSchema, listGradientsQuerySchema, templateSurfaceKindSchema, templateSurfacePreviewSchema, templateImageProviderSchema, templateImageRightsStatusSchema, templateImageProvenanceSchema, importTemplateImageFileSchema, importTemplateImageInputSchema, importTemplateImageBodySchema, createRenderAssetInputSchema, renderAssetReferenceSchema, iconStyleSchema, templateIconLicenseSchema, searchTemplateIconsRequestSchema, templateIconCandidateSchema, getTemplateIconRequestSchema, templateIconProvenanceSchema, templateIconAssetReferenceSchema, templateIconErrorCodeSchema, templateImageReferenceSchema, themeCreateInputSchema, draftThemeInputSchema, createTemplateDraftInputSchema, updateTemplateDraftInputSchema, templateAuthoringDraftSchema, DEFAULT_AUTHORING_STUDIO_BASE_URL, templatePrincipalErrorSchema, slideshowPlatformCaps, slideshowPlatformSchema, slideshowRunStatusSchema, publicSlotValueSchema, contentPackPageSchema, contentPackSchema, slideshowRunPageSchema, brandProfilePreferenceSchema, brandProfileSchema, createBrandProfileInputSchema, updateBrandProfileInputSchema, brandTypographySchema, brandColorsSchema, brandSchema, createBrandInputSchema, updateBrandInputSchema, slideshowRunSummarySchema, slideshowRunSchema, createSlideshowRunInputSchema, updateSlideshowRunInputSchema, renderSlideshowRunInputSchema, listSlideshowRunsQuerySchema;
|
|
15364
|
+
var FORBIDDEN_PUBLIC_KEYS, templatePlatformSchema, canvasPresetSchema, pageRoleSchema, contentFamilySchema, contentArchetypeSchema, densityLevelSchema, visualStyleSchema, imageRoleSchema, slotSummarySchema, selectionMetadataSchema, selectionMetadataDraftSchema, listTemplatesQuerySchema, templateSummarySchema, publicTemplateSlotTypeSchema, publicTemplateSlotSchema, templateDetailSchema, templateSelectionSchema, presentationIntentSchema, renderSlotValueSchema, renderJobRequestSchema, legacyRenderJobRequestSchema, renderJobStatusSchema, renderCaptureHintSchema, renderJobViewSchema, renderPreviewMaterializationSchema, renderSelectionSummarySchema, renderManifestSchema, templateAuthoringCanvasSchema, templateAuthoringProvenanceSchema, templateImageModeSchema, templateImageNodeSchema, authoringImageNodeSchema, authoringIconNodeSchema, templateAuthoringSourceSchema, themeContrastEntrySchema, themePaletteSchema, themeTokensSchema, themeSummarySchema, themeDetailSchema, gradientTextSafeZoneSchema, gradientStopSchema, gradientSummarySchema, gradientDetailSchema, listGradientsQuerySchema, templateSurfaceKindSchema, templateSurfacePreviewSchema, templateImageProviderSchema, templateImageRightsStatusSchema, templateImageProvenanceSchema, importTemplateImageFileSchema, importTemplateImageInputSchema, importTemplateImageBodySchema, createRenderAssetInputSchema, renderAssetReferenceSchema, iconStyleSchema, templateIconLicenseSchema, searchTemplateIconsRequestSchema, templateIconCandidateSchema, getTemplateIconRequestSchema, templateIconProvenanceSchema, templateIconAssetReferenceSchema, templateIconErrorCodeSchema, templateImageReferenceSchema, themeCreateInputSchema, draftThemeInputSchema, createTemplateDraftInputSchema, updateTemplateDraftInputSchema, authoringDraftVariantSchema, templateAuthoringDraftSchema, DEFAULT_AUTHORING_STUDIO_BASE_URL, templatePrincipalErrorSchema, slideshowPlatformCaps, slideshowPlatformSchema, slideshowRunStatusSchema, publicSlotValueSchema, contentPackPageSchema, contentPackSchema, slideshowRunPageSchema, brandProfilePreferenceSchema, brandProfileSchema, createBrandProfileInputSchema, updateBrandProfileInputSchema, brandTypographySchema, brandColorsSchema, brandSchema, createBrandInputSchema, updateBrandInputSchema, slideshowRunSummarySchema, slideshowRunSchema, createSlideshowRunInputSchema, updateSlideshowRunInputSchema, renderSlideshowRunInputSchema, listSlideshowRunsQuerySchema;
|
|
15361
15365
|
var init_src = __esm({
|
|
15362
15366
|
"../../packages/template-public-contracts/src/index.ts"() {
|
|
15363
15367
|
"use strict";
|
|
@@ -15487,8 +15491,8 @@ var init_src = __esm({
|
|
|
15487
15491
|
notFor: external_exports.array(external_exports.string()).min(1).max(3).optional(),
|
|
15488
15492
|
selectionHints: external_exports.string().optional(),
|
|
15489
15493
|
visualStyle: visualStyleSchema.optional(),
|
|
15490
|
-
|
|
15491
|
-
|
|
15494
|
+
// ADR-0033: published selection metadata must not bind a Theme.
|
|
15495
|
+
// Runtime appearance comes from Brand themeSnapshot at fill/render.
|
|
15492
15496
|
locale: external_exports.enum(["zh-CN", "en", "bilingual"]).optional(),
|
|
15493
15497
|
exampleFilledPreviewUrl: external_exports.string().url().optional(),
|
|
15494
15498
|
// P2
|
|
@@ -15538,7 +15542,10 @@ var init_src = __esm({
|
|
|
15538
15542
|
notFor: external_exports.array(external_exports.string()).optional(),
|
|
15539
15543
|
locale: external_exports.enum(["zh-CN", "en", "bilingual"]).optional(),
|
|
15540
15544
|
capacity: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
15541
|
-
previewImageUrl: external_exports.string().url().optional()
|
|
15545
|
+
previewImageUrl: external_exports.string().url().optional(),
|
|
15546
|
+
/** Layout Family id — catalog UIs group variants by this (ADR-0033). */
|
|
15547
|
+
familyId: external_exports.string().optional(),
|
|
15548
|
+
familyRole: external_exports.enum(["master", "variant"]).optional()
|
|
15542
15549
|
}).strict();
|
|
15543
15550
|
publicTemplateSlotTypeSchema = external_exports.enum(["text", "number", "image"]);
|
|
15544
15551
|
publicTemplateSlotSchema = external_exports.object({
|
|
@@ -15630,7 +15637,11 @@ var init_src = __esm({
|
|
|
15630
15637
|
}).strict();
|
|
15631
15638
|
renderSelectionSummarySchema = external_exports.object({
|
|
15632
15639
|
templateId: external_exports.string().min(1),
|
|
15633
|
-
|
|
15640
|
+
/**
|
|
15641
|
+
* Optional audit id for the tokens used (Brand snapshot / preview fallback).
|
|
15642
|
+
* Not a Template→Theme publish binding (ADR-0033).
|
|
15643
|
+
*/
|
|
15644
|
+
themeId: external_exports.string().min(1).optional(),
|
|
15634
15645
|
role: external_exports.string().min(1),
|
|
15635
15646
|
canvas: external_exports.object({
|
|
15636
15647
|
width: external_exports.number().int().positive(),
|
|
@@ -15999,23 +16010,18 @@ var init_src = __esm({
|
|
|
15999
16010
|
tokens: themeTokensSchema
|
|
16000
16011
|
}).strict();
|
|
16001
16012
|
draftThemeInputSchema = external_exports.object({
|
|
16013
|
+
/** @deprecated TemplateTheme retired — ignored; use create.tokens or tokens. */
|
|
16002
16014
|
themeId: external_exports.string().min(1).optional(),
|
|
16003
|
-
/**
|
|
16015
|
+
/** Preferred: write these onto LayoutFamily.preview_tokens. */
|
|
16004
16016
|
tokens: themeTokensSchema.optional(),
|
|
16005
16017
|
create: themeCreateInputSchema.optional()
|
|
16006
16018
|
}).strict().refine(
|
|
16007
16019
|
(value) => {
|
|
16008
|
-
const hasId = Boolean(value.themeId);
|
|
16009
16020
|
const hasCreate = Boolean(value.create);
|
|
16010
|
-
|
|
16011
|
-
|
|
16012
|
-
if (!hasId && !hasCreate)
|
|
16013
|
-
return false;
|
|
16014
|
-
if (value.tokens && !hasId)
|
|
16015
|
-
return false;
|
|
16016
|
-
return true;
|
|
16021
|
+
const hasTokens = Boolean(value.tokens);
|
|
16022
|
+
return hasCreate || hasTokens;
|
|
16017
16023
|
},
|
|
16018
|
-
{ message: "theme must provide
|
|
16024
|
+
{ message: "theme must provide create.tokens or tokens for Family.preview_tokens" }
|
|
16019
16025
|
);
|
|
16020
16026
|
createTemplateDraftInputSchema = external_exports.object({
|
|
16021
16027
|
name: external_exports.string().min(1),
|
|
@@ -16035,12 +16041,28 @@ var init_src = __esm({
|
|
|
16035
16041
|
theme: draftThemeInputSchema.optional(),
|
|
16036
16042
|
selectionMetadata: selectionMetadataDraftSchema.optional()
|
|
16037
16043
|
}).strict();
|
|
16044
|
+
authoringDraftVariantSchema = external_exports.object({
|
|
16045
|
+
pageId: external_exports.string(),
|
|
16046
|
+
familyRole: external_exports.enum(["master", "variant"]),
|
|
16047
|
+
canvasPreset: external_exports.string().nullable().optional(),
|
|
16048
|
+
canvas: external_exports.object({
|
|
16049
|
+
width: external_exports.number(),
|
|
16050
|
+
height: external_exports.number()
|
|
16051
|
+
}),
|
|
16052
|
+
platforms: external_exports.array(external_exports.string())
|
|
16053
|
+
}).strict();
|
|
16038
16054
|
templateAuthoringDraftSchema = external_exports.object({
|
|
16039
16055
|
id: external_exports.string(),
|
|
16040
16056
|
/** Equals draft id — drafts are folded into TemplatePage. */
|
|
16041
16057
|
templateId: external_exports.string().optional(),
|
|
16042
16058
|
/** Soft theme preview reference; tokens are not stored on the draft. */
|
|
16043
16059
|
themeId: external_exports.string().optional(),
|
|
16060
|
+
/** Alias of themeId after Layout Family / Theme unbind. */
|
|
16061
|
+
previewThemeId: external_exports.string().nullable().optional(),
|
|
16062
|
+
familyId: external_exports.string().optional(),
|
|
16063
|
+
familyRole: external_exports.enum(["master", "variant"]).optional(),
|
|
16064
|
+
variants: external_exports.array(authoringDraftVariantSchema).optional(),
|
|
16065
|
+
intendedPlatforms: external_exports.array(external_exports.string()).optional(),
|
|
16044
16066
|
name: external_exports.string(),
|
|
16045
16067
|
status: external_exports.enum(["draft", "validated", "published", "archived", "trashed"]),
|
|
16046
16068
|
revision: external_exports.number().int().positive().optional(),
|
|
@@ -16273,7 +16295,7 @@ function isRetryableStatus(status) {
|
|
|
16273
16295
|
return status === 429 || status === 502 || status === 503 || status === 504;
|
|
16274
16296
|
}
|
|
16275
16297
|
function sleep(ms) {
|
|
16276
|
-
return new Promise((
|
|
16298
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
16277
16299
|
}
|
|
16278
16300
|
var TemplateGatewayError, TemplateGatewayClient;
|
|
16279
16301
|
var init_client = __esm({
|
|
@@ -16449,6 +16471,25 @@ var init_client = __esm({
|
|
|
16449
16471
|
this.options.authoringStudioBaseUrl
|
|
16450
16472
|
);
|
|
16451
16473
|
}
|
|
16474
|
+
async getTemplateFamily(familyId) {
|
|
16475
|
+
const response = await this.request("GET", `/v1/template-families/${encodeURIComponent(familyId)}`);
|
|
16476
|
+
this.throwIfError(response.status, response.json);
|
|
16477
|
+
return response.json.data ?? response.json;
|
|
16478
|
+
}
|
|
16479
|
+
async deriveTemplateFamily(familyId, body = {}) {
|
|
16480
|
+
const response = await this.request(
|
|
16481
|
+
"POST",
|
|
16482
|
+
`/v1/template-families/${encodeURIComponent(familyId)}/derive`,
|
|
16483
|
+
body
|
|
16484
|
+
);
|
|
16485
|
+
this.throwIfError(response.status, response.json);
|
|
16486
|
+
return response.json.data ?? response.json;
|
|
16487
|
+
}
|
|
16488
|
+
async migrateLegacyTemplateFamilies() {
|
|
16489
|
+
const response = await this.request("POST", "/v1/template-families/migrate-legacy", {});
|
|
16490
|
+
this.throwIfError(response.status, response.json);
|
|
16491
|
+
return response.json.data;
|
|
16492
|
+
}
|
|
16452
16493
|
async updateDraft(draftId, body) {
|
|
16453
16494
|
const input = parseUpdateTemplateDraftInput(body);
|
|
16454
16495
|
const response = await this.request("PUT", `/v1/template-drafts/${encodeURIComponent(draftId)}`, input);
|
|
@@ -16535,11 +16576,11 @@ var init_client = __esm({
|
|
|
16535
16576
|
this.throwIfError(response.status, response.json);
|
|
16536
16577
|
return parseSlideshowRun(response.json);
|
|
16537
16578
|
}
|
|
16579
|
+
/** Permanently delete a Slideshow Run (ADR-0034 hard delete). */
|
|
16538
16580
|
async trashSlideshowRun(runId) {
|
|
16539
16581
|
const response = await this.request("DELETE", `/v1/slideshow/runs/${encodeURIComponent(runId)}`);
|
|
16540
16582
|
this.throwIfError(response.status, response.json);
|
|
16541
|
-
|
|
16542
|
-
return rows[0];
|
|
16583
|
+
return parseSlideshowRunSummary(response.json);
|
|
16543
16584
|
}
|
|
16544
16585
|
async renderSlideshowRun(runId, body) {
|
|
16545
16586
|
const input = renderSlideshowRunInputSchema.parse(body ?? {});
|
|
@@ -23418,7 +23459,7 @@ var init_protocol = __esm({
|
|
|
23418
23459
|
return;
|
|
23419
23460
|
}
|
|
23420
23461
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
23421
|
-
await new Promise((
|
|
23462
|
+
await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
|
|
23422
23463
|
options?.signal?.throwIfAborted();
|
|
23423
23464
|
}
|
|
23424
23465
|
} catch (error52) {
|
|
@@ -23435,7 +23476,7 @@ var init_protocol = __esm({
|
|
|
23435
23476
|
*/
|
|
23436
23477
|
request(request, resultSchema, options) {
|
|
23437
23478
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
23438
|
-
return new Promise((
|
|
23479
|
+
return new Promise((resolve3, reject) => {
|
|
23439
23480
|
const earlyReject = (error52) => {
|
|
23440
23481
|
reject(error52);
|
|
23441
23482
|
};
|
|
@@ -23513,7 +23554,7 @@ var init_protocol = __esm({
|
|
|
23513
23554
|
if (!parseResult.success) {
|
|
23514
23555
|
reject(parseResult.error);
|
|
23515
23556
|
} else {
|
|
23516
|
-
|
|
23557
|
+
resolve3(parseResult.data);
|
|
23517
23558
|
}
|
|
23518
23559
|
} catch (error52) {
|
|
23519
23560
|
reject(error52);
|
|
@@ -23774,12 +23815,12 @@ var init_protocol = __esm({
|
|
|
23774
23815
|
}
|
|
23775
23816
|
} catch {
|
|
23776
23817
|
}
|
|
23777
|
-
return new Promise((
|
|
23818
|
+
return new Promise((resolve3, reject) => {
|
|
23778
23819
|
if (signal.aborted) {
|
|
23779
23820
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
23780
23821
|
return;
|
|
23781
23822
|
}
|
|
23782
|
-
const timeoutId = setTimeout(
|
|
23823
|
+
const timeoutId = setTimeout(resolve3, interval);
|
|
23783
23824
|
signal.addEventListener("abort", () => {
|
|
23784
23825
|
clearTimeout(timeoutId);
|
|
23785
23826
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -26806,7 +26847,7 @@ var require_compile = __commonJS({
|
|
|
26806
26847
|
const schOrFunc = root.refs[ref];
|
|
26807
26848
|
if (schOrFunc)
|
|
26808
26849
|
return schOrFunc;
|
|
26809
|
-
let _sch =
|
|
26850
|
+
let _sch = resolve3.call(this, root, ref);
|
|
26810
26851
|
if (_sch === void 0) {
|
|
26811
26852
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
26812
26853
|
const { schemaId } = this.opts;
|
|
@@ -26833,7 +26874,7 @@ var require_compile = __commonJS({
|
|
|
26833
26874
|
function sameSchemaEnv(s1, s2) {
|
|
26834
26875
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
26835
26876
|
}
|
|
26836
|
-
function
|
|
26877
|
+
function resolve3(root, ref) {
|
|
26837
26878
|
let sch;
|
|
26838
26879
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
26839
26880
|
ref = sch;
|
|
@@ -27408,7 +27449,7 @@ var require_fast_uri = __commonJS({
|
|
|
27408
27449
|
}
|
|
27409
27450
|
return uri;
|
|
27410
27451
|
}
|
|
27411
|
-
function
|
|
27452
|
+
function resolve3(baseURI, relativeURI, options) {
|
|
27412
27453
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
27413
27454
|
const resolved = resolveComponent(parse5(baseURI, schemelessOptions), parse5(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
27414
27455
|
schemelessOptions.skipEscape = true;
|
|
@@ -27635,7 +27676,7 @@ var require_fast_uri = __commonJS({
|
|
|
27635
27676
|
var fastUri = {
|
|
27636
27677
|
SCHEMES,
|
|
27637
27678
|
normalize,
|
|
27638
|
-
resolve,
|
|
27679
|
+
resolve: resolve3,
|
|
27639
27680
|
resolveComponent,
|
|
27640
27681
|
equal,
|
|
27641
27682
|
serialize,
|
|
@@ -31534,12 +31575,12 @@ var init_stdio2 = __esm({
|
|
|
31534
31575
|
this.onclose?.();
|
|
31535
31576
|
}
|
|
31536
31577
|
send(message) {
|
|
31537
|
-
return new Promise((
|
|
31578
|
+
return new Promise((resolve3) => {
|
|
31538
31579
|
const json2 = serializeMessage(message);
|
|
31539
31580
|
if (this._stdout.write(json2)) {
|
|
31540
|
-
|
|
31581
|
+
resolve3();
|
|
31541
31582
|
} else {
|
|
31542
|
-
this._stdout.once("drain",
|
|
31583
|
+
this._stdout.once("drain", resolve3);
|
|
31543
31584
|
}
|
|
31544
31585
|
});
|
|
31545
31586
|
}
|
|
@@ -31610,8 +31651,8 @@ async function serveStdioMcp(options) {
|
|
|
31610
31651
|
await waitForStdioServerClose(server, process.stdin);
|
|
31611
31652
|
}
|
|
31612
31653
|
async function waitForStdioServerClose(server, stdin = process.stdin) {
|
|
31613
|
-
await new Promise((
|
|
31614
|
-
server.onclose = () =>
|
|
31654
|
+
await new Promise((resolve3) => {
|
|
31655
|
+
server.onclose = () => resolve3();
|
|
31615
31656
|
if (stdin.readableEnded || stdin.destroyed) {
|
|
31616
31657
|
void server.close().catch(() => void 0);
|
|
31617
31658
|
return;
|
|
@@ -31940,7 +31981,7 @@ var init_src4 = __esm({
|
|
|
31940
31981
|
{
|
|
31941
31982
|
name: "create_render_job",
|
|
31942
31983
|
title: "Create render job",
|
|
31943
|
-
description: "
|
|
31984
|
+
description: "Retired as a paid delivery path. PNG packs come from Studio Download. Gateway returns HEADLESS_RENDER_DISABLED. Kept for compatibility; do not use for customer PNG delivery. Historic fill-slots shape: templateId + slots + outputFormats (ADR-0021).",
|
|
31944
31985
|
effect: "local-write-job",
|
|
31945
31986
|
inputSchema: {
|
|
31946
31987
|
type: "object",
|
|
@@ -32241,8 +32282,8 @@ var init_src5 = __esm({
|
|
|
32241
32282
|
{ 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 },
|
|
32242
32283
|
{ name: "archive_run", title: "Archive slideshow run", description: "Hide a Run from default lists without deleting it.", effect: "local-write-job", inputSchema: { ...objectSchema, properties: { runId: { type: "string" } }, required: ["runId"] }, outputSchema: objectSchema },
|
|
32243
32284
|
{ name: "restore_run", title: "Restore slideshow run", description: "Restore an archived or trashed Run.", effect: "local-write-job", inputSchema: { ...objectSchema, properties: { runId: { type: "string" } }, required: ["runId"] }, outputSchema: objectSchema },
|
|
32244
|
-
{ name: "trash_run", title: "
|
|
32245
|
-
{ name: "render_run", title: "Render slideshow run", description: "
|
|
32285
|
+
{ name: "trash_run", title: "Delete slideshow run", description: "Permanently delete a Slideshow Run (hard delete; not recoverable).", effect: "explicit-approval", inputSchema: { ...objectSchema, properties: { runId: { type: "string" } }, required: ["runId"] }, outputSchema: objectSchema },
|
|
32286
|
+
{ name: "render_run", title: "Render slideshow run", description: "Retired. PNG packs come from Studio Download in the browser, not hosted render jobs.", effect: "local-write-job", inputSchema: { ...objectSchema, properties: { runId: { type: "string" }, idempotencyKey: { type: "string", minLength: 1, maxLength: 128 } }, required: ["runId", "idempotencyKey"] }, outputSchema: objectSchema }
|
|
32246
32287
|
];
|
|
32247
32288
|
slideshowResourceTemplates = [
|
|
32248
32289
|
{ uriTemplate: "slideshow://runs/{runId}", name: "Slideshow Run", description: "Owner-scoped Run JSON snapshot", mimeType: "application/json" }
|
|
@@ -32277,7 +32318,7 @@ var init_src5 = __esm({
|
|
|
32277
32318
|
case "trash_run":
|
|
32278
32319
|
return { ok: true, data: await this.client.trashSlideshowRun(String(args.runId)), meta: m };
|
|
32279
32320
|
case "render_run":
|
|
32280
|
-
return { ok:
|
|
32321
|
+
return { ok: false, error: { code: "HEADLESS_RENDER_DISABLED", message: "PNG packs come from Studio Download, not CLI/MCP hosted jobs", retryable: false, suggestedAction: "Open the Slideshow in Studio and click Download" }, meta: m };
|
|
32281
32322
|
default:
|
|
32282
32323
|
return { ok: false, error: { code: "UNKNOWN_TOOL", message: `Unknown tool: ${toolName}`, retryable: false }, meta: m };
|
|
32283
32324
|
}
|
|
@@ -32309,13 +32350,20 @@ async function serveUnifiedStdioMcp(client) {
|
|
|
32309
32350
|
resourceTemplates: unifiedResourceTemplates
|
|
32310
32351
|
}, { backendName: "gateway" });
|
|
32311
32352
|
}
|
|
32312
|
-
var removedTools, templateNames, slideshowNames, brandTools, rename, templateTools, slideshowTools, imageTools, unifiedToolRegistry, unifiedResourceTemplates, UnifiedMcpBackend;
|
|
32353
|
+
var HEADLESS_PNG_DELIVERY, HEADLESS_TOOLS, removedTools, templateNames, slideshowNames, brandTools, rename, templateTools, slideshowTools, imageTools, unifiedToolRegistry, unifiedResourceTemplates, UnifiedMcpBackend;
|
|
32313
32354
|
var init_src6 = __esm({
|
|
32314
32355
|
"../../packages/mcp-server/src/index.ts"() {
|
|
32315
32356
|
"use strict";
|
|
32316
32357
|
init_src3();
|
|
32317
32358
|
init_src4();
|
|
32318
32359
|
init_src5();
|
|
32360
|
+
HEADLESS_PNG_DELIVERY = {
|
|
32361
|
+
code: "HEADLESS_RENDER_DISABLED",
|
|
32362
|
+
message: "PNG packs come from Studio Download, not CLI/MCP hosted jobs",
|
|
32363
|
+
retryable: false,
|
|
32364
|
+
suggestedAction: "Open the Slideshow in Studio and click Download"
|
|
32365
|
+
};
|
|
32366
|
+
HEADLESS_TOOLS = /* @__PURE__ */ new Set(["create_template_render_job", "render_slideshow_run"]);
|
|
32319
32367
|
removedTools = /* @__PURE__ */ new Set(["publish_run", "unpublish_run"]);
|
|
32320
32368
|
templateNames = {
|
|
32321
32369
|
create_draft: "create_template_draft",
|
|
@@ -32369,6 +32417,13 @@ var init_src6 = __esm({
|
|
|
32369
32417
|
this.slideshow = new SlideshowMcpBackend(client);
|
|
32370
32418
|
}
|
|
32371
32419
|
invoke(toolName, args) {
|
|
32420
|
+
if (HEADLESS_TOOLS.has(toolName)) {
|
|
32421
|
+
return Promise.resolve({
|
|
32422
|
+
ok: false,
|
|
32423
|
+
error: { ...HEADLESS_PNG_DELIVERY },
|
|
32424
|
+
meta: { requestId: `mcp_${Date.now().toString(36)}`, runtimeVersion: "0.0.0", schemaVersion: 1, toolContractVersion: "2026-09-04" }
|
|
32425
|
+
});
|
|
32426
|
+
}
|
|
32372
32427
|
const templateTool = templateTools.find((tool) => tool.name === toolName);
|
|
32373
32428
|
if (templateTool) return this.template.invoke(Object.entries(templateNames).find(([, name]) => name === toolName)?.[0] ?? toolName, args);
|
|
32374
32429
|
const slideshowTool = slideshowTools.find((tool) => tool.name === toolName);
|
|
@@ -32452,11 +32507,10 @@ var init_v1_mcp = __esm({
|
|
|
32452
32507
|
|
|
32453
32508
|
// src/v1-cli.ts
|
|
32454
32509
|
init_src2();
|
|
32455
|
-
import { cp,
|
|
32456
|
-
import { existsSync as
|
|
32457
|
-
import {
|
|
32458
|
-
import {
|
|
32459
|
-
import { join as join3 } from "path";
|
|
32510
|
+
import { cp, readFile, writeFile, mkdir, chmod, copyFile } from "fs/promises";
|
|
32511
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
32512
|
+
import { homedir as homedir3 } from "os";
|
|
32513
|
+
import { join as join4, resolve as resolve2 } from "path";
|
|
32460
32514
|
import { Command } from "commander";
|
|
32461
32515
|
|
|
32462
32516
|
// src/runtime/mcp-hosts.ts
|
|
@@ -32581,24 +32635,430 @@ function resolveDefaultSkillsSource(moduleUrl) {
|
|
|
32581
32635
|
return bundled;
|
|
32582
32636
|
}
|
|
32583
32637
|
|
|
32638
|
+
// src/engine.ts
|
|
32639
|
+
import { spawn, spawnSync } from "child_process";
|
|
32640
|
+
import {
|
|
32641
|
+
copyFileSync,
|
|
32642
|
+
existsSync as existsSync3,
|
|
32643
|
+
mkdirSync as mkdirSync2,
|
|
32644
|
+
readdirSync,
|
|
32645
|
+
readFileSync as readFileSync2,
|
|
32646
|
+
statSync,
|
|
32647
|
+
writeFileSync as writeFileSync2
|
|
32648
|
+
} from "fs";
|
|
32649
|
+
import net from "net";
|
|
32650
|
+
import { homedir as homedir2 } from "os";
|
|
32651
|
+
import { basename, dirname as dirname3, join as join3, resolve } from "path";
|
|
32652
|
+
var ENGINE_ROOT_NAME = "Content Engine";
|
|
32653
|
+
var WORKBENCH_PORT = 8765;
|
|
32654
|
+
var WORKBENCH_URL = `http://127.0.0.1:${WORKBENCH_PORT}/workbench/`;
|
|
32655
|
+
var WORKBENCH_FILES = ["template.html", "build.py", "serve.py"];
|
|
32656
|
+
function contentEnginePackageRoot(moduleUrl) {
|
|
32657
|
+
const pkg = cliPackageRoot(moduleUrl);
|
|
32658
|
+
const bundled = join3(pkg, "content-engine");
|
|
32659
|
+
if (existsSync3(join3(bundled, "starter")))
|
|
32660
|
+
return bundled;
|
|
32661
|
+
const sibling = join3(pkg, "content-engine");
|
|
32662
|
+
if (existsSync3(join3(sibling, "starter")))
|
|
32663
|
+
return sibling;
|
|
32664
|
+
return bundled;
|
|
32665
|
+
}
|
|
32666
|
+
function starterDir(moduleUrl) {
|
|
32667
|
+
return join3(contentEnginePackageRoot(moduleUrl), "starter");
|
|
32668
|
+
}
|
|
32669
|
+
function workbenchSrc(moduleUrl) {
|
|
32670
|
+
return join3(contentEnginePackageRoot(moduleUrl), "workbench");
|
|
32671
|
+
}
|
|
32672
|
+
function scriptsDir(moduleUrl) {
|
|
32673
|
+
return join3(contentEnginePackageRoot(moduleUrl), "scripts");
|
|
32674
|
+
}
|
|
32675
|
+
function isDir(path) {
|
|
32676
|
+
return existsSync3(path) && statSync(path).isDirectory();
|
|
32677
|
+
}
|
|
32678
|
+
function isEngine(path) {
|
|
32679
|
+
return isDir(path) && existsSync3(join3(path, "CLAUDE.md")) && isDir(join3(path, "runs"));
|
|
32680
|
+
}
|
|
32681
|
+
function resolveEngine(rootOrEngine) {
|
|
32682
|
+
const absolute = resolve(rootOrEngine);
|
|
32683
|
+
if (isEngine(absolute) || basename(absolute) === ENGINE_ROOT_NAME)
|
|
32684
|
+
return absolute;
|
|
32685
|
+
return join3(absolute, ENGINE_ROOT_NAME);
|
|
32686
|
+
}
|
|
32687
|
+
function walkFiles(dir) {
|
|
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
|
+
products: "products",
|
|
32713
|
+
recommendations: "recommendations",
|
|
32714
|
+
swipe: "swipe",
|
|
32715
|
+
profiles: "profiles",
|
|
32716
|
+
inbox: "inbox",
|
|
32717
|
+
accounts: "accounts",
|
|
32718
|
+
raw: "raw",
|
|
32719
|
+
published: "published",
|
|
32720
|
+
wiki: "wiki",
|
|
32721
|
+
platforms: "platforms",
|
|
32722
|
+
workbench: "workbench"
|
|
32723
|
+
}
|
|
32724
|
+
}, null, 2)}
|
|
32725
|
+
`;
|
|
32726
|
+
}
|
|
32727
|
+
function starterFiles(moduleUrl) {
|
|
32728
|
+
const root = starterDir(moduleUrl);
|
|
32729
|
+
const files = {};
|
|
32730
|
+
for (const path of walkFiles(root)) {
|
|
32731
|
+
const relativePath = path.slice(root.length + 1).split("\\").join("/");
|
|
32732
|
+
files[relativePath] = readFileSync2(path, "utf8");
|
|
32733
|
+
}
|
|
32734
|
+
files["engine.json"] = engineJson();
|
|
32735
|
+
return files;
|
|
32736
|
+
}
|
|
32737
|
+
function inventory(engine, moduleUrl) {
|
|
32738
|
+
const files = starterFiles(moduleUrl);
|
|
32739
|
+
const missing = [];
|
|
32740
|
+
const existing = [];
|
|
32741
|
+
for (const relative of Object.keys(files)) {
|
|
32742
|
+
const path = join3(engine, relative);
|
|
32743
|
+
(existsSync3(path) ? existing : missing).push(relative);
|
|
32744
|
+
}
|
|
32745
|
+
return {
|
|
32746
|
+
engine,
|
|
32747
|
+
engineExists: isDir(engine),
|
|
32748
|
+
rootName: ENGINE_ROOT_NAME,
|
|
32749
|
+
missing,
|
|
32750
|
+
existing,
|
|
32751
|
+
starterComplete: missing.length === 0
|
|
32752
|
+
};
|
|
32753
|
+
}
|
|
32754
|
+
function tableCell(md, field) {
|
|
32755
|
+
const escaped = field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
32756
|
+
const match = md.match(new RegExp(`^\\|\\s*(?:\\*\\*)?${escaped}(?:\\*\\*)?\\s*\\|\\s*([^|]*?)\\|`, "im"));
|
|
32757
|
+
return match ? match[1].trim() : null;
|
|
32758
|
+
}
|
|
32759
|
+
function isFilledCell(value) {
|
|
32760
|
+
if (value == null)
|
|
32761
|
+
return false;
|
|
32762
|
+
const text = value.trim();
|
|
32763
|
+
return text.length > 0 && !/\(fill\)/i.test(text);
|
|
32764
|
+
}
|
|
32765
|
+
function headingSection(md, title) {
|
|
32766
|
+
const escaped = title.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
32767
|
+
const match = md.match(new RegExp(`^##\\s+${escaped}\\s*$`, "im"));
|
|
32768
|
+
if (!match || match.index == null)
|
|
32769
|
+
return null;
|
|
32770
|
+
const rest = md.slice(match.index + match[0].length);
|
|
32771
|
+
const next = rest.search(/^##\s+/m);
|
|
32772
|
+
return (next < 0 ? rest : rest.slice(0, next)).trim();
|
|
32773
|
+
}
|
|
32774
|
+
function isFilledSection(body) {
|
|
32775
|
+
if (body == null)
|
|
32776
|
+
return false;
|
|
32777
|
+
const cleaned = body.replace(/\(fill\)/gi, "").replace(/^[-*]\s*$/gm, "").replace(/^\d+\.\s*$/gm, "").trim();
|
|
32778
|
+
return cleaned.length > 0;
|
|
32779
|
+
}
|
|
32780
|
+
function activeProfileId(engine) {
|
|
32781
|
+
const path = join3(engine, "accounts", "_index.md");
|
|
32782
|
+
if (!existsSync3(path))
|
|
32783
|
+
return null;
|
|
32784
|
+
for (const line of readFileSync2(path, "utf8").split("\n")) {
|
|
32785
|
+
if (!line.startsWith("|"))
|
|
32786
|
+
continue;
|
|
32787
|
+
const cells = line.split("|").slice(1, -1).map((cell) => cell.trim());
|
|
32788
|
+
if (cells.length < 7)
|
|
32789
|
+
continue;
|
|
32790
|
+
if (/^-+$/.test(cells[0]) || /^handle$/i.test(cells[0]) || /^column$/i.test(cells[0]))
|
|
32791
|
+
continue;
|
|
32792
|
+
if (cells[6].toLowerCase() === "active" && cells[1])
|
|
32793
|
+
return cells[1];
|
|
32794
|
+
}
|
|
32795
|
+
return null;
|
|
32796
|
+
}
|
|
32797
|
+
function countNeedIds(md) {
|
|
32798
|
+
let count = 0;
|
|
32799
|
+
for (const line of md.split("\n")) {
|
|
32800
|
+
if (/^\|\s*N-\d{8}-\d+/.test(line))
|
|
32801
|
+
count += 1;
|
|
32802
|
+
}
|
|
32803
|
+
return count;
|
|
32804
|
+
}
|
|
32805
|
+
function checkKnowledge(engine) {
|
|
32806
|
+
const missing = [];
|
|
32807
|
+
const profileId = activeProfileId(engine);
|
|
32808
|
+
if (!profileId)
|
|
32809
|
+
missing.push("accounts/_index.md");
|
|
32810
|
+
const profile = profileId || "default";
|
|
32811
|
+
const voiceRel = `profiles/${profile}/voice.md`;
|
|
32812
|
+
const voicePath = join3(engine, voiceRel);
|
|
32813
|
+
if (!existsSync3(voicePath)) {
|
|
32814
|
+
missing.push(voiceRel);
|
|
32815
|
+
} else {
|
|
32816
|
+
const voice = readFileSync2(voicePath, "utf8");
|
|
32817
|
+
for (const field of ["Role", "What I build", "Point of view"]) {
|
|
32818
|
+
if (!isFilledCell(tableCell(voice, field))) {
|
|
32819
|
+
missing.push(voiceRel);
|
|
32820
|
+
break;
|
|
32821
|
+
}
|
|
32822
|
+
}
|
|
32823
|
+
}
|
|
32824
|
+
const boundariesRel = `profiles/${profile}/boundaries.md`;
|
|
32825
|
+
const boundariesPath = join3(engine, boundariesRel);
|
|
32826
|
+
if (!existsSync3(boundariesPath)) {
|
|
32827
|
+
missing.push(boundariesRel);
|
|
32828
|
+
} else {
|
|
32829
|
+
const boundaries = readFileSync2(boundariesPath, "utf8");
|
|
32830
|
+
if (!isFilledSection(headingSection(boundaries, "Not covering")) || !isFilledSection(headingSection(boundaries, "Never claim")))
|
|
32831
|
+
missing.push(boundariesRel);
|
|
32832
|
+
}
|
|
32833
|
+
const needsDir = join3(engine, "needs");
|
|
32834
|
+
if (isDir(needsDir)) {
|
|
32835
|
+
const needsRel = "needs/_index.md";
|
|
32836
|
+
const needsPath = join3(engine, needsRel);
|
|
32837
|
+
if (!existsSync3(needsPath) || countNeedIds(readFileSync2(needsPath, "utf8")) < 3)
|
|
32838
|
+
missing.push(needsRel);
|
|
32839
|
+
}
|
|
32840
|
+
return { valid: missing.length === 0, missing };
|
|
32841
|
+
}
|
|
32842
|
+
function validateEngine(rootOrEngine, moduleUrl, { strict = false, requireKnowledge = false } = {}) {
|
|
32843
|
+
const engine = resolveEngine(rootOrEngine);
|
|
32844
|
+
const parent = resolve(engine, "..");
|
|
32845
|
+
const errors = [];
|
|
32846
|
+
if (!existsSync3(parent) || !statSync(parent).isDirectory()) {
|
|
32847
|
+
errors.push("Parent directory does not exist");
|
|
32848
|
+
return { ...inventory(engine, moduleUrl), valid: false, errors, created: [] };
|
|
32849
|
+
}
|
|
32850
|
+
const result = inventory(engine, moduleUrl);
|
|
32851
|
+
if (existsSync3(engine) && !isDir(engine))
|
|
32852
|
+
errors.push("Content Engine exists but is not a directory");
|
|
32853
|
+
if (strict) {
|
|
32854
|
+
if (!result.engineExists)
|
|
32855
|
+
errors.push("Content Engine/ folder does not exist");
|
|
32856
|
+
else if (result.missing.length > 0)
|
|
32857
|
+
errors.push(`Starter incomplete: ${result.missing.length} file(s) missing (use engine init --yes to add only missing files)`);
|
|
32858
|
+
}
|
|
32859
|
+
const knowledge = requireKnowledge ? checkKnowledge(engine) : void 0;
|
|
32860
|
+
if (knowledge && !knowledge.valid)
|
|
32861
|
+
errors.push(`Knowledge gate failed: ${knowledge.missing.join(", ")}`);
|
|
32862
|
+
return { ...result, valid: errors.length === 0, errors, created: [], ...knowledge ? { knowledge } : {} };
|
|
32863
|
+
}
|
|
32864
|
+
function python3Bin() {
|
|
32865
|
+
const result = spawnSync("python3", ["--version"], { encoding: "utf8" });
|
|
32866
|
+
return result.status === 0 ? "python3" : "";
|
|
32867
|
+
}
|
|
32868
|
+
function ensureWorkbench(engine, moduleUrl, { update = false } = {}) {
|
|
32869
|
+
const destDir = join3(engine, "workbench");
|
|
32870
|
+
mkdirSync2(destDir, { recursive: true });
|
|
32871
|
+
const copied = [];
|
|
32872
|
+
const updated = [];
|
|
32873
|
+
const skipped = [];
|
|
32874
|
+
const src = workbenchSrc(moduleUrl);
|
|
32875
|
+
for (const name of WORKBENCH_FILES) {
|
|
32876
|
+
const dest = join3(destDir, name);
|
|
32877
|
+
const from = join3(src, name);
|
|
32878
|
+
if (existsSync3(dest) && !update) {
|
|
32879
|
+
skipped.push(name);
|
|
32880
|
+
continue;
|
|
32881
|
+
}
|
|
32882
|
+
const existed = existsSync3(dest);
|
|
32883
|
+
copyFileSync(from, dest);
|
|
32884
|
+
if (existed)
|
|
32885
|
+
updated.push(name);
|
|
32886
|
+
else
|
|
32887
|
+
copied.push(name);
|
|
32888
|
+
}
|
|
32889
|
+
return { destDir, copied, updated, skipped };
|
|
32890
|
+
}
|
|
32891
|
+
function buildWorkbench(engine) {
|
|
32892
|
+
const python = python3Bin();
|
|
32893
|
+
if (!python)
|
|
32894
|
+
return { ok: false, code: "PYTHON3_REQUIRED", message: "python3 is required for the workbench. Install Python 3 and retry." };
|
|
32895
|
+
const script = join3(engine, "workbench", "build.py");
|
|
32896
|
+
if (!existsSync3(script))
|
|
32897
|
+
return { ok: false, code: "WORKBENCH_MISSING", message: "workbench/build.py is missing. Re-run easysociable engine init --yes." };
|
|
32898
|
+
const result = spawnSync(python, [script], { encoding: "utf8", cwd: engine });
|
|
32899
|
+
if (result.status !== 0)
|
|
32900
|
+
return { ok: false, code: "WORKBENCH_BUILD_FAILED", message: result.stderr.trim() || result.stdout.trim() || "workbench build failed" };
|
|
32901
|
+
return { ok: true, message: result.stdout.trim() };
|
|
32902
|
+
}
|
|
32903
|
+
function portInUse(port = WORKBENCH_PORT) {
|
|
32904
|
+
return new Promise((resolvePort) => {
|
|
32905
|
+
const socket = net.connect({ port, host: "127.0.0.1" }, () => {
|
|
32906
|
+
socket.end();
|
|
32907
|
+
resolvePort(true);
|
|
32908
|
+
});
|
|
32909
|
+
socket.on("error", () => resolvePort(false));
|
|
32910
|
+
});
|
|
32911
|
+
}
|
|
32912
|
+
function openUrl(url2) {
|
|
32913
|
+
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
32914
|
+
const args = process.platform === "win32" ? ["/c", "start", url2] : [url2];
|
|
32915
|
+
spawn(command, args, { stdio: "ignore", detached: true }).unref();
|
|
32916
|
+
}
|
|
32917
|
+
async function startWorkbench(engine, moduleUrl, { noOpen = false } = {}) {
|
|
32918
|
+
const python = python3Bin();
|
|
32919
|
+
if (!python)
|
|
32920
|
+
return { ok: false, code: "PYTHON3_REQUIRED", message: "python3 is required for the workbench. Install Python 3 and retry." };
|
|
32921
|
+
ensureWorkbench(engine, moduleUrl, { update: true });
|
|
32922
|
+
const built = buildWorkbench(engine);
|
|
32923
|
+
if (!built.ok)
|
|
32924
|
+
return built;
|
|
32925
|
+
const url2 = WORKBENCH_URL;
|
|
32926
|
+
if (await portInUse()) {
|
|
32927
|
+
if (!noOpen && process.env.EASYSOCIABLE_NO_OPEN !== "true")
|
|
32928
|
+
openUrl(url2);
|
|
32929
|
+
return { ok: true, alreadyRunning: true, url: url2, build: built.message };
|
|
32930
|
+
}
|
|
32931
|
+
const args = [join3(engine, "workbench", "serve.py")];
|
|
32932
|
+
if (noOpen)
|
|
32933
|
+
args.push("--no-open");
|
|
32934
|
+
const child = spawn(python, args, { cwd: engine, detached: true, stdio: "ignore" });
|
|
32935
|
+
child.unref();
|
|
32936
|
+
return { ok: true, alreadyRunning: false, url: url2, pid: child.pid, build: built.message };
|
|
32937
|
+
}
|
|
32938
|
+
async function initEngine(rootOrEngine, moduleUrl, {
|
|
32939
|
+
yes = false,
|
|
32940
|
+
noOpen = false,
|
|
32941
|
+
serve = false
|
|
32942
|
+
} = {}) {
|
|
32943
|
+
const engine = resolveEngine(rootOrEngine);
|
|
32944
|
+
if (!yes) {
|
|
32945
|
+
const preview = validateEngine(engine, moduleUrl);
|
|
32946
|
+
return {
|
|
32947
|
+
...preview,
|
|
32948
|
+
action: "preview",
|
|
32949
|
+
next: "Review missing files and re-run with --yes"
|
|
32950
|
+
};
|
|
32951
|
+
}
|
|
32952
|
+
const parent = resolve(engine, "..");
|
|
32953
|
+
if (!existsSync3(parent) || !statSync(parent).isDirectory()) {
|
|
32954
|
+
return {
|
|
32955
|
+
engine,
|
|
32956
|
+
action: "applied",
|
|
32957
|
+
valid: false,
|
|
32958
|
+
code: "PARENT_MISSING",
|
|
32959
|
+
errors: ["Parent directory does not exist"],
|
|
32960
|
+
created: []
|
|
32961
|
+
};
|
|
32962
|
+
}
|
|
32963
|
+
mkdirSync2(engine, { recursive: true });
|
|
32964
|
+
const report = inventory(engine, moduleUrl);
|
|
32965
|
+
const created = [];
|
|
32966
|
+
const files = starterFiles(moduleUrl);
|
|
32967
|
+
for (const relative of report.missing) {
|
|
32968
|
+
const path = join3(engine, relative);
|
|
32969
|
+
mkdirSync2(dirname3(path), { recursive: true });
|
|
32970
|
+
writeFileSync2(path, files[relative], { encoding: "utf8", flag: "wx" });
|
|
32971
|
+
created.push(relative);
|
|
32972
|
+
}
|
|
32973
|
+
const workbench = ensureWorkbench(engine, moduleUrl);
|
|
32974
|
+
const python = python3Bin();
|
|
32975
|
+
if (!python) {
|
|
32976
|
+
return {
|
|
32977
|
+
...validateEngine(engine, moduleUrl),
|
|
32978
|
+
created,
|
|
32979
|
+
workbench,
|
|
32980
|
+
action: "applied",
|
|
32981
|
+
valid: false,
|
|
32982
|
+
code: "PYTHON3_REQUIRED",
|
|
32983
|
+
errors: ["python3 is required for the workbench. Install Python 3 and retry. Starter files were written; workbench was not started."]
|
|
32984
|
+
};
|
|
32985
|
+
}
|
|
32986
|
+
const built = buildWorkbench(engine);
|
|
32987
|
+
const started = serve ? await startWorkbench(engine, moduleUrl, { noOpen }) : { skipped: true, build: built };
|
|
32988
|
+
return {
|
|
32989
|
+
...validateEngine(engine, moduleUrl),
|
|
32990
|
+
created,
|
|
32991
|
+
workbench,
|
|
32992
|
+
workbenchBuild: built,
|
|
32993
|
+
workbenchStart: started,
|
|
32994
|
+
action: "applied"
|
|
32995
|
+
};
|
|
32996
|
+
}
|
|
32997
|
+
function detectEngines() {
|
|
32998
|
+
const extra = (process.env.EASYSOCIABLE_ENGINE_SEARCH_ROOTS || "").split(process.platform === "win32" ? ";" : ":").map((item) => item.trim()).filter(Boolean);
|
|
32999
|
+
const home = homedir2();
|
|
33000
|
+
const roots = [...extra, join3(home, "Documents"), home];
|
|
33001
|
+
const found = [];
|
|
33002
|
+
for (const root of roots) {
|
|
33003
|
+
if (!isDir(root))
|
|
33004
|
+
continue;
|
|
33005
|
+
const direct = join3(root, ENGINE_ROOT_NAME);
|
|
33006
|
+
if (isEngine(direct) || isDir(direct))
|
|
33007
|
+
found.push(direct);
|
|
33008
|
+
try {
|
|
33009
|
+
for (const name of readdirSync(root)) {
|
|
33010
|
+
const child = join3(root, name, ENGINE_ROOT_NAME);
|
|
33011
|
+
if (isDir(child))
|
|
33012
|
+
found.push(child);
|
|
33013
|
+
}
|
|
33014
|
+
} catch {
|
|
33015
|
+
continue;
|
|
33016
|
+
}
|
|
33017
|
+
}
|
|
33018
|
+
return [...new Set(found)];
|
|
33019
|
+
}
|
|
33020
|
+
function validateRun(moduleUrl, args) {
|
|
33021
|
+
const script = join3(scriptsDir(moduleUrl), "validate-run.mjs");
|
|
33022
|
+
if (!existsSync3(script))
|
|
33023
|
+
throw new Error(`Missing validate-run script at ${script}`);
|
|
33024
|
+
const argv = ["--run", args.run];
|
|
33025
|
+
if (args.requirePack)
|
|
33026
|
+
argv.push("--require-pack");
|
|
33027
|
+
if (args.requireExport)
|
|
33028
|
+
argv.push("--require-export");
|
|
33029
|
+
if (args.exportDir)
|
|
33030
|
+
argv.push("--export", args.exportDir);
|
|
33031
|
+
if (args.requirePageTemplateId)
|
|
33032
|
+
argv.push("--require-page-template-id");
|
|
33033
|
+
if (args.json !== false)
|
|
33034
|
+
argv.push("--json");
|
|
33035
|
+
const result = spawnSync(process.execPath, [script, ...argv], { encoding: "utf8" });
|
|
33036
|
+
return {
|
|
33037
|
+
status: result.status ?? 1,
|
|
33038
|
+
stdout: result.stdout,
|
|
33039
|
+
stderr: result.stderr
|
|
33040
|
+
};
|
|
33041
|
+
}
|
|
33042
|
+
|
|
32584
33043
|
// src/v1-cli.ts
|
|
32585
33044
|
var CLI_MODULE_URL = import.meta.url;
|
|
32586
33045
|
function readCliVersion() {
|
|
32587
33046
|
try {
|
|
32588
|
-
const pkg = JSON.parse(
|
|
33047
|
+
const pkg = JSON.parse(readFileSync3(join4(cliPackageRoot(CLI_MODULE_URL), "package.json"), "utf8"));
|
|
32589
33048
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
|
|
32590
33049
|
} catch {
|
|
32591
33050
|
return "0.0.0";
|
|
32592
33051
|
}
|
|
32593
33052
|
}
|
|
32594
|
-
var
|
|
33053
|
+
var HEADLESS_RENDER_DISABLED = "PNG delivery is Studio Download (browser ZIP). CLI/MCP hosted PNG jobs are retired. Open the Run in Studio and use Download.";
|
|
33054
|
+
var credentialPath = join4(homedir3(), ".config", "easysociable", "credentials.json");
|
|
32595
33055
|
function resolveInstallSkillIds(options) {
|
|
32596
33056
|
return parseInstallSkills(typeof options.skills === "string" ? options.skills : void 0);
|
|
32597
33057
|
}
|
|
32598
33058
|
function readStoredCredentials() {
|
|
32599
33059
|
try {
|
|
32600
|
-
if (!
|
|
32601
|
-
const parsed = JSON.parse(
|
|
33060
|
+
if (!existsSync4(credentialPath)) return null;
|
|
33061
|
+
const parsed = JSON.parse(readFileSync3(credentialPath, "utf8"));
|
|
32602
33062
|
if (typeof parsed.apiKey !== "string" || typeof parsed.baseUrl !== "string") return null;
|
|
32603
33063
|
return { apiKey: parsed.apiKey, baseUrl: parsed.baseUrl };
|
|
32604
33064
|
} catch {
|
|
@@ -32606,7 +33066,7 @@ function readStoredCredentials() {
|
|
|
32606
33066
|
}
|
|
32607
33067
|
}
|
|
32608
33068
|
async function writeStoredCredentials(credentials) {
|
|
32609
|
-
await mkdir(
|
|
33069
|
+
await mkdir(join4(homedir3(), ".config", "easysociable"), { recursive: true, mode: 448 });
|
|
32610
33070
|
await writeFile(credentialPath, `${JSON.stringify(credentials, null, 2)}
|
|
32611
33071
|
`, { mode: 384 });
|
|
32612
33072
|
await chmod(credentialPath, 384);
|
|
@@ -32622,6 +33082,13 @@ function print(value, json2) {
|
|
|
32622
33082
|
else process.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
32623
33083
|
`);
|
|
32624
33084
|
}
|
|
33085
|
+
function commandWantsJson(command) {
|
|
33086
|
+
const local = command.opts();
|
|
33087
|
+
if (local.json === true)
|
|
33088
|
+
return true;
|
|
33089
|
+
const withGlobals = typeof command.optsWithGlobals === "function" ? command.optsWithGlobals() : {};
|
|
33090
|
+
return withGlobals.json === true;
|
|
33091
|
+
}
|
|
32625
33092
|
function clientFromEnv() {
|
|
32626
33093
|
const stored = readStoredCredentials();
|
|
32627
33094
|
const allowEnv = process.env.EASYSOCIABLE_ALLOW_ENV_CREDENTIALS === "true";
|
|
@@ -32638,8 +33105,16 @@ function clientFromEnv() {
|
|
|
32638
33105
|
function jsonOption(command) {
|
|
32639
33106
|
return command.option("--json", "Emit a JSON envelope");
|
|
32640
33107
|
}
|
|
33108
|
+
function defaultEngineRoot() {
|
|
33109
|
+
try {
|
|
33110
|
+
if (existsSync4("/workspace") && statSync2("/workspace").isDirectory())
|
|
33111
|
+
return "/workspace";
|
|
33112
|
+
} catch {
|
|
33113
|
+
}
|
|
33114
|
+
return process.cwd();
|
|
33115
|
+
}
|
|
32641
33116
|
function installHome(options) {
|
|
32642
|
-
return typeof options.home === "string" && options.home ? String(options.home) :
|
|
33117
|
+
return typeof options.home === "string" && options.home ? String(options.home) : homedir3();
|
|
32643
33118
|
}
|
|
32644
33119
|
function installSource(options) {
|
|
32645
33120
|
if (typeof options.source === "string" && options.source)
|
|
@@ -32650,17 +33125,17 @@ function installSource(options) {
|
|
|
32650
33125
|
}
|
|
32651
33126
|
function detectedHosts(home) {
|
|
32652
33127
|
const candidates = [
|
|
32653
|
-
{ host: "codex", dir:
|
|
32654
|
-
{ host: "claude", dir:
|
|
33128
|
+
{ host: "codex", dir: join4(home, ".codex") },
|
|
33129
|
+
{ host: "claude", dir: join4(home, ".claude") }
|
|
32655
33130
|
];
|
|
32656
|
-
return candidates.filter((item) =>
|
|
33131
|
+
return candidates.filter((item) => existsSync4(item.dir)).map((item) => ({ host: item.host, configPath: join4(item.dir, "mcp.json"), skillsPath: join4(item.dir, "skills") }));
|
|
32657
33132
|
}
|
|
32658
33133
|
async function planInstallation(options) {
|
|
32659
33134
|
const home = installHome(options);
|
|
32660
33135
|
const source = installSource(options);
|
|
32661
33136
|
const hosts = detectedHosts(home);
|
|
32662
33137
|
const skillNames = resolveInstallSkillIds(options);
|
|
32663
|
-
const missingSkills = skillNames.filter((name) => !
|
|
33138
|
+
const missingSkills = skillNames.filter((name) => !existsSync4(join4(source, name)));
|
|
32664
33139
|
return {
|
|
32665
33140
|
source,
|
|
32666
33141
|
home,
|
|
@@ -32669,7 +33144,7 @@ async function planInstallation(options) {
|
|
|
32669
33144
|
missingSkills,
|
|
32670
33145
|
changes: hosts.flatMap((host) => [
|
|
32671
33146
|
`merge ${host.configPath} with one easysociable MCP registration`,
|
|
32672
|
-
...skillNames.map((name) => `install ${
|
|
33147
|
+
...skillNames.map((name) => `install ${join4(host.skillsPath, name)}`)
|
|
32673
33148
|
])
|
|
32674
33149
|
};
|
|
32675
33150
|
}
|
|
@@ -32685,7 +33160,7 @@ async function applyInstallation(options) {
|
|
|
32685
33160
|
const backupSuffix = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
32686
33161
|
const backups = [];
|
|
32687
33162
|
for (const host of detectedHosts(String(plan.home))) {
|
|
32688
|
-
if (
|
|
33163
|
+
if (existsSync4(host.configPath)) {
|
|
32689
33164
|
const backupPath = `${host.configPath}.bak.${backupSuffix}`;
|
|
32690
33165
|
await copyFile(host.configPath, backupPath);
|
|
32691
33166
|
backups.push(backupPath);
|
|
@@ -32693,31 +33168,22 @@ async function applyInstallation(options) {
|
|
|
32693
33168
|
await installHostConfig({ host: host.host, dataDir: "", configPath: host.configPath });
|
|
32694
33169
|
await mkdir(host.skillsPath, { recursive: true, mode: 448 });
|
|
32695
33170
|
for (const skill of resolveInstallSkillIds(options))
|
|
32696
|
-
await cp(
|
|
33171
|
+
await cp(join4(String(plan.source), skill), join4(host.skillsPath, skill), { recursive: true, force: false, errorOnExist: false });
|
|
33172
|
+
}
|
|
33173
|
+
if (options.json !== true) {
|
|
33174
|
+
process.stdout.write(`Installed skills your Agent will use:
|
|
33175
|
+
easysociable-slideshow \u2014 turns a draft into slideshow pages you preview and download here
|
|
33176
|
+
easysociable-template \u2014 creates page templates
|
|
33177
|
+
`);
|
|
32697
33178
|
}
|
|
32698
33179
|
return { ...plan, applied: true, backups };
|
|
32699
33180
|
}
|
|
32700
|
-
async function readJsonArgument(value) {
|
|
32701
|
-
if (existsSync3(value))
|
|
32702
|
-
return JSON.parse(await readFile(value, "utf8"));
|
|
32703
|
-
return JSON.parse(value);
|
|
32704
|
-
}
|
|
32705
33181
|
function mimeTypeFor(fileName) {
|
|
32706
33182
|
const extension = fileName.toLowerCase().split(".").pop();
|
|
32707
33183
|
if (extension === "jpg" || extension === "jpeg") return "image/jpeg";
|
|
32708
33184
|
if (extension === "webp") return "image/webp";
|
|
32709
33185
|
return "image/png";
|
|
32710
33186
|
}
|
|
32711
|
-
function renderSlots(value) {
|
|
32712
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
32713
|
-
throw new Error("Render slots must be a JSON object");
|
|
32714
|
-
const entries = Object.entries(value);
|
|
32715
|
-
for (const [key, item] of entries) {
|
|
32716
|
-
if (!(typeof item === "string" || typeof item === "number" || item === null))
|
|
32717
|
-
throw new Error(`Render slot ${key} must be a string, number or null`);
|
|
32718
|
-
}
|
|
32719
|
-
return Object.fromEntries(entries);
|
|
32720
|
-
}
|
|
32721
33187
|
function withClient(action) {
|
|
32722
33188
|
return async (...args) => {
|
|
32723
33189
|
const command = args.at(-1);
|
|
@@ -32732,69 +33198,6 @@ function withClient(action) {
|
|
|
32732
33198
|
}
|
|
32733
33199
|
};
|
|
32734
33200
|
}
|
|
32735
|
-
async function exportManifest(client, jobId, output) {
|
|
32736
|
-
const job = await client.getRenderJob(jobId);
|
|
32737
|
-
if (job.status !== "completed" || !job.manifest)
|
|
32738
|
-
throw new Error(`Render job ${jobId} is not completed or has no manifest`);
|
|
32739
|
-
const staging = await mkdtemp(join3(tmpdir(), "easysociable-export-"));
|
|
32740
|
-
try {
|
|
32741
|
-
for (const [index, artifact] of job.manifest.artifacts.entries()) {
|
|
32742
|
-
const response = await fetch(artifact.url);
|
|
32743
|
-
if (!response.ok) throw new Error(`Artifact download failed (${response.status})`);
|
|
32744
|
-
const bytes = Buffer.from(await response.arrayBuffer());
|
|
32745
|
-
const checksum = createHash("sha256").update(bytes).digest("hex");
|
|
32746
|
-
if (checksum !== artifact.sha256) throw new Error(`Artifact checksum mismatch for page ${index + 1}`);
|
|
32747
|
-
await writeFile(join3(staging, `${String(index + 1).padStart(2, "0")}.png`), bytes);
|
|
32748
|
-
}
|
|
32749
|
-
await writeFile(join3(staging, "manifest.json"), `${JSON.stringify(job.manifest, null, 2)}
|
|
32750
|
-
`);
|
|
32751
|
-
await rm(output, { recursive: true, force: true });
|
|
32752
|
-
await rename2(staging, output);
|
|
32753
|
-
return { jobId, output, pages: job.manifest.artifacts.length, manifest: job.manifest };
|
|
32754
|
-
} catch (error52) {
|
|
32755
|
-
await rm(staging, { recursive: true, force: true });
|
|
32756
|
-
throw error52;
|
|
32757
|
-
}
|
|
32758
|
-
}
|
|
32759
|
-
async function exportSlideshowRun(client, runId, output) {
|
|
32760
|
-
const manifest = await client.getSlideshowRunManifest(runId);
|
|
32761
|
-
const staging = await mkdtemp(join3(tmpdir(), "easysociable-slideshow-export-"));
|
|
32762
|
-
try {
|
|
32763
|
-
const pages = [];
|
|
32764
|
-
for (const artifact of manifest.artifacts) {
|
|
32765
|
-
const bytes = Buffer.from(await client.downloadSlideshowArtifact(runId, artifact.pageIndex));
|
|
32766
|
-
const checksum = createHash("sha256").update(bytes).digest("hex");
|
|
32767
|
-
if (checksum !== artifact.sha256)
|
|
32768
|
-
throw new Error(`Artifact checksum mismatch for page ${artifact.pageIndex + 1}`);
|
|
32769
|
-
const role = artifact.role || `page${artifact.pageIndex}`;
|
|
32770
|
-
const fileName = `${String(artifact.pageIndex + 1).padStart(2, "0")}-${role}.png`;
|
|
32771
|
-
await writeFile(join3(staging, fileName), bytes);
|
|
32772
|
-
pages.push({
|
|
32773
|
-
pageIndex: artifact.pageIndex,
|
|
32774
|
-
role,
|
|
32775
|
-
file: fileName,
|
|
32776
|
-
bytes: bytes.length,
|
|
32777
|
-
sha256: checksum,
|
|
32778
|
-
width: artifact.width,
|
|
32779
|
-
height: artifact.height
|
|
32780
|
-
});
|
|
32781
|
-
}
|
|
32782
|
-
const localManifest = {
|
|
32783
|
-
schema: "slideshow-hosted-export.v1",
|
|
32784
|
-
runId: manifest.runId,
|
|
32785
|
-
deckJobId: manifest.deckJobId,
|
|
32786
|
-
pages
|
|
32787
|
-
};
|
|
32788
|
-
await writeFile(join3(staging, "manifest.json"), `${JSON.stringify(localManifest, null, 2)}
|
|
32789
|
-
`);
|
|
32790
|
-
await rm(output, { recursive: true, force: true });
|
|
32791
|
-
await rename2(staging, output);
|
|
32792
|
-
return { runId, output, pages: pages.length, manifest: localManifest };
|
|
32793
|
-
} catch (error52) {
|
|
32794
|
-
await rm(staging, { recursive: true, force: true });
|
|
32795
|
-
throw error52;
|
|
32796
|
-
}
|
|
32797
|
-
}
|
|
32798
33201
|
function addCrudCommands(parent, resource, routes) {
|
|
32799
33202
|
jsonOption(parent.command("list").description(`List ${resource}`)).action(withClient(async (client) => client.requestJson("GET", routes.list)));
|
|
32800
33203
|
jsonOption(parent.command("get").requiredOption("--id <id>").description(`Get ${resource}`)).action(withClient(async (client, opts) => client.requestJson("GET", routes.get.replace(":id", String(opts.id)))));
|
|
@@ -32821,6 +33224,80 @@ function buildV1Cli() {
|
|
|
32821
33224
|
const result = opts.yes === true ? await applyInstallation(opts) : { ...plan, applied: false, next: "Review changes and re-run with --yes" };
|
|
32822
33225
|
print(result, Boolean(opts.json));
|
|
32823
33226
|
});
|
|
33227
|
+
const engine = program.command("engine").description("Create and operate a local Content Engine + workbench");
|
|
33228
|
+
jsonOption(engine.command("detect").description("Find Content Engine folders under search roots")).action((...args) => {
|
|
33229
|
+
const command = args.at(-1);
|
|
33230
|
+
print({ action: "detect", engines: detectEngines() }, commandWantsJson(command));
|
|
33231
|
+
});
|
|
33232
|
+
jsonOption(engine.command("init").description("Scaffold Content Engine starter files (never overwrites existing)").option("--root <path>", "Parent directory or Content Engine path", defaultEngineRoot()).option("--yes", "Write missing starter files").option("--serve", "Also start the workbench server").option("--no-open", "Do not open a browser when starting the workbench")).action(async (...args) => {
|
|
33233
|
+
const command = args.at(-1);
|
|
33234
|
+
const opts = command.opts();
|
|
33235
|
+
const result = await initEngine(String(opts.root), CLI_MODULE_URL, {
|
|
33236
|
+
yes: opts.yes === true,
|
|
33237
|
+
noOpen: opts.noOpen === true,
|
|
33238
|
+
serve: opts.serve === true
|
|
33239
|
+
});
|
|
33240
|
+
print(result, commandWantsJson(command));
|
|
33241
|
+
if (opts.yes === true && (result.valid === false || result.code)) {
|
|
33242
|
+
const errors = result.errors;
|
|
33243
|
+
throw new Error(errors?.[0] ?? result.code ?? "engine init failed");
|
|
33244
|
+
}
|
|
33245
|
+
});
|
|
33246
|
+
jsonOption(engine.command("validate").description("Validate engine starter completeness or a run folder").option("--root <path>", "Parent directory or Content Engine path").option("--run <path>", "Run directory to validate").option("--require-pack", "Require pack-*.json on the run").option("--require-export", "Require export directory").option("--export <path>", "Export directory for --require-export").option("--require-knowledge", "Require Identity (Role / What I build / POV) + boundaries; needs count only if needs/ exists")).action((...args) => {
|
|
33247
|
+
const command = args.at(-1);
|
|
33248
|
+
const opts = command.opts();
|
|
33249
|
+
if (opts.run) {
|
|
33250
|
+
if (opts.requireKnowledge === true) {
|
|
33251
|
+
const engineRoot = resolve2(String(opts.run), "..", "..");
|
|
33252
|
+
const knowledge = checkKnowledge(engineRoot);
|
|
33253
|
+
if (!knowledge.valid) {
|
|
33254
|
+
print({ valid: false, missing: knowledge.missing, knowledge, action: "validated" }, commandWantsJson(command));
|
|
33255
|
+
throw new Error(`Knowledge gate failed: ${knowledge.missing.join(", ")}`);
|
|
33256
|
+
}
|
|
33257
|
+
}
|
|
33258
|
+
const result = validateRun(CLI_MODULE_URL, {
|
|
33259
|
+
run: String(opts.run),
|
|
33260
|
+
requirePack: opts.requirePack === true,
|
|
33261
|
+
requireExport: opts.requireExport === true,
|
|
33262
|
+
exportDir: opts.export ? String(opts.export) : void 0,
|
|
33263
|
+
json: true
|
|
33264
|
+
});
|
|
33265
|
+
if (result.stdout)
|
|
33266
|
+
process.stdout.write(result.stdout.endsWith("\n") ? result.stdout : `${result.stdout}
|
|
33267
|
+
`);
|
|
33268
|
+
if (result.status !== 0)
|
|
33269
|
+
throw new Error(result.stderr.trim() || "engine validate --run failed");
|
|
33270
|
+
return;
|
|
33271
|
+
}
|
|
33272
|
+
if (!opts.root)
|
|
33273
|
+
throw new Error("Pass --root <path> or --run <path>.");
|
|
33274
|
+
const report = validateEngine(String(opts.root), CLI_MODULE_URL, {
|
|
33275
|
+
strict: true,
|
|
33276
|
+
requireKnowledge: opts.requireKnowledge === true
|
|
33277
|
+
});
|
|
33278
|
+
print({ ...report, action: "validated" }, commandWantsJson(command));
|
|
33279
|
+
if (!report.valid)
|
|
33280
|
+
throw new Error(report.errors[0] ?? "engine validate failed");
|
|
33281
|
+
});
|
|
33282
|
+
jsonOption(engine.command("serve").description("Sync workbench runtime from CLI, rebuild, start on :8765").option("--engine <path>", "Content Engine path or parent", defaultEngineRoot()).option("--no-open", "Do not open a browser")).action(async (...args) => {
|
|
33283
|
+
const command = args.at(-1);
|
|
33284
|
+
const opts = command.opts();
|
|
33285
|
+
const enginePath = resolveEngine(String(opts.engine));
|
|
33286
|
+
const started = await startWorkbench(enginePath, CLI_MODULE_URL, { noOpen: opts.noOpen === true });
|
|
33287
|
+
print({ action: "serve", engine: enginePath, ...started }, commandWantsJson(command));
|
|
33288
|
+
if (!started.ok)
|
|
33289
|
+
throw new Error("message" in started ? String(started.message) : "engine serve failed");
|
|
33290
|
+
});
|
|
33291
|
+
jsonOption(engine.command("build").description("Sync workbench runtime from CLI, then rebuild workbench/index.html").option("--engine <path>", "Content Engine path or parent", defaultEngineRoot())).action((...args) => {
|
|
33292
|
+
const command = args.at(-1);
|
|
33293
|
+
const opts = command.opts();
|
|
33294
|
+
const enginePath = resolveEngine(String(opts.engine));
|
|
33295
|
+
const workbench = ensureWorkbench(enginePath, CLI_MODULE_URL, { update: true });
|
|
33296
|
+
const built = buildWorkbench(enginePath);
|
|
33297
|
+
print({ action: "build", engine: enginePath, workbench, ...built }, commandWantsJson(command));
|
|
33298
|
+
if (!built.ok)
|
|
33299
|
+
throw new Error(built.message);
|
|
33300
|
+
});
|
|
32824
33301
|
const auth = program.command("auth").description("Manage the shared EasySociable credential");
|
|
32825
33302
|
jsonOption(auth.command("status").description("Show authentication status")).action(async (...args) => {
|
|
32826
33303
|
const command = args.at(-1);
|
|
@@ -32860,6 +33337,13 @@ function buildV1Cli() {
|
|
|
32860
33337
|
jsonOption(templates.command("archive").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.archiveDraft(String(opts.id))));
|
|
32861
33338
|
jsonOption(templates.command("restore").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.restoreDraft(String(opts.id))));
|
|
32862
33339
|
jsonOption(templates.command("delete").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.deleteDraft(String(opts.id))));
|
|
33340
|
+
const families = templates.command("families").description("Layout Family (multi-platform template identity)");
|
|
33341
|
+
jsonOption(families.command("get").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.getTemplateFamily(String(opts.id))));
|
|
33342
|
+
jsonOption(families.command("derive").requiredOption("--id <id>").option("--presets <list>", "Comma-separated presets e.g. 4:5,9:16")).action(withClient(async (client, opts) => {
|
|
33343
|
+
const presets = typeof opts.presets === "string" && opts.presets.trim() ? String(opts.presets).split(",").map((item) => item.trim()).filter(Boolean) : void 0;
|
|
33344
|
+
return client.deriveTemplateFamily(String(opts.id), { presets });
|
|
33345
|
+
}));
|
|
33346
|
+
jsonOption(families.command("migrate-legacy").description("Wrap pages missing familyId into single-variant families")).action(withClient(async (client) => client.migrateLegacyTemplateFamilies()));
|
|
32863
33347
|
const icons = program.command("icons").description("Search the internal safe icon catalog");
|
|
32864
33348
|
jsonOption(icons.command("search").requiredOption("--query <query>")).action(withClient(async (client, opts) => client.searchIcons({ query: String(opts.query) })));
|
|
32865
33349
|
jsonOption(icons.command("get").requiredOption("--id <id>").requiredOption("--idempotency-key <key>")).action(withClient(async (client, opts) => client.getIcon({ iconId: String(opts.id), idempotencyKey: String(opts.idempotencyKey) })));
|
|
@@ -32877,8 +33361,12 @@ function buildV1Cli() {
|
|
|
32877
33361
|
jsonOption(slideshows.command("archive").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.archiveSlideshowRun(String(opts.id))));
|
|
32878
33362
|
jsonOption(slideshows.command("restore").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.restoreSlideshowRun(String(opts.id))));
|
|
32879
33363
|
jsonOption(slideshows.command("delete").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.trashSlideshowRun(String(opts.id))));
|
|
32880
|
-
jsonOption(slideshows.command("render").requiredOption("--id <id>").requiredOption("--idempotency-key <key>")).action(withClient(async (
|
|
32881
|
-
|
|
33364
|
+
jsonOption(slideshows.command("render").description("Retired: PNG packs come from Studio Download").requiredOption("--id <id>").requiredOption("--idempotency-key <key>")).action(withClient(async () => {
|
|
33365
|
+
throw new Error(HEADLESS_RENDER_DISABLED);
|
|
33366
|
+
}));
|
|
33367
|
+
jsonOption(slideshows.command("export").description("Retired: PNG packs come from Studio Download").requiredOption("--id <id>").requiredOption("--output <path>")).action(withClient(async () => {
|
|
33368
|
+
throw new Error(HEADLESS_RENDER_DISABLED);
|
|
33369
|
+
}));
|
|
32882
33370
|
const renders = program.command("renders").description("Inspect final render jobs");
|
|
32883
33371
|
jsonOption(renders.command("create-asset").requiredOption("--file <path>").requiredOption("--idempotency-key <key>")).action(withClient(async (client, opts) => {
|
|
32884
33372
|
const fileName = String(opts.file);
|
|
@@ -32893,16 +33381,15 @@ function buildV1Cli() {
|
|
|
32893
33381
|
idempotencyKey: String(opts.idempotencyKey)
|
|
32894
33382
|
});
|
|
32895
33383
|
}));
|
|
32896
|
-
jsonOption(renders.command("create").requiredOption("--template-id <id>").requiredOption("--slots <json-or-file>").option("--format <format>", "Final output format", "png").requiredOption("--idempotency-key <key>")).action(withClient(async (
|
|
32897
|
-
|
|
32898
|
-
|
|
32899
|
-
outputFormats: [String(opts.format)],
|
|
32900
|
-
idempotencyKey: String(opts.idempotencyKey)
|
|
32901
|
-
})));
|
|
33384
|
+
jsonOption(renders.command("create").description("Retired: PNG packs come from Studio Download").requiredOption("--template-id <id>").requiredOption("--slots <json-or-file>").option("--format <format>", "Final output format", "png").requiredOption("--idempotency-key <key>")).action(withClient(async () => {
|
|
33385
|
+
throw new Error(HEADLESS_RENDER_DISABLED);
|
|
33386
|
+
}));
|
|
32902
33387
|
jsonOption(renders.command("get").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.getRenderJob(String(opts.id))));
|
|
32903
33388
|
jsonOption(renders.command("manifest").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.getRenderManifest(String(opts.id))));
|
|
32904
33389
|
jsonOption(renders.command("wait").requiredOption("--id <id>")).action(withClient(async (client, opts) => client.pollRenderJob(String(opts.id))));
|
|
32905
|
-
jsonOption(renders.command("export").requiredOption("--id <id>").requiredOption("--output <path>")).action(withClient(async (
|
|
33390
|
+
jsonOption(renders.command("export").description("Retired: PNG packs come from Studio Download").requiredOption("--id <id>").requiredOption("--output <path>")).action(withClient(async () => {
|
|
33391
|
+
throw new Error(HEADLESS_RENDER_DISABLED);
|
|
33392
|
+
}));
|
|
32906
33393
|
const mcp = program.command("mcp").description("Install and run the unified EasySociable MCP server");
|
|
32907
33394
|
jsonOption(mcp.command("install").requiredOption("--host <host>", "codex, claude, hermes, or openclaw").option("--config-path <path>")).action((...args) => {
|
|
32908
33395
|
const command = args.at(-1);
|