agent-relay 2.0.23 → 2.0.24

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.
Files changed (168) hide show
  1. package/dist/src/cli/index.js +66 -13
  2. package/package.json +18 -52
  3. package/packages/api-types/package.json +1 -1
  4. package/packages/bridge/package.json +8 -8
  5. package/packages/cli-tester/package.json +1 -1
  6. package/packages/config/package.json +2 -2
  7. package/packages/continuity/package.json +1 -1
  8. package/packages/daemon/package.json +12 -12
  9. package/packages/hooks/package.json +4 -4
  10. package/packages/mcp/package.json +2 -2
  11. package/packages/memory/package.json +2 -2
  12. package/packages/policy/package.json +2 -2
  13. package/packages/protocol/package.json +1 -1
  14. package/packages/resiliency/package.json +1 -1
  15. package/packages/sdk/package.json +2 -2
  16. package/packages/spawner/package.json +1 -1
  17. package/packages/state/package.json +1 -1
  18. package/packages/storage/package.json +2 -2
  19. package/packages/telemetry/package.json +1 -1
  20. package/packages/trajectory/package.json +2 -2
  21. package/packages/user-directory/package.json +2 -2
  22. package/packages/utils/package.json +1 -1
  23. package/packages/wrapper/package.json +6 -6
  24. package/deploy/init-db.sql +0 -5
  25. package/deploy/scripts/setup-fly-workspaces.sh +0 -69
  26. package/deploy/scripts/setup-railway.sh +0 -75
  27. package/dist/src/cloud/index.d.ts +0 -8
  28. package/dist/src/cloud/index.js +0 -8
  29. package/packages/cloud/dist/api/admin.d.ts +0 -8
  30. package/packages/cloud/dist/api/admin.js +0 -225
  31. package/packages/cloud/dist/api/auth.d.ts +0 -20
  32. package/packages/cloud/dist/api/auth.js +0 -138
  33. package/packages/cloud/dist/api/billing.d.ts +0 -7
  34. package/packages/cloud/dist/api/billing.js +0 -564
  35. package/packages/cloud/dist/api/cli-pty-runner.d.ts +0 -53
  36. package/packages/cloud/dist/api/cli-pty-runner.js +0 -175
  37. package/packages/cloud/dist/api/codex-auth-helper.d.ts +0 -21
  38. package/packages/cloud/dist/api/codex-auth-helper.js +0 -327
  39. package/packages/cloud/dist/api/consensus.d.ts +0 -13
  40. package/packages/cloud/dist/api/consensus.js +0 -261
  41. package/packages/cloud/dist/api/coordinators.d.ts +0 -8
  42. package/packages/cloud/dist/api/coordinators.js +0 -750
  43. package/packages/cloud/dist/api/daemons.d.ts +0 -12
  44. package/packages/cloud/dist/api/daemons.js +0 -535
  45. package/packages/cloud/dist/api/email-auth.d.ts +0 -11
  46. package/packages/cloud/dist/api/email-auth.js +0 -347
  47. package/packages/cloud/dist/api/generic-webhooks.d.ts +0 -8
  48. package/packages/cloud/dist/api/generic-webhooks.js +0 -129
  49. package/packages/cloud/dist/api/git.d.ts +0 -8
  50. package/packages/cloud/dist/api/git.js +0 -269
  51. package/packages/cloud/dist/api/github-app.d.ts +0 -11
  52. package/packages/cloud/dist/api/github-app.js +0 -223
  53. package/packages/cloud/dist/api/middleware/planLimits.d.ts +0 -43
  54. package/packages/cloud/dist/api/middleware/planLimits.js +0 -202
  55. package/packages/cloud/dist/api/monitoring.d.ts +0 -11
  56. package/packages/cloud/dist/api/monitoring.js +0 -578
  57. package/packages/cloud/dist/api/nango-auth.d.ts +0 -9
  58. package/packages/cloud/dist/api/nango-auth.js +0 -741
  59. package/packages/cloud/dist/api/onboarding.d.ts +0 -15
  60. package/packages/cloud/dist/api/onboarding.js +0 -679
  61. package/packages/cloud/dist/api/policy.d.ts +0 -8
  62. package/packages/cloud/dist/api/policy.js +0 -229
  63. package/packages/cloud/dist/api/provider-env.d.ts +0 -26
  64. package/packages/cloud/dist/api/provider-env.js +0 -141
  65. package/packages/cloud/dist/api/providers.d.ts +0 -7
  66. package/packages/cloud/dist/api/providers.js +0 -574
  67. package/packages/cloud/dist/api/repos.d.ts +0 -8
  68. package/packages/cloud/dist/api/repos.js +0 -577
  69. package/packages/cloud/dist/api/sessions.d.ts +0 -11
  70. package/packages/cloud/dist/api/sessions.js +0 -302
  71. package/packages/cloud/dist/api/teams.d.ts +0 -7
  72. package/packages/cloud/dist/api/teams.js +0 -281
  73. package/packages/cloud/dist/api/test-helpers.d.ts +0 -10
  74. package/packages/cloud/dist/api/test-helpers.js +0 -745
  75. package/packages/cloud/dist/api/usage.d.ts +0 -7
  76. package/packages/cloud/dist/api/usage.js +0 -111
  77. package/packages/cloud/dist/api/webhooks.d.ts +0 -8
  78. package/packages/cloud/dist/api/webhooks.js +0 -645
  79. package/packages/cloud/dist/api/workspaces.d.ts +0 -25
  80. package/packages/cloud/dist/api/workspaces.js +0 -1799
  81. package/packages/cloud/dist/billing/index.d.ts +0 -9
  82. package/packages/cloud/dist/billing/index.js +0 -9
  83. package/packages/cloud/dist/billing/plans.d.ts +0 -39
  84. package/packages/cloud/dist/billing/plans.js +0 -245
  85. package/packages/cloud/dist/billing/service.d.ts +0 -80
  86. package/packages/cloud/dist/billing/service.js +0 -388
  87. package/packages/cloud/dist/billing/types.d.ts +0 -141
  88. package/packages/cloud/dist/billing/types.js +0 -7
  89. package/packages/cloud/dist/config.d.ts +0 -5
  90. package/packages/cloud/dist/config.js +0 -5
  91. package/packages/cloud/dist/db/bulk-ingest.d.ts +0 -89
  92. package/packages/cloud/dist/db/bulk-ingest.js +0 -268
  93. package/packages/cloud/dist/db/drizzle.d.ts +0 -290
  94. package/packages/cloud/dist/db/drizzle.js +0 -1422
  95. package/packages/cloud/dist/db/index.d.ts +0 -56
  96. package/packages/cloud/dist/db/index.js +0 -70
  97. package/packages/cloud/dist/db/schema.d.ts +0 -5117
  98. package/packages/cloud/dist/db/schema.js +0 -656
  99. package/packages/cloud/dist/index.d.ts +0 -11
  100. package/packages/cloud/dist/index.js +0 -38
  101. package/packages/cloud/dist/provisioner/index.d.ts +0 -207
  102. package/packages/cloud/dist/provisioner/index.js +0 -2118
  103. package/packages/cloud/dist/server.d.ts +0 -17
  104. package/packages/cloud/dist/server.js +0 -2055
  105. package/packages/cloud/dist/services/auto-scaler.d.ts +0 -152
  106. package/packages/cloud/dist/services/auto-scaler.js +0 -439
  107. package/packages/cloud/dist/services/capacity-manager.d.ts +0 -148
  108. package/packages/cloud/dist/services/capacity-manager.js +0 -449
  109. package/packages/cloud/dist/services/ci-agent-spawner.d.ts +0 -49
  110. package/packages/cloud/dist/services/ci-agent-spawner.js +0 -373
  111. package/packages/cloud/dist/services/cloud-message-bus.d.ts +0 -28
  112. package/packages/cloud/dist/services/cloud-message-bus.js +0 -19
  113. package/packages/cloud/dist/services/compute-enforcement.d.ts +0 -57
  114. package/packages/cloud/dist/services/compute-enforcement.js +0 -175
  115. package/packages/cloud/dist/services/coordinator.d.ts +0 -62
  116. package/packages/cloud/dist/services/coordinator.js +0 -389
  117. package/packages/cloud/dist/services/index.d.ts +0 -17
  118. package/packages/cloud/dist/services/index.js +0 -25
  119. package/packages/cloud/dist/services/intro-expiration.d.ts +0 -60
  120. package/packages/cloud/dist/services/intro-expiration.js +0 -252
  121. package/packages/cloud/dist/services/mention-handler.d.ts +0 -65
  122. package/packages/cloud/dist/services/mention-handler.js +0 -405
  123. package/packages/cloud/dist/services/nango.d.ts +0 -219
  124. package/packages/cloud/dist/services/nango.js +0 -424
  125. package/packages/cloud/dist/services/persistence.d.ts +0 -131
  126. package/packages/cloud/dist/services/persistence.js +0 -200
  127. package/packages/cloud/dist/services/planLimits.d.ts +0 -147
  128. package/packages/cloud/dist/services/planLimits.js +0 -335
  129. package/packages/cloud/dist/services/presence-registry.d.ts +0 -56
  130. package/packages/cloud/dist/services/presence-registry.js +0 -91
  131. package/packages/cloud/dist/services/scaling-orchestrator.d.ts +0 -159
  132. package/packages/cloud/dist/services/scaling-orchestrator.js +0 -502
  133. package/packages/cloud/dist/services/scaling-policy.d.ts +0 -121
  134. package/packages/cloud/dist/services/scaling-policy.js +0 -415
  135. package/packages/cloud/dist/services/ssh-security.d.ts +0 -31
  136. package/packages/cloud/dist/services/ssh-security.js +0 -63
  137. package/packages/cloud/dist/services/workspace-keepalive.d.ts +0 -76
  138. package/packages/cloud/dist/services/workspace-keepalive.js +0 -234
  139. package/packages/cloud/dist/shims/consensus.d.ts +0 -23
  140. package/packages/cloud/dist/shims/consensus.js +0 -5
  141. package/packages/cloud/dist/webhooks/index.d.ts +0 -24
  142. package/packages/cloud/dist/webhooks/index.js +0 -29
  143. package/packages/cloud/dist/webhooks/parsers/github.d.ts +0 -8
  144. package/packages/cloud/dist/webhooks/parsers/github.js +0 -234
  145. package/packages/cloud/dist/webhooks/parsers/index.d.ts +0 -23
  146. package/packages/cloud/dist/webhooks/parsers/index.js +0 -30
  147. package/packages/cloud/dist/webhooks/parsers/linear.d.ts +0 -9
  148. package/packages/cloud/dist/webhooks/parsers/linear.js +0 -258
  149. package/packages/cloud/dist/webhooks/parsers/slack.d.ts +0 -9
  150. package/packages/cloud/dist/webhooks/parsers/slack.js +0 -214
  151. package/packages/cloud/dist/webhooks/responders/github.d.ts +0 -8
  152. package/packages/cloud/dist/webhooks/responders/github.js +0 -73
  153. package/packages/cloud/dist/webhooks/responders/index.d.ts +0 -23
  154. package/packages/cloud/dist/webhooks/responders/index.js +0 -30
  155. package/packages/cloud/dist/webhooks/responders/linear.d.ts +0 -9
  156. package/packages/cloud/dist/webhooks/responders/linear.js +0 -149
  157. package/packages/cloud/dist/webhooks/responders/slack.d.ts +0 -20
  158. package/packages/cloud/dist/webhooks/responders/slack.js +0 -178
  159. package/packages/cloud/dist/webhooks/router.d.ts +0 -25
  160. package/packages/cloud/dist/webhooks/router.js +0 -504
  161. package/packages/cloud/dist/webhooks/rules-engine.d.ts +0 -24
  162. package/packages/cloud/dist/webhooks/rules-engine.js +0 -287
  163. package/packages/cloud/dist/webhooks/types.d.ts +0 -186
  164. package/packages/cloud/dist/webhooks/types.js +0 -8
  165. package/packages/cloud/package.json +0 -60
  166. package/scripts/run-migrations.js +0 -43
  167. package/scripts/setup-stripe-products.ts +0 -312
  168. package/scripts/verify-schema.js +0 -134
