@ganju/utils 0.0.14 → 0.0.16

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 (111) hide show
  1. package/dist/channelCustomer.d.ts +99 -0
  2. package/dist/channelCustomer.d.ts.map +1 -0
  3. package/dist/channelCustomer.js +533 -0
  4. package/dist/channelDebounce.d.ts +7 -0
  5. package/dist/channelDebounce.d.ts.map +1 -1
  6. package/dist/chunkOverlap.d.ts +2 -0
  7. package/dist/chunkOverlap.d.ts.map +1 -0
  8. package/dist/chunkOverlap.js +9 -0
  9. package/dist/chunking.d.ts.map +1 -1
  10. package/dist/chunking.js +24 -4
  11. package/dist/citations.d.ts +28 -0
  12. package/dist/citations.d.ts.map +1 -0
  13. package/dist/citations.js +111 -0
  14. package/dist/constants.d.ts +49 -0
  15. package/dist/constants.d.ts.map +1 -1
  16. package/dist/constants.js +202 -17
  17. package/dist/data.d.ts +9 -0
  18. package/dist/data.d.ts.map +1 -0
  19. package/dist/data.js +78 -0
  20. package/dist/dataApi.d.ts +511 -0
  21. package/dist/dataApi.d.ts.map +1 -0
  22. package/dist/dataApi.js +355 -0
  23. package/dist/dataCompiler.d.ts +68 -0
  24. package/dist/dataCompiler.d.ts.map +1 -0
  25. package/dist/dataCompiler.js +726 -0
  26. package/dist/dataDdl.d.ts +29 -0
  27. package/dist/dataDdl.d.ts.map +1 -0
  28. package/dist/dataDdl.js +354 -0
  29. package/dist/dataEngine.d.ts +143 -0
  30. package/dist/dataEngine.d.ts.map +1 -0
  31. package/dist/dataEngine.js +2022 -0
  32. package/dist/dataIdentifiers.d.ts +8 -0
  33. package/dist/dataIdentifiers.d.ts.map +1 -0
  34. package/dist/dataIdentifiers.js +55 -0
  35. package/dist/dataImport.d.ts +77 -0
  36. package/dist/dataImport.d.ts.map +1 -0
  37. package/dist/dataImport.js +450 -0
  38. package/dist/dataRpc.d.ts +131 -0
  39. package/dist/dataRpc.d.ts.map +1 -0
  40. package/dist/dataRpc.js +2 -0
  41. package/dist/dataTypes.d.ts +157 -0
  42. package/dist/dataTypes.d.ts.map +1 -0
  43. package/dist/dataTypes.js +160 -0
  44. package/dist/index.d.ts +570 -36
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +72 -0
  47. package/dist/jsonSchemaToZodShape.d.ts +5 -1
  48. package/dist/jsonSchemaToZodShape.d.ts.map +1 -1
  49. package/dist/jsonSchemaToZodShape.js +21 -9
  50. package/dist/oauth.d.ts +14 -0
  51. package/dist/oauth.d.ts.map +1 -1
  52. package/dist/oauth.js +42 -2
  53. package/dist/pagination.d.ts +47 -0
  54. package/dist/pagination.d.ts.map +1 -0
  55. package/dist/pagination.js +160 -0
  56. package/dist/processQueueBatch.d.ts +6 -1
  57. package/dist/processQueueBatch.d.ts.map +1 -1
  58. package/dist/processQueueBatch.js +23 -10
  59. package/dist/queueFailure.d.ts +14 -0
  60. package/dist/queueFailure.d.ts.map +1 -0
  61. package/dist/queueFailure.js +43 -0
  62. package/dist/resourceRerank.d.ts +3 -2
  63. package/dist/resourceRerank.d.ts.map +1 -1
  64. package/dist/resourceRerank.js +8 -3
  65. package/dist/schema.d.ts +374 -29
  66. package/dist/schema.d.ts.map +1 -1
  67. package/dist/schema.js +290 -6
  68. package/dist/ssrf.d.ts +1 -0
  69. package/dist/ssrf.d.ts.map +1 -1
  70. package/dist/ssrf.js +48 -12
  71. package/dist/toolConfirmation.d.ts +48 -0
  72. package/dist/toolConfirmation.d.ts.map +1 -1
  73. package/dist/toolConfirmation.js +75 -1
  74. package/dist/toolCount.d.ts +13 -0
  75. package/dist/toolCount.d.ts.map +1 -0
  76. package/dist/toolCount.js +45 -0
  77. package/dist/toolLint.d.ts +1 -1
  78. package/dist/toolLint.d.ts.map +1 -1
  79. package/dist/toolLint.js +20 -0
  80. package/dist/untrustedContent.d.ts +135 -0
  81. package/dist/untrustedContent.d.ts.map +1 -0
  82. package/dist/untrustedContent.js +402 -0
  83. package/package.json +17 -1
  84. package/src/channelCustomer.ts +604 -0
  85. package/src/channelDebounce.ts +17 -0
  86. package/src/chunkOverlap.ts +6 -0
  87. package/src/chunking.ts +25 -4
  88. package/src/citations.ts +127 -0
  89. package/src/constants.ts +219 -17
  90. package/src/data.ts +74 -0
  91. package/src/dataApi.ts +428 -0
  92. package/src/dataCompiler.ts +948 -0
  93. package/src/dataDdl.ts +419 -0
  94. package/src/dataEngine.ts +2753 -0
  95. package/src/dataIdentifiers.ts +63 -0
  96. package/src/dataImport.ts +554 -0
  97. package/src/dataRpc.ts +121 -0
  98. package/src/dataTypes.ts +312 -0
  99. package/src/index.ts +156 -2
  100. package/src/jsonSchemaToZodShape.ts +31 -13
  101. package/src/oauth.ts +42 -1
  102. package/src/pagination.ts +193 -0
  103. package/src/processQueueBatch.ts +42 -12
  104. package/src/queueFailure.ts +63 -0
  105. package/src/resourceRerank.ts +10 -3
  106. package/src/schema.ts +346 -4
  107. package/src/ssrf.ts +40 -11
  108. package/src/toolConfirmation.ts +123 -0
  109. package/src/toolCount.ts +53 -0
  110. package/src/toolLint.ts +27 -0
  111. package/src/untrustedContent.ts +476 -0
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2xBxB,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgGrB,CAAC;AAyDN,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;iBAmCpB,CAAC;AAWH,QAAA,MAAM,kBAAkB;;;;;;;;;;iBA+CtB,CAAC;AAqCH,QAAA,MAAM,gBAAgB;;;;;kBAOX,CAAC;AAEZ,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAcpB,CAAC;AAYH,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgCxB,CAAC;AA4LH,QAAA,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4DpC,CAAC;AA4BL,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAkDzB,CAAC;AAuHH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6GlB,CAAC;AAGF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAG1E,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAIlE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAMtE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAGtE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAMtE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAIvE,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAC5C,OAAO,kCAAkC,CAC1C,CAAC;AAKF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IAIrB,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;CAChD;AAKD,MAAM,WAAW,0BAA0B;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAC1E;AAMD,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACzC,OAAO,CAAC,EAAE,wBAAwB,EAAE,CAAC;CACtC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA0hCxB,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgGrB,CAAC;AAyDN,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4CpB,CAAC;AAWH,QAAA,MAAM,kBAAkB;;;;;;;;;;iBA+CtB,CAAC;AAqCH,QAAA,MAAM,gBAAgB;;;;;kBAOX,CAAC;AAEZ,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAcpB,CAAC;AAYH,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgCxB,CAAC;AA2OH,QAAA,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4DpC,CAAC;AA4BL,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAkDzB,CAAC;AAuHH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4IlB,CAAC;AAGF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAG1E,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAIlE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAMtE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAGtE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAMtE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAIvE,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAC5C,OAAO,kCAAkC,CAC1C,CAAC;AAKF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IAIrB,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;CAChD;AAKD,MAAM,WAAW,0BAA0B;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAC1E;AAMD,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACzC,OAAO,CAAC,EAAE,wBAAwB,EAAE,CAAC;CACtC"}
package/dist/schema.js CHANGED
@@ -5,9 +5,12 @@ const zod_1 = require("zod");
5
5
  const constants_1 = require("./constants");
6
6
  const llmBaseUrl_1 = require("./llmBaseUrl");
7
7
  const slug_1 = require("./slug");
8
+ const ssrf_1 = require("./ssrf");
8
9
  const reservedToolName_1 = require("./reservedToolName");
9
10
  const slugifyTitle_1 = require("./slugifyTitle");
10
11
  const toolConfirmation_1 = require("./toolConfirmation");
12
+ const channelCustomer_1 = require("./channelCustomer");
13
+ const dataTypes_1 = require("./dataTypes");
11
14
  // A prompt title becomes a slash command; it must not collide with a command
12
15
  // the channel runner handles itself (e.g. `/link`).
13
16
  const PROMPT_TITLE = zod_1.z
@@ -149,6 +152,13 @@ const INVITATION_RESPOND = zod_1.z.object({
149
152
  userId: zod_1.z.uuid(),
150
153
  action: zod_1.z.enum(constants_1.constants.INVITATION_RESPONSES)
151
154
  });
155
+ const TOOL_APPROVAL_GET = zod_1.z.object({
156
+ approvalId: zod_1.z.uuid()
157
+ });
158
+ const TOOL_APPROVAL_DECIDE = zod_1.z.object({
159
+ approvalId: zod_1.z.uuid(),
160
+ decision: zod_1.z.enum(constants_1.constants.TOOL_APPROVAL_DECISIONS)
161
+ });
152
162
  const INVITATION_GET_BY_TOKEN = zod_1.z.object({
153
163
  token: zod_1.z.string().min(8).max(128)
154
164
  });
