@convex-dev/agent 0.0.15-alpha.1 → 0.0.16-alpha.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 (84) hide show
  1. package/README.md +93 -29
  2. package/dist/commonjs/client/index.d.ts +771 -74
  3. package/dist/commonjs/client/index.d.ts.map +1 -1
  4. package/dist/commonjs/client/index.js +82 -45
  5. package/dist/commonjs/client/index.js.map +1 -1
  6. package/dist/commonjs/client/playground.d.ts +474 -0
  7. package/dist/commonjs/client/playground.d.ts.map +1 -0
  8. package/dist/commonjs/client/playground.js +178 -0
  9. package/dist/commonjs/client/playground.js.map +1 -0
  10. package/dist/commonjs/component/apiKeys.d.ts +11 -0
  11. package/dist/commonjs/component/apiKeys.d.ts.map +1 -0
  12. package/dist/commonjs/component/apiKeys.js +69 -0
  13. package/dist/commonjs/component/apiKeys.js.map +1 -0
  14. package/dist/commonjs/component/files.d.ts +31 -0
  15. package/dist/commonjs/component/files.d.ts.map +1 -0
  16. package/dist/commonjs/component/files.js +61 -0
  17. package/dist/commonjs/component/files.js.map +1 -0
  18. package/dist/commonjs/component/messages.d.ts +40 -109
  19. package/dist/commonjs/component/messages.d.ts.map +1 -1
  20. package/dist/commonjs/component/messages.js +44 -260
  21. package/dist/commonjs/component/messages.js.map +1 -1
  22. package/dist/commonjs/component/schema.d.ts +54 -10
  23. package/dist/commonjs/component/schema.d.ts.map +1 -1
  24. package/dist/commonjs/component/schema.js +7 -2
  25. package/dist/commonjs/component/schema.js.map +1 -1
  26. package/dist/commonjs/component/threads.d.ts +95 -0
  27. package/dist/commonjs/component/threads.d.ts.map +1 -0
  28. package/dist/commonjs/component/threads.js +151 -0
  29. package/dist/commonjs/component/threads.js.map +1 -0
  30. package/dist/commonjs/component/users.d.ts +37 -0
  31. package/dist/commonjs/component/users.d.ts.map +1 -0
  32. package/dist/commonjs/component/users.js +118 -0
  33. package/dist/commonjs/component/users.js.map +1 -0
  34. package/dist/commonjs/validators.d.ts +2 -6
  35. package/dist/commonjs/validators.d.ts.map +1 -1
  36. package/dist/commonjs/validators.js +0 -1
  37. package/dist/commonjs/validators.js.map +1 -1
  38. package/dist/esm/client/index.d.ts +771 -74
  39. package/dist/esm/client/index.d.ts.map +1 -1
  40. package/dist/esm/client/index.js +82 -45
  41. package/dist/esm/client/index.js.map +1 -1
  42. package/dist/esm/client/playground.d.ts +474 -0
  43. package/dist/esm/client/playground.d.ts.map +1 -0
  44. package/dist/esm/client/playground.js +178 -0
  45. package/dist/esm/client/playground.js.map +1 -0
  46. package/dist/esm/component/apiKeys.d.ts +11 -0
  47. package/dist/esm/component/apiKeys.d.ts.map +1 -0
  48. package/dist/esm/component/apiKeys.js +69 -0
  49. package/dist/esm/component/apiKeys.js.map +1 -0
  50. package/dist/esm/component/files.d.ts +31 -0
  51. package/dist/esm/component/files.d.ts.map +1 -0
  52. package/dist/esm/component/files.js +61 -0
  53. package/dist/esm/component/files.js.map +1 -0
  54. package/dist/esm/component/messages.d.ts +40 -109
  55. package/dist/esm/component/messages.d.ts.map +1 -1
  56. package/dist/esm/component/messages.js +44 -260
  57. package/dist/esm/component/messages.js.map +1 -1
  58. package/dist/esm/component/schema.d.ts +54 -10
  59. package/dist/esm/component/schema.d.ts.map +1 -1
  60. package/dist/esm/component/schema.js +7 -2
  61. package/dist/esm/component/schema.js.map +1 -1
  62. package/dist/esm/component/threads.d.ts +95 -0
  63. package/dist/esm/component/threads.d.ts.map +1 -0
  64. package/dist/esm/component/threads.js +151 -0
  65. package/dist/esm/component/threads.js.map +1 -0
  66. package/dist/esm/component/users.d.ts +37 -0
  67. package/dist/esm/component/users.d.ts.map +1 -0
  68. package/dist/esm/component/users.js +118 -0
  69. package/dist/esm/component/users.js.map +1 -0
  70. package/dist/esm/validators.d.ts +2 -6
  71. package/dist/esm/validators.d.ts.map +1 -1
  72. package/dist/esm/validators.js +0 -1
  73. package/dist/esm/validators.js.map +1 -1
  74. package/package.json +10 -2
  75. package/src/client/index.ts +152 -120
  76. package/src/client/playground.ts +231 -0
  77. package/src/component/_generated/api.d.ts +319 -107
  78. package/src/component/apiKeys.ts +74 -0
  79. package/src/component/files.ts +72 -0
  80. package/src/component/messages.ts +54 -308
  81. package/src/component/schema.ts +7 -2
  82. package/src/component/threads.ts +184 -0
  83. package/src/component/users.ts +145 -0
  84. package/src/validators.ts +0 -1
