@promptedgames/cli 0.1.1 → 0.1.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/dist/index.js +58 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { Command, Option } from "commander";
|
|
5
5
|
import Conf from "conf";
|
|
6
6
|
import crypto from "crypto";
|
|
7
|
+
import { execSync } from "child_process";
|
|
7
8
|
import fs from "fs";
|
|
8
9
|
import { createRequire } from "module";
|
|
9
10
|
import path from "path";
|
|
@@ -863,6 +864,8 @@ var require2 = createRequire(import.meta.url);
|
|
|
863
864
|
var pkg = require2("../package.json");
|
|
864
865
|
var config = new Conf({ projectName: "prompted" });
|
|
865
866
|
var DEFAULT_SERVER = "https://prompted.games";
|
|
867
|
+
var CLI_USER_AGENT = `prompted-cli/${pkg.version}`;
|
|
868
|
+
var CLI_UPDATE_COMMAND = `npm i -g ${pkg.name}`;
|
|
866
869
|
function getServer() {
|
|
867
870
|
return program.opts().host ?? process.env.PROMPTED_SERVER ?? DEFAULT_SERVER;
|
|
868
871
|
}
|
|
@@ -913,6 +916,51 @@ function fail(message, exitCode = 1) {
|
|
|
913
916
|
console.error(JSON.stringify({ error: message }));
|
|
914
917
|
process.exit(exitCode);
|
|
915
918
|
}
|
|
919
|
+
function withUserAgent(headers) {
|
|
920
|
+
return { ...headers, "User-Agent": CLI_USER_AGENT };
|
|
921
|
+
}
|
|
922
|
+
function shouldPromptForUpdate() {
|
|
923
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY && !process.env.CI);
|
|
924
|
+
}
|
|
925
|
+
function promptYesNo(question) {
|
|
926
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
927
|
+
return new Promise((resolve) => {
|
|
928
|
+
rl.question(question, (answer) => {
|
|
929
|
+
rl.close();
|
|
930
|
+
resolve(answer.trim().toLowerCase().startsWith("y"));
|
|
931
|
+
});
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
function runCliUpdate() {
|
|
935
|
+
try {
|
|
936
|
+
execSync(CLI_UPDATE_COMMAND, { stdio: "inherit" });
|
|
937
|
+
return true;
|
|
938
|
+
} catch {
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
async function enforceMinimumCliVersion(status, body) {
|
|
943
|
+
if (status !== 426 || typeof body !== "object" || body === null) return;
|
|
944
|
+
const err = body;
|
|
945
|
+
if (err.error !== "cli_version_too_old") return;
|
|
946
|
+
const message = typeof err.message === "string" && err.message.length > 0 ? err.message : "Your Prompted CLI version is too old. Please update.";
|
|
947
|
+
const minimumVersion = typeof err.minimumVersion === "string" && err.minimumVersion.length > 0 ? err.minimumVersion : "unknown";
|
|
948
|
+
const currentVersion = typeof err.currentVersion === "string" && err.currentVersion.length > 0 ? err.currentVersion : pkg.version;
|
|
949
|
+
const details = `Current version: ${currentVersion}. Minimum required: ${minimumVersion}.`;
|
|
950
|
+
if (shouldPromptForUpdate()) {
|
|
951
|
+
console.error(message);
|
|
952
|
+
console.error(details);
|
|
953
|
+
const shouldUpdate = await promptYesNo(`Run \`${CLI_UPDATE_COMMAND}\` now? (y/n) `);
|
|
954
|
+
if (shouldUpdate) {
|
|
955
|
+
console.error(`Running: ${CLI_UPDATE_COMMAND}`);
|
|
956
|
+
if (runCliUpdate()) {
|
|
957
|
+
fail("CLI updated successfully. Please rerun your previous command.");
|
|
958
|
+
}
|
|
959
|
+
fail(`Automatic update failed. Run \`${CLI_UPDATE_COMMAND}\` manually.`);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
fail(`${message} ${details} Update with: ${CLI_UPDATE_COMMAND}`);
|
|
963
|
+
}
|
|
916
964
|
function sleep(ms) {
|
|
917
965
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
918
966
|
}
|
|
@@ -929,6 +977,7 @@ async function request(path2, options) {
|
|
|
929
977
|
const headers = {
|
|
930
978
|
...options?.headers ?? {}
|
|
931
979
|
};
|
|
980
|
+
headers["User-Agent"] = CLI_USER_AGENT;
|
|
932
981
|
if (token) {
|
|
933
982
|
headers["Authorization"] = `Bearer ${token}`;
|
|
934
983
|
} else if (userId) {
|
|
@@ -942,6 +991,7 @@ async function request(path2, options) {
|
|
|
942
991
|
if (!res.ok) fail(`Request failed: ${res.status}`);
|
|
943
992
|
fail("Invalid JSON response");
|
|
944
993
|
}
|
|
994
|
+
await enforceMinimumCliVersion(res.status, body);
|
|
945
995
|
if (res.status === 401) {
|
|
946
996
|
fail("Authentication failed. Run `prompted login` to sign in again.");
|
|
947
997
|
}
|
|
@@ -958,6 +1008,7 @@ async function requestMayFail(path2, options) {
|
|
|
958
1008
|
const headers = {
|
|
959
1009
|
...options?.headers ?? {}
|
|
960
1010
|
};
|
|
1011
|
+
headers["User-Agent"] = CLI_USER_AGENT;
|
|
961
1012
|
if (token) {
|
|
962
1013
|
headers["Authorization"] = `Bearer ${token}`;
|
|
963
1014
|
} else if (userId) {
|
|
@@ -970,6 +1021,7 @@ async function requestMayFail(path2, options) {
|
|
|
970
1021
|
} catch {
|
|
971
1022
|
body = null;
|
|
972
1023
|
}
|
|
1024
|
+
await enforceMinimumCliVersion(res.status, body);
|
|
973
1025
|
if (!res.ok) {
|
|
974
1026
|
const msg = body?.error ?? `Request failed: ${res.status}`;
|
|
975
1027
|
return { ok: false, status: res.status, data: body, error: msg };
|
|
@@ -1073,10 +1125,12 @@ program.command("login").description("Store auth credentials or start device log
|
|
|
1073
1125
|
const clientId = "prompted-cli";
|
|
1074
1126
|
const startRes = await fetch(`${getServer()}/api/auth/device/code`, {
|
|
1075
1127
|
method: "POST",
|
|
1076
|
-
headers: { "Content-Type": "application/json" },
|
|
1128
|
+
headers: withUserAgent({ "Content-Type": "application/json" }),
|
|
1077
1129
|
body: JSON.stringify({ client_id: clientId })
|
|
1078
1130
|
});
|
|
1079
1131
|
if (!startRes.ok) {
|
|
1132
|
+
const err = await startRes.json().catch(() => null);
|
|
1133
|
+
await enforceMinimumCliVersion(startRes.status, err);
|
|
1080
1134
|
fail("Failed to start device login");
|
|
1081
1135
|
}
|
|
1082
1136
|
const start = await startRes.json();
|
|
@@ -1098,7 +1152,7 @@ program.command("login").description("Store auth credentials or start device log
|
|
|
1098
1152
|
try {
|
|
1099
1153
|
response = await fetch(`${getServer()}/api/auth/device/token`, {
|
|
1100
1154
|
method: "POST",
|
|
1101
|
-
headers: { "Content-Type": "application/json" },
|
|
1155
|
+
headers: withUserAgent({ "Content-Type": "application/json" }),
|
|
1102
1156
|
body: JSON.stringify({
|
|
1103
1157
|
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
1104
1158
|
device_code: start.device_code,
|
|
@@ -1106,6 +1160,7 @@ program.command("login").description("Store auth credentials or start device log
|
|
|
1106
1160
|
})
|
|
1107
1161
|
});
|
|
1108
1162
|
body = await response.json().catch(() => ({}));
|
|
1163
|
+
await enforceMinimumCliVersion(response.status, body);
|
|
1109
1164
|
networkRetries = 0;
|
|
1110
1165
|
} catch {
|
|
1111
1166
|
networkRetries += 1;
|
|
@@ -1118,7 +1173,7 @@ program.command("login").description("Store auth credentials or start device log
|
|
|
1118
1173
|
config.set("token", body.access_token);
|
|
1119
1174
|
try {
|
|
1120
1175
|
const meRes = await fetch(`${getServer()}/api/me`, {
|
|
1121
|
-
headers: { "Authorization": `Bearer ${body.access_token}` }
|
|
1176
|
+
headers: withUserAgent({ "Authorization": `Bearer ${body.access_token}` })
|
|
1122
1177
|
});
|
|
1123
1178
|
if (meRes.ok) {
|
|
1124
1179
|
const me = await meRes.json();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promptedgames/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"packageManager": "pnpm@10.33.0",
|
|
5
5
|
"description": "CLI for playing games on the Prompted platform. Build AI agents that play poker, Secret Hitler, Coup, Skull, and Liar's Dice.",
|
|
6
6
|
"type": "module",
|