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
138 changes: 66 additions & 72 deletions Resources/Localization/en.lproj/Localizable.strings

Large diffs are not rendered by default.

36 changes: 15 additions & 21 deletions Resources/Localization/zh-Hans.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"Previous match" = "上一个匹配";
"Back" = "返回";
"Forward" = "前进";
"Next task needing attention" = "下一个待处理任务";
"Drafts could not be saved" = "草稿未能保存";
"Keep Perch open" = "留在 Perch";
"Quit anyway" = "仍然退出";
Expand All @@ -26,7 +25,6 @@
"Completed responses, requests for input, and failures. Click a notification to open the task." = "已完成的回复、待处理的输入请求和失败。点击通知可打开对应任务。";

"Stop task" = "停止任务";
"搜索任务" = "搜索任务";
"新建会话" = "新建会话";
"工作台" = "工作台";
"待处理" = "待处理";
Expand All @@ -42,7 +40,6 @@
"全部会话" = "全部会话";
"筛选最近会话" = "筛选最近会话";
"筛选最近会话:%@" = "筛选最近会话:%@";
"新任务会出现在这里" = "新任务会出现在这里";
"没有符合筛选的会话" = "没有符合筛选的会话";
"没有找到会话" = "没有找到会话";
"标题、Agent、环境或目录" = "标题、Agent、环境或目录";
Expand Down Expand Up @@ -70,7 +67,6 @@
"Kimi 归档与服务端同步;终端归档只整理本机列表,不结束远端进程。" = "Kimi 归档与服务端同步;终端归档只整理本机列表,不结束远端进程。";
"没有归档会话" = "没有归档会话";
"环境与 Agent" = "环境与 Agent";
"添加 SSH 机器" = "添加 SSH 机器";
"本机 Agent…" = "本机 Agent…";
"重新连接 Kimi" = "重新连接 Kimi";
"原生对话" = "原生对话";
Expand Down Expand Up @@ -142,7 +138,6 @@
"浅色" = "浅色";
"深色" = "深色";
"Agent 与执行环境" = "Agent 与执行环境";
"添加 SSH 环境…" = "添加 SSH 环境…";
"远程连接沿用本机 SSH 配置。连接、重连与移除机器都在侧边栏的环境入口。" = "远程连接沿用本机 SSH 配置。连接、重连与移除机器都在侧边栏的环境入口。";
"界面" = "界面";
"侧边栏可拖动调整宽度,系统会记住位置。透明度与动态效果遵循 macOS 辅助功能设置。" = "侧边栏可拖动调整宽度,系统会记住位置。透明度与动态效果遵循 macOS 辅助功能设置。";
Expand Down Expand Up @@ -213,8 +208,6 @@
"保存任务组" = "保存任务组";
"切换侧栏" = "切换侧栏";
"显示或隐藏侧栏" = "显示或隐藏侧栏";
"新建任务" = "新建任务";
"新建任务 · ⌘N" = "新建任务 · ⌘N";
"当前会话" = "当前会话";
"会话操作" = "会话操作";
"正在恢复会话…" = "正在恢复会话…";
Expand All @@ -225,7 +218,6 @@
"断开本地连接" = "断开本地连接";
"连接终端" = "连接终端";
"任务组…" = "任务组…";
"原生对话…" = "原生对话…";
"新建" = "新建";
"远端终端…" = "远端终端…";

Expand Down Expand Up @@ -366,12 +358,10 @@
"断开或离开前正在运行的任务,重新连接后的状态:" = "断开或离开前正在运行的任务,重新连接后的状态:";
"连接后才能确认这些会话的当前状态。" = "连接后才能确认这些会话的当前状态。";
"远程 Agent 沿用你的 SSH 配置。本机环境目前仅支持安装检测。" = "远程 Agent 沿用你的 SSH 配置。本机环境目前仅支持安装检测。";
"连接远程机器…" = "连接远程机器…";
"检测本机 Agent…" = "检测本机 Agent…";
"连接后查看最新进展" = "连接后查看最新进展";
"先连接一台运行 Agent 的机器" = "先连接一台运行 Agent 的机器";
"选择 Agent 和工作目录后开始" = "选择 Agent 和工作目录后开始";
"开始第一段会话" = "开始第一段会话";

