mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
docs: document agent utility helpers
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
/**
|
||||
* YAML frontmatter parsing helpers.
|
||||
*
|
||||
* Agent docs/tools use this to split optional Markdown frontmatter from the
|
||||
* body while preserving normal content when no complete frontmatter fence exists.
|
||||
*/
|
||||
import { parse } from "yaml";
|
||||
|
||||
/** Parsed frontmatter metadata plus the remaining document body. */
|
||||
type ParsedFrontmatter<T extends Record<string, unknown>> = {
|
||||
frontmatter: T;
|
||||
body: string;
|
||||
@@ -26,6 +33,7 @@ const extractFrontmatter = (content: string): { yamlString: string | null; body:
|
||||
};
|
||||
};
|
||||
|
||||
/** Parses optional YAML frontmatter from Markdown-like content. */
|
||||
export const parseFrontmatter = <T extends Record<string, unknown> = Record<string, unknown>>(
|
||||
content: string,
|
||||
): ParsedFrontmatter<T> => {
|
||||
@@ -37,4 +45,5 @@ export const parseFrontmatter = <T extends Record<string, unknown> = Record<stri
|
||||
return { frontmatter: (parsed ?? {}) as T, body };
|
||||
};
|
||||
|
||||
/** Removes YAML frontmatter from content when a complete frontmatter block exists. */
|
||||
export const stripFrontmatter = (content: string): string => parseFrontmatter(content).body;
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
/**
|
||||
* Lightweight MIME sniffing helpers for agent image inputs.
|
||||
*
|
||||
* The checks here avoid trusting file extensions and reject unsupported image
|
||||
* variants before provider upload paths try to process them.
|
||||
*/
|
||||
import { open } from "node:fs/promises";
|
||||
|
||||
const IMAGE_TYPE_SNIFF_BYTES = 4100;
|
||||
const PNG_SIGNATURE = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
|
||||
|
||||
/** Detects supported image MIME types from leading file bytes. */
|
||||
export function detectSupportedImageMimeType(buffer: Uint8Array): string | null {
|
||||
if (startsWith(buffer, [0xff, 0xd8, 0xff])) {
|
||||
return buffer[3] === 0xf7 ? null : "image/jpeg";
|
||||
@@ -19,6 +26,7 @@ export function detectSupportedImageMimeType(buffer: Uint8Array): string | null
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Reads a bounded prefix from disk and detects its supported image MIME type. */
|
||||
export async function detectSupportedImageMimeTypeFromFile(
|
||||
filePath: string,
|
||||
): Promise<string | null> {
|
||||
@@ -52,6 +60,7 @@ function isAnimatedPng(buffer: Uint8Array): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
// PNG chunk length is untrusted input; bail if advancing would wrap or exceed the sniffed bytes.
|
||||
const nextOffset = offset + 8 + chunkLength + 4;
|
||||
if (nextOffset <= offset || nextOffset > buffer.length) {
|
||||
return false;
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
/**
|
||||
* Syntax highlighting renderer for terminal-friendly formatted output.
|
||||
*
|
||||
* Highlight.js emits HTML spans; this module walks that small HTML subset and
|
||||
* maps active scopes to caller-provided text formatters.
|
||||
*/
|
||||
import hljs from "highlight.js";
|
||||
import { decodeHtmlEntityAt } from "./html.js";
|
||||
|
||||
/** Formatter applied to highlighted text segments. */
|
||||
export type HighlightFormatter = (text: string) => string;
|
||||
/** Mapping from highlight.js scope names to text formatters. */
|
||||
export type HighlightTheme = Partial<Record<string, HighlightFormatter>>;
|
||||
|
||||
/** Options used when highlighting code and rendering themed text. */
|
||||
export interface HighlightOptions {
|
||||
language?: string;
|
||||
ignoreIllegals?: boolean;
|
||||
@@ -86,6 +95,7 @@ function isSpanOpenTagStart(html: string, index: number): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
/** Renders highlight.js span HTML into themed plain text. */
|
||||
export function renderHighlightedHtml(html: string, theme: HighlightTheme = {}): string {
|
||||
let output = "";
|
||||
let textBuffer = "";
|
||||
@@ -105,6 +115,7 @@ export function renderHighlightedHtml(html: string, theme: HighlightTheme = {}):
|
||||
if (isSpanOpenTagStart(html, index)) {
|
||||
const tagEndIndex = html.indexOf(">", index + 5);
|
||||
if (tagEndIndex !== -1) {
|
||||
// Scope stack mirrors nested highlight.js spans so inner scopes override outer ones.
|
||||
flushText();
|
||||
const tag = html.slice(index, tagEndIndex + 1);
|
||||
const scope = getScopeFromSpanTag(tag);
|
||||
@@ -140,6 +151,7 @@ export function renderHighlightedHtml(html: string, theme: HighlightTheme = {}):
|
||||
return output;
|
||||
}
|
||||
|
||||
/** Highlights code using an explicit language or highlight.js auto-detection. */
|
||||
export function highlight(code: string, options: HighlightOptions = {}): string {
|
||||
const html = options.language
|
||||
? hljs.highlight(code, {
|
||||
@@ -150,6 +162,7 @@ export function highlight(code: string, options: HighlightOptions = {}): string
|
||||
return renderHighlightedHtml(html, options.theme);
|
||||
}
|
||||
|
||||
/** Returns whether highlight.js has a registered language by this name. */
|
||||
export function supportsLanguage(name: string): boolean {
|
||||
return hljs.getLanguage(name) !== undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user