create-agntcms-app 0.2.1
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 +39 -0
- package/dist/index.mjs +297 -0
- package/dist/template/.claude/settings.json +6 -0
- package/dist/template/.claude/skills/.gitkeep +0 -0
- package/dist/template/.claude-plugin/channel/server.mjs +254 -0
- package/dist/template/.claude-plugin/channel/server.ts +369 -0
- package/dist/template/.claude-plugin/plugin.json +17 -0
- package/dist/template/.mcp.json +8 -0
- package/dist/template/BRAND.md +49 -0
- package/dist/template/CLAUDE.md +157 -0
- package/dist/template/agntcms/config.ts +49 -0
- package/dist/template/agntcms/sections/ArticleBody/component.tsx +32 -0
- package/dist/template/agntcms/sections/ArticleBody/index.ts +10 -0
- package/dist/template/agntcms/sections/ArticleBody/schema.ts +5 -0
- package/dist/template/agntcms/sections/ArticleHero/component.tsx +87 -0
- package/dist/template/agntcms/sections/ArticleHero/index.ts +10 -0
- package/dist/template/agntcms/sections/ArticleHero/schema.ts +12 -0
- package/dist/template/agntcms/sections/Banner/component.tsx +83 -0
- package/dist/template/agntcms/sections/Banner/index.ts +10 -0
- package/dist/template/agntcms/sections/Banner/schema.ts +9 -0
- package/dist/template/agntcms/sections/BlogIndex/component.tsx +173 -0
- package/dist/template/agntcms/sections/BlogIndex/index.ts +10 -0
- package/dist/template/agntcms/sections/BlogIndex/schema.ts +33 -0
- package/dist/template/agntcms/sections/BlogIndexHeader/component.tsx +44 -0
- package/dist/template/agntcms/sections/BlogIndexHeader/index.ts +10 -0
- package/dist/template/agntcms/sections/BlogIndexHeader/schema.ts +8 -0
- package/dist/template/agntcms/sections/BlogPostBody/component.tsx +50 -0
- package/dist/template/agntcms/sections/BlogPostBody/index.ts +10 -0
- package/dist/template/agntcms/sections/BlogPostBody/schema.ts +10 -0
- package/dist/template/agntcms/sections/BlogPostHero/component.tsx +88 -0
- package/dist/template/agntcms/sections/BlogPostHero/index.ts +10 -0
- package/dist/template/agntcms/sections/BlogPostHero/schema.ts +35 -0
- package/dist/template/agntcms/sections/CaseStudies/component.tsx +92 -0
- package/dist/template/agntcms/sections/CaseStudies/index.ts +10 -0
- package/dist/template/agntcms/sections/CaseStudies/schema.ts +17 -0
- package/dist/template/agntcms/sections/ContactForm/component.tsx +119 -0
- package/dist/template/agntcms/sections/ContactForm/index.ts +10 -0
- package/dist/template/agntcms/sections/ContactForm/schema.ts +15 -0
- package/dist/template/agntcms/sections/DocsArticle/component.tsx +266 -0
- package/dist/template/agntcms/sections/DocsArticle/index.ts +10 -0
- package/dist/template/agntcms/sections/DocsArticle/schema.ts +33 -0
- package/dist/template/agntcms/sections/FAQ/component.tsx +57 -0
- package/dist/template/agntcms/sections/FAQ/index.ts +10 -0
- package/dist/template/agntcms/sections/FAQ/schema.ts +11 -0
- package/dist/template/agntcms/sections/FeatureGrid/component.tsx +117 -0
- package/dist/template/agntcms/sections/FeatureGrid/index.ts +10 -0
- package/dist/template/agntcms/sections/FeatureGrid/schema.ts +21 -0
- package/dist/template/agntcms/sections/FeaturedArticles/component.tsx +99 -0
- package/dist/template/agntcms/sections/FeaturedArticles/index.ts +10 -0
- package/dist/template/agntcms/sections/FeaturedArticles/schema.ts +17 -0
- package/dist/template/agntcms/sections/GettingStarted/component.tsx +116 -0
- package/dist/template/agntcms/sections/GettingStarted/index.ts +10 -0
- package/dist/template/agntcms/sections/GettingStarted/schema.ts +11 -0
- package/dist/template/agntcms/sections/Hero/component.tsx +148 -0
- package/dist/template/agntcms/sections/Hero/index.ts +10 -0
- package/dist/template/agntcms/sections/Hero/schema.ts +16 -0
- package/dist/template/agntcms/sections/HowItWorks/component.tsx +57 -0
- package/dist/template/agntcms/sections/HowItWorks/index.ts +10 -0
- package/dist/template/agntcms/sections/HowItWorks/schema.ts +11 -0
- package/dist/template/agntcms/sections/ImageText/component.tsx +110 -0
- package/dist/template/agntcms/sections/ImageText/index.ts +10 -0
- package/dist/template/agntcms/sections/ImageText/schema.ts +14 -0
- package/dist/template/agntcms/sections/LogoStrip/component.tsx +37 -0
- package/dist/template/agntcms/sections/LogoStrip/index.ts +10 -0
- package/dist/template/agntcms/sections/LogoStrip/schema.ts +6 -0
- package/dist/template/agntcms/sections/Newsletter/component.tsx +48 -0
- package/dist/template/agntcms/sections/Newsletter/index.ts +10 -0
- package/dist/template/agntcms/sections/Newsletter/schema.ts +8 -0
- package/dist/template/agntcms/sections/OpenSource/component.tsx +99 -0
- package/dist/template/agntcms/sections/OpenSource/index.ts +10 -0
- package/dist/template/agntcms/sections/OpenSource/schema.ts +13 -0
- package/dist/template/agntcms/sections/PainAnswer/component.tsx +81 -0
- package/dist/template/agntcms/sections/PainAnswer/index.ts +10 -0
- package/dist/template/agntcms/sections/PainAnswer/schema.ts +15 -0
- package/dist/template/agntcms/sections/PricingPlans/component.tsx +100 -0
- package/dist/template/agntcms/sections/PricingPlans/index.ts +10 -0
- package/dist/template/agntcms/sections/PricingPlans/schema.ts +13 -0
- package/dist/template/agntcms/sections/Problem/component.tsx +49 -0
- package/dist/template/agntcms/sections/Problem/index.ts +10 -0
- package/dist/template/agntcms/sections/Problem/schema.ts +12 -0
- package/dist/template/agntcms/sections/SiteFooter/component.tsx +88 -0
- package/dist/template/agntcms/sections/SiteFooter/index.ts +10 -0
- package/dist/template/agntcms/sections/SiteFooter/schema.ts +13 -0
- package/dist/template/agntcms/sections/SiteHeader/component.tsx +99 -0
- package/dist/template/agntcms/sections/SiteHeader/index.ts +10 -0
- package/dist/template/agntcms/sections/SiteHeader/schema.ts +14 -0
- package/dist/template/agntcms/sections/SiteMeta/component.tsx +26 -0
- package/dist/template/agntcms/sections/SiteMeta/index.ts +13 -0
- package/dist/template/agntcms/sections/SiteMeta/schema.ts +18 -0
- package/dist/template/agntcms/sections/TabbedFeatures/component.tsx +120 -0
- package/dist/template/agntcms/sections/TabbedFeatures/index.ts +10 -0
- package/dist/template/agntcms/sections/TabbedFeatures/schema.ts +13 -0
- package/dist/template/agntcms/sections/TeamGrid/component.tsx +77 -0
- package/dist/template/agntcms/sections/TeamGrid/index.ts +10 -0
- package/dist/template/agntcms/sections/TeamGrid/schema.ts +14 -0
- package/dist/template/agntcms/sections/Testimonials/component.tsx +76 -0
- package/dist/template/agntcms/sections/Testimonials/index.ts +10 -0
- package/dist/template/agntcms/sections/Testimonials/schema.ts +12 -0
- package/dist/template/agntcms/sections/WhatIsBuilt/component.tsx +86 -0
- package/dist/template/agntcms/sections/WhatIsBuilt/index.ts +10 -0
- package/dist/template/agntcms/sections/WhatIsBuilt/schema.ts +20 -0
- package/dist/template/agntcms/site-meta.ts +81 -0
- package/dist/template/app/[[...slug]]/page.tsx +123 -0
- package/dist/template/app/admin/AdminPageClient.tsx +77 -0
- package/dist/template/app/admin/AdminPageDynamic.tsx +24 -0
- package/dist/template/app/admin/page.tsx +14 -0
- package/dist/template/app/api/agntcms/_shared.ts +80 -0
- package/dist/template/app/api/agntcms/assets/route.ts +11 -0
- package/dist/template/app/api/agntcms/assets/upload/route.ts +11 -0
- package/dist/template/app/api/agntcms/draft/discard/route.ts +12 -0
- package/dist/template/app/api/agntcms/draft/list/route.ts +11 -0
- package/dist/template/app/api/agntcms/draft/publish/route.ts +11 -0
- package/dist/template/app/api/agntcms/draft/reorder/route.ts +10 -0
- package/dist/template/app/api/agntcms/draft/save/route.ts +11 -0
- package/dist/template/app/api/agntcms/events/route.ts +12 -0
- package/dist/template/app/api/agntcms/forms/delete/route.ts +17 -0
- package/dist/template/app/api/agntcms/forms/list/route.ts +24 -0
- package/dist/template/app/api/agntcms/forms/read/route.ts +23 -0
- package/dist/template/app/api/agntcms/forms/submit/route.ts +17 -0
- package/dist/template/app/api/agntcms/global/delete/route.ts +13 -0
- package/dist/template/app/api/agntcms/global/history/route.ts +10 -0
- package/dist/template/app/api/agntcms/global/list/route.ts +14 -0
- package/dist/template/app/api/agntcms/global/read/route.ts +11 -0
- package/dist/template/app/api/agntcms/global/rollback/route.ts +10 -0
- package/dist/template/app/api/agntcms/global/save/route.ts +14 -0
- package/dist/template/app/api/agntcms/mcp/route.ts +12 -0
- package/dist/template/app/api/agntcms/page/delete/route.ts +10 -0
- package/dist/template/app/api/agntcms/page/duplicate/route.ts +11 -0
- package/dist/template/app/api/agntcms/page/history/route.ts +10 -0
- package/dist/template/app/api/agntcms/page/list/route.ts +10 -0
- package/dist/template/app/api/agntcms/page/read/route.ts +11 -0
- package/dist/template/app/api/agntcms/page/rename/route.ts +10 -0
- package/dist/template/app/api/agntcms/page/rollback/route.ts +10 -0
- package/dist/template/app/api/agntcms/page/unpublish/route.ts +11 -0
- package/dist/template/app/api/agntcms/preview/enter/route.ts +13 -0
- package/dist/template/app/api/agntcms/preview/exit/route.ts +10 -0
- package/dist/template/app/api/agntcms/preview/issue/route.ts +12 -0
- package/dist/template/app/api/agntcms/template/list/route.ts +15 -0
- package/dist/template/app/apple-icon.svg +9 -0
- package/dist/template/app/icon.svg +9 -0
- package/dist/template/app/layout.tsx +107 -0
- package/dist/template/app/not-found.tsx +75 -0
- package/dist/template/app/robots.ts +33 -0
- package/dist/template/app/sitemap.ts +49 -0
- package/dist/template/content/globals/site-footer.json +53 -0
- package/dist/template/content/globals/site-header.json +18 -0
- package/dist/template/content/globals/site-meta.json +13 -0
- package/dist/template/content/pages/404.json +34 -0
- package/dist/template/content/pages/about.json +307 -0
- package/dist/template/content/pages/article-editor.json +61 -0
- package/dist/template/content/pages/article-schemas.json +61 -0
- package/dist/template/content/pages/blog.json +162 -0
- package/dist/template/content/pages/contact.json +29 -0
- package/dist/template/content/pages/home.json +243 -0
- package/dist/template/content/pages/pricing.json +219 -0
- package/dist/template/content/pages/services.json +177 -0
- package/dist/template/fonts/Satoshi-Medium.woff2 +0 -0
- package/dist/template/fonts/Satoshi-Regular.woff2 +0 -0
- package/dist/template/next.config.ts +6 -0
- package/dist/template/package.json +36 -0
- package/dist/template/postcss.config.mjs +5 -0
- package/dist/template/public/assets/.gitkeep +0 -0
- package/dist/template/public/assets/0418d7ed21f57e7b9e0546725c92b8419daeaa355675d9070fab0c2013cf1524.jpg +0 -0
- package/dist/template/public/assets/0d0475f21aa96435a8ed3cdb2fddcc6278492e76ae842f569432454f4d33631a.jpg +0 -0
- package/dist/template/public/assets/27457a1adee2372030d9876b0d52c44d46be98843999935eaef2526b9b961f12.jpg +0 -0
- package/dist/template/public/assets/3855d91192f0c6120b01427b78ef84e52baa9f4b5a17d4271e41c1bfd95a5b0c.jpg +0 -0
- package/dist/template/public/assets/3b3b90c5084635b746be673ede92a328f002f5621a42c9a5cb89c5e2435652cb.jpg +0 -0
- package/dist/template/public/assets/3e76165a78fd3e7b8ed1e93dee50803ae11110c756c8c1c89229a2dec2bc0abf.jpg +0 -0
- package/dist/template/public/assets/4a3e28f85dc850c347ea0fd931696aa936a6bd45f193e7f1c9328b5896fb272c.jpg +0 -0
- package/dist/template/public/assets/579f67d5fd4c9106c6cdf2ef29f50df934ad0fc2b7849bac1e1cfb1e3f92303b.jpg +0 -0
- package/dist/template/public/assets/5b95209269661bb60fb250f1da682e05b9efa64dd42f350608b299e6bf1f2f35.jpg +0 -0
- package/dist/template/public/assets/5e04b46f8317ef95a7ddf85aedfe5c098a755f05056325d0251eccf95ce51172.jpg +0 -0
- package/dist/template/public/assets/6167a9164be2cf1183bdfdd4946bf9b908570e79e92a2380c25f0bb702422bbd.jpg +0 -0
- package/dist/template/public/assets/75e723ec316de28247924e5dfb73a4b266e10de605e749f150883d280ed8ed16.jpg +0 -0
- package/dist/template/public/assets/816a11e6a7245feaf51bbebf09d1bda3f125b334bc24fc3b8f47b5380a7b4294.jpg +0 -0
- package/dist/template/public/assets/81eba6f5654b8746a9b0cba1a9521a67f2b4afaaefc7c88d66dfab1461270d8f.jpg +0 -0
- package/dist/template/public/assets/82a2ce9e49361098f77a28755779dc5a7c026831cbd135175749c1304e21dacc.jpg +0 -0
- package/dist/template/public/assets/8d7b02ba277ba56bdafdbd47b01f7df6d993c714b4dc2305eb65a1307c09647d.jpg +0 -0
- package/dist/template/public/assets/b303185b471678e4d62f678a1549ee26022f4745407d08cae44ecb1c25352293.jpg +0 -0
- package/dist/template/public/assets/b69b49169c11546100d6dd5280073bc0d84cbbcc6d33fa01ecf6a5866fa42237.jpg +0 -0
- package/dist/template/public/assets/c4d2f0d1a310e457ac722a399693652e3c86c55b294243d5ffc679394e12f9d1.jpg +0 -0
- package/dist/template/public/assets/cae09f4729f8a348b67267c2f2a550be0f3bfa420689afe1a5cf8b7e2b146238.png +0 -0
- package/dist/template/public/assets/cb3acf58b57417a4b26474ba04c096af7103c4320ed2f4f3683f79d7670a055c.jpg +0 -0
- package/dist/template/public/assets/d5a0701b2d156284e0ce851cd2534ec632db34f91fbcbee3b8a7784d45ce78d2.jpg +0 -0
- package/dist/template/public/assets/d6ef1c3f48b0e488521794fb60701da1fd2c3a1621d6ac5f17ccfd4909d3be60.jpg +0 -0
- package/dist/template/public/assets/de249ff9be2539cf0d1ce092de3c57001839b6c3e14fcee3fc31a7b7673ae007.jpg +0 -0
- package/dist/template/public/assets/eac45438956be187b010e24b3289757aa00f227c190d49ee99fea510552dd2ba.jpg +0 -0
- package/dist/template/public/assets/f8b9200065b5436c6a88361839edc2b89be88d3037c84a80d3ee95c32891510b.jpg +0 -0
- package/dist/template/public/assets/placeholder.png +0 -0
- package/dist/template/public/brand/mark.svg +6 -0
- package/dist/template/public/brand/wordmark-light.svg +6 -0
- package/dist/template/public/brand/wordmark.svg +6 -0
- package/dist/template/styles/globals.css +69 -0
- package/dist/template/styles/theme.css +492 -0
- package/dist/template/styles/typography.css +469 -0
- package/dist/template/tsconfig.json +30 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# create-agntcms-app
|
|
2
|
+
|
|
3
|
+
Scaffold a new agntcms project from the canonical template.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx create-agntcms-app my-site
|
|
9
|
+
cd my-site
|
|
10
|
+
pnpm dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Local development (monorepo)
|
|
14
|
+
|
|
15
|
+
When developing the framework itself, use `--local` to link the scaffolded
|
|
16
|
+
project back to your monorepo checkout via `file:` protocol:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# 1. Build all packages
|
|
20
|
+
pnpm build
|
|
21
|
+
|
|
22
|
+
# 2. Scaffold with --local
|
|
23
|
+
node packages/cli/dist/index.mjs --local ~/test-site
|
|
24
|
+
|
|
25
|
+
# 3. Start watch mode in the monorepo (rebuilds packages on change)
|
|
26
|
+
pnpm dev
|
|
27
|
+
|
|
28
|
+
# 4. Start the scaffolded project
|
|
29
|
+
cd ~/test-site && pnpm dev
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Changes in `packages/next/` are rebuilt by the monorepo watcher and picked up
|
|
33
|
+
automatically by the scaffolded project through the symlink.
|
|
34
|
+
|
|
35
|
+
### What `--local` does
|
|
36
|
+
|
|
37
|
+
- Rewrites `workspace:*` dependencies to `file:` references pointing at the monorepo
|
|
38
|
+
- Points `tsconfig.json` extends at the monorepo's `tsconfig.base.json`
|
|
39
|
+
- Everything else (template copy, skills init, Telegram setup) works identically
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import * as readline from "readline/promises";
|
|
6
|
+
import { stdin as input, stdout as output } from "process";
|
|
7
|
+
|
|
8
|
+
// src/scaffold.ts
|
|
9
|
+
import * as fs from "fs";
|
|
10
|
+
import * as path2 from "path";
|
|
11
|
+
import { execSync as execSync2 } from "child_process";
|
|
12
|
+
import { syncSkills } from "@agntcms/skills";
|
|
13
|
+
|
|
14
|
+
// src/utils.ts
|
|
15
|
+
import { existsSync } from "fs";
|
|
16
|
+
import { execSync } from "child_process";
|
|
17
|
+
import * as path from "path";
|
|
18
|
+
function detectPackageManager() {
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
if (existsSync(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
21
|
+
if (existsSync(path.join(cwd, "yarn.lock"))) return "yarn";
|
|
22
|
+
if (existsSync(path.join(cwd, "package-lock.json"))) return "npm";
|
|
23
|
+
if (commandExists("pnpm")) return "pnpm";
|
|
24
|
+
if (commandExists("yarn")) return "yarn";
|
|
25
|
+
return "npm";
|
|
26
|
+
}
|
|
27
|
+
function commandExists(cmd) {
|
|
28
|
+
try {
|
|
29
|
+
execSync(`which ${cmd}`, { stdio: "ignore" });
|
|
30
|
+
return true;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function installCommand(pm) {
|
|
36
|
+
switch (pm) {
|
|
37
|
+
case "pnpm":
|
|
38
|
+
return "pnpm install";
|
|
39
|
+
case "yarn":
|
|
40
|
+
return "yarn install";
|
|
41
|
+
case "npm":
|
|
42
|
+
return "npm install";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/version.ts
|
|
47
|
+
var CLI_VERSION = true ? "0.2.1" : "0.0.0-dev";
|
|
48
|
+
|
|
49
|
+
// src/scaffold.ts
|
|
50
|
+
var COPY_EXCLUDES = /* @__PURE__ */ new Set([
|
|
51
|
+
".next",
|
|
52
|
+
".turbo",
|
|
53
|
+
"node_modules",
|
|
54
|
+
"tsconfig.tsbuildinfo",
|
|
55
|
+
"next-env.d.ts"
|
|
56
|
+
// next generates this on first dev run
|
|
57
|
+
]);
|
|
58
|
+
var WORKSPACE_PACKAGE_VERSION_MAP = {
|
|
59
|
+
"@agntcms/next": CLI_VERSION,
|
|
60
|
+
"@agntcms/skills": CLI_VERSION
|
|
61
|
+
};
|
|
62
|
+
async function scaffold(targetDir, options = {}) {
|
|
63
|
+
const absoluteTarget = path2.resolve(targetDir);
|
|
64
|
+
const projectName = path2.basename(absoluteTarget);
|
|
65
|
+
const local = options.local ?? false;
|
|
66
|
+
validateTarget(absoluteTarget);
|
|
67
|
+
const templateDir = resolveTemplateDir();
|
|
68
|
+
const monorepoRoot = local ? resolveMonorepoRoot() : void 0;
|
|
69
|
+
console.log(`
|
|
70
|
+
Scaffolding agntcms project into ${absoluteTarget} ...
|
|
71
|
+
`);
|
|
72
|
+
copyTemplate(templateDir, absoluteTarget);
|
|
73
|
+
rewritePackageJson(absoluteTarget, projectName, { local, monorepoRoot });
|
|
74
|
+
rewriteTsconfig(absoluteTarget, { local, monorepoRoot });
|
|
75
|
+
if (local && monorepoRoot !== void 0) {
|
|
76
|
+
console.log(`Building monorepo packages for --local mode (${monorepoRoot}) ...
|
|
77
|
+
`);
|
|
78
|
+
execSync2("pnpm build", { cwd: monorepoRoot, stdio: "inherit" });
|
|
79
|
+
}
|
|
80
|
+
const pm = detectPackageManager();
|
|
81
|
+
console.log(`Installing dependencies with ${pm} ...
|
|
82
|
+
`);
|
|
83
|
+
execSync2(installCommand(pm), { cwd: absoluteTarget, stdio: "inherit" });
|
|
84
|
+
console.log("Initializing .claude/skills/ ...\n");
|
|
85
|
+
await syncSkills(absoluteTarget);
|
|
86
|
+
const gitkeep = path2.join(absoluteTarget, ".claude", "skills", ".gitkeep");
|
|
87
|
+
if (fs.existsSync(gitkeep)) {
|
|
88
|
+
fs.rmSync(gitkeep);
|
|
89
|
+
}
|
|
90
|
+
printNextSteps(projectName, pm, { local, monorepoRoot });
|
|
91
|
+
}
|
|
92
|
+
function validateTarget(absoluteTarget) {
|
|
93
|
+
if (!fs.existsSync(absoluteTarget)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const stat = fs.statSync(absoluteTarget);
|
|
97
|
+
if (!stat.isDirectory()) {
|
|
98
|
+
throw new Error(`${absoluteTarget} already exists and is not a directory.`);
|
|
99
|
+
}
|
|
100
|
+
const entries = fs.readdirSync(absoluteTarget).filter((e) => e !== ".git");
|
|
101
|
+
if (entries.length > 0) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Directory ${absoluteTarget} already exists and is not empty. Please choose an empty directory or a new path.`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function resolveTemplateDir() {
|
|
108
|
+
const here = path2.dirname(new URL(import.meta.url).pathname);
|
|
109
|
+
const candidates = [
|
|
110
|
+
path2.resolve(here, "template"),
|
|
111
|
+
path2.resolve(here, "..", "template"),
|
|
112
|
+
path2.resolve(here, "..", "..", "..", "template")
|
|
113
|
+
];
|
|
114
|
+
for (const candidate of candidates) {
|
|
115
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
|
|
116
|
+
return candidate;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
throw new Error(
|
|
120
|
+
`Cannot locate template directory. Searched:
|
|
121
|
+
` + candidates.map((c) => ` ${c}`).join("\n")
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
function resolveMonorepoRoot() {
|
|
125
|
+
const here = path2.dirname(new URL(import.meta.url).pathname);
|
|
126
|
+
const candidate = path2.resolve(here, "..", "..", "..");
|
|
127
|
+
const marker = path2.join(candidate, "packages", "next", "package.json");
|
|
128
|
+
if (fs.existsSync(marker)) {
|
|
129
|
+
return candidate;
|
|
130
|
+
}
|
|
131
|
+
throw new Error(
|
|
132
|
+
`Cannot find monorepo root. --local only works when running from the agntcms source tree.
|
|
133
|
+
Looked for: ${marker}`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
function copyTemplate(src, dest) {
|
|
137
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
138
|
+
copyDir(src, dest);
|
|
139
|
+
}
|
|
140
|
+
function copyDir(src, dest) {
|
|
141
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
142
|
+
for (const entry of entries) {
|
|
143
|
+
if (COPY_EXCLUDES.has(entry.name)) continue;
|
|
144
|
+
const srcPath = path2.join(src, entry.name);
|
|
145
|
+
const destPath = path2.join(dest, entry.name);
|
|
146
|
+
if (entry.isDirectory()) {
|
|
147
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
148
|
+
copyDir(srcPath, destPath);
|
|
149
|
+
} else if (entry.isFile()) {
|
|
150
|
+
fs.copyFileSync(srcPath, destPath);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function rewritePackageJson(projectDir, projectName, opts) {
|
|
155
|
+
const pkgPath = path2.join(projectDir, "package.json");
|
|
156
|
+
if (!fs.existsSync(pkgPath)) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const raw = fs.readFileSync(pkgPath, "utf-8");
|
|
160
|
+
const pkg = JSON.parse(raw);
|
|
161
|
+
if (!isRecord(pkg)) {
|
|
162
|
+
throw new Error(`package.json in template is not a JSON object.`);
|
|
163
|
+
}
|
|
164
|
+
pkg["name"] = projectName;
|
|
165
|
+
delete pkg["private"];
|
|
166
|
+
rewriteWorkspaceDeps(pkg, "dependencies", opts);
|
|
167
|
+
rewriteWorkspaceDeps(pkg, "devDependencies", opts);
|
|
168
|
+
rewriteWorkspaceDeps(pkg, "peerDependencies", opts);
|
|
169
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
170
|
+
}
|
|
171
|
+
var WORKSPACE_PACKAGE_DIR_MAP = {
|
|
172
|
+
"@agntcms/next": "packages/next",
|
|
173
|
+
"@agntcms/skills": "packages/skills"
|
|
174
|
+
};
|
|
175
|
+
function rewriteWorkspaceDeps(pkg, field, opts) {
|
|
176
|
+
const deps = pkg[field];
|
|
177
|
+
if (!isRecord(deps)) return;
|
|
178
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
179
|
+
if (typeof version === "string" && version.startsWith("workspace:")) {
|
|
180
|
+
if (opts.local && opts.monorepoRoot !== void 0) {
|
|
181
|
+
const subdir = WORKSPACE_PACKAGE_DIR_MAP[name];
|
|
182
|
+
if (subdir !== void 0) {
|
|
183
|
+
deps[name] = `file:${path2.join(opts.monorepoRoot, subdir)}`;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const mapped = WORKSPACE_PACKAGE_VERSION_MAP[name];
|
|
188
|
+
deps[name] = mapped !== void 0 ? `^${mapped}` : `^${CLI_VERSION}`;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function isRecord(value) {
|
|
193
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
194
|
+
}
|
|
195
|
+
function rewriteTsconfig(projectDir, opts) {
|
|
196
|
+
const tsconfigPath = path2.join(projectDir, "tsconfig.json");
|
|
197
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const raw = fs.readFileSync(tsconfigPath, "utf-8");
|
|
201
|
+
const tsconfig = JSON.parse(raw);
|
|
202
|
+
if (!isRecord(tsconfig)) return;
|
|
203
|
+
const extendsValue = tsconfig["extends"];
|
|
204
|
+
if (typeof extendsValue !== "string" || !extendsValue.includes("tsconfig.base")) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (opts.local && opts.monorepoRoot !== void 0) {
|
|
208
|
+
tsconfig["extends"] = path2.join(opts.monorepoRoot, "tsconfig.base.json");
|
|
209
|
+
fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2) + "\n", "utf-8");
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
delete tsconfig["extends"];
|
|
213
|
+
const base = {
|
|
214
|
+
target: "ES2022",
|
|
215
|
+
lib: ["ES2022", "DOM", "DOM.Iterable"],
|
|
216
|
+
module: "ESNext",
|
|
217
|
+
moduleResolution: "Bundler",
|
|
218
|
+
resolveJsonModule: true,
|
|
219
|
+
isolatedModules: true,
|
|
220
|
+
verbatimModuleSyntax: true,
|
|
221
|
+
esModuleInterop: true,
|
|
222
|
+
forceConsistentCasingInFileNames: true,
|
|
223
|
+
skipLibCheck: true,
|
|
224
|
+
strict: true,
|
|
225
|
+
noUncheckedIndexedAccess: true,
|
|
226
|
+
noImplicitOverride: true,
|
|
227
|
+
noFallthroughCasesInSwitch: true,
|
|
228
|
+
exactOptionalPropertyTypes: true,
|
|
229
|
+
declaration: true,
|
|
230
|
+
declarationMap: true,
|
|
231
|
+
sourceMap: true,
|
|
232
|
+
useDefineForClassFields: true
|
|
233
|
+
};
|
|
234
|
+
const existing = isRecord(tsconfig["compilerOptions"]) ? tsconfig["compilerOptions"] : {};
|
|
235
|
+
tsconfig["compilerOptions"] = { ...base, ...existing };
|
|
236
|
+
fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2) + "\n", "utf-8");
|
|
237
|
+
}
|
|
238
|
+
function printNextSteps(projectName, pm, opts) {
|
|
239
|
+
const runCmd = pm === "npm" ? "npm run" : pm;
|
|
240
|
+
const localNote = opts.local && opts.monorepoRoot !== void 0 ? `
|
|
241
|
+
Warning: Local mode: dependencies are symlinked to the monorepo at ${opts.monorepoRoot}.
|
|
242
|
+
Run "pnpm dev" in the monorepo to keep packages rebuilt in watch mode.
|
|
243
|
+
` : "";
|
|
244
|
+
console.log(`
|
|
245
|
+
agntcms project created successfully!
|
|
246
|
+
${localNote}
|
|
247
|
+
Next steps:
|
|
248
|
+
|
|
249
|
+
First, personalize the template:
|
|
250
|
+
|
|
251
|
+
cd ${projectName}
|
|
252
|
+
claude # open Claude Code in the project
|
|
253
|
+
/agntcms-init # interview-driven personalization (or "explore demo" branch)
|
|
254
|
+
|
|
255
|
+
Or skip the interview and run \`${runCmd} dev\` to explore the agntcms demo as-is.
|
|
256
|
+
|
|
257
|
+
${runCmd} dev # start the dev server at http://localhost:3000
|
|
258
|
+
|
|
259
|
+
${runCmd} build # production build
|
|
260
|
+
|
|
261
|
+
To configure your project:
|
|
262
|
+
- Edit agntcms/config.ts to register sections and adapters.
|
|
263
|
+
- Add new sections under agntcms/sections/<SectionName>/.
|
|
264
|
+
- Run \`pnpm dev\` alongside an interactive Claude Code session to enable agent-driven editing.
|
|
265
|
+
`);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// src/index.ts
|
|
269
|
+
var program = new Command();
|
|
270
|
+
program.name("create-agntcms-app").description("Scaffold a new agntcms project from the canonical template").version(CLI_VERSION).argument("[dir]", "Target directory for the new project").option(
|
|
271
|
+
"--local",
|
|
272
|
+
"Link to local monorepo packages via file: protocol (dev only)"
|
|
273
|
+
).action(async (dir, opts) => {
|
|
274
|
+
let targetDir = dir?.trim();
|
|
275
|
+
if (!targetDir) {
|
|
276
|
+
const rl = readline.createInterface({ input, output });
|
|
277
|
+
try {
|
|
278
|
+
targetDir = (await rl.question("Project directory name: ")).trim();
|
|
279
|
+
} finally {
|
|
280
|
+
rl.close();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (!targetDir) {
|
|
284
|
+
console.error("Error: a target directory is required.");
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
try {
|
|
288
|
+
await scaffold(targetDir, { local: opts.local ?? false });
|
|
289
|
+
} catch (err) {
|
|
290
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
291
|
+
console.error(`
|
|
292
|
+
Error: ${message}
|
|
293
|
+
`);
|
|
294
|
+
process.exit(1);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
program.parse();
|
|
File without changes
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
// server.ts
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import {
|
|
5
|
+
ListToolsRequestSchema,
|
|
6
|
+
CallToolRequestSchema
|
|
7
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
+
import * as http from "http";
|
|
9
|
+
var CHANNEL_PORT = Number(process.env["agntcms_CHANNEL_PORT"] ?? 4819);
|
|
10
|
+
var DEFAULT_CALLBACK_URL = process.env["agntcms_CALLBACK_URL"] ?? "http://localhost:3000/api/agntcms/mcp";
|
|
11
|
+
var taskCallbacks = /* @__PURE__ */ new Map();
|
|
12
|
+
var INSTRUCTIONS = [
|
|
13
|
+
"Tasks from the agntcms runtime arrive as channel messages.",
|
|
14
|
+
'Each message starts with "task_assigned" followed by task_id, type, and payload fields.',
|
|
15
|
+
"",
|
|
16
|
+
"For every task_assigned message:",
|
|
17
|
+
"1. Parse the task_id, type, and payload.",
|
|
18
|
+
"2. Check your loaded skills for one that covers this task type",
|
|
19
|
+
" (e.g. agntcms-section-replace for type=section_replace).",
|
|
20
|
+
" If a skill matches, follow its workflow.",
|
|
21
|
+
"3. Carry out the work using your file tools.",
|
|
22
|
+
"4. Report completion by calling the report_task_done tool with the",
|
|
23
|
+
" exact task_id and a short human-readable result.",
|
|
24
|
+
"5. For long-running tasks, call report_task_progress one or more times",
|
|
25
|
+
" before report_task_done.",
|
|
26
|
+
"",
|
|
27
|
+
"Always call report_task_done, even on error \u2014 use a result starting",
|
|
28
|
+
'with "Error: " and a short reason. Never leave a task without a',
|
|
29
|
+
"report_task_done call.",
|
|
30
|
+
"",
|
|
31
|
+
"IMPORTANT: Never read image files (png, jpg, jpeg, gif, webp, svg, ico).",
|
|
32
|
+
"Image paths in content JSON are opaque strings \u2014 copy them as-is.",
|
|
33
|
+
"You only edit text: JSON content files, TypeScript config, Markdown."
|
|
34
|
+
].join("\n");
|
|
35
|
+
var mcp = new Server(
|
|
36
|
+
{ name: "agntcms", version: "0.1.6" },
|
|
37
|
+
{
|
|
38
|
+
capabilities: {
|
|
39
|
+
tools: {},
|
|
40
|
+
experimental: {
|
|
41
|
+
"claude/channel": {}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
instructions: INSTRUCTIONS
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
48
|
+
tools: [
|
|
49
|
+
{
|
|
50
|
+
name: "report_task_done",
|
|
51
|
+
description: "Report that an assigned task has been completed. Pass the task_id from the task_assigned message and a short human-readable result.",
|
|
52
|
+
inputSchema: {
|
|
53
|
+
type: "object",
|
|
54
|
+
properties: {
|
|
55
|
+
task_id: {
|
|
56
|
+
type: "string",
|
|
57
|
+
description: "The task_id from the task_assigned message"
|
|
58
|
+
},
|
|
59
|
+
result: {
|
|
60
|
+
type: "string",
|
|
61
|
+
description: "Short human-readable description of what was done"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
required: ["task_id", "result"]
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "report_task_progress",
|
|
69
|
+
description: "Report incremental progress on a long-running task. Optional \u2014 only use for tasks that take more than a few seconds.",
|
|
70
|
+
inputSchema: {
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: {
|
|
73
|
+
task_id: {
|
|
74
|
+
type: "string",
|
|
75
|
+
description: "The task_id from the task_assigned message"
|
|
76
|
+
},
|
|
77
|
+
message: {
|
|
78
|
+
type: "string",
|
|
79
|
+
description: "Short progress update"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
required: ["task_id", "message"]
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}));
|
|
87
|
+
var postCallback = async (callbackUrl, body) => {
|
|
88
|
+
const res = await fetch(callbackUrl, {
|
|
89
|
+
method: "POST",
|
|
90
|
+
headers: { "Content-Type": "application/json" },
|
|
91
|
+
body: JSON.stringify(body)
|
|
92
|
+
});
|
|
93
|
+
if (!res.ok) {
|
|
94
|
+
throw new Error(`callback returned ${String(res.status)}`);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
mcp.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
98
|
+
const { name } = request.params;
|
|
99
|
+
const args = request.params.arguments ?? {};
|
|
100
|
+
switch (name) {
|
|
101
|
+
case "report_task_done": {
|
|
102
|
+
const taskId = String(args["task_id"] ?? "");
|
|
103
|
+
const result = String(args["result"] ?? "");
|
|
104
|
+
const callbackUrl = taskCallbacks.get(taskId) ?? DEFAULT_CALLBACK_URL;
|
|
105
|
+
try {
|
|
106
|
+
await postCallback(callbackUrl, {
|
|
107
|
+
action: "task_callback",
|
|
108
|
+
event: "completed",
|
|
109
|
+
task_id: taskId,
|
|
110
|
+
result
|
|
111
|
+
});
|
|
112
|
+
taskCallbacks.delete(taskId);
|
|
113
|
+
return { content: [{ type: "text", text: `acknowledged: ${taskId}` }] };
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
116
|
+
return {
|
|
117
|
+
content: [{ type: "text", text: `callback failed: ${msg}` }],
|
|
118
|
+
isError: true
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
case "report_task_progress": {
|
|
123
|
+
const taskId = String(args["task_id"] ?? "");
|
|
124
|
+
const message = String(args["message"] ?? "");
|
|
125
|
+
const callbackUrl = taskCallbacks.get(taskId) ?? DEFAULT_CALLBACK_URL;
|
|
126
|
+
try {
|
|
127
|
+
await postCallback(callbackUrl, {
|
|
128
|
+
action: "task_callback",
|
|
129
|
+
event: "progress",
|
|
130
|
+
task_id: taskId,
|
|
131
|
+
message
|
|
132
|
+
});
|
|
133
|
+
return { content: [{ type: "text", text: `progress recorded for ${taskId}` }] };
|
|
134
|
+
} catch (err) {
|
|
135
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
136
|
+
return {
|
|
137
|
+
content: [{ type: "text", text: `callback failed: ${msg}` }],
|
|
138
|
+
isError: true
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
default:
|
|
143
|
+
return {
|
|
144
|
+
content: [{ type: "text", text: `unknown tool: ${name}` }],
|
|
145
|
+
isError: true
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
var buildTaskAssignedText = (taskId, type, payload) => {
|
|
150
|
+
const payloadJson = (() => {
|
|
151
|
+
try {
|
|
152
|
+
return JSON.stringify(payload);
|
|
153
|
+
} catch {
|
|
154
|
+
return '"<unserializable payload>"';
|
|
155
|
+
}
|
|
156
|
+
})();
|
|
157
|
+
return [
|
|
158
|
+
"task_assigned",
|
|
159
|
+
`task_id=${taskId}`,
|
|
160
|
+
`type=${type}`,
|
|
161
|
+
`payload=${payloadJson}`,
|
|
162
|
+
"",
|
|
163
|
+
"Carry out the task and then call report_task_done with the task_id above."
|
|
164
|
+
].join("\n");
|
|
165
|
+
};
|
|
166
|
+
var readBody = async (req) => {
|
|
167
|
+
const chunks = [];
|
|
168
|
+
for await (const chunk of req) {
|
|
169
|
+
chunks.push(chunk);
|
|
170
|
+
}
|
|
171
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
172
|
+
};
|
|
173
|
+
var jsonResponse = (res, status, body) => {
|
|
174
|
+
res.writeHead(status, { "Content-Type": "application/json" });
|
|
175
|
+
res.end(JSON.stringify(body));
|
|
176
|
+
};
|
|
177
|
+
var httpServer = http.createServer((req, res) => {
|
|
178
|
+
if (req.method === "GET" && req.url === "/health") {
|
|
179
|
+
jsonResponse(res, 200, { status: "ok" });
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (req.method === "POST" && req.url === "/task") {
|
|
183
|
+
readBody(req).then((raw) => {
|
|
184
|
+
let parsed;
|
|
185
|
+
try {
|
|
186
|
+
parsed = JSON.parse(raw);
|
|
187
|
+
} catch {
|
|
188
|
+
jsonResponse(res, 400, { error: "invalid_json" });
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const taskId = parsed["task_id"];
|
|
192
|
+
const type = parsed["type"];
|
|
193
|
+
const payload = parsed["payload"];
|
|
194
|
+
const callbackUrl = parsed["callback_url"];
|
|
195
|
+
if (typeof taskId !== "string" || taskId === "") {
|
|
196
|
+
jsonResponse(res, 400, {
|
|
197
|
+
error: "missing_field",
|
|
198
|
+
message: "task_id is required"
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (typeof type !== "string" || type === "") {
|
|
203
|
+
jsonResponse(res, 400, {
|
|
204
|
+
error: "missing_field",
|
|
205
|
+
message: "type is required"
|
|
206
|
+
});
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const resolvedCallback = typeof callbackUrl === "string" && callbackUrl !== "" ? callbackUrl : DEFAULT_CALLBACK_URL;
|
|
210
|
+
taskCallbacks.set(taskId, resolvedCallback);
|
|
211
|
+
const content = buildTaskAssignedText(taskId, type, payload);
|
|
212
|
+
mcp.notification({
|
|
213
|
+
method: "notifications/claude/channel",
|
|
214
|
+
params: { content, meta: { task_id: taskId, type } }
|
|
215
|
+
}).then(() => {
|
|
216
|
+
jsonResponse(res, 200, { ok: true, task_id: taskId });
|
|
217
|
+
}).catch((err) => {
|
|
218
|
+
taskCallbacks.delete(taskId);
|
|
219
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
220
|
+
jsonResponse(res, 502, {
|
|
221
|
+
error: "notification_failed",
|
|
222
|
+
message: msg
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}).catch(() => {
|
|
226
|
+
jsonResponse(res, 500, { error: "internal" });
|
|
227
|
+
});
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
jsonResponse(res, 404, { error: "not_found" });
|
|
231
|
+
});
|
|
232
|
+
var isDirectRun = process.argv[1] !== void 0 && (process.argv[1].endsWith("/server.mjs") || process.argv[1].endsWith("/server.js") || process.argv[1].endsWith("/server.ts"));
|
|
233
|
+
if (isDirectRun) {
|
|
234
|
+
const transport = new StdioServerTransport();
|
|
235
|
+
mcp.connect(transport).then(() => {
|
|
236
|
+
httpServer.listen(CHANNEL_PORT, "127.0.0.1", () => {
|
|
237
|
+
process.stderr.write(
|
|
238
|
+
`agntcms channel server listening on 127.0.0.1:${String(CHANNEL_PORT)}
|
|
239
|
+
`
|
|
240
|
+
);
|
|
241
|
+
});
|
|
242
|
+
}).catch((err) => {
|
|
243
|
+
process.stderr.write(`agntcms channel server fatal: ${String(err)}
|
|
244
|
+
`);
|
|
245
|
+
process.exit(1);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
export {
|
|
249
|
+
INSTRUCTIONS,
|
|
250
|
+
buildTaskAssignedText,
|
|
251
|
+
httpServer,
|
|
252
|
+
mcp,
|
|
253
|
+
taskCallbacks
|
|
254
|
+
};
|