"%lld 个关联 · %lld 个未归档 · %lld 个已归档" = "%lld 个关联 · %lld 个未归档 · %lld 个已归档";
"上次会话尚未连接" = "上次会话尚未连接";
Expand All @@ -388,7 +378,6 @@

"%lld 个未归档 · %lld 个已归档 · %lld 个尚未同步" = "%lld 个未归档 · %lld 个已归档 · %lld 个尚未同步";
"Retry" = "重试";
"Unable to load this conversation." = "无法读取此会话。";
"Choose Kimi or remove the attachments to start this task." = "请选择 Kimi 或移除附件,再开始任务。";

/* Composer commands */
Expand All @@ -410,11 +399,9 @@
"Goal resume requested." = "已请求继续目标。";
"Plan mode enabled." = "计划模式已开启。";
"Plan mode disabled." = "计划模式已关闭。";
"This agent does not expose /goal to Perch. Use its terminal or a Kimi conversation." = "此 Agent 尚未向 Perch 开放 /goal,请在其终端或 Kimi 会话中使用。";
"↑↓ 选择 · Tab 补全 · Return 执行完整命令 · Esc 关闭" = "↑↓ 选择 · Tab 补全 · Return 执行完整命令 · Esc 关闭";
"Run command" = "执行命令";
"Goal created. First message accepted." = "目标已创建,首条消息已接收。";
"Goal created; the first message is unconfirmed. Check the conversation before sending again." = "目标已创建,但首条消息尚未确认。请检查会话后再发送。";
"Choose a model before starting a goal." = "开始目标前请先选择模型。";
"Continue this task, or type / for commands…" = "继续此任务,或输入 / 使用命令…";

Expand Down Expand Up @@ -469,8 +456,6 @@
"安装或更新 Perch 桥接组件后重新检查。空闲的旧服务会自动安全重启;有任务运行时会等待任务结束。" = "安装或更新 Perch 桥接组件后重新检查。空闲的旧服务会自动安全重启;有任务运行时会等待任务结束。";
"安装说明" = "安装说明";
"已检测到远端凭据;模型目录在首次 ACP 会话握手时读取,鉴权在发送时验证。" = "已检测到远端凭据;模型目录在首次 ACP 会话握手时读取,鉴权在发送时验证。";
"开始任务" = "开始任务";
"开始首个任务" = "开始首个任务";
"打开远端终端" = "打开远端终端";
"服务只通过 SSH 访问远端 127.0.0.1。填写文件路径即可,令牌不保存在 Mac 配置中。" = "服务只通过 SSH 访问远端 127.0.0.1。填写文件路径即可,令牌不保存在 Mac 配置中。";
"服务连接" = "服务连接";
Expand Down Expand Up @@ -522,7 +507,6 @@
"继续后即可填写首个任务;机器、Agent、目录与模型会自动带入。" = "继续后即可填写首个任务;机器、Agent、目录与模型会自动带入。";
"缺少 Qoder SDK 或 Node.js。请安装桥接组件和 Node.js 后重试。" = "缺少 Qoder SDK 或 Node.js。请安装桥接组件和 Node.js 后重试。";
"缺少 Claude Code SDK 或 Node.js。请安装桥接组件和 Node.js 后重试。" = "缺少 Claude Code SDK 或 Node.js。请安装桥接组件和 Node.js 后重试。";
"要连接另一台机器,请添加新环境。" = "要连接另一台机器,请添加新环境。";
"请在远端安装并启动 Herdr,然后重新检查。" = "请在远端安装并启动 Herdr,然后重新检查。";
"请输入远端已存在且当前用户可访问的目录。" = "请输入远端已存在且当前用户可访问的目录。";
"请输入远端项目的绝对路径。" = "请输入远端项目的绝对路径。";
Expand Down Expand Up @@ -817,7 +801,6 @@

"已发现 %lld 个本机 Agent" = "已发现 %lld 个本机 Agent";

"已安装,尚未接入本机对话" = "已安装,尚未接入本机对话";

"未找到可执行文件" = "未找到可执行文件";

Expand All @@ -839,7 +822,6 @@

