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
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ export function CapabilityDetailHeader({ capability, locale, source }: Readonly<
}>) {
const { t } = useWorkspaceI18n();
const localized = localizeCapability(capability, locale);
// Capability ownership remains visible even when this editor is read-only.
const scopes = capability.configuration_editor.supported_scopes;
const scopeKind = scopes.includes("machine")
? scopes.includes("goal") ? "machineAndGoal" : "machine"
: scopes.includes("goal") ? "goal" : "unknown";
return (
<header>
<span className="personal-settings-icon"><SlidersHorizontal aria-hidden size={18} /></span>
Expand All @@ -129,6 +134,7 @@ export function CapabilityDetailHeader({ capability, locale, source }: Readonly<
<h2>{localized.display_name}</h2>
<CapabilityEffectiveSource source={source} t={t} />
</div>
<p className="personal-capability-supported-scopes">{t(`capabilities.configurationScope.${scopeKind}`)}</p>
{capability.context_contribution && (
<details className="personal-capability-help" data-testid="capability-context-phases">
<summary>{locale === "zh-CN" ? "主 Agent 协作指导" : "Coordinator workflow guidance"}</summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useMemo, useState } from "react";
import { AlertTriangle, Code2, LoaderCircle, RefreshCw, ShieldCheck } from "lucide-react";
import { AlertTriangle, Code2, LoaderCircle, RefreshCw } from "lucide-react";

import {
applyGoalConfiguration,
Expand Down Expand Up @@ -248,6 +248,7 @@ function CapabilityCatalog({ callbacks, catalog, goalId, notification, onApplied
locale={locale}
onSelect={setSelectedCapabilityId}
scope="goal"
showScope={false}
selectedCapabilityId={localizedSelected.capability_id}
t={t}
/>
Expand Down Expand Up @@ -361,11 +362,7 @@ export function GoalCapabilitySettings({ callbacks, goalId, notification, onChan
if (!inspection) return null;

return (
<section className="personal-capability-settings" data-revision={inspection.revision}>
<details className="personal-capability-scope-note">
<summary><ShieldCheck aria-hidden size={17} />{t("capabilities.atomicOverride")}</summary>
<p>{t("capabilities.atomicOverrideDescription")}</p>
</details>
<section className="personal-capability-settings is-goal-scoped" data-revision={inspection.revision}>
<CapabilityCatalog
callbacks={callbacks}
catalog={inspection.capability_catalog}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,10 @@ const en = {
"capabilities.description": "Inspect the capabilities available to this Goal and the exact scope of each setting.",
"capabilities.editorPrepared": "Typed editor contract available",
"capabilities.effectiveSource": "Effective source",
"capabilities.configurationScope.machine": "Device-wide setting · Goals cannot override",
"capabilities.configurationScope.goal": "Goal-specific setting · No device default",
"capabilities.configurationScope.machineAndGoal": "Device default · Each Goal can override",
"capabilities.configurationScope.unknown": "Configuration scope unavailable",
"capabilities.empty": "No capability descriptors are available for this Goal.",
"capabilities.fields": "Registered fields",
"capabilities.goalPolicy": "Goal capability policy",
Expand All @@ -933,12 +937,12 @@ const en = {
"capabilities.larkInboxNotificationSetting": "Human-gate group notifications",
"capabilities.loading": "Loading Goal capabilities…",
"capabilities.machineOnly": "This capability is configured only at machine scope.",
"capabilities.machineValue": "Live machine default",
"capabilities.machineValue": "Device defaults",
"capabilities.machineScope": "Machine",
"capabilities.previewOnly": "Inspection is live. Goal writes remain unavailable until the revision-locked preview and apply path is connected.",
"capabilities.preview": "Revision-locked preview",
"capabilities.previewChanges": "Preview changes",
"capabilities.restoreInheritance": "Restore machine-default inheritance",
"capabilities.restoreInheritance": "Use device defaults",
"capabilities.previewFailed": "Could not preview Goal capability changes.",
"capabilities.previewLocked": "Apply will re-check this exact plan revision and reject stale changes.",
"capabilities.partialWrite": "Goal value saved; shared projection needs reconciliation",
Expand All @@ -950,8 +954,8 @@ const en = {
"capabilities.revisionLockedReady": "Changes require a preview and are applied only when its exact revision is still current.",
"capabilities.retry": "Retry",
"capabilities.source.capability_default": "Capability default",
"capabilities.source.goal_override": "Goal override",
"capabilities.source.machine_default": "Live machine default",
"capabilities.source.goal_override": "Goal-specific configuration",
"capabilities.source.machine_default": "Device defaults",
"capabilities.source.not_configured": "Not configured",
"capabilities.title": "Goal capabilities",
"settings.close": "Close settings",
Expand All @@ -971,6 +975,12 @@ const en = {
"settings.language": "Language",
"settings.modelProvider": "Model provider",
"settings.globalCapabilities": "Capability Center",
"settings.capabilityScope": "Configure for",
"settings.capabilityScope.machine": "Device defaults",
"settings.capabilityScope.goal": "One Goal",
"settings.capabilityScope.machineDescription": "Defaults on this device. A Goal’s own configuration takes priority.",
"settings.capabilityScope.goalDescription": "Only this Goal changes. Each customized capability uses its own complete configuration; other capabilities keep their defaults.",
"settings.targetGoal": "Target Goal",
"settings.languageDescription": "Choose the language used by the LoopX desktop workspace.",
"settings.languageEnglishDescription": "Use English for navigation, settings, and workspace controls.",
"settings.languageEnglish": "English",
Expand Down Expand Up @@ -2083,6 +2093,10 @@ const zhCN: Record<WorkspaceMessageKey, string> = {
"capabilities.description": "查看当前 Goal 可用的能力,以及每项配置的准确作用域。",
"capabilities.editorPrepared": "已注册 typed editor contract",
"capabilities.effectiveSource": "当前生效来源",
"capabilities.configurationScope.machine": "设备全局配置 · 不支持 Goal 覆盖",
"capabilities.configurationScope.goal": "仅单个 Goal 配置 · 无设备默认值",
"capabilities.configurationScope.machineAndGoal": "设备默认配置 · 支持 Goal 单独覆盖",
"capabilities.configurationScope.unknown": "配置范围暂不可用",
"capabilities.empty": "当前 Goal 没有可用的能力描述。",
"capabilities.fields": "已注册字段",
"capabilities.goalPolicy": "Goal 能力策略",
Expand All @@ -2093,12 +2107,12 @@ const zhCN: Record<WorkspaceMessageKey, string> = {
"capabilities.larkInboxNotificationSetting": "Gate 群通知",
"capabilities.loading": "正在加载 Goal 能力…",
"capabilities.machineOnly": "此能力只能在机器作用域配置。",
"capabilities.machineValue": "实时机器默认值",
"capabilities.machineValue": "设备默认值",
"capabilities.machineScope": "机器",
"capabilities.previewOnly": "当前读取结果来自真实配置;在 revision-locked preview/apply 路径接通前,Dashboard 不会提供 Goal 写入控件。",
"capabilities.preview": "锁定 revision 的变更预览",
"capabilities.previewChanges": "预览变更",
"capabilities.restoreInheritance": "恢复继承机器默认值",
"capabilities.restoreInheritance": "恢复沿用设备默认",
"capabilities.previewFailed": "无法预览 Goal 能力变更。",
"capabilities.previewLocked": "应用时会重新校验这一个 plan revision;过期变更将被拒绝。",
"capabilities.partialWrite": "Goal 值已保存;共享投影仍需修复",
Expand All @@ -2110,8 +2124,8 @@ const zhCN: Record<WorkspaceMessageKey, string> = {
"capabilities.revisionLockedReady": "所有变更必须先预览;只有对应的精确 revision 仍然有效时才会写入。",
"capabilities.retry": "重试",
"capabilities.source.capability_default": "能力默认值",
"capabilities.source.goal_override": "Goal override",
"capabilities.source.machine_default": "实时机器默认值",
"capabilities.source.goal_override": "本 Goal 单独设置",
"capabilities.source.machine_default": "设备默认值",
"capabilities.source.not_configured": "未配置",
"capabilities.title": "Goal 能力",
"settings.close": "关闭设置",
Expand All @@ -2131,6 +2145,12 @@ const zhCN: Record<WorkspaceMessageKey, string> = {
"settings.language": "语言",
"settings.modelProvider": "模型 Provider 配置",
"settings.globalCapabilities": "能力中心",
"settings.capabilityScope": "配置范围",
"settings.capabilityScope.machine": "此设备默认",
"settings.capabilityScope.goal": "单个 Goal",
"settings.capabilityScope.machineDescription": "适用于此设备;Goal 已单独设置的配置优先生效。",
"settings.capabilityScope.goalDescription": "仅修改所选 Goal。单独设置的能力使用完整配置,其余能力沿用默认值。",
"settings.targetGoal": "目标 Goal",
"settings.languageDescription": "选择 LoopX Desktop 工作区使用的界面语言。",
"settings.languageEnglishDescription": "使用英文显示导航、设置和工作区控件。",
"settings.languageEnglish": "English",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,10 +337,10 @@ export function MachineConfigurationSettings({ section }: { section: "steward" |
return (
<section className="personal-capability-settings" data-revision={inspection?.revision}>
<div>
<details className="personal-capability-scope-note">
{section === "steward" ? <details className="personal-capability-scope-note">
<summary><ShieldCheck aria-hidden size={17} />{t("machine.liveDefault")}</summary>
<p>{t("machine.liveDefaultDescription")}</p>
</details>
</details> : null}
{section === "other" ? <UsageStatisticsSettings /> : null}
</div>

Expand All @@ -356,7 +356,7 @@ export function MachineConfigurationSettings({ section }: { section: "steward" |
) : null}

<div className="personal-capability-layout">
<CapabilityCatalogNavigation capabilities={capabilities} locale={locale} onSelect={setSelectedCapabilityId} scope="machine" selectedCapabilityId={selected.capability_id} showScope={section !== "steward"} t={t} />
<CapabilityCatalogNavigation capabilities={capabilities} locale={locale} onSelect={setSelectedCapabilityId} scope="machine" selectedCapabilityId={selected.capability_id} showScope={false} t={t} />

<article aria-label={selected.display_name} className="personal-capability-detail" tabIndex={0}>
<CapabilityDetailHeader capability={selectedRaw} locale={locale}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ assert.doesNotMatch(workspaceSettings, /NotificationSettingsPanel/, "Settings do
assert.match(workspaceSettings, /key: "lark"/, "Settings expose a Lark tab");
assert.match(workspaceSettings, /key: "appearance"/, "Settings expose an appearance tab");
assert.match(workspaceSettings, /key: "language"/, "Settings expose a language tab");
assert.match(workspaceSettings, /key: "machine"/, "Settings expose generic machine configuration");
assert.match(workspaceSettings, /key: "capabilities"/, "Settings expose a unified capability destination");
assert.match(workspaceSettings, /<MachineConfigurationSettings/, "Settings mount the machine configuration registry");
assert.match(workspaceSettings, /<LarkSettingsPage[\s\S]*embedded/, "Settings embed the Lark management page");
assert.match(larkSettings, /state: "ready" \| "unverified" \| "not_ready"/, "Lark readiness keeps unverified routes separate from actual failures");
Expand Down Expand Up @@ -413,7 +413,7 @@ assert.match(machineSettings, /<CapabilityCatalogNavigation/, "Machine settings
assert.match(goalCapabilitySettings, /<CapabilityCatalogNavigation/, "Goal settings use the shared capability catalog navigation");
assert.match(goalCapabilitySettings, /capability_id === "lark_event_inbox"[\s\S]*<GoalAutoNotifyToggle/, "Lark inbox capability exposes the independent human-gate notification control");
assert.match(notificationSettings, /disabled=\{busy \|\| notification\?\.configured !== true/, "Gate notification control stays disabled until a Goal Channel is configured");
assert.match(workspaceSettings, /goalNotifications\.find\(\(row\) => row\.goalId === initialGoalId\)/, "Goal capability settings receive the live Goal Channel notification state");
assert.match(workspaceSettings, /goalNotifications\.find\(\(row\) => row\.goalId === capabilityGoalId\)/, "Goal capability settings receive the selected Goal Channel notification state");
assert.match(machineSettings, /<CapabilityDetailHeader/, "Machine settings use the shared capability detail header");
assert.match(goalCapabilitySettings, /<CapabilityDetailHeader/, "Goal settings use the shared capability detail header");
assert.match(capabilityWorkbench, /localizeCapability\(rawCapability, locale\)/, "Shared navigation localizes capability metadata without changing capability ids");
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading