@agent-team-foundation/first-tree-hub 0.10.2 → 0.10.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-Ca5Fiqz6.mjs → bootstrap-CBAVWQUT.mjs} +1 -2
- package/dist/cli/index.mjs +60 -7
- package/dist/{dist-CLiN7cVS.mjs → dist-DUCelK3Z.mjs} +116 -13
- package/dist/drizzle/0027_runtime_provider.sql +10 -0
- package/dist/drizzle/0028_auth_identity_user_github_unique.sql +12 -0
- package/dist/drizzle/meta/_journal.json +14 -0
- package/dist/{feishu-FTWnoOsc.mjs → feishu-Boy3n8CT.mjs} +1 -1
- package/dist/index.mjs +4 -4
- package/dist/{invitation-BTlGMy0o-dIoR8JRj.mjs → invitation-BTlGMy0o-Coj07kYi.mjs} +1 -1
- package/dist/{saas-connect-idjpoPTk.mjs → saas-connect-3p-vBkuY.mjs} +1244 -173
- package/dist/web/assets/index-CHoaSIzI.js +21 -0
- package/dist/web/assets/index-CP8uLPyO.css +1 -0
- package/dist/web/assets/index-D7OzKrI2.js +387 -0
- package/dist/web/index.html +2 -2
- package/package.json +3 -2
- package/dist/web/assets/index-CEAPwdg7.js +0 -377
- package/dist/web/assets/index-CzWeWItA.css +0 -1
|
@@ -582,8 +582,7 @@ const serverConfigSchema = defineConfig({
|
|
|
582
582
|
clientSecret: field(z.string(), {
|
|
583
583
|
env: "FIRST_TREE_HUB_GITHUB_OAUTH_CLIENT_SECRET",
|
|
584
584
|
secret: true
|
|
585
|
-
})
|
|
586
|
-
devCallbackEnabled: field(z.boolean().default(false), { env: "FIRST_TREE_HUB_GITHUB_OAUTH_DEV_CALLBACK" })
|
|
585
|
+
})
|
|
587
586
|
}) }),
|
|
588
587
|
cors: optional({ origin: field(z.string(), { env: "FIRST_TREE_HUB_CORS_ORIGIN" }) }),
|
|
589
588
|
rateLimit: optional({
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "../observability-DPyf745N-BSc8QNcR.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { A as checkServerHealth, C as checkAgentConfigs, D as checkDocker, E as checkDatabase, F as installClientService, G as createOwner, H as ClientRuntime, I as isServiceSupported, J as fail, M as checkWebSocket, N as printResults, O as checkNodeVersion, P as getClientServiceStatus, Q as setJsonMode, S as runMigrations, T as checkClientConfig, U as handleClientOrgMismatch, V as stopPostgres, Y as success, Z as print, _ as onboardCreate, a as declineUpdate, at as probeCapabilities, b as createApiNameResolver, c as COMMAND_VERSION, d as isInteractive, et as ClientOrgMismatchError, f as promptAddAgent, g as onboardCheck, h as loadOnboardState, i as createExecuteUpdate, it as cleanWorkspaces, j as checkServerReachable, k as checkServerConfig, l as reconcileLocalRuntimeProviders, m as formatCheckReport, nt as SdkError, o as promptUpdate, ot as applyClientLoggerConfig, p as promptMissingFields, q as resolveReplyToFromEnv, r as registerSaaSConnectCommand, rt as SessionRegistry, s as startServer, st as configureClientLoggerForService, tt as FirstTreeHubSDK, u as uploadClientCapabilities, v as saveOnboardState, w as checkBackgroundService, x as migrateLocalAgentDirs, y as runHomeMigration } from "../saas-connect-3p-vBkuY.mjs";
|
|
4
4
|
import "../logger-core-BTmvdflj-DjW8FM4T.mjs";
|
|
5
|
-
import { C as serverConfigSchema, _ as loadAgents, b as resetConfig, c as saveCredentials, d as DEFAULT_HOME_DIR, f as agentConfigSchema, g as initConfig, h as getConfigValue, i as loadCredentials, l as DEFAULT_CONFIG_DIR, n as ensureFreshAccessToken, o as resolveServerUrl, p as clientConfigSchema, r as ensureFreshAdminToken, s as saveAgentConfig, u as DEFAULT_DATA_DIR, w as setConfigValue, x as resetConfigMeta, y as readConfigFile } from "../bootstrap-
|
|
6
|
-
import "../dist-
|
|
7
|
-
import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-
|
|
5
|
+
import { C as serverConfigSchema, _ as loadAgents, b as resetConfig, c as saveCredentials, d as DEFAULT_HOME_DIR, f as agentConfigSchema, g as initConfig, h as getConfigValue, i as loadCredentials, l as DEFAULT_CONFIG_DIR, n as ensureFreshAccessToken, o as resolveServerUrl, p as clientConfigSchema, r as ensureFreshAdminToken, s as saveAgentConfig, u as DEFAULT_DATA_DIR, w as setConfigValue, x as resetConfigMeta, y as readConfigFile } from "../bootstrap-CBAVWQUT.mjs";
|
|
6
|
+
import "../dist-DUCelK3Z.mjs";
|
|
7
|
+
import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-Boy3n8CT.mjs";
|
|
8
8
|
import "../invitation-C_zAhB8x-8Khychlu.mjs";
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
|
@@ -349,7 +349,8 @@ function registerAgentCommands(program) {
|
|
|
349
349
|
const createBody = {
|
|
350
350
|
name,
|
|
351
351
|
type: options.type,
|
|
352
|
-
clientId: options.clientId
|
|
352
|
+
clientId: options.clientId,
|
|
353
|
+
runtimeProvider: options.runtime
|
|
353
354
|
};
|
|
354
355
|
if (options.displayName) createBody.displayName = options.displayName;
|
|
355
356
|
const createRes = await fetch(`${serverUrl}/api/v1/admin/agents`, {
|
|
@@ -916,6 +917,20 @@ function registerConnectCommand(parent) {
|
|
|
916
917
|
const msg = err instanceof Error ? err.message : String(err);
|
|
917
918
|
print.status("⚠️", `agent-dir migration skipped: ${msg}`);
|
|
918
919
|
}
|
|
920
|
+
let probedCapabilities = null;
|
|
921
|
+
try {
|
|
922
|
+
const accessToken = await ensureFreshAccessToken();
|
|
923
|
+
probedCapabilities = await probeCapabilities();
|
|
924
|
+
await reconcileLocalRuntimeProviders({
|
|
925
|
+
serverUrl: config.server.url,
|
|
926
|
+
accessToken,
|
|
927
|
+
agentsDir,
|
|
928
|
+
log: (level, msg) => print.status(level === "warn" ? "⚠️" : "•", msg)
|
|
929
|
+
});
|
|
930
|
+
} catch (err) {
|
|
931
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
932
|
+
print.status("⚠️", `runtime-provider reconcile skipped: ${msg}`);
|
|
933
|
+
}
|
|
919
934
|
const agents = loadAgents({
|
|
920
935
|
schema: agentConfigSchema,
|
|
921
936
|
agentsDir
|
|
@@ -930,6 +945,18 @@ function registerConnectCommand(parent) {
|
|
|
930
945
|
});
|
|
931
946
|
for (const [name, agentConfig] of agents) runtime.addAgent(name, agentConfig);
|
|
932
947
|
await runtime.start();
|
|
948
|
+
if (probedCapabilities) try {
|
|
949
|
+
const accessToken = await ensureFreshAccessToken();
|
|
950
|
+
await uploadClientCapabilities({
|
|
951
|
+
serverUrl: config.server.url,
|
|
952
|
+
accessToken,
|
|
953
|
+
clientId: config.client.id,
|
|
954
|
+
capabilities: probedCapabilities
|
|
955
|
+
});
|
|
956
|
+
} catch (err) {
|
|
957
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
958
|
+
print.status("⚠️", `capabilities upload skipped: ${msg}`);
|
|
959
|
+
}
|
|
933
960
|
runtime.watchAgentsDir(agentsDir);
|
|
934
961
|
const shutdown = async () => {
|
|
935
962
|
print.line("\n Shutting down...\n");
|
|
@@ -989,6 +1016,20 @@ function registerClientCommands(program) {
|
|
|
989
1016
|
const msg = err instanceof Error ? err.message : String(err);
|
|
990
1017
|
print.status("⚠️", `agent-dir migration skipped: ${msg}`);
|
|
991
1018
|
}
|
|
1019
|
+
let probedCapabilities = null;
|
|
1020
|
+
try {
|
|
1021
|
+
const accessToken = await ensureFreshAccessToken();
|
|
1022
|
+
probedCapabilities = await probeCapabilities();
|
|
1023
|
+
await reconcileLocalRuntimeProviders({
|
|
1024
|
+
serverUrl: config.server.url,
|
|
1025
|
+
accessToken,
|
|
1026
|
+
agentsDir,
|
|
1027
|
+
log: (level, msg) => print.status(level === "warn" ? "⚠️" : "•", msg)
|
|
1028
|
+
});
|
|
1029
|
+
} catch (err) {
|
|
1030
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1031
|
+
print.status("⚠️", `runtime-provider reconcile skipped: ${msg}`);
|
|
1032
|
+
}
|
|
992
1033
|
const agents = loadAgents({
|
|
993
1034
|
schema: agentConfigSchema,
|
|
994
1035
|
agentsDir
|
|
@@ -1005,6 +1046,18 @@ function registerClientCommands(program) {
|
|
|
1005
1046
|
});
|
|
1006
1047
|
for (const [name, agentConfig] of agents) runtime.addAgent(name, agentConfig);
|
|
1007
1048
|
await runtime.start();
|
|
1049
|
+
if (probedCapabilities) try {
|
|
1050
|
+
const accessToken = await ensureFreshAccessToken();
|
|
1051
|
+
await uploadClientCapabilities({
|
|
1052
|
+
serverUrl: config.server.url,
|
|
1053
|
+
accessToken,
|
|
1054
|
+
clientId: config.client.id,
|
|
1055
|
+
capabilities: probedCapabilities
|
|
1056
|
+
});
|
|
1057
|
+
} catch (err) {
|
|
1058
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1059
|
+
print.status("⚠️", `capabilities upload skipped: ${msg}`);
|
|
1060
|
+
}
|
|
1008
1061
|
runtime.watchAgentsDir(agentsDir);
|
|
1009
1062
|
const shutdown = async () => {
|
|
1010
1063
|
print.line("\n Shutting down...\n");
|
|
@@ -1212,13 +1265,13 @@ function isSecretField(schema, dotPath) {
|
|
|
1212
1265
|
//#region src/commands/onboard.ts
|
|
1213
1266
|
async function promptMissing(args) {
|
|
1214
1267
|
if (!args.server) try {
|
|
1215
|
-
const { resolveServerUrl } = await import("../bootstrap-
|
|
1268
|
+
const { resolveServerUrl } = await import("../bootstrap-CBAVWQUT.mjs").then((n) => n.t);
|
|
1216
1269
|
resolveServerUrl();
|
|
1217
1270
|
} catch {
|
|
1218
1271
|
args.server = await input({ message: "Hub server URL:" });
|
|
1219
1272
|
saveOnboardState(args);
|
|
1220
1273
|
}
|
|
1221
|
-
const { loadCredentials } = await import("../bootstrap-
|
|
1274
|
+
const { loadCredentials } = await import("../bootstrap-CBAVWQUT.mjs").then((n) => n.t);
|
|
1222
1275
|
if (!loadCredentials()) throw new Error("No saved credentials. Run `first-tree-hub client connect <server-url>` before onboarding.");
|
|
1223
1276
|
if (!args.id) {
|
|
1224
1277
|
args.id = await input({ message: "Agent ID:" });
|
|
@@ -160,14 +160,16 @@ const AGENT_BIND_REJECT_REASONS = {
|
|
|
160
160
|
NOT_OWNED: "not_owned",
|
|
161
161
|
AGENT_SUSPENDED: "agent_suspended",
|
|
162
162
|
WRONG_ORG: "wrong_org",
|
|
163
|
-
UNKNOWN_AGENT: "unknown_agent"
|
|
163
|
+
UNKNOWN_AGENT: "unknown_agent",
|
|
164
|
+
RUNTIME_PROVIDER_MISMATCH: "runtime_provider_mismatch"
|
|
164
165
|
};
|
|
165
166
|
z.enum([
|
|
166
167
|
"wrong_client",
|
|
167
168
|
"not_owned",
|
|
168
169
|
"agent_suspended",
|
|
169
170
|
"wrong_org",
|
|
170
|
-
"unknown_agent"
|
|
171
|
+
"unknown_agent",
|
|
172
|
+
"runtime_provider_mismatch"
|
|
171
173
|
]);
|
|
172
174
|
/** Header used on agent-scoped HTTP calls to select which managed agent the JWT acts as. */
|
|
173
175
|
const AGENT_SELECTOR_HEADER = "x-agent-id";
|
|
@@ -195,6 +197,8 @@ z.object({
|
|
|
195
197
|
}),
|
|
196
198
|
clients: z.number().int()
|
|
197
199
|
});
|
|
200
|
+
const runtimeProviderSchema = z.enum(["claude-code", "codex"]);
|
|
201
|
+
const DEFAULT_RUNTIME_PROVIDER = "claude-code";
|
|
198
202
|
const AGENT_TYPES = {
|
|
199
203
|
HUMAN: "human",
|
|
200
204
|
PERSONAL_ASSISTANT: "personal_assistant",
|
|
@@ -254,7 +258,8 @@ const createAgentSchema = z.object({
|
|
|
254
258
|
visibility: agentVisibilitySchema.optional(),
|
|
255
259
|
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
256
260
|
managerId: z.string().optional(),
|
|
257
|
-
clientId: z.string().min(1).max(100).optional()
|
|
261
|
+
clientId: z.string().min(1).max(100).optional(),
|
|
262
|
+
runtimeProvider: runtimeProviderSchema.optional()
|
|
258
263
|
});
|
|
259
264
|
const updateAgentSchema = z.object({
|
|
260
265
|
type: agentTypeSchema.optional(),
|
|
@@ -265,6 +270,18 @@ const updateAgentSchema = z.object({
|
|
|
265
270
|
managerId: z.string().nullable().optional(),
|
|
266
271
|
clientId: z.string().min(1).max(100).nullable().optional()
|
|
267
272
|
});
|
|
273
|
+
/**
|
|
274
|
+
* Service-level rebind input. Admin / owner re-binds an agent to a new
|
|
275
|
+
* client and/or a new runtime provider in one atomic operation.
|
|
276
|
+
*
|
|
277
|
+
* `force` bypasses the capability-match check (e.g. when the client is
|
|
278
|
+
* offline and capabilities are stale).
|
|
279
|
+
*/
|
|
280
|
+
const rebindAgentSchema = z.object({
|
|
281
|
+
clientId: z.string().min(1).max(100),
|
|
282
|
+
runtimeProvider: runtimeProviderSchema,
|
|
283
|
+
force: z.boolean().optional()
|
|
284
|
+
});
|
|
268
285
|
z.object({
|
|
269
286
|
uuid: z.string(),
|
|
270
287
|
name: z.string().nullable(),
|
|
@@ -279,6 +296,7 @@ z.object({
|
|
|
279
296
|
metadata: z.record(z.string(), z.unknown()),
|
|
280
297
|
managerId: z.string().nullable(),
|
|
281
298
|
clientId: z.string().nullable(),
|
|
299
|
+
runtimeProvider: runtimeProviderSchema,
|
|
282
300
|
presenceStatus: presenceStatusSchema.optional(),
|
|
283
301
|
createdAt: z.string(),
|
|
284
302
|
updatedAt: z.string()
|
|
@@ -298,14 +316,16 @@ const agentPinnedMessageSchema = z.object({
|
|
|
298
316
|
agentId: z.string(),
|
|
299
317
|
name: z.string().nullable(),
|
|
300
318
|
displayName: z.string(),
|
|
301
|
-
agentType: agentTypeSchema
|
|
319
|
+
agentType: agentTypeSchema,
|
|
320
|
+
runtimeProvider: runtimeProviderSchema
|
|
302
321
|
});
|
|
303
322
|
/**
|
|
304
|
-
* Agent runtime configuration
|
|
323
|
+
* Agent runtime configuration.
|
|
305
324
|
*
|
|
306
325
|
* Defines the 5 user-tunable field groups that the Hub centrally manages
|
|
307
326
|
* and pushes down to the client runtime: prompt append, model, MCP servers,
|
|
308
|
-
* env vars, and Git repos.
|
|
327
|
+
* env vars, and Git repos. Tagged by `kind` (a runtime provider) so future
|
|
328
|
+
* provider-specific fields can land on a dedicated variant.
|
|
309
329
|
*
|
|
310
330
|
* NOTE: do not co-locate with `packages/shared/src/config/` — that namespace
|
|
311
331
|
* is reserved for the local YAML config (`agent.yaml` / server / client) and
|
|
@@ -349,9 +369,11 @@ const gitRepoSchema = z.object({
|
|
|
349
369
|
localPath: z.string().min(1).optional()
|
|
350
370
|
});
|
|
351
371
|
/**
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
372
|
+
* Untagged base shape — 5 user-tunable fields, no `kind` discriminator.
|
|
373
|
+
* Used for `.partial()` derivations on the PATCH side, where `kind` is
|
|
374
|
+
* pinned to `agents.runtime_provider` and never changes via config PATCH.
|
|
375
|
+
* Zod 4 forbids `.partial()` on a refined object, so we keep refinements
|
|
376
|
+
* on the tagged schema below.
|
|
355
377
|
*/
|
|
356
378
|
const agentRuntimeConfigPayloadShape = z.object({
|
|
357
379
|
prompt: promptConfigSchema.default({ append: "" }),
|
|
@@ -360,6 +382,17 @@ const agentRuntimeConfigPayloadShape = z.object({
|
|
|
360
382
|
env: z.array(envEntrySchema).default([]),
|
|
361
383
|
gitRepos: z.array(gitRepoSchema).default([])
|
|
362
384
|
});
|
|
385
|
+
/**
|
|
386
|
+
* Tagged variants — read-side, full payload including `kind`. Adding a new
|
|
387
|
+
* provider means adding a variant here, plus a handler factory and a
|
|
388
|
+
* capability probe module on the client side.
|
|
389
|
+
*
|
|
390
|
+
* Provider-specific fields (e.g. codex `sandboxMode`) belong on the
|
|
391
|
+
* matching variant, not on the base shape.
|
|
392
|
+
*/
|
|
393
|
+
const claudeRuntimeConfigPayloadShape = agentRuntimeConfigPayloadShape.extend({ kind: z.literal("claude-code") });
|
|
394
|
+
const codexRuntimeConfigPayloadShape = agentRuntimeConfigPayloadShape.extend({ kind: z.literal("codex") });
|
|
395
|
+
const taggedPayloadUnion = z.discriminatedUnion("kind", [claudeRuntimeConfigPayloadShape, codexRuntimeConfigPayloadShape]);
|
|
363
396
|
const payloadDuplicatesRefinement = (payload, ctx) => {
|
|
364
397
|
const seenMcp = /* @__PURE__ */ new Set();
|
|
365
398
|
payload.mcpServers.forEach((server, idx) => {
|
|
@@ -404,15 +437,54 @@ const payloadDuplicatesRefinement = (payload, ctx) => {
|
|
|
404
437
|
seenPaths.add(path);
|
|
405
438
|
});
|
|
406
439
|
};
|
|
407
|
-
|
|
408
|
-
|
|
440
|
+
/**
|
|
441
|
+
* Read-side full payload schema. Rows persisted before 0026 do not carry
|
|
442
|
+
* `kind`; `z.preprocess` injects `"claude-code"` so they parse cleanly into
|
|
443
|
+
* the claude variant. The service layer separately enforces
|
|
444
|
+
* `payload.kind === agents.runtime_provider` on writes.
|
|
445
|
+
*/
|
|
446
|
+
const agentRuntimeConfigPayloadSchema = z.preprocess((input) => {
|
|
447
|
+
if (input && typeof input === "object" && !Array.isArray(input) && !("kind" in input)) return {
|
|
448
|
+
...input,
|
|
449
|
+
kind: "claude-code"
|
|
450
|
+
};
|
|
451
|
+
return input;
|
|
452
|
+
}, taggedPayloadUnion).superRefine((payload, ctx) => {
|
|
453
|
+
payloadDuplicatesRefinement(payload, ctx);
|
|
454
|
+
});
|
|
455
|
+
/** Default payload used when creating a fresh claude-code agent. */
|
|
409
456
|
const DEFAULT_AGENT_RUNTIME_CONFIG_PAYLOAD = {
|
|
457
|
+
kind: "claude-code",
|
|
410
458
|
prompt: { append: "" },
|
|
411
459
|
model: "opus",
|
|
412
460
|
mcpServers: [],
|
|
413
461
|
env: [],
|
|
414
462
|
gitRepos: []
|
|
415
463
|
};
|
|
464
|
+
/**
|
|
465
|
+
* Default payload for a fresh codex agent. Same 5 fields as claude-code.
|
|
466
|
+
* `model` is left empty by default so the Codex CLI picks one matching the
|
|
467
|
+
* user's auth mode — `gpt-5-codex` is rejected by ChatGPT-account auth, while
|
|
468
|
+
* an empty string lets the SDK fall through to its built-in default.
|
|
469
|
+
*/
|
|
470
|
+
const DEFAULT_CODEX_RUNTIME_CONFIG_PAYLOAD = {
|
|
471
|
+
kind: "codex",
|
|
472
|
+
prompt: { append: "" },
|
|
473
|
+
model: "",
|
|
474
|
+
mcpServers: [],
|
|
475
|
+
env: [],
|
|
476
|
+
gitRepos: []
|
|
477
|
+
};
|
|
478
|
+
/**
|
|
479
|
+
* Default payload selector by runtime provider.
|
|
480
|
+
*/
|
|
481
|
+
function defaultRuntimeConfigPayload(provider) {
|
|
482
|
+
switch (provider) {
|
|
483
|
+
case "codex": return { ...DEFAULT_CODEX_RUNTIME_CONFIG_PAYLOAD };
|
|
484
|
+
case "claude-code": return { ...DEFAULT_AGENT_RUNTIME_CONFIG_PAYLOAD };
|
|
485
|
+
default: return { ...DEFAULT_AGENT_RUNTIME_CONFIG_PAYLOAD };
|
|
486
|
+
}
|
|
487
|
+
}
|
|
416
488
|
const agentRuntimeConfigSchema = z.object({
|
|
417
489
|
agentId: z.string(),
|
|
418
490
|
version: z.number().int().positive(),
|
|
@@ -531,6 +603,37 @@ const clientRegisterSchema = z.object({
|
|
|
531
603
|
os: z.string().max(50).optional(),
|
|
532
604
|
sdkVersion: z.string().max(50).optional()
|
|
533
605
|
});
|
|
606
|
+
const capabilityStateSchema = z.enum([
|
|
607
|
+
"ok",
|
|
608
|
+
"missing",
|
|
609
|
+
"unauthenticated",
|
|
610
|
+
"error"
|
|
611
|
+
]);
|
|
612
|
+
const capabilityAuthMethodSchema = z.enum([
|
|
613
|
+
"api_key",
|
|
614
|
+
"oauth",
|
|
615
|
+
"auth_json",
|
|
616
|
+
"none"
|
|
617
|
+
]);
|
|
618
|
+
const capabilityEntrySchema = z.object({
|
|
619
|
+
state: capabilityStateSchema,
|
|
620
|
+
available: z.boolean(),
|
|
621
|
+
authenticated: z.boolean(),
|
|
622
|
+
sdkVersion: z.string().nullable().optional(),
|
|
623
|
+
authMethod: capabilityAuthMethodSchema,
|
|
624
|
+
error: z.string().nullable().optional(),
|
|
625
|
+
detectedAt: z.string()
|
|
626
|
+
});
|
|
627
|
+
/**
|
|
628
|
+
* Capabilities snapshot keyed by runtime provider name. Recorded as a plain
|
|
629
|
+
* `Record<string, CapabilityEntry>` — every entry is optional (a client may
|
|
630
|
+
* report only the runtimes it actually probed) and the key set evolves
|
|
631
|
+
* naturally as new providers ship without a schema migration. Service-layer
|
|
632
|
+
* lookups (`agents.runtime_provider ∈ keys(capabilities)`) treat the keys
|
|
633
|
+
* as `RuntimeProvider` strings.
|
|
634
|
+
*/
|
|
635
|
+
const clientCapabilitiesSchema = z.record(z.string(), capabilityEntrySchema);
|
|
636
|
+
const updateClientCapabilitiesSchema = z.object({ capabilities: clientCapabilitiesSchema });
|
|
534
637
|
const paginationQuerySchema = z.object({
|
|
535
638
|
limit: z.coerce.number().int().min(1).max(100).default(20),
|
|
536
639
|
cursor: z.string().optional()
|
|
@@ -801,7 +904,7 @@ const githubCallbackQuerySchema = z.object({
|
|
|
801
904
|
});
|
|
802
905
|
/**
|
|
803
906
|
* Dev-only callback to bypass the GitHub round-trip — sign in as a stub
|
|
804
|
-
* Github user. Gated by NODE_ENV !== 'production'
|
|
907
|
+
* Github user. Gated by NODE_ENV !== 'production'; production always 404s.
|
|
805
908
|
*/
|
|
806
909
|
const githubDevCallbackQuerySchema = z.object({
|
|
807
910
|
githubId: z.string().min(1),
|
|
@@ -1147,4 +1250,4 @@ z.object({
|
|
|
1147
1250
|
serverTimeMs: z.number().int().nonnegative()
|
|
1148
1251
|
}).passthrough();
|
|
1149
1252
|
//#endregion
|
|
1150
|
-
export {
|
|
1253
|
+
export { safeRedirectPath as $, createOrgFromMeSchema as A, imageInlineContentSchema as B, clientRegisterSchema as C, createAgentSchema as D, createAdapterMappingSchema as E, dryRunAgentRuntimeConfigSchema as F, linkTaskChatSchema as G, isRedactedEnvValue as H, extractMentions as I, notificationQuerySchema as J, loginSchema as K, githubCallbackQuerySchema as L, createTaskSchema as M, defaultRuntimeConfigPayload as N, createChatSchema as O, delegateFeishuUserSchema as P, runtimeStateMessageSchema as Q, githubDevCallbackQuerySchema as R, clientCapabilitiesSchema as S, createAdapterConfigSchema as T, isReservedAgentName as U, inboxPollQuerySchema as V, joinByInvitationSchema as W, rebindAgentSchema as X, paginationQuerySchema as Y, refreshTokenSchema as Z, adminUpdateTaskSchema as _, updateOrganizationSchema as _t, AGENT_STATUSES as a, sessionEventMessageSchema as at, agentRuntimeConfigPayloadSchema as b, wsAuthFrameSchema as bt, DEFAULT_RUNTIME_PROVIDER as c, sessionStateMessageSchema as ct, TASK_HEALTH_SIGNALS as d, updateAdapterConfigSchema as dt, scanMentionTokens as et, TASK_STATUSES as f, updateAgentRuntimeConfigSchema as ft, adminCreateTaskSchema as g, updateMemberSchema as gt, addParticipantSchema as h, updateClientCapabilitiesSchema as ht, AGENT_SOURCES as i, sessionCompletionMessageSchema as it, createOrganizationSchema as j, createMemberSchema as k, SYSTEM_CONFIG_DEFAULTS as l, switchOrgSchema as lt, WS_AUTH_FRAME_TIMEOUT_MS as m, updateChatSchema as mt, AGENT_NAME_REGEX as n, sendMessageSchema as nt, AGENT_TYPES as o, sessionEventSchema as ot, TASK_TERMINAL_STATUSES as p, updateAgentSchema as pt, messageSourceSchema as q, AGENT_SELECTOR_HEADER as r, sendToAgentSchema as rt, AGENT_VISIBILITY as s, sessionReconcileRequestSchema as st, AGENT_BIND_REJECT_REASONS as t, selfServiceFeishuBotSchema as tt, TASK_CREATOR_TYPES as u, taskListQuerySchema as ut, agentBindRequestSchema as v, updateSystemConfigSchema as vt, connectTokenExchangeSchema as w, agentTypeSchema as x, agentPinnedMessageSchema as y, updateTaskStatusSchema as yt, githubStartQuerySchema as z };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- Add runtime_provider to agents.
|
|
2
|
+
--
|
|
3
|
+
-- Tags each agent with the runtime that drives it (e.g. "claude-code", "codex").
|
|
4
|
+
-- DEFAULT 'claude-code' backfills every existing row so the NOT NULL constraint
|
|
5
|
+
-- is safe to land in a single step. Hub deploys are stop-migrate-restart, not
|
|
6
|
+
-- rolling, so we don't need a two-phase add (nullable → backfill → not null).
|
|
7
|
+
--
|
|
8
|
+
-- Capabilities reporting reuses the existing `clients.metadata` jsonb column
|
|
9
|
+
-- under the `capabilities` subkey (Option C); no SQL change for clients.
|
|
10
|
+
ALTER TABLE "agents" ADD COLUMN "runtime_provider" text DEFAULT 'claude-code' NOT NULL;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
-- Partial unique index: each user can hold at most one github identity.
|
|
2
|
+
--
|
|
3
|
+
-- Defense-in-depth. The (provider, identifier) UNIQUE catches duplicates
|
|
4
|
+
-- of the SAME githubId, but does not stop a single user from collecting
|
|
5
|
+
-- multiple DIFFERENT githubIds (e.g. a future "merge accounts" or
|
|
6
|
+
-- "rebind" flow that misfires, or a one-off SQL migration that errs).
|
|
7
|
+
-- This index makes any such double-bind fail atomically with a
|
|
8
|
+
-- unique-violation at the storage layer.
|
|
9
|
+
|
|
10
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "uq_auth_identities_user_github"
|
|
11
|
+
ON "auth_identities" ("user_id")
|
|
12
|
+
WHERE "provider" = 'github';
|
|
@@ -190,6 +190,20 @@
|
|
|
190
190
|
"when": 1777507200000,
|
|
191
191
|
"tag": "0026_saas_onboarding",
|
|
192
192
|
"breakpoints": true
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"idx": 27,
|
|
196
|
+
"version": "7",
|
|
197
|
+
"when": 1777593600000,
|
|
198
|
+
"tag": "0027_runtime_provider",
|
|
199
|
+
"breakpoints": true
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"idx": 28,
|
|
203
|
+
"version": "7",
|
|
204
|
+
"when": 1777680000000,
|
|
205
|
+
"tag": "0028_auth_identity_user_github_unique",
|
|
206
|
+
"breakpoints": true
|
|
193
207
|
}
|
|
194
208
|
]
|
|
195
209
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { d as __exportAll } from "./esm-CYu4tXXn.mjs";
|
|
2
|
-
import { r as AGENT_SELECTOR_HEADER } from "./dist-
|
|
2
|
+
import { r as AGENT_SELECTOR_HEADER } from "./dist-DUCelK3Z.mjs";
|
|
3
3
|
//#region src/core/feishu.ts
|
|
4
4
|
var feishu_exports = /* @__PURE__ */ __exportAll({
|
|
5
5
|
bindFeishuBot: () => bindFeishuBot,
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "./observability-DPyf745N-BSc8QNcR.mjs";
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as status, A as checkServerHealth, B as isDockerAvailable, C as checkAgentConfigs, D as checkDocker, E as checkDatabase, F as installClientService, G as createOwner, H as ClientRuntime, I as isServiceSupported, K as hasUser, L as resolveCliInvocation, M as checkWebSocket, N as printResults, O as checkNodeVersion, P as getClientServiceStatus, R as uninstallClientService, S as runMigrations, T as checkClientConfig, U as handleClientOrgMismatch, V as stopPostgres, W as rotateClientIdWithBackup, X as blank, _ as onboardCreate, d as isInteractive, f as promptAddAgent, g as onboardCheck, j as checkServerReachable, k as checkServerConfig, m as formatCheckReport, n as deriveHubUrlFromToken, nt as SdkError, p as promptMissingFields, s as startServer, t as HubUrlDerivationError, tt as FirstTreeHubSDK, y as runHomeMigration, z as ensurePostgres } from "./saas-connect-3p-vBkuY.mjs";
|
|
3
3
|
import "./logger-core-BTmvdflj-DjW8FM4T.mjs";
|
|
4
|
-
import { a as resolveAccessToken, n as ensureFreshAccessToken, o as resolveServerUrl, r as ensureFreshAdminToken } from "./bootstrap-
|
|
5
|
-
import "./dist-
|
|
6
|
-
import { n as bindFeishuUser, t as bindFeishuBot } from "./feishu-
|
|
4
|
+
import { a as resolveAccessToken, n as ensureFreshAccessToken, o as resolveServerUrl, r as ensureFreshAdminToken } from "./bootstrap-CBAVWQUT.mjs";
|
|
5
|
+
import "./dist-DUCelK3Z.mjs";
|
|
6
|
+
import { n as bindFeishuUser, t as bindFeishuBot } from "./feishu-Boy3n8CT.mjs";
|
|
7
7
|
import "./invitation-C_zAhB8x-8Khychlu.mjs";
|
|
8
8
|
export { ClientRuntime, FirstTreeHubSDK, HubUrlDerivationError, SdkError, bindFeishuBot, bindFeishuUser, blank, checkAgentConfigs, checkClientConfig, checkDatabase, checkDocker, checkNodeVersion, checkServerConfig, checkServerHealth, checkServerReachable, checkWebSocket, createOwner, deriveHubUrlFromToken, ensureFreshAccessToken, ensureFreshAdminToken, ensurePostgres, formatCheckReport, getClientServiceStatus, handleClientOrgMismatch, hasUser, installClientService, isDockerAvailable, isInteractive, isServiceSupported, onboardCheck, onboardCreate, printResults, promptAddAgent, promptMissingFields, resolveAccessToken, resolveCliInvocation, resolveServerUrl, rotateClientIdWithBackup, runHomeMigration, runMigrations, startServer, status, stopPostgres, uninstallClientService };
|