"连接会复用或启动本机服务;关闭 Perch 不会停止正在执行的任务。" = "连接会复用或启动本机服务;关闭 Perch 不会停止正在执行的任务。";

"连接并新建任务" = "连接并新建任务";

"连接本机已安装的 Agent,在你选择的 Mac 项目目录执行。" = "连接本机已安装的 Agent,在你选择的 Mac 项目目录执行。";

Expand Down Expand Up @@ -1098,7 +1080,6 @@
"全部处理完了" = "全部处理完了";
"没有等待确认、回答或处理的事项;查看结果请到工作台。" = "没有等待确认、回答或处理的事项;查看结果请到工作台。";
"共 %lld 项 · 确认、回答或处理错误;查看结果请到工作台。" = "共 %lld 项 · 确认、回答或处理错误;查看结果请到工作台。";
"打开会话" = "打开会话";
"粘贴内容已丢失,请重新粘贴后再发送。" = "粘贴内容已丢失,请重新粘贴后再发送。";
"附件需要在线上传,连接恢复后再发送。" = "附件需要在线上传,连接恢复后再发送。";
"命令需要连接后执行,请等待恢复在线。" = "命令需要连接后执行,请等待恢复在线。";
Expand Down Expand Up @@ -1158,7 +1139,6 @@

"置顶常用会话,随时继续" = "置顶常用会话,随时继续";

"切换会话视图" = "切换会话视图";

"搜索会话" = "搜索会话";

Expand Down Expand Up @@ -1568,7 +1548,6 @@
"此终端已不在远端列表中" = "此终端已不在远端列表中";
"本地工作台读取失败,原文件已保留:%@" = "本地工作台读取失败,原文件已保留:%@";
"工作台保存失败:%@" = "工作台保存失败:%@";
"The task environment is unavailable" = "任务环境不可用";
"Menlo 14 pt\n窗口 backingScaleFactor: %@\n视图逻辑尺寸: %@ pt\n视图 backing 尺寸: %@ px\nGhostty surface: %@ px\n终端网格: %@\n像素尺寸一致: %@" = "Menlo 14 pt\n窗口 backingScaleFactor: %@\n视图逻辑尺寸: %@ pt\n视图 backing 尺寸: %@ px\nGhostty surface: %@ px\n终端网格: %@\n像素尺寸一致: %@";
"是" = "是";
"否" = "否";
Expand Down Expand Up @@ -1605,3 +1584,18 @@
"回车排到下一轮发送" = "回车排到下一轮发送";
"回车执行命令" = "回车执行命令";
"成果操作" = "成果操作";

