mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(plugin-sdk): align Discord component edit facade types (#91679)
* fix(plugin-sdk): align Discord component edit facade types * test(plugin-sdk): satisfy Discord facade type lint * test(upgrade): seed migrated survivor sessions --------- Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,10 +1,34 @@
|
||||
import { describe, expect, expectTypeOf, it, vi } from "vitest";
|
||||
import type { MessageReceipt } from "./channel-outbound.js";
|
||||
/**
|
||||
* Tests Discord SDK helpers and Discord-facing compatibility behavior.
|
||||
*/
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type {
|
||||
DiscordComponentSendOpts,
|
||||
DiscordComponentSendResult,
|
||||
OpenClawConfig,
|
||||
} from "./discord.js";
|
||||
|
||||
const mocks = vi.hoisted(() => {
|
||||
const runtimeConfig = { channels: { discord: { token: "token" } } };
|
||||
const componentEditResult = {
|
||||
channelId: "channel",
|
||||
messageId: "message",
|
||||
receipt: {
|
||||
parts: [
|
||||
{
|
||||
index: 0,
|
||||
kind: "card",
|
||||
platformMessageId: "message",
|
||||
raw: { channel: "discord", channelId: "channel", messageId: "message" },
|
||||
},
|
||||
],
|
||||
platformMessageIds: ["message"],
|
||||
primaryPlatformMessageId: "message",
|
||||
raw: [{ channel: "discord", channelId: "channel", messageId: "message" }],
|
||||
sentAt: 0,
|
||||
},
|
||||
};
|
||||
const apiModule = {
|
||||
buildDiscordComponentMessage: vi.fn((params: { spec: { text?: string } }) => ({
|
||||
components: [],
|
||||
@@ -40,7 +64,7 @@ const mocks = vi.hoisted(() => {
|
||||
cfg: params.cfg,
|
||||
})),
|
||||
collectDiscordAuditChannelIds: vi.fn(() => ({ channelIds: [], unresolvedChannels: [] })),
|
||||
editDiscordComponentMessage: vi.fn(async () => ({ id: "message" })),
|
||||
editDiscordComponentMessage: vi.fn(async () => componentEditResult),
|
||||
listThreadBindingsBySessionKey: vi.fn(() => []),
|
||||
registerBuiltDiscordComponentMessage: vi.fn(),
|
||||
unbindThreadBindingsBySessionKey: vi.fn(() => []),
|
||||
@@ -48,6 +72,7 @@ const mocks = vi.hoisted(() => {
|
||||
|
||||
return {
|
||||
apiModule,
|
||||
componentEditResult,
|
||||
runtimeModule,
|
||||
runtimeConfig,
|
||||
loadBundledPluginPublicSurfaceModuleSync: vi.fn((params: { artifactBasename: string }) => {
|
||||
@@ -128,7 +153,7 @@ describe("discord plugin-sdk facade", () => {
|
||||
} = await import("./discord.js");
|
||||
|
||||
const built = buildDiscordComponentMessage({ spec: { text: "hello" } });
|
||||
await editDiscordComponentMessage(
|
||||
const editResult = await editDiscordComponentMessage(
|
||||
"channel",
|
||||
"message",
|
||||
{ text: "edited" },
|
||||
@@ -148,12 +173,28 @@ describe("discord plugin-sdk facade", () => {
|
||||
{ text: "edited" },
|
||||
{ cfg: mocks.runtimeConfig },
|
||||
);
|
||||
expect(editResult).toEqual(mocks.componentEditResult);
|
||||
expect(mocks.runtimeModule.registerBuiltDiscordComponentMessage).toHaveBeenCalledWith({
|
||||
buildResult: built,
|
||||
messageId: "message",
|
||||
});
|
||||
});
|
||||
|
||||
it("types Discord component edit options and normalized result", () => {
|
||||
type IsCfgOptional = object extends Pick<DiscordComponentSendOpts, "cfg"> ? true : false;
|
||||
|
||||
expectTypeOf<IsCfgOptional>().toEqualTypeOf<false>();
|
||||
expectTypeOf<DiscordComponentSendOpts["cfg"]>().toEqualTypeOf<OpenClawConfig>();
|
||||
expectTypeOf<DiscordComponentSendResult>().toEqualTypeOf<{
|
||||
messageId: string;
|
||||
channelId: string;
|
||||
receipt: MessageReceipt;
|
||||
}>();
|
||||
expectTypeOf<keyof DiscordComponentSendResult>().toEqualTypeOf<
|
||||
"messageId" | "channelId" | "receipt"
|
||||
>();
|
||||
});
|
||||
|
||||
it("fills runtime config for Discord subagent auto-bind calls without cfg", async () => {
|
||||
const { autoBindSpawnedDiscordSubagent } = await import("./discord.js");
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import type {
|
||||
ChannelStatusIssue,
|
||||
} from "./channel-contract.js";
|
||||
import type { ChannelPlugin } from "./channel-core.js";
|
||||
import type { MessageReceipt } from "./channel-outbound.js";
|
||||
import type { OpenClawConfig } from "./config-types.js";
|
||||
import {
|
||||
createLazyFacadeObjectValue,
|
||||
@@ -67,7 +68,7 @@ export type DiscordComponentBuildResult = {
|
||||
|
||||
/** Send/edit options for Discord component messages. */
|
||||
export type DiscordComponentSendOpts = {
|
||||
cfg?: OpenClawConfig;
|
||||
cfg: OpenClawConfig;
|
||||
accountId?: string;
|
||||
replyTo?: string;
|
||||
files?: unknown;
|
||||
@@ -80,11 +81,11 @@ export type DiscordComponentSendOpts = {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
/** Minimal Discord API message result returned by component send/edit helpers. */
|
||||
/** Normalized Discord message result returned by component send/edit helpers. */
|
||||
export type DiscordComponentSendResult = {
|
||||
id?: string;
|
||||
channel_id?: string;
|
||||
[key: string]: unknown;
|
||||
messageId: string;
|
||||
channelId: string;
|
||||
receipt: MessageReceipt;
|
||||
};
|
||||
|
||||
/** Resolved Discord account with token source metadata for status and runtime checks. */
|
||||
|
||||
@@ -3,6 +3,7 @@ import { execFileSync } from "node:child_process";
|
||||
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { DatabaseSync } from "node:sqlite";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const ASSERTIONS_PATH = "scripts/e2e/lib/upgrade-survivor/assertions.mjs";
|
||||
@@ -11,6 +12,70 @@ function writeJson(path: string, value: unknown): void {
|
||||
writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`);
|
||||
}
|
||||
|
||||
function writeMigratedSessionState(stateDir: string): void {
|
||||
const agentSessionsDir = join(stateDir, "agents", "main", "sessions");
|
||||
const agentDbDir = join(stateDir, "agents", "main", "agent");
|
||||
const mainSessionFile = join(agentSessionsDir, "upgrade-main-session.jsonl");
|
||||
const directSessionFile = join(agentSessionsDir, "upgrade-direct-session.jsonl");
|
||||
const groupSessionFile = join(agentSessionsDir, "upgrade-group-session.jsonl");
|
||||
mkdirSync(agentSessionsDir, { recursive: true });
|
||||
mkdirSync(agentDbDir, { recursive: true });
|
||||
writeFileSync(mainSessionFile, '{"type":"main"}\n');
|
||||
writeFileSync(directSessionFile, '{"type":"direct"}\n');
|
||||
writeFileSync(groupSessionFile, '{"type":"group"}\n');
|
||||
|
||||
const db = new DatabaseSync(join(agentDbDir, "openclaw-agent.sqlite"));
|
||||
try {
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS cache_entries (
|
||||
scope TEXT NOT NULL,
|
||||
key TEXT NOT NULL,
|
||||
value_json TEXT,
|
||||
blob BLOB,
|
||||
expires_at INTEGER,
|
||||
updated_at INTEGER NOT NULL,
|
||||
PRIMARY KEY (scope, key)
|
||||
);
|
||||
`);
|
||||
const insert = db.prepare(`
|
||||
INSERT INTO cache_entries (scope, key, value_json, updated_at)
|
||||
VALUES (?, ?, ?, ?)
|
||||
`);
|
||||
insert.run(
|
||||
"session_entries",
|
||||
"agent:main:main",
|
||||
JSON.stringify({
|
||||
sessionFile: mainSessionFile,
|
||||
sessionId: "upgrade-main-session",
|
||||
skillsSnapshot: {
|
||||
prompt: "legacy prompt survives as metadata",
|
||||
},
|
||||
}),
|
||||
1710000000000,
|
||||
);
|
||||
insert.run(
|
||||
"session_entries",
|
||||
"agent:main:+15551234567",
|
||||
JSON.stringify({
|
||||
sessionFile: directSessionFile,
|
||||
sessionId: "upgrade-direct-session",
|
||||
}),
|
||||
1710000000100,
|
||||
);
|
||||
insert.run(
|
||||
"session_entries",
|
||||
"agent:main:slack:channel:cupgrade",
|
||||
JSON.stringify({
|
||||
sessionFile: groupSessionFile,
|
||||
sessionId: "upgrade-group-session",
|
||||
}),
|
||||
1710000000200,
|
||||
);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
||||
function assertConfiguredPluginState(params: { installPath?: string } = {}): void {
|
||||
const root = mkdtempSync(join(tmpdir(), "openclaw-upgrade-survivor-"));
|
||||
try {
|
||||
@@ -25,6 +90,7 @@ function assertConfiguredPluginState(params: { installPath?: string } = {}): voi
|
||||
writeJson(join(stateDir, "agents", "main", "sessions", "legacy-session.json"), {
|
||||
id: "legacy-session",
|
||||
});
|
||||
writeMigratedSessionState(stateDir);
|
||||
writeJson(join(matrixInstallDir, "package.json"), {
|
||||
name: "@openclaw/matrix",
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user