dsh-root-planner-preset 1.1.2 → 1.1.3
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 +1 -1
- package/release.mjs +51 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-root-planner-preset",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "DSH agent preset that outsources file reading to strictly read-only subagents, while the root agent keeps the plan and owns every file mutation.",
|
|
6
6
|
"license": "MIT",
|
package/release.mjs
CHANGED
|
@@ -39,8 +39,8 @@ const here = dirname(fileURLToPath(import.meta.url));
|
|
|
39
39
|
const OFFICIAL_REGISTRY = 'https://registry.npmjs.org/';
|
|
40
40
|
const PROXY = process.env.HTTPS_PROXY ?? process.env.HTTP_PROXY ?? 'http://127.0.0.1:7897';
|
|
41
41
|
const GIT = process.env.DSH_RELEASE_GIT ?? 'git';
|
|
42
|
-
const NPM = process.env.DSH_RELEASE_NPM ?? 'npm';
|
|
43
42
|
const GH = process.env.DSH_RELEASE_GH ?? 'gh';
|
|
43
|
+
const PUBLISHER = process.env.DSH_RELEASE_PUBLISHER ?? (process.platform === 'win32' ? 'pnpm' : 'npm');
|
|
44
44
|
|
|
45
45
|
const argv = process.argv.slice(2);
|
|
46
46
|
const dryRun = argv.includes('--dry-run');
|
|
@@ -62,12 +62,15 @@ if (bump === undefined) {
|
|
|
62
62
|
|
|
63
63
|
const env = { ...process.env, HTTPS_PROXY: PROXY, HTTP_PROXY: PROXY, GIT_TERMINAL_PROMPT: '0' };
|
|
64
64
|
const step = (text) => process.stdout.write(`\n\u25b6 ${text}\n`);
|
|
65
|
-
const run = (command, args,
|
|
66
|
-
const result = spawnSync(command, args, { cwd: here, env, encoding: 'utf8', ...
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
const run = (command, args, { allowFailure = false, shell = false, ...rest } = {}) => {
|
|
66
|
+
const result = spawnSync(command, args, { cwd: here, env, encoding: 'utf8', shell, ...rest });
|
|
67
|
+
// A spawn that never started reports status null and puts the reason in `error`;
|
|
68
|
+
// surfacing that by name is what turns a silent no-op into a diagnosable failure.
|
|
69
|
+
if (result.status !== 0 && !allowFailure) {
|
|
70
|
+
const reason = result.error ? `${result.error.code}: ${result.error.message}` : `exit ${result.status}`;
|
|
71
|
+
throw new Error(`${command} ${args.join(' ')} failed (${reason})\n${result.stdout ?? ''}${result.stderr ?? ''}`);
|
|
69
72
|
}
|
|
70
|
-
return `${result.stdout ?? ''}${result.stderr ?? ''}`;
|
|
73
|
+
return `${result.stdout ?? ''}${result.stderr ?? ''}${result.error ? `\n${result.error.code}: ${result.error.message}` : ''}`;
|
|
71
74
|
};
|
|
72
75
|
const git = (...args) => run(GIT, args).trim();
|
|
73
76
|
|
|
@@ -149,12 +152,28 @@ if (dryRun) {
|
|
|
149
152
|
}
|
|
150
153
|
|
|
151
154
|
// ── Publish ──────────────────────────────────────────────────────────────────
|
|
152
|
-
step(`Publish to the official registry (the configured one is a read-only mirror)`);
|
|
155
|
+
step(`Publish with ${PUBLISHER} to the official registry (the configured one is a read-only mirror)`);
|
|
153
156
|
if (dryRun) {
|
|
154
|
-
process.stdout.write(` --dry-run: would run
|
|
157
|
+
process.stdout.write(` --dry-run: would run ${PUBLISHER} publish --registry ${OFFICIAL_REGISTRY}\n`);
|
|
155
158
|
} else {
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
// Two Windows facts force the shape of this call, both learned by watching a
|
|
160
|
+
// publish silently do nothing:
|
|
161
|
+
// * `npm` and `pnpm` are shell shims, not executables — `npm` is an sh script
|
|
162
|
+
// (ENOENT), `npm.cmd`/`pnpm.cmd` refuse to spawn without a shell (EINVAL),
|
|
163
|
+
// and `npm.ps1` is PowerShell (EFTYPE). So the publisher is invoked WITH a
|
|
164
|
+
// shell, which is why every argument below must stay shell-safe.
|
|
165
|
+
// * The output must be shown even on failure. The first version filtered it
|
|
166
|
+
// down to matching lines and printed a blank line when the command never
|
|
167
|
+
// ran, hiding the real problem behind a successful-looking step.
|
|
168
|
+
const published = run(PUBLISHER, ['publish', '--registry', OFFICIAL_REGISTRY, '--access', 'public'], {
|
|
169
|
+
allowFailure: true,
|
|
170
|
+
shell: true,
|
|
171
|
+
});
|
|
172
|
+
const summary = published
|
|
173
|
+
.split('\n')
|
|
174
|
+
.map((line) => line.trim())
|
|
175
|
+
.filter((line) => line.length > 0 && !/^Progress:|^Packages:|^\+?$/.test(line));
|
|
176
|
+
process.stdout.write(`${summary.map((line) => ` ${line}`).join('\n') || ' (the publisher printed nothing — treat that as a failure)'}\n`);
|
|
158
177
|
}
|
|
159
178
|
|
|
160
179
|
// ── Confirm on the registry ──────────────────────────────────────────────────
|
|
@@ -170,22 +189,26 @@ if (dryRun) {
|
|
|
170
189
|
encoding: 'utf8',
|
|
171
190
|
}).stdout?.trim();
|
|
172
191
|
|
|
192
|
+
// Measured on this account: 1.1.2 was still 404 at 200s and live shortly after,
|
|
193
|
+
// so the window has to be generous or a successful release reads as a failure.
|
|
173
194
|
let live = false;
|
|
174
|
-
for (let attempt = 1; attempt <=
|
|
195
|
+
for (let attempt = 1; attempt <= 60 && !live; attempt += 1) {
|
|
175
196
|
await new Promise((resolve) => setTimeout(resolve, 10_000));
|
|
176
197
|
const code = probe(`${OFFICIAL_REGISTRY}${manifest.name}/${version}`);
|
|
177
198
|
if (code === '200') {
|
|
178
199
|
live = true;
|
|
179
200
|
process.stdout.write(` ${manifest.name}@${version} is live on the registry\n`);
|
|
180
|
-
} else if (attempt %
|
|
201
|
+
} else if (attempt % 6 === 0) {
|
|
181
202
|
process.stdout.write(` still not visible after ${attempt * 10}s (last HTTP ${code})\n`);
|
|
182
203
|
}
|
|
183
204
|
}
|
|
184
205
|
if (!live) {
|
|
185
206
|
process.stderr.write(
|
|
186
|
-
'\n NOT VISIBLE
|
|
187
|
-
'
|
|
188
|
-
'
|
|
207
|
+
'\n NOT VISIBLE after 10 minutes. Two known causes, in order of likelihood:\n' +
|
|
208
|
+
' 1. propagation lag — this registry answered 404 for over three minutes on a\n' +
|
|
209
|
+
' publish that had already succeeded, so re-check before concluding anything;\n' +
|
|
210
|
+
' 2. staged publishing — check npmjs.com for a pending approval. `npm stage list`\n' +
|
|
211
|
+
' reports nothing even when a version is held, so it is not the test.\n',
|
|
189
212
|
);
|
|
190
213
|
process.exit(1);
|
|
191
214
|
}
|
|
@@ -196,10 +219,14 @@ step(`Upgrade the local "${profile}" profile so the machine runs what was publis
|
|
|
196
219
|
if (dryRun || skipInstall) {
|
|
197
220
|
process.stdout.write(' skipped\n');
|
|
198
221
|
} else {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
222
|
+
// `dsh` is a shell shim on Windows too, so it is invoked through Node rather
|
|
223
|
+
// than spawned directly. DSH_RELEASE_DSH overrides the entry point.
|
|
224
|
+
const dshEntry = process.env.DSH_RELEASE_DSH ?? 'D:/nodejs/npm_global/node_modules/@deepseek-ai/dsh/lib/bin.js';
|
|
225
|
+
const output = run(
|
|
226
|
+
process.execPath,
|
|
227
|
+
[dshEntry, 'plugin', '--profile', profile, 'add', `${manifest.name}@${version}`, '--registry', OFFICIAL_REGISTRY],
|
|
228
|
+
{ allowFailure: true },
|
|
229
|
+
);
|
|
203
230
|
const installed = (() => {
|
|
204
231
|
try {
|
|
205
232
|
return JSON.parse(
|
|
@@ -212,7 +239,11 @@ if (dryRun || skipInstall) {
|
|
|
212
239
|
if (installed === version) {
|
|
213
240
|
process.stdout.write(` profile now runs ${manifest.name}@${installed}\n`);
|
|
214
241
|
} else {
|
|
215
|
-
process.stdout.write(
|
|
242
|
+
process.stdout.write(
|
|
243
|
+
` the profile reports ${installed ?? 'unknown'} rather than ${version} — install it by hand:\n` +
|
|
244
|
+
` dsh plugin --profile ${profile} add ${manifest.name}@${version} --registry ${OFFICIAL_REGISTRY}\n` +
|
|
245
|
+
`${output.trim().split('\n').slice(-6).map((line) => ` ${line}`).join('\n')}\n`,
|
|
246
|
+
);
|
|
216
247
|
}
|
|
217
248
|
}
|
|
218
249
|
|