Skip to content

Commit 563b47e

Browse files
committed
Release v0.0.12
## What's New in v0.0.12 ### Features - Drafts section in sidebar with preview and delete functionality - Interrupted state for tools - shows "{toolName} interrupted" when stopping agent with ESC - Tooltip with full file path when hovering over truncated filenames - "See what's new" banner after app updates with link to changelog ### Improvements & Fixes - Fixed sub-chat renaming not persisting to database - Fixed editor focus after drag & drop image insertion - Pending questions now bound to specific sub-chat (no longer appear in wrong chat) - Fixed duplicate text in todo tool when status is in_progress - Renamed "Premium support" button to "Feedback" - Performance optimizations for pending questions
1 parent 00d4e5b commit 563b47e

28 files changed

+1160
-263
lines changed

RELEASE.md

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ cd apps/desktop
2424
npm version patch --no-git-tag-version # 0.0.5 → 0.0.6
2525
```
2626

27-
### 2. Update Download Links
27+
### 2. Commit Version Bump
2828

29-
Update version in these files:
30-
- `apps/web/app/agents/landing-page.tsx`
31-
- `apps/web/app/agents/download/download-landing.tsx`
32-
33-
Replace old version URLs with new version (e.g., `Agents-0.0.5``Agents-0.0.6`).
29+
```bash
30+
git add apps/desktop/package.json
31+
git commit -m "chore(desktop): bump version to 0.0.X"
32+
git push
33+
```
3434

3535
### 3. Run Release Script
3636

@@ -62,19 +62,19 @@ Once both DMGs show `status: Accepted`, staple and re-upload:
6262
cd apps/desktop/release
6363

6464
# Staple notarization tickets
65-
xcrun stapler staple Agents-0.0.X-arm64.dmg
66-
xcrun stapler staple Agents-0.0.X.dmg
65+
xcrun stapler staple 1Code-0.0.X-arm64.dmg
66+
xcrun stapler staple 1Code-0.0.X.dmg
6767

6868
# Re-upload stapled DMGs to R2
69-
npx wrangler r2 object put "components-code/releases/desktop/Agents-0.0.X-arm64.dmg" \
70-
--file="Agents-0.0.X-arm64.dmg" --content-type="application/x-apple-diskimage"
71-
npx wrangler r2 object put "components-code/releases/desktop/Agents-0.0.X.dmg" \
72-
--file="Agents-0.0.X.dmg" --content-type="application/x-apple-diskimage"
69+
npx wrangler r2 object put "components-code/releases/desktop/1Code-0.0.X-arm64.dmg" \
70+
--file="1Code-0.0.X-arm64.dmg" --content-type="application/x-apple-diskimage"
71+
npx wrangler r2 object put "components-code/releases/desktop/1Code-0.0.X.dmg" \
72+
--file="1Code-0.0.X.dmg" --content-type="application/x-apple-diskimage"
7373

7474
# Update GitHub release assets
75-
gh release delete-asset v0.0.X Agents-0.0.X-arm64.dmg --yes
76-
gh release delete-asset v0.0.X Agents-0.0.X.dmg --yes
77-
gh release upload v0.0.X Agents-0.0.X-arm64.dmg Agents-0.0.X.dmg --clobber
75+
gh release delete-asset v0.0.X 1Code-0.0.X-arm64.dmg --yes
76+
gh release delete-asset v0.0.X 1Code-0.0.X.dmg --yes
77+
gh release upload v0.0.X 1Code-0.0.X-arm64.dmg 1Code-0.0.X.dmg --clobber
7878
```
7979

8080
### 5. Publish Release & Update Changelog
@@ -108,7 +108,29 @@ gh release edit v0.0.X --draft=false --latest
108108
gh release edit v0.0.X --notes "..."
109109
```
110110

111-
### 6. Commit & Tag
111+
### 6. Sync to Public Repository
112+
113+
**Important:** After releasing, sync to the open-source repo:
114+
115+
```bash
116+
cd apps/desktop
117+
./scripts/sync-to-public.sh
118+
```
119+
120+
This script:
121+
1. Syncs code from private repo to public `21st-dev/1code` repo
122+
2. Creates a matching GitHub release in the public repo
123+
3. Uses release notes from the private repo
124+
125+
### 7. Update Download Links
126+
127+
Update version in `apps/web/lib/desktop.ts`:
128+
129+
```typescript
130+
export const DESKTOP_VERSION = "0.0.X"
131+
```
132+
133+
### 8. Commit & Tag
112134

113135
```bash
114136
git add -A
@@ -129,23 +151,24 @@ git push origin v0.0.X
129151

