Skip to content

Commit 202be6e

Browse files
authored
Improve Qwen3.6 coding agent and inference defaults (#300)
* Improve Qwen3.6 coding agent and inference defaults * Clarify TUI agent cancellation behavior * Trim coding agent tool paths
1 parent b27355e commit 202be6e

69 files changed

Lines changed: 8092 additions & 9949 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
## Unreleased
22

3+
* Changed unset native decoder/generative context batching from full-context
4+
batches to llama.cpp-aligned caps of `n_batch = min(n_ctx, 2048)` and
5+
`n_ubatch = min(n_batch, 512)`. Explicit positive values remain supported,
6+
native encoder-only models retain full-context batching, and WebGPU preserves
7+
its architecture-agnostic full-context fallback to avoid encoder regressions.
8+
* Reworked the TUI coding agent into a small Pi-style demo with one sequential
9+
JSON loop, exactly `read`/`write`/`edit`/`bash`, a single-screen session, and
10+
startup-only model selection, plus an optional read-only mode. It retains the
11+
Qwen3.6 35B-A3B preset, shared model cache, cancellation and resource limits,
12+
workspace-confined file tools, and an explicit unsandboxed-shell trust
13+
boundary. The quality default now uses Unsloth `UD-Q4_K_M` with the
14+
publisher-aligned non-thinking sampler, while `--thinking` opts into a larger
15+
coding-focused reasoning profile. Model loading now delegates directly to
16+
`LlamaEngine.loadModelSource`, replacing the example-specific downloader and
17+
fuzzy repository resolver with the core local, HTTP, and exact `hf://` source
18+
formats. Reasoning and normal answers now stream as separate transcript
19+
channels, and final answers render with compact Markdown, syntax-highlighted
20+
fenced code, solid code-block backgrounds, and no automatic block/message
21+
spacer rows. Frame-coalesced presentation keeps long streams responsive, and
22+
a lightweight single-window TurboVision theme restores the example's visual
23+
identity without its former window manager. The example now targets Nocterm
24+
`0.8.0`.
25+
* Added `GenerationParams.presencePenalty` for native llama.cpp sampling.
26+
WebGPU and LiteRT-LM reject non-zero values until their runtimes expose an
27+
equivalent control.
28+
* Made `ChatSession` context trimming reserve the requested output budget up to
29+
half the active context, account for tool schemas, retain protocol turn
30+
anchors while compacting completed exchanges, and reduce streaming
31+
accumulation overhead.
32+
333
* Switched the OpenAI-compatible server example default to Unsloth's Qwen3.6
434
27B `UD-Q4_K_XL` GGUF, added model-specific non-thinking and thinking sampler profiles,
535
and documented its text-only / desktop-memory requirements. The server keeps

example/README.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,26 @@ dart run bin/llamadart_cli.dart --help
8383
```
8484

8585
### 5. TUI coding agent (`tui_coding_agent/`)
86-
A terminal UI coding agent built with `nocterm` and `llamadart` showing:
87-
- Streaming coding-chat UX in a TUI layout
88-
- Built-in tool loop (`list_files`, `read_file`, `search_files`, `write_file`, `run_command`)
89-
- Workspace-scoped path safety guard
90-
- Runtime model switching with `/model <source>`
91-
- Default GLM-4.7-Flash model source with custom model override support
86+
A small, Pi-style terminal coding agent built with `nocterm` and `llamadart`
87+
showing:
88+
89+
- One sequential JSON tool loop with exactly `read`, `write`, `edit`, and
90+
`bash`
91+
- A single-screen, single-session chat UI
92+
- A compact TurboVision-inspired frame with streamed reasoning and dense
93+
Markdown answers, including syntax-highlighted fenced code blocks
94+
- Workspace-confined file tools plus bounded, cancellable source downloads,
95+
generation, and active shell work; a model load cancelled during native
96+
allocation unloads after that allocation call returns
97+
- An Unsloth Qwen3.6 35B-A3B `UD-Q4_K_M` default with publisher-aligned
98+
non-thinking sampling and shared `llamadart` model caching
99+
- Optional `--thinking` mode with a larger context and coding-focused sampler
100+
- Startup-only workspace and model selection
101+
- Optional `--read-only` mode that exposes only the `read` tool
102+
103+
The `bash` tool uses Bash on Unix or `cmd.exe` on Windows and runs with the
104+
current user's permissions. It is not sandboxed, and file-tool workspace
105+
confinement does not apply to shell commands.
92106

93107
**Best for:** Building local terminal coding-agent workflows in Dart
94108

example/basic_app/bin/llamadart_embedding_example.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ Future<void> main(List<String> arguments) async {
4848
)
4949
..addOption(
5050
'batch-size',
51-
help: 'Logical batch size (0 uses context size).',
51+
help: 'Logical batch size (0 uses the model-aware default).',
5252
defaultsTo: '0',
5353
)
5454
..addOption(
5555
'ubatch-size',
56-
help: 'Micro-batch size (0 follows batch size).',
56+
help: 'Micro-batch size (0 uses the model-aware default).',
5757
defaultsTo: '0',
5858
)
5959
..addOption(

example/basic_app/lib/services/sqlite_vector_cli_options.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,12 @@ ArgParser createSqliteVectorArgParser({required String defaultModelUrl}) {
181181
)
182182
..addOption(
183183
'batch-size',
184-
help: 'Logical batch size (0 uses context size).',
184+
help: 'Logical batch size (0 uses the model-aware default).',
185185
defaultsTo: '0',
186186
)
187187
..addOption(
188188
'ubatch-size',
189-
help: 'Micro-batch size (0 follows batch size).',
189+
help: 'Micro-batch size (0 uses the model-aware default).',
190190
defaultsTo: '0',
191191
)
192192
..addOption(

example/tui_coding_agent/README.md

Lines changed: 153 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -2,128 +2,176 @@
22

33
Path: `example/tui_coding_agent`
44

5-
This example shows a terminal UI coding agent built with:
6-
7-
- `llamadart` for local model inference and tool calling
8-
- `nocterm` for the interactive TUI layer
9-
10-
By default it starts with GLM 4.7 Flash (`unsloth/GLM-4.7-Flash-GGUF:UD-Q4_K_XL`).
11-
You can switch to any local path, URL, or Hugging Face shorthand at startup or
12-
inside the app.
13-
14-
Tool mode defaults to a **stable text-protocol tool loop** (recommended for
15-
GLM). Native template grammar tool-calling is optional and can be enabled with
16-
`--native-tool-calling`.
17-
18-
## Features
19-
20-
- Streaming assistant output in a TUI chat layout
21-
- TurboVision-inspired desktop with overlapping windows
22-
- Turbo C-style menu bar with popup menus (`Alt` + mnemonic)
23-
- Compact centered exit confirmation dialog
24-
- Built-in coding tools: `list_files`, `read_file`, `search_files`,
25-
`write_file`, `run_command`
26-
- Workspace path guard (blocks tool access outside the selected workspace)
27-
- Model switching command at runtime (`/model <source>`)
28-
- Multi-session chat workflow (create/switch/close local sessions)
29-
- One desktop window per session (MDI-style overlapping chat windows)
30-
- Mouse window controls (focus, drag title bar, resize from lower-right handle)
31-
- Slash command autocomplete (`Tab`, `Shift+Tab`, `Up`, `Down`)
32-
- Tool-policy guardrails:
33-
- direct conceptual prompts default to no-tool answers
34-
- workspace/repo prompts enforce inspection before answering
35-
- duplicate and over-limit tool calls are skipped safely
36-
- Default coding-oriented sampling values
5+
This is a deliberately small, Pi-style local coding agent built with
6+
`llamadart` and `nocterm`. It keeps one model, one conversation, one screen,
7+
four general tools, and a sequential model-to-tool loop that is easy to read
8+
and adapt.
379

38-
## Run
10+
## Agent loop
3911

40-
```bash
41-
cd example/tui_coding_agent
42-
dart pub get
43-
dart run bin/tui_coding_agent.dart
44-
```
12+
For each user request, the example:
4513

46-
### Run with a specific workspace
14+
1. asks the model for the next response;
15+
2. accepts either a normal final answer or exactly one standalone JSON tool
16+
call;
17+
3. executes that tool and returns its JSON result to the model; and
18+
4. repeats until the model answers normally or the round limit is reached.
4719

48-
```bash
49-
dart run bin/tui_coding_agent.dart --workspace /path/to/project
20+
The only executable text-protocol form is:
21+
22+
```text
23+
<tool_call>{"name":"tool_name","arguments":{...}}</tool_call>
5024
```
5125

52-
### Run with a specific model
26+
The block must be the complete assistant response. Calls run one at a time;
27+
prose around a call, sibling calls, shorthand, XML variants, unknown tools,
28+
and malformed or incomplete JSON are not executed.
5329

54-
```bash
55-
dart run bin/tui_coding_agent.dart --model /path/to/model.gguf
30+
## Tools
31+
32+
The model normally receives exactly four tools:
33+
34+
| Tool | Purpose |
35+
| --- | --- |
36+
| `read` | Read bounded UTF-8 text from a workspace file. |
37+
| `write` | Create or overwrite a UTF-8 workspace file. |
38+
| `edit` | Replace exactly one literal occurrence in a workspace file. |
39+
| `bash` | Run a command with Bash on Unix or `cmd.exe` on Windows. |
40+
41+
The file tools resolve paths canonically and reject paths, including symlink
42+
targets, outside the selected workspace. Applicable `AGENTS.md` files from the
43+
workspace and its ancestors are loaded once when the session starts and added
44+
to the system prompt. Start with `--read-only` to expose only `read` and omit
45+
all mutation and shell tools.
46+
47+
## Default model and cache
48+
49+
The default model is Qwen3.6 35B-A3B:
50+
51+
```text
52+
hf://unsloth/Qwen3.6-35B-A3B-GGUF/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf
5653
```
5754

58-
or
55+
The native-desktop preset targets systems with at least 32 GB of RAM and uses:
56+
57+
- 16,384-token context
58+
- up to 4,096 output tokens
59+
- full GPU offload where supported
60+
- logical batch size `2,048`, physical micro-batch size `512`
61+
- temperature `0.7`, top-K `20`, top-P `0.8`, min-P `0`
62+
- repeat penalty `1.0`, presence penalty `1.5`
63+
- non-thinking generation
64+
- at most 24 tool rounds per request
65+
66+
Pass `--thinking` to opt into the higher-quality reasoning profile:
67+
68+
- 32,768-token context
69+
- up to 8,192 output tokens
70+
- logical batch size `2,048`, physical micro-batch size `512`
71+
- temperature `0.6`, top-K `20`, top-P `0.95`, min-P `0`
72+
- repeat penalty `1.0`, presence penalty `0`
73+
- thinking enabled
74+
75+
Thinking is opt-in because it is slower, uses substantially more context and
76+
memory, and can spend much of the output budget reasoning before it reaches a
77+
tool call or final answer. The default non-thinking profile keeps the local
78+
demo responsive; use `--thinking` when solution quality matters more than
79+
latency and your machine can accommodate the larger context. The 32K profile
80+
keeps practical memory headroom for the quantized model on a 64 GB Apple Silicon
81+
system; larger 48K and 64K contexts can exhaust Metal allocations.
82+
83+
Qwen3.6 exposes thinking as an on/off capability, not a trained
84+
low/medium/high reasoning-effort scale. The example therefore keeps the control
85+
honest: omit `--thinking` for off, or pass it for on. When enabled, prior
86+
reasoning is preserved across the agent's tool rounds through Qwen's
87+
`preserve_thinking` template option. Upstream llama.cpp also has a mechanical
88+
reasoning-token budget, but llamadart's embedded inference API does not expose
89+
that control yet; total output tokens are not used as a fake reasoning level.
90+
91+
The session passes this source directly to `LlamaEngine.loadModelSource`, so
92+
downloads use `llamadart`'s shared per-user model cache and resume behavior.
93+
Use `--cache-dir` only to override that cache root. An earlier flat
94+
`UD-Q4_K_S` TUI file remains usable by passing its local path explicitly; it is
95+
not substituted for the new `UD-Q4_K_M` default.
96+
97+
The model is selected only at startup. Pass a local GGUF path, HTTP(S) URL, or
98+
exact `hf://owner/repo/path/to/model.gguf` reference with `--model` before
99+
launching the TUI.
100+
101+
## Run
59102

60103
```bash
61-
dart run bin/tui_coding_agent.dart --model owner/repo:Q4_K_M
104+
cd example/tui_coding_agent
105+
dart pub get
106+
dart run bin/tui_coding_agent.dart
62107
```
63108

64-
### Enable native template tool-calling (experimental)
109+
Choose a workspace and model at startup when needed:
65110

66111
```bash
67-
dart run bin/tui_coding_agent.dart --native-tool-calling
112+
dart run bin/tui_coding_agent.dart --workspace /path/to/project
113+
dart run bin/tui_coding_agent.dart --thinking
114+
dart run bin/tui_coding_agent.dart --read-only
115+
dart run bin/tui_coding_agent.dart --model /path/to/model.gguf
116+
dart run bin/tui_coding_agent.dart \
117+
--model hf://owner/repo/path/to/model.gguf \
118+
--cache-dir /path/to/model-cache
68119
```
69120

70-
## Interactive Commands
71-
72-
- `/help` - Show available commands
73-
- `/clear` - Clear active session log
74-
- `/model` - Show current model source and loaded path
75-
- `/model <path|url|owner/repo[:hint]>` - Switch model and reset session history
76-
- `/workspace` - Show workspace root
77-
- `/new` - Create a new session
78-
- `/next` - Switch to next session
79-
- `/prev` - Switch to previous session
80-
- `/close` - Close current session
81-
- `/zoom-window` - Zoom/unzoom active desktop window
82-
- `/next-window` - Focus next desktop window
83-
- `/prev-window` - Focus previous desktop window
84-
- `/tile-windows` - Arrange all windows in a tiled grid
85-
- `/stack-windows` - Arrange all windows in stacked cascade
86-
- `/cancel` - Cancel active generation
87-
- `/exit` - Open exit confirmation dialog
88-
- `/quit` - Open exit confirmation dialog
89-
90-
## Keyboard Shortcuts
91-
92-
- `F1` - Show help
93-
- `F2` - Seed `/model ` command
94-
- `F3` - Clear conversation
95-
- `F4` - Previous session
96-
- `F5` - Zoom/unzoom active window
97-
- `F6` - Focus next desktop window
98-
- `F7` - Create new session
99-
- `F8` - Next session
100-
- `F9` - Focus previous desktop window
101-
- `F10` - Open/close top menu bar
102-
- `F12` - Close active session
103-
- `Alt+W` - Close active session
104-
- `Alt+X` - Open exit confirmation
105-
- `Alt` + Arrow keys - Move active window
106-
- `Alt` + `Shift` + Arrow keys - Resize active window
107-
- `Esc` - Cancel generation when busy, otherwise open exit confirmation
108-
- `Alt+<menu letter>` - Open top menu (`File/Edit/Search/...`)
109-
110-
In the exit confirmation dialog:
111-
112-
- `Left`/`Right`/`Tab` (`h`/`l` also supported) toggles YES/NO
113-
- `Enter` confirms the currently selected option
114-
- `Esc` or `N` selects NO and dismisses the dialog
115-
116-
## Notes
117-
118-
- The first run may take time due to model download and initialization.
119-
- Downloaded models use the per-user shared `llamadart` model cache by default;
120-
pass `--cache-dir` to use a workspace-local or app-specific cache instead.
121-
- `run_command` uses a safety filter and executes from the workspace root
122-
(or a workspace-relative subdirectory).
123-
- `run_command` accepts `command` and also tolerates alias keys (`cmd`,
124-
`input`, `shell_command`) for model-compatibility.
125-
- If you hit grammar-related crashes in native mode, run without
126-
`--native-tool-calling` (default stable mode).
121+
Use `--help` for the complete startup options.
122+
123+
## TUI
124+
125+
The single-screen UI restores a compact TurboVision-inspired blue window,
126+
gray status chrome, and framed transcript without restoring the old multi-window
127+
desktop. It maintains one in-memory conversation for the loaded model.
128+
129+
Normal answers stream incrementally through a compact GitHub-flavored Markdown
130+
renderer with headings, lists, links, inline code, and syntax-highlighted fenced
131+
code. Code fences use their language label when available, cheaply recognize a
132+
few common unlabelled formats, and fall back safely to plain code. Their
133+
background fills every row, including empty lines. Markdown blocks and
134+
transcript messages no longer add automatic blank spacer rows. With
135+
`--thinking`, reasoning streams separately under a subdued `[think]` label and
136+
the final answer remains under `[agent]`. The stream gate withholds text that
137+
could be a split `<tool_call>` envelope, so raw executable JSON never flashes
138+
in the transcript before validation. High-frequency deltas are coalesced to
139+
terminal frame cadence and accumulated in buffers. Off-screen transcript rows
140+
are built lazily, while the active Markdown row is reparsed only at presentation
141+
cadence rather than for every burst of backend deltas. Syntax highlighting is
142+
bounded for unusually large generated blocks so streaming stays responsive.
143+
144+
- `/help` shows the small command list.
145+
- `/clear` resets the conversation without reloading the model.
146+
- `/model` reports the startup-selected source and loaded model name.
147+
- `/workspace` reports the workspace root.
148+
- `/cancel` cancels current work.
149+
- `/quit` exits.
150+
- `Esc` cancels while busy; otherwise press it twice to quit.
151+
- `Ctrl+C` cancels while busy and exits cleanly while idle.
152+
153+
## Limits and trust boundary
154+
155+
Model resolution and downloads, generation, and the active `bash` process tree
156+
can be cancelled. File reads and edits, tool results, shell output, command
157+
duration, context use, and tool rounds are bounded so the demo fails clearly
158+
instead of growing without limit.
159+
160+
Native model allocation itself cannot be interrupted. If cancellation is
161+
requested during that phase, the session unloads the model as soon as the
162+
allocation call returns.
163+
164+
Cancellation does not roll back effects that already happened. The transcript
165+
shows the command or file path, a bounded result summary, and a warning when an
166+
interrupted tool may have changed state; the next turn retains that warning.
167+
168+
`bash` is intentionally a general shell tool and is **not sandboxed**. Its
169+
commands run with the current user's normal permissions and can read or modify
170+
files outside the selected workspace, access the environment and network, and
171+
start arbitrary child processes. Workspace confinement applies only to
172+
`read`, `write`, and `edit`. Use the demo only with trusted prompts and
173+
repositories, or run the whole process inside an external sandbox or
174+
container.
127175

128176
## Test
129177

0 commit comments

Comments
 (0)