ide-agents 0.3.0 → 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/dist/cli.js CHANGED
@@ -3,6 +3,7 @@ import { spawn } from "node:child_process";
3
3
  import net from "node:net";
4
4
  import path from "node:path";
5
5
  import { readConfig } from "./config.js";
6
+ import { checkNpmUpdate, formatCliUpdateMessage } from "./npmUpdate.js";
6
7
  import { startServer } from "./server.js";
7
8
  function parseArgs(argv) {
8
9
  const options = {};
@@ -11,6 +12,9 @@ function parseArgs(argv) {
11
12
  if (arg === "--no-open") {
12
13
  options.noOpen = true;
13
14
  }
15
+ else if (arg === "--no-update-check") {
16
+ options.noUpdateCheck = true;
17
+ }
14
18
  else if (arg === "--port" && argv[i + 1]) {
15
19
  options.port = Number.parseInt(argv[i + 1], 10);
16
20
  i++;
@@ -59,6 +63,12 @@ async function main() {
59
63
  const requestedPort = options.port ?? config.server.port;
60
64
  const port = await findAvailablePort(requestedPort, host);
61
65
  const url = `http://${host}:${port}`;
66
+ if (!options.noUpdateCheck) {
67
+ const updateMessage = formatCliUpdateMessage(await checkNpmUpdate());
68
+ if (updateMessage) {
69
+ console.log(updateMessage);
70
+ }
71
+ }
62
72
  const app = await startServer({
63
73
  port,
64
74
  host,
@@ -0,0 +1,12 @@
1
+ export declare const NPM_PACKAGE_NAME = "ide-agents";
2
+ export interface NpmUpdateInfo {
3
+ current: string;
4
+ latest: string | null;
5
+ updateAvailable: boolean;
6
+ installCommand: string;
7
+ }
8
+ export declare function isNewerVersion(latest: string, current: string): boolean;
9
+ export declare function checkNpmUpdate(options?: {
10
+ skipCache?: boolean;
11
+ }): Promise<NpmUpdateInfo>;
12
+ export declare function formatCliUpdateMessage(info: NpmUpdateInfo): string;
@@ -0,0 +1,102 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { ensureIdeAgentsHome } from "./config.js";
4
+ import { getIdeAgentsHome } from "./paths.js";
5
+ import { PACKAGE_VERSION } from "./version.js";
6
+ export const NPM_PACKAGE_NAME = "ide-agents";
7
+ const REGISTRY_URL = `https://registry.npmjs.org/${NPM_PACKAGE_NAME}/latest`;
8
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
9
+ const FETCH_TIMEOUT_MS = 3000;
10
+ function getCachePath() {
11
+ return path.join(getIdeAgentsHome(), "npm-update-check.json");
12
+ }
13
+ function parseVersion(version) {
14
+ const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
15
+ if (!match) {
16
+ return null;
17
+ }
18
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
19
+ }
20
+ export function isNewerVersion(latest, current) {
21
+ const a = parseVersion(latest);
22
+ const b = parseVersion(current);
23
+ if (!a || !b) {
24
+ return false;
25
+ }
26
+ for (let i = 0; i < 3; i++) {
27
+ if (a[i] > b[i]) {
28
+ return true;
29
+ }
30
+ if (a[i] < b[i]) {
31
+ return false;
32
+ }
33
+ }
34
+ return false;
35
+ }
36
+ async function readCache() {
37
+ try {
38
+ const raw = await readFile(getCachePath(), "utf8");
39
+ const parsed = JSON.parse(raw);
40
+ if (typeof parsed.checkedAt !== "number" ||
41
+ (parsed.latest !== null && typeof parsed.latest !== "string")) {
42
+ return null;
43
+ }
44
+ return parsed;
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ }
50
+ async function writeCache(latest) {
51
+ await ensureIdeAgentsHome();
52
+ const cache = { checkedAt: Date.now(), latest };
53
+ await writeFile(getCachePath(), `${JSON.stringify(cache, null, 2)}\n`, "utf8");
54
+ }
55
+ async function fetchLatestVersion() {
56
+ try {
57
+ const res = await fetch(REGISTRY_URL, {
58
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
59
+ headers: { Accept: "application/json" },
60
+ });
61
+ if (!res.ok) {
62
+ return null;
63
+ }
64
+ const data = (await res.json());
65
+ return typeof data.version === "string" ? data.version : null;
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
71
+ async function resolveLatestVersion(skipCache) {
72
+ if (!skipCache) {
73
+ const cache = await readCache();
74
+ if (cache && Date.now() - cache.checkedAt < CACHE_TTL_MS) {
75
+ return cache.latest;
76
+ }
77
+ }
78
+ const latest = await fetchLatestVersion();
79
+ await writeCache(latest);
80
+ return latest;
81
+ }
82
+ export async function checkNpmUpdate(options) {
83
+ const current = PACKAGE_VERSION;
84
+ const installCommand = `npm i -g ${NPM_PACKAGE_NAME}@latest`;
85
+ const latest = await resolveLatestVersion(options?.skipCache ?? false);
86
+ const updateAvailable = latest !== null && isNewerVersion(latest, current);
87
+ return {
88
+ current,
89
+ latest,
90
+ updateAvailable,
91
+ installCommand,
92
+ };
93
+ }
94
+ export function formatCliUpdateMessage(info) {
95
+ if (!info.updateAvailable || !info.latest) {
96
+ return "";
97
+ }
98
+ return [
99
+ `ide-agents v${info.current} — доступна v${info.latest}`,
100
+ ` ${info.installCommand}`,
101
+ ].join("\n");
102
+ }
package/dist/server.js CHANGED
@@ -9,6 +9,7 @@ import { scanRepoArtifacts } from "./scan.js";
9
9
  import { getArtifactTargets } from "./targets.js";
10
10
  import { expandUserPath, getIdeAgentsHome, getRepoPath, getWebDistDir, slugFromUrl, } from "./paths.js";
11
11
  import { defaultAdapterFromIdes, getDefaultIdes } from "./ides.js";
12
+ import { checkNpmUpdate } from "./npmUpdate.js";
12
13
  import { PACKAGE_VERSION as VERSION } from "./version.js";
13
14
  export async function createServer(options) {
14
15
  const app = Fastify({ logger: false });
@@ -19,21 +20,25 @@ export async function createServer(options) {
19
20
  });
20
21
  app.get("/api/status", async () => {
21
22
  const config = await readConfig();
23
+ const npmUpdate = await checkNpmUpdate();
22
24
  return {
23
25
  home: getIdeAgentsHome(),
24
26
  port: options.port,
25
27
  version: VERSION,
28
+ npmUpdate,
26
29
  defaultProjectPath: options.launchCwd ?? null,
27
30
  ides: config.ides,
28
31
  };
29
32
  });
30
33
  app.get("/api/settings", async () => {
31
34
  const config = await readConfig();
35
+ const npmUpdate = await checkNpmUpdate();
32
36
  return {
33
37
  ides: config.ides,
34
38
  defaults: getDefaultIdes(),
35
39
  home: getIdeAgentsHome(),
36
40
  version: VERSION,
41
+ npmUpdate,
37
42
  };
38
43
  });
39
44
  app.put("/api/settings", async (request, reply) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ide-agents",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Local admin for IDE agents and skills from git repos",
5
5
  "type": "module",
6
6
  "bin": {