@chaaskit/server 0.1.0

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 (189) hide show
  1. package/dist/api/admin.js +438 -0
  2. package/dist/api/admin.js.map +1 -0
  3. package/dist/api/agents.js +21 -0
  4. package/dist/api/agents.js.map +1 -0
  5. package/dist/api/api-keys.js +122 -0
  6. package/dist/api/api-keys.js.map +1 -0
  7. package/dist/api/auth.js +399 -0
  8. package/dist/api/auth.js.map +1 -0
  9. package/dist/api/chat.js +900 -0
  10. package/dist/api/chat.js.map +1 -0
  11. package/dist/api/config.js +91 -0
  12. package/dist/api/config.js.map +1 -0
  13. package/dist/api/documents.js +237 -0
  14. package/dist/api/documents.js.map +1 -0
  15. package/dist/api/export.js +107 -0
  16. package/dist/api/export.js.map +1 -0
  17. package/dist/api/health.js +25 -0
  18. package/dist/api/health.js.map +1 -0
  19. package/dist/api/mcp-server.js +84 -0
  20. package/dist/api/mcp-server.js.map +1 -0
  21. package/dist/api/mcp.js +400 -0
  22. package/dist/api/mcp.js.map +1 -0
  23. package/dist/api/mentions.js +94 -0
  24. package/dist/api/mentions.js.map +1 -0
  25. package/dist/api/oauth.js +366 -0
  26. package/dist/api/oauth.js.map +1 -0
  27. package/dist/api/payments.js +473 -0
  28. package/dist/api/payments.js.map +1 -0
  29. package/dist/api/projects.js +301 -0
  30. package/dist/api/projects.js.map +1 -0
  31. package/dist/api/scheduled-prompts.js +617 -0
  32. package/dist/api/scheduled-prompts.js.map +1 -0
  33. package/dist/api/search.js +85 -0
  34. package/dist/api/search.js.map +1 -0
  35. package/dist/api/share.js +188 -0
  36. package/dist/api/share.js.map +1 -0
  37. package/dist/api/slack.js +468 -0
  38. package/dist/api/slack.js.map +1 -0
  39. package/dist/api/teams.js +693 -0
  40. package/dist/api/teams.js.map +1 -0
  41. package/dist/api/templates.js +134 -0
  42. package/dist/api/templates.js.map +1 -0
  43. package/dist/api/threads.js +323 -0
  44. package/dist/api/threads.js.map +1 -0
  45. package/dist/api/upload.js +57 -0
  46. package/dist/api/upload.js.map +1 -0
  47. package/dist/api/user.js +111 -0
  48. package/dist/api/user.js.map +1 -0
  49. package/dist/api/v1/openai.js +245 -0
  50. package/dist/api/v1/openai.js.map +1 -0
  51. package/dist/app.js +168 -0
  52. package/dist/app.js.map +1 -0
  53. package/dist/bin/cli.js +57 -0
  54. package/dist/bin/cli.js.map +1 -0
  55. package/dist/commands/db-sync.js +108 -0
  56. package/dist/commands/db-sync.js.map +1 -0
  57. package/dist/config/loader.js +374 -0
  58. package/dist/config/loader.js.map +1 -0
  59. package/dist/documents/extractors.js +136 -0
  60. package/dist/documents/extractors.js.map +1 -0
  61. package/dist/extensions/glob.js +53 -0
  62. package/dist/extensions/glob.js.map +1 -0
  63. package/dist/extensions/loader.js +72 -0
  64. package/dist/extensions/loader.js.map +1 -0
  65. package/dist/index.js +25 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/loaders/index.js +75 -0
  68. package/dist/loaders/index.js.map +1 -0
  69. package/dist/mcp/client.js +551 -0
  70. package/dist/mcp/client.js.map +1 -0
  71. package/dist/mcp/server.js +335 -0
  72. package/dist/mcp/server.js.map +1 -0
  73. package/dist/middleware/apiKeyAuth.js +136 -0
  74. package/dist/middleware/apiKeyAuth.js.map +1 -0
  75. package/dist/middleware/auth.js +192 -0
  76. package/dist/middleware/auth.js.map +1 -0
  77. package/dist/middleware/errorHandler.js +41 -0
  78. package/dist/middleware/errorHandler.js.map +1 -0
  79. package/dist/middleware/mcpServerAuth.js +164 -0
  80. package/dist/middleware/mcpServerAuth.js.map +1 -0
  81. package/dist/middleware/requestLogger.js +9 -0
  82. package/dist/middleware/requestLogger.js.map +1 -0
  83. package/dist/middleware/team.js +132 -0
  84. package/dist/middleware/team.js.map +1 -0
  85. package/dist/oauth/server.js +410 -0
  86. package/dist/oauth/server.js.map +1 -0
  87. package/dist/queue/cli.js +93 -0
  88. package/dist/queue/cli.js.map +1 -0
  89. package/dist/queue/handlers/index.js +91 -0
  90. package/dist/queue/handlers/index.js.map +1 -0
  91. package/dist/queue/handlers/scheduled-prompt.js +270 -0
  92. package/dist/queue/handlers/scheduled-prompt.js.map +1 -0
  93. package/dist/queue/index.js +91 -0
  94. package/dist/queue/index.js.map +1 -0
  95. package/dist/queue/providers/memory.js +296 -0
  96. package/dist/queue/providers/memory.js.map +1 -0
  97. package/dist/queue/providers/sqs.js +275 -0
  98. package/dist/queue/providers/sqs.js.map +1 -0
  99. package/dist/queue/scheduler.js +355 -0
  100. package/dist/queue/scheduler.js.map +1 -0
  101. package/dist/queue/types.js +5 -0
  102. package/dist/queue/types.js.map +1 -0
  103. package/dist/queue/worker.js +230 -0
  104. package/dist/queue/worker.js.map +1 -0
  105. package/dist/registry/index.js +40 -0
  106. package/dist/registry/index.js.map +1 -0
  107. package/dist/server.js +207 -0
  108. package/dist/server.js.map +1 -0
  109. package/dist/services/agent.js +530 -0
  110. package/dist/services/agent.js.map +1 -0
  111. package/dist/services/agents.js +194 -0
  112. package/dist/services/agents.js.map +1 -0
  113. package/dist/services/documents.js +507 -0
  114. package/dist/services/documents.js.map +1 -0
  115. package/dist/services/email/index.js +91 -0
  116. package/dist/services/email/index.js.map +1 -0
  117. package/dist/services/email/providers/ses.js +97 -0
  118. package/dist/services/email/providers/ses.js.map +1 -0
  119. package/dist/services/email/templates.js +194 -0
  120. package/dist/services/email/templates.js.map +1 -0
  121. package/dist/services/email/types.js +5 -0
  122. package/dist/services/email/types.js.map +1 -0
  123. package/dist/services/encryption.js +69 -0
  124. package/dist/services/encryption.js.map +1 -0
  125. package/dist/services/oauth-discovery.js +226 -0
  126. package/dist/services/oauth-discovery.js.map +1 -0
  127. package/dist/services/pendingConfirmation.js +105 -0
  128. package/dist/services/pendingConfirmation.js.map +1 -0
  129. package/dist/services/scheduledPrompts.js +70 -0
  130. package/dist/services/scheduledPrompts.js.map +1 -0
  131. package/dist/services/slack/client.js +174 -0
  132. package/dist/services/slack/client.js.map +1 -0
  133. package/dist/services/slack/events.js +189 -0
  134. package/dist/services/slack/events.js.map +1 -0
  135. package/dist/services/slack/index.js +6 -0
  136. package/dist/services/slack/index.js.map +1 -0
  137. package/dist/services/slack/notifications.js +124 -0
  138. package/dist/services/slack/notifications.js.map +1 -0
  139. package/dist/services/slack/signature.js +74 -0
  140. package/dist/services/slack/signature.js.map +1 -0
  141. package/dist/services/slack/thread-context.js +191 -0
  142. package/dist/services/slack/thread-context.js.map +1 -0
  143. package/dist/services/toolConfirmation.js +55 -0
  144. package/dist/services/toolConfirmation.js.map +1 -0
  145. package/dist/services/usage.js +241 -0
  146. package/dist/services/usage.js.map +1 -0
  147. package/dist/ssr/build.js +90 -0
  148. package/dist/ssr/build.js.map +1 -0
  149. package/dist/ssr/components/SSRMessageList.js +120 -0
  150. package/dist/ssr/components/SSRMessageList.js.map +1 -0
  151. package/dist/ssr/entry.client.js +8 -0
  152. package/dist/ssr/entry.client.js.map +1 -0
  153. package/dist/ssr/entry.server.js +71 -0
  154. package/dist/ssr/entry.server.js.map +1 -0
  155. package/dist/ssr/handler.js +51 -0
  156. package/dist/ssr/handler.js.map +1 -0
  157. package/dist/ssr/root.js +184 -0
  158. package/dist/ssr/root.js.map +1 -0
  159. package/dist/ssr/routes/login.js +140 -0
  160. package/dist/ssr/routes/login.js.map +1 -0
  161. package/dist/ssr/routes/pricing.js +195 -0
  162. package/dist/ssr/routes/pricing.js.map +1 -0
  163. package/dist/ssr/routes/privacy.js +39 -0
  164. package/dist/ssr/routes/privacy.js.map +1 -0
  165. package/dist/ssr/routes/register.js +148 -0
  166. package/dist/ssr/routes/register.js.map +1 -0
  167. package/dist/ssr/routes/shared.$shareId.js +153 -0
  168. package/dist/ssr/routes/shared.$shareId.js.map +1 -0
  169. package/dist/ssr/routes/terms.js +39 -0
  170. package/dist/ssr/routes/terms.js.map +1 -0
  171. package/dist/storage/index.js +43 -0
  172. package/dist/storage/index.js.map +1 -0
  173. package/dist/storage/providers/database.js +38 -0
  174. package/dist/storage/providers/database.js.map +1 -0
  175. package/dist/storage/providers/filesystem.js +51 -0
  176. package/dist/storage/providers/filesystem.js.map +1 -0
  177. package/dist/storage/types.js +2 -0
  178. package/dist/storage/types.js.map +1 -0
  179. package/dist/tools/documents.js +336 -0
  180. package/dist/tools/documents.js.map +1 -0
  181. package/dist/tools/get-plan-usage.js +82 -0
  182. package/dist/tools/get-plan-usage.js.map +1 -0
  183. package/dist/tools/index.js +106 -0
  184. package/dist/tools/index.js.map +1 -0
  185. package/dist/tools/types.js +2 -0
  186. package/dist/tools/types.js.map +1 -0
  187. package/dist/tools/web-scrape.js +145 -0
  188. package/dist/tools/web-scrape.js.map +1 -0
  189. package/package.json +93 -0
