@ganju/utils 0.0.1

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 (220) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +9 -0
  3. package/README.md +23 -0
  4. package/dist/apiError.d.ts +3 -0
  5. package/dist/apiError.d.ts.map +1 -0
  6. package/dist/apiError.js +36 -0
  7. package/dist/attachment.d.ts +33 -0
  8. package/dist/attachment.d.ts.map +1 -0
  9. package/dist/attachment.js +59 -0
  10. package/dist/base64.d.ts +10 -0
  11. package/dist/base64.d.ts.map +1 -0
  12. package/dist/base64.js +50 -0
  13. package/dist/channelDebounce.d.ts +26 -0
  14. package/dist/channelDebounce.d.ts.map +1 -0
  15. package/dist/channelDebounce.js +35 -0
  16. package/dist/channelNotifier.d.ts +9 -0
  17. package/dist/channelNotifier.d.ts.map +1 -0
  18. package/dist/channelNotifier.js +31 -0
  19. package/dist/chunking.d.ts +28 -0
  20. package/dist/chunking.d.ts.map +1 -0
  21. package/dist/chunking.js +97 -0
  22. package/dist/cliConstants.d.ts +9 -0
  23. package/dist/cliConstants.d.ts.map +1 -0
  24. package/dist/cliConstants.js +47 -0
  25. package/dist/coerce.d.ts +2 -0
  26. package/dist/coerce.d.ts.map +1 -0
  27. package/dist/coerce.js +13 -0
  28. package/dist/constants.d.ts +624 -0
  29. package/dist/constants.d.ts.map +1 -0
  30. package/dist/constants.js +2220 -0
  31. package/dist/crypto.d.ts +14 -0
  32. package/dist/crypto.d.ts.map +1 -0
  33. package/dist/crypto.js +93 -0
  34. package/dist/customCodeProject.d.ts +91 -0
  35. package/dist/customCodeProject.d.ts.map +1 -0
  36. package/dist/customCodeProject.js +154 -0
  37. package/dist/customCodeToken.d.ts +41 -0
  38. package/dist/customCodeToken.d.ts.map +1 -0
  39. package/dist/customCodeToken.js +115 -0
  40. package/dist/deadline.d.ts +6 -0
  41. package/dist/deadline.d.ts.map +1 -0
  42. package/dist/deadline.js +45 -0
  43. package/dist/discordSend.d.ts +25 -0
  44. package/dist/discordSend.d.ts.map +1 -0
  45. package/dist/discordSend.js +8 -0
  46. package/dist/embeddable.d.ts +2 -0
  47. package/dist/embeddable.d.ts.map +1 -0
  48. package/dist/embeddable.js +6 -0
  49. package/dist/exposedResource.d.ts +6 -0
  50. package/dist/exposedResource.d.ts.map +1 -0
  51. package/dist/exposedResource.js +18 -0
  52. package/dist/extractedDocument.d.ts +70 -0
  53. package/dist/extractedDocument.d.ts.map +1 -0
  54. package/dist/extractedDocument.js +2 -0
  55. package/dist/fetcher.d.ts +8 -0
  56. package/dist/fetcher.d.ts.map +1 -0
  57. package/dist/fetcher.js +68 -0
  58. package/dist/formatFilename.d.ts +2 -0
  59. package/dist/formatFilename.d.ts.map +1 -0
  60. package/dist/formatFilename.js +19 -0
  61. package/dist/formatRelative.d.ts +12 -0
  62. package/dist/formatRelative.d.ts.map +1 -0
  63. package/dist/formatRelative.js +28 -0
  64. package/dist/formatRelativeTime.d.ts +2 -0
  65. package/dist/formatRelativeTime.d.ts.map +1 -0
  66. package/dist/formatRelativeTime.js +49 -0
  67. package/dist/getEnv.d.ts +5 -0
  68. package/dist/getEnv.d.ts.map +1 -0
  69. package/dist/getEnv.js +11 -0
  70. package/dist/gmailSend.d.ts +24 -0
  71. package/dist/gmailSend.d.ts.map +1 -0
  72. package/dist/gmailSend.js +9 -0
  73. package/dist/index.d.ts +2839 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +155 -0
  76. package/dist/jsonSchemaToZodShape.d.ts +38 -0
  77. package/dist/jsonSchemaToZodShape.d.ts.map +1 -0
  78. package/dist/jsonSchemaToZodShape.js +117 -0
  79. package/dist/l2Normalize.d.ts +2 -0
  80. package/dist/l2Normalize.d.ts.map +1 -0
  81. package/dist/l2Normalize.js +25 -0
  82. package/dist/languageCookieDomain.d.ts +21 -0
  83. package/dist/languageCookieDomain.d.ts.map +1 -0
  84. package/dist/languageCookieDomain.js +39 -0
  85. package/dist/localizeZodIssue.d.ts +43 -0
  86. package/dist/localizeZodIssue.d.ts.map +1 -0
  87. package/dist/localizeZodIssue.js +90 -0
  88. package/dist/mailHeaders.d.ts +4 -0
  89. package/dist/mailHeaders.d.ts.map +1 -0
  90. package/dist/mailHeaders.js +11 -0
  91. package/dist/mcpProxy.d.ts +2 -0
  92. package/dist/mcpProxy.d.ts.map +1 -0
  93. package/dist/mcpProxy.js +21 -0
  94. package/dist/mimeMessage.d.ts +21 -0
  95. package/dist/mimeMessage.d.ts.map +1 -0
  96. package/dist/mimeMessage.js +58 -0
  97. package/dist/oauth.d.ts +21 -0
  98. package/dist/oauth.d.ts.map +1 -0
  99. package/dist/oauth.js +75 -0
  100. package/dist/oauthProviders.d.ts +12 -0
  101. package/dist/oauthProviders.d.ts.map +1 -0
  102. package/dist/oauthProviders.js +99 -0
  103. package/dist/outlookSend.d.ts +19 -0
  104. package/dist/outlookSend.d.ts.map +1 -0
  105. package/dist/outlookSend.js +9 -0
  106. package/dist/parseHttpError.d.ts +2 -0
  107. package/dist/parseHttpError.d.ts.map +1 -0
  108. package/dist/parseHttpError.js +23 -0
  109. package/dist/planLimitError.d.ts +18 -0
  110. package/dist/planLimitError.d.ts.map +1 -0
  111. package/dist/planLimitError.js +35 -0
  112. package/dist/processQueueBatch.d.ts +17 -0
  113. package/dist/processQueueBatch.d.ts.map +1 -0
  114. package/dist/processQueueBatch.js +32 -0
  115. package/dist/reservedToolName.d.ts +16 -0
  116. package/dist/reservedToolName.d.ts.map +1 -0
  117. package/dist/reservedToolName.js +25 -0
  118. package/dist/resourceUri.d.ts +2 -0
  119. package/dist/resourceUri.d.ts.map +1 -0
  120. package/dist/resourceUri.js +19 -0
  121. package/dist/retry.d.ts +10 -0
  122. package/dist/retry.d.ts.map +1 -0
  123. package/dist/retry.js +37 -0
  124. package/dist/sanitize.d.ts +7 -0
  125. package/dist/sanitize.d.ts.map +1 -0
  126. package/dist/sanitize.js +69 -0
  127. package/dist/schema.d.ts +2175 -0
  128. package/dist/schema.d.ts.map +1 -0
  129. package/dist/schema.js +1382 -0
  130. package/dist/sdkConstants.d.ts +15 -0
  131. package/dist/sdkConstants.d.ts.map +1 -0
  132. package/dist/sdkConstants.js +43 -0
  133. package/dist/slackSend.d.ts +38 -0
  134. package/dist/slackSend.d.ts.map +1 -0
  135. package/dist/slackSend.js +14 -0
  136. package/dist/slug.d.ts +5 -0
  137. package/dist/slug.d.ts.map +1 -0
  138. package/dist/slug.js +34 -0
  139. package/dist/slugifyTitle.d.ts +2 -0
  140. package/dist/slugifyTitle.d.ts.map +1 -0
  141. package/dist/slugifyTitle.js +11 -0
  142. package/dist/sources.d.ts +43 -0
  143. package/dist/sources.d.ts.map +1 -0
  144. package/dist/sources.js +73 -0
  145. package/dist/ssrf.d.ts +3 -0
  146. package/dist/ssrf.d.ts.map +1 -0
  147. package/dist/ssrf.js +46 -0
  148. package/dist/tallyUsageKinds.d.ts +9 -0
  149. package/dist/tallyUsageKinds.d.ts.map +1 -0
  150. package/dist/tallyUsageKinds.js +20 -0
  151. package/dist/telegramSend.d.ts +28 -0
  152. package/dist/telegramSend.d.ts.map +1 -0
  153. package/dist/telegramSend.js +9 -0
  154. package/dist/toolCatalog.d.ts +452 -0
  155. package/dist/toolCatalog.d.ts.map +1 -0
  156. package/dist/toolCatalog.js +552 -0
  157. package/dist/validateMessageVariables.d.ts +7 -0
  158. package/dist/validateMessageVariables.d.ts.map +1 -0
  159. package/dist/validateMessageVariables.js +16 -0
  160. package/dist/vendorError.d.ts +2 -0
  161. package/dist/vendorError.d.ts.map +1 -0
  162. package/dist/vendorError.js +25 -0
  163. package/dist/whatsappSend.d.ts +31 -0
  164. package/dist/whatsappSend.d.ts.map +1 -0
  165. package/dist/whatsappSend.js +11 -0
  166. package/package.json +76 -0
  167. package/src/apiError.ts +40 -0
  168. package/src/attachment.ts +97 -0
  169. package/src/base64.ts +60 -0
  170. package/src/channelDebounce.ts +76 -0
  171. package/src/channelNotifier.ts +39 -0
  172. package/src/chunking.ts +131 -0
  173. package/src/cliConstants.ts +50 -0
  174. package/src/coerce.ts +9 -0
  175. package/src/constants.ts +2542 -0
  176. package/src/crypto.ts +108 -0
  177. package/src/customCodeProject.ts +182 -0
  178. package/src/customCodeToken.ts +198 -0
  179. package/src/deadline.ts +43 -0
  180. package/src/discordSend.ts +41 -0
  181. package/src/embeddable.ts +4 -0
  182. package/src/exposedResource.ts +40 -0
  183. package/src/extractedDocument.ts +62 -0
  184. package/src/fetcher.ts +82 -0
  185. package/src/formatFilename.ts +19 -0
  186. package/src/formatRelative.ts +36 -0
  187. package/src/formatRelativeTime.ts +45 -0
  188. package/src/getEnv.ts +13 -0
  189. package/src/gmailSend.ts +34 -0
  190. package/src/index.ts +397 -0
  191. package/src/jsonSchemaToZodShape.ts +111 -0
  192. package/src/l2Normalize.ts +19 -0
  193. package/src/languageCookieDomain.ts +37 -0
  194. package/src/localizeZodIssue.ts +124 -0
  195. package/src/mailHeaders.ts +12 -0
  196. package/src/mcpProxy.ts +20 -0
  197. package/src/mimeMessage.ts +82 -0
  198. package/src/oauth.ts +103 -0
  199. package/src/oauthProviders.ts +118 -0
  200. package/src/outlookSend.ts +44 -0
  201. package/src/parseHttpError.ts +16 -0
  202. package/src/planLimitError.ts +50 -0
  203. package/src/processQueueBatch.ts +46 -0
  204. package/src/reservedToolName.ts +27 -0
  205. package/src/resourceUri.ts +17 -0
  206. package/src/retry.ts +43 -0
  207. package/src/sanitize.ts +67 -0
  208. package/src/schema.ts +1624 -0
  209. package/src/sdkConstants.ts +44 -0
  210. package/src/slackSend.ts +65 -0
  211. package/src/slug.ts +37 -0
  212. package/src/slugifyTitle.ts +8 -0
  213. package/src/sources.ts +117 -0
  214. package/src/ssrf.ts +34 -0
  215. package/src/tallyUsageKinds.ts +20 -0
  216. package/src/telegramSend.ts +39 -0
  217. package/src/toolCatalog.ts +635 -0
  218. package/src/validateMessageVariables.ts +18 -0
  219. package/src/vendorError.ts +19 -0
  220. package/src/whatsappSend.ts +47 -0
