Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
aa638ce
chore: format code
actions-user Dec 9, 2025
ae4993f
wip(desktop): progress
adamdotdevin Dec 9, 2025
a54b663
chore: regen sdk
actions-user Dec 9, 2025
ad0c4c5
chore: format code
actions-user Dec 9, 2025
fb1b6c5
add project.name/icon
thdxr Dec 9, 2025
c944d19
wip(desktop): progress
adamdotdevin Dec 9, 2025
9a34965
feat: add color to project
adamdotdevin Dec 9, 2025
8a9e258
chore: regen sdk
actions-user Dec 9, 2025
de577e1
chore: format code
actions-user Dec 9, 2025
1e3bdcc
rename bus
thdxr Dec 9, 2025
0b40c3d
rework project loading
thdxr Dec 9, 2025
8bff3cd
fix ci
thdxr Dec 9, 2025
553d901
chore: regen sdk
actions-user Dec 9, 2025
380c34a
chore: format code
actions-user Dec 9, 2025
b48caec
core: add automatic project icon discovery from favicon/logo files
thdxr Dec 9, 2025
19ec970
chore: regen sdk
actions-user Dec 9, 2025
2ad9971
chore: format code
actions-user Dec 9, 2025
7439a40
core: fix project icon update to preserve existing icon properties
thdxr Dec 9, 2025
0fd2ecd
chore: regen sdk
actions-user Dec 9, 2025
fa32fbd
chore: format code
actions-user Dec 9, 2025
8c07382
ci: fix sdk gen
rekram1-node Dec 9, 2025
0571a83
chore: regen sdk
actions-user Dec 9, 2025
238f441
chore: format code
actions-user Dec 9, 2025
edffcc3
core: make project updated timestamp optional to support legacy proje…
thdxr Dec 9, 2025
3655840
core: fix project creation to include updated timestamp
thdxr Dec 9, 2025
204fa54
chore: regen sdk
actions-user Dec 9, 2025
75a9c42
chore: format code
actions-user Dec 9, 2025
84a0868
fix: read when file is svg
rekram1-node Dec 9, 2025
abf176a
chore: regen sdk
actions-user Dec 9, 2025
9337852
chore: format code
actions-user Dec 9, 2025
c5e5627
test fixes
thdxr Dec 9, 2025
f1955b4
core: fix project event emission to include updated worktree data
thdxr Dec 9, 2025
70f7287
chore: regen sdk
actions-user Dec 9, 2025
dfd67cd
chore: format code
actions-user Dec 9, 2025
06aa1f4
sync
thdxr Dec 9, 2025
1a3f7c3
chore: regen sdk
actions-user Dec 9, 2025
fc9081a
chore: format code
actions-user Dec 9, 2025
a2e460b
discover logic
thdxr Dec 9, 2025
209b0a0
chore: regen sdk
actions-user Dec 9, 2025
e34f189
chore: format code
actions-user Dec 9, 2025
5f6b2fd
fix tests
thdxr Dec 9, 2025
b242659
fix types
thdxr Dec 9, 2025
13755f4
chore: regen sdk
actions-user Dec 9, 2025
b0cd171
chore: format code
actions-user Dec 9, 2025
802b862
format on write
thdxr Dec 9, 2025
c33a903
fix: resolve 'latest' to actual version when caching plugins (#5292)
nick-vi Dec 9, 2025
dbcc779
ci: fix sdk workflow
rekram1-node Dec 9, 2025
f736751
wip(desktop): progress
adamdotdevin Dec 9, 2025
b9fa7d9
wip(desktop): progress
adamdotdevin Dec 9, 2025
d7563d1
wip(desktop): progress
adamdotdevin Dec 9, 2025
1fbd7a7
wip(desktop): progress
adamdotdevin Dec 9, 2025
35c04d9
wip(desktop): progress
adamdotdevin Dec 9, 2025
16c4b02
feat: add Biome LSP support (#5290)
ry2009 Dec 9, 2025
41d78c1
wip(desktop): progress
adamdotdevin Dec 9, 2025
2dad56c
wip(desktop): progress
adamdotdevin Dec 9, 2025
8a9c7a4
add OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT
rekram1-node Dec 9, 2025
9c93853
wip(desktop): progress
adamdotdevin Dec 9, 2025
ebab7e1
wip(desktop): progress
adamdotdevin Dec 9, 2025
62cbed5
wip(desktop): progress
adamdotdevin Dec 9, 2025
132e772
core: fix project icon update handling to preserve existing icon prop…
thdxr Dec 9, 2025
44c17c1
wip(desktop): progress
adamdotdevin Dec 9, 2025
0aa3e6c
wip(desktop): progress
adamdotdevin Dec 9, 2025
df64612
better interleaved thinking support (#5298)
rekram1-node Dec 9, 2025
9fdbe19
fix: add spacer before queued badge
iamdavidhill Dec 9, 2025
552ee81
tweak: add OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS
rekram1-node Dec 9, 2025
b8f5809
ignore: rm chalk
rekram1-node Dec 9, 2025
3c1e6c2
Update Nix flake.lock and hashes
actions-user Dec 9, 2025
4bdc7c1
ci fix
thdxr Dec 10, 2025
2c27afa
chore: regen sdk
actions-user Dec 10, 2025
8b8b17d
chore: format code
actions-user Dec 10, 2025
6fb32ce
ci
thdxr Dec 10, 2025
632a0fe
chore: regen sdk
actions-user Dec 10, 2025
1efdcea
ci: combine sdk and format workflows into single generate workflow
thdxr Dec 10, 2025
3512d02
ci
thdxr Dec 10, 2025
63d9656
ci
thdxr Dec 10, 2025
cb188f9
ci
thdxr Dec 10, 2025
73e9534
ci
thdxr Dec 10, 2025
4aa1b8d
ci
thdxr Dec 10, 2025
3cf17bc
ci
thdxr Dec 10, 2025
e5af0dd
ci
thdxr Dec 10, 2025
bb1c225
ci
thdxr Dec 10, 2025
5652611
ci
thdxr Dec 10, 2025
ebe6015
fix: re-enable tauri typecheck
adamdotdevin Dec 10, 2025
52ef8de
ci
thdxr Dec 10, 2025
2ed6298
ci
thdxr Dec 10, 2025
f82156f
ci
thdxr Dec 10, 2025
ee00b4e
ci
thdxr Dec 10, 2025
fc9bc26
ci
thdxr Dec 10, 2025
e7e32c9
ci
thdxr Dec 10, 2025
a9aacdb
ci
thdxr Dec 10, 2025
5682ddd
ci
thdxr Dec 10, 2025
bafad6b
ci
thdxr Dec 10, 2025
38a79fa
ci
thdxr Dec 10, 2025
4ecebc2
ci
thdxr Dec 10, 2025
6dbcacf
ci
thdxr Dec 10, 2025
78c5137
sync
thdxr Dec 10, 2025
150baf3
ci
thdxr Dec 10, 2025
09b402a
ci
thdxr Dec 10, 2025
0decdf6
ci
thdxr Dec 10, 2025
1ae2809
ci
thdxr Dec 10, 2025
59dce63
docs: Add portal project to ecosystem documentation (#5300)
hosenur Dec 10, 2025
0759696
core: enable project discovery for experimental builds
thdxr Dec 10, 2025
8e33ac0
ci: publish with multiple tags instead of using dist-tag
thdxr Dec 10, 2025
fa6c060
ci
thdxr Dec 10, 2025
a762da7
ci
thdxr Dec 10, 2025
e72c974
ci
thdxr Dec 10, 2025
a3fbbec
release: v1.0.141
Dec 10, 2025
d60073d
sync: merge upstream v1.0.141 into integration
opencode-agent[bot] Dec 10, 2025
a6ac93a
sync: record last synced tag v1.0.141
opencode-agent[bot] Dec 10, 2025
126fd12
chore: format code
actions-user Dec 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/last-synced-tag
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v1.0.138
v1.0.141
19 changes: 10 additions & 9 deletions .github/workflows/format.yml → .github/workflows/generate.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: format
name: generate

on:
push:
Expand All @@ -8,14 +8,10 @@ on:
branches-ignore:
- production
workflow_dispatch:
workflow_run:
workflows: ["sdk"]
types:
- completed

jobs:
format:
generate:
runs-on: blacksmith-4vcpu-ubuntu-2404
if: github.event.workflow_run.conclusion == 'success'
permissions:
contents: write
steps:
Expand All @@ -29,9 +25,14 @@ jobs:
- name: Setup Bun
uses: ./.github/actions/setup-bun

- name: run
- name: Generate SDK
run: |
./script/format.ts
bun ./packages/sdk/js/script/build.ts
(cd packages/opencode && bun dev generate > ../sdk/openapi.json)
bun x prettier --write packages/sdk/openapi.json

- name: Format
run: ./script/format.ts
env:
CI: true
PUSH_BRANCH: ${{ github.event.pull_request.head.ref || github.ref_name }}
39 changes: 0 additions & 39 deletions .github/workflows/sdk.yml

This file was deleted.

1 change: 1 addition & 0 deletions .opencode/command/commit.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
description: git commit and push
model: opencode/glm-4.6
---

commit and push
Expand Down
4 changes: 1 addition & 3 deletions .opencode/opencode.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
"instructions": ["STYLE_GUIDE.md"],
"provider": {
"opencode": {
"options": {
// "baseURL": "http://localhost:8080",
},
"options": {},
},
},
"mcp": {
Expand Down
356 changes: 108 additions & 248 deletions bun.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/console/app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-app",
"version": "1.0.138",
"version": "1.0.141",
"type": "module",
"scripts": {
"typecheck": "tsgo --noEmit",
Expand Down
2 changes: 1 addition & 1 deletion packages/console/core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/console-core",
"version": "1.0.138",
"version": "1.0.141",
"private": true,
"type": "module",
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/console/function/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-function",
"version": "1.0.138",
"version": "1.0.141",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
Expand Down
2 changes: 1 addition & 1 deletion packages/console/mail/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-mail",
"version": "1.0.138",
"version": "1.0.141",
"dependencies": {
"@jsx-email/all": "2.2.3",
"@jsx-email/cli": "1.4.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/desktop",
"version": "1.0.138",
"version": "1.0.141",
"description": "",
"type": "module",
"exports": {
Expand Down
17 changes: 14 additions & 3 deletions packages/desktop/src/components/prompt-input.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useFilteredList } from "@opencode-ai/ui/hooks"
import { createEffect, on, Component, Show, For, onMount, onCleanup, Switch, Match } from "solid-js"
import { createEffect, on, Component, Show, For, onMount, onCleanup, Switch, Match, createSignal } from "solid-js"
import { createStore } from "solid-js/store"
import { createFocusSignal } from "@solid-primitives/active-element"
import { useLocal } from "@/context/local"
Expand All @@ -22,6 +22,8 @@ interface PromptInputProps {
ref?: (el: HTMLDivElement) => void
}

const PLACEHOLDERS = ["Fix a TODO in the codebase", "What is the tech stack of this project?", "Fix broken tests"]

export const PromptInput: Component<PromptInputProps> = (props) => {
const navigate = useNavigate()
const sdk = useSDK()
Expand All @@ -36,6 +38,15 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
popoverIsOpen: false,
})

const [placeholder, setPlaceholder] = createSignal(Math.floor(Math.random() * PLACEHOLDERS.length))

onMount(() => {
const interval = setInterval(() => {
setPlaceholder((prev) => (prev + 1) % PLACEHOLDERS.length)
}, 5000)
onCleanup(() => clearInterval(interval))
})

createEffect(() => {
session.id
editorRef.focus()
Expand Down Expand Up @@ -68,7 +79,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {

const handleFileSelect = (path: string | undefined) => {
if (!path) return
addPart({ type: "file", path, content: "@" + getFilename(path), start: 0, end: 0 })
addPart({ type: "file", path, content: "@" + path, start: 0, end: 0 })
}

const { flat, active, onInput, onKeyDown, refetch } = useFilteredList<string>({
Expand Down Expand Up @@ -403,7 +414,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
/>
<Show when={!session.prompt.dirty()}>
<div class="absolute top-0 left-0 px-5 py-3 text-14-regular text-text-weak pointer-events-none">
Plan and build anything
Ask anything... "{PLACEHOLDERS[placeholder()]}"
</div>
</Show>
</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/src/context/global-sdk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const { use: useGlobalSDK, provider: GlobalSDKProvider } = createSimpleCo
sdk.global.event().then(async (events) => {
for await (const event of events.stream) {
// console.log("event", event)
emitter.emit(event.directory, event.payload)
emitter.emit(event.directory ?? "global", event.payload)
}
})

Expand Down
68 changes: 57 additions & 11 deletions packages/desktop/src/context/global-sync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,36 @@ import { Binary } from "@opencode-ai/util/binary"
import { createSimpleContext } from "@opencode-ai/ui/context"
import { useGlobalSDK } from "./global-sdk"

const PASTEL_COLORS = [
"#FCEAFD", // pastel pink
"#FFDFBA", // pastel peach
"#FFFFBA", // pastel yellow
"#BAFFC9", // pastel green
"#EAF6FD", // pastel blue
"#EFEAFD", // pastel lavender
"#FEC8D8", // pastel rose
"#D4F0F0", // pastel cyan
"#FDF0EA", // pastel coral
"#C1E1C1", // pastel mint
]

function randomPastelColor() {
return PASTEL_COLORS[Math.floor(Math.random() * PASTEL_COLORS.length)]
}

async function ensureProjectColor(project: Project, sdk: ReturnType<typeof useGlobalSDK>): Promise<Project> {
if (project.icon?.color) return project
const color = randomPastelColor()
const updated = { ...project, icon: { ...project.icon, color } }
sdk.client.project.update({ projectID: project.id, icon: { color } })
return updated
}

type State = {
ready: boolean
provider: Provider[]
agent: Agent[]
project: Project
project: string
config: Config
path: Path
session: Session[]
Expand Down Expand Up @@ -60,11 +85,10 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple
})

const children: Record<string, ReturnType<typeof createStore<State>>> = {}

function child(directory: string) {
if (!children[directory]) {
setGlobalStore("children", directory, {
project: { id: "", worktree: "", time: { created: 0, initialized: 0 } },
project: "",
config: {},
path: { state: "", config: "", worktree: "", directory: "" },
ready: false,
Expand All @@ -88,9 +112,31 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple
const sdk = useGlobalSDK()
sdk.event.listen((e) => {
const directory = e.name
const [store, setStore] = child(directory)

const event = e.details

if (directory === "global") {
switch (event.type) {
case "project.updated": {
ensureProjectColor(event.properties, sdk).then((project) => {
const result = Binary.search(globalStore.projects, project.id, (s) => s.id)
if (result.found) {
setGlobalStore("projects", result.index, reconcile(project))
return
}
setGlobalStore(
"projects",
produce((draft) => {
draft.splice(result.index, 0, project)
}),
)
})
break
}
}
return
}

const [store, setStore] = child(directory)
switch (event.type) {
case "session.updated": {
const result = Binary.search(store.session, event.properties.info.id, (s) => s.id)
Expand Down Expand Up @@ -163,14 +209,14 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple
Promise.all([
sdk.client.project
.list()
.then((x) =>
.then(async (x) => {
const filtered = (x.data ?? []).filter((p) => !p.worktree.includes("opencode-test") && p.vcs)
const projects = await Promise.all(filtered.map((p) => ensureProjectColor(p, sdk)))
setGlobalStore(
"projects",
(x.data ?? [])
.filter((x) => !x.worktree.includes("opencode-test") && x.vcs)
.sort((a, b) => b.time.created - a.time.created),
),
)
projects.sort((a, b) => a.id.localeCompare(b.id)),
)
})
.catch(() => setGlobalStore("projects", [])),
]).then(() => setGlobalStore("ready", true))

Expand Down
33 changes: 22 additions & 11 deletions packages/desktop/src/context/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
const globalSync = useGlobalSync()
const [store, setStore] = makePersisted(
createStore({
projects: [] as { directory: string; expanded: boolean }[],
projects: [] as { worktree: string; expanded: boolean }[],
sidebar: {
opened: false,
width: 280,
Expand All @@ -26,7 +26,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
},
}),
{
name: "default-layout.v4",
name: "default-layout.v6",
},
)

Expand All @@ -48,32 +48,43 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(

onMount(() => {
Promise.all(
store.projects.map(({ directory }) => {
return loadProjectSessions(directory)
store.projects.map(({ worktree }) => {
return loadProjectSessions(worktree)
}),
)
})

function enrich(project: { worktree: string; expanded: boolean }) {
const metadata = globalSync.data.projects.find((x) => x.worktree === project.worktree)
if (!metadata) return []
return [
{
...project,
...metadata,
},
]
}

return {
projects: {
list: createMemo(() => store.projects),
list: createMemo(() => store.projects.flatMap(enrich)),
open(directory: string) {
if (store.projects.find((x) => x.directory === directory)) return
if (store.projects.find((x) => x.worktree === directory)) return
loadProjectSessions(directory)
setStore("projects", (x) => [...x, { directory, expanded: true }])
setStore("projects", (x) => [...x, { worktree: directory, expanded: true }])
},
close(directory: string) {
setStore("projects", (x) => x.filter((x) => x.directory !== directory))
setStore("projects", (x) => x.filter((x) => x.worktree !== directory))
},
expand(directory: string) {
setStore("projects", (x) => x.map((x) => (x.directory === directory ? { ...x, expanded: true } : x)))
setStore("projects", (x) => x.map((x) => (x.worktree === directory ? { ...x, expanded: true } : x)))
},
collapse(directory: string) {
setStore("projects", (x) => x.map((x) => (x.directory === directory ? { ...x, expanded: false } : x)))
setStore("projects", (x) => x.map((x) => (x.worktree === directory ? { ...x, expanded: false } : x)))
},
move(directory: string, toIndex: number) {
setStore("projects", (projects) => {
const fromIndex = projects.findIndex((x) => x.directory === directory)
const fromIndex = projects.findIndex((x) => x.worktree === directory)
if (fromIndex === -1 || fromIndex === toIndex) return projects
const result = [...projects]
const [item] = result.splice(fromIndex, 1)
Expand Down
Loading