jeopi-cli 16.2.18 → 16.2.20

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.
@@ -1,3 +1,25 @@
1
+ /**
2
+ * npm package that ships the CLI. Exported so the startup update notice
3
+ * (`checkForNewVersion` in main.ts) queries the same package this command
4
+ * installs — the two must never drift or the notice checks a phantom name.
5
+ */
6
+ export declare const NPM_PACKAGE = "jeopi-cli";
7
+ /**
8
+ * Official npm registry origin.
9
+ *
10
+ * Pinned across both the version check and the bun install step so the two
11
+ * agree on which catalog they are talking to. A user's bun may be pointed at
12
+ * an unofficial mirror (corporate proxy, Taobao, etc.) that lags the upstream
13
+ * registry by minutes-to-hours, in which case `getLatestRelease` would resolve
14
+ * a version the mirror has not yet replicated and the install would fail with
15
+ * `No version matching "X" found for specifier "<pkg>" (but package exists)`.
16
+ * See #1686.
17
+ */
18
+ export declare const NPM_REGISTRY = "https://registry.npmjs.org/";
19
+ interface ReleaseInfo {
20
+ tag: string;
21
+ version: string;
22
+ }
1
23
  /** Result from running the installed binary and parsing its reported version. */
2
24
  export interface InstalledVersionVerification {
3
25
  ok: boolean;
@@ -27,6 +49,21 @@ interface UpdateMethodResolutionOptions {
27
49
  miseDataDir?: string;
28
50
  }
29
51
  export declare function resolveUpdateMethodForTest(jeopiPath: string, bunBinDir: string | undefined, options?: UpdateMethodResolutionOptions): UpdateMethod;
52
+ /**
53
+ * Get the latest release info from the npm registry.
54
+ * Uses npm instead of GitHub API to avoid unauthenticated rate limiting.
55
+ *
56
+ * Exported for tests: the error contract below is what a user sees when the
57
+ * update check dies, and it must stay diagnosable.
58
+ */
59
+ export declare function getLatestRelease(): Promise<ReleaseInfo>;
60
+ /**
61
+ * Resolve the latest published {@link NPM_PACKAGE} version when it is newer
62
+ * than `currentVersion`, else `undefined`. Backs the startup update notice
63
+ * (`New version X is available. Run: jeopi update`); errors and offline
64
+ * registries resolve to `undefined` so startup never blocks on the check.
65
+ */
66
+ export declare function fetchNewerPublishedVersion(currentVersion: string): Promise<string | undefined>;
30
67
  interface BunInstallCachePruneResult {
31
68
  scannedPackages: number;
32
69
  removedEntries: number;
@@ -83,7 +120,7 @@ export declare function replaceBinaryForUpdate(options: BinaryReplacementOptions
83
120
  * (`The .node file on disk is from a different release than this loader`).
84
121
  * Listing the natives explicitly forces bun to replace them in lock-step.
85
122
  * The leaf is added only on tags the release pipeline actually publishes
86
- * ({@link SUPPORTED_NATIVE_TAGS}) so unsupported platforms still fail with
123
+ * ({@link NATIVE_LEAF_PACKAGES}) so unsupported platforms still fail with
87
124
  * the original "no matching version" message instead of `EBADPLATFORM`.
88
125
  * See #1824.
89
126
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "jeopi-cli",
4
- "version": "16.2.18",
4
+ "version": "16.2.20",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/akillness/jeopi",
7
7
  "author": "Can Boluk",
@@ -56,17 +56,17 @@
56
56
  "@agentclientprotocol/sdk": "0.25.0",
57
57
  "@babel/parser": "^7.29.7",
58
58
  "@mozilla/readability": "^0.6.0",
59
- "jeopi-hashline": "16.2.18",
60
- "jeopi-stats": "16.2.18",
61
- "jeopi-agent-core": "16.2.18",
62
- "jeopi-ai": "16.2.18",
63
- "jeopi-catalog": "16.2.18",
64
- "jeopi-mnemopi": "16.2.18",
65
- "jeopi-natives": "16.2.18",
66
- "jeopi-tui": "16.2.18",
67
- "jeopi-utils": "16.2.18",
68
- "jeopi-wire": "16.2.18",
69
- "jeopi-snapcompact": "16.2.18",
59
+ "jeopi-hashline": "16.2.20",
60
+ "jeopi-stats": "16.2.20",
61
+ "jeopi-agent-core": "16.2.20",
62
+ "jeopi-ai": "16.2.20",
63
+ "jeopi-catalog": "16.2.20",
64
+ "jeopi-mnemopi": "16.2.20",
65
+ "jeopi-natives": "16.2.20",
66
+ "jeopi-tui": "16.2.20",
67
+ "jeopi-utils": "16.2.20",
68
+ "jeopi-wire": "16.2.20",
69
+ "jeopi-snapcompact": "16.2.20",
70
70
  "@opentelemetry/api": "^1.9.1",
71
71
  "@opentelemetry/context-async-hooks": "^2.7.1",
72
72
  "@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
@@ -14,7 +14,12 @@ import { $which, APP_NAME, isEnoent, VERSION } from "jeopi-utils";
14
14
  import { theme } from "../modes/theme/theme";
15
15
 
16
16
  const REPO = "akillness/jeopi";
17
- const PACKAGE = "jeopi-cli";
17
+ /**
18
+ * npm package that ships the CLI. Exported so the startup update notice
19
+ * (`checkForNewVersion` in main.ts) queries the same package this command
20
+ * installs — the two must never drift or the notice checks a phantom name.
21
+ */
22
+ export const NPM_PACKAGE = "jeopi-cli";
18
23
  const HOMEBREW_FORMULA = "akillness/tap/jeopi";
19
24
  const MISE_TOOL = "github:akillness/jeopi";
20
25
  /**
@@ -28,10 +33,10 @@ const MISE_TOOL = "github:akillness/jeopi";
28
33
  * `No version matching "X" found for specifier "<pkg>" (but package exists)`.
29
34
  * See #1686.
30
35
  */
31
- const NPM_REGISTRY = "https://registry.npmjs.org/";
36
+ export const NPM_REGISTRY = "https://registry.npmjs.org/";
32
37
 
33
38
  /**
34
- * Core native addon package. Bumped in lock-step with {@link PACKAGE} so the
39
+ * Core native addon package. Bumped in lock-step with {@link NPM_PACKAGE} so the
35
40
  * version sentinel the loader looks up at runtime matches the `.node` on
36
41
  * disk; see {@link buildBunInstallArgs} for why this must be installed
37
42
  * explicitly rather than inherited as a transitive dependency.
@@ -39,18 +44,20 @@ const NPM_REGISTRY = "https://registry.npmjs.org/";
39
44
  const NATIVES_PACKAGE = "jeopi-natives";
40
45
 
41
46
  /**
42
- * Platform tags the release pipeline publishes as
43
- * `jeopi-natives-<tag>` leaves. Mirrors `SUPPORTED_PLATFORMS` in
44
- * `packages/natives/native/loader-state.js` and `LEAF_TARGETS` in
45
- * `packages/natives/scripts/gen-npm-packages.ts`; kept here as the local
47
+ * Platform tags the release pipeline publishes as native addon leaves, mapped
48
+ * to the npm package that carries each addon. Mirrors `SUPPORTED_PLATFORMS` in
49
+ * `packages/natives/native/loader-state.js` and `LEAF_TARGETS`/`leafPackageName`
50
+ * in `packages/natives/scripts/gen-npm-packages.ts`; kept here as the local
46
51
  * source of truth so the update path stays free of cross-package imports.
52
+ * `win32-x64` ships as `jeopi-natives-windows-x64` — the registry's name
53
+ * heuristic rejects the tag-derived name with `403 … spam detection`.
47
54
  */
48
- const SUPPORTED_NATIVE_TAGS: ReadonlySet<string> = new Set([
49
- "linux-x64",
50
- "linux-arm64",
51
- "darwin-x64",
52
- "darwin-arm64",
53
- "win32-x64",
55
+ const NATIVE_LEAF_PACKAGES: ReadonlyMap<string, string> = new Map([
56
+ ["linux-x64", "jeopi-natives-linux-x64"],
57
+ ["linux-arm64", "jeopi-natives-linux-arm64"],
58
+ ["darwin-x64", "jeopi-natives-darwin-x64"],
59
+ ["darwin-arm64", "jeopi-natives-darwin-arm64"],
60
+ ["win32-x64", "jeopi-natives-windows-x64"],
54
61
  ]);
55
62
 
56
63
  function currentNativeTag(): string {
@@ -237,11 +244,29 @@ async function resolveUpdateTarget(): Promise<UpdateTarget> {
237
244
  /**
238
245
  * Get the latest release info from the npm registry.
239
246
  * Uses npm instead of GitHub API to avoid unauthenticated rate limiting.
247
+ *
248
+ * Exported for tests: the error contract below is what a user sees when the
249
+ * update check dies, and it must stay diagnosable.
240
250
  */
241
- async function getLatestRelease(): Promise<ReleaseInfo> {
242
- const response = await fetch(`${NPM_REGISTRY}${PACKAGE}/latest`);
251
+ export async function getLatestRelease(): Promise<ReleaseInfo> {
252
+ const url = `${NPM_REGISTRY}${NPM_PACKAGE}/latest`;
253
+ const response = await fetch(url);
254
+ if (response.status === 404) {
255
+ // A 404 here means the package this build was compiled to track does not
256
+ // exist on the registry (e.g. the CLI was renamed after this build
257
+ // shipped — `jeopi` → `jeopi-cli`). Self-update can never recover from
258
+ // this, so name the phantom package and the manual escape hatch instead
259
+ // of surfacing a bare "Not Found".
260
+ throw new Error(
261
+ `Package "${NPM_PACKAGE}" was not found on ${NPM_REGISTRY} (HTTP 404). ` +
262
+ `This build's update check targets a package that is not published; ` +
263
+ `reinstall manually: bun install -g ${NPM_PACKAGE}`,
264
+ );
265
+ }
243
266
  if (!response.ok) {
244
- throw new Error(`Failed to fetch release info: ${response.statusText}`);
267
+ throw new Error(
268
+ `Failed to fetch release info for ${NPM_PACKAGE} from ${NPM_REGISTRY}: HTTP ${response.status} ${response.statusText}`,
269
+ );
245
270
  }
246
271
 
247
272
  const data = (await response.json()) as { version: string };
@@ -254,6 +279,30 @@ async function getLatestRelease(): Promise<ReleaseInfo> {
254
279
  };
255
280
  }
256
281
 
282
+ /**
283
+ * Resolve the latest published {@link NPM_PACKAGE} version when it is newer
284
+ * than `currentVersion`, else `undefined`. Backs the startup update notice
285
+ * (`New version X is available. Run: jeopi update`); errors and offline
286
+ * registries resolve to `undefined` so startup never blocks on the check.
287
+ */
288
+ export async function fetchNewerPublishedVersion(currentVersion: string): Promise<string | undefined> {
289
+ try {
290
+ const response = await fetch(`${NPM_REGISTRY}${NPM_PACKAGE}/latest`);
291
+ if (!response.ok) return undefined;
292
+
293
+ const data = (await response.json()) as { version?: string };
294
+ const latestVersion = data.version;
295
+
296
+ if (latestVersion && Bun.semver.order(latestVersion, currentVersion) > 0) {
297
+ return latestVersion;
298
+ }
299
+
300
+ return undefined;
301
+ } catch {
302
+ return undefined;
303
+ }
304
+ }
305
+
257
306
  /**
258
307
  * Compare semver versions. Returns:
259
308
  * - negative if a < b
@@ -727,7 +776,7 @@ export async function replaceBinaryForUpdate(options: BinaryReplacementOptions):
727
776
  * (`The .node file on disk is from a different release than this loader`).
728
777
  * Listing the natives explicitly forces bun to replace them in lock-step.
729
778
  * The leaf is added only on tags the release pipeline actually publishes
730
- * ({@link SUPPORTED_NATIVE_TAGS}) so unsupported platforms still fail with
779
+ * ({@link NATIVE_LEAF_PACKAGES}) so unsupported platforms still fail with
731
780
  * the original "no matching version" message instead of `EBADPLATFORM`.
732
781
  * See #1824.
733
782
  */
@@ -737,11 +786,12 @@ export function buildBunInstallArgs(expectedVersion: string, nativeTag: string =
737
786
  "-g",
738
787
  "--no-cache",
739
788
  `--registry=${NPM_REGISTRY}`,
740
- `${PACKAGE}@${expectedVersion}`,
789
+ `${NPM_PACKAGE}@${expectedVersion}`,
741
790
  `${NATIVES_PACKAGE}@${expectedVersion}`,
742
791
  ];
743
- if (SUPPORTED_NATIVE_TAGS.has(nativeTag)) {
744
- args.push(`${NATIVES_PACKAGE}-${nativeTag}@${expectedVersion}`);
792
+ const leafPackage = NATIVE_LEAF_PACKAGES.get(nativeTag);
793
+ if (leafPackage) {
794
+ args.push(`${leafPackage}@${expectedVersion}`);
745
795
  }
746
796
  return args;
747
797
  }