v0.8.6: general mode, clipboard text, PDF text extraction
Working mode: --mode coding|general (CST_MODE, settings.json, /mode, WebUI run settings). general swaps the default framing for a general assistant one -- workflow, safety notes, tool wording (run_shell, the subagents) -- and /status shows it; minimal (the paper profile) stays byte-frozen. The prompt state carries the mode so a switch leaves a system note in history. Clipboard: clipboard_read / clipboard_write tools (16 MiB cap read, default 64 KiB window; writing is a WRITE permission with a preview) on pbcopy / wl-copy / xclip / pbpaste / wl-paste / xclip and the Win32 clipboard. In the TUI, /attach paste falls back to clipboard text when there is no image on it. PDF: a dependency-free text extractor (src/pdf_text.c): inflate, Flate/ASCIIHex/ASCII85, PNG/TIFF predictors, layout-independent object scan, object streams, page tree walk with inherited resources, content lexer (Tj/TJ/'/" and the Td/TD/T*/Tm spacing heuristics), per-font ToUnicode CMaps and inline images skipped. Encrypted files and pages with no text layer are refused with the reason. Attachments: /attach (a path or files dropped on the terminal) now take images, PDFs and text. A PDF is stored as its text layer with the mime still saying application/pdf and its page count; anything else has to be UTF-8 text. Documents travel inline as text parts, so CST_NO_IMAGES and text-only models no longer drop them, while images keep their old path. Tests: test_pdf_text (plain, bare and zlib-framed Flate, inline image, CID + ToUnicode, object stream, error paths), documents in test_attach, inlined documents in test_llm_body, mode in test_config.
This commit is contained in:
+24
-14
@@ -9,16 +9,24 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* --- image attachments ---------------------------------------------------
|
||||
* An attachment is a validated copy of an image file, stored beside the
|
||||
* session so the bytes a model is shown stay the bytes that were picked.
|
||||
* Only the metadata travels in the JSONL; the bytes are encoded into the
|
||||
* request when it is built. */
|
||||
/* --- 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). */
|
||||
#define CST_ATTACH_MAX_BYTES (16 * 1024 * 1024) /* one stored image */
|
||||
/* 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)
|
||||
|
||||
/* 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). */
|
||||
@@ -35,23 +43,25 @@ int cst_attach_dir(const char *session_path, char *out, size_t out_sz);
|
||||
int cst_attach_full_path(const char *session_path, const cst_attachment_t *a,
|
||||
char *out, size_t out_sz);
|
||||
|
||||
/* Read src_path, verify it is a supported image within limits, and copy it
|
||||
* into the session's attachment directory. Returns a malloc'd entry the
|
||||
* caller owns (cst_attach_free), or NULL with err filled. */
|
||||
/* 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 bytes (clipboard, downloads); name is display-only. */
|
||||
/* 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);
|
||||
|
||||
/* Validate and read back a stored image, or NULL when it is gone. */
|
||||
/* 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; NULL when the file is gone. */
|
||||
/* "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" style one-liner for prompts and the UI. */
|
||||
/* "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);
|
||||
|
||||
Reference in New Issue
Block a user