mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-19 08:34:45 +00:00
220 lines
6.0 KiB
TypeScript
220 lines
6.0 KiB
TypeScript
export type CommandTurnKind = "native" | "text-slash" | "normal";
|
|
export type CommandTurnSource = "native" | "text" | "message";
|
|
|
|
type BaseCommandTurnContext = {
|
|
commandName?: string;
|
|
body?: string;
|
|
};
|
|
|
|
export type NativeCommandTurnContext = BaseCommandTurnContext & {
|
|
kind: "native";
|
|
source: "native";
|
|
authorized: boolean;
|
|
};
|
|
|
|
export type TextSlashCommandTurnContext = BaseCommandTurnContext & {
|
|
kind: "text-slash";
|
|
source: "text";
|
|
authorized: boolean;
|
|
};
|
|
|
|
export type NormalCommandTurnContext = BaseCommandTurnContext & {
|
|
kind: "normal";
|
|
source: "message";
|
|
authorized: false;
|
|
};
|
|
|
|
export type CommandTurnContext =
|
|
| NativeCommandTurnContext
|
|
| TextSlashCommandTurnContext
|
|
| NormalCommandTurnContext;
|
|
|
|
export type CommandTurnContextInput = {
|
|
CommandTurn?: unknown;
|
|
CommandSource?: unknown;
|
|
CommandAuthorized?: unknown;
|
|
CommandBody?: unknown;
|
|
BodyForCommands?: unknown;
|
|
RawBody?: unknown;
|
|
Body?: unknown;
|
|
};
|
|
|
|
function normalizeOptionalString(value: unknown): string | undefined {
|
|
if (typeof value !== "string") {
|
|
return undefined;
|
|
}
|
|
const trimmed = value.trim();
|
|
return trimmed.length > 0 ? trimmed : undefined;
|
|
}
|
|
|
|
function resolveCommandBody(input: CommandTurnContextInput): string | undefined {
|
|
return (
|
|
normalizeOptionalString(input.CommandBody) ??
|
|
normalizeOptionalString(input.BodyForCommands) ??
|
|
normalizeOptionalString(input.RawBody) ??
|
|
normalizeOptionalString(input.Body)
|
|
);
|
|
}
|
|
|
|
function parseCommandName(body: string | undefined): string | undefined {
|
|
if (!body?.startsWith("/")) {
|
|
return undefined;
|
|
}
|
|
const name = body.slice(1).split(/\s+/, 1)[0]?.split("@", 1)[0];
|
|
return normalizeOptionalString(name);
|
|
}
|
|
|
|
export function commandTurnKindToSource(kind: CommandTurnKind): CommandTurnSource {
|
|
if (kind === "native") {
|
|
return "native";
|
|
}
|
|
if (kind === "text-slash") {
|
|
return "text";
|
|
}
|
|
return "message";
|
|
}
|
|
|
|
function normalizeCommandTurnKind(value: unknown): CommandTurnKind | undefined {
|
|
return value === "native" || value === "text-slash" || value === "normal" ? value : undefined;
|
|
}
|
|
|
|
function normalizeCommandTurnSource(value: unknown): CommandTurnSource | undefined {
|
|
return value === "native" || value === "text" || value === "message" ? value : undefined;
|
|
}
|
|
|
|
export function commandTurnSourceToKind(source: CommandTurnSource): CommandTurnKind {
|
|
if (source === "native") {
|
|
return "native";
|
|
}
|
|
if (source === "text") {
|
|
return "text-slash";
|
|
}
|
|
return "normal";
|
|
}
|
|
|
|
export function createCommandTurnContext(
|
|
source: CommandTurnSource,
|
|
input: {
|
|
authorized: boolean;
|
|
commandName?: string;
|
|
body?: string;
|
|
},
|
|
): CommandTurnContext {
|
|
if (source === "native") {
|
|
return {
|
|
kind: "native",
|
|
source: "native",
|
|
authorized: input.authorized,
|
|
commandName: input.commandName,
|
|
body: input.body,
|
|
};
|
|
}
|
|
if (source === "text") {
|
|
return {
|
|
kind: "text-slash",
|
|
source: "text",
|
|
authorized: input.authorized,
|
|
commandName: input.commandName,
|
|
body: input.body,
|
|
};
|
|
}
|
|
return {
|
|
kind: "normal",
|
|
source: "message",
|
|
authorized: false,
|
|
commandName: input.commandName,
|
|
body: input.body,
|
|
};
|
|
}
|
|
|
|
function normalizeExplicitCommandTurn(
|
|
value: unknown,
|
|
input: CommandTurnContextInput,
|
|
): CommandTurnContext | undefined {
|
|
if (!value || typeof value !== "object") {
|
|
return undefined;
|
|
}
|
|
const record = value as Record<string, unknown>;
|
|
const kind = normalizeCommandTurnKind(record.kind);
|
|
const source =
|
|
normalizeCommandTurnSource(record.source) ?? (kind ? commandTurnKindToSource(kind) : undefined);
|
|
const resolvedKind = kind ?? (source ? commandTurnSourceToKind(source) : undefined);
|
|
if (kind && source && commandTurnKindToSource(kind) !== source) {
|
|
return undefined;
|
|
}
|
|
if (!resolvedKind || !source) {
|
|
return undefined;
|
|
}
|
|
const body = normalizeOptionalString(record.body) ?? resolveCommandBody(input);
|
|
return createCommandTurnContext(source, {
|
|
authorized:
|
|
resolvedKind === "normal"
|
|
? false
|
|
: typeof record.authorized === "boolean"
|
|
? record.authorized
|
|
: input.CommandAuthorized === true,
|
|
commandName: normalizeOptionalString(record.commandName) ?? parseCommandName(body),
|
|
body,
|
|
});
|
|
}
|
|
|
|
export function resolveCommandTurnContext(input: CommandTurnContextInput): CommandTurnContext {
|
|
const explicit = normalizeExplicitCommandTurn(input.CommandTurn, input);
|
|
if (explicit) {
|
|
return explicit;
|
|
}
|
|
const source =
|
|
input.CommandSource === "native"
|
|
? "native"
|
|
: input.CommandSource === "text"
|
|
? "text"
|
|
: "message";
|
|
const body = resolveCommandBody(input);
|
|
const kind = commandTurnSourceToKind(source);
|
|
return createCommandTurnContext(source, {
|
|
authorized: kind === "normal" ? false : input.CommandAuthorized === true,
|
|
commandName: parseCommandName(body),
|
|
body,
|
|
});
|
|
}
|
|
|
|
export function isNativeCommandTurn(commandTurn: CommandTurnContext | undefined): boolean {
|
|
return commandTurn?.kind === "native";
|
|
}
|
|
|
|
export function isTextSlashCommandTurn(commandTurn: CommandTurnContext | undefined): boolean {
|
|
return commandTurn?.kind === "text-slash";
|
|
}
|
|
|
|
export function isAuthorizedTextSlashCommandTurn(
|
|
commandTurn: CommandTurnContext | undefined,
|
|
): boolean {
|
|
return commandTurn?.kind === "text-slash" && commandTurn.authorized;
|
|
}
|
|
|
|
export function isExplicitCommandTurn(commandTurn: CommandTurnContext | undefined): boolean {
|
|
return (
|
|
commandTurn?.kind === "native" || (commandTurn?.kind === "text-slash" && commandTurn.authorized)
|
|
);
|
|
}
|
|
|
|
export function resolveCommandTurnTargetSessionKey(input: {
|
|
CommandTurn?: CommandTurnContext;
|
|
CommandSource?: unknown;
|
|
CommandAuthorized?: unknown;
|
|
CommandBody?: unknown;
|
|
BodyForCommands?: unknown;
|
|
RawBody?: unknown;
|
|
Body?: unknown;
|
|
CommandTargetSessionKey?: unknown;
|
|
}): string | undefined {
|
|
if (
|
|
!isNativeCommandTurn(resolveCommandTurnContext(input)) ||
|
|
typeof input.CommandTargetSessionKey !== "string"
|
|
) {
|
|
return undefined;
|
|
}
|
|
const trimmed = input.CommandTargetSessionKey.trim();
|
|
return trimmed.length > 0 ? trimmed : undefined;
|
|
}
|