discord-ops 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +150 -0
  4. package/dist/cli/health.d.ts +2 -0
  5. package/dist/cli/health.d.ts.map +1 -0
  6. package/dist/cli/health.js +2 -0
  7. package/dist/cli/health.js.map +1 -0
  8. package/dist/cli/index.d.ts +3 -0
  9. package/dist/cli/index.d.ts.map +1 -0
  10. package/dist/cli/index.js +98 -0
  11. package/dist/cli/index.js.map +1 -0
  12. package/dist/client.d.ts +22 -0
  13. package/dist/client.d.ts.map +1 -0
  14. package/dist/client.js +87 -0
  15. package/dist/client.js.map +1 -0
  16. package/dist/config/index.d.ts +17 -0
  17. package/dist/config/index.d.ts.map +1 -0
  18. package/dist/config/index.js +58 -0
  19. package/dist/config/index.js.map +1 -0
  20. package/dist/config/profiles.d.ts +18 -0
  21. package/dist/config/profiles.d.ts.map +1 -0
  22. package/dist/config/profiles.js +28 -0
  23. package/dist/config/profiles.js.map +1 -0
  24. package/dist/config/schema.d.ts +76 -0
  25. package/dist/config/schema.d.ts.map +1 -0
  26. package/dist/config/schema.js +29 -0
  27. package/dist/config/schema.js.map +1 -0
  28. package/dist/index.d.ts +7 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +5 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/routing/fuzzy.d.ts +16 -0
  33. package/dist/routing/fuzzy.d.ts.map +1 -0
  34. package/dist/routing/fuzzy.js +67 -0
  35. package/dist/routing/fuzzy.js.map +1 -0
  36. package/dist/routing/resolver.d.ts +31 -0
  37. package/dist/routing/resolver.d.ts.map +1 -0
  38. package/dist/routing/resolver.js +60 -0
  39. package/dist/routing/resolver.js.map +1 -0
  40. package/dist/security/audit.d.ts +9 -0
  41. package/dist/security/audit.d.ts.map +1 -0
  42. package/dist/security/audit.js +20 -0
  43. package/dist/security/audit.js.map +1 -0
  44. package/dist/security/permissions.d.ts +6 -0
  45. package/dist/security/permissions.d.ts.map +1 -0
  46. package/dist/security/permissions.js +15 -0
  47. package/dist/security/permissions.js.map +1 -0
  48. package/dist/security/rate-limiter.d.ts +16 -0
  49. package/dist/security/rate-limiter.d.ts.map +1 -0
  50. package/dist/security/rate-limiter.js +36 -0
  51. package/dist/security/rate-limiter.js.map +1 -0
  52. package/dist/security/sanitizer.d.ts +5 -0
  53. package/dist/security/sanitizer.d.ts.map +1 -0
  54. package/dist/security/sanitizer.js +26 -0
  55. package/dist/security/sanitizer.js.map +1 -0
  56. package/dist/security/token-validator.d.ts +9 -0
  57. package/dist/security/token-validator.d.ts.map +1 -0
  58. package/dist/security/token-validator.js +18 -0
  59. package/dist/security/token-validator.js.map +1 -0
  60. package/dist/server.d.ts +4 -0
  61. package/dist/server.d.ts.map +1 -0
  62. package/dist/server.js +64 -0
  63. package/dist/server.js.map +1 -0
  64. package/dist/tools/channels/create-channel.d.ts +3 -0
  65. package/dist/tools/channels/create-channel.d.ts.map +1 -0
  66. package/dist/tools/channels/create-channel.js +46 -0
  67. package/dist/tools/channels/create-channel.js.map +1 -0
  68. package/dist/tools/channels/delete-channel.d.ts +3 -0
  69. package/dist/tools/channels/delete-channel.d.ts.map +1 -0
  70. package/dist/tools/channels/delete-channel.js +20 -0
  71. package/dist/tools/channels/delete-channel.js.map +1 -0
  72. package/dist/tools/channels/edit-channel.d.ts +3 -0
  73. package/dist/tools/channels/edit-channel.d.ts.map +1 -0
  74. package/dist/tools/channels/edit-channel.js +32 -0
  75. package/dist/tools/channels/edit-channel.js.map +1 -0
  76. package/dist/tools/channels/get-channel.d.ts +3 -0
  77. package/dist/tools/channels/get-channel.d.ts.map +1 -0
  78. package/dist/tools/channels/get-channel.js +34 -0
  79. package/dist/tools/channels/get-channel.js.map +1 -0
  80. package/dist/tools/channels/index.d.ts +6 -0
  81. package/dist/tools/channels/index.d.ts.map +1 -0
  82. package/dist/tools/channels/index.js +6 -0
  83. package/dist/tools/channels/index.js.map +1 -0
  84. package/dist/tools/channels/list-channels.d.ts +3 -0
  85. package/dist/tools/channels/list-channels.d.ts.map +1 -0
  86. package/dist/tools/channels/list-channels.js +47 -0
  87. package/dist/tools/channels/list-channels.js.map +1 -0
  88. package/dist/tools/guilds/get-guild.d.ts +3 -0
  89. package/dist/tools/guilds/get-guild.d.ts.map +1 -0
  90. package/dist/tools/guilds/get-guild.js +30 -0
  91. package/dist/tools/guilds/get-guild.js.map +1 -0
  92. package/dist/tools/guilds/index.d.ts +3 -0
  93. package/dist/tools/guilds/index.d.ts.map +1 -0
  94. package/dist/tools/guilds/index.js +3 -0
  95. package/dist/tools/guilds/index.js.map +1 -0
  96. package/dist/tools/guilds/list-guilds.d.ts +3 -0
  97. package/dist/tools/guilds/list-guilds.d.ts.map +1 -0
  98. package/dist/tools/guilds/list-guilds.js +25 -0
  99. package/dist/tools/guilds/list-guilds.js.map +1 -0
  100. package/dist/tools/health-check.d.ts +3 -0
  101. package/dist/tools/health-check.d.ts.map +1 -0
  102. package/dist/tools/health-check.js +45 -0
  103. package/dist/tools/health-check.js.map +1 -0
  104. package/dist/tools/index.d.ts +3 -0
  105. package/dist/tools/index.d.ts.map +1 -0
  106. package/dist/tools/index.js +46 -0
  107. package/dist/tools/index.js.map +1 -0
  108. package/dist/tools/members/get-member.d.ts +3 -0
  109. package/dist/tools/members/get-member.d.ts.map +1 -0
  110. package/dist/tools/members/get-member.js +30 -0
  111. package/dist/tools/members/get-member.js.map +1 -0
  112. package/dist/tools/members/index.d.ts +3 -0
  113. package/dist/tools/members/index.d.ts.map +1 -0
  114. package/dist/tools/members/index.js +3 -0
  115. package/dist/tools/members/index.js.map +1 -0
  116. package/dist/tools/members/list-members.d.ts +3 -0
  117. package/dist/tools/members/list-members.d.ts.map +1 -0
  118. package/dist/tools/members/list-members.js +32 -0
  119. package/dist/tools/members/list-members.js.map +1 -0
  120. package/dist/tools/messaging/add-reaction.d.ts +3 -0
  121. package/dist/tools/messaging/add-reaction.d.ts.map +1 -0
  122. package/dist/tools/messaging/add-reaction.js +28 -0
  123. package/dist/tools/messaging/add-reaction.js.map +1 -0
  124. package/dist/tools/messaging/delete-message.d.ts +3 -0
  125. package/dist/tools/messaging/delete-message.d.ts.map +1 -0
  126. package/dist/tools/messaging/delete-message.js +28 -0
  127. package/dist/tools/messaging/delete-message.js.map +1 -0
  128. package/dist/tools/messaging/edit-message.d.ts +3 -0
  129. package/dist/tools/messaging/edit-message.d.ts.map +1 -0
  130. package/dist/tools/messaging/edit-message.js +33 -0
  131. package/dist/tools/messaging/edit-message.js.map +1 -0
  132. package/dist/tools/messaging/get-messages.d.ts +3 -0
  133. package/dist/tools/messaging/get-messages.d.ts.map +1 -0
  134. package/dist/tools/messaging/get-messages.js +48 -0
  135. package/dist/tools/messaging/get-messages.js.map +1 -0
  136. package/dist/tools/messaging/index.d.ts +6 -0
  137. package/dist/tools/messaging/index.d.ts.map +1 -0
  138. package/dist/tools/messaging/index.js +6 -0
  139. package/dist/tools/messaging/index.js.map +1 -0
  140. package/dist/tools/messaging/send-message.d.ts +3 -0
  141. package/dist/tools/messaging/send-message.d.ts.map +1 -0
  142. package/dist/tools/messaging/send-message.js +40 -0
  143. package/dist/tools/messaging/send-message.js.map +1 -0
  144. package/dist/tools/roles/index.d.ts +2 -0
  145. package/dist/tools/roles/index.d.ts.map +1 -0
  146. package/dist/tools/roles/index.js +2 -0
  147. package/dist/tools/roles/index.js.map +1 -0
  148. package/dist/tools/roles/list-roles.d.ts +3 -0
  149. package/dist/tools/roles/list-roles.d.ts.map +1 -0
  150. package/dist/tools/roles/list-roles.js +32 -0
  151. package/dist/tools/roles/list-roles.js.map +1 -0
  152. package/dist/tools/threads/create-thread.d.ts +3 -0
  153. package/dist/tools/threads/create-thread.d.ts.map +1 -0
  154. package/dist/tools/threads/create-thread.js +46 -0
  155. package/dist/tools/threads/create-thread.js.map +1 -0
  156. package/dist/tools/threads/index.d.ts +3 -0
  157. package/dist/tools/threads/index.d.ts.map +1 -0
  158. package/dist/tools/threads/index.js +3 -0
  159. package/dist/tools/threads/index.js.map +1 -0
  160. package/dist/tools/threads/list-threads.d.ts +3 -0
  161. package/dist/tools/threads/list-threads.d.ts.map +1 -0
  162. package/dist/tools/threads/list-threads.js +33 -0
  163. package/dist/tools/threads/list-threads.js.map +1 -0
  164. package/dist/tools/types.d.ts +29 -0
  165. package/dist/tools/types.d.ts.map +1 -0
  166. package/dist/tools/types.js +10 -0
  167. package/dist/tools/types.js.map +1 -0
  168. package/dist/transport/stdio.d.ts +3 -0
  169. package/dist/transport/stdio.d.ts.map +1 -0
  170. package/dist/transport/stdio.js +8 -0
  171. package/dist/transport/stdio.js.map +1 -0
  172. package/dist/utils/cache.d.ts +10 -0
  173. package/dist/utils/cache.d.ts.map +1 -0
  174. package/dist/utils/cache.js +27 -0
  175. package/dist/utils/cache.js.map +1 -0
  176. package/dist/utils/logger.d.ts +14 -0
  177. package/dist/utils/logger.d.ts.map +1 -0
  178. package/dist/utils/logger.js +32 -0
  179. package/dist/utils/logger.js.map +1 -0
  180. package/dist/utils/retry.d.ts +7 -0
  181. package/dist/utils/retry.d.ts.map +1 -0
  182. package/dist/utils/retry.js +27 -0
  183. package/dist/utils/retry.js.map +1 -0
  184. package/package.json +80 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,gBAAgB,8EAO3B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,sBAAsB;;;;;;;;;EAGjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,eAAe;;;;;;;;;;;;EAI1B,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ export const NotificationType = z.enum([
3
+ "ci_build",
4
+ "deploy",
5
+ "release",
6
+ "error",
7
+ "announcement",
8
+ "dev",
9
+ ]);
10
+ export const ProjectConfigSchema = z.object({
11
+ guild_id: z.string().regex(/^\d{17,20}$/, "Must be a valid Discord snowflake ID"),
12
+ channels: z.record(z.string(), z.string().regex(/^\d{17,20}$/)),
13
+ default_channel: z.string().optional(),
14
+ });
15
+ export const GlobalConfigSchema = z.object({
16
+ projects: z.record(z.string(), ProjectConfigSchema),
17
+ default_project: z.string().optional(),
18
+ notification_routing: z.record(NotificationType, z.string()).optional(),
19
+ });
20
+ export const PerProjectConfigSchema = z.object({
21
+ project: z.string(),
22
+ notification_routing: z.record(NotificationType, z.string()).optional(),
23
+ });
24
+ export const EnvConfigSchema = z.object({
25
+ DISCORD_TOKEN: z.string().min(50),
26
+ DISCORD_OPS_CONFIG: z.string().optional(),
27
+ DISCORD_OPS_LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).optional(),
28
+ });
29
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC;IACrC,UAAU;IACV,QAAQ;IACR,SAAS;IACT,OAAO;IACP,cAAc;IACd,KAAK;CACN,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,sCAAsC,CAAC;IACjF,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC;IACnD,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,oBAAoB,EAAE,CAAC,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACxE,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,oBAAoB,EAAE,CAAC,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACxE,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;IACjC,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC7E,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { createServer } from "./server.js";
2
+ export { DiscordClient } from "./client.js";
3
+ export { loadConfig } from "./config/index.js";
4
+ export { allTools } from "./tools/index.js";
5
+ export type { ToolDefinition, ToolContext, ToolResult } from "./tools/types.js";
6
+ export type { GlobalConfig, PerProjectConfig } from "./config/schema.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAChF,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { createServer } from "./server.js";
2
+ export { DiscordClient } from "./client.js";
3
+ export { loadConfig } from "./config/index.js";
4
+ export { allTools } from "./tools/index.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Fuzzy name resolution for channels, roles, and members.
3
+ * Resolution order: exact ID → exact name → normalized → substring.
4
+ */
5
+ export interface Named {
6
+ id: string;
7
+ name: string;
8
+ }
9
+ export interface FuzzyMatch<T extends Named> {
10
+ item: T;
11
+ score: number;
12
+ matchType: "exact_id" | "exact_name" | "normalized" | "substring";
13
+ }
14
+ export declare function fuzzyFind<T extends Named>(items: T[], query: string, threshold?: number): FuzzyMatch<T> | undefined;
15
+ export declare function fuzzyFindAll<T extends Named>(items: T[], query: string, threshold?: number): FuzzyMatch<T>[];
16
+ //# sourceMappingURL=fuzzy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy.d.ts","sourceRoot":"","sources":["../../src/routing/fuzzy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,KAAK;IACzC,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,CAAC;CACnE;AAMD,wBAAgB,SAAS,CAAC,CAAC,SAAS,KAAK,EACvC,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAa,GACvB,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,CAoC3B;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,KAAK,EAC1C,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAY,GACtB,UAAU,CAAC,CAAC,CAAC,EAAE,CAwBjB"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Fuzzy name resolution for channels, roles, and members.
3
+ * Resolution order: exact ID → exact name → normalized → substring.
4
+ */
5
+ function normalize(s) {
6
+ return s.toLowerCase().replace(/[-_ ]/g, "");
7
+ }
8
+ export function fuzzyFind(items, query, threshold = 0.75) {
9
+ // 1. Exact ID match
10
+ const byId = items.find((item) => item.id === query);
11
+ if (byId)
12
+ return { item: byId, score: 1, matchType: "exact_id" };
13
+ const lowerQuery = query.toLowerCase();
14
+ // 2. Exact name match (case-insensitive)
15
+ const byName = items.find((item) => item.name.toLowerCase() === lowerQuery);
16
+ if (byName)
17
+ return { item: byName, score: 1, matchType: "exact_name" };
18
+ // 3. Normalized match (strip separators)
19
+ const normalizedQuery = normalize(query);
20
+ const byNormalized = items.find((item) => normalize(item.name) === normalizedQuery);
21
+ if (byNormalized)
22
+ return { item: byNormalized, score: 0.9, matchType: "normalized" };
23
+ // 4. Substring containment with score
24
+ const substringMatches = [];
25
+ for (const item of items) {
26
+ const normalName = normalize(item.name);
27
+ if (normalName.includes(normalizedQuery) || normalizedQuery.includes(normalName)) {
28
+ const shorter = Math.min(normalName.length, normalizedQuery.length);
29
+ const longer = Math.max(normalName.length, normalizedQuery.length);
30
+ const score = shorter / longer;
31
+ if (score >= threshold) {
32
+ substringMatches.push({ item, score, matchType: "substring" });
33
+ }
34
+ }
35
+ }
36
+ if (substringMatches.length > 0) {
37
+ substringMatches.sort((a, b) => b.score - a.score);
38
+ return substringMatches[0];
39
+ }
40
+ return undefined;
41
+ }
42
+ export function fuzzyFindAll(items, query, threshold = 0.5) {
43
+ const results = [];
44
+ const normalizedQuery = normalize(query);
45
+ for (const item of items) {
46
+ const normalName = normalize(item.name);
47
+ if (item.id === query) {
48
+ results.push({ item, score: 1, matchType: "exact_id" });
49
+ }
50
+ else if (item.name.toLowerCase() === query.toLowerCase()) {
51
+ results.push({ item, score: 1, matchType: "exact_name" });
52
+ }
53
+ else if (normalName === normalizedQuery) {
54
+ results.push({ item, score: 0.9, matchType: "normalized" });
55
+ }
56
+ else if (normalName.includes(normalizedQuery) || normalizedQuery.includes(normalName)) {
57
+ const shorter = Math.min(normalName.length, normalizedQuery.length);
58
+ const longer = Math.max(normalName.length, normalizedQuery.length);
59
+ const score = shorter / longer;
60
+ if (score >= threshold) {
61
+ results.push({ item, score, matchType: "substring" });
62
+ }
63
+ }
64
+ }
65
+ return results.sort((a, b) => b.score - a.score);
66
+ }
67
+ //# sourceMappingURL=fuzzy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy.js","sourceRoot":"","sources":["../../src/routing/fuzzy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { LoadedConfig } from "../config/index.js";
2
+ export interface ResolvedTarget {
3
+ guildId: string;
4
+ channelId: string;
5
+ project?: string;
6
+ }
7
+ export interface ResolveParams {
8
+ /** Direct channel ID — highest priority */
9
+ channel_id?: string;
10
+ /** Direct guild ID */
11
+ guild_id?: string;
12
+ /** Project name for routing */
13
+ project?: string;
14
+ /** Channel alias within a project */
15
+ channel?: string;
16
+ /** Notification type for automatic routing */
17
+ notification_type?: string;
18
+ }
19
+ /**
20
+ * Resolves a target guild + channel from flexible input params.
21
+ *
22
+ * Priority:
23
+ * 1. Direct channel_id + guild_id (always works)
24
+ * 2. Project + channel alias
25
+ * 3. Project + notification_type → channel alias
26
+ * 4. Project + default_channel
27
+ */
28
+ export declare function resolveTarget(params: ResolveParams, config: LoadedConfig): ResolvedTarget | {
29
+ error: string;
30
+ };
31
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/routing/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,YAAY,GACnB,cAAc,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAoCpC"}
@@ -0,0 +1,60 @@
1
+ import { resolveProject, getDefaultProjectName } from "../config/profiles.js";
2
+ /**
3
+ * Resolves a target guild + channel from flexible input params.
4
+ *
5
+ * Priority:
6
+ * 1. Direct channel_id + guild_id (always works)
7
+ * 2. Project + channel alias
8
+ * 3. Project + notification_type → channel alias
9
+ * 4. Project + default_channel
10
+ */
11
+ export function resolveTarget(params, config) {
12
+ // Direct IDs always win
13
+ if (params.channel_id) {
14
+ return {
15
+ guildId: params.guild_id ?? "",
16
+ channelId: params.channel_id,
17
+ project: params.project,
18
+ };
19
+ }
20
+ // Need a project for alias-based resolution
21
+ const projectName = params.project ?? getDefaultProjectName(config.global, config.perProject);
22
+ if (!projectName) {
23
+ return { error: "No project specified and no default_project configured" };
24
+ }
25
+ const project = resolveProject(projectName, config.global, config.perProject);
26
+ if (!project) {
27
+ return { error: `Project "${projectName}" not found in config` };
28
+ }
29
+ // Resolve channel
30
+ const channelId = resolveChannel(params, project);
31
+ if (!channelId) {
32
+ return {
33
+ error: `Cannot resolve channel for project "${projectName}". Provide channel, notification_type, or set default_channel`,
34
+ };
35
+ }
36
+ return {
37
+ guildId: project.guildId,
38
+ channelId,
39
+ project: projectName,
40
+ };
41
+ }
42
+ function resolveChannel(params, project) {
43
+ // Explicit channel alias
44
+ if (params.channel) {
45
+ return project.channels[params.channel];
46
+ }
47
+ // Notification type → channel alias → channel ID
48
+ if (params.notification_type && project.notificationRouting) {
49
+ const channelAlias = project.notificationRouting[params.notification_type];
50
+ if (channelAlias) {
51
+ return project.channels[channelAlias];
52
+ }
53
+ }
54
+ // Default channel
55
+ if (project.defaultChannel) {
56
+ return project.channels[project.defaultChannel];
57
+ }
58
+ return undefined;
59
+ }
60
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/routing/resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAwB,MAAM,uBAAuB,CAAC;AAsBpG;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAqB,EACrB,MAAoB;IAEpB,wBAAwB;IACxB,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE;YAC9B,SAAS,EAAE,MAAM,CAAC,UAAU;YAC5B,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC;IACJ,CAAC;IAED,4CAA4C;IAC5C,MAAM,WAAW,GACf,MAAM,CAAC,OAAO,IAAI,qBAAqB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAE5E,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,EAAE,KAAK,EAAE,wDAAwD,EAAE,CAAC;IAC7E,CAAC;IAED,MAAM,OAAO,GAAG,cAAc,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9E,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,KAAK,EAAE,YAAY,WAAW,uBAAuB,EAAE,CAAC;IACnE,CAAC;IAED,kBAAkB;IAClB,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;YACL,KAAK,EAAE,uCAAuC,WAAW,+DAA+D;SACzH,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS;QACT,OAAO,EAAE,WAAW;KACrB,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CACrB,MAAqB,EACrB,OAAwB;IAExB,yBAAyB;IACzB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,iDAAiD;IACjD,IAAI,MAAM,CAAC,iBAAiB,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAC5D,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,iBAAqC,CAAC,CAAC;QAC/F,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface AuditEntry {
2
+ tool: string;
3
+ params: Record<string, unknown>;
4
+ durationMs: number;
5
+ success: boolean;
6
+ error?: string;
7
+ }
8
+ export declare function auditToolCall(entry: AuditEntry): void;
9
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/security/audit.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAOrD"}
@@ -0,0 +1,20 @@
1
+ import { logger } from "../utils/logger.js";
2
+ export function auditToolCall(entry) {
3
+ logger.info(`tool:${entry.tool}`, {
4
+ params: redactSensitiveParams(entry.params),
5
+ durationMs: entry.durationMs,
6
+ success: entry.success,
7
+ ...(entry.error ? { error: entry.error } : {}),
8
+ });
9
+ }
10
+ function redactSensitiveParams(params) {
11
+ const redacted = { ...params };
12
+ const sensitiveKeys = ["token", "secret", "password", "webhook_url"];
13
+ for (const key of Object.keys(redacted)) {
14
+ if (sensitiveKeys.some((sk) => key.toLowerCase().includes(sk))) {
15
+ redacted[key] = "[REDACTED]";
16
+ }
17
+ }
18
+ return redacted;
19
+ }
20
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/security/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAU5C,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,MAAM,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,IAAI,EAAE,EAAE;QAChC,MAAM,EAAE,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC;QAC3C,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/C,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB,CAAC,MAA+B;IAC5D,MAAM,QAAQ,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IAC/B,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IAErE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxC,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAC/D,QAAQ,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { type GuildMember, type PermissionResolvable } from "discord.js";
2
+ export declare function checkPermissions(member: GuildMember, required: PermissionResolvable[]): {
3
+ allowed: boolean;
4
+ missing: string[];
5
+ };
6
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/security/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,oBAAoB,EAAuB,MAAM,YAAY,CAAC;AAE9F,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,oBAAoB,EAAE,GAC/B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAczC"}
@@ -0,0 +1,15 @@
1
+ import { PermissionsBitField } from "discord.js";
2
+ export function checkPermissions(member, required) {
3
+ const missing = [];
4
+ for (const perm of required) {
5
+ if (!member.permissions.has(perm)) {
6
+ const resolved = new PermissionsBitField(perm);
7
+ missing.push(...resolved.toArray());
8
+ }
9
+ }
10
+ return {
11
+ allowed: missing.length === 0,
12
+ missing: [...new Set(missing)],
13
+ };
14
+ }
15
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/security/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+C,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE9F,MAAM,UAAU,gBAAgB,CAC9B,MAAmB,EACnB,QAAgC;IAEhC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC;QAC7B,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;KAC/B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Client-side sliding window rate limiter.
3
+ * Acts as a first line of defense before Discord's own rate limits.
4
+ */
5
+ export declare class RateLimiter {
6
+ private buckets;
7
+ private readonly maxRequests;
8
+ private readonly windowMs;
9
+ constructor(maxRequests?: number, windowSeconds?: number);
10
+ check(bucket: string): {
11
+ allowed: boolean;
12
+ retryAfterMs?: number;
13
+ };
14
+ reset(bucket?: string): void;
15
+ }
16
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/security/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,WAAW,GAAE,MAAW,EAAE,aAAa,GAAE,MAAW;IAKhE,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE;IAkBlE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;CAO7B"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Client-side sliding window rate limiter.
3
+ * Acts as a first line of defense before Discord's own rate limits.
4
+ */
5
+ export class RateLimiter {
6
+ buckets = new Map();
7
+ maxRequests;
8
+ windowMs;
9
+ constructor(maxRequests = 30, windowSeconds = 60) {
10
+ this.maxRequests = maxRequests;
11
+ this.windowMs = windowSeconds * 1000;
12
+ }
13
+ check(bucket) {
14
+ const now = Date.now();
15
+ const entry = this.buckets.get(bucket) ?? { timestamps: [] };
16
+ // Prune expired timestamps
17
+ entry.timestamps = entry.timestamps.filter((ts) => now - ts < this.windowMs);
18
+ if (entry.timestamps.length >= this.maxRequests) {
19
+ const oldestInWindow = entry.timestamps[0];
20
+ const retryAfterMs = this.windowMs - (now - oldestInWindow);
21
+ return { allowed: false, retryAfterMs };
22
+ }
23
+ entry.timestamps.push(now);
24
+ this.buckets.set(bucket, entry);
25
+ return { allowed: true };
26
+ }
27
+ reset(bucket) {
28
+ if (bucket) {
29
+ this.buckets.delete(bucket);
30
+ }
31
+ else {
32
+ this.buckets.clear();
33
+ }
34
+ }
35
+ }
36
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/security/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,OAAO,WAAW;IACd,OAAO,GAAG,IAAI,GAAG,EAA2B,CAAC;IACpC,WAAW,CAAS;IACpB,QAAQ,CAAS;IAElC,YAAY,cAAsB,EAAE,EAAE,gBAAwB,EAAE;QAC9D,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,aAAa,GAAG,IAAI,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,MAAc;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;QAE7D,2BAA2B;QAC3B,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE7E,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAChD,MAAM,cAAc,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;YAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,GAAG,cAAc,CAAC,CAAC;YAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;QAC1C,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAChC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,MAAe;QACnB,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Sanitizes error messages to prevent leaking sensitive Discord data.
3
+ */
4
+ export declare function sanitizeError(error: unknown): string;
5
+ //# sourceMappingURL=sanitizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../../src/security/sanitizer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAqBpD"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Sanitizes error messages to prevent leaking sensitive Discord data.
3
+ */
4
+ const SNOWFLAKE_IN_URL = /\/\d{17,20}/g;
5
+ const TOKEN_FRAGMENT = /[A-Za-z0-9_-]{24,}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,}/g;
6
+ const WEBHOOK_URL = /https:\/\/discord\.com\/api\/webhooks\/\d+\/[A-Za-z0-9_-]+/g;
7
+ export function sanitizeError(error) {
8
+ let message;
9
+ if (error instanceof Error) {
10
+ message = error.message;
11
+ }
12
+ else if (typeof error === "string") {
13
+ message = error;
14
+ }
15
+ else {
16
+ message = "An unknown error occurred";
17
+ }
18
+ // Strip tokens first (most sensitive)
19
+ message = message.replace(TOKEN_FRAGMENT, "[REDACTED_TOKEN]");
20
+ // Strip webhook URLs
21
+ message = message.replace(WEBHOOK_URL, "[REDACTED_WEBHOOK_URL]");
22
+ // Strip snowflake IDs from URLs (keep standalone IDs — they're needed for debugging)
23
+ message = message.replace(SNOWFLAKE_IN_URL, "/[REDACTED_ID]");
24
+ return message;
25
+ }
26
+ //# sourceMappingURL=sanitizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/security/sanitizer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,gBAAgB,GAAG,cAAc,CAAC;AACxC,MAAM,cAAc,GAAG,2DAA2D,CAAC;AACnF,MAAM,WAAW,GAAG,6DAA6D,CAAC;AAElF,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAe,CAAC;IAEpB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1B,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,GAAG,KAAK,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,2BAA2B,CAAC;IACxC,CAAC;IAED,sCAAsC;IACtC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;IAE9D,qBAAqB;IACrB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,wBAAwB,CAAC,CAAC;IAEjE,qFAAqF;IACrF,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;IAE9D,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Validates Discord bot token format without making API calls.
3
+ * Tokens follow the pattern: base64(bot_id).timestamp.hmac
4
+ */
5
+ export declare function validateTokenFormat(token: string): {
6
+ valid: boolean;
7
+ reason?: string;
8
+ };
9
+ //# sourceMappingURL=token-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-validator.d.ts","sourceRoot":"","sources":["../../src/security/token-validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CActF"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Validates Discord bot token format without making API calls.
3
+ * Tokens follow the pattern: base64(bot_id).timestamp.hmac
4
+ */
5
+ const TOKEN_PATTERN = /^[A-Za-z0-9_-]{24,}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,}$/;
6
+ export function validateTokenFormat(token) {
7
+ if (!token || typeof token !== "string") {
8
+ return { valid: false, reason: "Token is empty or not a string" };
9
+ }
10
+ if (token.length < 50) {
11
+ return { valid: false, reason: "Token is too short" };
12
+ }
13
+ if (!TOKEN_PATTERN.test(token)) {
14
+ return { valid: false, reason: "Token does not match expected format (base64.timestamp.hmac)" };
15
+ }
16
+ return { valid: true };
17
+ }
18
+ //# sourceMappingURL=token-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-validator.js","sourceRoot":"","sources":["../../src/security/token-validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,aAAa,GAAG,4DAA4D,CAAC;AAEnF,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,gCAAgC,EAAE,CAAC;IACpE,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;IACxD,CAAC;IAED,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,8DAA8D,EAAE,CAAC;IAClG,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ToolContext } from "./tools/types.js";
3
+ export declare function createServer(ctx: ToolContext): McpServer;
4
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAiBpD,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,SAAS,CAqDxD"}
package/dist/server.js ADDED
@@ -0,0 +1,64 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { allTools } from "./tools/index.js";
3
+ import { sanitizeError } from "./security/sanitizer.js";
4
+ import { auditToolCall } from "./security/audit.js";
5
+ import { logger } from "./utils/logger.js";
6
+ /**
7
+ * Extract the raw shape from a ZodObject for MCP SDK registration.
8
+ * The SDK expects Record<string, ZodType> (the shape), not the ZodObject itself.
9
+ */
10
+ function getZodShape(schema) {
11
+ const def = schema._def;
12
+ if (def?.typeName === "ZodObject") {
13
+ return def.shape();
14
+ }
15
+ return undefined;
16
+ }
17
+ export function createServer(ctx) {
18
+ const server = new McpServer({
19
+ name: "discord-ops",
20
+ version: "0.1.0",
21
+ });
22
+ for (const tool of allTools) {
23
+ const shape = getZodShape(tool.inputSchema);
24
+ const callback = async (params) => {
25
+ const start = Date.now();
26
+ try {
27
+ const parsed = tool.inputSchema.parse(params);
28
+ const result = await tool.handle(parsed, ctx);
29
+ auditToolCall({
30
+ tool: tool.name,
31
+ params,
32
+ durationMs: Date.now() - start,
33
+ success: !result.isError,
34
+ error: result.isError ? result.content[0]?.text : undefined,
35
+ });
36
+ return result;
37
+ }
38
+ catch (err) {
39
+ const sanitized = sanitizeError(err);
40
+ auditToolCall({
41
+ tool: tool.name,
42
+ params,
43
+ durationMs: Date.now() - start,
44
+ success: false,
45
+ error: sanitized,
46
+ });
47
+ logger.error(`Tool ${tool.name} failed`, { error: sanitized });
48
+ return {
49
+ content: [{ type: "text", text: sanitized }],
50
+ isError: true,
51
+ };
52
+ }
53
+ };
54
+ if (shape) {
55
+ server.tool(tool.name, tool.description, shape, callback);
56
+ }
57
+ else {
58
+ server.tool(tool.name, tool.description, callback);
59
+ }
60
+ }
61
+ logger.info(`Registered ${allTools.length} tools`);
62
+ return server;
63
+ }
64
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C;;;GAGG;AACH,SAAS,WAAW,CAAC,MAAiB;IACpC,MAAM,GAAG,GAAI,MAAc,CAAC,IAAI,CAAC;IACjC,IAAI,GAAG,EAAE,QAAQ,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,GAAG,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAgB;IAC3C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE5C,MAAM,QAAQ,GAAG,KAAK,EAAE,MAA+B,EAAE,EAAE;YACzD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC9C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;gBAE9C,aAAa,CAAC;oBACZ,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,MAAM;oBACN,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;oBAC9B,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO;oBACxB,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS;iBAC5D,CAAC,CAAC;gBAEH,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;gBAErC,aAAa,CAAC;oBACZ,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,MAAM;oBACN,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;oBAC9B,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,SAAS;iBACjB,CAAC,CAAC;gBAEH,MAAM,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,IAAI,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;gBAE/D,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;oBACrD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,QAAe,CAAC,CAAC;QACnE,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,QAAe,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,cAAc,QAAQ,CAAC,MAAM,QAAQ,CAAC,CAAC;IACnD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDefinition } from "../types.js";
2
+ export declare const createChannel: ToolDefinition;
3
+ //# sourceMappingURL=create-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-channel.d.ts","sourceRoot":"","sources":["../../../src/tools/channels/create-channel.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAuBlD,eAAO,MAAM,aAAa,EAAE,cAyB3B,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ import { ChannelType } from "discord.js";
3
+ import { toolResultJson } from "../types.js";
4
+ const inputSchema = z.object({
5
+ guild_id: z.string().describe("Guild ID to create channel in"),
6
+ name: z.string().min(1).max(100).describe("Channel name"),
7
+ type: z
8
+ .enum(["text", "voice", "category", "announcement", "forum", "stage"])
9
+ .default("text")
10
+ .describe("Channel type"),
11
+ topic: z.string().max(1024).optional().describe("Channel topic"),
12
+ parent_id: z.string().optional().describe("Category ID to place channel under"),
13
+ });
14
+ const CHANNEL_TYPE_MAP = {
15
+ text: ChannelType.GuildText,
16
+ voice: ChannelType.GuildVoice,
17
+ category: ChannelType.GuildCategory,
18
+ announcement: ChannelType.GuildAnnouncement,
19
+ forum: ChannelType.GuildForum,
20
+ stage: ChannelType.GuildStageVoice,
21
+ };
22
+ export const createChannel = {
23
+ name: "create_channel",
24
+ description: "Create a new channel in a guild.",
25
+ category: "channels",
26
+ inputSchema,
27
+ requiresGuild: true,
28
+ permissions: ["ManageChannels"],
29
+ handle: async (input, ctx) => {
30
+ const guild = await ctx.discord.getGuild(input.guild_id);
31
+ const channel = await guild.channels.create({
32
+ name: input.name,
33
+ type: CHANNEL_TYPE_MAP[input.type],
34
+ topic: input.topic,
35
+ parent: input.parent_id,
36
+ });
37
+ return toolResultJson({
38
+ id: channel.id,
39
+ name: channel.name,
40
+ type: ChannelType[channel.type],
41
+ guild_id: guild.id,
42
+ parent_id: channel.parentId,
43
+ });
44
+ },
45
+ };
46
+ //# sourceMappingURL=create-channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-channel.js","sourceRoot":"","sources":["../../../src/tools/channels/create-channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAA0B,MAAM,YAAY,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAC9D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;IACzD,IAAI,EAAE,CAAC;SACJ,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;SACrE,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,cAAc,CAAC;IAC3B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;IAChE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;CAChF,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAsC;IAC1D,IAAI,EAAE,WAAW,CAAC,SAAS;IAC3B,KAAK,EAAE,WAAW,CAAC,UAAU;IAC7B,QAAQ,EAAE,WAAW,CAAC,aAAa;IACnC,YAAY,EAAE,WAAW,CAAC,iBAAiB;IAC3C,KAAK,EAAE,WAAW,CAAC,UAAU;IAC7B,KAAK,EAAE,WAAW,CAAC,eAAe;CACnC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAmB;IAC3C,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,kCAAkC;IAC/C,QAAQ,EAAE,UAAU;IACpB,WAAW;IACX,aAAa,EAAE,IAAI;IACnB,WAAW,EAAE,CAAC,gBAAgB,CAAC;IAC/B,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC3B,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAEzD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC1C,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAE;YACnC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,KAAK,CAAC,SAAS;SACxB,CAAC,CAAC;QAEH,OAAO,cAAc,CAAC;YACpB,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;YAC/B,QAAQ,EAAE,KAAK,CAAC,EAAE;YAClB,SAAS,EAAE,OAAO,CAAC,QAAQ;SAC5B,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDefinition } from "../types.js";
2
+ export declare const deleteChannel: ToolDefinition;
3
+ //# sourceMappingURL=delete-channel.d.ts.map