copilotkit 0.0.25 → 0.0.27

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 (47) 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 +329 -102
  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 +243 -59
  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 +198 -35
  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/agent.js +1 -1
  19. package/dist/lib/init/scaffold/agent.js.map +1 -1
  20. package/dist/lib/init/scaffold/crew-inputs.js +1 -1
  21. package/dist/lib/init/scaffold/crew-inputs.js.map +1 -1
  22. package/dist/lib/init/scaffold/env.d.ts +1 -0
  23. package/dist/lib/init/scaffold/env.js +5 -2
  24. package/dist/lib/init/scaffold/env.js.map +1 -1
  25. package/dist/lib/init/scaffold/index.d.ts +1 -0
  26. package/dist/lib/init/scaffold/index.js +133 -32
  27. package/dist/lib/init/scaffold/index.js.map +1 -1
  28. package/dist/lib/init/scaffold/langgraph-assistants.js +1 -1
  29. package/dist/lib/init/scaffold/langgraph-assistants.js.map +1 -1
  30. package/dist/lib/init/scaffold/packages.d.ts +1 -0
  31. package/dist/lib/init/scaffold/shadcn.d.ts +1 -0
  32. package/dist/lib/init/scaffold/shadcn.js +126 -28
  33. package/dist/lib/init/scaffold/shadcn.js.map +1 -1
  34. package/dist/lib/init/types/index.d.ts +2 -1
  35. package/dist/lib/init/types/index.js +114 -8
  36. package/dist/lib/init/types/index.js.map +1 -1
  37. package/dist/lib/init/types/questions.d.ts +164 -36
  38. package/dist/lib/init/types/questions.js +112 -6
  39. package/dist/lib/init/types/questions.js.map +1 -1
  40. package/dist/lib/init/types/templates.d.ts +1 -1
  41. package/dist/lib/init/types/templates.js +3 -3
  42. package/dist/lib/init/types/templates.js.map +1 -1
  43. package/dist/utils/version.d.ts +1 -1
  44. package/dist/utils/version.js +1 -1
  45. package/dist/utils/version.js.map +1 -1
  46. package/oclif.manifest.json +4 -7
  47. 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.25";
225
+ var LIB_VERSION = "0.0.27";
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
- var AGENT_FRAMEWORKS = ["CrewAI", "LangGraph", "None"];
278
+ var AGENT_FRAMEWORKS = ["CrewAI", "LangGraph"];
278
279
  var CREW_TYPES = ["Crews", "Flows"];
279
280
  var CHAT_COMPONENTS = ["CopilotChat", "CopilotSidebar", "Headless", "CopilotPopup"];
280
- var LANGGRAPH_AGENTS = ["Python Starter", "TypeScript Starter", "None"];
281
- var CREW_FLOW_TEMPLATES = ["Starter", "None"];
281
+ var LANGGRAPH_AGENTS = ["Python Starter", "TypeScript Starter"];
282
+ var CREW_FLOW_TEMPLATES = ["Starter"];
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 }),
@@ -296,14 +389,14 @@ var ConfigFlags = {
296
389
  };
297
390
 
298
391
  // src/lib/init/types/templates.ts
