f5d340bd2a3f4405f0b9fcaabaed714663c51953
16
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5ba215b36c |
v0.8.7: tool capability metadata, in-process engine, Qt app, Android engine
The engine can be embedded now instead of only driven from a terminal: the same objects link into a Qt front end (app/) that owns a cst_agent_t inside its own process -- no port, no token, no second process -- and that front end now runs on the desktop and, engine-side, on the phone. Capability metadata (include/cst_tools.h, src/tools/registry.c): - cst_tool_def_t gains perm_name, platforms and available (a probe that returns a reason), so a permission is addressable by name and a tool can say why it cannot run here. - cst_platform_name(), cst_tool_platform_ok(), cst_tool_available(), cst_tool_meta_reload(), cst_tool_perm_name() and CST_PLAT_DESKTOP[]. - cst_tool_register() may take over a built-in name that is not runnable on this platform, so a front end replaces it with its own implementation. - the registry entries carry their class (delete_file -> "delete"), the desktop clipboard tools carry a clipboard probe; find/active/run gate on it. - /api/settings.tools[] exposes perm_name, platforms, available, why and the declared parameters. Engine as a library (Makefile, CMakeLists.txt): - libcstcore.a from the CORE_OBJ set, and a CMake cstcore target shared by the CLI and by app/ (-DCST_BUILD_APP=ON): the engine is compiled once. - Android branch for the vendored sashidown: a per-ABI archive built with the NDK's aarch64-linux-android24-clang wrapper, because CMake's compiler is plain clang and keeps --target/--sysroot in its own variables. Qt front end (app/, new): - AgentCore wraps one cst_agent_t: turns run on a worker thread, every cst_agent_hooks_t callback becomes a Qt signal, and the two hooks that need an answer (on_permission, on_ask_user) block the worker until the GUI replies; mode, approval and plan mode go through the engine's config. - ToolProvider hands the front end's tools to the engine (owner "app:*"); the Linux one is notification_send with a probe for notify-send/D-Bus. - Main.qml: transcript, tool blocks, consent dialog (Deny/Once/Always -> CST_PERM_*), ask_user, mode switch, Esc to cancel; --selftest stays headless and runs the embedding checks without QML. Android (scripts/, docs/android.md, new): - scripts/build_third_party_android.sh builds static mbedTLS + libcurl for an ABI (CA path /system/etc/security/cacerts); build_android.sh builds cst-agent, libcstcore.a and the test binaries for the phone, can push them and run the whole suite there. - sandbox_exec.c keeps the plain exec path on Android: the seccomp supervisor compiled in and the probe reported "seccomp", but writes outside the workspace were not denied on the device -- claiming a sandbox that does not hold is worse than reporting none. - tests/test_diff.c compares layouts only against real GNU diffutils: toybox's diff prints the same hunk header with its own hunk/context rules. Tests: test_tool_meta (metadata, platform gate, probe reasons, takeover of a built-in name) and test_embed (in-process embedding contract) are new; the existing registry/llm_body assertions now follow availability. 38 test binaries pass on the host, 36/36 on arm64-v8a Android 16, cst-app-selftest passes in both the standalone app/ build and the repo build. Version 0.8.7. |
||
|
|
e0b0eddf3a |
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. |
||
|
|
50abcf1a91 | build: finish cross-platform release tooling | ||
|
|
2d1052fd5f |
v0.8.3: WebUI models, providers and keys; garbled thinking fixed
Streaming: Chinese reasoning showed up garbled in the WebUI. The agent loop now feeds visible/thinking text in runs instead of byte by byte, and the WebUI holds an incomplete UTF-8 tail until the next chunk (cst_utf8_hold_feed), so every think_delta/assistant_delta is whole. src/provider_switch.c: model list fetch/cache, key verify-and-save and provider switching moved out of tui.c and shared by TUI and WebUI. WebUI API: - GET /api/providers, GET /api/models[?refresh=1] (401 on a rejected key, still listing built-ins), POST /api/provider, POST /api/key (key checked against /v1/models, saved to credentials 0600, never echoed in replies, events or logs) - /api/config validates everything before applying, persists model, effort and approval (not yolo), warns when effort does not apply; plan_mode no longer forces read-only - state: turn_usage, api_base, key_set/key_from, model_info, effort_applies, sees_images, max_steps, tool_profile, perm_timeout; permission events carry their timeout Frontend: searchable model picker with refresh and manual entry, provider picker and key dialog, effort/vision hints, toasts instead of silent failures, Chinese error text, real protocol in the settings and usage panels, approval countdown from the server's timeout. Tests: utf8 hold unit test, scripts/e2e_webui_settings.py (fake /v1/models, wrong key, switching, persistence, Chinese thinking) run from e2e_webui.sh, scripts/tui_keys/provider.py. |
||
|
|
6e81513e36 |
v0.7.8: WebUI (--web): HTTP/1.1 + SSE front end, engine API v1, tests
A second implementation of cst_agent_hooks_t next to the TUI: the turn runs on a worker thread, the hooks publish events into a ring buffer that SSE clients read, so the engine itself needs no changes. - src/net.c, include/cst_net.h: POSIX/Winsock sockets, non-blocking connect - src/http_srv.c, include/cst_http.h: HTTP/1.1, keep-alive, chunked streaming, body caps (413), Expect: 100-continue, connection cap, exact routing - src/web_md.c, include/cst_web_md.h: streaming markdown -> sanitized HTML (tag/attribute allowlist, javascript: URLs and off-site images dropped) - src/webui.c, include/cst_webui.h: event ring + SSE broadcast, all routes, token (Bearer/Cookie/query) and loopback Host checks, 3 s auto-deny when no client is attached - src/webui_stub.c, CST_WEBUI=0 / CST_BUILD_WEBUI=OFF: build without the WebUI - web/: no-build front end (transcript, approvals, todo, sessions, image upload, status bar) - docs/webui.md: engine API v1 - events, requests, security model - tests/test_webui.c, scripts/e2e_webui.sh: unit tests plus an end-to-end run driven by a recorded SSE stream (no API key needed) - src/main.c: --web --web-port --web-host --web-token --web-dev --web-open and CST_WEB_PORT/HOST/TOKEN/ROOT An empty POST body is now accepted without Content-Length (RFC 9112 6.3) so curl-driven clients can reach cancel/undo/compact/quit; CMakeList's core tests learned about sashidown and test_webui, and CST_WEBUI=0 defines CST_NO_WEBUI. |
||
|
|
895b47274c |
v0.7.0: image input, model registry, prefix-cache savings
Images - vision gate: text-only models get a note instead of image parts and no view_image tool; unknown models retry once without images on HTTP 400 - paste: Ctrl+V and /attach paste read the clipboard (wl-paste, xclip, pngpaste/osascript, Win32 PNG or CF_DIB converted to PNG); pasting image file paths attaches them - MCP image content is stored in the session and sent with the tool result - attach: rel path validation, base64 decode, /retry keeps images Model registry - built-in src/models_builtin.json embedded at build time, merged with <config>/models.json and cached GET /models metadata (context, vision, pricing); most specific rule wins per field - /model labels, /status source, --list-models [provider] Cache and cost - stable request prefix (frozen tools, notes as messages), DeepSeek prefix completion, OpenAI/Anthropic cache hints, /cost and hit rate in the status |
||
|
|
630e8f4295 |
ci: Windows zip only builds cst-agent; link util for replay tests
os_win.c needs cst_buf_* / cst_utf8_valid from util.c after os_compat was added to the small replay CMake targets. Release packaging only needs cst-agent.exe, so bootstrap_windows.sh builds that target alone. |
||
|
|
546a4c7eeb |
ci: link os_compat for replay CMake tests; fix llvm-mingw mirrors
gcc -O0 keeps unused cst_test_util.h helpers that need os_*; clang GC'd them so only the gcc CMake step failed. Prefer ghfast/ghproxy.net for the llvm-mingw tarball (gitclone 500 / github unreachable on the runner). |
||
|
|
1476f1774a |
Temp dir falls back when TMPDIR or /tmp is unusable (Termux); v0.6.1
os_temp_dir() used $TMPDIR or "/tmp" without checking either. On Termux
/tmp usually does not exist (or SELinux denies it) unless TMPDIR points at
$PREFIX/tmp, so plugin and MCP temp files failed and shell children that
need a temp file (heredocs) broke.
* os_temp_dir() picks, once, the first of $TMPDIR, $PREFIX/tmp, /tmp,
/var/tmp and ~/.cache/cst-agent/tmp where a file can really be
created; if none works it keeps the old answer
* os_temp_dir_export() at startup writes the choice back to TMPDIR, so
shell children and the sandbox's writable temp dir agree
* tests/test_tmpdir.c covers the fallbacks in fresh forks
|
||
|
|
2a43ae6622 |
Windows: official port -- UCRT static build, UTF-8 throughout, Low IL sandbox, ncurses TUI, installer; v0.6.0
Build
* cross build switches to pkgsCross.ucrt64 (shell-win.nix); curl (Schannel),
winpthreads and ncurses 6.6 are linked statically, so the release is
cst-agent.exe + busybox.exe (busybox-w32 Unicode) with no extra DLLs
* windres embeds a manifest with activeCodePage=UTF-8 and a version resource
* ncurses 6.6 Windows console driver patches (mouse button state, A_DIM,
wide-char declarations): scripts/patches/
* scripts/bootstrap_msys2.sh builds the same release natively in MSYS2
UCRT64; PR #1's MINGW64 notes now point there
* vendor/tre-regex (musl's TRE) provides <regex.h> on MinGW
UTF-8
* paths cross the system call boundary as UTF-16 (*W APIs); console code
pages set to 65001 and restored on exit; files are read and written in
binary mode
* child output that is not valid UTF-8 is decoded from the console, OEM or
ANSI system code page
* read_file hides CR; edit_file, apply_patch and write_file keep CRLF line
endings and a UTF-8 BOM
OS layer and processes
* os_dir_* and cst_fnmatch replace the POSIX-only directory walks in
subagent, plugins, skills, undo and fs_tools; realpath / path_under and
symlink rejection work on Windows
* every child goes through CreateProcessW with its own environment block
inside a Job Object, so timeouts and Esc end the whole process tree
Sandbox (auto mode, "auto · lowil")
* run_shell runs with a restricted Low integrity token; the workspace gets
an inheritable Low label once, the sandbox TEMP is labeled Low, and the
credentials file gets a no-read-up label
* drive roots, the profile and system folders are never labeled
* network commands still ask, since Low IL does not block the network;
Access denied and MSYS2's 0xc0000142 offer a rerun outside the sandbox
* /sandbox lists labeled folders, /sandbox reset-labels restores them
TUI
* raster console fonts are switched to Consolas / NSimSun while running
* the home logo falls back to text when the console font lacks U+2580
* mouse drag copy goes to the Windows clipboard
Distribution
* scripts/install_windows.ps1 installs a Gitea release into
%LOCALAPPDATA%\Programs\cst-agent and adds it to the user PATH;
cst-agent-update.cmd reruns it; scripts/release_windows.sh uploads the
zip with the token taken from the environment
* scripts/run_windows.bat is gone; docs/README-windows.md is rewritten
Tests
* new test_lowil, test_win_utf8 and test_os_dir; tests made portable
(cst_test_util.h)
* scripts/win_test.sh and scripts/winvm/ run the suite on English and
Chinese Windows Server VMs as Administrator, a standard user and a
Chinese user name: 29/29 on all six
|
||
|
|
3db33eddac | Windows: make the CMake build work with MSYS2's native toolchain | ||
|
|
1c26cc6e30 |
TUI: mouse drag selection with OSC 52 copy; Markdown emphasis follows CommonMark; v0.5.0
- Drag, double-click (word) and triple-click (line) selection in the log, auto-scroll at the edges, soft-wrapped lines joined on copy. - sashidown ANSI renderer: delimiter runs with flanking rules, so intraword underscores (test_apply_patch.c) stay literal; unmatched * _ and backticks are shown as-is; * and _ do not close each other. - tests: test_textsel, test_markdown. |
||
|
|
7d3ec9fcb9 |
Extensions: skills, plugins, MCP, sub-agents; configurable keys
- Skills (SKILL.md discovery, skill tool, /skills /skill) - plugin.json exec tools with permission prompts, timeouts and workspace trust (/plugins) - MCP stdio client: JSON-RPC initialize/tools/list/tools/call, mcp__server__tool, /mcp and sidebar status - task tool with general/explore/plan and .agent/agents/*.md roles, parallel read-only runs, cancel propagation, /agents - Keymap with Ctrl+X leader, keybinds.json overrides and /keys panel - Collapsed thinking, throttled streaming Markdown, leaner tool output, parallel read-only tools - Spawn: close-on-exec pipes and a process-wide fork lock - Tests for keymap, skills, plugins, MCP, sub-agents, shell compaction; docs/plugins.md |
||
|
|
ef63f6d612 |
OpenCode-style TUI, model probing, sandboxed auto approval
- TUI: centered home screen with logo, boxed input with mode line, sidebar (>=120 cols), Ctrl+P palette, Tab Build/Plan, Shift+Tab approval cycle, mouse (cards, cursor, pickers, wheel), /sidebar /mouse /approval - /models probing: key check on entry (401 re-asks), API models in /model - Shell sandbox in C: Linux Landlock (writes limited to workspace/tmp, ABI>=4 blocks TCP), macOS sandbox_init, rules fallback elsewhere - Approval modes ask/auto/yolo (default auto); read-only command whitelist; ask to rerun outside the sandbox when a command looks blocked - Upgradable bootstrap scripts (git pull --ff-only, rebuild, reinstall) and cst-agent-update; cst-agent --version - tests: test_sandbox, test_models |
||
|
|
2fde898da0 |
Usability pass: tool registry, TUI polish, saved keys and settings
Tools - Table-driven tool registry with permission classes and default/minimal profiles; new tools: edit_file, list_dir, glob, grep, delete_file, move_file, todo_write, web_fetch, ask_user (plus read_file paging). - Built-in Myers diff; write tools return unified diffs. - Persistent permission rules (.agent/permissions.json), per-turn undo snapshots (.agent/undo), AGENTS.md project notes, auto-compact at 80% of the model context, cancellable run_shell with process-group kill. TUI - Table-driven slash commands: /provider /key /effort /status /tools /permissions /yolo /undo /retry /diff /export /copy /rename /delete /init /max-steps /todo, with / and @ completion. - Permission modal with diff and prefix rules, ask_user modal, todo panel, header with model/effort/context, bracketed paste, line editing, wide-char cursor, NO_COLOR and ASCII fallback; Esc never quits. Startup and configuration - API keys are entered in the TUI (hidden) and saved per provider in <config>/credentials (0600); env variables are only a fallback. - Last provider, per-provider model and reasoning effort are remembered in <config>/settings.json; --effort/-e and /effort send reasoning_effort (low|medium|high|max) to models that accept it. - DeepSeek preset uses deepseek-flash / deepseek-v4-pro. - Session flags --new/--continue/--resume/--list-sessions, --yolo, --confirm. Compatibility and tests - ncurses detection, macOS/Homebrew support, make install, XDG config dir, POSIX cleanups; Gitea CI (gcc/clang/asan/musl/macOS). - Unit tests for diff, fs tools, registry, undo/perms and config; e2e fixtures multi_file_refactor and ask_or_todo; vendored cJSON. |
||
|
|
1f1fcba7ad |
Initial CST-Agent: portable Linux/Termux/Windows coding agent.
Vendored sashidown, OpenAI-compatible env (OPENAI_*), and bootstrap scripts. Co-authored-by: Cursor <cursoragent@cursor.com> |