@lssm/lib.content-gen 1.42.7 → 1.42.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @lssm/lib.content-gen
2
2
 
3
- Website: https://contractspec.lssm.tech/
3
+ Website: https://contractspec.io/
4
4
 
5
5
 
6
6
  Composable generators that turn ContractSpec briefs, specs, and telemetry into publish-ready marketing artifacts: blogs, landing pages, SEO metadata, email drips, and social posts.
@@ -47,7 +47,7 @@ var SocialPostGenerator = class {
47
47
  channel: "twitter",
48
48
  body: `${brief.solutions[0]} in <60s. ${brief.solutions[1] ?? ""}`.trim(),
49
49
  hashtags: hashtags.slice(0, 3),
50
- cta: "→ contractspec.lssm.tech/sandbox"
50
+ cta: "→ contractspec.io/sandbox"
51
51
  },
52
52
  {
53
53
  channel: "threads",
@@ -1 +1 @@
1
- {"version":3,"file":"social.js","names":[],"sources":["../../src/generators/social.ts"],"sourcesContent":["import type { ContentBrief, GeneratorOptions, SocialPost } from '../types';\nimport type { LLMProvider } from '@lssm/lib.contracts/integrations/providers/llm';\n\nexport class SocialPostGenerator {\n private readonly llm?: LLMProvider;\n private readonly model?: string;\n\n constructor(options?: GeneratorOptions) {\n this.llm = options?.llm;\n this.model = options?.model;\n }\n\n async generate(brief: ContentBrief): Promise<SocialPost[]> {\n if (this.llm) {\n const posts = await this.generateWithLlm(brief);\n if (posts.length) return posts;\n }\n return this.generateFallback(brief);\n }\n\n private async generateWithLlm(brief: ContentBrief): Promise<SocialPost[]> {\n if (!this.llm) return [];\n const response = await this.llm.chat(\n [\n {\n role: 'system',\n content: [\n {\n type: 'text',\n text: 'Create JSON array of social posts for twitter/linkedin/threads with body, hashtags, cta.',\n },\n ],\n },\n {\n role: 'user',\n content: [{ type: 'text', text: JSON.stringify(brief) }],\n },\n ],\n { responseFormat: 'json', model: this.model }\n );\n const part = response.message.content.find((chunk) => 'text' in chunk);\n if (!part || !('text' in part)) return [];\n return JSON.parse(part.text) as SocialPost[];\n }\n\n private generateFallback(brief: ContentBrief): SocialPost[] {\n const hashtags = this.buildHashtags(brief);\n return [\n {\n channel: 'linkedin',\n body: `${brief.title}: ${brief.summary}\\n${brief.problems[0]} → ${brief.solutions[0]}`,\n hashtags,\n cta: brief.callToAction ?? 'Book a 15-min run-through',\n },\n {\n channel: 'twitter',\n body: `${brief.solutions[0]} in <60s. ${brief.solutions[1] ?? ''}`.trim(),\n hashtags: hashtags.slice(0, 3),\n cta: '→ contractspec.lssm.tech/sandbox',\n },\n {\n channel: 'threads',\n body: `Ops + policy can move fast. ${brief.title} automates guardrails so teams ship daily.`,\n hashtags: hashtags.slice(1, 4),\n },\n ];\n }\n\n private buildHashtags(brief: ContentBrief): string[] {\n const base = [\n brief.audience.industry\n ? `#${camel(brief.audience.industry)}`\n : '#operations',\n '#automation',\n '#aiops',\n '#compliance',\n ];\n return [...new Set(base.map((tag) => tag.replace(/\\s+/g, '')))].slice(0, 5);\n }\n}\n\nfunction camel(text: string) {\n return text\n .split(/\\s|-/)\n .filter(Boolean)\n .map((word) => word[0]?.toUpperCase() + word.slice(1))\n .join('');\n}\n"],"mappings":";AAGA,IAAa,sBAAb,MAAiC;CAC/B,AAAiB;CACjB,AAAiB;CAEjB,YAAY,SAA4B;AACtC,OAAK,MAAM,SAAS;AACpB,OAAK,QAAQ,SAAS;;CAGxB,MAAM,SAAS,OAA4C;AACzD,MAAI,KAAK,KAAK;GACZ,MAAM,QAAQ,MAAM,KAAK,gBAAgB,MAAM;AAC/C,OAAI,MAAM,OAAQ,QAAO;;AAE3B,SAAO,KAAK,iBAAiB,MAAM;;CAGrC,MAAc,gBAAgB,OAA4C;AACxE,MAAI,CAAC,KAAK,IAAK,QAAO,EAAE;EAmBxB,MAAM,QAlBW,MAAM,KAAK,IAAI,KAC9B,CACE;GACE,MAAM;GACN,SAAS,CACP;IACE,MAAM;IACN,MAAM;IACP,CACF;GACF,EACD;GACE,MAAM;GACN,SAAS,CAAC;IAAE,MAAM;IAAQ,MAAM,KAAK,UAAU,MAAM;IAAE,CAAC;GACzD,CACF,EACD;GAAE,gBAAgB;GAAQ,OAAO,KAAK;GAAO,CAC9C,EACqB,QAAQ,QAAQ,MAAM,UAAU,UAAU,MAAM;AACtE,MAAI,CAAC,QAAQ,EAAE,UAAU,MAAO,QAAO,EAAE;AACzC,SAAO,KAAK,MAAM,KAAK,KAAK;;CAG9B,AAAQ,iBAAiB,OAAmC;EAC1D,MAAM,WAAW,KAAK,cAAc,MAAM;AAC1C,SAAO;GACL;IACE,SAAS;IACT,MAAM,GAAG,MAAM,MAAM,IAAI,MAAM,QAAQ,IAAI,MAAM,SAAS,GAAG,KAAK,MAAM,UAAU;IAClF;IACA,KAAK,MAAM,gBAAgB;IAC5B;GACD;IACE,SAAS;IACT,MAAM,GAAG,MAAM,UAAU,GAAG,YAAY,MAAM,UAAU,MAAM,KAAK,MAAM;IACzE,UAAU,SAAS,MAAM,GAAG,EAAE;IAC9B,KAAK;IACN;GACD;IACE,SAAS;IACT,MAAM,+BAA+B,MAAM,MAAM;IACjD,UAAU,SAAS,MAAM,GAAG,EAAE;IAC/B;GACF;;CAGH,AAAQ,cAAc,OAA+B;EACnD,MAAM,OAAO;GACX,MAAM,SAAS,WACX,IAAI,MAAM,MAAM,SAAS,SAAS,KAClC;GACJ;GACA;GACA;GACD;AACD,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,QAAQ,IAAI,QAAQ,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE;;;AAI/E,SAAS,MAAM,MAAc;AAC3B,QAAO,KACJ,MAAM,OAAO,CACb,OAAO,QAAQ,CACf,KAAK,SAAS,KAAK,IAAI,aAAa,GAAG,KAAK,MAAM,EAAE,CAAC,CACrD,KAAK,GAAG"}
1
+ {"version":3,"file":"social.js","names":[],"sources":["../../src/generators/social.ts"],"sourcesContent":["import type { ContentBrief, GeneratorOptions, SocialPost } from '../types';\nimport type { LLMProvider } from '@lssm/lib.contracts/integrations/providers/llm';\n\nexport class SocialPostGenerator {\n private readonly llm?: LLMProvider;\n private readonly model?: string;\n\n constructor(options?: GeneratorOptions) {\n this.llm = options?.llm;\n this.model = options?.model;\n }\n\n async generate(brief: ContentBrief): Promise<SocialPost[]> {\n if (this.llm) {\n const posts = await this.generateWithLlm(brief);\n if (posts.length) return posts;\n }\n return this.generateFallback(brief);\n }\n\n private async generateWithLlm(brief: ContentBrief): Promise<SocialPost[]> {\n if (!this.llm) return [];\n const response = await this.llm.chat(\n [\n {\n role: 'system',\n content: [\n {\n type: 'text',\n text: 'Create JSON array of social posts for twitter/linkedin/threads with body, hashtags, cta.',\n },\n ],\n },\n {\n role: 'user',\n content: [{ type: 'text', text: JSON.stringify(brief) }],\n },\n ],\n { responseFormat: 'json', model: this.model }\n );\n const part = response.message.content.find((chunk) => 'text' in chunk);\n if (!part || !('text' in part)) return [];\n return JSON.parse(part.text) as SocialPost[];\n }\n\n private generateFallback(brief: ContentBrief): SocialPost[] {\n const hashtags = this.buildHashtags(brief);\n return [\n {\n channel: 'linkedin',\n body: `${brief.title}: ${brief.summary}\\n${brief.problems[0]} → ${brief.solutions[0]}`,\n hashtags,\n cta: brief.callToAction ?? 'Book a 15-min run-through',\n },\n {\n channel: 'twitter',\n body: `${brief.solutions[0]} in <60s. ${brief.solutions[1] ?? ''}`.trim(),\n hashtags: hashtags.slice(0, 3),\n cta: '→ contractspec.io/sandbox',\n },\n {\n channel: 'threads',\n body: `Ops + policy can move fast. ${brief.title} automates guardrails so teams ship daily.`,\n hashtags: hashtags.slice(1, 4),\n },\n ];\n }\n\n private buildHashtags(brief: ContentBrief): string[] {\n const base = [\n brief.audience.industry\n ? `#${camel(brief.audience.industry)}`\n : '#operations',\n '#automation',\n '#aiops',\n '#compliance',\n ];\n return [...new Set(base.map((tag) => tag.replace(/\\s+/g, '')))].slice(0, 5);\n }\n}\n\nfunction camel(text: string) {\n return text\n .split(/\\s|-/)\n .filter(Boolean)\n .map((word) => word[0]?.toUpperCase() + word.slice(1))\n .join('');\n}\n"],"mappings":";AAGA,IAAa,sBAAb,MAAiC;CAC/B,AAAiB;CACjB,AAAiB;CAEjB,YAAY,SAA4B;AACtC,OAAK,MAAM,SAAS;AACpB,OAAK,QAAQ,SAAS;;CAGxB,MAAM,SAAS,OAA4C;AACzD,MAAI,KAAK,KAAK;GACZ,MAAM,QAAQ,MAAM,KAAK,gBAAgB,MAAM;AAC/C,OAAI,MAAM,OAAQ,QAAO;;AAE3B,SAAO,KAAK,iBAAiB,MAAM;;CAGrC,MAAc,gBAAgB,OAA4C;AACxE,MAAI,CAAC,KAAK,IAAK,QAAO,EAAE;EAmBxB,MAAM,QAlBW,MAAM,KAAK,IAAI,KAC9B,CACE;GACE,MAAM;GACN,SAAS,CACP;IACE,MAAM;IACN,MAAM;IACP,CACF;GACF,EACD;GACE,MAAM;GACN,SAAS,CAAC;IAAE,MAAM;IAAQ,MAAM,KAAK,UAAU,MAAM;IAAE,CAAC;GACzD,CACF,EACD;GAAE,gBAAgB;GAAQ,OAAO,KAAK;GAAO,CAC9C,EACqB,QAAQ,QAAQ,MAAM,UAAU,UAAU,MAAM;AACtE,MAAI,CAAC,QAAQ,EAAE,UAAU,MAAO,QAAO,EAAE;AACzC,SAAO,KAAK,MAAM,KAAK,KAAK;;CAG9B,AAAQ,iBAAiB,OAAmC;EAC1D,MAAM,WAAW,KAAK,cAAc,MAAM;AAC1C,SAAO;GACL;IACE,SAAS;IACT,MAAM,GAAG,MAAM,MAAM,IAAI,MAAM,QAAQ,IAAI,MAAM,SAAS,GAAG,KAAK,MAAM,UAAU;IAClF;IACA,KAAK,MAAM,gBAAgB;IAC5B;GACD;IACE,SAAS;IACT,MAAM,GAAG,MAAM,UAAU,GAAG,YAAY,MAAM,UAAU,MAAM,KAAK,MAAM;IACzE,UAAU,SAAS,MAAM,GAAG,EAAE;IAC9B,KAAK;IACN;GACD;IACE,SAAS;IACT,MAAM,+BAA+B,MAAM,MAAM;IACjD,UAAU,SAAS,MAAM,GAAG,EAAE;IAC/B;GACF;;CAGH,AAAQ,cAAc,OAA+B;EACnD,MAAM,OAAO;GACX,MAAM,SAAS,WACX,IAAI,MAAM,MAAM,SAAS,SAAS,KAClC;GACJ;GACA;GACA;GACD;AACD,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,QAAQ,IAAI,QAAQ,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE;;;AAI/E,SAAS,MAAM,MAAc;AAC3B,QAAO,KACJ,MAAM,OAAO,CACb,OAAO,QAAQ,CACf,KAAK,SAAS,KAAK,IAAI,aAAa,GAAG,KAAK,MAAM,EAAE,CAAC,CACrD,KAAK,GAAG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/lib.content-gen",
3
- "version": "1.42.7",
3
+ "version": "1.42.9",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -23,11 +23,11 @@
23
23
  "test": "bun run"
24
24
  },
25
25
  "dependencies": {
26
- "@lssm/lib.contracts": "1.42.7"
26
+ "@lssm/lib.contracts": "1.42.9"
27
27
  },
28
28
  "devDependencies": {
29
- "@lssm/tool.tsdown": "1.42.7",
30
- "@lssm/tool.typescript": "1.42.7",
29
+ "@lssm/tool.tsdown": "1.42.9",
30
+ "@lssm/tool.typescript": "1.42.9",
31
31
  "tsdown": "^0.18.3",
32
32
  "typescript": "^5.9.3"
33
33
  },