@agent-team-foundation/first-tree-hub 0.10.9 → 0.10.11

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.
@@ -585,11 +585,14 @@ const serverConfigSchema = defineConfig({
585
585
  })
586
586
  }) }),
587
587
  cors: optional({ origin: field(z.string(), { env: "FIRST_TREE_HUB_CORS_ORIGIN" }) }),
588
+ trustProxy: field(z.boolean().default(false), { env: "FIRST_TREE_HUB_TRUST_PROXY" }),
588
589
  rateLimit: optional({
589
590
  max: field(z.number().default(100), { env: "FIRST_TREE_HUB_RATE_LIMIT_MAX" }),
590
591
  loginMax: field(z.number().default(5), { env: "FIRST_TREE_HUB_RATE_LIMIT_LOGIN_MAX" }),
591
- webhookMax: field(z.number().default(60), { env: "FIRST_TREE_HUB_RATE_LIMIT_WEBHOOK_MAX" })
592
+ webhookMax: field(z.number().default(60), { env: "FIRST_TREE_HUB_RATE_LIMIT_WEBHOOK_MAX" }),
593
+ agentMessageMax: field(z.number().default(30), { env: "FIRST_TREE_HUB_RATE_LIMIT_AGENT_MESSAGE_MAX" })
592
594
  }),
595
+ ws: optional({ maxPayload: field(z.number().int().min(1024).default(262144), { env: "FIRST_TREE_HUB_WS_MAX_PAYLOAD" }) }),
593
596
  inbox: optional({ maxInFlightPerAgent: field(z.number().int().min(1).max(1024).default(32), { env: "FIRST_TREE_HUB_INBOX_MAX_IN_FLIGHT_PER_AGENT" }) }),
