@agent-team-foundation/first-tree-hub 0.12.3 → 0.12.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.
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import "../observability-BAScT_5S-BcW9HgkG.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-_lNV0Liy.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 fail, b as onboardCreate, c as detectInstallMode, ct as ClientUserMismatchError, d as startServer, dt as SessionRegistry, et as removeLocalAgent, f as reconcileLocalRuntimeProviders, ft as cleanWorkspaces, g as promptMissingFields, h as promptAddAgent, ht as configureClientLoggerForService, i as createExecuteUpdate, it as resolveSenderName, j as checkNodeVersion, k as checkDatabase, l as fetchLatestVersion, lt as FirstTreeHubSDK, m as isInteractive, mt as applyClientLoggerConfig, o as promptUpdate, ot as success, p as uploadClientCapabilities, pt as probeCapabilities, r as registerSaaSConnectCommand, rt as resolveReplyToFromEnv, s as PACKAGE_NAME, st as ClientOrgMismatchError, tt as createOwner, u as installGlobalLatest, ut as SdkError, v as loadOnboardState, w as migrateLocalAgentDirs, x as saveOnboardState, y as onboardCheck, z as installClientService } from "../saas-connect-DYjvx5yr.mjs";
4
4
  import "../logger-core-BTmvdflj-DjW8FM4T.mjs";
5
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-DHHd2dar.mjs";
8
- import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-fLnwqCOs.mjs";
7
+ import "../dist-BwPlBZWi.mjs";
8
+ import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-CKGzIamp.mjs";
9
9
  import "../errors-CF5evtJt-B0NTIVPt.mjs";
10
10
  import "../src-DNBS5Yjj.mjs";
11
- import "../client-D1TDiik_-gxtXN9bj.mjs";
11
+ import "../client-DL5vHhvQ-CnYGq2x-.mjs";
12
12
  import "../invitation-Bg0TRiyx-BsZH4GCS.mjs";
13
13
  import { join } from "node:path";
14
14
  import { existsSync, mkdirSync, readFileSync, readdirSync } from "node:fs";
@@ -215,14 +215,16 @@ function resolveLocalAgent(agentName) {
215
215
  schema: agentConfigSchema,
216
216
  agentsDir
217
217
  });
218
- if (agents.size === 0) fail("MISSING_AGENT", "No agent configured. Run `first-tree-hub agent add` first.", 2);
218
+ const resolution = resolveSenderName({
219
+ override: agentName,
220
+ envAgentId: process.env.FIRST_TREE_HUB_AGENT_ID,
221
+ agents
222
+ });
219
223
  let resolvedName;
220
- if (agentName) resolvedName = agentName;
221
- else if (agents.size === 1) {
222
- const [only] = [...agents.keys()];
223
- if (!only) fail("MISSING_AGENT", "No agent configured. Run `first-tree-hub agent add` first.", 2);
224
- resolvedName = only;
225
- } else fail("AMBIGUOUS_AGENT", `Multiple agents configured — specify --agent <name>. Available: ${[...agents.keys()].join(", ")}`, 2);
224
+ if (resolution.kind === "ok") resolvedName = resolution.name;
225
+ else if (resolution.kind === "none") fail("MISSING_AGENT", "No agent configured. Run `first-tree-hub agent add` first.", 2);
226
+ else if (resolution.kind === "envMismatch") fail("ENV_AGENT_NOT_LOCAL", `FIRST_TREE_HUB_AGENT_ID="${resolution.envAgentId}" is not configured on this machine. Available local agents: ${resolution.available.join(", ")}. Pick one explicitly: \`first-tree-hub agent send --agent <senderName> <recipientName> "..."\`.`, 2);
227
+ else fail("AMBIGUOUS_AGENT", `Multiple agents are configured on this machine (${resolution.available.join(", ")}) and FIRST_TREE_HUB_AGENT_ID is not set, so the CLI can't tell which one is the sender. Specify it explicitly: \`first-tree-hub agent send --agent <senderName> <recipientName> "..."\` (--agent picks the SENDER; the recipient is the next positional argument).`, 2);
226
228
  const cfg = agents.get(resolvedName);
227
229
  if (!cfg) fail("UNKNOWN_AGENT", `Agent "${resolvedName}" not found in ${agentsDir}`, 2);
