copilotkit 0.0.24 → 0.0.26

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 (42) hide show
  1. package/dist/commands/base-command.js +1 -1
  2. package/dist/commands/base-command.js.map +1 -1
  3. package/dist/commands/dev.js +1 -1
  4. package/dist/commands/dev.js.map +1 -1
  5. package/dist/commands/init.js +276 -51
  6. package/dist/commands/init.js.map +1 -1
  7. package/dist/commands/login.js +1 -1
  8. package/dist/commands/login.js.map +1 -1
  9. package/dist/commands/logout.js +1 -1
  10. package/dist/commands/logout.js.map +1 -1
  11. package/dist/lib/init/index.d.ts +4 -3
  12. package/dist/lib/init/index.js +203 -19
  13. package/dist/lib/init/index.js.map +1 -1
  14. package/dist/lib/init/questions.d.ts +1 -0
  15. package/dist/lib/init/questions.js +174 -14
  16. package/dist/lib/init/questions.js.map +1 -1
  17. package/dist/lib/init/scaffold/agent.d.ts +1 -0
  18. package/dist/lib/init/scaffold/crew-inputs.js +1 -1
  19. package/dist/lib/init/scaffold/crew-inputs.js.map +1 -1
  20. package/dist/lib/init/scaffold/env.d.ts +1 -0
  21. package/dist/lib/init/scaffold/env.js +3 -4
  22. package/dist/lib/init/scaffold/env.js.map +1 -1
  23. package/dist/lib/init/scaffold/index.d.ts +1 -0
  24. package/dist/lib/init/scaffold/index.js +111 -7
  25. package/dist/lib/init/scaffold/index.js.map +1 -1
  26. package/dist/lib/init/scaffold/langgraph-assistants.js +3 -4
  27. package/dist/lib/init/scaffold/langgraph-assistants.js.map +1 -1
  28. package/dist/lib/init/scaffold/packages.d.ts +1 -0
  29. package/dist/lib/init/scaffold/shadcn.d.ts +1 -0
  30. package/dist/lib/init/scaffold/shadcn.js +107 -2
  31. package/dist/lib/init/scaffold/shadcn.js.map +1 -1
  32. package/dist/lib/init/types/index.d.ts +2 -1
  33. package/dist/lib/init/types/index.js +108 -2
  34. package/dist/lib/init/types/index.js.map +1 -1
  35. package/dist/lib/init/types/questions.d.ts +164 -36
  36. package/dist/lib/init/types/questions.js +109 -3
  37. package/dist/lib/init/types/questions.js.map +1 -1
  38. package/dist/utils/version.d.ts +1 -1
  39. package/dist/utils/version.js +1 -1
  40. package/dist/utils/version.js.map +1 -1
  41. package/oclif.manifest.json +1 -1
  42. package/package.json +1 -1
@@ -222,7 +222,7 @@ import { Command } from "@oclif/core";
222
222
  import Sentry, { consoleIntegration } from "@sentry/node";
223
223
 
224
224
  // src/utils/version.ts
225
- var LIB_VERSION = "0.0.24";
225
+ var LIB_VERSION = "0.0.26";
226
226
 
227
227
  // src/commands/base-command.ts
228
228
  import chalk2 from "chalk";
@@ -273,17 +273,110 @@ var BaseCommand = class extends Command {
273
273
  };
274
274
 
275
275
  // src/lib/init/types/questions.ts
276
+ import { z } from "zod";
276
277
  import { Flags } from "@oclif/core";
277
278
  var AGENT_FRAMEWORKS = ["CrewAI", "LangGraph", "None"];
278
279
  var CREW_TYPES = ["Crews", "Flows"];
279
280
  var CHAT_COMPONENTS = ["CopilotChat", "CopilotSidebar", "Headless", "CopilotPopup"];
280
281
  var LANGGRAPH_AGENTS = ["Python Starter", "TypeScript Starter", "None"];
281
282
  var CREW_FLOW_TEMPLATES = ["Starter", "None"];
