@agent-team-foundation/first-tree-hub 0.11.2 → 0.11.3
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-B-FRMuvL.mjs → bootstrap-D4rdqM2F.mjs} +2 -1
- package/dist/cli/index.mjs +44 -41
- package/dist/cli-fetch--tiwKm5S.mjs +167 -0
- package/dist/client-By1K4VVT-C5K7WZo6.mjs +4 -0
- package/dist/{client-CLdRbuml-B416INrm.mjs → client-CLdRbuml-BRtalKpQ.mjs} +2 -2
- package/dist/{dist-BLY7Bu-l.mjs → dist-BQtAQNRD.mjs} +1 -1
- package/dist/{feishu-GvFABWW5.mjs → feishu-Th_-ivJ7.mjs} +4 -3
- package/dist/{getMachineId-bsd-DjLgZlll.mjs → getMachineId-bsd-DyySs8xz.mjs} +2 -2
- package/dist/{getMachineId-bsd-DR4-Dysy.mjs → getMachineId-bsd-c2VImogj.mjs} +2 -2
- package/dist/{getMachineId-darwin-CaD2juTg.mjs → getMachineId-darwin-Cl7TSzgO.mjs} +2 -2
- package/dist/{getMachineId-darwin-B6WCAhc4.mjs → getMachineId-darwin-DKgI8b1d.mjs} +2 -2
- package/dist/{getMachineId-linux-Dk3gWdQK.mjs → getMachineId-linux-1OIMWfdh.mjs} +1 -1
- package/dist/{getMachineId-linux-BeWHG1gK.mjs → getMachineId-linux-cT7EbP10.mjs} +1 -1
- package/dist/{getMachineId-unsupported-BMJQItvF.mjs → getMachineId-unsupported-CkX-YOG1.mjs} +1 -1
- package/dist/{getMachineId-unsupported-Bgz_Je1J.mjs → getMachineId-unsupported-CmVlhzIo.mjs} +1 -1
- package/dist/{getMachineId-win-vJ6VfDRI.mjs → getMachineId-win-C2cM60YT.mjs} +2 -2
- package/dist/{getMachineId-win-CdgcrzCW.mjs → getMachineId-win-Chl03TYe.mjs} +2 -2
- package/dist/index.mjs +10 -9
- package/dist/invitation-DWlyNb8x-D3zjZSwI.mjs +4 -0
- package/dist/{invitation-Dnn5gGGX-Ce7zbZpn.mjs → invitation-Dnn5gGGX-DXryyvRG.mjs} +1 -1
- package/dist/{multipart-parser-BIksYTkk.mjs → multipart-parser-QRu3OKK4.mjs} +1 -1
- package/dist/{observability-C3nY6Jcz-Bk7FX689.mjs → observability-BAScT_5S-gw1ODB_o.mjs} +140 -17
- package/dist/observability-CYsdAcoF.mjs +5 -0
- package/dist/{saas-connect-Df2CVAGp.mjs → saas-connect-gcT6Q10z.mjs} +78 -158
- package/dist/{src-CzQ5KF6D.mjs → src-DFlbpJfU.mjs} +2 -2
- package/package.json +1 -1
- package/dist/client-By1K4VVT-nVOhsXBy.mjs +0 -4
- package/dist/invitation-DWlyNb8x-BEgoZ9k1.mjs +0 -4
- package/dist/observability-DttujCqj.mjs +0 -5
- /package/dist/{dist-FuUBFTEB.mjs → dist-BAqGZkco.mjs} +0 -0
- /package/dist/{errors-BmyRwN0Y-CIZZ_sDc.mjs → errors-BmyRwN0Y-Dad3eV8F.mjs} +0 -0
- /package/dist/{esm-iadMkGbV.mjs → esm-Ci8E1Gtj.mjs} +0 -0
- /package/dist/{execAsync-pImxPKN5.mjs → execAsync-DUfRkc4a.mjs} +0 -0
- /package/dist/{execAsync-CCyouKZM.mjs → execAsync-YbEZSOYd.mjs} +0 -0
- /package/dist/{from-CaD373S1.mjs → from-DQ7eNRwu.mjs} +0 -0
- /package/dist/{src-DNBS5Yjj.mjs → src-aJMV60mR.mjs} +0 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { a as __toCommonJS, o as __toESM, t as __commonJSMin } from "./chunk-BSw8zbkd.mjs";
|
|
2
|
-
import { C as
|
|
3
|
-
import { C as resetConfigMeta, E as setConfigValue, S as resetConfig, T as serverConfigSchema, b as migrateLegacyHome, c as resolveServerUrl, d as DEFAULT_CONFIG_DIR, f as DEFAULT_DATA_DIR$1, g as collectMissingPrompts, h as clientConfigSchema, i as ensureFreshAccessToken, l as saveAgentConfig, m as agentConfigSchema, o as loadCredentials, p as DEFAULT_HOME_DIR$1, u as saveCredentials, v as initConfig, w as resolveConfigReadonly, y as loadAgents } from "./bootstrap-
|
|
4
|
-
import {
|
|
5
|
-
import { a as
|
|
6
|
-
import {
|
|
7
|
-
import { n as
|
|
8
|
-
import {
|
|
2
|
+
import { A as FIRST_TREE_HUB_ATTR, C as stampOrgScope, D as untrustedAttrs, E as startWsConnectionSpan, M as require_pino, O as withSpan, S as stampChatResource, _ as rootLogger$1, a as buildRateLimitError, c as currentTraceId, f as messageAttrs, g as reportErrorToRoot, i as bodyCaptureOnSendHook, j as redactUrl, k as withWsMessageSpan, l as decodeJwtForTrace, m as observabilityPlugin, n as applyLoggerConfig, o as classifyJoseError, r as attachRequestContext, s as createLogger$1, t as adapterAttrs, u as endWsConnectionSpan, x as stampAgentResource, y as setWsConnectionAttrs } from "./observability-BAScT_5S-gw1ODB_o.mjs";
|
|
3
|
+
import { C as resetConfigMeta, E as setConfigValue, S as resetConfig, T as serverConfigSchema, b as migrateLegacyHome, c as resolveServerUrl, d as DEFAULT_CONFIG_DIR, f as DEFAULT_DATA_DIR$1, g as collectMissingPrompts, h as clientConfigSchema, i as ensureFreshAccessToken, l as saveAgentConfig, m as agentConfigSchema, o as loadCredentials, p as DEFAULT_HOME_DIR$1, u as saveCredentials, v as initConfig, w as resolveConfigReadonly, y as loadAgents } from "./bootstrap-D4rdqM2F.mjs";
|
|
4
|
+
import { a as print, i as blank, n as CLI_USER_AGENT, r as COMMAND_VERSION, s as status, t as cliFetch } from "./cli-fetch--tiwKm5S.mjs";
|
|
5
|
+
import { $ as notificationQuerySchema, A as createChatSchema, B as githubDevCallbackQuerySchema, Ct as updateTaskStatusSchema, D as createAdapterConfigSchema, E as contextTreeSnapshotSchema, F as defaultRuntimeConfigPayload, G as inboxPollQuerySchema, H as imageInlineContentSchema, I as delegateFeishuUserSchema, J as joinByInvitationSchema, K as isRedactedEnvValue, L as dryRunAgentRuntimeConfigSchema, M as createMemberSchema, N as createOrgFromMeSchema, O as createAdapterMappingSchema, P as createTaskSchema, Q as messageSourceSchema$1, R as extractMentions, S as agentTypeSchema$1, St as updateOrganizationSchema, T as connectTokenExchangeSchema, U as inboxAckFrameSchema, V as githubStartQuerySchema, W as inboxDeliverFrameSchema$1, X as listMeChatsQuerySchema, Y as linkTaskChatSchema, Z as loginSchema, _ as adminCreateTaskSchema, _t as updateAgentRuntimeConfigSchema, a as AGENT_STATUSES, at as scanMentionTokens, b as agentPinnedMessageSchema$1, bt as updateClientCapabilitiesSchema, ct as sendToAgentSchema, d as TASK_HEALTH_SIGNALS, dt as sessionEventSchema$1, et as paginationQuerySchema, f as TASK_STATUSES, ft as sessionReconcileRequestSchema, g as addParticipantSchema, gt as updateAdapterConfigSchema, h as addMeChatParticipantsSchema, ht as taskListQuerySchema, i as AGENT_SOURCES, it as safeRedirectPath, j as createMeChatSchema, k as createAgentSchema, l as MENTION_REGEX, lt as sessionCompletionMessageSchema, m as WS_AUTH_FRAME_TIMEOUT_MS, mt as stripCode, n as AGENT_NAME_REGEX$1, nt as refreshTokenSchema, o as AGENT_TYPES, ot as selfServiceFeishuBotSchema, p as TASK_TERMINAL_STATUSES, pt as sessionStateMessageSchema, q as isReservedAgentName$1, r as AGENT_SELECTOR_HEADER$1, rt as runtimeStateMessageSchema, s as AGENT_VISIBILITY, st as sendMessageSchema, t as AGENT_BIND_REJECT_REASONS, tt as rebindAgentSchema, u as TASK_CREATOR_TYPES, ut as sessionEventMessageSchema, v as adminUpdateTaskSchema, vt as updateAgentSchema, w as clientRegisterSchema, wt as wsAuthFrameSchema, x as agentRuntimeConfigPayloadSchema$1, xt as updateMemberSchema, y as agentBindRequestSchema, yt as updateChatSchema, z as githubCallbackQuerySchema } from "./dist-BAqGZkco.mjs";
|
|
6
|
+
import { a as ConflictError, c as UnauthorizedError, i as ClientUserMismatchError$1, l as organizations, n as BadRequestError, o as ForbiddenError, r as ClientOrgMismatchError$1, s as NotFoundError, t as AppError, u as users } from "./errors-BmyRwN0Y-Dad3eV8F.mjs";
|
|
7
|
+
import { C as retireClient, D as touchAgent, E as setRuntimeState, O as unbindAgent, S as registerClient, T as setOffline, _ as listClients, a as claimClient, b as markStaleAgents, c as clients, d as getClient, f as getOnlineCount, g as listActiveAgentsPinnedToClient, h as heartbeatInstance, i as bindAgent, k as updateClientCapabilities, l as deriveAuthState, m as heartbeatClient, n as agents, o as cleanupStaleClients, p as getPresence, r as assertClientOwner, s as cleanupStalePresence, t as agentPresence, u as disconnectClient, v as listClientsForOrgAdmin, w as serverInstances, x as members } from "./client-CLdRbuml-BRtalKpQ.mjs";
|
|
8
|
+
import { n as init_esm, r as trace, t as esm_exports } from "./esm-Ci8E1Gtj.mjs";
|
|
9
|
+
import { a as invitationRedemptions, c as recordRedemption, i as getActiveInvitation, l as rotateInvitation, n as ensureActiveInvitation, o as invitations, r as findActiveByToken, t as buildInviteUrl, u as uuidv7 } from "./invitation-Dnn5gGGX-DXryyvRG.mjs";
|
|
9
10
|
import { createRequire } from "node:module";
|
|
10
11
|
import { ZodError, z } from "zod";
|
|
11
12
|
import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
@@ -29,12 +30,12 @@ import { drizzle } from "drizzle-orm/postgres-js";
|
|
|
29
30
|
import postgres from "postgres";
|
|
30
31
|
import { migrate } from "drizzle-orm/postgres-js/migrator";
|
|
31
32
|
import { bigserial, boolean, index, integer, jsonb, pgTable, primaryKey, serial, text, timestamp, unique, uniqueIndex } from "drizzle-orm/pg-core";
|
|
33
|
+
import { SignJWT, jwtVerify } from "jose";
|
|
32
34
|
import cors from "@fastify/cors";
|
|
33
35
|
import rateLimit from "@fastify/rate-limit";
|
|
34
36
|
import fastifyStatic from "@fastify/static";
|
|
35
37
|
import websocket from "@fastify/websocket";
|
|
36
38
|
import Fastify from "fastify";
|
|
37
|
-
import { SignJWT, jwtVerify } from "jose";
|
|
38
39
|
import { promisify } from "node:util";
|
|
39
40
|
import matter from "gray-matter";
|
|
40
41
|
import { Client, EventDispatcher, LoggerLevel, WSClient } from "@larksuiteoapi/node-sdk";
|
|
@@ -1808,10 +1809,12 @@ var FirstTreeHubSDK = class {
|
|
|
1808
1809
|
_baseUrl;
|
|
1809
1810
|
getAccessToken;
|
|
1810
1811
|
_agentId;
|
|
1812
|
+
_userAgent;
|
|
1811
1813
|
constructor(config) {
|
|
1812
1814
|
this._baseUrl = config.serverUrl.replace(/\/+$/, "");
|
|
1813
1815
|
this.getAccessToken = config.getAccessToken;
|
|
1814
1816
|
this._agentId = config.agentId;
|
|
1817
|
+
this._userAgent = config.userAgent;
|
|
1815
1818
|
}
|
|
1816
1819
|
/** Server base URL (without trailing slash). */
|
|
1817
1820
|
get serverUrl() {
|
|
@@ -1863,7 +1866,12 @@ var FirstTreeHubSDK = class {
|
|
|
1863
1866
|
async isHubReachable(timeoutMs = 3e3) {
|
|
1864
1867
|
try {
|
|
1865
1868
|
const url = `${this._baseUrl}/api/v1/health`;
|
|
1866
|
-
|
|
1869
|
+
const headers = {};
|
|
1870
|
+
if (this._userAgent) headers["User-Agent"] = this._userAgent;
|
|
1871
|
+
return (await fetch(url, {
|
|
1872
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
1873
|
+
headers
|
|
1874
|
+
})).ok;
|
|
1867
1875
|
} catch {
|
|
1868
1876
|
return false;
|
|
1869
1877
|
}
|
|
@@ -1922,6 +1930,7 @@ var FirstTreeHubSDK = class {
|
|
|
1922
1930
|
const url = `${this._baseUrl}${path}`;
|
|
1923
1931
|
const headers = { Authorization: `Bearer ${await this.getAccessToken()}` };
|
|
1924
1932
|
if (this._agentId) headers[AGENT_SELECTOR_HEADER] = this._agentId;
|
|
1933
|
+
if (this._userAgent) headers["User-Agent"] = this._userAgent;
|
|
1925
1934
|
if (init?.body) headers["Content-Type"] = "application/json";
|
|
1926
1935
|
const timeout = AbortSignal.timeout(FETCH_TIMEOUT_MS);
|
|
1927
1936
|
const signal = init?.signal ? AbortSignal.any([init.signal, timeout]) : timeout;
|
|
@@ -2031,6 +2040,7 @@ var ClientConnection = class extends EventEmitter {
|
|
|
2031
2040
|
clientId;
|
|
2032
2041
|
serverUrl;
|
|
2033
2042
|
sdkVersion;
|
|
2043
|
+
userAgent;
|
|
2034
2044
|
getAccessToken;
|
|
2035
2045
|
ws = null;
|
|
2036
2046
|
wsConnectTimer = null;
|
|
@@ -2084,6 +2094,7 @@ var ClientConnection = class extends EventEmitter {
|
|
|
2084
2094
|
this.clientId = config.clientId ?? process.env.FIRST_TREE_HUB_CLIENT_ID ?? `client_${randomUUID().slice(0, 8)}`;
|
|
2085
2095
|
this.serverUrl = config.serverUrl.replace(/\/+$/, "");
|
|
2086
2096
|
this.sdkVersion = config.sdkVersion;
|
|
2097
|
+
this.userAgent = config.userAgent;
|
|
2087
2098
|
this.getAccessToken = config.getAccessToken;
|
|
2088
2099
|
this.wsLogger = createLogger("ws").child({ clientId: this.clientId });
|
|
2089
2100
|
this.authLogger = createLogger("auth").child({ clientId: this.clientId });
|
|
@@ -2225,7 +2236,7 @@ var ClientConnection = class extends EventEmitter {
|
|
|
2225
2236
|
return new Promise((resolve, reject) => {
|
|
2226
2237
|
const wsUrl = `${this.serverUrl.replace(/^http/, "ws")}/api/v1/agent/ws/client`;
|
|
2227
2238
|
this.wsLogger.info({ url: wsUrl }, "connecting");
|
|
2228
|
-
const ws = new WebSocket(wsUrl);
|
|
2239
|
+
const ws = new WebSocket(wsUrl, this.userAgent ? { headers: { "User-Agent": this.userAgent } } : void 0);
|
|
2229
2240
|
let settled = false;
|
|
2230
2241
|
const settle = (fn, value) => {
|
|
2231
2242
|
if (settled) return;
|
|
@@ -2376,7 +2387,8 @@ var ClientConnection = class extends EventEmitter {
|
|
|
2376
2387
|
const sdk = new FirstTreeHubSDK({
|
|
2377
2388
|
serverUrl: this.serverUrl,
|
|
2378
2389
|
getAccessToken: this.getAccessToken,
|
|
2379
|
-
agentId
|
|
2390
|
+
agentId,
|
|
2391
|
+
userAgent: this.userAgent
|
|
2380
2392
|
});
|
|
2381
2393
|
const agent = {
|
|
2382
2394
|
agentId,
|
|
@@ -6062,71 +6074,6 @@ function sleep(ms) {
|
|
|
6062
6074
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6063
6075
|
}
|
|
6064
6076
|
//#endregion
|
|
6065
|
-
//#region src/core/output.ts
|
|
6066
|
-
/**
|
|
6067
|
-
* Print layer — the only place CLI code should write to stdout/stderr.
|
|
6068
|
-
*
|
|
6069
|
-
* Contract:
|
|
6070
|
-
* - `print.result(data)` / `print.fail(...)` emit machine-readable JSON on
|
|
6071
|
-
* stdout / stderr respectively. Scripts pipe into `jq` and expect a clean
|
|
6072
|
-
* envelope, so nothing else may touch stdout.
|
|
6073
|
-
* - `print.status` / `print.check` / `print.blank` / `print.line` are
|
|
6074
|
-
* human-friendly and go to stderr so they never pollute a redirected stdout.
|
|
6075
|
-
* In `--json` mode they are silenced — scripted consumers only care about
|
|
6076
|
-
* the envelope.
|
|
6077
|
-
*/
|
|
6078
|
-
let jsonMode = false;
|
|
6079
|
-
function setJsonMode(enabled) {
|
|
6080
|
-
jsonMode = enabled;
|
|
6081
|
-
}
|
|
6082
|
-
function result(data) {
|
|
6083
|
-
process.stdout.write(`${JSON.stringify({
|
|
6084
|
-
ok: true,
|
|
6085
|
-
data
|
|
6086
|
-
})}\n`);
|
|
6087
|
-
}
|
|
6088
|
-
function fail$1(code, message, exitCode = 1) {
|
|
6089
|
-
process.stderr.write(`${JSON.stringify({
|
|
6090
|
-
ok: false,
|
|
6091
|
-
error: {
|
|
6092
|
-
code,
|
|
6093
|
-
message
|
|
6094
|
-
}
|
|
6095
|
-
})}\n`);
|
|
6096
|
-
process.exit(exitCode);
|
|
6097
|
-
}
|
|
6098
|
-
function status(label, message) {
|
|
6099
|
-
if (jsonMode) return;
|
|
6100
|
-
process.stderr.write(` ${label.padEnd(20)} ${message}\n`);
|
|
6101
|
-
}
|
|
6102
|
-
function check(pass, label, detail = "") {
|
|
6103
|
-
if (jsonMode) return;
|
|
6104
|
-
const icon = pass ? "✓" : "✗";
|
|
6105
|
-
const tail = detail ? ` ${detail}` : "";
|
|
6106
|
-
process.stderr.write(` ${icon} ${label.padEnd(22)}${tail}\n`);
|
|
6107
|
-
}
|
|
6108
|
-
function blank() {
|
|
6109
|
-
if (jsonMode) return;
|
|
6110
|
-
process.stderr.write("\n");
|
|
6111
|
-
}
|
|
6112
|
-
/**
|
|
6113
|
-
* Generic stderr writer for pre-formatted human text (multi-line tables,
|
|
6114
|
-
* interactive prompts). Prefer `status` / `check` when the text fits; this
|
|
6115
|
-
* exists so the `--json` mode gate can silence arbitrary human chatter.
|
|
6116
|
-
*/
|
|
6117
|
-
function line(text) {
|
|
6118
|
-
if (jsonMode) return;
|
|
6119
|
-
process.stderr.write(text);
|
|
6120
|
-
}
|
|
6121
|
-
const print = {
|
|
6122
|
-
result,
|
|
6123
|
-
fail: fail$1,
|
|
6124
|
-
status,
|
|
6125
|
-
check,
|
|
6126
|
-
blank,
|
|
6127
|
-
line
|
|
6128
|
-
};
|
|
6129
|
-
//#endregion
|
|
6130
6077
|
//#region src/cli/output.ts
|
|
6131
6078
|
/**
|
|
6132
6079
|
* CLI output re-exports. The underlying implementation lives in
|
|
@@ -6491,6 +6438,7 @@ var ClientRuntime = class {
|
|
|
6491
6438
|
serverUrl,
|
|
6492
6439
|
clientId,
|
|
6493
6440
|
sdkVersion: options.currentVersion,
|
|
6441
|
+
userAgent: CLI_USER_AGENT,
|
|
6494
6442
|
getAccessToken: (opts) => ensureFreshAccessToken(opts)
|
|
6495
6443
|
});
|
|
6496
6444
|
registerBuiltinHandlers();
|
|
@@ -7645,7 +7593,7 @@ async function checkServerHealth() {
|
|
|
7645
7593
|
const port = get(config, "server.port") ?? 8e3;
|
|
7646
7594
|
const url = `http://${host}:${port}/healthz`;
|
|
7647
7595
|
try {
|
|
7648
|
-
const res = await
|
|
7596
|
+
const res = await cliFetch(url, { signal: AbortSignal.timeout(3e3) });
|
|
7649
7597
|
if (res.ok) return {
|
|
7650
7598
|
label: "Server Health",
|
|
7651
7599
|
ok: true,
|
|
@@ -7696,7 +7644,7 @@ async function checkServerReachable() {
|
|
|
7696
7644
|
detail: "not configured (FIRST_TREE_HUB_SERVER_URL or config file)"
|
|
7697
7645
|
};
|
|
7698
7646
|
try {
|
|
7699
|
-
const res = await
|
|
7647
|
+
const res = await cliFetch(`${serverUrl}/healthz`, { signal: AbortSignal.timeout(5e3) });
|
|
7700
7648
|
if (res.ok) return {
|
|
7701
7649
|
label: "Server URL",
|
|
7702
7650
|
ok: true,
|
|
@@ -7841,7 +7789,7 @@ async function checkWebSocket() {
|
|
|
7841
7789
|
};
|
|
7842
7790
|
const wsUrl = serverUrl.replace(/^http/, "ws");
|
|
7843
7791
|
try {
|
|
7844
|
-
if ((await
|
|
7792
|
+
if ((await cliFetch(`${serverUrl}/healthz`, { signal: AbortSignal.timeout(3e3) })).ok) return {
|
|
7845
7793
|
label: "WebSocket",
|
|
7846
7794
|
ok: true,
|
|
7847
7795
|
detail: `${wsUrl} (server reachable)`
|
|
@@ -7931,7 +7879,7 @@ function createApiNameResolver(serverUrl, getAccessToken) {
|
|
|
7931
7879
|
if (cache) return cache;
|
|
7932
7880
|
const token = await getAccessToken();
|
|
7933
7881
|
const map = /* @__PURE__ */ new Map();
|
|
7934
|
-
const res = await
|
|
7882
|
+
const res = await cliFetch(`${serverUrl}/api/v1/me/managed-agents`, {
|
|
7935
7883
|
method: "GET",
|
|
7936
7884
|
headers: { Authorization: `Bearer ${token}` },
|
|
7937
7885
|
signal: AbortSignal.timeout(1e4)
|
|
@@ -8163,7 +8111,7 @@ async function onboardCheck(args) {
|
|
|
8163
8111
|
value: serverUrl
|
|
8164
8112
|
});
|
|
8165
8113
|
try {
|
|
8166
|
-
const res = await
|
|
8114
|
+
const res = await cliFetch(`${serverUrl}/api/v1/health`);
|
|
8167
8115
|
items.push({
|
|
8168
8116
|
key: "server_reachable",
|
|
8169
8117
|
label: "Server reachable",
|
|
@@ -8235,7 +8183,7 @@ function formatCheckReport(items) {
|
|
|
8235
8183
|
return lines.join("\n");
|
|
8236
8184
|
}
|
|
8237
8185
|
async function resolveDefaultOrgId$1(serverUrl, accessToken) {
|
|
8238
|
-
const res = await
|
|
8186
|
+
const res = await cliFetch(`${serverUrl}/api/v1/me`, {
|
|
8239
8187
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
8240
8188
|
signal: AbortSignal.timeout(1e4)
|
|
8241
8189
|
});
|
|
@@ -8247,7 +8195,7 @@ async function resolveDefaultOrgId$1(serverUrl, accessToken) {
|
|
|
8247
8195
|
throw new Error("Multiple organizations — pass --org explicitly to onboard");
|
|
8248
8196
|
}
|
|
8249
8197
|
async function createAgentViaAdmin(serverUrl, accessToken, orgId, body) {
|
|
8250
|
-
const res = await
|
|
8198
|
+
const res = await cliFetch(`${serverUrl}/api/v1/orgs/${encodeURIComponent(orgId)}/agents`, {
|
|
8251
8199
|
method: "POST",
|
|
8252
8200
|
headers: {
|
|
8253
8201
|
Authorization: `Bearer ${accessToken}`,
|
|
@@ -8306,7 +8254,7 @@ async function onboardCreate(args) {
|
|
|
8306
8254
|
}
|
|
8307
8255
|
const runtimeAgent = args.type === "human" ? args.assistant : args.id;
|
|
8308
8256
|
if (args.feishuBotAppId && args.feishuBotAppSecret) {
|
|
8309
|
-
const { bindFeishuBot } = await import("./feishu-
|
|
8257
|
+
const { bindFeishuBot } = await import("./feishu-Th_-ivJ7.mjs").then((n) => n.r);
|
|
8310
8258
|
const targetAgentUuid = args.type === "human" ? assistantUuid : primary.uuid;
|
|
8311
8259
|
if (!targetAgentUuid) print.line(`Warning: Cannot bind Feishu bot — no runtime agent available for "${args.id}".\n`);
|
|
8312
8260
|
else {
|
|
@@ -8406,7 +8354,7 @@ async function promptAddAgent(opts = {}) {
|
|
|
8406
8354
|
validate: (v) => v.length > 0 ? true : "Agent UUID is required"
|
|
8407
8355
|
});
|
|
8408
8356
|
const token = await ensureFreshAccessToken();
|
|
8409
|
-
const res = await
|
|
8357
|
+
const res = await cliFetch(`${serverUrl}/api/v1/agents/${encodeURIComponent(agentId)}`, {
|
|
8410
8358
|
headers: { Authorization: `Bearer ${token}` },
|
|
8411
8359
|
signal: AbortSignal.timeout(1e4)
|
|
8412
8360
|
});
|
|
@@ -8478,7 +8426,7 @@ function setNestedByDot(obj, dotPath, value) {
|
|
|
8478
8426
|
* value (the in-band repair path catches any remaining drift on first bind).
|
|
8479
8427
|
*/
|
|
8480
8428
|
async function reconcileLocalRuntimeProviders(opts) {
|
|
8481
|
-
const res = await
|
|
8429
|
+
const res = await cliFetch(`${opts.serverUrl}/api/v1/me/pinned-agents`, { headers: { Authorization: `Bearer ${opts.accessToken}` } });
|
|
8482
8430
|
if (!res.ok) throw new Error(`hub returned ${res.status} on /clients/me/agents`);
|
|
8483
8431
|
const items = await res.json();
|
|
8484
8432
|
const byAgentId = new Map(items.map((it) => [it.agentId, it]));
|
|
@@ -8518,7 +8466,7 @@ async function reconcileLocalRuntimeProviders(opts) {
|
|
|
8518
8466
|
* client startup since capabilities only matter for UI / admin checks.
|
|
8519
8467
|
*/
|
|
8520
8468
|
async function uploadClientCapabilities(opts) {
|
|
8521
|
-
const res = await
|
|
8469
|
+
const res = await cliFetch(`${opts.serverUrl}/api/v1/clients/${encodeURIComponent(opts.clientId)}/capabilities`, {
|
|
8522
8470
|
method: "PATCH",
|
|
8523
8471
|
headers: {
|
|
8524
8472
|
Authorization: `Bearer ${opts.accessToken}`,
|
|
@@ -9519,7 +9467,7 @@ function createFeedbackHandler(config) {
|
|
|
9519
9467
|
return { handle };
|
|
9520
9468
|
}
|
|
9521
9469
|
//#endregion
|
|
9522
|
-
//#region ../server/dist/app-
|
|
9470
|
+
//#region ../server/dist/app-EvpSNDM6.mjs
|
|
9523
9471
|
var import_fastify_opentelemetry = /* @__PURE__ */ __toESM(require_fastify_opentelemetry(), 1);
|
|
9524
9472
|
init_esm();
|
|
9525
9473
|
var __defProp = Object.defineProperty;
|
|
@@ -13653,8 +13601,12 @@ function clientWsRoutes(notifier, instanceId) {
|
|
|
13653
13601
|
return async (app) => {
|
|
13654
13602
|
const jwtSecretBytes = new TextEncoder().encode(app.config.secrets.jwtSecret);
|
|
13655
13603
|
const inboxMaxInFlightPerAgent = app.config.inbox?.maxInFlightPerAgent ?? DEFAULT_INBOX_MAX_IN_FLIGHT_PER_AGENT;
|
|
13656
|
-
app.get("/client", { websocket: true }, async (socket) => {
|
|
13657
|
-
|
|
13604
|
+
app.get("/client", { websocket: true }, async (socket, request) => {
|
|
13605
|
+
const ua = request.headers["user-agent"];
|
|
13606
|
+
startWsConnectionSpan(socket, {
|
|
13607
|
+
remoteIp: request.ip,
|
|
13608
|
+
userAgent: typeof ua === "string" ? ua.slice(0, 200) : void 0
|
|
13609
|
+
});
|
|
13658
13610
|
let session = null;
|
|
13659
13611
|
let jwtDefaultOrgId = null;
|
|
13660
13612
|
let clientId = null;
|
|
@@ -14566,8 +14518,12 @@ async function refreshAccessToken(db, refreshToken, jwtSecretKey, expiries) {
|
|
|
14566
14518
|
try {
|
|
14567
14519
|
const { payload: p } = await jwtVerify(refreshToken, secret);
|
|
14568
14520
|
payload = p;
|
|
14569
|
-
} catch {
|
|
14570
|
-
|
|
14521
|
+
} catch (err) {
|
|
14522
|
+
const untrusted = decodeJwtForTrace(refreshToken);
|
|
14523
|
+
throw new UnauthorizedError("Invalid or expired refresh token", {
|
|
14524
|
+
"auth.refresh.reason": classifyJoseError(err),
|
|
14525
|
+
...untrustedAttrs("auth.refresh", untrusted)
|
|
14526
|
+
});
|
|
14571
14527
|
}
|
|
14572
14528
|
if (payload.type !== "refresh" || !payload.sub) throw new UnauthorizedError("Invalid token type", {
|
|
14573
14529
|
"auth.refresh.reason": "wrong_token_type",
|
|
@@ -14618,10 +14574,17 @@ async function exchangeConnectToken(db, connectToken, jwtSecretKey, expiries) {
|
|
|
14618
14574
|
try {
|
|
14619
14575
|
const { payload: p } = await jwtVerify(connectToken, secret);
|
|
14620
14576
|
payload = p;
|
|
14621
|
-
} catch {
|
|
14622
|
-
|
|
14577
|
+
} catch (err) {
|
|
14578
|
+
const untrusted = decodeJwtForTrace(connectToken);
|
|
14579
|
+
throw new UnauthorizedError("Invalid or expired connect token", {
|
|
14580
|
+
"auth.connect.reason": classifyJoseError(err),
|
|
14581
|
+
...untrustedAttrs("auth.connect", untrusted)
|
|
14582
|
+
});
|
|
14623
14583
|
}
|
|
14624
|
-
if (payload.type !== "connect" || !payload.sub) throw new UnauthorizedError("Invalid token type — expected connect token"
|
|
14584
|
+
if (payload.type !== "connect" || !payload.sub) throw new UnauthorizedError("Invalid token type — expected connect token", {
|
|
14585
|
+
"auth.connect.reason": "wrong_token_type",
|
|
14586
|
+
"auth.connect.actual_type": String(payload.type ?? "<missing>")
|
|
14587
|
+
});
|
|
14625
14588
|
const jti = payload.jti;
|
|
14626
14589
|
if (jti) {
|
|
14627
14590
|
if (consumedConnectJtis.has(jti)) throw new UnauthorizedError("Connect token has already been used");
|
|
@@ -16838,7 +16801,7 @@ async function healthzRoutes(app) {
|
|
|
16838
16801
|
* `api/orgs/invitations.ts` (Class B, admin-gated).
|
|
16839
16802
|
*/
|
|
16840
16803
|
async function publicInvitationRoutes(app) {
|
|
16841
|
-
const { previewInvitation } = await import("./invitation-DWlyNb8x-
|
|
16804
|
+
const { previewInvitation } = await import("./invitation-DWlyNb8x-D3zjZSwI.mjs");
|
|
16842
16805
|
app.get("/:token/preview", async (request, reply) => {
|
|
16843
16806
|
if (!request.params.token) throw new UnauthorizedError("Token required");
|
|
16844
16807
|
const preview = await previewInvitation(app.db, request.params.token);
|
|
@@ -16935,7 +16898,7 @@ async function meRoutes(app) {
|
|
|
16935
16898
|
*/
|
|
16936
16899
|
app.get("/me/pinned-agents", async (request) => {
|
|
16937
16900
|
const { userId } = requireUser(request);
|
|
16938
|
-
const { listMyPinnedAgents } = await import("./client-By1K4VVT-
|
|
16901
|
+
const { listMyPinnedAgents } = await import("./client-By1K4VVT-C5K7WZo6.mjs");
|
|
16939
16902
|
return listMyPinnedAgents(app.db, { userId });
|
|
16940
16903
|
});
|
|
16941
16904
|
/**
|
|
@@ -17760,7 +17723,11 @@ function orgWsRoutes(notifier, jwtSecret) {
|
|
|
17760
17723
|
}
|
|
17761
17724
|
return async (app) => {
|
|
17762
17725
|
app.get("/", { websocket: true }, async (socket, request) => {
|
|
17763
|
-
|
|
17726
|
+
const ua = request.headers["user-agent"];
|
|
17727
|
+
startWsConnectionSpan(socket, {
|
|
17728
|
+
remoteIp: request.ip,
|
|
17729
|
+
userAgent: typeof ua === "string" ? ua.slice(0, 200) : void 0
|
|
17730
|
+
});
|
|
17764
17731
|
const orgIdFromPath = request.params.orgId;
|
|
17765
17732
|
const token = request.query.token;
|
|
17766
17733
|
if (!token || !orgIdFromPath) {
|
|
@@ -18531,8 +18498,12 @@ function userAuthHook(db, jwtSecret) {
|
|
|
18531
18498
|
try {
|
|
18532
18499
|
const { payload: p } = await jwtVerify(token, secret);
|
|
18533
18500
|
payload = p;
|
|
18534
|
-
} catch {
|
|
18535
|
-
|
|
18501
|
+
} catch (err) {
|
|
18502
|
+
const untrusted = decodeJwtForTrace(token);
|
|
18503
|
+
throw new UnauthorizedError("Invalid or expired token", {
|
|
18504
|
+
"auth.failure_reason": classifyJoseError(err),
|
|
18505
|
+
...untrustedAttrs("auth", untrusted)
|
|
18506
|
+
});
|
|
18536
18507
|
}
|
|
18537
18508
|
if (payload.type !== "access" || !payload.sub) throw new UnauthorizedError("Invalid token type", {
|
|
18538
18509
|
"auth.failure_reason": "wrong_token_type",
|
|
@@ -19736,7 +19707,7 @@ function createPulseAggregator(options) {
|
|
|
19736
19707
|
* Returning a string (rather than undefined) keeps the welcome frame well-
|
|
19737
19708
|
* formed — the client treats the value advisorily.
|
|
19738
19709
|
*/
|
|
19739
|
-
function resolveCommandVersion
|
|
19710
|
+
function resolveCommandVersion(injected) {
|
|
19740
19711
|
if (injected && injected.trim().length > 0) return injected;
|
|
19741
19712
|
try {
|
|
19742
19713
|
const pkg = createRequire(import.meta.url)("../package.json");
|
|
@@ -19828,7 +19799,7 @@ async function buildApp(config) {
|
|
|
19828
19799
|
const db = connectDatabase(config.database.url);
|
|
19829
19800
|
app.decorate("db", db);
|
|
19830
19801
|
app.decorate("config", config);
|
|
19831
|
-
const commandVersion = resolveCommandVersion
|
|
19802
|
+
const commandVersion = resolveCommandVersion(config.commandVersion);
|
|
19832
19803
|
app.decorate("commandVersion", commandVersion);
|
|
19833
19804
|
app.log.info({ commandVersion }, "Hub server advertising command version");
|
|
19834
19805
|
const listenClient = postgres(config.database.url, { max: 1 });
|
|
@@ -19843,7 +19814,8 @@ async function buildApp(config) {
|
|
|
19843
19814
|
await app.register(rateLimit, {
|
|
19844
19815
|
max: config.rateLimit?.max ?? 100,
|
|
19845
19816
|
timeWindow: "1 minute",
|
|
19846
|
-
hook: "preHandler"
|
|
19817
|
+
hook: "preHandler",
|
|
19818
|
+
errorResponseBuilder: buildRateLimitError
|
|
19847
19819
|
});
|
|
19848
19820
|
app.addHook("onSend", bodyCaptureOnSendHook);
|
|
19849
19821
|
const userAuth = userAuthHook(db, config.secrets.jwtSecret);
|
|
@@ -20042,58 +20014,6 @@ async function buildApp(config) {
|
|
|
20042
20014
|
return app;
|
|
20043
20015
|
}
|
|
20044
20016
|
//#endregion
|
|
20045
|
-
//#region src/core/version.ts
|
|
20046
|
-
/**
|
|
20047
|
-
* Version of the consumer-facing `@agent-team-foundation/first-tree-hub`
|
|
20048
|
-
* package. Read once at module load so the CLI, client runtime, and server
|
|
20049
|
-
* bootstrap all quote the same string.
|
|
20050
|
-
*
|
|
20051
|
-
* Path-based lookups (`require("../../package.json")`) do not survive the
|
|
20052
|
-
* tsdown bundle: the source lives at `src/core/version.ts` but every
|
|
20053
|
-
* emitted chunk lands in `dist/` — shifting the relative depth by one and
|
|
20054
|
-
* pointing at `packages/package.json` instead of our own manifest (the
|
|
20055
|
-
* v0.9.1 "Cannot find module ../../package.json" crash). Walk up from this
|
|
20056
|
-
* module's URL and accept the first `package.json` whose `name` matches, so
|
|
20057
|
-
* dev runs (`tsx src/cli/index.ts`) and the published bundle
|
|
20058
|
-
* (`dist/cli/index.mjs`) both resolve the same file.
|
|
20059
|
-
*/
|
|
20060
|
-
const PACKAGE_NAME$1 = "@agent-team-foundation/first-tree-hub";
|
|
20061
|
-
/**
|
|
20062
|
-
* Sentinel returned when the walker exhausts every parent directory without
|
|
20063
|
-
* finding our manifest. Deliberately NOT valid SemVer so the client-side
|
|
20064
|
-
* `UpdateManager` drops into its `semver.valid(current) === false` warn-and-
|
|
20065
|
-
* skip branch instead of treating it as `< target` and triggering a spurious
|
|
20066
|
-
* self-update loop (the scenario where the startup crash this module fixes
|
|
20067
|
-
* would otherwise quietly reincarnate as repeated `npm install -g @latest`).
|
|
20068
|
-
*/
|
|
20069
|
-
const UNRESOLVED_VERSION = "unknown";
|
|
20070
|
-
/**
|
|
20071
|
-
* Exported for tests. Walks up from `moduleUrl`'s directory looking for a
|
|
20072
|
-
* `package.json` whose `name` field equals {@link PACKAGE_NAME}. Returns
|
|
20073
|
-
* {@link UNRESOLVED_VERSION} as a last-resort fallback so the CLI never
|
|
20074
|
-
* crashes on a missing manifest.
|
|
20075
|
-
*/
|
|
20076
|
-
function resolveCommandVersion(moduleUrl = import.meta.url) {
|
|
20077
|
-
let dir = dirname(fileURLToPath(moduleUrl));
|
|
20078
|
-
for (let i = 0; i < 10; i++) {
|
|
20079
|
-
try {
|
|
20080
|
-
const pkg = JSON.parse(readFileSync(resolve(dir, "package.json"), "utf8"));
|
|
20081
|
-
if (pkg.name === PACKAGE_NAME$1 && typeof pkg.version === "string" && pkg.version.length > 0) return pkg.version;
|
|
20082
|
-
} catch (err) {
|
|
20083
|
-
const code = err.code;
|
|
20084
|
-
if (code !== "ENOENT" && code !== "ENOTDIR") {
|
|
20085
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
20086
|
-
print.line(`[first-tree-hub] warning: could not read ${dir}/package.json: ${message}\n`);
|
|
20087
|
-
}
|
|
20088
|
-
}
|
|
20089
|
-
const parent = dirname(dir);
|
|
20090
|
-
if (parent === dir) break;
|
|
20091
|
-
dir = parent;
|
|
20092
|
-
}
|
|
20093
|
-
return UNRESOLVED_VERSION;
|
|
20094
|
-
}
|
|
20095
|
-
const COMMAND_VERSION = resolveCommandVersion();
|
|
20096
|
-
//#endregion
|
|
20097
20017
|
//#region src/core/server.ts
|
|
20098
20018
|
/**
|
|
20099
20019
|
* Full server start orchestration:
|
|
@@ -20148,7 +20068,7 @@ async function startServer(options) {
|
|
|
20148
20068
|
instanceId: `srv_${randomUUID().slice(0, 8)}`,
|
|
20149
20069
|
commandVersion: COMMAND_VERSION
|
|
20150
20070
|
};
|
|
20151
|
-
const { initTelemetry, shutdownTelemetry } = await import("./observability-
|
|
20071
|
+
const { initTelemetry, shutdownTelemetry } = await import("./observability-CYsdAcoF.mjs");
|
|
20152
20072
|
await initTelemetry(serverConfig.observability.tracing, config.instanceId);
|
|
20153
20073
|
const app = await buildApp(config);
|
|
20154
20074
|
const SHUTDOWN_FORCE_EXIT_MS = 8e3;
|
|
@@ -20509,7 +20429,7 @@ async function promptReplaceOrCancel(newMemberId) {
|
|
|
20509
20429
|
}) === "replace" ? "proceed" : "cancel";
|
|
20510
20430
|
}
|
|
20511
20431
|
async function exchangeToken(url, token) {
|
|
20512
|
-
const res = await
|
|
20432
|
+
const res = await cliFetch(`${url}/api/v1/auth/connect-token`, {
|
|
20513
20433
|
method: "POST",
|
|
20514
20434
|
headers: { "Content-Type": "application/json" },
|
|
20515
20435
|
body: JSON.stringify({ token }),
|
|
@@ -20621,4 +20541,4 @@ function registerSaaSConnectCommand(program) {
|
|
|
20621
20541
|
});
|
|
20622
20542
|
}
|
|
20623
20543
|
//#endregion
|
|
20624
|
-
export {
|
|
20544
|
+
export { formatStaleReason as $, checkDocker as A, isServiceSupported as B, createApiNameResolver as C, checkBackgroundService as D, checkAgentConfigs as E, checkWebSocket as F, uninstallClientService as G, restartClientService as H, printResults as I, stopPostgres as J, ensurePostgres as K, reconcileAgentConfigs as L, checkServerConfig as M, checkServerHealth as N, checkClientConfig as O, checkServerReachable as P, findStaleAliases as Q, getClientServiceStatus as R, runHomeMigration as S, runMigrations as T, startClientService as U, resolveCliInvocation as V, stopClientService as W, handleClientOrgMismatch as X, ClientRuntime as Y, rotateClientIdWithBackup as Z, formatCheckReport as _, declineUpdate as a, success as at, onboardCreate as b, detectInstallMode as c, FirstTreeHubSDK as ct, startServer as d, cleanWorkspaces as dt, removeLocalAgent as et, reconcileLocalRuntimeProviders as f, probeCapabilities as ft, promptMissingFields as g, promptAddAgent as h, createExecuteUpdate as i, fail as it, checkNodeVersion as j, checkDatabase as k, fetchLatestVersion as l, SdkError as lt, isInteractive as m, configureClientLoggerForService as mt, deriveHubUrlFromToken as n, hasUser as nt, promptUpdate as o, ClientOrgMismatchError as ot, uploadClientCapabilities as p, applyClientLoggerConfig as pt, isDockerAvailable as q, registerSaaSConnectCommand as r, resolveReplyToFromEnv as rt, PACKAGE_NAME as s, ClientUserMismatchError as st, HubUrlDerivationError as t, createOwner as tt, installGlobalLatest as u, SessionRegistry as ut, loadOnboardState as v, migrateLocalAgentDirs as w, saveOnboardState as x, onboardCheck as y, installClientService as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as __esmMin } from "./chunk-BSw8zbkd.mjs";
|
|
2
|
-
import { i as init_esm_min, n as FormData, o as Blob, r as formDataToBlob, s as init_fetch_blob, t as init_from } from "./from-
|
|
2
|
+
import { i as init_esm_min, n as FormData, o as Blob, r as formDataToBlob, s as init_fetch_blob, t as init_from } from "./from-DQ7eNRwu.mjs";
|
|
3
3
|
import Stream, { PassThrough, pipeline } from "node:stream";
|
|
4
4
|
import { format } from "node:url";
|
|
5
5
|
import { deprecate, promisify, types } from "node:util";
|
|
@@ -209,7 +209,7 @@ var init_body = __esmMin((() => {
|
|
|
209
209
|
for (const [name, value] of parameters) formData.append(name, value);
|
|
210
210
|
return formData;
|
|
211
211
|
}
|
|
212
|
-
const { toFormData } = await import("./multipart-parser-
|
|
212
|
+
const { toFormData } = await import("./multipart-parser-QRu3OKK4.mjs");
|
|
213
213
|
return toFormData(this.body, ct);
|
|
214
214
|
}
|
|
215
215
|
/**
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|