@kya-os/create-molti 0.1.0-canary.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.
Files changed (117) hide show
  1. package/dist/cli.d.ts +10 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +83 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/helpers/generate-identity.d.ts +22 -0
  6. package/dist/helpers/generate-identity.d.ts.map +1 -0
  7. package/dist/helpers/generate-identity.js +63 -0
  8. package/dist/helpers/generate-identity.js.map +1 -0
  9. package/dist/helpers/generate-molti-project.d.ts +31 -0
  10. package/dist/helpers/generate-molti-project.d.ts.map +1 -0
  11. package/dist/helpers/generate-molti-project.js +200 -0
  12. package/dist/helpers/generate-molti-project.js.map +1 -0
  13. package/dist/helpers/get-package-versions.d.ts +22 -0
  14. package/dist/helpers/get-package-versions.d.ts.map +1 -0
  15. package/dist/helpers/get-package-versions.js +60 -0
  16. package/dist/helpers/get-package-versions.js.map +1 -0
  17. package/dist/helpers/index.d.ts +12 -0
  18. package/dist/helpers/index.d.ts.map +1 -0
  19. package/dist/helpers/index.js +14 -0
  20. package/dist/helpers/index.js.map +1 -0
  21. package/dist/helpers/validate-name.d.ts +16 -0
  22. package/dist/helpers/validate-name.d.ts.map +1 -0
  23. package/dist/helpers/validate-name.js +31 -0
  24. package/dist/helpers/validate-name.js.map +1 -0
  25. package/dist/index.d.ts +12 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +16 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/templates/auth-module.d.ts +7 -0
  30. package/dist/templates/auth-module.d.ts.map +1 -0
  31. package/dist/templates/auth-module.js +68 -0
  32. package/dist/templates/auth-module.js.map +1 -0
  33. package/dist/templates/dockerfile.d.ts +8 -0
  34. package/dist/templates/dockerfile.d.ts.map +1 -0
  35. package/dist/templates/dockerfile.js +40 -0
  36. package/dist/templates/dockerfile.js.map +1 -0
  37. package/dist/templates/gateway.d.ts +8 -0
  38. package/dist/templates/gateway.d.ts.map +1 -0
  39. package/dist/templates/gateway.js +112 -0
  40. package/dist/templates/gateway.js.map +1 -0
  41. package/dist/templates/github-workflow.d.ts +7 -0
  42. package/dist/templates/github-workflow.d.ts.map +1 -0
  43. package/dist/templates/github-workflow.js +48 -0
  44. package/dist/templates/github-workflow.js.map +1 -0
  45. package/dist/templates/health-module.d.ts +7 -0
  46. package/dist/templates/health-module.d.ts.map +1 -0
  47. package/dist/templates/health-module.js +62 -0
  48. package/dist/templates/health-module.js.map +1 -0
  49. package/dist/templates/identity-json.d.ts +15 -0
  50. package/dist/templates/identity-json.d.ts.map +1 -0
  51. package/dist/templates/identity-json.js +18 -0
  52. package/dist/templates/identity-json.js.map +1 -0
  53. package/dist/templates/identity-module.d.ts +8 -0
  54. package/dist/templates/identity-module.d.ts.map +1 -0
  55. package/dist/templates/identity-module.js +89 -0
  56. package/dist/templates/identity-module.js.map +1 -0
  57. package/dist/templates/moltbot-config.d.ts +7 -0
  58. package/dist/templates/moltbot-config.d.ts.map +1 -0
  59. package/dist/templates/moltbot-config.js +19 -0
  60. package/dist/templates/moltbot-config.js.map +1 -0
  61. package/dist/templates/package-json.d.ts +13 -0
  62. package/dist/templates/package-json.d.ts.map +1 -0
  63. package/dist/templates/package-json.js +34 -0
  64. package/dist/templates/package-json.js.map +1 -0
  65. package/dist/templates/readme.d.ts +14 -0
  66. package/dist/templates/readme.d.ts.map +1 -0
  67. package/dist/templates/readme.js +92 -0
  68. package/dist/templates/readme.js.map +1 -0
  69. package/dist/templates/startup-script.d.ts +8 -0
  70. package/dist/templates/startup-script.d.ts.map +1 -0
  71. package/dist/templates/startup-script.js +54 -0
  72. package/dist/templates/startup-script.js.map +1 -0
  73. package/dist/templates/tsconfig-template.d.ts +7 -0
  74. package/dist/templates/tsconfig-template.d.ts.map +1 -0
  75. package/dist/templates/tsconfig-template.js +22 -0
  76. package/dist/templates/tsconfig-template.js.map +1 -0
  77. package/dist/templates/types-module.d.ts +7 -0
  78. package/dist/templates/types-module.d.ts.map +1 -0
  79. package/dist/templates/types-module.js +73 -0
  80. package/dist/templates/types-module.js.map +1 -0
  81. package/dist/templates/worker-index.d.ts +8 -0
  82. package/dist/templates/worker-index.d.ts.map +1 -0
  83. package/dist/templates/worker-index.js +99 -0
  84. package/dist/templates/worker-index.js.map +1 -0
  85. package/dist/templates/wrangler.d.ts +16 -0
  86. package/dist/templates/wrangler.d.ts.map +1 -0
  87. package/dist/templates/wrangler.js +77 -0
  88. package/dist/templates/wrangler.js.map +1 -0
  89. package/dist/types.d.ts +61 -0
  90. package/dist/types.d.ts.map +1 -0
  91. package/dist/types.js +8 -0
  92. package/dist/types.js.map +1 -0
  93. package/package.json +50 -0
  94. package/scripts/validate-dependencies.js +38 -0
  95. package/src/cli.ts +98 -0
  96. package/src/helpers/generate-identity.ts +90 -0
  97. package/src/helpers/generate-molti-project.ts +239 -0
  98. package/src/helpers/get-package-versions.ts +78 -0
  99. package/src/helpers/index.ts +24 -0
  100. package/src/helpers/validate-name.ts +42 -0
  101. package/src/index.ts +18 -0
  102. package/src/templates/auth-module.ts +68 -0
  103. package/src/templates/dockerfile.ts +40 -0
  104. package/src/templates/gateway.ts +112 -0
  105. package/src/templates/github-workflow.ts +48 -0
  106. package/src/templates/health-module.ts +62 -0
  107. package/src/templates/identity-json.ts +29 -0
  108. package/src/templates/identity-module.ts +89 -0
  109. package/src/templates/moltbot-config.ts +23 -0
  110. package/src/templates/package-json.ts +46 -0
  111. package/src/templates/readme.ts +101 -0
  112. package/src/templates/startup-script.ts +54 -0
  113. package/src/templates/tsconfig-template.ts +26 -0
  114. package/src/templates/types-module.ts +73 -0
  115. package/src/templates/worker-index.ts +99 -0
  116. package/src/templates/wrangler.ts +89 -0
  117. package/src/types.ts +64 -0
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Auth Module Template (src/auth.ts)
3
+ *
4
+ * Generates Cloudflare Access middleware for JWT verification.
5
+ */
6
+
7
+ export function generateAuthModule(): string {
8
+ return `/**
9
+ * Cloudflare Access Authentication Middleware
10
+ *
11
+ * Verifies CF Access JWT tokens for protected routes.
12
+ * Skips auth in dev mode for local development.
13
+ */
14
+
15
+ import type { Context, Next } from "hono";
16
+ import type { AppEnv } from "./types";
17
+
18
+ interface AccessMiddlewareOptions {
19
+ type: "api" | "admin";
20
+ redirectOnMissing?: boolean;
21
+ }
22
+
23
+ /**
24
+ * Create CF Access authentication middleware
25
+ */
26
+ export function createAccessMiddleware(options: AccessMiddlewareOptions) {
27
+ return async (c: Context<AppEnv>, next: Next) => {
28
+ const env = c.env;
29
+
30
+ // Skip auth in dev mode
31
+ if (env.DEV_MODE === "true") {
32
+ c.set("accessUser", { email: "dev@localhost", name: "Dev User" });
33
+ return next();
34
+ }
35
+
36
+ // Skip auth if CF Access is not configured
37
+ if (!env.CF_ACCESS_TEAM_DOMAIN || !env.CF_ACCESS_AUD) {
38
+ c.set("accessUser", { email: "unconfigured@localhost" });
39
+ return next();
40
+ }
41
+
42
+ // Extract JWT from CF-Access-JWT-Assertion header or cookie
43
+ const jwt =
44
+ c.req.header("CF-Access-JWT-Assertion") ||
45
+ getCookie(c.req.header("cookie") || "", "CF_Authorization");
46
+
47
+ if (!jwt) {
48
+ if (options.redirectOnMissing) {
49
+ return c.redirect(
50
+ \`https://\${env.CF_ACCESS_TEAM_DOMAIN}/cdn-cgi/access/login\`
51
+ );
52
+ }
53
+ return c.json({ error: "Authentication required" }, 401);
54
+ }
55
+
56
+ // For production, verify JWT with CF Access JWKS
57
+ // Simplified: trust CF Access header in Workers environment
58
+ c.set("accessUser", { email: "authenticated@user" });
59
+ await next();
60
+ };
61
+ }
62
+
63
+ function getCookie(cookieHeader: string, name: string): string | undefined {
64
+ const match = cookieHeader.match(new RegExp(\`(?:^|;\\\\s*)\${name}=([^;]*)\`));
65
+ return match?.[1];
66
+ }
67
+ `;
68
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Dockerfile Template
3
+ *
4
+ * Generates a Dockerfile for the Moltworker container.
5
+ * Based on the Cloudflare sandbox base image with Node.js and moltbot CLI.
6
+ */
7
+
8
+ export function generateDockerfile(): string {
9
+ return `FROM docker.io/cloudflare/sandbox:0.7.0
10
+
11
+ # Install Node.js 22 (required by moltbot)
12
+ ENV NODE_VERSION=22.13.1
13
+ RUN apt-get update && apt-get install -y xz-utils ca-certificates rsync \\
14
+ && curl -fsSLk https://nodejs.org/dist/v\${NODE_VERSION}/node-v\${NODE_VERSION}-linux-x64.tar.xz -o /tmp/node.tar.xz \\
15
+ && tar -xJf /tmp/node.tar.xz -C /usr/local --strip-components=1 \\
16
+ && rm /tmp/node.tar.xz
17
+
18
+ # Install pnpm
19
+ RUN npm install -g pnpm
20
+
21
+ # Install moltbot CLI
22
+ RUN npm install -g clawdbot@2026.1.24-3
23
+
24
+ # Create directories
25
+ RUN mkdir -p /root/.clawdbot \\
26
+ && mkdir -p /root/.clawdbot-templates \\
27
+ && mkdir -p /root/clawd \\
28
+ && mkdir -p /root/clawd/skills
29
+
30
+ # Copy startup script
31
+ COPY start-moltbot.sh /usr/local/bin/start-moltbot.sh
32
+ RUN chmod +x /usr/local/bin/start-moltbot.sh
33
+
34
+ # Copy config template
35
+ COPY moltbot.json.template /root/.clawdbot-templates/moltbot.json.template
36
+
37
+ WORKDIR /root/clawd
38
+ EXPOSE 18789
39
+ `;
40
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Gateway Module Template (src/gateway.ts)
3
+ *
4
+ * Generates the gateway management code that ensures the
5
+ * Moltbot process is running inside the container.
6
+ */
7
+
8
+ export function generateGatewayModule(): string {
9
+ return `/**
10
+ * Moltbot Gateway Management
11
+ *
12
+ * Ensures the Moltbot process is running inside the container
13
+ * and waits for the gateway port to be ready.
14
+ */
15
+
16
+ export const MOLTBOT_PORT = 18789;
17
+ const STARTUP_TIMEOUT_MS = 180_000; // 3 minutes
18
+
19
+ /**
20
+ * Ensure the Moltbot gateway is running and ready
21
+ */
22
+ export async function ensureMoltbotGateway(
23
+ sandbox: any,
24
+ env: Record<string, unknown>
25
+ ): Promise<void> {
26
+ // Check for existing process
27
+ const processes = await sandbox.ps();
28
+ const existing = processes.find(
29
+ (p: { command: string; status: string }) =>
30
+ (p.command.includes("start-moltbot.sh") || p.command.includes("clawdbot gateway")) &&
31
+ p.status === "running"
32
+ );
33
+
34
+ if (existing) {
35
+ await waitForPort(sandbox, MOLTBOT_PORT, STARTUP_TIMEOUT_MS);
36
+ return;
37
+ }
38
+
39
+ // Build environment variables for the container process
40
+ const envVars = buildEnvVars(env);
41
+
42
+ // Start the moltbot process
43
+ await sandbox.start("/usr/local/bin/start-moltbot.sh", {
44
+ env: envVars,
45
+ });
46
+
47
+ await waitForPort(sandbox, MOLTBOT_PORT, STARTUP_TIMEOUT_MS);
48
+ }
49
+
50
+ /**
51
+ * Build environment variables to pass to the container
52
+ */
53
+ function buildEnvVars(env: Record<string, unknown>): Record<string, string> {
54
+ const vars: Record<string, string> = {};
55
+
56
+ // AI Gateway priority
57
+ if (env.AI_GATEWAY_API_KEY) {
58
+ const baseUrl = String(env.AI_GATEWAY_BASE_URL || "");
59
+ if (baseUrl.includes("openai")) {
60
+ vars.OPENAI_API_KEY = String(env.AI_GATEWAY_API_KEY);
61
+ vars.OPENAI_BASE_URL = baseUrl.replace(/\\/$/, "");
62
+ } else {
63
+ vars.ANTHROPIC_API_KEY = String(env.AI_GATEWAY_API_KEY);
64
+ vars.ANTHROPIC_BASE_URL = baseUrl.replace(/\\/$/, "");
65
+ }
66
+ } else {
67
+ if (env.ANTHROPIC_API_KEY) vars.ANTHROPIC_API_KEY = String(env.ANTHROPIC_API_KEY);
68
+ if (env.OPENAI_API_KEY) vars.OPENAI_API_KEY = String(env.OPENAI_API_KEY);
69
+ }
70
+
71
+ // Gateway token
72
+ if (env.MOLTBOT_GATEWAY_TOKEN) {
73
+ vars.CLAWDBOT_GATEWAY_TOKEN = String(env.MOLTBOT_GATEWAY_TOKEN);
74
+ }
75
+
76
+ // Bot tokens
77
+ if (env.TELEGRAM_BOT_TOKEN) vars.TELEGRAM_BOT_TOKEN = String(env.TELEGRAM_BOT_TOKEN);
78
+ if (env.DISCORD_BOT_TOKEN) vars.DISCORD_BOT_TOKEN = String(env.DISCORD_BOT_TOKEN);
79
+ if (env.SLACK_BOT_TOKEN) vars.SLACK_BOT_TOKEN = String(env.SLACK_BOT_TOKEN);
80
+
81
+ if (env.DEV_MODE) vars.DEV_MODE = String(env.DEV_MODE);
82
+
83
+ return vars;
84
+ }
85
+
86
+ /**
87
+ * Wait for a port to become available
88
+ */
89
+ async function waitForPort(
90
+ sandbox: any,
91
+ port: number,
92
+ timeoutMs: number
93
+ ): Promise<void> {
94
+ const start = Date.now();
95
+
96
+ while (Date.now() - start < timeoutMs) {
97
+ try {
98
+ const response = await sandbox.containerFetch(
99
+ new Request(\`http://localhost:\${port}/\`),
100
+ port
101
+ );
102
+ if (response.status < 500) return;
103
+ } catch {
104
+ // Port not ready yet
105
+ }
106
+ await new Promise((resolve) => setTimeout(resolve, 1000));
107
+ }
108
+
109
+ throw new Error(\`Moltbot gateway did not start within \${timeoutMs / 1000}s\`);
110
+ }
111
+ `;
112
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * GitHub Actions Workflow Template
3
+ *
4
+ * Generates the deploy.yml for CI/CD to Cloudflare.
5
+ */
6
+
7
+ export function generateDeployWorkflow(): string {
8
+ return `name: Deploy to Cloudflare
9
+
10
+ on:
11
+ push:
12
+ branches: [main]
13
+ workflow_dispatch:
14
+ inputs:
15
+ reason:
16
+ description: 'Reason for manual deployment'
17
+ required: false
18
+ default: 'Manual deployment'
19
+
20
+ jobs:
21
+ deploy:
22
+ runs-on: ubuntu-latest
23
+ name: Deploy Moltworker
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - name: Setup Node.js
28
+ uses: actions/setup-node@v4
29
+ with:
30
+ node-version: '20'
31
+
32
+ - name: Install dependencies
33
+ run: npm install
34
+
35
+ - name: Deploy to Cloudflare
36
+ uses: cloudflare/wrangler-action@v3
37
+ with:
38
+ apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
39
+ secrets: |
40
+ MCP_IDENTITY_PRIVATE_KEY
41
+ AGENTSHIELD_API_KEY
42
+ ANTHROPIC_API_KEY
43
+ env:
44
+ MCP_IDENTITY_PRIVATE_KEY: \${{ secrets.MCP_IDENTITY_PRIVATE_KEY }}
45
+ AGENTSHIELD_API_KEY: \${{ secrets.AGENTSHIELD_API_KEY }}
46
+ ANTHROPIC_API_KEY: \${{ secrets.ANTHROPIC_API_KEY }}
47
+ `;
48
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Health Module Template (src/routes/public.ts)
3
+ *
4
+ * Generates public routes including health checks and status endpoints.
5
+ */
6
+
7
+ export function generateHealthModule(projectName: string): string {
8
+ return `/**
9
+ * Public Routes
10
+ *
11
+ * Health checks and status endpoints — no authentication required.
12
+ */
13
+
14
+ import { Hono } from "hono";
15
+ import type { AppEnv } from "../types";
16
+
17
+ export const publicRoutes = new Hono<AppEnv>();
18
+
19
+ /**
20
+ * Basic health check
21
+ */
22
+ publicRoutes.get("/sandbox-health", (c) => {
23
+ return c.json({
24
+ status: "ok",
25
+ service: "${projectName}",
26
+ timestamp: new Date().toISOString(),
27
+ });
28
+ });
29
+
30
+ /**
31
+ * Detailed status with gateway check
32
+ */
33
+ publicRoutes.get("/api/status", async (c) => {
34
+ const sandbox = c.get("sandbox");
35
+
36
+ try {
37
+ const processes = await sandbox.ps();
38
+ const moltbot = processes.find(
39
+ (p: { command: string; status: string }) =>
40
+ (p.command.includes("start-moltbot.sh") || p.command.includes("clawdbot gateway")) &&
41
+ p.status === "running"
42
+ );
43
+
44
+ return c.json({
45
+ status: moltbot ? "running" : "starting",
46
+ service: "${projectName}",
47
+ identity: {
48
+ did: c.env.MCP_IDENTITY_AGENT_DID,
49
+ },
50
+ gateway: moltbot
51
+ ? { pid: moltbot.pid, status: moltbot.status }
52
+ : null,
53
+ });
54
+ } catch {
55
+ return c.json({
56
+ status: "unknown",
57
+ service: "${projectName}",
58
+ });
59
+ }
60
+ });
61
+ `;
62
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * .mcpi/identity.json Template
3
+ *
4
+ * Generates the public identity file that is committed to the repo.
5
+ * Contains the agent DID and public key — private key is a secret.
6
+ */
7
+
8
+ interface IdentityJsonOptions {
9
+ did: string;
10
+ publicKey: string;
11
+ agentName?: string;
12
+ agentDescription?: string;
13
+ }
14
+
15
+ export function generateIdentityJson(opts: IdentityJsonOptions): string {
16
+ return JSON.stringify(
17
+ {
18
+ version: '1.0',
19
+ type: 'molti-agent',
20
+ did: opts.did,
21
+ publicKey: opts.publicKey,
22
+ agentName: opts.agentName || undefined,
23
+ agentDescription: opts.agentDescription || undefined,
24
+ createdAt: new Date().toISOString(),
25
+ },
26
+ null,
27
+ 2
28
+ );
29
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Identity Module Template (src/identity.ts)
3
+ *
4
+ * Generates the MCP-I identity provider initialization code.
5
+ * Uses @kya-os/mcp-i-cloudflare for Cloudflare-specific providers.
6
+ */
7
+
8
+ export function generateIdentityModule(): string {
9
+ return `/**
10
+ * MCP-I Identity Provider
11
+ *
12
+ * Initializes cryptographic identity from environment variables.
13
+ * Uses @kya-os/mcp-i-cloudflare for Cloudflare Workers-compatible
14
+ * Ed25519 signing via Web Crypto API.
15
+ */
16
+
17
+ import {
18
+ WebCryptoProvider,
19
+ KVNonceCacheProvider,
20
+ CloudflareProofGenerator,
21
+ } from "@kya-os/mcp-i-cloudflare";
22
+
23
+ interface IdentityConfig {
24
+ did: string;
25
+ publicKey: string;
26
+ privateKey: string;
27
+ }
28
+
29
+ interface IdentityProviderResult {
30
+ proofGenerator: InstanceType<typeof CloudflareProofGenerator>;
31
+ config: IdentityConfig;
32
+ }
33
+
34
+ /**
35
+ * Get the identity provider from environment
36
+ */
37
+ export function getIdentityProvider(env: {
38
+ MCP_IDENTITY_AGENT_DID: string;
39
+ MCP_IDENTITY_PUBLIC_KEY: string;
40
+ MCP_IDENTITY_PRIVATE_KEY: string;
41
+ NONCE_CACHE: KVNamespace;
42
+ PROOF_ARCHIVE: KVNamespace;
43
+ }): IdentityProviderResult {
44
+ const config: IdentityConfig = {
45
+ did: env.MCP_IDENTITY_AGENT_DID,
46
+ publicKey: env.MCP_IDENTITY_PUBLIC_KEY,
47
+ privateKey: env.MCP_IDENTITY_PRIVATE_KEY,
48
+ };
49
+
50
+ const cryptoProvider = new WebCryptoProvider();
51
+ const nonceCache = new KVNonceCacheProvider(env.NONCE_CACHE);
52
+
53
+ const proofGenerator = new CloudflareProofGenerator(
54
+ cryptoProvider,
55
+ nonceCache,
56
+ {
57
+ did: config.did,
58
+ privateKey: config.privateKey,
59
+ publicKey: config.publicKey,
60
+ }
61
+ );
62
+
63
+ return { proofGenerator, config };
64
+ }
65
+
66
+ /**
67
+ * Generate a proof for a tool execution
68
+ */
69
+ export async function generateProof(
70
+ proofGenerator: InstanceType<typeof CloudflareProofGenerator>,
71
+ toolName: string,
72
+ input: unknown,
73
+ output: unknown
74
+ ): Promise<string | null> {
75
+ try {
76
+ const proof = await proofGenerator.generateProof({
77
+ toolName,
78
+ input: JSON.stringify(input),
79
+ output: JSON.stringify(output),
80
+ timestamp: new Date().toISOString(),
81
+ });
82
+ return proof;
83
+ } catch {
84
+ // Proof generation is non-critical — don't block tool execution
85
+ return null;
86
+ }
87
+ }
88
+ `;
89
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Moltbot Config Template (moltbot.json.template)
3
+ *
4
+ * Default configuration for the Moltbot gateway.
5
+ */
6
+
7
+ export function generateMoltbotConfig(): string {
8
+ return JSON.stringify(
9
+ {
10
+ agents: {
11
+ defaults: {
12
+ workspace: '/root/clawd',
13
+ },
14
+ },
15
+ gateway: {
16
+ port: 18789,
17
+ mode: 'local',
18
+ },
19
+ },
20
+ null,
21
+ 2
22
+ );
23
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * package.json Template
3
+ *
4
+ * Generates the package.json for the scaffolded Moltworker project.
5
+ */
6
+
7
+ import type { MoltiPackageVersions } from '../helpers/get-package-versions.js';
8
+
9
+ interface PackageJsonOptions {
10
+ projectName: string;
11
+ versions: MoltiPackageVersions;
12
+ }
13
+
14
+ export function generatePackageJson(opts: PackageJsonOptions): string {
15
+ const { projectName, versions } = opts;
16
+
17
+ return JSON.stringify(
18
+ {
19
+ name: projectName,
20
+ version: '0.1.0',
21
+ private: true,
22
+ scripts: {
23
+ deploy: 'wrangler deploy',
24
+ dev: 'wrangler dev',
25
+ start: 'wrangler dev',
26
+ 'type-check': 'tsc --noEmit',
27
+ 'cf-typegen': 'wrangler types',
28
+ },
29
+ dependencies: {
30
+ '@cloudflare/sandbox': 'latest',
31
+ '@kya-os/mcp-i-core': versions['@kya-os/mcp-i-core'],
32
+ '@kya-os/mcp-i-cloudflare': versions['@kya-os/mcp-i-cloudflare'],
33
+ '@kya-os/contracts': versions['@kya-os/contracts'],
34
+ hono: '^4.11.6',
35
+ jose: '^6.0.0',
36
+ },
37
+ devDependencies: {
38
+ '@cloudflare/workers-types': '^4.20251126.0',
39
+ typescript: '^5.6.2',
40
+ wrangler: '^4.61.1',
41
+ },
42
+ },
43
+ null,
44
+ 2
45
+ );
46
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * README.md Template
3
+ *
4
+ * Generates documentation for the scaffolded project.
5
+ */
6
+
7
+ interface ReadmeOptions {
8
+ projectName: string;
9
+ agentName?: string;
10
+ agentDescription?: string;
11
+ agentShieldProjectId?: string;
12
+ }
13
+
14
+ export function generateReadme(opts: ReadmeOptions): string {
15
+ const { projectName, agentName, agentDescription, agentShieldProjectId } = opts;
16
+ const displayName = agentName || projectName;
17
+ const description = agentDescription || 'AI agent running on Cloudflare Workers with MCP-I identity';
18
+
19
+ const dashboardUrl = agentShieldProjectId
20
+ ? `https://kya.vouched.id/dashboard/bouncer/${agentShieldProjectId}`
21
+ : 'https://kya.vouched.id/dashboard/bouncer';
22
+
23
+ return `# ${displayName}
24
+
25
+ ${description}
26
+
27
+ Built with [Moltworker](https://github.com/cloudflare/moltworker) + [MCP-I Identity](https://github.com/modelcontextprotocol-identity/xmcp-i).
28
+
29
+ ## Quick Start
30
+
31
+ 1. **Install dependencies**
32
+ \`\`\`bash
33
+ npm install
34
+ \`\`\`
35
+
36
+ 2. **Configure secrets**
37
+ \`\`\`bash
38
+ # Add your AI provider key
39
+ wrangler secret put ANTHROPIC_API_KEY
40
+ # or
41
+ wrangler secret put OPENAI_API_KEY
42
+
43
+ # Identity private key (already set if deployed via AgentShield)
44
+ wrangler secret put MCP_IDENTITY_PRIVATE_KEY
45
+
46
+ # AgentShield API key (for proof reporting)
47
+ wrangler secret put AGENTSHIELD_API_KEY
48
+ \`\`\`
49
+
50
+ 3. **Deploy**
51
+ \`\`\`bash
52
+ npm run deploy
53
+ \`\`\`
54
+
55
+ ## Architecture
56
+
57
+ \`\`\`
58
+ Cloudflare Worker (Hono)
59
+ \u251c\u2500\u2500 /sandbox-health \u2192 Health check (public)
60
+ \u251c\u2500\u2500 /api/status \u2192 Detailed status (public)
61
+ \u251c\u2500\u2500 /api/* \u2192 Protected API (CF Access)
62
+ \u251c\u2500\u2500 /_admin/* \u2192 Admin UI (CF Access)
63
+ \u2514\u2500\u2500 /* \u2192 Proxy to Moltbot container (port 18789)
64
+
65
+ Container (Cloudflare Sandbox)
66
+ \u251c\u2500\u2500 OpenClaw runtime (clawdbot)
67
+ \u251c\u2500\u2500 Node.js 22
68
+ \u2514\u2500\u2500 R2-backed persistent storage
69
+ \`\`\`
70
+
71
+ ## MCP-I Identity
72
+
73
+ This agent has a cryptographic identity:
74
+ - **DID**: See \`.mcpi/identity.json\`
75
+ - **Proof Generation**: Tool executions are signed with Ed25519
76
+ - **Nonce Replay Prevention**: Via KV-backed nonce cache
77
+ - **Proof Archive**: Historical proofs stored in KV
78
+
79
+ ## AgentShield Dashboard
80
+
81
+ Monitor and configure your agent: ${dashboardUrl}
82
+
83
+ ## Environment Variables
84
+
85
+ | Variable | Description | Required |
86
+ |----------|-------------|----------|
87
+ | \`MCP_IDENTITY_PRIVATE_KEY\` | Agent's Ed25519 private key | Yes |
88
+ | \`ANTHROPIC_API_KEY\` | Anthropic API key | Yes* |
89
+ | \`OPENAI_API_KEY\` | OpenAI API key | Yes* |
90
+ | \`AGENTSHIELD_API_KEY\` | AgentShield API key | Recommended |
91
+ | \`CLOUDFLARE_API_TOKEN\` | Wrangler deployment token | For CI/CD |
92
+ | \`CF_ACCESS_TEAM_DOMAIN\` | CF Access team domain | For auth |
93
+ | \`CF_ACCESS_AUD\` | CF Access audience tag | For auth |
94
+
95
+ *At least one AI provider key is required.
96
+
97
+ ## License
98
+
99
+ MIT
100
+ `;
101
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Startup Script Template (start-moltbot.sh)
3
+ *
4
+ * Generates the bash script that runs inside the container
5
+ * to initialize config and start the Moltbot gateway.
6
+ */
7
+
8
+ export function generateStartupScript(): string {
9
+ return `#!/bin/bash
10
+ set -e
11
+
12
+ CONFIG_DIR="/root/.clawdbot"
13
+ CONFIG_FILE="\${CONFIG_DIR}/moltbot.json"
14
+ TEMPLATE_FILE="/root/.clawdbot-templates/moltbot.json.template"
15
+ BACKUP_DIR="/data/moltbot/.clawdbot"
16
+
17
+ # Exit early if already running
18
+ if pgrep -f 'clawdbot gateway' > /dev/null 2>&1; then
19
+ echo "Moltbot gateway is already running, exiting."
20
+ exit 0
21
+ fi
22
+
23
+ # Restore from R2 backup if newer
24
+ if [ -d "\${BACKUP_DIR}" ] && [ -f "\${BACKUP_DIR}/moltbot.json" ]; then
25
+ BACKUP_MTIME=\$(stat -c %Y "\${BACKUP_DIR}/moltbot.json" 2>/dev/null || echo 0)
26
+ CONFIG_MTIME=\$(stat -c %Y "\${CONFIG_FILE}" 2>/dev/null || echo 0)
27
+
28
+ if [ "\${BACKUP_MTIME}" -gt "\${CONFIG_MTIME}" ]; then
29
+ echo "Restoring config from R2 backup..."
30
+ rsync -a "\${BACKUP_DIR}/" "\${CONFIG_DIR}/"
31
+ fi
32
+ fi
33
+
34
+ # Initialize config from template if needed
35
+ if [ ! -f "\${CONFIG_FILE}" ]; then
36
+ if [ -f "\${TEMPLATE_FILE}" ]; then
37
+ cp "\${TEMPLATE_FILE}" "\${CONFIG_FILE}"
38
+ echo "Initialized config from template"
39
+ else
40
+ echo '{"agents":{"defaults":{"workspace":"/root/clawd"}},"gateway":{"port":18789,"mode":"local"}}' > "\${CONFIG_FILE}"
41
+ echo "Initialized config with defaults"
42
+ fi
43
+ fi
44
+
45
+ echo "Starting Moltbot gateway on port 18789..."
46
+
47
+ # Start gateway with or without token
48
+ if [ -n "\${CLAWDBOT_GATEWAY_TOKEN}" ]; then
49
+ exec clawdbot gateway --port 18789 --verbose --bind 0.0.0.0 --token "\${CLAWDBOT_GATEWAY_TOKEN}"
50
+ else
51
+ exec clawdbot gateway --port 18789 --verbose --bind 0.0.0.0 --allow-unconfigured
52
+ fi
53
+ `;
54
+ }