/* Sidebar and workbench consistency: canonical session, machine and task group terms (2026-10-16) */
"下一个待处理会话" = "下一个待处理会话";
"无法读取此会话。" = "无法读取此会话。";
"此 Agent 尚未向 Perch 开放 /goal,请在其终端或 Kimi 会话中使用。" = "此 Agent 尚未向 Perch 开放 /goal,请在其终端或 Kimi 会话中使用。";
"目标已创建,但首条消息尚未确认。请检查会话后再发送。" = "目标已创建,但首条消息尚未确认。请检查会话后再发送。";
"项目视图选项" = "项目视图选项";
"新会话会出现在这里" = "新会话会出现在这里";
"新建会话 · ⌘N" = "新建会话 · ⌘N";
"会话…" = "会话…";
"开始首个会话" = "开始首个会话";
"开始会话" = "开始会话";
"连接并新建会话" = "连接并新建会话";
"已安装,尚未接入本机会话" = "已安装,尚未接入本机会话";
"要连接另一台机器,请添加新机器。" = "要连接另一台机器,请添加新机器。";
11 changes: 7 additions & 4 deletions Sources/AgentWorkbench/CommandPalette.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ struct CommandPalette: View {
Text("↑↓ 选择 · Tab 补全 · Return 执行完整命令 · Esc 关闭")
.font(.system(size: 10)).foregroundStyle(.secondary).padding(10)
}.frame(maxWidth: .infinity, alignment: .leading)
.background(Color(nsColor: .controlBackgroundColor), in: RoundedRectangle(cornerRadius: 10))
.overlay(RoundedRectangle(cornerRadius: 10).strokeBorder(Color.primary.opacity(0.08)))
.background(Color(nsColor: .controlBackgroundColor), in: RoundedRectangle(cornerRadius: WorkbenchTheme.Radius.card))
.overlay(RoundedRectangle(cornerRadius: WorkbenchTheme.Radius.card)
.strokeBorder(Color.primary.opacity(WorkbenchTheme.Stroke.hairline)))
.accessibilityLabel("命令建议,\(completion.matches.count) 项")
}
}
Expand All @@ -58,8 +59,10 @@ private struct CommandPaletteRow: View {
Text("\(command.children.count) 个子命令").font(.system(size: 10)).foregroundStyle(.tertiary)
}
}.padding(.horizontal, 10).padding(.vertical, 7).contentShape(Rectangle())
.background(selected || hovered ? Color.primary.opacity(0.06) : .clear,
in: RoundedRectangle(cornerRadius: 6))
// The keyboard row outranks the pointer's, so hover never reads as a second selection.
.background(Color.primary.opacity(selected ? WorkbenchTheme.Fill.selected
: hovered ? WorkbenchTheme.Fill.hover : 0),
in: RoundedRectangle(cornerRadius: WorkbenchTheme.Radius.row))
}.buttonStyle(.plain).onHover { hovered = $0 }
.accessibilityAddTraits(selected ? .isSelected : [])
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/AgentWorkbench/ConversationActivityBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,8 @@ private struct KimiTaskRow: View {
}
}
}.frame(maxWidth: .infinity, alignment: .leading).padding(10)
.background(Color.primary.opacity(0.035), in: RoundedRectangle(cornerRadius: 6))
.background(Color.primary.opacity(WorkbenchTheme.Fill.surface),
in: RoundedRectangle(cornerRadius: WorkbenchTheme.Radius.card))
.padding(.leading, 10).padding(.top, 5)
}

