@mastra/discord 1.1.0 → 1.2.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/index.cjs +74 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +74 -16
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -83,7 +83,9 @@ interface DiscordProviderConfig {
|
|
|
83
83
|
* App credentials (bot token / public key / application id). May be omitted
|
|
84
84
|
* here and provided via the `DISCORD_BOT_TOKEN` / `DISCORD_PUBLIC_KEY` /
|
|
85
85
|
* `DISCORD_APPLICATION_ID` env vars, or later via {@link DiscordProvider.configure}.
|
|
86
|
-
*
|
|
86
|
+
* A bot token alone is enough: `publicKey` and `applicationId` are resolved
|
|
87
|
+
* from `GET /applications/@me` when omitted. Whichever source resolves first
|
|
88
|
+
* is persisted **once** to channels storage.
|
|
87
89
|
*/
|
|
88
90
|
app?: Partial<DiscordAppConfig>;
|
|
89
91
|
/**
|
|
@@ -333,7 +335,10 @@ declare class DiscordProvider implements ChannelProvider {
|
|
|
333
335
|
/**
|
|
334
336
|
* Provide or clear the app credentials at runtime. An object merges/overrides
|
|
335
337
|
* `botToken` / `publicKey` / `applicationId` (persisted on the next `connect`);
|
|
336
|
-
* `null` clears the stored app config.
|
|
338
|
+
* `null` clears the stored app config. Supplying a **different bot token**
|
|
339
|
+
* replaces the app config instead of merging: the token identifies the
|
|
340
|
+
* Discord application, so any `publicKey`/`applicationId` from the previous
|
|
341
|
+
* application must not survive the switch.
|
|
337
342
|
*/
|
|
338
343
|
configure(credentials: Partial<DiscordAppConfig> | null): Promise<void>;
|
|
339
344
|
/**
|
|
@@ -444,6 +449,12 @@ interface DiscordApplication {
|
|
|
444
449
|
id: string;
|
|
445
450
|
/** The application's name. */
|
|
446
451
|
name: string;
|
|
452
|
+
/**
|
|
453
|
+
* The Ed25519 public key used to verify interaction signatures. Discord
|
|
454
|
+
* includes it on every application object, so a bot token alone is enough to
|
|
455
|
+
* resolve the interaction-verification key.
|
|
456
|
+
*/
|
|
457
|
+
verify_key: string;
|
|
447
458
|
}
|
|
448
459
|
/**
|
|
449
460
|
* Call the Discord REST API with Bot-token auth. `method` is required; supplying
|
package/dist/index.d.ts
CHANGED
|
@@ -83,7 +83,9 @@ interface DiscordProviderConfig {
|
|
|
83
83
|
* App credentials (bot token / public key / application id). May be omitted
|
|
84
84
|
* here and provided via the `DISCORD_BOT_TOKEN` / `DISCORD_PUBLIC_KEY` /
|
|
85
85
|
* `DISCORD_APPLICATION_ID` env vars, or later via {@link DiscordProvider.configure}.
|
|
86
|
-
*
|
|
86
|
+
* A bot token alone is enough: `publicKey` and `applicationId` are resolved
|
|
87
|
+
* from `GET /applications/@me` when omitted. Whichever source resolves first
|
|
88
|
+
* is persisted **once** to channels storage.
|
|
87
89
|
*/
|
|
88
90
|
app?: Partial<DiscordAppConfig>;
|
|
89
91
|
/**
|
|
@@ -333,7 +335,10 @@ declare class DiscordProvider implements ChannelProvider {
|
|
|
333
335
|
/**
|
|
334
336
|
* Provide or clear the app credentials at runtime. An object merges/overrides
|
|
335
337
|
* `botToken` / `publicKey` / `applicationId` (persisted on the next `connect`);
|
|
336
|
-
* `null` clears the stored app config.
|
|
338
|
+
* `null` clears the stored app config. Supplying a **different bot token**
|
|
339
|
+
* replaces the app config instead of merging: the token identifies the
|
|
340
|
+
* Discord application, so any `publicKey`/`applicationId` from the previous
|
|
341
|
+
* application must not survive the switch.
|
|
337
342
|
*/
|
|
338
343
|
configure(credentials: Partial<DiscordAppConfig> | null): Promise<void>;
|
|
339
344
|
/**
|
|
@@ -444,6 +449,12 @@ interface DiscordApplication {
|
|
|
444
449
|
id: string;
|
|
445
450
|
/** The application's name. */
|
|
446
451
|
name: string;
|
|
452
|
+
/**
|
|
453
|
+
* The Ed25519 public key used to verify interaction signatures. Discord
|
|
454
|
+
* includes it on every application object, so a bot token alone is enough to
|
|
455
|
+
* resolve the interaction-verification key.
|
|
456
|
+
*/
|
|
457
|
+
verify_key: string;
|
|
447
458
|
}
|
|
448
459
|
/**
|
|
449
460
|
* Call the Discord REST API with Bot-token auth. `method` is required; supplying
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/discord-provider.ts","../src/install-store.ts","../src/discord-client.ts","../src/commands.ts","../src/crypto.ts"],"mappings":";;;;;;;;;;;;cAgBa;;cAGA;;;;;;;;cASA;WACX;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;;;;;;;;cAUW;;cAWA;;;;;;UAOI;;EAEf;;EAEA;;;KAIU;EAAiC;EAAc;;;;;;;;UAQ1C;;EAEf;;EAEA;;EAEA;;;;;;;;;;UAWe
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/discord-provider.ts","../src/install-store.ts","../src/discord-client.ts","../src/commands.ts","../src/crypto.ts"],"mappings":";;;;;;;;;;;;cAgBa;;cAGA;;;;;;;;cASA;WACX;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;;;;;;;;cAUW;;cAWA;;;;;;UAOI;;EAEf;;EAEA;;;KAIU;EAAiC;EAAc;;;;;;;;UAQ1C;;EAEf;;EAEA;;EAEA;;;;;;;;;;UAWe;;;;;;;;;EASf,MAAM,QAAQ;;;;;EAKd;;;;;;EAMA,UAAU;;;;;EAKV;;;;;;;EAOA;;;;;EAKA;;;;;;EAMA,WAAW;;;;;;;;;;EAUX;;;;;EAKA,YAAY;;;;;;;;EAQZ;;;;;EAKA;;;;;;EAMA,mBAAmB;;EAEnB,SAAS;;;;;;;;EAQT,YAAY;;;;;;EAMZ;;EASA,WAAW;;EAEX,cAAc;;EAEd,cAAc;;EAEd,QAAQ;;EAER,gBAAgB;;EAEhB,cAAc;;EAEd,oBAAoB;;EAEpB,mBAAmB;;EAEnB,OAAO;;EAEP,cAAc;;;;;;;;EAQd,cAAc;;;;;;;EAOd,QAAQ;;EAER,aAAa,cAAc,+BAA+B;;;UAI3C;;;;;;;EAOf;;EAEA;;;;;EAKA,WAAW;;EAEX;;;;;;;;;UAUe;;EAEf;;EAEA;;;;;EAKA;;;;;EAKA;;EAEA;;EAEA;;EAEA,WAAW;;;;;;EAMX,kBAAkB;;EAElB,aAAa;;;;;;;;;;;iBC/PC,4BACd,QAAQ,KAAK;EAEb,WAAW;EACX;EACA,aAAa;EACb;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmCW,2BAA2B;;WAC7B;EAoCT,YAAY,SAAQ;;;;;EAYpB,SAAS,QAAQ;;;;;;;;;EAwCjB,aAAa;;EAoBb,WAAW;;;;;;EAgCL,cAAc;;;;;;;;;EAiCd,UAAU,aAAa,QAAQ,2BAA2B;;;;;;;;;;;;;;EAmE1D,QAAQ,iBAAiB,UAAS,wBAA6B,QAAQ;;;;;;;EA6EvE,cAAc,mBAAmB,kBAAkB,QAAQ;;;;;;;;;;EAmD3D,WAAW,kBAAkB;;EAY7B,qBAAqB,QAAQ;;EAO7B,gBAAgB,kBAAkB,QAAQ;;EAMhD;;EAKA,WAAW,yBAAyB;;;;;cCvdzB;;;;;;;;;;;;;cAgCA;;mBAEQ;mBACA;EAFnB,YACmB,SAAS,iBACT;;EAMb,gBAAgB,QAAQ;;EAaxB,cAAc,KAAK,mBAAmB;;EAUtC,mBAAmB;;EAOnB,WAAW,kBAAkB,QAAQ;;EAMrC,eAAe,oBAAoB,QAAQ;;;;;;;;;;;;;;;;EAoB3C,aAAa,kBAAkB,QAAQ;;EAqBvC,KAAK,cAAc,sBAAsB;;EAKzC,QAAQ,QAAQ;;EAMhB,cAAc,kBAAkB;;;iBA6DxB,mBAAmB,SAAS,sBAAsB;;;;;;;;UC/JjD;;EAEf;;EAEA;;;;;;EAMA;;;;;;;;;;;;iBAmBoB,eACpB,kBACA,gBACA,cACA,qBACA,iBACC,QAAQ;;;;;;;iBA+BW,YACpB,kBACA,sBACC,QAAQ;;;;;;;;;;;;;;iBAyBW,iBACpB,kBACA,iBACA,sBACC;;;;;;;;iBA8EmB,sBACpB,kBACA,uBACA,iBACA,mBAAmB,kBACnB,sBACC;;;;;;;;iBAcmB,uBACpB,kBACA,uBACA,mBAAmB,kBACnB,sBACC;;UAOc;;EAEf;;EAEA;;EAEA;;;;;EAKA;;;;;;;;;iBAUc,eAAe,SAAS;;;;;;;;;cCjQ3B,2BAA2B;;;;;;;;;;iBAaxB,kBAAkB,cAAc,oCAAoC;;;;;;;iBAyBpE,aAAa,mBAAmB;;;;iBC3BhC,YAAY;;iBAKZ,QAAQ,mBAAmB;;iBAU3B,QAAQ,eAAe"}
|
package/dist/index.js
CHANGED
|
@@ -548,7 +548,7 @@ var DiscordProvider = class {
|
|
|
548
548
|
#storeGeneration = 0;
|
|
549
549
|
constructor(config = {}) {
|
|
550
550
|
this.#config = config;
|
|
551
|
-
this.#configured = this.#
|
|
551
|
+
this.#configured = this.#hasSuppliedCredentials();
|
|
552
552
|
}
|
|
553
553
|
/**
|
|
554
554
|
* Called by Mastra when this channel is registered.
|
|
@@ -565,7 +565,7 @@ var DiscordProvider = class {
|
|
|
565
565
|
}
|
|
566
566
|
if (isNewInstance) {
|
|
567
567
|
this.#adapters.clear();
|
|
568
|
-
this.#configured = this.#
|
|
568
|
+
this.#configured = this.#hasSuppliedCredentials();
|
|
569
569
|
}
|
|
570
570
|
this.#mastra = mastra;
|
|
571
571
|
}
|
|
@@ -637,7 +637,7 @@ var DiscordProvider = class {
|
|
|
637
637
|
async #doInitialize() {
|
|
638
638
|
const store = await this.#getStore();
|
|
639
639
|
const active = (await store.list()).filter((i) => i.status === "active");
|
|
640
|
-
const hasApp = await store.getAppConfig() != null || this.#
|
|
640
|
+
const hasApp = await store.getAppConfig() != null || this.#hasSuppliedCredentials();
|
|
641
641
|
this.#configured = hasApp || active.length > 0;
|
|
642
642
|
for (const installation of active) try {
|
|
643
643
|
await this.#activateInstallation(installation);
|
|
@@ -648,7 +648,10 @@ var DiscordProvider = class {
|
|
|
648
648
|
/**
|
|
649
649
|
* Provide or clear the app credentials at runtime. An object merges/overrides
|
|
650
650
|
* `botToken` / `publicKey` / `applicationId` (persisted on the next `connect`);
|
|
651
|
-
* `null` clears the stored app config.
|
|
651
|
+
* `null` clears the stored app config. Supplying a **different bot token**
|
|
652
|
+
* replaces the app config instead of merging: the token identifies the
|
|
653
|
+
* Discord application, so any `publicKey`/`applicationId` from the previous
|
|
654
|
+
* application must not survive the switch.
|
|
652
655
|
*/
|
|
653
656
|
async configure(credentials) {
|
|
654
657
|
if (credentials === null) {
|
|
@@ -670,7 +673,7 @@ var DiscordProvider = class {
|
|
|
670
673
|
...credentials
|
|
671
674
|
}
|
|
672
675
|
};
|
|
673
|
-
this.#configured = this.#
|
|
676
|
+
this.#configured = this.#hasSuppliedCredentials() || this.#configured;
|
|
674
677
|
if (![
|
|
675
678
|
"botToken",
|
|
676
679
|
"publicKey",
|
|
@@ -678,7 +681,14 @@ var DiscordProvider = class {
|
|
|
678
681
|
].some((k) => credentials[k] !== void 0 && credentials[k] !== previous?.[k])) return;
|
|
679
682
|
const store = await this.#getStore();
|
|
680
683
|
const stored = await store.getAppConfig();
|
|
681
|
-
|
|
684
|
+
const tokenSupersedes = (base) => credentials.botToken !== void 0 && base?.botToken !== void 0 && base.botToken !== credentials.botToken;
|
|
685
|
+
if (tokenSupersedes(previous) || tokenSupersedes(stored)) {
|
|
686
|
+
this.#config = {
|
|
687
|
+
...this.#config,
|
|
688
|
+
app: { ...credentials }
|
|
689
|
+
};
|
|
690
|
+
await store.deleteAppConfig();
|
|
691
|
+
} else if (stored) {
|
|
682
692
|
const merged = {
|
|
683
693
|
...stored,
|
|
684
694
|
...credentials
|
|
@@ -707,8 +717,8 @@ var DiscordProvider = class {
|
|
|
707
717
|
const store = await this.#getStore();
|
|
708
718
|
const existing = await store.getByAgent(agentId);
|
|
709
719
|
if (existing?.status === "active") throw new Error(`Agent "${agentId}" is already connected to Discord. Disconnect first to reconnect. To add another server, invite the bot with the existing URL — new guilds activate on first use.`);
|
|
710
|
-
const { app, persisted } = await this.#resolveAppConfig(store);
|
|
711
|
-
const identity = await validateApp(app.botToken, this.#apiBaseUrl());
|
|
720
|
+
const { app, persisted, identity: resolvedIdentity } = await this.#resolveAppConfig(store);
|
|
721
|
+
const identity = resolvedIdentity ?? await validateApp(app.botToken, this.#apiBaseUrl());
|
|
712
722
|
if (!persisted) await store.saveAppConfig(app);
|
|
713
723
|
const installationId = existing?.id ?? randomUUID();
|
|
714
724
|
const webhookId = existing?.webhookId ?? randomUUID();
|
|
@@ -975,12 +985,33 @@ var DiscordProvider = class {
|
|
|
975
985
|
return;
|
|
976
986
|
}
|
|
977
987
|
}
|
|
988
|
+
/**
|
|
989
|
+
* App credentials from provider config or `DISCORD_*` env.
|
|
990
|
+
*
|
|
991
|
+
* A config-supplied bot token defines the application identity, so
|
|
992
|
+
* `publicKey` / `applicationId` never fall back to the environment in that
|
|
993
|
+
* case — stale `DISCORD_PUBLIC_KEY` / `DISCORD_APPLICATION_ID` from a
|
|
994
|
+
* *different* application would otherwise complete the config and keep that
|
|
995
|
+
* application's Ed25519 key trusted for webhook verification (bypassing the
|
|
996
|
+
* `GET /applications/@me` backfill). Env fallback for those fields applies
|
|
997
|
+
* only when the bot token itself comes from the environment.
|
|
998
|
+
*/
|
|
999
|
+
#suppliedPartialAppConfig() {
|
|
1000
|
+
const a = this.#config.app ?? {};
|
|
1001
|
+
if (a.botToken != null) return {
|
|
1002
|
+
botToken: a.botToken,
|
|
1003
|
+
publicKey: a.publicKey,
|
|
1004
|
+
applicationId: a.applicationId
|
|
1005
|
+
};
|
|
1006
|
+
return {
|
|
1007
|
+
botToken: process.env.DISCORD_BOT_TOKEN,
|
|
1008
|
+
publicKey: a.publicKey ?? process.env.DISCORD_PUBLIC_KEY,
|
|
1009
|
+
applicationId: a.applicationId ?? process.env.DISCORD_APPLICATION_ID
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
978
1012
|
/** App credentials from provider config or `DISCORD_*` env, or `null` if incomplete. */
|
|
979
1013
|
#suppliedAppConfig() {
|
|
980
|
-
const
|
|
981
|
-
const botToken = a.botToken ?? process.env.DISCORD_BOT_TOKEN;
|
|
982
|
-
const publicKey = a.publicKey ?? process.env.DISCORD_PUBLIC_KEY;
|
|
983
|
-
const applicationId = a.applicationId ?? process.env.DISCORD_APPLICATION_ID;
|
|
1014
|
+
const { botToken, publicKey, applicationId } = this.#suppliedPartialAppConfig();
|
|
984
1015
|
if (botToken && publicKey && applicationId) return {
|
|
985
1016
|
botToken,
|
|
986
1017
|
publicKey,
|
|
@@ -989,10 +1020,22 @@ var DiscordProvider = class {
|
|
|
989
1020
|
return null;
|
|
990
1021
|
}
|
|
991
1022
|
/**
|
|
1023
|
+
* Whether credentials are resolvable without storage. A bot token alone is
|
|
1024
|
+
* enough: `applicationId` and `publicKey` are backfilled from
|
|
1025
|
+
* `GET /applications/@me` by {@link #resolveAppConfig}.
|
|
1026
|
+
*/
|
|
1027
|
+
#hasSuppliedCredentials() {
|
|
1028
|
+
return this.#suppliedPartialAppConfig().botToken != null;
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
992
1031
|
* Resolve the app config: prefer the stored one, else the supplied credentials
|
|
993
|
-
* (config / `DISCORD_*` env). `
|
|
994
|
-
*
|
|
995
|
-
*
|
|
1032
|
+
* (config / `DISCORD_*` env). A supplied `botToken` without `publicKey` /
|
|
1033
|
+
* `applicationId` is completed from `GET /applications/@me` — the application
|
|
1034
|
+
* object carries both the id and the Ed25519 `verify_key`. `persisted` says
|
|
1035
|
+
* whether it's already in storage, so the caller can persist supplied
|
|
1036
|
+
* credentials **once**, after validation. `identity` is set when the token was
|
|
1037
|
+
* already validated against `/applications/@me` here, so callers can skip a
|
|
1038
|
+
* second validation call. Throws if no credentials are available.
|
|
996
1039
|
*/
|
|
997
1040
|
async #resolveAppConfig(store) {
|
|
998
1041
|
const stored = await store.getAppConfig();
|
|
@@ -1005,7 +1048,22 @@ var DiscordProvider = class {
|
|
|
1005
1048
|
app: supplied,
|
|
1006
1049
|
persisted: false
|
|
1007
1050
|
};
|
|
1008
|
-
|
|
1051
|
+
const partial = this.#suppliedPartialAppConfig();
|
|
1052
|
+
if (partial.botToken) {
|
|
1053
|
+
const identity = await validateApp(partial.botToken, this.#apiBaseUrl());
|
|
1054
|
+
const publicKey = partial.publicKey ?? identity.verify_key;
|
|
1055
|
+
if (!publicKey) throw new Error("Discord /applications/@me returned no verify_key; provide publicKey explicitly.");
|
|
1056
|
+
return {
|
|
1057
|
+
app: {
|
|
1058
|
+
botToken: partial.botToken,
|
|
1059
|
+
publicKey,
|
|
1060
|
+
applicationId: partial.applicationId ?? identity.id
|
|
1061
|
+
},
|
|
1062
|
+
persisted: false,
|
|
1063
|
+
identity
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
throw new Error("Discord app is not configured. Provide at least a botToken via the provider `app` option, the DISCORD_BOT_TOKEN env var, or configure() — publicKey and applicationId are resolved from Discord automatically when omitted. Discord applications are created in the Developer Portal, not programmatically.");
|
|
1009
1067
|
}
|
|
1010
1068
|
/**
|
|
1011
1069
|
* The single entry point to the store. Every caller either gets the cached
|