@flatkey-ai/cli 0.2.0 → 0.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flatkey-ai/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Flatkey media generation CLI for image, video, audio, credits, status, and models.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { withCliRequestHeaders } from "./requestHeaders.js";
2
+
1
3
  export const DEFAULT_BASE_URL = "https://router.flatkey.ai";
2
4
  export const DEFAULT_MODELS_BASE_URL = "https://console.flatkey.ai";
3
5
  export const DEFAULT_CONSOLE_URL = "https://console.flatkey.ai";
@@ -231,7 +233,7 @@ function planRequest(options, path, init = {}) {
231
233
  return {
232
234
  url: buildUrl(options.baseUrl, path),
233
235
  method: init.method ?? "GET",
234
- headers: init.headers ?? authHeaders(options.apiKey),
236
+ headers: withCliRequestHeaders(init.headers ?? authHeaders(options.apiKey)),
235
237
  body: init.body,
236
238
  };
237
239
  }
package/src/artifacts.js CHANGED
@@ -2,6 +2,8 @@ import { mkdir, writeFile } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { dirname, extname, join } from "node:path";
4
4
 
5
+ import { CLI_REQUEST_HEADERS } from "./requestHeaders.js";
6
+
5
7
  const DEFAULT_EXTENSIONS = {
6
8
  audio: "mp3",
7
9
  image: "png",
@@ -80,7 +82,7 @@ async function persistItem({ kind, item, outDir, output, index, fetchImpl }) {
80
82
  }
81
83
 
82
84
  async function downloadArtifact({ url, path, fetchImpl }) {
83
- const response = await fetchImpl(url);
85
+ const response = await fetchImpl(url, { headers: CLI_REQUEST_HEADERS });
84
86
  if (!response.ok) {
85
87
  throw new Error(`Failed to download artifact ${url}: HTTP ${response.status}`);
86
88
  }
package/src/cli.js CHANGED
@@ -146,26 +146,30 @@ function validateCommandOptions(command) {
146
146
  return command;
147
147
  }
148
148
 
149
- export async function main(argv) {
149
+ export async function main(argv, deps = {}) {
150
+ const stdout = deps.stdout ?? process.stdout;
151
+ const stderr = deps.stderr ?? process.stderr;
150
152
  const command = parseArgv(argv);
151
153
  if (command.options.help) {
152
- const result = await runCommand(command);
153
- process.stdout.write(`${formatHuman(result)}\n`);
154
+ const result = await runCommand(command, { ...deps, stdout, stderr });
155
+ stdout.write(`${formatHuman(result)}\n`);
154
156
  return;
155
157
  }
156
158
  if (command.group === "onboard") {
157
159
  const { writeConfig } = await import("./config.js");
158
- const configPath = await writeConfig({ apiKey: command.options.api_key });
159
- process.stdout.write(`Saved Flatkey config: ${configPath}\n`);
160
+ const configPath = await writeConfig({ apiKey: command.options.api_key, configDir: deps.configDir });
161
+ stdout.write(`Saved Flatkey config: ${configPath}\n`);
162
+ await maybeWriteUpdateNotice(command, { ...deps, stderr });
160
163
  return;
161
164
  }
162
165
 
163
- const result = await runCommand(command);
166
+ const result = await runCommand(command, { ...deps, stdout, stderr });
164
167
  if (result !== undefined) {
165
- process.stdout.write(
168
+ stdout.write(
166
169
  command.options.json ? `${JSON.stringify(result)}\n` : `${formatHuman(result)}\n`,
167
170
  );
168
171
  }
172
+ await maybeWriteUpdateNotice(command, { ...deps, stderr });
169
173
  }
170
174
 
171
175
  export async function runCommand(command, deps = {}) {
@@ -1027,3 +1031,54 @@ async function readPackageVersion() {
1027
1031
  const packageUrl = new URL("../package.json", import.meta.url);
1028
1032
  return JSON.parse(await readFile(packageUrl, "utf8")).version;
1029
1033
  }
1034
+
1035
+ async function maybeWriteUpdateNotice(command, deps = {}) {
1036
+ if (command.options.json || command.options.help || command.group === "help" || command.group === "version") {
1037
+ return;
1038
+ }
1039
+ try {
1040
+ const current = await readPackageVersion();
1041
+ const latest = await fetchLatestPackageVersion(deps);
1042
+ if (!latest || compareVersions(latest, current) <= 0) return;
1043
+ deps.stderr?.write?.([
1044
+ `\nFlatkey CLI update available: ${current} -> ${latest}`,
1045
+ "Upgrade: npm install -g @flatkey-ai/cli",
1046
+ "",
1047
+ ].join("\n"));
1048
+ } catch {
1049
+ // Update checks must never break normal CLI commands.
1050
+ }
1051
+ }
1052
+
1053
+ async function fetchLatestPackageVersion(deps = {}) {
1054
+ const { CLI_REQUEST_HEADERS } = await import("./requestHeaders.js");
1055
+ const fetchImpl = deps.fetch ?? globalThis.fetch;
1056
+ if (typeof fetchImpl !== "function") return undefined;
1057
+ const response = await fetchImpl("https://registry.npmjs.org/@flatkey-ai%2fcli/latest", {
1058
+ headers: CLI_REQUEST_HEADERS,
1059
+ signal: typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function"
1060
+ ? AbortSignal.timeout(750)
1061
+ : undefined,
1062
+ });
1063
+ if (!response?.ok) return undefined;
1064
+ const body = await response.json();
1065
+ return typeof body?.version === "string" ? body.version : undefined;
1066
+ }
1067
+
1068
+ function compareVersions(left, right) {
1069
+ const leftParts = parseVersionParts(left);
1070
+ const rightParts = parseVersionParts(right);
1071
+ for (let index = 0; index < Math.max(leftParts.length, rightParts.length); index += 1) {
1072
+ const difference = (leftParts[index] ?? 0) - (rightParts[index] ?? 0);
1073
+ if (difference !== 0) return difference;
1074
+ }
1075
+ return 0;
1076
+ }
1077
+
1078
+ function parseVersionParts(version) {
1079
+ return String(version)
1080
+ .split("-", 1)[0]
1081
+ .split(".")
1082
+ .map((part) => Number.parseInt(part, 10))
1083
+ .map((part) => Number.isFinite(part) ? part : 0);
1084
+ }
@@ -0,0 +1,10 @@
1
+ export const CLI_REQUEST_HEADERS = {
2
+ "x-flatkey-client": "cli",
3
+ };
4
+
5
+ export function withCliRequestHeaders(headers = {}) {
6
+ return {
7
+ ...headers,
8
+ ...CLI_REQUEST_HEADERS,
9
+ };
10
+ }