Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,26 @@

## [Unreleased]

## [0.5.0] — 2026-10-12

### Added

- 千问办公新增 Windows 原生助手接入,WSL 员工通过私有通道提交专属会话并查看进度与结果;审批留在客户端,取消与退出仅处理本次任务,模型、工具、账号及额度遵循客户端设置。
- WorkBuddy 增加 Windows 客户端本地登录接入,WSL 员工通过桌面拥有的私有通道复用客户端自动模型;提供本地登录/API 选择,接入失效时保持原员工绑定。

### Changed

- 员工编辑改为紧凑的基本信息、技能、连接器和高级权限区域,补齐输入校验与无效改动检测;千问办公员工只编辑名称,工具与审批在客户端设置。
- 岗位搜索采用同高的搜索框与展开/收起图标,支持清空及键盘焦点恢复;项目列表、看板与排期统一主题颜色和留白。
- 单聊、群聊与流式回复统一显示可点击链接、重点加粗、换行及代码复制反馈;格式提示保留用户指定格式和原始请求记录。

- 审批与上报统一使用工作台的背景、字体、边距和中性选中态,移除收件箱独立蓝黑配色及加高顶栏;风险和错误标签沿用全局状态配色。
- 导航与选择控件采用中性灰底、轻量文字和无外框选项组,去除彩色边框与选中底线;保持选中、悬停、键盘焦点及禁用状态的区别,静态分组名称与可点击选项分开显示,主题与群聊列表补齐选中状态语义。
- 关系图谱默认从员工和关联资料开始,能力与配置、完整对象列表、图形和来源信息按需展开;依据侧栏仅在主动查证时打开,并提供真实工作区对象的三步实操引导。

### Fixed

- Codex 接入检查使用实际解析到的 CLI,并验证员工会话所需的启动参数与工具开关;不兼容的旧安装提示升级,避免显示可用后启动即失败。
- Windows 的 Qoder 探测不再把 IDE 启动器当成代理 CLI,模型选择测试隔离本机目录探测,避免读员工卡片或运行测试时意外打开编辑器。
- WorkBuddy 的模型配置使用自身接入信息,避免读取 Codex 模型缓存。
- 图谱回访已浏览对象时收回重复路径,避免员工、资料来源和文档之间往返造成重复层级;切换对象后回到内容顶部,当前位置显示为文本。
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ Its organizing principle is simple: **the file tree is the org chart.** Roles li

For example, an open-source maintenance team can have a repository owner with three supporting roles: an issue researcher, a community operator, and a release engineer. The repository includes an [example workspace](examples/oss-maintainer) with this structure and role budgets.

The v0.4.0 source adds a persistent approval center, project execution with human acceptance, goal and progress workspaces, connected drive browsing, a workspace Markdown vault with manual Mem synchronization, and relationship/organization graph views. Conversations gain image/PDF attachments, a visible thought/tool activity trail, and a Gemini CLI host; Windows can download and install updates after explicit confirmation. See the [release notes](docs/releases/v0.4.0.md) for compatibility changes and [continuing work with an AI team](docs/thread-context-and-collaboration.md) for usage and limits. Older v0.3.0 installers do not include these changes.
The v0.5.0 source adds local WorkBuddy and Qwen Office client connections, improves Agent readiness checks, and refines employee settings, organization search, project layouts and rich conversation replies. See the [v0.5.0 notes](docs/releases/v0.5.0.md) for the local candidate and [continuing work with an AI team](docs/thread-context-and-collaboration.md) for usage and limits.

Workspace auto-open diagnostics remain best-effort: an unavailable stderr stream does not turn a diagnostic write into a failed startup. The current source restores an accessible workspace you previously opened and honors explicit workspace overrides. Otherwise, it starts without a workspace; it does not create or open a demo automatically. This empty first-launch behavior ships with v0.2.0.

## Download