283
+ var YES_NO = ["Yes", "No"];
284
+ var sanitizers = {
285
+ // Remove trailing slash from URLs
286
+ url: (value) => {
287
+ if (!value) return value;
288
+ return value.trim().replace(/\/+$/, "");
289
+ },
290
+ // Trim whitespace from strings
291
+ trim: (value) => {
292
+ if (!value) return value;
293
+ return value.trim();
294
+ },
295
+ // Lowercase strings
296
+ lowercase: (value) => {
297
+ if (!value) return value;
298
+ return value.toLowerCase().trim();
299
+ },
300
+ // Clean API keys (remove whitespace)
301
+ apiKey: (value) => {
302
+ if (!value) return value;
303
+ return value.trim().replace(/\s/g, "");
304
+ }
305
+ };
306
+ var AgentFrameworkSchema = z.enum(AGENT_FRAMEWORKS);
307
+ var CrewTypeSchema = z.enum(CREW_TYPES);
308
+ var ChatComponentSchema = z.enum(CHAT_COMPONENTS);
309
+ var LangGraphAgentSchema = z.enum(LANGGRAPH_AGENTS);
310
+ var CrewFlowTemplateSchema = z.enum(CREW_FLOW_TEMPLATES);
311
+ var YesNoSchema = z.enum(YES_NO);
312
+ var UrlSchema = z.preprocess(
313
+ (val) => sanitizers.url(String(val)),
314
+ z.string().url("Please enter a valid URL").min(1, "URL is required")
315
+ );
316
+ var TokenSchema = z.preprocess(
317
+ (val) => sanitizers.trim(String(val)),
318
+ z.string().min(1, "Token is required")
319
+ );
320
+ var ApiKeySchema = z.preprocess(
321
+ (val) => sanitizers.apiKey(String(val)),
322
+ z.string().min(1, "API key is required")
323
+ );
324
+ var NameSchema = z.preprocess(
325
+ (val) => sanitizers.trim(String(val)),
326
+ z.string().min(1, "Name is required")
327
+ );
328
+ var ConfigSchema = z.object({
329
+ // Core fields
330
+ copilotKitVersion: z.string().optional(),
331
+ agentFramework: AgentFrameworkSchema,
332
+ chatUi: ChatComponentSchema.optional(),
333
+ // Yes/No fields
334
+ alreadyDeployed: YesNoSchema.optional(),
335
+ fastApiEnabled: YesNoSchema.optional(),
336
+ useCopilotCloud: YesNoSchema.optional(),
337
+ // LangGraph specific fields
338
+ langGraphAgent: LangGraphAgentSchema.optional(),
339
+ langGraphPlatform: YesNoSchema.optional(),
340
+ langGraphPlatformUrl: UrlSchema.optional(),
341
+ langGraphRemoteEndpointURL: UrlSchema.optional(),
342
+ // CrewAI specific fields
343
+ crewType: CrewTypeSchema.optional(),
344
+ crewName: NameSchema.optional(),
345
+ crewUrl: UrlSchema.optional(),
346
+ crewBearerToken: TokenSchema.optional(),
347
+ crewFlowAgent: CrewFlowTemplateSchema.optional(),
348
+ // API keys and tokens
349
+ copilotCloudPublicApiKey: z.string().optional(),
350
+ langSmithApiKey: ApiKeySchema.optional(),
351
+ llmToken: ApiKeySchema.optional()
352
+ }).refine(
353
+ (data) => {
354
+ if (data.agentFramework === "CrewAI" && data.crewType === "Crews") {
355
+ return !!data.crewUrl && !!data.crewBearerToken;
356
+ }
357
+ return true;
358
+ },
359
+ {
360
+ message: "Crew URL and bearer token are required for CrewAI Crews",
361
+ path: ["crewUrl", "crewBearerToken"]
362
+ }
363
+ ).refine(
364
+ (data) => {
365
+ if (data.agentFramework === "LangGraph" && data.alreadyDeployed === "Yes" && data.langGraphPlatform === "Yes") {
366
+ return !!data.langGraphPlatformUrl && !!data.langSmithApiKey;
367
+ }
368
+ return true;
369
+ },
370
+ {
371
+ message: "LangGraph Platform URL and LangSmith API key are required",
372
+ path: ["langGraphPlatformUrl", "langSmithApiKey"]
373
+ }
374
+ );
282
375
  var ConfigFlags = {
283
376
  copilotKitVersion: Flags.string({ description: "CopilotKit version to use (e.g. 1.7.0)" }),
284
377
  agentFramework: Flags.string({ description: "Agent framework to power your copilot", options: AGENT_FRAMEWORKS }),
285
- fastApiEnabled: Flags.string({ description: "Use FastAPI to serve your agent locally", options: ["Yes", "No"] }),
286
- useCopilotCloud: Flags.string({ description: "Use Copilot Cloud for production-ready hosting", options: ["Yes", "No"] }),
378
+ fastApiEnabled: Flags.string({ description: "Use FastAPI to serve your agent locally", options: YES_NO }),
379
+ useCopilotCloud: Flags.string({ description: "Use Copilot Cloud for production-ready hosting", options: YES_NO }),
287
380
  chatUi: Flags.string({ description: "Chat UI component to add to your app", options: CHAT_COMPONENTS }),
288
381
  langGraphAgent: Flags.string({ description: "LangGraph agent template to use", options: LANGGRAPH_AGENTS }),
289
382
  crewType: Flags.string({ description: "CrewAI implementation type", options: CREW_TYPES }),
@@ -320,13 +413,34 @@ var templateMapping = {
320
413
  };
321
414
 
322
415
  // src/lib/init/questions.ts
416
+ var validateUrl = (input) => {
417
+ try {
418
+ const sanitized = sanitizers.url(input);
419
+ const result = UrlSchema.safeParse(sanitized);
420
+ if (result.success) return true;
421
+ return result.error.errors[0]?.message || "Invalid URL format";
422
+ } catch (error) {
423
+ return "Invalid URL format";
424
+ }
425
+ };
426
+ var validateRequired = (input) => {
427
+ return sanitizers.trim(input) ? true : "This field is required";
428
+ };
323
429
  var questions = [
324
430
  // Core setup questions - always shown first
325
431
  {
326
432
  type: "select",
327
433
  name: "agentFramework",
328
434
  message: "\u{1F916} Choose your AI framework:",
329
- choices: Array.from(AGENT_FRAMEWORKS)
435
+ choices: Array.from(AGENT_FRAMEWORKS),
436
+ validate: (input) => {
437
+ try {
438
+ AgentFrameworkSchema.parse(input);
439
+ return true;
440
+ } catch (error) {
441
+ return "Please select a valid framework";
442
+ }
443
+ }
330
444
  },
331
445
  // CrewAI specific questions - shown when CrewAI selected
332
446
  {
@@ -334,7 +448,15 @@ var questions = [
334
448
  name: "crewType",
335
449
  message: "\u{1F465} What kind of CrewAI implementation would you like to use?",
336
450
  choices: Array.from(CREW_TYPES),
337
- when: (answers) => answers.agentFramework === "CrewAI"
451
+ when: (answers) => answers.agentFramework === "CrewAI",
452
+ validate: (input) => {
453
+ try {
454
+ CrewTypeSchema.parse(input);
455
+ return true;
456
+ } catch (error) {
457
+ return "Please select a valid crew type";
458
+ }
459
+ }
338
460
  },
339
461
  // CrewAI Crews specific questions - shown when CrewAI Crews selected
340
462
  {
@@ -342,20 +464,26 @@ var questions = [
342
464
  name: "crewName",
343
465
  message: "\u{1F465} What would you like to name your crew? (can be anything)",
344
466
  when: (answers) => answers.agentFramework === "CrewAI" && answers.crewType === "Crews",
345
- default: "MyCopilotCrew"
467
+ default: "MyCopilotCrew",
468
+ validate: validateRequired,
469
+ sanitize: sanitizers.trim
346
470
  },
347
471
  {
348
472
  type: "input",
349
473
  name: "crewUrl",
350
474
  message: "\u{1F517} Enter your Crew's URL:",
351
- when: (answers) => answers.agentFramework === "CrewAI" && answers.crewType === "Crews"
475
+ when: (answers) => answers.agentFramework === "CrewAI" && answers.crewType === "Crews",
476
+ validate: validateUrl,
477
+ sanitize: sanitizers.url
352
478
  },
353
479
  {
354
480
  type: "input",
355
481
  name: "crewBearerToken",
356
482
  message: "\u{1F511} Enter your Crew's bearer token:",
357
483
  when: (answers) => answers.agentFramework === "CrewAI" && answers.crewType === "Crews",
358
- sensitive: true
484
+ sensitive: true,
485
+ validate: validateRequired,
486
+ sanitize: sanitizers.trim
359
487
  },
360
488
  // CrewAI Flows specific questions - shown when CrewAI Flows selected
361
489
  {
@@ -370,25 +498,45 @@ var questions = [
370
498
  type: "yes/no",
371
499
  name: "alreadyDeployed",
372
500
  message: "\u{1F680} Is your LangGraph agent already deployed?",
373
- when: (answers) => answers.agentFramework === "LangGraph"
501
+ when: (answers) => answers.agentFramework === "LangGraph",
502
+ validate: (input) => {
503
+ try {
504
+ YesNoSchema.parse(input);
505
+ return true;
506
+ } catch (error) {
507
+ return "Please select Yes or No";
508
+ }
509
+ }
374
510
  },
375
511
  {
376
512
  type: "yes/no",
377
513
  name: "langGraphPlatform",
378
514
  message: "\u{1F99C}\u{1F517} Is it hosted with LangGraph Platform (local or cloud)?",
379
- when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "Yes"
515
+ when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "Yes",
516
+ validate: (input) => {
517
+ try {
518
+ YesNoSchema.parse(input);
519
+ return true;
520
+ } catch (error) {
521
+ return "Please select Yes or No";
522
+ }
523
+ }
380
524
  },
381
525
  {
382
526
  type: "input",
383
527
  name: "langGraphPlatformUrl",
384
528
  message: "\u{1F99C}\u{1F517} Enter your LangGraph platform URL:",
385
- when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "Yes" && answers.langGraphPlatform === "Yes"
529
+ when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "Yes" && answers.langGraphPlatform === "Yes",
530
+ validate: validateUrl,
531
+ sanitize: sanitizers.url
386
532
  },
387
533
  {
388
534
  type: "input",
389
535
  name: "langGraphRemoteEndpointURL",
390
536
  message: "\u{1F50C} Enter your LangGraph endpoint URL:",
391
- when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "Yes" && answers.langGraphPlatform === "No"
537
+ when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "Yes" && answers.langGraphPlatform === "No",
538
+ validate: validateUrl,
539
+ sanitize: sanitizers.url
392
540
  },
393
541
  {
394
542
  type: "select",
@@ -402,14 +550,24 @@ var questions = [
402
550
  name: "langSmithApiKey",
403
551
  message: "\u{1F99C}\u{1F517} Enter your LangSmith API key (required by LangGraph Platform) :",
404
552
  when: (answers) => answers.agentFramework === "LangGraph" && answers.langGraphPlatform === "Yes",
405
- sensitive: true
553
+ sensitive: true,
554
+ validate: validateRequired,
555
+ sanitize: sanitizers.apiKey
406
556
  },
407
557
  // Deployment options
408
558
  {
409
559
  type: "yes/no",
410
560
  name: "useCopilotCloud",
411
561
  message: "\u{1FA81} Deploy with Copilot Cloud? (recommended for production)",
412
- when: (answers) => !(answers.agentFramework === "CrewAI" && answers.crewType === "Crews") && answers.crewType !== "Flows" && answers.alreadyDeployed === "Yes"
562
+ when: (answers) => !(answers.agentFramework === "CrewAI" && answers.crewType === "Crews") && answers.crewType !== "Flows" && answers.alreadyDeployed === "Yes",
563
+ validate: (input) => {
564
+ try {
565
+ YesNoSchema.parse(input);
566
+ return true;
567
+ } catch (error) {
568
+ return "Please select Yes or No";
569
+ }
570
+ }
413
571
  },
414
572
  // {
415
573
  // type: 'yes/no',
@@ -435,7 +593,9 @@ var questions = [
435
593
  name: "llmToken",
436
594
  message: "\u{1F511} Enter your OpenAI API key (required for agent functionality):",
437
595
  when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "No" || answers.agentFramework === "CrewAI" && answers.crewType === "Flows",
438
- sensitive: true
596
+ sensitive: true,
597
+ validate: validateRequired,
598
+ sanitize: sanitizers.apiKey
439
599
  }
440
600
  ];
441
601
 
@@ -466,6 +626,18 @@ async function scaffoldShadCN(userAnswers) {
466
626
  components.push(templateMapping.RemoteEndpoint);
467
627
  break;
468
628
  }
629
+ } else {
630
+ switch (userAnswers.chatUi) {
631
+ case "CopilotChat":
632
+ components.push(...templateMapping.CopilotChat);
633
+ break;
634
+ case "CopilotSidebar":
635
+ components.push(...templateMapping.CopilotSidebar);
636
+ break;
637
+ case "CopilotPopup":
638
+ components.push(...templateMapping.CopilotPopup);
639
+ break;
640
+ }
469
641
  }
470
642
  await new Promise((resolve) => setTimeout(resolve, 100));
471
643
  try {
@@ -492,7 +664,7 @@ import fs from "fs";
492
664
  async function getLangGraphAgents(url, langSmithApiKey) {
493
665
  try {
494
666
  const response = await fetch(
495
- `${url}/assistants/search`,
667
+ `${url.trim().replace(/\/$/, "")}/assistants/search`,
496
668
  {
497
669
  method: "POST",
498
670
  headers: {
@@ -505,10 +677,9 @@ async function getLangGraphAgents(url, langSmithApiKey) {
505
677
  })
506
678
  }
507
679
  );
508
- const result = await response.json();
509
- return result;
680
+ return await response.json();
510
681
  } catch (error) {
511
- throw new Error("Failed to get LangGraph agents");
682
+ throw new Error(`Failed to get LangGraph agents: ${error}`);
512
683
  }
513
684
  }
514
685
 
@@ -781,7 +952,7 @@ async function addCrewInputs(url, token) {
781
952
  }
782
953
  }
783
954
  async function getCrewInputs(url, token) {
784
- const response = await fetch(`${url}/inputs`, {
955
+ const response = await fetch(`${url.trim()}/inputs`, {
785
956
  headers: {
786
957
  Authorization: `Bearer ${token}`
787
958
  }
@@ -838,7 +1009,8 @@ var CloudInit = class _CloudInit extends BaseCommand {
838
1009
  name: q.name,
839
1010
  message: q.message,
840
1011
  when: q.when,
841
- default: q.default
1012
+ default: q.default,
1013
+ validate: q.validate
842
1014
  };
843
1015
  switch (q.type) {
844
1016
  case "yes/no":
@@ -858,12 +1030,32 @@ var CloudInit = class _CloudInit extends BaseCommand {
858
1030
  return {
859
1031
  ...baseQuestion,
860
1032
  type: q.sensitive ? "password" : "input",
861
- mask: q.sensitive ? "*" : void 0
1033
+ mask: q.sensitive ? "*" : void 0,
1034
+ // Add sanitization filter for input fields
1035
+ filter: q.sanitize ? (input) => q.sanitize(input) : void 0
862
1036
  };
863
1037
  }
864
1038
  });
865
1039
  const answers = await inquirer3.prompt(inquirerQuestions);
866
- return { ...answers };
1040
+ try {
1041
+ const spinner = ora5({ text: "Validating configuration...", color: "green" }).start();
1042
+ const validatedConfig = ConfigSchema.parse(answers);
1043
+ spinner.succeed(`\u{1F50D} Configuration validated successfully`);
1044
+ return validatedConfig;
1045
+ } catch (error) {
1046
+ const spinner = ora5({ text: "Validation failed...", color: "red" }).start();
1047
+ if (error.errors) {
1048
+ const formattedErrors = error.errors.map(
1049
+ (err) => `- ${err.path.join(".")}: ${err.message}`
1050
+ ).join("\n");
1051
+ spinner.fail(chalk6.red("Configuration validation failed:"));
1052
+ console.error(chalk6.red(formattedErrors));
1053
+ process.exit(1);
1054
+ }
1055
+ spinner.fail(chalk6.red("Unexpected validation error:"));
1056
+ console.error(chalk6.red(error.message || "Unknown error"));
1057
+ process.exit(1);
1058
+ }
867
1059
  }
868
1060
  async setupCloud(flags, userAnswers) {
869
1061
  const { cliToken, organization } = await this.authService.requireLogin(this);
@@ -892,24 +1084,46 @@ var CloudInit = class _CloudInit extends BaseCommand {
892
1084
  selectedProjectId = projectId;
893
1085
  }
894
1086
  const copilotCloudPublicApiKey = await this.trpcClient.getCopilotCloudPublicApiKey.query({ projectId: selectedProjectId });
895
- userAnswers.copilotCloudPublicApiKey = copilotCloudPublicApiKey?.key;
1087
+ try {
1088
+ const sanitizedConfig = {
1089
+ ...userAnswers,
1090
+ copilotCloudPublicApiKey: copilotCloudPublicApiKey?.key,
1091
+ crewUrl: userAnswers.crewUrl ? sanitizers.url(userAnswers.crewUrl) : void 0,
1092
+ langGraphPlatformUrl: userAnswers.langGraphPlatformUrl ? sanitizers.url(userAnswers.langGraphPlatformUrl) : void 0,
1093
+ langGraphRemoteEndpointURL: userAnswers.langGraphRemoteEndpointURL ? sanitizers.url(userAnswers.langGraphRemoteEndpointURL) : void 0,
1094
+ crewBearerToken: userAnswers.crewBearerToken ? sanitizers.apiKey(userAnswers.crewBearerToken) : void 0,
1095
+ langSmithApiKey: userAnswers.langSmithApiKey ? sanitizers.apiKey(userAnswers.langSmithApiKey) : void 0,
1096
+ llmToken: userAnswers.llmToken ? sanitizers.apiKey(userAnswers.llmToken) : void 0
1097
+ };
1098
+ const updatedConfig = ConfigSchema.parse(sanitizedConfig);
1099
+ Object.assign(userAnswers, updatedConfig);
1100
+ } catch (error) {
1101
+ this.log(chalk6.red(`Failed to update configuration with Copilot Cloud API key: ${error.message}`));
1102
+ }
896
1103
  if (userAnswers.crewUrl && userAnswers.crewName && userAnswers.crewBearerToken) {
897
1104
  const crewSpinner = ora5({
898
1105
  text: chalk6("\u{1F465} Adding Crew to Copilot Cloud..."),
899
1106
  color: "cyan"
900
1107
  }).start();
901
- await this.trpcClient.createRemoteEndpoint.mutate({
902
- type: "CrewAI",
903
- projectId: selectedProjectId,
904
- config: {
1108
+ try {
1109
+ await this.trpcClient.createRemoteEndpoint.mutate({
905
1110
  type: "CrewAI",
906
- url: userAnswers.crewUrl,
907
- agentName: userAnswers.crewName,
908
- agentDescription: "A helpful Crew",
909
- crewApiBearerToken: userAnswers.crewBearerToken
910
- }
911
- });
912
- crewSpinner.succeed(chalk6("\u{1F465} Crew added to Copilot Cloud"));
1111
+ projectId: selectedProjectId,
1112
+ config: {
1113
+ type: "CrewAI",
1114
+ url: userAnswers.crewUrl,
1115
+ // Already sanitized
1116
+ agentName: userAnswers.crewName,
1117
+ agentDescription: "A helpful Crew",
1118
+ crewApiBearerToken: userAnswers.crewBearerToken
1119
+ }
1120
+ });
1121
+ crewSpinner.succeed(chalk6("\u{1F465} Crew added to Copilot Cloud"));
1122
+ } catch (error) {
1123
+ crewSpinner.fail(chalk6("\u{1F465} Failed to add Crew to Copilot Cloud"));
1124
+ console.error(error);
1125
+ process.exit(1);
1126
+ }
913
1127
  }
914
1128
  if (userAnswers.agentFramework === "LangGraph" && userAnswers.useCopilotCloud === "Yes" && userAnswers.alreadyDeployed === "Yes") {
915
1129
  const langGraphSpinner = ora5({
@@ -927,6 +1141,7 @@ var CloudInit = class _CloudInit extends BaseCommand {
927
1141
  projectId: selectedProjectId,
928
1142
  config: {
929
1143
  deploymentUrl: userAnswers.langGraphPlatformUrl,
1144
+ // Already sanitized
930
1145
  langsmithApiKey: userAnswers.langSmithApiKey,
931
1146
  agents: []
932
1147
  }
@@ -944,6 +1159,7 @@ var CloudInit = class _CloudInit extends BaseCommand {
944
1159
  config: {
945
1160
  type: "CopilotKit",
946
1161
  url: userAnswers.langGraphRemoteEndpointURL
1162
+ // Already sanitized
947
1163
  }
948
1164
  });
949
1165
  langGraphSpinner.succeed(chalk6("\u{1F99C}\u{1F517} LangGraph remote endpoint created"));
@@ -955,24 +1171,33 @@ var CloudInit = class _CloudInit extends BaseCommand {
955
1171
  }
956
1172
  }
957
1173
  validateProjectCompatibility(flags) {
958
- const projectPath = path5.resolve(process.cwd(), flags.dir);
959
- if (!fs5.existsSync(projectPath)) {
960
- this.gracefulError(`Directory ${flags.dir} does not exist. Please provide a valid Next.js project directory.`);
961
- return;
962
- }
963
- const packageJsonPath = path5.join(projectPath, "package.json");
964
- if (!fs5.existsSync(packageJsonPath)) {
965
- this.gracefulError(`Directory ${projectPath} does not contain a package.json file. Please provide a valid Next.js project.`);
966
- process.exit(1);
967
- }
968
- const packageJson = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
969
- if (!packageJson.dependencies?.next && !packageJson.devDependencies?.next) {
970
- this.gracefulError(`Directory ${projectPath} does not appear to be a Next.js project. Make sure it has next in dependencies.`);
1174
+ const spinner = ora5("Checking Next.js project compatibility...").start();
1175
+ try {
1176
+ const projectPath = path5.resolve(process.cwd(), flags.dir);
1177
+ if (!fs5.existsSync(projectPath)) {
1178
+ spinner.fail(`Directory ${flags.dir} does not exist`);
1179
+ throw new Error(`Please provide a valid Next.js project directory.`);
1180
+ }
1181
+ const packageJsonPath = path5.join(projectPath, "package.json");
1182
+ if (!fs5.existsSync(packageJsonPath)) {
1183
+ spinner.fail(`No package.json found in ${projectPath}`);
1184
+ throw new Error(`Please provide a valid Next.js project with a package.json file.`);
1185
+ }
1186
+ const packageJson = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
1187
+ if (!packageJson.dependencies?.next && !packageJson.devDependencies?.next) {
1188
+ spinner.fail(`Not a Next.js project`);
1189
+ throw new Error(`Directory ${projectPath} does not appear to be a Next.js project. Make sure it has next in dependencies.`);
1190
+ }
1191
+ spinner.succeed(chalk6.green(`Valid Next.js project detected at ${projectPath}`));
1192
+ return true;
1193
+ } catch (error) {
1194
+ if (!spinner.isSpinning) {
1195
+ this.log(chalk6.red(error.message));
1196
+ } else {
1197
+ spinner.fail(chalk6.red(error.message));
1198
+ }
971
1199
  process.exit(1);
972
1200
  }
973
- this.log(chalk6.green(`Valid Next.js project detected
974
- `));
975
- return true;
976
1201
  }
977
1202
  finalSummary(userAnswers) {
978
1203
  let agentDevInstructions = "";