You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
4.3 KiB
158 lines
4.3 KiB
import { z } from "zod";
|
|
import { createHash, randomBytes } from "node:crypto";
|
|
import type { JSONSchema7 } from "json-schema";
|
|
import type { ToolExecutor, ToolContext, ToolResult } from "../../registry";
|
|
import type { Base64ToolConfig } from "./config";
|
|
|
|
export const base64InputSchema = z.object({
|
|
operation: z
|
|
.enum([
|
|
"base64-encode",
|
|
"base64-decode",
|
|
"base64url-encode",
|
|
"base64url-decode",
|
|
"url-encode",
|
|
"url-decode",
|
|
"hash",
|
|
])
|
|
.describe("操作类型"),
|
|
input: z.string().describe("输入内容"),
|
|
algorithm: z
|
|
.enum(["md5", "sha1", "sha256", "sha384", "sha512"])
|
|
.optional()
|
|
.describe("哈希算法 (hash 操作使用)"),
|
|
encoding: z
|
|
.enum(["hex", "base64"])
|
|
.optional()
|
|
.describe("哈希输出编码 (hash 操作使用)"),
|
|
});
|
|
|
|
type Base64Input = z.infer<typeof base64InputSchema>;
|
|
|
|
export const base64Executor: ToolExecutor<Base64ToolConfig> = {
|
|
buildInputSchema(_config: Base64ToolConfig): JSONSchema7 {
|
|
return {
|
|
type: "object",
|
|
properties: {
|
|
operation: {
|
|
type: "string",
|
|
enum: [
|
|
"base64-encode",
|
|
"base64-decode",
|
|
"base64url-encode",
|
|
"base64url-decode",
|
|
"url-encode",
|
|
"url-decode",
|
|
"hash",
|
|
],
|
|
description: "操作类型",
|
|
},
|
|
input: { type: "string", description: "输入内容" },
|
|
algorithm: {
|
|
type: "string",
|
|
enum: ["md5", "sha1", "sha256", "sha384", "sha512"],
|
|
description: "哈希算法 (hash 操作)",
|
|
},
|
|
encoding: {
|
|
type: "string",
|
|
enum: ["hex", "base64"],
|
|
description: "哈希输出编码",
|
|
},
|
|
},
|
|
required: ["operation", "input"],
|
|
};
|
|
},
|
|
|
|
buildDescription(config: Base64ToolConfig): string {
|
|
return `编解码工具。支持 Base64/Base64URL 编解码、URL 编解码、哈希计算(md5/sha1/sha256/sha384/sha512)。最大输入 ${config.maxInputLength} 字符。`;
|
|
},
|
|
|
|
async execute(
|
|
input: unknown,
|
|
config: Base64ToolConfig,
|
|
_ctx: ToolContext,
|
|
): Promise<ToolResult> {
|
|
const start = Date.now();
|
|
|
|
const parsed = base64InputSchema.safeParse(input);
|
|
if (!parsed.success) {
|
|
return {
|
|
success: false,
|
|
data: null,
|
|
error: `输入参数校验失败: ${parsed.error.message}`,
|
|
metadata: { durationMs: Date.now() - start },
|
|
};
|
|
}
|
|
|
|
const inp = parsed.data as Base64Input;
|
|
|
|
if (inp.input.length > config.maxInputLength) {
|
|
return {
|
|
success: false,
|
|
data: null,
|
|
error: `输入过长: ${inp.input.length} 字符 (限制 ${config.maxInputLength})`,
|
|
metadata: { durationMs: Date.now() - start },
|
|
};
|
|
}
|
|
|
|
try {
|
|
let result: string;
|
|
|
|
switch (inp.operation) {
|
|
case "base64-encode":
|
|
result = Buffer.from(inp.input, "utf-8").toString("base64");
|
|
break;
|
|
|
|
case "base64-decode":
|
|
result = Buffer.from(inp.input, "base64").toString("utf-8");
|
|
break;
|
|
|
|
case "base64url-encode":
|
|
result = Buffer.from(inp.input, "utf-8").toString("base64url");
|
|
break;
|
|
|
|
case "base64url-decode":
|
|
result = Buffer.from(inp.input, "base64url").toString("utf-8");
|
|
break;
|
|
|
|
case "url-encode":
|
|
result = encodeURIComponent(inp.input);
|
|
break;
|
|
|
|
case "url-decode":
|
|
result = decodeURIComponent(inp.input);
|
|
break;
|
|
|
|
case "hash": {
|
|
const algorithm = inp.algorithm ?? "sha256";
|
|
const encoding = inp.encoding ?? "hex";
|
|
const hash = createHash(algorithm).update(inp.input, "utf-8");
|
|
result = hash.digest(encoding);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
throw new Error(`未知操作: ${inp.operation}`);
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
data: {
|
|
operation: inp.operation,
|
|
input: inp.input,
|
|
output: result,
|
|
inputLength: inp.input.length,
|
|
outputLength: result.length,
|
|
},
|
|
metadata: { durationMs: Date.now() - start },
|
|
};
|
|
} catch (e) {
|
|
return {
|
|
success: false,
|
|
data: null,
|
|
error: e instanceof Error ? e.message : String(e),
|
|
metadata: { durationMs: Date.now() - start },
|
|
};
|
|
}
|
|
},
|
|
};
|
|
|