diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9c6f609c..5d8e567b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,8 @@
### Fixed
+- #297:创建数字员工默认先展示 Agent 与基础信息;Agent 草案、头像、权限、能力、记忆、运行模式和预算改为按需展开,保留安全默认值、原有字段校验与 hire 请求 payload。
+
- 组织树员工行的右键菜单与省略号菜单首位新增「编辑」入口:点击后打开 #292 的员工编辑抽屉,并按被右键/省略号唤起的那一行现取该员工档案回填表单,保存也对该行提交,不再绑定或抢占主面板当前选中的对话;岗位卡片头部的「编辑」按钮改用同一入口。企业根行菜单不变(仍为项目设置等)。附渲染层测试:行菜单两种触发均出编辑项、企业行菜单不出,以及 App 级端到端断言右键某行后抽屉预填该行档案、改名保存以正确 id 走档案更新桥且选中保持不变。
- #301:创建数字员工抽屉移除左上角无响应的标题关闭按钮(×):创建执行中取消本就被设计拒绝(#43),而该按钮在提交、审批与成功三个阶段静默吞掉点击,与同屏置灰的「执行中不可取消」提示相矛盾。按报告要求直接删除;可编辑面板保留底部「取消」,遮罩与 Esc 行为不变,员工编辑抽屉的关闭按钮不受影响。
diff --git a/apps/desktop/renderer/src/app.css b/apps/desktop/renderer/src/app.css
index b7c3291d..fffad33c 100644
--- a/apps/desktop/renderer/src/app.css
+++ b/apps/desktop/renderer/src/app.css
@@ -2014,15 +2014,31 @@
}
-/* #57 agent 引擎品牌 icon(Qoder 应用标 / Claude starburst):14px 档、圆角 3px,
- 与引擎文字标签内联对齐。 */
+/* #57 agent 引擎品牌 icon:统一 18px 布局盒子;不同素材的画布留白不一,
+ 用轻微 optical scale 让实际可见的品牌面积保持同一档位。 */
.owb-engine-icon {
- width: 14px;
- height: 14px;
- border-radius: 3px;
- margin-right: 4px;
- vertical-align: -2px;
+ width: 18px;
+ height: 18px;
+ border-radius: 5px;
+ margin-right: 5px;
+ vertical-align: -4px;
flex: none;
+ transform: scale(var(--owb-engine-icon-optical-scale, 1));
+}
+
+.owb-engine-icon--qoder {
+ --owb-engine-icon-optical-scale: 1.2;
+}
+
+.owb-engine-icon--workbuddy {
+ --owb-engine-icon-optical-scale: .92;
+}
+
+/* design-system 的树元数据默认把所有图像压到 12px;品牌标识需要与
+ 岗位头像同一视觉档位,避免在深色树中显得像一枚无关紧要的点。 */
+.ui-org-tree__metadata .owb-engine-icon {
+ width: 18px;
+ height: 18px;
}
/* #35 S3 文档模块面:岗位选择器与 DocsPanel 纵向排布,间距走档位变量。 */
@@ -2933,9 +2949,92 @@
overflow-wrap: break-word;
}
-.owb-hire-agent-picker .ant-select {
+.owb-hire-choice-select {
+ position: relative;
min-width: 0;
+}
+
+.owb-hire-choice-select__trigger {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ width: 100%;
+ min-width: 0;
+ min-height: 36px;
+ padding: 0 10px;
+ border: 1px solid var(--ui-border);
+ border-radius: 8px;
+ background: var(--ui-surface);
+ color: var(--ui-foreground);
+ font: inherit;
+ text-align: left;
+ cursor: pointer;
+}
+
+.owb-hire-choice-select__trigger:hover,
+.owb-hire-choice-select__trigger[aria-expanded="true"] {
+ border-color: color-mix(in srgb, var(--ui-primary) 62%, var(--ui-border));
+}
+
+.owb-hire-choice-select__trigger:focus-visible {
+ outline: 2px solid var(--ui-focus);
+ outline-offset: 2px;
+}
+
+.owb-hire-choice-select__trigger > span {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.owb-hire-choice-select__trigger > svg {
+ flex: 0 0 auto;
+ color: var(--ui-foreground-muted);
+ transition: transform 120ms ease;
+}
+
+.owb-hire-choice-select__trigger[aria-expanded="true"] > svg {
+ transform: rotate(180deg);
+}
+
+.owb-hire-choice-select__menu {
+ position: absolute;
+ z-index: 1100;
+ top: calc(100% + 4px);
+ right: 0;
+ left: 0;
+ display: grid;
+ gap: 2px;
+ min-width: 100%;
+ padding: 4px;
+ border: 1px solid var(--ui-border);
+ border-radius: 8px;
+ background: var(--ui-surface-raised);
+ box-shadow: var(--ui-shadow-md);
+}
+
+.owb-hire-choice-select__menu > button {
width: 100%;
+ padding: 8px 9px;
+ border: 0;
+ border-radius: 6px;
+ background: transparent;
+ color: var(--ui-foreground);
+ font: inherit;
+ text-align: left;
+ cursor: pointer;
+}
+
+.owb-hire-choice-select__menu > button:hover,
+.owb-hire-choice-select__menu > button.is-selected {
+ background: color-mix(in srgb, var(--ui-primary) 14%, var(--ui-surface));
+ color: var(--ui-primary);
+}
+
+.owb-hire-choice-select__menu > button:focus-visible {
+ outline: 2px solid var(--ui-focus);
+ outline-offset: -2px;
}
.owb-hire-agent-binding {
@@ -2964,6 +3063,31 @@
background: var(--ui-surface-inset);
}
+.owb-hire-assist {
+ overflow: hidden;
+ border: 1px solid var(--ui-border);
+ border-radius: 10px;
+ background: color-mix(in srgb, var(--ui-surface-inset) 52%, transparent);
+}
+
+.owb-hire-assist > summary {
+ display: flex;
+ align-items: center;
+ gap: 7px;
+ min-height: 42px;
+ padding: 0 13px;
+ color: var(--ui-foreground);
+ font-size: 12px;
+ font-weight: 650;
+ cursor: pointer;
+ list-style: none;
+}
+
+.owb-hire-assist > summary::-webkit-details-marker { display: none; }
+.owb-hire-assist > summary > svg { color: var(--ui-primary); }
+.owb-hire-assist > summary > span { margin-left: auto; color: var(--ui-foreground-muted); font-size: 10px; font-weight: 400; }
+.owb-hire-assist > .owb-hire-conversation { border: 0; border-top: 1px solid var(--ui-border); border-radius: 0; }
+
.owb-hire-conversation__meta,
.owb-hire-prompt__footer,
.owb-hire-draft-card__heading,
@@ -3115,6 +3239,13 @@
font-size: 10px;
}
+.owb-hire-basic-description {
+ margin: 5px 0 0;
+ color: var(--ui-foreground-muted);
+ font-size: 11px;
+ line-height: 1.45;
+}
+
.owb-hire-basic-grid,
.owb-hire-two-col {
display: grid;
diff --git a/apps/desktop/renderer/src/assets/workbuddy.png b/apps/desktop/renderer/src/assets/workbuddy.png
deleted file mode 100644
index 6b23faae..00000000
Binary files a/apps/desktop/renderer/src/assets/workbuddy.png and /dev/null differ
diff --git a/apps/desktop/renderer/src/assets/workbuddy.svg b/apps/desktop/renderer/src/assets/workbuddy.svg
new file mode 100644
index 00000000..2fb0e5a9
--- /dev/null
+++ b/apps/desktop/renderer/src/assets/workbuddy.svg
@@ -0,0 +1,29 @@
+
diff --git a/apps/desktop/renderer/src/org/HireDrawer.tsx b/apps/desktop/renderer/src/org/HireDrawer.tsx
index bb78d125..a40db3b2 100644
--- a/apps/desktop/renderer/src/org/HireDrawer.tsx
+++ b/apps/desktop/renderer/src/org/HireDrawer.tsx
@@ -8,7 +8,7 @@
* POST /hire gate.
*/
import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
-import { Button as AntButton, Checkbox, Drawer, Input, Select, Steps, message } from "antd";
+import { Button as AntButton, Checkbox, Drawer, Input, Steps, message } from "antd";
import { CheckCircle2, ChevronDown, LoaderCircle, RotateCcw, Sparkles, XCircle } from "lucide-react";
import { Input as OwbInput } from "@fullstack-ai-infra/ui";
import { useT, type OwbT } from "@roleweave/ui";
@@ -97,6 +97,46 @@ function defaultPrompt(t: OwbT): string {
return t("hire.agentPromptTemplate");
}
+function HireChoiceSelect({ ariaLabel, value, options, onChange, t }: {
+ ariaLabel: string;
+ value: string;
+ options: Array<{ value: string; label: string }>;
+ onChange: (value: string) => void;
+ t: OwbT;
+}) {
+ const [open, setOpen] = useState(false);
+ const selected = options.find((option) => option.value === value);
+ const selectedLabel = selected?.label ?? value;
+ return (
+
+
+ {open ?
+ {options.map((option) => )}
+
: null}
+
+ );
+}
+
export function HireDrawer({ open, workspacePath, positions, presetReportTo, engine, conversationEngine, engineAvailability, conversationHostId, conversationHostName, budgetPoolTokens = PLATFORM_BUDGET_POOL, budgetAllocatedTokens = 0, onClose, onHired }: HireDrawerProps) {
const t = useT();
const [flow, dispatch] = useReducer(reduceHireFlow, undefined, () => initialHireFlow());
@@ -116,6 +156,7 @@ export function HireDrawer({ open, workspacePath, positions, presetReportTo, eng
const [messages, setMessages] = useState([]);
const [conversationBusy, setConversationBusy] = useState(false);
const [conversationError, setConversationError] = useState(null);
+ const [designAssistOpen, setDesignAssistOpen] = useState(false);
const [advancedOpen, setAdvancedOpen] = useState(false);
const [permissions, setPermissions] = useState({ tools: ["Read", "Grep", "Glob"], rules: [{ scope: "position", resource: "./knowledge/**", actions: ["read"] }], skills: [], mcpServers: [] });
const [memorySources, setMemorySources] = useState([{ kind: "position_docs", locator: "./knowledge/**" }]);
@@ -147,7 +188,7 @@ export function HireDrawer({ open, workspacePath, positions, presetReportTo, eng
setName(""); setDescription(""); setAvatar(undefined); setAvatarGenerating(false); setAvatarError(null); setReportTo(presetReportTo);
setMode("approval_required"); setTaskTokens("20000"); setTaskIterations("8"); setDayTokens("200000"); setDayIterations("64");
setAgentHost(defaultAgentHost(engineAvailability));
- setPrompt(defaultPrompt(t)); setMessages([]); setConversationBusy(false); setConversationError(null); setAdvancedOpen(false);
+ setPrompt(defaultPrompt(t)); setMessages([]); setConversationBusy(false); setConversationError(null); setDesignAssistOpen(false); setAdvancedOpen(false);
setPermissions({ tools: ["Read", "Grep", "Glob"], rules: [{ scope: "position", resource: "./knowledge/**", actions: ["read"] }], skills: [], mcpServers: [] });
setMemorySources([{ kind: "position_docs", locator: "./knowledge/**" }]); setPhaseCopy(t("hire.phaseSubmit"));
}, [clearTimers, engineAvailability, open, presetReportTo, t]);
@@ -298,55 +339,59 @@ export function HireDrawer({ open, workspacePath, positions, presetReportTo, eng
{t("hire.agentTitle")}
{t("hire.agentDescription")}
-