@@ -230,7 +240,8 @@ const ARTIFACT_CREATE_WEBSITE_VIEW = zod_1.z.object({
230
240
  title: zod_1.z.string().min(3).max(200),
231
241
  uri: zod_1.z
232
242
  .url('Enter a valid URL')
233
- .refine(v => /^https?:\/\//i.test(v), 'Only http and https URLs are supported'),
243
+ .refine(v => /^https?:\/\//i.test(v), 'Only http and https URLs are supported')
244
+ .refine(v => !(0, ssrf_1.isBlockedUrl)(v), "This address points to a private network and can't be crawled"),
234
245
  description: zod_1.z.string().optional(),
235
246
  maxPages: zod_1.z.number().int().min(1).max(constants_1.constants.CRAWL_MAX_PAGES_LIMIT),
236
247
  maxDepth: zod_1.z.number().int().min(0).max(constants_1.constants.CRAWL_MAX_DEPTH_LIMIT)
@@ -239,7 +250,8 @@ const ARTIFACT_CREATE_WEBSITE = zod_1.z.object({
239
250
  title: zod_1.z.string().min(3).max(200),
240
251
  uri: zod_1.z
241
252
  .url('Enter a valid URL')
242
- .refine(v => /^https?:\/\//i.test(v), 'Only http and https URLs are supported'),
253
+ .refine(v => /^https?:\/\//i.test(v), 'Only http and https URLs are supported')
254
+ .refine(v => !(0, ssrf_1.isBlockedUrl)(v), "This address points to a private network and can't be crawled"),
243
255
  description: zod_1.z.string().optional(),
244
256
  crawlConfig: zod_1.z.object({
245
257
  maxPages: zod_1.z.number().int().min(1).max(constants_1.constants.CRAWL_MAX_PAGES_LIMIT),
@@ -416,6 +428,183 @@ const ARTIFACT_REMOVE_RESOURCE = zod_1.z.object({
416
428
  userId: zod_1.z.uuid(),
417
429
  organizationId: zod_1.z.uuid()
418
430
  });
431
+ const DATA_DATABASE_GET = zod_1.z.object({
432
+ projectId: zod_1.z.uuid(),
433
+ userId: zod_1.z.uuid(),
434
+ organizationId: zod_1.z.uuid()
435
+ });
436
+ // The name is what the owner types to delete it; it defaults to the
437
+ // project's slug. `replaceDeleted` starts over while a deleted database is
438
+ // still in its grace period, giving up the chance to restore it.
439
+ const DATA_DATABASE_CREATE = DATA_DATABASE_GET.extend({
440
+ name: zod_1.z.string().trim().min(1).max(100).optional(),
441
+ replaceDeleted: zod_1.z.boolean().optional()
442
+ });
443
+ const DATA_DATABASE_DELETE = DATA_DATABASE_GET.extend({
444
+ confirmName: zod_1.z.string().min(1)
445
+ });
446
+ // The bodies and query strings of the Data API. Each one is what a client
447
+ // sends; the route schemas below add the path's ids. The database object
448
+ // checks every rule again (names, types, relations), so these describe the
449
+ // shape and leave the meaning to it.
450
+ const DATA_IDENTIFIER = zod_1.z.string().min(1).max(63);
451
+ const DATA_DEFAULT_VALUE = zod_1.z.union([
452
+ zod_1.z.string(),
453
+ zod_1.z.number(),
454
+ zod_1.z.boolean(),
455
+ zod_1.z.null()
456
+ ]);
457
+ const DATA_TEXT = (max) => zod_1.z.string().max(max).nullable().optional();
458
+ const DATA_COLUMN_INPUT = zod_1.z.strictObject({
459
+ name: DATA_IDENTIFIER,
460
+ type: zod_1.z.enum(dataTypes_1.DATA_COLUMN_TYPES),
461
+ label: DATA_TEXT(dataTypes_1.DATA_MAX_LABEL),
462
+ description: DATA_TEXT(dataTypes_1.DATA_MAX_DESCRIPTION),
463
+ required: zod_1.z.boolean().optional(),
464
+ unique: zod_1.z.boolean().optional(),
465
+ filterable: zod_1.z.boolean().optional(),
466
+ searchable: zod_1.z.boolean().optional(),
467
+ personal: zod_1.z.boolean().optional(),
468
+ values: zod_1.z.array(zod_1.z.string().min(1)).max(dataTypes_1.DATA_MAX_ENUM_VALUES).optional(),
469
+ table: DATA_IDENTIFIER.optional(),
470
+ onDelete: zod_1.z.enum(dataTypes_1.DATA_ON_DELETE).optional(),
471
+ min: zod_1.z.number().nullable().optional(),
472
+ default: DATA_DEFAULT_VALUE.optional()
473
+ });
474
+ // The CLI's schema file holds a list of these.
475
+ const DATA_TABLE_INPUT = zod_1.z.strictObject({
476
+ name: DATA_IDENTIFIER,
477
+ label: DATA_TEXT(dataTypes_1.DATA_MAX_LABEL),
478
+ description: DATA_TEXT(dataTypes_1.DATA_MAX_DESCRIPTION),
479
+ displayColumn: DATA_IDENTIFIER.nullable().optional(),
480
+ access: zod_1.z.enum(dataTypes_1.DATA_ACCESS_LEVELS).optional(),
481
+ customerScoped: zod_1.z.boolean().optional(),
482
+ history: zod_1.z.boolean().optional(),
483
+ columns: zod_1.z.array(DATA_COLUMN_INPUT).max(dataTypes_1.DATA_MAX_COLUMNS)
484
+ });
485
+ const DATA_TABLE_PATCH = DATA_TABLE_INPUT.omit({ columns: true }).partial();
486
+ // A null puts the setting back to its default.
487
+ const DATA_COLUMN_PATCH = DATA_COLUMN_INPUT.partial();
488
+ const DATA_TABLE_DROP_BODY = zod_1.z.strictObject({ confirmName: zod_1.z.string().min(1) });
489
+ const DATA_ROW_VALUES = zod_1.z.record(zod_1.z.string(), zod_1.z.unknown());
490
+ // A JSON value carried in a query string, e.g. `where={"status":"open"}`.
491
+ const DATA_JSON_PARAM = zod_1.z.string().transform((text, ctx) => {
492
+ try {
493
+ return JSON.parse(text);
494
+ }
495
+ catch {
496
+ ctx.addIssue({
497
+ code: 'custom',
498
+ message: 'This is JSON, e.g. {"status":"open"}'
499
+ });
500
+ return zod_1.z.NEVER;
501
+ }
502
+ });
503
+ // A comma-separated list in a query string: `sort=-created_at,name`.
504
+ const DATA_LIST_PARAM = zod_1.z.string().transform(text => text
505
+ .split(',')
506
+ .map(item => item.trim())
507
+ .filter(Boolean));
508
+ const DATA_ROW_LIST_QUERY = zod_1.z.strictObject({
509
+ where: DATA_JSON_PARAM.optional(),
510
+ sort: DATA_LIST_PARAM.optional(),
511
+ include: DATA_LIST_PARAM.optional(),
512
+ limit: zod_1.z.coerce.number().int().min(1).max(dataTypes_1.DATA_MAX_PAGE).optional(),
513
+ cursor: zod_1.z.string().max(2000).optional(),
514
+ q: zod_1.z.string().max(500).optional(),
515
+ timeZone: zod_1.z.string().max(64).optional()
516
+ });
517
+ const DATA_ROW_GET_QUERY = DATA_ROW_LIST_QUERY.pick({
518
+ include: true,
519
+ timeZone: true
520
+ });
521
+ const DATA_ROW_CREATE_BODY = zod_1.z.union([
522
+ zod_1.z.strictObject({ values: DATA_ROW_VALUES }),
523
+ zod_1.z.strictObject({
524
+ rows: zod_1.z.array(DATA_ROW_VALUES).min(1).max(dataTypes_1.DATA_MAX_INSERT_ROWS)
525
+ })
526
+ ]);
527
+ const DATA_ROW_VERSION = zod_1.z.number().int().min(1);
528
+ // `set` takes values, or relative changes such as { "stock": { "decrement": 2 } }.
529
+ const DATA_ROW_UPDATE_BODY = zod_1.z.strictObject({
530
+ set: DATA_ROW_VALUES,
531
+ version: DATA_ROW_VERSION.optional()
532
+ });
533
+ const DATA_ROW_DELETE_BODY = zod_1.z.strictObject({
534
+ version: DATA_ROW_VERSION.optional()
535
+ });
536
+ const DATA_ROW_ID = zod_1.z.coerce.number().int().min(1);
537
+ // Without `ids`, every row of the table.
538
+ const DATA_DELETE_PREVIEW_BODY = zod_1.z.strictObject({
539
+ ids: zod_1.z.array(zod_1.z.number().int().min(1)).min(1).max(dataTypes_1.DATA_IMPACT_MAX_IDS).optional()
540
+ });
541
+ const DATA_WRITE_TARGET = {
542
+ table: DATA_IDENTIFIER,
543
+ id: zod_1.z
544
+ .union([
545
+ zod_1.z.number().int().min(1),
546
+ zod_1.z.strictObject({ $ref: zod_1.z.number().int().min(0) })
547
+ ])
548
+ .optional(),
549
+ where: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
550
+ expect: zod_1.z.number().int().min(0).optional(),
551
+ version: DATA_ROW_VERSION.optional()
552
+ };
553
+ // Applied together or not at all. A later step can use an earlier insert's
554
+ // id as { "$ref": <step> }.
555
+ const DATA_WRITE_OPERATION = zod_1.z.discriminatedUnion('op', [
556
+ zod_1.z.strictObject({
557
+ op: zod_1.z.literal('insert'),
558
+ table: DATA_IDENTIFIER,
559
+ values: DATA_ROW_VALUES.optional(),
560
+ rows: zod_1.z.array(DATA_ROW_VALUES).min(1).max(dataTypes_1.DATA_MAX_INSERT_ROWS).optional()
561
+ }),
562
+ zod_1.z.strictObject({
563
+ op: zod_1.z.literal('update'),
564
+ ...DATA_WRITE_TARGET,
565
+ set: DATA_ROW_VALUES
566
+ }),
567
+ zod_1.z.strictObject({ op: zod_1.z.literal('delete'), ...DATA_WRITE_TARGET })
568
+ ]);
569
+ const DATA_WRITE_BODY = zod_1.z.strictObject({
570
+ operations: zod_1.z
571
+ .array(DATA_WRITE_OPERATION)
572
+ .min(1)
573
+ .max(dataTypes_1.DATA_MAX_WRITE_OPERATIONS)
574
+ });
575
+ const DATA_ROW_HISTORY_QUERY = zod_1.z.strictObject({
576
+ limit: zod_1.z.coerce.number().int().min(1).max(100).optional(),
577
+ cursor: zod_1.z.coerce.number().int().min(1).optional(),
578
+ timeZone: zod_1.z.string().max(64).optional()
579
+ });
580
+ // A time within the last 30 days, or a bookmark this API handed out (a drop,
581
+ // a type change, or the restore to undo).
582
+ const DATA_RESTORE_POINT_BODY = zod_1.z.union([
583
+ zod_1.z.strictObject({
584
+ timestamp: zod_1.z.union([zod_1.z.iso.datetime({ offset: true }), zod_1.z.number().int()])
585
+ }),
586
+ zod_1.z.strictObject({ bookmark: zod_1.z.string().min(1).max(200) })
587
+ ]);
588
+ const DATA_EXPORT_BODY = zod_1.z.strictObject({
589
+ format: zod_1.z.enum(['jsonl', 'csv']).optional()
590
+ });
591
+ const DATA_EXPORT_QUERY = zod_1.z.strictObject({
592
+ exportId: zod_1.z.uuid().optional()
593
+ });
594
+ // Without `table`, the export's schema.json.
595
+ const DATA_EXPORT_FILE_QUERY = zod_1.z.strictObject({
596
+ exportId: zod_1.z.uuid(),
597
+ table: DATA_IDENTIFIER.optional()
598
+ });
599
+ const DATA_CHANGE_LIST_QUERY = zod_1.z.strictObject({
600
+ limit: zod_1.z.coerce.number().int().min(1).max(100).optional(),
601
+ cursor: zod_1.z.uuid().optional()
602
+ });
603
+ const DATA_TABLE_PARAMS = DATA_DATABASE_GET.extend({ table: DATA_IDENTIFIER });
604
+ const DATA_COLUMN_PARAMS = DATA_TABLE_PARAMS.extend({
605
+ column: DATA_IDENTIFIER
606
+ });
607
+ const DATA_ROW_PARAMS = DATA_TABLE_PARAMS.extend({ id: DATA_ROW_ID });
419
608
  const ARTIFACT_UPLOAD_RESOURCE_FILE = zod_1.z.object({
420
609
  resourceId: zod_1.z.uuid(),
421
610
  projectId: zod_1.z.uuid(),
@@ -600,18 +789,27 @@ const ORGANIZATION_UPDATE_LLM_VIEW = refineUpdateBaseUrl(ORGANIZATION_UPDATE_LLM
600
789
  userId: true,
601
790
  organizationId: true
602
791
  }));
603
- // `channel.config` is an open bag, so this stays loose — it only pins down the
604
- // keys we actually read, and passes everything else through untouched.
792
+ // The channel settings an owner can write. Strict: a typo or a setting that
793
+ // no longer exists is refused rather than stored, where nothing would read it.
605
794
  // `debounceMs` is how long a burst from one participant is buffered before the
606
795
  // agent answers it as a single turn; 0 disables buffering.
607
- const CHANNEL_CONFIG = zod_1.z.looseObject({
796
+ const CHANNEL_CONFIG = zod_1.z.strictObject({
608
797
  debounceMs: zod_1.z
609
798
  .number()
610
799
  .int()
611
800
  .refine(value => value === constants_1.constants.CHANNEL_DEBOUNCE_DISABLED ||
612
801
  (value >= constants_1.constants.CHANNEL_DEBOUNCE_MIN_MS &&
613
802
  value <= constants_1.constants.CHANNEL_DEBOUNCE_MAX_MS), `debounceMs must be 0 (disabled) or between ${constants_1.constants.CHANNEL_DEBOUNCE_MIN_MS} and ${constants_1.constants.CHANNEL_DEBOUNCE_MAX_MS} ms`)
614
- .optional()
803
+ .optional(),
804
+ // Replies one customer gets in 24 hours; 0 turns the limit off.
805
+ participantDailyLimit: zod_1.z
806
+ .number()
807
+ .int()
808
+ .min(channelCustomer_1.PARTICIPANT_DAILY_LIMIT_OFF)
809
+ .max(channelCustomer_1.PARTICIPANT_DAILY_LIMIT_MAX)
810
+ .optional(),
811
+ // Remember each customer's name, address, allergies and dates.
812
+ participantMemory: zod_1.z.boolean().optional()
615
813
  });
616
814
  const CHANNEL_CREATE = zod_1.z.object({
617
815
  platform: zod_1.z.enum(constants_1.constants.CHANNEL_PLATFORMS),
@@ -626,6 +824,9 @@ const CHANNEL_UPDATE = zod_1.z.object({
626
824
  channelId: zod_1.z.uuid(),
627
825
  status: zod_1.z.enum(constants_1.constants.CHANNEL_STATUS).optional(),
628
826
  config: CHANNEL_CONFIG.optional(),
827
+ // Keys to change on the stored config, merged by the database, so two
828
+ // settings saved at once don't overwrite each other.
829
+ configPatch: CHANNEL_CONFIG.optional(),
629
830
  credentials: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
630
831
  llmId: zod_1.z.uuid().nullable().optional(),
631
832
  projectId: zod_1.z.uuid(),
@@ -827,6 +1028,15 @@ const MCP_PROXY_CONFIG = zod_1.z.object({
827
1028
  allowedResources: zod_1.z.array(zod_1.z.string().min(1).max(2048)).max(500).optional(),
828
1029
  allowedPrompts: zod_1.z.array(zod_1.z.string().min(1).max(256)).max(500).optional(),
829
1030
  auth: MCP_PROXY_AUTH.default({ kind: constants_1.constants.MCP_PROXY_AUTH_KIND_NONE }),
1031
+ // Whether the remote's own readOnlyHint / destructiveHint decide which of its
1032
+ // tools are confirmed. Off (or absent), every proxied tool counts as
1033
+ // sensitive unless the owner marked it below: a server that labels its
1034
+ // delete "read-only" would otherwise skip the question.
1035
+ trustAnnotations: zod_1.z.boolean().optional(),
1036
+ // Remote tool names the owner marked as only reading. Read-only whatever the
1037
+ // remote says, trusted or not. Left optional rather than defaulted, so a
1038
+ // save that doesn't mention it keeps the stored marks.
1039
+ readOnlyTools: zod_1.z.array(zod_1.z.string().min(1).max(256)).max(500).optional(),
830
1040
  timeoutMs: zod_1.z
831
1041
  .number()
832
1042
  .int()
@@ -1080,6 +1290,49 @@ const ARTIFACT_CUSTOM_CODE_LIST_LOGS = zod_1.z.object({
1080
1290
  userId: zod_1.z.uuid(),
1081
1291
  organizationId: zod_1.z.uuid()
1082
1292
  });
1293
+ // Tool observability on the project home: per-tool health over a window.
1294
+ const PROJECT_TOOL_HEALTH = zod_1.z.object({
1295
+ days: zod_1.z.coerce
1296
+ .number()
1297
+ .int()
1298
+ .refine(days => constants_1.constants.OBSERVABILITY_RANGE_DAYS.includes(days), {
1299
+ message: 'Range is not valid'
1300
+ })
1301
+ .default(7),
1302
+ projectId: zod_1.z.uuid(),
1303
+ userId: zod_1.z.uuid(),
1304
+ organizationId: zod_1.z.uuid()
1305
+ });
1306
+ // The calls behind a row of that table, newest first. Paged by the id of the
1307
+ // last call shown, not its time: calls written in one insert share a
1308
+ // timestamp, and the client only sees it to the millisecond.
1309
+ const PROJECT_TOOL_CALLS = zod_1.z.object({
1310
+ tool: zod_1.z.string().min(1).max(256).optional(),
1311
+ status: zod_1.z.enum(['all', 'error']).default('all'),
1312
+ limit: zod_1.z.coerce
1313
+ .number()
1314
+ .int()
1315
+ .min(1)
1316
+ .max(constants_1.constants.OBSERVABILITY_CALLS_MAX_LIMIT)
1317
+ .default(constants_1.constants.OBSERVABILITY_CALLS_DEFAULT_LIMIT),
1318
+ after: zod_1.z.uuid().optional(),
1319
+ projectId: zod_1.z.uuid(),
1320
+ userId: zod_1.z.uuid(),
1321
+ organizationId: zod_1.z.uuid()
1322
+ });
1323
+ // One recorded call, whole, and the session timeline it belongs to.
1324
+ const PROJECT_TOOL_CALL = zod_1.z.object({
1325
+ requestId: zod_1.z.uuid(),
1326
+ projectId: zod_1.z.uuid(),
1327
+ userId: zod_1.z.uuid(),
1328
+ organizationId: zod_1.z.uuid()
1329
+ });
1330
+ const PROJECT_MCP_SESSION = zod_1.z.object({
1331
+ sessionId: zod_1.z.uuid(),
1332
+ projectId: zod_1.z.uuid(),
1333
+ userId: zod_1.z.uuid(),
1334
+ organizationId: zod_1.z.uuid()
1335
+ });
1083
1336
  // Reads the artifact's version history and which one is currently active.
1084
1337
  const ARTIFACT_CUSTOM_CODE_LIST_VERSIONS = zod_1.z.object({
1085
1338
  projectId: zod_1.z.uuid(),
@@ -1402,6 +1655,8 @@ exports.Schema = {
1402
1655
  PROJECT_INVITATION_REMOVE,
1403
1656
  INVITATION_RESPOND,
1404
1657
  INVITATION_GET_BY_TOKEN,
1658
+ TOOL_APPROVAL_GET,
1659
+ TOOL_APPROVAL_DECIDE,
1405
1660
  ORGANIZATION_MEMBER_LIST,
1406
1661
  ORGANIZATION_MEMBER_REMOVE,
1407
1662
  PROJECT_MEMBER_LIST,
@@ -1428,6 +1683,31 @@ exports.Schema = {
1428
1683
  ARTIFACT_UPDATE_RESOURCE_VIEW,
1429
1684
  ARTIFACT_GET_RESOURCE,
1430
1685
  ARTIFACT_GET_RESOURCE_BY_ID,
1686
+ DATA_DATABASE_GET,
1687
+ DATA_DATABASE_CREATE,
1688
+ DATA_DATABASE_DELETE,
1689
+ DATA_COLUMN_INPUT,
1690
+ DATA_TABLE_INPUT,
1691
+ DATA_TABLE_PATCH,
1692
+ DATA_COLUMN_PATCH,
1693
+ DATA_TABLE_DROP_BODY,
1694
+ DATA_ROW_LIST_QUERY,
1695
+ DATA_ROW_GET_QUERY,
1696
+ DATA_ROW_CREATE_BODY,
1697
+ DATA_ROW_UPDATE_BODY,
1698
+ DATA_ROW_DELETE_BODY,
1699
+ DATA_DELETE_PREVIEW_BODY,
1700
+ DATA_WRITE_OPERATION,
1701
+ DATA_WRITE_BODY,
1702
+ DATA_ROW_HISTORY_QUERY,
1703
+ DATA_RESTORE_POINT_BODY,
1704
+ DATA_EXPORT_BODY,
1705
+ DATA_EXPORT_QUERY,
1706
+ DATA_EXPORT_FILE_QUERY,
1707
+ DATA_CHANGE_LIST_QUERY,
1708
+ DATA_TABLE_PARAMS,
1709
+ DATA_COLUMN_PARAMS,
1710
+ DATA_ROW_PARAMS,
1431
1711
  ARTIFACT_REMOVE_RESOURCE,
1432
1712
  ARTIFACT_UPLOAD_RESOURCE_FILE,
1433
1713
  ARTIFACT_DOWNLOAD_RESOURCE_FILE,
@@ -1481,6 +1761,10 @@ exports.Schema = {
1481
1761
  ARTIFACT_CUSTOM_CODE_ROLLBACK,
1482
1762
  ARTIFACT_CUSTOM_CODE_LIST_LOGS,
1483
1763
  ARTIFACT_CUSTOM_CODE_LIST_VERSIONS,
1764
+ PROJECT_TOOL_HEALTH,
1765
+ PROJECT_TOOL_CALLS,
1766
+ PROJECT_TOOL_CALL,
1767
+ PROJECT_MCP_SESSION,
1484
1768
  CUSTOM_CODE_INVOKE_REQUEST,
1485
1769
  CUSTOM_CODE_INVOKE_RESPONSE,
1486
1770
  CUSTOM_CODE_BROKER_CONNECTION,
package/dist/ssrf.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export declare const ipv4InPrivateRange: (host: string) => boolean;
2
2
  export declare const isBlockedHost: (hostname: string) => boolean;
3
+ export declare const isBlockedUrl: (url: string) => boolean;
3
4
  //# sourceMappingURL=ssrf.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ssrf.d.ts","sourceRoot":"","sources":["../src/ssrf.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,OAWjD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,KAAG,OAehD,CAAC"}
1
+ {"version":3,"file":"ssrf.d.ts","sourceRoot":"","sources":["../src/ssrf.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,OAYjD,CAAC;AAeF,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,KAAG,OAiBhD,CAAC;AAIF,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,OAS1C,CAAC"}
package/dist/ssrf.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isBlockedHost = exports.ipv4InPrivateRange = void 0;
3
+ exports.isBlockedUrl = exports.isBlockedHost = exports.ipv4InPrivateRange = void 0;
4
4
  // Literal-host SSRF screening shared by the proxied tool dispatchers
5
- // (http-endpoint, mcp-proxy). The Workers runtime can't resolve DNS, so we can
5
+ // (http-endpoint, mcp-proxy) and the website crawler. The Workers runtime can't resolve DNS, so we can
6
6
  // only screen literal hosts and IPs (not DNS rebinding). Private/loopback/
7
7
  // link-local ranges are always rejected; callers may further narrow with an
8
8
  // allowlist.
@@ -22,25 +22,61 @@ const ipv4InPrivateRange = (host) => {
22
22
  return true; // private
23
23
  if (a === 172 && b >= 16 && b <= 31)
24
24
  return true; // private
25
+ if (a === 100 && b >= 64 && b <= 127)
26
+ return true; // carrier-grade NAT
25
27
  return false;
26
28
  };
27
29
  exports.ipv4InPrivateRange = ipv4InPrivateRange;
30
+ // The IPv4 address an IPv4-mapped IPv6 literal reaches. URL parsing rewrites
31
+ // `[::ffff:127.0.0.1]` to `[::ffff:7f00:1]`, so both spellings are read.
32
+ const mappedIpv4 = (host) => {
33
+ if (!host.startsWith('::ffff:'))
34
+ return null;
35
+ const rest = host.slice('::ffff:'.length);
36
+ if (rest.includes('.'))
37
+ return rest;
38
+ const match = /^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(rest);
39
+ if (!match)
40
+ return null;
41
+ const hi = Number.parseInt(match[1], 16);
42
+ const lo = Number.parseInt(match[2], 16);
43
+ return [hi >> 8, hi & 0xff, lo >> 8, lo & 0xff].join('.');
44
+ };
28
45
  const isBlockedHost = (hostname) => {
29
- const host = hostname.toLowerCase().replace(/^\[|\]$/g, '');
46
+ const host = hostname
47
+ .toLowerCase()
48
+ .replace(/^\[|\]$/g, '')
49
+ .replace(/\.$/, '');
30
50
  if (!host)
31
51
  return true;
32
52
  if (host === 'localhost' || host.endsWith('.localhost'))
33
53
  return true;
34
- if (host === '::1' || host === '::')
35
- return true;
36
- // IPv6 link-local (fe80::/10) and unique-local (fc00::/7).
37
- if (host.startsWith('fe80:') ||
38
- host.startsWith('fc') ||
39
- host.startsWith('fd')) {
54
+ if (host.includes(':')) {
55
+ // An IPv6 literal. Its prefixes are only checked here: a domain name such
56
+ // as fdic.gov or fcbarcelona.com starts with the same letters.
57
+ if (host === '::1' || host === '::')
58
+ return true;
59
+ // Link-local (fe80::/10) and unique-local (fc00::/7).
60
+ if (/^fe[89ab]/.test(host) || /^f[cd]/.test(host))
61
+ return true;
62
+ const mapped = mappedIpv4(host);
63
+ return mapped !== null && (0, exports.ipv4InPrivateRange)(mapped);
64
+ }
65
+ return (0, exports.ipv4InPrivateRange)(host);
66
+ };
67
+ exports.isBlockedHost = isBlockedHost;
68
+ // Whether a URL may not be fetched on a user's behalf: not http(s), not a URL
69
+ // at all, or pointing at a private, loopback or link-local host.
70
+ const isBlockedUrl = (url) => {
71
+ let parsed;
72
+ try {
73
+ parsed = new URL(url);
74
+ }
75
+ catch {
40
76
  return true;
41
77
  }
42
- if ((0, exports.ipv4InPrivateRange)(host))
78
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
43
79
  return true;
44
- return false;
80
+ return (0, exports.isBlockedHost)(parsed.hostname);
45
81
  };
46
- exports.isBlockedHost = isBlockedHost;
82
+ exports.isBlockedUrl = isBlockedUrl;
@@ -54,5 +54,53 @@ export declare const isSensitiveTool: (annotations: {
54
54
  readOnlyHint?: boolean;
55
55
  destructiveHint?: boolean;
56
56
  } | null | undefined) => boolean;
57
+ export interface ProxiedToolTrust {
58
+ trustHints: boolean;
59
+ readOnly: boolean;
60
+ }
61
+ export declare const proxiedToolTrust: (config: {
62
+ trustAnnotations?: unknown;
63
+ readOnlyTools?: unknown;
64
+ } | null | undefined, remoteToolName: string) => ProxiedToolTrust;
65
+ /**
66
+ * The annotations a proxied tool is registered with. A remote server's hints
67
+ * are its own claim about itself, and one that marks a delete read-only would
68
+ * skip every confirmation — so unless the organization chose to trust that
69
+ * server, the read-only and destructive hints are dropped and the tool reads
70
+ * as sensitive by the defaults above. A tool the owner marked as only reading
71
+ * is read-only whatever the remote says, trusted or not. Clients see the
72
+ * same, so they ask about the same tools. The harmless parts (title,
73
+ * openWorldHint, idempotentHint) pass through.
74
+ */
75
+ export declare const proxiedToolAnnotations: <T extends {
76
+ readOnlyHint?: boolean;
77
+ destructiveHint?: boolean;
78
+ }>(annotations: T | null | undefined, trust: ProxiedToolTrust) => Partial<T> | undefined;
79
+ /**
80
+ * An install's new config with the owner's trust marks carried over from the
81
+ * stored one wherever the new one doesn't say. A save that only knew about
82
+ * the allow-lists (an older dashboard, a script) must not quietly turn the
83
+ * marks off; one that sends them, even as false or empty, decides.
84
+ */
85
+ export declare const keepProxiedToolMarks: (stored: unknown, incoming: unknown) => unknown;
86
+ /** Whether a proxied tool is confirmed, decided as its registration is. */
87
+ export declare const isSensitiveProxiedTool: (annotations: {
88
+ readOnlyHint?: boolean;
89
+ destructiveHint?: boolean;
90
+ } | null | undefined, trust: ProxiedToolTrust) => boolean;
57
91
  export declare const stableJson: (value: unknown) => string;
92
+ export type ToolApprovalStatus = 'pending' | 'approved' | 'denied' | 'used' | 'expired';
93
+ /**
94
+ * Where an approval stands. Spent and refused come first, since an answer
95
+ * stays the answer after the window closes; past its time, one never answered
96
+ * or never used can no longer be.
97
+ */
98
+ export declare const toolApprovalStatus: (approval: {
99
+ expiresAt: Date;
100
+ approvedAt: Date | null;
101
+ deniedAt: Date | null;
102
+ usedAt: Date | null;
103
+ }, now?: number) => ToolApprovalStatus;
104
+ /** The dashboard page where the user answers one approval. */
105
+ export declare const toolApprovalUrl: (webUrl: string, path: string, approvalId: string) => string;
58
106
  //# sourceMappingURL=toolConfirmation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"toolConfirmation.d.ts","sourceRoot":"","sources":["../src/toolConfirmation.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,uBAAuB;IAEtC,EAAE,EAAE,MAAM,CAAC;IAGX,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;QACX,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,CAAC,CAAC;CACJ;AAKD,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;AAO/E,eAAO,MAAM,YAAY,yCAA0C,CAAC;AAEpE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,UAAU,KACjB;IAAE,YAAY,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAKE,CAAC;AAmHvD,eAAO,MAAM,uBAAuB,GAAI,OAAO,MAAM,KAAG,MAAM,GAAG,IAOhE,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,SAAS,MAAM,GAAG,IAAI,KACrB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAG3B,CAAC;AAQF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,KAAK,GAAG,IAAI,EACpB,uBAAuB,MAAM,KAC5B,MAA4E,CAAC;AAEhF,eAAO,MAAM,uBAAuB,GAClC,IAAI,MAAM,KACT;IAAE,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IAAC,qBAAqB,EAAE,MAAM,CAAA;CAAE,GAAG,IAQ1D,CAAC;AAWF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,KAAG,OAIlD,CAAC;AAmBF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GACpC,OAAO,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,EAClE,SAAS,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,KAChC,MAcc,CAAC;AAElB;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAC1B,aACI;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GACrD,IAAI,GACJ,SAAS,KACZ,OAC2E,CAAC;AAI/E,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,MAY3C,CAAC"}
1
+ {"version":3,"file":"toolConfirmation.d.ts","sourceRoot":"","sources":["../src/toolConfirmation.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@
4
4
  // participant's next message is a plain yes. These are the pieces of that rule
5
5
  // that aren't the runner's own bookkeeping.
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.stableJson = exports.isSensitiveTool = exports.formatConfirmationSummary = exports.isConfirmationReply = exports.parseConfirmationButton = exports.confirmationButtonId = exports.confirmationButtonLabels = exports.languageFromPhoneNumber = exports.annotationsForEffect = exports.TOOL_EFFECTS = void 0;
7
+ exports.toolApprovalUrl = exports.toolApprovalStatus = exports.stableJson = exports.isSensitiveProxiedTool = exports.keepProxiedToolMarks = exports.proxiedToolAnnotations = exports.proxiedToolTrust = exports.isSensitiveTool = exports.formatConfirmationSummary = exports.isConfirmationReply = exports.parseConfirmationButton = exports.confirmationButtonId = exports.confirmationButtonLabels = exports.languageFromPhoneNumber = exports.annotationsForEffect = exports.TOOL_EFFECTS = void 0;
8
8
  // What an owner says a tool they wrote does, in the words the dashboard asks
9
9
  // it in, and the MCP annotations each answer stands for: `read` only looks
10
10
  // things up, `write` changes things that can be undone, `sensitive` sends,
@@ -223,6 +223,62 @@ exports.formatConfirmationSummary = formatConfirmationSummary;
223
223
  */
224
224
  const isSensitiveTool = (annotations) => annotations?.readOnlyHint !== true && annotations?.destructiveHint !== false;
225
225
  exports.isSensitiveTool = isSensitiveTool;
226
+ const proxiedToolTrust = (config, remoteToolName) => ({
227
+ trustHints: config?.trustAnnotations === true,
228
+ readOnly: Array.isArray(config?.readOnlyTools) &&
229
+ config.readOnlyTools.includes(remoteToolName)
230
+ });
231
+ exports.proxiedToolTrust = proxiedToolTrust;
232
+ /**
233
+ * The annotations a proxied tool is registered with. A remote server's hints
234
+ * are its own claim about itself, and one that marks a delete read-only would
235
+ * skip every confirmation — so unless the organization chose to trust that
236
+ * server, the read-only and destructive hints are dropped and the tool reads
237
+ * as sensitive by the defaults above. A tool the owner marked as only reading
238
+ * is read-only whatever the remote says, trusted or not. Clients see the
239
+ * same, so they ask about the same tools. The harmless parts (title,
240
+ * openWorldHint, idempotentHint) pass through.
241
+ */
242
+ const proxiedToolAnnotations = (annotations, trust) => {
243
+ const result = { ...annotations };
244
+ if (trust.readOnly) {
245
+ delete result.destructiveHint;
246
+ return { ...result, readOnlyHint: true };
247
+ }
248
+ if (!trust.trustHints) {
249
+ delete result.readOnlyHint;
250
+ delete result.destructiveHint;
251
+ }
252
+ return Object.keys(result).length > 0 ? result : undefined;
253
+ };
254
+ exports.proxiedToolAnnotations = proxiedToolAnnotations;
255
+ // The install-config keys that hold the owner's trust marks above.
256
+ const PROXIED_TOOL_MARK_KEYS = ['trustAnnotations', 'readOnlyTools'];
257
+ /**
258
+ * An install's new config with the owner's trust marks carried over from the
259
+ * stored one wherever the new one doesn't say. A save that only knew about
260
+ * the allow-lists (an older dashboard, a script) must not quietly turn the
261
+ * marks off; one that sends them, even as false or empty, decides.
262
+ */
263
+ const keepProxiedToolMarks = (stored, incoming) => {
264
+ if (!stored ||
265
+ typeof stored !== 'object' ||
266
+ !incoming ||
267
+ typeof incoming !== 'object') {
268
+ return incoming;
269
+ }
270
+ const merged = { ...incoming };
271
+ for (const key of PROXIED_TOOL_MARK_KEYS) {
272
+ if (merged[key] === undefined && key in stored) {
273
+ merged[key] = stored[key];
274
+ }
275
+ }
276
+ return merged;
277
+ };
278
+ exports.keepProxiedToolMarks = keepProxiedToolMarks;
279
+ /** Whether a proxied tool is confirmed, decided as its registration is. */
280
+ const isSensitiveProxiedTool = (annotations, trust) => (0, exports.isSensitiveTool)((0, exports.proxiedToolAnnotations)(annotations, trust));
281
+ exports.isSensitiveProxiedTool = isSensitiveProxiedTool;
226
282
  // JSON with keys sorted at every depth, so two argument objects that say the
227
283
  // same thing serialize the same whatever order the model emitted them in.
228
284
  const stableJson = (value) => {
@@ -237,3 +293,21 @@ const stableJson = (value) => {
237
293
  return JSON.stringify(value) ?? 'null';
238
294
  };
239
295
  exports.stableJson = stableJson;
296
+ /**
297
+ * Where an approval stands. Spent and refused come first, since an answer
298
+ * stays the answer after the window closes; past its time, one never answered
299
+ * or never used can no longer be.
300
+ */
301
+ const toolApprovalStatus = (approval, now = Date.now()) => {
302
+ if (approval.usedAt)
303
+ return 'used';
304
+ if (approval.deniedAt)
305
+ return 'denied';
306
+ if (approval.expiresAt.getTime() <= now)
307
+ return 'expired';
308
+ return approval.approvedAt ? 'approved' : 'pending';
309
+ };
310
+ exports.toolApprovalStatus = toolApprovalStatus;
311
+ /** The dashboard page where the user answers one approval. */
312
+ const toolApprovalUrl = (webUrl, path, approvalId) => `${webUrl.replace(/\/+$/, '')}${path}/${encodeURIComponent(approvalId)}`;
313
+ exports.toolApprovalUrl = toolApprovalUrl;