@buildinternet/uploads 0.55.0 → 0.55.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/dist/cli.js +1 -1
- package/dist/commands/install.d.ts +6 -0
- package/dist/commands/install.js +50 -8
- package/dist/commands/update.js +3 -3
- package/dist/update-check.d.ts +4 -1
- package/dist/update-check.js +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -402,7 +402,7 @@ export async function runCli(argv) {
|
|
|
402
402
|
return 2;
|
|
403
403
|
}
|
|
404
404
|
}
|
|
405
|
-
// Best-effort; skipped for mcp, --quiet/--json, and opt-out env vars.
|
|
405
|
+
// Best-effort; skipped for mcp, update, --quiet/--json, and opt-out env vars.
|
|
406
406
|
if (code === 0 && !showHelp) {
|
|
407
407
|
await maybeHintUpdate({ quiet: quiet || json, command: parsed.command });
|
|
408
408
|
}
|
|
@@ -31,6 +31,12 @@ export declare function npmTooOldHint(version: string): string;
|
|
|
31
31
|
*/
|
|
32
32
|
export declare function probeSkillTooling(run: CommandRunner): string | undefined;
|
|
33
33
|
export declare function runStep(run: CommandRunner, command: string[]): StepResult;
|
|
34
|
+
/**
|
|
35
|
+
* True when `mcp list` output already names this server.
|
|
36
|
+
* Matches a name token (Claude's `uploads: url` form, tables, JSON) and not
|
|
37
|
+
* a substring of a host like `agents.uploads.sh`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function mcpListIncludesName(output: string, name: string): boolean;
|
|
34
40
|
export declare function runInstall(args: string[], opts: {
|
|
35
41
|
globals: GlobalFlags;
|
|
36
42
|
json?: boolean;
|
package/dist/commands/install.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { flagBool, flagString, parseCommandArgs, UsageError, } from "../cli-args.js";
|
|
2
2
|
import { resolveConfig } from "../config.js";
|
|
3
|
-
import { execRunner } from "../github-gh.js";
|
|
3
|
+
import { execRunner, timedExecRunner } from "../github-gh.js";
|
|
4
4
|
import { writeCommandHelp } from "../cli-style.js";
|
|
5
5
|
import { HOOK_COMMAND, HOOK_INVOCATION, installHookManifests, } from "../hooks-install.js";
|
|
6
6
|
export const DEFAULT_MCP_URL = "https://agents.uploads.sh/mcp";
|
|
@@ -36,7 +36,9 @@ export const MCP_CLIENTS = [
|
|
|
36
36
|
// Codex HTTP MCP has no --header; auth is OAuth on first use (same as the
|
|
37
37
|
// plugin's .mcp.json). Passing --bearer-token-env-var UPLOADS_TOKEN would
|
|
38
38
|
// break machines that signed in via `uploads login` (token lives in the
|
|
39
|
-
// config file, not the environment).
|
|
39
|
+
// config file, not the environment). A second `mcp add` re-opens Codex's
|
|
40
|
+
// localhost callback ("Authentication complete. You may close this
|
|
41
|
+
// window.") — probe `mcp list` first so a refresh does not do that.
|
|
40
42
|
command: (name, url) => ["codex", "mcp", "add", name, "--url", url],
|
|
41
43
|
},
|
|
42
44
|
{
|
|
@@ -58,9 +60,10 @@ workspace from the bearer token, so only the token is needed.
|
|
|
58
60
|
Claude Code and Codex ship the same reminder via their plugins (same command:
|
|
59
61
|
\`${HOOK_INVOCATION}\`) — install those plugins instead of relying on this step.
|
|
60
62
|
|
|
61
|
-
Safe to re-run.
|
|
62
|
-
as \`already configured\` and left as-is —
|
|
63
|
-
|
|
63
|
+
Safe to re-run. Before \`mcp add\`, install checks \`mcp list\`. A server that is
|
|
64
|
+
already registered is reported as \`already configured\` and left as-is —
|
|
65
|
+
including the token it was created with — so a refresh does not open a browser
|
|
66
|
+
for OAuth. To point it at a new token: \`<cli> mcp remove <name>\` first
|
|
64
67
|
(e.g. \`claude mcp remove uploads\`).
|
|
65
68
|
|
|
66
69
|
Usage:
|
|
@@ -187,6 +190,28 @@ function skillCommand(skill) {
|
|
|
187
190
|
function isAlreadyConfigured(error) {
|
|
188
191
|
return /already exists|already (configured|registered|present)|duplicate/i.test(error);
|
|
189
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* True when `mcp list` output already names this server.
|
|
195
|
+
* Matches a name token (Claude's `uploads: url` form, tables, JSON) and not
|
|
196
|
+
* a substring of a host like `agents.uploads.sh`.
|
|
197
|
+
*/
|
|
198
|
+
export function mcpListIncludesName(output, name) {
|
|
199
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
200
|
+
const token = new RegExp(`(?:^|[\\s"'\\[{,])${escaped}(?:[:\\s"',\\]}]|$)`, "m");
|
|
201
|
+
return token.test(output);
|
|
202
|
+
}
|
|
203
|
+
/** Best-effort `mcp list` probe. Never opens a browser; times out on the default runner. */
|
|
204
|
+
const MCP_LIST_TIMEOUT_MS = 8_000;
|
|
205
|
+
function probeMcpAlreadyConfigured(run, client, name) {
|
|
206
|
+
const probe = run === execRunner ? timedExecRunner(MCP_LIST_TIMEOUT_MS) : run;
|
|
207
|
+
try {
|
|
208
|
+
const output = probe(client.id, ["mcp", "list"]);
|
|
209
|
+
return mcpListIncludesName(output, name) ? "yes" : "no";
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
return isEnoent(err) ? "missing" : "no";
|
|
213
|
+
}
|
|
214
|
+
}
|
|
190
215
|
function mcpStepKey(client) {
|
|
191
216
|
return `mcp:${client.id}`;
|
|
192
217
|
}
|
|
@@ -215,8 +240,25 @@ function partitionSteps(results) {
|
|
|
215
240
|
}
|
|
216
241
|
return { skills, mcp, other };
|
|
217
242
|
}
|
|
218
|
-
/**
|
|
219
|
-
|
|
243
|
+
/**
|
|
244
|
+
* Run one client's `mcp add`. Probe `mcp list` first so a refresh does not
|
|
245
|
+
* re-run add — Codex (and some other clients) treat a second add as success
|
|
246
|
+
* and open a localhost OAuth callback even when the server is already there.
|
|
247
|
+
*/
|
|
248
|
+
function runMcpClientStep(run, client, name, url, bearer) {
|
|
249
|
+
const command = client.command(name, url, bearer);
|
|
250
|
+
const listed = probeMcpAlreadyConfigured(run, client, name);
|
|
251
|
+
if (listed === "yes") {
|
|
252
|
+
return { command, ok: true, skipped: "already-configured" };
|
|
253
|
+
}
|
|
254
|
+
if (listed === "missing") {
|
|
255
|
+
return {
|
|
256
|
+
command,
|
|
257
|
+
ok: true,
|
|
258
|
+
skipped: "missing-cli",
|
|
259
|
+
error: `${client.id} not found on PATH`,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
220
262
|
try {
|
|
221
263
|
const output = run(command[0], command.slice(1)).trim();
|
|
222
264
|
return { command, ok: true, output: output || undefined };
|
|
@@ -412,7 +454,7 @@ export async function runInstall(args, opts, help = false) {
|
|
|
412
454
|
results[key] = { command, ok: true, skipped: "dry-run" };
|
|
413
455
|
}
|
|
414
456
|
else {
|
|
415
|
-
results[key] = runMcpClientStep(run,
|
|
457
|
+
results[key] = runMcpClientStep(run, client, name, url, bearer);
|
|
416
458
|
}
|
|
417
459
|
}
|
|
418
460
|
}
|
package/dist/commands/update.js
CHANGED
|
@@ -11,9 +11,9 @@ const UPDATE_HELP = `uploads update — update the CLI and refresh agent integra
|
|
|
11
11
|
Upgrades the globally installed npm package, then re-runs \`uploads install\` so
|
|
12
12
|
the agent skills match the new version. Skills drift on their own, so this
|
|
13
13
|
refreshes them even when the CLI is already current. An MCP server already
|
|
14
|
-
registered is left as-is (\`already configured\`) — \`
|
|
15
|
-
Codex
|
|
16
|
-
is skipped so it does not fail the rest of the refresh.
|
|
14
|
+
registered is left as-is (\`already configured\`) — install checks \`mcp list\`
|
|
15
|
+
first so \`mcp add\` (and Codex's OAuth browser) does not run again. A missing
|
|
16
|
+
agent CLI is skipped so it does not fail the rest of the refresh.
|
|
17
17
|
|
|
18
18
|
Usage:
|
|
19
19
|
uploads update [options]
|
package/dist/update-check.d.ts
CHANGED
|
@@ -6,7 +6,10 @@ export interface UpdateCache {
|
|
|
6
6
|
}
|
|
7
7
|
export interface UpdateCheckOptions {
|
|
8
8
|
quiet?: boolean;
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* `mcp` is always skipped (stdio purity). `update` is skipped so a successful
|
|
11
|
+
* upgrade does not immediately hint the old in-process version.
|
|
12
|
+
*/
|
|
10
13
|
command?: string;
|
|
11
14
|
currentVersion?: string;
|
|
12
15
|
cachePath?: string;
|
package/dist/update-check.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Checks the registry at most once per day, never throws, never blocks longer
|
|
5
5
|
* than a short timeout, and writes only to stderr. Silence with --quiet,
|
|
6
|
-
* UPLOADS_NO_UPDATE=1, or NO_UPDATE_NOTIFIER=1.
|
|
6
|
+
* `uploads update`, `uploads mcp`, UPLOADS_NO_UPDATE=1, or NO_UPDATE_NOTIFIER=1.
|
|
7
7
|
*/
|
|
8
8
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { dirname, join } from "node:path";
|
|
@@ -75,7 +75,7 @@ export function writeUpdateCache(path, cache) {
|
|
|
75
75
|
export async function checkForUpdate(opts = {}) {
|
|
76
76
|
const current = opts.currentVersion ?? packageVersion();
|
|
77
77
|
try {
|
|
78
|
-
if (opts.quiet || opts.command === "mcp") {
|
|
78
|
+
if (opts.quiet || opts.command === "mcp" || opts.command === "update") {
|
|
79
79
|
return { current, updateAvailable: false };
|
|
80
80
|
}
|
|
81
81
|
if (truthyEnv("UPLOADS_NO_UPDATE") || truthyEnv("NO_UPDATE_NOTIFIER")) {
|