probe-research 0.10.0 → 0.10.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/bin/probe-research.js +59 -5
- package/package.json +5 -2
package/bin/probe-research.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* there is nothing here that can drift from the CLI's behaviour.
|
|
12
12
|
*
|
|
13
13
|
* Resolution order, best first:
|
|
14
|
-
* 1. `probe`
|
|
14
|
+
* 1. `probe` on PATH AND new enough -> exec it (the common re-run case)
|
|
15
15
|
* 2. `uv` -> uvx, no install, no state left behind
|
|
16
16
|
* 3. `pipx` -> isolated install
|
|
17
17
|
* 4. bootstrap uv, then uvx -> the from-zero path
|
|
@@ -26,8 +26,48 @@ const { spawnSync } = require("node:child_process");
|
|
|
26
26
|
const os = require("node:os");
|
|
27
27
|
|
|
28
28
|
const DIST = "probe-research";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The minimum CLI version this launcher needs — NOT this package's own version.
|
|
32
|
+
*
|
|
33
|
+
* npm and PyPI release INDEPENDENTLY. This package can take a launcher-only
|
|
34
|
+
* patch (as 0.10.1 did) with no corresponding CLI release, so pinning
|
|
35
|
+
* `probe-research==<our version>` resolves to a PyPI version that does not
|
|
36
|
+
* exist. That is exactly how 0.10.1 shipped broken.
|
|
37
|
+
*
|
|
38
|
+
* Bump this only when the launcher starts depending on a NEW CLI feature.
|
|
39
|
+
* 0.10.0 is the release that introduced `probe wizard`.
|
|
40
|
+
*/
|
|
41
|
+
const MIN_CLI = "0.10.0";
|
|
29
42
|
const UV_INSTALL = "curl -LsSf https://astral.sh/uv/install.sh | sh";
|
|
30
43
|
|
|
44
|
+
/** Compare dotted numeric versions. Returns true when `a` >= `b`. */
|
|
45
|
+
function atLeast(a, b) {
|
|
46
|
+
const pa = String(a).split(".").map((n) => parseInt(n, 10) || 0);
|
|
47
|
+
const pb = String(b).split(".").map((n) => parseInt(n, 10) || 0);
|
|
48
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
49
|
+
const x = pa[i] || 0;
|
|
50
|
+
const y = pb[i] || 0;
|
|
51
|
+
if (x !== y) return x > y;
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The version of an existing `probe`, or null if it cannot be determined.
|
|
58
|
+
*
|
|
59
|
+
* Existence is NOT enough. Every current user already has some `probe`, and
|
|
60
|
+
* they are exactly the people most likely to run this command — handing off to
|
|
61
|
+
* whatever ancient build happens to be on PATH gives them a CLI with none of
|
|
62
|
+
* the wizard in it, which is precisely the bug this check exists to stop.
|
|
63
|
+
*/
|
|
64
|
+
function installedVersion() {
|
|
65
|
+
const r = spawnSync("probe", ["--version"], { encoding: "utf8", shell: false });
|
|
66
|
+
if (r.status !== 0 || !r.stdout) return null;
|
|
67
|
+
const m = r.stdout.match(/(\d+\.\d+\.\d+(?:\.\d+)?)/);
|
|
68
|
+
return m ? m[1] : null;
|
|
69
|
+
}
|
|
70
|
+
|
|
31
71
|
function has(cmd) {
|
|
32
72
|
const probe = process.platform === "win32" ? "where" : "command";
|
|
33
73
|
const args = process.platform === "win32" ? [cmd] : ["-v", cmd];
|
|
@@ -51,10 +91,24 @@ function main() {
|
|
|
51
91
|
// `npx probe-research` with no arguments runs the wizard — that is the entire
|
|
52
92
|
// reason this package exists, so it should not require remembering a verb.
|
|
53
93
|
const forwarded = args.length ? args : ["wizard"];
|
|
94
|
+
const wanted = MIN_CLI;
|
|
54
95
|
|
|
55
|
-
if
|
|
56
|
-
|
|
57
|
-
if (has("
|
|
96
|
+
// Only hand off to an existing install if it is at least as new as this
|
|
97
|
+
// launcher. Otherwise fall through and let uv/pipx fetch a matching CLI.
|
|
98
|
+
if (has("probe")) {
|
|
99
|
+
const found = installedVersion();
|
|
100
|
+
if (found && atLeast(found, wanted)) return run("probe", forwarded);
|
|
101
|
+
console.error(
|
|
102
|
+
`probe-research: installed probe ${found || "(unknown version)"} is older than ` +
|
|
103
|
+
`${wanted}; fetching ${wanted}…`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
// A FLOOR, not an exact pin. Unpinned, `uv tool run --from probe-research`
|
|
107
|
+
// reuses an already-installed 0.8.2 tool; pinned exactly, it demands a PyPI
|
|
108
|
+
// version that may not exist. `>=` fixes both.
|
|
109
|
+
const spec = `${DIST}>=${wanted}`;
|
|
110
|
+
if (has("uv")) return run("uv", ["tool", "run", "--from", spec, "probe", ...forwarded]);
|
|
111
|
+
if (has("pipx")) return run("pipx", ["run", "--spec", spec, "probe", ...forwarded]);
|
|
58
112
|
|
|
59
113
|
if (process.platform === "win32") {
|
|
60
114
|
console.error(
|
|
@@ -75,7 +129,7 @@ function main() {
|
|
|
75
129
|
// The installer drops uv in ~/.local/bin, which is not on THIS process's PATH
|
|
76
130
|
// because it was resolved before the install ran.
|
|
77
131
|
const uv = `${os.homedir()}/.local/bin/uv`;
|
|
78
|
-
return run(uv, ["tool", "run", "--from", DIST
|
|
132
|
+
return run(uv, ["tool", "run", "--from", `${DIST}>=${wanted}`, "probe", ...forwarded]);
|
|
79
133
|
}
|
|
80
134
|
|
|
81
135
|
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "probe-research",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "Setup wizard for Probe Research in Claude Code. Runs from zero with npx.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"probe-research": "bin/probe-research.js"
|
|
@@ -22,5 +22,8 @@
|
|
|
22
22
|
"mlops",
|
|
23
23
|
"experiment-tracking",
|
|
24
24
|
"probe-research"
|
|
25
|
-
]
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"test": "node --test test/resolve.test.js"
|
|
28
|
+
}
|
|
26
29
|
}
|