mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-13 17:07:40 +00:00
refactor(tlon): remove dead exports (#107233)
This commit is contained in:
committed by
GitHub
parent
69eb20871d
commit
ab95871dd5
@@ -10,7 +10,7 @@ const TlonChannelRuleSchema = z.object({
|
||||
allowedShips: z.array(ShipSchema).optional(),
|
||||
});
|
||||
|
||||
export const TlonAuthorizationSchema = z.object({
|
||||
const TlonAuthorizationSchema = z.object({
|
||||
channelRules: z.record(z.string(), TlonChannelRuleSchema).optional(),
|
||||
});
|
||||
|
||||
@@ -45,7 +45,7 @@ const TlonAccountSchema = z.object({
|
||||
...tlonCommonConfigFields,
|
||||
});
|
||||
|
||||
export const TlonConfigSchema = z.object({
|
||||
const TlonConfigSchema = z.object({
|
||||
...tlonCommonConfigFields,
|
||||
authorization: TlonAuthorizationSchema.optional(),
|
||||
defaultAuthorizedShips: z.array(ShipSchema).optional(),
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import type { WizardPrompter } from "openclaw/plugin-sdk/plugin-test-runtime";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../api.js";
|
||||
import { TlonAuthorizationSchema, TlonConfigSchema } from "./config-schema.js";
|
||||
import { tlonChannelConfigSchema } from "./config-schema.js";
|
||||
import { tlonSetupWizard } from "./setup-surface.js";
|
||||
import { normalizeShip, resolveTlonOutboundTarget } from "./targets.js";
|
||||
import { listTlonAccountIds, resolveTlonAccount } from "./types.js";
|
||||
@@ -47,6 +47,14 @@ const tlonTestPlugin = {
|
||||
const tlonConfigure = createPluginSetupWizardConfigure(tlonTestPlugin);
|
||||
const tlonStatus = createPluginSetupWizardStatus(tlonTestPlugin);
|
||||
|
||||
function parseTlonConfig(value: unknown) {
|
||||
const runtime = tlonChannelConfigSchema.runtime;
|
||||
if (!runtime) {
|
||||
throw new Error("expected Tlon channel config runtime");
|
||||
}
|
||||
return runtime.safeParse(value);
|
||||
}
|
||||
|
||||
describe("tlon core", () => {
|
||||
it("formats dm allowlist entries through the shared hybrid adapter", () => {
|
||||
expect(
|
||||
@@ -85,41 +93,50 @@ describe("tlon core", () => {
|
||||
});
|
||||
|
||||
it("accepts channelRules with string keys", () => {
|
||||
const parsed = TlonAuthorizationSchema.parse({
|
||||
channelRules: {
|
||||
"chat/~zod/test": {
|
||||
mode: "open",
|
||||
allowedShips: ["~zod"],
|
||||
expect(
|
||||
parseTlonConfig({
|
||||
authorization: {
|
||||
channelRules: {
|
||||
"chat/~zod/test": {
|
||||
mode: "open",
|
||||
allowedShips: ["~zod"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
).toMatchObject({
|
||||
success: true,
|
||||
data: { authorization: { channelRules: { "chat/~zod/test": { mode: "open" } } } },
|
||||
});
|
||||
|
||||
expect(parsed.channelRules?.["chat/~zod/test"]?.mode).toBe("open");
|
||||
});
|
||||
|
||||
it("accepts accounts with string keys", () => {
|
||||
const parsed = TlonConfigSchema.parse({
|
||||
accounts: {
|
||||
primary: {
|
||||
ship: "~zod",
|
||||
url: "https://example.com",
|
||||
code: "code-123",
|
||||
expect(
|
||||
parseTlonConfig({
|
||||
accounts: {
|
||||
primary: {
|
||||
ship: "~zod",
|
||||
url: "https://example.com",
|
||||
code: "code-123",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(parsed.accounts?.primary?.ship).toBe("~zod");
|
||||
}),
|
||||
).toMatchObject({ success: true, data: { accounts: { primary: { ship: "~zod" } } } });
|
||||
});
|
||||
|
||||
it("exposes group invite allowlists in channel config schema", () => {
|
||||
expect(TlonConfigSchema.parse({ groupInviteAllowlist: ["~zod"] }).groupInviteAllowlist).toEqual(
|
||||
["~zod"],
|
||||
);
|
||||
expect(
|
||||
TlonConfigSchema.parse({
|
||||
parseTlonConfig({
|
||||
groupInviteAllowlist: ["~zod"],
|
||||
accounts: { primary: { groupInviteAllowlist: ["~nec"] } },
|
||||
}).accounts?.primary?.groupInviteAllowlist,
|
||||
).toEqual(["~nec"]);
|
||||
}),
|
||||
).toMatchObject({
|
||||
success: true,
|
||||
data: {
|
||||
groupInviteAllowlist: ["~zod"],
|
||||
accounts: { primary: { groupInviteAllowlist: ["~nec"] } },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("configures ship, auth, and discovery settings", async () => {
|
||||
|
||||
@@ -9,26 +9,25 @@ vi.mock("node:crypto", () => ({
|
||||
randomBytes: cryptoMocks.randomBytes,
|
||||
}));
|
||||
|
||||
let generateApprovalId: typeof import("./approval.js").generateApprovalId;
|
||||
let createPendingApproval: typeof import("./approval.js").createPendingApproval;
|
||||
let formatApprovalRequest: typeof import("./approval.js").formatApprovalRequest;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ generateApprovalId, createPendingApproval, formatApprovalRequest } =
|
||||
await import("./approval.js"));
|
||||
({ createPendingApproval, formatApprovalRequest } = await import("./approval.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cryptoMocks.randomBytes.mockReset();
|
||||
});
|
||||
|
||||
describe("generateApprovalId", () => {
|
||||
describe("createPendingApproval ID", () => {
|
||||
it("uses secure hex entropy while preserving the ID format", () => {
|
||||
cryptoMocks.randomBytes.mockReturnValueOnce(Buffer.from("a1b2c3", "hex"));
|
||||
const nowSpy = vi.spyOn(Date, "now").mockReturnValue(1_717_171_717_171);
|
||||
|
||||
try {
|
||||
expect(generateApprovalId("dm")).toBe("dm-1717171717171-a1b2c3");
|
||||
const approval = createPendingApproval({ type: "dm", requestingShip: "~sampel-palnet" });
|
||||
expect(approval.id).toBe("dm-1717171717171-a1b2c3");
|
||||
expect(cryptoMocks.randomBytes).toHaveBeenCalledWith(3);
|
||||
} finally {
|
||||
nowSpy.mockRestore();
|
||||
|
||||
@@ -35,7 +35,7 @@ type CreateApprovalParams = {
|
||||
/**
|
||||
* Generate a unique approval ID in the format: {type}-{timestamp}-{shortHash}
|
||||
*/
|
||||
export function generateApprovalId(type: ApprovalType): string {
|
||||
function generateApprovalId(type: ApprovalType): string {
|
||||
const timestamp = Date.now();
|
||||
const randomPart = randomBytes(3).toString("hex");
|
||||
return `${type}-${timestamp}-${randomPart}`;
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
saveRemoteMedia,
|
||||
} from "openclaw/plugin-sdk/media-runtime";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { downloadMedia, extractImageBlocks } from "./media.js";
|
||||
import { downloadMessageImages } from "./media.js";
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/media-runtime", () => ({
|
||||
MAX_IMAGE_BYTES: 6 * 1024 * 1024,
|
||||
@@ -27,15 +27,21 @@ describe("tlon monitor media", () => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("caps extracted images at eight per message", () => {
|
||||
it("caps downloaded images at eight per message", async () => {
|
||||
const content = Array.from({ length: 10 }, (_, index) => ({
|
||||
block: { image: { src: `https://example.com/${index}.png`, alt: `image-${index}` } },
|
||||
}));
|
||||
saveRemoteMediaMock.mockImplementation(async ({ url }) => ({
|
||||
id: `photo-${url}.png`,
|
||||
path: `/tmp/openclaw/media/inbound/${url.split("/").pop()}`,
|
||||
size: 10,
|
||||
contentType: "image/png",
|
||||
}));
|
||||
|
||||
const images = extractImageBlocks(content);
|
||||
const images = await downloadMessageImages(content);
|
||||
|
||||
expect(images).toHaveLength(8);
|
||||
expect(images.map((image) => image.url)).toEqual(
|
||||
expect(saveRemoteMediaMock.mock.calls.map(([options]) => options.url)).toEqual(
|
||||
Array.from({ length: 8 }, (_, index) => `https://example.com/${index}.png`),
|
||||
);
|
||||
});
|
||||
@@ -48,7 +54,9 @@ describe("tlon monitor media", () => {
|
||||
contentType: "image/png",
|
||||
});
|
||||
|
||||
const result = await downloadMedia("https://example.com/photo.png");
|
||||
const result = await downloadMessageImages([
|
||||
{ block: { image: { src: "https://example.com/photo.png" } } },
|
||||
]);
|
||||
|
||||
expect(readRemoteMediaBufferMock).not.toHaveBeenCalled();
|
||||
expect(saveRemoteMediaMock).toHaveBeenCalledTimes(1);
|
||||
@@ -60,11 +68,9 @@ describe("tlon monitor media", () => {
|
||||
ssrfPolicy: undefined,
|
||||
requestInit: { method: "GET" },
|
||||
});
|
||||
expect(result).toEqual({
|
||||
localPath: "/tmp/openclaw/media/inbound/photo---uuid.png",
|
||||
contentType: "image/png",
|
||||
originalUrl: "https://example.com/photo.png",
|
||||
});
|
||||
expect(result).toEqual([
|
||||
{ path: "/tmp/openclaw/media/inbound/photo---uuid.png", contentType: "image/png" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("returns null when the fetch exceeds the image cap", async () => {
|
||||
@@ -74,9 +80,11 @@ describe("tlon monitor media", () => {
|
||||
),
|
||||
);
|
||||
|
||||
const result = await downloadMedia("https://example.com/photo.png");
|
||||
const result = await downloadMessageImages([
|
||||
{ block: { image: { src: "https://example.com/photo.png" } } },
|
||||
]);
|
||||
|
||||
expect(result).toBeNull();
|
||||
expect(result).toEqual([]);
|
||||
expect(readRemoteMediaBufferMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,7 +29,7 @@ interface DownloadedMedia {
|
||||
* Extract image blocks from Tlon message content.
|
||||
* Returns array of image URLs found in the message.
|
||||
*/
|
||||
export function extractImageBlocks(content: unknown): ExtractedImage[] {
|
||||
function extractImageBlocks(content: unknown): ExtractedImage[] {
|
||||
if (!content || !Array.isArray(content)) {
|
||||
return [];
|
||||
}
|
||||
@@ -55,10 +55,7 @@ export function extractImageBlocks(content: unknown): ExtractedImage[] {
|
||||
* Download a media file from URL to local storage.
|
||||
* Returns the local path where the file was saved.
|
||||
*/
|
||||
export async function downloadMedia(
|
||||
url: string,
|
||||
mediaDir?: string,
|
||||
): Promise<DownloadedMedia | null> {
|
||||
async function downloadMedia(url: string, mediaDir?: string): Promise<DownloadedMedia | null> {
|
||||
try {
|
||||
// Validate URL is http/https before fetching
|
||||
const parsedUrl = new URL(url);
|
||||
|
||||
@@ -272,11 +272,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"extensions/telegram/src/topic-name-cache.ts: setTelegramTopicNameStoreFactoryForTest",
|
||||
"extensions/telegram/src/update-offset-store.ts: setTelegramUpdateOffsetStoreForTest",
|
||||
"extensions/telegram/src/update-offset-store.ts: TelegramUpdateOffsetState",
|
||||
"extensions/tlon/src/config-schema.ts: TlonAuthorizationSchema",
|
||||
"extensions/tlon/src/config-schema.ts: TlonConfigSchema",
|
||||
"extensions/tlon/src/monitor/approval.ts: generateApprovalId",
|
||||
"extensions/tlon/src/monitor/media.ts: downloadMedia",
|
||||
"extensions/tlon/src/monitor/media.ts: extractImageBlocks",
|
||||
"extensions/twitch/src/client-manager-registry.ts: clearRegistryForTest",
|
||||
"extensions/twitch/src/config.ts: ResolvedTwitchAccountContext",
|
||||
"extensions/twitch/src/monitor.ts: testing",
|
||||
|
||||
Reference in New Issue
Block a user