Expand Down
3 changes: 2 additions & 1 deletion Sources/AgentWorkbench/ConversationFindBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ private struct FindOptionToggle: View {
Button { on.toggle(); onChange() } label: {
Text(label).font(.system(size: 11, weight: .medium, design: .monospaced))
.frame(width: 22, height: 20)
.background(on ? Color.primary.opacity(0.12) : Color.clear, in: RoundedRectangle(cornerRadius: 5))
.background(on ? Color.primary.opacity(WorkbenchTheme.Fill.selected) : Color.clear,
in: RoundedRectangle(cornerRadius: WorkbenchTheme.Radius.chip))
.contentShape(Rectangle())
}.buttonStyle(.plain).foregroundStyle(on ? .primary : .secondary).help(help)
.accessibilityLabel(help)
Expand Down
21 changes: 11 additions & 10 deletions Sources/AgentWorkbench/ConversationScrollControls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ struct ReturnToLatestButton: View {
.padding(.horizontal, hasNewReply ? 12 : 0)
.frame(width: hasNewReply ? nil : 32, height: 32)
.workbenchFloatingSurface()
.overlay(Capsule().fill(Color.primary.opacity(hovered && isVisible ? 0.05 : 0)))
.overlay(Capsule().strokeBorder(.primary.opacity(0.08)))
.overlay(Capsule().fill(Color.primary.opacity(hovered && isVisible ? WorkbenchTheme.Fill.hover : 0)))
.overlay(Capsule().strokeBorder(.primary.opacity(WorkbenchTheme.Stroke.hairline)))
.shadow(color: .black.opacity(0.08), radius: 5, y: 2)
.contentShape(Capsule())
}.buttonStyle(.plain).accessibilityIdentifier("return-to-latest")
Expand Down Expand Up @@ -306,7 +306,7 @@ private struct ConversationBookmarksMenu: View {
Image(systemName: "bookmark.fill").font(.system(size: 12))
.frame(width: 30, height: 30)
.workbenchFloatingSurface()
.overlay(RoundedRectangle(cornerRadius: 15).strokeBorder(.primary.opacity(0.08)))
.overlay(RoundedRectangle(cornerRadius: 15).strokeBorder(.primary.opacity(WorkbenchTheme.Stroke.hairline)))
.shadow(color: .black.opacity(0.08), radius: 5, y: 2)
}.menuStyle(.borderlessButton).menuIndicator(.hidden).fixedSize()
.help("已收藏的轮次").accessibilityLabel("已收藏的轮次")
Expand Down Expand Up @@ -376,8 +376,9 @@ private struct ConversationTurnRail: View {
}
.transaction { $0.animation = nil } // Neighbor text changes without crossfading.
.padding(12).frame(width: min(340, availableWidth), height: 136, alignment: .topLeading)
.background(Color(nsColor: .windowBackgroundColor), in: RoundedRectangle(cornerRadius: 10))
.overlay(RoundedRectangle(cornerRadius: 10).strokeBorder(.primary.opacity(0.06)))
.background(Color(nsColor: .windowBackgroundColor), in: RoundedRectangle(cornerRadius: WorkbenchTheme.Radius.card))
.overlay(RoundedRectangle(cornerRadius: WorkbenchTheme.Radius.card)
.strokeBorder(.primary.opacity(WorkbenchTheme.Stroke.hairline)))
.shadow(color: .black.opacity(0.07), radius: 8, y: 3)
.offset(x: railWidth, y: min(max(0, previewY - 28), max(0, height - 136)))
.allowsHitTesting(false).accessibilityHidden(true)
Expand Down Expand Up @@ -423,20 +424,20 @@ private struct ConversationTurnMarks: View {
}
if let hovered, hovered != selected {
let y = layout.y(for: hovered)
context.fill(Path(roundedRect: CGRect(x: 4, y: y - 6, width: 24, height: 14), cornerRadius: 5),
with: .color(.primary.opacity(0.045)))
context.fill(Path(roundedRect: CGRect(x: 4, y: y - 6, width: 24, height: 14), cornerRadius: WorkbenchTheme.Radius.chip),
with: .color(.primary.opacity(WorkbenchTheme.Fill.hover)))
tick(y: y, width: 14, opacity: 0.55)
}
tick(y: layout.y(for: current), width: 20, opacity: 0.85)
if keyboardFocused {
let y = layout.y(for: selected ?? current)
context.stroke(Path(roundedRect: CGRect(x: 3, y: y - 7, width: 26, height: 16), cornerRadius: 5),
context.stroke(Path(roundedRect: CGRect(x: 3, y: y - 7, width: 26, height: 16), cornerRadius: WorkbenchTheme.Radius.chip),
with: .color(.primary.opacity(0.18)), lineWidth: 1)
}
if let selected {
let y = layout.y(for: selected)
context.fill(Path(roundedRect: CGRect(x: 3, y: y - 7, width: 26, height: 16), cornerRadius: 5),
with: .color(.primary.opacity(0.09)))
context.fill(Path(roundedRect: CGRect(x: 3, y: y - 7, width: 26, height: 16), cornerRadius: WorkbenchTheme.Radius.chip),
with: .color(.primary.opacity(WorkbenchTheme.Fill.selected)))
tick(y: y, width: 20, opacity: 1, height: 2.5)
}
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/AgentWorkbench/HostIdentityIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ struct HostIdentityIcon: View {
return Image(nsImage: image).renderingMode(.original)
}

/// This Mac, or a remote machine. `globe` stays the language symbol in settings.
private static func symbol(for hostID: UUID?) -> String {
hostID == ExecutionEnvironment.localHostID ? "desktopcomputer" : "globe"
hostID == ExecutionEnvironment.localHostID ? "desktopcomputer" : "server.rack"
}

private static func color(for hostID: UUID?) -> NSColor {
Expand Down
2 changes: 1 addition & 1 deletion Sources/AgentWorkbench/KimiConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ final class KimiConnection {
}
} catch {
let message = L("发送未确认,草稿已保留。请检查会话后再发送。\n\(error.localizedDescription)")
if startingGoal { commandFeedback[id] = L("Goal created; the first message is unconfirmed. Check the conversation before sending again.") }
if startingGoal { commandFeedback[id] = L("目标已创建,但首条消息尚未确认。请检查会话后再发送。") }
updatePrompt(promptID, for: id, status: "unknown", error: message)
if selectedId == id { actionError = message }
}
Expand Down
Loading
Loading