agendex-cli 0.15.0 → 0.16.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/dist/cli.js +236 -23
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1058,10 +1058,10 @@ var init_cleanup = __esm(() => {
|
|
|
1058
1058
|
});
|
|
1059
1059
|
|
|
1060
1060
|
// src/cli.ts
|
|
1061
|
-
import { spawn as
|
|
1061
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
1062
1062
|
import { existsSync as existsSync11, statSync as statSync2, writeSync } from "node:fs";
|
|
1063
|
-
import { resolve as
|
|
1064
|
-
import { fileURLToPath as
|
|
1063
|
+
import { resolve as resolve8 } from "node:path";
|
|
1064
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
1065
1065
|
|
|
1066
1066
|
// ../shared/src/adapters/catalog.ts
|
|
1067
1067
|
import { homedir as homedir7 } from "node:os";
|
|
@@ -3946,6 +3946,7 @@ async function refreshToken(currentToken, convexUrl) {
|
|
|
3946
3946
|
return null;
|
|
3947
3947
|
return { token: body.token, expiresAt: body.expiresAt ?? 0 };
|
|
3948
3948
|
}
|
|
3949
|
+
var REQUEST_TIMEOUT_MS2 = Number.parseInt(process.env.AGENDEX_HTTP_TIMEOUT_MS ?? "", 10) || 1e4;
|
|
3949
3950
|
function requestText(urlString, options) {
|
|
3950
3951
|
const url = new URL(urlString);
|
|
3951
3952
|
const request = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
@@ -3957,7 +3958,8 @@ function requestText(urlString, options) {
|
|
|
3957
3958
|
const req = request(url, {
|
|
3958
3959
|
agent: false,
|
|
3959
3960
|
headers,
|
|
3960
|
-
method: options.method
|
|
3961
|
+
method: options.method,
|
|
3962
|
+
timeout: REQUEST_TIMEOUT_MS2
|
|
3961
3963
|
}, (res) => {
|
|
3962
3964
|
let body = "";
|
|
3963
3965
|
res.setEncoding("utf8");
|
|
@@ -3973,6 +3975,9 @@ function requestText(urlString, options) {
|
|
|
3973
3975
|
res.on("error", reject);
|
|
3974
3976
|
});
|
|
3975
3977
|
req.on("error", reject);
|
|
3978
|
+
req.on("timeout", () => {
|
|
3979
|
+
req.destroy(new Error(`Request to ${url.host} timed out after ${REQUEST_TIMEOUT_MS2}ms`));
|
|
3980
|
+
});
|
|
3976
3981
|
if (options.body) {
|
|
3977
3982
|
req.write(options.body);
|
|
3978
3983
|
}
|
|
@@ -4780,6 +4785,12 @@ async function syncAll(force = false) {
|
|
|
4780
4785
|
console.log(`[agendex] Sync complete: ${synced} synced${lowValueSuffix}, ${skipped} unchanged, ${failed} failed`);
|
|
4781
4786
|
}
|
|
4782
4787
|
|
|
4788
|
+
// src/upgrade.ts
|
|
4789
|
+
import { spawn as spawn3, spawnSync } from "node:child_process";
|
|
4790
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
4791
|
+
import { dirname as dirname4, resolve as resolve7, sep as sep4 } from "node:path";
|
|
4792
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4793
|
+
|
|
4783
4794
|
// src/version.ts
|
|
4784
4795
|
import { existsSync as existsSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "node:fs";
|
|
4785
4796
|
import { tmpdir } from "node:os";
|
|
@@ -4787,7 +4798,7 @@ import { join as join14 } from "node:path";
|
|
|
4787
4798
|
// package.json
|
|
4788
4799
|
var package_default = {
|
|
4789
4800
|
name: "agendex-cli",
|
|
4790
|
-
version: "0.
|
|
4801
|
+
version: "0.16.0",
|
|
4791
4802
|
description: "Agendex CLI for login, sync, and daemon workflows",
|
|
4792
4803
|
homepage: "https://github.com/Tyru5/Agendex#readme",
|
|
4793
4804
|
repository: {
|
|
@@ -4851,11 +4862,13 @@ function writeCache(result) {
|
|
|
4851
4862
|
writeFileSync5(CACHE_FILE, JSON.stringify({ result, ts: Date.now() }));
|
|
4852
4863
|
} catch {}
|
|
4853
4864
|
}
|
|
4854
|
-
async function checkForUpdate() {
|
|
4865
|
+
async function checkForUpdate(options = {}) {
|
|
4855
4866
|
const current = CLI_VERSION;
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4867
|
+
if (!options.forceRefresh) {
|
|
4868
|
+
const cached = readCache(current);
|
|
4869
|
+
if (cached)
|
|
4870
|
+
return cached;
|
|
4871
|
+
}
|
|
4859
4872
|
try {
|
|
4860
4873
|
const controller = new AbortController;
|
|
4861
4874
|
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
@@ -4863,21 +4876,27 @@ async function checkForUpdate() {
|
|
|
4863
4876
|
signal: controller.signal
|
|
4864
4877
|
}).finally(() => clearTimeout(timeout));
|
|
4865
4878
|
if (!res.ok) {
|
|
4866
|
-
return { updateAvailable: false, current, latest: current };
|
|
4879
|
+
return { checked: false, updateAvailable: false, current, latest: current };
|
|
4867
4880
|
}
|
|
4868
4881
|
const data = await res.json();
|
|
4869
4882
|
const latest = data.version;
|
|
4870
|
-
const result = {
|
|
4883
|
+
const result = {
|
|
4884
|
+
checked: true,
|
|
4885
|
+
updateAvailable: isNewer(latest, current),
|
|
4886
|
+
current,
|
|
4887
|
+
latest
|
|
4888
|
+
};
|
|
4871
4889
|
writeCache(result);
|
|
4872
4890
|
return result;
|
|
4873
4891
|
} catch {
|
|
4874
|
-
return { updateAvailable: false, current, latest: current };
|
|
4892
|
+
return { checked: false, updateAvailable: false, current, latest: current };
|
|
4875
4893
|
}
|
|
4876
4894
|
}
|
|
4877
4895
|
function normalizeResult(result, current) {
|
|
4878
4896
|
if (typeof result.latest !== "string")
|
|
4879
4897
|
return null;
|
|
4880
4898
|
return {
|
|
4899
|
+
checked: true,
|
|
4881
4900
|
updateAvailable: isNewer(result.latest, current),
|
|
4882
4901
|
current,
|
|
4883
4902
|
latest: result.latest
|
|
@@ -4897,6 +4916,195 @@ function isNewer(latest, current) {
|
|
|
4897
4916
|
return false;
|
|
4898
4917
|
}
|
|
4899
4918
|
|
|
4919
|
+
// src/upgrade.ts
|
|
4920
|
+
var PACKAGE_NAME = "agendex-cli";
|
|
4921
|
+
var moduleDir = dirname4(fileURLToPath2(import.meta.url));
|
|
4922
|
+
function getPackageRoot() {
|
|
4923
|
+
try {
|
|
4924
|
+
return realpathSync2(resolve7(moduleDir, ".."));
|
|
4925
|
+
} catch {
|
|
4926
|
+
return resolve7(moduleDir, "..");
|
|
4927
|
+
}
|
|
4928
|
+
}
|
|
4929
|
+
function detectPackageManager(packageRoot) {
|
|
4930
|
+
const userAgent = process.env.npm_config_user_agent ?? "";
|
|
4931
|
+
const execpath = process.env.npm_execpath ?? "";
|
|
4932
|
+
if (userAgent.startsWith("bun/") || execpath.includes("bun"))
|
|
4933
|
+
return "bun";
|
|
4934
|
+
if (userAgent.startsWith("pnpm/") || execpath.includes("pnpm"))
|
|
4935
|
+
return "pnpm";
|
|
4936
|
+
if (userAgent.startsWith("yarn/") || execpath.includes("yarn"))
|
|
4937
|
+
return "yarn";
|
|
4938
|
+
const lower = packageRoot.toLowerCase();
|
|
4939
|
+
if (lower.includes(`${sep4}.bun${sep4}`) || lower.includes("/.bun/"))
|
|
4940
|
+
return "bun";
|
|
4941
|
+
if (lower.includes(`${sep4}pnpm${sep4}`) || lower.includes("/pnpm/"))
|
|
4942
|
+
return "pnpm";
|
|
4943
|
+
if (lower.includes(`${sep4}yarn${sep4}`) || lower.includes("/yarn/"))
|
|
4944
|
+
return "yarn";
|
|
4945
|
+
if (typeof globalThis.Bun !== "undefined" || process.versions.bun) {
|
|
4946
|
+
return "bun";
|
|
4947
|
+
}
|
|
4948
|
+
return "npm";
|
|
4949
|
+
}
|
|
4950
|
+
function readYarnVersion() {
|
|
4951
|
+
const result = spawnSync("yarn", ["--version"], {
|
|
4952
|
+
encoding: "utf8",
|
|
4953
|
+
shell: process.platform === "win32"
|
|
4954
|
+
});
|
|
4955
|
+
if (result.error || result.status !== 0)
|
|
4956
|
+
return null;
|
|
4957
|
+
return result.stdout.trim() || null;
|
|
4958
|
+
}
|
|
4959
|
+
function parseMajorVersion(version) {
|
|
4960
|
+
const match = version.match(/^(\d+)/);
|
|
4961
|
+
if (!match)
|
|
4962
|
+
return null;
|
|
4963
|
+
const major = Number(match[1]);
|
|
4964
|
+
return Number.isFinite(major) ? major : null;
|
|
4965
|
+
}
|
|
4966
|
+
function buildGlobalInstallCommand(pm) {
|
|
4967
|
+
const pkgSpec = `${PACKAGE_NAME}@latest`;
|
|
4968
|
+
switch (pm) {
|
|
4969
|
+
case "bun":
|
|
4970
|
+
return {
|
|
4971
|
+
supported: true,
|
|
4972
|
+
command: { bin: "bun", args: ["add", "-g", pkgSpec], display: `bun add -g ${pkgSpec}` }
|
|
4973
|
+
};
|
|
4974
|
+
case "pnpm":
|
|
4975
|
+
return {
|
|
4976
|
+
supported: true,
|
|
4977
|
+
command: {
|
|
4978
|
+
bin: "pnpm",
|
|
4979
|
+
args: ["add", "-g", pkgSpec],
|
|
4980
|
+
display: `pnpm add -g ${pkgSpec}`
|
|
4981
|
+
}
|
|
4982
|
+
};
|
|
4983
|
+
case "yarn": {
|
|
4984
|
+
const yarnVersion = readYarnVersion();
|
|
4985
|
+
const yarnMajorVersion = yarnVersion ? parseMajorVersion(yarnVersion) : null;
|
|
4986
|
+
if (yarnMajorVersion !== null && yarnMajorVersion >= 2) {
|
|
4987
|
+
return {
|
|
4988
|
+
supported: false,
|
|
4989
|
+
reason: `automatic upgrade with Yarn only supports Yarn Classic (v1); detected Yarn v${yarnVersion}.`,
|
|
4990
|
+
manualCommand: `npm install -g ${pkgSpec}`
|
|
4991
|
+
};
|
|
4992
|
+
}
|
|
4993
|
+
return {
|
|
4994
|
+
supported: true,
|
|
4995
|
+
command: {
|
|
4996
|
+
bin: "yarn",
|
|
4997
|
+
args: ["global", "add", pkgSpec],
|
|
4998
|
+
display: `yarn global add ${pkgSpec}`
|
|
4999
|
+
}
|
|
5000
|
+
};
|
|
5001
|
+
}
|
|
5002
|
+
default:
|
|
5003
|
+
return {
|
|
5004
|
+
supported: true,
|
|
5005
|
+
command: {
|
|
5006
|
+
bin: "npm",
|
|
5007
|
+
args: ["install", "-g", pkgSpec],
|
|
5008
|
+
display: `npm install -g ${pkgSpec}`
|
|
5009
|
+
}
|
|
5010
|
+
};
|
|
5011
|
+
}
|
|
5012
|
+
}
|
|
5013
|
+
function isLikelyGlobalInstall(packageRoot) {
|
|
5014
|
+
const normalized = packageRoot.replace(/\\/g, "/");
|
|
5015
|
+
if (!normalized.includes("/node_modules/")) {
|
|
5016
|
+
return false;
|
|
5017
|
+
}
|
|
5018
|
+
const globalMarkers = [
|
|
5019
|
+
"/lib/node_modules/",
|
|
5020
|
+
"/pnpm/global/",
|
|
5021
|
+
"/yarn/global/",
|
|
5022
|
+
"/.bun/install/global/",
|
|
5023
|
+
"/.bun/install/",
|
|
5024
|
+
"/.config/yarn/global/",
|
|
5025
|
+
"/AppData/Roaming/npm/",
|
|
5026
|
+
"/AppData/Local/Yarn/",
|
|
5027
|
+
"/AppData/Local/pnpm/"
|
|
5028
|
+
];
|
|
5029
|
+
return globalMarkers.some((marker) => normalized.includes(marker));
|
|
5030
|
+
}
|
|
5031
|
+
async function runUpgrade(opts) {
|
|
5032
|
+
const packageRoot = getPackageRoot();
|
|
5033
|
+
const pm = detectPackageManager(packageRoot);
|
|
5034
|
+
const isGlobal = isLikelyGlobalInstall(packageRoot);
|
|
5035
|
+
if (!isGlobal) {
|
|
5036
|
+
process.stderr.write(`[agendex] this CLI appears to be running from a local checkout or linked install:
|
|
5037
|
+
` + `[agendex] ${packageRoot}
|
|
5038
|
+
` + `[agendex] automatic upgrade only supports global installs.
|
|
5039
|
+
` + `[agendex] reinstall globally (e.g. \`npm install -g ${PACKAGE_NAME}@latest\`) or update the source repo manually.
|
|
5040
|
+
`);
|
|
5041
|
+
return 1;
|
|
5042
|
+
}
|
|
5043
|
+
const { checked, updateAvailable, current, latest } = await checkForUpdate({
|
|
5044
|
+
forceRefresh: true
|
|
5045
|
+
});
|
|
5046
|
+
if (checked && !updateAvailable && !opts.force) {
|
|
5047
|
+
process.stdout.write(`[agendex] already up to date (v${current})
|
|
5048
|
+
`);
|
|
5049
|
+
return 0;
|
|
5050
|
+
}
|
|
5051
|
+
if (!checked) {
|
|
5052
|
+
process.stderr.write(`[agendex] could not verify the latest version; attempting upgrade anyway...
|
|
5053
|
+
`);
|
|
5054
|
+
}
|
|
5055
|
+
const commandResult = buildGlobalInstallCommand(pm);
|
|
5056
|
+
if (!commandResult.supported) {
|
|
5057
|
+
process.stderr.write(`[agendex] ${commandResult.reason}
|
|
5058
|
+
`);
|
|
5059
|
+
process.stderr.write(`[agendex] install the latest CLI manually, e.g. \`${commandResult.manualCommand}\`.
|
|
5060
|
+
`);
|
|
5061
|
+
return 1;
|
|
5062
|
+
}
|
|
5063
|
+
const cmd = commandResult.command;
|
|
5064
|
+
if (checked && updateAvailable) {
|
|
5065
|
+
process.stdout.write(`[agendex] upgrading: v${current} → v${latest}
|
|
5066
|
+
`);
|
|
5067
|
+
} else if (opts.force) {
|
|
5068
|
+
process.stdout.write(`[agendex] reinstalling v${CLI_VERSION} (forced)
|
|
5069
|
+
`);
|
|
5070
|
+
}
|
|
5071
|
+
process.stdout.write(`[agendex] running: ${cmd.display}
|
|
5072
|
+
`);
|
|
5073
|
+
return await new Promise((resolveExit) => {
|
|
5074
|
+
const child = spawn3(cmd.bin, cmd.args, {
|
|
5075
|
+
stdio: "inherit",
|
|
5076
|
+
shell: process.platform === "win32",
|
|
5077
|
+
env: process.env
|
|
5078
|
+
});
|
|
5079
|
+
let didError = false;
|
|
5080
|
+
child.on("error", (err) => {
|
|
5081
|
+
didError = true;
|
|
5082
|
+
process.stderr.write(`[agendex] failed to run ${cmd.bin}: ${err instanceof Error ? err.message : String(err)}
|
|
5083
|
+
`);
|
|
5084
|
+
process.stderr.write(`[agendex] you can run it manually: ${cmd.display}
|
|
5085
|
+
`);
|
|
5086
|
+
resolveExit(1);
|
|
5087
|
+
});
|
|
5088
|
+
child.on("close", (code) => {
|
|
5089
|
+
if (didError)
|
|
5090
|
+
return;
|
|
5091
|
+
if (code === 0) {
|
|
5092
|
+
process.stdout.write(`[agendex] upgrade complete.
|
|
5093
|
+
`);
|
|
5094
|
+
process.stdout.write(`[agendex] note: if the daemon is running, restart it: \`agendex stop && agendex start\`
|
|
5095
|
+
`);
|
|
5096
|
+
resolveExit(0);
|
|
5097
|
+
return;
|
|
5098
|
+
}
|
|
5099
|
+
process.stderr.write(`[agendex] upgrade failed with exit code ${code ?? "unknown"}
|
|
5100
|
+
`);
|
|
5101
|
+
process.stderr.write(`[agendex] you can run it manually: ${cmd.display}
|
|
5102
|
+
`);
|
|
5103
|
+
resolveExit(code ?? 1);
|
|
5104
|
+
});
|
|
5105
|
+
});
|
|
5106
|
+
}
|
|
5107
|
+
|
|
4900
5108
|
// src/web.ts
|
|
4901
5109
|
async function openAgendexWeb(siteUrlOverride) {
|
|
4902
5110
|
const base = siteUrlOverride ?? getDefaultSiteUrl();
|
|
@@ -4934,7 +5142,7 @@ function firstCommandToken(argv) {
|
|
|
4934
5142
|
return;
|
|
4935
5143
|
}
|
|
4936
5144
|
var command = firstCommandToken(args) ?? "start";
|
|
4937
|
-
var cliEntry =
|
|
5145
|
+
var cliEntry = resolve8(process.argv[1] ?? fileURLToPath3(import.meta.url));
|
|
4938
5146
|
async function main() {
|
|
4939
5147
|
const isInternal = args.includes("--daemon") || args.includes("--worker");
|
|
4940
5148
|
if (command === "--version" || command === "-v") {
|
|
@@ -4952,16 +5160,16 @@ async function main() {
|
|
|
4952
5160
|
"add-dir",
|
|
4953
5161
|
"remove-dir",
|
|
4954
5162
|
"list-dirs",
|
|
5163
|
+
"upgrade",
|
|
4955
5164
|
"help",
|
|
4956
5165
|
"--help",
|
|
4957
5166
|
"-h"
|
|
4958
5167
|
].includes(command);
|
|
4959
5168
|
if (!isInternal && !isPassthrough) {
|
|
4960
|
-
const { updateAvailable, current, latest } = await checkForUpdate();
|
|
4961
|
-
if (updateAvailable) {
|
|
4962
|
-
writeStderr(`[agendex] update
|
|
4963
|
-
writeStderr(`[agendex] run:
|
|
4964
|
-
return 1;
|
|
5169
|
+
const { checked, updateAvailable, current, latest } = await checkForUpdate();
|
|
5170
|
+
if (checked && updateAvailable) {
|
|
5171
|
+
writeStderr(`[agendex] update available: v${current} → v${latest}`);
|
|
5172
|
+
writeStderr(`[agendex] run: agendex upgrade`);
|
|
4965
5173
|
}
|
|
4966
5174
|
}
|
|
4967
5175
|
switch (command) {
|
|
@@ -5000,7 +5208,7 @@ async function main() {
|
|
|
5000
5208
|
const daemonArgs = [cliEntry, "start", "--daemon"];
|
|
5001
5209
|
if (devFlag)
|
|
5002
5210
|
daemonArgs.push("--dev");
|
|
5003
|
-
const child =
|
|
5211
|
+
const child = spawn4(process.execPath, daemonArgs, {
|
|
5004
5212
|
detached: true,
|
|
5005
5213
|
stdio: "ignore",
|
|
5006
5214
|
env: { ...process.env, ...devFlag ? { AGENDEX_DEV: "1" } : {} }
|
|
@@ -5153,7 +5361,7 @@ async function main() {
|
|
|
5153
5361
|
const { request } = await import("node:http");
|
|
5154
5362
|
const body = JSON.stringify({ path: resolved });
|
|
5155
5363
|
try {
|
|
5156
|
-
const res = await new Promise((
|
|
5364
|
+
const res = await new Promise((resolve9, reject) => {
|
|
5157
5365
|
const req = request(`http://localhost:${port}/api/v1/plan-sources`, {
|
|
5158
5366
|
method: "POST",
|
|
5159
5367
|
headers: {
|
|
@@ -5167,7 +5375,7 @@ async function main() {
|
|
|
5167
5375
|
res2.on("data", (chunk) => {
|
|
5168
5376
|
data += chunk;
|
|
5169
5377
|
});
|
|
5170
|
-
res2.on("end", () =>
|
|
5378
|
+
res2.on("end", () => resolve9({ status: res2.statusCode ?? 0, body: data }));
|
|
5171
5379
|
res2.on("error", reject);
|
|
5172
5380
|
});
|
|
5173
5381
|
req.on("error", reject);
|
|
@@ -5295,6 +5503,9 @@ async function main() {
|
|
|
5295
5503
|
}
|
|
5296
5504
|
return 0;
|
|
5297
5505
|
}
|
|
5506
|
+
case "upgrade": {
|
|
5507
|
+
return await runUpgrade({ force: args.includes("--force") });
|
|
5508
|
+
}
|
|
5298
5509
|
case "help":
|
|
5299
5510
|
case "--help":
|
|
5300
5511
|
case "-h": {
|
|
@@ -5321,6 +5532,8 @@ Usage:
|
|
|
5321
5532
|
agendex cleanup Interactively remove cloud daemons
|
|
5322
5533
|
agendex cleanup --stale Auto-remove all stale daemons
|
|
5323
5534
|
agendex status Show current config state + daemon status
|
|
5535
|
+
agendex upgrade Upgrade the globally installed CLI to the latest version
|
|
5536
|
+
agendex upgrade --force Reinstall latest even if already up to date
|
|
5324
5537
|
agendex help Show this help message
|
|
5325
5538
|
agendex --version Print CLI version
|
|
5326
5539
|
agendex -v Print CLI version
|
|
@@ -5349,13 +5562,13 @@ function flushStream(stream) {
|
|
|
5349
5562
|
if (stream.destroyed || !stream.writable) {
|
|
5350
5563
|
return Promise.resolve();
|
|
5351
5564
|
}
|
|
5352
|
-
return new Promise((
|
|
5565
|
+
return new Promise((resolve9, reject) => {
|
|
5353
5566
|
stream.write("", (error) => {
|
|
5354
5567
|
if (error) {
|
|
5355
5568
|
reject(error);
|
|
5356
5569
|
return;
|
|
5357
5570
|
}
|
|
5358
|
-
|
|
5571
|
+
resolve9();
|
|
5359
5572
|
});
|
|
5360
5573
|
});
|
|
5361
5574
|
}
|