copilotkit 0.0.51 → 0.0.52
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/bin/run.js +13 -1
- package/dist/commands/base-command.js +7 -6
- package/dist/commands/base-command.js.map +1 -1
- package/dist/commands/create.d.ts +1 -17
- package/dist/commands/create.js +96 -520
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/dev.js +7 -6
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.d.ts +1 -27
- package/dist/commands/init.js +104 -1989
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.js +7 -6
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +7 -6
- package/dist/commands/logout.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 +3 -3
- package/package.json +1 -1
package/dist/commands/create.js
CHANGED
|
@@ -1,299 +1,29 @@
|
|
|
1
1
|
// src/commands/create.ts
|
|
2
2
|
import { Flags, Args } from "@oclif/core";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import inquirer from "inquirer";
|
|
4
|
+
import chalk2 from "chalk";
|
|
5
5
|
import fs from "fs-extra";
|
|
6
6
|
import path from "path";
|
|
7
7
|
import { promisify } from "util";
|
|
8
8
|
import { pipeline } from "stream";
|
|
9
9
|
import { createWriteStream } from "fs";
|
|
10
10
|
import { extract } from "tar";
|
|
11
|
-
import ora2 from "ora";
|
|
12
|
-
|
|
13
|
-
// src/services/auth.service.ts
|
|
14
|
-
import Conf2 from "conf";
|
|
15
|
-
import cors from "cors";
|
|
16
|
-
import express from "express";
|
|
17
|
-
import crypto2 from "node:crypto";
|
|
18
|
-
import open from "open";
|
|
19
|
-
import getPort from "get-port";
|
|
20
11
|
import ora from "ora";
|
|
21
|
-
import chalk from "chalk";
|
|
22
|
-
import inquirer from "inquirer";
|
|
23
|
-
|
|
24
|
-
// src/utils/trpc.ts
|
|
25
|
-
import { createTRPCClient as trpcClient, httpBatchLink } from "@trpc/client";
|
|
26
|
-
import superjson from "superjson";
|
|
27
|
-
var COPILOT_CLOUD_BASE_URL = process.env.COPILOT_CLOUD_BASE_URL || "https://cloud.copilotkit.ai";
|
|
28
|
-
function createTRPCClient(cliToken) {
|
|
29
|
-
return trpcClient({
|
|
30
|
-
links: [
|
|
31
|
-
httpBatchLink({
|
|
32
|
-
url: `${COPILOT_CLOUD_BASE_URL}/api/trpc-cli`,
|
|
33
|
-
transformer: superjson,
|
|
34
|
-
headers: () => {
|
|
35
|
-
return {
|
|
36
|
-
"x-trpc-source": "cli",
|
|
37
|
-
"x-cli-token": cliToken
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
]
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// src/services/analytics.service.ts
|
|
46
|
-
import { Analytics } from "@segment/analytics-node";
|
|
47
|
-
import { PostHog } from "posthog-node";
|
|
48
|
-
import Conf from "conf";
|
|
49
|
-
var AnalyticsService = class {
|
|
50
|
-
constructor(authData) {
|
|
51
|
-
this.authData = authData;
|
|
52
|
-
if (process.env.SEGMENT_DISABLED === "true") {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const segmentWriteKey = process.env.SEGMENT_WRITE_KEY || "9Pv6QyExYef2P4hPz4gks6QAvNMi2AOf";
|
|
56
|
-
this.globalProperties = {
|
|
57
|
-
service: "cli"
|
|
58
|
-
};
|
|
59
|
-
if (this.authData?.userId) {
|
|
60
|
-
this.userId = this.authData.userId;
|
|
61
|
-
}
|
|
62
|
-
if (this.authData?.email) {
|
|
63
|
-
this.email = this.authData.email;
|
|
64
|
-
this.globalProperties.email = this.authData.email;
|
|
65
|
-
}
|
|
66
|
-
if (this.authData?.organizationId) {
|
|
67
|
-
this.organizationId = this.authData.organizationId;
|
|
68
|
-
}
|
|
69
|
-
this.segment = new Analytics({
|
|
70
|
-
writeKey: segmentWriteKey,
|
|
71
|
-
disable: process.env.SEGMENT_DISABLE === "true"
|
|
72
|
-
});
|
|
73
|
-
if (process.env.POSTHOG_DISABLED !== "true") {
|
|
74
|
-
const posthogKey = process.env.POSTHOG_KEY || "phc_XZdymVYjrph9Mi0xZYGNyCKexxgblXRR1jMENCtdz5Q";
|
|
75
|
-
const posthogHost = process.env.POSTHOG_HOST || "https://eu.i.posthog.com";
|
|
76
|
-
this.posthog = new PostHog(posthogKey, {
|
|
77
|
-
host: posthogHost
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
const config = new Conf({ projectName: "CopilotKitCLI" });
|
|
81
|
-
if (!config.get("anonymousId")) {
|
|
82
|
-
config.set("anonymousId", crypto.randomUUID());
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
segment;
|
|
86
|
-
posthog;
|
|
87
|
-
globalProperties = {};
|
|
88
|
-
userId;
|
|
89
|
-
email;
|
|
90
|
-
organizationId;
|
|
91
|
-
config = new Conf({ projectName: "CopilotKitCLI" });
|
|
92
|
-
getAnonymousId() {
|
|
93
|
-
const anonymousId = this.config.get("anonymousId");
|
|
94
|
-
if (!anonymousId) {
|
|
95
|
-
const anonymousId2 = crypto.randomUUID();
|
|
96
|
-
this.config.set("anonymousId", anonymousId2);
|
|
97
|
-
return anonymousId2;
|
|
98
|
-
}
|
|
99
|
-
return anonymousId;
|
|
100
|
-
}
|
|
101
|
-
track(event) {
|
|
102
|
-
if (!this.segment) {
|
|
103
|
-
return Promise.resolve();
|
|
104
|
-
}
|
|
105
|
-
const payload = {
|
|
106
|
-
userId: this.userId ? this.userId : void 0,
|
|
107
|
-
email: this.email ? this.email : void 0,
|
|
108
|
-
anonymousId: this.getAnonymousId(),
|
|
109
|
-
event: event.event,
|
|
110
|
-
properties: {
|
|
111
|
-
...this.globalProperties,
|
|
112
|
-
...event.properties,
|
|
113
|
-
$groups: this.organizationId ? {
|
|
114
|
-
segment_group: this.organizationId
|
|
115
|
-
} : void 0,
|
|
116
|
-
eventProperties: {
|
|
117
|
-
...event.properties,
|
|
118
|
-
...this.globalProperties
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
return new Promise((resolve, reject) => {
|
|
123
|
-
this.segment.track(payload, (err) => {
|
|
124
|
-
if (err) {
|
|
125
|
-
resolve();
|
|
126
|
-
}
|
|
127
|
-
resolve();
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Check if a feature flag is enabled
|
|
133
|
-
*/
|
|
134
|
-
async isFeatureEnabled(flagKey) {
|
|
135
|
-
if (!this.posthog) {
|
|
136
|
-
return false;
|
|
137
|
-
}
|
|
138
|
-
try {
|
|
139
|
-
const distinctId = this.userId || this.getAnonymousId();
|
|
140
|
-
const flag = await this.posthog.isFeatureEnabled(flagKey, distinctId);
|
|
141
|
-
return Boolean(flag);
|
|
142
|
-
} catch (error) {
|
|
143
|
-
console.warn(`Failed to check feature flag ${flagKey}:`, error);
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Get feature flag payload
|
|
149
|
-
*/
|
|
150
|
-
async getFeatureFlagPayload(flagKey) {
|
|
151
|
-
if (!this.posthog) {
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
try {
|
|
155
|
-
const distinctId = this.userId || this.getAnonymousId();
|
|
156
|
-
const payload = await this.posthog.getFeatureFlagPayload(flagKey, distinctId);
|
|
157
|
-
return payload;
|
|
158
|
-
} catch (error) {
|
|
159
|
-
console.warn(`Failed to get feature flag payload ${flagKey}:`, error);
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Shutdown analytics services
|
|
165
|
-
*/
|
|
166
|
-
async shutdown() {
|
|
167
|
-
if (this.posthog) {
|
|
168
|
-
await this.posthog.shutdown();
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
// src/services/auth.service.ts
|
|
174
|
-
var AuthService = class {
|
|
175
|
-
config = new Conf2({ projectName: "CopilotKitCLI" });
|
|
176
|
-
COPILOT_CLOUD_BASE_URL = process.env.COPILOT_CLOUD_BASE_URL || "https://cloud.copilotkit.ai";
|
|
177
|
-
getToken() {
|
|
178
|
-
return this.config.get("cliToken");
|
|
179
|
-
}
|
|
180
|
-
getCLIToken() {
|
|
181
|
-
const cliToken = this.config.get("cliToken");
|
|
182
|
-
return cliToken;
|
|
183
|
-
}
|
|
184
|
-
async logout(cmd) {
|
|
185
|
-
this.config.delete("cliToken");
|
|
186
|
-
}
|
|
187
|
-
async requireLogin(cmd, context) {
|
|
188
|
-
let cliToken = this.getCLIToken();
|
|
189
|
-
if (!cliToken) {
|
|
190
|
-
try {
|
|
191
|
-
let shouldLogin = true;
|
|
192
|
-
if (context !== "cloud-features") {
|
|
193
|
-
const response = await inquirer.prompt([
|
|
194
|
-
{
|
|
195
|
-
name: "shouldLogin",
|
|
196
|
-
type: "confirm",
|
|
197
|
-
message: "\u{1FA81} You are not yet authenticated. Authenticate with Copilot Cloud? (press Enter to confirm)",
|
|
198
|
-
default: true
|
|
199
|
-
}
|
|
200
|
-
]);
|
|
201
|
-
shouldLogin = response.shouldLogin;
|
|
202
|
-
}
|
|
203
|
-
if (shouldLogin) {
|
|
204
|
-
if (context === "cloud-features") {
|
|
205
|
-
cmd.log(chalk.cyan("\n\u{1F680} Setting up Copilot Cloud authentication...\n"));
|
|
206
|
-
}
|
|
207
|
-
const loginResult = await this.login({ exitAfterLogin: false });
|
|
208
|
-
cliToken = loginResult.cliToken;
|
|
209
|
-
return loginResult;
|
|
210
|
-
} else {
|
|
211
|
-
cmd.error("Authentication required to proceed.");
|
|
212
|
-
}
|
|
213
|
-
} catch (error) {
|
|
214
|
-
if (error instanceof Error && error.name === "ExitPromptError") {
|
|
215
|
-
cmd.error(chalk.yellow("\nAuthentication cancelled"));
|
|
216
|
-
}
|
|
217
|
-
throw error;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
let me;
|
|
221
|
-
const trpcClient2 = createTRPCClient(cliToken);
|
|
222
|
-
try {
|
|
223
|
-
me = await trpcClient2.me.query();
|
|
224
|
-
} catch (error) {
|
|
225
|
-
cmd.log(chalk.yellow("Your authentication has expired. Re-authenticating..."));
|
|
226
|
-
try {
|
|
227
|
-
const loginResult = await this.login({ exitAfterLogin: false });
|
|
228
|
-
return loginResult;
|
|
229
|
-
} catch (loginError) {
|
|
230
|
-
cmd.log(chalk.red("Could not authenticate with Copilot Cloud. Please run: npx copilotkit@latest login"));
|
|
231
|
-
process.exit(1);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
if (!me.organization || !me.user) {
|
|
235
|
-
cmd.error("Authentication required to proceed.");
|
|
236
|
-
}
|
|
237
|
-
return { cliToken, user: me.user, organization: me.organization };
|
|
238
|
-
}
|
|
239
|
-
async login({ exitAfterLogin } = { exitAfterLogin: true }) {
|
|
240
|
-
const spinner = ora("\u{1FA81} Opening browser for authentication...").start();
|
|
241
|
-
let analytics;
|
|
242
|
-
analytics = new AnalyticsService();
|
|
243
|
-
const app = express();
|
|
244
|
-
app.use(cors());
|
|
245
|
-
app.use(express.urlencoded({ extended: true }));
|
|
246
|
-
app.use(express.json());
|
|
247
|
-
const port = await getPort();
|
|
248
|
-
const state = crypto2.randomBytes(16).toString("hex");
|
|
249
|
-
return new Promise(async (resolve) => {
|
|
250
|
-
const server = app.listen(port, () => {
|
|
251
|
-
});
|
|
252
|
-
await analytics.track({
|
|
253
|
-
event: "cli.login.initiated",
|
|
254
|
-
properties: {}
|
|
255
|
-
});
|
|
256
|
-
spinner.text = "\u{1FA81} Waiting for browser authentication to complete...";
|
|
257
|
-
app.post("/callback", async (req, res) => {
|
|
258
|
-
const { cliToken, user, organization } = req.body;
|
|
259
|
-
analytics = new AnalyticsService({ userId: user.id, organizationId: organization.id, email: user.email });
|
|
260
|
-
await analytics.track({
|
|
261
|
-
event: "cli.login.success",
|
|
262
|
-
properties: {
|
|
263
|
-
organizationId: organization.id,
|
|
264
|
-
userId: user.id,
|
|
265
|
-
email: user.email
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
if (state !== req.query.state) {
|
|
269
|
-
res.status(401).json({ message: "Invalid state" });
|
|
270
|
-
spinner.fail("Invalid state");
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
this.config.set("cliToken", cliToken);
|
|
274
|
-
res.status(200).json({ message: "Callback called" });
|
|
275
|
-
spinner.succeed(`\u{1FA81} Successfully logged in as ${chalk.hex("#7553fc")(user.email)}`);
|
|
276
|
-
if (exitAfterLogin) {
|
|
277
|
-
process.exit(0);
|
|
278
|
-
} else {
|
|
279
|
-
server.close();
|
|
280
|
-
resolve({ cliToken, user, organization });
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
open(`${this.COPILOT_CLOUD_BASE_URL}/cli-auth?callbackUrl=http://localhost:${port}/callback&state=${state}`);
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
};
|
|
287
12
|
|
|
288
13
|
// src/commands/base-command.ts
|
|
289
14
|
import { Command } from "@oclif/core";
|
|
290
15
|
import Sentry, { consoleIntegration } from "@sentry/node";
|
|
291
16
|
|
|
292
17
|
// src/utils/version.ts
|
|
293
|
-
var LIB_VERSION = "0.0.
|
|
18
|
+
var LIB_VERSION = "0.0.52";
|
|
19
|
+
|
|
20
|
+
// src/utils/trpc.ts
|
|
21
|
+
import { createTRPCClient as trpcClient, httpBatchLink } from "@trpc/client";
|
|
22
|
+
import superjson from "superjson";
|
|
23
|
+
var COPILOT_CLOUD_BASE_URL = process.env.COPILOT_CLOUD_BASE_URL || "https://cloud.copilotkit.ai";
|
|
294
24
|
|
|
295
25
|
// src/commands/base-command.ts
|
|
296
|
-
import
|
|
26
|
+
import chalk from "chalk";
|
|
297
27
|
var BaseCommand = class extends Command {
|
|
298
28
|
async init() {
|
|
299
29
|
await this.checkCLIVersion();
|
|
@@ -309,12 +39,13 @@ var BaseCommand = class extends Command {
|
|
|
309
39
|
});
|
|
310
40
|
}
|
|
311
41
|
async catch(err) {
|
|
312
|
-
if (process.env.SENTRY_DISABLED
|
|
313
|
-
|
|
314
|
-
return;
|
|
42
|
+
if (process.env.SENTRY_DISABLED !== "true") {
|
|
43
|
+
Sentry.captureException(err);
|
|
315
44
|
}
|
|
316
|
-
|
|
317
|
-
|
|
45
|
+
const message = err?.message ?? "Unknown error";
|
|
46
|
+
this.log("\n" + chalk.red(message) + "\n");
|
|
47
|
+
const exitCode = err?.oclif?.exit ?? 1;
|
|
48
|
+
this.exit(exitCode);
|
|
318
49
|
}
|
|
319
50
|
async finally() {
|
|
320
51
|
if (process.env.SENTRY_DISABLED === "true") {
|
|
@@ -333,7 +64,7 @@ var BaseCommand = class extends Command {
|
|
|
333
64
|
}
|
|
334
65
|
}
|
|
335
66
|
async gracefulError(message) {
|
|
336
|
-
this.log("\n" +
|
|
67
|
+
this.log("\n" + chalk.red(message));
|
|
337
68
|
process.exit(1);
|
|
338
69
|
}
|
|
339
70
|
};
|
|
@@ -341,14 +72,14 @@ var BaseCommand = class extends Command {
|
|
|
341
72
|
// src/commands/create.ts
|
|
342
73
|
var streamPipeline = promisify(pipeline);
|
|
343
74
|
var theme = {
|
|
344
|
-
primary:
|
|
345
|
-
secondary:
|
|
346
|
-
tertiary:
|
|
347
|
-
error:
|
|
348
|
-
command:
|
|
349
|
-
success:
|
|
350
|
-
warning:
|
|
351
|
-
divider:
|
|
75
|
+
primary: chalk2.magenta,
|
|
76
|
+
secondary: chalk2.gray,
|
|
77
|
+
tertiary: chalk2.gray,
|
|
78
|
+
error: chalk2.red,
|
|
79
|
+
command: chalk2.blue,
|
|
80
|
+
success: chalk2.green,
|
|
81
|
+
warning: chalk2.yellow,
|
|
82
|
+
divider: chalk2.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"),
|
|
352
83
|
bottomPadding: ""
|
|
353
84
|
};
|
|
354
85
|
var TEMPLATE_REPOS = {
|
|
@@ -402,15 +133,7 @@ var KITE = `
|
|
|
402
133
|
\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
|
|
403
134
|
`;
|
|
404
135
|
var Create = class _Create extends BaseCommand {
|
|
405
|
-
|
|
406
|
-
super(argv, config);
|
|
407
|
-
this.authService = authService;
|
|
408
|
-
}
|
|
409
|
-
trpcClient = null;
|
|
410
|
-
analytics = null;
|
|
411
|
-
startTime = Date.now();
|
|
412
|
-
analyticsQueue = [];
|
|
413
|
-
static description = "Create a new CopilotKit project with Next.js and Cloud setup";
|
|
136
|
+
static description = "Create a new CopilotKit project";
|
|
414
137
|
static examples = [
|
|
415
138
|
"$ copilotkit create my-app",
|
|
416
139
|
"$ copilotkit create my-app --framework langgraph-js",
|
|
@@ -436,7 +159,7 @@ var Create = class _Create extends BaseCommand {
|
|
|
436
159
|
required: false
|
|
437
160
|
}),
|
|
438
161
|
project: Flags.string({
|
|
439
|
-
description: "project ID (
|
|
162
|
+
description: "project ID (deprecated, kept for backwards compatibility)"
|
|
440
163
|
})
|
|
441
164
|
};
|
|
442
165
|
static args = {
|
|
@@ -445,135 +168,82 @@ var Create = class _Create extends BaseCommand {
|
|
|
445
168
|
required: false
|
|
446
169
|
})
|
|
447
170
|
};
|
|
171
|
+
constructor(argv, config) {
|
|
172
|
+
super(argv, config);
|
|
173
|
+
}
|
|
448
174
|
async run() {
|
|
449
175
|
const { args, flags } = await this.parse(_Create);
|
|
450
|
-
|
|
451
|
-
this.
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
this.log(theme.
|
|
456
|
-
if ((!flags.name || flags.projectName) && !flags.framework) {
|
|
457
|
-
this.log("\n" + theme.secondary("Just a few questions to get started!\n"));
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
const projectName = flags.name || args.projectName || await this.promptProjectName();
|
|
461
|
-
const agentFramework = flags.framework || await this.promptAgentFramework();
|
|
462
|
-
this.queueAnalytics("cli.create.started", {
|
|
463
|
-
framework_selected: agentFramework,
|
|
464
|
-
project_name: projectName,
|
|
465
|
-
flags_used: Object.keys(flags).filter((key) => flags[key] !== void 0 && key !== "help")
|
|
466
|
-
});
|
|
467
|
-
const projectDir = path.resolve(process.cwd(), projectName);
|
|
468
|
-
if (fs.existsSync(projectDir)) {
|
|
469
|
-
this.log(theme.error(`
|
|
470
|
-
Directory "${projectName}" already exists.`));
|
|
471
|
-
this.log(theme.secondary("\nYou can:"));
|
|
472
|
-
this.log(theme.secondary(" 1. Choose a different project name"));
|
|
473
|
-
this.log(theme.secondary(" 2. Remove the existing directory manually if you want to use this name\n"));
|
|
474
|
-
this.exit(1);
|
|
475
|
-
}
|
|
476
|
-
this.log(chalk3.cyan("\n\u{1F511} Now get your API key"));
|
|
477
|
-
this.log(chalk3.gray("Setting up your cloud account and retrieving your API key...\n"));
|
|
478
|
-
let cloudSetupInfo = null;
|
|
479
|
-
try {
|
|
480
|
-
cloudSetupInfo = await this.setupCloudApiKey(flags);
|
|
481
|
-
if (this.analytics && cloudSetupInfo.cliToken) {
|
|
482
|
-
const trpcClient2 = createTRPCClient(cloudSetupInfo.cliToken);
|
|
483
|
-
const me = await trpcClient2.me.query();
|
|
484
|
-
if (me.user && me.organization) {
|
|
485
|
-
this.analytics = new AnalyticsService({
|
|
486
|
-
userId: me.user.id,
|
|
487
|
-
organizationId: me.organization.id,
|
|
488
|
-
email: me.user.email
|
|
489
|
-
});
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
this.queueAnalytics("cli.create.cloud_setup_completed", {
|
|
493
|
-
framework: agentFramework,
|
|
494
|
-
project_id: cloudSetupInfo.selectedProjectId,
|
|
495
|
-
api_key_retrieved: !!cloudSetupInfo.apiKey
|
|
496
|
-
});
|
|
497
|
-
} catch (error) {
|
|
498
|
-
this.queueAnalytics("cli.create.cloud_setup_failed", {
|
|
499
|
-
framework: agentFramework,
|
|
500
|
-
error: error.message
|
|
501
|
-
});
|
|
502
|
-
throw error;
|
|
176
|
+
if (!flags["no-banner"]) {
|
|
177
|
+
this.log(theme.primary(KITE));
|
|
178
|
+
this.log(theme.primary("~ Welcome to CopilotKit! ~\n"));
|
|
179
|
+
this.log(theme.divider);
|
|
180
|
+
if ((!flags.name || flags.projectName) && !flags.framework) {
|
|
181
|
+
this.log("\n" + theme.secondary("Just a few questions to get started!\n"));
|
|
503
182
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
spinner.text = theme.secondary.bold("Downloading template...");
|
|
518
|
-
await this.downloadTemplate(projectDir, options.agentFramework);
|
|
519
|
-
if (options.apiKey) {
|
|
520
|
-
spinner.text = theme.secondary.bold("Configuring API key...");
|
|
521
|
-
await this.configureApiKey(projectDir, options.apiKey);
|
|
522
|
-
}
|
|
523
|
-
spinner.succeed(theme.secondary.bold(`Project "${projectName}" created successfully!`));
|
|
524
|
-
this.queueAnalytics("cli.create.project_created", {
|
|
525
|
-
framework: agentFramework,
|
|
526
|
-
project_name: projectName,
|
|
527
|
-
has_api_key: !!options.apiKey,
|
|
528
|
-
duration_ms: Date.now() - this.startTime
|
|
529
|
-
});
|
|
530
|
-
this.log("\n" + theme.divider);
|
|
531
|
-
this.log(
|
|
532
|
-
"\n" + theme.secondary.bold(
|
|
533
|
-
`\u{1FA81}\u{1F91D}${FRAMEWORK_EMOJI[options.agentFramework]} All set!
|
|
534
|
-
|
|
535
|
-
Your project is ready with Copilot Cloud configured.`
|
|
536
|
-
)
|
|
537
|
-
);
|
|
538
|
-
this.log("\n" + theme.secondary("Next steps:"));
|
|
539
|
-
this.log(theme.secondary(` \u2022 ${theme.command(`cd ${projectName}`)}`));
|
|
540
|
-
this.log(theme.secondary(" \u2022 Follow the setup instructions in the README.md"));
|
|
541
|
-
this.log("\n" + theme.secondary("Documentation:"));
|
|
542
|
-
this.log(theme.secondary(" \u2022 ") + theme.command("https://docs.copilotkit.ai"));
|
|
543
|
-
this.log(theme.secondary(" \u2022 ") + theme.command(FRAMEWORK_DOCUMENTATION[options.agentFramework]));
|
|
544
|
-
this.log(theme.bottomPadding);
|
|
545
|
-
this.queueAnalytics("cli.create.completed", {
|
|
546
|
-
framework: agentFramework,
|
|
547
|
-
project_name: projectName,
|
|
548
|
-
cloud_setup_completed: !!cloudSetupInfo,
|
|
549
|
-
api_key_configured: !!options.apiKey,
|
|
550
|
-
duration_ms: Date.now() - this.startTime
|
|
551
|
-
});
|
|
552
|
-
await this.flushAnalytics();
|
|
553
|
-
} catch (error) {
|
|
554
|
-
spinner.fail(theme.error(`Failed to create project: ${error.message}`));
|
|
555
|
-
this.queueAnalytics("cli.create.failed", {
|
|
556
|
-
framework: agentFramework,
|
|
557
|
-
project_name: projectName,
|
|
558
|
-
error: error.message,
|
|
559
|
-
step: "project_creation",
|
|
560
|
-
duration_ms: Date.now() - this.startTime
|
|
561
|
-
});
|
|
562
|
-
await this.flushAnalytics();
|
|
183
|
+
}
|
|
184
|
+
const projectNameInput = flags.name || args.projectName || await this.promptProjectName();
|
|
185
|
+
const projectName = projectNameInput.trim();
|
|
186
|
+
const usingCurrentDir = projectName === "." || projectName === "./";
|
|
187
|
+
const agentFramework = flags.framework || await this.promptAgentFramework();
|
|
188
|
+
const projectDir = usingCurrentDir ? process.cwd() : path.resolve(process.cwd(), projectName);
|
|
189
|
+
if (usingCurrentDir) {
|
|
190
|
+
const allowedEntries = /* @__PURE__ */ new Set([".git", ".gitignore", ".DS_Store"]);
|
|
191
|
+
const existingEntries = await fs.readdir(projectDir);
|
|
192
|
+
const blockingEntries = existingEntries.filter((entry) => !allowedEntries.has(entry));
|
|
193
|
+
if (blockingEntries.length > 0) {
|
|
194
|
+
this.log(theme.error("\nCurrent directory is not empty."));
|
|
195
|
+
this.log(theme.secondary("\nPlease run create in an empty directory or specify a new project name."));
|
|
563
196
|
this.exit(1);
|
|
564
197
|
}
|
|
198
|
+
} else if (await fs.pathExists(projectDir)) {
|
|
199
|
+
this.log(theme.error(`
|
|
200
|
+
Directory "${projectName}" already exists.`));
|
|
201
|
+
this.log(theme.secondary("\nYou can:"));
|
|
202
|
+
this.log(theme.secondary(" 1. Choose a different project name"));
|
|
203
|
+
this.log(theme.secondary(" 2. Remove the existing directory manually if you want to use this name\n"));
|
|
204
|
+
this.exit(1);
|
|
205
|
+
}
|
|
206
|
+
const options = {
|
|
207
|
+
projectName,
|
|
208
|
+
agentFramework
|
|
209
|
+
};
|
|
210
|
+
const spinner = ora({
|
|
211
|
+
text: theme.secondary.bold("Creating your project..."),
|
|
212
|
+
color: "cyan",
|
|
213
|
+
spinner: "dots"
|
|
214
|
+
}).start();
|
|
215
|
+
try {
|
|
216
|
+
await fs.ensureDir(projectDir);
|
|
217
|
+
spinner.text = theme.secondary.bold("Downloading template...");
|
|
218
|
+
await this.downloadTemplate(projectDir, options.agentFramework);
|
|
219
|
+
const displayName = usingCurrentDir ? "current directory" : `"${projectName}"`;
|
|
220
|
+
spinner.succeed(theme.secondary.bold(`Project ${displayName} created successfully!`));
|
|
565
221
|
} catch (error) {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
222
|
+
spinner.fail(theme.error(`Failed to create project: ${error.message}`));
|
|
223
|
+
this.exit(1);
|
|
224
|
+
}
|
|
225
|
+
this.log("\n" + theme.divider);
|
|
226
|
+
this.log(
|
|
227
|
+
"\n" + theme.secondary.bold(
|
|
228
|
+
`\u{1FA81}\u{1F91D}${FRAMEWORK_EMOJI[options.agentFramework]} All set!
|
|
229
|
+
|
|
230
|
+
Your project is ready to explore CopilotKit locally.`
|
|
231
|
+
)
|
|
232
|
+
);
|
|
233
|
+
this.log("\n" + theme.secondary("Next steps:"));
|
|
234
|
+
if (usingCurrentDir) {
|
|
235
|
+
this.log(theme.secondary(" \u2022 You are already inside your new project directory"));
|
|
236
|
+
} else {
|
|
237
|
+
this.log(theme.secondary(` \u2022 ${theme.command(`cd ${projectName}`)}`));
|
|
573
238
|
}
|
|
239
|
+
this.log(theme.secondary(" \u2022 Follow the setup instructions in the README.md"));
|
|
240
|
+
this.log("\n" + theme.secondary("Documentation:"));
|
|
241
|
+
this.log(theme.secondary(" \u2022 ") + theme.command("https://docs.copilotkit.ai"));
|
|
242
|
+
this.log(theme.secondary(" \u2022 ") + theme.command(FRAMEWORK_DOCUMENTATION[options.agentFramework]));
|
|
243
|
+
this.log(theme.bottomPadding);
|
|
574
244
|
}
|
|
575
245
|
async promptProjectName() {
|
|
576
|
-
const { projectName } = await
|
|
246
|
+
const { projectName } = await inquirer.prompt([
|
|
577
247
|
{
|
|
578
248
|
type: "input",
|
|
579
249
|
name: "projectName",
|
|
@@ -593,7 +263,7 @@ Your project is ready with Copilot Cloud configured.`
|
|
|
593
263
|
return projectName;
|
|
594
264
|
}
|
|
595
265
|
async promptAgentFramework() {
|
|
596
|
-
const { framework } = await
|
|
266
|
+
const { framework } = await inquirer.prompt([
|
|
597
267
|
{
|
|
598
268
|
type: "list",
|
|
599
269
|
name: "framework",
|
|
@@ -603,11 +273,11 @@ Your project is ready with Copilot Cloud configured.`
|
|
|
603
273
|
{ name: `${FRAMEWORK_EMOJI["langgraph-js"]} LangGraph (JavaScript)`, value: "langgraph-js" },
|
|
604
274
|
{ name: `${FRAMEWORK_EMOJI.mastra} Mastra`, value: "mastra" },
|
|
605
275
|
{ name: `${FRAMEWORK_EMOJI["pydantic-ai"]} Pydantic AI`, value: "pydantic-ai" },
|
|
276
|
+
{ name: `${FRAMEWORK_EMOJI.adk} ADK`, value: "adk" },
|
|
606
277
|
{ name: `${FRAMEWORK_EMOJI.flows} CrewAI Flows`, value: "flows" },
|
|
607
278
|
{ name: `${FRAMEWORK_EMOJI.llamaindex} LlamaIndex`, value: "llamaindex" },
|
|
608
279
|
{ name: `${FRAMEWORK_EMOJI.agno} Agno`, value: "agno" },
|
|
609
|
-
{ name: `${FRAMEWORK_EMOJI.ag2} AG2`, value: "ag2" }
|
|
610
|
-
{ name: `${FRAMEWORK_EMOJI.adk} ADK`, value: "adk" }
|
|
280
|
+
{ name: `${FRAMEWORK_EMOJI.ag2} AG2`, value: "ag2" }
|
|
611
281
|
]
|
|
612
282
|
}
|
|
613
283
|
]);
|
|
@@ -633,100 +303,6 @@ Your project is ready with Copilot Cloud configured.`
|
|
|
633
303
|
throw new Error(`Failed to download template: ${error.message}`);
|
|
634
304
|
}
|
|
635
305
|
}
|
|
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
306
|
};
|
|
731
307
|
export {
|
|
732
308
|
Create as default
|