skalpel 3.0.0 → 3.0.1
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/package.json +6 -6
- package/postinstall/lib/detect-prior.js +24 -13
- package/postinstall/lib/paths.js +51 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skalpel",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Skalpel — local proxy and TUI for coding agents (skalpel + skalpeld bundle).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://skalpel.ai",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
"x64"
|
|
55
55
|
],
|
|
56
56
|
"optionalDependencies": {
|
|
57
|
-
"@skalpelai/skalpel-darwin-arm64": "3.0.
|
|
58
|
-
"@skalpelai/skalpel-darwin-x64": "3.0.
|
|
59
|
-
"@skalpelai/skalpel-linux-arm64": "3.0.
|
|
60
|
-
"@skalpelai/skalpel-linux-x64": "3.0.
|
|
61
|
-
"@skalpelai/skalpel-win32-x64": "3.0.
|
|
57
|
+
"@skalpelai/skalpel-darwin-arm64": "3.0.1",
|
|
58
|
+
"@skalpelai/skalpel-darwin-x64": "3.0.1",
|
|
59
|
+
"@skalpelai/skalpel-linux-arm64": "3.0.1",
|
|
60
|
+
"@skalpelai/skalpel-linux-x64": "3.0.1",
|
|
61
|
+
"@skalpelai/skalpel-win32-x64": "3.0.1"
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
// Step 1: detect prior install.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// v3.0.1 fix: `prior` now means specifically "user has auth state" —
|
|
4
|
+
// i.e. auth.json exists. v3.0.0 treated any of {auth.json, config.toml,
|
|
5
|
+
// lock file, service registration} as "prior" and skipped sign-in.
|
|
6
|
+
// That meant once a machine had ever installed skalpel, the systemd /
|
|
7
|
+
// launchd unit file persists outside configDir; every subsequent
|
|
8
|
+
// `npm install skalpel` would skip sign-in forever, and the user
|
|
9
|
+
// could never get logged in via the install flow on re-install.
|
|
7
10
|
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
+
// The other probes (config.toml / lock file / service registration)
|
|
12
|
+
// are informational only — they get reported in the log but no longer
|
|
13
|
+
// gate sign-in. SPEC.md §9.6: a fresh user with no auth.json must
|
|
14
|
+
// always be offered the sign-in step, regardless of mechanical
|
|
15
|
+
// install state (service units, rc snippets) that survived a prior
|
|
16
|
+
// install.
|
|
11
17
|
|
|
12
18
|
'use strict';
|
|
13
19
|
|
|
@@ -26,14 +32,15 @@ function fileExists(p) {
|
|
|
26
32
|
|
|
27
33
|
function run({ dryRun }) {
|
|
28
34
|
const probes = [
|
|
29
|
-
{ label: 'auth.json', path: paths.authFile() },
|
|
30
|
-
{ label: 'config.toml', path: paths.configToml() },
|
|
31
|
-
{ label: 'lock file', path: paths.lockFile() },
|
|
32
|
-
{ label: 'service registration', path: paths.servicePath() },
|
|
35
|
+
{ label: 'auth.json', path: paths.authFile(), gatesPrior: true },
|
|
36
|
+
{ label: 'config.toml', path: paths.configToml(), gatesPrior: false },
|
|
37
|
+
{ label: 'lock file', path: paths.lockFile(), gatesPrior: false },
|
|
38
|
+
{ label: 'service registration', path: paths.servicePath(), gatesPrior: false },
|
|
33
39
|
];
|
|
34
40
|
|
|
35
41
|
const findings = probes.map((p) => ({ ...p, exists: fileExists(p.path) }));
|
|
36
|
-
|
|
42
|
+
// `prior` reflects only auth.json existence — see header comment.
|
|
43
|
+
const prior = findings.some((f) => f.gatesPrior && f.exists);
|
|
37
44
|
|
|
38
45
|
if (dryRun) {
|
|
39
46
|
log.dryRun(`step 1 detect-prior: would probe ${findings.length} paths`);
|
|
@@ -44,7 +51,11 @@ function run({ dryRun }) {
|
|
|
44
51
|
);
|
|
45
52
|
}
|
|
46
53
|
|
|
47
|
-
log.info(
|
|
54
|
+
log.info(
|
|
55
|
+
prior
|
|
56
|
+
? 'detected prior auth (auth.json present) — sign-in will skip'
|
|
57
|
+
: 'no prior auth detected — sign-in will run'
|
|
58
|
+
);
|
|
48
59
|
return { prior, findings };
|
|
49
60
|
}
|
|
50
61
|
|
package/postinstall/lib/paths.js
CHANGED
|
@@ -96,13 +96,63 @@ function isNpxInvocation() {
|
|
|
96
96
|
return false;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
// Where the platform binary lives once optionalDependencies installed
|
|
99
|
+
// Where the platform binary lives once optionalDependencies installed
|
|
100
|
+
// it. v3.0.1 fix: previously this returned the GLOBAL-install path
|
|
101
|
+
// (`$HOME/.local/bin/<name>` on Linux, `/usr/local/bin/<name>` on
|
|
102
|
+
// macOS, `$HOME/AppData/Local/skalpel/<name>.exe` on Windows). That
|
|
103
|
+
// path is only correct for `npm install -g skalpel`. For local
|
|
104
|
+
// installs (`npm install skalpel` from any non-package directory)
|
|
105
|
+
// the binary lives at `node_modules/@skalpelai/skalpel-<plat>/bin/
|
|
106
|
+
// <name>` — the optionalDependencies-resolved sub-package's bin/.
|
|
107
|
+
//
|
|
108
|
+
// The right resolution is the same one npm-bin/skalpel.js already
|
|
109
|
+
// uses for runtime dispatch: `require.resolve` against the platform
|
|
110
|
+
// sub-package's package.json, then join with `bin/<name>{,.exe}`.
|
|
111
|
+
// This works uniformly for global, local, and npx-cached installs
|
|
112
|
+
// because node's module resolver walks up node_modules trees the
|
|
113
|
+
// same way in all three contexts.
|
|
114
|
+
//
|
|
115
|
+
// We fall back to the legacy global-install paths if require.resolve
|
|
116
|
+
// fails, so behaviour on a real global install stays unchanged.
|
|
117
|
+
function platformPackageName() {
|
|
118
|
+
// Map process.platform-process.arch → @skalpelai/skalpel-<npm-plat>.
|
|
119
|
+
// Mirrors PLATFORM_PACKAGES in npm-bin/skalpel.js.
|
|
120
|
+
const key = `${process.platform}-${process.arch}`;
|
|
121
|
+
const map = {
|
|
122
|
+
'darwin-arm64': '@skalpelai/skalpel-darwin-arm64',
|
|
123
|
+
'darwin-x64': '@skalpelai/skalpel-darwin-x64',
|
|
124
|
+
'linux-arm64': '@skalpelai/skalpel-linux-arm64',
|
|
125
|
+
'linux-x64': '@skalpelai/skalpel-linux-x64',
|
|
126
|
+
'win32-x64': '@skalpelai/skalpel-win32-x64',
|
|
127
|
+
};
|
|
128
|
+
return map[key] || null;
|
|
129
|
+
}
|
|
130
|
+
|
|
100
131
|
function binPath(name) {
|
|
101
132
|
if (isNpxInvocation()) {
|
|
102
133
|
throw new Error(
|
|
103
134
|
'Skalpel does not support `npx skalpel` — please run `npm i -g @skalpelai/skalpel` instead.'
|
|
104
135
|
);
|
|
105
136
|
}
|
|
137
|
+
const exe = process.platform === 'win32' ? `${name}.exe` : name;
|
|
138
|
+
|
|
139
|
+
// Preferred: resolve via the platform sub-package's package.json.
|
|
140
|
+
// Works for global, local, and any other npm-managed install context.
|
|
141
|
+
const pkgName = platformPackageName();
|
|
142
|
+
if (pkgName) {
|
|
143
|
+
try {
|
|
144
|
+
const pkgRoot = path.dirname(require.resolve(`${pkgName}/package.json`));
|
|
145
|
+
return path.join(pkgRoot, 'bin', exe);
|
|
146
|
+
} catch (_err) {
|
|
147
|
+
// fall through to legacy paths below
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Fallback: legacy hardcoded global-install paths. Reached only on
|
|
152
|
+
// a misinstall (no @skalpelai/skalpel-<plat> sub-package in the
|
|
153
|
+
// resolution tree) — service-register will then error with the
|
|
154
|
+
// legacy "binary missing at <path>" message which is at least a
|
|
155
|
+
// recognisable signature.
|
|
106
156
|
const h = home();
|
|
107
157
|
const npmPrefix = process.env.npm_config_prefix;
|
|
108
158
|
validatePath(npmPrefix, 'npm_config_prefix');
|