Commit Graph

610 Commits

Author SHA1 Message Date
YTjungle
cb802afcbb fix(control-ui): size grouped chat bubbles by content 2026-03-27 22:27:47 -05:00
Peter Steinberger
024f2cf6e6 style: apply oxfmt drift 2026-03-28 02:55:07 +00:00
Tak Hoffman
e4538a2a70 fix(regression): classify toolcall content as tool output 2026-03-27 21:08:58 -05:00
Peter Steinberger
8ab8f2c461 fix: center skills detail modal 2026-03-28 01:00:44 +00:00
Peter Steinberger
d0cd645b4a style: format exec approval prompt template 2026-03-28 00:05:32 +00:00
Peter Steinberger
4505987b9c style(ui): format control views 2026-03-27 20:15:13 +00:00
Peter Steinberger
894f57a4ce style(ui): apply formatter output 2026-03-27 18:15:40 +00:00
Peter Steinberger
d35f37a58c style: format ui views 2026-03-27 17:23:40 +00:00
Altay
4693813503 fix: re-format exec-approval view 2026-03-27 19:51:36 +03:00
Josh Avant
6ade9c474c feat(hooks): add async requireApproval to before_tool_call (#55339)
* Plugins: add native ask dialog for before_tool_call hooks

Extend the before_tool_call plugin hook with a requireApproval return field
that pauses agent execution and waits for real user approval via channels
(Telegram, Discord, /approve command) instead of relying on the agent to
cooperate with a soft block.

- Add requireApproval field to PluginHookBeforeToolCallResult with id, title,
  description, severity, timeout, and timeoutBehavior options
- Extend runModifyingHook merge callback to receive hook registration so
  mergers can stamp pluginId; always invoke merger even for the first result
- Make ExecApprovalManager generic so it can be reused for plugin approvals
- Add plugin.approval.request/waitDecision/resolve gateway methods with
  schemas, scope guards, and broadcast events
- Handle requireApproval in pi-tools via two-phase gateway RPC with fallback
  to soft block when the gateway is unavailable
- Extend the exec approval forwarder with plugin approval message builders
  and forwarding methods
- Update /approve command to fall back to plugin.approval.resolve when exec
  approval lookup fails
- Document before_tool_call requireApproval in hooks docs and unified
  /approve behavior in exec-approvals docs

* Plugins: simplify plugin approval code

- Extract mergeParamsWithApprovalOverrides helper to deduplicate param
  merge logic in before_tool_call hook handling
- Use idiomatic conditional spread syntax in toolContext construction
- Extract callApprovalMethod helper in /approve command to eliminate
  duplicated callGateway calls
- Simplify plugin approval schema by removing unnecessary Type.Union
  with Type.Null on optional fields
- Extract normalizeTrimmedString helper for turn source field trimming

* Tests: add plugin approval wiring and /approve fallback coverage

Fix 3 broken assertions expecting old "Exec approval" message text.
Add tests for the /approve command's exec→plugin fallback path,
plugin approval method registration and scope authorization, and
handler factory key verification.

* UI: wire plugin approval events into the exec approval overlay

Handle plugin.approval.requested and plugin.approval.resolved gateway
events by extending the existing exec approval queue with a kind
discriminator. Plugin approvals reuse the same overlay, queue management,
and expiry timer, with branched rendering for plugin-specific content
(title, description, severity). The decision handler routes resolve calls
to the correct gateway method based on kind.

* fix: read plugin approval fields from nested request payload

The gateway broadcasts plugin approval payloads with title, description,
severity, pluginId, agentId, and sessionKey nested inside the request
object (PluginApprovalRequestPayload), not at the top level. Fix the
parser to read from the correct location so the overlay actually appears.

* feat: invoke plugin onResolution callback after approval decision

Adds onResolution to the requireApproval type and invokes it after
the user resolves the approval dialog, enabling plugins to react to
allow-always vs allow-once decisions.

* docs: add onResolution callback to requireApproval hook documentation

* test: fix /approve assertion for unified approval response text

* docs: regenerate plugin SDK API baseline

* docs: add changelog entry for plugin approval hooks

* fix: harden plugin approval hook reliability

- Add APPROVAL_NOT_FOUND error code so /approve fallback uses structured
  matching instead of fragile string comparison
- Check block before requireApproval so higher-priority plugin blocks
  cannot be overridden by a lower-priority approval
- Race waitDecision against abort signal so users are not stuck waiting
  for the full approval timeout after cancelling a run
- Use null consistently for missing pluginDescription instead of
  converting to undefined
- Add comments explaining the +10s timeout buffer on gateway RPCs

* docs: document block > requireApproval precedence in hooks

* fix: address Phase 1 critical correctness issues for plugin approval hooks

- Fix timeout-allow param bug: return merged hook params instead of
  original params when timeoutBehavior is "allow", preventing security
  plugins from having their parameter rewrites silently discarded.

- Host-generate approval IDs: remove plugin-provided id field from the
  requireApproval type, gateway request, and protocol schema. Server
  always generates IDs via randomUUID() to prevent forged/predictable
  ID attacks.

- Define onResolution semantics: add PluginApprovalResolutions constants
  and PluginApprovalResolution type. onResolution callback now fires on
  every exit path (allow, deny, timeout, abort, gateway error, no-ID).
  Decision branching uses constants instead of hard-coded strings.

- Fix pre-existing test infrastructure issues: bypass CJS mock cache for
  getGlobalHookRunner global singleton, reset gateway mock between tests,
  fix hook merger priority ordering in block+requireApproval test.

* fix: tighten plugin approval schema and add kind-prefixed IDs

Harden the plugin approval request schema: restrict severity to
enum (info|warning|critical), cap timeoutMs at 600s, limit title
to 80 chars and description to 256 chars. Prefix plugin approval
IDs with `plugin:` so /approve routing can distinguish them from
exec approvals deterministically instead of relying on fallback.

* fix: address remaining PR feedback (Phases 1-3 source changes)

* chore: regenerate baselines and protocol artifacts

* fix: exclude requesting connection from approval-client availability check

hasExecApprovalClients() counted the backend connection that issued
the plugin.approval.request RPC as an approval client, preventing
the no-approval-route fast path from firing in headless setups and
causing 120s stalls. Pass the caller's connId so it is skipped.
Applied to both plugin and exec approval handlers.

* Approvals: complete Discord parity and compatibility fallback

* Hooks: make plugin approval onResolution non-blocking

* Hooks: freeze params after approval owner is selected

* Gateway: harden plugin approval request/decision flow

* Discord/Telegram: fix plugin approval delivery parity

* Approvals: fix Telegram plugin approval edge cases

* Auto-reply: enforce Telegram plugin approval approvers

* Approvals: harden Telegram and plugin resolve policies

* Agents: static-import gateway approval call and fix e2e mock loading

* Auto-reply: restore /approve Telegram import boundary

* Approvals: fail closed on no-route and neutralize Discord mentions

* docs: refresh generated config and plugin API baselines

---------

Co-authored-by: Václav Belák <vaclav.belak@gendigital.com>
2026-03-27 09:06:40 -07:00
Peter Steinberger
833636f0b2 style(ui): normalize control-ui formatting 2026-03-27 15:15:40 +00:00
bottenbenny
f9b8499bf6 fix(chat): send button should use system theme variables (#55075)
Merged via squash.

Prepared head SHA: eb3e197874
Co-authored-by: bottenbenny <270688955+bottenbenny@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-27 15:12:19 +01:00
Peter Steinberger
f625a0b106 style: apply current oxfmt output to ui views 2026-03-27 12:03:25 +00:00
Peter Steinberger
f86765cba3 style: refresh ui formatting 2026-03-27 06:06:37 +00:00
Tak Hoffman
417024f9ad style(ui): apply formatting cleanup 2026-03-27 00:57:46 -05:00
Ayaan Zaidi
9368f834c0 style(ui): format view templates 2026-03-27 10:59:07 +05:30
Peter Steinberger
8cf1e46a94 style: format ui sources 2026-03-27 04:45:17 +00:00
Peter Steinberger
be6b841334 fix: align skill and compaction API usage 2026-03-27 03:27:51 +00:00
Peter Steinberger
a331270f8a fix: restore green build after upstream API drift 2026-03-27 02:49:53 +00:00
Peter Steinberger
10527ff8a3 build: refresh deps and vitest cache lanes 2026-03-27 02:26:07 +00:00
Peter Steinberger
f0c1057f68 fix: restore reveal-to-edit raw config flow 2026-03-26 23:45:10 +00:00
Peter Steinberger
0106b0488a refactor: share config section card rendering 2026-03-26 23:20:26 +00:00
Peter Steinberger
8df6134a1b refactor: share usage metrics timeslice walker 2026-03-26 22:38:13 +00:00
Peter Steinberger
ff47ad58fc refactor: share config path traversal helper 2026-03-26 22:38:13 +00:00
Peter Steinberger
00aedb3414 refactor: split claude cli history import pipeline 2026-03-26 22:12:16 +00:00
Peter Steinberger
672a24cbde fix: unify claude cli imported tool messages 2026-03-26 22:02:26 +00:00
Peter Steinberger
d6f7de392c test: dedupe ui chat seams 2026-03-26 17:07:27 +00:00
Peter Steinberger
c12623a857 test: share plugin auth and ui storage fixtures 2026-03-26 16:55:20 +00:00
Peter Steinberger
d5acd7dee5 test: share ui reconnect and storage helpers 2026-03-26 16:41:51 +00:00
w-sss
0bdb8ac7ad fix(ui): add width/height to context-notice SVG icon
- Fixes #47924
- Prevents SVG icon from expanding and covering entire chat window
- Adds explicit 24x24px dimensions to context-notice__icon SVG

Root cause:
The SVG element lacked explicit width and height attributes,
causing it to expand to fill the parent container when the context
usage warning appears (at ~85% token limit).
2026-03-25 00:25:55 -05:00
Peter Steinberger
23a4932997 refactor: share channel card selectors and layout 2026-03-24 21:44:28 -07:00
ted
4d41b8664c fix(ui): return null when default account ID is stale instead of falling back to first account 2026-03-24 21:28:53 -07:00
ted
dc85235bf0 UI: derive channel configured state from default account 2026-03-24 21:28:53 -07:00
Tak Hoffman
f3eb620824 fix: refresh available tools when the session model changes (#54184) 2026-03-24 22:07:06 -05:00
Tak Hoffman
9c7823350b feat: add /tools runtime availability view (#54088)
* test(memory): lock qmd status counts regression

* feat: make /tools show what the agent can use right now

* fix: sync web ui slash commands with the shared registry

* feat: add profile and unavailable counts to /tools

* refine: keep /tools focused on available tools

* fix: resolve /tools review regressions

* fix: honor model compat in /tools inventory

* fix: sync generated protocol models for /tools

* fix: restore canonical slash command names

* fix: avoid ci lint drift in google helper exports

* perf: stop computing unused /tools unavailable counts

* docs: clarify /tools runtime behavior
2026-03-24 21:09:51 -05:00
Peter Steinberger
398d58fb8a fix: stabilize logging config imports 2026-03-24 17:21:28 +00:00
Val Alexander
b61a875d56 fix: widen installer regex allowlists and deduplicate safeExternalHref calls
- SAFE_GO_MODULE: allow uppercase in module paths (A-Z)
- SAFE_BREW_FORMULA: allow @ for versioned formulas (python@3.12)
- SAFE_UV_PACKAGE: allow extras [standard] and equality pins ==
- Cache safeExternalHref result in skills detail API key section
2026-03-24 01:46:33 -05:00
Val Alexander
cb58e45130 fix(security): resolve Aisle findings — skill installer validation, terminal sanitization, URL scheme allowlisting (#53471) thanks @BunsDev
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Co-authored-by: Nova <nova@openknot.ai>
2026-03-24 01:43:48 -05:00
Val Alexander
a710366e9e feat(ui): Control UI polish — skills revamp, markdown preview, agent workspace, macOS config tree (#53411) thanks @BunsDev
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Co-authored-by: Nova <nova@openknot.ai>
2026-03-24 01:21:13 -05:00
Peter Steinberger
ecb3aa7fe0 test: sync app chat model override expectation 2026-03-23 23:18:59 -07:00
Peter Steinberger
ff2e9a52ff fix: preserve deferred TUI history sync (#53130) (thanks @joelnishanth) 2026-03-23 23:18:59 -07:00
Peter Steinberger
9082795b10 refactor(ui): extract chat model resolution state 2026-03-23 22:24:43 -07:00
Peter Steinberger
013385e5c2 refactor: polish trigger and manifest seams 2026-03-23 22:22:48 -07:00
Peter Steinberger
25d52b56a0 fix: keep slash command model qualification on rebase 2026-03-24 05:17:34 +00:00
Peter Steinberger
a8beb55b74 fix: fetch model catalog for slash command updates 2026-03-24 05:17:34 +00:00
Peter Steinberger
2e1c88b728 refactor: tighten embedded prompt and sidecar guards 2026-03-23 22:09:22 -07:00
Val Alexander
da5b7ff0af style(ui): polish agent file preview and usage popovers (#53382)
* feat: make workspace links clickable in agent context card and files list

Updated the agent context card and files list to render workspace names as clickable links, allowing users to easily access the corresponding workspace files. This enhances usability by providing direct navigation to the workspace location.

* style(ui): polish markdown preview dialog

* style(ui): reduce markdown preview list indentation

* style(ui): update markdown preview dialog width and alignment

* fix(ui): open usage filter popovers toward the right

* style(ui): adjust positioning of usage filter and export popovers

* style(ui): update sidebar footer padding and modify usage header z-index

* style(ui): adjust positioning of usage filter popover to the left and export popover to the right

* style(ui): simplify workspace link rendering in agent context card

* UI: make workspace paths interactive buttons or plain text

Agent Context card workspace (Channels/Cron panels): replace non-interactive
<div> with a real <button> wired to onSelectPanel('files'), matching the
Overview panel pattern.

Core Files footer workspace: drop workspace-link class since the user is
already on the Files panel — keep as plain text.
2026-03-23 23:55:25 -05:00
HCL
be20eebc21 fix(ui): resolve model provider from catalog instead of stale session default
When the server returns a bare model name (e.g. "deepseek-chat") with
a session-level modelProvider (e.g. "zai"), the UI blindly prepends
the provider — producing "zai/deepseek-chat" instead of the correct
"deepseek/deepseek-chat". This causes "model not allowed" errors
when switching between models from different providers.

Root cause: resolveModelOverrideValue() and resolveDefaultModelValue()
in app-render.helpers.ts, plus the /model slash command handler in
slash-command-executor.ts, all call resolveServerChatModelValue()
which trusts the session's default provider. The session provider
reflects the PREVIOUS model, not the newly selected one.

Fix: for bare model names, create a raw ChatModelOverride and resolve
through normalizeChatModelOverrideValue() which looks up the correct
provider from the model catalog. Falls back to server-provided provider
only if the catalog lookup fails. All 3 call sites are fixed.

Closes #53031

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: HCL <chenglunhu@gmail.com>
2026-03-23 21:54:02 -07:00
Val Alexander
9dd0530b97 fix(ui): redact sensitive config values in diff panel
Use isSensitiveConfigPath to detect token/password/secret/apiKey paths
and display REDACTED_PLACEHOLDER instead of raw values in the config
diff panel, preventing credential exposure in the UI.
2026-03-23 20:48:08 -05:00
Val Alexander
21ac4b9a8a style(ui): continue ui clarity pass across theme, config, and usage (#53272) thanks @BunsDev
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Co-authored-by: Nova <nova@openknot.ai>
2026-03-23 20:45:43 -05:00