poltertab 1.5.0-beta.1 → 1.5.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/bin/doctor.js CHANGED
@@ -119,7 +119,7 @@ async function run(argv = []) {
119
119
  todo.push(
120
120
  `${c.red("The extension is older than the server.")} Browser commands can fail\n` +
121
121
  ` in ways that look like a missing element. Download and reload it:\n` +
122
- ` ${c.cyan(updates.EXTENSION_URL)}`,
122
+ ` ${c.cyan(updates.extensionUrl(sk.server))}`,
123
123
  );
124
124
  } else if (sk && sk.kind === "server-behind") {
125
125
  todo.push(
@@ -131,7 +131,7 @@ async function run(argv = []) {
131
131
  todo.push(
132
132
  `PolterTab ${c.bold(check.latest)} is available:\n` +
133
133
  ` ${c.cyan("npm update -g poltertab")}\n` +
134
- ` ${c.dim("then reload the extension from")} ${c.cyan(updates.EXTENSION_URL)}`,
134
+ ` ${c.dim("then reload the extension from")} ${c.cyan(updates.extensionUrl(check.latest))}`,
135
135
  );
136
136
  }
137
137
  if (!listening) {
@@ -150,7 +150,7 @@ async function run(argv = []) {
150
150
  console.log(
151
151
  `\n ${c.yellow("Nothing wrong found, but the extension has never checked in.")}\n` +
152
152
  ` ${c.dim("Install it, open a page, and run doctor again to compare versions:")}\n` +
153
- ` ${c.cyan(updates.EXTENSION_URL)}`,
153
+ ` ${c.cyan(updates.extensionUrl(own))}`,
154
154
  );
155
155
  } else {
156
156
  console.log(`\n ${c.green("Nothing to do — both halves agree and are current.")}`);
package/bin/setup.js CHANGED
@@ -24,7 +24,16 @@ const SNIPPET_SRC = path.join(PKG, "assets", "claude-md-snippet.md");
24
24
 
25
25
  // Bump to the Chrome Web Store listing once it clears review. The GitHub
26
26
  // release stays valid either way, so this is a one-line switch.
27
- const EXTENSION_URL = "https://github.com/abhinav162/poltertab/releases/latest";
27
+ //
28
+ // Pinned to the release for the version being installed, not "latest". Someone
29
+ // who installed a prerelease (npm i -g poltertab@beta) and followed a /latest
30
+ // link would get the previous stable extension, because GitHub's
31
+ // /releases/latest skips prereleases — a fresh, correctly-followed setup that
32
+ // lands in version skew.
33
+ const updates = require("../mcp-server/update-check.js");
34
+ const EXTENSION_URL = updates.extensionUrl(
35
+ require("../package.json").version,
36
+ );
28
37
 
29
38
  // Identifies our section in a CLAUDE.md we do not own. Presence means
30
39
  // "already installed" — this is the whole idempotency check for step 2.
@@ -196,7 +196,29 @@ function skew(serverVersion, extensionVersion) {
196
196
 
197
197
  // --- the one-line notice ---------------------------------------------------
198
198
 
199
- const EXTENSION_URL = "https://github.com/abhinav162/poltertab/releases/latest";
199
+ const RELEASES = "https://github.com/abhinav162/poltertab/releases";
200
+
201
+ // Which extension build to send someone to.
202
+ //
203
+ // It must match the server that drives it: mismatched halves are the exact
204
+ // failure the rest of this module exists to detect, so a link that manufactures
205
+ // one is worse than no link. GitHub's /releases/latest deliberately skips
206
+ // prereleases — so telling a 1.5.0-beta.1 install to "get the latest release"
207
+ // hands it a 1.4.0 extension, and the skew warning then fires on a fresh
208
+ // install that followed the instructions exactly. Worse, that was also the
209
+ // remediation advice printed *for* skew, so the fix re-created the fault.
210
+ //
211
+ // Ask for the release matching the version in hand. Callers pass whichever
212
+ // version is right for what they are saying: the running server for "your
213
+ // halves disagree", the version being upgraded to for "an update is available".
214
+ // /releases/latest survives only as the fallback for a build whose version we
215
+ // cannot parse — a dev checkout — where a tag URL would 404.
216
+ function extensionUrl(version) {
217
+ const v = String(version || "")
218
+ .trim()
219
+ .replace(/^v/, "");
220
+ return parse(v) ? `${RELEASES}/tag/v${v}` : `${RELEASES}/latest`;
221
+ }
200
222
 
201
223
  // Surfaced once per server process on a tool response, because it is the only
202
224
  // channel the user reliably reads: doctor and the popup both require them to
@@ -207,7 +229,7 @@ function notice({ current, latest, updateAvailable, skew: sk }) {
207
229
  parts.push(
208
230
  `The Chrome extension (${sk.extension}) is older than this server (${sk.server}) — ` +
209
231
  `browser commands may fail in ways that look like missing elements. ` +
210
- `Reload it from ${EXTENSION_URL}`,
232
+ `Reload it from ${extensionUrl(sk.server)}`,
211
233
  );
212
234
  } else if (sk && sk.kind === "server-behind") {
213
235
  parts.push(
@@ -218,7 +240,8 @@ function notice({ current, latest, updateAvailable, skew: sk }) {
218
240
  if (updateAvailable && latest) {
219
241
  parts.push(
220
242
  `PolterTab ${latest} is available (running ${current}). ` +
221
- `Update with: npm update -g poltertab && poltertab setup`,
243
+ `Update with: npm update -g poltertab && poltertab setup, ` +
244
+ `then reload the extension from ${extensionUrl(latest)}`,
222
245
  );
223
246
  }
224
247
  if (!parts.length) return null;
@@ -236,7 +259,7 @@ module.exports = {
236
259
  skew,
237
260
  notice,
238
261
  disabled,
239
- EXTENSION_URL,
262
+ extensionUrl,
240
263
  CACHE_FILE,
241
264
  STATE_FILE,
242
265
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poltertab",
3
- "version": "1.5.0-beta.1",
3
+ "version": "1.5.0",
4
4
  "description": "Let any AI assistant drive and scrape your existing Chrome profile — no headless browser, no complex setup.",
5
5
  "bin": {
6
6
  "poltertab": "./bin/poltertab.js"