copilotkit 0.0.48 → 0.0.50
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/dist/commands/base-command.js +1 -1
- package/dist/commands/base-command.js.map +1 -1
- package/dist/commands/create.js +1 -1
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/dev.js +13 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +617 -197
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.js +1 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/utils/detect-endpoint-type.utils.js +12 -0
- package/dist/utils/detect-endpoint-type.utils.js.map +1 -1
- package/dist/utils/version.d.ts +1 -1
- package/dist/utils/version.js +1 -1
- package/dist/utils/version.js.map +1 -1
- package/oclif.manifest.json +4 -3
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/commands/init.ts
|
|
2
|
-
import { Flags as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
2
|
+
import { Flags as Flags3 } from "@oclif/core";
|
|
3
|
+
import inquirer4 from "inquirer";
|
|
4
|
+
import path7 from "path";
|
|
5
|
+
import fs7 from "fs";
|
|
6
6
|
|
|
7
7
|
// src/services/auth.service.ts
|
|
8
8
|
import Conf2 from "conf";
|
|
@@ -284,7 +284,7 @@ import { Command } from "@oclif/core";
|
|
|
284
284
|
import Sentry, { consoleIntegration } from "@sentry/node";
|
|
285
285
|
|
|
286
286
|
// src/utils/version.ts
|
|
287
|
-
var LIB_VERSION = "0.0.
|
|
287
|
+
var LIB_VERSION = "0.0.50";
|
|
288
288
|
|
|
289
289
|
// src/commands/base-command.ts
|
|
290
290
|
import chalk2 from "chalk";
|
|
@@ -332,9 +332,406 @@ var BaseCommand = class extends Command {
|
|
|
332
332
|
}
|
|
333
333
|
};
|
|
334
334
|
|
|
335
|
+
// src/commands/create.ts
|
|
336
|
+
import { Flags, Args } from "@oclif/core";
|
|
337
|
+
import inquirer2 from "inquirer";
|
|
338
|
+
import chalk3 from "chalk";
|
|
339
|
+
import fs from "fs-extra";
|
|
340
|
+
import path from "path";
|
|
341
|
+
import { promisify } from "util";
|
|
342
|
+
import { pipeline } from "stream";
|
|
343
|
+
import { createWriteStream } from "fs";
|
|
344
|
+
import { extract } from "tar";
|
|
345
|
+
import ora2 from "ora";
|
|
346
|
+
var streamPipeline = promisify(pipeline);
|
|
347
|
+
var theme = {
|
|
348
|
+
primary: chalk3.magenta,
|
|
349
|
+
secondary: chalk3.gray,
|
|
350
|
+
tertiary: chalk3.gray,
|
|
351
|
+
error: chalk3.red,
|
|
352
|
+
command: chalk3.blue,
|
|
353
|
+
success: chalk3.green,
|
|
354
|
+
warning: chalk3.yellow,
|
|
355
|
+
divider: chalk3.gray("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"),
|
|
356
|
+
bottomPadding: ""
|
|
357
|
+
};
|
|
358
|
+
var TEMPLATE_REPOS = {
|
|
359
|
+
"langgraph-py": "copilotkit/with-langgraph-python",
|
|
360
|
+
"langgraph-js": "copilotkit/with-langgraph-js",
|
|
361
|
+
mastra: "copilotkit/with-mastra",
|
|
362
|
+
flows: "copilotkit/with-crewai-flows",
|
|
363
|
+
llamaindex: "copilotkit/with-llamaindex",
|
|
364
|
+
agno: "copilotkit/with-agno",
|
|
365
|
+
"pydantic-ai": "copilotkit/with-pydantic-ai",
|
|
366
|
+
ag2: "ag2ai/ag2-copilotkit-starter"
|
|
367
|
+
};
|
|
368
|
+
var FRAMEWORK_DOCUMENTATION = {
|
|
369
|
+
"langgraph-py": "https://langchain-ai.github.io/langgraph/concepts/why-langgraph",
|
|
370
|
+
"langgraph-js": "https://langchain-ai.github.io/langgraphjs",
|
|
371
|
+
flows: "https://docs.crewai.com/guides/flows/first-flow",
|
|
372
|
+
mastra: "https://mastra.ai/en/docs",
|
|
373
|
+
"pydantic-ai": "https://ai.pydantic.dev/ag-ui/",
|
|
374
|
+
llamaindex: "https://docs.llamaindex.ai/en/stable",
|
|
375
|
+
agno: "https://docs.agno.com/",
|
|
376
|
+
ag2: "https://docs.ag2.ai/latest/docs/user-guide/basic-concepts/overview"
|
|
377
|
+
};
|
|
378
|
+
var FRAMEWORK_EMOJI = {
|
|
379
|
+
"langgraph-js": "\u{1F99C}",
|
|
380
|
+
"langgraph-py": "\u{1F99C}",
|
|
381
|
+
flows: "\u{1F465}",
|
|
382
|
+
mastra: "\u{1F311}",
|
|
383
|
+
"pydantic-ai": "\u{1F53C}",
|
|
384
|
+
llamaindex: "\u{1F999}",
|
|
385
|
+
ag2: "\u{1F916}",
|
|
386
|
+
agno: "\u{1F170}\uFE0F"
|
|
387
|
+
};
|
|
388
|
+
var KITE = `
|
|
389
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF
|
|
390
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u281F\u2819\u28FF\u285B\u283B\u283F\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF
|
|
391
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u280B\u2800\u2800\u2808\u28BF\u2844\u2800\u2800\u2800\u2808\u2809\u2819\u28FB\u28FF\u28FF\u28FF
|
|
392
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u281F\u2801\u2800\u2800\u2800\u2800\u2808\u28BF\u2844\u2800\u2880\u28E0\u28F4\u283E\u280B\u28B8\u28FF\u28FF
|
|
393
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u285F\u2801\u2880\u28C0\u28C0\u28C0\u28C0\u28E4\u28E4\u287E\u28BF\u285F\u281B\u2809\u2800\u2800\u2800\u2800\u28FF\u28FF
|
|
394
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u285B\u281B\u281B\u281B\u2809\u2809\u2809\u2801\u2800\u28A0\u287F\u28FF\u2840\u2800\u2800\u2800\u2800\u2800\u28FF\u28FF
|
|
395
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28C6\u2800\u2800\u2800\u2800\u2800\u2800\u28F0\u285F\u2800\u2838\u28E7\u2800\u2800\u2800\u2800\u28A0\u28FF\u28FF
|
|
396
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28F7\u28C4\u2800\u2800\u2880\u28FC\u280F\u2800\u2800\u2800\u28FF\u2840\u2800\u2800\u2800\u28B8\u28FF\u28FF
|
|
397
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u2802\u28E0\u287F\u2801\u2800\u2800\u2800\u2800\u28B8\u2847\u2800\u2800\u2800\u28FF\u28FF\u28FF
|
|
398
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u281F\u28E1\u28FE\u28FF\u28C4\u2800\u2800\u2800\u2800\u2800\u28B8\u2847\u2800\u2800\u28B0\u28FF\u28FF\u28FF
|
|
399
|
+
\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u285F\u281B\u287F\u280B\u28E1\u28FE\u28FF\u28FF\u28FF\u28FF\u28E6\u2840\u2800\u2800\u2800\u28B8\u2847\u2800\u2800\u28FF\u28FF\u28FF\u28FF
|
|
400
|
+
\u28FF\u28FF\u28FF\u28FF\u287F\u283F\u28FF\u2837\u2802\u2840\u2818\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28F7\u2840\u2800\u2800\u28B8\u2847\u2800\u28FC\u28FF\u28FF\u28FF\u28FF
|
|
401
|
+
\u28FF\u28FF\u283B\u28BF\u2877\u2800\u2801\u2834\u28FF\u28F7\u28FE\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u2844\u2800\u28FE\u2807\u28F4\u28FF\u28FF\u28FF\u28FF\u28FF
|
|
402
|
+
\u287F\u281B\u2800\u2800\u28B4\u28FE\u28F7\u28F6\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28E4\u28FF\u28FE\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF
|
|
403
|
+
\u28F7\u28FE\u28FF\u28E4\u28FE\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF\u28FF
|
|
404
|
+
`;
|
|
405
|
+
var Create = class _Create extends BaseCommand {
|
|
406
|
+
constructor(argv, config, authService = new AuthService()) {
|
|
407
|
+
super(argv, config);
|
|
408
|
+
this.authService = authService;
|
|
409
|
+
}
|
|
410
|
+
trpcClient = null;
|
|
411
|
+
analytics = null;
|
|
412
|
+
startTime = Date.now();
|
|
413
|
+
analyticsQueue = [];
|
|
414
|
+
static description = "Create a new CopilotKit project with Next.js and Cloud setup";
|
|
415
|
+
static examples = [
|
|
416
|
+
"$ copilotkit create my-app",
|
|
417
|
+
"$ copilotkit create my-app --framework langgraph-js",
|
|
418
|
+
"$ copilotkit create -n my-app -f langgraph-js"
|
|
419
|
+
];
|
|
420
|
+
static flags = {
|
|
421
|
+
...BaseCommand.flags,
|
|
422
|
+
framework: Flags.string({
|
|
423
|
+
char: "f",
|
|
424
|
+
description: "Agent framework to use",
|
|
425
|
+
options: Object.keys(TEMPLATE_REPOS),
|
|
426
|
+
required: false
|
|
427
|
+
}),
|
|
428
|
+
name: Flags.string({
|
|
429
|
+
char: "n",
|
|
430
|
+
description: "Name of the project",
|
|
431
|
+
required: false
|
|
432
|
+
}),
|
|
433
|
+
"no-banner": Flags.boolean({
|
|
434
|
+
char: "q",
|
|
435
|
+
description: "Removes the banner",
|
|
436
|
+
default: false,
|
|
437
|
+
required: false
|
|
438
|
+
}),
|
|
439
|
+
project: Flags.string({
|
|
440
|
+
description: "project ID (can be found in the Copilot Cloud dashboard)"
|
|
441
|
+
})
|
|
442
|
+
};
|
|
443
|
+
static args = {
|
|
444
|
+
projectName: Args.string({
|
|
445
|
+
description: "Name of the project",
|
|
446
|
+
required: false
|
|
447
|
+
})
|
|
448
|
+
};
|
|
449
|
+
async run() {
|
|
450
|
+
const { args, flags } = await this.parse(_Create);
|
|
451
|
+
try {
|
|
452
|
+
this.analytics = new AnalyticsService();
|
|
453
|
+
if (!flags["no-banner"]) {
|
|
454
|
+
this.log(theme.primary(KITE));
|
|
455
|
+
this.log(theme.primary("~ Welcome to CopilotKit! ~\n"));
|
|
456
|
+
this.log(theme.divider);
|
|
457
|
+
if ((!flags.name || flags.projectName) && !flags.framework) {
|
|
458
|
+
this.log("\n" + theme.secondary("Just a few questions to get started!\n"));
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
const projectName = flags.name || args.projectName || await this.promptProjectName();
|
|
462
|
+
const agentFramework = flags.framework || await this.promptAgentFramework();
|
|
463
|
+
this.queueAnalytics("cli.create.started", {
|
|
464
|
+
framework_selected: agentFramework,
|
|
465
|
+
project_name: projectName,
|
|
466
|
+
flags_used: Object.keys(flags).filter((key) => flags[key] !== void 0 && key !== "help")
|
|
467
|
+
});
|
|
468
|
+
const projectDir = path.resolve(process.cwd(), projectName);
|
|
469
|
+
if (fs.existsSync(projectDir)) {
|
|
470
|
+
this.log(theme.error(`
|
|
471
|
+
Directory "${projectName}" already exists.`));
|
|
472
|
+
this.log(theme.secondary("\nYou can:"));
|
|
473
|
+
this.log(theme.secondary(" 1. Choose a different project name"));
|
|
474
|
+
this.log(theme.secondary(" 2. Remove the existing directory manually if you want to use this name\n"));
|
|
475
|
+
this.exit(1);
|
|
476
|
+
}
|
|
477
|
+
this.log(chalk3.cyan("\n\u{1F511} Now get your API key"));
|
|
478
|
+
this.log(chalk3.gray("Setting up your cloud account and retrieving your API key...\n"));
|
|
479
|
+
let cloudSetupInfo = null;
|
|
480
|
+
try {
|
|
481
|
+
cloudSetupInfo = await this.setupCloudApiKey(flags);
|
|
482
|
+
if (this.analytics && cloudSetupInfo.cliToken) {
|
|
483
|
+
const trpcClient2 = createTRPCClient(cloudSetupInfo.cliToken);
|
|
484
|
+
const me = await trpcClient2.me.query();
|
|
485
|
+
if (me.user && me.organization) {
|
|
486
|
+
this.analytics = new AnalyticsService({
|
|
487
|
+
userId: me.user.id,
|
|
488
|
+
organizationId: me.organization.id,
|
|
489
|
+
email: me.user.email
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
this.queueAnalytics("cli.create.cloud_setup_completed", {
|
|
494
|
+
framework: agentFramework,
|
|
495
|
+
project_id: cloudSetupInfo.selectedProjectId,
|
|
496
|
+
api_key_retrieved: !!cloudSetupInfo.apiKey
|
|
497
|
+
});
|
|
498
|
+
} catch (error) {
|
|
499
|
+
this.queueAnalytics("cli.create.cloud_setup_failed", {
|
|
500
|
+
framework: agentFramework,
|
|
501
|
+
error: error.message
|
|
502
|
+
});
|
|
503
|
+
throw error;
|
|
504
|
+
}
|
|
505
|
+
const options = {
|
|
506
|
+
projectName,
|
|
507
|
+
agentFramework,
|
|
508
|
+
apiKey: cloudSetupInfo?.apiKey,
|
|
509
|
+
projectId: cloudSetupInfo?.selectedProjectId
|
|
510
|
+
};
|
|
511
|
+
const spinner = ora2({
|
|
512
|
+
text: theme.secondary.bold("Creating your project..."),
|
|
513
|
+
color: "cyan",
|
|
514
|
+
spinner: "dots"
|
|
515
|
+
}).start();
|
|
516
|
+
try {
|
|
517
|
+
await fs.ensureDir(projectDir);
|
|
518
|
+
spinner.text = theme.secondary.bold("Downloading template...");
|
|
519
|
+
await this.downloadTemplate(projectDir, options.agentFramework);
|
|
520
|
+
if (options.apiKey) {
|
|
521
|
+
spinner.text = theme.secondary.bold("Configuring API key...");
|
|
522
|
+
await this.configureApiKey(projectDir, options.apiKey);
|
|
523
|
+
}
|
|
524
|
+
spinner.succeed(theme.secondary.bold(`Project "${projectName}" created successfully!`));
|
|
525
|
+
this.queueAnalytics("cli.create.project_created", {
|
|
526
|
+
framework: agentFramework,
|
|
527
|
+
project_name: projectName,
|
|
528
|
+
has_api_key: !!options.apiKey,
|
|
529
|
+
duration_ms: Date.now() - this.startTime
|
|
530
|
+
});
|
|
531
|
+
this.log("\n" + theme.divider);
|
|
532
|
+
this.log(
|
|
533
|
+
"\n" + theme.secondary.bold(
|
|
534
|
+
`\u{1FA81}\u{1F91D}${FRAMEWORK_EMOJI[options.agentFramework]} All set!
|
|
535
|
+
|
|
536
|
+
Your project is ready with Copilot Cloud configured.`
|
|
537
|
+
)
|
|
538
|
+
);
|
|
539
|
+
this.log("\n" + theme.secondary("Next steps:"));
|
|
540
|
+
this.log(theme.secondary(` \u2022 ${theme.command(`cd ${projectName}`)}`));
|
|
541
|
+
this.log(theme.secondary(" \u2022 Follow the setup instructions in the README.md"));
|
|
542
|
+
this.log("\n" + theme.secondary("Documentation:"));
|
|
543
|
+
this.log(theme.secondary(" \u2022 ") + theme.command("https://docs.copilotkit.ai"));
|
|
544
|
+
this.log(theme.secondary(" \u2022 ") + theme.command(FRAMEWORK_DOCUMENTATION[options.agentFramework]));
|
|
545
|
+
this.log(theme.bottomPadding);
|
|
546
|
+
this.queueAnalytics("cli.create.completed", {
|
|
547
|
+
framework: agentFramework,
|
|
548
|
+
project_name: projectName,
|
|
549
|
+
cloud_setup_completed: !!cloudSetupInfo,
|
|
550
|
+
api_key_configured: !!options.apiKey,
|
|
551
|
+
duration_ms: Date.now() - this.startTime
|
|
552
|
+
});
|
|
553
|
+
await this.flushAnalytics();
|
|
554
|
+
} catch (error) {
|
|
555
|
+
spinner.fail(theme.error(`Failed to create project: ${error.message}`));
|
|
556
|
+
this.queueAnalytics("cli.create.failed", {
|
|
557
|
+
framework: agentFramework,
|
|
558
|
+
project_name: projectName,
|
|
559
|
+
error: error.message,
|
|
560
|
+
step: "project_creation",
|
|
561
|
+
duration_ms: Date.now() - this.startTime
|
|
562
|
+
});
|
|
563
|
+
await this.flushAnalytics();
|
|
564
|
+
this.exit(1);
|
|
565
|
+
}
|
|
566
|
+
} catch (error) {
|
|
567
|
+
this.queueAnalytics("cli.create.failed", {
|
|
568
|
+
error: error.message,
|
|
569
|
+
step: "initialization",
|
|
570
|
+
duration_ms: Date.now() - this.startTime
|
|
571
|
+
});
|
|
572
|
+
await this.flushAnalytics();
|
|
573
|
+
this.gracefulError(error.message);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
async promptProjectName() {
|
|
577
|
+
const { projectName } = await inquirer2.prompt([
|
|
578
|
+
{
|
|
579
|
+
type: "input",
|
|
580
|
+
name: "projectName",
|
|
581
|
+
message: theme.secondary("What is your project named?"),
|
|
582
|
+
validate: (input) => {
|
|
583
|
+
if (!input) return theme.error("Project name is required");
|
|
584
|
+
if (!/^[a-z0-9-]+$/.test(input)) {
|
|
585
|
+
return theme.error("Project name can only contain lowercase letters, numbers, and hyphens");
|
|
586
|
+
}
|
|
587
|
+
if (input.length > 30) {
|
|
588
|
+
return theme.error("Project name must be less than 30 characters");
|
|
589
|
+
}
|
|
590
|
+
return true;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
]);
|
|
594
|
+
return projectName;
|
|
595
|
+
}
|
|
596
|
+
async promptAgentFramework() {
|
|
597
|
+
const { framework } = await inquirer2.prompt([
|
|
598
|
+
{
|
|
599
|
+
type: "list",
|
|
600
|
+
name: "framework",
|
|
601
|
+
message: theme.secondary("Which agent framework would you like to use?"),
|
|
602
|
+
choices: [
|
|
603
|
+
{ name: `${FRAMEWORK_EMOJI["langgraph-py"]} LangGraph (Python)`, value: "langgraph-py" },
|
|
604
|
+
{ name: `${FRAMEWORK_EMOJI["langgraph-js"]} LangGraph (JavaScript)`, value: "langgraph-js" },
|
|
605
|
+
{ name: `${FRAMEWORK_EMOJI.mastra} Mastra`, value: "mastra" },
|
|
606
|
+
{ name: `${FRAMEWORK_EMOJI["pydantic-ai"]} Pydantic AI`, value: "pydantic-ai" },
|
|
607
|
+
{ name: `${FRAMEWORK_EMOJI.flows} CrewAI Flows`, value: "flows" },
|
|
608
|
+
{ name: `${FRAMEWORK_EMOJI.llamaindex} LlamaIndex`, value: "llamaindex" },
|
|
609
|
+
{ name: `${FRAMEWORK_EMOJI.agno} Agno`, value: "agno" },
|
|
610
|
+
{ name: `${FRAMEWORK_EMOJI.ag2} AG2`, value: "ag2" }
|
|
611
|
+
]
|
|
612
|
+
}
|
|
613
|
+
]);
|
|
614
|
+
return framework;
|
|
615
|
+
}
|
|
616
|
+
async downloadTemplate(projectDir, framework) {
|
|
617
|
+
const repo = TEMPLATE_REPOS[framework];
|
|
618
|
+
const url = `https://github.com/${repo}/archive/refs/heads/main.tar.gz`;
|
|
619
|
+
try {
|
|
620
|
+
const response = await fetch(url);
|
|
621
|
+
if (!response.ok) throw new Error(`Failed to download template: ${response.statusText}`);
|
|
622
|
+
const tempFile = path.join(projectDir, "template.tar.gz");
|
|
623
|
+
const fileStream = createWriteStream(tempFile);
|
|
624
|
+
if (!response.body) throw new Error("Failed to get response body");
|
|
625
|
+
await streamPipeline(response.body, fileStream);
|
|
626
|
+
await extract({
|
|
627
|
+
file: tempFile,
|
|
628
|
+
cwd: projectDir,
|
|
629
|
+
strip: 1
|
|
630
|
+
});
|
|
631
|
+
await fs.remove(tempFile);
|
|
632
|
+
} catch (error) {
|
|
633
|
+
throw new Error(`Failed to download template: ${error.message}`);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Queue an analytics event to be sent later (non-blocking)
|
|
638
|
+
*/
|
|
639
|
+
queueAnalytics(event, properties) {
|
|
640
|
+
this.analyticsQueue.push({ event, properties });
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Send all queued analytics events in fire-and-forget manner
|
|
644
|
+
*/
|
|
645
|
+
async flushAnalytics() {
|
|
646
|
+
if (!this.analytics || this.analyticsQueue.length === 0) {
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
const promises = this.analyticsQueue.map(
|
|
650
|
+
({ event, properties }) => this.analytics.track({ event, properties }).catch(() => {
|
|
651
|
+
})
|
|
652
|
+
);
|
|
653
|
+
Promise.all(promises).catch(() => {
|
|
654
|
+
});
|
|
655
|
+
if (this.analytics) {
|
|
656
|
+
this.analytics.shutdown().catch(() => {
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
async setupCloudApiKey(flags) {
|
|
661
|
+
const { cliToken, organization } = await this.authService.requireLogin(this, "cloud-features");
|
|
662
|
+
this.trpcClient = createTRPCClient(cliToken);
|
|
663
|
+
const availableProjects = await this.trpcClient.listOrgProjects.query({ orgId: organization.id });
|
|
664
|
+
let selectedProjectId;
|
|
665
|
+
if (flags.project) {
|
|
666
|
+
if (!availableProjects.some((project) => project.id === flags.project)) {
|
|
667
|
+
this.log(chalk3.red(`\u{1F4C1} Project with ID ${flags.project} not found`));
|
|
668
|
+
process.exit(1);
|
|
669
|
+
}
|
|
670
|
+
selectedProjectId = flags.project;
|
|
671
|
+
this.log(chalk3.green(`\u{1F4C1} Selected project ${selectedProjectId}`));
|
|
672
|
+
} else if (availableProjects.length === 1) {
|
|
673
|
+
selectedProjectId = availableProjects[0].id;
|
|
674
|
+
this.log(chalk3.green(`\u{1F4C1} Auto-selected project ${selectedProjectId}`));
|
|
675
|
+
} else {
|
|
676
|
+
const { projectId } = await inquirer2.prompt([
|
|
677
|
+
{
|
|
678
|
+
name: "projectId",
|
|
679
|
+
type: "list",
|
|
680
|
+
message: "\u{1F4C1} Choose a project:",
|
|
681
|
+
choices: availableProjects.map((project) => ({
|
|
682
|
+
value: project.id,
|
|
683
|
+
name: `${project.name} (ID: ${project.id})`
|
|
684
|
+
}))
|
|
685
|
+
}
|
|
686
|
+
]);
|
|
687
|
+
selectedProjectId = projectId;
|
|
688
|
+
}
|
|
689
|
+
const spinner = ora2({
|
|
690
|
+
text: "Retrieving your API key...",
|
|
691
|
+
color: "cyan"
|
|
692
|
+
}).start();
|
|
693
|
+
try {
|
|
694
|
+
const copilotCloudPublicApiKey = await this.trpcClient.getCopilotCloudPublicApiKey.query({
|
|
695
|
+
projectId: selectedProjectId
|
|
696
|
+
});
|
|
697
|
+
if (!copilotCloudPublicApiKey?.key) {
|
|
698
|
+
spinner.fail("Failed to retrieve API key");
|
|
699
|
+
throw new Error("No API key found for the selected project");
|
|
700
|
+
}
|
|
701
|
+
spinner.succeed("\u2705 API key retrieved successfully");
|
|
702
|
+
return {
|
|
703
|
+
cliToken,
|
|
704
|
+
organization,
|
|
705
|
+
selectedProjectId,
|
|
706
|
+
apiKey: copilotCloudPublicApiKey.key
|
|
707
|
+
};
|
|
708
|
+
} catch (error) {
|
|
709
|
+
spinner.fail("Failed to retrieve API key");
|
|
710
|
+
throw error;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
async configureApiKey(projectDir, apiKey) {
|
|
714
|
+
const envPath = path.join(projectDir, ".env.local");
|
|
715
|
+
const envExamplePath = path.join(projectDir, ".env.example");
|
|
716
|
+
try {
|
|
717
|
+
let envContent = "";
|
|
718
|
+
if (await fs.pathExists(envExamplePath)) {
|
|
719
|
+
envContent = await fs.readFile(envExamplePath, "utf8");
|
|
720
|
+
envContent = envContent.replace(/COPILOT_CLOUD_PUBLIC_API_KEY=.*/g, `COPILOT_CLOUD_PUBLIC_API_KEY=${apiKey}`);
|
|
721
|
+
} else {
|
|
722
|
+
envContent = `COPILOT_CLOUD_PUBLIC_API_KEY=${apiKey}
|
|
723
|
+
`;
|
|
724
|
+
}
|
|
725
|
+
await fs.writeFile(envPath, envContent);
|
|
726
|
+
} catch (error) {
|
|
727
|
+
console.warn("Warning: Could not configure API key in .env.local file");
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
|
|
335
732
|
// src/lib/init/types/questions.ts
|
|
336
733
|
import { z } from "zod";
|
|
337
|
-
import { Flags } from "@oclif/core";
|
|
734
|
+
import { Flags as Flags2 } from "@oclif/core";
|
|
338
735
|
|
|
339
736
|
// src/lib/init/utils.ts
|
|
340
737
|
var isLocalhost = (url) => {
|
|
@@ -443,24 +840,24 @@ var ConfigSchema = z.object({
|
|
|
443
840
|
}
|
|
444
841
|
);
|
|
445
842
|
var ConfigFlags = {
|
|
446
|
-
booth:
|
|
447
|
-
mode:
|
|
448
|
-
"copilotkit-version":
|
|
449
|
-
"use-copilot-cloud":
|
|
450
|
-
"langgraph-agent":
|
|
451
|
-
"crew-type":
|
|
452
|
-
"crew-name":
|
|
453
|
-
"crew-url":
|
|
454
|
-
"crew-bearer-token":
|
|
455
|
-
"langsmith-api-key":
|
|
456
|
-
"llm-token":
|
|
457
|
-
"setup-ide-docs":
|
|
458
|
-
"selected-ide":
|
|
843
|
+
booth: Flags2.boolean({ description: "Use CopilotKit in booth mode", default: false, char: "b" }),
|
|
844
|
+
mode: Flags2.string({ description: "How you will be interacting with AI", options: MODES, char: "m" }),
|
|
845
|
+
"copilotkit-version": Flags2.string({ description: "CopilotKit version to use (e.g. 1.7.0)" }),
|
|
846
|
+
"use-copilot-cloud": Flags2.string({ description: "Use Copilot Cloud for production-ready hosting", options: YES_NO }),
|
|
847
|
+
"langgraph-agent": Flags2.string({ description: "LangGraph agent template to use", options: LANGGRAPH_AGENTS }),
|
|
848
|
+
"crew-type": Flags2.string({ description: "CrewAI implementation type", options: CREW_TYPES }),
|
|
849
|
+
"crew-name": Flags2.string({ description: "Name for your CrewAI agent" }),
|
|
850
|
+
"crew-url": Flags2.string({ description: "URL endpoint for your CrewAI agent" }),
|
|
851
|
+
"crew-bearer-token": Flags2.string({ description: "Bearer token for CrewAI authentication" }),
|
|
852
|
+
"langsmith-api-key": Flags2.string({ description: "LangSmith API key for LangGraph observability" }),
|
|
853
|
+
"llm-token": Flags2.string({ description: "API key for your preferred LLM provider" }),
|
|
854
|
+
"setup-ide-docs": Flags2.string({ description: "Setup IDE documentation rules for AI assistance", options: YES_NO }),
|
|
855
|
+
"selected-ide": Flags2.string({
|
|
459
856
|
description: "IDE to configure with documentation rules",
|
|
460
857
|
options: ["cursor", "windsurf", "skip"]
|
|
461
858
|
}),
|
|
462
859
|
// NEW: A/B/C test flags
|
|
463
|
-
"deployment-choice":
|
|
860
|
+
"deployment-choice": Flags2.string({
|
|
464
861
|
description: "Choose between Copilot Cloud or Self-hosted deployment",
|
|
465
862
|
options: DEPLOYMENT_CHOICES
|
|
466
863
|
})
|
|
@@ -487,10 +884,10 @@ var templateMapping = {
|
|
|
487
884
|
};
|
|
488
885
|
|
|
489
886
|
// src/lib/init/ide-docs.ts
|
|
490
|
-
import
|
|
887
|
+
import path2 from "path";
|
|
491
888
|
import { existsSync } from "fs";
|
|
492
|
-
import * as
|
|
493
|
-
import
|
|
889
|
+
import * as fs2 from "fs/promises";
|
|
890
|
+
import chalk4 from "chalk";
|
|
494
891
|
var COPILOTKIT_DOC_RULE_TEMPLATE = `---
|
|
495
892
|
description: CopilotKit Documentation - Complete CopilotKit framework documentation for AI assistance
|
|
496
893
|
alwaysApply: false
|
|
@@ -528,7 +925,7 @@ var IDE_DOCS_CONFIGS = {
|
|
|
528
925
|
};
|
|
529
926
|
async function ensureDir(dirPath) {
|
|
530
927
|
try {
|
|
531
|
-
await
|
|
928
|
+
await fs2.mkdir(dirPath, { recursive: true });
|
|
532
929
|
} catch (error) {
|
|
533
930
|
if (!existsSync(dirPath)) {
|
|
534
931
|
throw error;
|
|
@@ -537,7 +934,7 @@ async function ensureDir(dirPath) {
|
|
|
537
934
|
}
|
|
538
935
|
async function pathExists(filePath) {
|
|
539
936
|
try {
|
|
540
|
-
await
|
|
937
|
+
await fs2.access(filePath);
|
|
541
938
|
return true;
|
|
542
939
|
} catch {
|
|
543
940
|
return false;
|
|
@@ -549,10 +946,10 @@ async function checkIDEInstallation(ide) {
|
|
|
549
946
|
let configPath;
|
|
550
947
|
switch (ide) {
|
|
551
948
|
case "cursor":
|
|
552
|
-
configPath =
|
|
949
|
+
configPath = path2.join(homeDir, ".cursor");
|
|
553
950
|
break;
|
|
554
951
|
case "windsurf":
|
|
555
|
-
configPath =
|
|
952
|
+
configPath = path2.join(homeDir, ".codeium", "windsurf");
|
|
556
953
|
break;
|
|
557
954
|
default:
|
|
558
955
|
return false;
|
|
@@ -574,30 +971,30 @@ async function detectInstalledIDEs() {
|
|
|
574
971
|
}
|
|
575
972
|
async function setupIDEDocs(ide, projectDir) {
|
|
576
973
|
const config = IDE_DOCS_CONFIGS[ide];
|
|
577
|
-
const rulesDir =
|
|
578
|
-
const ruleFilePath =
|
|
974
|
+
const rulesDir = path2.join(projectDir, config.rulesDir);
|
|
975
|
+
const ruleFilePath = path2.join(rulesDir, config.ruleFileName);
|
|
579
976
|
await ensureDir(rulesDir);
|
|
580
977
|
if (await pathExists(ruleFilePath)) {
|
|
581
|
-
console.log(
|
|
978
|
+
console.log(chalk4.yellow(`\u26A0\uFE0F CopilotKit documentation rule already exists for ${config.displayName}`));
|
|
582
979
|
return;
|
|
583
980
|
}
|
|
584
981
|
const ruleContent = config.createRuleContent();
|
|
585
|
-
await
|
|
982
|
+
await fs2.writeFile(ruleFilePath, ruleContent, "utf8");
|
|
586
983
|
}
|
|
587
984
|
function getIDEInstructions(ide) {
|
|
588
985
|
const config = IDE_DOCS_CONFIGS[ide];
|
|
589
986
|
const instructions = [
|
|
590
|
-
|
|
987
|
+
chalk4.cyan(`\u{1F4DA} CopilotKit documentation configured for ${config.displayName}!`),
|
|
591
988
|
"",
|
|
592
|
-
|
|
989
|
+
chalk4.bold("What this does:"),
|
|
593
990
|
" \u2022 Adds CopilotKit documentation context to your IDE AI assistant",
|
|
594
991
|
" \u2022 Provides accurate, up-to-date information about CopilotKit APIs",
|
|
595
992
|
" \u2022 Improves code suggestions and help responses",
|
|
596
993
|
"",
|
|
597
|
-
|
|
598
|
-
` \u2022 Rule file: ${
|
|
994
|
+
chalk4.bold("Location:"),
|
|
995
|
+
` \u2022 Rule file: ${chalk4.gray(path2.join(config.rulesDir, config.ruleFileName))}`,
|
|
599
996
|
"",
|
|
600
|
-
|
|
997
|
+
chalk4.bold("Usage:"),
|
|
601
998
|
" \u2022 Your IDE AI assistant now has access to CopilotKit documentation",
|
|
602
999
|
" \u2022 Ask questions about CopilotKit APIs, components, and patterns",
|
|
603
1000
|
" \u2022 The AI will reference official documentation for accurate answers"
|
|
@@ -605,7 +1002,7 @@ function getIDEInstructions(ide) {
|
|
|
605
1002
|
if (ide === "cursor") {
|
|
606
1003
|
instructions.push(
|
|
607
1004
|
"",
|
|
608
|
-
|
|
1005
|
+
chalk4.bold("Next steps for Cursor:"),
|
|
609
1006
|
" \u2022 Restart Cursor if currently open",
|
|
610
1007
|
" \u2022 The rule will be automatically available in your AI context",
|
|
611
1008
|
" \u2022 Start a new chat to use the documentation context"
|
|
@@ -613,7 +1010,7 @@ function getIDEInstructions(ide) {
|
|
|
613
1010
|
} else if (ide === "windsurf") {
|
|
614
1011
|
instructions.push(
|
|
615
1012
|
"",
|
|
616
|
-
|
|
1013
|
+
chalk4.bold("Next steps for Windsurf:"),
|
|
617
1014
|
" \u2022 Restart Windsurf if currently open",
|
|
618
1015
|
" \u2022 The rule will be automatically available in your AI context",
|
|
619
1016
|
" \u2022 Start a new chat to use the documentation context"
|
|
@@ -623,14 +1020,14 @@ function getIDEInstructions(ide) {
|
|
|
623
1020
|
}
|
|
624
1021
|
async function handleIDEDocsSetup(selectedIDE, projectDir, spinner) {
|
|
625
1022
|
try {
|
|
626
|
-
spinner.text =
|
|
1023
|
+
spinner.text = chalk4.cyan(`Setting up CopilotKit documentation for ${IDE_DOCS_CONFIGS[selectedIDE].displayName}...`);
|
|
627
1024
|
await setupIDEDocs(selectedIDE, projectDir);
|
|
628
|
-
spinner.succeed(
|
|
1025
|
+
spinner.succeed(chalk4.green(`CopilotKit documentation configured for ${IDE_DOCS_CONFIGS[selectedIDE].displayName}`));
|
|
629
1026
|
const instructions = getIDEInstructions(selectedIDE);
|
|
630
1027
|
console.log("\n" + instructions.join("\n"));
|
|
631
1028
|
} catch (error) {
|
|
632
1029
|
spinner.fail(
|
|
633
|
-
|
|
1030
|
+
chalk4.red(`Failed to setup IDE documentation: ${error instanceof Error ? error.message : "Unknown error"}`)
|
|
634
1031
|
);
|
|
635
1032
|
throw error;
|
|
636
1033
|
}
|
|
@@ -914,8 +1311,8 @@ async function scaffoldShadCN(flags, userAnswers) {
|
|
|
914
1311
|
}
|
|
915
1312
|
|
|
916
1313
|
// src/lib/init/scaffold/env.ts
|
|
917
|
-
import
|
|
918
|
-
import
|
|
1314
|
+
import path3 from "path";
|
|
1315
|
+
import fs3 from "fs";
|
|
919
1316
|
|
|
920
1317
|
// src/lib/init/scaffold/langgraph-assistants.ts
|
|
921
1318
|
async function getLangGraphAgents(url, langSmithApiKey) {
|
|
@@ -938,7 +1335,7 @@ async function getLangGraphAgents(url, langSmithApiKey) {
|
|
|
938
1335
|
}
|
|
939
1336
|
|
|
940
1337
|
// src/lib/init/scaffold/env.ts
|
|
941
|
-
import
|
|
1338
|
+
import inquirer3 from "inquirer";
|
|
942
1339
|
function needsCloudDeployment(userAnswers) {
|
|
943
1340
|
return userAnswers.deploymentChoice === "Copilot Cloud" || // Branch B choice
|
|
944
1341
|
userAnswers.useCopilotCloud === "Yes" || // Branch C choice
|
|
@@ -947,9 +1344,9 @@ function needsCloudDeployment(userAnswers) {
|
|
|
947
1344
|
}
|
|
948
1345
|
async function scaffoldEnv(flags, userAnswers) {
|
|
949
1346
|
try {
|
|
950
|
-
const envFile =
|
|
951
|
-
if (!
|
|
952
|
-
|
|
1347
|
+
const envFile = path3.join(process.cwd(), ".env");
|
|
1348
|
+
if (!fs3.existsSync(envFile)) {
|
|
1349
|
+
fs3.writeFileSync(envFile, "", "utf8");
|
|
953
1350
|
} else {
|
|
954
1351
|
}
|
|
955
1352
|
let newEnvValues = "";
|
|
@@ -996,7 +1393,7 @@ async function scaffoldEnv(flags, userAnswers) {
|
|
|
996
1393
|
);
|
|
997
1394
|
let langGraphAgent = "";
|
|
998
1395
|
if (langGraphAgents.length > 1) {
|
|
999
|
-
const { langGraphAgentChoice } = await
|
|
1396
|
+
const { langGraphAgentChoice } = await inquirer3.prompt([
|
|
1000
1397
|
{
|
|
1001
1398
|
type: "list",
|
|
1002
1399
|
name: "langGraphAgentChoice",
|
|
@@ -1017,7 +1414,7 @@ async function scaffoldEnv(flags, userAnswers) {
|
|
|
1017
1414
|
`;
|
|
1018
1415
|
}
|
|
1019
1416
|
if (newEnvValues) {
|
|
1020
|
-
|
|
1417
|
+
fs3.appendFileSync(envFile, newEnvValues);
|
|
1021
1418
|
}
|
|
1022
1419
|
} catch (error) {
|
|
1023
1420
|
throw error;
|
|
@@ -1026,59 +1423,59 @@ async function scaffoldEnv(flags, userAnswers) {
|
|
|
1026
1423
|
|
|
1027
1424
|
// src/lib/init/scaffold/github.ts
|
|
1028
1425
|
import { execSync } from "child_process";
|
|
1029
|
-
import * as
|
|
1030
|
-
import * as
|
|
1426
|
+
import * as fs4 from "fs";
|
|
1427
|
+
import * as path4 from "path";
|
|
1031
1428
|
import * as os from "os";
|
|
1032
|
-
import
|
|
1429
|
+
import chalk5 from "chalk";
|
|
1033
1430
|
async function cloneGitHubSubdirectory(githubUrl, destinationPath, spinner) {
|
|
1034
1431
|
try {
|
|
1035
1432
|
const { owner, repo, branch, subdirectoryPath } = parseGitHubUrl(githubUrl);
|
|
1036
|
-
spinner.text =
|
|
1433
|
+
spinner.text = chalk5.cyan(`Cloning from ${owner}/${repo}...`);
|
|
1037
1434
|
return await sparseCheckout(owner, repo, branch, subdirectoryPath, destinationPath, spinner);
|
|
1038
1435
|
} catch (error) {
|
|
1039
|
-
spinner.text =
|
|
1436
|
+
spinner.text = chalk5.red(`Failed to clone from GitHub: ${error}`);
|
|
1040
1437
|
return false;
|
|
1041
1438
|
}
|
|
1042
1439
|
}
|
|
1043
1440
|
async function sparseCheckout(owner, repo, branch, subdirectoryPath, destinationPath, spinner) {
|
|
1044
|
-
const tempDir =
|
|
1441
|
+
const tempDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "copilotkit-sparse-"));
|
|
1045
1442
|
try {
|
|
1046
|
-
spinner.text =
|
|
1443
|
+
spinner.text = chalk5.cyan("Creating temporary workspace...");
|
|
1047
1444
|
execSync("git init", { cwd: tempDir, stdio: "pipe" });
|
|
1048
|
-
spinner.text =
|
|
1445
|
+
spinner.text = chalk5.cyan("Connecting to repository...");
|
|
1049
1446
|
execSync(`git remote add origin https://github.com/${owner}/${repo}.git`, { cwd: tempDir, stdio: "pipe" });
|
|
1050
1447
|
execSync("git config core.sparseCheckout true", { cwd: tempDir, stdio: "pipe" });
|
|
1051
|
-
|
|
1052
|
-
spinner.text =
|
|
1448
|
+
fs4.writeFileSync(path4.join(tempDir, ".git/info/sparse-checkout"), subdirectoryPath);
|
|
1449
|
+
spinner.text = chalk5.cyan("Downloading agent files...");
|
|
1053
1450
|
execSync(`git pull origin ${branch} --depth=1`, { cwd: tempDir, stdio: "pipe" });
|
|
1054
|
-
const sourcePath =
|
|
1055
|
-
if (!
|
|
1451
|
+
const sourcePath = path4.join(tempDir, subdirectoryPath);
|
|
1452
|
+
if (!fs4.existsSync(sourcePath)) {
|
|
1056
1453
|
throw new Error(`Subdirectory '${subdirectoryPath}' not found in the repository.`);
|
|
1057
1454
|
}
|
|
1058
|
-
|
|
1059
|
-
spinner.text =
|
|
1455
|
+
fs4.mkdirSync(destinationPath, { recursive: true });
|
|
1456
|
+
spinner.text = chalk5.cyan("Installing agent files...");
|
|
1060
1457
|
await copyDirectoryAsync(sourcePath, destinationPath);
|
|
1061
1458
|
return true;
|
|
1062
1459
|
} finally {
|
|
1063
1460
|
try {
|
|
1064
|
-
|
|
1461
|
+
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
1065
1462
|
} catch (error) {
|
|
1066
1463
|
console.warn(`Failed to clean up temporary directory: ${error}`);
|
|
1067
1464
|
}
|
|
1068
1465
|
}
|
|
1069
1466
|
}
|
|
1070
1467
|
async function copyDirectoryAsync(source, destination) {
|
|
1071
|
-
if (!
|
|
1072
|
-
|
|
1468
|
+
if (!fs4.existsSync(destination)) {
|
|
1469
|
+
fs4.mkdirSync(destination, { recursive: true });
|
|
1073
1470
|
}
|
|
1074
|
-
const entries =
|
|
1471
|
+
const entries = fs4.readdirSync(source, { withFileTypes: true });
|
|
1075
1472
|
for (const entry of entries) {
|
|
1076
|
-
const srcPath =
|
|
1077
|
-
const destPath =
|
|
1473
|
+
const srcPath = path4.join(source, entry.name);
|
|
1474
|
+
const destPath = path4.join(destination, entry.name);
|
|
1078
1475
|
if (entry.isDirectory()) {
|
|
1079
1476
|
await copyDirectoryAsync(srcPath, destPath);
|
|
1080
1477
|
} else {
|
|
1081
|
-
|
|
1478
|
+
fs4.copyFileSync(srcPath, destPath);
|
|
1082
1479
|
}
|
|
1083
1480
|
if (entries.length > 10) {
|
|
1084
1481
|
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
@@ -1107,20 +1504,20 @@ function parseGitHubUrl(githubUrl) {
|
|
|
1107
1504
|
|
|
1108
1505
|
// src/lib/init/scaffold/packages.ts
|
|
1109
1506
|
import spawn2 from "cross-spawn";
|
|
1110
|
-
import
|
|
1111
|
-
import
|
|
1507
|
+
import chalk6 from "chalk";
|
|
1508
|
+
import ora3 from "ora";
|
|
1112
1509
|
|
|
1113
1510
|
// src/lib/init/scaffold/agent.ts
|
|
1114
|
-
import
|
|
1115
|
-
import
|
|
1116
|
-
import
|
|
1117
|
-
import
|
|
1511
|
+
import ora4 from "ora";
|
|
1512
|
+
import chalk7 from "chalk";
|
|
1513
|
+
import path5 from "path";
|
|
1514
|
+
import fs5 from "fs";
|
|
1118
1515
|
async function scaffoldAgent(userAnswers) {
|
|
1119
1516
|
if (userAnswers.mode === "CrewAI" || userAnswers.mode === "LangGraph" && !userAnswers.langGraphAgent || userAnswers.mode === "Standard" || userAnswers.mode === "MCP") {
|
|
1120
1517
|
return;
|
|
1121
1518
|
}
|
|
1122
|
-
const spinner =
|
|
1123
|
-
text:
|
|
1519
|
+
const spinner = ora4({
|
|
1520
|
+
text: chalk7.cyan("Setting up AI agent..."),
|
|
1124
1521
|
color: "cyan"
|
|
1125
1522
|
}).start();
|
|
1126
1523
|
let template = "";
|
|
@@ -1134,13 +1531,13 @@ async function scaffoldAgent(userAnswers) {
|
|
|
1134
1531
|
break;
|
|
1135
1532
|
}
|
|
1136
1533
|
if (!template) {
|
|
1137
|
-
spinner.fail(
|
|
1534
|
+
spinner.fail(chalk7.red("Failed to determine agent template"));
|
|
1138
1535
|
throw new Error("Failed to determine agent template");
|
|
1139
1536
|
}
|
|
1140
|
-
const agentDir =
|
|
1537
|
+
const agentDir = path5.join(process.cwd(), "agent");
|
|
1141
1538
|
try {
|
|
1142
1539
|
await cloneGitHubSubdirectory(template, agentDir, spinner);
|
|
1143
|
-
spinner.text =
|
|
1540
|
+
spinner.text = chalk7.cyan("Creating agent environment variables...");
|
|
1144
1541
|
let envContent = "";
|
|
1145
1542
|
if (userAnswers.llmToken) {
|
|
1146
1543
|
envContent += `OPENAI_API_KEY=${userAnswers.llmToken}
|
|
@@ -1151,26 +1548,26 @@ async function scaffoldAgent(userAnswers) {
|
|
|
1151
1548
|
`;
|
|
1152
1549
|
}
|
|
1153
1550
|
if (envContent) {
|
|
1154
|
-
const agentEnvFile =
|
|
1155
|
-
|
|
1156
|
-
spinner.text =
|
|
1551
|
+
const agentEnvFile = path5.join(agentDir, ".env");
|
|
1552
|
+
fs5.writeFileSync(agentEnvFile, envContent, "utf8");
|
|
1553
|
+
spinner.text = chalk7.cyan("Added API keys to agent .env file");
|
|
1157
1554
|
}
|
|
1158
1555
|
if (userAnswers.mode === "LangGraph" && userAnswers.langSmithApiKey) {
|
|
1159
1556
|
envContent += `LANGSMITH_API_KEY=${userAnswers.langSmithApiKey}
|
|
1160
1557
|
`;
|
|
1161
1558
|
}
|
|
1162
1559
|
if (envContent) {
|
|
1163
|
-
const agentEnvFile =
|
|
1164
|
-
|
|
1165
|
-
spinner.text =
|
|
1560
|
+
const agentEnvFile = path5.join(agentDir, ".env");
|
|
1561
|
+
fs5.writeFileSync(agentEnvFile, envContent, "utf8");
|
|
1562
|
+
spinner.text = chalk7.cyan("Added API keys to agent .env file");
|
|
1166
1563
|
}
|
|
1167
1564
|
if (envContent) {
|
|
1168
|
-
const agentEnvFile =
|
|
1169
|
-
|
|
1170
|
-
spinner.text =
|
|
1565
|
+
const agentEnvFile = path5.join(agentDir, ".env");
|
|
1566
|
+
fs5.writeFileSync(agentEnvFile, envContent, "utf8");
|
|
1567
|
+
spinner.text = chalk7.cyan("Added API keys to agent .env file");
|
|
1171
1568
|
}
|
|
1172
1569
|
} catch (error) {
|
|
1173
|
-
spinner.fail(
|
|
1570
|
+
spinner.fail(chalk7.red("Failed to clone agent template"));
|
|
1174
1571
|
throw error;
|
|
1175
1572
|
}
|
|
1176
1573
|
spinner.succeed(`${userAnswers.mode} agent cloned successfully`);
|
|
@@ -1190,29 +1587,29 @@ var AgentTemplates = {
|
|
|
1190
1587
|
};
|
|
1191
1588
|
|
|
1192
1589
|
// src/lib/init/scaffold/crew-inputs.ts
|
|
1193
|
-
import * as
|
|
1194
|
-
import
|
|
1195
|
-
import * as
|
|
1590
|
+
import * as fs6 from "fs/promises";
|
|
1591
|
+
import ora5 from "ora";
|
|
1592
|
+
import * as path6 from "path";
|
|
1196
1593
|
async function addCrewInputs(url, token) {
|
|
1197
1594
|
try {
|
|
1198
|
-
const spinner =
|
|
1595
|
+
const spinner = ora5("Analyzing crew inputs...").start();
|
|
1199
1596
|
const inputs = await getCrewInputs(url, token);
|
|
1200
1597
|
spinner.text = "Adding inputs to app/copilotkit/page.tsx...";
|
|
1201
|
-
let filePath =
|
|
1598
|
+
let filePath = path6.join(process.cwd(), "app", "copilotkit", "page.tsx");
|
|
1202
1599
|
try {
|
|
1203
|
-
await
|
|
1600
|
+
await fs6.access(filePath);
|
|
1204
1601
|
} catch {
|
|
1205
|
-
filePath =
|
|
1602
|
+
filePath = path6.join(process.cwd(), "src", "app", "copilotkit", "page.tsx");
|
|
1206
1603
|
}
|
|
1207
1604
|
try {
|
|
1208
|
-
await
|
|
1605
|
+
await fs6.access(filePath);
|
|
1209
1606
|
} catch {
|
|
1210
1607
|
throw new Error("app/copilotkit/page.tsx and src/app/copilotkit/page.tsx not found");
|
|
1211
1608
|
}
|
|
1212
|
-
let fileContent = await
|
|
1609
|
+
let fileContent = await fs6.readFile(filePath, "utf8");
|
|
1213
1610
|
const inputsString = JSON.stringify(inputs);
|
|
1214
1611
|
fileContent = fileContent.replace(/\[["']YOUR_INPUTS_HERE["']\]/g, inputsString);
|
|
1215
|
-
await
|
|
1612
|
+
await fs6.writeFile(filePath, fileContent, "utf8");
|
|
1216
1613
|
spinner.succeed("Successfully added crew inputs to app/copilotkit/page.tsx");
|
|
1217
1614
|
} catch (error) {
|
|
1218
1615
|
console.error("Error updating crew inputs:", error);
|
|
@@ -1233,8 +1630,8 @@ async function getCrewInputs(url, token) {
|
|
|
1233
1630
|
}
|
|
1234
1631
|
|
|
1235
1632
|
// src/commands/init.ts
|
|
1236
|
-
import
|
|
1237
|
-
import
|
|
1633
|
+
import chalk8 from "chalk";
|
|
1634
|
+
import ora6 from "ora";
|
|
1238
1635
|
var CloudInit = class _CloudInit extends BaseCommand {
|
|
1239
1636
|
constructor(argv, config, authService = new AuthService()) {
|
|
1240
1637
|
super(argv, config);
|
|
@@ -1244,24 +1641,31 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1244
1641
|
analytics = null;
|
|
1245
1642
|
startTime = Date.now();
|
|
1246
1643
|
analyticsQueue = [];
|
|
1247
|
-
static description = "Set up CopilotKit in your Next.js project";
|
|
1248
|
-
static examples = ["<%= config.bin %> init"];
|
|
1644
|
+
static description = "Set up CopilotKit in your Next.js project, or create a new project if none exists";
|
|
1645
|
+
static examples = ["<%= config.bin %> init", "<%= config.bin %> init --dir ./my-app"];
|
|
1249
1646
|
static flags = {
|
|
1250
1647
|
...BaseCommand.flags,
|
|
1251
1648
|
...ConfigFlags,
|
|
1252
|
-
runtimeUrl:
|
|
1253
|
-
project:
|
|
1254
|
-
dir:
|
|
1649
|
+
runtimeUrl: Flags3.string({ description: "runtime URL" }),
|
|
1650
|
+
project: Flags3.string({ description: "project ID (can be found in the Copilot Cloud dashboard)" }),
|
|
1651
|
+
dir: Flags3.string({ description: "directory of the Next.js project", default: "." })
|
|
1255
1652
|
};
|
|
1256
1653
|
async run() {
|
|
1257
1654
|
const { flags } = await this.parse(_CloudInit);
|
|
1258
1655
|
try {
|
|
1259
1656
|
this.analytics = new AnalyticsService();
|
|
1260
|
-
this.
|
|
1657
|
+
const nextJsAppExists = this.isNextJsProject(flags);
|
|
1658
|
+
if (!nextJsAppExists) {
|
|
1659
|
+
this.log(chalk8.gray("Running copilotkit create to set up a new project...\n"));
|
|
1660
|
+
const createCommand = new Create(this.argv, this.config, this.authService);
|
|
1661
|
+
await createCommand.run();
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1664
|
+
this.log(chalk8.magenta("\n\u{1FA81} Welcome to CopilotKit"));
|
|
1261
1665
|
if (flags.booth) {
|
|
1262
|
-
this.log(
|
|
1666
|
+
this.log(chalk8.gray("Thanks for giving CopilotKit a try! Now, let's try to impress you \u{1F4AA}\n"));
|
|
1263
1667
|
} else {
|
|
1264
|
-
this.log(
|
|
1668
|
+
this.log(chalk8.gray("Let's power up your Next.js project with AI capabilities\n"));
|
|
1265
1669
|
}
|
|
1266
1670
|
const projectValidated = this.validateProjectCompatibility(flags);
|
|
1267
1671
|
this.queueAnalytics("cli.init.started", {
|
|
@@ -1283,19 +1687,19 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1283
1687
|
deployment_choice: userAnswers.deploymentChoice
|
|
1284
1688
|
});
|
|
1285
1689
|
if (userAnswers.mode === "Mastra") {
|
|
1286
|
-
this.log(
|
|
1690
|
+
this.log(chalk8.magenta(`
|
|
1287
1691
|
\u{1F517} Please go to https://docs.copilotkit.ai/mastra/quickstart to get started.`));
|
|
1288
1692
|
process.exit(0);
|
|
1289
1693
|
} else if (userAnswers.mode === "AG2") {
|
|
1290
|
-
this.log(
|
|
1694
|
+
this.log(chalk8.magenta(`
|
|
1291
1695
|
\u{1F517} Please go to https://docs.copilotkit.ai/ag2/quickstart to get started.`));
|
|
1292
1696
|
process.exit(0);
|
|
1293
1697
|
} else if (userAnswers.mode === "Agno") {
|
|
1294
|
-
this.log(
|
|
1698
|
+
this.log(chalk8.magenta(`
|
|
1295
1699
|
\u{1F517} Please go to https://docs.copilotkit.ai/agno/quickstart to get started.`));
|
|
1296
1700
|
process.exit(0);
|
|
1297
1701
|
} else if (userAnswers.mode === "LlamaIndex") {
|
|
1298
|
-
this.log(
|
|
1702
|
+
this.log(chalk8.magenta(`
|
|
1299
1703
|
\u{1F517} Please go to https://docs.copilotkit.ai/llamaindex/quickstart to get started.`));
|
|
1300
1704
|
process.exit(0);
|
|
1301
1705
|
}
|
|
@@ -1326,7 +1730,7 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1326
1730
|
if (userAnswers.crewUrl && userAnswers.crewBearerToken)
|
|
1327
1731
|
await addCrewInputs(userAnswers.crewUrl, userAnswers.crewBearerToken);
|
|
1328
1732
|
if (userAnswers.setupIDEDocs === "Yes" && userAnswers.selectedIDE !== "skip") {
|
|
1329
|
-
const ideDocsSpinner =
|
|
1733
|
+
const ideDocsSpinner = ora6({
|
|
1330
1734
|
text: "Setting up CopilotKit IDE documentation...",
|
|
1331
1735
|
color: "cyan"
|
|
1332
1736
|
}).start();
|
|
@@ -1348,12 +1752,12 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1348
1752
|
await this.flushAnalytics();
|
|
1349
1753
|
if (flags.booth) {
|
|
1350
1754
|
this.log("\n-----\n");
|
|
1351
|
-
this.log(
|
|
1352
|
-
this.log(
|
|
1353
|
-
this.log(` - Start the Next.js app: ${
|
|
1354
|
-
this.log(` - Navigate to ${
|
|
1755
|
+
this.log(chalk8.magenta("\u{1F389} Your CopilotKit setup is complete! \u{1F389}\n"));
|
|
1756
|
+
this.log(chalk8.bold("\n\u{1F680} Next steps:"));
|
|
1757
|
+
this.log(` - Start the Next.js app: ${chalk8.gray("$")} ${chalk8.cyan("npm run dev")}`);
|
|
1758
|
+
this.log(` - Navigate to ${chalk8.blue("http://localhost:3000/copilotkit")}`);
|
|
1355
1759
|
this.log(` - Talk to your agent.`);
|
|
1356
|
-
this.log(
|
|
1760
|
+
this.log(chalk8.magenta("\nThanks for giving CopilotKit a try! \u{1FA81}\n"));
|
|
1357
1761
|
} else {
|
|
1358
1762
|
this.finalSummary(userAnswers, cloudSetupInfo?.selectedProjectId);
|
|
1359
1763
|
}
|
|
@@ -1410,7 +1814,7 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1410
1814
|
}
|
|
1411
1815
|
}
|
|
1412
1816
|
async getBoothAnswers() {
|
|
1413
|
-
const url = await
|
|
1817
|
+
const url = await inquirer4.prompt({
|
|
1414
1818
|
type: "input",
|
|
1415
1819
|
message: "\u{1F99C}\u{1F517} What is the LangGraph's agent URL?",
|
|
1416
1820
|
name: "agentURL",
|
|
@@ -1485,15 +1889,15 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1485
1889
|
};
|
|
1486
1890
|
}
|
|
1487
1891
|
}).filter((q) => q !== null);
|
|
1488
|
-
const promptAnswers = await
|
|
1892
|
+
const promptAnswers = await inquirer4.prompt(inquirerQuestions);
|
|
1489
1893
|
const answers = {
|
|
1490
1894
|
...initialAnswers,
|
|
1491
1895
|
...promptAnswers,
|
|
1492
1896
|
...earlyApiKey && { copilotCloudPublicApiKey: earlyApiKey }
|
|
1493
1897
|
};
|
|
1494
1898
|
if (abcBranch === "B" && !cloudSetupInfo) {
|
|
1495
|
-
this.log(
|
|
1496
|
-
this.log(
|
|
1899
|
+
this.log(chalk8.cyan("\n\u{1F511} Now you will get an API key"));
|
|
1900
|
+
this.log(chalk8.gray("Setting up your cloud account and retrieving your API key...\n"));
|
|
1497
1901
|
try {
|
|
1498
1902
|
const tempConfig = { ...answers, signupForCopilotCloud: "Yes" };
|
|
1499
1903
|
const cloudSignupResult = await this.setupApiKey(flags, tempConfig);
|
|
@@ -1524,8 +1928,8 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1524
1928
|
}
|
|
1525
1929
|
}
|
|
1526
1930
|
if (abcBranch === "A" && !cloudSetupInfo) {
|
|
1527
|
-
this.log(
|
|
1528
|
-
this.log(
|
|
1931
|
+
this.log(chalk8.cyan("\n\u{1F511} Now get your API key"));
|
|
1932
|
+
this.log(chalk8.gray("Setting up your cloud account and retrieving your API key...\n"));
|
|
1529
1933
|
try {
|
|
1530
1934
|
const tempConfig = { ...answers, signupForCopilotCloud: "Yes" };
|
|
1531
1935
|
const cloudSignupResult = await this.setupApiKey(flags, tempConfig);
|
|
@@ -1559,24 +1963,24 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1559
1963
|
this.log(
|
|
1560
1964
|
"\nCurrently the CLI only supports scaffolding LangGraph Platform agents. Use our quickstart guide to get started:\n"
|
|
1561
1965
|
);
|
|
1562
|
-
this.log(
|
|
1966
|
+
this.log(chalk8.blue("https://docs.copilotkit.ai/coagents/quickstart/langgraph"));
|
|
1563
1967
|
process.exit(0);
|
|
1564
1968
|
}
|
|
1565
1969
|
try {
|
|
1566
|
-
const spinner =
|
|
1970
|
+
const spinner = ora6({ text: "Validating configuration...", color: "green" }).start();
|
|
1567
1971
|
const validatedConfig = ConfigSchema.parse(answers);
|
|
1568
1972
|
spinner.succeed(`\u{1F50D} Configuration validated successfully`);
|
|
1569
1973
|
return { config: validatedConfig, cloudSetupInfo };
|
|
1570
1974
|
} catch (error) {
|
|
1571
|
-
const spinner =
|
|
1975
|
+
const spinner = ora6({ text: "Validation failed...", color: "red" }).start();
|
|
1572
1976
|
if (error.errors) {
|
|
1573
1977
|
const formattedErrors = error.errors.map((err) => `- ${err.path.join(".")}: ${err.message}`).join("\n");
|
|
1574
|
-
spinner.fail(
|
|
1575
|
-
console.error(
|
|
1978
|
+
spinner.fail(chalk8.red("Configuration validation failed:"));
|
|
1979
|
+
console.error(chalk8.red(formattedErrors));
|
|
1576
1980
|
process.exit(1);
|
|
1577
1981
|
}
|
|
1578
|
-
spinner.fail(
|
|
1579
|
-
console.error(
|
|
1982
|
+
spinner.fail(chalk8.red("Unexpected validation error:"));
|
|
1983
|
+
console.error(chalk8.red(error.message || "Unknown error"));
|
|
1580
1984
|
process.exit(1);
|
|
1581
1985
|
}
|
|
1582
1986
|
}
|
|
@@ -1587,13 +1991,13 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1587
1991
|
let selectedProjectId;
|
|
1588
1992
|
if (flags.project) {
|
|
1589
1993
|
if (!availableProjects.some((project) => project.id === flags.project)) {
|
|
1590
|
-
this.log(
|
|
1994
|
+
this.log(chalk8.red(`\u{1F4C1} Project with ID ${flags.project} not found`));
|
|
1591
1995
|
process.exit(1);
|
|
1592
1996
|
}
|
|
1593
1997
|
selectedProjectId = flags.project;
|
|
1594
|
-
this.log(
|
|
1998
|
+
this.log(chalk8.green(`\u{1F4C1} Selected project ${selectedProjectId}`));
|
|
1595
1999
|
} else {
|
|
1596
|
-
const { projectId } = await
|
|
2000
|
+
const { projectId } = await inquirer4.prompt([
|
|
1597
2001
|
{
|
|
1598
2002
|
name: "projectId",
|
|
1599
2003
|
type: "list",
|
|
@@ -1623,12 +2027,12 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1623
2027
|
const updatedConfig = ConfigSchema.parse(sanitizedConfig);
|
|
1624
2028
|
Object.assign(userAnswers, updatedConfig);
|
|
1625
2029
|
} catch (error) {
|
|
1626
|
-
this.log(
|
|
2030
|
+
this.log(chalk8.red(`Failed to update configuration with Copilot Cloud API key: ${error.message}`));
|
|
1627
2031
|
}
|
|
1628
2032
|
if (userAnswers.crewUrl && userAnswers.crewName && userAnswers.crewBearerToken) {
|
|
1629
2033
|
const isFlow = userAnswers.crewType === "Flows";
|
|
1630
|
-
const crewSpinner =
|
|
1631
|
-
text:
|
|
2034
|
+
const crewSpinner = ora6({
|
|
2035
|
+
text: chalk8(`\u{1F465} Adding CrewAI ${isFlow ? "Flow" : "Crew"} to Copilot Cloud...`),
|
|
1632
2036
|
color: "cyan"
|
|
1633
2037
|
}).start();
|
|
1634
2038
|
try {
|
|
@@ -1644,22 +2048,22 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1644
2048
|
crewApiBearerToken: userAnswers.crewBearerToken
|
|
1645
2049
|
}
|
|
1646
2050
|
});
|
|
1647
|
-
crewSpinner.succeed(
|
|
2051
|
+
crewSpinner.succeed(chalk8(`\u{1F465} CrewAI ${isFlow ? "Flow" : "Crew"} added to Copilot Cloud`));
|
|
1648
2052
|
} catch (error) {
|
|
1649
|
-
crewSpinner.fail(
|
|
2053
|
+
crewSpinner.fail(chalk8(`\u{1F465} Failed to add CrewAI ${isFlow ? "Flow" : "Crew"} to Copilot Cloud`));
|
|
1650
2054
|
console.error(error);
|
|
1651
2055
|
process.exit(1);
|
|
1652
2056
|
}
|
|
1653
2057
|
}
|
|
1654
2058
|
if (userAnswers.mode === "LangGraph" && userAnswers.useCopilotCloud === "Yes" && userAnswers.alreadyDeployed === "Yes") {
|
|
1655
|
-
const langGraphSpinner =
|
|
1656
|
-
text:
|
|
2059
|
+
const langGraphSpinner = ora6({
|
|
2060
|
+
text: chalk8("\u{1F99C}\u{1F517} Adding LangGraph to Copilot Cloud..."),
|
|
1657
2061
|
color: "cyan"
|
|
1658
2062
|
}).start();
|
|
1659
2063
|
if (userAnswers.langGraphPlatform === "Yes" && userAnswers.langGraphPlatformUrl) {
|
|
1660
2064
|
try {
|
|
1661
2065
|
if (!userAnswers.langSmithApiKey) {
|
|
1662
|
-
langGraphSpinner.fail(
|
|
2066
|
+
langGraphSpinner.fail(chalk8("\u{1F99C}\u{1F517} LangSmith API key not found. Please provide a valid LangSmith API key."));
|
|
1663
2067
|
process.exit(1);
|
|
1664
2068
|
}
|
|
1665
2069
|
await this.trpcClient.createLGCRemoteEndpoint.mutate({
|
|
@@ -1672,9 +2076,9 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1672
2076
|
agents: []
|
|
1673
2077
|
}
|
|
1674
2078
|
});
|
|
1675
|
-
langGraphSpinner.succeed(
|
|
2079
|
+
langGraphSpinner.succeed(chalk8("\u{1F99C}\u{1F517} LangGraph Cloud remote endpoint created"));
|
|
1676
2080
|
} catch (error) {
|
|
1677
|
-
langGraphSpinner.fail(
|
|
2081
|
+
langGraphSpinner.fail(chalk8("\u{1F99C}\u{1F517} Failed to create LangGraph Cloud remote endpoint. Please try again."));
|
|
1678
2082
|
process.exit(1);
|
|
1679
2083
|
}
|
|
1680
2084
|
} else if (userAnswers.langGraphRemoteEndpointURL) {
|
|
@@ -1688,32 +2092,32 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1688
2092
|
// Already sanitized
|
|
1689
2093
|
}
|
|
1690
2094
|
});
|
|
1691
|
-
langGraphSpinner.succeed(
|
|
2095
|
+
langGraphSpinner.succeed(chalk8("\u{1F99C}\u{1F517} LangGraph remote endpoint created"));
|
|
1692
2096
|
} catch (error) {
|
|
1693
|
-
langGraphSpinner.fail(
|
|
2097
|
+
langGraphSpinner.fail(chalk8("\u{1F99C}\u{1F517} Failed to create LangGraph remote endpoint. Please try again."));
|
|
1694
2098
|
process.exit(1);
|
|
1695
2099
|
}
|
|
1696
2100
|
}
|
|
1697
2101
|
}
|
|
1698
2102
|
}
|
|
1699
2103
|
async setupApiKey(flags, userAnswers) {
|
|
1700
|
-
this.log(
|
|
2104
|
+
this.log(chalk8.cyan("\n\u{1F511} Setting up your API key...\n"));
|
|
1701
2105
|
const { cliToken, organization } = await this.authService.requireLogin(this, "cloud-features");
|
|
1702
2106
|
this.trpcClient = createTRPCClient(cliToken);
|
|
1703
2107
|
const availableProjects = await this.trpcClient.listOrgProjects.query({ orgId: organization.id });
|
|
1704
2108
|
let selectedProjectId;
|
|
1705
2109
|
if (flags.project) {
|
|
1706
2110
|
if (!availableProjects.some((project) => project.id === flags.project)) {
|
|
1707
|
-
this.log(
|
|
2111
|
+
this.log(chalk8.red(`\u{1F4C1} Project with ID ${flags.project} not found`));
|
|
1708
2112
|
process.exit(1);
|
|
1709
2113
|
}
|
|
1710
2114
|
selectedProjectId = flags.project;
|
|
1711
|
-
this.log(
|
|
2115
|
+
this.log(chalk8.green(`\u{1F4C1} Selected project ${selectedProjectId}`));
|
|
1712
2116
|
} else if (availableProjects.length === 1) {
|
|
1713
2117
|
selectedProjectId = availableProjects[0].id;
|
|
1714
|
-
this.log(
|
|
2118
|
+
this.log(chalk8.green(`\u{1F4C1} Auto-selected project ${selectedProjectId}`));
|
|
1715
2119
|
} else {
|
|
1716
|
-
const { projectId } = await
|
|
2120
|
+
const { projectId } = await inquirer4.prompt([
|
|
1717
2121
|
{
|
|
1718
2122
|
name: "projectId",
|
|
1719
2123
|
type: "list",
|
|
@@ -1728,7 +2132,7 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1728
2132
|
}
|
|
1729
2133
|
let apiKey;
|
|
1730
2134
|
if (selectedProjectId) {
|
|
1731
|
-
const spinner =
|
|
2135
|
+
const spinner = ora6({
|
|
1732
2136
|
text: "Retrieving your API key...",
|
|
1733
2137
|
color: "cyan"
|
|
1734
2138
|
}).start();
|
|
@@ -1743,7 +2147,7 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1743
2147
|
console.error(error);
|
|
1744
2148
|
}
|
|
1745
2149
|
}
|
|
1746
|
-
this.log(
|
|
2150
|
+
this.log(chalk8.green("\u2705 API key setup complete!\n"));
|
|
1747
2151
|
return { cliToken, organization, selectedProjectId, apiKey };
|
|
1748
2152
|
}
|
|
1749
2153
|
async completeCloudDeploymentSetup(flags, userAnswers, cloudSetupInfo) {
|
|
@@ -1753,8 +2157,8 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1753
2157
|
const selectedProjectId = cloudSetupInfo.selectedProjectId;
|
|
1754
2158
|
if (userAnswers.crewUrl && userAnswers.crewName && userAnswers.crewBearerToken) {
|
|
1755
2159
|
const isFlow = userAnswers.crewType === "Flows";
|
|
1756
|
-
const crewSpinner =
|
|
1757
|
-
text:
|
|
2160
|
+
const crewSpinner = ora6({
|
|
2161
|
+
text: chalk8(`\u{1F465} Adding CrewAI ${isFlow ? "Flow" : "Crew"} to Copilot Cloud...`),
|
|
1758
2162
|
color: "cyan"
|
|
1759
2163
|
}).start();
|
|
1760
2164
|
try {
|
|
@@ -1769,22 +2173,22 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1769
2173
|
crewApiBearerToken: userAnswers.crewBearerToken
|
|
1770
2174
|
}
|
|
1771
2175
|
});
|
|
1772
|
-
crewSpinner.succeed(
|
|
2176
|
+
crewSpinner.succeed(chalk8(`\u{1F465} CrewAI ${isFlow ? "Flow" : "Crew"} added to Copilot Cloud`));
|
|
1773
2177
|
} catch (error) {
|
|
1774
|
-
crewSpinner.fail(
|
|
2178
|
+
crewSpinner.fail(chalk8(`\u{1F465} Failed to add CrewAI ${isFlow ? "Flow" : "Crew"} to Copilot Cloud`));
|
|
1775
2179
|
console.error(error);
|
|
1776
2180
|
process.exit(1);
|
|
1777
2181
|
}
|
|
1778
2182
|
}
|
|
1779
2183
|
if (userAnswers.mode === "LangGraph" && userAnswers.useCopilotCloud === "Yes" && userAnswers.alreadyDeployed === "Yes") {
|
|
1780
|
-
const langGraphSpinner =
|
|
1781
|
-
text:
|
|
2184
|
+
const langGraphSpinner = ora6({
|
|
2185
|
+
text: chalk8("\u{1F99C}\u{1F517} Adding LangGraph to Copilot Cloud..."),
|
|
1782
2186
|
color: "cyan"
|
|
1783
2187
|
}).start();
|
|
1784
2188
|
if (userAnswers.langGraphPlatform === "Yes" && userAnswers.langGraphPlatformUrl) {
|
|
1785
2189
|
try {
|
|
1786
2190
|
if (!userAnswers.langSmithApiKey) {
|
|
1787
|
-
langGraphSpinner.fail(
|
|
2191
|
+
langGraphSpinner.fail(chalk8("\u{1F99C}\u{1F517} LangSmith API key not found. Please provide a valid LangSmith API key."));
|
|
1788
2192
|
process.exit(1);
|
|
1789
2193
|
}
|
|
1790
2194
|
await this.trpcClient.createLGCRemoteEndpoint.mutate({
|
|
@@ -1796,9 +2200,9 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1796
2200
|
agents: []
|
|
1797
2201
|
}
|
|
1798
2202
|
});
|
|
1799
|
-
langGraphSpinner.succeed(
|
|
2203
|
+
langGraphSpinner.succeed(chalk8("\u{1F99C}\u{1F517} LangGraph Cloud remote endpoint created"));
|
|
1800
2204
|
} catch (error) {
|
|
1801
|
-
langGraphSpinner.fail(
|
|
2205
|
+
langGraphSpinner.fail(chalk8("\u{1F99C}\u{1F517} Failed to create LangGraph Cloud remote endpoint. Please try again."));
|
|
1802
2206
|
process.exit(1);
|
|
1803
2207
|
}
|
|
1804
2208
|
} else if (userAnswers.langGraphRemoteEndpointURL) {
|
|
@@ -1811,41 +2215,57 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1811
2215
|
url: userAnswers.langGraphRemoteEndpointURL
|
|
1812
2216
|
}
|
|
1813
2217
|
});
|
|
1814
|
-
langGraphSpinner.succeed(
|
|
2218
|
+
langGraphSpinner.succeed(chalk8("\u{1F99C}\u{1F517} LangGraph remote endpoint created"));
|
|
1815
2219
|
} catch (error) {
|
|
1816
|
-
langGraphSpinner.fail(
|
|
2220
|
+
langGraphSpinner.fail(chalk8("\u{1F99C}\u{1F517} Failed to create LangGraph remote endpoint. Please try again."));
|
|
1817
2221
|
process.exit(1);
|
|
1818
2222
|
}
|
|
1819
2223
|
}
|
|
1820
2224
|
}
|
|
1821
2225
|
}
|
|
1822
|
-
|
|
1823
|
-
const spinner = ora5("Checking Next.js project compatibility...").start();
|
|
2226
|
+
isNextJsProject(flags) {
|
|
1824
2227
|
try {
|
|
1825
|
-
const projectPath =
|
|
1826
|
-
if (!
|
|
1827
|
-
|
|
1828
|
-
throw new Error(`Please provide a valid Next.js project directory.`);
|
|
2228
|
+
const projectPath = path7.resolve(process.cwd(), flags.dir);
|
|
2229
|
+
if (!fs7.existsSync(projectPath)) {
|
|
2230
|
+
return false;
|
|
1829
2231
|
}
|
|
1830
|
-
const packageJsonPath =
|
|
1831
|
-
if (!
|
|
1832
|
-
|
|
1833
|
-
throw new Error(`Please provide a valid Next.js project with a package.json file.`);
|
|
2232
|
+
const packageJsonPath = path7.join(projectPath, "package.json");
|
|
2233
|
+
if (!fs7.existsSync(packageJsonPath)) {
|
|
2234
|
+
return false;
|
|
1834
2235
|
}
|
|
1835
|
-
const packageJson = JSON.parse(
|
|
1836
|
-
|
|
2236
|
+
const packageJson = JSON.parse(fs7.readFileSync(packageJsonPath, "utf8"));
|
|
2237
|
+
return !!(packageJson.dependencies?.next || packageJson.devDependencies?.next);
|
|
2238
|
+
} catch {
|
|
2239
|
+
return false;
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
validateProjectCompatibility(flags) {
|
|
2243
|
+
const spinner = ora6("Checking Next.js project compatibility...").start();
|
|
2244
|
+
try {
|
|
2245
|
+
if (!this.isNextJsProject(flags)) {
|
|
2246
|
+
const projectPath2 = path7.resolve(process.cwd(), flags.dir);
|
|
2247
|
+
if (!fs7.existsSync(projectPath2)) {
|
|
2248
|
+
spinner.fail(`Directory ${flags.dir} does not exist`);
|
|
2249
|
+
throw new Error(`Please provide a valid Next.js project directory.`);
|
|
2250
|
+
}
|
|
2251
|
+
const packageJsonPath = path7.join(projectPath2, "package.json");
|
|
2252
|
+
if (!fs7.existsSync(packageJsonPath)) {
|
|
2253
|
+
spinner.fail(`No package.json found in ${projectPath2}`);
|
|
2254
|
+
throw new Error(`Please provide a valid Next.js project with a package.json file.`);
|
|
2255
|
+
}
|
|
1837
2256
|
spinner.fail(`Not a Next.js project`);
|
|
1838
2257
|
throw new Error(
|
|
1839
|
-
`Directory ${
|
|
2258
|
+
`Directory ${projectPath2} does not appear to be a Next.js project. Make sure it has next in dependencies.`
|
|
1840
2259
|
);
|
|
1841
2260
|
}
|
|
2261
|
+
const projectPath = path7.resolve(process.cwd(), flags.dir);
|
|
1842
2262
|
spinner.succeed(`\u{1F53C} Valid Next.js project detected at ${projectPath}`);
|
|
1843
2263
|
return true;
|
|
1844
2264
|
} catch (error) {
|
|
1845
2265
|
if (!spinner.isSpinning) {
|
|
1846
|
-
this.log(
|
|
2266
|
+
this.log(chalk8.red(error.message));
|
|
1847
2267
|
} else {
|
|
1848
|
-
spinner.fail(
|
|
2268
|
+
spinner.fail(chalk8.red(error.message));
|
|
1849
2269
|
}
|
|
1850
2270
|
process.exit(1);
|
|
1851
2271
|
}
|
|
@@ -1855,9 +2275,9 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1855
2275
|
let agentSetupMessage = "";
|
|
1856
2276
|
if (userAnswers.mode === "CrewAI") {
|
|
1857
2277
|
if (userAnswers.crewType === "Crews") {
|
|
1858
|
-
agentSetupMessage = `Using your Crew from ${
|
|
2278
|
+
agentSetupMessage = `Using your Crew from ${chalk8.cyan(userAnswers.crewUrl || "the provided URL")}.`;
|
|
1859
2279
|
} else if (userAnswers.crewType === "Flows") {
|
|
1860
|
-
agentSetupMessage = `We've scaffolded a ${
|
|
2280
|
+
agentSetupMessage = `We've scaffolded a ${chalk8.cyan("CrewAI Flow")} agent in the ${chalk8.cyan("./agent")} directory.`;
|
|
1861
2281
|
agentDevInstructions = "poetry lock && poetry install && poetry run demo";
|
|
1862
2282
|
}
|
|
1863
2283
|
}
|
|
@@ -1865,11 +2285,11 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1865
2285
|
case "LangGraph":
|
|
1866
2286
|
switch (userAnswers.langGraphAgent) {
|
|
1867
2287
|
case "Python Starter":
|
|
1868
|
-
agentSetupMessage = `We've scaffolded a ${
|
|
2288
|
+
agentSetupMessage = `We've scaffolded a ${chalk8.cyan(userAnswers.langGraphAgent || "LangGraph")} agent in the ${chalk8.cyan("./agent")} directory.`;
|
|
1869
2289
|
agentDevInstructions = "poetry lock && poetry install && poetry run demo";
|
|
1870
2290
|
break;
|
|
1871
2291
|
case "TypeScript Starter":
|
|
1872
|
-
agentSetupMessage = `We've scaffolded a ${
|
|
2292
|
+
agentSetupMessage = `We've scaffolded a ${chalk8.cyan(userAnswers.langGraphAgent || "LangGraph")} agent in the ${chalk8.cyan("./agent")} directory.`;
|
|
1873
2293
|
agentDevInstructions = "npm install && npm run dev";
|
|
1874
2294
|
break;
|
|
1875
2295
|
default:
|
|
@@ -1879,18 +2299,18 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1879
2299
|
case "CrewAI":
|
|
1880
2300
|
switch (userAnswers.crewType) {
|
|
1881
2301
|
case "Crews":
|
|
1882
|
-
agentSetupMessage = `Using your Crew from ${
|
|
2302
|
+
agentSetupMessage = `Using your Crew from ${chalk8.cyan(userAnswers.crewUrl || "the provided URL")}.`;
|
|
1883
2303
|
break;
|
|
1884
2304
|
case "Flows":
|
|
1885
|
-
agentSetupMessage = `We've scaffolded a ${
|
|
2305
|
+
agentSetupMessage = `We've scaffolded a ${chalk8.cyan("CrewAI Flow")} agent in the ${chalk8.cyan("./agent")} directory.`;
|
|
1886
2306
|
break;
|
|
1887
2307
|
}
|
|
1888
2308
|
break;
|
|
1889
2309
|
default:
|
|
1890
2310
|
}
|
|
1891
2311
|
this.log("\n-----\n");
|
|
1892
|
-
this.log(
|
|
1893
|
-
this.log(
|
|
2312
|
+
this.log(chalk8.magenta("\u{1F389} Your CopilotKit setup is complete! \u{1F389}\n"));
|
|
2313
|
+
this.log(chalk8.bold(`\u{1F4CB} Recap`));
|
|
1894
2314
|
this.log(` - CopilotKit has been added to your Next.js app.`);
|
|
1895
2315
|
if (agentSetupMessage) this.log(` - ${agentSetupMessage}`);
|
|
1896
2316
|
const isCloudDeployment = userAnswers.deploymentChoice === "Copilot Cloud" || // Branch B choice
|
|
@@ -1903,23 +2323,23 @@ var CloudInit = class _CloudInit extends BaseCommand {
|
|
|
1903
2323
|
} else if (isSelfHosted) {
|
|
1904
2324
|
this.log(` - \u{1F3E0} Configured for self-hosted deployment.`);
|
|
1905
2325
|
}
|
|
1906
|
-
this.log(
|
|
1907
|
-
this.log(` - Start your Next.js app: ${
|
|
2326
|
+
this.log(chalk8.bold("\n\u{1F680} Next steps:"));
|
|
2327
|
+
this.log(` - Start your Next.js app: ${chalk8.gray("$")} ${chalk8.cyan("npm run dev")}`);
|
|
1908
2328
|
if (agentDevInstructions) {
|
|
1909
|
-
this.log(` - Start your agent: ${
|
|
2329
|
+
this.log(` - Start your agent: ${chalk8.gray("$")} ${chalk8.cyan(`cd agent && ${agentDevInstructions}`)}`);
|
|
1910
2330
|
if (isCloudDeployment) {
|
|
1911
2331
|
this.log(
|
|
1912
|
-
` - Create local tunnel for your agent: ${
|
|
2332
|
+
` - Create local tunnel for your agent: ${chalk8.gray("$")} ${chalk8.cyan(`npx copilotkit@latest dev --port <value>${projectId ? ` --project ${projectId}` : " [--project <value>]"}`)}`
|
|
1913
2333
|
);
|
|
1914
2334
|
}
|
|
1915
2335
|
}
|
|
1916
|
-
this.log(` - Navigate to ${
|
|
2336
|
+
this.log(` - Navigate to ${chalk8.blue("http://localhost:3000/copilotkit")}`);
|
|
1917
2337
|
this.log(` - Talk to your agent.`);
|
|
1918
2338
|
if (userAnswers.setupIDEDocs === "Yes" && userAnswers.selectedIDE !== "skip") {
|
|
1919
2339
|
this.log(` - Your IDE now has CopilotKit documentation context for better AI assistance.`);
|
|
1920
2340
|
}
|
|
1921
|
-
this.log(` - Read the docs: ${
|
|
1922
|
-
this.log(
|
|
2341
|
+
this.log(` - Read the docs: ${chalk8.blue("https://docs.copilotkit.ai")}`);
|
|
2342
|
+
this.log(chalk8.magenta("\nEnjoy building with CopilotKit \u{1FA81}\n"));
|
|
1923
2343
|
}
|
|
1924
2344
|
};
|
|
1925
2345
|
export {
|