@helyx/bot 1.5.4 → 1.7.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 +19 -0
- package/README.md +5 -2
- package/command-root-catalogue.json +21 -5
- package/dist/cloud-connector.js +2 -0
- package/dist/cloud-control-dispatcher.js +20 -0
- package/dist/command-registration-policy.js +2 -0
- package/dist/control-directory-contracts.d.ts +50 -0
- package/dist/control-directory-contracts.js +2 -0
- package/dist/control-server-schemas.d.ts +3 -3
- package/dist/control-server.d.ts +10 -46
- package/dist/control-server.js +50 -3
- package/dist/creator-invite-service.d.ts +7 -0
- package/dist/creator-invite-service.js +17 -0
- package/dist/developer-operations-module.js +0 -55
- package/dist/diagnostic-command.js +1 -0
- package/dist/discord-guild-health.d.ts +2 -2
- package/dist/discord-guild-health.js +1 -0
- package/dist/events.d.ts +1 -0
- package/dist/events.js +2 -0
- package/dist/help-credentials.d.ts +25 -0
- package/dist/help-credentials.js +149 -0
- package/dist/help-module.d.ts +27 -0
- package/dist/help-module.js +288 -0
- package/dist/help-runtime.d.ts +3 -0
- package/dist/help-runtime.js +42 -0
- package/dist/help-transport.d.ts +53 -0
- package/dist/help-transport.js +267 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +10 -0
- package/dist/interactions.js +10 -6
- package/dist/process-info-module.d.ts +3 -0
- package/dist/process-info-module.js +97 -0
- package/dist/server-overview-control.d.ts +35 -0
- package/dist/server-overview-control.js +362 -0
- package/dist/server-overview-discord.d.ts +33 -0
- package/dist/server-overview-discord.js +212 -0
- package/dist/server-overview-profile.d.ts +8 -0
- package/dist/server-overview-profile.js +62 -0
- package/dist/server-overview-routes.d.ts +4 -0
- package/dist/server-overview-routes.js +41 -0
- package/dist/shard-contracts.d.ts +66 -0
- package/dist/shard-contracts.js +23 -0
- package/dist/shard-coordinator.d.ts +1 -1
- package/dist/shard-router.d.ts +9 -0
- package/dist/shard-router.js +6 -0
- package/dist/shard-supervisor.d.ts +1 -1
- package/dist/shard-supervisor.js +8 -0
- package/dist/shard-worker.d.ts +1 -1
- package/dist/shard-worker.js +8 -0
- package/dist/verification-service.d.ts +4 -0
- package/dist/verification-service.js +10 -0
- package/documentation/README.md +1 -0
- package/documentation/examples/.env.example +29 -85
- package/documentation/guides/help-command.md +62 -0
- package/documentation/reference/environment.md +7 -6
- package/documentation/runbooks/installation-and-upgrades.md +4 -1
- package/package.json +6 -6
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ServerOverviewControl } from "@helyx/control-protocol";
|
|
2
|
+
import type { FastifyInstance } from "fastify";
|
|
3
|
+
export declare function registerServerOverviewControlRoutes(server: FastifyInstance, control: ServerOverviewControl): void;
|
|
4
|
+
//# sourceMappingURL=server-overview-routes.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { overviewReadInputSchema, overviewRevokeInputSchema, } from "@helyx/control-protocol";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { BotControlTransportError } from "./control-errors.js";
|
|
4
|
+
export function registerServerOverviewControlRoutes(server, control) {
|
|
5
|
+
const actor = z.string().regex(/^\d{17,20}$/u);
|
|
6
|
+
server.post("/v1/guilds/:guildId/overview", async (request) => {
|
|
7
|
+
const { guildId } = z
|
|
8
|
+
.object({ guildId: actor })
|
|
9
|
+
.strict()
|
|
10
|
+
.parse(request.params);
|
|
11
|
+
const raw = z
|
|
12
|
+
.object({ actorUserId: actor })
|
|
13
|
+
.passthrough()
|
|
14
|
+
.parse(request.body);
|
|
15
|
+
const { actorUserId, ...query } = raw;
|
|
16
|
+
const input = overviewReadInputSchema.parse({ ...query, guildId });
|
|
17
|
+
if (query.guildId !== undefined && query.guildId !== guildId)
|
|
18
|
+
throw new BotControlTransportError(400, "Server scope does not match");
|
|
19
|
+
if (!control.readServerOverview)
|
|
20
|
+
throw new BotControlTransportError(503, "Overview is unavailable");
|
|
21
|
+
return control.readServerOverview({ ...input, actorUserId });
|
|
22
|
+
});
|
|
23
|
+
server.post("/v1/guilds/:guildId/overview/invites/revoke", async (request) => {
|
|
24
|
+
const { guildId } = z
|
|
25
|
+
.object({ guildId: actor })
|
|
26
|
+
.strict()
|
|
27
|
+
.parse(request.params);
|
|
28
|
+
const raw = z
|
|
29
|
+
.object({ actorUserId: actor })
|
|
30
|
+
.passthrough()
|
|
31
|
+
.parse(request.body);
|
|
32
|
+
const { actorUserId, ...query } = raw;
|
|
33
|
+
const input = overviewRevokeInputSchema.parse({ ...query, guildId });
|
|
34
|
+
if (query.guildId !== undefined && query.guildId !== guildId)
|
|
35
|
+
throw new BotControlTransportError(400, "Server scope does not match");
|
|
36
|
+
if (!control.revokeServerOverviewInvite)
|
|
37
|
+
throw new BotControlTransportError(503, "Invite management is unavailable");
|
|
38
|
+
return control.revokeServerOverviewInvite({ ...input, actorUserId });
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=server-overview-routes.js.map
|
|
@@ -239,6 +239,28 @@ export declare const shardControlOperationSchema: z.ZodDiscriminatedUnion<[z.Zod
|
|
|
239
239
|
}, z.core.$strict>, z.ZodObject<{
|
|
240
240
|
kind: z.ZodLiteral<"guild.state.get">;
|
|
241
241
|
guildId: z.ZodString;
|
|
242
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
243
|
+
guildId: z.ZodString;
|
|
244
|
+
operation: z.ZodEnum<{
|
|
245
|
+
summary: "summary";
|
|
246
|
+
members: "members";
|
|
247
|
+
member: "member";
|
|
248
|
+
invites: "invites";
|
|
249
|
+
}>;
|
|
250
|
+
memberId: z.ZodOptional<z.ZodString>;
|
|
251
|
+
refresh: z.ZodOptional<z.ZodBoolean>;
|
|
252
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
253
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
254
|
+
search: z.ZodOptional<z.ZodString>;
|
|
255
|
+
roleId: z.ZodOptional<z.ZodString>;
|
|
256
|
+
kind: z.ZodLiteral<"guild.overview.read">;
|
|
257
|
+
actorUserId: z.ZodString;
|
|
258
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
259
|
+
guildId: z.ZodString;
|
|
260
|
+
code: z.ZodString;
|
|
261
|
+
confirmed: z.ZodLiteral<true>;
|
|
262
|
+
kind: z.ZodLiteral<"guild.overview.invite.revoke">;
|
|
263
|
+
actorUserId: z.ZodString;
|
|
242
264
|
}, z.core.$strict>, z.ZodObject<{
|
|
243
265
|
guildId: z.ZodString;
|
|
244
266
|
userIds: z.ZodArray<z.ZodString>;
|
|
@@ -742,6 +764,28 @@ export declare const shardControlRequestSchema: z.ZodObject<{
|
|
|
742
764
|
}, z.core.$strict>, z.ZodObject<{
|
|
743
765
|
kind: z.ZodLiteral<"guild.state.get">;
|
|
744
766
|
guildId: z.ZodString;
|
|
767
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
768
|
+
guildId: z.ZodString;
|
|
769
|
+
operation: z.ZodEnum<{
|
|
770
|
+
summary: "summary";
|
|
771
|
+
members: "members";
|
|
772
|
+
member: "member";
|
|
773
|
+
invites: "invites";
|
|
774
|
+
}>;
|
|
775
|
+
memberId: z.ZodOptional<z.ZodString>;
|
|
776
|
+
refresh: z.ZodOptional<z.ZodBoolean>;
|
|
777
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
778
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
779
|
+
search: z.ZodOptional<z.ZodString>;
|
|
780
|
+
roleId: z.ZodOptional<z.ZodString>;
|
|
781
|
+
kind: z.ZodLiteral<"guild.overview.read">;
|
|
782
|
+
actorUserId: z.ZodString;
|
|
783
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
784
|
+
guildId: z.ZodString;
|
|
785
|
+
code: z.ZodString;
|
|
786
|
+
confirmed: z.ZodLiteral<true>;
|
|
787
|
+
kind: z.ZodLiteral<"guild.overview.invite.revoke">;
|
|
788
|
+
actorUserId: z.ZodString;
|
|
745
789
|
}, z.core.$strict>, z.ZodObject<{
|
|
746
790
|
guildId: z.ZodString;
|
|
747
791
|
userIds: z.ZodArray<z.ZodString>;
|
|
@@ -1765,6 +1809,28 @@ export declare const supervisorMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObje
|
|
|
1765
1809
|
}, z.core.$strict>, z.ZodObject<{
|
|
1766
1810
|
kind: z.ZodLiteral<"guild.state.get">;
|
|
1767
1811
|
guildId: z.ZodString;
|
|
1812
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1813
|
+
guildId: z.ZodString;
|
|
1814
|
+
operation: z.ZodEnum<{
|
|
1815
|
+
summary: "summary";
|
|
1816
|
+
members: "members";
|
|
1817
|
+
member: "member";
|
|
1818
|
+
invites: "invites";
|
|
1819
|
+
}>;
|
|
1820
|
+
memberId: z.ZodOptional<z.ZodString>;
|
|
1821
|
+
refresh: z.ZodOptional<z.ZodBoolean>;
|
|
1822
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
1823
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
1824
|
+
search: z.ZodOptional<z.ZodString>;
|
|
1825
|
+
roleId: z.ZodOptional<z.ZodString>;
|
|
1826
|
+
kind: z.ZodLiteral<"guild.overview.read">;
|
|
1827
|
+
actorUserId: z.ZodString;
|
|
1828
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1829
|
+
guildId: z.ZodString;
|
|
1830
|
+
code: z.ZodString;
|
|
1831
|
+
confirmed: z.ZodLiteral<true>;
|
|
1832
|
+
kind: z.ZodLiteral<"guild.overview.invite.revoke">;
|
|
1833
|
+
actorUserId: z.ZodString;
|
|
1768
1834
|
}, z.core.$strict>, z.ZodObject<{
|
|
1769
1835
|
guildId: z.ZodString;
|
|
1770
1836
|
userIds: z.ZodArray<z.ZodString>;
|
package/dist/shard-contracts.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { overviewReadInputSchema, overviewRevokeInputSchema, } from "@helyx/control-protocol";
|
|
2
3
|
import { discordUserIdentityRequestSchema } from "@helyx/control-protocol/discord-user-identities";
|
|
3
4
|
import { dashboardFieldValidationSchema } from "@helyx/control-protocol/field-validation";
|
|
4
5
|
import { channelAuditModuleIdSchema, channelAuditInputSchema, channelAuditConfigurationSchema, channelAuditReportSchema, } from "@helyx/control-protocol/channel-audit";
|
|
@@ -299,6 +300,14 @@ export const shardControlOperationSchema = z.discriminatedUnion("kind", [
|
|
|
299
300
|
})
|
|
300
301
|
.strict(),
|
|
301
302
|
z.object({ kind: z.literal("guild.state.get"), guildId: snowflake }).strict(),
|
|
303
|
+
overviewReadInputSchema.safeExtend({
|
|
304
|
+
kind: z.literal("guild.overview.read"),
|
|
305
|
+
actorUserId: snowflake,
|
|
306
|
+
}),
|
|
307
|
+
overviewRevokeInputSchema.extend({
|
|
308
|
+
kind: z.literal("guild.overview.invite.revoke"),
|
|
309
|
+
actorUserId: snowflake,
|
|
310
|
+
}),
|
|
302
311
|
discordUserIdentityRequestSchema.extend({
|
|
303
312
|
kind: z.literal("guild.user-identities.read"),
|
|
304
313
|
}),
|
|
@@ -1107,6 +1116,20 @@ export async function executeShardControlOperation(handler, operation) {
|
|
|
1107
1116
|
});
|
|
1108
1117
|
case "guild.state.get":
|
|
1109
1118
|
return handler.getGuildState(operation.guildId);
|
|
1119
|
+
case "guild.overview.read": {
|
|
1120
|
+
if (!handler.readServerOverview)
|
|
1121
|
+
throw new Error("Overview is unavailable");
|
|
1122
|
+
const { kind: _kind, ...input } = operation;
|
|
1123
|
+
void _kind;
|
|
1124
|
+
return handler.readServerOverview(input);
|
|
1125
|
+
}
|
|
1126
|
+
case "guild.overview.invite.revoke": {
|
|
1127
|
+
if (!handler.revokeServerOverviewInvite)
|
|
1128
|
+
throw new Error("Invite management is unavailable");
|
|
1129
|
+
const { kind: _kind, ...input } = operation;
|
|
1130
|
+
void _kind;
|
|
1131
|
+
return handler.revokeServerOverviewInvite(input);
|
|
1132
|
+
}
|
|
1110
1133
|
case "guild.user-identities.read": {
|
|
1111
1134
|
if (!handler.resolveDiscordUserIdentities)
|
|
1112
1135
|
throw new Error("Discord identity lookup is unavailable");
|
|
@@ -5,9 +5,9 @@ declare const generationDescriptorSchema: z.ZodObject<{
|
|
|
5
5
|
version: z.ZodLiteral<1>;
|
|
6
6
|
applicationId: z.ZodString;
|
|
7
7
|
environment: z.ZodEnum<{
|
|
8
|
-
production: "production";
|
|
9
8
|
development: "development";
|
|
10
9
|
test: "test";
|
|
10
|
+
production: "production";
|
|
11
11
|
}>;
|
|
12
12
|
generation: z.ZodString;
|
|
13
13
|
shardCount: z.ZodNumber;
|
package/dist/shard-router.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { OverviewReadInput, OverviewRevokeInput, OverviewResponse } from "@helyx/control-protocol";
|
|
1
2
|
import type { DiscordUserIdentityRequest, DiscordUserIdentityResponse } from "@helyx/control-protocol/discord-user-identities";
|
|
2
3
|
import { type AutoModerationEnhancedResultOutcome, type CreatorOnboardingRequest, type CreatorOnboardingResponse } from "@helyx/sdk";
|
|
3
4
|
import { type BotControlHandler } from "./control-server.js";
|
|
@@ -9,6 +10,14 @@ type LocalDispatcher = (shardId: number, request: ShardControlRequest) => Promis
|
|
|
9
10
|
export declare class ShardControlRouter implements BotControlHandler {
|
|
10
11
|
#private;
|
|
11
12
|
private readonly input;
|
|
13
|
+
readServerOverview(input: OverviewReadInput & {
|
|
14
|
+
actorUserId: string;
|
|
15
|
+
}): Promise<OverviewResponse>;
|
|
16
|
+
revokeServerOverviewInvite(input: OverviewRevokeInput & {
|
|
17
|
+
actorUserId: string;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
revoked: true;
|
|
20
|
+
}>;
|
|
12
21
|
creatorOnboarding(input: CreatorOnboardingRequest): Promise<CreatorOnboardingResponse>;
|
|
13
22
|
constructor(input: {
|
|
14
23
|
generation: string;
|
package/dist/shard-router.js
CHANGED
|
@@ -11,6 +11,12 @@ const LEASE_VALIDATION_TIMEOUT_MS = 3_000;
|
|
|
11
11
|
const ECKO_RESULT_TIMEOUT_MS = AUTOMOD_SCANNER_LIMITS.resultAcknowledgementSeconds * 1_000;
|
|
12
12
|
export class ShardControlRouter {
|
|
13
13
|
input;
|
|
14
|
+
readServerOverview(input) {
|
|
15
|
+
return this.#route({ kind: "guild.overview.read", ...input });
|
|
16
|
+
}
|
|
17
|
+
revokeServerOverviewInvite(input) {
|
|
18
|
+
return this.#route({ kind: "guild.overview.invite.revoke", ...input });
|
|
19
|
+
}
|
|
14
20
|
creatorOnboarding(input) {
|
|
15
21
|
return this.#route({
|
|
16
22
|
kind: "creator.onboarding",
|
|
@@ -22,7 +22,7 @@ export declare function shardHostedControlCallbacks(router: Pick<ShardControlRou
|
|
|
22
22
|
deliverHostedServerLeave: (input: {
|
|
23
23
|
operationId: string;
|
|
24
24
|
guildId: string;
|
|
25
|
-
}) => Promise<"
|
|
25
|
+
}) => Promise<"queued" | "completed" | "not_currently_installed" | "accepted_for_retry" | "requires_review">;
|
|
26
26
|
refreshHostedServerOwner: (guildId: string) => Promise<{
|
|
27
27
|
username: string;
|
|
28
28
|
observedAt: string;
|
package/dist/shard-supervisor.js
CHANGED
|
@@ -36,6 +36,8 @@ import { SupervisorCloudDiscordDirectory } from "./supervisor-cloud-directory.js
|
|
|
36
36
|
import { createSupportModule } from "./support-module.js";
|
|
37
37
|
import { createOAuthModule } from "./oauth-module.js";
|
|
38
38
|
import { createPrivacyModule } from "./privacy-module.js";
|
|
39
|
+
import { createProcessInfoModule } from "./process-info-module.js";
|
|
40
|
+
import { createRuntimeHelpModule } from "./help-runtime.js";
|
|
39
41
|
import { REVIEWED_PREMIUM_MODULE_IDS } from "@helyx/module-manifest";
|
|
40
42
|
import { createPremiumActivationModule } from "./premium-activation-module.js";
|
|
41
43
|
import { DiscordPremiumGuildAuthority } from "./premium-guild-authority.js";
|
|
@@ -248,6 +250,8 @@ export async function startShardSupervisor(environment, processEnvironment, work
|
|
|
248
250
|
: undefined;
|
|
249
251
|
const supportModule = createSupportModule(cloudConnector);
|
|
250
252
|
const privacyModule = createPrivacyModule();
|
|
253
|
+
const processInfoModule = createProcessInfoModule("shard supervisor");
|
|
254
|
+
const helpModule = createRuntimeHelpModule(environment);
|
|
251
255
|
const premiumEnvironment = requirePremiumProviderEnvironment(featureModules, environment.STRIPE_ENVIRONMENT);
|
|
252
256
|
const premiumActivationModule = !premiumEnvironment
|
|
253
257
|
? undefined
|
|
@@ -267,6 +271,8 @@ export async function startShardSupervisor(environment, processEnvironment, work
|
|
|
267
271
|
permissionsModule,
|
|
268
272
|
supportModule,
|
|
269
273
|
privacyModule,
|
|
274
|
+
processInfoModule,
|
|
275
|
+
helpModule,
|
|
270
276
|
...(premiumActivationModule ? [premiumActivationModule] : []),
|
|
271
277
|
...(oauthModule ? [oauthModule] : []),
|
|
272
278
|
...(cloudManagementModule ? [cloudManagementModule] : []),
|
|
@@ -291,6 +297,8 @@ export async function startShardSupervisor(environment, processEnvironment, work
|
|
|
291
297
|
permissionsModule,
|
|
292
298
|
supportModule,
|
|
293
299
|
privacyModule,
|
|
300
|
+
processInfoModule,
|
|
301
|
+
helpModule,
|
|
294
302
|
...(premiumActivationModule ? [premiumActivationModule] : []),
|
|
295
303
|
...(oauthModule ? [oauthModule] : []),
|
|
296
304
|
...(cloudManagementModule ? [cloudManagementModule] : []),
|
package/dist/shard-worker.d.ts
CHANGED
|
@@ -63,7 +63,7 @@ export declare function parseShardWorkerEnvironment(processEnvironment: NodeJS.P
|
|
|
63
63
|
HELYX_OAUTH_ENABLED: boolean;
|
|
64
64
|
HELYX_CLOUD_ENDPOINT: string;
|
|
65
65
|
HELYX_OWNER_USER_IDS: string[];
|
|
66
|
-
HELYX_SHARD_MODE: "
|
|
66
|
+
HELYX_SHARD_MODE: "off" | "auto" | "fixed";
|
|
67
67
|
HELYX_SHARD_SCOPE: "local" | "coordinated";
|
|
68
68
|
HELYX_CLOUD_AUDIT_RETENTION_DAYS: number;
|
|
69
69
|
HELYX_CLOUD_CREDENTIAL_AUDIT_RETENTION_DAYS: number;
|
package/dist/shard-worker.js
CHANGED
|
@@ -44,6 +44,8 @@ import { HostedBotInviteGateClient, HostedServerLeaveWorker, HostedServerModerat
|
|
|
44
44
|
import { createSupportModule } from "./support-module.js";
|
|
45
45
|
import { createOAuthModule } from "./oauth-module.js";
|
|
46
46
|
import { createPrivacyModule } from "./privacy-module.js";
|
|
47
|
+
import { createProcessInfoModule } from "./process-info-module.js";
|
|
48
|
+
import { createRuntimeHelpModule } from "./help-runtime.js";
|
|
47
49
|
import { HttpOAuthService } from "./oauth-service.js";
|
|
48
50
|
import { createLocalScheduledTaskRoute, } from "./scheduled-task-runner.js";
|
|
49
51
|
import { createLocalNumericWriteBehind } from "./numeric-write-behind.js";
|
|
@@ -202,6 +204,8 @@ export async function startShardWorker(processEnvironment = process.env, identit
|
|
|
202
204
|
: undefined;
|
|
203
205
|
const supportModule = createSupportModule(cloudProxy);
|
|
204
206
|
const privacyModule = createPrivacyModule();
|
|
207
|
+
const processInfoModule = createProcessInfoModule(`shard worker ${identity.shardId}`);
|
|
208
|
+
const helpModule = createRuntimeHelpModule(environment);
|
|
205
209
|
const premiumEnvironment = requirePremiumProviderEnvironment(featureModules, environment.STRIPE_ENVIRONMENT);
|
|
206
210
|
const premiumActivationModule = !premiumEnvironment
|
|
207
211
|
? undefined
|
|
@@ -221,6 +225,8 @@ export async function startShardWorker(processEnvironment = process.env, identit
|
|
|
221
225
|
permissionsModule,
|
|
222
226
|
supportModule,
|
|
223
227
|
privacyModule,
|
|
228
|
+
processInfoModule,
|
|
229
|
+
helpModule,
|
|
224
230
|
...(premiumActivationModule ? [premiumActivationModule] : []),
|
|
225
231
|
...(oauthModule ? [oauthModule] : []),
|
|
226
232
|
...(cloudManagementModule ? [cloudManagementModule] : []),
|
|
@@ -244,6 +250,8 @@ export async function startShardWorker(processEnvironment = process.env, identit
|
|
|
244
250
|
permissionsModule,
|
|
245
251
|
supportModule,
|
|
246
252
|
privacyModule,
|
|
253
|
+
processInfoModule,
|
|
254
|
+
helpModule,
|
|
247
255
|
...(premiumActivationModule ? [premiumActivationModule] : []),
|
|
248
256
|
...(oauthModule ? [oauthModule] : []),
|
|
249
257
|
...(cloudManagementModule ? [cloudManagementModule] : []),
|
|
@@ -21,6 +21,10 @@ export declare class HttpVerificationService implements VerificationService {
|
|
|
21
21
|
}): Promise<{
|
|
22
22
|
cancelled: number;
|
|
23
23
|
}>;
|
|
24
|
+
countPendingAttempts(input: {
|
|
25
|
+
installationId: string;
|
|
26
|
+
guildId: string;
|
|
27
|
+
}): Promise<number>;
|
|
24
28
|
listAttempts(input: DashboardAttemptQuery & {
|
|
25
29
|
installationId: string;
|
|
26
30
|
guildId: string;
|
|
@@ -82,6 +82,16 @@ export class HttpVerificationService {
|
|
|
82
82
|
}
|
|
83
83
|
return cancelled;
|
|
84
84
|
}
|
|
85
|
+
async countPendingAttempts(input) {
|
|
86
|
+
const result = z
|
|
87
|
+
.object({ count: z.number().int().nonnegative() })
|
|
88
|
+
.strict()
|
|
89
|
+
.parse(await this.#request("/internal/v1/attempts/pending-count", {
|
|
90
|
+
method: "POST",
|
|
91
|
+
body: input,
|
|
92
|
+
}));
|
|
93
|
+
return result.count;
|
|
94
|
+
}
|
|
85
95
|
async listAttempts(input) {
|
|
86
96
|
const { installationId, guildId, ...query } = input;
|
|
87
97
|
return dashboardAttemptPageSchema.parse(await this.#request("/internal/v1/attempts/query", {
|
package/documentation/README.md
CHANGED
|
@@ -18,6 +18,7 @@ and module guides.
|
|
|
18
18
|
- [Operate installations and upgrades](runbooks/installation-and-upgrades.md)
|
|
19
19
|
- [Plan backup and recovery](runbooks/backup-and-recovery.md)
|
|
20
20
|
- [Handle privacy and support](guides/privacy-and-support.md)
|
|
21
|
+
- [Use Help and optional online matching](guides/help-command.md)
|
|
21
22
|
- [Build an independent module](modules/building-a-module.md)
|
|
22
23
|
- [Test a module](modules/testing-a-module.md)
|
|
23
24
|
- [Prepare a module package](modules/publishing-a-module.md)
|
|
@@ -1,89 +1,33 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Helyx self-hosted environment
|
|
2
|
+
# Keep this file private. Retain the encryption key when updating.
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
# Runtime
|
|
5
|
+
HELYX_RUNTIME_PROFILE='self-hosted'
|
|
6
|
+
HELYX_DEPLOYMENT_ENVIRONMENT='self-hosted'
|
|
7
|
+
NODE_ENV='production'
|
|
5
8
|
|
|
6
9
|
# Discord
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
HELYX_MESSAGE_CONTENT_ENABLED=false
|
|
12
|
-
# Enable for loaded member workflows such as Welcome, Access Control or Levels,
|
|
13
|
-
# with Server Members Intent also enabled in the Discord developer portal.
|
|
14
|
-
HELYX_GUILD_MEMBERS_ENABLED=false
|
|
15
|
-
# Database
|
|
16
|
-
# Docker: keep the URL. Direct Node.js/managed hosting: use your provider URL.
|
|
17
|
-
DATABASE_ENGINE=postgresql
|
|
18
|
-
DATABASE_URL=postgresql://database:5432/helyx
|
|
19
|
-
DATABASE_SSL=disable
|
|
20
|
-
# Self-host startup applies pending migrations automatically (the default).
|
|
21
|
-
# Hosted-only inspect mode is not a self-host setting; leave this commented.
|
|
22
|
-
# HELYX_DATABASE_STARTUP_MODE=apply
|
|
23
|
-
# Match your provider: disable=no TLS; require=TLS without certificate
|
|
24
|
-
# verification; verify-full=TLS with certificate verification.
|
|
25
|
-
|
|
26
|
-
# Included Docker database — both password values must match.
|
|
27
|
-
PGUSER=helyx
|
|
28
|
-
PGPASSWORD=replace-with-a-strong-password
|
|
29
|
-
POSTGRES_DB=helyx
|
|
30
|
-
POSTGRES_USER=helyx
|
|
31
|
-
POSTGRES_PASSWORD=replace-with-a-strong-password
|
|
32
|
-
|
|
33
|
-
# OPTIONAL EVERYDAY SETTINGS
|
|
34
|
-
|
|
35
|
-
# Ready for dashboard linking, but remains unpaired until you use a one-use code.
|
|
36
|
-
HELYX_CLOUD_CONNECT_ENABLED=true
|
|
37
|
-
# Public dashboard origin used in bot-generated report links.
|
|
38
|
-
# HELYX_DASHBOARD_PUBLIC_URL=https://app.helyx.gg
|
|
39
|
-
# HELYX_OWNER_USER_IDS=12345678901234567
|
|
40
|
-
|
|
41
|
-
# trace, debug, info, warn, error, fatal or silent
|
|
42
|
-
LOG_LEVEL=info
|
|
43
|
-
|
|
44
|
-
# SHARDING: OFF BY DEFAULT
|
|
45
|
-
|
|
46
|
-
# `off` is the compatible self-host default. Keep shard-only values commented
|
|
47
|
-
# in this mode; an empty value is still rejected as configured. MySQL must stay
|
|
48
|
-
# off. Advanced PostgreSQL self-hosting may use `auto` under one
|
|
49
|
-
# supervisor, or `fixed` with a deliberate total count. Local mode never needs
|
|
50
|
-
# Redis. Coordinated multi-host self-hosting is outside the first release.
|
|
51
|
-
HELYX_SHARD_MODE=off
|
|
52
|
-
# HELYX_SHARD_SCOPE=local
|
|
53
|
-
# HELYX_SHARD_COUNT=2
|
|
54
|
-
# HELYX_SHARD_WORKERS_PER_REPLICA=2
|
|
55
|
-
# HELYX_SHARD_REDIS_URL=rediss://private-redis.example:6379
|
|
56
|
-
# HELYX_SHARD_REDIS_NAMESPACE=helyx.self-host
|
|
57
|
-
# HELYX_SHARD_GENERATION=local-20260728
|
|
58
|
-
# HELYX_SHARD_DATABASE_CONNECTION_BUDGET=10
|
|
59
|
-
# HELYX_SHARD_SUPERVISOR_DATABASE_POOL_MAX=2
|
|
60
|
-
# HELYX_SHARD_WORKER_DATABASE_POOL_MAX=4
|
|
61
|
-
# Redis URL and namespace are intentionally unsupported for the first
|
|
62
|
-
# self-hosted release: do not uncomment them for local auto or fixed mode.
|
|
10
|
+
DISCORD_CLIENT_ID='12345678901234567'
|
|
11
|
+
DISCORD_TOKEN='replace-me'
|
|
12
|
+
HELYX_GUILD_MEMBERS_ENABLED='false'
|
|
13
|
+
HELYX_MESSAGE_CONTENT_ENABLED='false'
|
|
63
14
|
|
|
64
|
-
#
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
#
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
#
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
#
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
# Generated privately by npm run setup. Required by Cloud Connect, Giveaways,
|
|
85
|
-
# and Invite Tracking; retain it unchanged across restarts and deployments.
|
|
86
|
-
# HELYX_DATA_ENCRYPTION_KEY=replace-with-a-base64-encoded-32-byte-key
|
|
87
|
-
|
|
88
|
-
# Runtime mode
|
|
89
|
-
NODE_ENV=production
|
|
15
|
+
# Database
|
|
16
|
+
DATABASE_ENGINE='postgresql'
|
|
17
|
+
DATABASE_URL='postgresql://database:5432/helyx'
|
|
18
|
+
DATABASE_SSL='disable'
|
|
19
|
+
|
|
20
|
+
# Commands
|
|
21
|
+
HELYX_GUILD_COMMAND_WRITES_ENABLED='true'
|
|
22
|
+
HELYX_GUILD_COMMAND_WRITE_SCOPE='allowlist'
|
|
23
|
+
HELYX_GLOBAL_COMMAND_MODE='platform-only'
|
|
24
|
+
HELYX_GUILD_COMMAND_WRITE_GUILD_IDS=''
|
|
25
|
+
|
|
26
|
+
# Modules and dashboard
|
|
27
|
+
HELYX_MODULE_CATALOGUE_PATH='./helyx.modules.json'
|
|
28
|
+
HELYX_CLOUD_CONNECT_ENABLED='true'
|
|
29
|
+
HELYX_SHARD_MODE='off'
|
|
30
|
+
LOG_LEVEL='info'
|
|
31
|
+
|
|
32
|
+
# Keep this key unchanged across restarts and updates
|
|
33
|
+
HELYX_DATA_ENCRYPTION_KEY='replace-with-a-base64-encoded-32-byte-key'
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Help Command
|
|
2
|
+
|
|
3
|
+
Use `/help question:your question` to search Helyx's saved FAQ answers. You can
|
|
4
|
+
choose a module or documentation area to narrow the question, for example
|
|
5
|
+
`/help module:Feedback question:The command is not visible`. Use `/help` for a
|
|
6
|
+
short introduction. Replies are private, and Help is available without enabling
|
|
7
|
+
a customer module or purchasing Premium.
|
|
8
|
+
|
|
9
|
+
Help returns a stored answer, possible FAQ questions to choose from, or a
|
|
10
|
+
documentation link when it cannot find a suitable match. You can also enter a
|
|
11
|
+
six-digit FAQ ID. Answers retain their source and availability labels; a Planned
|
|
12
|
+
or Testing answer does not mean that feature is available. Staff-authored shared
|
|
13
|
+
and Custom answers are labelled separately. Help does not inspect your server
|
|
14
|
+
settings, execute repairs or generate new answers.
|
|
15
|
+
|
|
16
|
+
## Self-hosted installations
|
|
17
|
+
|
|
18
|
+
The bot includes an approved FAQ snapshot for local search. Local Help needs no
|
|
19
|
+
Helyx account, Cloud Connect, Cloudflare key, local AI model or internet service.
|
|
20
|
+
The snapshot belongs to the installed release; update the bot to receive a newer
|
|
21
|
+
one. Central suppression or editing cannot change an offline release already on
|
|
22
|
+
your computer. When an enrolled online request fails, self-hosted Help labels
|
|
23
|
+
its local fallback clearly.
|
|
24
|
+
|
|
25
|
+
Online matching is optional. When available, open your Helyx account's
|
|
26
|
+
self-hosting page and create a Help code. On the bot's host, from the generated
|
|
27
|
+
project folder, run:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
npx helyx help connect
|
|
31
|
+
npx helyx help status
|
|
32
|
+
npx helyx help disconnect
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Read the connection notice and paste the single-use code at the prompt. Codes
|
|
36
|
+
expire after ten minutes; do not put one in a command argument or screenshot.
|
|
37
|
+
The project needs its existing data-encryption key and a writable `.helyx`
|
|
38
|
+
directory. Help saves a separate encrypted credential there. Docker starters
|
|
39
|
+
retain it in their private named volume. Preserve the encryption key when
|
|
40
|
+
restarting; changing it makes the saved credential unreadable.
|
|
41
|
+
|
|
42
|
+
Status reads only the local file. Disconnect revokes online access when the
|
|
43
|
+
service is reachable and removes the local credential. If remote revocation
|
|
44
|
+
fails, revoke the installation from the account dashboard. A replacement code
|
|
45
|
+
rotates the credential when consumed; account revocation takes effect centrally.
|
|
46
|
+
Neither action disables local Help or requires Cloud Connect.
|
|
47
|
+
|
|
48
|
+
## Questions and privacy
|
|
49
|
+
|
|
50
|
+
Online Help sends the question and selected area to Helyx; its embedding
|
|
51
|
+
provider receives the public question text needed for meaning comparison.
|
|
52
|
+
Do not include credentials, private messages or personal details. Self-host
|
|
53
|
+
online requests use a Help installation identity and do not send Discord user
|
|
54
|
+
or server IDs. Hosted requests use trusted member/server identities for limits.
|
|
55
|
+
The service does not store a persistent history of member questions or completed
|
|
56
|
+
question embeddings. Short-lived request counters and Help connection metadata
|
|
57
|
+
are handled through Helyx's privacy system. Providers have their own processing
|
|
58
|
+
terms. See [Privacy and support](privacy-and-support.md).
|
|
59
|
+
|
|
60
|
+
Shared request and spending limits may make semantic matching temporarily
|
|
61
|
+
unavailable. Hosted Help fails safely to documentation when it cannot verify
|
|
62
|
+
the current collection; self-hosted Help can still use its labelled local copy.
|
|
@@ -4,7 +4,7 @@ Start from [the published example](../examples/.env.example). The example is a
|
|
|
4
4
|
copy of the starter emitted by the supported CLI and is checked for drift.
|
|
5
5
|
|
|
6
6
|
This page explains the ownership and safe defaults of the generated variables;
|
|
7
|
-
the
|
|
7
|
+
the compact `.env.example` contains only the standard installation settings.
|
|
8
8
|
|
|
9
9
|
## Required values
|
|
10
10
|
|
|
@@ -12,8 +12,9 @@ the comments in `.env.example` remain the version-matched field reference.
|
|
|
12
12
|
`DISCORD_CLIENT_ID` is the application's numeric ID. `DATABASE_ENGINE` accepts
|
|
13
13
|
`postgresql` or `mysql` and defaults to PostgreSQL when omitted. `DATABASE_URL`
|
|
14
14
|
must match the selected engine, and `DATABASE_SSL` must match the database
|
|
15
|
-
provider. PostgreSQL Docker users
|
|
16
|
-
|
|
15
|
+
provider. PostgreSQL Docker users can run `npm run envbuilder` and select the
|
|
16
|
+
bundled database. That choice adds matching `PGPASSWORD` and `POSTGRES_PASSWORD`
|
|
17
|
+
values and the Docker database/user settings. The MySQL Compose starter
|
|
17
18
|
runs only the bot and connects to the external database in `DATABASE_URL`.
|
|
18
19
|
|
|
19
20
|
Percent-encode special characters in URL credentials. `DATABASE_SSL=disable`
|
|
@@ -30,7 +31,7 @@ boundary and prevents Hosted-only Helyx Ecko calls from entering the local
|
|
|
30
31
|
runtime.
|
|
31
32
|
|
|
32
33
|
Privileged Discord intents, privacy execution, hosted OAuth, status reporting,
|
|
33
|
-
|
|
34
|
+
and advanced sharding stay disabled until their complete
|
|
34
35
|
requirements are deliberately configured. An empty variable still counts as a
|
|
35
36
|
configured value in many environments, so leave unused optional lines
|
|
36
37
|
commented.
|
|
@@ -48,8 +49,8 @@ For enabled-module command builds in approved servers, set
|
|
|
48
49
|
Discord server IDs. Use `HELYX_GLOBAL_COMMAND_MODE=platform-only` to retain global
|
|
49
50
|
core/deployment commands while feature commands use per-server builds. Restart
|
|
50
51
|
after changing these values and check the dashboard command-build status. The
|
|
51
|
-
template
|
|
52
|
-
|
|
52
|
+
template uses `platform-only` and enables guild writes for the server IDs you
|
|
53
|
+
provide. Enter those IDs before starting; leave the allowlist scope in place.
|
|
53
54
|
Do not use the advanced `all` scope merely to bypass an allowlist error.
|
|
54
55
|
|
|
55
56
|
`HELYX_AUTOMOD_EMBEDDED_WORKERS` controls only the in-process Self-Hosted
|
|
@@ -22,7 +22,10 @@ below.
|
|
|
22
22
|
|
|
23
23
|
1. Download a starter ZIP, or generate it from the builder's reviewed manifest.
|
|
24
24
|
2. Install its dependencies with `npm ci` unless generation used `--install`.
|
|
25
|
-
3. Run `npm run
|
|
25
|
+
3. Run `npm run envbuilder` to prepare `.env`, or use `npm run setup` and edit
|
|
26
|
+
the compact example. For the included Docker PostgreSQL service, use the
|
|
27
|
+
builder and choose **bundled** so its required database credentials are added.
|
|
28
|
+
A managed host may supply the
|
|
26
29
|
required values through its protected variables panel instead. Keep the
|
|
27
30
|
generated encryption key stable.
|
|
28
31
|
4. Make the selected database reachable and run doctor through the matching
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helyx/bot",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Production Discord runtime for the modular Helyx platform.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"helyx",
|
|
@@ -51,15 +51,15 @@
|
|
|
51
51
|
"start": "node --env-file-if-exists=../../.env dist/index.js"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@helyx/config": ">=1.
|
|
55
|
-
"@helyx/control-protocol": ">=0.9.
|
|
56
|
-
"@helyx/core": ">=0.2.
|
|
57
|
-
"@helyx/database": ">=2.5.
|
|
54
|
+
"@helyx/config": ">=1.7.0 <2.0.0",
|
|
55
|
+
"@helyx/control-protocol": ">=0.9.1 <0.10.0",
|
|
56
|
+
"@helyx/core": ">=0.2.3 <0.3.0",
|
|
57
|
+
"@helyx/database": ">=2.5.1 <3.0.0",
|
|
58
58
|
"@helyx/database-contracts": ">=0.3.0 <0.4.0",
|
|
59
59
|
"@helyx/framework": ">=0.2.0 <0.3.0",
|
|
60
60
|
"@helyx/module-manifest": ">=0.14.0 <0.15.0",
|
|
61
61
|
"@helyx/platform": ">=1.3.0 <2.0.0",
|
|
62
|
-
"@helyx/sdk": ">=0.17.
|
|
62
|
+
"@helyx/sdk": ">=0.17.1 <0.18.0",
|
|
63
63
|
"@helyx/status-client": ">=0.3.0 <0.4.0",
|
|
64
64
|
"@helyx/verification-contracts": ">=0.5.0 <0.6.0",
|
|
65
65
|
"discord.js": "14.27.0",
|