#ifndef CST_ATTACH_H #define CST_ATTACH_H #include "cst_agent.h" #include #ifdef __cplusplus extern "C" { #endif /* --- attachments --------------------------------------------------------- * An attachment is a validated copy of a file, stored beside the session so * what a model is shown stays what was picked. Images are stored as they are * and encoded into the request when it is built; a PDF is reduced to its text * layer and a text file is stored as is, both of which travel inline as text * (so a text-only model still gets them). Only the metadata goes in the * JSONL. */ /* Supported: PNG, JPEG, GIF, WebP, BMP (static images), PDF, UTF-8 text. */ #define CST_ATTACH_MAX_BYTES (16 * 1024 * 1024) /* one picked file */ #define CST_ATTACH_MAX_TOTAL (32 * 1024 * 1024) /* per request */ #define CST_ATTACH_MAX_COUNT 8 /* per message */ /* Text stored and inlined per document (a PDF also caps its text here). */ #define CST_ATTACH_TEXT_MAX (4 * 1024 * 1024) /* A delivered file (deliver_file) is the opposite of an attachment: it is * handed to the person, not to the model, so any bytes are allowed up to this * size, the extension names the type, and no request ever shows it. */ #define CST_ARTIFACT_MAX_BYTES (64 * 1024 * 1024) /* Images go on the wire as image parts; everything else is inlined as text. */ int cst_attach_is_image(const cst_attachment_t *a); int cst_attach_is_text(const cst_attachment_t *a); /* Magic-byte test: 0 and a canonical mime when data holds a supported * image, -1 otherwise (an extension alone never decides). */ int cst_attach_sniff(const void *data, size_t n, char *mime, size_t mime_sz); /* Pixel size from the header when it is readable; 0 for unknown. */ int cst_attach_dimensions(const void *data, size_t n, int *w, int *h); /* A stored file name as store() makes it ("."); rejects anything * that could leave the attachment directory. */ int cst_attach_rel_ok(const char *rel); /* Directory holding this session's stored images (created on demand). */ int cst_attach_dir(const char *session_path, char *out, size_t out_sz); /* Absolute path of a stored image (0 / -1). */ int cst_attach_full_path(const char *session_path, const cst_attachment_t *a, char *out, size_t out_sz); /* Read src_path and copy it into the session's attachment directory: an image * as it is, a PDF as its extracted text, anything else only when it is text. * Returns a malloc'd entry the caller owns (cst_attach_free), or NULL with * err filled. */ cst_attachment_t *cst_attach_import_file(const char *session_path, const char *src_path, char *err, size_t err_sz); /* Store already-read image bytes (clipboard, downloads); name is * display-only. */ cst_attachment_t *cst_attach_import_bytes(const char *session_path, const char *name, const char *data, size_t n, char *err, size_t err_sz); /* Copy src_path into the session's store as a finished file for the user: * any bytes up to CST_ARTIFACT_MAX_BYTES, mime from the name's extension, and * `for_user` set so it stays out of every request. title (optional) is the * display name, the source's file name the default. */ cst_attachment_t *cst_attach_import_artifact(const char *session_path, const char *src_path, const char *title, char *err, size_t err_sz); /* Validate and read back a stored payload, or NULL when it is gone. */ char *cst_attach_read(const char *session_path, const cst_attachment_t *a, size_t *out_len, char *err, size_t err_sz); /* "data:image/png;base64,...." for the wire; images only, NULL otherwise. */ char *cst_attach_data_url(const char *session_path, const cst_attachment_t *a); /* "1920x1080 png 412 KB" / "pdf 1.2 MB, 12 pages" one-liner for prompts. */ void cst_attach_describe(const cst_attachment_t *a, char *out, size_t out_sz); void cst_attach_free(cst_attachment_t *a); /* Free a list of n entries allocated as separate blocks. */ void cst_attachments_free(cst_attachment_t *list, int n); /* Deep copy (NULL on OOM or when n <= 0). */ cst_attachment_t *cst_attachments_dup(const cst_attachment_t *list, int n); /* Append src to *list (grows with realloc). 0 / -1. */ int cst_attachments_push(cst_attachment_t **list, int *n, int *cap, const cst_attachment_t *src); /* JSON array of n attachments for the session JSONL (malloc'd), or NULL. */ char *cst_attachments_to_json(const cst_attachment_t *list, int n); /* Parse a JSON array; caller frees with cst_attachments_free. */ cst_attachment_t *cst_attachments_from_json(const void *array_json, int *n_out); /* Base64 of n bytes (malloc'd, no line breaks). */ char *cst_base64_encode(const void *data, size_t n); /* Standard or URL-safe base64 (whitespace ignored) to bytes; malloc'd, * NULL on a bad character. */ char *cst_base64_decode(const char *s, size_t n, size_t *out_len); #ifdef __cplusplus } #endif #endif