fix: resolve format/build failures
This commit is contained in:
@@ -495,7 +495,7 @@ export function createExecTool(
|
|||||||
)) as { decision?: string } | null;
|
)) as { decision?: string } | null;
|
||||||
const decision =
|
const decision =
|
||||||
decisionResult && typeof decisionResult === "object"
|
decisionResult && typeof decisionResult === "object"
|
||||||
? decisionResult.decision ?? null
|
? (decisionResult.decision ?? null)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (decision === "deny") {
|
if (decision === "deny") {
|
||||||
@@ -506,9 +506,7 @@ export function createExecTool(
|
|||||||
approvedByAsk = true;
|
approvedByAsk = true;
|
||||||
} else if (askFallback === "allowlist") {
|
} else if (askFallback === "allowlist") {
|
||||||
if (!allowlistMatch) {
|
if (!allowlistMatch) {
|
||||||
throw new Error(
|
throw new Error("exec denied: approval required (approval UI not available)");
|
||||||
"exec denied: approval required (approval UI not available)",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
approvedByAsk = true;
|
approvedByAsk = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -624,7 +622,7 @@ export function createExecTool(
|
|||||||
)) as { decision?: string } | null;
|
)) as { decision?: string } | null;
|
||||||
const decision =
|
const decision =
|
||||||
decisionResult && typeof decisionResult === "object"
|
decisionResult && typeof decisionResult === "object"
|
||||||
? decisionResult.decision ?? null
|
? (decisionResult.decision ?? null)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (decision === "deny") {
|
if (decision === "deny") {
|
||||||
@@ -635,9 +633,7 @@ export function createExecTool(
|
|||||||
approvedByAsk = true;
|
approvedByAsk = true;
|
||||||
} else if (askFallback === "allowlist") {
|
} else if (askFallback === "allowlist") {
|
||||||
if (!allowlistMatch) {
|
if (!allowlistMatch) {
|
||||||
throw new Error(
|
throw new Error("exec denied: approval required (approval UI not available)");
|
||||||
"exec denied: approval required (approval UI not available)",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
approvedByAsk = true;
|
approvedByAsk = true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -55,7 +55,9 @@ function resolveAgentIdByWorkspace(
|
|||||||
): string[] {
|
): string[] {
|
||||||
const list = listAgentEntries(cfg);
|
const list = listAgentEntries(cfg);
|
||||||
const ids =
|
const ids =
|
||||||
list.length > 0 ? list.map((entry) => normalizeAgentId(entry.id)) : [resolveDefaultAgentId(cfg)];
|
list.length > 0
|
||||||
|
? list.map((entry) => normalizeAgentId(entry.id))
|
||||||
|
: [resolveDefaultAgentId(cfg)];
|
||||||
const normalizedTarget = normalizeWorkspacePath(workspaceDir);
|
const normalizedTarget = normalizeWorkspacePath(workspaceDir);
|
||||||
return ids.filter(
|
return ids.filter(
|
||||||
(id) => normalizeWorkspacePath(resolveAgentWorkspaceDir(cfg, id)) === normalizedTarget,
|
(id) => normalizeWorkspacePath(resolveAgentWorkspaceDir(cfg, id)) === normalizedTarget,
|
||||||
@@ -134,10 +136,7 @@ export async function agentsSetIdentityCommand(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fileTheme =
|
const fileTheme =
|
||||||
identityFromFile?.theme ??
|
identityFromFile?.theme ?? identityFromFile?.creature ?? identityFromFile?.vibe ?? undefined;
|
||||||
identityFromFile?.creature ??
|
|
||||||
identityFromFile?.vibe ??
|
|
||||||
undefined;
|
|
||||||
const incomingIdentity: IdentityConfig = {
|
const incomingIdentity: IdentityConfig = {
|
||||||
...(nameRaw || identityFromFile?.name ? { name: nameRaw ?? identityFromFile?.name } : {}),
|
...(nameRaw || identityFromFile?.name ? { name: nameRaw ?? identityFromFile?.name } : {}),
|
||||||
...(emojiRaw || identityFromFile?.emoji ? { emoji: emojiRaw ?? identityFromFile?.emoji } : {}),
|
...(emojiRaw || identityFromFile?.emoji ? { emoji: emojiRaw ?? identityFromFile?.emoji } : {}),
|
||||||
|
|||||||
@@ -79,11 +79,7 @@ export function parseIdentityMarkdown(content: string): AgentIdentity {
|
|||||||
const cleaned = line.trim().replace(/^\s*-\s*/, "");
|
const cleaned = line.trim().replace(/^\s*-\s*/, "");
|
||||||
const colonIndex = cleaned.indexOf(":");
|
const colonIndex = cleaned.indexOf(":");
|
||||||
if (colonIndex === -1) continue;
|
if (colonIndex === -1) continue;
|
||||||
const label = cleaned
|
const label = cleaned.slice(0, colonIndex).replace(/[*_]/g, "").trim().toLowerCase();
|
||||||
.slice(0, colonIndex)
|
|
||||||
.replace(/[*_]/g, "")
|
|
||||||
.trim()
|
|
||||||
.toLowerCase();
|
|
||||||
const value = cleaned
|
const value = cleaned
|
||||||
.slice(colonIndex + 1)
|
.slice(colonIndex + 1)
|
||||||
.replace(/^[*_]+|[*_]+$/g, "")
|
.replace(/^[*_]+|[*_]+$/g, "")
|
||||||
|
|||||||
@@ -93,7 +93,12 @@ describe("agents set-identity command", () => {
|
|||||||
configMocks.readConfigFileSnapshot.mockResolvedValue({
|
configMocks.readConfigFileSnapshot.mockResolvedValue({
|
||||||
...baseSnapshot,
|
...baseSnapshot,
|
||||||
config: {
|
config: {
|
||||||
agents: { list: [{ id: "main", workspace }, { id: "ops", workspace }] },
|
agents: {
|
||||||
|
list: [
|
||||||
|
{ id: "main", workspace },
|
||||||
|
{ id: "ops", workspace },
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import type { LoggingConfig, SessionConfig, WebConfig } from "./types.base.js";
|
|||||||
import type { BrowserConfig } from "./types.browser.js";
|
import type { BrowserConfig } from "./types.browser.js";
|
||||||
import type { ChannelsConfig } from "./types.channels.js";
|
import type { ChannelsConfig } from "./types.channels.js";
|
||||||
import type { CronConfig } from "./types.cron.js";
|
import type { CronConfig } from "./types.cron.js";
|
||||||
import type { CanvasHostConfig, DiscoveryConfig, GatewayConfig, TalkConfig } from "./types.gateway.js";
|
import type {
|
||||||
|
CanvasHostConfig,
|
||||||
|
DiscoveryConfig,
|
||||||
|
GatewayConfig,
|
||||||
|
TalkConfig,
|
||||||
|
} from "./types.gateway.js";
|
||||||
import type { HooksConfig } from "./types.hooks.js";
|
import type { HooksConfig } from "./types.hooks.js";
|
||||||
import type {
|
import type {
|
||||||
AudioConfig,
|
AudioConfig,
|
||||||
|
|||||||
@@ -113,7 +113,6 @@ export type GatewayHttpConfig = {
|
|||||||
endpoints?: GatewayHttpEndpointsConfig;
|
endpoints?: GatewayHttpEndpointsConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type GatewayConfig = {
|
export type GatewayConfig = {
|
||||||
/** Single multiplexed port for Gateway WS + HTTP (default: 18789). */
|
/** Single multiplexed port for Gateway WS + HTTP (default: 18789). */
|
||||||
port?: number;
|
port?: number;
|
||||||
|
|||||||
@@ -231,12 +231,7 @@ export const ClawdbotSchema = z
|
|||||||
port: z.number().int().positive().optional(),
|
port: z.number().int().positive().optional(),
|
||||||
mode: z.union([z.literal("local"), z.literal("remote")]).optional(),
|
mode: z.union([z.literal("local"), z.literal("remote")]).optional(),
|
||||||
bind: z
|
bind: z
|
||||||
.union([
|
.union([z.literal("auto"), z.literal("lan"), z.literal("loopback"), z.literal("custom")])
|
||||||
z.literal("auto"),
|
|
||||||
z.literal("lan"),
|
|
||||||
z.literal("loopback"),
|
|
||||||
z.literal("custom"),
|
|
||||||
])
|
|
||||||
.optional(),
|
.optional(),
|
||||||
controlUi: z
|
controlUi: z
|
||||||
.object({
|
.object({
|
||||||
|
|||||||
@@ -136,10 +136,7 @@ export async function callGateway<T = unknown>(opts: CallGatewayOptions): Promis
|
|||||||
});
|
});
|
||||||
const url = connectionDetails.url;
|
const url = connectionDetails.url;
|
||||||
const useLocalTls =
|
const useLocalTls =
|
||||||
config.gateway?.tls?.enabled === true &&
|
config.gateway?.tls?.enabled === true && !urlOverride && !remoteUrl && url.startsWith("wss://");
|
||||||
!urlOverride &&
|
|
||||||
!remoteUrl &&
|
|
||||||
url.startsWith("wss://");
|
|
||||||
const tlsRuntime = useLocalTls ? await loadGatewayTlsRuntime(config.gateway?.tls) : undefined;
|
const tlsRuntime = useLocalTls ? await loadGatewayTlsRuntime(config.gateway?.tls) : undefined;
|
||||||
const tlsFingerprint = tlsRuntime?.enabled ? tlsRuntime.fingerprintSha256 : undefined;
|
const tlsFingerprint = tlsRuntime?.enabled ? tlsRuntime.fingerprintSha256 : undefined;
|
||||||
const token =
|
const token =
|
||||||
|
|||||||
@@ -93,22 +93,14 @@ export class GatewayClient {
|
|||||||
wsOptions.checkServerIdentity = (_host: string, cert: CertMeta) => {
|
wsOptions.checkServerIdentity = (_host: string, cert: CertMeta) => {
|
||||||
const fingerprintValue =
|
const fingerprintValue =
|
||||||
typeof cert === "object" && cert && "fingerprint256" in cert
|
typeof cert === "object" && cert && "fingerprint256" in cert
|
||||||
? (cert as { fingerprint256?: string }).fingerprint256 ?? ""
|
? ((cert as { fingerprint256?: string }).fingerprint256 ?? "")
|
||||||
: "";
|
: "";
|
||||||
const fingerprint = normalizeFingerprint(
|
const fingerprint = normalizeFingerprint(
|
||||||
typeof fingerprintValue === "string" ? fingerprintValue : "",
|
typeof fingerprintValue === "string" ? fingerprintValue : "",
|
||||||
);
|
);
|
||||||
const expected = normalizeFingerprint(this.opts.tlsFingerprint ?? "");
|
const expected = normalizeFingerprint(this.opts.tlsFingerprint ?? "");
|
||||||
if (!expected) {
|
if (!expected || !fingerprint) return false;
|
||||||
return new Error("gateway tls fingerprint missing");
|
return fingerprint === expected;
|
||||||
}
|
|
||||||
if (!fingerprint) {
|
|
||||||
return new Error("gateway tls fingerprint unavailable");
|
|
||||||
}
|
|
||||||
if (fingerprint !== expected) {
|
|
||||||
return new Error("gateway tls fingerprint mismatch");
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.ws = new WebSocket(url, wsOptions);
|
this.ws = new WebSocket(url, wsOptions);
|
||||||
|
|||||||
@@ -45,7 +45,10 @@ export class ExecApprovalManager {
|
|||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
async waitForDecision(record: ExecApprovalRecord, timeoutMs: number): Promise<ExecApprovalDecision | null> {
|
async waitForDecision(
|
||||||
|
record: ExecApprovalRecord,
|
||||||
|
timeoutMs: number,
|
||||||
|
): Promise<ExecApprovalDecision | null> {
|
||||||
return await new Promise<ExecApprovalDecision | null>((resolve, reject) => {
|
return await new Promise<ExecApprovalDecision | null>((resolve, reject) => {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
this.pending.delete(record.id);
|
this.pending.delete(record.id);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export class NodeRegistry {
|
|||||||
const nodeId = connect.device?.id ?? connect.client.id;
|
const nodeId = connect.device?.id ?? connect.client.id;
|
||||||
const caps = Array.isArray(connect.caps) ? connect.caps : [];
|
const caps = Array.isArray(connect.caps) ? connect.caps : [];
|
||||||
const commands = Array.isArray((connect as { commands?: string[] }).commands)
|
const commands = Array.isArray((connect as { commands?: string[] }).commands)
|
||||||
? (connect as { commands?: string[] }).commands ?? []
|
? ((connect as { commands?: string[] }).commands ?? [])
|
||||||
: [];
|
: [];
|
||||||
const permissions =
|
const permissions =
|
||||||
typeof (connect as { permissions?: Record<string, boolean> }).permissions === "object"
|
typeof (connect as { permissions?: Record<string, boolean> }).permissions === "object"
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ import {
|
|||||||
} from "../protocol/index.js";
|
} from "../protocol/index.js";
|
||||||
import type { GatewayRequestHandlers } from "./types.js";
|
import type { GatewayRequestHandlers } from "./types.js";
|
||||||
|
|
||||||
export function createExecApprovalHandlers(
|
export function createExecApprovalHandlers(manager: ExecApprovalManager): GatewayRequestHandlers {
|
||||||
manager: ExecApprovalManager,
|
|
||||||
): GatewayRequestHandlers {
|
|
||||||
return {
|
return {
|
||||||
"exec.approval.request": async ({ params, respond, context }) => {
|
"exec.approval.request": async ({ params, respond, context }) => {
|
||||||
if (!validateExecApprovalRequestParams(params)) {
|
if (!validateExecApprovalRequestParams(params)) {
|
||||||
@@ -61,12 +59,16 @@ export function createExecApprovalHandlers(
|
|||||||
{ dropIfSlow: true },
|
{ dropIfSlow: true },
|
||||||
);
|
);
|
||||||
const decision = await manager.waitForDecision(record, timeoutMs);
|
const decision = await manager.waitForDecision(record, timeoutMs);
|
||||||
respond(true, {
|
respond(
|
||||||
|
true,
|
||||||
|
{
|
||||||
id: record.id,
|
id: record.id,
|
||||||
decision,
|
decision,
|
||||||
createdAtMs: record.createdAtMs,
|
createdAtMs: record.createdAtMs,
|
||||||
expiresAtMs: record.expiresAtMs,
|
expiresAtMs: record.expiresAtMs,
|
||||||
}, undefined);
|
},
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
"exec.approval.resolve": async ({ params, respond, client, context }) => {
|
"exec.approval.resolve": async ({ params, respond, client, context }) => {
|
||||||
if (!validateExecApprovalResolveParams(params)) {
|
if (!validateExecApprovalResolveParams(params)) {
|
||||||
|
|||||||
@@ -453,14 +453,10 @@ export const nodeHandlers: GatewayRequestHandlers = {
|
|||||||
loadGatewayModelCatalog: context.loadGatewayModelCatalog,
|
loadGatewayModelCatalog: context.loadGatewayModelCatalog,
|
||||||
logGateway: { warn: context.logGateway.warn },
|
logGateway: { warn: context.logGateway.warn },
|
||||||
};
|
};
|
||||||
await handleNodeEvent(
|
await handleNodeEvent(nodeContext, "node", {
|
||||||
nodeContext,
|
|
||||||
"node",
|
|
||||||
{
|
|
||||||
event: p.event,
|
event: p.event,
|
||||||
payloadJSON,
|
payloadJSON,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
respond(true, { ok: true }, undefined);
|
respond(true, { ok: true }, undefined);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,11 +11,7 @@ import type { NodeEvent, NodeEventContext } from "./server-node-events-types.js"
|
|||||||
import { loadSessionEntry } from "./session-utils.js";
|
import { loadSessionEntry } from "./session-utils.js";
|
||||||
import { formatForLog } from "./ws-log.js";
|
import { formatForLog } from "./ws-log.js";
|
||||||
|
|
||||||
export const handleNodeEvent = async (
|
export const handleNodeEvent = async (ctx: NodeEventContext, nodeId: string, evt: NodeEvent) => {
|
||||||
ctx: NodeEventContext,
|
|
||||||
nodeId: string,
|
|
||||||
evt: NodeEvent,
|
|
||||||
) => {
|
|
||||||
switch (evt.event) {
|
switch (evt.event) {
|
||||||
case "voice.transcript": {
|
case "voice.transcript": {
|
||||||
if (!evt.payloadJSON) return;
|
if (!evt.payloadJSON) return;
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
import type { GatewayAuthConfig, GatewayBindMode, GatewayTailscaleConfig, loadConfig } from "../config/config.js";
|
import type {
|
||||||
|
GatewayAuthConfig,
|
||||||
|
GatewayBindMode,
|
||||||
|
GatewayTailscaleConfig,
|
||||||
|
loadConfig,
|
||||||
|
} from "../config/config.js";
|
||||||
import {
|
import {
|
||||||
assertGatewayAuthConfigured,
|
assertGatewayAuthConfigured,
|
||||||
type ResolvedGatewayAuth,
|
type ResolvedGatewayAuth,
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ export function logGatewayStartup(params: {
|
|||||||
consoleMessage: `agent model: ${chalk.whiteBright(modelRef)}`,
|
consoleMessage: `agent model: ${chalk.whiteBright(modelRef)}`,
|
||||||
});
|
});
|
||||||
const scheme = params.tlsEnabled ? "wss" : "ws";
|
const scheme = params.tlsEnabled ? "wss" : "ws";
|
||||||
params.log.info(`listening on ${scheme}://${params.bindHost}:${params.port} (PID ${process.pid})`);
|
params.log.info(
|
||||||
|
`listening on ${scheme}://${params.bindHost}:${params.port} (PID ${process.pid})`,
|
||||||
|
);
|
||||||
params.log.info(`log file: ${getResolvedLoggerSettings().file}`);
|
params.log.info(`log file: ${getResolvedLoggerSettings().file}`);
|
||||||
if (params.isNixMode) {
|
if (params.isNixMode) {
|
||||||
params.log.info("gateway: running in Nix mode (config managed externally)");
|
params.log.info("gateway: running in Nix mode (config managed externally)");
|
||||||
|
|||||||
@@ -260,5 +260,4 @@ describe("gateway server models + voicewake", () => {
|
|||||||
ws.close();
|
ws.close();
|
||||||
await server.close();
|
await server.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -499,7 +499,9 @@ export function attachGatewayWsMessageHandler(params: {
|
|||||||
commands: nodeSession.commands,
|
commands: nodeSession.commands,
|
||||||
cfg: loadConfig(),
|
cfg: loadConfig(),
|
||||||
}).catch((err) =>
|
}).catch((err) =>
|
||||||
logGateway.warn(`remote bin probe failed for ${nodeSession.nodeId}: ${formatForLog(err)}`),
|
logGateway.warn(
|
||||||
|
`remote bin probe failed for ${nodeSession.nodeId}: ${formatForLog(err)}`,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
void loadVoiceWakeConfig()
|
void loadVoiceWakeConfig()
|
||||||
.then((cfg) => {
|
.then((cfg) => {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import type { PluginRegistry } from "../plugins/registry.js";
|
|||||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||||
import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js";
|
import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js";
|
||||||
|
|
||||||
|
|
||||||
type StubChannelOptions = {
|
type StubChannelOptions = {
|
||||||
id: ChannelPlugin["id"];
|
id: ChannelPlugin["id"];
|
||||||
label: string;
|
label: string;
|
||||||
|
|||||||
@@ -27,11 +27,7 @@ function ensureDir(filePath: string) {
|
|||||||
const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
||||||
|
|
||||||
function base64UrlEncode(buf: Buffer): string {
|
function base64UrlEncode(buf: Buffer): string {
|
||||||
return buf
|
return buf.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/g, "");
|
||||||
.toString("base64")
|
|
||||||
.replaceAll("+", "-")
|
|
||||||
.replaceAll("/", "_")
|
|
||||||
.replace(/=+$/g, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function base64UrlDecode(input: string): Buffer {
|
function base64UrlDecode(input: string): Buffer {
|
||||||
|
|||||||
@@ -26,10 +26,7 @@ import { getMachineDisplayName } from "../infra/machine-name.js";
|
|||||||
import { loadOrCreateDeviceIdentity } from "../infra/device-identity.js";
|
import { loadOrCreateDeviceIdentity } from "../infra/device-identity.js";
|
||||||
import { loadConfig } from "../config/config.js";
|
import { loadConfig } from "../config/config.js";
|
||||||
import { VERSION } from "../version.js";
|
import { VERSION } from "../version.js";
|
||||||
import {
|
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
|
||||||
GATEWAY_CLIENT_MODES,
|
|
||||||
GATEWAY_CLIENT_NAMES,
|
|
||||||
} from "../utils/message-channel.js";
|
|
||||||
|
|
||||||
import { ensureNodeHostConfig, saveNodeHostConfig, type NodeHostGatewayConfig } from "./config.js";
|
import { ensureNodeHostConfig, saveNodeHostConfig, type NodeHostGatewayConfig } from "./config.js";
|
||||||
import { GatewayClient } from "../gateway/client.js";
|
import { GatewayClient } from "../gateway/client.js";
|
||||||
@@ -804,8 +801,7 @@ function coerceNodeInvokePayload(payload: unknown): NodeInvokeRequestPayload | n
|
|||||||
? JSON.stringify(obj.params)
|
? JSON.stringify(obj.params)
|
||||||
: null;
|
: null;
|
||||||
const timeoutMs = typeof obj.timeoutMs === "number" ? obj.timeoutMs : null;
|
const timeoutMs = typeof obj.timeoutMs === "number" ? obj.timeoutMs : null;
|
||||||
const idempotencyKey =
|
const idempotencyKey = typeof obj.idempotencyKey === "string" ? obj.idempotencyKey : null;
|
||||||
typeof obj.idempotencyKey === "string" ? obj.idempotencyKey : null;
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
nodeId,
|
nodeId,
|
||||||
@@ -840,11 +836,7 @@ async function sendInvokeResult(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendNodeEvent(
|
async function sendNodeEvent(client: GatewayClient, event: string, payload: unknown) {
|
||||||
client: GatewayClient,
|
|
||||||
event: string,
|
|
||||||
payload: unknown,
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
await client.request("node.event", {
|
await client.request("node.event", {
|
||||||
event,
|
event,
|
||||||
|
|||||||
Reference in New Issue
Block a user