299
- var BASE_URL = "https://registry.copilotkit.ai/r";
392
+ var BASE_URL = "http://localhost:3002/r";
300
393
  var templateMapping = {
301
- "LangGraphPlatform": `${BASE_URL}/langgraph-platform-starter.json`,
394
+ "LangGraphPlatformRuntime": `${BASE_URL}/langgraph-platform-starter.json`,
302
395
  "RemoteEndpoint": `${BASE_URL}/remote-endpoint-starter.json`,
303
396
  "CrewEnterprise": [
304
397
  `${BASE_URL}/coagents-crew-starter.json`
305
398
  ],
306
- "LangGraphGeneric": `${BASE_URL}/generic-lg-starter.json`,
399
+ "LangGraphGeneric": `${BASE_URL}/generic-lg-starter-with-cloud.json`,
307
400
  "CrewFlowsStarter": [
308
401
  `${BASE_URL}/coagents-starter-ui.json`,
309
402
  `${BASE_URL}/agent-layout.json`,
@@ -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
- message: "\u{1F517} Enter your Crew's URL:",
351
- when: (answers) => answers.agentFramework === "CrewAI" && answers.crewType === "Crews"
474
+ message: "\u{1F517} Enter your Crew's Enterprise URL (more info at https://app.crewai.com):",
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,26 +498,49 @@ 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
- message: "\u{1F99C}\u{1F517} Is it hosted with LangGraph Platform (local or cloud)?",
379
- when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "Yes"
514
+ message: "\u{1F99C}\u{1F517} Is it hosted with LangGraph Platform (either self-hosted or in LangSmith)?",
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"
386
- },
387
- {
388
- type: "input",
389
- name: "langGraphRemoteEndpointURL",
390
- message: "\u{1F50C} Enter your LangGraph endpoint URL:",
391
- when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "Yes" && answers.langGraphPlatform === "No"
529
+ when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "Yes" && answers.langGraphPlatform === "Yes",
530
+ validate: validateUrl,
531
+ sanitize: sanitizers.url
392
532
  },
533
+ // {
534
+ // type: 'input',
535
+ // name: 'langGraphRemoteEndpointURL',
536
+ // message: '🔌 Enter your LangGraph endpoint URL:',
537
+ // when: (answers) =>
538
+ // answers.agentFramework === 'LangGraph' &&
539
+ // answers.alreadyDeployed === 'Yes' &&
540
+ // answers.langGraphPlatform === 'No',
541
+ // validate: validateUrl,
542
+ // sanitize: sanitizers.url
543
+ // },
393
544
  {
394
545
  type: "select",
395
546
  name: "langGraphAgent",
@@ -402,14 +553,24 @@ var questions = [
402
553
  name: "langSmithApiKey",
403
554
  message: "\u{1F99C}\u{1F517} Enter your LangSmith API key (required by LangGraph Platform) :",
404
555
  when: (answers) => answers.agentFramework === "LangGraph" && answers.langGraphPlatform === "Yes",
405
- sensitive: true
556
+ sensitive: true,
557
+ validate: validateRequired,
558
+ sanitize: sanitizers.apiKey
406
559
  },
407
560
  // Deployment options
408
561
  {
409
562
  type: "yes/no",
410
563
  name: "useCopilotCloud",
411
564
  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"
565
+ when: (answers) => !(answers.agentFramework === "CrewAI" && answers.crewType === "Crews") && answers.crewType !== "Flows" && answers.alreadyDeployed === "Yes" && answers.langGraphPlatform !== "No",
566
+ validate: (input) => {
567
+ try {
568
+ YesNoSchema.parse(input);
569
+ return true;
570
+ } catch (error) {
571
+ return "Please select Yes or No";
572
+ }
573
+ }
413
574
  },
414
575
  // {
415
576
  // type: 'yes/no',
@@ -422,20 +583,22 @@ var questions = [
422
583
  // answers.useCopilotCloud !== 'Yes',
423
584
  // },
424
585
  // UI components - always shown last
425
- {
426
- type: "select",
427
- name: "chatUi",
428
- message: "\u{1F4AC} Select a UI component for your copilot:",
429
- choices: Array.from(CHAT_COMPONENTS),
430
- default: "CopilotChat",
431
- when: (answers) => answers.agentFramework === "None"
432
- },
586
+ // {
587
+ // type: 'select',
588
+ // name: 'chatUi',
589
+ // message: '💬 Select a UI component for your copilot:',
590
+ // choices: Array.from(CHAT_COMPONENTS),
591
+ // default: 'CopilotChat',
592
+ // when: (answers) => answers.agentFramework === 'None',
593
+ // },
433
594
  {
434
595
  type: "input",
435
596
  name: "llmToken",
436
597
  message: "\u{1F511} Enter your OpenAI API key (required for agent functionality):",
437
598
  when: (answers) => answers.agentFramework === "LangGraph" && answers.alreadyDeployed === "No" || answers.agentFramework === "CrewAI" && answers.crewType === "Flows",
438
- sensitive: true
599
+ sensitive: true,
600
+ validate: validateRequired,
601
+ sanitize: sanitizers.apiKey
439
602
  }
440
603
  ];
441
604
 
@@ -444,28 +607,33 @@ import spawn from "cross-spawn";
444
607
  async function scaffoldShadCN(userAnswers) {
445
608
  try {
446
609
  const components = [];
447
- if (userAnswers.agentFramework !== "None") {
448
- switch (userAnswers.agentFramework) {
449
- case "LangGraph":
450
- if (userAnswers.langGraphAgent && userAnswers.langGraphAgent !== "None") {
451
- components.push(...templateMapping.LangGraphStarter);
452
- } else {
453
- components.push(templateMapping.LangGraphGeneric);
454
- }
455
- break;
456
- case "CrewAI":
457
- if (userAnswers.crewType === "Crews") {
458
- components.push(...templateMapping.CrewEnterprise);
459
- } else if (userAnswers.crewFlowAgent) {
460
- components.push(...templateMapping.CrewFlowsStarter);
461
- } else {
462
- components.push(templateMapping.RemoteEndpoint);
610
+ switch (userAnswers.agentFramework) {
611
+ case "LangGraph":
612
+ if (userAnswers.langGraphAgent) {
613
+ components.push(...templateMapping.LangGraphStarter);
614
+ } else {
615
+ components.push(templateMapping.LangGraphGeneric);
616
+ if (userAnswers.useCopilotCloud !== "Yes") {
617
+ if (userAnswers.langGraphPlatform === "Yes") {
618
+ components.push(templateMapping.LangGraphPlatformRuntime);
619
+ } else {
620
+ components.push(templateMapping.RemoteEndpoint);
621
+ }
463
622
  }
464
- break;
465
- default:
623
+ }
624
+ break;
625
+ case "CrewAI":
626
+ if (userAnswers.crewType === "Crews") {
627
+ components.push(...templateMapping.CrewEnterprise);
628
+ } else if (userAnswers.crewFlowAgent) {
629
+ components.push(...templateMapping.CrewFlowsStarter);
630
+ } else {
466
631
  components.push(templateMapping.RemoteEndpoint);
467
- break;
468
- }
632
+ }
633
+ break;
634
+ default:
635
+ components.push(templateMapping.RemoteEndpoint);
636
+ break;
469
637
  }
470
638
  await new Promise((resolve) => setTimeout(resolve, 100));
471
639
  try {
@@ -492,7 +660,7 @@ import fs from "fs";
492
660
  async function getLangGraphAgents(url, langSmithApiKey) {
493
661
  try {
494
662
  const response = await fetch(
495
- `${url}/assistants/search`,
663
+ `${url.trim().replace(/\/$/, "")}/assistants/search`,
496
664
  {
497
665
  method: "POST",
498
666
  headers: {
@@ -537,13 +705,16 @@ async function scaffoldEnv(flags, userAnswers) {
537
705
  newEnvValues += `NEXT_PUBLIC_COPILOTKIT_AGENT_NAME=${userAnswers.crewName}
538
706
  `;
539
707
  }
540
- if (userAnswers.langGraphAgent !== "None" && userAnswers.langGraphPlatform !== "Yes") {
708
+ if (userAnswers.langGraphAgent) {
541
709
  newEnvValues += `NEXT_PUBLIC_COPILOTKIT_AGENT_NAME=sample_agent
542
710
  `;
543
711
  newEnvValues += `LANGGRAPH_DEPLOYMENT_URL=http://localhost:8123
544
712
  `;
545
713
  } else if (userAnswers.langGraphPlatform === "Yes" && userAnswers.useCopilotCloud === "No") {
546
714
  newEnvValues += `LANGGRAPH_DEPLOYMENT_URL=${userAnswers.langGraphPlatformUrl}
715
+ `;
716
+ } else if (userAnswers.langGraphRemoteEndpointURL) {
717
+ newEnvValues += `COPILOTKIT_REMOTE_ENDPOINT=${userAnswers.langGraphRemoteEndpointURL}
547
718
  `;
548
719
  }
549
720
  if (flags.runtimeUrl) {
@@ -681,7 +852,7 @@ import chalk5 from "chalk";
681
852
  import path3 from "path";
682
853
  import fs3 from "fs";
683
854
  async function scaffoldAgent(userAnswers) {
684
- if (userAnswers.agentFramework === "None" || userAnswers.agentFramework === "CrewAI" && userAnswers.crewType === "Crews" || userAnswers.agentFramework === "LangGraph" && (!userAnswers.langGraphAgent || userAnswers.langGraphAgent === "None")) {
855
+ if (userAnswers.agentFramework === "CrewAI" && userAnswers.crewType === "Crews" || userAnswers.agentFramework === "LangGraph" && !userAnswers.langGraphAgent) {
685
856
  return;
686
857
  }
687
858
  const spinner = ora3({
@@ -780,7 +951,7 @@ async function addCrewInputs(url, token) {
780
951
  }
781
952
  }
782
953
  async function getCrewInputs(url, token) {
783
- const response = await fetch(`${url}/inputs`, {
954
+ const response = await fetch(`${url.trim()}/inputs`, {
784
955
  headers: {
785
956
  Authorization: `Bearer ${token}`
786
957
  }
@@ -837,7 +1008,8 @@ var CloudInit = class _CloudInit extends BaseCommand {
837
1008
  name: q.name,
838
1009
  message: q.message,
839
1010
  when: q.when,
840
- default: q.default
1011
+ default: q.default,
1012
+ validate: q.validate
841
1013
  };
842
1014
  switch (q.type) {
843
1015
  case "yes/no":
@@ -857,12 +1029,37 @@ var CloudInit = class _CloudInit extends BaseCommand {
857
1029
  return {
858
1030
  ...baseQuestion,
859
1031
  type: q.sensitive ? "password" : "input",
860
- mask: q.sensitive ? "*" : void 0
1032
+ mask: q.sensitive ? "*" : void 0,
1033
+ // Add sanitization filter for input fields
1034
+ filter: q.sanitize ? (input) => q.sanitize(input) : void 0
861
1035
  };
862
1036
  }
863
1037
  });
864
1038
  const answers = await inquirer3.prompt(inquirerQuestions);
865
- return { ...answers };
1039
+ if (answers.langGraphPlatform === "No") {
1040
+ this.log("\nCurrently the CLI only supports scaffolding LangGraph Platform agents. Use our quickstart guide to get started:\n");
1041
+ this.log(chalk6.blue("https://docs.copilotkit.ai/coagents/quickstart/langgraph"));
1042
+ process.exit(0);
1043
+ }
1044
+ try {
1045
+ const spinner = ora5({ text: "Validating configuration...", color: "green" }).start();
1046
+ const validatedConfig = ConfigSchema.parse(answers);
1047
+ spinner.succeed(`\u{1F50D} Configuration validated successfully`);
1048
+ return validatedConfig;
1049
+ } catch (error) {
1050
+ const spinner = ora5({ text: "Validation failed...", color: "red" }).start();
1051
+ if (error.errors) {
1052
+ const formattedErrors = error.errors.map(
1053
+ (err) => `- ${err.path.join(".")}: ${err.message}`
1054
+ ).join("\n");
1055
+ spinner.fail(chalk6.red("Configuration validation failed:"));
1056
+ console.error(chalk6.red(formattedErrors));
1057
+ process.exit(1);
1058
+ }
1059
+ spinner.fail(chalk6.red("Unexpected validation error:"));
1060
+ console.error(chalk6.red(error.message || "Unknown error"));
1061
+ process.exit(1);
1062
+ }
866
1063
  }
867
1064
  async setupCloud(flags, userAnswers) {
868
1065
  const { cliToken, organization } = await this.authService.requireLogin(this);
@@ -891,24 +1088,46 @@ var CloudInit = class _CloudInit extends BaseCommand {
891
1088
  selectedProjectId = projectId;
892
1089
  }
893
1090
  const copilotCloudPublicApiKey = await this.trpcClient.getCopilotCloudPublicApiKey.query({ projectId: selectedProjectId });
894
- userAnswers.copilotCloudPublicApiKey = copilotCloudPublicApiKey?.key;
1091
+ try {
1092
+ const sanitizedConfig = {
1093
+ ...userAnswers,
1094
+ copilotCloudPublicApiKey: copilotCloudPublicApiKey?.key,
1095
+ crewUrl: userAnswers.crewUrl ? sanitizers.url(userAnswers.crewUrl) : void 0,
1096
+ langGraphPlatformUrl: userAnswers.langGraphPlatformUrl ? sanitizers.url(userAnswers.langGraphPlatformUrl) : void 0,
1097
+ langGraphRemoteEndpointURL: userAnswers.langGraphRemoteEndpointURL ? sanitizers.url(userAnswers.langGraphRemoteEndpointURL) : void 0,
1098
+ crewBearerToken: userAnswers.crewBearerToken ? sanitizers.apiKey(userAnswers.crewBearerToken) : void 0,
1099
+ langSmithApiKey: userAnswers.langSmithApiKey ? sanitizers.apiKey(userAnswers.langSmithApiKey) : void 0,
1100
+ llmToken: userAnswers.llmToken ? sanitizers.apiKey(userAnswers.llmToken) : void 0
1101
+ };
1102
+ const updatedConfig = ConfigSchema.parse(sanitizedConfig);
1103
+ Object.assign(userAnswers, updatedConfig);
1104
+ } catch (error) {
1105
+ this.log(chalk6.red(`Failed to update configuration with Copilot Cloud API key: ${error.message}`));
1106
+ }
895
1107
  if (userAnswers.crewUrl && userAnswers.crewName && userAnswers.crewBearerToken) {
896
1108
  const crewSpinner = ora5({
897
1109
  text: chalk6("\u{1F465} Adding Crew to Copilot Cloud..."),
898
1110
  color: "cyan"
899
1111
  }).start();
900
- await this.trpcClient.createRemoteEndpoint.mutate({
901
- type: "CrewAI",
902
- projectId: selectedProjectId,
903
- config: {
1112
+ try {
1113
+ await this.trpcClient.createRemoteEndpoint.mutate({
904
1114
  type: "CrewAI",
905
- url: userAnswers.crewUrl,
906
- agentName: userAnswers.crewName,
907
- agentDescription: "A helpful Crew",
908
- crewApiBearerToken: userAnswers.crewBearerToken
909
- }
910
- });
911
- crewSpinner.succeed(chalk6("\u{1F465} Crew added to Copilot Cloud"));
1115
+ projectId: selectedProjectId,
1116
+ config: {
1117
+ type: "CrewAI",
1118
+ url: userAnswers.crewUrl,
1119
+ // Already sanitized
1120
+ agentName: userAnswers.crewName,
1121
+ agentDescription: "A helpful Crew",
1122
+ crewApiBearerToken: userAnswers.crewBearerToken
1123
+ }
1124
+ });
1125
+ crewSpinner.succeed(chalk6("\u{1F465} Crew added to Copilot Cloud"));
1126
+ } catch (error) {
1127
+ crewSpinner.fail(chalk6("\u{1F465} Failed to add Crew to Copilot Cloud"));
1128
+ console.error(error);
1129
+ process.exit(1);
1130
+ }
912
1131
  }
913
1132
  if (userAnswers.agentFramework === "LangGraph" && userAnswers.useCopilotCloud === "Yes" && userAnswers.alreadyDeployed === "Yes") {
914
1133
  const langGraphSpinner = ora5({
@@ -926,6 +1145,7 @@ var CloudInit = class _CloudInit extends BaseCommand {
926
1145
  projectId: selectedProjectId,
927
1146
  config: {
928
1147
  deploymentUrl: userAnswers.langGraphPlatformUrl,
1148
+ // Already sanitized
929
1149
  langsmithApiKey: userAnswers.langSmithApiKey,
930
1150
  agents: []
931
1151
  }
@@ -943,6 +1163,7 @@ var CloudInit = class _CloudInit extends BaseCommand {
943
1163
  config: {
944
1164
  type: "CopilotKit",
945
1165
  url: userAnswers.langGraphRemoteEndpointURL
1166
+ // Already sanitized
946
1167
  }
947
1168
  });
948
1169
  langGraphSpinner.succeed(chalk6("\u{1F99C}\u{1F517} LangGraph remote endpoint created"));
@@ -954,38 +1175,44 @@ var CloudInit = class _CloudInit extends BaseCommand {
954
1175
  }
955
1176
  }
956
1177
  validateProjectCompatibility(flags) {
957
- const projectPath = path5.resolve(process.cwd(), flags.dir);
958
- if (!fs5.existsSync(projectPath)) {
959
- this.gracefulError(`Directory ${flags.dir} does not exist. Please provide a valid Next.js project directory.`);
960
- return;
961
- }
962
- const packageJsonPath = path5.join(projectPath, "package.json");
963
- if (!fs5.existsSync(packageJsonPath)) {
964
- this.gracefulError(`Directory ${projectPath} does not contain a package.json file. Please provide a valid Next.js project.`);
965
- process.exit(1);
966
- }
967
- const packageJson = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
968
- if (!packageJson.dependencies?.next && !packageJson.devDependencies?.next) {
969
- this.gracefulError(`Directory ${projectPath} does not appear to be a Next.js project. Make sure it has next in dependencies.`);
1178
+ const spinner = ora5("Checking Next.js project compatibility...").start();
1179
+ try {
1180
+ const projectPath = path5.resolve(process.cwd(), flags.dir);
1181
+ if (!fs5.existsSync(projectPath)) {
1182
+ spinner.fail(`Directory ${flags.dir} does not exist`);
1183
+ throw new Error(`Please provide a valid Next.js project directory.`);
1184
+ }
1185
+ const packageJsonPath = path5.join(projectPath, "package.json");
1186
+ if (!fs5.existsSync(packageJsonPath)) {
1187
+ spinner.fail(`No package.json found in ${projectPath}`);
1188
+ throw new Error(`Please provide a valid Next.js project with a package.json file.`);
1189
+ }
1190
+ const packageJson = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
1191
+ if (!packageJson.dependencies?.next && !packageJson.devDependencies?.next) {
1192
+ spinner.fail(`Not a Next.js project`);
1193
+ throw new Error(`Directory ${projectPath} does not appear to be a Next.js project. Make sure it has next in dependencies.`);
1194
+ }
1195
+ spinner.succeed(`\u{1F53C} Valid Next.js project detected at ${projectPath}`);
1196
+ return true;
1197
+ } catch (error) {
1198
+ if (!spinner.isSpinning) {
1199
+ this.log(chalk6.red(error.message));
1200
+ } else {
1201
+ spinner.fail(chalk6.red(error.message));
1202
+ }
970
1203
  process.exit(1);
971
1204
  }
972
- this.log(chalk6.green(`Valid Next.js project detected
973
- `));
974
- return true;
975
1205
  }
976
1206
  finalSummary(userAnswers) {
977
1207
  let agentDevInstructions = "";
978
1208
  let agentType = "";
979
1209
  let agentSetupMessage = "";
980
- if (userAnswers.agentFramework !== "None") {
981
- if (userAnswers.agentFramework === "CrewAI") {
982
- agentType = "CrewAI";
983
- if (userAnswers.crewType === "Crews") {
984
- agentSetupMessage = `Using your Crew from ${chalk6.cyan(userAnswers.crewUrl || "the provided URL")}.`;
985
- } else if (userAnswers.crewType === "Flows") {
986
- agentSetupMessage = `We've scaffolded a ${chalk6.cyan(userAnswers.crewFlowAgent || "CrewAI")} agent in the ${chalk6.cyan("./agent")} directory.`;
987
- agentDevInstructions = "poetry install && poetry run demo";
988
- }
1210
+ if (userAnswers.agentFramework === "CrewAI") {
1211
+ agentType = "CrewAI";
1212
+ if (userAnswers.crewType === "Crews") {
1213
+ agentSetupMessage = `Using your Crew from ${chalk6.cyan(userAnswers.crewUrl || "the provided URL")}.`;
1214
+ } else if (userAnswers.crewType === "Flows") {
1215
+ agentSetupMessage = `We've scaffolded a ${chalk6.cyan(userAnswers.crewFlowAgent || "CrewAI")} agent in the ${chalk6.cyan("./agent")} directory.`;
989
1216
  }
990
1217
  }
991
1218
  switch (userAnswers.agentFramework) {
@@ -993,7 +1220,7 @@ var CloudInit = class _CloudInit extends BaseCommand {
993
1220
  switch (userAnswers.langGraphAgent) {
994
1221
  case "Python Starter":
995
1222
  agentSetupMessage = `We've scaffolded a ${chalk6.cyan(userAnswers.langGraphAgent || "LangGraph")} agent in the ${chalk6.cyan("./agent")} directory.`;
996
- agentDevInstructions = "poetry install && npx @langchain/langgraph-cli dev --port 8123";
1223
+ agentDevInstructions = "poetry lock && poetry install && npx @langchain/langgraph-cli dev --port 8123";
997
1224
  break;
998
1225
  case "TypeScript Starter":
999
1226
  agentSetupMessage = `We've scaffolded a ${chalk6.cyan(userAnswers.langGraphAgent || "LangGraph")} agent in the ${chalk6.cyan("./agent")} directory.`;
@@ -1025,7 +1252,7 @@ var CloudInit = class _CloudInit extends BaseCommand {
1025
1252
  this.log(` - Start your Next.js app: ${chalk6.gray("$")} ${chalk6.cyan("npm run dev")}`);
1026
1253
  if (agentDevInstructions) this.log(` - Start your agent: ${chalk6.gray("$")} ${chalk6.cyan(`cd agent && ${agentDevInstructions}`)}`);
1027
1254
  this.log(` - Navigate to ${chalk6.blue("http://localhost:3000/copilotkit")}`);
1028
- this.log(` - Talk to your ${userAnswers.agentFramework !== "None" ? "agent" : "application"}.`);
1255
+ this.log(` - Talk to your agent.`);
1029
1256
  this.log(` - Read the docs: ${chalk6.blue("https://docs.copilotkit.ai")}`);
1030
1257
  this.log(chalk6.magenta("\nEnjoy building with CopilotKit \u{1FA81}\n"));
1031
1258
  }