130152
| File | Purpose |
131153
|------|---------|
132-
| `Agents-X.X.X-arm64.dmg` | ARM64 installer (Apple Silicon) |
133-
| `Agents-X.X.X.dmg` | x64 installer (Intel) |
134-
| `Agents-X.X.X-arm64-mac.zip` | ARM64 auto-update package |
135-
| `Agents-X.X.X-mac.zip` | x64 auto-update package |
154+
| `1Code-X.X.X-arm64.dmg` | ARM64 installer (Apple Silicon) |
155+
| `1Code-X.X.X.dmg` | x64 installer (Intel) |
156+
| `1Code-X.X.X-arm64-mac.zip` | ARM64 auto-update package |
157+
| `1Code-X.X.X-mac.zip` | x64 auto-update package |
136158
| `latest-mac.yml` | ARM64 update manifest |
137159
| `latest-mac-x64.yml` | x64 update manifest |
138160
| `*.blockmap` | Delta update blockmaps |
139161

140162
### CDN URLs
141163

142164
- Manifests: `https://cdn.21st.dev/releases/desktop/latest-mac.yml`
143-
- DMGs: `https://cdn.21st.dev/releases/desktop/Agents-X.X.X-arm64.dmg`
144-
- ZIPs: `https://cdn.21st.dev/releases/desktop/Agents-X.X.X-arm64-mac.zip`
165+
- DMGs: `https://cdn.21st.dev/releases/desktop/1Code-X.X.X-arm64.dmg`
166+
- ZIPs: `https://cdn.21st.dev/releases/desktop/1Code-X.X.X-arm64-mac.zip`
145167

146-
### GitHub Release
168+
### GitHub Releases
147169

148-
- URL: `https://github.com/21st-dev/21st/releases/tag/vX.X.X`
170+
- Private: `https://github.com/21st-dev/21st/releases/tag/vX.X.X`
171+
- Public: `https://github.com/21st-dev/1code/releases/tag/vX.X.X`
149172

150173
## How Auto-Updates Work
151174

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "21st-desktop",
3-
"version": "0.0.11",
3+
"version": "0.0.12",
44
"private": true,
55
"description": "1Code - UI for parallel work with AI agents",
66
"author": "21st.dev",

