@agent-team-foundation/first-tree-hub 0.6.0 → 0.6.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.
@@ -487,6 +487,7 @@ var bootstrap_exports = /* @__PURE__ */ __exportAll({
487
487
  ensureFreshAdminToken: () => ensureFreshAdminToken,
488
488
  getGitHubToken: () => getGitHubToken,
489
489
  getGitHubUsername: () => getGitHubUsername,
490
+ loadAgentTokenByName: () => loadAgentTokenByName,
490
491
  loadCredentials: () => loadCredentials,
491
492
  maskToken: () => maskToken,
492
493
  resolveAgentToken: () => resolveAgentToken,
@@ -524,12 +525,12 @@ function getGitHubToken() {
524
525
  */
525
526
  function resolveServerUrl(flagValue) {
526
527
  if (flagValue) return flagValue;
527
- if (process.env.FIRST_TREE_HUB_SERVER) return process.env.FIRST_TREE_HUB_SERVER;
528
+ if (process.env.FIRST_TREE_HUB_SERVER_URL) return process.env.FIRST_TREE_HUB_SERVER_URL;
528
529
  try {
529
530
  const config = getClientConfig();
530
531
  if (config.server?.url) return config.server.url;
531
532
  } catch {}
532
- throw new Error("Server URL not configured.\n Provide via: --server <url>, FIRST_TREE_HUB_SERVER env var, or\n first-tree-hub config set -c server.url <url>");
533
+ throw new Error("Server URL not configured.\n Provide via: --server <url>, FIRST_TREE_HUB_SERVER_URL env var, or\n first-tree-hub config set -c server.url <url>");
533
534
  }
534
535
  /**
535
536
  * Bootstrap a token for an agent using GitHub identity.
@@ -572,13 +573,36 @@ async function bootstrapToken(serverUrl, agentName, options = {}) {
572
573
  return data;
573
574
  }
574
575
  /**
575
- * Resolve agent token from FIRST_TREE_HUB_TOKEN env var.
576
- * Throws if not set.
576
+ * Load an agent's token from `~/.first-tree-hub/agents/<agentName>/agent.yaml`.
577
+ * Returns null if the file is missing or has no token.
578
+ */
579
+ function loadAgentTokenByName(agentName) {
580
+ const configPath = join(DEFAULT_CONFIG_DIR, "agents", agentName, "agent.yaml");
581
+ if (!existsSync(configPath)) return null;
582
+ try {
583
+ const raw = parse(readFileSync(configPath, "utf-8"));
584
+ if (typeof raw.token === "string" && raw.token.length > 0) return raw.token;
585
+ return null;
586
+ } catch {
587
+ return null;
588
+ }
589
+ }
590
+ /**
591
+ * Resolve agent token with the following precedence:
592
+ * 1. FIRST_TREE_HUB_AGENT_TOKEN env var (explicit token; runtime or manual export)
593
+ * 2. FIRST_TREE_HUB_AGENT env var → lookup in ~/.first-tree-hub/agents/<name>/agent.yaml
594
+ * Throws if neither is configured or the named agent has no stored token.
577
595
  */
578
596
  function resolveAgentToken() {
579
- const token = process.env.FIRST_TREE_HUB_TOKEN;
580
- if (!token) throw new Error("FIRST_TREE_HUB_TOKEN environment variable is required.");
581
- return token;
597
+ const token = process.env.FIRST_TREE_HUB_AGENT_TOKEN;
598
+ if (token) return token;
599
+ const agentName = process.env.FIRST_TREE_HUB_AGENT;
600
+ if (agentName) {
601
+ const loaded = loadAgentTokenByName(agentName);
602
+ if (loaded) return loaded;
603
+ throw new Error(`Agent "${agentName}" has no token in ${join(DEFAULT_CONFIG_DIR, "agents", agentName)}/agent.yaml.\n Verify the agent exists locally or set FIRST_TREE_HUB_AGENT_TOKEN explicitly.`);
604
+ }
605
+ throw new Error("No agent token configured.\n Set FIRST_TREE_HUB_AGENT_TOKEN directly, or\n set FIRST_TREE_HUB_AGENT=<agentName> to use a stored agent config.");
582
606
  }
583
607
  /**
584
608
  * Ensure the persisted access token is fresh. Call before any admin API request
@@ -666,4 +690,4 @@ function maskToken(token) {
666
690
  return token.length > 8 ? `${token.slice(0, 6)}***${token.slice(-2)}` : "***";
667
691
  }
668
692
  //#endregion
669
- export { resetConfigMeta as C, setConfigValue as E, resetConfig as S, serverConfigSchema as T, collectMissingPrompts as _, getGitHubToken as a, loadAgents as b, resolveAgentToken as c, saveCredentials as d, DEFAULT_CONFIG_DIR as f, clientConfigSchema as g, agentConfigSchema as h, ensureFreshAdminToken as i, resolveServerUrl as l, DEFAULT_HOME_DIR as m, bootstrap_exports as n, getGitHubUsername as o, DEFAULT_DATA_DIR as p, checkBootstrapStatus as r, maskToken as s, bootstrapToken as t, saveAgentConfig as u, getConfigValue as v, resolveConfigReadonly as w, readConfigFile as x, initConfig as y };
693
+ export { resetConfig as C, setConfigValue as D, serverConfigSchema as E, readConfigFile as S, resolveConfigReadonly as T, clientConfigSchema as _, getGitHubToken as a, initConfig as b, maskToken as c, saveAgentConfig as d, saveCredentials as f, agentConfigSchema as g, DEFAULT_HOME_DIR as h, ensureFreshAdminToken as i, resolveAgentToken as l, DEFAULT_DATA_DIR as m, bootstrap_exports as n, getGitHubUsername as o, DEFAULT_CONFIG_DIR as p, checkBootstrapStatus as r, loadAgentTokenByName as s, bootstrapToken as t, resolveServerUrl as u, collectMissingPrompts as v, resetConfigMeta as w, loadAgents as x, getConfigValue as y };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { C as resetConfigMeta, E as setConfigValue, S as resetConfig, T as serverConfigSchema, b as loadAgents, c as resolveAgentToken, d as saveCredentials, f as DEFAULT_CONFIG_DIR, g as clientConfigSchema, h as agentConfigSchema, i as ensureFreshAdminToken, l as resolveServerUrl, m as DEFAULT_HOME_DIR, p as DEFAULT_DATA_DIR, s as maskToken, t as bootstrapToken, u as saveAgentConfig, v as getConfigValue, x as readConfigFile, y as initConfig } from "../bootstrap-BnlTKa0H.mjs";
3
- import { A as FirstTreeHubSDK, D as ClientRuntime, E as stopPostgres, M as SessionRegistry, N as cleanWorkspaces, O as createOwner, _ as checkServerConfig, a as formatCheckReport, b as checkWebSocket, c as onboardCreate, d as checkAgentConfigs, f as checkAgentTokens, g as checkNodeVersion, h as checkDocker, i as promptMissingFields, j as SdkError, l as saveOnboardState, m as checkDatabase, n as isInteractive, o as loadOnboardState, p as checkClientConfig, r as promptAddAgent, s as onboardCheck, t as startServer, u as runMigrations, v as checkServerHealth, x as printResults, y as checkServerReachable } from "../core-B9bH7EjM.mjs";
2
+ import { C as resetConfig, D as setConfigValue, E as serverConfigSchema, S as readConfigFile, _ as clientConfigSchema, b as initConfig, c as maskToken, d as saveAgentConfig, f as saveCredentials, g as agentConfigSchema, h as DEFAULT_HOME_DIR, i as ensureFreshAdminToken, l as resolveAgentToken, m as DEFAULT_DATA_DIR, p as DEFAULT_CONFIG_DIR, t as bootstrapToken, u as resolveServerUrl, w as resetConfigMeta, x as loadAgents, y as getConfigValue } from "../bootstrap-Dq_k_6ZD.mjs";
3
+ import { A as FirstTreeHubSDK, D as ClientRuntime, E as stopPostgres, M as SessionRegistry, N as cleanWorkspaces, O as createOwner, _ as checkServerConfig, a as formatCheckReport, b as checkWebSocket, c as onboardCreate, d as checkAgentConfigs, f as checkAgentTokens, g as checkNodeVersion, h as checkDocker, i as promptMissingFields, j as SdkError, l as saveOnboardState, m as checkDatabase, n as isInteractive, o as loadOnboardState, p as checkClientConfig, r as promptAddAgent, s as onboardCheck, t as startServer, u as runMigrations, v as checkServerHealth, x as printResults, y as checkServerReachable } from "../core-Dt3yNBTm.mjs";
4
4
  import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-Y4m2zFc3.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import { Command } from "commander";
@@ -30,11 +30,15 @@ function fail(code, message, exitCode = 1) {
30
30
  //#region src/commands/agent.ts
31
31
  const DEFAULT_WORKSPACE_TTL_MS = 10080 * 60 * 1e3;
32
32
  function resolveAgentConfig() {
33
- const token = process.env.FIRST_TREE_HUB_TOKEN;
34
- if (!token) fail("MISSING_TOKEN", "FIRST_TREE_HUB_TOKEN environment variable is required.", 2);
33
+ let token;
34
+ try {
35
+ token = resolveAgentToken();
36
+ } catch (error) {
37
+ fail("MISSING_TOKEN", error instanceof Error ? error.message : String(error), 2);
38
+ }
35
39
  let serverUrl;
36
40
  try {
37
- serverUrl = resolveServerUrl(process.env.FIRST_TREE_HUB_SERVER);
41
+ serverUrl = resolveServerUrl(process.env.FIRST_TREE_HUB_SERVER_URL);
38
42
  } catch {
39
43
  serverUrl = "http://localhost:8000";
40
44
  }
@@ -841,13 +845,13 @@ function registerConnectCommand(program) {
841
845
  //#region src/commands/onboard.ts
842
846
  async function promptMissing(args) {
843
847
  if (!args.server) try {
844
- const { resolveServerUrl } = await import("../bootstrap-BnlTKa0H.mjs").then((n) => n.n);
848
+ const { resolveServerUrl } = await import("../bootstrap-Dq_k_6ZD.mjs").then((n) => n.n);
845
849
  resolveServerUrl();
846
850
  } catch {
847
851
  args.server = await input({ message: "Hub server URL:" });
848
852
  saveOnboardState(args);
849
853
  }
850
- const { resolveServerUrl } = await import("../bootstrap-BnlTKa0H.mjs").then((n) => n.n);
854
+ const { resolveServerUrl } = await import("../bootstrap-Dq_k_6ZD.mjs").then((n) => n.n);
851
855
  const serverUrl = resolveServerUrl(args.server).replace(/\/+$/, "");
852
856
  try {
853
857
  const res = await fetch(`${serverUrl}/api/v1/bootstrap/config`);
@@ -859,7 +863,7 @@ async function promptMissing(args) {
859
863
  }
860
864
  let ghUsername = null;
861
865
  try {
862
- const { getGitHubUsername } = await import("../bootstrap-BnlTKa0H.mjs").then((n) => n.n);
866
+ const { getGitHubUsername } = await import("../bootstrap-Dq_k_6ZD.mjs").then((n) => n.n);
863
867
  ghUsername = getGitHubUsername();
864
868
  } catch {}
865
869
  if (!args.id) {