@agent-team-foundation/first-tree-hub 0.14.7-alpha.286.1 → 0.14.8
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/{bootstrap-BmeaRhRp.mjs → bootstrap-BC1M0f6A.mjs} +1 -1
- package/dist/{bootstrap-CmkHQsnS.mjs → bootstrap-D6RsdtJg.mjs} +6 -0
- package/dist/cli/index.mjs +4 -4
- package/dist/index.mjs +2 -2
- package/dist/{saas-connect-gXv14p6J.mjs → saas-connect-BOe1ynz2.mjs} +57 -13
- package/package.json +1 -1
|
@@ -664,6 +664,12 @@ defineConfig({
|
|
|
664
664
|
captureClientIp: field(z.boolean().default(false), { env: "FIRST_TREE_HUB_OTEL_CAPTURE_CLIENT_IP" })
|
|
665
665
|
})
|
|
666
666
|
},
|
|
667
|
+
update: {
|
|
668
|
+
channel: field(z.enum(["latest", "alpha"]).default("latest"), { env: "FIRST_TREE_HUB_UPDATE_CHANNEL" }),
|
|
669
|
+
commandVersion: field(z.string().optional(), { env: "FIRST_TREE_HUB_COMMAND_VERSION" }),
|
|
670
|
+
pollIntervalMinutes: field(z.coerce.number().int().min(1).max(1440).default(60), { env: "FIRST_TREE_HUB_UPDATE_POLL_INTERVAL_MINUTES" }),
|
|
671
|
+
registryUrl: field(z.string().url().default("https://registry.npmjs.org"), { env: "FIRST_TREE_HUB_UPDATE_REGISTRY_URL" })
|
|
672
|
+
},
|
|
667
673
|
runtime: {
|
|
668
674
|
inboxTimeoutSeconds: field(z.coerce.number().int().positive().default(300), { env: "FIRST_TREE_HUB_INBOX_TIMEOUT_SECONDS" }),
|
|
669
675
|
maxRetryCount: field(z.coerce.number().int().nonnegative().default(3), { env: "FIRST_TREE_HUB_MAX_RETRY_COUNT" }),
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as SdkError, A as printResults, B as ClientRuntime, C as migrateLocalAgentDirs, D as checkNodeVersion, E as checkClientConfig, G as removeLocalAgent, I as restartClientService, J as fail, K as resolveReplyToFromEnv, L as startClientService, M as getClientServiceStatus, N as installClientService, O as checkServerReachable, P as isServiceSupported, Q as FirstTreeHubSDK, R as stopClientService, S as createApiNameResolver, T as checkBackgroundService, U as findStaleAliases, V as handleClientOrgMismatch, W as formatStaleReason, X as ClientOrgMismatchError, Y as success, Z as ClientUserMismatchError, _ as loadOnboardState, a as declineUpdate, b as saveOnboardState, c as detectInstallMode, d as reconcileLocalRuntimeProviders, et as SessionRegistry, f as uploadClientCapabilities, g as formatCheckReport, h as promptMissingFields, i as createExecuteUpdate, it as configureClientLoggerForService, j as reconcileAgentConfigs, k as checkWebSocket, l as fetchLatestVersion, m as promptAddAgent, nt as probeCapabilities, o as promptUpdate, p as isInteractive, q as resolveSenderName, r as registerSaaSConnectCommand, rt as applyClientLoggerConfig, s as PACKAGE_NAME, tt as cleanWorkspaces, u as installGlobalLatest, v as onboardCheck, w as checkAgentConfigs, x as runHomeMigration, y as onboardCreate } from "../saas-connect-
|
|
3
|
-
import { C as resolveConfigReadonly, S as resetConfigMeta, _ as initConfig, a as loadCredentials, b as readConfigFile, c as saveAgentConfig, d as DEFAULT_DATA_DIR, f as DEFAULT_HOME_DIR, g as getConfigValue, i as ensureFreshAdminToken, m as clientConfigSchema, p as agentConfigSchema, r as ensureFreshAccessToken, s as resolveServerUrl, u as DEFAULT_CONFIG_DIR, v as loadAgents, w as setConfigValue, x as resetConfig } from "../bootstrap-
|
|
2
|
+
import { $ as SdkError, A as printResults, B as ClientRuntime, C as migrateLocalAgentDirs, D as checkNodeVersion, E as checkClientConfig, G as removeLocalAgent, I as restartClientService, J as fail, K as resolveReplyToFromEnv, L as startClientService, M as getClientServiceStatus, N as installClientService, O as checkServerReachable, P as isServiceSupported, Q as FirstTreeHubSDK, R as stopClientService, S as createApiNameResolver, T as checkBackgroundService, U as findStaleAliases, V as handleClientOrgMismatch, W as formatStaleReason, X as ClientOrgMismatchError, Y as success, Z as ClientUserMismatchError, _ as loadOnboardState, a as declineUpdate, b as saveOnboardState, c as detectInstallMode, d as reconcileLocalRuntimeProviders, et as SessionRegistry, f as uploadClientCapabilities, g as formatCheckReport, h as promptMissingFields, i as createExecuteUpdate, it as configureClientLoggerForService, j as reconcileAgentConfigs, k as checkWebSocket, l as fetchLatestVersion, m as promptAddAgent, nt as probeCapabilities, o as promptUpdate, p as isInteractive, q as resolveSenderName, r as registerSaaSConnectCommand, rt as applyClientLoggerConfig, s as PACKAGE_NAME, tt as cleanWorkspaces, u as installGlobalLatest, v as onboardCheck, w as checkAgentConfigs, x as runHomeMigration, y as onboardCreate } from "../saas-connect-BOe1ynz2.mjs";
|
|
3
|
+
import { C as resolveConfigReadonly, S as resetConfigMeta, _ as initConfig, a as loadCredentials, b as readConfigFile, c as saveAgentConfig, d as DEFAULT_DATA_DIR, f as DEFAULT_HOME_DIR, g as getConfigValue, i as ensureFreshAdminToken, m as clientConfigSchema, p as agentConfigSchema, r as ensureFreshAccessToken, s as resolveServerUrl, u as DEFAULT_CONFIG_DIR, v as loadAgents, w as setConfigValue, x as resetConfig } from "../bootstrap-D6RsdtJg.mjs";
|
|
4
4
|
import { a as print, n as CLI_USER_AGENT, o as setJsonMode, r as COMMAND_VERSION, t as cliFetch } from "../cli-fetch-BGVItZxo.mjs";
|
|
5
5
|
import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-BBUEVTnb.mjs";
|
|
6
6
|
import { join } from "node:path";
|
|
@@ -1463,13 +1463,13 @@ function decodeJwtExpSeconds(token) {
|
|
|
1463
1463
|
//#region src/commands/onboard.ts
|
|
1464
1464
|
async function promptMissing(args) {
|
|
1465
1465
|
if (!args.server) try {
|
|
1466
|
-
const { resolveServerUrl } = await import("../bootstrap-
|
|
1466
|
+
const { resolveServerUrl } = await import("../bootstrap-BC1M0f6A.mjs");
|
|
1467
1467
|
resolveServerUrl();
|
|
1468
1468
|
} catch {
|
|
1469
1469
|
args.server = await input({ message: "Hub server URL:" });
|
|
1470
1470
|
saveOnboardState(args);
|
|
1471
1471
|
}
|
|
1472
|
-
const { loadCredentials } = await import("../bootstrap-
|
|
1472
|
+
const { loadCredentials } = await import("../bootstrap-BC1M0f6A.mjs");
|
|
1473
1473
|
if (!loadCredentials()) throw new Error("No saved credentials. Run `first-tree-hub connect <token>` before onboarding.");
|
|
1474
1474
|
if (!args.id) {
|
|
1475
1475
|
args.id = await input({ message: "Agent ID:" });
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as SdkError, A as printResults, B as ClientRuntime, D as checkNodeVersion, E as checkClientConfig, F as resolveCliInvocation, H as rotateClientIdWithBackup, I as restartClientService, L as startClientService, M as getClientServiceStatus, N as installClientService, O as checkServerReachable, P as isServiceSupported, Q as FirstTreeHubSDK, R as stopClientService, V as handleClientOrgMismatch, g as formatCheckReport, h as promptMissingFields, k as checkWebSocket, m as promptAddAgent, n as deriveHubUrlFromToken, p as isInteractive, t as HubUrlDerivationError, v as onboardCheck, w as checkAgentConfigs, x as runHomeMigration, y as onboardCreate, z as uninstallClientService } from "./saas-connect-
|
|
2
|
-
import { i as ensureFreshAdminToken, n as AuthRefreshRateLimitedError, o as resolveAccessToken, r as ensureFreshAccessToken, s as resolveServerUrl, t as AuthRefreshFailedError } from "./bootstrap-
|
|
1
|
+
import { $ as SdkError, A as printResults, B as ClientRuntime, D as checkNodeVersion, E as checkClientConfig, F as resolveCliInvocation, H as rotateClientIdWithBackup, I as restartClientService, L as startClientService, M as getClientServiceStatus, N as installClientService, O as checkServerReachable, P as isServiceSupported, Q as FirstTreeHubSDK, R as stopClientService, V as handleClientOrgMismatch, g as formatCheckReport, h as promptMissingFields, k as checkWebSocket, m as promptAddAgent, n as deriveHubUrlFromToken, p as isInteractive, t as HubUrlDerivationError, v as onboardCheck, w as checkAgentConfigs, x as runHomeMigration, y as onboardCreate, z as uninstallClientService } from "./saas-connect-BOe1ynz2.mjs";
|
|
2
|
+
import { i as ensureFreshAdminToken, n as AuthRefreshRateLimitedError, o as resolveAccessToken, r as ensureFreshAccessToken, s as resolveServerUrl, t as AuthRefreshFailedError } from "./bootstrap-D6RsdtJg.mjs";
|
|
3
3
|
import { i as blank, s as status } from "./cli-fetch-BGVItZxo.mjs";
|
|
4
4
|
import { n as bindFeishuUser, t as bindFeishuBot } from "./feishu-BBUEVTnb.mjs";
|
|
5
5
|
export { AuthRefreshFailedError, AuthRefreshRateLimitedError, ClientRuntime, FirstTreeHubSDK, HubUrlDerivationError, SdkError, bindFeishuBot, bindFeishuUser, blank, checkAgentConfigs, checkClientConfig, checkNodeVersion, checkServerReachable, checkWebSocket, deriveHubUrlFromToken, ensureFreshAccessToken, ensureFreshAdminToken, formatCheckReport, getClientServiceStatus, handleClientOrgMismatch, installClientService, isInteractive, isServiceSupported, onboardCheck, onboardCreate, printResults, promptAddAgent, promptMissingFields, resolveAccessToken, resolveCliInvocation, resolveServerUrl, restartClientService, rotateClientIdWithBackup, runHomeMigration, startClientService, status, stopClientService, uninstallClientService };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as resolveConfigReadonly, S as resetConfigMeta, _ as initConfig, a as loadCredentials, c as saveAgentConfig, d as DEFAULT_DATA_DIR$1, f as DEFAULT_HOME_DIR$1, h as collectMissingPrompts, l as saveCredentials, m as clientConfigSchema, p as agentConfigSchema, r as ensureFreshAccessToken, s as resolveServerUrl, u as DEFAULT_CONFIG_DIR, v as loadAgents, w as setConfigValue, x as resetConfig, y as migrateLegacyHome } from "./bootstrap-
|
|
1
|
+
import { C as resolveConfigReadonly, S as resetConfigMeta, _ as initConfig, a as loadCredentials, c as saveAgentConfig, d as DEFAULT_DATA_DIR$1, f as DEFAULT_HOME_DIR$1, h as collectMissingPrompts, l as saveCredentials, m as clientConfigSchema, p as agentConfigSchema, r as ensureFreshAccessToken, s as resolveServerUrl, u as DEFAULT_CONFIG_DIR, v as loadAgents, w as setConfigValue, x as resetConfig, y as migrateLegacyHome } from "./bootstrap-D6RsdtJg.mjs";
|
|
2
2
|
import { a as print, i as blank, n as CLI_USER_AGENT, r as COMMAND_VERSION, t as cliFetch } from "./cli-fetch-BGVItZxo.mjs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { z } from "zod";
|
|
@@ -5883,6 +5883,12 @@ defineConfig({
|
|
|
5883
5883
|
captureClientIp: field(z.boolean().default(false), { env: "FIRST_TREE_HUB_OTEL_CAPTURE_CLIENT_IP" })
|
|
5884
5884
|
})
|
|
5885
5885
|
},
|
|
5886
|
+
update: {
|
|
5887
|
+
channel: field(z.enum(["latest", "alpha"]).default("latest"), { env: "FIRST_TREE_HUB_UPDATE_CHANNEL" }),
|
|
5888
|
+
commandVersion: field(z.string().optional(), { env: "FIRST_TREE_HUB_COMMAND_VERSION" }),
|
|
5889
|
+
pollIntervalMinutes: field(z.coerce.number().int().min(1).max(1440).default(60), { env: "FIRST_TREE_HUB_UPDATE_POLL_INTERVAL_MINUTES" }),
|
|
5890
|
+
registryUrl: field(z.string().url().default("https://registry.npmjs.org"), { env: "FIRST_TREE_HUB_UPDATE_REGISTRY_URL" })
|
|
5891
|
+
},
|
|
5886
5892
|
runtime: {
|
|
5887
5893
|
inboxTimeoutSeconds: field(z.coerce.number().int().positive().default(300), { env: "FIRST_TREE_HUB_INBOX_TIMEOUT_SECONDS" }),
|
|
5888
5894
|
maxRetryCount: field(z.coerce.number().int().nonnegative().default(3), { env: "FIRST_TREE_HUB_MAX_RETRY_COUNT" }),
|
|
@@ -13610,17 +13616,46 @@ function detectInstallMode(argv1 = process.argv[1] ?? "") {
|
|
|
13610
13616
|
return "npx";
|
|
13611
13617
|
}
|
|
13612
13618
|
/**
|
|
13613
|
-
*
|
|
13614
|
-
*
|
|
13615
|
-
*
|
|
13616
|
-
*
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
+
* Validate an npm install spec (the part after `@` in `<pkg>@<spec>`). We
|
|
13620
|
+
* accept either a known dist-tag string (`latest`, `alpha`, …) or an exact
|
|
13621
|
+
* SemVer version (`0.14.7`, `0.14.8-alpha.286.1`). The intent is purely
|
|
13622
|
+
* defensive: the spec is concatenated into the npm CLI args, and we never
|
|
13623
|
+
* want to forward an attacker-controlled shell metacharacter from a
|
|
13624
|
+
* (compromised) server welcome frame straight into `spawn`. spawn() already
|
|
13625
|
+
* argv-escapes, but a `--registry=...` style spec would still be
|
|
13626
|
+
* interpreted as an npm flag — refusing leading dashes and whitespace
|
|
13627
|
+
* collapses the surface unambiguously.
|
|
13628
|
+
*/
|
|
13629
|
+
function isSafeInstallSpec(spec) {
|
|
13630
|
+
if (typeof spec !== "string" || spec.length === 0 || spec.length > 128) return false;
|
|
13631
|
+
if (spec.startsWith("-")) return false;
|
|
13632
|
+
return /^[A-Za-z0-9.+-]+$/.test(spec);
|
|
13633
|
+
}
|
|
13634
|
+
/**
|
|
13635
|
+
* Install `<pkg>@<spec>` globally. `spec` is either a dist-tag (e.g. `latest`)
|
|
13636
|
+
* or an exact version (e.g. `0.14.7-alpha.286.1`). Returns after the child
|
|
13637
|
+
* exits. Does not exit the parent process — callers are expected to handle
|
|
13638
|
+
* that (so the UpdateManager can attempt the restart itself while this
|
|
13639
|
+
* function remains side-effect-scoped).
|
|
13640
|
+
*
|
|
13641
|
+
* Why both shapes exist: the auto-update path receives `targetVersion` from
|
|
13642
|
+
* the server `welcome` frame and MUST install that exact version — using
|
|
13643
|
+
* `@latest` from auto-update would silently mis-resolve once the server
|
|
13644
|
+
* starts advertising alpha builds (alpha lives on a different dist-tag).
|
|
13645
|
+
* The manual `first-tree-hub update` CLI keeps the dist-tag form so users
|
|
13646
|
+
* who type the command without args still get "newest stable on npm".
|
|
13647
|
+
*/
|
|
13648
|
+
async function installGlobalSpec(spec) {
|
|
13649
|
+
if (!isSafeInstallSpec(spec)) return {
|
|
13650
|
+
ok: false,
|
|
13651
|
+
mode: "global",
|
|
13652
|
+
reason: `Refusing to install: invalid npm spec ${JSON.stringify(spec)}`
|
|
13653
|
+
};
|
|
13619
13654
|
return new Promise((resolvePromise) => {
|
|
13620
13655
|
const child = spawn(resolveNpmCommand(), [
|
|
13621
13656
|
"install",
|
|
13622
13657
|
"-g",
|
|
13623
|
-
`${PACKAGE_NAME}
|
|
13658
|
+
`${PACKAGE_NAME}@${spec}`
|
|
13624
13659
|
], { stdio: [
|
|
13625
13660
|
"ignore",
|
|
13626
13661
|
"pipe",
|
|
@@ -13658,6 +13693,15 @@ async function installGlobalLatest() {
|
|
|
13658
13693
|
});
|
|
13659
13694
|
}
|
|
13660
13695
|
/**
|
|
13696
|
+
* Back-compat shim: install `<pkg>@latest`. The manual `first-tree-hub
|
|
13697
|
+
* update` CLI uses this so an operator-typed `update` keeps the
|
|
13698
|
+
* "newest stable on npm" behaviour. Auto-update prefers `installGlobalSpec`
|
|
13699
|
+
* with the welcome frame's `targetVersion`.
|
|
13700
|
+
*/
|
|
13701
|
+
async function installGlobalLatest() {
|
|
13702
|
+
return installGlobalSpec("latest");
|
|
13703
|
+
}
|
|
13704
|
+
/**
|
|
13661
13705
|
* Best-effort extraction of the version npm reported as installed. npm's
|
|
13662
13706
|
* stdout lines look like `+ @agent-team-foundation/first-tree-hub@0.9.2`.
|
|
13663
13707
|
* Returns null if nothing matches — callers treat null as "install succeeded
|
|
@@ -13710,7 +13754,7 @@ function fetchLatestVersion(timeoutMs = 1e4) {
|
|
|
13710
13754
|
}
|
|
13711
13755
|
/** Interactive update prompt. Defaults to N on timeout. */
|
|
13712
13756
|
const promptUpdate = async ({ currentVersion, targetVersion, timeoutSeconds }) => {
|
|
13713
|
-
const message = `A newer First Tree Hub client is available.\n You: ${currentVersion}\n Server
|
|
13757
|
+
const message = `A newer First Tree Hub client is available.\n You: ${currentVersion}\n Server recommends: ${targetVersion}\n Will install: ${targetVersion}\n Updating will restart the client and briefly interrupt any active sessions.\n Update now?`;
|
|
13714
13758
|
try {
|
|
13715
13759
|
const controller = new AbortController();
|
|
13716
13760
|
const timer = setTimeout(() => controller.abort(), timeoutSeconds * 1e3);
|
|
@@ -13748,7 +13792,7 @@ const declineUpdate = async () => false;
|
|
|
13748
13792
|
* operator restarts manually.
|
|
13749
13793
|
*/
|
|
13750
13794
|
function createExecuteUpdate({ managed }) {
|
|
13751
|
-
return async () => {
|
|
13795
|
+
return async ({ targetVersion }) => {
|
|
13752
13796
|
const mode = detectInstallMode();
|
|
13753
13797
|
if (mode === "source") {
|
|
13754
13798
|
print.line(" [update] Running from source checkout — self-update skipped. Use `git pull` instead.\n");
|
|
@@ -13758,13 +13802,13 @@ function createExecuteUpdate({ managed }) {
|
|
|
13758
13802
|
print.line(" [update] Cannot self-update — not launched from a global npm install.\n Run `npm i -g @agent-team-foundation/first-tree-hub` manually.\n");
|
|
13759
13803
|
return { installed: false };
|
|
13760
13804
|
}
|
|
13761
|
-
print.line(
|
|
13762
|
-
const result = await
|
|
13805
|
+
print.line(` [update] Running \`npm install -g @agent-team-foundation/first-tree-hub@${targetVersion}\`...\n`);
|
|
13806
|
+
const result = await installGlobalSpec(targetVersion);
|
|
13763
13807
|
if (!result.ok) {
|
|
13764
13808
|
print.line(` [update] Install failed: ${result.reason}\n`);
|
|
13765
13809
|
return { installed: false };
|
|
13766
13810
|
}
|
|
13767
|
-
const installed = result.installedVersion ??
|
|
13811
|
+
const installed = result.installedVersion ?? targetVersion;
|
|
13768
13812
|
if (managed) {
|
|
13769
13813
|
print.line(` [update] Installed ${installed}. Restarting (exit 75).\n`);
|
|
13770
13814
|
process.exit(75);
|