create-agents24-app 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -2
- package/dist/{chunk-OCIF3LSI.js → chunk-PXJTBSPX.js} +99 -23
- package/dist/chunk-PXJTBSPX.js.map +1 -0
- package/dist/cli.js +39 -61
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +6 -7
- package/dist/index.js +9 -1
- package/dist/scaffold/components.json +25 -0
- package/dist/scaffold/manifest.json +28 -0
- package/dist/scaffold/src/app.tsx +71 -0
- package/dist/scaffold/src/chat.css +54 -0
- package/dist/scaffold/src/components/chat/chat-composer.tsx +237 -0
- package/dist/scaffold/src/components/chat/chat-message.tsx +76 -0
- package/dist/scaffold/src/components/chat/chat-shell.tsx +257 -0
- package/dist/scaffold/src/components/chat/collapsible-user-message.tsx +37 -0
- package/dist/scaffold/src/components/chat/external-link-dialog.tsx +48 -0
- package/dist/scaffold/src/components/chat/identity-control.tsx +69 -0
- package/dist/scaffold/src/components/chat/message-parts.tsx +83 -0
- package/dist/scaffold/src/components/chat/theme-menu.tsx +79 -0
- package/dist/scaffold/src/components/chat/thread-sidebar.tsx +114 -0
- package/dist/scaffold/src/components/chat/timeline-loading.ts +17 -0
- package/dist/scaffold/src/components/chat/turn-outline.tsx +73 -0
- package/dist/scaffold/src/components/theme-provider.tsx +91 -0
- package/dist/scaffold/src/components/ui/attachment.tsx +204 -0
- package/dist/scaffold/src/components/ui/bubble.tsx +125 -0
- package/dist/scaffold/src/components/ui/button-group.tsx +83 -0
- package/dist/scaffold/src/components/ui/button.tsx +65 -0
- package/dist/scaffold/src/components/ui/dialog.tsx +171 -0
- package/dist/scaffold/src/components/ui/dropdown-menu.tsx +271 -0
- package/dist/scaffold/src/components/ui/input.tsx +19 -0
- package/dist/scaffold/src/components/ui/marker.tsx +69 -0
- package/dist/scaffold/src/components/ui/message-scroller.tsx +129 -0
- package/dist/scaffold/src/components/ui/message.tsx +92 -0
- package/dist/scaffold/src/components/ui/popover.tsx +40 -0
- package/dist/scaffold/src/components/ui/select.tsx +92 -0
- package/dist/scaffold/src/components/ui/separator.tsx +28 -0
- package/dist/scaffold/src/components/ui/sheet.tsx +150 -0
- package/dist/scaffold/src/components/ui/sidebar.tsx +677 -0
- package/dist/scaffold/src/components/ui/skeleton.tsx +13 -0
- package/dist/scaffold/src/components/ui/textarea.tsx +18 -0
- package/dist/scaffold/src/components/ui/tooltip.tsx +56 -0
- package/dist/scaffold/src/hooks/use-mobile.ts +24 -0
- package/dist/scaffold/src/identity.ts +17 -0
- package/dist/scaffold/src/index.css +221 -0
- package/dist/scaffold/src/index.tsx +39 -0
- package/dist/scaffold/src/lib/utils.ts +6 -0
- package/dist/scaffold/styles.css +3 -0
- package/dist/scaffold-manifest.json +66 -0
- package/package.json +7 -3
- package/templates/common/README.md +16 -3
- package/templates/common/index.html +3 -3
- package/templates/common/scripts/apply-preset.mjs +17 -0
- package/templates/common/scripts/scope-preset-theme.mjs +38 -0
- package/templates/common/src/styles.css +10 -6
- package/templates/common/src/use-thread-query-navigation.ts +41 -0
- package/templates/common/tsconfig.json +2 -1
- package/templates/integrations/bff/server/env.ts +3 -3
- package/templates/integrations/bff/server/index.ts +1 -2
- package/templates/integrations/bff/server/principal.ts +3 -3
- package/templates/integrations/bff/src/host-identity.ts +6 -0
- package/templates/integrations/bff/src/main.tsx +21 -16
- package/templates/integrations/bff/tsconfig.json +2 -1
- package/templates/integrations/bff/vite.config.ts +5 -1
- package/templates/integrations/client-deployment/src/main.tsx +26 -18
- package/templates/integrations/client-deployment/vite.config.ts +37 -4
- package/templates/starters/rag/agents24/agents/assistant.md +11 -0
- package/templates/starters/rag/agents24/agents24.yaml +19 -0
- package/templates/starters/rag/agents24/rag/knowledge.yaml +32 -0
- package/templates/starters/rag/agents24/stores/knowledge.yaml +10 -0
- package/templates/starters/rag/agents24/workflows/main.yaml +16 -0
- package/versions.json +4 -4
- package/dist/chunk-OCIF3LSI.js.map +0 -1
- package/templates/themes/essential/src/theme.css +0 -2
- package/templates/themes/flow/src/theme.css +0 -60
- package/templates/themes/workbench/src/theme.css +0 -51
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# create-agents24-app
|
|
2
2
|
|
|
3
|
-
Last Updated: 2026-
|
|
3
|
+
Last Updated: 2026-08-06
|
|
4
4
|
|
|
5
5
|
Create a canonical Agents24 React/Vite application:
|
|
6
6
|
|
|
@@ -8,4 +8,42 @@ Create a canonical Agents24 React/Vite application:
|
|
|
8
8
|
npm create agents24-app@latest
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Create the self-contained RAG starter with:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm create agents24-app@latest my-agent -- --starter rag
|
|
15
|
+
cd my-agent
|
|
16
|
+
agents24 install ./agents24
|
|
17
|
+
pnpm dev
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The starter adds an editable `agents24/` source package containing an Agent, a managed Knowledge Store, and its retrieval pipeline. Installation imports and publishes the Agent through the canonical Agent publication API, which publishes its required RAG dependencies. It does not run ingestion; the Knowledge Store starts empty and can be populated later.
|
|
21
|
+
|
|
22
|
+
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.
|
|
23
|
+
|
|
24
|
+
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.
|
|
25
|
+
|
|
26
|
+
Generation does not require a deployment ID, Agent ID, or API key. `agents24 install` detects the generated app and configures its selected integration. Client deployment writes `VITE_AGENTS24_DEPLOYMENT_ID` and copies an explicit non-production `AGENTS24_BASE_URL` as public `VITE_AGENTS24_BASE_URL`; BFF writes `AGENTS24_API_KEY` and `AGENTS24_AGENT_ID`. Use `--no-write-env` to configure those values later.
|
|
27
|
+
|
|
28
|
+
Generated apps own their Shadcn component source, while `@agents24/client`, `@agents24/react`, and `@agents24/chat-react` provide the hardened runtime, state, streaming markdown, and MCP security behavior. Run `pnpm --filter create-agents24-app materialize:fixture` to create a disposable local fixture from the same canonical source used by the generator.
|
|
29
|
+
|
|
30
|
+
The generated scaffold uses canonical ordered `message.parts` and the default `AgentResponseTimeline`. Customize `components.Timeline` to reorder copied parts, compose the package part primitives, or render a fully custom timeline. Do not mutate canonical parts or fork the scaffold transport/runtime lifecycle.
|
|
31
|
+
|
|
32
|
+
For example, keep the package renderer but change its display order:
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { AgentResponseTimeline } from "@agents24/chat-react/ui";
|
|
36
|
+
import type { Agents24ChatTimelineSlotProps } from "@agents24/chat-react/scaffold";
|
|
37
|
+
|
|
38
|
+
function Timeline({ parts, ...props }: Agents24ChatTimelineSlotProps) {
|
|
39
|
+
return <AgentResponseTimeline {...props} parts={[...parts].reverse()} />;
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or fully replace it by mapping copied `parts` and rendering `AgentChatPart` (or
|
|
44
|
+
your own controls) with the supplied HITL callbacks. The generated app README
|
|
45
|
+
points to the same canonical scaffold and package guidance.
|
|
46
|
+
|
|
47
|
+
## Maintainer development
|
|
48
|
+
|
|
49
|
+
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. Use `pnpm dev:agents24 -- --rag` to generate the RAG starter and run its `agents24/` package through the locally packed installer before starting the app. Set `AGENTS24_BASE_URL` when targeting a local backend; the installer reads `AGENTS24_API_KEY` from the environment or its masked prompt. Unchanged tarballs, scans, and packed runners are reused from the bounded development cache; add `--fresh` after `--` for a clean rebuild. The resulting app and lockfile are disposable local fixtures because their registry disappears on exit. `pnpm release:canary` publishes a clean committed train to the opt-in npm `dev` tag after bounded registry smoke validation. Neither command changes npm `rc` or `latest`.
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// src/types.ts
|
|
4
|
+
var INTEGRATIONS = ["client-deployment", "bff"];
|
|
5
|
+
var PACKAGE_MANAGERS = ["pnpm", "npm", "yarn", "bun"];
|
|
6
|
+
var STARTERS = ["rag"];
|
|
7
|
+
var DEFAULT_PRESET = "b2D1FHzlY";
|
|
8
|
+
|
|
3
9
|
// src/generator.ts
|
|
4
10
|
import { spawnSync } from "child_process";
|
|
5
11
|
import { randomBytes } from "crypto";
|
|
@@ -17,9 +23,13 @@ import {
|
|
|
17
23
|
} from "fs";
|
|
18
24
|
import { basename, dirname, join, resolve } from "path";
|
|
19
25
|
import { fileURLToPath } from "url";
|
|
26
|
+
import { createRequire } from "module";
|
|
20
27
|
var packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
21
28
|
var templateRoot = join(packageRoot, "templates");
|
|
29
|
+
var scaffoldRoot = join(packageRoot, "dist/scaffold");
|
|
30
|
+
var scaffoldManifest = JSON.parse(readFileSync(join(packageRoot, "dist/scaffold-manifest.json"), "utf8"));
|
|
22
31
|
var versions = JSON.parse(readFileSync(join(packageRoot, "versions.json"), "utf8"));
|
|
32
|
+
var require2 = createRequire(import.meta.url);
|
|
23
33
|
function packageName(directory) {
|
|
24
34
|
const value = basename(resolve(directory)).toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^[._-]+|[._-]+$/g, "");
|
|
25
35
|
if (!value || !/^[a-z0-9]/.test(value)) throw new Error("The destination does not produce a valid npm package name.");
|
|
@@ -52,26 +62,29 @@ function generatedManifest(options, name) {
|
|
|
52
62
|
"@agents24/client": versions.agents24["@agents24/client"],
|
|
53
63
|
"@agents24/react": versions.agents24["@agents24/react"],
|
|
54
64
|
"@agents24/chat-react": versions.agents24["@agents24/chat-react"],
|
|
65
|
+
...scaffoldManifest.dependencies,
|
|
55
66
|
react: versions.runtime.react,
|
|
56
67
|
"react-dom": versions.runtime["react-dom"]
|
|
57
68
|
};
|
|
58
69
|
const devDependencies = {
|
|
70
|
+
"@types/node": versions.development["@types/node"],
|
|
59
71
|
"@types/react": versions.development["@types/react"],
|
|
60
72
|
"@types/react-dom": versions.development["@types/react-dom"],
|
|
61
73
|
"@vitejs/plugin-react": versions.development["@vitejs/plugin-react"],
|
|
74
|
+
...scaffoldManifest.devDependencies,
|
|
62
75
|
typescript: versions.development.typescript,
|
|
63
76
|
vite: versions.development.vite
|
|
64
77
|
};
|
|
65
78
|
const scripts = {
|
|
66
79
|
dev: "vite",
|
|
67
80
|
build: "tsc --noEmit && vite build",
|
|
68
|
-
preview: "vite preview"
|
|
81
|
+
preview: "vite preview",
|
|
82
|
+
preset: "node scripts/apply-preset.mjs"
|
|
69
83
|
};
|
|
70
84
|
if (options.integration === "bff") {
|
|
71
85
|
dependencies["@agents24/node"] = versions.agents24["@agents24/node"];
|
|
72
86
|
dependencies.hono = versions.runtime.hono;
|
|
73
87
|
dependencies["@hono/node-server"] = versions.runtime["@hono/node-server"];
|
|
74
|
-
devDependencies["@types/node"] = versions.development["@types/node"];
|
|
75
88
|
devDependencies.concurrently = versions.development.concurrently;
|
|
76
89
|
devDependencies.tsx = versions.development.tsx;
|
|
77
90
|
devDependencies.tsup = "^8.5.1";
|
|
@@ -79,37 +92,53 @@ function generatedManifest(options, name) {
|
|
|
79
92
|
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";
|
|
80
93
|
scripts.start = "node server-dist/index.js --production";
|
|
81
94
|
}
|
|
82
|
-
return {
|
|
95
|
+
return {
|
|
96
|
+
name,
|
|
97
|
+
private: true,
|
|
98
|
+
version: "0.0.0",
|
|
99
|
+
type: "module",
|
|
100
|
+
engines: { node: "^22.0.0 || ^24.0.0" },
|
|
101
|
+
agents24: {
|
|
102
|
+
integration: options.integration,
|
|
103
|
+
package_manager: options.packageManager,
|
|
104
|
+
preset: options.preset,
|
|
105
|
+
scaffold_sha256: scaffoldManifest.sha256,
|
|
106
|
+
...options.starter ? { starter: options.starter } : {}
|
|
107
|
+
},
|
|
108
|
+
scripts,
|
|
109
|
+
dependencies,
|
|
110
|
+
devDependencies
|
|
111
|
+
};
|
|
83
112
|
}
|
|
84
113
|
function envFiles(options) {
|
|
85
114
|
const value = (input) => JSON.stringify(String(input || ""));
|
|
115
|
+
const baseUrlOverride = options.baseUrl === "https://api.agents24.dev" ? [] : [
|
|
116
|
+
`${options.integration === "client-deployment" ? "VITE_" : ""}AGENTS24_BASE_URL=${value(options.baseUrl)}`
|
|
117
|
+
];
|
|
86
118
|
if (options.integration === "client-deployment") {
|
|
87
119
|
return {
|
|
88
|
-
example: "VITE_AGENTS24_BASE_URL=
|
|
89
|
-
local: `
|
|
90
|
-
VITE_AGENTS24_DEPLOYMENT_ID=${value(options.deploymentId)}
|
|
91
|
-
`
|
|
120
|
+
example: "# VITE_AGENTS24_BASE_URL=http://localhost:8026 # optional advanced override\nVITE_AGENTS24_DEPLOYMENT_ID=acd_your_public_deployment_id\n",
|
|
121
|
+
local: [...baseUrlOverride, ...options.deploymentId ? [`VITE_AGENTS24_DEPLOYMENT_ID=${value(options.deploymentId)}`] : [], ""].join("\n")
|
|
92
122
|
};
|
|
93
123
|
}
|
|
94
124
|
return {
|
|
95
125
|
example: [
|
|
96
|
-
"AGENTS24_BASE_URL=
|
|
126
|
+
"# AGENTS24_BASE_URL=http://localhost:8026 # optional advanced override",
|
|
97
127
|
"AGENTS24_API_KEY=your_server_only_api_key",
|
|
98
|
-
"AGENTS24_ORGANIZATION_ID=your_organization_uuid",
|
|
99
|
-
"AGENTS24_PROJECT_ID=your_project_uuid",
|
|
100
128
|
"AGENTS24_AGENT_ID=your_agent_uuid",
|
|
129
|
+
"AGENTS24_DEPLOYMENT_ID=your_deployment_uuid",
|
|
130
|
+
"AGENTS24_CUSTOMER_ISSUER=https://your-app.example",
|
|
101
131
|
"AGENTS24_AGENT_VERSION_ID=",
|
|
102
132
|
"SESSION_COOKIE_SECRET=generate_at_least_32_random_bytes",
|
|
103
133
|
"PORT=3001",
|
|
104
134
|
""
|
|
105
135
|
].join("\n"),
|
|
106
136
|
local: [
|
|
107
|
-
|
|
108
|
-
`
|
|
109
|
-
`
|
|
110
|
-
|
|
111
|
-
`
|
|
112
|
-
`AGENTS24_AGENT_VERSION_ID=${value(options.agentVersionId)}`,
|
|
137
|
+
...baseUrlOverride,
|
|
138
|
+
...options.agentId ? [`AGENTS24_AGENT_ID=${value(options.agentId)}`] : [],
|
|
139
|
+
...options.deploymentId ? [`AGENTS24_DEPLOYMENT_ID=${value(options.deploymentId)}`] : [],
|
|
140
|
+
"AGENTS24_CUSTOMER_ISSUER=https://your-app.example",
|
|
141
|
+
...options.agentVersionId ? [`AGENTS24_AGENT_VERSION_ID=${value(options.agentVersionId)}`] : [],
|
|
113
142
|
`SESSION_COOKIE_SECRET=${value(randomBytes(32).toString("base64url"))}`,
|
|
114
143
|
"PORT=3001",
|
|
115
144
|
""
|
|
@@ -120,7 +149,7 @@ function installCommand(packageManager) {
|
|
|
120
149
|
if (packageManager === "npm") return ["npm", ["install"]];
|
|
121
150
|
if (packageManager === "yarn") return ["yarn", []];
|
|
122
151
|
if (packageManager === "bun") return ["bun", ["install"]];
|
|
123
|
-
return ["pnpm", ["install"]];
|
|
152
|
+
return ["pnpm", ["install", "--ignore-workspace"]];
|
|
124
153
|
}
|
|
125
154
|
function runScriptCommand(packageManager, script) {
|
|
126
155
|
if (packageManager === "npm") return `npm run ${script}`;
|
|
@@ -134,6 +163,37 @@ function installDependencies(directory, packageManager) {
|
|
|
134
163
|
if (result.error) throw new Error(`Could not start ${command}: ${result.error.message}`);
|
|
135
164
|
if (result.status !== 0) throw new Error(`${command} ${args.join(" ")} failed with exit ${result.status}.`);
|
|
136
165
|
}
|
|
166
|
+
function clearPresetInstallArtifacts(directory) {
|
|
167
|
+
for (const name of ["node_modules", "bun.lock", "bun.lockb", "package-lock.json", "pnpm-lock.yaml", "yarn.lock"]) {
|
|
168
|
+
rmSync(join(directory, name), { recursive: true, force: true });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function applyShadcnPreset(directory, preset) {
|
|
172
|
+
if (preset === DEFAULT_PRESET) return;
|
|
173
|
+
const executable = require2.resolve("shadcn");
|
|
174
|
+
const { AGENTS24_API_KEY: _apiKey, ...presetEnvironment } = process.env;
|
|
175
|
+
const result = spawnSync(
|
|
176
|
+
process.execPath,
|
|
177
|
+
[executable, "apply", preset, "--yes", "--silent", "--cwd", directory],
|
|
178
|
+
{ cwd: directory, encoding: "utf8", env: presetEnvironment }
|
|
179
|
+
);
|
|
180
|
+
if (result.error) throw new Error(`Could not start Shadcn preset materialization: ${result.error.message}`);
|
|
181
|
+
if (result.status !== 0) {
|
|
182
|
+
const detail = String(result.stderr || result.stdout || "").trim().split("\n").at(-1);
|
|
183
|
+
throw new Error(detail || `Shadcn could not apply preset ${preset}.`);
|
|
184
|
+
}
|
|
185
|
+
const scopeResult = spawnSync(
|
|
186
|
+
process.execPath,
|
|
187
|
+
[join(directory, "scripts/scope-preset-theme.mjs")],
|
|
188
|
+
{ cwd: directory, encoding: "utf8" }
|
|
189
|
+
);
|
|
190
|
+
if (scopeResult.error) throw new Error(`Could not scope the selected Shadcn preset: ${scopeResult.error.message}`);
|
|
191
|
+
if (scopeResult.status !== 0) {
|
|
192
|
+
const detail = String(scopeResult.stderr || scopeResult.stdout || "").trim().split("\n").at(-1);
|
|
193
|
+
throw new Error(detail || `Could not scope Shadcn preset ${preset}.`);
|
|
194
|
+
}
|
|
195
|
+
clearPresetInstallArtifacts(directory);
|
|
196
|
+
}
|
|
137
197
|
function createApp(options) {
|
|
138
198
|
const destination = resolve(options.directory);
|
|
139
199
|
assertDestination(destination);
|
|
@@ -143,23 +203,35 @@ function createApp(options) {
|
|
|
143
203
|
const staging = join(parent, `.${name}.agents24-${randomBytes(6).toString("hex")}`);
|
|
144
204
|
try {
|
|
145
205
|
mkdirSync(staging, { mode: 448 });
|
|
206
|
+
cpSync(scaffoldRoot, staging, { recursive: true, force: true });
|
|
207
|
+
rmSync(join(staging, "manifest.json"), { force: true });
|
|
146
208
|
copyLayer("common", staging);
|
|
147
209
|
copyLayer(`integrations/${options.integration}`, staging);
|
|
148
|
-
copyLayer(`
|
|
149
|
-
const apiOrigin = new URL(options.baseUrl).origin;
|
|
210
|
+
if (options.starter) copyLayer(`starters/${options.starter}`, staging);
|
|
150
211
|
replaceTemplateValues(staging, {
|
|
151
212
|
"__APP_NAME__": name,
|
|
152
|
-
"
|
|
213
|
+
"__PRESET__": options.preset,
|
|
153
214
|
"__INTEGRATION__": options.integration,
|
|
154
|
-
"__CONNECT_SOURCE__": options.integration === "client-deployment" ?
|
|
215
|
+
"__CONNECT_SOURCE__": options.integration === "client-deployment" ? " __AGENTS24_CONNECT_SOURCE__" : "",
|
|
155
216
|
"__PM_DEV__": runScriptCommand(options.packageManager, "dev"),
|
|
156
217
|
"__PM_BUILD__": runScriptCommand(options.packageManager, "build"),
|
|
157
|
-
"__PM_PRODUCTION__": runScriptCommand(options.packageManager, options.integration === "bff" ? "start" : "preview")
|
|
218
|
+
"__PM_PRODUCTION__": runScriptCommand(options.packageManager, options.integration === "bff" ? "start" : "preview"),
|
|
219
|
+
"__PM_PRESET__": `${runScriptCommand(options.packageManager, "preset")} --`,
|
|
220
|
+
"__STARTER_SETUP__": options.starter ? `## Publish the included Agent
|
|
221
|
+
|
|
222
|
+
This repository includes an editable Agent package in \`agents24/\`. From this directory run:
|
|
223
|
+
|
|
224
|
+
\`\`\`bash
|
|
225
|
+
agents24 install ./agents24
|
|
226
|
+
\`\`\`
|
|
227
|
+
|
|
228
|
+
The installer publishes the Agent and its RAG dependencies, then configures this app. It creates no ingestion job; the managed Knowledge Store starts empty.` : ""
|
|
158
229
|
});
|
|
159
230
|
const gitignore = join(staging, "_gitignore");
|
|
160
231
|
if (existsSync(gitignore)) renameSync(gitignore, join(staging, ".gitignore"));
|
|
161
232
|
writeFileSync(join(staging, "package.json"), `${JSON.stringify(generatedManifest(options, name), null, 2)}
|
|
162
233
|
`);
|
|
234
|
+
applyShadcnPreset(staging, options.preset);
|
|
163
235
|
const env = envFiles(options);
|
|
164
236
|
writeFileSync(join(staging, ".env.example"), env.example);
|
|
165
237
|
if (options.install) installDependencies(staging, options.packageManager);
|
|
@@ -175,7 +247,11 @@ function createApp(options) {
|
|
|
175
247
|
}
|
|
176
248
|
|
|
177
249
|
export {
|
|
250
|
+
INTEGRATIONS,
|
|
251
|
+
PACKAGE_MANAGERS,
|
|
252
|
+
STARTERS,
|
|
253
|
+
DEFAULT_PRESET,
|
|
178
254
|
installDependencies,
|
|
179
255
|
createApp
|
|
180
256
|
};
|
|
181
|
-
//# sourceMappingURL=chunk-
|
|
257
|
+
//# sourceMappingURL=chunk-PXJTBSPX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/generator.ts"],"sourcesContent":["export const INTEGRATIONS = [\"client-deployment\", \"bff\"] as const;\nexport const PACKAGE_MANAGERS = [\"pnpm\", \"npm\", \"yarn\", \"bun\"] as const;\nexport const STARTERS = [\"rag\"] as const;\nexport const DEFAULT_PRESET = \"b2D1FHzlY\";\n\nexport type Integration = (typeof INTEGRATIONS)[number];\nexport type PackageManager = (typeof PACKAGE_MANAGERS)[number];\nexport type Starter = (typeof STARTERS)[number];\n\nexport type CreateAppOptions = {\n directory: string;\n integration: Integration;\n preset: string;\n packageManager: PackageManager;\n install: boolean;\n baseUrl: string;\n starter?: Starter;\n deploymentId?: string;\n agentId?: 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 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 ? { starter: options.starter } : {}),\n },\n scripts,\n dependencies,\n devDependencies,\n };\n}\n\nfunction envFiles(options: CreateAppOptions): { example: string; local: string } {\n const value = (input: string | undefined) => JSON.stringify(String(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 \"AGENTS24_AGENT_ID=your_agent_uuid\",\n \"AGENTS24_DEPLOYMENT_ID=your_deployment_uuid\",\n \"AGENTS24_CUSTOMER_ISSUER=https://your-app.example\",\n \"AGENTS24_AGENT_VERSION_ID=\",\n \"SESSION_COOKIE_SECRET=generate_at_least_32_random_bytes\",\n \"PORT=3001\",\n \"\",\n ].join(\"\\n\"),\n local: [\n ...baseUrlOverride,\n ...(options.agentId ? [`AGENTS24_AGENT_ID=${value(options.agentId)}`] : []),\n ...(options.deploymentId ? [`AGENTS24_DEPLOYMENT_ID=${value(options.deploymentId)}`] : []),\n \"AGENTS24_CUSTOMER_ISSUER=https://your-app.example\",\n ...(options.agentVersionId ? [`AGENTS24_AGENT_VERSION_ID=${value(options.agentVersionId)}`] : []),\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 if (options.starter) copyLayer(`starters/${options.starter}`, staging);\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 ? `## Publish the included Agent\\n\\nThis repository includes an editable Agent package in \\`agents24/\\`. From this directory run:\\n\\n\\`\\`\\`bash\\nagents24 install ./agents24\\n\\`\\`\\`\\n\\nThe installer publishes the Agent and its RAG dependencies, then configures this app. It creates no ingestion job; the managed Knowledge Store starts empty.`\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);\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"],"mappings":"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","names":["require"]}
|
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
DEFAULT_PRESET,
|
|
4
|
+
INTEGRATIONS,
|
|
5
|
+
PACKAGE_MANAGERS,
|
|
6
|
+
STARTERS,
|
|
3
7
|
createApp
|
|
4
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-PXJTBSPX.js";
|
|
5
9
|
|
|
6
10
|
// src/cli.ts
|
|
11
|
+
import { writeFileSync } from "fs";
|
|
7
12
|
import process3 from "process";
|
|
8
13
|
import { intro, outro } from "@clack/prompts";
|
|
9
14
|
|
|
@@ -11,14 +16,13 @@ import { intro, outro } from "@clack/prompts";
|
|
|
11
16
|
import process from "process";
|
|
12
17
|
var VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
13
18
|
"integration",
|
|
14
|
-
"
|
|
19
|
+
"preset",
|
|
15
20
|
"package-manager",
|
|
16
21
|
"base-url",
|
|
17
22
|
"deployment-id",
|
|
18
23
|
"agent-id",
|
|
19
24
|
"agent-version-id",
|
|
20
|
-
"
|
|
21
|
-
"project-id"
|
|
25
|
+
"starter"
|
|
22
26
|
]);
|
|
23
27
|
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["yes", "no-install", "help"]);
|
|
24
28
|
function parseArguments(argv = process.argv.slice(2)) {
|
|
@@ -52,33 +56,25 @@ Usage:
|
|
|
52
56
|
|
|
53
57
|
Options:
|
|
54
58
|
--integration <client-deployment|bff>
|
|
55
|
-
--
|
|
59
|
+
--preset <shadcn-preset-code> Defaults to b2D1FHzlY
|
|
56
60
|
--package-manager <pnpm|npm|yarn|bun>
|
|
57
61
|
--base-url <url>
|
|
58
62
|
--deployment-id <acd_...> Client deployment mode
|
|
59
63
|
--agent-id <uuid> BFF mode
|
|
60
64
|
--agent-version-id <uuid> Optional pinned BFF version
|
|
61
|
-
--
|
|
62
|
-
--project-id <uuid> BFF mode
|
|
65
|
+
--starter <rag> Include an editable Agent + RAG source package
|
|
63
66
|
--no-install
|
|
64
67
|
--yes Disable prompts; required values must be supplied
|
|
65
68
|
--help
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
AGENTS24_API_KEY environment variable.`;
|
|
70
|
+
Run agents24 install after generation to publish and configure the app.`;
|
|
69
71
|
|
|
70
72
|
// src/prompts.ts
|
|
71
73
|
import process2 from "process";
|
|
72
|
-
import { confirm, isCancel,
|
|
73
|
-
|
|
74
|
-
// src/types.ts
|
|
75
|
-
var INTEGRATIONS = ["client-deployment", "bff"];
|
|
76
|
-
var THEMES = ["essential", "workbench", "flow"];
|
|
77
|
-
var PACKAGE_MANAGERS = ["pnpm", "npm", "yarn", "bun"];
|
|
78
|
-
|
|
79
|
-
// src/prompts.ts
|
|
74
|
+
import { confirm, isCancel, select, text } from "@clack/prompts";
|
|
80
75
|
var 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;
|
|
81
76
|
var DEPLOYMENT_ID = /^acd_[A-Za-z0-9_-]{10,}$/;
|
|
77
|
+
var PRESET = /^[A-Za-z0-9]{6,32}$/;
|
|
82
78
|
function cancelled(value) {
|
|
83
79
|
if (isCancel(value)) throw new Error("App creation cancelled.");
|
|
84
80
|
}
|
|
@@ -122,9 +118,10 @@ async function resolveOptions(args) {
|
|
|
122
118
|
const nonInteractive = args.flags.yes === true;
|
|
123
119
|
let directory = args.directory;
|
|
124
120
|
let integration = oneOf(flag(args, "integration"), INTEGRATIONS, "integration");
|
|
125
|
-
let
|
|
121
|
+
let preset = flag(args, "preset");
|
|
126
122
|
let packageManager = oneOf(flag(args, "package-manager"), PACKAGE_MANAGERS, "package-manager");
|
|
127
123
|
let baseUrl = flag(args, "base-url");
|
|
124
|
+
const starter = oneOf(flag(args, "starter"), STARTERS, "starter");
|
|
128
125
|
let install = args.flags["no-install"] !== true;
|
|
129
126
|
if (!nonInteractive) {
|
|
130
127
|
directory ||= await requiredText("Where should the app be created?", "my-agents24-app");
|
|
@@ -136,22 +133,17 @@ async function resolveOptions(args) {
|
|
|
136
133
|
cancelled(result);
|
|
137
134
|
integration = result;
|
|
138
135
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
] });
|
|
145
|
-
cancelled(result);
|
|
146
|
-
theme = result;
|
|
147
|
-
}
|
|
136
|
+
preset ||= await requiredText(
|
|
137
|
+
"Shadcn preset code",
|
|
138
|
+
DEFAULT_PRESET,
|
|
139
|
+
(value) => PRESET.test(value) ? void 0 : "Enter a valid Shadcn preset code."
|
|
140
|
+
);
|
|
148
141
|
if (!packageManager) {
|
|
149
142
|
const detected = detectedPackageManager();
|
|
150
143
|
const result = await select({ message: "Package manager", initialValue: detected, options: PACKAGE_MANAGERS.map((value) => ({ value, label: value })) });
|
|
151
144
|
cancelled(result);
|
|
152
145
|
packageManager = result;
|
|
153
146
|
}
|
|
154
|
-
baseUrl ||= await requiredText("Agents24 API URL", "https://api.agents24.dev", validateUrl);
|
|
155
147
|
if (args.flags["no-install"] !== true) {
|
|
156
148
|
const result = await confirm({ message: "Install dependencies?", initialValue: true });
|
|
157
149
|
cancelled(result);
|
|
@@ -160,51 +152,28 @@ async function resolveOptions(args) {
|
|
|
160
152
|
}
|
|
161
153
|
directory = String(directory || "").trim();
|
|
162
154
|
integration ||= "client-deployment";
|
|
163
|
-
|
|
155
|
+
preset ||= DEFAULT_PRESET;
|
|
164
156
|
packageManager ||= detectedPackageManager();
|
|
165
157
|
baseUrl ||= "https://api.agents24.dev";
|
|
166
158
|
const urlError = validateUrl(baseUrl);
|
|
167
159
|
if (!directory) throw new Error("A destination directory is required.");
|
|
168
160
|
if (urlError) throw new Error(urlError);
|
|
161
|
+
if (!PRESET.test(preset)) throw new Error("--preset must be a valid Shadcn preset code.");
|
|
169
162
|
if (integration === "client-deployment") {
|
|
170
|
-
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
return { directory, integration, theme, packageManager, install, baseUrl, deploymentId };
|
|
163
|
+
const deploymentId = flag(args, "deployment-id");
|
|
164
|
+
if (deploymentId && !DEPLOYMENT_ID.test(deploymentId)) throw new Error("--deployment-id must be a valid public acd_\u2026 deployment ID.");
|
|
165
|
+
return { directory, integration, preset, packageManager, install, baseUrl, starter, deploymentId };
|
|
174
166
|
}
|
|
175
167
|
const fields = {
|
|
176
168
|
agentId: flag(args, "agent-id"),
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
projectId: flag(args, "project-id")
|
|
169
|
+
deploymentId: flag(args, "deployment-id"),
|
|
170
|
+
agentVersionId: flag(args, "agent-version-id")
|
|
180
171
|
};
|
|
181
|
-
if (!nonInteractive) {
|
|
182
|
-
fields.agentId ||= await requiredText("Agent ID", void 0, (value) => UUID.test(value) ? void 0 : "Enter an Agent UUID.");
|
|
183
|
-
fields.organizationId ||= await requiredText("Organization ID", void 0, (value) => UUID.test(value) ? void 0 : "Enter an organization UUID.");
|
|
184
|
-
fields.projectId ||= await requiredText("Project ID", void 0, (value) => UUID.test(value) ? void 0 : "Enter a project UUID.");
|
|
185
|
-
if (!fields.agentVersionId) {
|
|
186
|
-
const result = await text({
|
|
187
|
-
message: "Agent version ID (optional)",
|
|
188
|
-
placeholder: "Leave blank to use latest published",
|
|
189
|
-
validate: (value) => String(value || "").trim() && !UUID.test(String(value).trim()) ? "Enter an Agent version UUID or leave blank." : void 0
|
|
190
|
-
});
|
|
191
|
-
cancelled(result);
|
|
192
|
-
fields.agentVersionId = String(result || "").trim() || void 0;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
172
|
for (const [name, value] of Object.entries(fields)) {
|
|
196
|
-
if (
|
|
197
|
-
if (!
|
|
198
|
-
}
|
|
199
|
-
let apiKey = String(process2.env.AGENTS24_API_KEY || "").trim();
|
|
200
|
-
if (!apiKey && !nonInteractive) {
|
|
201
|
-
const result = await password({ message: "Agents24 API key", validate: (value) => String(value || "").trim() ? void 0 : "The API key is required." });
|
|
202
|
-
cancelled(result);
|
|
203
|
-
apiKey = String(result).trim();
|
|
173
|
+
if (!value) continue;
|
|
174
|
+
if (!UUID.test(value)) throw new Error(`--${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)} must be a valid UUID.`);
|
|
204
175
|
}
|
|
205
|
-
|
|
206
|
-
if (/[\r\n\0]/.test(apiKey)) throw new Error("AGENTS24_API_KEY contains invalid control characters.");
|
|
207
|
-
return { directory, integration, theme, packageManager, install, baseUrl, apiKey, ...fields };
|
|
176
|
+
return { directory, integration, preset, packageManager, install, baseUrl, starter, ...fields };
|
|
208
177
|
}
|
|
209
178
|
|
|
210
179
|
// src/cli.ts
|
|
@@ -223,6 +192,15 @@ async function main() {
|
|
|
223
192
|
intro("Create Agents24 App");
|
|
224
193
|
const options = await resolveOptions(args);
|
|
225
194
|
const generated = createApp(options);
|
|
195
|
+
if (process3.env.AGENTS24_CREATE_RESULT_FILE) {
|
|
196
|
+
writeFileSync(process3.env.AGENTS24_CREATE_RESULT_FILE, `${JSON.stringify({
|
|
197
|
+
...generated,
|
|
198
|
+
install: options.install,
|
|
199
|
+
integration: options.integration,
|
|
200
|
+
packageManager: options.packageManager
|
|
201
|
+
})}
|
|
202
|
+
`, { mode: 384 });
|
|
203
|
+
}
|
|
226
204
|
const relative = generated.directory.startsWith(`${process3.cwd()}/`) ? generated.directory.slice(process3.cwd().length + 1) : generated.directory;
|
|
227
205
|
const install = `${options.packageManager} install`;
|
|
228
206
|
const productionScript = options.integration === "bff" ? "start" : "preview";
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/arguments.ts","../src/prompts.ts","../src/types.ts"],"sourcesContent":["import 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 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 \"theme\",\n \"package-manager\",\n \"base-url\",\n \"deployment-id\",\n \"agent-id\",\n \"agent-version-id\",\n \"organization-id\",\n \"project-id\",\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 --theme <essential|workbench|flow>\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-version-id <uuid> Optional pinned BFF version\n --organization-id <uuid> BFF mode\n --project-id <uuid> BFF mode\n --no-install\n --yes Disable prompts; required values must be supplied\n --help\n\nFor security, API keys are accepted only through the masked prompt or the\nAGENTS24_API_KEY environment variable.`;\n","import process from \"node:process\";\nimport { confirm, isCancel, password, select, text } from \"@clack/prompts\";\n\nimport type { ParsedArguments } from \"./arguments.js\";\nimport {\n INTEGRATIONS,\n PACKAGE_MANAGERS,\n THEMES,\n type CreateAppOptions,\n type Integration,\n type PackageManager,\n type Theme,\n} from \"./types.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,}$/;\n\nfunction cancelled(value: unknown): asserts value is Exclude<typeof value, 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 theme = oneOf(flag(args, \"theme\"), THEMES, \"theme\");\n let packageManager = oneOf(flag(args, \"package-manager\"), PACKAGE_MANAGERS, \"package-manager\");\n let baseUrl = flag(args, \"base-url\");\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 if (!theme) {\n const result = await select<Theme>({ message: \"Choose a visual recipe\", initialValue: \"essential\", options: [\n { value: \"essential\", label: \"Essential\", hint: \"Canonical shared-page UI\" },\n { value: \"workbench\", label: \"Workbench\", hint: \"Dense and structured\" },\n { value: \"flow\", label: \"Flow\", hint: \"Soft and conversational\" },\n ] });\n cancelled(result); theme = result;\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 baseUrl ||= await requiredText(\"Agents24 API URL\", \"https://api.agents24.dev\", validateUrl);\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 theme ||= \"essential\";\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\n if (integration === \"client-deployment\") {\n let deploymentId = flag(args, \"deployment-id\");\n if (!deploymentId && !nonInteractive) deploymentId = await requiredText(\"Public deployment ID\", undefined, (value) => DEPLOYMENT_ID.test(value) ? undefined : \"Use a public acd_… deployment ID.\");\n if (!deploymentId || !DEPLOYMENT_ID.test(deploymentId)) throw new Error(\"A valid --deployment-id (acd_…) is required.\");\n return { directory, integration, theme, packageManager, install, baseUrl, deploymentId };\n }\n\n const fields = {\n agentId: flag(args, \"agent-id\"),\n agentVersionId: flag(args, \"agent-version-id\"),\n organizationId: flag(args, \"organization-id\"),\n projectId: flag(args, \"project-id\"),\n };\n if (!nonInteractive) {\n fields.agentId ||= await requiredText(\"Agent ID\", undefined, (value) => UUID.test(value) ? undefined : \"Enter an Agent UUID.\");\n fields.organizationId ||= await requiredText(\"Organization ID\", undefined, (value) => UUID.test(value) ? undefined : \"Enter an organization UUID.\");\n fields.projectId ||= await requiredText(\"Project ID\", undefined, (value) => UUID.test(value) ? undefined : \"Enter a project UUID.\");\n if (!fields.agentVersionId) {\n const result = await text({\n message: \"Agent version ID (optional)\",\n placeholder: \"Leave blank to use latest published\",\n validate: (value) => String(value || \"\").trim() && !UUID.test(String(value).trim()) ? \"Enter an Agent version UUID or leave blank.\" : undefined,\n });\n cancelled(result);\n fields.agentVersionId = String(result || \"\").trim() || undefined;\n }\n }\n for (const [name, value] of Object.entries(fields)) {\n if (name === \"agentVersionId\" && !value) continue;\n if (!value || !UUID.test(value)) throw new Error(`A valid --${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)} UUID is required.`);\n }\n let apiKey = String(process.env.AGENTS24_API_KEY || \"\").trim();\n if (!apiKey && !nonInteractive) {\n const result = await password({ message: \"Agents24 API key\", validate: (value) => String(value || \"\").trim() ? undefined : \"The API key is required.\" });\n cancelled(result); apiKey = String(result).trim();\n }\n if (!apiKey) throw new Error(\"AGENTS24_API_KEY is required for noninteractive BFF creation.\");\n if (/[\\r\\n\\0]/.test(apiKey)) throw new Error(\"AGENTS24_API_KEY contains invalid control characters.\");\n return { directory, integration, theme, packageManager, install, baseUrl, apiKey, ...fields } as CreateAppOptions;\n}\n","export const INTEGRATIONS = [\"client-deployment\", \"bff\"] as const;\nexport const THEMES = [\"essential\", \"workbench\", \"flow\"] as const;\nexport const PACKAGE_MANAGERS = [\"pnpm\", \"npm\", \"yarn\", \"bun\"] as const;\n\nexport type Integration = (typeof INTEGRATIONS)[number];\nexport type Theme = (typeof THEMES)[number];\nexport type PackageManager = (typeof PACKAGE_MANAGERS)[number];\n\nexport type CreateAppOptions = {\n directory: string;\n integration: Integration;\n theme: Theme;\n packageManager: PackageManager;\n install: boolean;\n baseUrl: string;\n deploymentId?: string;\n agentId?: string;\n agentVersionId?: string;\n organizationId?: string;\n projectId?: string;\n apiKey?: string;\n};\n\nexport type GeneratedApp = {\n directory: string;\n packageName: string;\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 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-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-version-id <uuid> Optional pinned BFF version\n --starter <rag> Include an editable Agent + RAG source package\n --no-install\n --yes Disable prompts; required values must be supplied\n --help\n\nRun agents24 install after generation to publish 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 STARTERS,\n DEFAULT_PRESET,\n type CreateAppOptions,\n type Integration,\n type PackageManager,\n type Starter,\n} from \"./types.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 starter = oneOf<Starter>(flag(args, \"starter\"), STARTERS, \"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 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 deploymentId: flag(args, \"deployment-id\"),\n agentVersionId: flag(args, \"agent-version-id\"),\n };\n for (const [name, value] of Object.entries(fields)) {\n if (!value) continue;\n if (!UUID.test(value)) throw new Error(`--${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)} must be a valid UUID.`);\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"]}
|