@@ -8,7 +8,11 @@
8
8
  * @module
9
9
  */
10
10
 
11
+ import type * as apiKeys from "../apiKeys.js";
12
+ import type * as files from "../files.js";
11
13
  import type * as messages from "../messages.js";
14
+ import type * as threads from "../threads.js";
15
+ import type * as users from "../users.js";
12
16
  import type * as vector_index from "../vector/index.js";
13
17
  import type * as vector_tables from "../vector/tables.js";
14
18
 
@@ -27,11 +31,58 @@ import type {
27
31
  * ```
28
32
  */
29
33
  declare const fullApi: ApiFromModules<{
34
+ apiKeys: typeof apiKeys;
35
+ files: typeof files;
30
36
  messages: typeof messages;
37
+ threads: typeof threads;
38
+ users: typeof users;
31
39
  "vector/index": typeof vector_index;
32
40
  "vector/tables": typeof vector_tables;
33
41
  }>;
34
42
  export type Mounts = {
43
+ apiKeys: {
44
+ destroy: FunctionReference<
45
+ "mutation",
46
+ "public",
47
+ { apiKey?: string; name?: string },
48
+ | "missing"
49
+ | "deleted"
50
+ | "name mismatch"
51
+ | "must provide either apiKey or name"
52
+ >;
53
+ issue: FunctionReference<"mutation", "public", { name?: string }, string>;
54
+ validate: FunctionReference<"query", "public", { apiKey: string }, boolean>;
55
+ };
56
+ files: {
57
+ addFile: FunctionReference<
58
+ "mutation",
59
+ "public",
60
+ { hash: string; storageId: string },
61
+ string
62
+ >;
63
+ getFilesToDelete: FunctionReference<
64
+ "query",
65
+ "public",
66
+ { cursor?: string; limit?: number },
67
+ {
68
+ continueCursor: string;
69
+ files: Array<{
70
+ _creationTime: number;
71
+ _id: string;
72
+ hash: string;
73
+ refcount: number;
74
+ storageId: string;
75
+ }>;
76
+ isDone: boolean;
77
+ }
78
+ >;
79
+ resuseFile: FunctionReference<
80
+ "mutation",
81
+ "public",
82
+ { fileId: string },
83
+ null
84
+ >;
85
+ };
35
86
  messages: {
36
87
  addMessages: FunctionReference<
37
88
  "mutation",
@@ -496,7 +547,7 @@ export type Mounts = {
496
547
  "public",
497
548
  {
498
549
  failPendingSteps?: boolean;
499
- messageId: string;
550
+ parentMessageId: string;
500
551
  step: {
501
552
  messages: Array<{
502
553
  embedding?: {
@@ -1066,102 +1117,10 @@ export type Mounts = {
1066
1117
  { messageId: string },
1067
1118
  null
1068
1119
  >;
1069
- createThread: FunctionReference<
1070
- "mutation",
1071
- "public",
1072
- {
1073
- defaultSystemPrompt?: string;
1074
- parentThreadIds?: Array<string>;
1075
- summary?: string;
1076
- title?: string;
1077
- userId?: string;
1078
- },
1079
- {
1080
- _creationTime: number;
1081
- _id: string;
1082
- defaultSystemPrompt?: string;
1083
- order?: number;
1084
- parentThreadIds?: Array<string>;
1085
- status: "active" | "archived";
1086
- summary?: string;
1087
- title?: string;
1088
- userId?: string;
1089
- }
1090
- >;
1091
- deleteAllForThreadIdAsync: FunctionReference<
1092
- "mutation",
1093
- "public",
1094
- { cursor?: string; limit?: number; threadId: string },
1095
- { cursor: string; isDone: boolean }
1096
- >;
1097
- deleteAllForThreadIdSync: FunctionReference<
1098
- "action",
1099
- "public",
1100
- { cursor?: string; limit?: number; threadId: string },
1101
- { cursor: string; isDone: boolean }
1102
- >;
1103
- deleteAllForUserId: FunctionReference<
1104
- "action",
1105
- "public",
1106
- { userId: string },
1107
- null
1108
- >;
1109
- deleteAllForUserIdAsync: FunctionReference<
1110
- "mutation",
1111
- "public",
1112
- { userId: string },
1113
- boolean
1114
- >;
1115
- getFilesToDelete: FunctionReference<
1116
- "query",
1117
- "public",
1118
- { cursor?: string; limit?: number },
1119
- {
1120
- continueCursor: string;
1121
- files: Array<{
1122
- _creationTime: number;
1123
- _id: string;
1124
- hash: string;
1125
- refcount: number;
1126
- storageId: string;
1127
- }>;
1128
- isDone: boolean;
1129
- }
1130
- >;
1131
- getThread: FunctionReference<
1132
- "query",
1133
- "public",
1134
- { threadId: string },
1135
- {
1136
- _creationTime: number;
1137
- _id: string;
1138
- defaultSystemPrompt?: string;
1139
- order?: number;
1140
- parentThreadIds?: Array<string>;
1141
- status: "active" | "archived";
1142
- summary?: string;
1143
- title?: string;
1144
- userId?: string;
1145
- } | null
1146
- >;
1147
1120
  getThreadMessages: FunctionReference<
1148
1121
  "query",
1149
1122
  "public",
1150
- {
1151
- isTool?: boolean;
1152
- order?: "asc" | "desc";
1153
- paginationOpts?: {
1154
- cursor: string | null;
1155
- endCursor?: string | null;
1156
- id?: number;
1157
- maximumBytesRead?: number;
1158
- maximumRowsRead?: number;
1159
- numItems: number;
1160
- };
1161
- parentMessageId?: string;
1162
- statuses?: Array<"pending" | "success" | "failed">;
1163
- threadId: string;
1164
- },
1123
+ { deprecated: "Use listMessagesByThreadId instead" },
1165
1124
  {
1166
1125
  continueCursor: string;
1167
1126
  isDone: boolean;
@@ -1322,10 +1281,13 @@ export type Mounts = {
1322
1281
  splitCursor?: string | null;
1323
1282
  }
1324
1283
  >;
1325
- getThreadsByUserId: FunctionReference<
1284
+ listMessagesByThreadId: FunctionReference<
1326
1285
  "query",
1327
1286
  "public",
1328
1287
  {
1288
+ beforeMessageId?: string;
1289
+ excludeToolMessages?: boolean;
1290
+ isTool?: "use excludeToolMessages instead of this";
1329
1291
  order?: "asc" | "desc";
1330
1292
  paginationOpts?: {
1331
1293
  cursor: string | null;
@@ -1335,7 +1297,8 @@ export type Mounts = {
1335
1297
  maximumRowsRead?: number;
1336
1298
  numItems: number;
1337
1299
  };
1338
- userId: string;
1300
+ statuses?: Array<"pending" | "success" | "failed">;
1301
+ threadId: string;
1339
1302
  },
1340
1303
  {
1341
1304
  continueCursor: string;
@@ -1343,13 +1306,155 @@ export type Mounts = {
1343
1306
  page: Array<{
1344
1307
  _creationTime: number;
1345
1308
  _id: string;
1346
- defaultSystemPrompt?: string;
1347
- order?: number;
1348
- parentThreadIds?: Array<string>;
1349
- status: "active" | "archived";
1350
- summary?: string;
1351
- title?: string;
1309
+ agentName?: string;
1310
+ embeddingId?:
1311
+ | string
1312
+ | string
1313
+ | string
1314
+ | string
1315
+ | string
1316
+ | string
1317
+ | string
1318
+ | string
1319
+ | string;
1320
+ error?: string;
1321
+ fileId?: string;
1322
+ finishReason?:
1323
+ | "stop"
1324
+ | "length"
1325
+ | "content-filter"
1326
+ | "tool-calls"
1327
+ | "error"
1328
+ | "other"
1329
+ | "unknown";
1330
+ id?: string;
1331
+ message?:
1332
+ | {
1333
+ content:
1334
+ | string
1335
+ | Array<
1336
+ | {
1337
+ experimental_providerMetadata?: Record<string, any>;
1338
+ providerOptions?: Record<string, any>;
1339
+ text: string;
1340
+ type: "text";
1341
+ }
1342
+ | {
1343
+ experimental_providerMetadata?: Record<string, any>;
1344
+ image: string | ArrayBuffer;
1345
+ mimeType?: string;
1346
+ providerOptions?: Record<string, any>;
1347
+ type: "image";
1348
+ }
1349
+ | {
1350
+ data: string | ArrayBuffer;
1351
+ experimental_providerMetadata?: Record<string, any>;
1352
+ mimeType: string;
1353
+ providerOptions?: Record<string, any>;
1354
+ type: "file";
1355
+ }
1356
+ >;
1357
+ experimental_providerMetadata?: Record<string, any>;
1358
+ providerOptions?: Record<string, any>;
1359
+ role: "user";
1360
+ }
1361
+ | {
1362
+ content:
1363
+ | string
1364
+ | Array<
1365
+ | {
1366
+ experimental_providerMetadata?: Record<string, any>;
1367
+ providerOptions?: Record<string, any>;
1368
+ text: string;
1369
+ type: "text";
1370
+ }
1371
+ | {
1372
+ data: string | ArrayBuffer;
1373
+ experimental_providerMetadata?: Record<string, any>;
1374
+ mimeType: string;
1375
+ providerOptions?: Record<string, any>;
1376
+ type: "file";
1377
+ }
1378
+ | {
1379
+ experimental_providerMetadata?: Record<string, any>;
1380
+ providerOptions?: Record<string, any>;
1381
+ text: string;
1382
+ type: "reasoning";
1383
+ }
1384
+ | {
1385
+ data: string;
1386
+ experimental_providerMetadata?: Record<string, any>;
1387
+ providerOptions?: Record<string, any>;
1388
+ type: "redacted-reasoning";
1389
+ }
1390
+ | {
1391
+ args: any;
1392
+ experimental_providerMetadata?: Record<string, any>;
1393
+ providerOptions?: Record<string, any>;
1394
+ toolCallId: string;
1395
+ toolName: string;
1396
+ type: "tool-call";
1397
+ }
1398
+ >;
1399
+ experimental_providerMetadata?: Record<string, any>;
1400
+ providerOptions?: Record<string, any>;
1401
+ role: "assistant";
1402
+ }
1403
+ | {
1404
+ content: Array<{
1405
+ args?: any;
1406
+ experimental_content?: Array<
1407
+ | { text: string; type: "text" }
1408
+ | { data: string; mimeType?: string; type: "image" }
1409
+ >;
1410
+ experimental_providerMetadata?: Record<string, any>;
1411
+ isError?: boolean;
1412
+ providerOptions?: Record<string, any>;
1413
+ result: any;
1414
+ toolCallId: string;
1415
+ toolName: string;
1416
+ type: "tool-result";
1417
+ }>;
1418
+ experimental_providerMetadata?: Record<string, any>;
1419
+ providerOptions?: Record<string, any>;
1420
+ role: "tool";
1421
+ }
1422
+ | {
1423
+ content: string;
1424
+ experimental_providerMetadata?: Record<string, any>;
1425
+ providerOptions?: Record<string, any>;
1426
+ role: "system";
1427
+ };
1428
+ model?: string;
1429
+ order: number;
1430
+ parentMessageId?: string;
1431
+ provider?: string;
1432
+ providerMetadata?: Record<string, any>;
1433
+ reasoning?: string;
1434
+ sources?: Array<{
1435
+ id: string;
1436
+ providerMetadata?: Record<string, Record<string, any>>;
1437
+ sourceType: "url";
1438
+ title?: string;
1439
+ url: string;
1440
+ }>;
1441
+ status: "pending" | "success" | "failed";
1442
+ stepId?: string;
1443
+ stepOrder: number;
1444
+ text?: string;
1445
+ threadId: string;
1446
+ tool: boolean;
1447
+ usage?: {
1448
+ completionTokens: number;
1449
+ promptTokens: number;
1450
+ totalTokens: number;
1451
+ };
1352
1452
  userId?: string;
1453
+ warnings?: Array<
1454
+ | { details?: string; setting: string; type: "unsupported-setting" }
1455
+ | { details?: string; tool: any; type: "unsupported-tool" }
1456
+ | { message: string; type: "other" }
1457
+ >;
1353
1458
  }>;
1354
1459
  pageStatus?: "SplitRecommended" | "SplitRequired" | null;
1355
1460
  splitCursor?: string | null;
@@ -1365,9 +1470,9 @@ export type Mounts = {
1365
1470
  "action",
1366
1471
  "public",
1367
1472
  {
1473
+ beforeMessageId?: string;
1368
1474
  limit: number;
1369
1475
  messageRange?: { after: number; before: number };
1370
- parentMessageId?: string;
1371
1476
  text?: string;
1372
1477
  threadId?: string;
1373
1478
  userId?: string;
@@ -1687,12 +1792,87 @@ export type Mounts = {
1687
1792
  >;
1688
1793
  }>
1689
1794
  >;
1795
+ };
1796
+ threads: {
1797
+ createThread: FunctionReference<
1798
+ "mutation",
1799
+ "public",
1800
+ {
1801
+ defaultSystemPrompt?: string;
1802
+ parentThreadIds?: Array<string>;
1803
+ summary?: string;
1804
+ title?: string;
1805
+ userId?: string;
1806
+ },
1807
+ {
1808
+ _creationTime: number;
1809
+ _id: string;
1810
+ status: "active" | "archived";
1811
+ summary?: string;
1812
+ title?: string;
1813
+ userId?: string;
1814
+ }
1815
+ >;
1816
+ deleteAllForThreadIdAsync: FunctionReference<
1817
+ "mutation",
1818
+ "public",
1819
+ { cursor?: string; limit?: number; threadId: string },
1820
+ { cursor: string; isDone: boolean }
1821
+ >;
1822
+ deleteAllForThreadIdSync: FunctionReference<
1823
+ "action",
1824
+ "public",
1825
+ { cursor?: string; limit?: number; threadId: string },
1826
+ null
1827
+ >;
1828
+ getThread: FunctionReference<
1829
+ "query",
1830
+ "public",
1831
+ { threadId: string },
1832
+ {
1833
+ _creationTime: number;
1834
+ _id: string;
1835
+ status: "active" | "archived";
1836
+ summary?: string;
1837
+ title?: string;
1838
+ userId?: string;
1839
+ } | null
1840
+ >;
1841
+ listThreadsByUserId: FunctionReference<
1842
+ "query",
1843
+ "public",
1844
+ {
1845
+ order?: "asc" | "desc";
1846
+ paginationOpts?: {
1847
+ cursor: string | null;
1848
+ endCursor?: string | null;
1849
+ id?: number;
1850
+ maximumBytesRead?: number;
1851
+ maximumRowsRead?: number;
1852
+ numItems: number;
1853
+ };
1854
+ userId: string;
1855
+ },
1856
+ {
1857
+ continueCursor: string;
1858
+ isDone: boolean;
1859
+ page: Array<{
1860
+ _creationTime: number;
1861
+ _id: string;
1862
+ status: "active" | "archived";
1863
+ summary?: string;
1864
+ title?: string;
1865
+ userId?: string;
1866
+ }>;
1867
+ pageStatus?: "SplitRecommended" | "SplitRequired" | null;
1868
+ splitCursor?: string | null;
1869
+ }
1870
+ >;
1690
1871
  updateThread: FunctionReference<
1691
1872
  "mutation",
1692
1873
  "public",
1693
1874
  {
1694
1875
  patch: {
1695
- defaultSystemPrompt?: string;
1696
1876
  status?: "active" | "archived";
1697
1877
  summary?: string;
1698
1878
  title?: string;
@@ -1702,9 +1882,6 @@ export type Mounts = {
1702
1882
  {
1703
1883
  _creationTime: number;
1704
1884
  _id: string;
1705
- defaultSystemPrompt?: string;
1706
- order?: number;
1707
- parentThreadIds?: Array<string>;
1708
1885
  status: "active" | "archived";
1709
1886
  summary?: string;
1710
1887
  title?: string;
@@ -1712,6 +1889,41 @@ export type Mounts = {
1712
1889
  }
1713
1890
  >;
1714
1891
  };
1892
+ users: {
1893
+ deleteAllForUserId: FunctionReference<
1894
+ "action",
1895
+ "public",
1896
+ { userId: string },
1897
+ null
1898
+ >;
1899
+ deleteAllForUserIdAsync: FunctionReference<
1900
+ "mutation",
1901
+ "public",
1902
+ { userId: string },
1903
+ boolean
1904
+ >;
1905
+ listUsersWithThreads: FunctionReference<
1906
+ "query",
1907
+ "public",
1908
+ {
1909
+ paginationOpts: {
1910
+ cursor: string | null;
1911
+ endCursor?: string | null;
1912
+ id?: number;
1913
+ maximumBytesRead?: number;
1914
+ maximumRowsRead?: number;
1915
+ numItems: number;
1916
+ };
1917
+ },
1918
+ {
1919
+ continueCursor: string;
1920
+ isDone: boolean;
1921
+ page: Array<string>;
1922
+ pageStatus?: "SplitRecommended" | "SplitRequired" | null;
1923
+ splitCursor?: string | null;
1924
+ }
1925
+ >;
1926
+ };
1715
1927
  vector: {
1716
1928
  index: {
1717
1929
  deleteBatch: FunctionReference<
@@ -0,0 +1,74 @@
1
+ import { v } from "convex/values";
2
+ import { mutation, query } from "./_generated/server";
3
+
4
+ export const issue = mutation({
5
+ args: {
6
+ name: v.optional(v.string()),
7
+ },
8
+ handler: async (ctx, args) => {
9
+ if (args.name) {
10
+ const existingApiKey = await ctx.db
11
+ .query("apiKeys")
12
+ .withIndex("name", (q) => q.eq("name", args.name))
13
+ .first();
14
+ if (existingApiKey) {
15
+ console.warn(`API key ${args.name} already exists, deleting...`);
16
+ await ctx.db.delete(existingApiKey._id);
17
+ }
18
+ }
19
+ const apiKey = await ctx.db.insert("apiKeys", args);
20
+ return apiKey;
21
+ },
22
+ returns: v.id("apiKeys"),
23
+ });
24
+
25
+ export const validate = query({
26
+ args: {
27
+ apiKey: v.id("apiKeys"),
28
+ },
29
+ handler: async (ctx, args) => {
30
+ const apiKey = await ctx.db.get(args.apiKey);
31
+ if (!apiKey) {
32
+ throw new Error("Invalid API key");
33
+ }
34
+ return true;
35
+ },
36
+ returns: v.boolean(),
37
+ });
38
+
39
+ export const destroy = mutation({
40
+ args: v.object({
41
+ apiKey: v.optional(v.id("apiKeys")),
42
+ name: v.optional(v.string()),
43
+ }),
44
+ handler: async (ctx, args) => {
45
+ if (args.apiKey) {
46
+ const apiKey = await ctx.db.get(args.apiKey);
47
+ if (!apiKey) {
48
+ return "missing";
49
+ }
50
+ if (apiKey.name !== args.name) {
51
+ return "name mismatch";
52
+ }
53
+ await ctx.db.delete(args.apiKey);
54
+ } else if (args.name) {
55
+ const apiKey = await ctx.db
56
+ .query("apiKeys")
57
+ .withIndex("name", (q) => q.eq("name", args.name))
58
+ .first();
59
+ if (!apiKey) {
60
+ return "missing";
61
+ }
62
+ await ctx.db.delete(apiKey._id);
63
+ } else {
64
+ return "must provide either apiKey or name";
65
+ }
66
+ return "deleted";
67
+ },
68
+ returns: v.union(
69
+ v.literal("missing"),
70
+ v.literal("deleted"),
71
+ v.literal("name mismatch"),
72
+ v.literal("must provide either apiKey or name")
73
+ ),
74
+ });
@@ -0,0 +1,72 @@
1
+ import { paginator } from "convex-helpers/server/pagination";
2
+ import { mutation, MutationCtx, query } from "./_generated/server.js";
3
+ import { schema, v } from "./schema.js";
4
+ import { Id } from "./_generated/dataModel.js";
5
+
6
+ export const addFile = mutation({
7
+ args: {
8
+ storageId: v.string(),
9
+ hash: v.string(),
10
+ },
11
+ handler: addFileHandler,
12
+ returns: v.id("files"),
13
+ });
14
+
15
+ export async function addFileHandler(
16
+ ctx: MutationCtx,
17
+ args: { storageId: string; hash: string }
18
+ ) {
19
+ const fileId = await ctx.db.insert("files", {
20
+ storageId: args.storageId,
21
+ hash: args.hash,
22
+ refcount: 1,
23
+ });
24
+ return fileId;
25
+ }
26
+
27
+ export const resuseFile = mutation({
28
+ args: {
29
+ fileId: v.id("files"),
30
+ },
31
+ handler: reuseFileHandler,
32
+ returns: v.null(),
33
+ });
34
+
35
+ export async function reuseFileHandler(
36
+ ctx: MutationCtx,
37
+ args: { fileId: Id<"files"> }
38
+ ) {
39
+ const file = await ctx.db.get(args.fileId);
40
+ if (!file) {
41
+ throw new Error("File not found");
42
+ }
43
+ await ctx.db.patch(args.fileId, {
44
+ refcount: file.refcount + 1,
45
+ });
46
+ }
47
+
48
+ export const getFilesToDelete = query({
49
+ args: {
50
+ cursor: v.optional(v.string()),
51
+ limit: v.optional(v.number()),
52
+ },
53
+ handler: async (ctx, args) => {
54
+ const files = await paginator(ctx.db, schema)
55
+ .query("files")
56
+ .withIndex("refcount", (q) => q.eq("refcount", 0))
57
+ .paginate({
58
+ numItems: args.limit ?? 100,
59
+ cursor: args.cursor ?? null,
60
+ });
61
+ return {
62
+ files: files.page,
63
+ continueCursor: files.continueCursor,
64
+ isDone: files.isDone,
65
+ };
66
+ },
67
+ returns: v.object({
68
+ files: v.array(v.doc("files")),
69
+ continueCursor: v.string(),
70
+ isDone: v.boolean(),
71
+ }),
72
+ });