diff --git a/packages/app/src/components/settings-v2/general.tsx b/packages/app/src/components/settings-v2/general.tsx
index 8a72701fd..b7e11ba9e 100644
--- a/packages/app/src/components/settings-v2/general.tsx
+++ b/packages/app/src/components/settings-v2/general.tsx
@@ -9,7 +9,6 @@ import { useLanguage } from "@/context/language"
import { usePlatform } from "@/context/platform"
import { useUpdaterAction } from "../updater-action"
import { useSettings } from "@/context/settings"
-import { ExternalLink } from "../external-link"
import { SettingsListV2 } from "./parts/list"
import { SettingsRowV2 } from "./parts/row"
import { LayoutRetirementNotice, LayoutTransitionToggle } from "./interface-transition"
@@ -147,30 +146,6 @@ const AppearanceSection: Component<{ controller: AppearanceSettingsController }>
/>
-
- {language.t("settings.general.row.theme.description")}{" "}
-
- {language.t("common.learnMore")}
-
- >
- }
- >
- option.id}
- label={(option) => option.name}
- onSelect={props.controller.theme.select}
- />
-
-
diff --git a/packages/app/src/components/settings-v2/permissions.tsx b/packages/app/src/components/settings-v2/permissions.tsx
index 167386e68..61dadf1f3 100644
--- a/packages/app/src/components/settings-v2/permissions.tsx
+++ b/packages/app/src/components/settings-v2/permissions.tsx
@@ -1,6 +1,7 @@
import { ButtonV2 } from "@opencode-ai/ui/v2/button-v2"
import { Tag } from "@opencode-ai/ui/v2/badge-v2"
import { TextInputV2 } from "@opencode-ai/ui/v2/text-input-v2"
+import { SelectV2 } from "@opencode-ai/ui/v2/select-v2"
import { showToast } from "@/utils/toast"
import { createMemo, createSignal, For, Show, type Component } from "solid-js"
import { useLanguage } from "@/context/language"
@@ -21,6 +22,8 @@ const DEFAULT_TIERS: TrustTier[] = [
]
const DEFAULT_CONFIG: ProviderPermissionsConfig = { defaultTier: "unassigned", tiers: DEFAULT_TIERS, assignments: {} }
+const EFFECTS: Effect[] = ["allow", "deny", "ask"]
+const EFFECT_LABEL: Record = { allow: "Allow", deny: "Deny", ask: "Ask" }
const ACTION_GROUPS = ["read", "write", "execute", "network"] as const
type ActionGroup = (typeof ACTION_GROUPS)[number]
const GROUP_LABEL: Record = { read: "Read", write: "Write", execute: "Execute", network: "Network" }
@@ -162,10 +165,26 @@ export const SettingsPermissionsV2: Component = () => {
}
const addDirectoryRule = (tierId: string) => {
- const pattern = `src/private/**`
+ const tier = tiers().find((t) => t.id === tierId)
+ if (!tier) return
+ let pattern = "folder/**"
+ for (let n = 2; tier.directories[pattern]; n++) pattern = `folder-${n}/**`
+ updateTier(tierId, (t) => ({
+ ...t,
+ directories: { ...t.directories, [pattern]: { read: "deny", write: "deny", execute: "deny", network: "deny" } },
+ }))
+ setEditingPattern(`${tierId}:${pattern}`)
+ setPatternValue(pattern)
+ }
+
+ const renameDirectoryRule = (tierId: string, from: string, to: string) => {
+ const next = to.trim()
+ if (!next || next === from || next === "**") return
updateTier(tierId, (t) => {
- if (t.directories[pattern]) return t
- return { ...t, directories: { ...t.directories, [pattern]: { read: "deny", write: "deny", execute: "deny", network: "deny" } } }
+ if (!t.directories[from] || t.directories[next]) return t
+ const directories: Record = {}
+ for (const [k, v] of Object.entries(t.directories)) directories[k === from ? next : k] = v
+ return { ...t, directories }
})
}
@@ -180,18 +199,23 @@ export const SettingsPermissionsV2: Component = () => {
const [editingLabel, setEditingLabel] = createSignal(null)
const [editValue, setEditValue] = createSignal("")
+ // exception pattern being edited, keyed `${tierId}:${pattern}`
+ const [editingPattern, setEditingPattern] = createSignal(null)
+ const [patternValue, setPatternValue] = createSignal("")
return (
-