@blundergoat/goat-flow
Version:
AI coding agent harness and local dashboard for Claude Code, OpenAI Codex, Google Antigravity, and GitHub Copilot - setup audits, guardrails, structured skills, deny hooks, and persistent learning loops.
102 lines • 3.98 kB
TypeScript
export declare const TERMINAL_UPLOAD_MAX_FILES = 5;
export declare const TERMINAL_UPLOAD_MAX_BODY_BYTES: number;
/** Upload metadata returned only after bytes have been written inside the session upload directory. */
interface AcceptedUpload {
originalName: string;
savedName: string;
savedAbsPath: string;
savedRelPath: string;
bytes: number;
}
/** Per-file rejection shown to the caller while other valid files in the same request may continue. */
interface RejectedUpload {
originalName: string;
reason: string;
}
/** Batch result that keeps accepted and rejected files separate for partial-success responses. */
interface UploadResult {
accepted: AcceptedUpload[];
rejected: RejectedUpload[];
}
/** Validated session upload directory plus the real target root used for containment checks. */
interface UploadDirectory {
absPath: string;
relPath: string;
realRootPath: string;
}
/**
* Strip directory components and unsafe characters from an upload filename.
*
* @param rawName Browser-provided filename, which may include fake path components.
* @returns Safe basename plus an allowed extension, or an empty extension when unsupported.
*/
export declare function sanitizeUploadFilename(rawName: string): {
base: string;
ext: string;
};
/**
* Detect image format by magic bytes because client MIME types and extensions are not trusted.
*
* @param bytes Decoded file bytes from the upload body.
* @returns Canonical extension for supported image bytes, or null when the content is unsupported.
*/
export declare function detectImageExtension(bytes: Uint8Array): string | null;
/**
* Compose the upload directory path for one terminal session.
* Always under `<targetPath>/.goat-flow/logs/uploads/<sessionId>/` and asserted to remain inside
* `targetPath` to prevent path traversal via the session id.
*
* @param targetPath Selected target project path that owns upload evidence.
* @param sessionId Terminal session id used as the upload subdirectory.
* @returns Absolute and relative upload paths plus the real target root.
* @throws Error when the session id is not a simple path segment.
*/
export declare function uploadDirForSession(targetPath: string, sessionId: string): UploadDirectory;
/**
* Validate one base64 image payload and decode it to bytes.
*
* @param rawName Browser-provided filename used for extension and saved-name hints.
* @param base64 Base64 file body from the upload request.
* @returns Decoded bytes with sanitized filename metadata, or a caller-safe rejection reason.
*/
export declare function decodeUploadFile(rawName: string, base64: string): {
ok: true;
bytes: Uint8Array;
sanitized: {
base: string;
ext: string;
};
} | {
ok: false;
reason: string;
};
/**
* Persist accepted uploads to disk and return their saved metadata.
* Caller is responsible for upstream session/path validation.
*
* @param uploadDir Validated session upload directory.
* @param files Browser-provided file payloads from one upload request.
* @param options Test seams for deterministic saved filenames.
* @returns Accepted file metadata and per-file rejection reasons.
* @throws Error when the created upload directory escapes the real target root.
*/
export declare function persistUploads(uploadDir: {
absPath: string;
relPath: string;
realRootPath?: string;
}, files: Array<{
name: string;
data: string;
}>, options?: {
now?: () => number;
}): UploadResult;
/**
* Build the terminal-paste note that announces saved upload paths.
* Callers paste this into the active PTY; it is plain text only.
*
* @param accepted Files that were saved for the active terminal session.
* @returns Plain text note to paste into the PTY, or an empty string when nothing was accepted.
*/
export declare function buildAttachmentNote(accepted: AcceptedUpload[]): string;
export {};
//# sourceMappingURL=terminal-uploads.d.ts.map