@@ -0,0 +1,15 @@
1
+ export declare const CUSTOM_CODE_BINDING_TOKEN = "GANJU_TOOL_TOKEN";
2
+ export declare const CUSTOM_CODE_BINDING_BROKER = "GANJU_BROKER";
3
+ export declare const CUSTOM_CODE_BROKER_ORIGIN = "https://broker.ganju.internal";
4
+ export declare const CUSTOM_CODE_BROKER_PATH_CONNECTION = "/connection";
5
+ export declare const CUSTOM_CODE_BROKER_PATH_SECRET = "/secret";
6
+ export declare const CUSTOM_CODE_BROKER_PATH_RESOURCES_SEARCH = "/resources/search";
7
+ export declare const CUSTOM_CODE_BROKER_PATH_RESOURCES_READ = "/resources/read";
8
+ export declare const CUSTOM_CODE_BROKER_PATH_RESOURCES_LIST = "/resources/list";
9
+ export declare const CUSTOM_CODE_BROKER_PATH_RESOURCES_CREATE = "/resources/create";
10
+ export declare const CUSTOM_CODE_BROKER_PATH_RESOURCES_DELETE = "/resources/delete";
11
+ export declare const CUSTOM_CODE_BROKER_PATH_SEND_FILE = "/send-file";
12
+ export declare const CUSTOM_CODE_HEALTH_TOOL = "__ganju_health";
13
+ export declare const CUSTOM_CODE_MAX_LOGS = 50;
14
+ export declare const CUSTOM_CODE_MAX_LOG_LENGTH = 2000;
15
+ //# sourceMappingURL=sdkConstants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdkConstants.d.ts","sourceRoot":"","sources":["../src/sdkConstants.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAC5D,eAAO,MAAM,0BAA0B,iBAAiB,CAAC;AAKzD,eAAO,MAAM,yBAAyB,kCAAkC,CAAC;AACzE,eAAO,MAAM,kCAAkC,gBAAgB,CAAC;AAChE,eAAO,MAAM,8BAA8B,YAAY,CAAC;AACxD,eAAO,MAAM,wCAAwC,sBAAsB,CAAC;AAC5E,eAAO,MAAM,sCAAsC,oBAAoB,CAAC;AACxE,eAAO,MAAM,sCAAsC,oBAAoB,CAAC;AACxE,eAAO,MAAM,wCAAwC,sBAAsB,CAAC;AAC5E,eAAO,MAAM,wCAAwC,sBAAsB,CAAC;AAC5E,eAAO,MAAM,iCAAiC,eAAe,CAAC;AAO9D,eAAO,MAAM,uBAAuB,mBAAmB,CAAC;AAKxD,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,0BAA0B,OAAQ,CAAC"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ // The handful of constants that get bundled into every customer's deployed
3
+ // script, split out from the main constants module for exactly that reason.
4
+ //
5
+ // `@ganju/utils/constants` is one large object literal, so a bundler cannot drop
6
+ // the keys a consumer doesn't touch — importing it from the SDK pulled ~70KB of
7
+ // plan limits, MIME tables and vendor scopes into every uploaded Worker to reach
8
+ // fourteen strings. These live here instead, and the main module re-exports them
9
+ // so there is still one definition of each.
10
+ //
11
+ // The rule for this file: nothing lands here unless the SDK reads it at runtime,
12
+ // and it imports nothing.
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.CUSTOM_CODE_MAX_LOG_LENGTH = exports.CUSTOM_CODE_MAX_LOGS = exports.CUSTOM_CODE_HEALTH_TOOL = exports.CUSTOM_CODE_BROKER_PATH_SEND_FILE = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_DELETE = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_CREATE = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_LIST = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_READ = exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_SEARCH = exports.CUSTOM_CODE_BROKER_PATH_SECRET = exports.CUSTOM_CODE_BROKER_PATH_CONNECTION = exports.CUSTOM_CODE_BROKER_ORIGIN = exports.CUSTOM_CODE_BINDING_BROKER = exports.CUSTOM_CODE_BINDING_TOKEN = void 0;
15
+ // Bindings injected into every user script at upload time. The token is a
16
+ // secret_text binding rotated on each publish; the broker is a service binding.
17
+ // Names are part of the SDK's contract with the script, so they can't be
18
+ // renamed without breaking already-deployed code.
19
+ exports.CUSTOM_CODE_BINDING_TOKEN = 'GANJU_TOOL_TOKEN';
20
+ exports.CUSTOM_CODE_BINDING_BROKER = 'GANJU_BROKER';
21
+ // Broker routes, called by user code through the service binding above with
22
+ // `Authorization: Bearer <GANJU_TOOL_TOKEN>`. The origin is arbitrary — a
23
+ // service binding ignores the hostname.
24
+ exports.CUSTOM_CODE_BROKER_ORIGIN = 'https://broker.ganju.internal';
25
+ exports.CUSTOM_CODE_BROKER_PATH_CONNECTION = '/connection';
26
+ exports.CUSTOM_CODE_BROKER_PATH_SECRET = '/secret';
27
+ exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_SEARCH = '/resources/search';
28
+ exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_READ = '/resources/read';
29
+ exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_LIST = '/resources/list';
30
+ exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_CREATE = '/resources/create';
31
+ exports.CUSTOM_CODE_BROKER_PATH_RESOURCES_DELETE = '/resources/delete';
32
+ exports.CUSTOM_CODE_BROKER_PATH_SEND_FILE = '/send-file';
33
+ // The reserved tool name the publish pipeline calls against a freshly uploaded
34
+ // script to ask which tools it actually exports — which is what turns "the
35
+ // manifest declares lookup-order but the code exports lookupOrder" from a
36
+ // call-time mystery into a publish-time error. Underscore-prefixed so it can
37
+ // never collide with a declared name.
38
+ exports.CUSTOM_CODE_HEALTH_TOOL = '__ganju_health';
39
+ // How many ctx.log() lines travel back with a result. Logs are buffered inside
40
+ // the isolate and returned in the response rather than sent to the broker line
41
+ // by line — a log call shouldn't cost a network round trip.
42
+ exports.CUSTOM_CODE_MAX_LOGS = 50;
43
+ exports.CUSTOM_CODE_MAX_LOG_LENGTH = 2_000;
@@ -0,0 +1,38 @@
1
+ export type SlackOperation = 'post-message' | 'upload-file';
2
+ export interface SlackSendRequest {
3
+ accessToken: string;
4
+ operation: SlackOperation;
5
+ channel: string;
6
+ threadTs?: string;
7
+ text?: string;
8
+ mrkdwn?: boolean;
9
+ blocks?: unknown[];
10
+ title?: string;
11
+ initialComment?: string;
12
+ }
13
+ export interface SlackSendRemoteResourceRequest {
14
+ slack: {
15
+ accessToken: string;
16
+ channel: string;
17
+ threadTs?: string;
18
+ title?: string;
19
+ initialComment?: string;
20
+ };
21
+ remote: {
22
+ url: string;
23
+ transport: string;
24
+ authHeader?: {
25
+ name: string;
26
+ value: string;
27
+ } | null;
28
+ uri: string;
29
+ timeoutMs: number;
30
+ };
31
+ }
32
+ export interface SlackSendResponse {
33
+ id: string;
34
+ channel?: string;
35
+ ts?: string;
36
+ permalink?: string;
37
+ }
38
+ //# sourceMappingURL=slackSend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slackSend.d.ts","sourceRoot":"","sources":["../src/slackSend.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,aAAa,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,cAAc,CAAC;IAG1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IAGnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAOD,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE;QACL,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;QAElB,UAAU,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC;QACpD,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAIhC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ // Wire protocol shared between the MCP worker (which builds the request) and
3
+ // the resource-handler container (which talks to the Slack Web API).
4
+ //
5
+ // post-message: simple chat.postMessage. No attachments. Worker could call
6
+ // Slack directly, but we route through the container to keep one auth/error
7
+ // path for the slack provider and so future block-kit composition can grow
8
+ // without bloating the worker bundle.
9
+ //
10
+ // upload-file: Slack's new external-upload flow is three round trips
11
+ // (files.getUploadURLExternal → PUT bytes → files.completeUploadExternal).
12
+ // The bytes ride in as a multipart `attachment` field; the container
13
+ // streams them out to Slack's signed URL.
14
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/slug.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export declare const generateRandomSlug: () => string;
2
+ export declare const generateRandomToken: (byteLength?: number) => string;
3
+ export declare const isReservedSlug: (slug: string) => boolean;
4
+ export declare const isValidSlugFormat: (slug: string) => boolean;
5
+ //# sourceMappingURL=slug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slug.d.ts","sourceRoot":"","sources":["../src/slug.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,kBAAkB,QAAO,MAIrC,CAAC;AAGF,eAAO,MAAM,mBAAmB,GAC9B,mBAA6C,KAC5C,MAIF,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,OACZ,CAAC;AAEnC,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,OAIxB,CAAC"}
package/dist/slug.js ADDED
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isValidSlugFormat = exports.isReservedSlug = exports.generateRandomToken = exports.generateRandomSlug = void 0;
4
+ const constants_1 = require("./constants");
5
+ const SLUG_BYTES = 16;
6
+ const SLUG_PATTERN = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
7
+ const RESERVED = new Set(constants_1.constants.RESERVED_SLUGS);
8
+ const toHex = (bytes) => {
9
+ let hex = '';
10
+ for (const b of bytes) {
11
+ hex += b.toString(16).padStart(2, '0');
12
+ }
13
+ return hex;
14
+ };
15
+ const generateRandomSlug = () => {
16
+ const bytes = new Uint8Array(SLUG_BYTES);
17
+ crypto.getRandomValues(bytes);
18
+ return toHex(bytes);
19
+ };
20
+ exports.generateRandomSlug = generateRandomSlug;
21
+ // Opaque, unguessable token — used as the public handle for an invitation.
22
+ const generateRandomToken = (byteLength = constants_1.constants.INVITATION_TOKEN_BYTES) => {
23
+ const bytes = new Uint8Array(byteLength);
24
+ crypto.getRandomValues(bytes);
25
+ return toHex(bytes);
26
+ };
27
+ exports.generateRandomToken = generateRandomToken;
28
+ const isReservedSlug = (slug) => RESERVED.has(slug.toLowerCase());
29
+ exports.isReservedSlug = isReservedSlug;
30
+ const isValidSlugFormat = (slug) => typeof slug === 'string' &&
31
+ slug.length >= 3 &&
32
+ slug.length <= 63 &&
33
+ SLUG_PATTERN.test(slug);
34
+ exports.isValidSlugFormat = isValidSlugFormat;
@@ -0,0 +1,2 @@
1
+ export declare const slugifyTitle: (title: string) => string;
2
+ //# sourceMappingURL=slugifyTitle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slugifyTitle.d.ts","sourceRoot":"","sources":["../src/slugifyTitle.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,MAIjB,CAAC"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.slugifyTitle = void 0;
4
+ // Lowercase a human title into a slug usable as a command name / MCP id —
5
+ // shared by prompts and resources (anything titled), so it's deliberately
6
+ // generic rather than prompt-specific.
7
+ const slugifyTitle = (title) => title
8
+ .toLowerCase()
9
+ .replace(/[^a-z0-9]+/g, '_')
10
+ .replace(/^_+|_+$/g, '');
11
+ exports.slugifyTitle = slugifyTitle;
@@ -0,0 +1,43 @@
1
+ export interface Source {
2
+ resourceId: string;
3
+ uri: string;
4
+ title: string;
5
+ sourceType: 'FILE' | 'WEBSITE' | 'CUSTOM_CODE';
6
+ mimeType: string;
7
+ fileName: string | null;
8
+ pageNumber?: number;
9
+ chunkIndex?: number;
10
+ score?: number;
11
+ excerpt?: string;
12
+ }
13
+ export interface ResourceUrlContext {
14
+ apiUrl: string;
15
+ organizationId: string;
16
+ projectId: string;
17
+ }
18
+ /**
19
+ * Does this source resolve to bytes we serve, rather than to a URL a reader can
20
+ * open?
21
+ *
22
+ * The distinction the two formatters below need is "download link or web link",
23
+ * and for a long time that was the same question as "is it a FILE". It stopped
24
+ * being once a tool could write a resource: a script-created one holds bytes
25
+ * exactly as an upload does, and its uri is a `resource://` address that means
26
+ * nothing to a browser. Formatting it as a web link produced a dead button in
27
+ * whichever channel the answer went to.
28
+ */
29
+ export declare const isDownloadableSource: (sourceType: Source["sourceType"]) => boolean;
30
+ export declare const isResourceSourceEnabled: (resource: {
31
+ showSource?: string | null;
32
+ } | null | undefined) => boolean;
33
+ export declare const safeHostname: (url: string) => string | null;
34
+ export declare const buildResourceDownloadUrl: (ctx: ResourceUrlContext, resourceId: string, pageNumber?: number) => string;
35
+ export interface SourceButton {
36
+ text: string;
37
+ url: string;
38
+ }
39
+ export declare const formatSourcesAsButtons: (sources: Source[], ctx: ResourceUrlContext, options?: {
40
+ maxLabelLength?: number;
41
+ }) => SourceButton[];
42
+ export declare const formatSourcesAsMarkdown: (sources: Source[], ctx: ResourceUrlContext) => string;
43
+ //# sourceMappingURL=sources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../src/sources.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,MAAM;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,GAAI,YAAY,MAAM,CAAC,YAAY,CAAC,KAAG,OAEb,CAAC;AAE5D,eAAO,MAAM,uBAAuB,GAClC,UAAU;IAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,KAC1D,OAEwB,CAAC;AAE5B,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAGnD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,KAAK,kBAAkB,EACvB,YAAY,MAAM,EAClB,aAAa,MAAM,KAClB,MAGF,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAKD,eAAO,MAAM,sBAAsB,GACjC,SAAS,MAAM,EAAE,EACjB,KAAK,kBAAkB,EACvB,UAAU;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,KACpC,YAAY,EAwBd,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,SAAS,MAAM,EAAE,EACjB,KAAK,kBAAkB,KACtB,MAmBF,CAAC"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatSourcesAsMarkdown = exports.formatSourcesAsButtons = exports.buildResourceDownloadUrl = exports.safeHostname = exports.isResourceSourceEnabled = exports.isDownloadableSource = void 0;
4
+ const constants_1 = require("./constants");
5
+ /**
6
+ * Does this source resolve to bytes we serve, rather than to a URL a reader can
7
+ * open?
8
+ *
9
+ * The distinction the two formatters below need is "download link or web link",
10
+ * and for a long time that was the same question as "is it a FILE". It stopped
11
+ * being once a tool could write a resource: a script-created one holds bytes
12
+ * exactly as an upload does, and its uri is a `resource://` address that means
13
+ * nothing to a browser. Formatting it as a web link produced a dead button in
14
+ * whichever channel the answer went to.
15
+ */
16
+ const isDownloadableSource = (sourceType) => sourceType === constants_1.constants.RESOURCE_SOURCE_TYPE_FILE ||
17
+ sourceType === constants_1.constants.RESOURCE_SOURCE_TYPE_CUSTOM_CODE;
18
+ exports.isDownloadableSource = isDownloadableSource;
19
+ const isResourceSourceEnabled = (resource) => (resource?.showSource ?? constants_1.constants.STATUS_ACTIVE) !==
20
+ constants_1.constants.STATUS_DISABLED;
21
+ exports.isResourceSourceEnabled = isResourceSourceEnabled;
22
+ const safeHostname = (url) => {
23
+ if (!URL.canParse(url))
24
+ return null;
25
+ return new URL(url).hostname.replace(/^www\./, '');
26
+ };
27
+ exports.safeHostname = safeHostname;
28
+ const buildResourceDownloadUrl = (ctx, resourceId, pageNumber) => {
29
+ const fragment = pageNumber ? `#page=${pageNumber}` : '';
30
+ return `${ctx.apiUrl}/organization/${ctx.organizationId}/project/${ctx.projectId}/artifact/resource/${resourceId}/download${fragment}`;
31
+ };
32
+ exports.buildResourceDownloadUrl = buildResourceDownloadUrl;
33
+ const truncateLabel = (text, max) => text.length <= max ? text : `${text.slice(0, max - 1)}…`;
34
+ const formatSourcesAsButtons = (sources, ctx, options) => {
35
+ const maxLabelLength = options?.maxLabelLength ?? 60;
36
+ return sources.map((source, index) => {
37
+ const position = index + 1;
38
+ if ((0, exports.isDownloadableSource)(source.sourceType)) {
39
+ const label = source.fileName || source.title;
40
+ const pageSuffix = source.pageNumber ? ` · p.${source.pageNumber}` : '';
41
+ const url = (0, exports.buildResourceDownloadUrl)(ctx, source.resourceId, source.pageNumber);
42
+ return {
43
+ text: truncateLabel(`${position} ${label}${pageSuffix}`, maxLabelLength),
44
+ url
45
+ };
46
+ }
47
+ const domain = (0, exports.safeHostname)(source.uri);
48
+ const base = domain ? `${domain} — ${source.title}` : source.title;
49
+ return {
50
+ text: truncateLabel(`${position} ${base}`, maxLabelLength),
51
+ url: source.uri
52
+ };
53
+ });
54
+ };
55
+ exports.formatSourcesAsButtons = formatSourcesAsButtons;
56
+ const formatSourcesAsMarkdown = (sources, ctx) => {
57
+ if (sources.length === 0)
58
+ return '';
59
+ const lines = sources.map((source, index) => {
60
+ const position = index + 1;
61
+ if ((0, exports.isDownloadableSource)(source.sourceType)) {
62
+ const label = source.fileName || source.title;
63
+ const pageSuffix = source.pageNumber ? ` · p. ${source.pageNumber}` : '';
64
+ const url = (0, exports.buildResourceDownloadUrl)(ctx, source.resourceId, source.pageNumber);
65
+ return `${position}. [${label}${pageSuffix}](${url})`;
66
+ }
67
+ const domain = (0, exports.safeHostname)(source.uri);
68
+ const label = domain ? `${domain} — ${source.title}` : source.title;
69
+ return `${position}. [${label}](${source.uri})`;
70
+ });
71
+ return `**Sources**\n${lines.join('\n')}`;
72
+ };
73
+ exports.formatSourcesAsMarkdown = formatSourcesAsMarkdown;
package/dist/ssrf.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export declare const ipv4InPrivateRange: (host: string) => boolean;
2
+ export declare const isBlockedHost: (hostname: string) => boolean;
3
+ //# sourceMappingURL=ssrf.d.ts.map
@@ -0,0 +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"}
package/dist/ssrf.js ADDED
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isBlockedHost = exports.ipv4InPrivateRange = void 0;
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
6
+ // only screen literal hosts and IPs (not DNS rebinding). Private/loopback/
7
+ // link-local ranges are always rejected; callers may further narrow with an
8
+ // allowlist.
9
+ const ipv4InPrivateRange = (host) => {
10
+ const parts = host.split('.');
11
+ if (parts.length !== 4)
12
+ return false;
13
+ const octets = parts.map(p => Number(p));
14
+ if (octets.some(o => !Number.isInteger(o) || o < 0 || o > 255))
15
+ return false;
16
+ const [a, b] = octets;
17
+ if (a === 127 || a === 10 || a === 0)
18
+ return true; // loopback / private / "this host"
19
+ if (a === 169 && b === 254)
20
+ return true; // link-local (incl. cloud metadata)
21
+ if (a === 192 && b === 168)
22
+ return true; // private
23
+ if (a === 172 && b >= 16 && b <= 31)
24
+ return true; // private
25
+ return false;
26
+ };
27
+ exports.ipv4InPrivateRange = ipv4InPrivateRange;
28
+ const isBlockedHost = (hostname) => {
29
+ const host = hostname.toLowerCase().replace(/^\[|\]$/g, '');
30
+ if (!host)
31
+ return true;
32
+ if (host === 'localhost' || host.endsWith('.localhost'))
33
+ 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')) {
40
+ return true;
41
+ }
42
+ if ((0, exports.ipv4InPrivateRange)(host))
43
+ return true;
44
+ return false;
45
+ };
46
+ exports.isBlockedHost = isBlockedHost;
@@ -0,0 +1,9 @@
1
+ export interface UsageTally {
2
+ tool: number;
3
+ prompt: number;
4
+ resource: number;
5
+ }
6
+ export declare const tallyUsageKinds: (items: {
7
+ kind: string;
8
+ }[]) => UsageTally;
9
+ //# sourceMappingURL=tallyUsageKinds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tallyUsageKinds.d.ts","sourceRoot":"","sources":["../src/tallyUsageKinds.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD,eAAO,MAAM,eAAe,GAAI,OAAO;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,KAAG,UAQ3D,CAAC"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tallyUsageKinds = void 0;
4
+ const constants_1 = require("./constants");
5
+ // Count a batch of invocations by usage kind. Shared by the channel runner and
6
+ // the MCP flush so both feed the artifact's denormalized usage totals the same
7
+ // way (anything that isn't tool/prompt/resource — protocol noise — is ignored).
8
+ const tallyUsageKinds = (items) => {
9
+ const tally = { tool: 0, prompt: 0, resource: 0 };
10
+ for (const { kind } of items) {
11
+ if (kind === constants_1.constants.USAGE_KIND_TOOL)
12
+ tally.tool += 1;
13
+ else if (kind === constants_1.constants.USAGE_KIND_PROMPT)
14
+ tally.prompt += 1;
15
+ else if (kind === constants_1.constants.USAGE_KIND_RESOURCE)
16
+ tally.resource += 1;
17
+ }
18
+ return tally;
19
+ };
20
+ exports.tallyUsageKinds = tallyUsageKinds;
@@ -0,0 +1,28 @@
1
+ export interface TelegramSendRequest {
2
+ botToken: string;
3
+ chatId: number;
4
+ replyToMessageId?: number;
5
+ caption?: string;
6
+ parseMode?: 'HTML' | 'Markdown' | 'MarkdownV2';
7
+ }
8
+ export interface TelegramSendResponse {
9
+ ok: boolean;
10
+ result?: {
11
+ message_id: number;
12
+ };
13
+ description?: string;
14
+ }
15
+ export interface TelegramSendRemoteResourceRequest {
16
+ telegram: TelegramSendRequest;
17
+ remote: {
18
+ url: string;
19
+ transport: string;
20
+ authHeader?: {
21
+ name: string;
22
+ value: string;
23
+ } | null;
24
+ uri: string;
25
+ timeoutMs: number;
26
+ };
27
+ }
28
+ //# sourceMappingURL=telegramSend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegramSend.d.ts","sourceRoot":"","sources":["../src/telegramSend.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,CAAC;CAChD;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAQD,MAAM,WAAW,iCAAiC;IAChD,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;QAElB,UAAU,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC;QACpD,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ // Wire protocol shared between the worker (which constructs the request) and
3
+ // the resource-handler container (which parses it and calls the Telegram Bot
4
+ // API). Worker sends a multipart/form-data POST with one `metadata` field
5
+ // (JSON matching TelegramSendRequest) and exactly one `file` field (binary).
6
+ //
7
+ // Telegram supports one media object per send call, so unlike Gmail this is
8
+ // always a single attachment.
9
+ Object.defineProperty(exports, "__esModule", { value: true });