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.
- package/CHANGELOG.md +16 -0
- package/LICENSE +21 -0
- package/README.md +150 -0
- package/dist/cli/health.d.ts +2 -0
- package/dist/cli/health.d.ts.map +1 -0
- package/dist/cli/health.js +2 -0
- package/dist/cli/health.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +98 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/client.d.ts +22 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +87 -0
- package/dist/client.js.map +1 -0
- package/dist/config/index.d.ts +17 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +58 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/profiles.d.ts +18 -0
- package/dist/config/profiles.d.ts.map +1 -0
- package/dist/config/profiles.js +28 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/schema.d.ts +76 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +29 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/routing/fuzzy.d.ts +16 -0
- package/dist/routing/fuzzy.d.ts.map +1 -0
- package/dist/routing/fuzzy.js +67 -0
- package/dist/routing/fuzzy.js.map +1 -0
- package/dist/routing/resolver.d.ts +31 -0
- package/dist/routing/resolver.d.ts.map +1 -0
- package/dist/routing/resolver.js +60 -0
- package/dist/routing/resolver.js.map +1 -0
- package/dist/security/audit.d.ts +9 -0
- package/dist/security/audit.d.ts.map +1 -0
- package/dist/security/audit.js +20 -0
- package/dist/security/audit.js.map +1 -0
- package/dist/security/permissions.d.ts +6 -0
- package/dist/security/permissions.d.ts.map +1 -0
- package/dist/security/permissions.js +15 -0
- package/dist/security/permissions.js.map +1 -0
- package/dist/security/rate-limiter.d.ts +16 -0
- package/dist/security/rate-limiter.d.ts.map +1 -0
- package/dist/security/rate-limiter.js +36 -0
- package/dist/security/rate-limiter.js.map +1 -0
- package/dist/security/sanitizer.d.ts +5 -0
- package/dist/security/sanitizer.d.ts.map +1 -0
- package/dist/security/sanitizer.js +26 -0
- package/dist/security/sanitizer.js.map +1 -0
- package/dist/security/token-validator.d.ts +9 -0
- package/dist/security/token-validator.d.ts.map +1 -0
- package/dist/security/token-validator.js +18 -0
- package/dist/security/token-validator.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +64 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/channels/create-channel.d.ts +3 -0
- package/dist/tools/channels/create-channel.d.ts.map +1 -0
- package/dist/tools/channels/create-channel.js +46 -0
- package/dist/tools/channels/create-channel.js.map +1 -0
- package/dist/tools/channels/delete-channel.d.ts +3 -0
- package/dist/tools/channels/delete-channel.d.ts.map +1 -0
- package/dist/tools/channels/delete-channel.js +20 -0
- package/dist/tools/channels/delete-channel.js.map +1 -0
- package/dist/tools/channels/edit-channel.d.ts +3 -0
- package/dist/tools/channels/edit-channel.d.ts.map +1 -0
- package/dist/tools/channels/edit-channel.js +32 -0
- package/dist/tools/channels/edit-channel.js.map +1 -0
- package/dist/tools/channels/get-channel.d.ts +3 -0
- package/dist/tools/channels/get-channel.d.ts.map +1 -0
- package/dist/tools/channels/get-channel.js +34 -0
- package/dist/tools/channels/get-channel.js.map +1 -0
- package/dist/tools/channels/index.d.ts +6 -0
- package/dist/tools/channels/index.d.ts.map +1 -0
- package/dist/tools/channels/index.js +6 -0
- package/dist/tools/channels/index.js.map +1 -0
- package/dist/tools/channels/list-channels.d.ts +3 -0
- package/dist/tools/channels/list-channels.d.ts.map +1 -0
- package/dist/tools/channels/list-channels.js +47 -0
- package/dist/tools/channels/list-channels.js.map +1 -0
- package/dist/tools/guilds/get-guild.d.ts +3 -0
- package/dist/tools/guilds/get-guild.d.ts.map +1 -0
- package/dist/tools/guilds/get-guild.js +30 -0
- package/dist/tools/guilds/get-guild.js.map +1 -0
- package/dist/tools/guilds/index.d.ts +3 -0
- package/dist/tools/guilds/index.d.ts.map +1 -0
- package/dist/tools/guilds/index.js +3 -0
- package/dist/tools/guilds/index.js.map +1 -0
- package/dist/tools/guilds/list-guilds.d.ts +3 -0
- package/dist/tools/guilds/list-guilds.d.ts.map +1 -0
- package/dist/tools/guilds/list-guilds.js +25 -0
- package/dist/tools/guilds/list-guilds.js.map +1 -0
- package/dist/tools/health-check.d.ts +3 -0
- package/dist/tools/health-check.d.ts.map +1 -0
- package/dist/tools/health-check.js +45 -0
- package/dist/tools/health-check.js.map +1 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +46 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/members/get-member.d.ts +3 -0
- package/dist/tools/members/get-member.d.ts.map +1 -0
- package/dist/tools/members/get-member.js +30 -0
- package/dist/tools/members/get-member.js.map +1 -0
- package/dist/tools/members/index.d.ts +3 -0
- package/dist/tools/members/index.d.ts.map +1 -0
- package/dist/tools/members/index.js +3 -0
- package/dist/tools/members/index.js.map +1 -0
- package/dist/tools/members/list-members.d.ts +3 -0
- package/dist/tools/members/list-members.d.ts.map +1 -0
- package/dist/tools/members/list-members.js +32 -0
- package/dist/tools/members/list-members.js.map +1 -0
- package/dist/tools/messaging/add-reaction.d.ts +3 -0
- package/dist/tools/messaging/add-reaction.d.ts.map +1 -0
- package/dist/tools/messaging/add-reaction.js +28 -0
- package/dist/tools/messaging/add-reaction.js.map +1 -0
- package/dist/tools/messaging/delete-message.d.ts +3 -0
- package/dist/tools/messaging/delete-message.d.ts.map +1 -0
- package/dist/tools/messaging/delete-message.js +28 -0
- package/dist/tools/messaging/delete-message.js.map +1 -0
- package/dist/tools/messaging/edit-message.d.ts +3 -0
- package/dist/tools/messaging/edit-message.d.ts.map +1 -0
- package/dist/tools/messaging/edit-message.js +33 -0
- package/dist/tools/messaging/edit-message.js.map +1 -0
- package/dist/tools/messaging/get-messages.d.ts +3 -0
- package/dist/tools/messaging/get-messages.d.ts.map +1 -0
- package/dist/tools/messaging/get-messages.js +48 -0
- package/dist/tools/messaging/get-messages.js.map +1 -0
- package/dist/tools/messaging/index.d.ts +6 -0
- package/dist/tools/messaging/index.d.ts.map +1 -0
- package/dist/tools/messaging/index.js +6 -0
- package/dist/tools/messaging/index.js.map +1 -0
- package/dist/tools/messaging/send-message.d.ts +3 -0
- package/dist/tools/messaging/send-message.d.ts.map +1 -0
- package/dist/tools/messaging/send-message.js +40 -0
- package/dist/tools/messaging/send-message.js.map +1 -0
- package/dist/tools/roles/index.d.ts +2 -0
- package/dist/tools/roles/index.d.ts.map +1 -0
- package/dist/tools/roles/index.js +2 -0
- package/dist/tools/roles/index.js.map +1 -0
- package/dist/tools/roles/list-roles.d.ts +3 -0
- package/dist/tools/roles/list-roles.d.ts.map +1 -0
- package/dist/tools/roles/list-roles.js +32 -0
- package/dist/tools/roles/list-roles.js.map +1 -0
- package/dist/tools/threads/create-thread.d.ts +3 -0
- package/dist/tools/threads/create-thread.d.ts.map +1 -0
- package/dist/tools/threads/create-thread.js +46 -0
- package/dist/tools/threads/create-thread.js.map +1 -0
- package/dist/tools/threads/index.d.ts +3 -0
- package/dist/tools/threads/index.d.ts.map +1 -0
- package/dist/tools/threads/index.js +3 -0
- package/dist/tools/threads/index.js.map +1 -0
- package/dist/tools/threads/list-threads.d.ts +3 -0
- package/dist/tools/threads/list-threads.d.ts.map +1 -0
- package/dist/tools/threads/list-threads.js +33 -0
- package/dist/tools/threads/list-threads.js.map +1 -0
- package/dist/tools/types.d.ts +29 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +10 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/transport/stdio.d.ts +3 -0
- package/dist/transport/stdio.d.ts.map +1 -0
- package/dist/transport/stdio.js +8 -0
- package/dist/transport/stdio.js.map +1 -0
- package/dist/utils/cache.d.ts +10 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +27 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +32 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/retry.d.ts +7 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +27 -0
- package/dist/utils/retry.js.map +1 -0
- 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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|
package/dist/server.d.ts
ADDED
|
@@ -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 @@
|
|
|
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"}
|