@nordsym/apiclaw 1.7.2 → 1.7.4

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 (230) hide show
  1. package/convex/_generated/api.d.ts +115 -0
  2. package/convex/_generated/api.js +23 -0
  3. package/convex/_generated/dataModel.d.ts +60 -0
  4. package/convex/_generated/server.d.ts +143 -0
  5. package/convex/_generated/server.js +93 -0
  6. package/convex/adminActivate.d.ts +3 -0
  7. package/convex/adminActivate.d.ts.map +1 -0
  8. package/convex/adminActivate.js +47 -0
  9. package/convex/adminActivate.js.map +1 -0
  10. package/convex/adminActivate.ts +54 -0
  11. package/convex/adminStats.d.ts +3 -0
  12. package/convex/adminStats.d.ts.map +1 -0
  13. package/convex/adminStats.js +42 -0
  14. package/convex/adminStats.js.map +1 -0
  15. package/convex/adminStats.ts +44 -0
  16. package/convex/agents.d.ts +76 -0
  17. package/convex/agents.d.ts.map +1 -0
  18. package/convex/agents.js +699 -0
  19. package/convex/agents.js.map +1 -0
  20. package/convex/agents.ts +814 -0
  21. package/convex/analytics.d.ts +5 -0
  22. package/convex/analytics.d.ts.map +1 -0
  23. package/convex/analytics.js +166 -0
  24. package/convex/analytics.js.map +1 -0
  25. package/convex/analytics.ts +186 -0
  26. package/convex/billing.d.ts +88 -0
  27. package/convex/billing.d.ts.map +1 -0
  28. package/convex/billing.js +655 -0
  29. package/convex/billing.js.map +1 -0
  30. package/convex/billing.ts +791 -0
  31. package/convex/capabilities.d.ts +9 -0
  32. package/convex/capabilities.d.ts.map +1 -0
  33. package/convex/capabilities.js +145 -0
  34. package/convex/capabilities.js.map +1 -0
  35. package/convex/capabilities.ts +157 -0
  36. package/convex/chains.d.ts +68 -0
  37. package/convex/chains.d.ts.map +1 -0
  38. package/convex/chains.js +1105 -0
  39. package/convex/chains.js.map +1 -0
  40. package/convex/chains.ts +1318 -0
  41. package/convex/credits.d.ts +25 -0
  42. package/convex/credits.d.ts.map +1 -0
  43. package/convex/credits.js +186 -0
  44. package/convex/credits.js.map +1 -0
  45. package/convex/credits.ts +211 -0
  46. package/convex/crons.d.ts +3 -0
  47. package/convex/crons.d.ts.map +1 -0
  48. package/convex/crons.js +17 -0
  49. package/convex/crons.js.map +1 -0
  50. package/convex/crons.ts +28 -0
  51. package/convex/directCall.d.ts +72 -0
  52. package/convex/directCall.d.ts.map +1 -0
  53. package/convex/directCall.js +627 -0
  54. package/convex/directCall.js.map +1 -0
  55. package/convex/directCall.ts +678 -0
  56. package/convex/earnProgress.d.ts +58 -0
  57. package/convex/earnProgress.d.ts.map +1 -0
  58. package/convex/earnProgress.js +649 -0
  59. package/convex/earnProgress.js.map +1 -0
  60. package/convex/earnProgress.ts +753 -0
  61. package/convex/email.d.ts +14 -0
  62. package/convex/email.d.ts.map +1 -0
  63. package/convex/email.js +300 -0
  64. package/convex/email.js.map +1 -0
  65. package/convex/email.ts +329 -0
  66. package/convex/feedback.d.ts +7 -0
  67. package/convex/feedback.d.ts.map +1 -0
  68. package/convex/feedback.js +227 -0
  69. package/convex/feedback.js.map +1 -0
  70. package/convex/feedback.ts +265 -0
  71. package/convex/http.d.ts +3 -0
  72. package/convex/http.d.ts.map +1 -0
  73. package/convex/http.js +1405 -0
  74. package/convex/http.js.map +1 -0
  75. package/convex/http.ts +1577 -0
  76. package/convex/inbound.d.ts +2 -0
  77. package/convex/inbound.d.ts.map +1 -0
  78. package/convex/inbound.js +32 -0
  79. package/convex/inbound.js.map +1 -0
  80. package/convex/inbound.ts +32 -0
  81. package/convex/logs.d.ts +38 -0
  82. package/convex/logs.d.ts.map +1 -0
  83. package/convex/logs.js +487 -0
  84. package/convex/logs.js.map +1 -0
  85. package/convex/logs.ts +550 -0
  86. package/convex/mou.d.ts +6 -0
  87. package/convex/mou.d.ts.map +1 -0
  88. package/convex/mou.js +82 -0
  89. package/convex/mou.js.map +1 -0
  90. package/convex/mou.ts +91 -0
  91. package/convex/providerKeys.d.ts +31 -0
  92. package/convex/providerKeys.d.ts.map +1 -0
  93. package/convex/providerKeys.js +257 -0
  94. package/convex/providerKeys.js.map +1 -0
  95. package/convex/providerKeys.ts +289 -0
  96. package/convex/providers.d.ts +32 -0
  97. package/convex/providers.d.ts.map +1 -0
  98. package/convex/providers.js +814 -0
  99. package/convex/providers.js.map +1 -0
  100. package/convex/providers.ts +909 -0
  101. package/convex/purchases.d.ts +7 -0
  102. package/convex/purchases.d.ts.map +1 -0
  103. package/convex/purchases.js +157 -0
  104. package/convex/purchases.js.map +1 -0
  105. package/convex/purchases.ts +183 -0
  106. package/convex/ratelimit.d.ts +4 -0
  107. package/convex/ratelimit.d.ts.map +1 -0
  108. package/convex/ratelimit.js +91 -0
  109. package/convex/ratelimit.js.map +1 -0
  110. package/convex/ratelimit.ts +104 -0
  111. package/convex/schema.ts +802 -0
  112. package/convex/searchLogs.d.ts +4 -0
  113. package/convex/searchLogs.d.ts.map +1 -0
  114. package/convex/searchLogs.js +129 -0
  115. package/convex/searchLogs.js.map +1 -0
  116. package/convex/searchLogs.ts +146 -0
  117. package/convex/seedAPILayerAPIs.d.ts +7 -0
  118. package/convex/seedAPILayerAPIs.d.ts.map +1 -0
  119. package/convex/seedAPILayerAPIs.js +177 -0
  120. package/convex/seedAPILayerAPIs.js.map +1 -0
  121. package/convex/seedAPILayerAPIs.ts +191 -0
  122. package/convex/seedDirectCallConfigs.d.ts +2 -0
  123. package/convex/seedDirectCallConfigs.d.ts.map +1 -0
  124. package/convex/seedDirectCallConfigs.js +324 -0
  125. package/convex/seedDirectCallConfigs.js.map +1 -0
  126. package/convex/seedDirectCallConfigs.ts +336 -0
  127. package/convex/seedPratham.d.ts +6 -0
  128. package/convex/seedPratham.d.ts.map +1 -0
  129. package/convex/seedPratham.js +150 -0
  130. package/convex/seedPratham.js.map +1 -0
  131. package/convex/seedPratham.ts +161 -0
  132. package/convex/spendAlerts.d.ts +36 -0
  133. package/convex/spendAlerts.d.ts.map +1 -0
  134. package/convex/spendAlerts.js +380 -0
  135. package/convex/spendAlerts.js.map +1 -0
  136. package/convex/spendAlerts.ts +442 -0
  137. package/convex/stripeActions.d.ts +19 -0
  138. package/convex/stripeActions.d.ts.map +1 -0
  139. package/convex/stripeActions.js +411 -0
  140. package/convex/stripeActions.js.map +1 -0
  141. package/convex/stripeActions.ts +512 -0
  142. package/convex/teams.d.ts +21 -0
  143. package/convex/teams.d.ts.map +1 -0
  144. package/convex/teams.js +215 -0
  145. package/convex/teams.js.map +1 -0
  146. package/convex/teams.ts +243 -0
  147. package/convex/telemetry.d.ts +4 -0
  148. package/convex/telemetry.d.ts.map +1 -0
  149. package/convex/telemetry.js +74 -0
  150. package/convex/telemetry.js.map +1 -0
  151. package/convex/telemetry.ts +81 -0
  152. package/convex/tsconfig.json +25 -0
  153. package/convex/updateAPIStatus.d.ts +6 -0
  154. package/convex/updateAPIStatus.d.ts.map +1 -0
  155. package/convex/updateAPIStatus.js +40 -0
  156. package/convex/updateAPIStatus.js.map +1 -0
  157. package/convex/updateAPIStatus.ts +45 -0
  158. package/convex/usage.d.ts +27 -0
  159. package/convex/usage.d.ts.map +1 -0
  160. package/convex/usage.js +229 -0
  161. package/convex/usage.js.map +1 -0
  162. package/convex/usage.ts +260 -0
  163. package/convex/waitlist.d.ts +4 -0
  164. package/convex/waitlist.d.ts.map +1 -0
  165. package/convex/waitlist.js +49 -0
  166. package/convex/waitlist.js.map +1 -0
  167. package/convex/waitlist.ts +55 -0
  168. package/convex/webhooks.d.ts +12 -0
  169. package/convex/webhooks.d.ts.map +1 -0
  170. package/convex/webhooks.js +410 -0
  171. package/convex/webhooks.js.map +1 -0
  172. package/convex/webhooks.ts +494 -0
  173. package/convex/workspaces.d.ts +31 -0
  174. package/convex/workspaces.d.ts.map +1 -0
  175. package/convex/workspaces.js +975 -0
  176. package/convex/workspaces.js.map +1 -0
  177. package/convex/workspaces.ts +1130 -0
  178. package/dist/bin.js +0 -0
  179. package/dist/capability-router.js +1 -1
  180. package/dist/capability-router.js.map +1 -1
  181. package/dist/execute.d.ts +2 -0
  182. package/dist/execute.d.ts.map +1 -1
  183. package/dist/execute.js +18 -4
  184. package/dist/execute.js.map +1 -1
  185. package/dist/http-api.js +1 -1
  186. package/dist/http-api.js.map +1 -1
  187. package/dist/index.js +1 -1
  188. package/dist/index.js.map +1 -1
  189. package/dist/mcp-analytics.d.ts +32 -0
  190. package/dist/mcp-analytics.d.ts.map +1 -0
  191. package/dist/mcp-analytics.js +130 -0
  192. package/dist/mcp-analytics.js.map +1 -0
  193. package/package.json +1 -1
  194. package/dist/chain-types.d.ts +0 -187
  195. package/dist/chain-types.d.ts.map +0 -1
  196. package/dist/chain-types.js +0 -33
  197. package/dist/chain-types.js.map +0 -1
  198. package/dist/registry/apis.json.bak +0 -248811
  199. package/dist/src/bin.js +0 -17
  200. package/dist/src/capability-router.js +0 -240
  201. package/dist/src/chainExecutor.js +0 -451
  202. package/dist/src/chainResolver.js +0 -518
  203. package/dist/src/cli/commands/doctor.js +0 -324
  204. package/dist/src/cli/commands/mcp-install.js +0 -255
  205. package/dist/src/cli/commands/restore.js +0 -259
  206. package/dist/src/cli/commands/setup.js +0 -205
  207. package/dist/src/cli/commands/uninstall.js +0 -188
  208. package/dist/src/cli/index.js +0 -111
  209. package/dist/src/cli.js +0 -302
  210. package/dist/src/confirmation.js +0 -240
  211. package/dist/src/credentials.js +0 -357
  212. package/dist/src/credits.js +0 -260
  213. package/dist/src/crypto.js +0 -66
  214. package/dist/src/discovery.js +0 -504
  215. package/dist/src/enterprise/env.js +0 -123
  216. package/dist/src/enterprise/script-generator.js +0 -460
  217. package/dist/src/execute-dynamic.js +0 -473
  218. package/dist/src/execute.js +0 -1727
  219. package/dist/src/index.js +0 -2062
  220. package/dist/src/metered.js +0 -80
  221. package/dist/src/open-apis.js +0 -276
  222. package/dist/src/proxy.js +0 -28
  223. package/dist/src/session.js +0 -86
  224. package/dist/src/stripe.js +0 -407
  225. package/dist/src/telemetry.js +0 -49
  226. package/dist/src/types.js +0 -2
  227. package/dist/src/utils/backup.js +0 -181
  228. package/dist/src/utils/config.js +0 -220
  229. package/dist/src/utils/os.js +0 -105
  230. package/dist/src/utils/paths.js +0 -159
