@flatkey-ai/cli 0.1.22 → 0.1.25
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/README.md +34 -3
- package/package.json +1 -1
- package/src/cli.js +75 -5
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ Website: [flatkey.ai](https://flatkey.ai/?utm_source=github&utm_medium=readme&ut
|
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
npm install -g @flatkey-ai/cli
|
|
16
|
-
|
|
16
|
+
flatkey login
|
|
17
17
|
|
|
18
18
|
flatkey image generate --prompt "editorial cover, neon city at dawn" -o cover.png
|
|
19
19
|
flatkey video generate --prompt "cinematic product launch clip" --model seedance2 -o launch.mp4
|
|
@@ -67,13 +67,44 @@ flatkey -v
|
|
|
67
67
|
|
|
68
68
|
## Auth
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
Recommended: sign in through the Flatkey console:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
flatkey login
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`flatkey login` opens a browser authorization page, waits for approval, then saves the CLI API key and account metadata in your local Flatkey config. After login, check the active auth state:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
flatkey auth status
|
|
80
|
+
flatkey status --json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
If your terminal cannot open a browser automatically, print the approval URL and open it yourself:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
flatkey login --no-open
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
For staging or self-hosted console testing:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
flatkey login --console-url https://console.flatkey.ai
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
To remove the saved API key:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
flatkey logout
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Alternative: use an environment variable:
|
|
71
102
|
|
|
72
103
|
```bash
|
|
73
104
|
export FLATKEY_API_KEY=<key>
|
|
74
105
|
```
|
|
75
106
|
|
|
76
|
-
Or save
|
|
107
|
+
Or save a manually created key locally:
|
|
77
108
|
|
|
78
109
|
```bash
|
|
79
110
|
flatkey onboard --api-key <key>
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -267,6 +267,7 @@ async function handleLogin(command, deps) {
|
|
|
267
267
|
});
|
|
268
268
|
const pollData = poll?.data ?? poll;
|
|
269
269
|
if (pollData?.status === "approved") {
|
|
270
|
+
const account = accountFromAuthData(pollData);
|
|
270
271
|
if (!pollData.api_key) {
|
|
271
272
|
const saved = await readConfig(deps.configDir);
|
|
272
273
|
if (typeof saved?.apiKey === "string" && saved.apiKey.trim() !== "") {
|
|
@@ -276,6 +277,7 @@ async function handleLogin(command, deps) {
|
|
|
276
277
|
deviceId,
|
|
277
278
|
userId: pollData.user_id ?? saved.auth?.userId,
|
|
278
279
|
tokenId: pollData.token_id ?? saved.auth?.tokenId,
|
|
280
|
+
account: account ?? saved.auth?.account,
|
|
279
281
|
loginAt: Math.floor(Date.now() / 1000),
|
|
280
282
|
},
|
|
281
283
|
configDir: deps.configDir,
|
|
@@ -284,8 +286,7 @@ async function handleLogin(command, deps) {
|
|
|
284
286
|
? {
|
|
285
287
|
success: true,
|
|
286
288
|
configPath,
|
|
287
|
-
|
|
288
|
-
userId: pollData.user_id ?? saved.auth?.userId,
|
|
289
|
+
account: stripDisplayOnlyIds(account ?? saved.auth?.account),
|
|
289
290
|
reusedConfig: true,
|
|
290
291
|
}
|
|
291
292
|
: `Flatkey CLI already authorized. Saved config: ${configPath}`;
|
|
@@ -298,12 +299,17 @@ async function handleLogin(command, deps) {
|
|
|
298
299
|
deviceId,
|
|
299
300
|
userId: pollData.user_id,
|
|
300
301
|
tokenId: pollData.token_id,
|
|
302
|
+
account,
|
|
301
303
|
loginAt: Math.floor(Date.now() / 1000),
|
|
302
304
|
},
|
|
303
305
|
configDir: deps.configDir,
|
|
304
306
|
});
|
|
305
307
|
return command.options.json
|
|
306
|
-
? {
|
|
308
|
+
? {
|
|
309
|
+
success: true,
|
|
310
|
+
configPath,
|
|
311
|
+
account: stripDisplayOnlyIds(account),
|
|
312
|
+
}
|
|
307
313
|
: `Flatkey CLI authorized. Saved config: ${configPath}`;
|
|
308
314
|
}
|
|
309
315
|
if (pollData?.status === "denied") {
|
|
@@ -732,7 +738,8 @@ function redactRequest(request) {
|
|
|
732
738
|
}
|
|
733
739
|
|
|
734
740
|
async function handleUtility(command, deps) {
|
|
735
|
-
const { resolveApiKey, resolveOrigins } = await import("./config.js");
|
|
741
|
+
const { readConfig, resolveApiKey, resolveOrigins } = await import("./config.js");
|
|
742
|
+
const saved = await readConfig(deps.configDir);
|
|
736
743
|
const { getCredits, getStatus } = await import("./api.js");
|
|
737
744
|
const apiKey = await resolveApiKey({
|
|
738
745
|
apiKey: command.options.api_key,
|
|
@@ -749,7 +756,70 @@ async function handleUtility(command, deps) {
|
|
|
749
756
|
baseUrl: consoleOrigin,
|
|
750
757
|
fetch: deps.fetch,
|
|
751
758
|
};
|
|
752
|
-
|
|
759
|
+
if (command.group === "credits") return getCredits(options);
|
|
760
|
+
|
|
761
|
+
const status = sanitizeStatusResponse(await getStatus(options));
|
|
762
|
+
const account = effectiveAccountForStatus({ command, saved, apiKey });
|
|
763
|
+
if (!account || !status || typeof status !== "object" || Array.isArray(status) || status.account !== undefined) {
|
|
764
|
+
return command.options.json ? status : extractStatusDisplayFields(status);
|
|
765
|
+
}
|
|
766
|
+
const mergedStatus = sanitizeStatusResponse({ ...status, account });
|
|
767
|
+
return command.options.json ? mergedStatus : extractStatusDisplayFields(mergedStatus);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
function effectiveAccountForStatus({ command, saved, apiKey }) {
|
|
771
|
+
if (command.options.api_key || !saved?.apiKey || saved.apiKey !== apiKey) return null;
|
|
772
|
+
if (saved.auth?.account !== undefined) return saved.auth.account;
|
|
773
|
+
return accountFromAuthData(saved.auth);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
function accountFromAuthData(data) {
|
|
777
|
+
if (!data || typeof data !== "object") return null;
|
|
778
|
+
const email = data.account?.email ?? data.email ?? data.userEmail ?? data.user_email;
|
|
779
|
+
const name = data.account?.name ?? data.name;
|
|
780
|
+
const userId = data.account?.userId ?? data.account?.user_id ?? data.userId ?? data.user_id;
|
|
781
|
+
if (email === undefined && name === undefined && userId === undefined) return null;
|
|
782
|
+
return Object.fromEntries(
|
|
783
|
+
Object.entries({
|
|
784
|
+
email,
|
|
785
|
+
name,
|
|
786
|
+
userId,
|
|
787
|
+
}).filter(([, value]) => value !== undefined && value !== null),
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
function sanitizeStatusResponse(status) {
|
|
792
|
+
if (!status || typeof status !== "object") return status;
|
|
793
|
+
if (Array.isArray(status)) {
|
|
794
|
+
return status.map((entry) => sanitizeStatusResponse(entry));
|
|
795
|
+
}
|
|
796
|
+
return Object.fromEntries(
|
|
797
|
+
Object.entries(status)
|
|
798
|
+
.filter(([key]) => !["userId", "user_id"].includes(key))
|
|
799
|
+
.map(([key, value]) => [key, sanitizeStatusResponse(value)]),
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function stripDisplayOnlyIds(value) {
|
|
804
|
+
if (!value || typeof value !== "object") return value;
|
|
805
|
+
if (Array.isArray(value)) {
|
|
806
|
+
return value.map((entry) => stripDisplayOnlyIds(entry));
|
|
807
|
+
}
|
|
808
|
+
return Object.fromEntries(
|
|
809
|
+
Object.entries(value)
|
|
810
|
+
.filter(([key]) => !["userId", "user_id", "tokenId", "token_id"].includes(key))
|
|
811
|
+
.map(([key, nested]) => [key, stripDisplayOnlyIds(nested)]),
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
function extractStatusDisplayFields(status) {
|
|
816
|
+
if (!status || typeof status !== "object") return status;
|
|
817
|
+
const email = status.email ?? status.account?.email ?? status.user?.email;
|
|
818
|
+
const name = status.name ?? status.account?.name ?? status.user?.name;
|
|
819
|
+
const result = {};
|
|
820
|
+
if (email !== undefined) result.email = email;
|
|
821
|
+
if (name !== undefined) result.name = name;
|
|
822
|
+
return result;
|
|
753
823
|
}
|
|
754
824
|
|
|
755
825
|
async function handleModels(command, deps) {
|