@@ -1,656 +0,0 @@
1
- /**
2
- * Agent Relay Cloud - Drizzle Schema
3
- *
4
- * Type-safe database schema with PostgreSQL support.
5
- * Generate migrations: npm run db:generate
6
- * Run migrations: npm run db:migrate
7
- */
8
- import { pgTable, uuid, varchar, text, timestamp, boolean, bigint, jsonb, unique, index, } from 'drizzle-orm/pg-core';
9
- import { relations } from 'drizzle-orm';
10
- // ============================================================================
11
- // Users
12
- // ============================================================================
13
- export const users = pgTable('users', {
14
- id: uuid('id').primaryKey().defaultRandom(),
15
- // GitHub OAuth fields (nullable for email-only users)
16
- githubId: varchar('github_id', { length: 255 }).unique(),
17
- githubUsername: varchar('github_username', { length: 255 }),
18
- // Email authentication fields
19
- email: varchar('email', { length: 255 }).unique(),
20
- passwordHash: varchar('password_hash', { length: 255 }), // For email login
21
- emailVerified: boolean('email_verified').notNull().default(false),
22
- emailVerificationToken: varchar('email_verification_token', { length: 255 }),
23
- emailVerificationExpires: timestamp('email_verification_expires'),
24
- // Profile
25
- displayName: varchar('display_name', { length: 255 }), // User-provided name for email users
26
- avatarUrl: varchar('avatar_url', { length: 512 }),
27
- plan: varchar('plan', { length: 50 }).notNull().default('free'),
28
- // Stripe billing
29
- stripeCustomerId: varchar('stripe_customer_id', { length: 255 }),
30
- // Nango OAuth connections
31
- nangoConnectionId: varchar('nango_connection_id', { length: 255 }), // Permanent login connection
32
- incomingConnectionId: varchar('incoming_connection_id', { length: 255 }), // Temp polling connection
33
- pendingInstallationRequest: timestamp('pending_installation_request'), // Org approval wait
34
- onboardingCompletedAt: timestamp('onboarding_completed_at'),
35
- createdAt: timestamp('created_at').defaultNow().notNull(),
36
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
37
- }, (table) => ({
38
- nangoConnectionIdx: index('idx_users_nango_connection').on(table.nangoConnectionId),
39
- incomingConnectionIdx: index('idx_users_incoming_connection').on(table.incomingConnectionId),
40
- emailIdx: index('idx_users_email').on(table.email),
41
- }));
42
- export const usersRelations = relations(users, ({ many }) => ({
43
- credentials: many(credentials),
44
- workspaces: many(workspaces),
45
- projectGroups: many(projectGroups),
46
- repositories: many(repositories),
47
- linkedDaemons: many(linkedDaemons),
48
- installedGitHubApps: many(githubInstallations),
49
- emails: many(userEmails),
50
- }));
51
- // ============================================================================
52
- // User Emails (GitHub-linked email addresses for account reconciliation)
53
- // ============================================================================
54
- export const userEmails = pgTable('user_emails', {
55
- id: uuid('id').primaryKey().defaultRandom(),
56
- userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
57
- email: varchar('email', { length: 255 }).notNull(),
58
- /** Whether this email is verified on GitHub */
59
- verified: boolean('verified').notNull().default(false),
60
- /** Whether this is the primary email on GitHub */
61
- primary: boolean('primary').notNull().default(false),
62
- /** Source of this email: 'github', 'manual', etc. */
63
- source: varchar('source', { length: 50 }).notNull().default('github'),
64
- createdAt: timestamp('created_at').defaultNow().notNull(),
65
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
66
- }, (table) => ({
67
- userEmailIdx: unique('user_emails_user_email_unique').on(table.userId, table.email),
68
- emailIdx: index('idx_user_emails_email').on(table.email),
69
- userIdIdx: index('idx_user_emails_user_id').on(table.userId),
70
- }));
71
- export const userEmailsRelations = relations(userEmails, ({ one }) => ({
72
- user: one(users, {
73
- fields: [userEmails.userId],
74
- references: [users.id],
75
- }),
76
- }));
77
- // ============================================================================
78
- // GitHub App Installations
79
- // ============================================================================
80
- export const githubInstallations = pgTable('github_installations', {
81
- id: uuid('id').primaryKey().defaultRandom(),
82
- installationId: varchar('installation_id', { length: 255 }).unique().notNull(),
83
- accountType: varchar('account_type', { length: 50 }).notNull(), // 'user' | 'organization'
84
- accountLogin: varchar('account_login', { length: 255 }).notNull(),
85
- accountId: varchar('account_id', { length: 255 }).notNull(),
86
- installedById: uuid('installed_by_id').references(() => users.id, { onDelete: 'set null' }),
87
- // Permissions granted to the installation
88
- permissions: jsonb('permissions').$type().default({}),
89
- // Events the installation is subscribed to
90
- events: text('events').array(),
91
- // Installation state
92
- suspended: boolean('suspended').notNull().default(false),
93
- suspendedAt: timestamp('suspended_at'),
94
- suspendedBy: varchar('suspended_by', { length: 255 }),
95
- createdAt: timestamp('created_at').defaultNow().notNull(),
96
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
97
- }, (table) => ({
98
- accountLoginIdx: index('idx_github_installations_account_login').on(table.accountLogin),
99
- installedByIdx: index('idx_github_installations_installed_by').on(table.installedById),
100
- }));
101
- export const githubInstallationsRelations = relations(githubInstallations, ({ one, many }) => ({
102
- installedBy: one(users, {
103
- fields: [githubInstallations.installedById],
104
- references: [users.id],
105
- }),
106
- repositories: many(repositories),
107
- }));
108
- // ============================================================================
109
- // Credentials (connected provider registry - no token storage)
110
- // Note: Tokens are not stored centrally. CLI tools authenticate directly
111
- // on workspace instances. This table tracks which providers a user has connected.
112
- // ============================================================================
113
- export const credentials = pgTable('credentials', {
114
- id: uuid('id').primaryKey().defaultRandom(),
115
- userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
116
- // Workspace-specific credentials - tokens are stored on the workspace daemon
117
- // Note: workspaceId uses a raw SQL reference to avoid circular dependency with workspaces table
118
- workspaceId: uuid('workspace_id').references(() => workspaces.id, { onDelete: 'cascade' }),
119
- provider: varchar('provider', { length: 50 }).notNull(),
120
- scopes: text('scopes').array(),
121
- providerAccountId: varchar('provider_account_id', { length: 255 }),
122
- providerAccountEmail: varchar('provider_account_email', { length: 255 }),
123
- createdAt: timestamp('created_at').defaultNow().notNull(),
124
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
125
- }, (table) => ({
126
- // Unique constraint: one credential per provider per workspace per user
127
- userProviderWorkspaceIdx: unique('credentials_user_provider_workspace_unique').on(table.userId, table.provider, table.workspaceId),
128
- userIdIdx: index('idx_credentials_user_id').on(table.userId),
129
- workspaceIdIdx: index('idx_credentials_workspace_id').on(table.workspaceId),
130
- }));
131
- export const credentialsRelations = relations(credentials, ({ one }) => ({
132
- user: one(users, {
133
- fields: [credentials.userId],
134
- references: [users.id],
135
- }),
136
- workspace: one(workspaces, {
137
- fields: [credentials.workspaceId],
138
- references: [workspaces.id],
139
- }),
140
- }));
141
- export const workspaces = pgTable('workspaces', {
142
- id: uuid('id').primaryKey().defaultRandom(),
143
- userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
144
- name: varchar('name', { length: 255 }).notNull(),
145
- status: varchar('status', { length: 50 }).notNull().default('provisioning'),
146
- computeProvider: varchar('compute_provider', { length: 50 }).notNull(),
147
- computeId: varchar('compute_id', { length: 255 }),
148
- publicUrl: varchar('public_url', { length: 255 }),
149
- customDomain: varchar('custom_domain', { length: 255 }),
150
- customDomainStatus: varchar('custom_domain_status', { length: 50 }),
151
- config: jsonb('config').$type().notNull().default({}),
152
- errorMessage: text('error_message'),
153
- createdAt: timestamp('created_at').defaultNow().notNull(),
154
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
155
- }, (table) => ({
156
- userIdIdx: index('idx_workspaces_user_id').on(table.userId),
157
- customDomainIdx: index('idx_workspaces_custom_domain').on(table.customDomain),
158
- }));
159
- export const workspacesRelations = relations(workspaces, ({ one, many }) => ({
160
- user: one(users, {
161
- fields: [workspaces.userId],
162
- references: [users.id],
163
- }),
164
- members: many(workspaceMembers),
165
- repositories: many(repositories),
166
- credentials: many(credentials),
167
- }));
168
- // ============================================================================
169
- // Workspace Members
170
- // ============================================================================
171
- export const workspaceMembers = pgTable('workspace_members', {
172
- id: uuid('id').primaryKey().defaultRandom(),
173
- workspaceId: uuid('workspace_id').notNull().references(() => workspaces.id, { onDelete: 'cascade' }),
174
- userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
175
- role: varchar('role', { length: 50 }).notNull().default('member'),
176
- invitedBy: uuid('invited_by').references(() => users.id),
177
- invitedAt: timestamp('invited_at').defaultNow(),
178
- acceptedAt: timestamp('accepted_at'),
179
- }, (table) => ({
180
- workspaceUserIdx: unique('workspace_members_workspace_user_unique').on(table.workspaceId, table.userId),
181
- workspaceIdIdx: index('idx_workspace_members_workspace_id').on(table.workspaceId),
182
- userIdIdx: index('idx_workspace_members_user_id').on(table.userId),
183
- }));
184
- export const workspaceMembersRelations = relations(workspaceMembers, ({ one }) => ({
185
- workspace: one(workspaces, {
186
- fields: [workspaceMembers.workspaceId],
187
- references: [workspaces.id],
188
- }),
189
- user: one(users, {
190
- fields: [workspaceMembers.userId],
191
- references: [users.id],
192
- }),
193
- inviter: one(users, {
194
- fields: [workspaceMembers.invitedBy],
195
- references: [users.id],
196
- }),
197
- }));
198
- // ============================================================================
199
- // Project Groups (grouping of related repositories)
200
- // ============================================================================
201
- export const projectGroups = pgTable('project_groups', {
202
- id: uuid('id').primaryKey().defaultRandom(),
203
- userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
204
- name: varchar('name', { length: 255 }).notNull(),
205
- description: text('description'),
206
- color: varchar('color', { length: 7 }), // Hex color for UI (e.g., "#3B82F6")
207
- icon: varchar('icon', { length: 50 }), // Icon name for UI
208
- // Coordinator agent configuration - this agent oversees all repos in the group
209
- coordinatorAgent: jsonb('coordinator_agent').$type().default({ enabled: false }),
210
- // Display order for user's groups
211
- sortOrder: bigint('sort_order', { mode: 'number' }).notNull().default(0),
212
- createdAt: timestamp('created_at').defaultNow().notNull(),
213
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
214
- }, (table) => ({
215
- userIdIdx: index('idx_project_groups_user_id').on(table.userId),
216
- userNameIdx: unique('project_groups_user_name_unique').on(table.userId, table.name),
217
- }));
218
- export const projectGroupsRelations = relations(projectGroups, ({ one, many }) => ({
219
- user: one(users, {
220
- fields: [projectGroups.userId],
221
- references: [users.id],
222
- }),
223
- repositories: many(repositories),
224
- }));
225
- // ============================================================================
226
- // Repositories
227
- // ============================================================================
228
- export const repositories = pgTable('repositories', {
229
- id: uuid('id').primaryKey().defaultRandom(),
230
- userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
231
- workspaceId: uuid('workspace_id').references(() => workspaces.id, { onDelete: 'set null' }),
232
- projectGroupId: uuid('project_group_id').references(() => projectGroups.id, { onDelete: 'set null' }),
233
- // GitHub App installation that provides access to this repo
234
- installationId: uuid('installation_id').references(() => githubInstallations.id, { onDelete: 'set null' }),
235
- nangoConnectionId: varchar('nango_connection_id', { length: 255 }),
236
- githubFullName: varchar('github_full_name', { length: 255 }).notNull(),
237
- githubId: bigint('github_id', { mode: 'number' }).notNull(),
238
- defaultBranch: varchar('default_branch', { length: 255 }).notNull().default('main'),
239
- isPrivate: boolean('is_private').notNull().default(false),
240
- syncStatus: varchar('sync_status', { length: 50 }).notNull().default('pending'),
241
- lastSyncedAt: timestamp('last_synced_at'),
242
- // Project-level agent configuration (optional)
243
- projectAgent: jsonb('project_agent').$type().default({ enabled: false }),
244
- createdAt: timestamp('created_at').defaultNow().notNull(),
245
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
246
- }, (table) => ({
247
- userGithubIdx: unique('repositories_user_github_unique').on(table.userId, table.githubFullName),
248
- userIdIdx: index('idx_repositories_user_id').on(table.userId),
249
- workspaceIdIdx: index('idx_repositories_workspace_id').on(table.workspaceId),
250
- projectGroupIdIdx: index('idx_repositories_project_group_id').on(table.projectGroupId),
251
- installationIdIdx: index('idx_repositories_installation_id').on(table.installationId),
252
- nangoConnectionIdx: index('idx_repositories_nango_connection').on(table.nangoConnectionId),
253
- }));
254
- export const repositoriesRelations = relations(repositories, ({ one }) => ({
255
- user: one(users, {
256
- fields: [repositories.userId],
257
- references: [users.id],
258
- }),
259
- workspace: one(workspaces, {
260
- fields: [repositories.workspaceId],
261
- references: [workspaces.id],
262
- }),
263
- projectGroup: one(projectGroups, {
264
- fields: [repositories.projectGroupId],
265
- references: [projectGroups.id],
266
- }),
267
- installation: one(githubInstallations, {
268
- fields: [repositories.installationId],
269
- references: [githubInstallations.id],
270
- }),
271
- }));
272
- // ============================================================================
273
- // Linked Daemons (local agent-relay instances)
274
- // ============================================================================
275
- export const linkedDaemons = pgTable('linked_daemons', {
276
- id: uuid('id').primaryKey().defaultRandom(),
277
- userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
278
- name: varchar('name', { length: 255 }).notNull(),
279
- machineId: varchar('machine_id', { length: 255 }).notNull(),
280
- apiKeyHash: varchar('api_key_hash', { length: 255 }).notNull(),
281
- status: varchar('status', { length: 50 }).notNull().default('offline'),
282
- lastSeenAt: timestamp('last_seen_at'),
283
- metadata: jsonb('metadata').notNull().default({}),
284
- pendingUpdates: jsonb('pending_updates').notNull().default([]),
285
- messageQueue: jsonb('message_queue').notNull().default([]),
286
- workspaceId: uuid('workspace_id').references(() => workspaces.id, { onDelete: 'set null' }),
287
- createdAt: timestamp('created_at').defaultNow().notNull(),
288
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
289
- }, (table) => ({
290
- userMachineIdx: unique('linked_daemons_user_machine_unique').on(table.userId, table.machineId),
291
- userIdIdx: index('idx_linked_daemons_user_id').on(table.userId),
292
- apiKeyHashIdx: index('idx_linked_daemons_api_key_hash').on(table.apiKeyHash),
293
- statusIdx: index('idx_linked_daemons_status').on(table.status),
294
- workspaceIdIdx: index('idx_linked_daemons_workspace_id').on(table.workspaceId),
295
- }));
296
- export const linkedDaemonsRelations = relations(linkedDaemons, ({ one }) => ({
297
- user: one(users, {
298
- fields: [linkedDaemons.userId],
299
- references: [users.id],
300
- }),
301
- workspace: one(workspaces, {
302
- fields: [linkedDaemons.workspaceId],
303
- references: [workspaces.id],
304
- }),
305
- }));
306
- // ============================================================================
307
- // Subscriptions (billing)
308
- // ============================================================================
309
- export const subscriptions = pgTable('subscriptions', {
310
- id: uuid('id').primaryKey().defaultRandom(),
311
- userId: uuid('user_id').references(() => users.id, { onDelete: 'cascade' }),
312
- stripeSubscriptionId: varchar('stripe_subscription_id', { length: 255 }).unique(),
313
- stripeCustomerId: varchar('stripe_customer_id', { length: 255 }),
314
- plan: varchar('plan', { length: 50 }).notNull(),
315
- status: varchar('status', { length: 50 }).notNull().default('active'),
316
- currentPeriodStart: timestamp('current_period_start'),
317
- currentPeriodEnd: timestamp('current_period_end'),
318
- createdAt: timestamp('created_at').defaultNow().notNull(),
319
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
320
- });
321
- // ============================================================================
322
- // Usage Records
323
- // ============================================================================
324
- export const usageRecords = pgTable('usage_records', {
325
- id: uuid('id').primaryKey().defaultRandom(),
326
- userId: uuid('user_id').references(() => users.id, { onDelete: 'cascade' }),
327
- workspaceId: uuid('workspace_id').references(() => workspaces.id, { onDelete: 'set null' }),
328
- metric: varchar('metric', { length: 100 }).notNull(),
329
- value: bigint('value', { mode: 'number' }).notNull(),
330
- recordedAt: timestamp('recorded_at').defaultNow().notNull(),
331
- }, (table) => ({
332
- userIdIdx: index('idx_usage_records_user_id').on(table.userId),
333
- recordedAtIdx: index('idx_usage_records_recorded_at').on(table.recordedAt),
334
- }));
335
- // ============================================================================
336
- // Channels (workspace-scoped messaging channels)
337
- // ============================================================================
338
- export const channels = pgTable('channels', {
339
- id: uuid('id').primaryKey().defaultRandom(),
340
- workspaceId: uuid('workspace_id').notNull().references(() => workspaces.id, { onDelete: 'cascade' }),
341
- /** Channel identifier (e.g., '#general', '#random', 'dm:user1:user2') */
342
- channelId: varchar('channel_id', { length: 255 }).notNull(),
343
- /** Display name (without # prefix) */
344
- name: varchar('name', { length: 255 }).notNull(),
345
- description: text('description'),
346
- /** Channel type: 'public', 'private', 'dm' */
347
- visibility: varchar('visibility', { length: 50 }).notNull().default('public'),
348
- /** Channel status: 'active', 'archived' */
349
- status: varchar('status', { length: 50 }).notNull().default('active'),
350
- createdBy: varchar('created_by', { length: 255 }),
351
- createdAt: timestamp('created_at').defaultNow().notNull(),
352
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
353
- lastActivityAt: timestamp('last_activity_at'),
354
- }, (table) => ({
355
- workspaceChannelIdx: unique('channels_workspace_channel_unique').on(table.workspaceId, table.channelId),
356
- workspaceIdIdx: index('idx_channels_workspace_id').on(table.workspaceId),
357
- statusIdx: index('idx_channels_status').on(table.status),
358
- }));
359
- export const channelsRelations = relations(channels, ({ one, many }) => ({
360
- workspace: one(workspaces, {
361
- fields: [channels.workspaceId],
362
- references: [workspaces.id],
363
- }),
364
- members: many(channelMembers),
365
- }));
366
- // ============================================================================
367
- // Channel Members (who's in each channel)
368
- // ============================================================================
369
- export const channelMembers = pgTable('channel_members', {
370
- id: uuid('id').primaryKey().defaultRandom(),
371
- channelId: uuid('channel_id').notNull().references(() => channels.id, { onDelete: 'cascade' }),
372
- /** Member identifier (username or agent name) */
373
- memberId: varchar('member_id', { length: 255 }).notNull(),
374
- /** Member type: 'user' or 'agent' */
375
- memberType: varchar('member_type', { length: 50 }).notNull().default('user'),
376
- /** Role in channel: 'owner', 'admin', 'member' */
377
- role: varchar('role', { length: 50 }).notNull().default('member'),
378
- joinedAt: timestamp('joined_at').defaultNow().notNull(),
379
- invitedBy: varchar('invited_by', { length: 255 }),
380
- }, (table) => ({
381
- channelMemberIdx: unique('channel_members_channel_member_unique').on(table.channelId, table.memberId),
382
- channelIdIdx: index('idx_channel_members_channel_id').on(table.channelId),
383
- memberIdIdx: index('idx_channel_members_member_id').on(table.memberId),
384
- }));
385
- export const channelMembersRelations = relations(channelMembers, ({ one }) => ({
386
- channel: one(channels, {
387
- fields: [channelMembers.channelId],
388
- references: [channels.id],
389
- }),
390
- }));
391
- // ============================================================================
392
- // Agent Sessions (cloud persistence for PtyWrapper agents)
393
- // ============================================================================
394
- export const agentSessions = pgTable('agent_sessions', {
395
- id: uuid('id').primaryKey().defaultRandom(),
396
- workspaceId: uuid('workspace_id').notNull().references(() => workspaces.id, { onDelete: 'cascade' }),
397
- agentName: varchar('agent_name', { length: 255 }).notNull(),
398
- status: varchar('status', { length: 50 }).notNull().default('active'),
399
- startedAt: timestamp('started_at').defaultNow().notNull(),
400
- endedAt: timestamp('ended_at'),
401
- endMarker: jsonb('end_marker').$type(),
402
- metadata: jsonb('metadata').notNull().default({}),
403
- }, (table) => ({
404
- workspaceIdIdx: index('idx_agent_sessions_workspace_id').on(table.workspaceId),
405
- agentNameIdx: index('idx_agent_sessions_agent_name').on(table.agentName),
406
- statusIdx: index('idx_agent_sessions_status').on(table.status),
407
- }));
408
- // ============================================================================
409
- // Agent Summaries (cloud persistence for [[SUMMARY]] blocks)
410
- // ============================================================================
411
- export const agentSummaries = pgTable('agent_summaries', {
412
- id: uuid('id').primaryKey().defaultRandom(),
413
- sessionId: uuid('session_id').notNull().references(() => agentSessions.id, { onDelete: 'cascade' }),
414
- agentName: varchar('agent_name', { length: 255 }).notNull(),
415
- summary: jsonb('summary').$type().notNull(),
416
- createdAt: timestamp('created_at').defaultNow().notNull(),
417
- }, (table) => ({
418
- sessionIdIdx: index('idx_agent_summaries_session_id').on(table.sessionId),
419
- agentNameIdx: index('idx_agent_summaries_agent_name').on(table.agentName),
420
- }));
421
- export const agentMetrics = pgTable('agent_metrics', {
422
- id: uuid('id').primaryKey().defaultRandom(),
423
- daemonId: uuid('daemon_id').notNull().references(() => linkedDaemons.id, { onDelete: 'cascade' }),
424
- agentName: varchar('agent_name', { length: 255 }).notNull(),
425
- pid: bigint('pid', { mode: 'number' }),
426
- status: varchar('status', { length: 50 }).notNull().default('unknown'),
427
- // Current memory snapshot
428
- rssBytes: bigint('rss_bytes', { mode: 'number' }),
429
- heapUsedBytes: bigint('heap_used_bytes', { mode: 'number' }),
430
- cpuPercent: bigint('cpu_percent', { mode: 'number' }),
431
- // Trend data
432
- trend: varchar('trend', { length: 20 }),
433
- trendRatePerMinute: bigint('trend_rate_per_minute', { mode: 'number' }),
434
- alertLevel: varchar('alert_level', { length: 20 }).default('normal'),
435
- // Watermarks
436
- highWatermark: bigint('high_watermark', { mode: 'number' }),
437
- averageRss: bigint('average_rss', { mode: 'number' }),
438
- // Full metrics JSON for detailed data
439
- metricsData: jsonb('metrics_data').$type(),
440
- // Timestamps
441
- uptimeMs: bigint('uptime_ms', { mode: 'number' }),
442
- startedAt: timestamp('started_at'),
443
- recordedAt: timestamp('recorded_at').defaultNow().notNull(),
444
- }, (table) => ({
445
- daemonIdIdx: index('idx_agent_metrics_daemon_id').on(table.daemonId),
446
- agentNameIdx: index('idx_agent_metrics_agent_name').on(table.agentName),
447
- recordedAtIdx: index('idx_agent_metrics_recorded_at').on(table.recordedAt),
448
- alertLevelIdx: index('idx_agent_metrics_alert_level').on(table.alertLevel),
449
- }));
450
- export const agentMetricsRelations = relations(agentMetrics, ({ one }) => ({
451
- daemon: one(linkedDaemons, {
452
- fields: [agentMetrics.daemonId],
453
- references: [linkedDaemons.id],
454
- }),
455
- }));
456
- // ============================================================================
457
- // Agent Crashes (crash history with insights)
458
- // ============================================================================
459
- export const agentCrashes = pgTable('agent_crashes', {
460
- id: uuid('id').primaryKey().defaultRandom(),
461
- daemonId: uuid('daemon_id').notNull().references(() => linkedDaemons.id, { onDelete: 'cascade' }),
462
- agentName: varchar('agent_name', { length: 255 }).notNull(),
463
- pid: bigint('pid', { mode: 'number' }),
464
- exitCode: bigint('exit_code', { mode: 'number' }),
465
- signal: varchar('signal', { length: 50 }),
466
- reason: text('reason'),
467
- // Crash analysis
468
- likelyCause: varchar('likely_cause', { length: 50 }),
469
- confidence: varchar('confidence', { length: 20 }),
470
- summary: text('summary'),
471
- // Memory state at crash
472
- peakMemory: bigint('peak_memory', { mode: 'number' }),
473
- lastKnownMemory: bigint('last_known_memory', { mode: 'number' }),
474
- memoryTrend: varchar('memory_trend', { length: 20 }),
475
- // Full insight data
476
- insightData: jsonb('insight_data').$type(),
477
- // Last output (truncated)
478
- lastOutput: text('last_output'),
479
- crashedAt: timestamp('crashed_at').defaultNow().notNull(),
480
- }, (table) => ({
481
- daemonIdIdx: index('idx_agent_crashes_daemon_id').on(table.daemonId),
482
- agentNameIdx: index('idx_agent_crashes_agent_name').on(table.agentName),
483
- crashedAtIdx: index('idx_agent_crashes_crashed_at').on(table.crashedAt),
484
- likelyCauseIdx: index('idx_agent_crashes_likely_cause').on(table.likelyCause),
485
- }));
486
- export const agentCrashesRelations = relations(agentCrashes, ({ one }) => ({
487
- daemon: one(linkedDaemons, {
488
- fields: [agentCrashes.daemonId],
489
- references: [linkedDaemons.id],
490
- }),
491
- }));
492
- // ============================================================================
493
- // Memory Alerts (proactive alerting history)
494
- // ============================================================================
495
- export const memoryAlerts = pgTable('memory_alerts', {
496
- id: uuid('id').primaryKey().defaultRandom(),
497
- daemonId: uuid('daemon_id').notNull().references(() => linkedDaemons.id, { onDelete: 'cascade' }),
498
- agentName: varchar('agent_name', { length: 255 }).notNull(),
499
- alertType: varchar('alert_type', { length: 50 }).notNull(), // warning, critical, oom_imminent, trend_warning, recovered
500
- currentRss: bigint('current_rss', { mode: 'number' }),
501
- threshold: bigint('threshold', { mode: 'number' }),
502
- message: text('message'),
503
- recommendation: text('recommendation'),
504
- acknowledged: boolean('acknowledged').default(false),
505
- acknowledgedAt: timestamp('acknowledged_at'),
506
- createdAt: timestamp('created_at').defaultNow().notNull(),
507
- }, (table) => ({
508
- daemonIdIdx: index('idx_memory_alerts_daemon_id').on(table.daemonId),
509
- agentNameIdx: index('idx_memory_alerts_agent_name').on(table.agentName),
510
- alertTypeIdx: index('idx_memory_alerts_alert_type').on(table.alertType),
511
- createdAtIdx: index('idx_memory_alerts_created_at').on(table.createdAt),
512
- }));
513
- export const memoryAlertsRelations = relations(memoryAlerts, ({ one }) => ({
514
- daemon: one(linkedDaemons, {
515
- fields: [memoryAlerts.daemonId],
516
- references: [linkedDaemons.id],
517
- }),
518
- }));
519
- export const ciFailureEvents = pgTable('ci_failure_events', {
520
- id: uuid('id').primaryKey().defaultRandom(),
521
- repositoryId: uuid('repository_id').references(() => repositories.id, { onDelete: 'cascade' }),
522
- repository: varchar('repository', { length: 255 }).notNull(), // org/repo format
523
- prNumber: bigint('pr_number', { mode: 'number' }),
524
- branch: varchar('branch', { length: 255 }),
525
- commitSha: varchar('commit_sha', { length: 40 }),
526
- checkName: varchar('check_name', { length: 255 }).notNull(),
527
- checkId: bigint('check_id', { mode: 'number' }).notNull(),
528
- conclusion: varchar('conclusion', { length: 50 }).notNull(), // failure, cancelled, timed_out, etc.
529
- failureTitle: text('failure_title'),
530
- failureSummary: text('failure_summary'),
531
- failureDetails: text('failure_details'),
532
- annotations: jsonb('annotations').$type().default([]),
533
- workflowName: varchar('workflow_name', { length: 255 }),
534
- workflowRunId: bigint('workflow_run_id', { mode: 'number' }),
535
- // Processing state
536
- processedAt: timestamp('processed_at'),
537
- agentSpawned: boolean('agent_spawned').default(false),
538
- createdAt: timestamp('created_at').defaultNow().notNull(),
539
- }, (table) => ({
540
- repositoryIdx: index('idx_ci_failure_events_repository').on(table.repository),
541
- prNumberIdx: index('idx_ci_failure_events_pr_number').on(table.prNumber),
542
- checkNameIdx: index('idx_ci_failure_events_check_name').on(table.checkName),
543
- createdAtIdx: index('idx_ci_failure_events_created_at').on(table.createdAt),
544
- repoPrIdx: index('idx_ci_failure_events_repo_pr').on(table.repository, table.prNumber),
545
- }));
546
- export const ciFailureEventsRelations = relations(ciFailureEvents, ({ one, many }) => ({
547
- repositoryRef: one(repositories, {
548
- fields: [ciFailureEvents.repositoryId],
549
- references: [repositories.id],
550
- }),
551
- fixAttempts: many(ciFixAttempts),
552
- }));
553
- // ============================================================================
554
- // CI Fix Attempts (agent responses to failures)
555
- // ============================================================================
556
- export const ciFixAttempts = pgTable('ci_fix_attempts', {
557
- id: uuid('id').primaryKey().defaultRandom(),
558
- failureEventId: uuid('failure_event_id').notNull().references(() => ciFailureEvents.id, { onDelete: 'cascade' }),
559
- agentId: varchar('agent_id', { length: 255 }).notNull(),
560
- agentName: varchar('agent_name', { length: 255 }).notNull(),
561
- status: varchar('status', { length: 50 }).notNull().default('pending'), // pending, in_progress, success, failed
562
- commitSha: varchar('commit_sha', { length: 40 }),
563
- errorMessage: text('error_message'),
564
- // Timing
565
- startedAt: timestamp('started_at').defaultNow().notNull(),
566
- completedAt: timestamp('completed_at'),
567
- }, (table) => ({
568
- failureEventIdx: index('idx_ci_fix_attempts_failure_event').on(table.failureEventId),
569
- statusIdx: index('idx_ci_fix_attempts_status').on(table.status),
570
- agentIdIdx: index('idx_ci_fix_attempts_agent_id').on(table.agentId),
571
- }));
572
- export const ciFixAttemptsRelations = relations(ciFixAttempts, ({ one }) => ({
573
- failureEvent: one(ciFailureEvents, {
574
- fields: [ciFixAttempts.failureEventId],
575
- references: [ciFailureEvents.id],
576
- }),
577
- }));
578
- // ============================================================================
579
- // GitHub Issue Assignments (agent handling of issues)
580
- // ============================================================================
581
- export const issueAssignments = pgTable('issue_assignments', {
582
- id: uuid('id').primaryKey().defaultRandom(),
583
- repositoryId: uuid('repository_id').references(() => repositories.id, { onDelete: 'cascade' }),
584
- repository: varchar('repository', { length: 255 }).notNull(), // org/repo format
585
- issueNumber: bigint('issue_number', { mode: 'number' }).notNull(),
586
- issueTitle: text('issue_title').notNull(),
587
- issueBody: text('issue_body'),
588
- issueUrl: varchar('issue_url', { length: 512 }),
589
- // Assignment details
590
- agentId: varchar('agent_id', { length: 255 }),
591
- agentName: varchar('agent_name', { length: 255 }),
592
- assignedAt: timestamp('assigned_at'),
593
- // Status tracking
594
- status: varchar('status', { length: 50 }).notNull().default('pending'), // pending, assigned, in_progress, resolved, closed
595
- resolution: text('resolution'),
596
- // PR created to fix the issue
597
- linkedPrNumber: bigint('linked_pr_number', { mode: 'number' }),
598
- // Metadata
599
- labels: text('labels').array(),
600
- priority: varchar('priority', { length: 20 }), // low, medium, high, critical
601
- createdAt: timestamp('created_at').defaultNow().notNull(),
602
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
603
- }, (table) => ({
604
- repositoryIdx: index('idx_issue_assignments_repository').on(table.repository),
605
- issueNumberIdx: index('idx_issue_assignments_issue_number').on(table.issueNumber),
606
- statusIdx: index('idx_issue_assignments_status').on(table.status),
607
- agentIdIdx: index('idx_issue_assignments_agent_id').on(table.agentId),
608
- repoIssueIdx: unique('issue_assignments_repo_issue_unique').on(table.repository, table.issueNumber),
609
- }));
610
- export const issueAssignmentsRelations = relations(issueAssignments, ({ one }) => ({
611
- repositoryRef: one(repositories, {
612
- fields: [issueAssignments.repositoryId],
613
- references: [repositories.id],
614
- }),
615
- }));
616
- // ============================================================================
617
- // Comment Mentions (tracking @mentions to agents)
618
- // ============================================================================
619
- export const commentMentions = pgTable('comment_mentions', {
620
- id: uuid('id').primaryKey().defaultRandom(),
621
- repositoryId: uuid('repository_id').references(() => repositories.id, { onDelete: 'cascade' }),
622
- repository: varchar('repository', { length: 255 }).notNull(),
623
- // Source of the mention
624
- sourceType: varchar('source_type', { length: 50 }).notNull(), // issue_comment, pr_comment, pr_review
625
- sourceId: bigint('source_id', { mode: 'number' }).notNull(), // GitHub comment ID
626
- issueOrPrNumber: bigint('issue_or_pr_number', { mode: 'number' }).notNull(),
627
- // Comment details
628
- commentBody: text('comment_body').notNull(),
629
- commentUrl: varchar('comment_url', { length: 512 }),
630
- authorLogin: varchar('author_login', { length: 255 }).notNull(),
631
- authorId: bigint('author_id', { mode: 'number' }),
632
- // Mention details
633
- mentionedAgent: varchar('mentioned_agent', { length: 255 }).notNull(), // e.g., "agent-relay", "ci-fix", "lead"
634
- mentionContext: text('mention_context'), // Text surrounding the mention
635
- // Response tracking
636
- agentId: varchar('agent_id', { length: 255 }),
637
- agentName: varchar('agent_name', { length: 255 }),
638
- status: varchar('status', { length: 50 }).notNull().default('pending'), // pending, processing, responded, ignored
639
- responseCommentId: bigint('response_comment_id', { mode: 'number' }),
640
- responseBody: text('response_body'),
641
- respondedAt: timestamp('responded_at'),
642
- // Metadata
643
- createdAt: timestamp('created_at').defaultNow().notNull(),
644
- }, (table) => ({
645
- repositoryIdx: index('idx_comment_mentions_repository').on(table.repository),
646
- sourceIdx: index('idx_comment_mentions_source').on(table.sourceType, table.sourceId),
647
- statusIdx: index('idx_comment_mentions_status').on(table.status),
648
- mentionedAgentIdx: index('idx_comment_mentions_mentioned_agent').on(table.mentionedAgent),
649
- }));
650
- export const commentMentionsRelations = relations(commentMentions, ({ one }) => ({
651
- repositoryRef: one(repositories, {
652
- fields: [commentMentions.repositoryId],
653
- references: [repositories.id],
654
- }),
655
- }));
656
- //# sourceMappingURL=schema.js.map