Skip to content

Commit 6fe942f

Browse files
authored
Release v0.18.0 - Compact mobile UI, tool expansion controls, smoother streaming, session fixes and Winget automation (#568)
## Thanks for contributions - [@shantur](https://github.com/shantur): [#535](#535), [#556](#556), [#557](#557), [#562](#562), [#563](#563), [#564](#564), [#565](#565), [#567](#567) - [@pascalandr](https://github.com/pascalandr): [#533](#533), [#551](#551) - [@JDis03](https://github.com/JDis03): [#484](#484), [#536](#536) - [@aayurt](https://github.com/aayurt): [#552](#552) ## Highlights - **Compact mode is much better on mobile**: The message UI has been redesigned for compact layouts, with cleaner controls and a denser conversation view that works better on smaller screens. - **Tool output is easier to control**: New tool-level expansion settings let you choose how much tool-call detail you want to see, making busy sessions easier to scan. - **Streaming output feels steadier**: Bash output, tool output, and assistant responses now stay pinned more reliably while streaming, reducing jumps and missed updates. - **Project sessions are scoped more accurately**: Session lists now respect the active project more consistently, so switching projects is less likely to show unrelated sessions. - **Tab closing is more dependable**: Closing tabs has been tightened up to avoid cases where the wrong tab behavior could interrupt your workflow. ## What’s Improved - **Cleaner compact conversation layout**: Message blocks, message sections, tool calls, permissions, questions, todos, and task output have all been polished for a more readable compact experience. - **More useful tool-call presentation**: Tool calls now have a stronger registry-backed rendering path, clearer titles, improved status display, and better per-tool output handling. - **Better follow behavior near the bottom of sessions**: The session view now tracks bottom-follow intent more carefully, helping the app stay with new output when you expect it to. - **Smoother live session creation**: Session-created events from the live event stream are now handled directly, so new sessions appear more reliably without manual refreshes. - **Improved permission denial feedback**: Denied permissions now produce simpler, less noisy feedback in the conversation. ## Fixes - **More reliable autoscroll during long responses**: Hold-mode assistant autoscroll, message-part tool output autoscroll, and streaming bash output pinning were stabilized. - **Less duplicated streaming text**: SSE part deltas are throttled and buffered more carefully to prevent stale delta text from being duplicated in streamed messages. - **Better session list isolation**: Project session list requests are now scoped so sessions from one project do not bleed into another project’s list. - **More stable tab management**: A tab close bug was fixed to make multi-session navigation safer. - **Release pipeline reliability**: Winget release automation is now wired into the release workflow so Windows package updates can be published more consistently. ## Docs - **New contributor guide**: A `CONTRIBUTING.md` guide was added to help new contributors set up the project and understand the development workflow. - **Winget release docs updated**: Supporting documentation for Winget release automation was refreshed. ### Contributors - [@shantur](https://github.com/shantur) - [@pascalandr](https://github.com/pascalandr) - [@JDis03](https://github.com/JDis03) - [@aayurt](https://github.com/aayurt) **Full Changelog**: [v0.17.0...v0.18.0](v0.17.0...v0.18.0) ## Merged Pull Requests ### [@shantur](https://github.com/shantur) - PR [#535](#535) “fix(ui): simplify permission denial feedback” - PR [#556](#556) “fix(ui): keep streaming bash output pinned” - PR [#557](#557) “WIP: Compact mode message UI redesign” - PR [#562](#562) “fix(ui): handle session created SSE events” - PR [#563](#563) “feat(ui): Add tool level expansion settings.” - PR [#564](#564) “Improve compact mobile UI controls” - PR [#565](#565) “fix(ui): scope project session list requests” - PR [#567](#567) “fix(ui): keep message-part tool output auto-scroll synced” ### [@pascalandr](https://github.com/pascalandr) - PR [#533](#533) “fix: stabilize hold-mode assistant autoscroll” - PR [#551](#551) “fix: wire Winget automation into release pipeline” ### [@JDis03](https://github.com/JDis03) - PR [#484](#484) “docs: add CONTRIBUTING.md guide for new contributors” - PR [#536](#536) “fix(ui): throttle SSE part deltas and prevent stale delta text duplication” ### [@aayurt](https://github.com/aayurt) - PR [#552](#552) “Bugfix/tab close bug”
2 parents 111b0df + 353d8d2 commit 6fe942f

142 files changed

Lines changed: 5695 additions & 3001 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.

.github/workflows/reusable-release.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@ jobs:
9797
release_name: ${{ needs.prepare-release.outputs.release_name }}
9898
secrets: inherit
9999

100+
update-winget:
101+
needs:
102+
- prepare-release
103+
- build-and-upload
104+
if: ${{ !inputs.prerelease }}
105+
permissions:
106+
contents: read
107+
uses: ./.github/workflows/update-winget.yml
108+
with:
109+
release_tag: ${{ needs.prepare-release.outputs.tag }}
110+
secrets: inherit
111+
100112
release-ui:
101113
needs: prepare-release
102114
if: ${{ inputs.release_ui }}

.github/workflows/update-winget.yml

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,83 @@
11
name: Update Winget
22

33
on:
4-
release:
5-
types:
6-
- published
4+
workflow_call:
5+
inputs:
6+
release_tag:
7+
description: "Stable release tag to inspect"
8+
required: true
9+
type: string
10+
release_id:
11+
description: "Optional numeric GitHub release id"
12+
required: false
13+
default: ""
14+
type: string
15+
workflow_dispatch:
16+
inputs:
17+
release_tag:
18+
description: "Stable release tag to inspect"
19+
required: true
20+
type: string
21+
release_id:
22+
description: "Optional numeric GitHub release id"
23+
required: false
24+
default: ""
25+
type: string
726

827
permissions:
928
contents: read
1029

1130
jobs:
31+
resolve-release:
32+
name: Resolve release metadata
33+
runs-on: ubuntu-latest
34+
outputs:
35+
release_id: ${{ steps.release.outputs.release_id }}
36+
release_tag: ${{ steps.release.outputs.release_tag }}
37+
draft: ${{ steps.release.outputs.draft }}
38+
prerelease: ${{ steps.release.outputs.prerelease }}
39+
steps:
40+
- name: Resolve release metadata
41+
id: release
42+
env:
43+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44+
RELEASE_TAG: ${{ inputs.release_tag }}
45+
RELEASE_ID_INPUT: ${{ inputs.release_id }}
46+
run: |
47+
set -euo pipefail
48+
49+
if [ -n "$RELEASE_ID_INPUT" ]; then
50+
release_api="repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID_INPUT}"
51+
else
52+
release_api="repos/${GITHUB_REPOSITORY}/releases/tags/${RELEASE_TAG}"
53+
fi
54+
55+
release_id="$(gh api "$release_api" --jq '.id')"
56+
release_tag="$(gh api "$release_api" --jq '.tag_name')"
57+
draft="$(gh api "$release_api" --jq '.draft')"
58+
prerelease="$(gh api "$release_api" --jq '.prerelease')"
59+
60+
if [ -z "$release_id" ] || [ "$release_id" = "null" ]; then
61+
echo "Unable to resolve release id for tag '$RELEASE_TAG'" >&2
62+
exit 1
63+
fi
64+
65+
echo "release_id=$release_id" >> "$GITHUB_OUTPUT"
66+
echo "release_tag=$release_tag" >> "$GITHUB_OUTPUT"
67+
echo "draft=$draft" >> "$GITHUB_OUTPUT"
68+
echo "prerelease=$prerelease" >> "$GITHUB_OUTPUT"
69+
70+
- name: Log resolved release metadata
71+
run: |
72+
echo "Release tag: ${{ steps.release.outputs.release_tag }}"
73+
echo "Release id: ${{ steps.release.outputs.release_id }}"
74+
echo "Draft: ${{ steps.release.outputs.draft }}"
75+
echo "Prerelease: ${{ steps.release.outputs.prerelease }}"
76+
1277
update-winget:
1378
name: Submit Winget manifest update
14-
if: ${{ !github.event.release.draft && !github.event.release.prerelease }}
79+
needs: resolve-release
80+
if: ${{ needs.resolve-release.outputs.draft != 'true' && needs.resolve-release.outputs.prerelease != 'true' }}
1581
runs-on: ubuntu-latest
1682
env:
1783
WINGET_PACKAGE_IDENTIFIER: ${{ vars.WINGET_PACKAGE_IDENTIFIER || 'NeuralNomadsAI.CodeNomad' }}
@@ -35,8 +101,8 @@ jobs:
35101
run: |
36102
args=(
37103
--repo "${{ github.repository }}"
38-
--release-id "${{ github.event.release.id }}"
39-
--tag "${{ github.event.release.tag_name }}"
104+
--release-id "${{ needs.resolve-release.outputs.release_id }}"
105+
--tag "${{ needs.resolve-release.outputs.release_tag }}"
40106
--asset-name-template "$WINGET_WINDOWS_ASSET_NAME_TEMPLATE"
41107
--timeout-seconds "$WINGET_ASSET_WAIT_TIMEOUT_SECONDS"
42108
--poll-interval-seconds "$WINGET_ASSET_POLL_INTERVAL_SECONDS"
@@ -79,7 +145,7 @@ jobs:
79145
with:
80146
identifier: ${{ env.WINGET_PACKAGE_IDENTIFIER }}
81147
version: ${{ steps.release_asset.outputs.version }}
82-
release-tag: ${{ github.event.release.tag_name }}
148+
release-tag: ${{ needs.resolve-release.outputs.release_tag }}
83149
installers-regex: ${{ steps.release_asset.outputs.asset_regex }}
84150
fork-user: ${{ env.WINGET_FORK_OWNER }}
85151
token: ${{ secrets.WINGET_GITHUB_TOKEN }}

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- When adding new component styles, place them beside their peers in the scoped subdirectory (e.g., `src/styles/messaging/new-part.css`) and import them from the corresponding aggregator file.
77
- Prefer smaller, focused style files (≈150 lines or less) over large monoliths. Split by component or feature area if a file grows beyond that size.
88
- Co-locate reusable UI patterns (buttons, selectors, dropdowns, etc.) under `src/styles/components/` and avoid redefining the same utility classes elsewhere.
9+
- Never use rounded corners in UI styling; keep corners square unless the user explicitly requests otherwise for a specific change.
910
- Document any new styling conventions or directory additions in this file so future changes remain consistent.
1011

1112
## Coding Principles

CONTRIBUTING.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Contributing to CodeNomad
2+
3+
Thank you for your interest in contributing! This guide will help you get started.
4+
5+
## Prerequisites
6+
7+
- **Node.js 18+** and npm
8+
- **OpenCode CLI** in your `PATH` (the server connects to the OpenCode binary to manage workspaces)
9+
10+
## Quick Start
11+
12+
```bash
13+
git clone https://github.com/NeuralNomadsAI/CodeNomad.git
14+
cd CodeNomad
15+
npm install
16+
npm run dev
17+
```
18+
19+
## Finding Issues to Work On
20+
21+
Browse [open issues](https://github.com/NeuralNomadsAI/CodeNomad/issues) and look for these labels:
22+
23+
| Label | Meaning |
24+
|---|---|
25+
| `ready-to-work` | Clear scope, ready for anyone to pick up |
26+
| `good-first-issue` | Good for first-time contributors |
27+
| `enhancement` | New feature requests |
28+
| `bug` | Bug reports |
29+
30+
**Before starting:** comment on the issue so we can discuss approach and avoid duplicate work.
31+
32+
## Development Workflow
33+
34+
### 1. Fork and Branch
35+
36+
```bash
37+
# Fork the repo on GitHub, then clone your fork
38+
git clone https://github.com/YOUR_USERNAME/CodeNomad.git
39+
cd CodeNomad
40+
41+
# Add the upstream remote
42+
git remote add upstream https://github.com/NeuralNomadsAI/CodeNomad.git
43+
44+
# Create a branch from upstream/dev
45+
git fetch upstream
46+
git checkout -b fix/your-branch-name upstream/dev
47+
```
48+
49+
### 2. Branch Naming
50+
51+
| Prefix | Use for |
52+
|---|---|
53+
| `fix/` | Bug fixes |
54+
| `feat/` | New features |
55+
| `docs/` | Documentation changes |
56+
| `refactor/` | Code refactoring |
57+
| `chore/` | Build, config, maintenance |
58+
59+
Examples: `fix/question-queue-ordering`, `feat/retry-tool-call`, `docs/contributing-guide`
60+
61+
### 3. Make Your Changes
62+
63+
```bash
64+
# Install dependencies
65+
npm install
66+
67+
# Run the dev server
68+
npm run dev
69+
70+
# Run type checking
71+
npm run typecheck --workspace @codenomad/ui
72+
```
73+
74+
### 4. Commit
75+
76+
Write clear, descriptive commit messages. Explain **what** changed and **why**.
77+
78+
```bash
79+
git add .
80+
git commit -m "fix(ui): preserve question queue order when upserting duplicate requests
81+
82+
When a question arrives as a global entry and later resolves to a tool
83+
part with a newer timestamp, the original enqueue time was lost, causing
84+
the question to move behind newer entries and break interruption order."
85+
```
86+
87+
### 5. Push and Create a PR
88+
89+
```bash
90+
git push origin your-branch-name
91+
```
92+
93+
Then open a pull request on GitHub targeting the `dev` branch.
94+
95+
**PR checklist:**
96+
- [ ] Branch is based on latest `upstream/dev`
97+
- [ ] One issue per PR (don't mix unrelated changes)
98+
- [ ] Type checking passes: `npm run typecheck` (root) or the workspace-specific script matching your change area
99+
- [ ] Tests pass (if applicable)
100+
- [ ] PR description explains the change, includes relevant screenshots for UI changes, and links related issues when applicable
101+
102+
## Project Structure
103+
104+
| Package | Description |
105+
|---|---|
106+
| `packages/server` | Core logic & CLI — workspaces, OpenCode proxy, API, auth |
107+
| `packages/ui` | SolidJS frontend — reactive UI components and stores |
108+
| `packages/electron-app` | Electron desktop shell |
109+
| `packages/tauri-app` | Tauri desktop shell (experimental) |
110+
| `packages/opencode-plugin` | OpenCode plugin integration |
111+
| `packages/cloudflare` | Cloudflare deployment adapters |
112+
113+
### Key UI Files
114+
115+
| Path | Purpose |
116+
|---|---|
117+
| `packages/ui/src/stores/session-events.ts` | SSE event handlers (idle, status, permissions, questions) |
118+
| `packages/ui/src/stores/session-actions.ts` | User actions (send message, abort, revert, fork) |
119+
| `packages/ui/src/stores/message-v2/` | Message store (v2 architecture) |
120+
| `packages/ui/src/stores/instances.ts` | Instance management and interruption queues |
121+
| `packages/ui/src/components/tool-call.tsx` | Tool call rendering |
122+
| `packages/ui/src/components/message-block.tsx` | Message display blocks |
123+
| `packages/ui/src/components/session/session-view.tsx` | Main session view |
124+
| `packages/ui/src/lib/i18n/messages/` | Translation files (en, es, fr, ja, ru, he, zh-Hans) |
125+
126+
> For a comprehensive map of all six functional areas (server, UI, desktop, speech/audio, build, Cloudflare), SDK integration patterns, and feature traces, load the `codenomad-architecture-guide` skill:
127+
> `.opencode/skills/codenomad-architecture-guide/SKILL.md`
128+
129+
### Styling
130+
131+
- Tokens: `packages/ui/src/styles/tokens.css`
132+
- Utilities: `packages/ui/src/styles/utilities.css`
133+
- Component styles: `packages/ui/src/styles/components/`, `packages/ui/src/styles/messaging/`, `packages/ui/src/styles/panels/`
134+
- Keep style files under ~150 lines; split by component
135+
136+
### Internationalization (i18n)
137+
138+
- Use `useI18n()` in components, `tGlobal()` in stores
139+
- Messages live in `packages/ui/src/lib/i18n/messages/<locale>/`
140+
- When adding a string: add to `en/` first, then add the same key to every other locale
141+
- Placeholders use `{name}` syntax (word characters only)
142+
143+
## Code Principles
144+
145+
- **KISS**: Keep modules narrowly scoped
146+
- **DRY**: Share helpers before copy-pasting
147+
- **Single responsibility**: Split files when concerns diverge
148+
- **Composable primitives**: Prefer signals, hooks, utilities over deep inheritance
149+
150+
## Need Help?
151+
152+
- Check existing [issues](https://github.com/NeuralNomadsAI/CodeNomad/issues) and [PRs](https://github.com/NeuralNomadsAI/CodeNomad/pulls)
153+
- Ask in the issue you're working on
154+
- Review the [server documentation](packages/server/README.md) for CLI flags and configuration

docs/guides/winget-release-automation.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
# Winget release automation
22

3-
CodeNomad publishes Winget updates from GitHub Releases with `.github/workflows/update-winget.yml`.
3+
CodeNomad publishes Winget updates from the stable GitHub release pipeline. `.github/workflows/reusable-release.yml` now calls `.github/workflows/update-winget.yml` after the release assets finish uploading.
44

55
## Trigger
66

7-
- Runs on `release.published`.
8-
- Exits early for draft or prerelease releases.
7+
- Runs as a reusable workflow from the stable release pipeline, after `build-and-upload` completes.
8+
- Resolves the target release by tag through the GitHub API, then exits early for draft or prerelease releases.
9+
- Can also be rerun manually with `workflow_dispatch` by supplying the stable release tag (and optionally the numeric release id).
10+
- This avoids the old `release.published` trap where a release created by GitHub Actions with the default `GITHUB_TOKEN` does not fan out into a second workflow run.
911
- Waits for the expected stable Windows Tauri asset because the release record can exist before all assets finish uploading.
1012

1113
## Required configuration
@@ -28,7 +30,7 @@ CodeNomad publishes Winget updates from GitHub Releases with `.github/workflows/
2830

2931
## Runtime flow
3032

31-
1. Resolve the release version from `github.event.release.tag_name`.
33+
1. Resolve the target release by tag through the GitHub API, then derive the package version from the resolved release tag.
3234
2. Poll the release API until exactly one uploaded asset matches the configured Windows Tauri asset template.
3335
3. Download the matched asset once and compute a SHA-256 for logging and verification.
3436
4. Verify the PAT owner matches `WINGET_FORK_OWNER` and that `${WINGET_FORK_OWNER}/winget-pkgs` is a fork of `microsoft/winget-pkgs`.
@@ -38,3 +40,4 @@ CodeNomad publishes Winget updates from GitHub Releases with `.github/workflows/
3840

3941
- The workflow does not depend on a persistent local `winget-pkgs` clone.
4042
- The current package in `winget-pkgs` uses the release ZIP with a nested NSIS installer, so the workflow targets the stable `CodeNomad-Tauri-windows-x64-{version}.zip` asset.
43+
- If a maintainer publishes a release outside the standard release workflow, they should manually run `Update Winget` for that stable tag.

package-lock.json

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)