Commit Graph
23 Commits
Author SHA1 Message Date
WHC 82dee65942 v0.8.15: custom providers and model parameters under Advanced options
The settings dialog could pick a preset, a model and a key and nothing else.
Two things were missing: a provider the presets do not know, and what the
model is asked to do while it answers. Both live under "Advanced options"
now, next to the entry they belong to.

Custom providers (engine)
- cst_models_user_set_provider() / cst_models_user_drop_provider() write the
  engine's own user layer, <config>/cst-agent/models.json:
  {"providers": {"myllm": {"api_base": ..., "key_env": ...,
                           "default_model": ..., "models": [...]}}}
  and reload the registry, so the provider is at once in the provider list,
  in the wire models[] and in the CLI's /provider -- the file a hand-written
  override would go into is the same one, so the GUI and an editor agree.
  The name is checked (1-31 of letters, digits, '.', '_', '-'), a preset's
  name overrides that preset (a self-hosted endpoint, a proxy), everything
  else in the file (model rules) is kept, and a file that is not a JSON
  object is never overwritten. Dropping only removes the user's own entry.
- AgentCore::providers() gained "custom" (source == "user"), and
  addProvider() / removeProvider() drive the two calls above.

Model parameters (engine + wire)
- cst_agent_config_t and cst_llm_request_t carry temperature, top_p and
  max_tokens. 0 means the field is not sent at all -- an absent field is the
  provider's own default, which "temperature": 0 is not (deterministic
  decoding is a real choice), so cst_llm_build_body() only adds what was set.
  tests/test_llm_body.c:test_gen_params pins both halves.
- settings.json keeps them per provider ("params": {...}) via
  cst_settings_remember_params(); cst_settings_remember() carries them along
  with the provider choice, and cst_agent_create() reads them, so a CLI or
  TUI run sends what the window was set to. An all-zero config (the CLI)
  leaves what the GUI saved alone.
- AgentCore::genParams() / setGenParams(), and useProvider() applies both the
  remembered parameters of the provider it lands on and a base URL that was
  edited in the dialog.

The dialog
- Rewritten around one scrolling body with a fixed footer: a long model list
  used to push the key field and the buttons out of the dialog. The model
  chips are filtered (a filter field appears past twelve) and capped at 40
  with "... +N more", which is what a router with hundreds of models needs.
- "Advanced options" folds out the provider entry (name, base URL, key
  variable, default model, models; Save provider / Remove from models.json)
  and the model parameters (temperature, top-p, max tokens; empty = not
  sent). The fields follow the picked provider and are what gets saved, so a
  hand-typed edit is never lost to a stale property.

Verified: --uitest 67/67 (15 new checks: parameters round-trip through the
engine, a provider added through the form and removed again, a bad name
refused, a preset not removable), --selftest, ctest cst-app-selftest, and
make check with the new body test.

Version 0.8.15.

mode = coding
2026-10-11 13:26:02 +08:00
WHC 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.
2026-10-11 11:42:04 +08:00
WHC 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.
2026-10-11 11:09:39 +08:00
WHC 50abcf1a91 build: finish cross-platform release tooling 2026-10-10 16:21:00 +08:00
WHC 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.
2026-10-09 15:54:53 +08:00
WHC e238f5f37d v0.8.2: build fixes, WebUI security and correctness
Build: <fcntl.h> in tui.c, format-truncation in http_srv.c and /web.

WebUI:
- refuse cross-site requests (Origin must be the page itself) in the
  default no-token mode: any page could POST approval=yolo and a prompt
- session/workspace/undo/compact/attach/model changes are 409 while a
  turn runs (use-after-free, messages landing in the wrong session)
- ask_user returned "dismissed" at once instead of waiting
- cancel and shutdown wake a turn parked on a permission or question;
  SIGTERM mid-turn no longer hangs or crashes
- a page opened while a question is pending still gets it;
  Last-Event-ID resumes the stream; event seq matches the SSE id
- token mode: page assets load without the token, images via cookie
- --web-open works, --web-port/--web-token are validated
- frontend: gate keys ignored while typing, clear-images button,
  reasoning no longer wiped while streaming

HTTP server: auth and size cap before reading the body, strict
Content-Length, NUL in url_decode, 413 on keep-alive, idle timeout,
absolute-form only without a leading '/', case-insensitive Connection,
header deadline, 400 for long request lines, unlink before close,
poll() instead of select(), SO_EXCLUSIVEADDRUSE on Windows.

Markdown sanitizer escapes quotes in attribute values.

/web: passes this session's provider/model/base/effort/approval (key
via the environment), keeps output off the TUI, shows the real URL and
keeps CURRENT on the TUI's session.

