camstack 1.2.185 → 1.2.186

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 CHANGED
@@ -37,7 +37,7 @@ async function runServe(args) {
37
37
  ...typeof values.data === "string" ? { data: values.data } : {}
38
38
  };
39
39
  Object.assign(process.env, buildServeEnv(opts));
40
- await import("./launcher-6Q2JLZCB.js");
40
+ await import("./launcher-3LWROJEJ.js");
41
41
  }
42
42
 
43
43
  // src/commands/agent.ts
@@ -82,7 +82,7 @@ async function runAgent(args) {
82
82
  ...typeof values.port === "string" ? { port: values.port } : {}
83
83
  };
84
84
  Object.assign(process.env, buildAgentEnv(opts));
85
- await import("./launcher-6Q2JLZCB.js");
85
+ await import("./launcher-3LWROJEJ.js");
86
86
  }
87
87
 
88
88
  // src/commands/setup.ts
@@ -14769,7 +14769,7 @@ function date4(params) {
14769
14769
  // ../../node_modules/zod/v4/classic/external.js
14770
14770
  config(en_default());
14771
14771
 
14772
- // ../types/dist/sleep-Tkp9dHXv.mjs
14772
+ // ../types/dist/sleep-BjDbnx6-.mjs
14773
14773
  var AUDIO_CHUNK_FORMATS = [
14774
14774
  "f32le",
14775
14775
  "pcmu",
@@ -24841,14 +24841,6 @@ var HUB_ADDRESS_ROLES = [
24841
24841
  "internal",
24842
24842
  "publicEndpoint"
24843
24843
  ];
24844
- var HUB_MDNS_QUERY_NAME = "_camstack._tcp.local";
24845
- var HUB_MDNS_TXT_KEYS = {
24846
- nodeId: "nodeId",
24847
- version: "version",
24848
- role: "role",
24849
- url: "url"
24850
- };
24851
- var HUB_MDNS_ROLE = "hub";
24852
24844
  var AI_CAP_TRANSPORT_TIMEOUT_MS = 6e5;
24853
24845
  var AI_MODEL_INSTALL_TIMEOUT_MS = 60 * 6e4;
24854
24846
  var LlmUsageSchema = external_exports.object({
@@ -63958,12 +63950,31 @@ async function createAndStoreAdminToken(req) {
63958
63950
  }
63959
63951
  }
63960
63952
 
63953
+ // src/commands/login-server.ts
63954
+ import { normalizeHubAddress } from "@camstack/develop";
63955
+ function resolveLoginServer(flag, positionals, env) {
63956
+ if (positionals.length > 1) {
63957
+ throw new Error(`login takes one hub address, got: ${positionals.join(" ")}`);
63958
+ }
63959
+ const flagged = flag === void 0 ? void 0 : normalizeHubAddress(flag);
63960
+ const positional = positionals[0] === void 0 ? void 0 : normalizeHubAddress(positionals[0]);
63961
+ if (flagged && positional && flagged !== positional) {
63962
+ throw new Error(
63963
+ `login got two different hubs: ${positional} (argument) and ${flagged} (--server).`
63964
+ );
63965
+ }
63966
+ const fromEnv = env["CAMSTACK_SERVER"]?.trim() || env["CAMSTACK_HUB_URL"]?.trim();
63967
+ return flagged ?? positional ?? (fromEnv ? normalizeHubAddress(fromEnv) : void 0);
63968
+ }
63969
+
63961
63970
  // src/commands/auth.ts
63962
63971
  import * as os4 from "os";
63963
63972
  import * as clack from "@clack/prompts";
63964
63973
  import {
63965
63974
  adminTokenStatus,
63966
63975
  clearSession,
63976
+ defaultSession,
63977
+ listSessions,
63967
63978
  loadSession,
63968
63979
  saveSession
63969
63980
  } from "@camstack/develop";
@@ -63971,125 +63982,19 @@ import {
63971
63982
  // src/discovery/hub-finder.ts
63972
63983
  import * as fs5 from "fs";
63973
63984
  import * as path5 from "path";
63974
- import { defaultSessionDir, isSessionFile, resolveHubUrl } from "@camstack/develop";
63975
-
63976
- // src/discovery/mdns-browse.ts
63977
- import makeMdns from "multicast-dns";
63978
- function createRealMdnsSocket() {
63979
- const socket = makeMdns();
63980
- return {
63981
- onResponse: (listener) => {
63982
- socket.on("response", (packet, rinfo) => {
63983
- const records = [];
63984
- for (const a of [...packet.answers, ...packet.additionals]) {
63985
- if (a.type === "PTR") records.push({ kind: "ptr", name: a.name, target: a.data });
63986
- else if (a.type === "A") records.push({ kind: "a", name: a.name, address: a.data });
63987
- else if (a.type === "SRV")
63988
- records.push({ kind: "srv", name: a.name, port: a.data.port, target: a.data.target });
63989
- else if (a.type === "TXT") {
63990
- const raw = Array.isArray(a.data) ? a.data : [a.data];
63991
- records.push({ kind: "txt", name: a.name, entries: raw.map((e) => e.toString()) });
63992
- }
63993
- }
63994
- listener({ records, from: rinfo.address });
63995
- });
63996
- },
63997
- onError: (listener) => {
63998
- socket.on("error", listener);
63999
- },
64000
- query: (name) => socket.query({ questions: [{ name, type: "PTR" }] }),
64001
- destroy: () => socket.destroy()
64002
- };
64003
- }
64004
- function parseTxt(entries2) {
64005
- const out = /* @__PURE__ */ new Map();
64006
- for (const entry of entries2) {
64007
- const at = entry.indexOf("=");
64008
- if (at > 0) out.set(entry.slice(0, at), entry.slice(at + 1));
64009
- }
64010
- return out;
64011
- }
64012
- function originOf(value) {
64013
- if (value === void 0) return null;
64014
- try {
64015
- const u = new URL(value);
64016
- return u.protocol === "https:" ? u.origin : null;
64017
- } catch {
64018
- return null;
64019
- }
64020
- }
64021
- function hubsFromResponses(responses) {
64022
- const found = /* @__PURE__ */ new Map();
64023
- for (const { records, from } of responses) {
64024
- for (const ptr of records) {
64025
- if (ptr.kind !== "ptr") continue;
64026
- const srv = records.find((r) => r.kind === "srv" && r.name === ptr.target);
64027
- if (srv?.kind !== "srv") continue;
64028
- const txtRecord = records.find((r) => r.kind === "txt" && r.name === ptr.target);
64029
- const txt = txtRecord?.kind === "txt" ? parseTxt(txtRecord.entries) : /* @__PURE__ */ new Map();
64030
- const role = txt.get(HUB_MDNS_TXT_KEYS.role);
64031
- if (role !== void 0 && role !== HUB_MDNS_ROLE) continue;
64032
- const a = records.find((r) => r.kind === "a" && r.name === srv.target);
64033
- const host = a?.kind === "a" ? a.address : from;
64034
- const url2 = originOf(txt.get(HUB_MDNS_TXT_KEYS.url)) ?? `https://${host}:${srv.port}`;
64035
- found.set(url2, {
64036
- url: url2,
64037
- nodeId: txt.get(HUB_MDNS_TXT_KEYS.nodeId) ?? null,
64038
- version: txt.get(HUB_MDNS_TXT_KEYS.version) ?? null
64039
- });
64040
- }
64041
- }
64042
- return [...found.values()];
64043
- }
64044
- async function browseHubsMdns(options) {
64045
- const responses = [];
64046
- const problem = (error51) => options.onProblem?.(error51 instanceof Error ? error51.message : String(error51));
64047
- let socket;
64048
- try {
64049
- socket = (options.createSocket ?? createRealMdnsSocket)();
64050
- } catch (err) {
64051
- problem(err);
64052
- return [];
64053
- }
64054
- let requery = null;
64055
- try {
64056
- socket.onResponse((r) => responses.push(r));
64057
- socket.onError(problem);
64058
- socket.query(HUB_MDNS_QUERY_NAME);
64059
- requery = setInterval(() => socket.query(HUB_MDNS_QUERY_NAME), options.requeryMs ?? 1e3);
64060
- await new Promise((resolve6) => setTimeout(resolve6, options.timeoutMs));
64061
- } catch (err) {
64062
- problem(err);
64063
- } finally {
64064
- if (requery !== null) clearInterval(requery);
64065
- socket.destroy();
64066
- }
64067
- return hubsFromResponses(responses);
64068
- }
64069
-
64070
- // src/discovery/hub-finder.ts
63985
+ import {
63986
+ defaultSessionDir,
63987
+ isSessionFile,
63988
+ resolveHubUrl,
63989
+ validateHubAddress
63990
+ } from "@camstack/develop";
63991
+ import {
63992
+ discoverHubs,
63993
+ normalizeHubUrl
63994
+ } from "@camstack/develop/hub-discovery";
64071
63995
  var ADMIN_TOKEN_SUFFIX = ".admin-token";
64072
- var DEFAULT_HTTPS_PORT = 443;
64073
- var MDNS_LABEL = "LAN (mDNS)";
64074
- function normalizeHubUrl(value) {
64075
- let parsed;
64076
- try {
64077
- parsed = new URL(value.trim());
64078
- } catch {
64079
- return null;
64080
- }
64081
- if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return null;
64082
- if (parsed.hostname === "") return null;
64083
- const port = parsed.port === "" ? DEFAULT_HTTPS_PORT : Number.parseInt(parsed.port, 10);
64084
- const host = parsed.hostname.replace(/^\[|\]$/g, "");
64085
- const shown = host.includes(":") ? `[${host}]` : host;
64086
- return { url: `https://${shown}:${port}`, host, port };
64087
- }
64088
63996
  function validateManualHubUrl(value) {
64089
- const trimmed = value.trim();
64090
- if (!trimmed.startsWith("https://"))
64091
- return "Enter an https:// address, e.g. https://192.168.1.9:4443";
64092
- return normalizeHubUrl(trimmed) === null ? "That is not a valid URL." : void 0;
63997
+ return validateHubAddress(value);
64093
63998
  }
64094
63999
  function hubUrlFromAdminTokenFile(fileName) {
64095
64000
  if (!fileName.endsWith(ADMIN_TOKEN_SUFFIX)) return null;
@@ -64113,7 +64018,10 @@ function knownHubCandidates(deps) {
64113
64018
  try {
64114
64019
  const parsed = JSON.parse(fs5.readFileSync(path5.join(dir, file2), "utf8"));
64115
64020
  if (isSessionFile(parsed)) {
64116
- out.push({ url: parsed.server, source: `saved session ${parsed.username}` });
64021
+ out.push({
64022
+ url: parsed.server,
64023
+ source: `saved session ${parsed.username}`
64024
+ });
64117
64025
  }
64118
64026
  } catch {
64119
64027
  }
@@ -64128,94 +64036,46 @@ function knownHubCandidates(deps) {
64128
64036
  out.push({ url: fromEnv.url, source: name });
64129
64037
  }
64130
64038
  if (deps.workspaceRoot !== void 0) {
64131
- const scratch = resolveHubUrl({ env: {}, workspaceRoot: deps.workspaceRoot, session: null });
64039
+ const scratch = resolveHubUrl({
64040
+ env: {},
64041
+ workspaceRoot: deps.workspaceRoot,
64042
+ session: null
64043
+ });
64132
64044
  if (scratch) out.push({ url: scratch.url, source: "scratchpad/.hub-url" });
64133
64045
  }
64134
64046
  return out;
64135
64047
  }
64136
- function mergeCandidates(raw) {
64137
- const merged = /* @__PURE__ */ new Map();
64138
- for (const r of raw) {
64139
- const n = normalizeHubUrl(r.url);
64140
- if (n === null) continue;
64141
- const key = `${n.host}:${n.port}`;
64142
- const prev = merged.get(key);
64143
- merged.set(key, {
64144
- url: n.url,
64145
- host: n.host,
64146
- port: n.port,
64147
- nodeId: prev?.nodeId ?? r.nodeId ?? null,
64148
- version: prev?.version ?? r.version ?? null,
64149
- sources: prev?.sources.includes(r.source) ? prev.sources : [...prev?.sources ?? [], r.source]
64150
- });
64151
- }
64152
- return [...merged.values()];
64153
- }
64154
64048
  async function findHubs(deps = {}) {
64155
- const browse = deps.browse ?? browseHubsMdns;
64156
- const probe = deps.probe ?? probeHttps;
64157
- const announced = await browse({
64158
- timeoutMs: deps.mdnsTimeoutMs ?? 3e3,
64049
+ return discoverHubs({
64050
+ known: knownHubCandidates(deps),
64051
+ ...deps.browse ? { browse: deps.browse } : {},
64052
+ ...deps.probe ? { probe: deps.probe } : {},
64053
+ ...deps.mdnsTimeoutMs !== void 0 ? { mdnsTimeoutMs: deps.mdnsTimeoutMs } : {},
64159
64054
  ...deps.onProblem ? { onProblem: deps.onProblem } : {}
64160
64055
  });
64161
- const raw = [
64162
- ...announced.map((h) => ({
64163
- url: h.url,
64164
- source: MDNS_LABEL,
64165
- nodeId: h.nodeId,
64166
- version: h.version
64167
- })),
64168
- ...knownHubCandidates(deps)
64169
- ];
64170
- const candidates = mergeCandidates(raw);
64171
- const verdicts = await Promise.all(candidates.map((c) => probe(c.host, c.port)));
64172
- return candidates.filter((_, i) => verdicts[i] === true);
64173
64056
  }
64174
64057
  function describeHub(hub) {
64175
64058
  const identity = [hub.nodeId, hub.version === null ? null : `v${hub.version}`].filter((p) => p !== null).join(" ");
64176
64059
  return `${hub.url}${identity === "" ? "" : ` ${identity}`} (${hub.sources.join(", ")})`;
64177
64060
  }
64178
- async function probeHttps(host, port) {
64179
- const { request: request3 } = await import("https");
64180
- return new Promise((resolve6) => {
64181
- const req = request3(
64182
- {
64183
- host,
64184
- port,
64185
- method: "HEAD",
64186
- path: "/trpc/health",
64187
- timeout: 1500,
64188
- rejectUnauthorized: false
64189
- },
64190
- (res) => {
64191
- resolve6(typeof res.statusCode === "number");
64192
- res.resume();
64193
- }
64194
- );
64195
- req.on("error", () => resolve6(false));
64196
- req.on("timeout", () => {
64197
- req.destroy();
64198
- resolve6(false);
64199
- });
64200
- req.end();
64201
- });
64202
- }
64203
64061
 
64204
64062
  // src/discovery/hub-picker.ts
64063
+ import { normalizeHubAddress as normalizeHubAddress2 } from "@camstack/develop";
64205
64064
  var MANUAL_ENTRY_VALUE = "__manual__";
64206
64065
  var MANUAL_ENTRY_LABEL = "Enter an address\u2026";
64207
64066
  var NO_HUB_MESSAGE = "No camstack hub found on this network (mDNS) or among the hubs this machine knows. Pass --server https://<host>:<port>, and check the hub is reachable from here.";
64208
64067
  async function pickHub(hubs, prompts) {
64209
- const [only, ...rest] = hubs;
64210
- if (only === void 0) throw new Error(NO_HUB_MESSAGE);
64211
- if (rest.length === 0) return only.url;
64068
+ if (hubs.length === 0) throw new Error(NO_HUB_MESSAGE);
64212
64069
  const chosen = await prompts.select("Select a hub to log into", [
64213
64070
  ...hubs.map((h) => ({ value: h.url, label: describeHub(h) })),
64214
64071
  { value: MANUAL_ENTRY_VALUE, label: MANUAL_ENTRY_LABEL }
64215
64072
  ]);
64216
64073
  if (chosen !== MANUAL_ENTRY_VALUE) return chosen;
64217
- const typed = await prompts.text("Hub address (https://host:port)", validateManualHubUrl);
64218
- return typed.trim().replace(/\/+$/, "");
64074
+ const typed = await prompts.text(
64075
+ "Hub address (host, host:port or https://host:port)",
64076
+ validateManualHubUrl
64077
+ );
64078
+ return normalizeHubAddress2(typed);
64219
64079
  }
64220
64080
 
64221
64081
  // src/commands/auth.ts
@@ -64251,7 +64111,9 @@ async function askSelect(message, options) {
64251
64111
  return result;
64252
64112
  }
64253
64113
  async function callTrpcMutation(url2, authorization, payload, isPayload) {
64254
- const headers = { "Content-Type": "application/json" };
64114
+ const headers = {
64115
+ "Content-Type": "application/json"
64116
+ };
64255
64117
  if (authorization) headers["Authorization"] = authorization;
64256
64118
  const res = await hubRequest(url2, {
64257
64119
  method: "POST",
@@ -64344,7 +64206,10 @@ async function resolveServerInteractive() {
64344
64206
  return pickHub(hubs, {
64345
64207
  select: askSelect,
64346
64208
  text: async (message, validate) => {
64347
- const result = await clack.text({ message, validate: (value) => validate(value ?? "") });
64209
+ const result = await clack.text({
64210
+ message,
64211
+ validate: (value) => validate(value ?? "")
64212
+ });
64348
64213
  if (clack.isCancel(result)) {
64349
64214
  clack.cancel("Cancelled.");
64350
64215
  process.exit(130);
@@ -64546,7 +64411,30 @@ function describeAdminToken(server) {
64546
64411
  }
64547
64412
  return status.expiresAt === void 0 ? "admin token present (expiry unknown)" : `admin token present, expires ${new Date(status.expiresAt).toISOString()}`;
64548
64413
  }
64414
+ function formatSessionList(sessions, defaultServer, describeAdmin) {
64415
+ const lines = [
64416
+ `[camstack] ${sessions.length} saved sessions (* = used when no --server is given):`
64417
+ ];
64418
+ for (const s of sessions) {
64419
+ const mark = s.server === defaultServer ? "*" : " ";
64420
+ const scopes = s.scopes.map((x) => `${x.type}:${x.target}`).join(", ");
64421
+ lines.push(`${mark} ${s.server}`);
64422
+ lines.push(` user: ${s.username} scopes: ${scopes}`);
64423
+ lines.push(` last used: ${new Date(s.lastUsedAt ?? s.createdAt).toISOString()}`);
64424
+ lines.push(` admin: ${describeAdmin(s.server)}`);
64425
+ }
64426
+ lines.push("Default: $CAMSTACK_SERVER if set, else the most recently used session.");
64427
+ lines.push("Pick another with `camstack whoami --server <host>`.");
64428
+ return lines.join("\n");
64429
+ }
64549
64430
  async function whoamiCommand(opts) {
64431
+ if (!opts.server) {
64432
+ const sessions = listSessions();
64433
+ if (sessions.length > 1) {
64434
+ console.log(formatSessionList(sessions, defaultSession(sessions)?.server, describeAdminToken));
64435
+ return;
64436
+ }
64437
+ }
64550
64438
  const session = loadSession(opts.server);
64551
64439
  if (!session) {
64552
64440
  console.log(`[camstack] Not logged in${opts.server ? ` to ${opts.server}` : ""}.`);
@@ -64600,6 +64488,8 @@ async function whoamiCommand(opts) {
64600
64488
  import {
64601
64489
  loadSession as loadSession4,
64602
64490
  MissingCredentialsError,
64491
+ normalizeHubAddress as normalizeHubAddress3,
64492
+ touchSession as touchSession3,
64603
64493
  resolveCredentials as resolveCredentials3
64604
64494
  } from "@camstack/develop";
64605
64495
 
@@ -64847,7 +64737,7 @@ import * as fs7 from "fs";
64847
64737
  import * as path7 from "path";
64848
64738
  import { parseArgs as parseArgs6 } from "util";
64849
64739
  import * as clack3 from "@clack/prompts";
64850
- import { loadSession as loadSession2, resolveCredentials } from "@camstack/develop";
64740
+ import { loadSession as loadSession2, resolveCredentials, touchSession } from "@camstack/develop";
64851
64741
  var DEFAULT_DEBOUNCE_MS = 500;
64852
64742
  var DEFAULT_WATCH_SUBDIR = "src";
64853
64743
  function resolveAddonDir(arg) {
@@ -64920,6 +64810,7 @@ async function runDev(args) {
64920
64810
  loadSession: loadSession2
64921
64811
  });
64922
64812
  if (creds.warning) console.error(`[camstack dev] Warning: ${creds.warning}`);
64813
+ if (creds.source === "session" && creds.server) touchSession(creds.server);
64923
64814
  const serverUrl = creds.server;
64924
64815
  const token = creds.token;
64925
64816
  if (!serverUrl) {
@@ -65000,6 +64891,7 @@ import { parseArgs as parseArgs7 } from "util";
65000
64891
  import * as clack4 from "@clack/prompts";
65001
64892
  import {
65002
64893
  loadSession as loadSession3,
64894
+ touchSession as touchSession2,
65003
64895
  resolveCredentials as resolveCredentials2,
65004
64896
  withAuthHint as withAuthHint3
65005
64897
  } from "@camstack/develop";
@@ -65034,7 +64926,9 @@ function printLine(e, addonId) {
65034
64926
  async function fetchLogs(server, token, addonId, limit, authSource) {
65035
64927
  const input = encodeURIComponent(JSON.stringify({ json: { addonId, limit } }));
65036
64928
  const url2 = `${server}/trpc/addons.getLogs?input=${input}`;
65037
- const res = await hubRequest(url2, { headers: { Authorization: `Bearer ${token}` } });
64929
+ const res = await hubRequest(url2, {
64930
+ headers: { Authorization: `Bearer ${token}` }
64931
+ });
65038
64932
  if (!res.ok) {
65039
64933
  const text2 = await res.text().catch(() => "");
65040
64934
  throw new Error(
@@ -65069,6 +64963,7 @@ async function runWatch(args) {
65069
64963
  loadSession: loadSession3
65070
64964
  });
65071
64965
  if (creds.warning) console.error(`[camstack watch] Warning: ${creds.warning}`);
64966
+ if (creds.source === "session" && creds.server) touchSession2(creds.server);
65072
64967
  const serverUrl = creds.server;
65073
64968
  const token = creds.token;
65074
64969
  if (!serverUrl) {
@@ -65558,15 +65453,21 @@ function buildCommands() {
65558
65453
  summary: "Authenticate and cache a long-lived upload-only token at ~/.camstack/<host>.json",
65559
65454
  run: runLogin,
65560
65455
  help: () => [
65561
- "Usage: camstack login [options]",
65456
+ "Usage: camstack login [<host>] [options]",
65457
+ "",
65458
+ " <host> The hub, same as --server: 192.168.1.50, hub.local:4443,",
65459
+ " https://hub.local, [fe80::1]:4443. Port defaults to 4443, scheme is",
65460
+ " https (http:// is refused). Examples: camstack login 192.168.1.50",
65461
+ " camstack login --admin 192.168.1.50",
65562
65462
  "",
65563
65463
  "Default flow (no flags): finds the hub from what the LAN announces over mDNS",
65564
65464
  " plus the hubs this machine knows (saved sessions, admin tokens, $CAMSTACK_HUB_URL),",
65565
- " then prompts for user + password. One reachable hub is used automatically;",
65566
- ' several show a picker with the source of each and an "Enter an address\u2026" entry.',
65465
+ " then prompts for user + password. Found hubs show a picker (the first, the default, is",
65466
+ ' one Enter away) with the source of each and an "Enter an address\u2026" entry, so a hub',
65467
+ " that does not announce is still reachable. A given <host>/--server skips all of it.",
65567
65468
  "",
65568
65469
  "Options (all optional):",
65569
- " -s, --server <url> Skip discovery, use this URL directly ($CAMSTACK_SERVER)",
65470
+ " -s, --server <host> Skip discovery, use this hub ($CAMSTACK_SERVER, then $CAMSTACK_HUB_URL)",
65570
65471
  " -n, --namespace <ns> Ignored (kept so old scripts do not fail): hubs are found over mDNS",
65571
65472
  " -u, --username <name> Username (skips prompt)",
65572
65473
  " -p, --password <pwd> Password (skips prompt \u2014 prefer letting the CLI prompt)",
@@ -65602,7 +65503,7 @@ function buildCommands() {
65602
65503
  "Usage: camstack logout [options]",
65603
65504
  "",
65604
65505
  "Options:",
65605
- " -s, --server <url> CamStack server URL (default: $CAMSTACK_SERVER or https://localhost:4443)"
65506
+ " -s, --server <host> CamStack server URL (default: $CAMSTACK_SERVER or https://localhost:4443; a bare host or host:port is fine)"
65606
65507
  ].join("\n")
65607
65508
  },
65608
65509
  {
@@ -65612,8 +65513,12 @@ function buildCommands() {
65612
65513
  help: () => [
65613
65514
  "Usage: camstack whoami [options]",
65614
65515
  "",
65516
+ "With one saved session, prints it and checks the token against the hub. With several and",
65517
+ "no --server, lists them all (server, user, scopes, admin token) and marks the default:",
65518
+ "$CAMSTACK_SERVER if set, else the most recently used session.",
65519
+ "",
65615
65520
  "Options:",
65616
- " -s, --server <url> Pick a specific session (default: most recently used)"
65521
+ " -s, --server <host> Show one session (192.168.1.50, hub.local:4443, https://host)"
65617
65522
  ].join("\n")
65618
65523
  },
65619
65524
  {
@@ -65643,7 +65548,7 @@ function buildCommands() {
65643
65548
  " --no-verify Skip post-deploy verify / promotion poll",
65644
65549
  "",
65645
65550
  "Target options (addon and --closure):",
65646
- " -s, --server <url> Hub URL (default: $CAMSTACK_SERVER, then the cached session)",
65551
+ " -s, --server <host> Hub URL (default: $CAMSTACK_SERVER, then the cached session)",
65647
65552
  " -t, --token <token> Auth token override",
65648
65553
  " --token-file <path> Read the token from a file (bare token or a ~/.camstack session file)",
65649
65554
  " -n, --node <id> Target one agent. Mutually exclusive with --cluster",
@@ -65664,7 +65569,7 @@ function buildCommands() {
65664
65569
  "Deprecated alias of `camstack deploy --closure`. Prefer that form.",
65665
65570
  "",
65666
65571
  "Options:",
65667
- " -s, --server <url> Hub URL",
65572
+ " -s, --server <host> Hub URL",
65668
65573
  " -t, --token <token> Auth token override",
65669
65574
  " --token-file <path> Read the token from a file",
65670
65575
  " -n, --node <id> Propagate+apply on this agent. Mutually exclusive with --cluster/--all",
@@ -65687,7 +65592,7 @@ function buildCommands() {
65687
65592
  " path Addon dir / workspace name / `.` for 5-level scan",
65688
65593
  "",
65689
65594
  "Options:",
65690
- " -s, --server <url> Server URL (default: cached session)",
65595
+ " -s, --server <host> Server URL (default: cached session)",
65691
65596
  " -t, --token <token> Auth token override",
65692
65597
  " --token-file <path> Read the token from a file",
65693
65598
  " -n, --node <id> Push to a specific node",
@@ -65723,7 +65628,7 @@ function buildCommands() {
65723
65628
  " --build-script <n> Override script name (default: build)",
65724
65629
  "",
65725
65630
  "Target options:",
65726
- " -s, --server <url> Server URL (default: cached session)",
65631
+ " -s, --server <host> Server URL (default: cached session)",
65727
65632
  " -t, --token <token> Auth token override",
65728
65633
  " --token-file <path> Read the token from a file",
65729
65634
  " -n, --node <id> Push to a specific node",
@@ -65803,13 +65708,17 @@ async function runLogin(args) {
65803
65708
  // never errors with "Unknown option --no-verify".
65804
65709
  "no-verify": { type: "boolean" }
65805
65710
  },
65806
- false
65711
+ true
65807
65712
  );
65808
65713
  if (!parsed) {
65809
65714
  console.log(commandHelp("login"));
65810
65715
  return;
65811
65716
  }
65812
- const explicitServer = stringOpt(parsed.values, "server") ?? process.env.CAMSTACK_SERVER;
65717
+ const explicitServer = resolveLoginServer(
65718
+ stringOpt(parsed.values, "server"),
65719
+ parsed.positionals,
65720
+ process.env
65721
+ );
65813
65722
  if (stringOpt(parsed.values, "namespace") !== void 0) {
65814
65723
  console.warn("--namespace is ignored: hubs are found over mDNS, not the mesh channel.");
65815
65724
  }
@@ -65839,7 +65748,9 @@ async function runLogout(args) {
65839
65748
  console.log(commandHelp("logout"));
65840
65749
  return;
65841
65750
  }
65842
- const server = stringOpt(parsed.values, "server") ?? process.env.CAMSTACK_SERVER ?? "https://localhost:4443";
65751
+ const server = normalizeHubAddress3(
65752
+ stringOpt(parsed.values, "server") ?? process.env.CAMSTACK_SERVER ?? DEFAULT_SERVER_URL
65753
+ );
65843
65754
  await logoutCommand({ server });
65844
65755
  }
65845
65756
  async function runWhoami(args) {
@@ -65855,7 +65766,7 @@ async function runWhoami(args) {
65855
65766
  return;
65856
65767
  }
65857
65768
  const server = stringOpt(parsed.values, "server");
65858
- await whoamiCommand(server ? { server } : {});
65769
+ await whoamiCommand(server ? { server: normalizeHubAddress3(server) } : {});
65859
65770
  }
65860
65771
  function resolveClosureDeployOpts(values) {
65861
65772
  const nodeId = stringOpt(values, "node");
@@ -65978,6 +65889,7 @@ function resolveCommandCredentials(values) {
65978
65889
  loadSession: loadSession4
65979
65890
  });
65980
65891
  if (creds.warning) console.error(`[camstack] Warning: ${creds.warning}`);
65892
+ if (creds.source === "session" && creds.server) touchSession3(creds.server);
65981
65893
  return creds;
65982
65894
  } catch (err) {
65983
65895
  if (err instanceof MissingCredentialsError) {