diff --git a/CHANGELOG.md b/CHANGELOG.md index daf8ebb4..50a735a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,11 +52,13 @@ existing 1.3.x database. Both are additive; no data loss. See SDKs auto-generate `ws_id` client-side so cluster-routed callers can bind the body to the owning node before it lands. (#362) - **Slack channel adapter** (Socket Mode) — mirrors the Discord adapter: - per-user channel sessions via configurable slash command, DM routing, - SSE event consumption, tool approval buttons (with per-user owner - enforcement), plan-review approve / request-changes modal, - notification reply routing back into the workstream, session recovery - after restart. Install with `pip install 'turnstone[slack]'`. (#355) + per-user channel sessions via configurable slash command, DM routing + without slash command, SSE event consumption, tool approval buttons + with per-user owner enforcement, plan-review approve / request-changes + modal, notification reply routing back into the workstream, and + session recovery after restart via persisted recoverable route keys + (the bot re-subscribes to existing Slack-routed workstreams when it + comes back). Install with `pip install 'turnstone[slack]'`. (#355) - **Console admin UX support for Slack** — channel-link modal offers Slack alongside Discord; skill notify-on-complete forms expose a per-row channel-type dropdown (and no longer hardcode `discord`); @@ -64,16 +66,59 @@ existing 1.3.x database. Both are additive; no data loss. See theme-aware tokens (`--discord` / `--slack`) so light theme passes WCAG AA. (#365) - **Per-call plan/task model selection** — `plan_model` and `task_model` - are now distinct from the conversation model and from each other, with - configurable reasoning effort per agent. `ConfigStore` admin tab in - the console UI lets operators set defaults; per-call overrides - available via the `plan_agent` / `task_agent` tools. (#360, #361) + are now distinct from the conversation model and from each other, + with configurable reasoning effort per agent. Three layers: + - **Backend split** (`#54dd557`) — `ModelRegistry` gains `plan_model`, + `task_model`, `plan_effort`, `task_effort`; per-kind overrides win + over the legacy `agent_model`, which still works as the single-knob + fallback. `resolve_agent_alias(kind)` and `resolve_agent_effort(kind)` + centralise resolution. Loader validates effort against + `{none, minimal, low, medium, high, xhigh, max}` with warn+drop on + typos. + - **Runtime configurability** (`#360`) — `ConfigStore` admin tab in + the console UI lets operators switch alias and reasoning effort per + agent **without restarting**. `INHERIT_EMPTY_LABEL_KEYS` shows + `(inherit)` for empty effort selections — distinct from the literal + `none` choice which actually disables reasoning. Routing overrides + apply on `/v1/api/_internal/config-reload` (admin saves), and + `model-reload` short-circuits when nothing changed so no in-flight + clients churn. + - **Per-call override** (`#361`) — the calling LLM can pass + `model=""` to `plan_agent` or `task_agent` to override the + operator-configured per-kind model for that one invocation. Tool + descriptions list the live registered aliases (refreshed when the + operator hits "sync to nodes"), so the LLM always sees current + options. Bad aliases return a corrective error dict listing the + available choices. No whitelist — cost control is intentionally + ceded to the model. Plan-retry path reuses the alias so coaching + reflects real model behaviour. (#360, #361) - **Provider capability passthrough** — resolved per-model capabilities - (vision support, reasoning support, native web search, etc.) flow - through to provider clients so feature gating no longer relies on - string matching. Server companion published in the same change. (#352) -- **Claude Opus 4.7 support** — provider capabilities, tokenizer - awareness, and adaptive thinking semantics. (#357 — also in 1.3.1) + (vision, reasoning, native web search, thinking_mode, token_param, + etc.) flow through to provider clients via a new `capabilities` + parameter on `create_streaming` / `create_completion`, so feature + gating no longer relies on string matching and admin-UI / config.toml + overrides actually reach the provider. Defensive shallow-copy in + `_finalize_extra_body` so callers reusing the same dict across models + are safe; deep-merge of `chat_template_kwargs` so operators can + extend instead of silently overwriting. (#352) +- **Server compatibility layer for local model servers** — vLLM and + llama.cpp profiles suggest the right thinking mode and per-server + workarounds (`skip_special_tokens` for vLLM, `reasoning_format` for + llama.cpp) during model detection. Admin UI gains structured fields + for server type, thinking mode, and extra body params, hidden for + non-local providers (openai/anthropic/google). New `thinking_param` + text field surfaces the alias name (default `enable_thinking`; + Granite/DeepSeek use `thinking`). Verified end-to-end against real + vLLM (Gemma 4 31B) and llama.cpp (Gemma 4 E4B) servers. (#352) +- **Claude Opus 4.7 support** — `claude-opus-4-7` capability entry + (1M ctx, 128K output, adaptive thinking, `supports_temperature=False`, + `thinking_display=summarized`). New `ModelCapabilities.thinking_display` + field — Opus 4.7 omits thinking by default but always sends summarized + blocks back through the provider boundary. Adds `xhigh` effort level + to the global mapping and to Opus 4.7's `effort_levels`; admin-console + skill-template dropdowns gained `xhigh` and `max` options. Reasoning + effort label capitalization aligned across all console dropdowns. + (#357 — also in 1.3.1) - **Dashboard composer refactor** — unified single-flow create from the per-node dashboard. Multi-line textarea + collapsible Options panel (model / judge / skill) + paperclip + drag-drop / paste-image + chip @@ -84,7 +129,9 @@ existing 1.3.x database. Both are additive; no data loss. See separate modal. Options panel state persists in `localStorage`; active non-default selections render as an inline summary chip beside the Options button; drag-over shows an explicit "Drop to attach" - overlay. (#362, #366) + overlay. The tab-bar `+` new-workstream modal also gained a paperclip + + chip strip + first-message field so the same flow is reachable from + both entry points. (#362, #366) - **Workstream attachments — orphan reservation sweep** — periodic background sweep clears `reserved_for_msg_id` on rows whose `reserved_at` exceeds a 1-hour threshold, self-healing reservations @@ -116,9 +163,11 @@ existing 1.3.x database. Both are additive; no data loss. See show a `…and N more (preview truncated)` suffix. (#365) - **PostgreSQL deployment image** swapped from `bitnami/pgbouncer` to `edoburu/pgbouncer` to track upstream releases and reduce image size. - No config changes required for typical deployments; review your helm - values if you depend on `bitnami`-specific environment variable - conventions. (#353) + Environment variables remapped to the edoburu naming, ports updated + to match documented expectations, and the Kubernetes Helm Chart link + in the deployment docs now points at the same container. Review + your helm values if you depend on `bitnami`-specific environment + variable conventions. (#353) ### Fixed @@ -149,6 +198,28 @@ existing 1.3.x database. Both are additive; no data loss. See `.scope-slack` first shipped with raw hex that failed WCAG AA on light theme (1.8:1 / 2.4:1). Theme-aware `--discord` / `--slack` tokens with proper light variants now pass. (#365) +- **Cross-user attachment fetch hardening** — `get_attachment_content` + now scopes the row by `user_id` in addition to `ws_id`, so an + unowned workstream can't be a vector for cross-user blob fetches via + attachment-id guessing. (#356) +- **Attachment-list DoS guard** — `/v1/api/send` rejects + `attachment_ids` lists longer than the per-(ws, user) pending cap + with a 400, preventing hostile clients from blowing up the storage + `IN (...)` clause. (#356) +- **Bounded LRU for upload locks** — the per-(ws, user) attachment + upload-lock map now evicts the oldest unlocked entries past a soft + cap, so the in-process map can't grow unbounded on long-running + nodes. (#356) +- **3.12 CI deadlock on attachment uploads** — the upload-lock was + initially an `asyncio.Lock`, but Starlette's `TestClient` runs each + request on a fresh anyio task / event loop, so the cached lock's + `_waiters` bound to the first loop and a later request would block + on a Future from a closed loop (silent deadlock). Switched to + `threading.Lock` — loop-agnostic, and the critical section is one + COUNT + one INSERT. Same root cause is reproducible against any + Starlette TestClient harness on Python ≥ 3.10; 3.12 surfaces it + more often. Production users on a single event loop weren't + affected, but the test environment was. (#356) ### Security @@ -194,6 +265,40 @@ Python + TypeScript clients gained: - Refusal of `attachments + target_node` combination at the SDK boundary (the multipart routing layer doesn't honor `target_node`, so silently picking the wrong node is now an explicit error) +- `PlanResolvedEvent` SSE event with type guard, dispatched when one + client (e.g. mobile) resolves a plan so other connected clients can + dismiss their plan-approval modal in sync. Available in both the + Python and TypeScript SDKs. (#87a9af1) + +### Operational + +- **CI vendor-asset auto-download covers `hls.js`** — the + `vendor-js.yml` workflow previously only iterated katex/hljs/mermaid, + so Renovate bumps for `hls.js` failed the wheel-completeness check + and required manual file downloads. Detection loop now includes + `hls`, so future Renovate bumps are merge-ready without intervention. + (#354) + +### Contributors + +Thanks to the people who made this release happen — especially the +external contributors who picked up substantial pieces of work: + +- **[@daoxley](https://github.com/daoxley)** — designed and shipped + the Slack channel adapter (Socket Mode bot, per-user sessions, + approvals, plan-review, notification routing). Major new feature + surface in #355. +- **[@pizzaandcheese](https://github.com/pizzaandcheese)** — replaced + the deprecated bitnami pgbouncer image with the edoburu image, + remapped environment variables, ports, and helm chart references. + Operationally important for anyone running our reference Postgres + deployment (#353). +- Renovate kept dependencies and the JS vendor tree current via + several automated bumps. + +If you're interested in contributing, channel-attachment ingest from +Discord + Slack is the headline 1.4.1 feature and a solid place to +start — see the open issues on GitHub or open one to scope a piece. ## [1.3.1]