228
230
  let serverUrl;
@@ -1,10 +1,10 @@
1
1
  import { O as withSpan, f as messageAttrs, s as createLogger } from "./observability-BAScT_5S-BcW9HgkG.mjs";
2
- import { a as AGENT_STATUSES, at as questionAnswerMessageContentSchema, dt as scanMentionTokens, ot as questionMessageContentSchema, s as AGENT_VISIBILITY, w as clientCapabilitiesSchema, z as extractMentions } from "./dist-DHHd2dar.mjs";
2
+ import { X as questionAnswerMessageContentSchema, Z as questionMessageContentSchema, _ as clientCapabilitiesSchema, a as AGENT_VISIBILITY, i as AGENT_STATUSES, j as extractMentions, nt as scanMentionTokens } from "./dist-BwPlBZWi.mjs";
3
3
  import { a as ConflictError, i as ClientUserMismatchError, l as organizations, n as BadRequestError, o as ForbiddenError, s as NotFoundError, u as users } from "./errors-CF5evtJt-B0NTIVPt.mjs";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { and, desc, eq, inArray, isNotNull, lt, ne, or, sql } from "drizzle-orm";
6
6
  import { bigserial, boolean, index, integer, jsonb, pgTable, primaryKey, text, timestamp, unique } from "drizzle-orm/pg-core";
7
- //#region ../server/dist/client-D1TDiik_.mjs
7
+ //#region ../server/dist/client-DL5vHhvQ.mjs
8
8
  /**
9
9
  * Client connections. A client is a single SDK process (AgentRuntime) that may
10
10
  * host multiple agents. From the unified-user-token milestone on, a client is
@@ -518,6 +518,15 @@ async function assertParticipant(db, chatId, agentId) {
518
518
  const [row] = await db.select({ chatId: chatParticipants.chatId }).from(chatParticipants).where(and(eq(chatParticipants.chatId, chatId), eq(chatParticipants.agentId, agentId))).limit(1);
519
519
  if (!row) throw new ForbiddenError("Not a participant of this chat");
520
520
  }
521
+ /**
522
+ * Non-throwing membership check. Used by routing logic that needs to fall
523
+ * back to a different chat when the candidate target isn't a member of the
524
+ * caller's current chat (see `sendToAgent`'s current-chat routing branch).
525
+ */
526
+ async function isParticipant(db, chatId, agentId) {
527
+ const [row] = await db.select({ chatId: chatParticipants.chatId }).from(chatParticipants).where(and(eq(chatParticipants.chatId, chatId), eq(chatParticipants.agentId, agentId))).limit(1);
528
+ return Boolean(row);
529
+ }
521
530
  /** Ensure an agent is a participant of a chat. Silently adds them if not already. */