src/main/lib/claude/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export type UIMessageChunk =
3636
multiSelect: boolean
3737
}>
3838
}
39+
| { type: "ask-user-question-timeout"; toolUseId: string }
3940
| { type: "message-metadata"; messageMetadata: MessageMetadata }
4041
// System tools (rendered like regular tools)
4142
| {

src/main/lib/trpc/routers/claude.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,12 @@ export const claudeRouter = router({
352352
}>((resolve) => {
353353
const timeoutId = setTimeout(() => {
354354
pendingToolApprovals.delete(toolUseID)
355+
// Emit chunk to notify UI that the question has timed out
356+
// This ensures the pending question dialog is cleared
357+
safeEmit({
358+
type: "ask-user-question-timeout",
359+
toolUseId: toolUseID,
360+
} as UIMessageChunk)
355361
resolve({ approved: false, message: "Timed out" })
356362
}, 60000)
357363

src/renderer/components/dialogs/agents-shortcuts-dialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ function getAgentShortcuts(
9090
return [
9191
// Creation & Management (mirrors Workspaces order)
9292
{ label: "Create new agent", keys: ["cmd", "T"] },
93-
{ label: "Search agents", keys: ["/"] },
93+
{ label: "Search chats", keys: ["/"] },
9494
{ label: "Archive current agent", keys: ["cmd", "W"] },
9595
// Navigation
9696
{

src/renderer/components/update-banner.tsx

Lines changed: 94 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { useEffect, useRef, useState } from "react"
22
import { flushSync } from "react-dom"
33
import { useUpdateChecker } from "../lib/hooks/use-update-checker"
4+
import { useJustUpdated } from "../lib/hooks/use-just-updated"
45
import { Button } from "./ui/button"
56
import { IconSpinner } from "../icons"
67

7-
// For testing: set to "available" or "downloading" to see the UI
8+
// For testing: set to "available", "downloading", or "just-updated" to see the UI
89
// Change to "none" for production
9-
const MOCK_STATE: "none" | "available" | "downloading" = "none"
10+
const MOCK_STATE: "none" | "available" | "downloading" | "just-updated" = "none"
1011

1112
export function UpdateBanner() {
1213
const {
@@ -15,6 +16,13 @@ export function UpdateBanner() {
1516
installUpdate,
1617
dismissUpdate,
1718
} = useUpdateChecker()
19+
20+
const {
21+
justUpdated: realJustUpdated,
22+
justUpdatedVersion,
23+
dismissJustUpdated,
24+
openChangelog,
25+
} = useJustUpdated()
1826
const hasTriggeredInstall = useRef(false)
1927

2028
// Optimistic loading state - show spinner immediately on click
@@ -25,7 +33,7 @@ export function UpdateBanner() {
2533

2634
// Mock state for testing UI
2735
const [mockStatus, setMockStatus] = useState<
28-
"available" | "downloading" | "dismissed"
36+
"available" | "downloading" | "dismissed" | "just-updated"
2937
>(MOCK_STATE === "none" ? "available" : MOCK_STATE)
3038
const [mockProgress, setMockProgress] = useState(0)
3139

@@ -45,12 +53,33 @@ export function UpdateBanner() {
4553
}
4654
}, [isMocking, mockStatus])
4755

48-
const state = isMocking
49-
? {
50-
status: mockStatus === "dismissed" ? "idle" : mockStatus,
51-
progress: mockProgress,
52-
}
53-
: realState
56+
// Just updated state (show "What's New" banner)
57+
// When mocking "just-updated", we need to show that state regardless of real state
58+
const justUpdated =
59+
isMocking && MOCK_STATE === "just-updated" ? true : realJustUpdated
60+
61+
// Get current app version for display
62+
const [currentVersion, setCurrentVersion] = useState<string | null>(null)
63+
useEffect(() => {
64+
window.desktopApi?.getVersion().then(setCurrentVersion)
65+
}, [])
66+
67+
// Use current version for display (or the just updated version if available)
68+
const displayVersion = justUpdatedVersion || currentVersion
69+
70+
// For mocking just-updated, force idle state so only the "What's New" banner shows
71+
const state =
72+
isMocking && MOCK_STATE === "just-updated"
73+
? { status: "idle" as const, progress: 0 }
74+
: isMocking
75+
? {
76+
status:
77+
mockStatus === "dismissed" || mockStatus === "just-updated"
78+
? ("idle" as const)
79+
: mockStatus,
80+
progress: mockProgress,
81+
}
82+
: realState
5483

5584
// Clear pending state when status changes from "available"
5685
// This handles: download started, error occurred, or state reset
@@ -102,6 +131,62 @@ export function UpdateBanner() {
102131
}
103132
}
104133

134+
const handleOpenChangelog = () => {
135+
// Open changelog URL
136+
window.desktopApi?.openExternal("https://1code.dev/changelog")
137+
// Dismiss the banner
138+
if (isMocking) {
139+
setMockStatus("dismissed")
140+
} else {
141+
dismissJustUpdated()
142+
}
143+
}
144+
145+
const handleDismissWhatsNew = () => {
146+
if (isMocking) {
147+
setMockStatus("dismissed")
148+
} else {
149+
dismissJustUpdated()
150+
}
151+
}
152+
153+
// Show "What's New" banner if app was just updated
154+
if (justUpdated) {
155+
return (
156+
<div className="fixed bottom-4 left-4 z-50 flex items-center gap-3 rounded-lg border border-border bg-popover p-2.5 text-sm text-popover-foreground shadow-lg animate-in fade-in-0 slide-in-from-bottom-2">
157+
<span className="text-foreground">
158+
Updated to v{displayVersion}
159+
</span>
160+
<div className="flex items-center gap-2 ml-2">
161+
<Button size="sm" onClick={handleOpenChangelog}>
162+
See what's new
163+
</Button>
164+
<button
165+
onClick={handleDismissWhatsNew}
166+
className="text-muted-foreground hover:text-foreground transition-colors p-1 rounded hover:bg-muted"
167+
aria-label="Dismiss"
168+
>
169+
<svg
170+
width="14"
171+
height="14"
172+
viewBox="0 0 14 14"
173+
fill="none"
174+
xmlns="http://www.w3.org/2000/svg"
175+
>
176+
<path
177+
d="M11 3L3 11M3 3L11 11"
178+
stroke="currentColor"
179+
strokeWidth="1.5"
180+
strokeLinecap="round"
181+
strokeLinejoin="round"
182+
/>
183+
</svg>
184+
</button>
185+
</div>
186+
</div>
187+
)
188+
}
189+
105190
// Don't show anything for idle, checking, or error states
106191
if (
107192
state.status === "idle" ||

src/renderer/features/agents/atoms/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ export const selectedAgentChatIdAtom = atomWithStorage<string | null>(
99
{ getOnInit: true },
1010
)
1111

12+
// Selected draft ID - when user clicks on a draft in sidebar, this is set
13+
// NewChatForm uses this to restore the draft text
14+
// Reset to null when "New Workspace" is clicked or chat is created
15+
export const selectedDraftIdAtom = atom<string | null>(null)
16+
1217
// Preview paths storage - stores all preview paths keyed by chatId
1318
const previewPathsStorageAtom = atomWithStorage<Record<string, string>>(
1419
"agents:previewPaths",
@@ -434,6 +439,7 @@ export const QUESTIONS_SKIPPED_MESSAGE = "User skipped questions - proceed with
434439
export const QUESTIONS_TIMED_OUT_MESSAGE = "Timed out"
435440

436441
export type PendingUserQuestions = {
442+
subChatId: string
437443
toolUseId: string
438444
questions: Array<{
439445
question: string

0 commit comments

Comments
 (0)