@@ -0,0 +1,241 @@
1
+ import { db } from '@chaaskit/db';
2
+ import { getConfig } from '../config/loader.js';
3
+ export function getPlanLimits(planId) {
4
+ const config = getConfig();
5
+ const plan = config.payments.plans.find((p) => p.id === planId);
6
+ if (!plan) {
7
+ return { monthlyMessageLimit: 0, canUseCredits: false };
8
+ }
9
+ if (plan.type === 'free') {
10
+ const params = plan.params;
11
+ return {
12
+ monthlyMessageLimit: params.monthlyMessageLimit,
13
+ canUseCredits: false,
14
+ };
15
+ }
16
+ if (plan.type === 'monthly') {
17
+ const params = plan.params;
18
+ return {
19
+ monthlyMessageLimit: params.monthlyMessageLimit,
20
+ canUseCredits: false,
21
+ };
22
+ }
23
+ if (plan.type === 'credits') {
24
+ return {
25
+ monthlyMessageLimit: -1, // Unlimited with credits
26
+ canUseCredits: true,
27
+ };
28
+ }
29
+ return { monthlyMessageLimit: 0, canUseCredits: false };
30
+ }
31
+ /**
32
+ * Determine the billing context for a message.
33
+ * - Personal thread: Use user's personal plan/credits
34
+ * - Team thread with team plan: Use team's pool
35
+ * - Team thread without team plan: Fall back to user's personal plan
36
+ */
37
+ export async function getBillingContext(userId, teamId) {
38
+ const config = getConfig();
39
+ if (!config.payments.enabled) {
40
+ return null;
41
+ }
42
+ // If team thread, check if team has a plan
43
+ if (teamId) {
44
+ const team = await db.team.findUnique({
45
+ where: { id: teamId },
46
+ select: {
47
+ id: true,
48
+ plan: true,
49
+ credits: true,
50
+ messagesThisMonth: true,
51
+ },
52
+ });
53
+ if (team) {
54
+ const teamPlanConfig = config.payments.plans.find((p) => p.id === team.plan);
55
+ // Use team billing if team has an active plan (not 'free' or explicitly team-scoped)
56
+ const teamHasActivePlan = team.plan !== 'free' || (teamPlanConfig?.scope === 'team' || teamPlanConfig?.scope === 'both');
57
+ // Check if team has a paid plan or if the team's free plan should be used
58
+ if (team.plan !== 'free' || teamPlanConfig?.scope === 'team') {
59
+ const limits = getPlanLimits(team.plan);
60
+ return {
61
+ type: 'team',
62
+ entityId: team.id,
63
+ plan: team.plan,
64
+ credits: team.credits,
65
+ messagesThisMonth: team.messagesThisMonth,
66
+ monthlyLimit: limits.monthlyMessageLimit,
67
+ };
68
+ }
69
+ }
70
+ }
71
+ // Fall back to personal billing
72
+ const user = await db.user.findUnique({
73
+ where: { id: userId },
74
+ select: {
75
+ id: true,
76
+ plan: true,
77
+ credits: true,
78
+ messagesThisMonth: true,
79
+ },
80
+ });
81
+ if (!user) {
82
+ return null;
83
+ }
84
+ const limits = getPlanLimits(user.plan);
85
+ return {
86
+ type: 'personal',
87
+ entityId: user.id,
88
+ plan: user.plan,
89
+ credits: user.credits,
90
+ messagesThisMonth: user.messagesThisMonth,
91
+ monthlyLimit: limits.monthlyMessageLimit,
92
+ };
93
+ }
94
+ /**
95
+ * Check if user/team can send a message based on their usage limits.
96
+ * For team threads, checks team's quota first, then falls back to user's personal quota.
97
+ */
98
+ export async function checkUsageLimits(userId, teamId) {
99
+ const config = getConfig();
100
+ if (!config.payments.enabled) {
101
+ return true; // No limits if payments disabled
102
+ }
103
+ const context = await getBillingContext(userId, teamId);
104
+ if (!context) {
105
+ return false;
106
+ }
107
+ // Unlimited plan
108
+ if (context.monthlyLimit === -1) {
109
+ return true;
110
+ }
111
+ // Check monthly limit
112
+ if (context.messagesThisMonth < context.monthlyLimit) {
113
+ return true;
114
+ }
115
+ // Check if entity has credits
116
+ if (context.credits > 0) {
117
+ return true;
118
+ }
119
+ return false;
120
+ }
121
+ /**
122
+ * Increment usage on the correct entity (user or team).
123
+ * For team threads with team billing, increments team's usage.
124
+ * Otherwise, increments user's personal usage.
125
+ */
126
+ export async function incrementUsage(userId, teamId) {
127
+ const config = getConfig();
128
+ if (!config.payments.enabled) {
129
+ return;
130
+ }
131
+ const context = await getBillingContext(userId, teamId);
132
+ if (!context) {
133
+ return;
134
+ }
135
+ // If unlimited plan, increment monthly usage for tracking purposes
136
+ if (context.monthlyLimit === -1) {
137
+ if (context.type === 'team') {
138
+ await db.team.update({
139
+ where: { id: context.entityId },
140
+ data: {
141
+ messagesThisMonth: { increment: 1 },
142
+ },
143
+ });
144
+ }
145
+ else {
146
+ await db.user.update({
147
+ where: { id: context.entityId },
148
+ data: {
149
+ messagesThisMonth: { increment: 1 },
150
+ },
151
+ });
152
+ }
153
+ return;
154
+ }
155
+ // If under monthly limit, increment monthly usage
156
+ if (context.messagesThisMonth < context.monthlyLimit) {
157
+ if (context.type === 'team') {
158
+ await db.team.update({
159
+ where: { id: context.entityId },
160
+ data: {
161
+ messagesThisMonth: { increment: 1 },
162
+ },
163
+ });
164
+ }
165
+ else {
166
+ await db.user.update({
167
+ where: { id: context.entityId },
168
+ data: {
169
+ messagesThisMonth: { increment: 1 },
170
+ },
171
+ });
172
+ }
173
+ return;
174
+ }
175
+ // Otherwise, deduct a credit
176
+ if (context.credits > 0) {
177
+ if (context.type === 'team') {
178
+ await db.team.update({
179
+ where: { id: context.entityId },
180
+ data: {
181
+ credits: { decrement: 1 },
182
+ },
183
+ });
184
+ }
185
+ else {
186
+ await db.user.update({
187
+ where: { id: context.entityId },
188
+ data: {
189
+ credits: { decrement: 1 },
190
+ },
191
+ });
192
+ }
193
+ }
194
+ }
195
+ /**
196
+ * Reset monthly usage for all users AND teams.
197
+ * Call via cron job at start of month.
198
+ */
199
+ export async function resetMonthlyUsage() {
200
+ // Reset users
201
+ await db.user.updateMany({
202
+ data: {
203
+ messagesThisMonth: 0,
204
+ },
205
+ });
206
+ // Reset teams
207
+ await db.team.updateMany({
208
+ data: {
209
+ messagesThisMonth: 0,
210
+ },
211
+ });
212
+ }
213
+ /**
214
+ * Get team subscription info.
215
+ */
216
+ export async function getTeamSubscription(teamId) {
217
+ const config = getConfig();
218
+ const team = await db.team.findUnique({
219
+ where: { id: teamId },
220
+ select: {
221
+ plan: true,
222
+ credits: true,
223
+ messagesThisMonth: true,
224
+ stripeCustomerId: true,
225
+ },
226
+ });
227
+ if (!team) {
228
+ return null;
229
+ }
230
+ const limits = getPlanLimits(team.plan);
231
+ const planConfig = config.payments.plans.find((p) => p.id === team.plan);
232
+ return {
233
+ plan: team.plan,
234
+ planName: planConfig?.name || 'Unknown',
235
+ messagesThisMonth: team.messagesThisMonth,
236
+ monthlyLimit: limits.monthlyMessageLimit,
237
+ credits: team.credits,
238
+ hasStripeCustomer: !!team.stripeCustomerId,
239
+ };
240
+ }
241
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/services/usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Remix Build Configuration
3
+ *
4
+ * This module exports the server build for Remix.
5
+ * Routes are statically defined here for the Express integration.
6
+ */
7
+ // Import entry point
8
+ import * as serverEntry from './entry.server.js';
9
+ // Import root
10
+ import * as root from './root.js';
11
+ // Import routes
12
+ import * as sharedRoute from './routes/shared.$shareId.js';
13
+ import * as pricingRoute from './routes/pricing.js';
14
+ import * as loginRoute from './routes/login.js';
15
+ import * as registerRoute from './routes/register.js';
16
+ import * as privacyRoute from './routes/privacy.js';
17
+ import * as termsRoute from './routes/terms.js';
18
+ // Build the routes object - use type assertion to avoid strict type checking
19
+ // The Remix runtime will validate modules at runtime
20
+ const routes = {
21
+ root: {
22
+ id: 'root',
23
+ path: '',
24
+ module: root,
25
+ },
26
+ 'routes/shared.$shareId': {
27
+ id: 'routes/shared.$shareId',
28
+ parentId: 'root',
29
+ path: 'shared/:shareId',
30
+ module: sharedRoute,
31
+ },
32
+ 'routes/pricing': {
33
+ id: 'routes/pricing',
34
+ parentId: 'root',
35
+ path: 'pricing',
36
+ module: pricingRoute,
37
+ },
38
+ 'routes/login': {
39
+ id: 'routes/login',
40
+ parentId: 'root',
41
+ path: 'login',
42
+ module: loginRoute,
43
+ },
44
+ 'routes/register': {
45
+ id: 'routes/register',
46
+ parentId: 'root',
47
+ path: 'register',
48
+ module: registerRoute,
49
+ },
50
+ 'routes/privacy': {
51
+ id: 'routes/privacy',
52
+ parentId: 'root',
53
+ path: 'privacy',
54
+ module: privacyRoute,
55
+ },
56
+ 'routes/terms': {
57
+ id: 'routes/terms',
58
+ parentId: 'root',
59
+ path: 'terms',
60
+ module: termsRoute,
61
+ },
62
+ };
63
+ // Construct the server build using type assertion
64
+ export const build = {
65
+ entry: {
66
+ module: serverEntry,
67
+ },
68
+ routes,
69
+ assets: {
70
+ entry: {
71
+ module: '/build/entry.client.js',
72
+ imports: [],
73
+ },
74
+ routes: {},
75
+ url: '/build/manifest.json',
76
+ version: '1',
77
+ },
78
+ publicPath: '/build/',
79
+ assetsBuildDirectory: 'public/build',
80
+ future: {
81
+ v3_fetcherPersist: false,
82
+ v3_relativeSplatPath: false,
83
+ v3_throwAbortReason: false,
84
+ v3_lazyRouteDiscovery: false,
85
+ v3_singleFetch: false,
86
+ },
87
+ isSpaMode: false,
88
+ mode: process.env.NODE_ENV || 'development',
89
+ };
90
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/ssr/build.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,qBAAqB;AACrB,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAEjD,cAAc;AACd,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,gBAAgB;AAChB,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAEhD,6EAA6E;AAC7E,qDAAqD;AACrD,MAAM,MAAM,GAAG;IACb,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM;QACV,IAAI,EAAE,EAAE;QACR,MAAM,EAAE,IAAI;KACb;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,wBAAwB;QAC5B,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,WAAW;KACpB;IACD,gBAAgB,EAAE;QAChB,EAAE,EAAE,gBAAgB;QACpB,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,YAAY;KACrB;IACD,cAAc,EAAE;QACd,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,UAAU;KACnB;IACD,iBAAiB,EAAE;QACjB,EAAE,EAAE,iBAAiB;QACrB,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,aAAa;KACtB;IACD,gBAAgB,EAAE;QAChB,EAAE,EAAE,gBAAgB;QACpB,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,YAAY;KACrB;IACD,cAAc,EAAE;QACd,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,UAAU;KACnB;CACuB,CAAC;AAE3B,kDAAkD;AAClD,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,KAAK,EAAE;QACL,MAAM,EAAE,WAOP;KACF;IACD,MAAM;IACN,MAAM,EAAE;QACN,KAAK,EAAE;YACL,MAAM,EAAE,wBAAwB;YAChC,OAAO,EAAE,EAAE;SACZ;QACD,MAAM,EAAE,EAAE;QACV,GAAG,EAAE,sBAAsB;QAC3B,OAAO,EAAE,GAAG;KACb;IACD,UAAU,EAAE,SAAS;IACrB,oBAAoB,EAAE,cAAc;IACpC,MAAM,EAAE;QACN,iBAAiB,EAAE,KAAK;QACxB,oBAAoB,EAAE,KAAK;QAC3B,mBAAmB,EAAE,KAAK;QAC1B,qBAAqB,EAAE,KAAK;QAC5B,cAAc,EAAE,KAAK;KACtB;IACD,SAAS,EAAE,KAAK;IAChB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa;CAC7B,CAAC"}
@@ -0,0 +1,120 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ function UserIcon() {
3
+ return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" }), _jsx("circle", { cx: "12", cy: "7", r: "4" })] }));
4
+ }
5
+ function BotIcon() {
6
+ return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M12 8V4H8" }), _jsx("rect", { width: "16", height: "12", x: "4", y: "8", rx: "2" }), _jsx("path", { d: "M2 14h2" }), _jsx("path", { d: "M20 14h2" }), _jsx("path", { d: "M15 13v2" }), _jsx("path", { d: "M9 13v2" })] }));
7
+ }
8
+ // Simple markdown-like rendering for SSR
9
+ function SimpleMarkdown({ content }) {
10
+ // Split into paragraphs and render
11
+ const paragraphs = content.split('\n\n');
12
+ return (_jsx(_Fragment, { children: paragraphs.map((para, i) => {
13
+ // Check for code blocks
14
+ if (para.startsWith('```')) {
15
+ const lines = para.split('\n');
16
+ const lang = lines[0]?.slice(3) || 'text';
17
+ const code = lines.slice(1, -1).join('\n');
18
+ return (_jsxs("div", { style: {
19
+ margin: '1rem 0',
20
+ borderRadius: '0.5rem',
21
+ border: '1px solid rgb(var(--color-border))',
22
+ overflow: 'hidden',
23
+ }, children: [_jsx("div", { style: {
24
+ backgroundColor: 'rgb(var(--color-background-secondary))',
25
+ padding: '0.5rem 1rem',
26
+ fontSize: '0.75rem',
27
+ fontWeight: 500,
28
+ color: 'rgb(var(--color-text-muted))',
29
+ textTransform: 'uppercase',
30
+ }, children: lang }), _jsx("pre", { style: {
31
+ margin: 0,
32
+ padding: '1rem',
33
+ overflow: 'auto',
34
+ backgroundColor: 'rgb(var(--color-background-secondary))',
35
+ }, children: _jsx("code", { style: {
36
+ fontFamily: 'var(--font-mono)',
37
+ fontSize: '0.875rem',
38
+ whiteSpace: 'pre',
39
+ }, children: code }) })] }, i));
40
+ }
41
+ // Regular paragraph with inline formatting
42
+ return (_jsx("p", { style: { marginBottom: i < paragraphs.length - 1 ? '1rem' : 0 }, children: para.split('\n').map((line, j) => (_jsxs("span", { children: [j > 0 && _jsx("br", {}), line] }, j))) }, i));
43
+ }) }));
44
+ }
45
+ function SSRMessageItem({ message }) {
46
+ const isUser = message.role === 'user';
47
+ if (isUser) {
48
+ return (_jsxs("div", { style: {
49
+ display: 'flex',
50
+ gap: '0.75rem',
51
+ flexDirection: 'row-reverse',
52
+ }, children: [_jsx("div", { style: {
53
+ display: 'flex',
54
+ height: '1.5rem',
55
+ width: '1.5rem',
56
+ flexShrink: 0,
57
+ alignItems: 'center',
58
+ justifyContent: 'center',
59
+ borderRadius: '9999px',
60
+ backgroundColor: 'rgb(var(--color-primary))',
61
+ color: 'white',
62
+ }, children: _jsx(UserIcon, {}) }), _jsx("div", { style: {
63
+ display: 'flex',
64
+ maxWidth: '85%',
65
+ flexDirection: 'column',
66
+ alignItems: 'flex-end',
67
+ }, children: _jsx("div", { style: {
68
+ backgroundColor: 'rgb(var(--color-user-message-bg))',
69
+ color: 'rgb(var(--color-user-message-text))',
70
+ borderRadius: '0.5rem',
71
+ padding: '0.5rem 0.75rem',
72
+ }, children: _jsx("p", { style: {
73
+ whiteSpace: 'pre-wrap',
74
+ fontSize: '0.875rem',
75
+ margin: 0,
76
+ }, children: message.content }) }) })] }));
77
+ }
78
+ // Assistant message
79
+ return (_jsxs("div", { style: {
80
+ display: 'flex',
81
+ gap: '0.75rem',
82
+ }, children: [_jsx("div", { style: {
83
+ display: 'flex',
84
+ height: '1.5rem',
85
+ width: '1.5rem',
86
+ flexShrink: 0,
87
+ alignItems: 'center',
88
+ justifyContent: 'center',
89
+ borderRadius: '9999px',
90
+ backgroundColor: 'rgb(var(--color-secondary))',
91
+ color: 'white',
92
+ }, children: _jsx(BotIcon, {}) }), _jsx("div", { style: {
93
+ display: 'flex',
94
+ maxWidth: '85%',
95
+ flexDirection: 'column',
96
+ alignItems: 'flex-start',
97
+ }, children: _jsx("div", { style: {
98
+ backgroundColor: 'rgb(var(--color-assistant-message-bg))',
99
+ color: 'rgb(var(--color-assistant-message-text))',
100
+ borderRadius: '0.5rem',
101
+ padding: '0.5rem 0.75rem',
102
+ }, children: _jsx("div", { style: {
103
+ fontSize: '0.875rem',
104
+ lineHeight: 1.625,
105
+ }, children: _jsx(SimpleMarkdown, { content: message.content }) }) }) })] }));
106
+ }
107
+ export function SSRMessageList({ messages }) {
108
+ return (_jsx("div", { style: {
109
+ maxWidth: '48rem',
110
+ marginLeft: 'auto',
111
+ marginRight: 'auto',
112
+ padding: '1.5rem 1rem',
113
+ }, children: _jsx("div", { style: {
114
+ display: 'flex',
115
+ flexDirection: 'column',
116
+ gap: '1rem',
117
+ }, children: messages.map((message) => (_jsx(SSRMessageItem, { message: message }, message.id))) }) }));
118
+ }
119
+ export default SSRMessageList;
120
+ //# sourceMappingURL=SSRMessageList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SSRMessageList.js","sourceRoot":"","sources":["../../../src/ssr/components/SSRMessageList.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { RemixBrowser } from '@remix-run/react';
3
+ import { startTransition, StrictMode } from 'react';
4
+ import { hydrateRoot } from 'react-dom/client';
5
+ startTransition(() => {
6
+ hydrateRoot(document, _jsx(StrictMode, { children: _jsx(RemixBrowser, {}) }));
7
+ });
8
+ //# sourceMappingURL=entry.client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.client.js","sourceRoot":"","sources":["../../src/ssr/entry.client.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,eAAe,CAAC,GAAG,EAAE;IACnB,WAAW,CACT,QAAQ,EACR,KAAC,UAAU,cACT,KAAC,YAAY,KAAG,GACL,CACd,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { PassThrough } from 'node:stream';
3
+ import { createReadableStreamFromReadable } from '@remix-run/node';
4
+ import { RemixServer } from '@remix-run/react';
5
+ import { isbot } from 'isbot';
6
+ import { renderToPipeableStream } from 'react-dom/server';
7
+ const ABORT_DELAY = 5_000;
8
+ export default function handleRequest(request, responseStatusCode, responseHeaders, remixContext) {
9
+ const userAgent = request.headers.get('user-agent');
10
+ const isBotRequest = userAgent ? isbot(userAgent) : false;
11
+ return isBotRequest
12
+ ? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext)
13
+ : handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext);
14
+ }
15
+ function handleBotRequest(request, responseStatusCode, responseHeaders, remixContext) {
16
+ return new Promise((resolve, reject) => {
17
+ let shellRendered = false;
18
+ const { pipe, abort } = renderToPipeableStream(_jsx(RemixServer, { context: remixContext, url: request.url, abortDelay: ABORT_DELAY }), {
19
+ onAllReady() {
20
+ shellRendered = true;
21
+ const body = new PassThrough();
22
+ const stream = createReadableStreamFromReadable(body);
23
+ responseHeaders.set('Content-Type', 'text/html');
24
+ resolve(new Response(stream, {
25
+ headers: responseHeaders,
26
+ status: responseStatusCode,
27
+ }));
28
+ pipe(body);
29
+ },
30
+ onShellError(error) {
31
+ reject(error);
32
+ },
33
+ onError(error) {
34
+ responseStatusCode = 500;
35
+ if (shellRendered) {
36
+ console.error(error);
37
+ }
38
+ },
39
+ });
40
+ setTimeout(abort, ABORT_DELAY);
41
+ });
42
+ }
43
+ function handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext) {
44
+ return new Promise((resolve, reject) => {
45
+ let shellRendered = false;
46
+ const { pipe, abort } = renderToPipeableStream(_jsx(RemixServer, { context: remixContext, url: request.url, abortDelay: ABORT_DELAY }), {
47
+ onShellReady() {
48
+ shellRendered = true;
49
+ const body = new PassThrough();
50
+ const stream = createReadableStreamFromReadable(body);
51
+ responseHeaders.set('Content-Type', 'text/html');
52
+ resolve(new Response(stream, {
53
+ headers: responseHeaders,
54
+ status: responseStatusCode,
55
+ }));
56
+ pipe(body);
57
+ },
58
+ onShellError(error) {
59
+ reject(error);
60
+ },
61
+ onError(error) {
62
+ responseStatusCode = 500;
63
+ if (shellRendered) {
64
+ console.error(error);
65
+ }
66
+ },
67
+ });
68
+ setTimeout(abort, ABORT_DELAY);
69
+ });
70
+ }
71
+ //# sourceMappingURL=entry.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.server.js","sourceRoot":"","sources":["../../src/ssr/entry.server.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Remix SSR Handler for Express
3
+ *
4
+ * This module creates a Remix request handler that integrates with Express.
5
+ * It handles specific routes with SSR while allowing other routes to fall through to the SPA.
6
+ */
7
+ import { createRequestHandler } from '@remix-run/express';
8
+ // SSR routes - these will be rendered on the server
9
+ // All other routes fall through to the SPA
10
+ const SSR_ROUTES = [
11
+ '/shared/', // Shared threads (SEO-critical)
12
+ '/pricing', // Pricing page
13
+ '/login', // Login page
14
+ '/register', // Register page
15
+ '/privacy', // Privacy policy
16
+ '/terms', // Terms of service
17
+ ];
18
+ /**
19
+ * Check if a request path should be handled by SSR
20
+ */
21
+ export function isSSRRoute(path) {
22
+ return SSR_ROUTES.some((route) => {
23
+ if (route.endsWith('/')) {
24
+ return path.startsWith(route);
25
+ }
26
+ return path === route || path.startsWith(route + '/') || path.startsWith(route + '?');
27
+ });
28
+ }
29
+ /**
30
+ * Create Express middleware for Remix SSR
31
+ */
32
+ export function createRemixHandler(build) {
33
+ return createRequestHandler({
34
+ build,
35
+ mode: process.env.NODE_ENV,
36
+ });
37
+ }
38
+ /**
39
+ * Conditionally apply Remix handler for SSR routes only
40
+ */
41
+ export function createConditionalRemixHandler(build) {
42
+ const remixHandler = createRemixHandler(build);
43
+ return (req, res, next) => {
44
+ if (isSSRRoute(req.path)) {
45
+ return remixHandler(req, res, next);
46
+ }
47
+ // Let non-SSR routes fall through to SPA or other handlers
48
+ next();
49
+ };
50
+ }
51
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/ssr/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAI1D,oDAAoD;AACpD,2CAA2C;AAC3C,MAAM,UAAU,GAAG;IACjB,UAAU,EAAG,gCAAgC;IAC7C,UAAU,EAAG,eAAe;IAC5B,QAAQ,EAAK,aAAa;IAC1B,WAAW,EAAE,gBAAgB;IAC7B,UAAU,EAAG,iBAAiB;IAC9B,QAAQ,EAAK,mBAAmB;CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QAC/B,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAkB;IACnD,OAAO,oBAAoB,CAAC;QAC1B,KAAK;QACL,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ;KAC3B,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,6BAA6B,CAAC,KAAkB;IAC9D,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAE/C,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACtC,CAAC;QACD,2DAA2D;QAC3D,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}