522
531
  async function ensureParticipant(db, chatId, agentId) {
523
532
  const [existing] = await db.select({ agentId: chatParticipants.agentId }).from(chatParticipants).where(and(eq(chatParticipants.chatId, chatId), eq(chatParticipants.agentId, agentId))).limit(1);
@@ -1684,7 +1693,6 @@ async function sendToAgent(db, senderUuid, targetName, data) {
1684
1693
  if (!sender) throw new NotFoundError(`Agent "${senderUuid}" not found`);
1685
1694
  const [target] = await db.select({ uuid: agents.uuid }).from(agents).where(and(eq(agents.organizationId, sender.organizationId), eq(agents.name, targetName), ne(agents.status, "deleted"))).limit(1);
1686
1695
  if (!target) throw new NotFoundError(`Agent "${targetName}" not found${/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(targetName) ? " — `agent send` expects an agent NAME, not a uuid. Run `first-tree-hub agent list` to see available names." : ""}`);
1687
- const chat = await findOrCreateDirectChat(db, senderUuid, target.uuid);
1688
1696
  const incomingMeta = data.metadata ?? {};
1689
1697
  const existingMentionsRaw = incomingMeta.mentions;
1690
1698
  const existingMentions = Array.isArray(existingMentionsRaw) ? existingMentionsRaw.filter((m) => typeof m === "string") : [];
@@ -1693,7 +1701,18 @@ async function sendToAgent(db, senderUuid, targetName, data) {
1693
1701
  ...incomingMeta,
1694
1702
  mentions: mergedMentions
1695
1703
  };
1696
- return sendMessage(db, chat.id, senderUuid, {
1704
+ if (data.replyToChat) {
1705
+ const [targetIsMember, senderIsMember] = await Promise.all([isParticipant(db, data.replyToChat, target.uuid), isParticipant(db, data.replyToChat, senderUuid)]);
1706
+ if (targetIsMember && senderIsMember) return sendMessage(db, data.replyToChat, senderUuid, {
1707
+ format: data.format,
1708
+ content: data.content,
1709
+ metadata,
1710
+ replyToInbox: void 0,
1711
+ replyToChat: void 0,
1712
+ source: data.source
1713
+ }, { normalizeMentionsInContent: true });
1714
+ }
1715
+ return sendMessage(db, (await findOrCreateDirectChat(db, senderUuid, target.uuid)).id, senderUuid, {
1697
1716
  format: data.format,
1698
1717
  content: data.content,
1699
1718
  metadata,
@@ -1,7 +1,7 @@
1
1
  import "./observability-BAScT_5S-BcW9HgkG.mjs";
2
2
  import "./logger-core-BTmvdflj-DjW8FM4T.mjs";
3
- import "./dist-DHHd2dar.mjs";
3
+ import "./dist-BwPlBZWi.mjs";
4
4
  import "./errors-CF5evtJt-B0NTIVPt.mjs";
5
5
  import "./src-DNBS5Yjj.mjs";
6
- import { q as listMyPinnedAgents } from "./client-D1TDiik_-gxtXN9bj.mjs";
6
+ import { q as listMyPinnedAgents } from "./client-DL5vHhvQ-CnYGq2x-.mjs";
7
7
  export { listMyPinnedAgents };
@@ -438,11 +438,6 @@ z.object({
438
438
  });
439
439
  const runtimeProviderSchema = z.enum(["claude-code", "codex"]);
440
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
441
  const agentTypeSchema = z.enum([
447
442
  "human",
448
443
  "personal_assistant",
@@ -458,10 +453,6 @@ const AGENT_STATUSES = {
458
453
  SUSPENDED: "suspended",
459
454
  DELETED: "deleted"
460
455
  };
461
- const AGENT_SOURCES = {
462
- ADMIN_API: "admin-api",
463
- PORTAL: "portal"
464
- };
465
456
  const agentSourceSchema = z.enum(["admin-api", "portal"]);
466
457
  z.enum(["active", "suspended"]);
467
458
  /**
@@ -574,6 +565,30 @@ z.object({
574
565
  expiresIn: z.number(),
575
566
  command: z.string()
576
567
  });
568
+ const githubEntityTypeSchema = z.enum([
569
+ "issue",
570
+ "pull_request",
571
+ "discussion",
572
+ "commit"
573
+ ]);
574
+ const githubChatMetadataSchema = z.object({
575
+ source: z.literal("github"),
576
+ entityType: githubEntityTypeSchema,
577
+ entityKey: z.string().min(1),
578
+ entityUrl: z.string().url().optional()
579
+ });
580
+ const feishuChatMetadataSchema = z.object({
581
+ source: z.literal("feishu"),
582
+ externalChannelId: z.string().min(1)
583
+ });
584
+ const chatMetadataSchema = z.discriminatedUnion("source", [githubChatMetadataSchema, feishuChatMetadataSchema]);
585
+ /**
586
+ * `createChat` callers may not set metadata at all (admin-created group chats,
587
+ * me-chats, …), so the input schema accepts either an empty object or one of
588
+ * the typed variants. The empty `{}` arm is `.strict()` so a caller cannot
589
+ * sneak through `{ source: "github" }` without the required fields.
590
+ */
591
+ const optionalChatMetadataSchema = z.union([z.object({}).strict(), chatMetadataSchema]);
577
592
  const chatTypeSchema = z.enum([
578
593
  "direct",
579
594
  "group",
@@ -583,7 +598,7 @@ const createChatSchema = z.object({
583
598
  type: chatTypeSchema,
584
599
  topic: z.string().max(500).optional(),
585
600
  participantIds: z.array(z.string()).min(1),
586
- metadata: z.record(z.string(), z.unknown()).optional()
601
+ metadata: optionalChatMetadataSchema.optional()
587
602
  });
588
603
  const chatParticipantSchema = z.object({
589
604
  agentId: z.string(),
@@ -846,7 +861,6 @@ const messageFormatSchema = z.enum([
846
861
  "card",
847
862
  "reference",
848
863
  "file",
849
- "task",
850
864
  "question",
851
865
  "question_answer"
852
866
  ]);
@@ -1035,9 +1049,7 @@ const meChatRowSchema = z.object({
1035
1049
  lastMessageAt: z.string().nullable(),
1036
1050
  lastMessagePreview: z.string().nullable(),
1037
1051
  unreadMentionCount: z.number().int(),
1038
- canReply: z.boolean(),
1039
- taskId: z.string().nullable(),
1040
- taskStatus: z.string().nullable()
1052
+ canReply: z.boolean()
1041
1053
  });
1042
1054
  z.object({
1043
1055
  rows: z.array(meChatRowSchema),
@@ -1550,133 +1562,6 @@ z.object({
1550
1562
  totalMessages: z.number(),
1551
1563
  byOrganization: z.array(orgStatsSchema)
1552
1564
  });
1553
- /** Fixed 5-state machine. No custom statuses. */
1554
- const TASK_STATUSES = {
1555
- PENDING: "pending",
1556
- ASSIGNED: "assigned",
1557
- WORKING: "working",
1558
- COMPLETED: "completed",
1559
- FAILED: "failed",
1560
- CANCELLED: "cancelled"
1561
- };
1562
- const taskStatusSchema = z.enum([
1563
- "pending",
1564
- "assigned",
1565
- "working",
1566
- "completed",
1567
- "failed",
1568
- "cancelled"
1569
- ]);
1570
- /** Terminal statuses — once reached, no further transitions allowed. */
1571
- const TASK_TERMINAL_STATUSES = [
1572
- "completed",
1573
- "failed",
1574
- "cancelled"
1575
- ];
1576
- /** Creator type discriminator. */
1577
- const TASK_CREATOR_TYPES = {
1578
- AGENT: "agent",
1579
- ADMIN: "admin"
1580
- };
1581
- const taskCreatorTypeSchema = z.enum(["agent", "admin"]);
1582
- const taskMessageEventSchema = z.enum([
1583
- "assigned",
1584
- "status_changed",
1585
- "cancelled"
1586
- ]);
1587
- z.object({
1588
- taskId: z.string(),
1589
- event: taskMessageEventSchema,
1590
- title: z.string(),
1591
- body: z.string().default(""),
1592
- status: taskStatusSchema,
1593
- fromStatus: taskStatusSchema.optional(),
1594
- originRef: z.string().nullable().optional()
1595
- });
1596
- /** Create task input. Used by both agent API and admin API. */
1597
- const createTaskSchema = z.object({
1598
- title: z.string().min(1).max(500),
1599
- body: z.string().optional(),
1600
- assigneeAgentId: z.string().optional(),
1601
- originRef: z.string().max(500).optional(),
1602
- metadata: z.record(z.string(), z.unknown()).optional()
1603
- });
1604
- /** Admin-only create: allows passing an explicit organizationId. */
1605
- const adminCreateTaskSchema = createTaskSchema.extend({ organizationId: z.string().optional() });
1606
- /**
1607
- * Agent-facing status update. Agents may only self-report working/completed/failed.
1608
- * Cancellation goes through the dedicated cancel endpoint.
1609
- */
1610
- const updateTaskStatusSchema = z.object({
1611
- status: z.enum([
1612
- "working",
1613
- "completed",
1614
- "failed"
1615
- ]),
1616
- result: z.string().optional()
1617
- });
1618
- /** Admin-facing update — may re-assign or re-target status (within legal transitions). */
1619
- const adminUpdateTaskSchema = z.object({
1620
- assigneeAgentId: z.string().nullable().optional(),
1621
- status: taskStatusSchema.optional(),
1622
- result: z.string().optional()
1623
- });
1624
- const linkTaskChatSchema = z.object({ chatId: z.string().min(1) });
1625
- const taskSchema = z.object({
1626
- id: z.string(),
1627
- organizationId: z.string(),
1628
- title: z.string(),
1629
- body: z.string(),
1630
- status: taskStatusSchema,
1631
- assigneeAgentId: z.string().nullable(),
1632
- createdByType: taskCreatorTypeSchema,
1633
- createdById: z.string(),
1634
- originRef: z.string().nullable(),
1635
- result: z.string().nullable(),
1636
- metadata: z.record(z.string(), z.unknown()),
1637
- createdAt: z.string(),
1638
- updatedAt: z.string(),
1639
- cancelledAt: z.string().nullable(),
1640
- cancelledByType: taskCreatorTypeSchema.nullable(),
1641
- cancelledById: z.string().nullable()
1642
- });
1643
- const taskChatLinkSchema = z.object({
1644
- taskId: z.string(),
1645
- chatId: z.string(),
1646
- linkedByAgentId: z.string().nullable(),
1647
- linkedAt: z.string()
1648
- });
1649
- taskSchema.extend({ chats: z.array(taskChatLinkSchema) });
1650
- const taskListQuerySchema = z.object({
1651
- status: taskStatusSchema.optional(),
1652
- assigneeAgentId: z.string().optional(),
1653
- originRef: z.string().optional(),
1654
- limit: z.coerce.number().int().min(1).max(100).default(20),
1655
- cursor: z.string().optional()
1656
- });
1657
- /**
1658
- * Task health signals derived from associated chats' session state + recent messages.
1659
- * See hub-task-design Section 9.
1660
- */
1661
- const TASK_HEALTH_SIGNALS = {
1662
- NORMAL: "normal",
1663
- IDLE_ISLAND: "idle_island",
1664
- AWAITING_REPLY: "awaiting_reply",
1665
- NO_CHAT: "no_chat",
1666
- NOT_APPLICABLE: "not_applicable"
1667
- };
1668
- const taskHealthSignalSchema = z.enum([
1669
- "normal",
1670
- "idle_island",
1671
- "awaiting_reply",
1672
- "no_chat",
1673
- "not_applicable"
1674
- ]);
1675
- z.object({
1676
- taskId: z.string(),
1677
- signal: taskHealthSignalSchema,
1678
- reason: z.string()
1679
- });
1680
1565
  const userStatusSchema = z.enum(["active", "suspended"]);
1681
1566
  z.object({
1682
1567
  id: z.string(),
@@ -1721,4 +1606,4 @@ z.object({
1721
1606
  capabilities: serverCapabilitiesSchema.optional()
1722
1607
  }).passthrough();
1723
1608
  //#endregion
1724
- export { loginSchema as $, createAgentSchema as A, updateTaskStatusSchema as At, githubCallbackQuerySchema as B, agentTypeSchema as C, updateAdapterConfigSchema as Ct, contextTreeSnapshotSchema as D, updateClientCapabilitiesSchema as Dt, connectTokenExchangeSchema as E, updateChatSchema 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, updateMemberSchema as Ot, createOrgFromMeSchema as P, listMeChatsQuerySchema as Q, dryRunAgentRuntimeConfigSchema as R, agentRuntimeConfigPayloadSchema as S, taskListQuerySchema as St, clientRegisterSchema as T, updateAgentSchema as Tt, imageInlineContentSchema as U, githubDevCallbackQuerySchema as V, inboxAckFrameSchema as W, joinByInvitationSchema as X, isReservedAgentName as Y, linkTaskChatSchema as Z, addParticipantSchema as _, sessionEventSchema as _t, AGENT_STATUSES as a, questionAnswerMessageContentSchema as at, agentBindRequestSchema as b, stripCode as bt, DEFAULT_RUNTIME_PROVIDER as c, refreshTokenSchema as ct, TASK_CREATOR_TYPES as d, scanMentionTokens as dt, messageSourceSchema as et, TASK_HEALTH_SIGNALS as f, selfServiceFeishuBotSchema as ft, addMeChatParticipantsSchema as g, sessionEventMessageSchema as gt, WS_AUTH_FRAME_TIMEOUT_MS as h, sessionCompletionMessageSchema as ht, AGENT_SOURCES as i, patchOnboardingSchema as it, createChatSchema as j, wsAuthFrameSchema as jt, createAdapterMappingSchema as k, updateOrganizationSchema as kt, MENTION_REGEX as l, runtimeStateMessageSchema as lt, TASK_TERMINAL_STATUSES as m, sendToAgentSchema as mt, AGENT_NAME_REGEX as n, onboardingEventSchema as nt, AGENT_TYPES as o, questionMessageContentSchema as ot, TASK_STATUSES as p, sendMessageSchema as pt, isOrgSettingNamespace as q, AGENT_SELECTOR_HEADER as r, paginationQuerySchema as rt, AGENT_VISIBILITY as s, rebindAgentSchema as st, AGENT_BIND_REJECT_REASONS as t, notificationQuerySchema as tt, ORG_SETTINGS_NAMESPACES as u, safeRedirectPath as ut, adminCreateTaskSchema as v, sessionReconcileRequestSchema as vt, clientCapabilitiesSchema as w, updateAgentRuntimeConfigSchema as wt, agentPinnedMessageSchema as x, submitQuestionAnswerSchema as xt, adminUpdateTaskSchema as y, sessionStateMessageSchema as yt, extractMentions as z };
1609
+ export { refreshTokenSchema as $, dryRunAgentRuntimeConfigSchema as A, isRedactedEnvValue as B, createAgentSchema as C, createOrgFromMeSchema as D, createMemberSchema as E, imageInlineContentSchema as F, messageSourceSchema as G, joinByInvitationSchema as H, inboxAckFrameSchema as I, paginationQuerySchema as J, notificationQuerySchema as K, inboxDeliverFrameSchema as L, githubCallbackQuerySchema as M, githubDevCallbackQuerySchema as N, defaultRuntimeConfigPayload as O, githubStartQuerySchema as P, rebindAgentSchema as Q, inboxPollQuerySchema as R, createAdapterMappingSchema as S, createMeChatSchema as T, listMeChatsQuerySchema as U, isReservedAgentName as V, loginSchema as W, questionAnswerMessageContentSchema as X, patchOnboardingSchema as Y, questionMessageContentSchema as Z, clientCapabilitiesSchema as _, updateClientCapabilitiesSchema as _t, AGENT_VISIBILITY as a, sendToAgentSchema as at, contextTreeSnapshotSchema as b, wsAuthFrameSchema as bt, ORG_SETTINGS_NAMESPACES as c, sessionEventSchema as ct, addParticipantSchema as d, stripCode as dt, runtimeStateMessageSchema as et, agentBindRequestSchema as f, submitQuestionAnswerSchema as ft, chatMetadataSchema as g, updateChatSchema as gt, agentTypeSchema as h, updateAgentSchema as ht, AGENT_STATUSES as i, sendMessageSchema as it, extractMentions as j, delegateFeishuUserSchema as k, WS_AUTH_FRAME_TIMEOUT_MS as l, sessionReconcileRequestSchema as lt, agentRuntimeConfigPayloadSchema as m, updateAgentRuntimeConfigSchema as mt, AGENT_NAME_REGEX as n, scanMentionTokens as nt, DEFAULT_RUNTIME_PROVIDER as o, sessionCompletionMessageSchema as ot, agentPinnedMessageSchema as p, updateAdapterConfigSchema as pt, onboardingEventSchema as q, AGENT_SELECTOR_HEADER as r, selfServiceFeishuBotSchema as rt, MENTION_REGEX as s, sessionEventMessageSchema as st, AGENT_BIND_REJECT_REASONS as t, safeRedirectPath as tt, addMeChatParticipantsSchema as u, sessionStateMessageSchema as ut, clientRegisterSchema as v, updateMemberSchema as vt, createChatSchema as w, createAdapterConfigSchema as x, connectTokenExchangeSchema as y, updateOrganizationSchema as yt, isOrgSettingNamespace as z };
@@ -0,0 +1,7 @@
1
+ -- Drop the Hub Task subsystem. The product no longer uses tasks; the
2
+ -- chat-first workspace covers every flow that previously needed task rows.
3
+ -- Order matches the historical service-layer dependency; DB-level FKs were
4
+ -- already removed in 0014_drop_task_fks so either order would technically work.
5
+
6
+ DROP TABLE IF EXISTS "task_chats";--> statement-breakpoint
7
+ DROP TABLE IF EXISTS "tasks";
@@ -0,0 +1,47 @@
1
+ -- GitHub webhook → chat clustering (Phase 0).
2
+ -- Maps every (organization, human_agent, delegate_agent, entity) tuple to a
3
+ -- single chat. Replaces the legacy "one (human, delegate) chat absorbs every
4
+ -- GitHub event" behaviour — see docs webhook-routing-design.md §4 for the
5
+ -- background and §4.3 for the data-model decision.
6
+ --
7
+ -- The composite primary key is also the uniqueness constraint we rely on for
8
+ -- concurrent webhook safety: two near-simultaneous events for a brand-new
9
+ -- entity hit ON CONFLICT DO NOTHING and the second deliverer falls back to a
10
+ -- re-SELECT, so the pair never spawns duplicate chats.
11
+ --
12
+ -- ON DELETE CASCADE on agent / chat columns: a deleted agent or chat must
13
+ -- drop its mapping rows. We do NOT cascade from organizations because that
14
+ -- relationship is enforced via the agent FKs already.
15
+ --
16
+ -- This table is GitHub-specific. Future external sources (Linear, Slack
17
+ -- channel events, …) get their own table — their entity models differ
18
+ -- enough that a generic table would slide back into untyped jsonb.
19
+ --
20
+ -- Migration 0036 is hand-written to match the team's recent migration
21
+ -- workflow — drizzle-kit generate's snapshot metadata is incomplete pre-0019
22
+ -- and refuses to diff (same constraint that 0032's commit message called out).
23
+
24
+ CREATE TABLE IF NOT EXISTS "github_entity_chat_mappings" (
25
+ "organization_id" text NOT NULL,
26
+ "human_agent_id" text NOT NULL,
27
+ "delegate_agent_id" text NOT NULL,
28
+ "entity_type" text NOT NULL,
29
+ "entity_key" text NOT NULL,
30
+ "chat_id" text NOT NULL,
31
+ "bound_at" timestamp with time zone NOT NULL DEFAULT now(),
32
+ "bound_via" text NOT NULL,
33
+ CONSTRAINT "github_entity_chat_mappings_pkey"
34
+ PRIMARY KEY ("organization_id", "human_agent_id", "delegate_agent_id", "entity_type", "entity_key"),
35
+ CONSTRAINT "github_entity_chat_mappings_organization_id_organizations_id_fk"
36
+ FOREIGN KEY ("organization_id") REFERENCES "organizations"("id"),
37
+ CONSTRAINT "github_entity_chat_mappings_human_agent_id_agents_uuid_fk"
38
+ FOREIGN KEY ("human_agent_id") REFERENCES "agents"("uuid") ON DELETE CASCADE,
39
+ CONSTRAINT "github_entity_chat_mappings_delegate_agent_id_agents_uuid_fk"
40
+ FOREIGN KEY ("delegate_agent_id") REFERENCES "agents"("uuid") ON DELETE CASCADE,
41
+ CONSTRAINT "github_entity_chat_mappings_chat_id_chats_id_fk"
42
+ FOREIGN KEY ("chat_id") REFERENCES "chats"("id") ON DELETE CASCADE
43
+ );
44
+
45
+ --> statement-breakpoint
46
+ CREATE INDEX IF NOT EXISTS "idx_github_entity_chat_mappings_chat"
47
+ ON "github_entity_chat_mappings" ("chat_id");
@@ -246,6 +246,20 @@
246
246
  "when": 1778371200000,
247
247
  "tag": "0034_pending_questions",
248
248
  "breakpoints": true
249
+ },
250
+ {
251
+ "idx": 35,
252
+ "version": "7",
253
+ "when": 1778457600000,
254
+ "tag": "0035_drop_hub_tasks",
255
+ "breakpoints": true
256
+ },
257
+ {
258
+ "idx": 36,
259
+ "version": "7",
260
+ "when": 1778544000000,
261
+ "tag": "0036_github_entity_chat_mappings",
262
+ "breakpoints": true
249
263
  }
250
264
  ]
251
265
  }
@@ -1,6 +1,6 @@
1
1
  import { r as __exportAll } from "./chunk-BSw8zbkd.mjs";
2
2
  import { t as cliFetch } from "./cli-fetch--tiwKm5S.mjs";
3
- import { r as AGENT_SELECTOR_HEADER } from "./dist-DHHd2dar.mjs";
3
+ import { r as AGENT_SELECTOR_HEADER } from "./dist-BwPlBZWi.mjs";
4
4
  //#region src/core/feishu.ts
5
5
  var feishu_exports = /* @__PURE__ */ __exportAll({
6
6
  bindFeishuBot: () => bindFeishuBot,
package/dist/index.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  import "./observability-BAScT_5S-BcW9HgkG.mjs";
2
- import { A as checkDocker, B as isServiceSupported, E as checkAgentConfigs, F as checkWebSocket, G as uninstallClientService, H as restartClientService, I as printResults, J as stopPostgres, K as ensurePostgres, M as checkServerConfig, N as checkServerHealth, O as checkClientConfig, P as checkServerReachable, R as getClientServiceStatus, S as runHomeMigration, T as runMigrations, U as startClientService, V as resolveCliInvocation, W as stopClientService, X as handleClientOrgMismatch, Y as ClientRuntime, Z as rotateClientIdWithBackup, _ as formatCheckReport, b as onboardCreate, ct as FirstTreeHubSDK, d as startServer, g as promptMissingFields, h as promptAddAgent, j as checkNodeVersion, k as checkDatabase, lt as SdkError, m as isInteractive, n as deriveHubUrlFromToken, nt as hasUser, q as isDockerAvailable, t as HubUrlDerivationError, tt as createOwner, y as onboardCheck, z as installClientService } from "./saas-connect-_lNV0Liy.mjs";
2
+ import { A as checkDocker, B as isServiceSupported, E as checkAgentConfigs, F as checkWebSocket, G as uninstallClientService, H as restartClientService, I as printResults, J as stopPostgres, K as ensurePostgres, M as checkServerConfig, N as checkServerHealth, O as checkClientConfig, P as checkServerReachable, R as getClientServiceStatus, S as runHomeMigration, T as runMigrations, U as startClientService, V as resolveCliInvocation, W as stopClientService, X as handleClientOrgMismatch, Y as ClientRuntime, Z as rotateClientIdWithBackup, _ as formatCheckReport, b as onboardCreate, d as startServer, g as promptMissingFields, h as promptAddAgent, j as checkNodeVersion, k as checkDatabase, lt as FirstTreeHubSDK, m as isInteractive, n as deriveHubUrlFromToken, nt as hasUser, q as isDockerAvailable, t as HubUrlDerivationError, tt as createOwner, ut as SdkError, y as onboardCheck, z as installClientService } from "./saas-connect-DYjvx5yr.mjs";
3
3
  import "./logger-core-BTmvdflj-DjW8FM4T.mjs";
4
4
  import { a as ensureFreshAdminToken, c as resolveServerUrl, i as ensureFreshAccessToken, n as AuthRefreshRateLimitedError, s as resolveAccessToken, t as AuthRefreshFailedError } from "./bootstrap-C_K2CKXC.mjs";
5
5
  import { i as blank, s as status } from "./cli-fetch--tiwKm5S.mjs";
6
- import "./dist-DHHd2dar.mjs";
7
- import { n as bindFeishuUser, t as bindFeishuBot } from "./feishu-fLnwqCOs.mjs";
6
+ import "./dist-BwPlBZWi.mjs";
7
+ import { n as bindFeishuUser, t as bindFeishuBot } from "./feishu-CKGzIamp.mjs";
8
8
  import "./errors-CF5evtJt-B0NTIVPt.mjs";
9
9
  import "./src-DNBS5Yjj.mjs";
10
- import "./client-D1TDiik_-gxtXN9bj.mjs";
10
+ import "./client-DL5vHhvQ-CnYGq2x-.mjs";
11
11
  import "./invitation-Bg0TRiyx-BsZH4GCS.mjs";
12
12
  export { AuthRefreshFailedError, AuthRefreshRateLimitedError, 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, restartClientService, rotateClientIdWithBackup, runHomeMigration, runMigrations, startClientService, startServer, status, stopClientService, stopPostgres, uninstallClientService };
@@ -1,4 +1,4 @@
1
- import "./dist-DHHd2dar.mjs";
1
+ import "./dist-BwPlBZWi.mjs";
2
2
  import "./errors-CF5evtJt-B0NTIVPt.mjs";
3
3
  import { s as previewInvitation } from "./invitation-Bg0TRiyx-BsZH4GCS.mjs";
4
4
  export { previewInvitation };