Skip to content

Commit ec79611

Browse files
committed
v2.1.0: core 0.6.0 with QoderWork and TRAE SOLO support
1 parent a8e0dbd commit ec79611

10 files changed

Lines changed: 50 additions & 19 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
Website: [codedrobe.app](https://codedrobe.app) · [Download the latest release](https://github.com/CodeDrobe/desktop/releases/latest)
1212

13-
CodeDrobe Desktop is an open-source theme manager for AI desktop apps — currently **OpenAI Codex** and **WorkBuddy** — on macOS and Windows. Browse the CodeDrobe theme store, apply a theme to any supported app with one click, and restore the native interface at any time. Themes only change appearance: your app installation and data stay untouched.
13+
CodeDrobe Desktop is an open-source theme manager for AI desktop apps — currently **OpenAI Codex**, **WorkBuddy**, **QoderWork**, and **TRAE SOLO** — on macOS and Windows. Browse the CodeDrobe theme store, apply a theme to any supported app with one click, and restore the native interface at any time. Themes only change appearance: your app installation and data stay untouched.
1414

1515
![CodeDrobe Desktop theme manager](docs/images/desktop.png)
1616

@@ -19,7 +19,7 @@ CodeDrobe Desktop is an open-source theme manager for AI desktop apps — curren
1919
Version 2 is a complete rebuild:
2020

2121
- **New UI** built with Tailwind CSS + shadcn-style components, sharing the design language of [codedrobe.app](https://codedrobe.app).
22-
- **Multi-app support** on the new `@codedrobe/core` engine: one theme package can target several apps, and the detail drawer applies it per app (Codex, WorkBuddy).
22+
- **Multi-app support** on the new `@codedrobe/core` engine: one theme package can target several apps, and the detail drawer applies it per app (Codex, WorkBuddy, QoderWork, TRAE SOLO).
2323
- **CodeDrobe account sign-in** (OAuth 2.0 PKCE through your system browser) with likes, a synced **Favorites** view, and share actions.
2424
- **Deep links**: `codedrobe://themes/apply?theme=<slug>&app=<id>` from the website installs and applies a theme after an in-app confirmation.
2525
- **Settings dialog** with categorized sections: display language, manual app-path override, per-app debug ports, and software updates.

README_zh.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
官方网站:[codedrobe.app](https://codedrobe.app) · [下载最新版本](https://github.com/CodeDrobe/desktop/releases/latest)
1212

13-
CodeDrobe Desktop 是一款面向 AI 桌面应用的开源主题管理器,目前支持 **OpenAI Codex** **WorkBuddy**,运行于 macOS 和 Windows。在应用内浏览 CodeDrobe 主题商店、一键把主题应用到任意受支持的应用,并可随时恢复原生界面。主题只改变外观,不会修改应用安装包和你的数据。
13+
CodeDrobe Desktop 是一款面向 AI 桌面应用的开源主题管理器,目前支持 **OpenAI Codex****WorkBuddy****QoderWork** **TRAE SOLO**,运行于 macOS 和 Windows。在应用内浏览 CodeDrobe 主题商店、一键把主题应用到任意受支持的应用,并可随时恢复原生界面。主题只改变外观,不会修改应用安装包和你的数据。
1414

1515
![CodeDrobe Desktop 主题管理器](docs/images/desktop.png)
1616

@@ -19,7 +19,7 @@ CodeDrobe Desktop 是一款面向 AI 桌面应用的开源主题管理器,目
1919
v2 是一次彻底重构:
2020

2121
- **全新 UI**:基于 Tailwind CSS + shadcn 风格组件,与 [codedrobe.app](https://codedrobe.app) 共享同一套设计语言。
22-
- **多应用支持**:换用新的 `@codedrobe/core` 引擎,一个主题包可以适配多个应用,详情抽屉里按应用逐个应用(Codex、WorkBuddy)。
22+
- **多应用支持**:换用新的 `@codedrobe/core` 引擎,一个主题包可以适配多个应用,详情抽屉里按应用逐个应用(Codex、WorkBuddy、QoderWork、TRAE SOLO)。
2323
- **CodeDrobe 账号登录**:通过系统浏览器完成 OAuth 2.0 PKCE 授权,支持喜欢主题、同步的**收藏**列表和分享。
2424
- **深度链接**:网页上的 `codedrobe://themes/apply?theme=<slug>&app=<id>` 链接会在应用内确认后自动安装并应用主题。
2525
- **设置弹窗**:分类式设置——界面语言、手动指定应用安装位置、按应用配置调试端口、软件更新。

package-lock.json

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

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "codedrobe-desktop",
33
"productName": "CodeDrobe",
4-
"version": "2.0.2",
4+
"version": "2.1.0",
55
"description": "Open-source theme manager and desktop customization tool for the OpenAI Codex app on macOS and Windows.",
66
"author": "CodeDrobe",
77
"license": "MPL-2.0",
@@ -19,7 +19,7 @@
1919
},
2020
"dependencies": {
2121
"@base-ui/react": "^1.6.0",
22-
"@codedrobe/core": "0.4.0",
22+
"@codedrobe/core": "0.6.0",
2323
"@hugeicons/core-free-icons": "^4.2.2",
2424
"@hugeicons/react": "^1.1.9",
2525
"class-variance-authority": "^0.7.1",

src/main/core-service.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
findRunningPids,
99
findTargets,
1010
getAdapter,
11+
resolveDebugPorts,
1112
resolveThemeTarget,
1213
restoreSkin,
1314
} from '@codedrobe/core';
@@ -88,6 +89,31 @@ export class CoreService {
8889
?? this.adapter(appId).defaultPort;
8990
}
9091

92+
/**
93+
* Hosts that force an ephemeral debug port (e.g. QoderWork) publish the
94+
* live port through DevToolsActivePort files. An explicit user override
95+
* always wins; a file port is only trusted while it serves targets that
96+
* match the adapter.
97+
*/
98+
private async resolveLivePort(appId: AppId, preferredPort: number): Promise<number> {
99+
if (this.settings.overridesFor(appId).port != null) return preferredPort;
100+
const adapter = this.adapter(appId);
101+
try {
102+
if ((await findTargets(adapter, preferredPort, 1200)).length) return preferredPort;
103+
} catch {
104+
// Fall through to the published debug-port candidates.
105+
}
106+
for (const filePort of await resolveDebugPorts(adapter, process.platform)) {
107+
if (filePort === preferredPort) continue;
108+
try {
109+
if ((await findTargets(adapter, filePort, 1200)).length) return filePort;
110+
} catch {
111+
// Try the next candidate.
112+
}
113+
}
114+
return preferredPort;
115+
}
116+
91117
defaultPortFor(appId: AppId): number {
92118
return this.adapter(appId).defaultPort;
93119
}
@@ -98,7 +124,7 @@ export class CoreService {
98124

99125
private async appStatus(appId: AppId): Promise<AppStatus> {
100126
const adapter = this.adapter(appId);
101-
const port = this.portFor(appId);
127+
let port = this.portFor(appId);
102128
const override = this.settings.overridesFor(appId);
103129
let discovered: Awaited<ReturnType<typeof discoverApp>> = null;
104130
let running = false;
@@ -117,6 +143,7 @@ export class CoreService {
117143
}
118144
}
119145
if (running) {
146+
port = await this.resolveLivePort(appId, port);
120147
try {
121148
debugReady = (await findTargets(adapter, port, 1200)).length > 0;
122149
} catch {
@@ -144,7 +171,7 @@ export class CoreService {
144171
if (platform() === 'unsupported') throw new Error(copy.unsupportedPlatform);
145172
const appId = request.appId;
146173
const adapter = this.adapter(appId);
147-
const port = request.port ?? this.portFor(appId);
174+
const port = request.port ?? (await this.resolveLivePort(appId, this.portFor(appId)));
148175
if (!isPort(port)) throw new Error(copy.invalidCdpPort);
149176

150177
const entry = await this.library.find(request.themeId);
@@ -196,7 +223,7 @@ export class CoreService {
196223

197224
async restore(appId: AppId): Promise<SystemStatus> {
198225
const adapter = this.adapter(appId);
199-
const port = this.portFor(appId);
226+
const port = await this.resolveLivePort(appId, this.portFor(appId));
200227
this.log(`[restore] ${appId} (port ${port})`);
201228
try {
202229
await restoreSkin({ adapter, port });

src/shared/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import type { AppLocale } from './i18n';
55
export type Platform = 'darwin' | 'win32' | 'unsupported';
66

77
/** Platform-registered target applications (mirrors @codedrobe/core adapters). */
8-
export type AppId = 'codex' | 'workbuddy';
9-
export const APP_IDS: readonly AppId[] = ['codex', 'workbuddy'];
8+
export type AppId = 'codex' | 'workbuddy' | 'qoderwork' | 'traework';
9+
export const APP_IDS: readonly AppId[] = ['codex', 'workbuddy', 'qoderwork', 'traework'];
1010

1111
export function isAppId(value: unknown): value is AppId {
1212
return typeof value === 'string' && (APP_IDS as readonly string[]).includes(value);

src/ui/assets/apps/qoderwork.png

4.64 KB
Loading

src/ui/assets/apps/traework.png

2.18 KB
Loading

src/ui/components/app-mark.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ import type { AppId } from '@shared/types';
44
import { cn } from '@/lib/utils';
55
import codexIcon from '../assets/apps/codex.png';
66
import workbuddyIcon from '../assets/apps/workbuddy.png';
7+
import qoderworkIcon from '../assets/apps/qoderwork.png';
8+
import traeworkIcon from '../assets/apps/traework.png';
79

810
export const APP_META: Record<AppId, { name: string; icon: string }> = {
911
codex: { name: 'Codex', icon: codexIcon },
1012
workbuddy: { name: 'WorkBuddy', icon: workbuddyIcon },
13+
qoderwork: { name: 'QoderWork', icon: qoderworkIcon },
14+
traework: { name: 'TRAE SOLO', icon: traeworkIcon },
1115
};
1216

1317
/** App icon mark (mirrors the website's AppMark; rounded-square app icon). */

src/ui/components/store-view.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { HugeIcon } from '@/components/ui/huge-icon';
1616
import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from '@/components/ui/empty';
1717
import { InputGroup, InputGroupAddon, InputGroupInput } from '@/components/ui/input-group';
1818
import { Spinner } from '@/components/ui/spinner';
19-
import { AppMark } from '@/components/app-mark';
19+
import { APP_META, AppMark } from '@/components/app-mark';
2020
import { StoreThemeCard } from '@/components/theme-card';
2121
import { cn } from '@/lib/utils';
2222

@@ -138,7 +138,7 @@ export function StoreView({ controller }: { controller: AppController }) {
138138
)}
139139
>
140140
<AppMark appId={appId} size={14} />
141-
{appId === 'codex' ? 'Codex' : 'WorkBuddy'}
141+
{APP_META[appId].name}
142142
</button>
143143
))}
144144
<span className="mx-1 h-4 w-px bg-border" />

0 commit comments

Comments
 (0)