mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-11 23:36:51 +02:00
Bumps [@clack/prompts](https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts) from 0.11.0 to 1.7.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/bombshell-dev/clack/releases">@clack/prompts's releases</a>.</em></p> <blockquote> <h2><code>@clack/prompts</code><a href="https://github.com/1"><code>@1</code></a>.7.0</h2> <h3>Minor Changes</h3> <ul> <li><a href="https://redirect.github.com/bombshell-dev/clack/pull/574">#574</a> <a href="https://github.com/bombshell-dev/clack/commit/8f1c380683cfb5fb7a094610342046ae1603e28e"><code>8f1c380</code></a> Thanks <a href="https://github.com/dreyfus92"><code>@dreyfus92</code></a>! - Add <code>showInstructions</code> option to <code>select</code>, <code>multiselect</code>, and <code>groupMultiselect</code>. Keyboard hints remain shown by default; pass <code>showInstructions: false</code> to hide them.</li> </ul> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/bombshell-dev/clack/pull/582">#582</a> <a href="https://github.com/bombshell-dev/clack/commit/4b249539e28eecc16c13b3a1bd0ba447e9f38d06"><code>4b24953</code></a> Thanks <a href="https://github.com/43081j"><code>@43081j</code></a>! - Handle empty arrays in various prompts and utilities.</p> </li> <li> <p>Updated dependencies [<a href="https://github.com/bombshell-dev/clack/commit/4b249539e28eecc16c13b3a1bd0ba447e9f38d06"><code>4b24953</code></a>]:</p> <ul> <li><code>@clack/core</code><a href="https://github.com/1"><code>@1</code></a>.4.3</li> </ul> </li> </ul> <h2><code>@clack/prompts</code><a href="https://github.com/1"><code>@1</code></a>.6.0</h2> <h3>Minor Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/bombshell-dev/clack/pull/568">#568</a> <a href="https://github.com/bombshell-dev/clack/commit/f87933fb7b3f4c401b9e51a152b95cb8e7200fe5"><code>f87933f</code></a> Thanks <a href="https://github.com/florian-lefebvre"><code>@florian-lefebvre</code></a>! - Updates default formatter of <code>note()</code> to note dim lines anymore</p> <p>If you want the old behavior, provide a <code>format()</code> function:</p> <pre lang="diff"><code>import { note } from '@clack/prompts'; +import { styleText } from 'node:util'; <p>note( 'You can edit the file src/index.jsx', 'Next steps.'</p> <ul> <li>{ format: (text) => styleText('dim', text) } ); </code></pre></li> </ul> </li> <li> <p><a href="https://redirect.github.com/bombshell-dev/clack/pull/567">#567</a> <a href="https://github.com/bombshell-dev/clack/commit/cc6aab50186cff8a02dc98e9cfd3897c29a33b15"><code>cc6aab5</code></a> Thanks <a href="https://github.com/dreyfus92"><code>@dreyfus92</code></a>! - Add keyboard instruction footers to <code>select</code>, <code>multiselect</code>, and <code>groupMultiselect</code> in the active state, matching autocomplete. No option — always shown.</p> </li> </ul> <h3>Patch Changes</h3> <ul> <li>Updated dependencies [<a href="https://github.com/bombshell-dev/clack/commit/2f2b52f77cbfa9af618c6d929249ab8395fc37a1"><code>2f2b52f</code></a>, <a href="https://github.com/bombshell-dev/clack/commit/e1b6ee71a76e17a3c33ba7ee6e5fb34e886233bb"><code>e1b6ee7</code></a>]: <ul> <li><code>@clack/core</code><a href="https://github.com/1"><code>@1</code></a>.4.2</li> </ul> </li> </ul> <h2><code>@clack/prompts</code><a href="https://github.com/1"><code>@1</code></a>.5.1</h2> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/bombshell-dev/clack/pull/548">#548</a> <a href="https://github.com/bombshell-dev/clack/commit/2356e97c1f46007ead55133c3a26910404ef1cfb"><code>2356e97</code></a> Thanks <a href="https://github.com/43081j"><code>@43081j</code></a>! - Remove sourcemaps and enable pretty-ish build output.</p> </li> <li> <p><a href="https://redirect.github.com/bombshell-dev/clack/pull/546">#546</a> <a href="https://github.com/bombshell-dev/clack/commit/56e9d6707715bc858d9c2dbc444230b02813e809"><code>56e9d67</code></a> Thanks <a href="https://github.com/ghostdevv"><code>@ghostdevv</code></a>! - docs: add jsdoc for <code>date</code>, <code>limit-options</code>, and <code>messages</code></p> </li> <li> <p>Updated dependencies [<a href="https://github.com/bombshell-dev/clack/commit/2356e97c1f46007ead55133c3a26910404ef1cfb"><code>2356e97</code></a>]:</p> <ul> <li><code>@clack/core</code><a href="https://github.com/1"><code>@1</code></a>.4.1</li> </ul> </li> </ul> <h2><code>@clack/prompts</code><a href="https://github.com/1"><code>@1</code></a>.5.0</h2> <h3>Minor Changes</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/bombshell-dev/clack/blob/main/packages/prompts/CHANGELOG.md">@clack/prompts's changelog</a>.</em></p> <blockquote> <h2>1.7.0</h2> <h3>Minor Changes</h3> <ul> <li><a href="https://redirect.github.com/bombshell-dev/clack/pull/574">#574</a> <a href="https://github.com/bombshell-dev/clack/commit/8f1c380683cfb5fb7a094610342046ae1603e28e"><code>8f1c380</code></a> Thanks <a href="https://github.com/dreyfus92"><code>@dreyfus92</code></a>! - Add <code>showInstructions</code> option to <code>select</code>, <code>multiselect</code>, and <code>groupMultiselect</code>. Keyboard hints remain shown by default; pass <code>showInstructions: false</code> to hide them.</li> </ul> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/bombshell-dev/clack/pull/582">#582</a> <a href="https://github.com/bombshell-dev/clack/commit/4b249539e28eecc16c13b3a1bd0ba447e9f38d06"><code>4b24953</code></a> Thanks <a href="https://github.com/43081j"><code>@43081j</code></a>! - Handle empty arrays in various prompts and utilities.</p> </li> <li> <p>Updated dependencies [<a href="https://github.com/bombshell-dev/clack/commit/4b249539e28eecc16c13b3a1bd0ba447e9f38d06"><code>4b24953</code></a>]:</p> <ul> <li><code>@clack/core</code><a href="https://github.com/1"><code>@1</code></a>.4.3</li> </ul> </li> </ul> <h2>1.6.0</h2> <h3>Minor Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/bombshell-dev/clack/pull/568">#568</a> <a href="https://github.com/bombshell-dev/clack/commit/f87933fb7b3f4c401b9e51a152b95cb8e7200fe5"><code>f87933f</code></a> Thanks <a href="https://github.com/florian-lefebvre"><code>@florian-lefebvre</code></a>! - Updates default formatter of <code>note()</code> to note dim lines anymore</p> <p>If you want the old behavior, provide a <code>format()</code> function:</p> <pre lang="diff"><code>import { note } from '@clack/prompts'; +import { styleText } from 'node:util'; <p>note( 'You can edit the file src/index.jsx', 'Next steps.'</p> <ul> <li>{ format: (text) => styleText('dim', text) } ); </code></pre></li> </ul> </li> <li> <p><a href="https://redirect.github.com/bombshell-dev/clack/pull/567">#567</a> <a href="https://github.com/bombshell-dev/clack/commit/cc6aab50186cff8a02dc98e9cfd3897c29a33b15"><code>cc6aab5</code></a> Thanks <a href="https://github.com/dreyfus92"><code>@dreyfus92</code></a>! - Add keyboard instruction footers to <code>select</code>, <code>multiselect</code>, and <code>groupMultiselect</code> in the active state, matching autocomplete. No option — always shown.</p> </li> </ul> <h3>Patch Changes</h3> <ul> <li>Updated dependencies [<a href="https://github.com/bombshell-dev/clack/commit/2f2b52f77cbfa9af618c6d929249ab8395fc37a1"><code>2f2b52f</code></a>, <a href="https://github.com/bombshell-dev/clack/commit/e1b6ee71a76e17a3c33ba7ee6e5fb34e886233bb"><code>e1b6ee7</code></a>]: <ul> <li><code>@clack/core</code><a href="https://github.com/1"><code>@1</code></a>.4.2</li> </ul> </li> </ul> <h2>1.5.1</h2> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/bombshell-dev/clack/pull/548">#548</a> <a href="https://github.com/bombshell-dev/clack/commit/2356e97c1f46007ead55133c3a26910404ef1cfb"><code>2356e97</code></a> Thanks <a href="https://github.com/43081j"><code>@43081j</code></a>! - Remove sourcemaps and enable pretty-ish build output.</p> </li> <li> <p><a href="https://redirect.github.com/bombshell-dev/clack/pull/546">#546</a> <a href="https://github.com/bombshell-dev/clack/commit/56e9d6707715bc858d9c2dbc444230b02813e809"><code>56e9d67</code></a> Thanks <a href="https://github.com/ghostdevv"><code>@ghostdevv</code></a>! - docs: add jsdoc for <code>date</code>, <code>limit-options</code>, and <code>messages</code></p> </li> <li> <p>Updated dependencies [<a href="https://github.com/bombshell-dev/clack/commit/2356e97c1f46007ead55133c3a26910404ef1cfb"><code>2356e97</code></a>]:</p> <ul> <li><code>@clack/core</code><a href="https://github.com/1"><code>@1</code></a>.4.1</li> </ul> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/bombshell-dev/clack/commit/dc5bce8aae84a57b5863124adfaa839c1db1fa23"><code>dc5bce8</code></a> [ci] release (<a href="https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts/issues/575">#575</a>)</li> <li><a href="https://github.com/bombshell-dev/clack/commit/4b249539e28eecc16c13b3a1bd0ba447e9f38d06"><code>4b24953</code></a> chore: enable strict index checks (<a href="https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts/issues/582">#582</a>)</li> <li><a href="https://github.com/bombshell-dev/clack/commit/8f1c380683cfb5fb7a094610342046ae1603e28e"><code>8f1c380</code></a> feat(prompts): add showInstructions opt-out (<a href="https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts/issues/574">#574</a>)</li> <li><a href="https://github.com/bombshell-dev/clack/commit/06c16c7b65b69dee44301e7e6c8f1110c6da4149"><code>06c16c7</code></a> chore: update license copyright to Bombshell contributors (<a href="https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts/issues/572">#572</a>)</li> <li><a href="https://github.com/bombshell-dev/clack/commit/0e700562dfb54bd693d98c5b7e28d34213fcb226"><code>0e70056</code></a> [ci] release (<a href="https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts/issues/562">#562</a>)</li> <li><a href="https://github.com/bombshell-dev/clack/commit/f87933fb7b3f4c401b9e51a152b95cb8e7200fe5"><code>f87933f</code></a> fix(prompts): do not dim note contents (<a href="https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts/issues/568">#568</a>)</li> <li><a href="https://github.com/bombshell-dev/clack/commit/cc6aab50186cff8a02dc98e9cfd3897c29a33b15"><code>cc6aab5</code></a> feat(prompts): add instructions footer for <code>select</code>, <code>multi-select</code> & `group-...</li> <li><a href="https://github.com/bombshell-dev/clack/commit/02ae19193ed1155a57fb3dfd830ecc356a1cc11a"><code>02ae191</code></a> [ci] release (<a href="https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts/issues/549">#549</a>)</li> <li><a href="https://github.com/bombshell-dev/clack/commit/56e9d6707715bc858d9c2dbc444230b02813e809"><code>56e9d67</code></a> docs: add jsdoc for <code>date</code>, <code>limit-options</code>, and <code>messages</code> (<a href="https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts/issues/546">#546</a>)</li> <li><a href="https://github.com/bombshell-dev/clack/commit/030ba4d776e5985050c0e2712da7008bd93b8847"><code>030ba4d</code></a> [ci] release (<a href="https://github.com/bombshell-dev/clack/tree/HEAD/packages/prompts/issues/539">#539</a>)</li> <li>Additional commits viewable in <a href="https://github.com/bombshell-dev/clack/commits/@clack/prompts@1.7.0/packages/prompts">compare view</a></li> </ul> </details> <details> <summary>Maintainer changes</summary> <p>This version was pushed to npm by <a href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new releaser for <code>@clack/prompts</code> since your current version.</p> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Priya Raman <priya@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing>
222 lines
6.9 KiB
TypeScript
222 lines
6.9 KiB
TypeScript
import * as p from "@clack/prompts";
|
|
import { isLoopbackHost, type BindMode } from "@paperclipai/shared";
|
|
import type { AuthConfig, ServerConfig } from "../config/schema.js";
|
|
import { parseHostnameCsv } from "../config/hostnames.js";
|
|
import { buildCustomServerConfig, buildPresetServerConfig, inferConfiguredBind } from "../config/server-bind.js";
|
|
|
|
const TAILNET_BIND_WARNING =
|
|
"No Tailscale address was detected during setup. The saved config will stay on loopback until Tailscale is available or PAPERCLIP_TAILNET_BIND_HOST is set.";
|
|
|
|
function cancelled(): never {
|
|
p.cancel("Setup cancelled.");
|
|
process.exit(0);
|
|
}
|
|
|
|
export async function promptServer(opts?: {
|
|
currentServer?: Partial<ServerConfig>;
|
|
currentAuth?: Partial<AuthConfig>;
|
|
}): Promise<{ server: ServerConfig; auth: AuthConfig }> {
|
|
const currentServer = opts?.currentServer;
|
|
const currentAuth = opts?.currentAuth;
|
|
const currentBind = inferConfiguredBind(currentServer);
|
|
|
|
const bindSelection = await p.select({
|
|
message: "Reachability",
|
|
options: [
|
|
{
|
|
value: "loopback" as const,
|
|
label: "Trusted local",
|
|
hint: "Recommended for first run: localhost only, no login friction",
|
|
},
|
|
{
|
|
value: "lan" as const,
|
|
label: "Private network",
|
|
hint: "Broad private bind for LAN, VPN, or legacy --tailscale-auth style access",
|
|
},
|
|
{
|
|
value: "tailnet" as const,
|
|
label: "Tailnet",
|
|
hint: "Private authenticated access using the machine's detected Tailscale address",
|
|
},
|
|
{
|
|
value: "custom" as const,
|
|
label: "Custom",
|
|
hint: "Choose exact auth mode, exposure, and host manually",
|
|
},
|
|
],
|
|
initialValue: currentBind,
|
|
});
|
|
|
|
if (p.isCancel(bindSelection)) cancelled();
|
|
const bind = bindSelection as BindMode;
|
|
|
|
const portStr = await p.text({
|
|
message: "Server port",
|
|
defaultValue: String(currentServer?.port ?? 3100),
|
|
placeholder: "3100",
|
|
validate: (val) => {
|
|
const n = Number(val);
|
|
if (isNaN(n) || n < 1 || n > 65535 || !Number.isInteger(n)) {
|
|
return "Must be an integer between 1 and 65535";
|
|
}
|
|
},
|
|
});
|
|
|
|
if (p.isCancel(portStr)) cancelled();
|
|
const port = Number(portStr) || 3100;
|
|
const serveUi = currentServer?.serveUi ?? true;
|
|
|
|
if (bind === "loopback") {
|
|
return buildPresetServerConfig("loopback", {
|
|
port,
|
|
allowedHostnames: [],
|
|
serveUi,
|
|
});
|
|
}
|
|
|
|
if (bind === "lan" || bind === "tailnet") {
|
|
const allowedHostnamesInput = await p.text({
|
|
message: "Allowed private hostnames (comma-separated, optional)",
|
|
defaultValue: (currentServer?.allowedHostnames ?? []).join(", "),
|
|
placeholder:
|
|
bind === "tailnet"
|
|
? "your-machine.tailnet.ts.net"
|
|
: "dotta-macbook-pro, host.docker.internal",
|
|
validate: (val) => {
|
|
try {
|
|
parseHostnameCsv(val ?? "");
|
|
return;
|
|
} catch (err) {
|
|
return err instanceof Error ? err.message : "Invalid hostname list";
|
|
}
|
|
},
|
|
});
|
|
|
|
if (p.isCancel(allowedHostnamesInput)) cancelled();
|
|
|
|
const preset = buildPresetServerConfig(bind, {
|
|
port,
|
|
allowedHostnames: parseHostnameCsv(allowedHostnamesInput),
|
|
serveUi,
|
|
});
|
|
if (bind === "tailnet" && isLoopbackHost(preset.server.host)) {
|
|
p.log.warn(TAILNET_BIND_WARNING);
|
|
}
|
|
return preset;
|
|
}
|
|
|
|
const deploymentModeSelection = await p.select({
|
|
message: "Auth mode",
|
|
options: [
|
|
{
|
|
value: "local_trusted",
|
|
label: "Local trusted",
|
|
hint: "No login required; only safe with loopback-only or similarly trusted access",
|
|
},
|
|
{
|
|
value: "authenticated",
|
|
label: "Authenticated",
|
|
hint: "Login required; supports both private-network and public deployments",
|
|
},
|
|
],
|
|
initialValue: currentServer?.deploymentMode ?? "authenticated",
|
|
});
|
|
|
|
if (p.isCancel(deploymentModeSelection)) cancelled();
|
|
const deploymentMode = deploymentModeSelection as ServerConfig["deploymentMode"];
|
|
|
|
let exposure: ServerConfig["exposure"] = "private";
|
|
if (deploymentMode === "authenticated") {
|
|
const exposureSelection = await p.select({
|
|
message: "Exposure profile",
|
|
options: [
|
|
{
|
|
value: "private",
|
|
label: "Private network",
|
|
hint: "Private access only, with automatic URL handling",
|
|
},
|
|
{
|
|
value: "public",
|
|
label: "Public internet",
|
|
hint: "Internet-facing deployment with explicit public URL requirements",
|
|
},
|
|
],
|
|
initialValue: currentServer?.exposure ?? "private",
|
|
});
|
|
if (p.isCancel(exposureSelection)) cancelled();
|
|
exposure = exposureSelection as ServerConfig["exposure"];
|
|
}
|
|
|
|
const defaultHost =
|
|
currentServer?.customBindHost ??
|
|
currentServer?.host ??
|
|
(deploymentMode === "local_trusted" ? "127.0.0.1" : "0.0.0.0");
|
|
const host = await p.text({
|
|
message: "Bind host",
|
|
defaultValue: defaultHost,
|
|
placeholder: defaultHost,
|
|
validate: (val) => {
|
|
if (!val || !val.trim()) return "Host is required";
|
|
if (deploymentMode === "local_trusted" && !isLoopbackHost(val.trim())) {
|
|
return "Local trusted mode requires a loopback host such as 127.0.0.1";
|
|
}
|
|
},
|
|
});
|
|
|
|
if (p.isCancel(host)) cancelled();
|
|
|
|
let allowedHostnames: string[] = [];
|
|
if (deploymentMode === "authenticated" && exposure === "private") {
|
|
const allowedHostnamesInput = await p.text({
|
|
message: "Allowed private hostnames (comma-separated, optional)",
|
|
defaultValue: (currentServer?.allowedHostnames ?? []).join(", "),
|
|
placeholder: "dotta-macbook-pro, your-host.tailnet.ts.net",
|
|
validate: (val) => {
|
|
try {
|
|
parseHostnameCsv(val ?? "");
|
|
return;
|
|
} catch (err) {
|
|
return err instanceof Error ? err.message : "Invalid hostname list";
|
|
}
|
|
},
|
|
});
|
|
|
|
if (p.isCancel(allowedHostnamesInput)) cancelled();
|
|
allowedHostnames = parseHostnameCsv(allowedHostnamesInput);
|
|
}
|
|
|
|
let publicBaseUrl: string | undefined;
|
|
if (deploymentMode === "authenticated" && exposure === "public") {
|
|
const urlInput = await p.text({
|
|
message: "Public base URL",
|
|
defaultValue: currentAuth?.publicBaseUrl ?? "",
|
|
placeholder: "https://paperclip.example.com",
|
|
validate: (val) => {
|
|
const candidate = val?.trim() ?? "";
|
|
if (!candidate) return "Public base URL is required for public exposure";
|
|
try {
|
|
const url = new URL(candidate);
|
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
return "URL must start with http:// or https://";
|
|
}
|
|
return;
|
|
} catch {
|
|
return "Enter a valid URL";
|
|
}
|
|
},
|
|
});
|
|
if (p.isCancel(urlInput)) cancelled();
|
|
publicBaseUrl = urlInput.trim().replace(/\/+$/, "");
|
|
}
|
|
|
|
return buildCustomServerConfig({
|
|
deploymentMode,
|
|
exposure,
|
|
host: host.trim(),
|
|
port,
|
|
allowedHostnames,
|
|
serveUi,
|
|
publicBaseUrl,
|
|
});
|
|
}
|