@genui-a3/create 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -73,6 +73,23 @@ Inside a generated project you can run:
73
73
  | `npm run build` | Create a production build |
74
74
  | `npm start` | Run the production server |
75
75
 
76
+ ## Local Development
77
+
78
+ Test the CLI locally before publishing by packing it into a tarball.
79
+
80
+ ```bash
81
+ # 1. Build a local tarball
82
+ npm pack
83
+
84
+ # This will create a file named genui-a3-create-0.x.x.tgz at the root of this package
85
+
86
+ # 2. Switch to your desired test directory
87
+ cd ../my-test-workspace
88
+
89
+ # 3. Scaffold a new project using the tarball
90
+ npx --package=/absolute/path/to/genui-a3-create-0.x.x.tgz create-genui-a3
91
+ ```
92
+
76
93
  ## Prerequisites
77
94
 
78
95
  - Node.js 20.19.0 or later
package/dist/index.js CHANGED
@@ -2,97 +2,374 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { execSync } from "child_process";
5
- import path from "path";
5
+ import path3 from "path";
6
6
  import { fileURLToPath } from "url";
7
+ import * as p2 from "@clack/prompts";
7
8
  import chalk from "chalk";
8
- import fsExtra from "fs-extra";
9
- import prompts from "prompts";
10
- var __filename = fileURLToPath(import.meta.url);
11
- var __dirname = path.dirname(__filename);
12
- var banner = `
13
- ${chalk.cyan("\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ")}
14
- ${chalk.cyan("\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2557")}
15
- ${chalk.cyan("\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2554\u255D")}
16
- ${chalk.cyan("\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u255A\u2550\u2550\u2550\u2588\u2588\u2557")}
17
- ${chalk.cyan("\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D")}
18
- ${chalk.cyan("\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D ")}
9
+ import fs3 from "fs-extra";
19
10
 
20
- ${chalk.white.bold("A3")} ${chalk.dim("\u2014 Agentic App Architecture")}
21
- `;
22
- async function main() {
23
- console.log(banner);
24
- let projectName = process.argv[2];
25
- if (!projectName) {
26
- const response = await prompts(
27
- {
28
- type: "text",
29
- name: "projectName",
30
- message: "What is your project named?",
31
- initial: "my-a3-quickstart"
32
- },
33
- {
34
- onCancel: () => {
35
- console.log(chalk.red("\nSetup cancelled."));
36
- process.exit(1);
37
- }
38
- }
39
- );
40
- projectName = response.projectName;
11
+ // src/utils/generators.ts
12
+ import path from "path";
13
+ import fs from "fs-extra";
14
+
15
+ // src/utils/providers.ts
16
+ var PROVIDER_META = {
17
+ openai: {
18
+ label: "OpenAI",
19
+ importPath: "@genui-a3/providers/openai",
20
+ factory: "createOpenAIProvider",
21
+ models: ["gpt-4o", "gpt-4o-mini"]
22
+ },
23
+ bedrock: {
24
+ label: "AWS Bedrock",
25
+ importPath: "@genui-a3/providers/bedrock",
26
+ factory: "createBedrockProvider",
27
+ models: ["us.anthropic.claude-sonnet-4-5-20250929-v1:0", "us.anthropic.claude-haiku-4-5-20251001-v1:0"]
41
28
  }
42
- if (!projectName) {
43
- console.error(chalk.red("Project name is required."));
44
- process.exit(1);
29
+ };
30
+
31
+ // src/utils/generators.ts
32
+ function generateProviderFile(targetDir, primaryProvider) {
33
+ const { importPath, factory, models } = PROVIDER_META[primaryProvider];
34
+ const modelsLiteral = models.map((m) => `'${m}'`).join(", ");
35
+ const content = `import { ${factory} } from '${importPath}'
36
+ import type { Provider } from '@genui-a3/core'
37
+
38
+ let _provider: Provider
39
+
40
+ export function getProvider(): Provider {
41
+ if (!_provider) {
42
+ _provider = ${factory}({
43
+ models: [${modelsLiteral}],
44
+ })
45
45
  }
46
- const targetDir = path.resolve(process.cwd(), projectName);
47
- if (fsExtra.existsSync(targetDir)) {
48
- const contents = fsExtra.readdirSync(targetDir);
49
- if (contents.length > 0) {
50
- console.error(chalk.red(`
51
- Directory "${projectName}" already exists and is not empty.`));
52
- process.exit(1);
53
- }
46
+ return _provider
47
+ }
48
+ `;
49
+ fs.outputFileSync(path.join(targetDir, "app", "lib", "provider.ts"), content);
50
+ }
51
+ function generateEnvFile(targetDir, config) {
52
+ const lines = ["# Generated by create-genui-a3", "# This file is git-ignored. Do not commit credentials.", ""];
53
+ if (config.providers.includes("openai")) {
54
+ lines.push("# OpenAI", `OPENAI_API_KEY=${config.openaiApiKey || ""}`, "");
54
55
  }
55
- const templateDir = path.resolve(__dirname, "..", "template");
56
- if (!fsExtra.existsSync(templateDir)) {
57
- console.error(chalk.red("\nTemplate directory not found. The package may not have been built correctly."));
58
- process.exit(1);
56
+ if (config.providers.includes("bedrock")) {
57
+ if (config.bedrockAuthMode === "profile") {
58
+ lines.push("# AWS Bedrock (profile mode)", `AWS_PROFILE=${config.awsProfile || "default"}`);
59
+ } else {
60
+ lines.push("# AWS Bedrock (access keys)", `AWS_ACCESS_KEY_ID=${config.awsAccessKeyId || ""}`, `AWS_SECRET_ACCESS_KEY=${config.awsSecretAccessKey || ""}`);
61
+ }
62
+ lines.push(`AWS_REGION=${config.awsRegion || "us-east-1"}`, "");
59
63
  }
60
- console.log(chalk.dim(`
61
- Creating a new A3 app in ${chalk.bold(targetDir)}...
62
- `));
63
- fsExtra.copySync(templateDir, targetDir);
64
+ fs.writeFileSync(path.join(targetDir, ".env"), lines.join("\n"));
65
+ }
66
+ function scaffoldProject(templateDir, targetDir, projectName) {
67
+ fs.copySync(templateDir, targetDir);
64
68
  const pkgJsonPath = path.join(targetDir, "package.json");
65
- if (fsExtra.existsSync(pkgJsonPath)) {
66
- const pkg = fsExtra.readJsonSync(pkgJsonPath);
69
+ if (fs.existsSync(pkgJsonPath)) {
70
+ const pkg = fs.readJsonSync(pkgJsonPath);
67
71
  pkg.name = projectName;
68
72
  delete pkg.private;
69
- fsExtra.writeJsonSync(pkgJsonPath, pkg, { spaces: 2 });
73
+ fs.writeJsonSync(pkgJsonPath, pkg, { spaces: 2 });
70
74
  }
71
75
  const gitignoreSrc = path.join(targetDir, "_gitignore");
72
- const gitignoreDest = path.join(targetDir, ".gitignore");
73
- if (fsExtra.existsSync(gitignoreSrc)) {
74
- fsExtra.renameSync(gitignoreSrc, gitignoreDest);
76
+ if (fs.existsSync(gitignoreSrc)) {
77
+ fs.renameSync(gitignoreSrc, path.join(targetDir, ".gitignore"));
78
+ }
79
+ }
80
+
81
+ // src/utils/prompts.ts
82
+ import * as p from "@clack/prompts";
83
+
84
+ // src/utils/aws.ts
85
+ import fs2 from "fs";
86
+ import os from "os";
87
+ import path2 from "path";
88
+ function detectAwsProfiles() {
89
+ try {
90
+ const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE || path2.join(os.homedir(), ".aws", "credentials");
91
+ const content = fs2.readFileSync(credentialsPath, "utf-8");
92
+ const profiles = [];
93
+ const regex = /^\[([^\]]+)\]$/gm;
94
+ let match;
95
+ while ((match = regex.exec(content)) !== null) {
96
+ profiles.push(match[1]);
97
+ }
98
+ return profiles;
99
+ } catch {
100
+ return [];
101
+ }
102
+ }
103
+ function detectAwsProfileRegion(profileName) {
104
+ try {
105
+ const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE || path2.join(os.homedir(), ".aws", "credentials");
106
+ const content = fs2.readFileSync(credentialsPath, "utf-8");
107
+ const region = extractRegionFromIni(content, profileName);
108
+ if (region) return region;
109
+ } catch {
75
110
  }
76
- console.log(chalk.cyan("Installing dependencies...\n"));
77
111
  try {
78
- execSync("npm install", {
79
- cwd: targetDir,
80
- stdio: "inherit"
112
+ const configPath = process.env.AWS_CONFIG_FILE || path2.join(os.homedir(), ".aws", "config");
113
+ const content = fs2.readFileSync(configPath, "utf-8");
114
+ const sectionName = profileName === "default" ? profileName : `profile ${profileName}`;
115
+ const region = extractRegionFromIni(content, sectionName);
116
+ if (region) return region;
117
+ } catch {
118
+ }
119
+ return void 0;
120
+ }
121
+ function extractRegionFromIni(content, sectionName) {
122
+ const lines = content.split("\n");
123
+ let inSection = false;
124
+ for (const line of lines) {
125
+ const trimmed = line.trim();
126
+ if (trimmed.startsWith("[")) {
127
+ const name = trimmed.slice(1, -1);
128
+ inSection = name === sectionName;
129
+ continue;
130
+ }
131
+ if (inSection && trimmed.startsWith("region")) {
132
+ const match = /^region\s*=\s*(.+)$/.exec(trimmed);
133
+ if (match) return match[1].trim();
134
+ }
135
+ }
136
+ return void 0;
137
+ }
138
+
139
+ // src/utils/prompts.ts
140
+ function handleCancel(value) {
141
+ if (p.isCancel(value)) {
142
+ p.cancel("Setup cancelled.");
143
+ process.exit(1);
144
+ }
145
+ }
146
+ async function promptProjectName() {
147
+ let projectName = process.argv[2];
148
+ if (!projectName) {
149
+ const value = await p.text({
150
+ message: "What is your project named?",
151
+ placeholder: "my-a3-quickstart",
152
+ defaultValue: "my-a3-quickstart"
81
153
  });
154
+ handleCancel(value);
155
+ projectName = value;
156
+ }
157
+ return projectName;
158
+ }
159
+ async function promptAccessKeys(config) {
160
+ p.log.info("You'll need AWS access keys to authenticate with Bedrock.\n Create or manage keys at: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html");
161
+ const awsAccessKeyId = await p.text({
162
+ message: "AWS_ACCESS_KEY_ID:",
163
+ validate(input) {
164
+ if (!input) return "Access key ID is required.";
165
+ }
166
+ });
167
+ handleCancel(awsAccessKeyId);
168
+ config.awsAccessKeyId = awsAccessKeyId;
169
+ const awsSecretAccessKey = await p.password({
170
+ message: "AWS_SECRET_ACCESS_KEY:",
171
+ validate(input) {
172
+ if (!input) return "Secret access key is required.";
173
+ }
174
+ });
175
+ handleCancel(awsSecretAccessKey);
176
+ config.awsSecretAccessKey = awsSecretAccessKey;
177
+ }
178
+ async function promptOpenAIConfig(config) {
179
+ p.log.step(PROVIDER_META.openai.label);
180
+ const openaiApiKey = await p.text({
181
+ message: "OpenAI API key:",
182
+ placeholder: "sk-...",
183
+ validate(input) {
184
+ if (!input) return "API key is required. Get one at https://platform.openai.com/api-keys";
185
+ }
186
+ });
187
+ handleCancel(openaiApiKey);
188
+ config.openaiApiKey = openaiApiKey;
189
+ }
190
+ async function promptBedrockConfig(config) {
191
+ p.log.step(PROVIDER_META.bedrock.label);
192
+ const authMode = await p.select({
193
+ message: "How do you want to authenticate with AWS Bedrock?",
194
+ options: [
195
+ { label: "AWS Profile (recommended)", value: "profile", hint: "Uses ~/.aws/credentials" },
196
+ { label: "Access Keys", value: "keys", hint: "Provide key ID + secret directly" }
197
+ ]
198
+ });
199
+ handleCancel(authMode);
200
+ config.bedrockAuthMode = authMode;
201
+ if (authMode === "profile") {
202
+ const detectedProfiles = detectAwsProfiles();
203
+ let selectedProfile = "";
204
+ if (detectedProfiles.length > 0) {
205
+ const MANUAL_ENTRY = "__manual__";
206
+ const awsProfile = await p.select({
207
+ message: "AWS profile",
208
+ options: [
209
+ ...detectedProfiles.map((prof) => ({ label: prof, value: prof })),
210
+ { label: "Enter manually", value: MANUAL_ENTRY }
211
+ ]
212
+ });
213
+ handleCancel(awsProfile);
214
+ if (awsProfile === MANUAL_ENTRY) {
215
+ const manualProfile = await p.text({
216
+ message: "AWS profile name:",
217
+ placeholder: "default",
218
+ defaultValue: "default",
219
+ validate(input) {
220
+ if (!input) return "Profile name is required.";
221
+ }
222
+ });
223
+ handleCancel(manualProfile);
224
+ selectedProfile = manualProfile;
225
+ } else {
226
+ selectedProfile = awsProfile;
227
+ }
228
+ } else {
229
+ p.log.warn("No AWS profiles found in ~/.aws/credentials");
230
+ const noProfileAction = await p.select({
231
+ message: "How would you like to proceed?",
232
+ options: [
233
+ { label: "Enter a profile name", value: "manual", hint: "Configure the profile later with: aws configure --profile <name>" },
234
+ { label: "Use access keys instead", value: "keys", hint: "Provide key ID + secret directly" }
235
+ ]
236
+ });
237
+ handleCancel(noProfileAction);
238
+ if (noProfileAction === "manual") {
239
+ const awsProfile = await p.text({
240
+ message: "AWS profile name:",
241
+ placeholder: "default",
242
+ defaultValue: "default",
243
+ validate(input) {
244
+ if (!input) return "Profile name is required.";
245
+ }
246
+ });
247
+ handleCancel(awsProfile);
248
+ selectedProfile = awsProfile;
249
+ } else {
250
+ config.bedrockAuthMode = "keys";
251
+ await promptAccessKeys(config);
252
+ }
253
+ }
254
+ if (config.bedrockAuthMode === "profile") {
255
+ config.awsProfile = selectedProfile;
256
+ }
257
+ } else {
258
+ await promptAccessKeys(config);
259
+ }
260
+ const detectedRegion = config.bedrockAuthMode === "profile" ? detectAwsProfileRegion(config.awsProfile) : void 0;
261
+ const awsRegion = await p.text({
262
+ message: "AWS region:",
263
+ ...detectedRegion ? { initialValue: detectedRegion } : { placeholder: "us-east-1" },
264
+ validate(input) {
265
+ if (!input) return "AWS region is required.";
266
+ }
267
+ });
268
+ handleCancel(awsRegion);
269
+ config.awsRegion = awsRegion;
270
+ }
271
+ async function promptPrimaryProvider(providers, config) {
272
+ const primaryProvider = await p.select({
273
+ message: "Which provider should the app use by default?",
274
+ options: providers.map((prov) => ({ label: PROVIDER_META[prov].label, value: prov }))
275
+ });
276
+ handleCancel(primaryProvider);
277
+ config.primaryProvider = primaryProvider;
278
+ }
279
+ async function promptProviders() {
280
+ const providers = await p.multiselect({
281
+ message: "Which LLM provider(s) do you want to configure?",
282
+ options: [
283
+ { label: "OpenAI", value: "openai" },
284
+ { label: "AWS Bedrock", value: "bedrock" }
285
+ ],
286
+ required: true
287
+ });
288
+ handleCancel(providers);
289
+ const config = {
290
+ providers,
291
+ primaryProvider: providers[0]
292
+ };
293
+ if (providers.includes("openai")) {
294
+ await promptOpenAIConfig(config);
295
+ }
296
+ if (providers.includes("bedrock")) {
297
+ await promptBedrockConfig(config);
298
+ }
299
+ if (providers.length > 1) {
300
+ await promptPrimaryProvider(providers, config);
301
+ }
302
+ return config;
303
+ }
304
+
305
+ // src/index.ts
306
+ var __dirname = path3.dirname(fileURLToPath(import.meta.url));
307
+ var BANNER = `
308
+ ${chalk.cyan("\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ")}
309
+ ${chalk.cyan("\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2557")}
310
+ ${chalk.cyan("\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2554\u255D")}
311
+ ${chalk.cyan("\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u255A\u2550\u2550\u2550\u2588\u2588\u2557")}
312
+ ${chalk.cyan("\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D")}
313
+ ${chalk.cyan("\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D ")}
314
+
315
+ ${chalk.white.bold("A3")} ${chalk.dim("\u2014 Agentic App Architecture")}
316
+ `;
317
+ function installDependencies(targetDir, projectName) {
318
+ try {
319
+ execSync("npm install", { cwd: targetDir, stdio: "inherit" });
82
320
  } catch {
83
- console.error(chalk.red("\nFailed to install dependencies. You can try manually:"));
84
- console.log(` cd ${projectName}`);
85
- console.log(" npm install\n");
321
+ p2.log.error("Failed to install dependencies. You can try manually:");
322
+ p2.log.info(` cd ${projectName}
323
+ npm install`);
324
+ process.exit(1);
325
+ }
326
+ }
327
+ function printSuccess(projectName, targetDir, config) {
328
+ const { label } = PROVIDER_META[config.primaryProvider];
329
+ p2.note(
330
+ [
331
+ `Primary provider: ${label}`,
332
+ "Check .env for credentials configuration",
333
+ "",
334
+ "Get started:",
335
+ "",
336
+ ` cd ${projectName}`,
337
+ " npm run dev"
338
+ ].join("\n"),
339
+ `Created ${projectName} at ${targetDir}`
340
+ );
341
+ p2.outro("Happy building!");
342
+ }
343
+ async function main() {
344
+ console.log(BANNER);
345
+ p2.intro("Create a new A3 app");
346
+ const projectName = await promptProjectName();
347
+ const targetDir = path3.resolve(process.cwd(), projectName);
348
+ if (fs3.existsSync(targetDir) && fs3.readdirSync(targetDir).length > 0) {
349
+ p2.cancel(`Directory "${projectName}" already exists and is not empty.`);
350
+ process.exit(1);
351
+ }
352
+ const templateDir = path3.resolve(__dirname, "..", "template");
353
+ if (!fs3.existsSync(templateDir)) {
354
+ p2.cancel("Template directory not found. The package may not have been built correctly.");
86
355
  process.exit(1);
87
356
  }
88
- console.log(`
89
- ${chalk.green.bold("Success!")} Created ${chalk.bold(projectName)} at ${chalk.dim(targetDir)}
90
- `);
91
- console.log("Get started:\n");
92
- console.log(chalk.cyan(` cd ${projectName}`));
93
- console.log(chalk.cyan(" npm run dev\n"));
357
+ const providerConfig = await promptProviders();
358
+ p2.log.info(`Creating a new A3 app in ${targetDir}`);
359
+ const spin = p2.spinner();
360
+ spin.start("Scaffolding project files");
361
+ scaffoldProject(templateDir, targetDir, projectName);
362
+ spin.message("Configuring provider");
363
+ generateProviderFile(targetDir, providerConfig.primaryProvider);
364
+ spin.message("Generating .env file");
365
+ generateEnvFile(targetDir, providerConfig);
366
+ spin.stop("Project scaffolded");
367
+ p2.log.step("Installing dependencies...");
368
+ installDependencies(targetDir, projectName);
369
+ printSuccess(projectName, targetDir, providerConfig);
94
370
  }
95
371
  main().catch((err) => {
96
- console.error(chalk.red("Unexpected error:"), err);
372
+ p2.cancel("Unexpected error");
373
+ console.error(err);
97
374
  process.exit(1);
98
375
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genui-a3/create",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "CLI scaffolding tool for A3 agentic apps",
5
5
  "keywords": [
6
6
  "genui",
@@ -33,14 +33,13 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
+ "@clack/prompts": "1.1.0",
36
37
  "chalk": "5.4.1",
37
- "fs-extra": "11.3.0",
38
- "prompts": "2.4.2"
38
+ "fs-extra": "11.3.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/fs-extra": "11.0.4",
42
42
  "@types/node": "20.19.0",
43
- "@types/prompts": "2.4.9",
44
43
  "tsup": "8.5.1",
45
44
  "typescript": "5.9.3"
46
45
  }
@@ -25,6 +25,7 @@ yarn-debug.log*
25
25
  yarn-error.log*
26
26
 
27
27
  # local env files
28
+ .env
28
29
  .env*.local
29
30
 
30
31
  # vercel
@@ -2,6 +2,7 @@ import { NextRequest } from 'next/server'
2
2
  import { EventType, type RunAgentInput } from '@ag-ui/client'
3
3
  import { EventEncoder } from '@ag-ui/encoder'
4
4
  import { AgentRegistry, ChatSession, MemorySessionStore, AGUIAgent } from '@genui-a3/core'
5
+ import { getProvider } from '../../lib/provider'
5
6
  import { greetingAgent, State } from '../../agents/greeting'
6
7
  import { ageAgent } from '../../agents/age'
7
8
 
@@ -22,6 +23,7 @@ const a3Agent = new AGUIAgent({
22
23
  sessionId: input.threadId,
23
24
  store,
24
25
  initialAgentId: 'greeting',
26
+ provider: getProvider(),
25
27
  }),
26
28
  })
27
29
 
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { NextRequest, NextResponse } from 'next/server'
7
7
  import { AgentRegistry, ChatSession, MemorySessionStore } from '@genui-a3/core'
8
+ import { getProvider } from '../../lib/provider'
8
9
  import { greetingAgent, State } from '../../agents/greeting'
9
10
  import { ageAgent } from '../../agents/age'
10
11
 
@@ -35,9 +36,10 @@ export async function POST(request: NextRequest) {
35
36
  store,
36
37
  initialAgentId: 'greeting',
37
38
  initialState: { userName: undefined },
39
+ provider: getProvider(),
38
40
  })
39
41
 
40
- const result = await session.send(message)
42
+ const result = await session.send({ message })
41
43
 
42
44
  return NextResponse.json({
43
45
  response: result.responseMessage,
@@ -1,5 +1,6 @@
1
1
  import { NextRequest } from 'next/server'
2
2
  import { AgentRegistry, ChatSession, MemorySessionStore } from '@genui-a3/core'
3
+ import { getProvider } from '../../lib/provider'
3
4
  import { greetingAgent, State } from '../../agents/greeting'
4
5
  import { ageAgent } from '../../agents/age'
5
6
 
@@ -30,6 +31,7 @@ export async function POST(request: NextRequest) {
30
31
  store,
31
32
  initialAgentId: 'greeting',
32
33
  initialState: { userName: undefined },
34
+ provider: getProvider(),
33
35
  })
34
36
 
35
37
  const encoder = new TextEncoder()
@@ -37,7 +39,7 @@ export async function POST(request: NextRequest) {
37
39
  const stream = new ReadableStream({
38
40
  async start(controller) {
39
41
  try {
40
- for await (const event of session.sendStream(message)) {
42
+ for await (const event of session.send({ message, stream: true })) {
41
43
  controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\n\n`))
42
44
  }
43
45
  controller.enqueue(encoder.encode('data: [DONE]\n\n'))
@@ -49,6 +49,7 @@ export function ChatInput({ onSubmit, disabled, placeholder = 'Type a message...
49
49
  disabled={disabled}
50
50
  variant="outlined"
51
51
  size="small"
52
+ autoComplete="off"
52
53
  data-testid="chat-input"
53
54
  />
54
55
  <Button
@@ -1,6 +1,15 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ // Check if we are running in the GenUI A3 monorepo
5
+ const isMonorepo = fs.existsSync(path.join(import.meta.dirname, '..', 'a3.code-workspace'))
6
+
1
7
  /** @type {import('next').NextConfig} */
2
8
  const nextConfig = {
3
9
  reactStrictMode: true,
10
+ turbopack: {
11
+ root: isMonorepo ? path.join(import.meta.dirname, '..') : import.meta.dirname,
12
+ },
4
13
  }
5
14
 
6
15
  export default nextConfig
@@ -11,7 +11,8 @@
11
11
  "@ag-ui/encoder": "0.0.45",
12
12
  "@emotion/react": "11.14.0",
13
13
  "@emotion/styled": "11.14.1",
14
- "@genui-a3/core": "^0.1.4",
14
+ "@genui-a3/core": "^0.1.8",
15
+ "@genui-a3/providers": "^0.0.1",
15
16
  "@mui/icons-material": "7.3.7",
16
17
  "@mui/material": "7.3.7",
17
18
  "next": "16.1.6",