Skip to content

Commit 54e4fb0

Browse files
committed
Merge branch 'main' into trungutt/surface-finish-reason
2 parents 25bea5c + f99a708 commit 54e4fb0

34 files changed

Lines changed: 3812 additions & 336 deletions

CHANGELOG.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,98 @@
33
All notable changes to this project will be documented in this file.
44

55

6+
## [v1.39.0] - 2026-03-27
7+
8+
This release adds new color themes for the terminal interface and includes internal version management updates.
9+
10+
## What's New
11+
- Adds Calm Roots theme with warm white accents, sage green info messages, and charcoal background
12+
- Adds Neon Pink theme with vibrant pink tones and high-contrast white accents for readability
13+
14+
## Technical Changes
15+
- Freezes v7 version
16+
- Updates CHANGELOG.md for v1.38.0
17+
18+
### Pull Requests
19+
20+
- [#2256](https://github.com/docker/docker-agent/pull/2256) - docs: update CHANGELOG.md for v1.38.0
21+
- [#2260](https://github.com/docker/docker-agent/pull/2260) - Add Calm Roots and Neon Pink themes
22+
- [#2264](https://github.com/docker/docker-agent/pull/2264) - Freeze v7
23+
24+
25+
## [v1.38.0] - 2026-03-26
26+
27+
This release improves OAuth configuration and fixes tool caching issues with remote MCP server reconnections.
28+
29+
## Improvements
30+
31+
- Changes OAuth client name to "docker-agent" for better identification
32+
- Reworks compaction logic to prevent infinite loops when context overflow errors occur repeatedly
33+
34+
## Bug Fixes
35+
36+
- Fixes tool cache not refreshing after remote MCP server reconnects, ensuring updated tools are available after server restarts
37+
38+
## Technical Changes
39+
40+
- Updates CHANGELOG.md for v1.37.0 release documentation
41+
42+
### Pull Requests
43+
44+
- [#2242](https://github.com/docker/docker-agent/pull/2242) - Refactor compaction
45+
- [#2243](https://github.com/docker/docker-agent/pull/2243) - docs: update CHANGELOG.md for v1.37.0
46+
- [#2245](https://github.com/docker/docker-agent/pull/2245) - Change the oauth client name to docker-agent
47+
- [#2246](https://github.com/docker/docker-agent/pull/2246) - fix: refresh tool and prompt caches after remote MCP server reconnect
48+
49+
50+
## [v1.37.0] - 2026-03-25
51+
52+
This release adds support for forwarding sampling parameters to provider APIs, introduces global user-level permissions, and includes several bug fixes and improvements.
53+
54+
## What's New
55+
56+
- Adds support for forwarding sampling provider options (top_k, repetition_penalty, etc.) to provider APIs
57+
- Adds global-level permissions from user config that apply across all sessions and agents
58+
- Adds a welcome message to the interface
59+
- Adds custom linter to enforce config version import chain
60+
61+
## Improvements
62+
63+
- Refactors RAG from agent-level config to standard toolset type for consistency with other toolsets
64+
- Restores RAG indexing event forwarding to TUI after toolset refactor
65+
- Simplifies RAG event forwarding and cleans up RAGTool
66+
67+
## Bug Fixes
68+
69+
- Fixes Bedrock interleaved_thinking defaults to true and adds logging for provider_opts mismatches
70+
- Fixes issue where CacheControl markers were preserved during message compaction, exceeding Anthropic's limit
71+
- Fixes tool loop detector by resetting it after degenerate loop error
72+
- Fixes desktop proxy socket name on WSL where http-proxy socket is not allowed for users
73+
74+
## Technical Changes
75+
76+
- Documents max_old_tool_call_tokens and max_consecutive_tool_calls in agent config reference
77+
- Documents global permissions from user config in permissions reference and guides
78+
- Pins GitHub actions for improved security
79+
- Updates cagent-action to latest version with better permissions
80+
81+
### Pull Requests
82+
83+
- [#2210](https://github.com/docker/docker-agent/pull/2210) - Refactor RAG from agent-level config to standard toolset type
84+
- [#2225](https://github.com/docker/docker-agent/pull/2225) - Add custom linter to enforce config version import chain
85+
- [#2226](https://github.com/docker/docker-agent/pull/2226) - feat: forward sampling provider_opts (top_k, repetition_penalty) to provider APIs
86+
- [#2227](https://github.com/docker/docker-agent/pull/2227) - docs: update CHANGELOG.md for v1.36.1
87+
- [#2229](https://github.com/docker/docker-agent/pull/2229) - docs: add max_old_tool_call_tokens and max_consecutive_tool_calls to agent config reference
88+
- [#2230](https://github.com/docker/docker-agent/pull/2230) - Add global-level permissions from user config
89+
- [#2231](https://github.com/docker/docker-agent/pull/2231) - Pin GitHub actions
90+
- [#2233](https://github.com/docker/docker-agent/pull/2233) - update cagent-action to latest (with better permissions)
91+
- [#2236](https://github.com/docker/docker-agent/pull/2236) - fix: strip CacheControl from messages during compaction
92+
- [#2237](https://github.com/docker/docker-agent/pull/2237) - Reset tool loop detector after degenerate loop error
93+
- [#2238](https://github.com/docker/docker-agent/pull/2238) - Bump direct Go module dependencies
94+
- [#2240](https://github.com/docker/docker-agent/pull/2240) - Fix desktop proxy socket name on WSL
95+
- [#2241](https://github.com/docker/docker-agent/pull/2241) - docs: document global permissions from user config
96+
97+
698
## [v1.36.1] - 2026-03-23
799

8100
This release improves OCI reference handling, adds a tools command, and enhances MCP server reliability with better error recovery.
@@ -1560,3 +1652,9 @@ This release improves the terminal user interface with better error handling and
15601652
[v1.36.0]: https://github.com/docker/docker-agent/releases/tag/v1.36.0
15611653

15621654
[v1.36.1]: https://github.com/docker/docker-agent/releases/tag/v1.36.1
1655+
1656+
[v1.37.0]: https://github.com/docker/docker-agent/releases/tag/v1.37.0
1657+
1658+
[v1.38.0]: https://github.com/docker/docker-agent/releases/tag/v1.38.0
1659+
1660+
[v1.39.0]: https://github.com/docker/docker-agent/releases/tag/v1.39.0

docs/configuration/overview/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ providers:
5353
base_url: https://api.example.com/v1
5454
token_key: MY_API_KEY
5555

56-
# 7. Permissions — global tool permission rules (optional)
56+
# 7. Permissions — agent-level tool permission rules (optional)
57+
# For user-wide global permissions, see ~/.config/cagent/config.yaml
5758
permissions:
5859
allow: ["read_*"]
5960
deny: ["shell:cmd=sudo*"]

docs/configuration/permissions/index.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,18 @@ Permissions provide fine-grained control over tool execution. You can configure
1919

2020
</div>
2121

22-
## Configuration
22+
## Permission Levels
23+
24+
Permissions can be defined at two levels:
25+
26+
| Level | Location | Scope |
27+
| ----- | -------- | ----- |
28+
| **Agent-level** | Agent YAML config (`permissions:` section) | Applies to that specific agent config |
29+
| **Global (user-level)** | `~/.config/cagent/config.yaml` under `settings.permissions` | Applies to every agent you run |
30+
31+
Both levels use the same `allow`/`ask`/`deny` pattern syntax. When both are present, they are **merged** at startup -- patterns from both sources are combined into a single checker. See [Merging Behavior](#merging-behavior) for details.
32+
33+
## Agent-Level Configuration
2334

2435
```yaml
2536
agents:
@@ -42,6 +53,42 @@ permissions:
4253
- "dangerous_tool"
4354
```
4455
56+
## Global Permissions
57+
58+
Global permissions let you enforce rules across **all** agents, regardless of which agent config you run. Define them in your user config file:
59+
60+
```yaml
61+
# ~/.config/cagent/config.yaml
62+
settings:
63+
permissions:
64+
deny:
65+
- "shell:cmd=sudo*"
66+
- "shell:cmd=rm*-rf*"
67+
allow:
68+
- "read_*"
69+
- "shell:cmd=ls*"
70+
- "shell:cmd=cat*"
71+
```
72+
73+
This is useful for setting personal safety guardrails that apply everywhere -- for example, always blocking `sudo` or always auto-approving read-only tools -- without relying on each agent config to include those rules.
74+
75+
### Merging Behavior
76+
77+
When both global and agent-level permissions are present, they are merged into a single set of patterns before evaluation. The merge works as follows:
78+
79+
- **Deny patterns from either source block the tool.** A global deny cannot be overridden by an agent-level allow, and vice versa.
80+
- **Allow patterns from either source auto-approve the tool** (as long as no deny pattern matches).
81+
- **Ask patterns from either source force confirmation** (as long as no deny or allow pattern matches).
82+
83+
The evaluation order remains the same after merging: **Deny > Allow > Ask > default Ask**.
84+
85+
<div class="callout callout-tip">
86+
<div class="callout-title">Example: Global deny + agent allow
87+
</div>
88+
<p>If your global config denies <code>shell:cmd=sudo*</code> and an agent config allows <code>shell:cmd=sudo apt update</code>, the deny wins. Deny patterns always take priority regardless of source.</p>
89+
90+
</div>
91+
4592
## Pattern Syntax
4693

4794
Permissions support glob-style patterns with optional argument matching:

docs/guides/tips/index.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,26 @@ permissions:
232232
docker-agent run --sandbox agent.yaml
233233
```
234234

235+
### Set Global Permission Guardrails
236+
237+
Use [global permissions]({{ '/configuration/permissions/' | relative_url }}#global-permissions) in your user config to enforce safety rules across every agent:
238+
239+
```yaml
240+
# ~/.config/cagent/config.yaml
241+
settings:
242+
permissions:
243+
deny:
244+
- "shell:cmd=sudo*"
245+
- "shell:cmd=rm*-rf*"
246+
- "shell:cmd=git push --force*"
247+
allow:
248+
- "read_*"
249+
- "shell:cmd=ls*"
250+
- "shell:cmd=cat*"
251+
```
252+
253+
These rules merge with any agent-level permissions. Deny patterns from your global config cannot be overridden by agent configs, so you can trust that dangerous commands stay blocked regardless of which agent you run.
254+
235255
### Use Hooks for Audit Logging
236256

237257
Log all tool calls for compliance or debugging:

pkg/compaction/compaction.go

Lines changed: 4 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,7 @@
1-
// Package compaction provides conversation compaction (summarization) for
2-
// chat sessions that approach their model's context window limit.
3-
//
4-
// It is designed as a standalone component that can be used independently of
5-
// the runtime loop. The package exposes:
6-
//
7-
// - [BuildPrompt]: prepares a conversation for summarization by appending
8-
// the compaction prompt and sanitizing message costs.
9-
// - [ShouldCompact]: decides whether a session needs compaction based on
10-
// token usage and context window limits.
11-
// - [EstimateMessageTokens]: a fast heuristic for estimating the token
12-
// count of a single chat message.
13-
// - [HasConversationMessages]: checks whether a message list contains any
14-
// non-system messages worth summarizing.
151
package compaction
162

173
import (
184
_ "embed"
19-
"time"
205

216
"github.com/docker/docker-agent/pkg/chat"
227
)
@@ -26,68 +11,23 @@ var (
2611
SystemPrompt string
2712

2813
//go:embed prompts/compaction-user.txt
29-
userPrompt string
14+
UserPrompt string
3015
)
3116

3217
// contextThreshold is the fraction of the context window at which compaction
3318
// is triggered. When the estimated token usage exceeds this fraction of the
3419
// context limit, compaction is recommended.
3520
const contextThreshold = 0.9
3621

37-
// Result holds the outcome of a compaction operation.
38-
type Result struct {
39-
// Summary is the generated summary text.
40-
Summary string
41-
42-
// InputTokens is the token count reported by the summarization model,
43-
// used as an approximation of the new context size after compaction.
44-
InputTokens int64
45-
46-
// Cost is the cost of the summarization request in dollars.
47-
Cost float64
48-
}
49-
50-
// BuildPrompt prepares the messages for a summarization request.
51-
// It clones the conversation (zeroing per-message costs so they aren't
52-
// double-counted), then appends a user message containing the compaction
53-
// prompt. If additionalPrompt is non-empty it is included as extra
54-
// instructions.
55-
//
56-
// Callers should first check [HasConversationMessages] to avoid sending
57-
// an empty conversation to the model.
58-
func BuildPrompt(messages []chat.Message, additionalPrompt string) []chat.Message {
59-
prompt := userPrompt
60-
if additionalPrompt != "" {
61-
prompt += "\n\nAdditional instructions from user: " + additionalPrompt
62-
}
63-
64-
out := make([]chat.Message, len(messages), len(messages)+1)
65-
for i, msg := range messages {
66-
cloned := msg
67-
cloned.Cost = 0
68-
cloned.CacheControl = false
69-
out[i] = cloned
70-
}
71-
out = append(out, chat.Message{
72-
Role: chat.MessageRoleUser,
73-
Content: prompt,
74-
CreatedAt: time.Now().Format(time.RFC3339),
75-
})
76-
77-
return out
78-
}
79-
8022
// ShouldCompact reports whether a session's context usage has crossed the
81-
// compaction threshold. It returns true when the estimated total token count
23+
// compaction threshold. It returns true when the total token count
8224
// (input + output + addedTokens) exceeds [contextThreshold] (90%) of
83-
// contextLimit. A non-positive contextLimit is treated as unlimited and
84-
// always returns false.
25+
// contextLimit.
8526
func ShouldCompact(inputTokens, outputTokens, addedTokens, contextLimit int64) bool {
8627
if contextLimit <= 0 {
8728
return false
8829
}
89-
estimated := inputTokens + outputTokens + addedTokens
90-
return estimated > int64(float64(contextLimit)*contextThreshold)
30+
return (inputTokens + outputTokens + addedTokens) > int64(float64(contextLimit)*contextThreshold)
9131
}
9232

9333
// EstimateMessageTokens returns a rough token-count estimate for a single
@@ -121,15 +61,3 @@ func EstimateMessageTokens(msg *chat.Message) int64 {
12161
}
12262
return int64(chars/charsPerToken) + perMessageOverhead
12363
}
124-
125-
// HasConversationMessages reports whether messages contains at least one
126-
// non-system message. A session with only system prompts has no conversation
127-
// to summarize.
128-
func HasConversationMessages(messages []chat.Message) bool {
129-
for _, msg := range messages {
130-
if msg.Role != chat.MessageRoleSystem {
131-
return true
132-
}
133-
}
134-
return false
135-
}

0 commit comments

Comments
 (0)