Download src/auto-reply/reply/exec/directive.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 5.71 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/auto-reply/reply/exec/directive.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/auto-reply/reply/exec/directive.ts
-
curl -L -o directive.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/auto-reply/reply/exec/directive.ts
5.71 kB
| // Parses execution directives for approval, sandbox, and target settings. | |
| import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce"; | |
| import { | |
| type ExecAsk, | |
| type ExecSecurity, | |
| type ExecTarget, | |
| normalizeExecTarget, | |
| } from "../../../infra/exec-approvals-core.js"; | |
| import { | |
| removeDirectiveSpan, | |
| skipDirectiveArgPrefix, | |
| takeDirectiveToken, | |
| } from "../directive-parsing.js"; | |
| /** Parsed `/exec` directive state used to override execution policy for one turn. */ | |
| type ExecDirectiveParse = { | |
| cleaned: string; | |
| hasDirective: boolean; | |
| execHost?: ExecTarget; | |
| execSecurity?: ExecSecurity; | |
| execAsk?: ExecAsk; | |
| execNode?: string; | |
| rawExecHost?: string; | |
| rawExecSecurity?: string; | |
| rawExecAsk?: string; | |
| rawExecNode?: string; | |
| hasExecOptions: boolean; | |
| invalidHost: boolean; | |
| invalidSecurity: boolean; | |
| invalidAsk: boolean; | |
| invalidNode: boolean; | |
| }; | |
| function normalizeExecSecurity(value?: string): ExecSecurity | undefined { | |
| const normalized = normalizeOptionalLowercaseString(value); | |
| if (normalized === "deny" || normalized === "allowlist" || normalized === "full") { | |
| return normalized; | |
| } | |
| return undefined; | |
| } | |
| function normalizeExecAsk(value?: string): ExecAsk | undefined { | |
| const normalized = normalizeOptionalLowercaseString(value); | |
| if (normalized === "off" || normalized === "on-miss" || normalized === "always") { | |
| return normalized as ExecAsk; | |
| } | |
| return undefined; | |
| } | |
| function parseExecDirectiveArgs(raw: string): Omit< | |
| ExecDirectiveParse, | |
| "cleaned" | "hasDirective" | |
| > & { | |
| consumed: number; | |
| } { | |
| const len = raw.length; | |
| let i = skipDirectiveArgPrefix(raw); | |
| let consumed = i; | |
| let execHost: ExecTarget | undefined; | |
| let execSecurity: ExecSecurity | undefined; | |
| let execAsk: ExecAsk | undefined; | |
| let execNode: string | undefined; | |
| let rawExecHost: string | undefined; | |
| let rawExecSecurity: string | undefined; | |
| let rawExecAsk: string | undefined; | |
| let rawExecNode: string | undefined; | |
| let hasExecOptions = false; | |
| let invalidHost = false; | |
| let invalidSecurity = false; | |
| let invalidAsk = false; | |
| let invalidNode = false; | |
| const takeToken = (): string | null => { | |
| const res = takeDirectiveToken(raw, i); | |
| i = res.nextIndex; | |
| return res.token; | |
| }; | |
| const splitToken = (token: string): { key: string; value: string } | null => { | |
| const eq = token.indexOf("="); | |
| const colon = token.indexOf(":"); | |
| const idx = eq === -1 ? colon : colon === -1 ? eq : Math.min(eq, colon); | |
| if (idx === -1) { | |
| return null; | |
| } | |
| const key = normalizeOptionalLowercaseString(token.slice(0, idx)); | |
| const value = token.slice(idx + 1).trim(); | |
| if (!key) { | |
| return null; | |
| } | |
| return { key, value }; | |
| }; | |
| for (;;) { | |
| if (i >= len) { | |
| break; | |
| } | |
| const token = takeToken(); | |
| if (!token) { | |
| break; | |
| } | |
| const parsed = splitToken(token); | |
| if (!parsed) { | |
| break; | |
| } | |
| const { key, value } = parsed; | |
| if (key === "host") { | |
| rawExecHost = value; | |
| execHost = normalizeExecTarget(value) ?? undefined; | |
| if (!execHost) { | |
| invalidHost = true; | |
| } | |
| hasExecOptions = true; | |
| consumed = i; | |
| continue; | |
| } | |
| if (key === "security") { | |
| rawExecSecurity = value; | |
| execSecurity = normalizeExecSecurity(value); | |
| if (!execSecurity) { | |
| invalidSecurity = true; | |
| } | |
| hasExecOptions = true; | |
| consumed = i; | |
| continue; | |
| } | |
| if (key === "ask") { | |
| rawExecAsk = value; | |
| execAsk = normalizeExecAsk(value); | |
| if (!execAsk) { | |
| invalidAsk = true; | |
| } | |
| hasExecOptions = true; | |
| consumed = i; | |
| continue; | |
| } | |
| if (key === "node") { | |
| rawExecNode = value; | |
| const trimmed = value.trim(); | |
| if (!trimmed) { | |
| invalidNode = true; | |
| } else { | |
| execNode = trimmed; | |
| } | |
| hasExecOptions = true; | |
| consumed = i; | |
| continue; | |
| } | |
| break; | |
| } | |
| return { | |
| consumed, | |
| execHost, | |
| execSecurity, | |
| execAsk, | |
| execNode, | |
| rawExecHost, | |
| rawExecSecurity, | |
| rawExecAsk, | |
| rawExecNode, | |
| hasExecOptions, | |
| invalidHost, | |
| invalidSecurity, | |
| invalidAsk, | |
| invalidNode, | |
| }; | |
| } | |
| /** Extracts and removes `/exec` options from message text. */ | |
| export function extractExecDirective(body?: string): ExecDirectiveParse { | |
| if (!body) { | |
| return { | |
| cleaned: "", | |
| hasDirective: false, | |
| hasExecOptions: false, | |
| invalidHost: false, | |
| invalidSecurity: false, | |
| invalidAsk: false, | |
| invalidNode: false, | |
| }; | |
| } | |
| const re = /(?<!\S)\/exec(?=$|\s|:)/i; | |
| const match = re.exec(body); | |
| if (!match) { | |
| return { | |
| cleaned: body, | |
| hasDirective: false, | |
| hasExecOptions: false, | |
| invalidHost: false, | |
| invalidSecurity: false, | |
| invalidAsk: false, | |
| invalidNode: false, | |
| }; | |
| } | |
| const start = match.index; | |
| const argsStart = start + "/exec".length; | |
| const parsed = parseExecDirectiveArgs(body.slice(argsStart)); | |
| // Remove only consumed key/value options so remaining text still reaches the agent. | |
| const cleaned = removeDirectiveSpan(body, start, argsStart + parsed.consumed); | |
| return { | |
| cleaned, | |
| hasDirective: true, | |
| execHost: parsed.execHost, | |
| execSecurity: parsed.execSecurity, | |
| execAsk: parsed.execAsk, | |
| execNode: parsed.execNode, | |
| rawExecHost: parsed.rawExecHost, | |
| rawExecSecurity: parsed.rawExecSecurity, | |
| rawExecAsk: parsed.rawExecAsk, | |
| rawExecNode: parsed.rawExecNode, | |
| hasExecOptions: parsed.hasExecOptions, | |
| invalidHost: parsed.invalidHost, | |
| invalidSecurity: parsed.invalidSecurity, | |
| invalidAsk: parsed.invalidAsk, | |
| invalidNode: parsed.invalidNode, | |
| }; | |
| } | |