Tests: scripts/e2e_webui_ask.py, scripts/e2e_webui_http.py (run from
e2e_webui.sh), sanitizer quote test.
2026-10-09 13:51:34 +08:00
WHC 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.
2026-10-09 10:20:09 +08:00
WHC c7b32c3fd6 v0.7.5: arrow keys, image request fix, deepseek-flash vision, musl CI
TUI keys: register both CSI and SS3 forms of the cursor/Home/End keys and
the xterm modifier sequences when terminfo lacks them, so an arrow sent in
the "other" form no longer turns into Esc + a typed letter. Up/Down move by
visual (soft-wrapped) row, and the draft survives a trip through history.
scripts/tui_keys drives the TUI in a pty to check all of this.

Images: text inside a multimodal content array is now a {"type":"text"}
part; DeepSeek rejected the bare string with HTTP 422. deepseek-flash
(and its deepseek-chat / deepseek-reasoner aliases) read images, so the
registry marks them vision; deepseek-v4-pro stays text only.

CI: models.c lost _DEFAULT_SOURCE in 0.7.0 and gmtime_r broke the musl
build; tests sleep with poll() instead of usleep for the same reason.
2026-10-08 22:35:34 +08:00
WHC 32b4afd772 v0.7.1: allow network inside the run_shell sandbox
Landlock no longer handles TCP, the Seatbelt profile drops (deny network*),
and the seccomp filter stops refusing IPv4/IPv6 sockets. Sandboxed commands
run without asking in auto mode on every backend (Low-IL no longer asks for
network commands), and connection errors are not treated as sandbox blocks.
2026-10-08 21:05:14 +08:00
WHC 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
2026-10-08 20:34:09 +08:00
WHC 0226f417ff providers: add teamorouter; pick the first /models id when no default model 2026-10-08 14:30:00 +08:00
WHC 9b2c7acfae ci: fix test_subagent strcasestr crash; llvm-mingw Windows zip
clang under strict C11 left strcasestr undeclared (returns int → pointer
truncation → SIGSEGV). Parse Content-Length portably; keep -Werror on
make check. Drop Nix for windows-cross (root /nix fails) and use pinned
llvm-mingw UCRT instead; Alpine musl gets linux-headers for audit.h.
2026-10-07 02:39:36 +08:00
WHC 420f9b242c ci: drop sanitizers job; harden test_subagent fake server
test_subagent segfaulted in the Docker runner: the fake SSE handler took
user + strlen(user) - 1 with an empty user string. Guard JSON access and
format the child report with an empty-safe last character. Remove the
sanitizers job entirely (if: false still queued it and blocked the runner).
2026-10-07 02:27:00 +08:00
WHC daa92a6cfb seccomp: require child memory peek in the availability probe
With Yama ptrace_scope=2 and no CAP_SYS_PTRACE, process_vm_readv and
/proc/<pid>/mem both fail, so sc_decide cannot read path strings and every
workspace write gets EACCES. The old probe only checked the USER_NOTIF
round trip, so CST_SANDBOX=seccomp and the forced-seccomp test pass looked
available and then failed on the first write.

sc_can_peek() forks a child, places a marker on its stack, and retries the
same sc_peek path. sc_probe() now needs that too, so those hosts fall back
to none (or keep landlock) instead of a silent deny-all sandbox.
2026-10-07 01:39:08 +08:00
WHC 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
2026-10-06 23:32:21 +08:00
WHC 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
2026-10-06 23:08:14 +08:00
WHC 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.
2026-10-06 14:24:42 +08:00
WHC b28bca2cfc TUI: kitty keyboard protocol, word movement and deletion keys
Query CSI ? u at startup and push the disambiguate flag on the alternate
screen when the terminal answers; CSI u reports are mapped back to legacy
input (Shift/Ctrl+Enter insert a newline, Ctrl+Backspace deletes a word).
Ctrl/Alt+Left/Right move by word, Ctrl/Alt+Delete delete the next word.
Our define_key codes move above the range ncurses uses for terminfo
extended keys.
2026-10-06 01:52:48 +08:00
WHC 8efd63bb31 Sandbox: seccomp user-notify fallback for Termux and kernels without Landlock
- Child installs a seccomp filter with a listener; a supervisor thread
  resolves the path of write-type syscalls (cwd, dirfd, .., symlinks,
  /proc/self, /dev/stdout, both ends of rename/link) and answers
  CONTINUE or EACCES; IPv4/IPv6 sockets are refused
- Probe order Landlock -> seccomp -> none, checked in a throwaway child;
  CST_SANDBOX=landlock|seccomp|off
- curl connect failures count as sandbox refusals
- test_sandbox runs the detected sandbox and forced seccomp, with escape,
  symlink, rename, link, chmod, stdout, ENOENT, background and network cases
- Docs: platform matrix, limits (not a security boundary, Yama and
  background jobs)
2026-10-06 00:25:24 +08:00
WHC 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
2026-10-05 14:55:31 +08:00
WHC 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
2026-10-05 12:34:46 +08:00
WHC 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.
2026-10-05 01:47:01 +08:00
WHCandCursor 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>
2026-09-07 22:42:32 +08:00