create-agents24-app 0.2.1 → 0.2.3

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 (29) hide show
  1. package/README.md +21 -3
  2. package/dist/{chunk-ADXMZ3TT.js → chunk-F2J72UHQ.js} +35 -2
  3. package/dist/chunk-F2J72UHQ.js.map +1 -0
  4. package/dist/cli.js +44 -23
  5. package/dist/cli.js.map +1 -1
  6. package/dist/index.d.ts +5 -1
  7. package/dist/index.js +5 -1
  8. package/dist/scaffold/src/components/chat/chat-composer.tsx +4 -2
  9. package/dist/scaffold-manifest.json +1 -1
  10. package/package.json +2 -2
  11. package/templates/common/README.md +6 -2
  12. package/templates/common/_gitignore +2 -0
  13. package/templates/integrations/bff/server/index.ts +11 -21
  14. package/templates/integrations/nextjs/app/api/agents24/[[...path]]/route.ts +14 -0
  15. package/templates/integrations/nextjs/app/chat.tsx +8 -0
  16. package/templates/integrations/nextjs/app/layout.tsx +10 -0
  17. package/templates/integrations/nextjs/app/page.tsx +8 -0
  18. package/templates/integrations/nextjs/next-env.d.ts +2 -0
  19. package/templates/integrations/nextjs/next.config.ts +13 -0
  20. package/templates/integrations/nextjs/postcss.config.mjs +1 -0
  21. package/templates/integrations/nextjs/proxy.ts +29 -0
  22. package/templates/integrations/nextjs/src/chat-app.tsx +23 -0
  23. package/templates/integrations/nextjs/tsconfig.json +21 -0
  24. package/templates/{integrations → shared}/bff/server/env.ts +24 -21
  25. package/templates/shared/bff/server/handler.ts +23 -0
  26. package/templates/{integrations → shared}/bff/server/principal.ts +2 -2
  27. package/templates/{integrations → shared}/bff/src/host-identity.ts +1 -1
  28. package/versions.json +6 -2
  29. package/dist/chunk-ADXMZ3TT.js.map +0 -1
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # create-agents24-app
2
2
 
3
- Last Updated: 2026-09-02
3
+ Last Updated: 2026-09-07
4
4
 
5
- Create a canonical Agents24 React/Vite application:
5
+ Create a canonical Agents24 React application:
6
6
 
7
7
  ```bash
8
8
  npm create agents24-app@latest
@@ -28,7 +28,15 @@ Use `--starter deep-research` for the Planner/Researcher/Critic template, or omi
28
28
 
29
29
  The generator fetches the active compatible catalog and downloads only the selected immutable Package V2 archive. It verifies the advertised size and SHA-256 before extracting an editable `agents24/` tree with a fresh package identity. `customer-support` contains the Support Agent and empty reranked RAG foundation; `deep-research` contains the bounded Planner, Researcher, and Critic architecture with the same optional knowledge foundation. Templates never ingest content or configure credentials. `setup` combines apply, publish, and application configuration.
30
30
 
31
- Choose a direct client deployment or a server-backed BFF, then paste a preset code from [shadcn/create](https://ui.shadcn.com/create). Soft preset `b2D1FHzlY` is the canonical default.
31
+ Choose a server-backed BFF (default) or direct client deployment. BFF offers Next.js (default) or Vite + Hono; direct client uses Vite. The Agent starter is an independent choice. Then paste a preset code from [shadcn/create](https://ui.shadcn.com/create). Soft preset `b2D1FHzlY` is the canonical default.
32
+
33
+ ```bash
34
+ npm create agents24-app@latest my-app -- --integration bff --stack nextjs
35
+ npm create agents24-app@latest my-app -- --integration bff --stack vite-hono
36
+ npm create agents24-app@latest my-app -- --integration client-deployment
37
+ ```
38
+
39
+ `--stack` accepts `nextjs`, `vite-hono`, or `vite`; invalid integration/stack combinations fail before generation. `--yes` now defaults to BFF + Next.js, replacing the old direct-client default. Existing Hono apps remain supported by lifecycle commands, including apps without `agents24.stack` metadata; generation does not migrate them.
32
40
 
33
41
  The normal flow does not ask for an API base URL. Generated apps use `https://api.agents24.dev`; `--base-url` remains an advanced override for localhost, staging, private deployments, or proxies. Direct mode wires public deployment authentication through the browser session controller. BFF mode exposes a Guest host-identity adapter for customer-owned identity and login/logout navigation.
34
42
 
@@ -55,4 +63,14 @@ points to the same canonical scaffold and package guidance.
55
63
 
56
64
  ## Maintainer development
57
65
 
66
+ The stack-selection change is implemented in source and awaits canonical package publication and actual Vercel qualification. Do not assume the currently published `latest` contains it until release receipts confirm that version.
67
+
68
+ ## Hosting
69
+
70
+ Next.js uses Node 22/24, builds without runtime credentials, and starts with the generated `build`/`start` scripts on Vercel, Railway, Render, or another Node host. For containers, enable `output: "standalone"` in `next.config.ts` before building; package `.next/static` and any `public` assets with the standalone server. Its nonce-based CSP requires dynamic, non-cached HTML. Browser BFF requests stay same-origin and credentials remain server-only.
71
+
72
+ Vite + Hono keeps its Node-server deployment. It does not generate a Vercel serverless adapter. Set host environment variables separately: `agents24 publish` publishes Agent resources, and `setup` configures the local app; neither deploys your website or sets up Artifact hosting.
73
+
74
+ ## Local package development
75
+
58
76
  From the repository root, `pnpm dev:agents24` incrementally prepares the current coordinated package train, publishes it to an ephemeral loopback registry, launches this packed interactive CLI, installs the selected app, and starts it. To refresh an existing isolated generated app after every package source or version change, use `pnpm dev:agents24 -- --serve /absolute/path/to/app`; it force-reinstalls that app. Use `pnpm dev:agents24 -- --template customer-support` or `--template deep-research` to generate and set up an official template against the platform catalog. Set `AGENTS24_BASE_URL` when targeting a local backend. Unchanged tarballs, scans, and packed runners are reused from the bounded development cache; add `--fresh` for a clean rebuild.
@@ -2,6 +2,14 @@
2
2
 
3
3
  // src/types.ts
4
4
  var INTEGRATIONS = ["client-deployment", "bff"];
5
+ var STACKS = ["nextjs", "vite-hono", "vite"];
6
+ function resolveStack(integration, stack) {
7
+ const selected = stack ?? (integration === "bff" ? "nextjs" : "vite");
8
+ if (!INTEGRATIONS.includes(integration) || !STACKS.includes(selected) || (integration === "bff" ? selected === "vite" : selected !== "vite")) {
9
+ throw new Error(`Invalid stack/integration combination: ${selected} with ${integration}. Use bff with nextjs or vite-hono, or client-deployment with vite.`);
10
+ }
11
+ return selected;
12
+ }
5
13
  var PACKAGE_MANAGERS = ["pnpm", "npm", "yarn", "bun"];
6
14
  var DEFAULT_PRESET = "b2D1FHzlY";
7
15
 
@@ -98,6 +106,21 @@ function generatedManifest(options, name) {
98
106
  };
