@buildinternet/uploads 0.31.0 → 0.32.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.
|
@@ -11,7 +11,7 @@ non-secret page URL plus a code you share separately). The legacy
|
|
|
11
11
|
|
|
12
12
|
Options:
|
|
13
13
|
--admin-token <token> Or ADMIN_TOKEN (UPLOADS_ADMIN_TOKEN is a legacy alias)
|
|
14
|
-
--workspace <name>
|
|
14
|
+
--workspace <name> Required — the workspace the invite grants access to
|
|
15
15
|
--label <label>
|
|
16
16
|
--expires-in <seconds> Default: server policy
|
|
17
17
|
--token-expires-in <seconds> Upload token lifetime (default: server policy)
|
|
@@ -79,7 +79,15 @@ export async function runAdmin(args, opts, help = false) {
|
|
|
79
79
|
throw new UsageError("ADMIN_TOKEN is required for admin enrollment creation");
|
|
80
80
|
const apiUrl = flagString(parsed.flags, "--api-url") ?? opts.apiUrl ?? "https://api.uploads.sh";
|
|
81
81
|
const webUrl = flagString(parsed.flags, "--web-url");
|
|
82
|
-
|
|
82
|
+
// No default. An invite grants files:read/files:write on the workspace it
|
|
83
|
+
// names, so omitting the flag used to silently target the shared `default`
|
|
84
|
+
// workspace — and enrollment redemption mints a token without an org
|
|
85
|
+
// membership, so the recipient would not appear in any member list while
|
|
86
|
+
// still reading and writing its files.
|
|
87
|
+
const workspace = flagString(parsed.flags, "--workspace");
|
|
88
|
+
if (!workspace) {
|
|
89
|
+
throw new UsageError("--workspace is required (the workspace the invite grants access to)");
|
|
90
|
+
}
|
|
83
91
|
const label = flagString(parsed.flags, "--label");
|
|
84
92
|
const email = flagString(parsed.flags, "--email");
|
|
85
93
|
const result = await createEnrollment(apiUrl, adminToken, {
|
|
@@ -4,7 +4,7 @@ export declare const DEFAULT_MCP_URL = "https://agents.uploads.sh/mcp";
|
|
|
4
4
|
export interface StepResult {
|
|
5
5
|
command: string[];
|
|
6
6
|
ok: boolean;
|
|
7
|
-
skipped?: "dry-run" | "sign-in";
|
|
7
|
+
skipped?: "dry-run" | "sign-in" | "already-configured";
|
|
8
8
|
error?: string;
|
|
9
9
|
output?: string;
|
|
10
10
|
}
|
package/dist/commands/install.js
CHANGED
|
@@ -17,6 +17,10 @@ infers your workspace from the bearer token, so only the token is needed.
|
|
|
17
17
|
Claude Code and Codex ship the same reminder via their plugins (same command:
|
|
18
18
|
\`${HOOK_COMMAND}\`) — install those plugins instead of relying on this step.
|
|
19
19
|
|
|
20
|
+
Safe to re-run. An MCP server already registered under this name is reported
|
|
21
|
+
as \`already configured\` and left as-is — including the token it was created
|
|
22
|
+
with. To point it at a new token: \`claude mcp remove <name>\` first.
|
|
23
|
+
|
|
20
24
|
Usage:
|
|
21
25
|
uploads install [skill|mcp|hooks|all] (default: all)
|
|
22
26
|
|
|
@@ -73,6 +77,16 @@ function skillCommand(skill) {
|
|
|
73
77
|
// -g global, -y non-interactive, -a '*' every agent (skips the multi-select TUI)
|
|
74
78
|
return ["npx", "-y", "skills", "add", SKILL_SOURCE, "--skill", skill, "-g", "-y", "-a", "*"];
|
|
75
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* `claude mcp add` refuses to overwrite an existing entry and exits non-zero
|
|
82
|
+
* ("MCP server uploads already exists in local config"). That is the steady
|
|
83
|
+
* state for anyone re-running `uploads install`, not a failure — recognize it
|
|
84
|
+
* so the run stays green and the footer tells them how to re-add if they want
|
|
85
|
+
* a fresh token in the header.
|
|
86
|
+
*/
|
|
87
|
+
function alreadyConfigured(result) {
|
|
88
|
+
return !result.ok && /already exists/i.test(result.error ?? "");
|
|
89
|
+
}
|
|
76
90
|
function mcpCommand(name, url, bearer) {
|
|
77
91
|
return [
|
|
78
92
|
"claude",
|
|
@@ -101,7 +115,7 @@ function peekToken(globals) {
|
|
|
101
115
|
return undefined;
|
|
102
116
|
}
|
|
103
117
|
}
|
|
104
|
-
function printHumanSteps(results, redact, verbose) {
|
|
118
|
+
function printHumanSteps(results, redact, verbose, mcpName) {
|
|
105
119
|
for (const [step, r] of Object.entries(results)) {
|
|
106
120
|
const cmd = redact(r.command.join(" "));
|
|
107
121
|
if (r.skipped === "dry-run") {
|
|
@@ -110,6 +124,10 @@ function printHumanSteps(results, redact, verbose) {
|
|
|
110
124
|
else if (r.skipped === "sign-in") {
|
|
111
125
|
process.stdout.write(`${step}: skipped — ${redact(r.error ?? "needs sign-in")}\n`);
|
|
112
126
|
}
|
|
127
|
+
else if (r.skipped === "already-configured") {
|
|
128
|
+
process.stdout.write(`${step}: already configured — "${mcpName}" is registered in Claude Code (nothing to do)\n` +
|
|
129
|
+
` To re-register (e.g. with a new token): claude mcp remove ${mcpName} && uploads install mcp\n`);
|
|
130
|
+
}
|
|
113
131
|
else if (r.ok) {
|
|
114
132
|
process.stdout.write(`${step}: ok\n`);
|
|
115
133
|
if (verbose && r.output) {
|
|
@@ -189,7 +207,12 @@ export async function runInstall(args, opts, help = false) {
|
|
|
189
207
|
const command = mcpCommand(name, url, token || "<token>");
|
|
190
208
|
if (human)
|
|
191
209
|
process.stdout.write("Installing MCP server…\n");
|
|
192
|
-
|
|
210
|
+
const step = dryRun
|
|
211
|
+
? { command, ok: true, skipped: "dry-run" }
|
|
212
|
+
: runStep(run, command);
|
|
213
|
+
results.mcp = alreadyConfigured(step)
|
|
214
|
+
? { command, ok: true, skipped: "already-configured", output: step.error }
|
|
215
|
+
: step;
|
|
193
216
|
}
|
|
194
217
|
}
|
|
195
218
|
if (target === "hooks" || target === "all") {
|
|
@@ -223,7 +246,7 @@ export async function runInstall(args, opts, help = false) {
|
|
|
223
246
|
process.stdout.write(JSON.stringify({ ok: !failed, steps }, null, 2) + "\n");
|
|
224
247
|
return failed ? 1 : 0;
|
|
225
248
|
}
|
|
226
|
-
printHumanSteps(results, redact, verbose);
|
|
249
|
+
printHumanSteps(results, redact, verbose, name);
|
|
227
250
|
// Path-level detail for hooks (printHumanSteps only shows the synthetic step).
|
|
228
251
|
if ((target === "hooks" || target === "all") &&
|
|
229
252
|
(dryRun || (human && (verbose || hookWrites.some((w) => w.action !== "skipped"))))) {
|
package/dist/commands/update.js
CHANGED
|
@@ -9,9 +9,10 @@ import { runInstall, runStep } from "./install.js";
|
|
|
9
9
|
const UPDATE_HELP = `uploads update — update the CLI and refresh agent integrations
|
|
10
10
|
|
|
11
11
|
Upgrades the globally installed npm package, then re-runs \`uploads install\` so
|
|
12
|
-
the agent skills
|
|
13
|
-
|
|
14
|
-
already
|
|
12
|
+
the agent skills match the new version. Skills drift on their own, so this
|
|
13
|
+
refreshes them even when the CLI is already current. An MCP server already
|
|
14
|
+
registered is left as-is (\`already configured\`) — \`claude mcp add\` never
|
|
15
|
+
overwrites an existing entry.
|
|
15
16
|
|
|
16
17
|
Usage:
|
|
17
18
|
uploads update [options]
|