@agent-team-foundation/first-tree-hub 0.11.4 → 0.11.5
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-D-Yf8yOc.mjs → bootstrap-C_K2CKXC.mjs} +7 -0
- package/dist/cli/index.mjs +71 -9
- package/dist/client-D_TRJFZY-LbgJF47t.mjs +4 -0
- package/dist/{client-CLdRbuml-svTO0Eat.mjs → client-DqdGiggm-NQoGZ2vM.mjs} +3 -3
- package/dist/{dist-ClFs4WMj.mjs → dist-CfvCT4E0.mjs} +266 -194
- package/dist/drizzle/0033_onboarding_dismissed_at.sql +13 -0
- package/dist/drizzle/meta/_journal.json +7 -0
- package/dist/{errors-BmyRwN0Y-Dad3eV8F.mjs → errors-CF5evtJt-B0NTIVPt.mjs} +2 -1
- package/dist/{feishu-AI3pwmqN.mjs → feishu-DbSvp9UH.mjs} +1 -1
- package/dist/index.mjs +7 -7
- package/dist/{invitation-Dnn5gGGX-DXryyvRG.mjs → invitation-Bg0TRiyx-BsZH4GCS.mjs} +2 -2
- package/dist/invitation-C299fxkP-BR-niZyp.mjs +4 -0
- package/dist/{saas-connect-CVoRK0Ex.mjs → saas-connect-CO554S-V.mjs} +737 -254
- package/dist/web/assets/{index-Bm6hgcvt.js → index-B7noAoV-.js} +1 -1
- package/dist/web/assets/index-DPLa60vJ.css +1 -0
- package/dist/web/assets/index-DvGkka4N.js +390 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/client-By1K4VVT-DuI6EnSh.mjs +0 -4
- package/dist/invitation-DWlyNb8x-BvXubk24.mjs +0 -4
- package/dist/web/assets/index-fNb_M0nL.css +0 -1
- package/dist/web/assets/index-k2bWRKc-.js +0 -388
|
@@ -569,6 +569,13 @@ const serverConfigSchema = defineConfig({
|
|
|
569
569
|
refreshTokenExpiry: field(z.string().default("30d"), { env: "FIRST_TREE_HUB_AUTH_REFRESH_TOKEN_EXPIRY" }),
|
|
570
570
|
connectTokenExpiry: field(z.string().default("10m"), { env: "FIRST_TREE_HUB_AUTH_CONNECT_TOKEN_EXPIRY" })
|
|
571
571
|
},
|
|
572
|
+
contextTreeSync: optional({
|
|
573
|
+
githubToken: field(z.string(), {
|
|
574
|
+
env: "FIRST_TREE_HUB_CONTEXT_TREE_GITHUB_TOKEN",
|
|
575
|
+
secret: true
|
|
576
|
+
}),
|
|
577
|
+
githubTokenRepos: field(z.string().optional(), { env: "FIRST_TREE_HUB_CONTEXT_TREE_GITHUB_TOKEN_REPOS" })
|
|
578
|
+
}),
|
|
572
579
|
oauth: optional({ github: optional({
|
|
573
580
|
clientId: field(z.string(), { env: "FIRST_TREE_HUB_GITHUB_OAUTH_CLIENT_ID" }),
|
|
574
581
|
clientSecret: field(z.string(), {
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "../observability-BAScT_5S-gw1ODB_o.mjs";
|
|
3
|
-
import { $ as formatStaleReason, A as checkDocker, B as isServiceSupported, C as createApiNameResolver, D as checkBackgroundService, E as checkAgentConfigs, F as checkWebSocket, H as restartClientService, I as printResults, J as stopPostgres, L as reconcileAgentConfigs, M as checkServerConfig, N as checkServerHealth, O as checkClientConfig, P as checkServerReachable, Q as findStaleAliases, R as getClientServiceStatus, S as runHomeMigration, T as runMigrations, U as startClientService, W as stopClientService, X as handleClientOrgMismatch, Y as ClientRuntime, _ as formatCheckReport, a as declineUpdate, at as success, b as onboardCreate, c as detectInstallMode, ct as FirstTreeHubSDK, d as startServer, dt as cleanWorkspaces, et as removeLocalAgent, f as reconcileLocalRuntimeProviders, ft as probeCapabilities, g as promptMissingFields, h as promptAddAgent, i as createExecuteUpdate, it as fail, j as checkNodeVersion, k as checkDatabase, l as fetchLatestVersion, lt as SdkError, m as isInteractive, mt as configureClientLoggerForService, o as promptUpdate, ot as ClientOrgMismatchError, p as uploadClientCapabilities, pt as applyClientLoggerConfig, r as registerSaaSConnectCommand, rt as resolveReplyToFromEnv, s as PACKAGE_NAME, st as ClientUserMismatchError, tt as createOwner, u as installGlobalLatest, ut as SessionRegistry, v as loadOnboardState, w as migrateLocalAgentDirs, x as saveOnboardState, y as onboardCheck, z as installClientService } from "../saas-connect-
|
|
3
|
+
import { $ as formatStaleReason, A as checkDocker, B as isServiceSupported, C as createApiNameResolver, D as checkBackgroundService, E as checkAgentConfigs, F as checkWebSocket, H as restartClientService, I as printResults, J as stopPostgres, L as reconcileAgentConfigs, M as checkServerConfig, N as checkServerHealth, O as checkClientConfig, P as checkServerReachable, Q as findStaleAliases, R as getClientServiceStatus, S as runHomeMigration, T as runMigrations, U as startClientService, W as stopClientService, X as handleClientOrgMismatch, Y as ClientRuntime, _ as formatCheckReport, a as declineUpdate, at as success, b as onboardCreate, c as detectInstallMode, ct as FirstTreeHubSDK, d as startServer, dt as cleanWorkspaces, et as removeLocalAgent, f as reconcileLocalRuntimeProviders, ft as probeCapabilities, g as promptMissingFields, h as promptAddAgent, i as createExecuteUpdate, it as fail, j as checkNodeVersion, k as checkDatabase, l as fetchLatestVersion, lt as SdkError, m as isInteractive, mt as configureClientLoggerForService, o as promptUpdate, ot as ClientOrgMismatchError, p as uploadClientCapabilities, pt as applyClientLoggerConfig, r as registerSaaSConnectCommand, rt as resolveReplyToFromEnv, s as PACKAGE_NAME, st as ClientUserMismatchError, tt as createOwner, u as installGlobalLatest, ut as SessionRegistry, v as loadOnboardState, w as migrateLocalAgentDirs, x as saveOnboardState, y as onboardCheck, z as installClientService } from "../saas-connect-CO554S-V.mjs";
|
|
4
4
|
import "../logger-core-BTmvdflj-DjW8FM4T.mjs";
|
|
5
|
-
import { C as resetConfigMeta, E as setConfigValue, S as resetConfig, T as serverConfigSchema, _ as getConfigValue, a as ensureFreshAdminToken, c as resolveServerUrl, d as DEFAULT_CONFIG_DIR, f as DEFAULT_DATA_DIR, h as clientConfigSchema, i as ensureFreshAccessToken, l as saveAgentConfig, m as agentConfigSchema, o as loadCredentials, p as DEFAULT_HOME_DIR, u as saveCredentials, v as initConfig, w as resolveConfigReadonly, x as readConfigFile, y as loadAgents } from "../bootstrap-
|
|
5
|
+
import { C as resetConfigMeta, E as setConfigValue, S as resetConfig, T as serverConfigSchema, _ as getConfigValue, a as ensureFreshAdminToken, c as resolveServerUrl, d as DEFAULT_CONFIG_DIR, f as DEFAULT_DATA_DIR, h as clientConfigSchema, i as ensureFreshAccessToken, l as saveAgentConfig, m as agentConfigSchema, o as loadCredentials, p as DEFAULT_HOME_DIR, u as saveCredentials, v as initConfig, w as resolveConfigReadonly, x as readConfigFile, y as loadAgents } from "../bootstrap-C_K2CKXC.mjs";
|
|
6
6
|
import { a as print, n as CLI_USER_AGENT, o as setJsonMode, r as COMMAND_VERSION, t as cliFetch } from "../cli-fetch--tiwKm5S.mjs";
|
|
7
|
-
import "../dist-
|
|
8
|
-
import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-
|
|
9
|
-
import "../errors-
|
|
10
|
-
import "../client-
|
|
7
|
+
import "../dist-CfvCT4E0.mjs";
|
|
8
|
+
import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-DbSvp9UH.mjs";
|
|
9
|
+
import "../errors-CF5evtJt-B0NTIVPt.mjs";
|
|
10
|
+
import "../client-DqdGiggm-NQoGZ2vM.mjs";
|
|
11
11
|
import "../src-aJMV60mR.mjs";
|
|
12
|
-
import "../invitation-
|
|
12
|
+
import "../invitation-Bg0TRiyx-BsZH4GCS.mjs";
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
import { existsSync, mkdirSync, readFileSync, readdirSync } from "node:fs";
|
|
15
15
|
import * as semver from "semver";
|
|
@@ -1670,13 +1670,13 @@ function isSecretField(schema, dotPath) {
|
|
|
1670
1670
|
//#region src/commands/onboard.ts
|
|
1671
1671
|
async function promptMissing(args) {
|
|
1672
1672
|
if (!args.server) try {
|
|
1673
|
-
const { resolveServerUrl } = await import("../bootstrap-
|
|
1673
|
+
const { resolveServerUrl } = await import("../bootstrap-C_K2CKXC.mjs").then((n) => n.r);
|
|
1674
1674
|
resolveServerUrl();
|
|
1675
1675
|
} catch {
|
|
1676
1676
|
args.server = await input({ message: "Hub server URL:" });
|
|
1677
1677
|
saveOnboardState(args);
|
|
1678
1678
|
}
|
|
1679
|
-
const { loadCredentials } = await import("../bootstrap-
|
|
1679
|
+
const { loadCredentials } = await import("../bootstrap-C_K2CKXC.mjs").then((n) => n.r);
|
|
1680
1680
|
if (!loadCredentials()) throw new Error("No saved credentials. Run `first-tree-hub client connect <server-url>` before onboarding.");
|
|
1681
1681
|
if (!args.id) {
|
|
1682
1682
|
args.id = await input({ message: "Agent ID:" });
|
|
@@ -1798,6 +1798,67 @@ function registerOnboardCommand(program) {
|
|
|
1798
1798
|
});
|
|
1799
1799
|
}
|
|
1800
1800
|
//#endregion
|
|
1801
|
+
//#region src/commands/org.ts
|
|
1802
|
+
/**
|
|
1803
|
+
* `first-tree-hub org` — organization-level operations.
|
|
1804
|
+
*
|
|
1805
|
+
* Today this only ships `bind-tree`, called by Step 3 onboarding agents
|
|
1806
|
+
* after they create a fresh context-tree GitHub repo so the Hub records
|
|
1807
|
+
* the binding in the org's `context_tree` settings namespace. The verb
|
|
1808
|
+
* mirrors first-tree CLI's own `tree bind` vocabulary so agents reading
|
|
1809
|
+
* "bind-tree" know what it means without translation. See
|
|
1810
|
+
* docs/new-user-onboarding-design.md §7.4 (Path B).
|
|
1811
|
+
*/
|
|
1812
|
+
function registerOrgCommands(program) {
|
|
1813
|
+
program.command("org").description("Organization-level operations").command("bind-tree").description("Bind the caller's organization to a context-tree GitHub URL").argument("<url>", "GitHub URL of the context-tree repository (https://github.com/...)").option("--org <orgId>", "Override the org to bind. Defaults to your selected/default org via /me.").action(async (rawUrl, options) => {
|
|
1814
|
+
try {
|
|
1815
|
+
const url = rawUrl.trim();
|
|
1816
|
+
if (!url) fail("INVALID_URL", "URL must not be empty", 2);
|
|
1817
|
+
try {
|
|
1818
|
+
const parsed = new URL(url);
|
|
1819
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") fail("INVALID_URL", `URL scheme must be http or https (got ${parsed.protocol})`, 2);
|
|
1820
|
+
} catch {
|
|
1821
|
+
fail("INVALID_URL", `"${url}" is not a valid URL`, 2);
|
|
1822
|
+
}
|
|
1823
|
+
const serverUrl = resolveServerUrl();
|
|
1824
|
+
const accessToken = await ensureFreshAccessToken();
|
|
1825
|
+
const orgId = options.org?.trim() || await resolveDefaultOrgId(serverUrl, accessToken);
|
|
1826
|
+
const res = await fetch(`${serverUrl}/api/v1/orgs/${encodeURIComponent(orgId)}/settings/context_tree`, {
|
|
1827
|
+
method: "PUT",
|
|
1828
|
+
headers: {
|
|
1829
|
+
Authorization: `Bearer ${accessToken}`,
|
|
1830
|
+
"Content-Type": "application/json"
|
|
1831
|
+
},
|
|
1832
|
+
body: JSON.stringify({ repo: url })
|
|
1833
|
+
});
|
|
1834
|
+
if (!res.ok) {
|
|
1835
|
+
const text = await res.text().catch(() => "");
|
|
1836
|
+
fail("PUT_FAILED", `hub returned ${res.status} on PUT /orgs/${orgId}/settings/context_tree: ${text.slice(0, 256)}`, 1);
|
|
1837
|
+
}
|
|
1838
|
+
print.status("•", `Bound organization to context-tree at ${url}`);
|
|
1839
|
+
success({
|
|
1840
|
+
orgId,
|
|
1841
|
+
repo: url
|
|
1842
|
+
});
|
|
1843
|
+
} catch (err) {
|
|
1844
|
+
fail("UNEXPECTED", err instanceof Error ? err.message : String(err), 1);
|
|
1845
|
+
}
|
|
1846
|
+
});
|
|
1847
|
+
}
|
|
1848
|
+
async function resolveDefaultOrgId(serverUrl, accessToken) {
|
|
1849
|
+
const res = await fetch(`${serverUrl}/api/v1/me`, {
|
|
1850
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
1851
|
+
signal: AbortSignal.timeout(1e4)
|
|
1852
|
+
});
|
|
1853
|
+
if (!res.ok) fail("ME_FAILED", `hub returned ${res.status} on /me`, 1);
|
|
1854
|
+
const me = await res.json();
|
|
1855
|
+
const memberships = me.memberships ?? [];
|
|
1856
|
+
if (me.defaultOrganizationId && memberships.some((m) => m.organizationId === me.defaultOrganizationId)) return me.defaultOrganizationId;
|
|
1857
|
+
if (memberships.length === 1 && memberships[0]) return memberships[0].organizationId;
|
|
1858
|
+
if (memberships.length === 0) fail("NO_ORG", "You don't belong to any organization", 1);
|
|
1859
|
+
fail("AMBIGUOUS_ORG", "Multiple organizations — pass --org <orgId> explicitly or set a default in the web UI first", 1);
|
|
1860
|
+
}
|
|
1861
|
+
//#endregion
|
|
1801
1862
|
//#region src/commands/server.ts
|
|
1802
1863
|
function registerServerCommands(program) {
|
|
1803
1864
|
const server = program.command("server").description("Manage First Tree Hub server");
|
|
@@ -1990,6 +2051,7 @@ registerAgentCommands(program);
|
|
|
1990
2051
|
registerConfigCommands(program);
|
|
1991
2052
|
registerUpdateCommand(program);
|
|
1992
2053
|
registerOnboardCommand(program);
|
|
2054
|
+
registerOrgCommands(program);
|
|
1993
2055
|
program.parse();
|
|
1994
2056
|
//#endregion
|
|
1995
2057
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { w as clientCapabilitiesSchema } from "./dist-
|
|
2
|
-
import { a as ConflictError, i as ClientUserMismatchError, l as organizations, n as BadRequestError, s as NotFoundError, u as users } from "./errors-
|
|
1
|
+
import { w as clientCapabilitiesSchema } from "./dist-CfvCT4E0.mjs";
|
|
2
|
+
import { a as ConflictError, i as ClientUserMismatchError, l as organizations, n as BadRequestError, s as NotFoundError, u as users } from "./errors-CF5evtJt-B0NTIVPt.mjs";
|
|
3
3
|
import { and, eq, inArray, ne, sql } from "drizzle-orm";
|
|
4
4
|
import { index, integer, jsonb, pgTable, text, timestamp, unique } from "drizzle-orm/pg-core";
|
|
5
|
-
//#region ../server/dist/client-
|
|
5
|
+
//#region ../server/dist/client-DqdGiggm.mjs
|
|
6
6
|
/**
|
|
7
7
|
* Client connections. A client is a single SDK process (AgentRuntime) that may
|
|
8
8
|
* host multiple agents. From the unified-user-token milestone on, a client is
|
|
@@ -137,195 +137,6 @@ z.object({
|
|
|
137
137
|
connected: z.boolean(),
|
|
138
138
|
lastActiveAt: z.string().nullable()
|
|
139
139
|
});
|
|
140
|
-
const presenceStatusSchema = z.enum(["online", "offline"]);
|
|
141
|
-
const runtimeStateSchema = z.enum([
|
|
142
|
-
"idle",
|
|
143
|
-
"working",
|
|
144
|
-
"blocked",
|
|
145
|
-
"error"
|
|
146
|
-
]);
|
|
147
|
-
z.enum([
|
|
148
|
-
"active",
|
|
149
|
-
"suspended",
|
|
150
|
-
"evicted"
|
|
151
|
-
]);
|
|
152
|
-
/** Wire-level states a client may report. `evicted` from a stale client is rejected. */
|
|
153
|
-
const clientSessionStateSchema = z.enum(["active", "suspended"]);
|
|
154
|
-
const sessionStateMessageSchema = z.object({
|
|
155
|
-
chatId: z.string().min(1),
|
|
156
|
-
state: clientSessionStateSchema
|
|
157
|
-
});
|
|
158
|
-
/** Client-reported runtime state override (client → server, per-agent). */
|
|
159
|
-
const runtimeStateMessageSchema = z.object({ runtimeState: runtimeStateSchema });
|
|
160
|
-
const agentBindRequestSchema = z.object({
|
|
161
|
-
agentId: z.string().min(1),
|
|
162
|
-
runtimeType: z.string().max(50),
|
|
163
|
-
runtimeVersion: z.string().max(50).optional()
|
|
164
|
-
});
|
|
165
|
-
const AGENT_BIND_REJECT_REASONS = {
|
|
166
|
-
WRONG_CLIENT: "wrong_client",
|
|
167
|
-
NOT_OWNED: "not_owned",
|
|
168
|
-
AGENT_SUSPENDED: "agent_suspended",
|
|
169
|
-
WRONG_ORG: "wrong_org",
|
|
170
|
-
UNKNOWN_AGENT: "unknown_agent",
|
|
171
|
-
RUNTIME_PROVIDER_MISMATCH: "runtime_provider_mismatch"
|
|
172
|
-
};
|
|
173
|
-
z.enum([
|
|
174
|
-
"wrong_client",
|
|
175
|
-
"not_owned",
|
|
176
|
-
"agent_suspended",
|
|
177
|
-
"wrong_org",
|
|
178
|
-
"unknown_agent",
|
|
179
|
-
"runtime_provider_mismatch"
|
|
180
|
-
]);
|
|
181
|
-
/** Header used on agent-scoped HTTP calls to select which managed agent the JWT acts as. */
|
|
182
|
-
const AGENT_SELECTOR_HEADER = "x-agent-id";
|
|
183
|
-
z.object({
|
|
184
|
-
agentId: z.string(),
|
|
185
|
-
status: presenceStatusSchema,
|
|
186
|
-
connectedAt: z.string().nullable(),
|
|
187
|
-
lastSeenAt: z.string(),
|
|
188
|
-
clientId: z.string().nullable().optional(),
|
|
189
|
-
runtimeType: z.string().nullable().optional(),
|
|
190
|
-
runtimeVersion: z.string().nullable().optional(),
|
|
191
|
-
runtimeState: runtimeStateSchema.nullable().optional(),
|
|
192
|
-
activeSessions: z.number().int().nullable().optional(),
|
|
193
|
-
totalSessions: z.number().int().nullable().optional(),
|
|
194
|
-
runtimeUpdatedAt: z.string().nullable().optional()
|
|
195
|
-
});
|
|
196
|
-
z.object({
|
|
197
|
-
total: z.number().int(),
|
|
198
|
-
running: z.number().int(),
|
|
199
|
-
byState: z.object({
|
|
200
|
-
idle: z.number().int(),
|
|
201
|
-
working: z.number().int(),
|
|
202
|
-
blocked: z.number().int(),
|
|
203
|
-
error: z.number().int()
|
|
204
|
-
}),
|
|
205
|
-
clients: z.number().int()
|
|
206
|
-
});
|
|
207
|
-
const runtimeProviderSchema = z.enum(["claude-code", "codex"]);
|
|
208
|
-
const DEFAULT_RUNTIME_PROVIDER = "claude-code";
|
|
209
|
-
const AGENT_TYPES = {
|
|
210
|
-
HUMAN: "human",
|
|
211
|
-
PERSONAL_ASSISTANT: "personal_assistant",
|
|
212
|
-
AUTONOMOUS_AGENT: "autonomous_agent"
|
|
213
|
-
};
|
|
214
|
-
const agentTypeSchema = z.enum([
|
|
215
|
-
"human",
|
|
216
|
-
"personal_assistant",
|
|
217
|
-
"autonomous_agent"
|
|
218
|
-
]);
|
|
219
|
-
const AGENT_VISIBILITY = {
|
|
220
|
-
PRIVATE: "private",
|
|
221
|
-
ORGANIZATION: "organization"
|
|
222
|
-
};
|
|
223
|
-
const agentVisibilitySchema = z.enum(["private", "organization"]);
|
|
224
|
-
const AGENT_STATUSES = {
|
|
225
|
-
ACTIVE: "active",
|
|
226
|
-
SUSPENDED: "suspended",
|
|
227
|
-
DELETED: "deleted"
|
|
228
|
-
};
|
|
229
|
-
const AGENT_SOURCES = {
|
|
230
|
-
ADMIN_API: "admin-api",
|
|
231
|
-
PORTAL: "portal"
|
|
232
|
-
};
|
|
233
|
-
const agentSourceSchema = z.enum(["admin-api", "portal"]);
|
|
234
|
-
z.enum(["active", "suspended"]);
|
|
235
|
-
/**
|
|
236
|
-
* Agent-name rules (see docs/agent-naming-design.md §3.1):
|
|
237
|
-
* - Lowercase ASCII slug, hyphens + underscores allowed.
|
|
238
|
-
* - Must start with alphanumeric: `-` / `_` as first char collide with
|
|
239
|
-
* CLI flag parsing and markdown list syntax.
|
|
240
|
-
* - 1–64 chars — aligned with `MENTION_REGEX` so any valid name can be
|
|
241
|
-
* @-mentioned in chat. Older rows created under the previous 1–100
|
|
242
|
-
* regex are grandfathered; the tight rule only gates new creates.
|
|
243
|
-
*/
|
|
244
|
-
const AGENT_NAME_REGEX = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
245
|
-
const RESERVED_AGENT_NAMES_SET = new Set([
|
|
246
|
-
"admin",
|
|
247
|
-
"agent",
|
|
248
|
-
"first-tree",
|
|
249
|
-
"hub",
|
|
250
|
-
"me",
|
|
251
|
-
"null",
|
|
252
|
-
"system",
|
|
253
|
-
"undefined"
|
|
254
|
-
]);
|
|
255
|
-
function isReservedAgentName(name) {
|
|
256
|
-
return RESERVED_AGENT_NAMES_SET.has(name);
|
|
257
|
-
}
|
|
258
|
-
const createAgentSchema = z.object({
|
|
259
|
-
name: z.string().min(1).max(64).regex(AGENT_NAME_REGEX, "Must start with a letter or digit and contain only lowercase letters, digits, hyphens (-), and underscores (_). Max 64 chars.").refine((n) => !isReservedAgentName(n), { message: "That agent name is reserved — pick a different one." }).optional(),
|
|
260
|
-
type: agentTypeSchema,
|
|
261
|
-
displayName: z.string().min(1).max(200).optional(),
|
|
262
|
-
delegateMention: z.string().max(100).optional(),
|
|
263
|
-
organizationId: z.string().min(1).max(100).optional(),
|
|
264
|
-
source: agentSourceSchema.optional(),
|
|
265
|
-
visibility: agentVisibilitySchema.optional(),
|
|
266
|
-
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
267
|
-
managerId: z.string().optional(),
|
|
268
|
-
clientId: z.string().min(1).max(100).optional(),
|
|
269
|
-
runtimeProvider: runtimeProviderSchema.optional()
|
|
270
|
-
});
|
|
271
|
-
const updateAgentSchema = z.object({
|
|
272
|
-
type: agentTypeSchema.optional(),
|
|
273
|
-
displayName: z.string().min(1).max(200).optional(),
|
|
274
|
-
delegateMention: z.string().max(100).nullable().optional(),
|
|
275
|
-
visibility: agentVisibilitySchema.optional(),
|
|
276
|
-
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
277
|
-
managerId: z.string().nullable().optional(),
|
|
278
|
-
clientId: z.string().min(1).max(100).nullable().optional()
|
|
279
|
-
});
|
|
280
|
-
/**
|
|
281
|
-
* Service-level rebind input. Admin / owner re-binds an agent to a new
|
|
282
|
-
* client and/or a new runtime provider in one atomic operation.
|
|
283
|
-
*
|
|
284
|
-
* `force` bypasses the capability-match check (e.g. when the client is
|
|
285
|
-
* offline and capabilities are stale).
|
|
286
|
-
*/
|
|
287
|
-
const rebindAgentSchema = z.object({
|
|
288
|
-
clientId: z.string().min(1).max(100),
|
|
289
|
-
runtimeProvider: runtimeProviderSchema,
|
|
290
|
-
force: z.boolean().optional()
|
|
291
|
-
});
|
|
292
|
-
z.object({
|
|
293
|
-
uuid: z.string(),
|
|
294
|
-
name: z.string().nullable(),
|
|
295
|
-
organizationId: z.string(),
|
|
296
|
-
type: agentTypeSchema,
|
|
297
|
-
displayName: z.string(),
|
|
298
|
-
delegateMention: z.string().nullable(),
|
|
299
|
-
inboxId: z.string(),
|
|
300
|
-
status: z.string(),
|
|
301
|
-
source: z.string().nullable().optional(),
|
|
302
|
-
visibility: agentVisibilitySchema,
|
|
303
|
-
metadata: z.record(z.string(), z.unknown()),
|
|
304
|
-
managerId: z.string().nullable(),
|
|
305
|
-
clientId: z.string().nullable(),
|
|
306
|
-
runtimeProvider: runtimeProviderSchema,
|
|
307
|
-
presenceStatus: presenceStatusSchema.optional(),
|
|
308
|
-
createdAt: z.string(),
|
|
309
|
-
updatedAt: z.string()
|
|
310
|
-
});
|
|
311
|
-
z.object({
|
|
312
|
-
repo: z.string().nullable(),
|
|
313
|
-
branch: z.string().nullable()
|
|
314
|
-
});
|
|
315
|
-
/**
|
|
316
|
-
* Server → client WebSocket frame announcing that an agent has just been
|
|
317
|
-
* pinned to the connected client (either created with `clientId` or bound via
|
|
318
|
-
* PATCH NULL → ID). The client can auto-register a local config from this so
|
|
319
|
-
* the operator doesn't have to run `first-tree-hub agent add` manually.
|
|
320
|
-
*/
|
|
321
|
-
const agentPinnedMessageSchema = z.object({
|
|
322
|
-
type: z.literal("agent:pinned"),
|
|
323
|
-
agentId: z.string(),
|
|
324
|
-
name: z.string().nullable(),
|
|
325
|
-
displayName: z.string(),
|
|
326
|
-
agentType: agentTypeSchema,
|
|
327
|
-
runtimeProvider: runtimeProviderSchema
|
|
328
|
-
});
|
|
329
140
|
/**
|
|
330
141
|
* Agent runtime configuration.
|
|
331
142
|
*
|
|
@@ -500,6 +311,26 @@ const agentRuntimeConfigSchema = z.object({
|
|
|
500
311
|
updatedBy: z.string()
|
|
501
312
|
});
|
|
502
313
|
/**
|
|
314
|
+
* Write-side shape with no `.default()` per field.
|
|
315
|
+
*
|
|
316
|
+
* `agentRuntimeConfigPayloadShape` carries `.default()` on every field for the
|
|
317
|
+
* read path (so legacy DB rows parse cleanly). On the PATCH side those defaults
|
|
318
|
+
* are actively harmful: Zod 4's `.partial()` makes a field optional but keeps
|
|
319
|
+
* the inner `ZodDefault`, so a body like `{ mcpServers: [...] }` parses to a
|
|
320
|
+
* fully-populated patch where the omitted fields are filled with their
|
|
321
|
+
* defaults — the service layer's `patch.x ?? current.x` then sees a truthy
|
|
322
|
+
* default and *replaces* the user's saved value with empty. Mirroring the 5
|
|
323
|
+
* fields here without defaults keeps "field absent" → `undefined` in the
|
|
324
|
+
* parsed patch, which is what the merge logic expects.
|
|
325
|
+
*/
|
|
326
|
+
const agentRuntimeConfigPatchShape = z.object({
|
|
327
|
+
prompt: promptConfigSchema,
|
|
328
|
+
model: z.string(),
|
|
329
|
+
mcpServers: z.array(mcpServerSchema),
|
|
330
|
+
env: z.array(envEntrySchema),
|
|
331
|
+
gitRepos: z.array(gitRepoSchema)
|
|
332
|
+
}).partial();
|
|
333
|
+
/**
|
|
503
334
|
* Patch payload for PATCH /api/v1/admin/agents/:uuid/config.
|
|
504
335
|
*
|
|
505
336
|
* - `expectedVersion` enforces optimistic locking; mismatch → 409.
|
|
@@ -507,9 +338,9 @@ const agentRuntimeConfigSchema = z.object({
|
|
|
507
338
|
*/
|
|
508
339
|
const updateAgentRuntimeConfigSchema = z.object({
|
|
509
340
|
expectedVersion: z.number().int().positive(),
|
|
510
|
-
payload:
|
|
341
|
+
payload: agentRuntimeConfigPatchShape
|
|
511
342
|
});
|
|
512
|
-
const dryRunAgentRuntimeConfigSchema = z.object({ payload:
|
|
343
|
+
const dryRunAgentRuntimeConfigSchema = z.object({ payload: agentRuntimeConfigPatchShape });
|
|
513
344
|
z.object({
|
|
514
345
|
current: agentRuntimeConfigSchema,
|
|
515
346
|
next: agentRuntimeConfigPayloadSchema,
|
|
@@ -538,6 +369,196 @@ function deriveRepoLocalPath(url) {
|
|
|
538
369
|
if (!trimmed) return "";
|
|
539
370
|
return ((trimmed.split(/[?#]/)[0] ?? "").split(/[/:]/).filter(Boolean).pop() ?? "").replace(/\.git$/i, "");
|
|
540
371
|
}
|
|
372
|
+
const presenceStatusSchema = z.enum(["online", "offline"]);
|
|
373
|
+
const runtimeStateSchema = z.enum([
|
|
374
|
+
"idle",
|
|
375
|
+
"working",
|
|
376
|
+
"blocked",
|
|
377
|
+
"error"
|
|
378
|
+
]);
|
|
379
|
+
z.enum([
|
|
380
|
+
"active",
|
|
381
|
+
"suspended",
|
|
382
|
+
"evicted"
|
|
383
|
+
]);
|
|
384
|
+
/** Wire-level states a client may report. `evicted` from a stale client is rejected. */
|
|
385
|
+
const clientSessionStateSchema = z.enum(["active", "suspended"]);
|
|
386
|
+
const sessionStateMessageSchema = z.object({
|
|
387
|
+
chatId: z.string().min(1),
|
|
388
|
+
state: clientSessionStateSchema
|
|
389
|
+
});
|
|
390
|
+
/** Client-reported runtime state override (client → server, per-agent). */
|
|
391
|
+
const runtimeStateMessageSchema = z.object({ runtimeState: runtimeStateSchema });
|
|
392
|
+
const agentBindRequestSchema = z.object({
|
|
393
|
+
agentId: z.string().min(1),
|
|
394
|
+
runtimeType: z.string().max(50),
|
|
395
|
+
runtimeVersion: z.string().max(50).optional()
|
|
396
|
+
});
|
|
397
|
+
const AGENT_BIND_REJECT_REASONS = {
|
|
398
|
+
WRONG_CLIENT: "wrong_client",
|
|
399
|
+
NOT_OWNED: "not_owned",
|
|
400
|
+
AGENT_SUSPENDED: "agent_suspended",
|
|
401
|
+
WRONG_ORG: "wrong_org",
|
|
402
|
+
UNKNOWN_AGENT: "unknown_agent",
|
|
403
|
+
RUNTIME_PROVIDER_MISMATCH: "runtime_provider_mismatch"
|
|
404
|
+
};
|
|
405
|
+
z.enum([
|
|
406
|
+
"wrong_client",
|
|
407
|
+
"not_owned",
|
|
408
|
+
"agent_suspended",
|
|
409
|
+
"wrong_org",
|
|
410
|
+
"unknown_agent",
|
|
411
|
+
"runtime_provider_mismatch"
|
|
412
|
+
]);
|
|
413
|
+
/** Header used on agent-scoped HTTP calls to select which managed agent the JWT acts as. */
|
|
414
|
+
const AGENT_SELECTOR_HEADER = "x-agent-id";
|
|
415
|
+
z.object({
|
|
416
|
+
agentId: z.string(),
|
|
417
|
+
status: presenceStatusSchema,
|
|
418
|
+
connectedAt: z.string().nullable(),
|
|
419
|
+
lastSeenAt: z.string(),
|
|
420
|
+
clientId: z.string().nullable().optional(),
|
|
421
|
+
runtimeType: z.string().nullable().optional(),
|
|
422
|
+
runtimeVersion: z.string().nullable().optional(),
|
|
423
|
+
runtimeState: runtimeStateSchema.nullable().optional(),
|
|
424
|
+
activeSessions: z.number().int().nullable().optional(),
|
|
425
|
+
totalSessions: z.number().int().nullable().optional(),
|
|
426
|
+
runtimeUpdatedAt: z.string().nullable().optional()
|
|
427
|
+
});
|
|
428
|
+
z.object({
|
|
429
|
+
total: z.number().int(),
|
|
430
|
+
running: z.number().int(),
|
|
431
|
+
byState: z.object({
|
|
432
|
+
idle: z.number().int(),
|
|
433
|
+
working: z.number().int(),
|
|
434
|
+
blocked: z.number().int(),
|
|
435
|
+
error: z.number().int()
|
|
436
|
+
}),
|
|
437
|
+
clients: z.number().int()
|
|
438
|
+
});
|
|
439
|
+
const runtimeProviderSchema = z.enum(["claude-code", "codex"]);
|
|
440
|
+
const DEFAULT_RUNTIME_PROVIDER = "claude-code";
|
|
441
|
+
const AGENT_TYPES = {
|
|
442
|
+
HUMAN: "human",
|
|
443
|
+
PERSONAL_ASSISTANT: "personal_assistant",
|
|
444
|
+
AUTONOMOUS_AGENT: "autonomous_agent"
|
|
445
|
+
};
|
|
446
|
+
const agentTypeSchema = z.enum([
|
|
447
|
+
"human",
|
|
448
|
+
"personal_assistant",
|
|
449
|
+
"autonomous_agent"
|
|
450
|
+
]);
|
|
451
|
+
const AGENT_VISIBILITY = {
|
|
452
|
+
PRIVATE: "private",
|
|
453
|
+
ORGANIZATION: "organization"
|
|
454
|
+
};
|
|
455
|
+
const agentVisibilitySchema = z.enum(["private", "organization"]);
|
|
456
|
+
const AGENT_STATUSES = {
|
|
457
|
+
ACTIVE: "active",
|
|
458
|
+
SUSPENDED: "suspended",
|
|
459
|
+
DELETED: "deleted"
|
|
460
|
+
};
|
|
461
|
+
const AGENT_SOURCES = {
|
|
462
|
+
ADMIN_API: "admin-api",
|
|
463
|
+
PORTAL: "portal"
|
|
464
|
+
};
|
|
465
|
+
const agentSourceSchema = z.enum(["admin-api", "portal"]);
|
|
466
|
+
z.enum(["active", "suspended"]);
|
|
467
|
+
/**
|
|
468
|
+
* Agent-name rules (see docs/agent-naming-design.md §3.1):
|
|
469
|
+
* - Lowercase ASCII slug, hyphens + underscores allowed.
|
|
470
|
+
* - Must start with alphanumeric: `-` / `_` as first char collide with
|
|
471
|
+
* CLI flag parsing and markdown list syntax.
|
|
472
|
+
* - 1–64 chars — aligned with `MENTION_REGEX` so any valid name can be
|
|
473
|
+
* @-mentioned in chat. Older rows created under the previous 1–100
|
|
474
|
+
* regex are grandfathered; the tight rule only gates new creates.
|
|
475
|
+
*/
|
|
476
|
+
const AGENT_NAME_REGEX = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
477
|
+
const RESERVED_AGENT_NAMES_SET = new Set([
|
|
478
|
+
"admin",
|
|
479
|
+
"agent",
|
|
480
|
+
"first-tree",
|
|
481
|
+
"hub",
|
|
482
|
+
"me",
|
|
483
|
+
"null",
|
|
484
|
+
"system",
|
|
485
|
+
"undefined"
|
|
486
|
+
]);
|
|
487
|
+
function isReservedAgentName(name) {
|
|
488
|
+
return RESERVED_AGENT_NAMES_SET.has(name);
|
|
489
|
+
}
|
|
490
|
+
const createAgentSchema = z.object({
|
|
491
|
+
name: z.string().min(1).max(64).regex(AGENT_NAME_REGEX, "Must start with a letter or digit and contain only lowercase letters, digits, hyphens (-), and underscores (_). Max 64 chars.").refine((n) => !isReservedAgentName(n), { message: "That agent name is reserved — pick a different one." }).optional(),
|
|
492
|
+
type: agentTypeSchema,
|
|
493
|
+
displayName: z.string().min(1).max(200).optional(),
|
|
494
|
+
delegateMention: z.string().max(100).optional(),
|
|
495
|
+
organizationId: z.string().min(1).max(100).optional(),
|
|
496
|
+
source: agentSourceSchema.optional(),
|
|
497
|
+
visibility: agentVisibilitySchema.optional(),
|
|
498
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
499
|
+
managerId: z.string().optional(),
|
|
500
|
+
clientId: z.string().min(1).max(100).optional(),
|
|
501
|
+
runtimeProvider: runtimeProviderSchema.optional(),
|
|
502
|
+
gitRepos: z.array(gitRepoSchema).optional()
|
|
503
|
+
});
|
|
504
|
+
const updateAgentSchema = z.object({
|
|
505
|
+
type: agentTypeSchema.optional(),
|
|
506
|
+
displayName: z.string().min(1).max(200).optional(),
|
|
507
|
+
delegateMention: z.string().max(100).nullable().optional(),
|
|
508
|
+
visibility: agentVisibilitySchema.optional(),
|
|
509
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
510
|
+
managerId: z.string().nullable().optional(),
|
|
511
|
+
clientId: z.string().min(1).max(100).nullable().optional()
|
|
512
|
+
});
|
|
513
|
+
/**
|
|
514
|
+
* Service-level rebind input. Admin / owner re-binds an agent to a new
|
|
515
|
+
* client and/or a new runtime provider in one atomic operation.
|
|
516
|
+
*
|
|
517
|
+
* `force` bypasses the capability-match check (e.g. when the client is
|
|
518
|
+
* offline and capabilities are stale).
|
|
519
|
+
*/
|
|
520
|
+
const rebindAgentSchema = z.object({
|
|
521
|
+
clientId: z.string().min(1).max(100),
|
|
522
|
+
runtimeProvider: runtimeProviderSchema,
|
|
523
|
+
force: z.boolean().optional()
|
|
524
|
+
});
|
|
525
|
+
z.object({
|
|
526
|
+
uuid: z.string(),
|
|
527
|
+
name: z.string().nullable(),
|
|
528
|
+
organizationId: z.string(),
|
|
529
|
+
type: agentTypeSchema,
|
|
530
|
+
displayName: z.string(),
|
|
531
|
+
delegateMention: z.string().nullable(),
|
|
532
|
+
inboxId: z.string(),
|
|
533
|
+
status: z.string(),
|
|
534
|
+
source: z.string().nullable().optional(),
|
|
535
|
+
visibility: agentVisibilitySchema,
|
|
536
|
+
metadata: z.record(z.string(), z.unknown()),
|
|
537
|
+
managerId: z.string().nullable(),
|
|
538
|
+
clientId: z.string().nullable(),
|
|
539
|
+
runtimeProvider: runtimeProviderSchema,
|
|
540
|
+
presenceStatus: presenceStatusSchema.optional(),
|
|
541
|
+
createdAt: z.string(),
|
|
542
|
+
updatedAt: z.string()
|
|
543
|
+
});
|
|
544
|
+
z.object({
|
|
545
|
+
repo: z.string().nullable(),
|
|
546
|
+
branch: z.string().nullable()
|
|
547
|
+
});
|
|
548
|
+
/**
|
|
549
|
+
* Server → client WebSocket frame announcing that an agent has just been
|
|
550
|
+
* pinned to the connected client (either created with `clientId` or bound via
|
|
551
|
+
* PATCH NULL → ID). The client can auto-register a local config from this so
|
|
552
|
+
* the operator doesn't have to run `first-tree-hub agent add` manually.
|
|
553
|
+
*/
|
|
554
|
+
const agentPinnedMessageSchema = z.object({
|
|
555
|
+
type: z.literal("agent:pinned"),
|
|
556
|
+
agentId: z.string(),
|
|
557
|
+
name: z.string().nullable(),
|
|
558
|
+
displayName: z.string(),
|
|
559
|
+
agentType: agentTypeSchema,
|
|
560
|
+
runtimeProvider: runtimeProviderSchema
|
|
561
|
+
});
|
|
541
562
|
const loginSchema = z.object({
|
|
542
563
|
username: z.string().min(1),
|
|
543
564
|
password: z.string().min(1)
|
|
@@ -1054,6 +1075,43 @@ const createOrgFromMeSchema = z.object({
|
|
|
1054
1075
|
name: z.string().min(2).max(50).regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
1055
1076
|
displayName: z.string().min(1).max(200)
|
|
1056
1077
|
});
|
|
1078
|
+
/**
|
|
1079
|
+
* Body for `PATCH /me/onboarding`. v1 only mutates `dismissed` — true to
|
|
1080
|
+
* hide the onboarding stepper (server stamps `users.onboarding_dismissed_at
|
|
1081
|
+
* = NOW()`), false to restore it. See docs/new-user-onboarding-design.md
|
|
1082
|
+
* §8.4.
|
|
1083
|
+
*/
|
|
1084
|
+
const patchOnboardingSchema = z.object({ dismissed: z.boolean().optional() });
|
|
1085
|
+
/**
|
|
1086
|
+
* Body for `POST /me/onboarding/events`. The web SPA reports key
|
|
1087
|
+
* milestones so the server can log them as a single funnel-trackable
|
|
1088
|
+
* stream alongside server-emitted events (`team_created`, `dismissed`).
|
|
1089
|
+
*
|
|
1090
|
+
* Server emits:
|
|
1091
|
+
* - `team_created` — at OAuth callback when joinPath === "solo"
|
|
1092
|
+
* - `dismissed` — when PATCH /me/onboarding flips dismissed
|
|
1093
|
+
*
|
|
1094
|
+
* Web reports:
|
|
1095
|
+
* - `team_renamed` — Step 1 user changed the auto-named team
|
|
1096
|
+
* - `agent_created` — Step 2 successfully created the agent
|
|
1097
|
+
* - `tree_chat_started` — Step 3 [Yes, set it up] succeeded
|
|
1098
|
+
* - `tree_intro_dismissed` — Step 3 [I'll do it later] clicked
|
|
1099
|
+
*/
|
|
1100
|
+
const onboardingEventNameSchema = z.enum([
|
|
1101
|
+
"team_renamed",
|
|
1102
|
+
"agent_created",
|
|
1103
|
+
"tree_chat_started",
|
|
1104
|
+
"tree_intro_dismissed"
|
|
1105
|
+
]);
|
|
1106
|
+
const onboardingEventSchema = z.object({
|
|
1107
|
+
event: onboardingEventNameSchema,
|
|
1108
|
+
attrs: z.record(z.string(), z.union([
|
|
1109
|
+
z.string(),
|
|
1110
|
+
z.number(),
|
|
1111
|
+
z.boolean(),
|
|
1112
|
+
z.null()
|
|
1113
|
+
])).optional()
|
|
1114
|
+
});
|
|
1057
1115
|
z.object({
|
|
1058
1116
|
id: z.string(),
|
|
1059
1117
|
organizationId: z.string(),
|
|
@@ -1159,12 +1217,26 @@ const githubDevCallbackQuerySchema = z.object({
|
|
|
1159
1217
|
* 2. Add a key to `ORG_SETTINGS_NAMESPACES`.
|
|
1160
1218
|
* 3. Done. No DB migration, no new API route.
|
|
1161
1219
|
*/
|
|
1220
|
+
const orgContextTreeRepoUrlSchema = z.string().url().refine((value) => {
|
|
1221
|
+
try {
|
|
1222
|
+
return new URL(value).protocol === "https:";
|
|
1223
|
+
} catch {
|
|
1224
|
+
return false;
|
|
1225
|
+
}
|
|
1226
|
+
}, { message: "Context Tree repo URL must use HTTPS." }).refine((value) => {
|
|
1227
|
+
try {
|
|
1228
|
+
const url = new URL(value);
|
|
1229
|
+
return url.username.length === 0 && url.password.length === 0;
|
|
1230
|
+
} catch {
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
}, { message: "Context Tree repo URL must not include credentials." });
|
|
1162
1234
|
const orgContextTreeStorageSchema = z.object({
|
|
1163
|
-
repo:
|
|
1235
|
+
repo: orgContextTreeRepoUrlSchema.optional(),
|
|
1164
1236
|
branch: z.string().default("main")
|
|
1165
1237
|
});
|
|
1166
1238
|
const orgContextTreeInputSchema = z.object({
|
|
1167
|
-
repo:
|
|
1239
|
+
repo: orgContextTreeRepoUrlSchema.nullish(),
|
|
1168
1240
|
branch: z.string().min(1).nullish()
|
|
1169
1241
|
});
|
|
1170
1242
|
const orgContextTreeOutputSchema = z.object({
|
|
@@ -1521,4 +1593,4 @@ z.object({
|
|
|
1521
1593
|
capabilities: serverCapabilitiesSchema.optional()
|
|
1522
1594
|
}).passthrough();
|
|
1523
1595
|
//#endregion
|
|
1524
|
-
export { loginSchema as $, createAgentSchema as A, githubCallbackQuerySchema as B, agentTypeSchema as C,
|
|
1596
|
+
export { loginSchema as $, createAgentSchema as A, githubCallbackQuerySchema as B, agentTypeSchema as C, updateChatSchema as Ct, contextTreeSnapshotSchema as D, updateTaskStatusSchema as Dt, connectTokenExchangeSchema as E, updateOrganizationSchema as Et, createTaskSchema as F, inboxDeliverFrameSchema as G, githubStartQuerySchema as H, defaultRuntimeConfigPayload as I, isRedactedEnvValue as J, inboxPollQuerySchema as K, delegateFeishuUserSchema as L, createMeChatSchema as M, createMemberSchema as N, createAdapterConfigSchema as O, wsAuthFrameSchema as Ot, createOrgFromMeSchema as P, listMeChatsQuerySchema as Q, dryRunAgentRuntimeConfigSchema as R, agentRuntimeConfigPayloadSchema as S, updateAgentSchema as St, clientRegisterSchema as T, updateMemberSchema as Tt, imageInlineContentSchema as U, githubDevCallbackQuerySchema as V, inboxAckFrameSchema as W, joinByInvitationSchema as X, isReservedAgentName as Y, linkTaskChatSchema as Z, addParticipantSchema as _, sessionStateMessageSchema as _t, AGENT_STATUSES as a, rebindAgentSchema as at, agentBindRequestSchema as b, updateAdapterConfigSchema as bt, DEFAULT_RUNTIME_PROVIDER as c, safeRedirectPath as ct, TASK_CREATOR_TYPES as d, sendMessageSchema as dt, messageSourceSchema as et, TASK_HEALTH_SIGNALS as f, sendToAgentSchema as ft, addMeChatParticipantsSchema as g, sessionReconcileRequestSchema as gt, WS_AUTH_FRAME_TIMEOUT_MS as h, sessionEventSchema as ht, AGENT_SOURCES as i, patchOnboardingSchema as it, createChatSchema as j, createAdapterMappingSchema as k, MENTION_REGEX as l, scanMentionTokens as lt, TASK_TERMINAL_STATUSES as m, sessionEventMessageSchema as mt, AGENT_NAME_REGEX as n, onboardingEventSchema as nt, AGENT_TYPES as o, refreshTokenSchema as ot, TASK_STATUSES as p, sessionCompletionMessageSchema as pt, isOrgSettingNamespace as q, AGENT_SELECTOR_HEADER as r, paginationQuerySchema as rt, AGENT_VISIBILITY as s, runtimeStateMessageSchema as st, AGENT_BIND_REJECT_REASONS as t, notificationQuerySchema as tt, ORG_SETTINGS_NAMESPACES as u, selfServiceFeishuBotSchema as ut, adminCreateTaskSchema as v, stripCode as vt, clientCapabilitiesSchema as w, updateClientCapabilitiesSchema as wt, agentPinnedMessageSchema as x, updateAgentRuntimeConfigSchema as xt, adminUpdateTaskSchema as y, taskListQuerySchema as yt, extractMentions as z };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- Onboarding stepper dismissal flag. Decoupled from the server-side
|
|
2
|
+
-- `onboardingStep` enum so the stepper keeps rendering across all three
|
|
3
|
+
-- UI steps (server-side onboardingStep flips to `completed` at the end of
|
|
4
|
+
-- Step 2; Step 3 is purely client-driven and the stepper must keep
|
|
5
|
+
-- showing during the tree-init chat).
|
|
6
|
+
--
|
|
7
|
+
-- See docs/new-user-onboarding-design.md §8.
|
|
8
|
+
--
|
|
9
|
+
-- NULL → stepper renders
|
|
10
|
+
-- value → user clicked the `✕`; stepper unmounts. Irreversible from UI v1.
|
|
11
|
+
|
|
12
|
+
ALTER TABLE "users"
|
|
13
|
+
ADD COLUMN IF NOT EXISTS "onboarding_dismissed_at" timestamp with time zone;
|