@@ -0,0 +1,215 @@
1
+ import { v } from "convex/values";
2
+ import { mutation, query } from "./_generated/server";
3
+ // ============================================
4
+ // HELPER FUNCTIONS
5
+ // ============================================
6
+ function generateToken() {
7
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
8
+ let result = "";
9
+ for (let i = 0; i < 32; i++) {
10
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
11
+ }
12
+ return result;
13
+ }
14
+ // ============================================
15
+ // TEAM QUERIES
16
+ // ============================================
17
+ /**
18
+ * Get team members for a workspace
19
+ */
20
+ export const getMembers = query({
21
+ args: { token: v.string() },
22
+ handler: async (ctx, { token }) => {
23
+ const session = await ctx.db
24
+ .query("agentSessions")
25
+ .withIndex("by_sessionToken", (q) => q.eq("sessionToken", token))
26
+ .first();
27
+ if (!session)
28
+ return [];
29
+ const workspace = await ctx.db.get(session.workspaceId);
30
+ if (!workspace)
31
+ return [];
32
+ const members = await ctx.db
33
+ .query("workspaceMembers")
34
+ .withIndex("by_workspaceId", (q) => q.eq("workspaceId", session.workspaceId))
35
+ .collect();
36
+ // Add owner as first member
37
+ return [
38
+ {
39
+ email: workspace.email,
40
+ role: "owner",
41
+ status: "active",
42
+ isOwner: true,
43
+ createdAt: workspace.createdAt,
44
+ },
45
+ ...members.map((m) => ({
46
+ id: m._id,
47
+ email: m.email,
48
+ role: m.role,
49
+ status: m.status,
50
+ isOwner: false,
51
+ invitedBy: m.invitedBy,
52
+ createdAt: m.createdAt,
53
+ acceptedAt: m.acceptedAt,
54
+ })),
55
+ ];
56
+ },
57
+ });
58
+ // ============================================
59
+ // TEAM MUTATIONS
60
+ // ============================================
61
+ /**
62
+ * Invite a member to the workspace (creates pending invite)
63
+ */
64
+ export const inviteMember = mutation({
65
+ args: {
66
+ token: v.string(),
67
+ email: v.string(),
68
+ role: v.union(v.literal("admin"), v.literal("member")),
69
+ },
70
+ handler: async (ctx, { token, email, role }) => {
71
+ const session = await ctx.db
72
+ .query("agentSessions")
73
+ .withIndex("by_sessionToken", (q) => q.eq("sessionToken", token))
74
+ .first();
75
+ if (!session)
76
+ throw new Error("Invalid session");
77
+ const workspace = await ctx.db.get(session.workspaceId);
78
+ if (!workspace)
79
+ throw new Error("Workspace not found");
80
+ // Normalize email
81
+ const normalizedEmail = email.toLowerCase().trim();
82
+ // Can't invite yourself
83
+ if (normalizedEmail === workspace.email.toLowerCase()) {
84
+ throw new Error("Cannot invite yourself");
85
+ }
86
+ // Check if already member
87
+ const existing = await ctx.db
88
+ .query("workspaceMembers")
89
+ .withIndex("by_workspaceId_email", (q) => q.eq("workspaceId", session.workspaceId).eq("email", normalizedEmail))
90
+ .first();
91
+ if (existing) {
92
+ if (existing.status === "active") {
93
+ throw new Error("Already a team member");
94
+ }
95
+ if (existing.status === "pending") {
96
+ throw new Error("Invite already pending");
97
+ }
98
+ // If revoked, we can re-invite - update existing record
99
+ const inviteToken = generateToken();
100
+ await ctx.db.patch(existing._id, {
101
+ role,
102
+ invitedBy: workspace.email,
103
+ inviteToken,
104
+ status: "pending",
105
+ createdAt: Date.now(),
106
+ acceptedAt: undefined,
107
+ });
108
+ return { id: existing._id, inviteToken };
109
+ }
110
+ // Generate invite token
111
+ const inviteToken = generateToken();
112
+ const id = await ctx.db.insert("workspaceMembers", {
113
+ workspaceId: session.workspaceId,
114
+ email: normalizedEmail,
115
+ role,
116
+ invitedBy: workspace.email,
117
+ inviteToken,
118
+ status: "pending",
119
+ createdAt: Date.now(),
120
+ });
121
+ return { id, inviteToken };
122
+ },
123
+ });
124
+ /**
125
+ * Accept an invite
126
+ */
127
+ export const acceptInvite = mutation({
128
+ args: { inviteToken: v.string() },
129
+ handler: async (ctx, { inviteToken }) => {
130
+ const member = await ctx.db
131
+ .query("workspaceMembers")
132
+ .withIndex("by_inviteToken", (q) => q.eq("inviteToken", inviteToken))
133
+ .first();
134
+ if (!member)
135
+ throw new Error("Invalid invite token");
136
+ if (member.status !== "pending")
137
+ throw new Error("Invite already used or revoked");
138
+ await ctx.db.patch(member._id, {
139
+ status: "active",
140
+ acceptedAt: Date.now(),
141
+ inviteToken: undefined, // Clear token after use
142
+ });
143
+ // Get workspace info for response
144
+ const workspace = await ctx.db.get(member.workspaceId);
145
+ return {
146
+ success: true,
147
+ workspaceId: member.workspaceId,
148
+ workspaceEmail: workspace?.email,
149
+ role: member.role,
150
+ };
151
+ },
152
+ });
153
+ /**
154
+ * Remove a member from the workspace
155
+ */
156
+ export const removeMember = mutation({
157
+ args: {
158
+ token: v.string(),
159
+ memberEmail: v.string(),
160
+ },
161
+ handler: async (ctx, { token, memberEmail }) => {
162
+ const session = await ctx.db
163
+ .query("agentSessions")
164
+ .withIndex("by_sessionToken", (q) => q.eq("sessionToken", token))
165
+ .first();
166
+ if (!session)
167
+ throw new Error("Invalid session");
168
+ const workspace = await ctx.db.get(session.workspaceId);
169
+ if (!workspace)
170
+ throw new Error("Workspace not found");
171
+ const normalizedEmail = memberEmail.toLowerCase().trim();
172
+ // Cannot remove owner
173
+ if (normalizedEmail === workspace.email.toLowerCase()) {
174
+ throw new Error("Cannot remove workspace owner");
175
+ }
176
+ const member = await ctx.db
177
+ .query("workspaceMembers")
178
+ .withIndex("by_workspaceId_email", (q) => q.eq("workspaceId", session.workspaceId).eq("email", normalizedEmail))
179
+ .first();
180
+ if (!member)
181
+ throw new Error("Member not found");
182
+ // Set status to revoked instead of deleting
183
+ await ctx.db.patch(member._id, {
184
+ status: "revoked",
185
+ inviteToken: undefined,
186
+ });
187
+ return { success: true };
188
+ },
189
+ });
190
+ /**
191
+ * Get invite details (public, for invite acceptance page)
192
+ */
193
+ export const getInviteDetails = query({
194
+ args: { inviteToken: v.string() },
195
+ handler: async (ctx, { inviteToken }) => {
196
+ const member = await ctx.db
197
+ .query("workspaceMembers")
198
+ .withIndex("by_inviteToken", (q) => q.eq("inviteToken", inviteToken))
199
+ .first();
200
+ if (!member)
201
+ return null;
202
+ if (member.status !== "pending")
203
+ return null;
204
+ const workspace = await ctx.db.get(member.workspaceId);
205
+ if (!workspace)
206
+ return null;
207
+ return {
208
+ email: member.email,
209
+ role: member.role,
210
+ invitedBy: member.invitedBy,
211
+ workspaceEmail: workspace.email,
212
+ };
213
+ },
214
+ });
215
+ //# sourceMappingURL=teams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams.js","sourceRoot":"","sources":["teams.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,243 @@
1
+ import { v } from "convex/values";
2
+ import { mutation, query } from "./_generated/server";
3
+
4
+ // ============================================
5
+ // HELPER FUNCTIONS
6
+ // ============================================
7
+
8
+ function generateToken(): string {
9
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
10
+ let result = "";
11
+ for (let i = 0; i < 32; i++) {
12
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
13
+ }
14
+ return result;
15
+ }
16
+
17
+ // ============================================
18
+ // TEAM QUERIES
19
+ // ============================================
20
+
21
+ /**
22
+ * Get team members for a workspace
23
+ */
24
+ export const getMembers = query({
25
+ args: { token: v.string() },
26
+ handler: async (ctx, { token }) => {
27
+ const session = await ctx.db
28
+ .query("agentSessions")
29
+ .withIndex("by_sessionToken", (q) => q.eq("sessionToken", token))
30
+ .first();
31
+
32
+ if (!session) return [];
33
+
34
+ const workspace = await ctx.db.get(session.workspaceId);
35
+ if (!workspace) return [];
36
+
37
+ const members = await ctx.db
38
+ .query("workspaceMembers")
39
+ .withIndex("by_workspaceId", (q) => q.eq("workspaceId", session.workspaceId))
40
+ .collect();
41
+
42
+ // Add owner as first member
43
+ return [
44
+ {
45
+ email: workspace.email,
46
+ role: "owner" as const,
47
+ status: "active" as const,
48
+ isOwner: true,
49
+ createdAt: workspace.createdAt,
50
+ },
51
+ ...members.map((m) => ({
52
+ id: m._id,
53
+ email: m.email,
54
+ role: m.role,
55
+ status: m.status,
56
+ isOwner: false,
57
+ invitedBy: m.invitedBy,
58
+ createdAt: m.createdAt,
59
+ acceptedAt: m.acceptedAt,
60
+ })),
61
+ ];
62
+ },
63
+ });
64
+
65
+ // ============================================
66
+ // TEAM MUTATIONS
67
+ // ============================================
68
+
69
+ /**
70
+ * Invite a member to the workspace (creates pending invite)
71
+ */
72
+ export const inviteMember = mutation({
73
+ args: {
74
+ token: v.string(),
75
+ email: v.string(),
76
+ role: v.union(v.literal("admin"), v.literal("member")),
77
+ },
78
+ handler: async (ctx, { token, email, role }) => {
79
+ const session = await ctx.db
80
+ .query("agentSessions")
81
+ .withIndex("by_sessionToken", (q) => q.eq("sessionToken", token))
82
+ .first();
83
+
84
+ if (!session) throw new Error("Invalid session");
85
+
86
+ const workspace = await ctx.db.get(session.workspaceId);
87
+ if (!workspace) throw new Error("Workspace not found");
88
+
89
+ // Normalize email
90
+ const normalizedEmail = email.toLowerCase().trim();
91
+
92
+ // Can't invite yourself
93
+ if (normalizedEmail === workspace.email.toLowerCase()) {
94
+ throw new Error("Cannot invite yourself");
95
+ }
96
+
97
+ // Check if already member
98
+ const existing = await ctx.db
99
+ .query("workspaceMembers")
100
+ .withIndex("by_workspaceId_email", (q) =>
101
+ q.eq("workspaceId", session.workspaceId).eq("email", normalizedEmail)
102
+ )
103
+ .first();
104
+
105
+ if (existing) {
106
+ if (existing.status === "active") {
107
+ throw new Error("Already a team member");
108
+ }
109
+ if (existing.status === "pending") {
110
+ throw new Error("Invite already pending");
111
+ }
112
+ // If revoked, we can re-invite - update existing record
113
+ const inviteToken = generateToken();
114
+ await ctx.db.patch(existing._id, {
115
+ role,
116
+ invitedBy: workspace.email,
117
+ inviteToken,
118
+ status: "pending",
119
+ createdAt: Date.now(),
120
+ acceptedAt: undefined,
121
+ });
122
+ return { id: existing._id, inviteToken };
123
+ }
124
+
125
+ // Generate invite token
126
+ const inviteToken = generateToken();
127
+
128
+ const id = await ctx.db.insert("workspaceMembers", {
129
+ workspaceId: session.workspaceId,
130
+ email: normalizedEmail,
131
+ role,
132
+ invitedBy: workspace.email,
133
+ inviteToken,
134
+ status: "pending",
135
+ createdAt: Date.now(),
136
+ });
137
+
138
+ return { id, inviteToken };
139
+ },
140
+ });
141
+
142
+ /**
143
+ * Accept an invite
144
+ */
145
+ export const acceptInvite = mutation({
146
+ args: { inviteToken: v.string() },
147
+ handler: async (ctx, { inviteToken }) => {
148
+ const member = await ctx.db
149
+ .query("workspaceMembers")
150
+ .withIndex("by_inviteToken", (q) => q.eq("inviteToken", inviteToken))
151
+ .first();
152
+
153
+ if (!member) throw new Error("Invalid invite token");
154
+ if (member.status !== "pending") throw new Error("Invite already used or revoked");
155
+
156
+ await ctx.db.patch(member._id, {
157
+ status: "active",
158
+ acceptedAt: Date.now(),
159
+ inviteToken: undefined, // Clear token after use
160
+ });
161
+
162
+ // Get workspace info for response
163
+ const workspace = await ctx.db.get(member.workspaceId);
164
+
165
+ return {
166
+ success: true,
167
+ workspaceId: member.workspaceId,
168
+ workspaceEmail: workspace?.email,
169
+ role: member.role,
170
+ };
171
+ },
172
+ });
173
+
174
+ /**
175
+ * Remove a member from the workspace
176
+ */
177
+ export const removeMember = mutation({
178
+ args: {
179
+ token: v.string(),
180
+ memberEmail: v.string(),
181
+ },
182
+ handler: async (ctx, { token, memberEmail }) => {
183
+ const session = await ctx.db
184
+ .query("agentSessions")
185
+ .withIndex("by_sessionToken", (q) => q.eq("sessionToken", token))
186
+ .first();
187
+
188
+ if (!session) throw new Error("Invalid session");
189
+
190
+ const workspace = await ctx.db.get(session.workspaceId);
191
+ if (!workspace) throw new Error("Workspace not found");
192
+
193
+ const normalizedEmail = memberEmail.toLowerCase().trim();
194
+
195
+ // Cannot remove owner
196
+ if (normalizedEmail === workspace.email.toLowerCase()) {
197
+ throw new Error("Cannot remove workspace owner");
198
+ }
199
+
200
+ const member = await ctx.db
201
+ .query("workspaceMembers")
202
+ .withIndex("by_workspaceId_email", (q) =>
203
+ q.eq("workspaceId", session.workspaceId).eq("email", normalizedEmail)
204
+ )
205
+ .first();
206
+
207
+ if (!member) throw new Error("Member not found");
208
+
209
+ // Set status to revoked instead of deleting
210
+ await ctx.db.patch(member._id, {
211
+ status: "revoked",
212
+ inviteToken: undefined,
213
+ });
214
+
215
+ return { success: true };
216
+ },
217
+ });
218
+
219
+ /**
220
+ * Get invite details (public, for invite acceptance page)
221
+ */
222
+ export const getInviteDetails = query({
223
+ args: { inviteToken: v.string() },
224
+ handler: async (ctx, { inviteToken }) => {
225
+ const member = await ctx.db
226
+ .query("workspaceMembers")
227
+ .withIndex("by_inviteToken", (q) => q.eq("inviteToken", inviteToken))
228
+ .first();
229
+
230
+ if (!member) return null;
231
+ if (member.status !== "pending") return null;
232
+
233
+ const workspace = await ctx.db.get(member.workspaceId);
234
+ if (!workspace) return null;
235
+
236
+ return {
237
+ email: member.email,
238
+ role: member.role,
239
+ invitedBy: member.invitedBy,
240
+ workspaceEmail: workspace.email,
241
+ };
242
+ },
243
+ });
@@ -0,0 +1,4 @@
1
+ export declare const track: any;
2
+ export declare const getStats: any;
3
+ export declare const getRecent: any;
4
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["telemetry.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,KAAK,KA2BhB,CAAC;AAEH,eAAO,MAAM,QAAQ,KAsCnB,CAAC;AAEH,eAAO,MAAM,SAAS,KAQpB,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { mutation, query } from "./_generated/server";
2
+ import { v } from "convex/values";
3
+ export const track = mutation({
4
+ args: {
5
+ event: v.object({
6
+ type: v.string(),
7
+ query: v.optional(v.string()),
8
+ apiId: v.optional(v.string()),
9
+ resultCount: v.optional(v.number()),
10
+ responseTimeMs: v.optional(v.number()),
11
+ version: v.optional(v.string()),
12
+ platform: v.optional(v.string()),
13
+ nodeVersion: v.optional(v.string()),
14
+ timestamp: v.optional(v.number()),
15
+ }),
16
+ },
17
+ handler: async (ctx, { event }) => {
18
+ await ctx.db.insert("telemetry", {
19
+ type: event.type,
20
+ query: event.query,
21
+ apiId: event.apiId,
22
+ resultCount: event.resultCount,
23
+ responseTimeMs: event.responseTimeMs,
24
+ version: event.version || "unknown",
25
+ platform: event.platform || "unknown",
26
+ nodeVersion: event.nodeVersion || "unknown",
27
+ timestamp: event.timestamp || Date.now(),
28
+ });
29
+ },
30
+ });
31
+ export const getStats = query({
32
+ args: {},
33
+ handler: async (ctx) => {
34
+ const events = await ctx.db.query("telemetry").collect();
35
+ const startups = events.filter(e => e.type === "startup").length;
36
+ const searches = events.filter(e => e.type === "search").length;
37
+ const executes = events.filter(e => e.type === "execute").length;
38
+ const uniqueUsers = new Set(events.map(e => `${e.platform}-${e.nodeVersion}`)).size;
39
+ const topQueries = events
40
+ .filter(e => e.type === "search" && e.query)
41
+ .reduce((acc, e) => {
42
+ acc[e.query] = (acc[e.query] || 0) + 1;
43
+ return acc;
44
+ }, {});
45
+ const topAPIs = events
46
+ .filter(e => e.type === "execute" && e.apiId)
47
+ .reduce((acc, e) => {
48
+ acc[e.apiId] = (acc[e.apiId] || 0) + 1;
49
+ return acc;
50
+ }, {});
51
+ return {
52
+ totalStartups: startups,
53
+ totalSearches: searches,
54
+ totalExecutes: executes,
55
+ estimatedUniqueUsers: uniqueUsers,
56
+ topQueries: Object.entries(topQueries)
57
+ .sort(([, a], [, b]) => b - a)
58
+ .slice(0, 10),
59
+ topAPIs: Object.entries(topAPIs)
60
+ .sort(([, a], [, b]) => b - a)
61
+ .slice(0, 10),
62
+ };
63
+ },
64
+ });
65
+ export const getRecent = query({
66
+ args: { limit: v.optional(v.number()) },
67
+ handler: async (ctx, { limit = 50 }) => {
68
+ return await ctx.db
69
+ .query("telemetry")
70
+ .order("desc")
71
+ .take(limit);
72
+ },
73
+ });
74
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAElC,MAAM,CAAC,MAAM,KAAK,GAAG,QAAQ,CAAC;IAC5B,IAAI,EAAE;QACJ,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;YACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;YAChB,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YAC7B,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YAC7B,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YACnC,cAAc,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YACtC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YAC/B,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YAChC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YACnC,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SAClC,CAAC;KACH;IACD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QAChC,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE;YAC/B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,SAAS;YACnC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,SAAS;YACrC,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,SAAS;YAC3C,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;SACzC,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;IAC5B,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACrB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;QAEzD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;QAChE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QAEjE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAEpF,MAAM,UAAU,GAAG,MAAM;aACtB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC;aAC3C,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACjB,GAAG,CAAC,CAAC,CAAC,KAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACzC,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAA4B,CAAC,CAAC;QAEnC,MAAM,OAAO,GAAG,MAAM;aACnB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC;aAC5C,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACjB,GAAG,CAAC,CAAC,CAAC,KAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACzC,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAA4B,CAAC,CAAC;QAEnC,OAAO;YACL,aAAa,EAAE,QAAQ;YACvB,aAAa,EAAE,QAAQ;YACvB,aAAa,EAAE,QAAQ;YACvB,oBAAoB,EAAE,WAAW;YACjC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;iBACnC,IAAI,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,EAAE,CAAC,EAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;iBAC3B,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;iBAC7B,IAAI,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,EAAE,CAAC,EAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;iBAC3B,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SAChB,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC;IAC7B,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;IACvC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,EAAE;QACrC,OAAO,MAAM,GAAG,CAAC,EAAE;aAChB,KAAK,CAAC,WAAW,CAAC;aAClB,KAAK,CAAC,MAAM,CAAC;aACb,IAAI,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,81 @@
1
+ import { mutation, query } from "./_generated/server";
2
+ import { v } from "convex/values";
3
+
4
+ export const track = mutation({
5
+ args: {
6
+ event: v.object({
7
+ type: v.string(),
8
+ query: v.optional(v.string()),
9
+ apiId: v.optional(v.string()),
10
+ resultCount: v.optional(v.number()),
11
+ responseTimeMs: v.optional(v.number()),
12
+ version: v.optional(v.string()),
13
+ platform: v.optional(v.string()),
14
+ nodeVersion: v.optional(v.string()),
15
+ timestamp: v.optional(v.number()),
16
+ }),
17
+ },
18
+ handler: async (ctx, { event }) => {
19
+ await ctx.db.insert("telemetry", {
20
+ type: event.type,
21
+ query: event.query,
22
+ apiId: event.apiId,
23
+ resultCount: event.resultCount,
24
+ responseTimeMs: event.responseTimeMs,
25
+ version: event.version || "unknown",
26
+ platform: event.platform || "unknown",
27
+ nodeVersion: event.nodeVersion || "unknown",
28
+ timestamp: event.timestamp || Date.now(),
29
+ });
30
+ },
31
+ });
32
+
33
+ export const getStats = query({
34
+ args: {},
35
+ handler: async (ctx) => {
36
+ const events = await ctx.db.query("telemetry").collect();
37
+
38
+ const startups = events.filter(e => e.type === "startup").length;
39
+ const searches = events.filter(e => e.type === "search").length;
40
+ const executes = events.filter(e => e.type === "execute").length;
41
+
42
+ const uniqueUsers = new Set(events.map(e => `${e.platform}-${e.nodeVersion}`)).size;
43
+
44
+ const topQueries = events
45
+ .filter(e => e.type === "search" && e.query)
46
+ .reduce((acc, e) => {
47
+ acc[e.query!] = (acc[e.query!] || 0) + 1;
48
+ return acc;
49
+ }, {} as Record<string, number>);
50
+
51
+ const topAPIs = events
52
+ .filter(e => e.type === "execute" && e.apiId)
53
+ .reduce((acc, e) => {
54
+ acc[e.apiId!] = (acc[e.apiId!] || 0) + 1;
55
+ return acc;
56
+ }, {} as Record<string, number>);
57
+
58
+ return {
59
+ totalStartups: startups,
60
+ totalSearches: searches,
61
+ totalExecutes: executes,
62
+ estimatedUniqueUsers: uniqueUsers,
63
+ topQueries: Object.entries(topQueries)
64
+ .sort(([,a], [,b]) => b - a)
65
+ .slice(0, 10),
66
+ topAPIs: Object.entries(topAPIs)
67
+ .sort(([,a], [,b]) => b - a)
68
+ .slice(0, 10),
69
+ };
70
+ },
71
+ });
72
+
73
+ export const getRecent = query({
74
+ args: { limit: v.optional(v.number()) },
75
+ handler: async (ctx, { limit = 50 }) => {
76
+ return await ctx.db
77
+ .query("telemetry")
78
+ .order("desc")
79
+ .take(limit);
80
+ },
81
+ });
@@ -0,0 +1,25 @@
1
+ {
2
+ /* This TypeScript project config describes the environment that
3
+ * Convex functions run in and is used to typecheck them.
4
+ * You can modify it, but some settings are required to use Convex.
5
+ */
6
+ "compilerOptions": {
7
+ /* These settings are not required by Convex and can be modified. */
8
+ "allowJs": true,
9
+ "strict": true,
10
+ "moduleResolution": "Bundler",
11
+ "jsx": "react-jsx",
12
+ "skipLibCheck": true,
13
+ "allowSyntheticDefaultImports": true,
14
+
15
+ /* These compiler options are required by Convex */
16
+ "target": "ESNext",
17
+ "lib": ["ES2021", "dom"],
18
+ "forceConsistentCasingInFileNames": true,
19
+ "module": "ESNext",
20
+ "isolatedModules": true,
21
+ "noEmit": true
22
+ },
23
+ "include": ["./**/*"],
24
+ "exclude": ["./_generated"]
25
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Update providerAPIs status to reflect actual Direct Call status
3
+ * Run: npx convex run updateAPIStatus:update
4
+ */
5
+ export declare const update: any;
6
+ //# sourceMappingURL=updateAPIStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateAPIStatus.d.ts","sourceRoot":"","sources":["updateAPIStatus.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,MAAM,KAsCjB,CAAC"}