agent-factorio 0.3.4 → 0.4.0
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/commands/login.mjs +46 -26
- package/package.json +1 -1
package/commands/login.mjs
CHANGED
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* agent-factorio login —
|
|
2
|
+
* agent-factorio login — Browser-based authentication (like Claude Code /login)
|
|
3
3
|
*/
|
|
4
4
|
import { ask, choose } from "../lib/prompt.mjs";
|
|
5
5
|
import { readGlobalConfig, upsertOrg } from "../lib/config.mjs";
|
|
6
6
|
import { apiCall, checkHub } from "../lib/api.mjs";
|
|
7
7
|
import { success, error, info, dim } from "../lib/log.mjs";
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Try to open a URL in the default browser
|
|
11
|
+
* @param {string} url
|
|
12
|
+
*/
|
|
13
|
+
async function openBrowser(url) {
|
|
14
|
+
const { exec } = await import("child_process");
|
|
15
|
+
const { platform } = await import("os");
|
|
16
|
+
|
|
17
|
+
const cmd =
|
|
18
|
+
platform() === "darwin"
|
|
19
|
+
? `open "${url}"`
|
|
20
|
+
: platform() === "win32"
|
|
21
|
+
? `start "" "${url}"`
|
|
22
|
+
: `xdg-open "${url}"`;
|
|
23
|
+
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
exec(cmd, (err) => resolve(!err));
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
9
29
|
/**
|
|
10
30
|
* Poll verification status until verified or expired
|
|
11
31
|
* @param {string} hubUrl
|
|
@@ -23,7 +43,7 @@ async function waitForVerification(hubUrl, loginToken) {
|
|
|
23
43
|
});
|
|
24
44
|
|
|
25
45
|
if (res.status === 410) {
|
|
26
|
-
throw new Error("
|
|
46
|
+
throw new Error("Login session expired. Please try again.");
|
|
27
47
|
}
|
|
28
48
|
|
|
29
49
|
if (!res.ok) {
|
|
@@ -34,11 +54,10 @@ async function waitForVerification(hubUrl, loginToken) {
|
|
|
34
54
|
return { userId: res.data.userId, email: res.data.email };
|
|
35
55
|
}
|
|
36
56
|
|
|
37
|
-
// Wait before next poll
|
|
38
57
|
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
|
|
39
58
|
}
|
|
40
59
|
|
|
41
|
-
throw new Error("
|
|
60
|
+
throw new Error("Login timed out. Please try again.");
|
|
42
61
|
}
|
|
43
62
|
|
|
44
63
|
const DEFAULT_HUB_URL = "https://agent-factorio.vercel.app";
|
|
@@ -54,45 +73,46 @@ export async function loginCommand(options = {}) {
|
|
|
54
73
|
process.exit(1);
|
|
55
74
|
}
|
|
56
75
|
|
|
57
|
-
//
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
76
|
+
// 1. Initialize browser login session
|
|
77
|
+
const initRes = await apiCall(hubUrl, "/api/cli/login", {
|
|
78
|
+
body: { action: "init-browser-login" },
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (!initRes.ok) {
|
|
82
|
+
error(`Failed to initialize login: ${initRes.data?.error || "Unknown error"}`);
|
|
61
83
|
process.exit(1);
|
|
62
84
|
}
|
|
63
85
|
|
|
64
|
-
|
|
65
|
-
info("Sending verification email...");
|
|
66
|
-
const sendRes = await apiCall(hubUrl, "/api/cli/login", {
|
|
67
|
-
body: { action: "send-verification", email },
|
|
68
|
-
});
|
|
86
|
+
const { loginToken, loginUrl } = initRes.data;
|
|
69
87
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
88
|
+
// 2. Open browser
|
|
89
|
+
const opened = await openBrowser(loginUrl);
|
|
90
|
+
if (!opened) {
|
|
91
|
+
console.log();
|
|
92
|
+
info("Browser didn't open? Use the url below to sign in:");
|
|
93
|
+
console.log(` ${loginUrl}`);
|
|
73
94
|
}
|
|
74
95
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
info("Check your inbox and click the verification link.");
|
|
78
|
-
dim("Waiting for verification...");
|
|
96
|
+
console.log();
|
|
97
|
+
dim("Waiting for sign-in...");
|
|
79
98
|
|
|
80
|
-
//
|
|
81
|
-
let userId;
|
|
99
|
+
// 3. Poll for verification
|
|
100
|
+
let userId, email;
|
|
82
101
|
try {
|
|
83
102
|
const result = await waitForVerification(hubUrl, loginToken);
|
|
84
103
|
userId = result.userId;
|
|
104
|
+
email = result.email;
|
|
85
105
|
} catch (err) {
|
|
86
106
|
error(err.message);
|
|
87
107
|
process.exit(1);
|
|
88
108
|
}
|
|
89
109
|
|
|
90
|
-
success(
|
|
110
|
+
success(`Logged in as ${email}`);
|
|
91
111
|
|
|
92
|
-
//
|
|
112
|
+
// 4. Name input
|
|
93
113
|
const memberName = await ask("Your name (displayed in the org)", "CLI User");
|
|
94
114
|
|
|
95
|
-
//
|
|
115
|
+
// 5. Create or Join
|
|
96
116
|
const { index: actionIdx } = await choose("Create or join an organization?", [
|
|
97
117
|
"Create new",
|
|
98
118
|
"Join existing (invite code)",
|
|
@@ -143,5 +163,5 @@ export async function loginCommand(options = {}) {
|
|
|
143
163
|
success(`Joined "${orgName}" (${orgId})`);
|
|
144
164
|
}
|
|
145
165
|
|
|
146
|
-
console.log("\
|
|
166
|
+
console.log("\nLogin successful! Run `agent-factorio push` in any project to register an agent.");
|
|
147
167
|
}
|