@struere/cli 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +15 -107
- package/package.json +12 -4
package/dist/index.js
CHANGED
|
@@ -76,11 +76,13 @@ function getSyncUrl() {
|
|
|
76
76
|
|
|
77
77
|
class ApiClient {
|
|
78
78
|
baseUrl;
|
|
79
|
-
|
|
79
|
+
tokenOverride;
|
|
80
|
+
constructor(baseUrl, token) {
|
|
80
81
|
this.baseUrl = baseUrl || getApiUrl();
|
|
82
|
+
this.tokenOverride = token;
|
|
81
83
|
}
|
|
82
84
|
async request(path, options = {}) {
|
|
83
|
-
const token = getToken();
|
|
85
|
+
const token = this.tokenOverride || getToken();
|
|
84
86
|
const apiKey = getApiKey();
|
|
85
87
|
const headers = {
|
|
86
88
|
"Content-Type": "application/json",
|
|
@@ -165,7 +167,7 @@ class ApiError extends Error {
|
|
|
165
167
|
|
|
166
168
|
// src/commands/login.ts
|
|
167
169
|
var AUTH_CALLBACK_PORT = 9876;
|
|
168
|
-
var loginCommand = new Command("login").description("Log in to Struere").
|
|
170
|
+
var loginCommand = new Command("login").description("Log in to Struere").action(async () => {
|
|
169
171
|
const spinner = ora();
|
|
170
172
|
console.log();
|
|
171
173
|
console.log(chalk.bold("Struere Login"));
|
|
@@ -177,22 +179,14 @@ var loginCommand = new Command("login").description("Log in to Struere").option(
|
|
|
177
179
|
console.log();
|
|
178
180
|
return;
|
|
179
181
|
}
|
|
180
|
-
|
|
181
|
-
await headlessLogin(spinner);
|
|
182
|
-
} else {
|
|
183
|
-
await browserLogin(spinner);
|
|
184
|
-
}
|
|
182
|
+
await browserLogin(spinner);
|
|
185
183
|
});
|
|
186
|
-
async function performLogin(
|
|
184
|
+
async function performLogin() {
|
|
187
185
|
const spinner = ora();
|
|
188
186
|
console.log();
|
|
189
187
|
console.log(chalk.bold("Struere Login"));
|
|
190
188
|
console.log();
|
|
191
|
-
|
|
192
|
-
return headlessLoginInternal(spinner);
|
|
193
|
-
} else {
|
|
194
|
-
return browserLoginInternal(spinner);
|
|
195
|
-
}
|
|
189
|
+
return browserLoginInternal(spinner);
|
|
196
190
|
}
|
|
197
191
|
async function browserLogin(spinner) {
|
|
198
192
|
const result = await browserLoginInternal(spinner);
|
|
@@ -212,6 +206,7 @@ async function browserLoginInternal(spinner) {
|
|
|
212
206
|
const sessionId = url.searchParams.get("session_id");
|
|
213
207
|
if (token && sessionId) {
|
|
214
208
|
resolve({ token, sessionId });
|
|
209
|
+
setTimeout(() => server.stop(), 1000);
|
|
215
210
|
return new Response(getSuccessHtml(), {
|
|
216
211
|
headers: { "Content-Type": "text/html" }
|
|
217
212
|
});
|
|
@@ -250,7 +245,7 @@ async function browserLoginInternal(spinner) {
|
|
|
250
245
|
try {
|
|
251
246
|
const { token } = await authPromise;
|
|
252
247
|
spinner.text = "Fetching user info";
|
|
253
|
-
const api = new ApiClient;
|
|
248
|
+
const api = new ApiClient(undefined, token);
|
|
254
249
|
const { user, organization } = await api.getMe();
|
|
255
250
|
const credentials = {
|
|
256
251
|
token,
|
|
@@ -279,60 +274,6 @@ async function browserLoginInternal(spinner) {
|
|
|
279
274
|
console.log();
|
|
280
275
|
console.log(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
281
276
|
console.log();
|
|
282
|
-
console.log(chalk.gray("Try"), chalk.cyan("struere login --headless"), chalk.gray("for email/password login"));
|
|
283
|
-
console.log();
|
|
284
|
-
return null;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
async function headlessLogin(spinner) {
|
|
288
|
-
const result = await headlessLoginInternal(spinner);
|
|
289
|
-
if (result) {
|
|
290
|
-
printNextSteps();
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
async function headlessLoginInternal(spinner) {
|
|
294
|
-
const email = await prompt("Email: ");
|
|
295
|
-
const password = await prompt("Password: ", true);
|
|
296
|
-
if (!email || !password) {
|
|
297
|
-
console.log(chalk.red("Email and password are required"));
|
|
298
|
-
return null;
|
|
299
|
-
}
|
|
300
|
-
spinner.start("Logging in");
|
|
301
|
-
try {
|
|
302
|
-
const api = new ApiClient;
|
|
303
|
-
const { token, user } = await api.login(email, password);
|
|
304
|
-
const { organization } = await api.getMe();
|
|
305
|
-
const credentials = {
|
|
306
|
-
token,
|
|
307
|
-
user: {
|
|
308
|
-
id: user.id,
|
|
309
|
-
email: user.email,
|
|
310
|
-
name: user.name,
|
|
311
|
-
organizationId: user.organizationId
|
|
312
|
-
},
|
|
313
|
-
organization: {
|
|
314
|
-
id: organization.id,
|
|
315
|
-
name: organization.name,
|
|
316
|
-
slug: organization.slug
|
|
317
|
-
},
|
|
318
|
-
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString()
|
|
319
|
-
};
|
|
320
|
-
saveCredentials(credentials);
|
|
321
|
-
spinner.succeed("Logged in successfully");
|
|
322
|
-
console.log();
|
|
323
|
-
console.log(chalk.green("Welcome,"), chalk.cyan(user.name));
|
|
324
|
-
console.log(chalk.gray("Organization:"), organization.name);
|
|
325
|
-
console.log();
|
|
326
|
-
return credentials;
|
|
327
|
-
} catch (error) {
|
|
328
|
-
spinner.fail("Login failed");
|
|
329
|
-
console.log();
|
|
330
|
-
if (error instanceof ApiError) {
|
|
331
|
-
console.log(chalk.red("Error:"), error.message);
|
|
332
|
-
} else {
|
|
333
|
-
console.log(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
334
|
-
}
|
|
335
|
-
console.log();
|
|
336
277
|
return null;
|
|
337
278
|
}
|
|
338
279
|
}
|
|
@@ -344,9 +285,9 @@ function printNextSteps() {
|
|
|
344
285
|
console.log();
|
|
345
286
|
}
|
|
346
287
|
function getAuthUrl() {
|
|
347
|
-
const baseUrl = process.env.STRUERE_AUTH_URL || "https://struere.dev";
|
|
288
|
+
const baseUrl = process.env.STRUERE_AUTH_URL || "https://app.struere.dev";
|
|
348
289
|
const callbackUrl = `http://localhost:${AUTH_CALLBACK_PORT}/callback`;
|
|
349
|
-
return `${baseUrl}/
|
|
290
|
+
return `${baseUrl}/authorize?callback=${encodeURIComponent(callbackUrl)}`;
|
|
350
291
|
}
|
|
351
292
|
function getSuccessHtml() {
|
|
352
293
|
return `<!DOCTYPE html>
|
|
@@ -389,39 +330,6 @@ function getErrorHtml(message) {
|
|
|
389
330
|
</body>
|
|
390
331
|
</html>`;
|
|
391
332
|
}
|
|
392
|
-
async function prompt(message, hidden = false) {
|
|
393
|
-
process.stdout.write(chalk.gray(message));
|
|
394
|
-
return new Promise((resolve) => {
|
|
395
|
-
let input = "";
|
|
396
|
-
if (hidden) {
|
|
397
|
-
process.stdin.setRawMode(true);
|
|
398
|
-
}
|
|
399
|
-
process.stdin.resume();
|
|
400
|
-
process.stdin.setEncoding("utf8");
|
|
401
|
-
const onData = (char) => {
|
|
402
|
-
if (char === `
|
|
403
|
-
` || char === "\r") {
|
|
404
|
-
process.stdin.removeListener("data", onData);
|
|
405
|
-
process.stdin.pause();
|
|
406
|
-
if (hidden) {
|
|
407
|
-
process.stdin.setRawMode(false);
|
|
408
|
-
console.log();
|
|
409
|
-
}
|
|
410
|
-
resolve(input);
|
|
411
|
-
} else if (char === "\x03") {
|
|
412
|
-
process.exit();
|
|
413
|
-
} else if (char === "\x7F") {
|
|
414
|
-
input = input.slice(0, -1);
|
|
415
|
-
} else {
|
|
416
|
-
input += char;
|
|
417
|
-
if (!hidden) {
|
|
418
|
-
process.stdout.write(char);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
};
|
|
422
|
-
process.stdin.on("data", onData);
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
333
|
|
|
426
334
|
// src/utils/project.ts
|
|
427
335
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -774,7 +682,7 @@ function hasAgentFiles(cwd) {
|
|
|
774
682
|
}
|
|
775
683
|
|
|
776
684
|
// src/commands/init.ts
|
|
777
|
-
var initCommand = new Command2("init").description("Initialize a new Struere project").argument("[project-name]", "Project name").option("-y, --yes", "Skip prompts and use defaults").
|
|
685
|
+
var initCommand = new Command2("init").description("Initialize a new Struere project").argument("[project-name]", "Project name").option("-y, --yes", "Skip prompts and use defaults").action(async (projectNameArg, options) => {
|
|
778
686
|
const cwd = process.cwd();
|
|
779
687
|
const spinner = ora2();
|
|
780
688
|
console.log();
|
|
@@ -802,7 +710,7 @@ var initCommand = new Command2("init").description("Initialize a new Struere pro
|
|
|
802
710
|
if (!credentials) {
|
|
803
711
|
console.log(chalk2.gray("Authentication required"));
|
|
804
712
|
console.log();
|
|
805
|
-
credentials = await performLogin(
|
|
713
|
+
credentials = await performLogin();
|
|
806
714
|
if (!credentials) {
|
|
807
715
|
console.log(chalk2.red("Authentication failed"));
|
|
808
716
|
process.exit(1);
|
|
@@ -2208,7 +2116,7 @@ var whoamiCommand = new Command11("whoami").description("Show current logged in
|
|
|
2208
2116
|
});
|
|
2209
2117
|
|
|
2210
2118
|
// src/index.ts
|
|
2211
|
-
program.name("struere").description("Struere CLI - Build, test, and deploy AI agents").version("0.2.
|
|
2119
|
+
program.name("struere").description("Struere CLI - Build, test, and deploy AI agents").version("0.2.4");
|
|
2212
2120
|
program.addCommand(initCommand);
|
|
2213
2121
|
program.addCommand(loginCommand);
|
|
2214
2122
|
program.addCommand(logoutCommand);
|
package/package.json
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@struere/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "CLI tool for developing, testing, and deploying AI agents",
|
|
5
|
-
"keywords": [
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"agents",
|
|
8
|
+
"cli",
|
|
9
|
+
"developer-tools",
|
|
10
|
+
"llm"
|
|
11
|
+
],
|
|
6
12
|
"author": "struere",
|
|
7
13
|
"license": "MIT",
|
|
8
14
|
"publishConfig": {
|
|
@@ -22,13 +28,15 @@
|
|
|
22
28
|
"struere": "./dist/index.js"
|
|
23
29
|
},
|
|
24
30
|
"main": "./dist/index.js",
|
|
25
|
-
"files": [
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
26
34
|
"scripts": {
|
|
27
35
|
"build": "bun build ./src/index.ts --outdir ./dist --target bun --external commander --external chalk --external ora --external chokidar --external yaml --external @struere/runtime && chmod +x ./dist/index.js",
|
|
28
36
|
"dev": "tsc --watch",
|
|
29
37
|
"test": "bun test",
|
|
30
38
|
"prepublishOnly": "bun run build && bun run verify-build",
|
|
31
|
-
"bump": "node scripts/bump-version.
|
|
39
|
+
"bump": "node scripts/bump-version.cjs",
|
|
32
40
|
"verify-build": "node -e \"const pkg = require('./package.json'); const fs = require('fs'); const bundle = fs.readFileSync('./dist/index.js', 'utf8'); const match = bundle.match(/version\\(\\\"([^\\\"]+)\\\"\\)/); if (!match || match[1] !== pkg.version) { console.error('Version mismatch: package.json=' + pkg.version + ' bundle=' + (match ? match[1] : 'not found')); process.exit(1); } console.log('Build verified: v' + pkg.version);\""
|
|
33
41
|
},
|
|
34
42
|
"dependencies": {
|