RoleWeave is an **early preview**. This source targets **v0.4.0**. The versioned downloads below become available when the release is published; use the [latest published release](https://github.com/bytefolk/roleweave/releases/latest) until then.
RoleWeave is an **early preview**. This source targets **v0.5.0**, currently a local Windows candidate. The downloads below point to the published v0.4.0 installers; use the [latest published release](https://github.com/bytefolk/roleweave/releases/latest) for public packages.

| Platform | Download |
| --- | --- |
| macOS, Apple Silicon | [DMG installer](https://github.com/bytefolk/roleweave/releases/download/v0.4.0/roleweave-0.4.0-arm64.dmg) · [ZIP archive](https://github.com/bytefolk/roleweave/releases/download/v0.4.0/roleweave-0.4.0-arm64.zip) |
| Windows, x64 | [EXE installer](https://github.com/bytefolk/roleweave/releases/download/v0.4.0/roleweave-0.4.0-x64.exe) |

See the [v0.4.0 release notes](docs/releases/v0.4.0.md) for this candidate's changes and [all releases](https://github.com/bytefolk/roleweave/releases) for published packages. Intel Mac and Linux installers are not included in this release target.
See the [v0.5.0 notes](docs/releases/v0.5.0.md) for current source changes, the [v0.4.0 release notes](docs/releases/v0.4.0.md) for the published installers and [all releases](https://github.com/bytefolk/roleweave/releases) for published packages. Intel Mac and Linux installers are not included in this release target.

**Installation notes:** macOS packages are not Apple Developer ID-signed or notarized, and the Windows installer is not Authenticode-signed. Your operating system may show a security prompt on installation or first launch. The macOS update manifest has a separate cryptographic signature; this does not provide Apple code-signing trust. Windows updates use the HTTPS release feed and the installer's SHA-512 checksum, without publisher verification. Users of older Org Workbench development builds need to install RoleWeave manually once. Existing unsigned Windows builds that disable in-app installation also need one manual upgrade to a build containing this update change.

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@roleweave/desktop",
"version": "0.4.0",
"version": "0.5.0",
"description": "Electron shell for RoleWeave. Spawns the local control plane and renders the org tree via a whitelisted IPC bridge.",
"license": "Apache-2.0",
"private": true,
Expand Down
6 changes: 6 additions & 0 deletions apps/desktop/packaging/runtime-layout.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const DESKTOP_RUNTIME_FILES = [
"src/wsl-bootstrap.cjs",
"src/workbuddy-bridge.cjs",
"src/workbuddy-client.cjs",
"src/qwen-office-bridge.cjs",
"src/qwen-office-client.cjs",
"src/docs-ipc.cjs",
"src/drive-ipc.cjs",
"src/vault-ipc.cjs",
Expand Down Expand Up @@ -65,6 +67,7 @@ const SERVER_RUNTIME_FILES = [
"src/workbuddy-binary.js",
"src/workbuddy-runtime.js",
"src/workbuddy-local.js",
"src/qwen-office-local.js",
"src/local-provider-config.js",
"src/windows-launcher.js",
"dist/src/agent-binding.js",
Expand Down Expand Up @@ -114,6 +117,7 @@ const SERVER_RUNTIME_FILES = [
"dist/src/per-key-lock.js",
"dist/src/qoder-binary.js",
"dist/src/qoder-model-catalog.js",
"dist/src/qwen-office-local.js",
"dist/src/relationships/project.js",
"dist/src/routes/approvals.js",
"dist/src/routes/assets.js",
Expand Down Expand Up @@ -295,9 +299,11 @@ const APP_RESOURCE_REQUIRED_ENTRIES = [
"apps/server/src/workbuddy-binary.js",
"apps/server/src/workbuddy-runtime.js",
"apps/server/src/workbuddy-local.js",
"apps/server/src/qwen-office-local.js",
"apps/server/dist/src/workbuddy-binary.js",
"apps/server/dist/src/workbuddy-runtime.js",
"apps/server/dist/src/workbuddy-local.js",
"apps/server/dist/src/qwen-office-local.js",
"node_modules/@roleweave/shared/package.json",
"node_modules/@roleweave/shared/dist/index.js",
"node_modules/@roleweave/shared/dist/agent-binding.js",
Expand Down
15 changes: 14 additions & 1 deletion apps/desktop/renderer/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -451,13 +451,17 @@ function AppInner({
setEditPosition(null);
void window.owb.position(editTargetId).then((res) => {
if (!alive) return;
const body = res.body as { position?: PositionCardData; code?: string };
const body = res.body as { position?: PositionCardData; code?: string; agentEngine?: unknown };
if (res.status !== 200 || !body.position) {
setEditTargetId(undefined);
setOrgFeedback({ tone: "warn", text: t("org.stalePosition") });
return;
}
setEditPosition(normalizePositionForDisplay(body.position, locale));
if (isTurnEngine(body.agentEngine)) {
const targetEngine = body.agentEngine;
setPositionEngines(current => ({ ...current, [body.position!.id]: targetEngine }));
}
}).catch(() => {
if (alive) setEditTargetId(undefined);
});
Expand Down Expand Up @@ -1828,6 +1832,13 @@ function AppInner({
model: health?.hosts?.["workbuddy-local"]?.model,
connection: health?.hosts?.["workbuddy-local"]?.connection,
},
"qwen-office-local": {
configured: health?.hosts?.["qwen-office-local"]?.configured === true,
ready: health?.hosts?.["qwen-office-local"]?.ready === true,
reason: health?.hosts?.["qwen-office-local"]?.nextStep ?? t("office.connectionUnavailable"),
modelPinnable: false,
connection: health?.hosts?.["qwen-office-local"]?.connection,
},
gemini: {
configured: health?.hosts?.gemini?.configured === true,
ready: health?.hosts?.gemini?.ready === true,
Expand Down Expand Up @@ -2160,6 +2171,7 @@ function AppInner({
<EditEmployeeDrawer
open={editTargetId !== undefined && editPosition !== null}
position={editPosition}
engine={editPosition ? engineForPosition(editPosition.id) : undefined}
busy={orgBusy}
onClose={() => setEditTargetId(undefined)}
onSave={(patch) => saveEmployeeProfile(patch, editTargetId)}
Expand Down Expand Up @@ -2398,6 +2410,7 @@ function AppInner({
<div className="owb-position-column">
<PositionCard
position={card.data}
nativeToolOwner={card.data && engineForPosition(card.data.id) === "qwen-office-local" ? engineLabel("qwen-office-local") : undefined}
loading={card.loading}
notFound={card.notFound}
running={selectedId !== null && runningPositionIds.has(selectedId)}
Expand Down
20 changes: 13 additions & 7 deletions apps/desktop/renderer/src/org/EditEmployeeDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { useT } from "@roleweave/ui";
import type { HirePermissions, PositionProfilePatch } from "@roleweave/shared";
import type { PositionCardData } from "@roleweave/ui";
import { CapabilityPicker, PermissionPolicyEditor } from "./PermissionsEditor";
import type { TurnEngine } from "../turns/types";
import "./edit-employee.css";

const MAX_NAME_BYTES = 128;
Expand Down Expand Up @@ -49,18 +50,21 @@ function permissionFingerprint(policy: HirePermissions): string {
export function EditEmployeeDrawer({
open,
position,
engine,
busy,
onClose,
onSave,
}: {
open: boolean;
/** The selected position record; null while the card is still loading. */
position: PositionCardData | null;
engine?: TurnEngine;
busy: boolean;
onClose: () => void;
onSave: (patch: PositionProfilePatch) => Promise<{ ok: true; name: string } | { ok: false; code: string }>;
}) {
const t = useT();
const clientManaged = engine === "qwen-office-local";
const [name, setName] = useState("");
const [mode, setMode] = useState<PositionCardData["mode"]>("read_only");
const [permissions, setPermissions] = useState<HirePermissions>({ tools: [], rules: [] });
Expand Down Expand Up @@ -90,8 +94,8 @@ export function EditEmployeeDrawer({
const permissionsChanged = initial !== null && permissionFingerprint(permissions) !== permissionFingerprint(initial);
const changed = position !== null && (
trimmedName !== position.name
|| mode !== position.mode
|| permissionsChanged
|| (!clientManaged && mode !== position.mode)
|| (!clientManaged && permissionsChanged)
);
const canSave = position !== null && nameValid && changed && !saving && !busy;

Expand All @@ -101,8 +105,8 @@ export function EditEmployeeDrawer({
// permission grant this drawer did not intend to touch stays byte-identical.
const patch: PositionProfilePatch = {};
if (trimmedName !== position.name) patch.name = trimmedName;
if (mode !== position.mode) patch.mode = mode;
if (permissionsChanged) patch.permissions = permissions;
if (!clientManaged && mode !== position.mode) patch.mode = mode;
if (!clientManaged && permissionsChanged) patch.permissions = permissions;
setSaving(true);
setError(null);
const outcome = await onSave(patch);
Expand All @@ -114,7 +118,7 @@ export function EditEmployeeDrawer({
}
const copyKey = FAILURE_COPY_KEYS[outcome.code];
setError(copyKey !== undefined ? t(copyKey) : t("profile.failUnknown", { code: outcome.code }));
}, [canSave, messageApi, mode, onClose, onSave, permissions, permissionsChanged, position, t, trimmedName]);
}, [canSave, clientManaged, messageApi, mode, onClose, onSave, permissions, permissionsChanged, position, t, trimmedName]);

return (
<Drawer
Expand Down Expand Up @@ -151,7 +155,7 @@ export function EditEmployeeDrawer({
/>
</div>
{nameValid ? null : <p id={`${permissionsPanelId}-name-error`} className="owb-profile-error" role="alert">{t(trimmedName.length === 0 ? "profile.nameRequired" : "profile.nameTooLong")}</p>}
<div className="owb-profile-setting">
{!clientManaged ? <div className="owb-profile-setting">
<label htmlFor={`${permissionsPanelId}-mode`}>{t("profile.mode")}</label>
<Select
id={`${permissionsPanelId}-mode`}
Expand All @@ -163,8 +167,9 @@ export function EditEmployeeDrawer({
{ value: "approval_required", label: t("profile.modeApproval") },
]}
/>
</div>
</div> : null}
</section>
{clientManaged ? <p className="owb-profile-empty">{t("office.clientManaged")} {t("office.clientSettings")} {t("office.accountManaged")}</p> : <>
<CapabilityPicker variant="compact" permissions={permissions} onChange={setPermissions} />
<section className="owb-profile-advanced">
<button
Expand All @@ -184,6 +189,7 @@ export function EditEmployeeDrawer({
</div>
) : null}
</section>
</>}
</fieldset>
)}
</div>
Expand Down
Loading
Loading