594
597
  kael: optional({
595
598
  endpoint: field(z.string(), { env: "KAEL_ENDPOINT" }),
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import "../observability-DPyf745N-BSc8QNcR.mjs";
3
- import { $ as success, A as checkServerHealth, C as checkAgentConfigs, D as checkDocker, E as checkDatabase, F as getClientServiceStatus, H as stopPostgres, I as installClientService, J as removeLocalAgent, K as findStaleAliases, L as isServiceSupported, M as checkWebSocket, N as printResults, O as checkNodeVersion, P as reconcileAgentConfigs, Q as fail, S as runMigrations, T as checkClientConfig, U as ClientRuntime, W as handleClientOrgMismatch, Y as createOwner, Z as resolveReplyToFromEnv, _ as onboardCreate, a as declineUpdate, at as ClientUserMismatchError, b as createApiNameResolver, c as COMMAND_VERSION, ct as SessionRegistry, d as isInteractive, dt as applyClientLoggerConfig, f as promptAddAgent, ft as configureClientLoggerForService, g as onboardCheck, h as loadOnboardState, i as createExecuteUpdate, it as ClientOrgMismatchError, j as checkServerReachable, k as checkServerConfig, l as reconcileLocalRuntimeProviders, lt as cleanWorkspaces, m as formatCheckReport, nt as setJsonMode, o as promptUpdate, ot as FirstTreeHubSDK, p as promptMissingFields, q as formatStaleReason, r as registerSaaSConnectCommand, s as startServer, st as SdkError, tt as print, u as uploadClientCapabilities, ut as probeCapabilities, v as saveOnboardState, w as checkBackgroundService, x as migrateLocalAgentDirs, y as runHomeMigration } from "../saas-connect-CKQ15VLz.mjs";
3
+ import { $ as findStaleAliases, A as checkDatabase, B as installClientService, C as runHomeMigration, D as checkAgentConfigs, E as runMigrations, F as checkServerReachable, G as stopClientService, I as checkWebSocket, L as printResults, M as checkNodeVersion, N as checkServerConfig, O as checkBackgroundService, P as checkServerHealth, R as reconcileAgentConfigs, S as saveOnboardState, T as migrateLocalAgentDirs, U as restartClientService, V as isServiceSupported, W as startClientService, X as ClientRuntime, Y as stopPostgres, Z as handleClientOrgMismatch, _ as promptMissingFields, _t as probeCapabilities, a as declineUpdate, at as fail, b as onboardCheck, c as detectInstallMode, ct as print, d as startServer, dt as ClientOrgMismatchError, et as formatStaleReason, f as COMMAND_VERSION, ft as ClientUserMismatchError, g as promptAddAgent, gt as cleanWorkspaces, h as isInteractive, ht as SessionRegistry, i as createExecuteUpdate, it as resolveReplyToFromEnv, j as checkDocker, k as checkClientConfig, l as fetchLatestVersion, lt as setJsonMode, m as uploadClientCapabilities, mt as SdkError, nt as createOwner, o as promptUpdate, ot as success, p as reconcileLocalRuntimeProviders, pt as FirstTreeHubSDK, r as registerSaaSConnectCommand, s as PACKAGE_NAME, tt as removeLocalAgent, u as installGlobalLatest, v as formatCheckReport, vt as applyClientLoggerConfig, w as createApiNameResolver, x as onboardCreate, y as loadOnboardState, yt as configureClientLoggerForService, z as getClientServiceStatus } from "../saas-connect-D-7x9KRd.mjs";
4
4
  import "../logger-core-BTmvdflj-DjW8FM4T.mjs";
5
- import { C as serverConfigSchema, S as resolveConfigReadonly, _ as loadAgents, b as resetConfig, c as saveCredentials, d as DEFAULT_HOME_DIR, f as agentConfigSchema, g as initConfig, h as getConfigValue, i as loadCredentials, l as DEFAULT_CONFIG_DIR, n as ensureFreshAccessToken, o as resolveServerUrl, p as clientConfigSchema, r as ensureFreshAdminToken, s as saveAgentConfig, u as DEFAULT_DATA_DIR, w as setConfigValue, x as resetConfigMeta, y as readConfigFile } from "../bootstrap-jx5nN1qZ.mjs";
6
- import "../dist-DSr_I5Ia.mjs";
7
- import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-eynC54km.mjs";
5
+ import { C as serverConfigSchema, S as resolveConfigReadonly, _ as loadAgents, b as resetConfig, c as saveCredentials, d as DEFAULT_HOME_DIR, f as agentConfigSchema, g as initConfig, h as getConfigValue, i as loadCredentials, l as DEFAULT_CONFIG_DIR, n as ensureFreshAccessToken, o as resolveServerUrl, p as clientConfigSchema, r as ensureFreshAdminToken, s as saveAgentConfig, u as DEFAULT_DATA_DIR, w as setConfigValue, x as resetConfigMeta, y as readConfigFile } from "../bootstrap-BTKiVIYk.mjs";
6
+ import "../dist-DwbhZyGi.mjs";
7
+ import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-viiZmwcn.mjs";
8
8
  import "../invitation-B1pjAyOz-BaCA9PII.mjs";
9
9
  import { join } from "node:path";
10
10
  import { existsSync, mkdirSync, readFileSync, readdirSync } from "node:fs";
11
+ import * as semver from "semver";
11
12
  import { Command } from "commander";
12
13
  import { confirm, input, password, select } from "@inquirer/prompts";
13
14
  //#region src/commands/agent-config.ts
@@ -1081,8 +1082,37 @@ function registerConnectCommand(parent) {
1081
1082
  function registerClientCommands(program) {
1082
1083
  const client = program.command("client").description("Client runtime — connect agents to the server");
1083
1084
  registerConnectCommand(client);
1084
- client.command("start").description("Start client — connect all configured agents to the server").option("--no-interactive", "Skip interactive prompts (for Docker/CI)").action(async (options) => {
1085
+ client.command("start").description("Start client — connect all configured agents to the server").option("--no-interactive", "Skip interactive prompts (for Docker/CI)").option("--foreground", "Run inline instead of delegating to the background service (for debugging)").action(async (options) => {
1085
1086
  try {
1087
+ const isSupervisorChild = options.interactive === false && process.env.FIRST_TREE_HUB_SERVICE_MODE === "1";
1088
+ if (!(options.foreground === true || isSupervisorChild) && isServiceSupported()) {
1089
+ const svc = getClientServiceStatus();
1090
+ if (svc.state === "active") {
1091
+ print.line("\n");
1092
+ print.line(` Service is already running (${svc.platform}${svc.detail ? `, ${svc.detail}` : ""}).\n`);
1093
+ print.line(" Use `first-tree-hub client restart` to restart, or `--foreground` to run inline.\n\n");
1094
+ return;
1095
+ }
1096
+ if (svc.state === "inactive") {
1097
+ const res = startClientService();
1098
+ if (!res.ok) {
1099
+ print.line(`\n Failed to start service: ${res.reason}\n`);
1100
+ print.line(" Try `--foreground` to run inline instead.\n\n");
1101
+ process.exit(1);
1102
+ }
1103
+ const after = getClientServiceStatus();
1104
+ print.line("\n");
1105
+ print.line(` Started ${after.platform} service${after.detail ? ` (${after.detail})` : ""}.\n`);
1106
+ const journalHint = after.platform === "systemd" ? ` (or \`journalctl --user -u ${after.label.replace(/\.service$/, "")}\`)` : "";
1107
+ print.line(` Logs: ${after.logDir}${journalHint}\n\n`);
1108
+ return;
1109
+ }
1110
+ if (svc.state === "unknown") {
1111
+ print.line(`\n Service state could not be determined (${svc.platform}${svc.detail ? `: ${svc.detail}` : ""}).\n`);
1112
+ print.line(" Inspect with `first-tree-hub client doctor`, or pass `--foreground` to bypass.\n\n");
1113
+ process.exit(1);
1114
+ }
1115
+ }
1086
1116
  await promptMissingFields({
1087
1117
  schema: clientConfigSchema,
1088
1118
  role: "client",
@@ -1212,11 +1242,72 @@ function registerClientCommands(program) {
1212
1242
  checkBackgroundService()
1213
1243
  ]);
1214
1244
  });
1215
- client.command("stop").description("Stop the client (sends SIGTERM to running process)").action(() => {
1216
- print.line(" Client stop: use Ctrl+C or `kill` the running process.\n");
1217
- print.line(" Daemon mode with PID file is planned for a future release.\n");
1245
+ client.command("stop").description("Stop the background service (preserves auto-start; use `client start` to bring it back)").action(() => {
1246
+ if (!isServiceSupported()) {
1247
+ print.line(`\n Service control not supported on ${process.platform}.\n`);
1248
+ print.line(" If running inline, use Ctrl+C or kill the process.\n\n");
1249
+ return;
1250
+ }
1251
+ const svc = getClientServiceStatus();
1252
+ if (svc.state === "not-installed") {
1253
+ print.line("\n No background service installed — nothing to stop.\n");
1254
+ print.line(" If running inline, use Ctrl+C or kill the process.\n\n");
1255
+ return;
1256
+ }
1257
+ if (svc.state === "inactive") {
1258
+ print.line("\n Service is already stopped.\n\n");
1259
+ return;
1260
+ }
1261
+ const res = stopClientService();
1262
+ if (!res.ok) {
1263
+ print.line(`\n Failed to stop service: ${res.reason}\n\n`);
1264
+ process.exit(1);
1265
+ }
1266
+ print.line(`\n Stopped ${svc.platform} service.\n`);
1267
+ print.line(" Auto-start on next login is preserved. Run `first-tree-hub client start` to bring it back.\n\n");
1268
+ });
1269
+ client.command("restart").description("Restart the background service").action(() => {
1270
+ if (!isServiceSupported()) {
1271
+ print.line(`\n Service control not supported on ${process.platform}.\n`);
1272
+ print.line(" Restart your inline `client start` process manually.\n\n");
1273
+ return;
1274
+ }
1275
+ if (getClientServiceStatus().state === "not-installed") {
1276
+ print.line("\n No background service installed.\n");
1277
+ print.line(" Run `first-tree-hub client connect <url>` first.\n\n");
1278
+ process.exit(1);
1279
+ }
1280
+ const res = restartClientService();
1281
+ if (!res.ok) {
1282
+ print.line(`\n Failed to restart service: ${res.reason}\n\n`);
1283
+ process.exit(1);
1284
+ }
1285
+ const after = getClientServiceStatus();
1286
+ print.line(`\n Restarted ${after.platform} service${after.detail ? ` (${after.detail})` : ""}.\n\n`);
1218
1287
  });
1219
- client.command("status").description("Show client and agent connection status").action(() => {
1288
+ client.command("status").description("Show CLI, service, hub, and agent status (one-screen overview)").action(() => {
1289
+ print.line("\n");
1290
+ print.line(` CLI: ${COMMAND_VERSION}\n`);
1291
+ if (isServiceSupported()) {
1292
+ const svc = getClientServiceStatus();
1293
+ const tail = svc.platform === "systemd" ? ` (logs: journalctl --user -u ${svc.label.replace(/\.service$/, "")} -f)` : "";
1294
+ if (svc.state === "active") print.line(` Service: ✓ running (${svc.platform}${svc.detail ? `, ${svc.detail}` : ""})${tail}\n`);
1295
+ else if (svc.state === "inactive") print.line(` Service: ✗ stopped (${svc.platform}${svc.detail ? `, ${svc.detail}` : ""})\n`);
1296
+ else if (svc.state === "not-installed") print.line(" Service: not installed — run `first-tree-hub client connect <url>`\n");
1297
+ else print.line(` Service: unknown (${svc.platform}${svc.detail ? `, ${svc.detail}` : ""})\n`);
1298
+ } else print.line(` Service: not supported on ${process.platform} (runs inline)\n`);
1299
+ const clientYaml = join(DEFAULT_CONFIG_DIR, "client.yaml");
1300
+ if (existsSync(clientYaml)) try {
1301
+ const cfg = readConfigFile(clientYaml);
1302
+ const serverUrl = getNested(cfg, "server.url");
1303
+ const clientId = getNested(cfg, "client.id");
1304
+ print.line(` Hub: ${serverUrl ?? "(not configured)"}\n`);
1305
+ print.line(` Client: ${clientId ?? "(not configured)"}\n`);
1306
+ } catch (err) {
1307
+ const msg = err instanceof Error ? err.message : String(err);
1308
+ print.line(` Hub: (could not read ${clientYaml}: ${msg.slice(0, 60)})\n`);
1309
+ }
1310
+ else print.line(" Hub: (not configured — run `first-tree-hub client connect <url>`)\n");
1220
1311
  const agentsDir = join(DEFAULT_CONFIG_DIR, "agents");
1221
1312
  try {
1222
1313
  const agents = loadAgents({
@@ -1224,14 +1315,14 @@ function registerClientCommands(program) {
1224
1315
  agentsDir
1225
1316
  });
1226
1317
  if (agents.size === 0) {
1227
- print.line(" No agents configured.\n");
1318
+ print.line(" Agents: 0 configured\n\n");
1228
1319
  return;
1229
1320
  }
1230
- print.line("\n Configured agents:\n\n");
1231
- for (const [name, config] of agents) print.line(` ${name.padEnd(20)} runtime: ${config.runtime.padEnd(14)} agentId: ${config.agentId}\n`);
1321
+ print.line(` Agents: ${agents.size} configured\n\n`);
1322
+ for (const [name, config] of agents) print.line(` ${name.padEnd(20)} runtime: ${config.runtime.padEnd(14)} agentId: ${config.agentId}\n`);
1232
1323
  print.line("\n");
1233
1324
  } catch {
1234
- print.line(" No agents directory found.\n");
1325
+ print.line(" Agents: (no agents directory)\n\n");
1235
1326
  }
1236
1327
  });
1237
1328
  client.command("hub-list").description("List clients on the Hub server").option("--server <url>", "Hub server URL").action(async (options) => {
@@ -1374,6 +1465,15 @@ function timeSince(isoDate) {
1374
1465
  if (hours < 24) return `${hours}h ${minutes % 60}m`;
1375
1466
  return `${Math.floor(hours / 24)}d ${hours % 24}h`;
1376
1467
  }
1468
+ /** Read a `dot.path.like.this` from a parsed YAML object, returning string | null. */
1469
+ function getNested(obj, path) {
1470
+ let cur = obj;
1471
+ for (const part of path.split(".")) {
1472
+ if (cur === null || cur === void 0 || typeof cur !== "object") return null;
1473
+ cur = cur[part];
1474
+ }
1475
+ return typeof cur === "string" ? cur : null;
1476
+ }
1377
1477
  //#endregion
1378
1478
  //#region src/commands/config.ts
1379
1479
  function resolveConfigPath(flags) {
@@ -1471,13 +1571,13 @@ function isSecretField(schema, dotPath) {
1471
1571
  //#region src/commands/onboard.ts
1472
1572
  async function promptMissing(args) {
1473
1573
  if (!args.server) try {
1474
- const { resolveServerUrl } = await import("../bootstrap-jx5nN1qZ.mjs").then((n) => n.t);
1574
+ const { resolveServerUrl } = await import("../bootstrap-BTKiVIYk.mjs").then((n) => n.t);
1475
1575
  resolveServerUrl();
1476
1576
  } catch {
1477
1577
  args.server = await input({ message: "Hub server URL:" });
1478
1578
  saveOnboardState(args);
1479
1579
  }
1480
- const { loadCredentials } = await import("../bootstrap-jx5nN1qZ.mjs").then((n) => n.t);
1580
+ const { loadCredentials } = await import("../bootstrap-BTKiVIYk.mjs").then((n) => n.t);
1481
1581
  if (!loadCredentials()) throw new Error("No saved credentials. Run `first-tree-hub client connect <server-url>` before onboarding.");
1482
1582
  if (!args.id) {
1483
1583
  args.id = await input({ message: "Agent ID:" });
@@ -1679,62 +1779,92 @@ function registerServerCommands(program) {
1679
1779
  });
1680
1780
  }
1681
1781
  //#endregion
1682
- //#region src/commands/status.ts
1683
- function registerStatusCommand(program) {
1684
- program.command("status").description("Global overviewserver health + configured agents").action(async () => {
1685
- print.line("\n");
1686
- const serverConfig = readConfigFile(join(DEFAULT_CONFIG_DIR, "server.yaml"));
1687
- const serverPort = getNestedValue(serverConfig, "server.port") ?? 8e3;
1688
- const serverUrl = `http://${getNestedValue(serverConfig, "server.host") ?? "127.0.0.1"}:${serverPort}`;
1782
+ //#region src/commands/update.ts
1783
+ /**
1784
+ * `first-tree-hub update` user-driven CLI upgrade.
1785
+ *
1786
+ * Lives at the top level (not under `client`) because the tarball bundles
1787
+ * server / client / web / shared into a single artifact: upgrading affects
1788
+ * the whole CLI, not the client subsystem alone.
1789
+ *
1790
+ * Pairs with — but does not replace — the server-driven UpdateManager
1791
+ * (packages/client/src/runtime/update-manager.ts), which fires automatically
1792
+ * when a connected client falls behind the server-bundled version. This
1793
+ * command is the manual equivalent: same install + restart sequence, but
1794
+ * triggered on the operator's terms.
1795
+ */
1796
+ function registerUpdateCommand(program) {
1797
+ program.command("update").description("Upgrade first-tree-hub to the latest published version and restart the service").option("--check", "Only check whether a newer version is available; do not install").option("--no-restart", "Install the new version but skip restarting the background service").action(async (options) => {
1798
+ const mode = detectInstallMode();
1799
+ if (mode === "source") {
1800
+ print.line("\n Running from a source checkout — `update` is a no-op.\n");
1801
+ print.line(" Use `git pull` instead.\n\n");
1802
+ return;
1803
+ }
1804
+ if (mode === "npx") {
1805
+ print.line("\n Not launched from a global npm install — cannot self-update.\n");
1806
+ print.line(` Install globally first: npm i -g ${PACKAGE_NAME}\n\n`);
1807
+ return;
1808
+ }
1809
+ print.line("\n Checking npm registry...\n");
1810
+ const latest = fetchLatestVersion();
1811
+ if (!latest.ok) {
1812
+ print.line(` Could not fetch latest version: ${latest.reason}\n\n`);
1813
+ process.exit(1);
1814
+ }
1815
+ const current = COMMAND_VERSION;
1816
+ if ((semver.valid(current) ? semver.compare(current, latest.version) : -1) >= 0) {
1817
+ print.line(` Already on ${current} (latest is ${latest.version}).\n\n`);
1818
+ return;
1819
+ }
1820
+ if (options.check) {
1821
+ print.line(` Update available: ${current} → ${latest.version}\n`);
1822
+ print.line(" Run `first-tree-hub update` to install.\n\n");
1823
+ return;
1824
+ }
1825
+ print.line(` Updating ${current} → ${latest.version}...\n`);
1826
+ const installRes = await installGlobalLatest();
1827
+ if (!installRes.ok) {
1828
+ print.line(`\n Install failed: ${installRes.reason}\n\n`);
1829
+ process.exit(1);
1830
+ }
1831
+ const installed = installRes.installedVersion ?? latest.version;
1832
+ print.line(` Installed ${installed}.\n`);
1833
+ if (options.restart === false) {
1834
+ print.line(" Skipping restart (--no-restart). Run `first-tree-hub client restart` when ready.\n\n");
1835
+ return;
1836
+ }
1837
+ if (!isServiceSupported()) {
1838
+ print.line(` No service manager on ${process.platform}; restart your inline `);
1839
+ print.line("`client start` process to pick up the new version.\n\n");
1840
+ return;
1841
+ }
1842
+ const svc = getClientServiceStatus();
1843
+ if (svc.state === "not-installed") {
1844
+ print.line(" No background service installed — nothing to restart.\n");
1845
+ print.line(" Run `first-tree-hub client connect <url>` to set one up.\n\n");
1846
+ return;
1847
+ }
1689
1848
  try {
1690
- const res = await fetch(`${serverUrl}/api/v1/health`);
1691
- if (res.ok) {
1692
- const data = await res.json();
1693
- const uptime = data.uptime_seconds ? formatUptime(data.uptime_seconds) : "unknown";
1694
- print.line(` Server: ✓ running (${serverUrl}, uptime: ${uptime})\n`);
1695
- } else print.line(` Server: ✗ unhealthy (${res.status})\n`);
1696
- } catch {
1697
- print.line(` Server: ✗ not running (${serverUrl})\n`);
1849
+ installClientService();
1850
+ } catch (err) {
1851
+ const msg = err instanceof Error ? err.message : String(err);
1852
+ print.line(` warning: unit-file refresh failed: ${msg}\n`);
1853
+ print.line(" Continuing with restart against the old unit.\n");
1698
1854
  }
1699
- const dbProvider = getNestedValue(serverConfig, "database.provider") ?? "unknown";
1700
- const hasDbUrl = getNestedValue(serverConfig, "database.url") !== void 0;
1701
- print.line(` Database: ${hasDbUrl ? "✓ configured" : "✗ not configured"} (${dbProvider})\n`);
1702
- const agentsDir = join(DEFAULT_CONFIG_DIR, "agents");
1703
- if (existsSync(agentsDir)) try {
1704
- const agents = loadAgents({
1705
- schema: agentConfigSchema,
1706
- agentsDir
1707
- });
1708
- print.line(` Agents: ${agents.size} configured\n`);
1709
- } catch {
1710
- print.line(" Agents: error reading config\n");
1711
- }
1712
- else print.line(" Agents: 0 configured\n");
1713
- const clientConfigPath = join(DEFAULT_CONFIG_DIR, "client.yaml");
1714
- if (existsSync(clientConfigPath)) {
1715
- const clientServerUrl = getNestedValue(readConfigFile(clientConfigPath), "server.url");
1716
- print.line(` Client: configured → ${clientServerUrl}\n`);
1717
- } else print.line(" Client: not configured\n");
1718
- print.line("\n");
1855
+ if (svc.state === "inactive") {
1856
+ print.line(" Service is stopped leaving it stopped. Use `client start` to bring it up.\n\n");
1857
+ return;
1858
+ }
1859
+ const restartRes = restartClientService();
1860
+ if (!restartRes.ok) {
1861
+ print.line(`\n Service restart failed: ${restartRes.reason}\n`);
1862
+ print.line(" Run `first-tree-hub client restart` to retry.\n\n");
1863
+ process.exit(1);
1864
+ }
1865
+ print.line(` Service restarted on ${installed}.\n\n`);
1719
1866
  });
1720
1867
  }
1721
- function getNestedValue(obj, dotPath) {
1722
- const parts = dotPath.split(".");
1723
- let current = obj;
1724
- for (const part of parts) {
1725
- if (current === null || current === void 0 || typeof current !== "object") return void 0;
1726
- current = current[part];
1727
- }
1728
- return current;
1729
- }
1730
- function formatUptime(seconds) {
1731
- const days = Math.floor(seconds / 86400);
1732
- const hours = Math.floor(seconds % 86400 / 3600);
1733
- const mins = Math.floor(seconds % 3600 / 60);
1734
- if (days > 0) return `${days}d ${hours}h`;
1735
- if (hours > 0) return `${hours}h ${mins}m`;
1736
- return `${mins}m`;
1737
- }
1738
1868
  //#endregion
1739
1869
  //#region src/cli/index.ts
1740
1870
  runHomeMigration();
@@ -1759,7 +1889,7 @@ registerServerCommands(program);
1759
1889
  registerClientCommands(program);
1760
1890
  registerAgentCommands(program);
1761
1891
  registerConfigCommands(program);
1762
- registerStatusCommand(program);
1892
+ registerUpdateCommand(program);
1763
1893
  registerOnboardCommand(program);
1764
1894
  program.parse();
1765
1895
  //#endregion
@@ -253,7 +253,7 @@ const createAgentSchema = z.object({
253
253
  type: agentTypeSchema,
254
254
  displayName: z.string().min(1).max(200).optional(),
255
255
  delegateMention: z.string().max(100).optional(),
256
- organizationId: z.string().max(100).optional(),
256
+ organizationId: z.string().min(1).max(100).optional(),
257
257
  source: agentSourceSchema.optional(),
258
258
  visibility: agentVisibilitySchema.optional(),
259
259
  metadata: z.record(z.string(), z.unknown()).optional(),
@@ -1,5 +1,5 @@
1
1
  import { d as __exportAll } from "./esm-CYu4tXXn.mjs";
2
- import { r as AGENT_SELECTOR_HEADER } from "./dist-DSr_I5Ia.mjs";
2
+ import { r as AGENT_SELECTOR_HEADER } from "./dist-DwbhZyGi.mjs";
3
3
  //#region src/core/feishu.ts
4
4
  var feishu_exports = /* @__PURE__ */ __exportAll({
5
5
  bindFeishuBot: () => bindFeishuBot,
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import "./observability-DPyf745N-BSc8QNcR.mjs";
2
- import { A as checkServerHealth, B as ensurePostgres, C as checkAgentConfigs, D as checkDocker, E as checkDatabase, F as getClientServiceStatus, G as rotateClientIdWithBackup, H as stopPostgres, I as installClientService, L as isServiceSupported, M as checkWebSocket, N as printResults, O as checkNodeVersion, R as resolveCliInvocation, S as runMigrations, T as checkClientConfig, U as ClientRuntime, V as isDockerAvailable, W as handleClientOrgMismatch, X as hasUser, Y as createOwner, _ as onboardCreate, d as isInteractive, et as blank, f as promptAddAgent, g as onboardCheck, j as checkServerReachable, k as checkServerConfig, m as formatCheckReport, n as deriveHubUrlFromToken, ot as FirstTreeHubSDK, p as promptMissingFields, rt as status, s as startServer, st as SdkError, t as HubUrlDerivationError, y as runHomeMigration, z as uninstallClientService } from "./saas-connect-CKQ15VLz.mjs";
2
+ import { A as checkDatabase, B as installClientService, C as runHomeMigration, D as checkAgentConfigs, E as runMigrations, F as checkServerReachable, G as stopClientService, H as resolveCliInvocation, I as checkWebSocket, J as isDockerAvailable, K as uninstallClientService, L as printResults, M as checkNodeVersion, N as checkServerConfig, P as checkServerHealth, Q as rotateClientIdWithBackup, U as restartClientService, V as isServiceSupported, W as startClientService, X as ClientRuntime, Y as stopPostgres, Z as handleClientOrgMismatch, _ as promptMissingFields, b as onboardCheck, d as startServer, g as promptAddAgent, h as isInteractive, j as checkDocker, k as checkClientConfig, mt as SdkError, n as deriveHubUrlFromToken, nt as createOwner, pt as FirstTreeHubSDK, q as ensurePostgres, rt as hasUser, st as blank, t as HubUrlDerivationError, ut as status, v as formatCheckReport, x as onboardCreate, z as getClientServiceStatus } from "./saas-connect-D-7x9KRd.mjs";
3
3
  import "./logger-core-BTmvdflj-DjW8FM4T.mjs";
4
- import { a as resolveAccessToken, n as ensureFreshAccessToken, o as resolveServerUrl, r as ensureFreshAdminToken } from "./bootstrap-jx5nN1qZ.mjs";
5
- import "./dist-DSr_I5Ia.mjs";
6
- import { n as bindFeishuUser, t as bindFeishuBot } from "./feishu-eynC54km.mjs";
4
+ import { a as resolveAccessToken, n as ensureFreshAccessToken, o as resolveServerUrl, r as ensureFreshAdminToken } from "./bootstrap-BTKiVIYk.mjs";
5
+ import "./dist-DwbhZyGi.mjs";
6
+ import { n as bindFeishuUser, t as bindFeishuBot } from "./feishu-viiZmwcn.mjs";
7
7
  import "./invitation-B1pjAyOz-BaCA9PII.mjs";
8
- export { ClientRuntime, FirstTreeHubSDK, HubUrlDerivationError, SdkError, bindFeishuBot, bindFeishuUser, blank, checkAgentConfigs, checkClientConfig, checkDatabase, checkDocker, checkNodeVersion, checkServerConfig, checkServerHealth, checkServerReachable, checkWebSocket, createOwner, deriveHubUrlFromToken, ensureFreshAccessToken, ensureFreshAdminToken, ensurePostgres, formatCheckReport, getClientServiceStatus, handleClientOrgMismatch, hasUser, installClientService, isDockerAvailable, isInteractive, isServiceSupported, onboardCheck, onboardCreate, printResults, promptAddAgent, promptMissingFields, resolveAccessToken, resolveCliInvocation, resolveServerUrl, rotateClientIdWithBackup, runHomeMigration, runMigrations, startServer, status, stopPostgres, uninstallClientService };
8
+ export { ClientRuntime, FirstTreeHubSDK, HubUrlDerivationError, SdkError, bindFeishuBot, bindFeishuUser, blank, checkAgentConfigs, checkClientConfig, checkDatabase, checkDocker, checkNodeVersion, checkServerConfig, checkServerHealth, checkServerReachable, checkWebSocket, createOwner, deriveHubUrlFromToken, ensureFreshAccessToken, ensureFreshAdminToken, ensurePostgres, formatCheckReport, getClientServiceStatus, handleClientOrgMismatch, hasUser, installClientService, isDockerAvailable, isInteractive, isServiceSupported, onboardCheck, onboardCreate, printResults, promptAddAgent, promptMissingFields, resolveAccessToken, resolveCliInvocation, resolveServerUrl, restartClientService, rotateClientIdWithBackup, runHomeMigration, runMigrations, startClientService, startServer, status, stopClientService, stopPostgres, uninstallClientService };
@@ -1,3 +1,3 @@
1
- import "./dist-DSr_I5Ia.mjs";
1
+ import "./dist-DwbhZyGi.mjs";
2
2
  import { g as previewInvitation, v as rotateInvitation } from "./invitation-B1pjAyOz-BaCA9PII.mjs";
3
3
  export { previewInvitation, rotateInvitation };