feat(webui): add project workspaces and access controls (#4007)

* feat(webui): add project workspaces and access controls

* feat(webui): add project workspaces and access controls

* refactor(tools): centralize workspace access resolution

* refactor(webui): remove unused workspace host state

* fix(webui): hide estimated file edit label

* fix(webui): clarify file edit deletion feedback

* fix(webui): label deleted file activity

* fix(webui): flatten file edit activity rows

* fix(core): remove path-only patch deletion

* fix(core): keep apply patch non-destructive

* refactor(webui): trim workspace host plumbing

* fix(tools): register exec with tools config
This commit is contained in:
Xubin Ren
2026-05-29 03:42:53 +08:00
committed by GitHub
parent 84428136e6
commit 3a420136bb
111 changed files with 9972 additions and 1822 deletions
+90 -40
View File
@@ -25,7 +25,9 @@
"section": "系统",
"restartHint": "重启 nanobot 以应用运行时更改。",
"restart": "重启 nanobot",
"restarting": "正在重启..."
"restarting": "正在重启...",
"restartEngine": "重启引擎",
"restartingEngine": "正在重启引擎..."
},
"restart": {
"completed": "重启已完成,用时 {{seconds}} 秒。"
@@ -40,25 +42,13 @@
},
"sidebar": {
"navigation": "侧边栏导航",
"globalActions": "全局操作",
"collapse": "收起侧边栏",
"toggleTheme": "切换主题",
"home": "首页",
"newChat": "新建对话",
"searchAria": "搜索",
"viewOptions": "视图",
"compactList": "紧凑列表",
"showPreviews": "显示预览",
"showTimestamps": "显示时间",
"sortLabel": "排序",
"sortUpdated": "最近更新",
"sortCreated": "最近创建",
"sortTitle": "标题 A-Z",
"searchPlaceholder": "搜索",
"searchResults": "搜索结果",
"noSearchResults": "没有匹配的会话。",
"recent": "最近对话",
"refreshSessions": "刷新会话",
"settings": "设置",
"language": {
"label": "语言",
@@ -80,11 +70,11 @@
"models": "模型",
"providers": "提供商",
"image": "图片",
"web": "网页",
"browser": "网页",
"cliApps": "CLI 应用",
"mcp": "MCP",
"runtime": "运行时",
"advanced": "高级",
"runtime": "系统",
"advanced": "安全",
"apps": "应用"
},
"sections": {
@@ -101,10 +91,11 @@
"cliApps": "CLI 应用",
"mcp": "MCP 服务",
"identity": "身份",
"safety": "安全",
"webuiSafety": "网页端安全",
"capabilities": "能力",
"integrations": "集成",
"apps": "应用"
"apps": "应用",
"nativeHost": "App",
"hostSafety": "App 安全"
},
"models": {
"selectModel": "选择模型",
@@ -112,6 +103,7 @@
"newConfiguration": "新建模型配置",
"newConfigurationHelp": "把服务商和模型保存为一个可直接切换的选项。",
"configurationName": "名称",
"configurationNameHelp": "重命名这个已保存的模型配置。",
"configurationNamePlaceholder": "快速写作"
},
"rows": {
@@ -147,20 +139,14 @@
"botName": "Bot 名称",
"botIcon": "Bot 图标",
"timezone": "时区",
"toolHintMaxLength": "工具提示长度",
"workspacePath": "工作区路径",
"heartbeat": "Heartbeat",
"dream": "Dream",
"unifiedSession": "统一会话",
"restrictWorkspace": "限制在工作区内",
"execTool": "Exec 工具",
"execSandbox": "Exec 沙箱",
"ssrfWhitelist": "SSRF 白名单",
"mcpServers": "MCP 服务器",
"pathAppend": "PATH 追加",
"workspacePath": "默认工作区",
"localServiceAccess": "本机服务",
"webuiDefaultAccess": "默认权限",
"cliAppsCatalog": "目录",
"cliAppsFilter": "筛选",
"configurationDocs": "配置文档"
"engine": "引擎",
"logs": "日志",
"diagnostics": "诊断"
},
"help": {
"theme": "在浅色和深色外观之间切换。",
@@ -187,13 +173,18 @@
"defaultAspectRatio": "当提示词没有选择比例时使用。",
"defaultImageSize": "发送给支持该能力的服务商的尺寸提示。",
"maxImagesPerTurn": "单次 generate_image 请求允许的图片上限。",
"botName": "显示在使用 bot 身份的运行时界面里。",
"botName": "显示在 nanobot 使用名称的地方。",
"botIcon": "显示在 bot 名称旁的短 emoji 或文本。",
"timezone": "运行时上下文和计划任务使用的 IANA 时区。",
"toolHintMaxLength": "工具进度提示显示的最大字符数。",
"timezone": "用于计划任务和需要时间感知的回复。",
"cliAppsCatalog": "只安装 nanobot 在本机调用应用时需要的 CLI 适配层,不触碰应用本体。",
"cliAppsFilter": "按应用、分类或能力搜索。",
"advancedReadOnly": "高级安全控制在 WebUI 中只读;需要时请谨慎编辑 config.json。"
"localServiceAccess": "允许完全访问模式下的 shell 命令访问 localhost 服务。",
"webuiDefaultAccess": "用于没有单独选择权限的网页端对话。",
"securityManagedControls": "网页抓取始终保护本机、内网和元数据服务。核心渠道安全仍由 config.json 管理。",
"logs": "打开App引擎日志文件夹。",
"diagnostics": "导出一份用于支持排查的运行时报告。",
"localServiceAccessNative": "允许完全访问模式下的 shell 命令访问这台 Mac 上的服务。",
"webuiDefaultAccessNative": "用于没有单独选择权限的原生 App 对话。"
},
"timezone": {
"select": "选择时区",
@@ -298,8 +289,12 @@
"expanded": "展开",
"on": "开",
"off": "关",
"defaultPermission": "默认权限",
"fullAccess": "完全访问",
"configured": "已配置",
"notConfigured": "未配置"
"notConfigured": "未配置",
"pending": "待应用",
"restartingEngine": "正在重启"
},
"status": {
"loading": "正在加载设置...",
@@ -309,14 +304,24 @@
"savedRestart": "已保存。重启 nanobot 后生效。",
"restartAfterSaving": "保存后,可在合适时重启。",
"savedRestartApply": "已保存,可稍后重启。",
"imageProviderRestart": "图片服务商改动已保存,可稍后重启。"
"imageProviderRestart": "图片服务商改动已保存,可稍后重启。",
"hostRestartAfterSaving": "保存后,nanobot 会自动重启引擎。",
"hostRestartPending": "已保存,将在合适时重启引擎。",
"hostApiUnavailable": "宿主操作只能在原生 App 内使用。",
"logsOpened": "已打开日志文件夹。",
"logsOpenFailed": "无法打开日志文件夹。",
"diagnosticsExported": "诊断已导出到 {{path}}。",
"diagnosticsExportFailed": "无法导出诊断。"
},
"actions": {
"save": "保存",
"saving": "保存中",
"edit": "编辑",
"cancel": "取消",
"openDocs": "打开文档"
"open": "打开",
"export": "导出",
"opening": "打开中...",
"exporting": "导出中..."
},
"byok": {
"description": "自带服务商密钥。Nanobot 会从当前 config 读取这些值,只有已配置的服务商才能在通用设置里选择。",
@@ -397,6 +402,19 @@
"featured": "精选",
"loading": "正在加载应用...",
"empty": "没有符合筛选条件的应用。"
},
"oauth": {
"authentication": "OAuth 认证",
"signIn": "登录",
"signingIn": "正在登录…",
"signInAgain": "重新登录",
"signOut": "退出登录",
"signedInAs": "已登录为 {{account}}",
"signInHelp": "在这台设备上登录;不会把 API key 写入配置。",
"signInRequired": "需要登录",
"signInBeforeSaving": "先登录这个 OAuth 提供商,然后再保存为当前模型提供商。",
"signedIn": "已登录",
"notSignedIn": "未登录"
}
},
"chat": {
@@ -404,7 +422,10 @@
"loading": "加载中…",
"noSessions": "还没有会话。",
"showMore": "再显示 {{count}} 个",
"collapsed": "已折叠 {{count}} 个对话",
"showLess": "收起",
"actions": "“{{title}}” 的会话操作",
"newInProject": "在 {{project}} 中开始新对话",
"activity": {
"running": "Agent 正在运行",
"complete": "Agent 已完成"
@@ -415,6 +436,9 @@
"renameTitle": "重命名对话",
"renameDescription": "为这个对话设置一个仅用于 WebUI 侧边栏的名称。",
"renamePlaceholder": "对话名称",
"renameProjectTitle": "重命名项目",
"renameProjectDescription": "为这个项目设置一个仅用于 WebUI 侧边栏的名称。",
"renameProjectPlaceholder": "项目名称",
"renameSave": "保存",
"archive": "归档",
"unarchive": "取消归档",
@@ -425,6 +449,7 @@
"groups": {
"pinned": "置顶",
"all": "对话",
"projects": "项目",
"today": "今天",
"yesterday": "昨天",
"earlier": "更早",
@@ -448,7 +473,12 @@
"thread": {
"loadingConversation": "正在加载对话…",
"empty": {
"greeting": "我可以帮你做什么?",
"greetings": {
"workOn": "我们要一起做点什么?",
"start": "今天从哪里开始?",
"build": "今天一起构建什么?",
"tackle": "我们要一起解决什么?"
},
"quickActions": {
"plan": {
"title": "创建项目计划",
@@ -632,7 +662,14 @@
"too_large": "图片太大,请换一张小一点的",
"io": "无法读取该文件"
},
"goalStateCloseAria": "关闭目标"
"goalStateCloseAria": "关闭目标",
"workspace": {
"accessAria": "工作区访问权限",
"projectAria": "选择项目",
"projectPlaceholder": "选择项目",
"default": "默认权限",
"full": "完全访问权限"
}
},
"scrollToBottom": "滚动到底部",
"loadEarlier": "加载更早消息"
@@ -690,6 +727,19 @@
"messageTooBig": {
"title": "消息过大",
"body": "服务端因超过大小限制拒收了上一条消息。可移除部分图片或使用更小的图片后重试。"
},
"workspaceScopeRejected": {
"title": "工作区未更改",
"body": "网关拒绝了请求的项目或访问权限,Nanobot 已继续使用之前的工作区。"
}
},
"workspace": {
"dialog": {
"defaultProject": "默认工作区",
"manual": "粘贴路径",
"manualPlaceholder": "/Users/name/project",
"usePath": "使用路径",
"absolutePathRequired": "请输入这台机器上的绝对文件夹路径。"
}
}
}