99
107
  if (options.integration === "bff") {
100
108
  dependencies["@agents24/node"] = versions.agents24["@agents24/node"];
109
+ dependencies.zod = versions.runtime.zod;
110
+ }
111
+ if (options.stack === "nextjs") {
112
+ dependencies.next = versions.runtime.next;
113
+ dependencies["server-only"] = versions.runtime["server-only"];
114
+ delete devDependencies.vite;
115
+ delete devDependencies["@vitejs/plugin-react"];
116
+ delete devDependencies["@tailwindcss/vite"];
117
+ devDependencies["@tailwindcss/postcss"] = versions.development["@tailwindcss/postcss"];
118
+ scripts.dev = "next dev";
119
+ scripts.build = "next build";
120
+ scripts.start = "next start";
121
+ delete scripts.preview;
122
+ }
123
+ if (options.stack === "vite-hono") {
101
124
  dependencies.hono = versions.runtime.hono;
102
125
  dependencies["@hono/node-server"] = versions.runtime["@hono/node-server"];
103
126
  devDependencies.concurrently = versions.development.concurrently;
@@ -115,6 +138,7 @@ function generatedManifest(options, name) {
115
138
  engines: { node: "^22.0.0 || ^24.0.0" },
116
139
  agents24: {
117
140
  integration: options.integration,
141
+ stack: options.stack,
118
142
  package_manager: options.packageManager,
119
143
  preset: options.preset,
120
144
  scaffold_sha256: scaffoldManifest.sha256,
@@ -219,6 +243,7 @@ function applyShadcnPreset(directory, preset) {
219
243
  clearPresetInstallArtifacts(directory);
220
244
  }
221
245
  function createApp(options) {
246
+ options = { ...options, stack: resolveStack(options.integration, options.stack) };
222
247
  const destination = resolve(options.directory);
223
248
  assertDestination(destination);
224
249
  const name = packageName(destination);
@@ -230,12 +255,18 @@ function createApp(options) {
230
255
  cpSync(scaffoldRoot, staging, { recursive: true, force: true });
231
256
  rmSync(join(staging, "manifest.json"), { force: true });
232
257
  copyLayer("common", staging);
233
- copyLayer(`integrations/${options.integration}`, staging);
258
+ if (options.integration === "bff") copyLayer("shared/bff", staging);
259
+ copyLayer(`integrations/${options.stack === "nextjs" ? "nextjs" : options.integration}`, staging);
260
+ if (options.stack === "nextjs") {
261
+ for (const file of ["index.html", "src/vite-env.d.ts"]) rmSync(join(staging, file), { force: true });
262
+ }
234
263
  materializeTemplate(staging, options);
235
264
  replaceTemplateValues(staging, {
236
265
  "__APP_NAME__": name,
237
266
  "__PRESET__": options.preset,
238
267
  "__INTEGRATION__": options.integration,
268
+ "__STACK__": options.stack,
269
+ "__HOSTING__": options.stack === "nextjs" ? "Next.js runs on Vercel or any supported Node host, including Railway and Render. Configure server variables from `.env.example` in your host; `next build` does not need runtime credentials. For containers, enable `output: 'standalone'` in `next.config.ts` before building, then copy `.next/standalone`, `.next/static` (to `.next/static` in the standalone directory), and `public` if present, then run `node server.js` with `HOSTNAME=0.0.0.0`. The document CSP uses a fresh nonce and dynamic HTML rendering. BFF routes are never cached. Streaming duration is limited by your hosting plan; the route requests 300 seconds." : options.stack === "vite-hono" ? "The production command runs the Hono Node server and serves the built Vite frontend. Configure server variables from `.env.example` in your host. This Node template does not include a Vercel serverless routing adapter." : "Deploy `dist/` to a static host. The preview command is for local verification. Configure the exact public origin in your Client Deployment and set its public build variables before building.",
239
270
  "__CONNECT_SOURCE__": options.integration === "client-deployment" ? " __AGENTS24_CONNECT_SOURCE__" : "",
240
271
  "__PM_DEV__": runScriptCommand(options.packageManager, "dev"),
241
272
  "__PM_BUILD__": runScriptCommand(options.packageManager, "build"),
@@ -411,6 +442,8 @@ async function selectTemplate(baseUrl, catalog, id) {
411
442
 
412
443
  export {
413
444
  INTEGRATIONS,
445
+ STACKS,
446
+ resolveStack,
414
447
  PACKAGE_MANAGERS,
415
448
  DEFAULT_PRESET,
416
449
  installDependencies,
@@ -419,4 +452,4 @@ export {
419
452
  compatibleTemplates,
420
453
  selectTemplate
421
454
  };
422
- //# sourceMappingURL=chunk-ADXMZ3TT.js.map
455
+ //# sourceMappingURL=chunk-F2J72UHQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/generator.ts","../src/template-catalog.ts"],"sourcesContent":["export const INTEGRATIONS = [\"client-deployment\", \"bff\"] as const;\nexport const STACKS = [\"nextjs\", \"vite-hono\", \"vite\"] as const;\nexport type Stack = (typeof STACKS)[number];\n\nexport function resolveStack(integration: Integration, stack?: Stack): Stack {\n const selected = stack ?? (integration === \"bff\" ? \"nextjs\" : \"vite\");\n if (!INTEGRATIONS.includes(integration) || !STACKS.includes(selected) ||\n (integration === \"bff\" ? selected === \"vite\" : selected !== \"vite\")) {\n throw new Error(`Invalid stack/integration combination: ${selected} with ${integration}. Use bff with nextjs or vite-hono, or client-deployment with vite.`);\n }\n return selected;\n}\nexport const PACKAGE_MANAGERS = [\"pnpm\", \"npm\", \"yarn\", \"bun\"] as const;\nexport const DEFAULT_PRESET = \"b2D1FHzlY\";\n\nexport type Integration = (typeof INTEGRATIONS)[number];\nexport type PackageManager = (typeof PACKAGE_MANAGERS)[number];\nexport type Starter = string;\n\nexport type TemplateSelection = {\n id: Starter;\n version: string;\n displayName: string;\n sha256: string;\n catalogRevision: string;\n files: Map<string, string>;\n};\n\nexport type CreateAppOptions = {\n directory: string;\n integration: Integration;\n stack?: Stack;\n preset: string;\n packageManager: PackageManager;\n install: boolean;\n baseUrl: string;\n starter?: TemplateSelection;\n deploymentId?: string;\n agentId?: string;\n agentAlias?: string;\n agentVersionId?: string;\n};\n\nexport type GeneratedApp = {\n directory: string;\n packageName: string;\n};\n","import { spawnSync } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport {\n chmodSync,\n cpSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { createRequire } from \"node:module\";\n\nimport { DEFAULT_PRESET, resolveStack, type CreateAppOptions, type GeneratedApp, type PackageManager } from \"./types.js\";\n\ntype Versions = {\n agents24: Record<string, string>;\n runtime: Record<string, string>;\n development: Record<string, string>;\n};\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), \"..\");\nconst templateRoot = join(packageRoot, \"templates\");\nconst scaffoldRoot = join(packageRoot, \"dist/scaffold\");\nconst scaffoldManifest = JSON.parse(readFileSync(join(packageRoot, \"dist/scaffold-manifest.json\"), \"utf8\")) as {\n dependencies: Record<string, string>;\n devDependencies: Record<string, string>;\n sha256: string;\n};\nconst versions = JSON.parse(readFileSync(join(packageRoot, \"versions.json\"), \"utf8\")) as Versions;\nconst require = createRequire(import.meta.url);\n\nfunction packageName(directory: string): string {\n const value = basename(resolve(directory))\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, \"-\")\n .replace(/^[._-]+|[._-]+$/g, \"\");\n if (!value || !/^[a-z0-9]/.test(value)) throw new Error(\"The destination does not produce a valid npm package name.\");\n return value;\n}\n\nfunction assertDestination(destination: string): void {\n if (!existsSync(destination)) return;\n if (!statSync(destination).isDirectory()) throw new Error(\"The destination already exists and is not a directory.\");\n if (readdirSync(destination).length > 0) throw new Error(\"The destination directory must be empty.\");\n}\n\nfunction walk(directory: string): string[] {\n return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {\n const path = join(directory, entry.name);\n return entry.isDirectory() ? walk(path) : [path];\n });\n}\n\nfunction replaceTemplateValues(directory: string, replacements: Record<string, string>): void {\n for (const file of walk(directory)) {\n if (file.endsWith(\".png\") || file.endsWith(\".ico\")) continue;\n let content = readFileSync(file, \"utf8\");\n for (const [token, value] of Object.entries(replacements)) content = content.split(token).join(value);\n writeFileSync(file, content);\n }\n}\n\nfunction copyLayer(name: string, destination: string): void {\n cpSync(join(templateRoot, name), destination, { recursive: true, force: true });\n}\n\nfunction materializeTemplate(destination: string, options: CreateAppOptions): void {\n if (!options.starter) return;\n const packageId = `pkg_${randomBytes(16).toString(\"hex\")}`;\n let replacedManifest = false;\n for (const [path, original] of options.starter.files) {\n let content = original;\n if (path === \"agents24.yaml\") {\n content = content.replace(/^(package_id:\\s*)[^\\s#]+/m, `$1${packageId}`);\n replacedManifest = content !== original;\n }\n const target = join(destination, \"agents24\", path);\n mkdirSync(dirname(target), { recursive: true });\n writeFileSync(target, content);\n }\n if (!replacedManifest) throw new Error(\"The selected Agent template has no replaceable package_id.\");\n}\n\nfunction generatedManifest(options: CreateAppOptions, name: string): Record<string, unknown> {\n const dependencies: Record<string, string> = {\n \"@agents24/client\": versions.agents24[\"@agents24/client\"]!,\n \"@agents24/react\": versions.agents24[\"@agents24/react\"]!,\n \"@agents24/chat-react\": versions.agents24[\"@agents24/chat-react\"]!,\n ...scaffoldManifest.dependencies,\n react: versions.runtime.react!,\n \"react-dom\": versions.runtime[\"react-dom\"]!,\n };\n const devDependencies: Record<string, string> = {\n \"@types/node\": versions.development[\"@types/node\"]!,\n \"@types/react\": versions.development[\"@types/react\"]!,\n \"@types/react-dom\": versions.development[\"@types/react-dom\"]!,\n \"@vitejs/plugin-react\": versions.development[\"@vitejs/plugin-react\"]!,\n ...scaffoldManifest.devDependencies,\n typescript: versions.development.typescript!,\n vite: versions.development.vite!,\n };\n const scripts: Record<string, string> = {\n dev: \"vite\",\n build: \"tsc --noEmit && vite build\",\n preview: \"vite preview\",\n preset: \"node scripts/apply-preset.mjs\",\n };\n if (options.integration === \"bff\") {\n dependencies[\"@agents24/node\"] = versions.agents24[\"@agents24/node\"]!;\n dependencies.zod = versions.runtime.zod!;\n }\n if (options.stack === \"nextjs\") {\n dependencies.next = versions.runtime.next!;\n dependencies[\"server-only\"] = versions.runtime[\"server-only\"]!;\n delete devDependencies.vite;\n delete devDependencies[\"@vitejs/plugin-react\"];\n delete devDependencies[\"@tailwindcss/vite\"];\n devDependencies[\"@tailwindcss/postcss\"] = versions.development[\"@tailwindcss/postcss\"]!;\n scripts.dev = \"next dev\";\n scripts.build = \"next build\";\n scripts.start = \"next start\";\n delete scripts.preview;\n }\n if (options.stack === \"vite-hono\") {\n dependencies.hono = versions.runtime.hono!;\n dependencies[\"@hono/node-server\"] = versions.runtime[\"@hono/node-server\"]!;\n devDependencies.concurrently = versions.development.concurrently!;\n devDependencies.tsx = versions.development.tsx!;\n devDependencies.tsup = \"^8.5.1\";\n scripts.dev = \"concurrently -k -n web,bff \\\"vite\\\" \\\"tsx watch server/index.ts\\\"\";\n scripts.build = \"tsc --noEmit && vite build && tsup server/index.ts --format esm --platform node --out-dir server-dist --external @agents24/node --external hono --external @hono/node-server\";\n scripts.start = \"node server-dist/index.js --production\";\n }\n return {\n name,\n private: true,\n version: \"0.0.0\",\n type: \"module\",\n engines: { node: \"^22.0.0 || ^24.0.0\" },\n agents24: {\n integration: options.integration,\n stack: options.stack,\n package_manager: options.packageManager,\n preset: options.preset,\n scaffold_sha256: scaffoldManifest.sha256,\n ...(options.starter ? { template: {\n id: options.starter.id,\n version: options.starter.version,\n sha256: options.starter.sha256,\n catalog_revision: options.starter.catalogRevision,\n } } : {}),\n },\n scripts,\n dependencies,\n devDependencies,\n };\n}\n\nfunction envFiles(options: CreateAppOptions, appName: string): { example: string; local: string } {\n const value = (input: string | undefined) => JSON.stringify(String(input || \"\"));\n const jsonValue = (input: unknown) => JSON.stringify(input);\n const baseUrlOverride = options.baseUrl === \"https://api.agents24.dev\" ? [] : [\n `${options.integration === \"client-deployment\" ? \"VITE_\" : \"\"}AGENTS24_BASE_URL=${value(options.baseUrl)}`,\n ];\n if (options.integration === \"client-deployment\") {\n return {\n example: \"# VITE_AGENTS24_BASE_URL=http://localhost:8026 # optional advanced override\\nVITE_AGENTS24_DEPLOYMENT_ID=acd_your_public_deployment_id\\n\",\n local: [...baseUrlOverride, ...(options.deploymentId ? [`VITE_AGENTS24_DEPLOYMENT_ID=${value(options.deploymentId)}`] : []), \"\"].join(\"\\n\"),\n };\n }\n return {\n example: [\n \"# AGENTS24_BASE_URL=http://localhost:8026 # optional advanced override\",\n \"AGENTS24_API_KEY=your_server_only_api_key\",\n \"# agentVersion accepts draft, latest, or an exact published version such as v1\",\n \"AGENTS24_AGENTS=[{\\\"agentAlias\\\":\\\"your-agent-alias\\\",\\\"agentVersion\\\":\\\"v1\\\"}]\",\n \"# agentId remains supported instead of agentAlias when UUID configuration is preferred\",\n \"AGENTS24_INTEGRATION_ID=generate_one_stable_random_value\",\n \"AGENTS24_INTEGRATION_NAME=your_app_name # optional\",\n \"# AGENTS24_RUNTIME_TARGET=draft # optional server-only override\",\n \"SESSION_COOKIE_SECRET=generate_at_least_32_random_bytes\",\n \"PORT=3001\",\n \"\",\n ].join(\"\\n\"),\n local: [\n ...baseUrlOverride,\n ...(options.agentAlias || options.agentId ? [\n `AGENTS24_AGENTS=${jsonValue([{ ...(options.agentAlias ? { agentAlias: options.agentAlias } : { agentId: options.agentId }), ...(options.agentVersionId ? { agentVersionId: options.agentVersionId } : {}) }])}`,\n ] : []),\n `AGENTS24_INTEGRATION_ID=${value(randomBytes(24).toString(\"base64url\"))}`,\n `AGENTS24_INTEGRATION_NAME=${value(appName)}`,\n `SESSION_COOKIE_SECRET=${value(randomBytes(32).toString(\"base64url\"))}`,\n \"PORT=3001\",\n \"\",\n ].join(\"\\n\"),\n };\n}\n\nfunction installCommand(packageManager: PackageManager): [string, string[]] {\n if (packageManager === \"npm\") return [\"npm\", [\"install\"]];\n if (packageManager === \"yarn\") return [\"yarn\", []];\n if (packageManager === \"bun\") return [\"bun\", [\"install\"]];\n return [\"pnpm\", [\"install\", \"--ignore-workspace\"]];\n}\n\nfunction runScriptCommand(packageManager: PackageManager, script: string): string {\n if (packageManager === \"npm\") return `npm run ${script}`;\n if (packageManager === \"bun\") return `bun run ${script}`;\n return `${packageManager} ${script}`;\n}\n\nexport function installDependencies(directory: string, packageManager: PackageManager): void {\n const [command, args] = installCommand(packageManager);\n const { AGENTS24_API_KEY: _apiKey, ...installerEnvironment } = process.env;\n const result = spawnSync(command, args, { cwd: directory, stdio: \"inherit\", env: installerEnvironment });\n if (result.error) throw new Error(`Could not start ${command}: ${result.error.message}`);\n if (result.status !== 0) throw new Error(`${command} ${args.join(\" \")} failed with exit ${result.status}.`);\n}\n\nfunction clearPresetInstallArtifacts(directory: string): void {\n for (const name of [\"node_modules\", \"bun.lock\", \"bun.lockb\", \"package-lock.json\", \"pnpm-lock.yaml\", \"yarn.lock\"]) {\n rmSync(join(directory, name), { recursive: true, force: true });\n }\n}\n\nfunction applyShadcnPreset(directory: string, preset: string): void {\n if (preset === DEFAULT_PRESET) return;\n const executable = require.resolve(\"shadcn\");\n const { AGENTS24_API_KEY: _apiKey, ...presetEnvironment } = process.env;\n const result = spawnSync(\n process.execPath,\n [executable, \"apply\", preset, \"--yes\", \"--silent\", \"--cwd\", directory],\n { cwd: directory, encoding: \"utf8\", env: presetEnvironment },\n );\n if (result.error) throw new Error(`Could not start Shadcn preset materialization: ${result.error.message}`);\n if (result.status !== 0) {\n const detail = String(result.stderr || result.stdout || \"\").trim().split(\"\\n\").at(-1);\n throw new Error(detail || `Shadcn could not apply preset ${preset}.`);\n }\n const scopeResult = spawnSync(\n process.execPath,\n [join(directory, \"scripts/scope-preset-theme.mjs\")],\n { cwd: directory, encoding: \"utf8\" },\n );\n if (scopeResult.error) throw new Error(`Could not scope the selected Shadcn preset: ${scopeResult.error.message}`);\n if (scopeResult.status !== 0) {\n const detail = String(scopeResult.stderr || scopeResult.stdout || \"\").trim().split(\"\\n\").at(-1);\n throw new Error(detail || `Could not scope Shadcn preset ${preset}.`);\n }\n clearPresetInstallArtifacts(directory);\n}\n\nexport function createApp(options: CreateAppOptions): GeneratedApp {\n options = { ...options, stack: resolveStack(options.integration, options.stack) };\n const destination = resolve(options.directory);\n assertDestination(destination);\n const name = packageName(destination);\n const parent = dirname(destination);\n mkdirSync(parent, { recursive: true });\n const staging = join(parent, `.${name}.agents24-${randomBytes(6).toString(\"hex\")}`);\n try {\n mkdirSync(staging, { mode: 0o700 });\n cpSync(scaffoldRoot, staging, { recursive: true, force: true });\n rmSync(join(staging, \"manifest.json\"), { force: true });\n copyLayer(\"common\", staging);\n if (options.integration === \"bff\") copyLayer(\"shared/bff\", staging);\n copyLayer(`integrations/${options.stack === \"nextjs\" ? \"nextjs\" : options.integration}`, staging);\n if (options.stack === \"nextjs\") {\n for (const file of [\"index.html\", \"src/vite-env.d.ts\"]) rmSync(join(staging, file), { force: true });\n }\n materializeTemplate(staging, options);\n replaceTemplateValues(staging, {\n \"__APP_NAME__\": name,\n \"__PRESET__\": options.preset,\n \"__INTEGRATION__\": options.integration,\n \"__STACK__\": options.stack!,\n \"__HOSTING__\": options.stack === \"nextjs\"\n ? \"Next.js runs on Vercel or any supported Node host, including Railway and Render. Configure server variables from `.env.example` in your host; `next build` does not need runtime credentials. For containers, enable `output: 'standalone'` in `next.config.ts` before building, then copy `.next/standalone`, `.next/static` (to `.next/static` in the standalone directory), and `public` if present, then run `node server.js` with `HOSTNAME=0.0.0.0`. The document CSP uses a fresh nonce and dynamic HTML rendering. BFF routes are never cached. Streaming duration is limited by your hosting plan; the route requests 300 seconds.\"\n : options.stack === \"vite-hono\"\n ? \"The production command runs the Hono Node server and serves the built Vite frontend. Configure server variables from `.env.example` in your host. This Node template does not include a Vercel serverless routing adapter.\"\n : \"Deploy `dist/` to a static host. The preview command is for local verification. Configure the exact public origin in your Client Deployment and set its public build variables before building.\",\n \"__CONNECT_SOURCE__\": options.integration === \"client-deployment\" ? \" __AGENTS24_CONNECT_SOURCE__\" : \"\",\n \"__PM_DEV__\": runScriptCommand(options.packageManager, \"dev\"),\n \"__PM_BUILD__\": runScriptCommand(options.packageManager, \"build\"),\n \"__PM_PRODUCTION__\": runScriptCommand(options.packageManager, options.integration === \"bff\" ? \"start\" : \"preview\"),\n \"__PM_PRESET__\": `${runScriptCommand(options.packageManager, \"preset\")} --`,\n \"__STARTER_SETUP__\": options.starter\n ? `## Set up the included Agent\\n\\nThis repository includes an editable Resource Package in \\`agents24/\\`. For a BFF, run \\`agents24 apply ./agents24\\` to reconcile drafts and \\`agents24 publish ./agents24\\` for production. For a direct-client app, run \\`agents24 setup ./agents24 --app .\\` so publication happens before deployment configuration. Use \\`agents24 dev ./agents24\\` when a local Artifact server is required.`\n : \"\",\n });\n const gitignore = join(staging, \"_gitignore\");\n if (existsSync(gitignore)) renameSync(gitignore, join(staging, \".gitignore\"));\n writeFileSync(join(staging, \"package.json\"), `${JSON.stringify(generatedManifest(options, name), null, 2)}\\n`);\n applyShadcnPreset(staging, options.preset);\n const env = envFiles(options, name);\n writeFileSync(join(staging, \".env.example\"), env.example);\n if (options.install) installDependencies(staging, options.packageManager);\n writeFileSync(join(staging, \".env.local\"), env.local, { mode: 0o600 });\n chmodSync(join(staging, \".env.local\"), 0o600);\n if (existsSync(destination)) rmSync(destination, { recursive: true });\n renameSync(staging, destination);\n return { directory: destination, packageName: name };\n } catch (error) {\n rmSync(staging, { recursive: true, force: true });\n throw error;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { unpackFiles } from \"@agents24/cli\";\n\nimport { type Starter, type TemplateSelection } from \"./types.js\";\n\ntype CatalogTemplate = {\n id: string;\n version: string;\n display_name: string;\n description: string;\n compatibility: { min_generator_version?: string; resource_package_schema?: string };\n archive: { sha256: string; size: number; download_url: string };\n};\n\ntype Catalog = {\n schema_version: \"agents24.template-catalog.v1\";\n revision: string;\n templates: CatalogTemplate[];\n};\n\ntype CachedCatalog = { etag?: string; catalog: Catalog };\n\nconst GENERATOR_VERSION = \"0.2.0\";\nconst SHA256 = /^[0-9a-f]{64}$/;\nconst SEMVER = /^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$/;\nconst TEMPLATE_ID = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;\n\nfunction cacheRoot(): string {\n const override = String(process.env.AGENTS24_TEMPLATE_CACHE_DIR || \"\").trim();\n if (override) return override;\n const platformRoot = process.platform === \"win32\"\n ? process.env.LOCALAPPDATA\n : process.env.XDG_CACHE_HOME || join(homedir(), \".cache\");\n return join(platformRoot || tmpdir(), \"agents24\", \"templates-v1\");\n}\n\nfunction atomicWrite(path: string, data: string | Uint8Array): void {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n const temporary = `${path}.${process.pid}.tmp`;\n writeFileSync(temporary, data, { mode: 0o600 });\n renameSync(temporary, path);\n}\n\nfunction parseVersion(value: string): [number, number, number] | null {\n const match = SEMVER.exec(value);\n return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;\n}\n\nfunction compatible(item: CatalogTemplate): boolean {\n const minimum = parseVersion(String(item.compatibility?.min_generator_version || \"0.0.0\"));\n const current = parseVersion(GENERATOR_VERSION)!;\n if (!minimum || item.compatibility?.resource_package_schema !== \"2.0\") return false;\n return current[0] > minimum[0]\n || (current[0] === minimum[0] && current[1] > minimum[1])\n || (current[0] === minimum[0] && current[1] === minimum[1] && current[2] >= minimum[2]);\n}\n\nfunction validateCatalog(value: unknown): Catalog {\n const catalog = value as Catalog;\n if (catalog?.schema_version !== \"agents24.template-catalog.v1\" || !SHA256.test(catalog.revision) || !Array.isArray(catalog.templates)) {\n throw new Error(\"The Agents24 template catalog is invalid.\");\n }\n const ids = new Set<string>();\n for (const item of catalog.templates) {\n if (!TEMPLATE_ID.test(item?.id) || ids.has(item.id) || !SEMVER.test(item.version)\n || !item.display_name || !SHA256.test(item.archive?.sha256) || !Number.isSafeInteger(item.archive?.size)\n || item.archive.size < 1 || item.archive.size > 5 * 1024 * 1024 || !item.archive.download_url?.startsWith(\"/templates/\")) {\n throw new Error(\"The Agents24 template catalog contains an invalid release.\");\n }\n ids.add(item.id);\n }\n return catalog;\n}\n\nfunction readCachedCatalog(path: string): CachedCatalog | null {\n try {\n const cached = JSON.parse(readFileSync(path, \"utf8\")) as CachedCatalog;\n return { ...(cached.etag ? { etag: cached.etag } : {}), catalog: validateCatalog(cached.catalog) };\n } catch {\n return null;\n }\n}\n\nexport async function loadTemplateCatalog(baseUrl: string): Promise<{ catalog: Catalog; live: boolean }> {\n const path = join(cacheRoot(), \"catalog.json\");\n const cached = existsSync(path) ? readCachedCatalog(path) : null;\n try {\n const response = await fetch(new URL(\"/templates\", `${baseUrl}/`), {\n headers: cached?.etag ? { \"If-None-Match\": cached.etag } : {},\n signal: AbortSignal.timeout(10_000),\n });\n if (response.status === 304 && cached) return { catalog: cached.catalog, live: true };\n if (!response.ok) throw new Error(`catalog request returned ${response.status}`);\n const catalog = validateCatalog(await response.json());\n const etag = response.headers.get(\"etag\") || undefined;\n atomicWrite(path, `${JSON.stringify({ ...(etag ? { etag } : {}), catalog })}\\n`);\n return { catalog, live: true };\n } catch (error) {\n if (cached) return { catalog: cached.catalog, live: false };\n const detail = error instanceof Error ? error.message : \"request failed\";\n throw new Error(`Could not load the Agents24 template catalog (${detail}), and no verified cached catalog is available.`);\n }\n}\n\nexport function compatibleTemplates(catalog: Catalog): CatalogTemplate[] {\n return catalog.templates.filter(compatible);\n}\n\nfunction verifiedArchive(path: string, item: CatalogTemplate): Uint8Array | null {\n try {\n const archive = readFileSync(path);\n if (archive.byteLength !== item.archive.size || createHash(\"sha256\").update(archive).digest(\"hex\") !== item.archive.sha256) return null;\n unpackFiles(archive);\n return archive;\n } catch {\n return null;\n }\n}\n\nasync function readArchiveResponse(response: Response, expectedSize: number): Promise<Uint8Array> {\n if (!response.body) throw new Error(\"Template download returned no archive body.\");\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let size = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.byteLength;\n if (size > expectedSize || size > 5 * 1024 * 1024) {\n await reader.cancel();\n throw new Error(\"Template download exceeds its advertised archive size.\");\n }\n chunks.push(value);\n }\n const archive = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) {\n archive.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return archive;\n}\n\nexport async function selectTemplate(baseUrl: string, catalog: Catalog, id: string): Promise<TemplateSelection> {\n if (id === \"rag\") throw new Error(\"The 'rag' starter was removed. Use --starter customer-support or --starter deep-research.\");\n const item = catalog.templates.find((candidate) => candidate.id === id);\n if (!item) throw new Error(`Template '${id}' is not available in the active catalog.`);\n if (!compatible(item)) throw new Error(`Template '${id}' requires a newer create-agents24-app release.`);\n const path = join(cacheRoot(), \"archives\", `${item.archive.sha256}.zip`);\n let archive = existsSync(path) ? verifiedArchive(path, item) : null;\n if (!archive) {\n let response: Response;\n try {\n response = await fetch(new URL(item.archive.download_url, `${baseUrl}/`), { signal: AbortSignal.timeout(30_000) });\n } catch (error) {\n throw new Error(`Could not download template '${id}', and no verified cached archive is available.`);\n }\n if (!response.ok) throw new Error(`Could not download template '${id}' (HTTP ${response.status}).`);\n const length = response.headers.get(\"content-length\");\n if (length && Number(length) !== item.archive.size) throw new Error(`Template '${id}' download size does not match the catalog.`);\n archive = await readArchiveResponse(response, item.archive.size);\n if (archive.byteLength !== item.archive.size || createHash(\"sha256\").update(archive).digest(\"hex\") !== item.archive.sha256) {\n throw new Error(`Template '${id}' failed integrity verification.`);\n }\n unpackFiles(archive);\n atomicWrite(path, archive);\n }\n return {\n id: item.id as Starter,\n version: item.version,\n displayName: item.display_name,\n sha256: item.archive.sha256,\n catalogRevision: catalog.revision,\n files: unpackFiles(archive),\n };\n}\n"],"mappings":"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","names":["require","existsSync","mkdirSync","readFileSync","renameSync","writeFileSync","dirname","join"]}
package/dist/cli.js CHANGED
@@ -3,11 +3,13 @@ import {
3
3
  DEFAULT_PRESET,
4
4
  INTEGRATIONS,
5
5
  PACKAGE_MANAGERS,
6
+ STACKS,
6
7
  compatibleTemplates,
7
8
  createApp,
8
9
  loadTemplateCatalog,
10
+ resolveStack,
9
11
  selectTemplate
10
- } from "./chunk-ADXMZ3TT.js";
12
+ } from "./chunk-F2J72UHQ.js";
11
13
 
12
14
  // src/cli.ts
13
15
  import { writeFileSync } from "fs";
@@ -18,6 +20,7 @@ import { intro, outro } from "@clack/prompts";
18
20
  import process from "process";
19
21
  var VALUE_FLAGS = /* @__PURE__ */ new Set([
20
22
  "integration",
23
+ "stack",
21
24
  "preset",
22
25
  "package-manager",
23
26
  "base-url",
@@ -59,6 +62,7 @@ Usage:
59
62
 
60
63
  Options:
61
64
  --integration <client-deployment|bff>
65
+ --stack <nextjs|vite-hono|vite> BFF defaults to Next.js; direct client uses Vite
62
66
  --preset <shadcn-preset-code> Defaults to b2D1FHzlY
63
67
  --package-manager <pnpm|npm|yarn|bun>
64
68
  --base-url <url>
@@ -122,6 +126,7 @@ async function resolveOptions(args) {
122
126
  const nonInteractive = args.flags.yes === true;
123
127
  let directory = args.directory;
124
128
  let integration = oneOf(flag(args, "integration"), INTEGRATIONS, "integration");
129
+ let stack = oneOf(flag(args, "stack"), STACKS, "stack");
125
130
  let preset = flag(args, "preset");
126
131
  let packageManager = oneOf(flag(args, "package-manager"), PACKAGE_MANAGERS, "package-manager");
127
132
  let baseUrl = flag(args, "base-url");
@@ -131,38 +136,33 @@ async function resolveOptions(args) {
131
136
  directory ||= await requiredText("Where should the app be created?", "my-agents24-app");
132
137
  if (!integration) {
133
138
  const result = await select({ message: "How should the app connect?", options: [
134
- { value: "client-deployment", label: "Client deployment", hint: "Direct anonymous browser connection" },
135
- { value: "bff", label: "Server BFF", hint: "API key remains on your Node server" }
139
+ { value: "bff", label: "Server BFF (recommended)", hint: "API key remains on your server" },
140
+ { value: "client-deployment", label: "Client deployment", hint: "Direct browser connection" }
136
141
  ] });
137
142
  cancelled(result);
138
143
  integration = result;
139
144
  }
140
- preset ||= await requiredText(
141
- "Shadcn preset code",
142
- DEFAULT_PRESET,
143
- (value) => PRESET.test(value) ? void 0 : "Enter a valid Shadcn preset code."
144
- );
145
- if (!packageManager) {
146
- const detected = detectedPackageManager();
147
- const result = await select({ message: "Package manager", initialValue: detected, options: PACKAGE_MANAGERS.map((value) => ({ value, label: value })) });
148
- cancelled(result);
149
- packageManager = result;
150
- }
151
- if (args.flags["no-install"] !== true) {
152
- const result = await confirm({ message: "Install dependencies?", initialValue: true });
145
+ if (integration === "bff" && !stack) {
146
+ const result = await select({ message: "Application stack", initialValue: "nextjs", options: [
147
+ { value: "nextjs", label: "Next.js (recommended)", hint: "Full-stack App Router application" },
148
+ { value: "vite-hono", label: "Vite + Hono", hint: "Vite frontend and Node server" }
149
+ ] });
153
150
  cancelled(result);
154
- install = result;
151
+ stack = result;
155
152
  }
156
153
  }
154
+ integration ||= "bff";
155
+ stack = resolveStack(integration, stack);
156
+ if (integration === "bff" && flag(args, "deployment-id")) throw new Error("--deployment-id requires --integration client-deployment.");
157
+ if (integration === "client-deployment" && ["agent-id", "agent-alias", "agent-version-id"].some((name) => flag(args, name))) {
158
+ throw new Error("Agent selectors require --integration bff.");
159
+ }
157
160
  directory = String(directory || "").trim();
158
- integration ||= "client-deployment";
159
- preset ||= DEFAULT_PRESET;
160
- packageManager ||= detectedPackageManager();
161
161
  baseUrl ||= "https://api.agents24.dev";
162
162
  const urlError = validateUrl(baseUrl);
163
163
  if (!directory) throw new Error("A destination directory is required.");
164
164
  if (urlError) throw new Error(urlError);
165
- if (!PRESET.test(preset)) throw new Error("--preset must be a valid Shadcn preset code.");
165
+ if (preset && !PRESET.test(preset)) throw new Error("--preset must be a valid Shadcn preset code.");
166
166
  let starter;
167
167
  if (requestedStarter || !nonInteractive) {
168
168
  const { catalog } = await loadTemplateCatalog(baseUrl);
@@ -181,10 +181,30 @@ async function resolveOptions(args) {
181
181
  }
182
182
  if (selectedId) starter = await selectTemplate(baseUrl, catalog, selectedId);
183
183
  }
184
+ if (!nonInteractive) {
185
+ preset ||= await requiredText(
186
+ "Shadcn preset code",
187
+ DEFAULT_PRESET,
188
+ (value) => PRESET.test(value) ? void 0 : "Enter a valid Shadcn preset code."
189
+ );
190
+ if (!packageManager) {
191
+ const detected = detectedPackageManager();
192
+ const result = await select({ message: "Package manager", initialValue: detected, options: PACKAGE_MANAGERS.map((value) => ({ value, label: value })) });
193
+ cancelled(result);
194
+ packageManager = result;
195
+ }
196
+ if (args.flags["no-install"] !== true) {
197
+ const result = await confirm({ message: "Install dependencies?", initialValue: true });
198
+ cancelled(result);
199
+ install = result;
200
+ }
201
+ }
202
+ preset ||= DEFAULT_PRESET;
203
+ packageManager ||= detectedPackageManager();
184
204
  if (integration === "client-deployment") {
185
205
  const deploymentId = flag(args, "deployment-id");
186
206
  if (deploymentId && !DEPLOYMENT_ID.test(deploymentId)) throw new Error("--deployment-id must be a valid public acd_\u2026 deployment ID.");
187
- return { directory, integration, preset, packageManager, install, baseUrl, starter, deploymentId };
207
+ return { directory, integration, stack, preset, packageManager, install, baseUrl, starter, deploymentId };
188
208
  }
189
209
  const fields = {
190
210
  agentId: flag(args, "agent-id"),
@@ -197,7 +217,7 @@ async function resolveOptions(args) {
197
217
  if (fields.agentAlias && !/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(fields.agentAlias)) {
198
218
  throw new Error("--agent-alias must be lowercase kebab-case.");
199
219
  }
200
- return { directory, integration, preset, packageManager, install, baseUrl, starter, ...fields };
220
+ return { directory, integration, stack, preset, packageManager, install, baseUrl, starter, ...fields };
201
221
  }
202
222
 
203
223
  // src/cli.ts
@@ -221,6 +241,7 @@ async function main() {
221
241
  ...generated,
222
242
  install: options.install,
223
243
  integration: options.integration,
244
+ stack: options.stack,
224
245
  packageManager: options.packageManager
225
246
  })}
226
247
  `, { mode: 384 });
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/arguments.ts","../src/prompts.ts"],"sourcesContent":["import { writeFileSync } from \"node:fs\";\nimport process from \"node:process\";\nimport { intro, outro } from \"@clack/prompts\";\n\nimport { HELP, parseArguments } from \"./arguments.js\";\nimport { createApp } from \"./generator.js\";\nimport { resolveOptions } from \"./prompts.js\";\n\nfunction scriptCommand(packageManager: string, script: string): string {\n if (packageManager === \"npm\") return `npm run ${script}`;\n if (packageManager === \"bun\") return `bun run ${script}`;\n return `${packageManager} ${script}`;\n}\n\nasync function main(): Promise<void> {\n const args = parseArguments();\n if (args.flags.help) {\n process.stdout.write(`${HELP}\\n`);\n return;\n }\n intro(\"Create Agents24 App\");\n const options = await resolveOptions(args);\n const generated = createApp(options);\n if (process.env.AGENTS24_CREATE_RESULT_FILE) {\n writeFileSync(process.env.AGENTS24_CREATE_RESULT_FILE, `${JSON.stringify({\n ...generated,\n install: options.install,\n integration: options.integration,\n packageManager: options.packageManager,\n })}\\n`, { mode: 0o600 });\n }\n const relative = generated.directory.startsWith(`${process.cwd()}/`)\n ? generated.directory.slice(process.cwd().length + 1)\n : generated.directory;\n const install = `${options.packageManager} install`;\n const productionScript = options.integration === \"bff\" ? \"start\" : \"preview\";\n outro([\n `Created ${generated.packageName}`,\n \"\",\n ` cd ${relative}`,\n ` ${install}${options.install ? \" # already completed\" : \"\"}`,\n ` ${scriptCommand(options.packageManager, \"dev\")}`,\n ` ${scriptCommand(options.packageManager, \"build\")}`,\n ` ${scriptCommand(options.packageManager, productionScript)}`,\n ].join(\"\\n\"));\n}\n\nmain().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : \"App creation failed.\";\n process.stderr.write(`create-agents24-app: ${message}\\n`);\n process.exitCode = 1;\n});\n","import process from \"node:process\";\n\nexport type ParsedArguments = {\n directory?: string;\n flags: Record<string, string | boolean>;\n};\n\nconst VALUE_FLAGS = new Set([\n \"integration\",\n \"preset\",\n \"package-manager\",\n \"base-url\",\n \"deployment-id\",\n \"agent-id\",\n \"agent-alias\",\n \"agent-version-id\",\n \"starter\",\n]);\nconst BOOLEAN_FLAGS = new Set([\"yes\", \"no-install\", \"help\"]);\n\nexport function parseArguments(argv = process.argv.slice(2)): ParsedArguments {\n const flags: Record<string, string | boolean> = {};\n let directory: string | undefined;\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index] || \"\";\n if (!argument.startsWith(\"--\")) {\n if (directory) throw new Error(\"Only one destination directory may be provided.\");\n directory = argument;\n continue;\n }\n const [rawName, inlineValue] = argument.slice(2).split(\"=\", 2);\n if (BOOLEAN_FLAGS.has(rawName)) {\n if (inlineValue !== undefined) throw new Error(`--${rawName} does not accept a value.`);\n flags[rawName] = true;\n continue;\n }\n if (!VALUE_FLAGS.has(rawName)) throw new Error(`Unknown option: --${rawName}`);\n const value = inlineValue ?? argv[index + 1];\n if (!value || value.startsWith(\"--\")) throw new Error(`--${rawName} requires a value.`);\n flags[rawName] = value;\n if (inlineValue === undefined) index += 1;\n }\n return { ...(directory ? { directory } : {}), flags };\n}\n\nexport const HELP = `Create an Agents24 React application.\n\nUsage:\n npm create agents24-app@latest [directory] [options]\n\nOptions:\n --integration <client-deployment|bff>\n --preset <shadcn-preset-code> Defaults to b2D1FHzlY\n --package-manager <pnpm|npm|yarn|bun>\n --base-url <url>\n --deployment-id <acd_...> Client deployment mode\n --agent-id <uuid> BFF mode\n --agent-alias <alias> BFF mode; preferred human-readable selector\n --agent-version-id <uuid> Optional pinned BFF version\n --starter <template-id> customer-support or deep-research\n --no-install\n --yes Disable prompts; required values must be supplied\n --help\n\nRun agents24 apply for drafts, agents24 publish for production, or agents24 setup to perform both and configure the app.`;\n","import process from \"node:process\";\nimport { confirm, isCancel, select, text } from \"@clack/prompts\";\n\nimport type { ParsedArguments } from \"./arguments.js\";\nimport {\n INTEGRATIONS,\n PACKAGE_MANAGERS,\n DEFAULT_PRESET,\n type CreateAppOptions,\n type Integration,\n type PackageManager,\n} from \"./types.js\";\nimport { compatibleTemplates, loadTemplateCatalog, selectTemplate } from \"./template-catalog.js\";\n\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\nconst DEPLOYMENT_ID = /^acd_[A-Za-z0-9_-]{10,}$/;\nconst PRESET = /^[A-Za-z0-9]{6,32}$/;\n\nfunction cancelled<T>(value: T): asserts value is Exclude<T, symbol> {\n if (isCancel(value)) throw new Error(\"App creation cancelled.\");\n}\n\nfunction flag(args: ParsedArguments, name: string): string | undefined {\n const value = args.flags[name];\n return typeof value === \"string\" ? value.trim() : undefined;\n}\n\nfunction oneOf<T extends string>(value: string | undefined, choices: readonly T[], field: string): T | undefined {\n if (value === undefined) return undefined;\n if (!choices.includes(value as T)) throw new Error(`${field} must be one of: ${choices.join(\", \")}.`);\n return value as T;\n}\n\nfunction detectedPackageManager(): PackageManager {\n const name = String(process.env.npm_config_user_agent || \"\").split(\"/\")[0];\n return PACKAGE_MANAGERS.includes(name as PackageManager) ? name as PackageManager : \"pnpm\";\n}\n\nfunction validateUrl(value: string): string | undefined {\n try {\n const parsed = new URL(value);\n if (/[\\r\\n\\0]/.test(value) || parsed.username || parsed.password || parsed.search || parsed.hash) {\n return \"Use a base URL without credentials, query parameters, or fragments.\";\n }\n return parsed.protocol === \"https:\" || (parsed.protocol === \"http:\" && [\"localhost\", \"127.0.0.1\", \"::1\"].includes(parsed.hostname))\n ? undefined\n : \"Use HTTPS, or HTTP for a local development server.\";\n } catch { return \"Enter a valid URL.\"; }\n}\n\nasync function requiredText(message: string, initialValue: string | undefined, validate?: (value: string) => string | undefined): Promise<string> {\n const result = await text({\n message,\n ...(initialValue ? { initialValue } : {}),\n validate(value) {\n const normalized = String(value || \"\").trim();\n return normalized ? validate?.(normalized) : \"This value is required.\";\n },\n });\n cancelled(result);\n return String(result).trim();\n}\n\nexport async function resolveOptions(args: ParsedArguments): Promise<CreateAppOptions> {\n const nonInteractive = args.flags.yes === true;\n let directory = args.directory;\n let integration = oneOf(flag(args, \"integration\"), INTEGRATIONS, \"integration\");\n let preset = flag(args, \"preset\");\n let packageManager = oneOf(flag(args, \"package-manager\"), PACKAGE_MANAGERS, \"package-manager\");\n let baseUrl = flag(args, \"base-url\");\n const requestedStarter = flag(args, \"starter\");\n let install = args.flags[\"no-install\"] !== true;\n\n if (!nonInteractive) {\n directory ||= await requiredText(\"Where should the app be created?\", \"my-agents24-app\");\n if (!integration) {\n const result = await select<Integration>({ message: \"How should the app connect?\", options: [\n { value: \"client-deployment\", label: \"Client deployment\", hint: \"Direct anonymous browser connection\" },\n { value: \"bff\", label: \"Server BFF\", hint: \"API key remains on your Node server\" },\n ] });\n cancelled(result); integration = result;\n }\n preset ||= await requiredText(\n \"Shadcn preset code\",\n DEFAULT_PRESET,\n (value) => PRESET.test(value) ? undefined : \"Enter a valid Shadcn preset code.\",\n );\n if (!packageManager) {\n const detected = detectedPackageManager();\n const result = await select<PackageManager>({ message: \"Package manager\", initialValue: detected, options: PACKAGE_MANAGERS.map((value) => ({ value, label: value })) });\n cancelled(result); packageManager = result;\n }\n if (args.flags[\"no-install\"] !== true) {\n const result = await confirm({ message: \"Install dependencies?\", initialValue: true });\n cancelled(result); install = result;\n }\n }\n\n directory = String(directory || \"\").trim();\n integration ||= \"client-deployment\";\n preset ||= DEFAULT_PRESET;\n packageManager ||= detectedPackageManager();\n baseUrl ||= \"https://api.agents24.dev\";\n const urlError = validateUrl(baseUrl);\n if (!directory) throw new Error(\"A destination directory is required.\");\n if (urlError) throw new Error(urlError);\n if (!PRESET.test(preset)) throw new Error(\"--preset must be a valid Shadcn preset code.\");\n\n let starter;\n if (requestedStarter || !nonInteractive) {\n const { catalog } = await loadTemplateCatalog(baseUrl);\n let selectedId = requestedStarter;\n if (!selectedId) {\n const templates = compatibleTemplates(catalog);\n const result = await select<string>({\n message: \"Start with an Agent template?\",\n options: [\n { value: \"none\", label: \"No Agent template\" },\n ...templates.map((item) => ({ value: item.id, label: item.display_name, hint: item.description })),\n ],\n });\n cancelled(result);\n selectedId = result === \"none\" ? undefined : result;\n }\n if (selectedId) starter = await selectTemplate(baseUrl, catalog, selectedId);\n }\n\n if (integration === \"client-deployment\") {\n const deploymentId = flag(args, \"deployment-id\");\n if (deploymentId && !DEPLOYMENT_ID.test(deploymentId)) throw new Error(\"--deployment-id must be a valid public acd_… deployment ID.\");\n return { directory, integration, preset, packageManager, install, baseUrl, starter, deploymentId };\n }\n\n const fields = {\n agentId: flag(args, \"agent-id\"),\n agentAlias: flag(args, \"agent-alias\"),\n agentVersionId: flag(args, \"agent-version-id\"),\n };\n if (fields.agentId && fields.agentAlias) throw new Error(\"Use either --agent-id or --agent-alias, not both.\");\n if (fields.agentId && !UUID.test(fields.agentId)) throw new Error(\"--agent-id must be a valid UUID.\");\n if (fields.agentVersionId && !UUID.test(fields.agentVersionId)) throw new Error(\"--agent-version-id must be a valid UUID.\");\n if (fields.agentAlias && !/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(fields.agentAlias)) {\n throw new Error(\"--agent-alias must be lowercase kebab-case.\");\n }\n return { directory, integration, preset, packageManager, install, baseUrl, starter, ...fields } as CreateAppOptions;\n}\n"],"mappings":"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","names":["process","process","process","process"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/arguments.ts","../src/prompts.ts"],"sourcesContent":["import { writeFileSync } from \"node:fs\";\nimport process from \"node:process\";\nimport { intro, outro } from \"@clack/prompts\";\n\nimport { HELP, parseArguments } from \"./arguments.js\";\nimport { createApp } from \"./generator.js\";\nimport { resolveOptions } from \"./prompts.js\";\n\nfunction scriptCommand(packageManager: string, script: string): string {\n if (packageManager === \"npm\") return `npm run ${script}`;\n if (packageManager === \"bun\") return `bun run ${script}`;\n return `${packageManager} ${script}`;\n}\n\nasync function main(): Promise<void> {\n const args = parseArguments();\n if (args.flags.help) {\n process.stdout.write(`${HELP}\\n`);\n return;\n }\n intro(\"Create Agents24 App\");\n const options = await resolveOptions(args);\n const generated = createApp(options);\n if (process.env.AGENTS24_CREATE_RESULT_FILE) {\n writeFileSync(process.env.AGENTS24_CREATE_RESULT_FILE, `${JSON.stringify({\n ...generated,\n install: options.install,\n integration: options.integration,\n stack: options.stack,\n packageManager: options.packageManager,\n })}\\n`, { mode: 0o600 });\n }\n const relative = generated.directory.startsWith(`${process.cwd()}/`)\n ? generated.directory.slice(process.cwd().length + 1)\n : generated.directory;\n const install = `${options.packageManager} install`;\n const productionScript = options.integration === \"bff\" ? \"start\" : \"preview\";\n outro([\n `Created ${generated.packageName}`,\n \"\",\n ` cd ${relative}`,\n ` ${install}${options.install ? \" # already completed\" : \"\"}`,\n ` ${scriptCommand(options.packageManager, \"dev\")}`,\n ` ${scriptCommand(options.packageManager, \"build\")}`,\n ` ${scriptCommand(options.packageManager, productionScript)}`,\n ].join(\"\\n\"));\n}\n\nmain().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : \"App creation failed.\";\n process.stderr.write(`create-agents24-app: ${message}\\n`);\n process.exitCode = 1;\n});\n","import process from \"node:process\";\n\nexport type ParsedArguments = {\n directory?: string;\n flags: Record<string, string | boolean>;\n};\n\nconst VALUE_FLAGS = new Set([\n \"integration\",\n \"stack\",\n \"preset\",\n \"package-manager\",\n \"base-url\",\n \"deployment-id\",\n \"agent-id\",\n \"agent-alias\",\n \"agent-version-id\",\n \"starter\",\n]);\nconst BOOLEAN_FLAGS = new Set([\"yes\", \"no-install\", \"help\"]);\n\nexport function parseArguments(argv = process.argv.slice(2)): ParsedArguments {\n const flags: Record<string, string | boolean> = {};\n let directory: string | undefined;\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index] || \"\";\n if (!argument.startsWith(\"--\")) {\n if (directory) throw new Error(\"Only one destination directory may be provided.\");\n directory = argument;\n continue;\n }\n const [rawName, inlineValue] = argument.slice(2).split(\"=\", 2);\n if (BOOLEAN_FLAGS.has(rawName)) {\n if (inlineValue !== undefined) throw new Error(`--${rawName} does not accept a value.`);\n flags[rawName] = true;\n continue;\n }\n if (!VALUE_FLAGS.has(rawName)) throw new Error(`Unknown option: --${rawName}`);\n const value = inlineValue ?? argv[index + 1];\n if (!value || value.startsWith(\"--\")) throw new Error(`--${rawName} requires a value.`);\n flags[rawName] = value;\n if (inlineValue === undefined) index += 1;\n }\n return { ...(directory ? { directory } : {}), flags };\n}\n\nexport const HELP = `Create an Agents24 React application.\n\nUsage:\n npm create agents24-app@latest [directory] [options]\n\nOptions:\n --integration <client-deployment|bff>\n --stack <nextjs|vite-hono|vite> BFF defaults to Next.js; direct client uses Vite\n --preset <shadcn-preset-code> Defaults to b2D1FHzlY\n --package-manager <pnpm|npm|yarn|bun>\n --base-url <url>\n --deployment-id <acd_...> Client deployment mode\n --agent-id <uuid> BFF mode\n --agent-alias <alias> BFF mode; preferred human-readable selector\n --agent-version-id <uuid> Optional pinned BFF version\n --starter <template-id> customer-support or deep-research\n --no-install\n --yes Disable prompts; required values must be supplied\n --help\n\nRun agents24 apply for drafts, agents24 publish for production, or agents24 setup to perform both and configure the app.`;\n","import process from \"node:process\";\nimport { confirm, isCancel, select, text } from \"@clack/prompts\";\n\nimport type { ParsedArguments } from \"./arguments.js\";\nimport {\n INTEGRATIONS,\n STACKS,\n resolveStack,\n type Stack,\n PACKAGE_MANAGERS,\n DEFAULT_PRESET,\n type CreateAppOptions,\n type Integration,\n type PackageManager,\n} from \"./types.js\";\nimport { compatibleTemplates, loadTemplateCatalog, selectTemplate } from \"./template-catalog.js\";\n\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\nconst DEPLOYMENT_ID = /^acd_[A-Za-z0-9_-]{10,}$/;\nconst PRESET = /^[A-Za-z0-9]{6,32}$/;\n\nfunction cancelled<T>(value: T): asserts value is Exclude<T, symbol> {\n if (isCancel(value)) throw new Error(\"App creation cancelled.\");\n}\n\nfunction flag(args: ParsedArguments, name: string): string | undefined {\n const value = args.flags[name];\n return typeof value === \"string\" ? value.trim() : undefined;\n}\n\nfunction oneOf<T extends string>(value: string | undefined, choices: readonly T[], field: string): T | undefined {\n if (value === undefined) return undefined;\n if (!choices.includes(value as T)) throw new Error(`${field} must be one of: ${choices.join(\", \")}.`);\n return value as T;\n}\n\nfunction detectedPackageManager(): PackageManager {\n const name = String(process.env.npm_config_user_agent || \"\").split(\"/\")[0];\n return PACKAGE_MANAGERS.includes(name as PackageManager) ? name as PackageManager : \"pnpm\";\n}\n\nfunction validateUrl(value: string): string | undefined {\n try {\n const parsed = new URL(value);\n if (/[\\r\\n\\0]/.test(value) || parsed.username || parsed.password || parsed.search || parsed.hash) {\n return \"Use a base URL without credentials, query parameters, or fragments.\";\n }\n return parsed.protocol === \"https:\" || (parsed.protocol === \"http:\" && [\"localhost\", \"127.0.0.1\", \"::1\"].includes(parsed.hostname))\n ? undefined\n : \"Use HTTPS, or HTTP for a local development server.\";\n } catch { return \"Enter a valid URL.\"; }\n}\n\nasync function requiredText(message: string, initialValue: string | undefined, validate?: (value: string) => string | undefined): Promise<string> {\n const result = await text({\n message,\n ...(initialValue ? { initialValue } : {}),\n validate(value) {\n const normalized = String(value || \"\").trim();\n return normalized ? validate?.(normalized) : \"This value is required.\";\n },\n });\n cancelled(result);\n return String(result).trim();\n}\n\nexport async function resolveOptions(args: ParsedArguments): Promise<CreateAppOptions> {\n const nonInteractive = args.flags.yes === true;\n let directory = args.directory;\n let integration = oneOf(flag(args, \"integration\"), INTEGRATIONS, \"integration\");\n let stack = oneOf(flag(args, \"stack\"), STACKS, \"stack\");\n let preset = flag(args, \"preset\");\n let packageManager = oneOf(flag(args, \"package-manager\"), PACKAGE_MANAGERS, \"package-manager\");\n let baseUrl = flag(args, \"base-url\");\n const requestedStarter = flag(args, \"starter\");\n let install = args.flags[\"no-install\"] !== true;\n\n if (!nonInteractive) {\n directory ||= await requiredText(\"Where should the app be created?\", \"my-agents24-app\");\n if (!integration) {\n const result = await select<Integration>({ message: \"How should the app connect?\", options: [\n { value: \"bff\", label: \"Server BFF (recommended)\", hint: \"API key remains on your server\" },\n { value: \"client-deployment\", label: \"Client deployment\", hint: \"Direct browser connection\" },\n ] });\n cancelled(result); integration = result;\n }\n if (integration === \"bff\" && !stack) {\n const result = await select<Stack>({ message: \"Application stack\", initialValue: \"nextjs\", options: [\n { value: \"nextjs\", label: \"Next.js (recommended)\", hint: \"Full-stack App Router application\" },\n { value: \"vite-hono\", label: \"Vite + Hono\", hint: \"Vite frontend and Node server\" },\n ] });\n cancelled(result); stack = result;\n }\n }\n\n integration ||= \"bff\";\n stack = resolveStack(integration, stack);\n if (integration === \"bff\" && flag(args, \"deployment-id\")) throw new Error(\"--deployment-id requires --integration client-deployment.\");\n if (integration === \"client-deployment\" && [\"agent-id\", \"agent-alias\", \"agent-version-id\"].some((name) => flag(args, name))) {\n throw new Error(\"Agent selectors require --integration bff.\");\n }\n\n directory = String(directory || \"\").trim();\n baseUrl ||= \"https://api.agents24.dev\";\n const urlError = validateUrl(baseUrl);\n if (!directory) throw new Error(\"A destination directory is required.\");\n if (urlError) throw new Error(urlError);\n if (preset && !PRESET.test(preset)) throw new Error(\"--preset must be a valid Shadcn preset code.\");\n\n let starter;\n if (requestedStarter || !nonInteractive) {\n const { catalog } = await loadTemplateCatalog(baseUrl);\n let selectedId = requestedStarter;\n if (!selectedId) {\n const templates = compatibleTemplates(catalog);\n const result = await select<string>({\n message: \"Start with an Agent template?\",\n options: [\n { value: \"none\", label: \"No Agent template\" },\n ...templates.map((item) => ({ value: item.id, label: item.display_name, hint: item.description })),\n ],\n });\n cancelled(result);\n selectedId = result === \"none\" ? undefined : result;\n }\n if (selectedId) starter = await selectTemplate(baseUrl, catalog, selectedId);\n }\n\n if (!nonInteractive) {\n preset ||= await requiredText(\n \"Shadcn preset code\",\n DEFAULT_PRESET,\n (value) => PRESET.test(value) ? undefined : \"Enter a valid Shadcn preset code.\",\n );\n if (!packageManager) {\n const detected = detectedPackageManager();\n const result = await select<PackageManager>({ message: \"Package manager\", initialValue: detected, options: PACKAGE_MANAGERS.map((value) => ({ value, label: value })) });\n cancelled(result); packageManager = result;\n }\n if (args.flags[\"no-install\"] !== true) {\n const result = await confirm({ message: \"Install dependencies?\", initialValue: true });\n cancelled(result); install = result;\n }\n }\n preset ||= DEFAULT_PRESET;\n packageManager ||= detectedPackageManager();\n\n if (integration === \"client-deployment\") {\n const deploymentId = flag(args, \"deployment-id\");\n if (deploymentId && !DEPLOYMENT_ID.test(deploymentId)) throw new Error(\"--deployment-id must be a valid public acd_… deployment ID.\");\n return { directory, integration, stack, preset, packageManager, install, baseUrl, starter, deploymentId };\n }\n\n const fields = {\n agentId: flag(args, \"agent-id\"),\n agentAlias: flag(args, \"agent-alias\"),\n agentVersionId: flag(args, \"agent-version-id\"),\n };\n if (fields.agentId && fields.agentAlias) throw new Error(\"Use either --agent-id or --agent-alias, not both.\");\n if (fields.agentId && !UUID.test(fields.agentId)) throw new Error(\"--agent-id must be a valid UUID.\");\n if (fields.agentVersionId && !UUID.test(fields.agentVersionId)) throw new Error(\"--agent-version-id must be a valid UUID.\");\n if (fields.agentAlias && !/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(fields.agentAlias)) {\n throw new Error(\"--agent-alias must be lowercase kebab-case.\");\n }\n return { directory, integration, stack, preset, packageManager, install, baseUrl, starter, ...fields } as CreateAppOptions;\n}\n"],"mappings":"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","names":["process","process","process","process"]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  declare const INTEGRATIONS: readonly ["client-deployment", "bff"];
2
+ declare const STACKS: readonly ["nextjs", "vite-hono", "vite"];
3
+ type Stack = (typeof STACKS)[number];
4
+ declare function resolveStack(integration: Integration, stack?: Stack): Stack;
2
5
  declare const PACKAGE_MANAGERS: readonly ["pnpm", "npm", "yarn", "bun"];
3
6
  declare const DEFAULT_PRESET = "b2D1FHzlY";
4
7
  type Integration = (typeof INTEGRATIONS)[number];
@@ -15,6 +18,7 @@ type TemplateSelection = {
15
18
  type CreateAppOptions = {
16
19
  directory: string;
17
20
  integration: Integration;
21
+ stack?: Stack;
18
22
  preset: string;
19
23
  packageManager: PackageManager;
20
24
  install: boolean;
@@ -60,4 +64,4 @@ declare function loadTemplateCatalog(baseUrl: string): Promise<{
60
64
  declare function compatibleTemplates(catalog: Catalog): CatalogTemplate[];
61
65
  declare function selectTemplate(baseUrl: string, catalog: Catalog, id: string): Promise<TemplateSelection>;
62
66
 
63
- export { type CreateAppOptions, DEFAULT_PRESET, type GeneratedApp, INTEGRATIONS, type Integration, PACKAGE_MANAGERS, type PackageManager, type Starter, type TemplateSelection, compatibleTemplates, createApp, installDependencies, loadTemplateCatalog, selectTemplate };
67
+ export { type CreateAppOptions, DEFAULT_PRESET, type GeneratedApp, INTEGRATIONS, type Integration, PACKAGE_MANAGERS, type PackageManager, STACKS, type Stack, type Starter, type TemplateSelection, compatibleTemplates, createApp, installDependencies, loadTemplateCatalog, resolveStack, selectTemplate };
package/dist/index.js CHANGED
@@ -3,20 +3,24 @@ import {
3
3
  DEFAULT_PRESET,
4
4
  INTEGRATIONS,
5
5
  PACKAGE_MANAGERS,
6
+ STACKS,
6
7
  compatibleTemplates,
7
8
  createApp,
8
9
  installDependencies,
9
10
  loadTemplateCatalog,
11
+ resolveStack,
10
12
  selectTemplate
11
- } from "./chunk-ADXMZ3TT.js";
13
+ } from "./chunk-F2J72UHQ.js";
12
14
  export {
13
15
  DEFAULT_PRESET,
14
16
  INTEGRATIONS,
15
17
  PACKAGE_MANAGERS,
18
+ STACKS,
16
19
  compatibleTemplates,
17
20
  createApp,
18
21
  installDependencies,
19
22
  loadTemplateCatalog,
23
+ resolveStack,
20
24
  selectTemplate
21
25
  };
22
26
  //# sourceMappingURL=index.js.map
@@ -290,9 +290,11 @@ export function ChatComposer({
290
290
  </Button>
291
291
  ) : (
292
292
  validationError ? (
293
- <Tooltip tabIndex={0}>
293
+ <Tooltip>
294
294
  <TooltipTrigger asChild>
295
- <Button size="icon" aria-label="Send message" disabled onClick={() => void submit()}><ArrowUp /></Button>
295
+ <span tabIndex={0} aria-label={validationError}>
296
+ <Button size="icon" aria-label="Send message" disabled onClick={() => void submit()}><ArrowUp /></Button>
297
+ </span>
296
298
  </TooltipTrigger>
297
299
  <TooltipContent>{validationError}</TooltipContent>
298
300
  </Tooltip>
@@ -20,7 +20,7 @@
20
20
  "tailwindcss": "^4.1.16"
21
21
  },
22
22
  "source": "packages/agents24-chat-react/scaffold",
23
- "sha256": "8327db5822a239a119e1dc5e1c6ce8cce9ada218b1baf0a7de32bcfc38f87a14",
23
+ "sha256": "219ce9cefa31343090e56a1f27418985a9f75fa1e1aaa59468e1cdaaf1b07841",
24
24
  "files": [
25
25
  "components.json",
26
26
  "manifest.json",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agents24-app",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Create a production-ready Agents24 React application.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,7 +33,7 @@
33
33
  "provenance": false
34
34
  },
35
35
  "dependencies": {
36
- "@agents24/cli": "0.3.3",
36
+ "@agents24/cli": "0.3.5",
37
37
  "@clack/prompts": "1.7.0",
38
38
  "shadcn": "4.13.1"
39
39
  },
@@ -1,8 +1,8 @@
1
1
  # __APP_NAME__
2
2
 
3
- Last Updated: 2026-07-29
3
+ Last Updated: 2026-09-07
4
4
 
5
- This app was generated by `create-agents24-app` with the `__INTEGRATION__` integration and Shadcn preset `__PRESET__`.
5
+ This app was generated by `create-agents24-app` with the `__INTEGRATION__` integration, `__STACK__` stack, and Shadcn preset `__PRESET__`.
6
6
 
7
7
  The app includes a strict document CSP. If you deploy the static client-deployment build without the generated BFF, configure your host to send `Content-Security-Policy: frame-ancestors 'none'`; browsers do not honor that directive in an HTML meta tag.
8
8
 
@@ -18,6 +18,10 @@ __STARTER_SETUP__
18
18
 
19
19
  ## Production
20
20
 
21
+ __HOSTING__
22
+
23
+ `agents24 publish` publishes Agent resources; it does not deploy this website or upload its environment variables.
24
+
21
25
  ```bash
22
26
  __PM_BUILD__
23
27
  __PM_PRODUCTION__
@@ -1,6 +1,8 @@
1
1
  node_modules
2
2
  dist
3
3
  server-dist
4
+ .next
5
+ .vercel
4
6
  .env.local
5
7
  *.log
6
8
  *.tsbuildinfo
@@ -2,26 +2,16 @@ import { readFile } from "node:fs/promises";
2
2
  import { resolve } from "node:path";
3
3
  import { serve } from "@hono/node-server";
4
4
  import { serveStatic } from "@hono/node-server/serve-static";
5
- import { Agents24 } from "@agents24/node";
6
- import { createAgents24BffHandler } from "@agents24/node/bff";
7
5
  import { Hono } from "hono";
8
6
 
9
- import { env } from "./env.js";
10
- import { resolveAgents24Principal, revokeAgents24Principal } from "./principal.js";
7
+ import { getServerEnvironment } from "./env";
8
+ import { handleAgents24 } from "./handler";
11
9
 
12
- const client = new Agents24({
13
- baseUrl: env.AGENTS24_BASE_URL,
14
- apiKey: env.AGENTS24_API_KEY,
15
- });
16
- const agents24 = createAgents24BffHandler({
17
- client,
18
- agents: env.AGENTS24_AGENTS,
19
- integrationId: env.AGENTS24_INTEGRATION_ID,
20
- integrationName: env.AGENTS24_INTEGRATION_NAME,
21
- runtimeTarget: (env.AGENTS24_RUNTIME_TARGET || (process.env.NODE_ENV === "production" ? "published" : "draft")) as "draft" | "published",
22
- resolvePrincipal: resolveAgents24Principal,
23
- revokePrincipal: (request) => revokeAgents24Principal(request),
24
- });
10
+ try { process.loadEnvFile(".env.local"); }
11
+ catch (error) { if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error; }
12
+ if (process.argv.includes("--production")) process.env.NODE_ENV = "production";
13
+ const env = getServerEnvironment();
14
+ const production = process.env.NODE_ENV === "production";
25
15
  const app = new Hono();
26
16
 
27
17
  app.use("*", async (context, next) => {
@@ -31,14 +21,14 @@ app.use("*", async (context, next) => {
31
21
  context.header("X-Content-Type-Options", "nosniff");
32
22
  context.header("X-Frame-Options", "DENY");
33
23
  });
34
- app.all("/api/agents24", (context) => agents24(context.req.raw));
35
- app.all("/api/agents24/*", (context) => agents24(context.req.raw));
24
+ app.all("/api/agents24", (context) => handleAgents24(context.req.raw));
25
+ app.all("/api/agents24/*", (context) => handleAgents24(context.req.raw));
36
26
 
37
- if (process.argv.includes("--production") || process.env.NODE_ENV === "production") {
27
+ if (production) {
38
28
  app.use("*", serveStatic({ root: "./dist" }));
39
29
  app.get("*", async (context) => context.html(await readFile(resolve("dist/index.html"), "utf8")));
40
30
  }
41
31
 
42
- serve({ fetch: app.fetch, hostname: "127.0.0.1", port: env.PORT }, (info) => {
32
+ serve({ fetch: app.fetch, hostname: production ? "0.0.0.0" : "127.0.0.1", port: env.PORT }, (info) => {
43
33
  process.stdout.write(`Agents24 app listening on http://127.0.0.1:${info.port}\n`);
44
34
  });
@@ -0,0 +1,14 @@
1
+ import "server-only";
2
+ import { handleAgents24 } from "../../../../server/handler";
3
+
4
+ export const runtime = "nodejs";
5
+ export const dynamic = "force-dynamic";
6
+ export const maxDuration = 300;
7
+
8
+ export const GET = handleAgents24;
9
+ export const POST = handleAgents24;
10
+ export const PUT = handleAgents24;
11
+ export const PATCH = handleAgents24;
12
+ export const DELETE = handleAgents24;
13
+ export const HEAD = handleAgents24;
14
+ export const OPTIONS = handleAgents24;
@@ -0,0 +1,8 @@
1
+ "use client";
2
+
3
+ import dynamic from "next/dynamic";
4
+
5
+ // The chat controller and query navigation own browser state. Do not initialize
6
+ // them during server rendering or share a controller between server requests.
7
+ const Chat = dynamic(() => import("@/chat-app"), { ssr: false });
8
+ export default Chat;
@@ -0,0 +1,10 @@
1
+ import type { Metadata, Viewport } from "next";
2
+ import type { ReactNode } from "react";
3
+ import "../src/styles.css";
4
+
5
+ export const metadata: Metadata = { title: "__APP_NAME__" };
6
+ export const viewport: Viewport = { width: "device-width", initialScale: 1, viewportFit: "cover" };
7
+
8
+ export default function RootLayout({ children }: { children: ReactNode }) {
9
+ return <html lang="en"><body><div id="root">{children}</div></body></html>;
10
+ }
@@ -0,0 +1,8 @@
1
+ import { connection } from "next/server";
2
+ import Chat from "./chat";
3
+
4
+ export default async function Page() {
5
+ // Each HTML response must use the fresh CSP nonce supplied by proxy.ts.
6
+ await connection();
7
+ return <Chat />;
8
+ }
@@ -0,0 +1,2 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
@@ -0,0 +1,13 @@
1
+ import type { NextConfig } from "next";
2
+
3
+ const config: NextConfig = {
4
+ poweredByHeader: false,
5
+ async headers() {
6
+ return [{ source: "/:path*", headers: [
7
+ { key: "Referrer-Policy", value: "no-referrer" },
8
+ { key: "X-Content-Type-Options", value: "nosniff" },
9
+ { key: "X-Frame-Options", value: "DENY" },
10
+ ] }];
11
+ },
12
+ };
13
+ export default config;
@@ -0,0 +1 @@
1
+ export default { plugins: { "@tailwindcss/postcss": {} } };
@@ -0,0 +1,29 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { NextResponse, type NextRequest } from "next/server";
3
+
4
+ export function proxy(request: NextRequest) {
5
+ const nonce = randomBytes(16).toString("base64");
6
+ const development = process.env.NODE_ENV === "development";
7
+ const csp = [
8
+ "default-src 'self'",
9
+ "base-uri 'none'",
10
+ "object-src 'none'",
11
+ `script-src 'self' 'nonce-${nonce}' 'strict-dynamic'${development ? " 'unsafe-eval'" : ""}`,
12
+ `style-src 'self' 'nonce-${nonce}'`,
13
+ // Radix positioning and chat layout use React style attributes, not executable scripts.
14
+ "style-src-attr 'unsafe-inline'",
15
+ "font-src 'self' data:",
16
+ "img-src 'self' data: blob:",
17
+ `connect-src 'self'${development ? " ws: wss:" : ""}`,
18
+ "form-action 'self'",
19
+ "frame-ancestors 'none'",
20
+ ].join("; ");
21
+ const headers = new Headers(request.headers);
22
+ headers.set("Content-Security-Policy", csp);
23
+ const response = NextResponse.next({ request: { headers } });
24
+ response.headers.set("Content-Security-Policy", csp);
25
+ response.headers.set("Cache-Control", "private, no-store");
26
+ return response;
27
+ }
28
+
29
+ export const config = { matcher: ["/((?!api(?:/|$)|_next/|favicon.ico).*)"] };
@@ -0,0 +1,23 @@
1
+ "use client";
2
+
3
+ import { createBffAgentClient } from "@agents24/client/bff";
4
+ import { useState } from "react";
5
+ import { Agents24ChatScaffold } from "@/index";
6
+ import { useThreadQueryNavigation } from "@/use-thread-query-navigation";
7
+ import { getHostIdentity } from "@/host-identity";
8
+
9
+ export default function ChatApp() {
10
+ const [client] = useState(() => createBffAgentClient({ basePath: "/api/agents24" }));
11
+ const navigation = useThreadQueryNavigation();
12
+ return <Agents24ChatScaffold
13
+ client={client}
14
+ identity={getHostIdentity()}
15
+ activeThreadId={navigation.activeThreadId}
16
+ onActiveThreadIdChange={navigation.onActiveThreadIdChange}
17
+ completeMcpAuthorization={async ({ completion, serverId }) => {
18
+ if (completion.serverId !== serverId || !completion.connectionId) {
19
+ throw new Error("MCP authorization did not return the expected connection.");
20
+ }
21
+ }}
22
+ />;
23
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["DOM", "DOM.Iterable", "ES2022"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "ESNext",
11
+ "moduleResolution": "Bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "react-jsx",
15
+ "incremental": true,
16
+ "plugins": [{ "name": "next" }],
17
+ "paths": { "@/*": ["./src/*"] }
18
+ },
19
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"],
20
+ "exclude": ["node_modules"]
21
+ }
@@ -1,10 +1,5 @@
1
1
  import process from "node:process";
2
2
 
3
- try { process.loadEnvFile?.(".env.local"); }
4
- catch (error) {
5
- if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
6
- }
7
-
8
3
  const REQUIRED = [
9
4
  "AGENTS24_API_KEY",
10
5
  "AGENTS24_AGENTS",
@@ -62,21 +57,29 @@ function agentsConfig(): {
62
57
  return { agents, impliedRuntimeTarget: impliedTargets.values().next().value };
63
58
  }
64
59
 
65
- const parsedAgents = agentsConfig();
66
- const explicitRuntimeTarget = String(process.env.AGENTS24_RUNTIME_TARGET || "").trim() || undefined;
67
- if (explicitRuntimeTarget && !["draft", "published"].includes(explicitRuntimeTarget)) throw new Error("AGENTS24_RUNTIME_TARGET must be draft or published.");
68
- if (explicitRuntimeTarget && parsedAgents.impliedRuntimeTarget && explicitRuntimeTarget !== parsedAgents.impliedRuntimeTarget) {
69
- throw new Error("AGENTS24_RUNTIME_TARGET conflicts with the configured agentVersion selectors.");
70
- }
60
+ export function readServerEnvironment() {
61
+ const parsedAgents = agentsConfig();
62
+ const explicitRuntimeTarget = String(process.env.AGENTS24_RUNTIME_TARGET || "").trim() || undefined;
63
+ if (explicitRuntimeTarget && !["draft", "published"].includes(explicitRuntimeTarget)) throw new Error("AGENTS24_RUNTIME_TARGET must be draft or published.");
64
+ if (explicitRuntimeTarget && parsedAgents.impliedRuntimeTarget && explicitRuntimeTarget !== parsedAgents.impliedRuntimeTarget) {
65
+ throw new Error("AGENTS24_RUNTIME_TARGET conflicts with the configured agentVersion selectors.");
66
+ }
71
67
 
72
- export const env = {
73
- ...Object.fromEntries(REQUIRED.map((name) => [name, required(name)])) as Record<(typeof REQUIRED)[number], string>,
74
- AGENTS24_BASE_URL: String(process.env.AGENTS24_BASE_URL || "https://api.agents24.dev").trim(),
75
- AGENTS24_AGENTS: parsedAgents.agents,
76
- AGENTS24_RUNTIME_TARGET: explicitRuntimeTarget || parsedAgents.impliedRuntimeTarget,
77
- AGENTS24_INTEGRATION_NAME: String(process.env.AGENTS24_INTEGRATION_NAME || "").trim() || undefined,
78
- PORT: Number(process.env.PORT || 3001),
79
- };
68
+ const env = {
69
+ ...Object.fromEntries(REQUIRED.map((name) => [name, required(name)])) as Record<(typeof REQUIRED)[number], string>,
70
+ AGENTS24_BASE_URL: String(process.env.AGENTS24_BASE_URL || "https://api.agents24.dev").trim(),
71
+ AGENTS24_AGENTS: parsedAgents.agents,
72
+ AGENTS24_RUNTIME_TARGET: explicitRuntimeTarget || parsedAgents.impliedRuntimeTarget,
73
+ AGENTS24_INTEGRATION_NAME: String(process.env.AGENTS24_INTEGRATION_NAME || "").trim() || undefined,
74
+ PORT: Number(process.env.PORT || 3001),
75
+ };
80
76
 
81
- if (!Number.isInteger(env.PORT) || env.PORT < 1 || env.PORT > 65535) throw new Error("PORT must be a valid port.");
82
- if (env.SESSION_COOKIE_SECRET.length < 32) throw new Error("SESSION_COOKIE_SECRET must contain at least 32 characters.");
77
+ if (!Number.isInteger(env.PORT) || env.PORT < 1 || env.PORT > 65535) throw new Error("PORT must be a valid port.");
78
+ if (env.SESSION_COOKIE_SECRET.length < 32) throw new Error("SESSION_COOKIE_SECRET must contain at least 32 characters.");
79
+ return env;
80
+ }
81
+
82
+ let environment: ReturnType<typeof readServerEnvironment> | undefined;
83
+ export function getServerEnvironment() {
84
+ return environment ??= readServerEnvironment();
85
+ }
@@ -0,0 +1,23 @@
1
+ import { Agents24 } from "@agents24/node";
2
+ import { createAgents24BffHandler, type Agents24BffHandler } from "@agents24/node/bff";
3
+ import { getServerEnvironment } from "./env";
4
+ import { resolveAgents24Principal, revokeAgents24Principal } from "./principal";
5
+
6
+ let handler: Agents24BffHandler | undefined;
7
+
8
+ // Initialize on the first runtime request, never while the host collects routes during a build.
9
+ export function handleAgents24(request: Request): Promise<Response> {
10
+ if (!handler) {
11
+ const env = getServerEnvironment();
12
+ handler = createAgents24BffHandler({
13
+ client: new Agents24({ baseUrl: env.AGENTS24_BASE_URL, apiKey: env.AGENTS24_API_KEY }),
14
+ agents: env.AGENTS24_AGENTS,
15
+ integrationId: env.AGENTS24_INTEGRATION_ID,
16
+ integrationName: env.AGENTS24_INTEGRATION_NAME,
17
+ runtimeTarget: (env.AGENTS24_RUNTIME_TARGET || (process.env.NODE_ENV === "production" ? "published" : "draft")) as "draft" | "published",
18
+ resolvePrincipal: resolveAgents24Principal,
19
+ revokePrincipal: revokeAgents24Principal,
20
+ });
21
+ }
22
+ return handler(request);
23
+ }
@@ -1,13 +1,13 @@
1
1
  import { createHmac, randomUUID, timingSafeEqual } from "node:crypto";
2
2
  import type { AgentBffPrincipalResolution } from "@agents24/node/bff";
3
3
 
4
- import { env } from "./env.js";
4
+ import { getServerEnvironment } from "./env";
5
5
 
6
6
  const COOKIE = "agents24_app_session";
7
7
  const MAX_AGE = 60 * 60 * 24 * 30;
8
8
 
9
9
  function signature(value: string): string {
10
- return createHmac("sha256", env.SESSION_COOKIE_SECRET).update(value).digest("base64url");
10
+ return createHmac("sha256", getServerEnvironment().SESSION_COOKIE_SECRET).update(value).digest("base64url");
11
11
  }
12
12
 
13
13
  function parseCookies(request: Request): Record<string, string> {
@@ -1,6 +1,6 @@
1
1
  import type { Agents24ChatIdentity } from "@/identity";
2
2
 
3
- /** Replace this adapter with your host application's authenticated identity. */
3
+ /** Replace this adapter with your host application's authenticated display identity. */
4
4
  export function getHostIdentity(): Agents24ChatIdentity {
5
5
  return { state: "guest", displayName: "Guest" };
6
6
  }
package/versions.json CHANGED
@@ -2,16 +2,20 @@
2
2
  "agents24": {
3
3
  "@agents24/client": "^0.2.4",
4
4
  "@agents24/react": "^0.2.4",
5
- "@agents24/chat-react": "^0.5.7",
6
- "@agents24/node": "^0.5.3"
5
+ "@agents24/chat-react": "^0.5.9",
6
+ "@agents24/node": "^0.5.4"
7
7
  },
8
8
  "runtime": {
9
+ "next": "^16.3.4",
10
+ "server-only": "^0.0.1",
11
+ "zod": "^4.5.4",
9
12
  "react": "^19.2.3",
10
13
  "react-dom": "^19.2.3",
11
14
  "hono": "^4.12.31",
12
15
  "@hono/node-server": "^2.0.10"
13
16
  },
14
17
  "development": {
18
+ "@tailwindcss/postcss": "^4.1.16",
15
19
  "@types/node": "^24.7.2",
16
20
  "@types/react": "^19.2.3",
17
21
  "@types/react-dom": "^19.2.3",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/types.ts","../src/generator.ts","../src/template-catalog.ts"],"sourcesContent":["export const INTEGRATIONS = [\"client-deployment\", \"bff\"] as const;\nexport const PACKAGE_MANAGERS = [\"pnpm\", \"npm\", \"yarn\", \"bun\"] as const;\nexport const DEFAULT_PRESET = \"b2D1FHzlY\";\n\nexport type Integration = (typeof INTEGRATIONS)[number];\nexport type PackageManager = (typeof PACKAGE_MANAGERS)[number];\nexport type Starter = string;\n\nexport type TemplateSelection = {\n id: Starter;\n version: string;\n displayName: string;\n sha256: string;\n catalogRevision: string;\n files: Map<string, string>;\n};\n\nexport type CreateAppOptions = {\n directory: string;\n integration: Integration;\n preset: string;\n packageManager: PackageManager;\n install: boolean;\n baseUrl: string;\n starter?: TemplateSelection;\n deploymentId?: string;\n agentId?: string;\n agentAlias?: string;\n agentVersionId?: string;\n};\n\nexport type GeneratedApp = {\n directory: string;\n packageName: string;\n};\n","import { spawnSync } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport {\n chmodSync,\n cpSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { createRequire } from \"node:module\";\n\nimport { DEFAULT_PRESET, type CreateAppOptions, type GeneratedApp, type PackageManager } from \"./types.js\";\n\ntype Versions = {\n agents24: Record<string, string>;\n runtime: Record<string, string>;\n development: Record<string, string>;\n};\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), \"..\");\nconst templateRoot = join(packageRoot, \"templates\");\nconst scaffoldRoot = join(packageRoot, \"dist/scaffold\");\nconst scaffoldManifest = JSON.parse(readFileSync(join(packageRoot, \"dist/scaffold-manifest.json\"), \"utf8\")) as {\n dependencies: Record<string, string>;\n devDependencies: Record<string, string>;\n sha256: string;\n};\nconst versions = JSON.parse(readFileSync(join(packageRoot, \"versions.json\"), \"utf8\")) as Versions;\nconst require = createRequire(import.meta.url);\n\nfunction packageName(directory: string): string {\n const value = basename(resolve(directory))\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, \"-\")\n .replace(/^[._-]+|[._-]+$/g, \"\");\n if (!value || !/^[a-z0-9]/.test(value)) throw new Error(\"The destination does not produce a valid npm package name.\");\n return value;\n}\n\nfunction assertDestination(destination: string): void {\n if (!existsSync(destination)) return;\n if (!statSync(destination).isDirectory()) throw new Error(\"The destination already exists and is not a directory.\");\n if (readdirSync(destination).length > 0) throw new Error(\"The destination directory must be empty.\");\n}\n\nfunction walk(directory: string): string[] {\n return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {\n const path = join(directory, entry.name);\n return entry.isDirectory() ? walk(path) : [path];\n });\n}\n\nfunction replaceTemplateValues(directory: string, replacements: Record<string, string>): void {\n for (const file of walk(directory)) {\n if (file.endsWith(\".png\") || file.endsWith(\".ico\")) continue;\n let content = readFileSync(file, \"utf8\");\n for (const [token, value] of Object.entries(replacements)) content = content.split(token).join(value);\n writeFileSync(file, content);\n }\n}\n\nfunction copyLayer(name: string, destination: string): void {\n cpSync(join(templateRoot, name), destination, { recursive: true, force: true });\n}\n\nfunction materializeTemplate(destination: string, options: CreateAppOptions): void {\n if (!options.starter) return;\n const packageId = `pkg_${randomBytes(16).toString(\"hex\")}`;\n let replacedManifest = false;\n for (const [path, original] of options.starter.files) {\n let content = original;\n if (path === \"agents24.yaml\") {\n content = content.replace(/^(package_id:\\s*)[^\\s#]+/m, `$1${packageId}`);\n replacedManifest = content !== original;\n }\n const target = join(destination, \"agents24\", path);\n mkdirSync(dirname(target), { recursive: true });\n writeFileSync(target, content);\n }\n if (!replacedManifest) throw new Error(\"The selected Agent template has no replaceable package_id.\");\n}\n\nfunction generatedManifest(options: CreateAppOptions, name: string): Record<string, unknown> {\n const dependencies: Record<string, string> = {\n \"@agents24/client\": versions.agents24[\"@agents24/client\"]!,\n \"@agents24/react\": versions.agents24[\"@agents24/react\"]!,\n \"@agents24/chat-react\": versions.agents24[\"@agents24/chat-react\"]!,\n ...scaffoldManifest.dependencies,\n react: versions.runtime.react!,\n \"react-dom\": versions.runtime[\"react-dom\"]!,\n };\n const devDependencies: Record<string, string> = {\n \"@types/node\": versions.development[\"@types/node\"]!,\n \"@types/react\": versions.development[\"@types/react\"]!,\n \"@types/react-dom\": versions.development[\"@types/react-dom\"]!,\n \"@vitejs/plugin-react\": versions.development[\"@vitejs/plugin-react\"]!,\n ...scaffoldManifest.devDependencies,\n typescript: versions.development.typescript!,\n vite: versions.development.vite!,\n };\n const scripts: Record<string, string> = {\n dev: \"vite\",\n build: \"tsc --noEmit && vite build\",\n preview: \"vite preview\",\n preset: \"node scripts/apply-preset.mjs\",\n };\n if (options.integration === \"bff\") {\n dependencies[\"@agents24/node\"] = versions.agents24[\"@agents24/node\"]!;\n dependencies.hono = versions.runtime.hono!;\n dependencies[\"@hono/node-server\"] = versions.runtime[\"@hono/node-server\"]!;\n devDependencies.concurrently = versions.development.concurrently!;\n devDependencies.tsx = versions.development.tsx!;\n devDependencies.tsup = \"^8.5.1\";\n scripts.dev = \"concurrently -k -n web,bff \\\"vite\\\" \\\"tsx watch server/index.ts\\\"\";\n scripts.build = \"tsc --noEmit && vite build && tsup server/index.ts --format esm --platform node --out-dir server-dist --external @agents24/node --external hono --external @hono/node-server\";\n scripts.start = \"node server-dist/index.js --production\";\n }\n return {\n name,\n private: true,\n version: \"0.0.0\",\n type: \"module\",\n engines: { node: \"^22.0.0 || ^24.0.0\" },\n agents24: {\n integration: options.integration,\n package_manager: options.packageManager,\n preset: options.preset,\n scaffold_sha256: scaffoldManifest.sha256,\n ...(options.starter ? { template: {\n id: options.starter.id,\n version: options.starter.version,\n sha256: options.starter.sha256,\n catalog_revision: options.starter.catalogRevision,\n } } : {}),\n },\n scripts,\n dependencies,\n devDependencies,\n };\n}\n\nfunction envFiles(options: CreateAppOptions, appName: string): { example: string; local: string } {\n const value = (input: string | undefined) => JSON.stringify(String(input || \"\"));\n const jsonValue = (input: unknown) => JSON.stringify(input);\n const baseUrlOverride = options.baseUrl === \"https://api.agents24.dev\" ? [] : [\n `${options.integration === \"client-deployment\" ? \"VITE_\" : \"\"}AGENTS24_BASE_URL=${value(options.baseUrl)}`,\n ];\n if (options.integration === \"client-deployment\") {\n return {\n example: \"# VITE_AGENTS24_BASE_URL=http://localhost:8026 # optional advanced override\\nVITE_AGENTS24_DEPLOYMENT_ID=acd_your_public_deployment_id\\n\",\n local: [...baseUrlOverride, ...(options.deploymentId ? [`VITE_AGENTS24_DEPLOYMENT_ID=${value(options.deploymentId)}`] : []), \"\"].join(\"\\n\"),\n };\n }\n return {\n example: [\n \"# AGENTS24_BASE_URL=http://localhost:8026 # optional advanced override\",\n \"AGENTS24_API_KEY=your_server_only_api_key\",\n \"# agentVersion accepts draft, latest, or an exact published version such as v1\",\n \"AGENTS24_AGENTS=[{\\\"agentAlias\\\":\\\"your-agent-alias\\\",\\\"agentVersion\\\":\\\"v1\\\"}]\",\n \"# agentId remains supported instead of agentAlias when UUID configuration is preferred\",\n \"AGENTS24_INTEGRATION_ID=generate_one_stable_random_value\",\n \"AGENTS24_INTEGRATION_NAME=your_app_name # optional\",\n \"# AGENTS24_RUNTIME_TARGET=draft # optional server-only override\",\n \"SESSION_COOKIE_SECRET=generate_at_least_32_random_bytes\",\n \"PORT=3001\",\n \"\",\n ].join(\"\\n\"),\n local: [\n ...baseUrlOverride,\n ...(options.agentAlias || options.agentId ? [\n `AGENTS24_AGENTS=${jsonValue([{ ...(options.agentAlias ? { agentAlias: options.agentAlias } : { agentId: options.agentId }), ...(options.agentVersionId ? { agentVersionId: options.agentVersionId } : {}) }])}`,\n ] : []),\n `AGENTS24_INTEGRATION_ID=${value(randomBytes(24).toString(\"base64url\"))}`,\n `AGENTS24_INTEGRATION_NAME=${value(appName)}`,\n `SESSION_COOKIE_SECRET=${value(randomBytes(32).toString(\"base64url\"))}`,\n \"PORT=3001\",\n \"\",\n ].join(\"\\n\"),\n };\n}\n\nfunction installCommand(packageManager: PackageManager): [string, string[]] {\n if (packageManager === \"npm\") return [\"npm\", [\"install\"]];\n if (packageManager === \"yarn\") return [\"yarn\", []];\n if (packageManager === \"bun\") return [\"bun\", [\"install\"]];\n return [\"pnpm\", [\"install\", \"--ignore-workspace\"]];\n}\n\nfunction runScriptCommand(packageManager: PackageManager, script: string): string {\n if (packageManager === \"npm\") return `npm run ${script}`;\n if (packageManager === \"bun\") return `bun run ${script}`;\n return `${packageManager} ${script}`;\n}\n\nexport function installDependencies(directory: string, packageManager: PackageManager): void {\n const [command, args] = installCommand(packageManager);\n const { AGENTS24_API_KEY: _apiKey, ...installerEnvironment } = process.env;\n const result = spawnSync(command, args, { cwd: directory, stdio: \"inherit\", env: installerEnvironment });\n if (result.error) throw new Error(`Could not start ${command}: ${result.error.message}`);\n if (result.status !== 0) throw new Error(`${command} ${args.join(\" \")} failed with exit ${result.status}.`);\n}\n\nfunction clearPresetInstallArtifacts(directory: string): void {\n for (const name of [\"node_modules\", \"bun.lock\", \"bun.lockb\", \"package-lock.json\", \"pnpm-lock.yaml\", \"yarn.lock\"]) {\n rmSync(join(directory, name), { recursive: true, force: true });\n }\n}\n\nfunction applyShadcnPreset(directory: string, preset: string): void {\n if (preset === DEFAULT_PRESET) return;\n const executable = require.resolve(\"shadcn\");\n const { AGENTS24_API_KEY: _apiKey, ...presetEnvironment } = process.env;\n const result = spawnSync(\n process.execPath,\n [executable, \"apply\", preset, \"--yes\", \"--silent\", \"--cwd\", directory],\n { cwd: directory, encoding: \"utf8\", env: presetEnvironment },\n );\n if (result.error) throw new Error(`Could not start Shadcn preset materialization: ${result.error.message}`);\n if (result.status !== 0) {\n const detail = String(result.stderr || result.stdout || \"\").trim().split(\"\\n\").at(-1);\n throw new Error(detail || `Shadcn could not apply preset ${preset}.`);\n }\n const scopeResult = spawnSync(\n process.execPath,\n [join(directory, \"scripts/scope-preset-theme.mjs\")],\n { cwd: directory, encoding: \"utf8\" },\n );\n if (scopeResult.error) throw new Error(`Could not scope the selected Shadcn preset: ${scopeResult.error.message}`);\n if (scopeResult.status !== 0) {\n const detail = String(scopeResult.stderr || scopeResult.stdout || \"\").trim().split(\"\\n\").at(-1);\n throw new Error(detail || `Could not scope Shadcn preset ${preset}.`);\n }\n clearPresetInstallArtifacts(directory);\n}\n\nexport function createApp(options: CreateAppOptions): GeneratedApp {\n const destination = resolve(options.directory);\n assertDestination(destination);\n const name = packageName(destination);\n const parent = dirname(destination);\n mkdirSync(parent, { recursive: true });\n const staging = join(parent, `.${name}.agents24-${randomBytes(6).toString(\"hex\")}`);\n try {\n mkdirSync(staging, { mode: 0o700 });\n cpSync(scaffoldRoot, staging, { recursive: true, force: true });\n rmSync(join(staging, \"manifest.json\"), { force: true });\n copyLayer(\"common\", staging);\n copyLayer(`integrations/${options.integration}`, staging);\n materializeTemplate(staging, options);\n replaceTemplateValues(staging, {\n \"__APP_NAME__\": name,\n \"__PRESET__\": options.preset,\n \"__INTEGRATION__\": options.integration,\n \"__CONNECT_SOURCE__\": options.integration === \"client-deployment\" ? \" __AGENTS24_CONNECT_SOURCE__\" : \"\",\n \"__PM_DEV__\": runScriptCommand(options.packageManager, \"dev\"),\n \"__PM_BUILD__\": runScriptCommand(options.packageManager, \"build\"),\n \"__PM_PRODUCTION__\": runScriptCommand(options.packageManager, options.integration === \"bff\" ? \"start\" : \"preview\"),\n \"__PM_PRESET__\": `${runScriptCommand(options.packageManager, \"preset\")} --`,\n \"__STARTER_SETUP__\": options.starter\n ? `## Set up the included Agent\\n\\nThis repository includes an editable Resource Package in \\`agents24/\\`. For a BFF, run \\`agents24 apply ./agents24\\` to reconcile drafts and \\`agents24 publish ./agents24\\` for production. For a direct-client app, run \\`agents24 setup ./agents24 --app .\\` so publication happens before deployment configuration. Use \\`agents24 dev ./agents24\\` when a local Artifact server is required.`\n : \"\",\n });\n const gitignore = join(staging, \"_gitignore\");\n if (existsSync(gitignore)) renameSync(gitignore, join(staging, \".gitignore\"));\n writeFileSync(join(staging, \"package.json\"), `${JSON.stringify(generatedManifest(options, name), null, 2)}\\n`);\n applyShadcnPreset(staging, options.preset);\n const env = envFiles(options, name);\n writeFileSync(join(staging, \".env.example\"), env.example);\n if (options.install) installDependencies(staging, options.packageManager);\n writeFileSync(join(staging, \".env.local\"), env.local, { mode: 0o600 });\n chmodSync(join(staging, \".env.local\"), 0o600);\n if (existsSync(destination)) rmSync(destination, { recursive: true });\n renameSync(staging, destination);\n return { directory: destination, packageName: name };\n } catch (error) {\n rmSync(staging, { recursive: true, force: true });\n throw error;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { unpackFiles } from \"@agents24/cli\";\n\nimport { type Starter, type TemplateSelection } from \"./types.js\";\n\ntype CatalogTemplate = {\n id: string;\n version: string;\n display_name: string;\n description: string;\n compatibility: { min_generator_version?: string; resource_package_schema?: string };\n archive: { sha256: string; size: number; download_url: string };\n};\n\ntype Catalog = {\n schema_version: \"agents24.template-catalog.v1\";\n revision: string;\n templates: CatalogTemplate[];\n};\n\ntype CachedCatalog = { etag?: string; catalog: Catalog };\n\nconst GENERATOR_VERSION = \"0.2.0\";\nconst SHA256 = /^[0-9a-f]{64}$/;\nconst SEMVER = /^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$/;\nconst TEMPLATE_ID = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;\n\nfunction cacheRoot(): string {\n const override = String(process.env.AGENTS24_TEMPLATE_CACHE_DIR || \"\").trim();\n if (override) return override;\n const platformRoot = process.platform === \"win32\"\n ? process.env.LOCALAPPDATA\n : process.env.XDG_CACHE_HOME || join(homedir(), \".cache\");\n return join(platformRoot || tmpdir(), \"agents24\", \"templates-v1\");\n}\n\nfunction atomicWrite(path: string, data: string | Uint8Array): void {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n const temporary = `${path}.${process.pid}.tmp`;\n writeFileSync(temporary, data, { mode: 0o600 });\n renameSync(temporary, path);\n}\n\nfunction parseVersion(value: string): [number, number, number] | null {\n const match = SEMVER.exec(value);\n return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;\n}\n\nfunction compatible(item: CatalogTemplate): boolean {\n const minimum = parseVersion(String(item.compatibility?.min_generator_version || \"0.0.0\"));\n const current = parseVersion(GENERATOR_VERSION)!;\n if (!minimum || item.compatibility?.resource_package_schema !== \"2.0\") return false;\n return current[0] > minimum[0]\n || (current[0] === minimum[0] && current[1] > minimum[1])\n || (current[0] === minimum[0] && current[1] === minimum[1] && current[2] >= minimum[2]);\n}\n\nfunction validateCatalog(value: unknown): Catalog {\n const catalog = value as Catalog;\n if (catalog?.schema_version !== \"agents24.template-catalog.v1\" || !SHA256.test(catalog.revision) || !Array.isArray(catalog.templates)) {\n throw new Error(\"The Agents24 template catalog is invalid.\");\n }\n const ids = new Set<string>();\n for (const item of catalog.templates) {\n if (!TEMPLATE_ID.test(item?.id) || ids.has(item.id) || !SEMVER.test(item.version)\n || !item.display_name || !SHA256.test(item.archive?.sha256) || !Number.isSafeInteger(item.archive?.size)\n || item.archive.size < 1 || item.archive.size > 5 * 1024 * 1024 || !item.archive.download_url?.startsWith(\"/templates/\")) {\n throw new Error(\"The Agents24 template catalog contains an invalid release.\");\n }\n ids.add(item.id);\n }\n return catalog;\n}\n\nfunction readCachedCatalog(path: string): CachedCatalog | null {\n try {\n const cached = JSON.parse(readFileSync(path, \"utf8\")) as CachedCatalog;\n return { ...(cached.etag ? { etag: cached.etag } : {}), catalog: validateCatalog(cached.catalog) };\n } catch {\n return null;\n }\n}\n\nexport async function loadTemplateCatalog(baseUrl: string): Promise<{ catalog: Catalog; live: boolean }> {\n const path = join(cacheRoot(), \"catalog.json\");\n const cached = existsSync(path) ? readCachedCatalog(path) : null;\n try {\n const response = await fetch(new URL(\"/templates\", `${baseUrl}/`), {\n headers: cached?.etag ? { \"If-None-Match\": cached.etag } : {},\n signal: AbortSignal.timeout(10_000),\n });\n if (response.status === 304 && cached) return { catalog: cached.catalog, live: true };\n if (!response.ok) throw new Error(`catalog request returned ${response.status}`);\n const catalog = validateCatalog(await response.json());\n const etag = response.headers.get(\"etag\") || undefined;\n atomicWrite(path, `${JSON.stringify({ ...(etag ? { etag } : {}), catalog })}\\n`);\n return { catalog, live: true };\n } catch (error) {\n if (cached) return { catalog: cached.catalog, live: false };\n const detail = error instanceof Error ? error.message : \"request failed\";\n throw new Error(`Could not load the Agents24 template catalog (${detail}), and no verified cached catalog is available.`);\n }\n}\n\nexport function compatibleTemplates(catalog: Catalog): CatalogTemplate[] {\n return catalog.templates.filter(compatible);\n}\n\nfunction verifiedArchive(path: string, item: CatalogTemplate): Uint8Array | null {\n try {\n const archive = readFileSync(path);\n if (archive.byteLength !== item.archive.size || createHash(\"sha256\").update(archive).digest(\"hex\") !== item.archive.sha256) return null;\n unpackFiles(archive);\n return archive;\n } catch {\n return null;\n }\n}\n\nasync function readArchiveResponse(response: Response, expectedSize: number): Promise<Uint8Array> {\n if (!response.body) throw new Error(\"Template download returned no archive body.\");\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let size = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.byteLength;\n if (size > expectedSize || size > 5 * 1024 * 1024) {\n await reader.cancel();\n throw new Error(\"Template download exceeds its advertised archive size.\");\n }\n chunks.push(value);\n }\n const archive = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) {\n archive.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return archive;\n}\n\nexport async function selectTemplate(baseUrl: string, catalog: Catalog, id: string): Promise<TemplateSelection> {\n if (id === \"rag\") throw new Error(\"The 'rag' starter was removed. Use --starter customer-support or --starter deep-research.\");\n const item = catalog.templates.find((candidate) => candidate.id === id);\n if (!item) throw new Error(`Template '${id}' is not available in the active catalog.`);\n if (!compatible(item)) throw new Error(`Template '${id}' requires a newer create-agents24-app release.`);\n const path = join(cacheRoot(), \"archives\", `${item.archive.sha256}.zip`);\n let archive = existsSync(path) ? verifiedArchive(path, item) : null;\n if (!archive) {\n let response: Response;\n try {\n response = await fetch(new URL(item.archive.download_url, `${baseUrl}/`), { signal: AbortSignal.timeout(30_000) });\n } catch (error) {\n throw new Error(`Could not download template '${id}', and no verified cached archive is available.`);\n }\n if (!response.ok) throw new Error(`Could not download template '${id}' (HTTP ${response.status}).`);\n const length = response.headers.get(\"content-length\");\n if (length && Number(length) !== item.archive.size) throw new Error(`Template '${id}' download size does not match the catalog.`);\n archive = await readArchiveResponse(response, item.archive.size);\n if (archive.byteLength !== item.archive.size || createHash(\"sha256\").update(archive).digest(\"hex\") !== item.archive.sha256) {\n throw new Error(`Template '${id}' failed integrity verification.`);\n }\n unpackFiles(archive);\n atomicWrite(path, archive);\n }\n return {\n id: item.id as Starter,\n version: item.version,\n displayName: item.display_name,\n sha256: item.archive.sha256,\n catalogRevision: catalog.revision,\n files: unpackFiles(archive),\n };\n}\n"],"mappings":"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","names":["require","existsSync","mkdirSync","readFileSync","renameSync","writeFileSync","dirname","join"]}