diff options
| author | Adam <[email protected]> | 2025-12-27 05:16:39 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2025-12-27 14:43:42 -0600 |
| commit | 21eba5f987482b4e2e75ab1c564815bd7b0613f4 (patch) | |
| tree | 2d8cad03e54baa29d83e1e835a7ef2e64d3897e4 /packages/app/src/context | |
| parent | c523ca412747d66e0236865a4fa2481f7d50f64e (diff) | |
| download | opencode-21eba5f987482b4e2e75ab1c564815bd7b0613f4.tar.gz opencode-21eba5f987482b4e2e75ab1c564815bd7b0613f4.zip | |
feat(desktop): permissions
Diffstat (limited to 'packages/app/src/context')
| -rw-r--r-- | packages/app/src/context/global-sync.tsx | 61 | ||||
| -rw-r--r-- | packages/app/src/context/local.tsx | 25 |
2 files changed, 75 insertions, 11 deletions
diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx index c51901eb2..50c8a9d1c 100644 --- a/packages/app/src/context/global-sync.tsx +++ b/packages/app/src/context/global-sync.tsx @@ -15,6 +15,7 @@ import { type McpStatus, type LspStatus, type VcsInfo, + type Permission, createOpencodeClient, } from "@opencode-ai/sdk/v2/client" import { createStore, produce, reconcile } from "solid-js/store" @@ -44,6 +45,9 @@ type State = { todo: { [sessionID: string]: Todo[] } + permission: { + [sessionID: string]: Permission[] + } mcp: { [name: string]: McpStatus } @@ -78,6 +82,7 @@ function createGlobalSync() { }) const children: Record<string, ReturnType<typeof createStore<State>>> = {} + const permissionListeners: Set<(info: { directory: string; permission: Permission }) => void> = new Set() function child(directory: string) { if (!directory) console.error("No directory provided") if (!children[directory]) { @@ -93,6 +98,7 @@ function createGlobalSync() { session_status: {}, session_diff: {}, todo: {}, + permission: {}, mcp: {}, lsp: [], vcs: undefined, @@ -163,6 +169,15 @@ function createGlobalSync() { mcp: () => sdk.mcp.status().then((x) => setStore("mcp", x.data ?? {})), lsp: () => sdk.lsp.status().then((x) => setStore("lsp", x.data ?? [])), vcs: () => sdk.vcs.get().then((x) => setStore("vcs", x.data)), + permission: () => + sdk.permission.list().then((x) => { + const grouped: Record<string, typeof x.data> = {} + for (const perm of x.data ?? []) { + grouped[perm.sessionID] = grouped[perm.sessionID] ?? [] + grouped[perm.sessionID]!.push(perm) + } + setStore("permission", grouped) + }), } await Promise.all(Object.values(load).map((p) => retry(p).catch((e) => setGlobalStore("error", e)))) .then(() => setStore("ready", true)) @@ -313,6 +328,46 @@ function createGlobalSync() { setStore("vcs", { branch: event.properties.branch }) break } + case "permission.updated": { + const permissions = store.permission[event.properties.sessionID] + const isNew = !permissions || !permissions.find((p) => p.id === event.properties.id) + if (!permissions) { + setStore("permission", event.properties.sessionID, [event.properties]) + } else { + const result = Binary.search(permissions, event.properties.id, (p) => p.id) + setStore( + "permission", + event.properties.sessionID, + produce((draft) => { + if (result.found) { + draft[result.index] = event.properties + return + } + draft.push(event.properties) + }), + ) + } + if (isNew) { + for (const listener of permissionListeners) { + listener({ directory, permission: event.properties }) + } + } + break + } + case "permission.replied": { + const permissions = store.permission[event.properties.sessionID] + if (!permissions) break + const result = Binary.search(permissions, event.properties.permissionID, (p) => p.id) + if (!result.found) break + setStore( + "permission", + event.properties.sessionID, + produce((draft) => { + draft.splice(result.index, 1) + }), + ) + break + } } }) @@ -384,6 +439,12 @@ function createGlobalSync() { project: { loadSessions, }, + permission: { + onUpdated(listener: (info: { directory: string; permission: Permission }) => void) { + permissionListeners.add(listener) + return () => permissionListeners.delete(listener) + }, + }, } } diff --git a/packages/app/src/context/local.tsx b/packages/app/src/context/local.tsx index 600a0e4b1..49217b82b 100644 --- a/packages/app/src/context/local.tsx +++ b/packages/app/src/context/local.tsx @@ -377,17 +377,20 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ } const list = async (path: string) => { - return sdk.client.file.list({ path: path + "/" }).then((x) => { - setStore( - "node", - produce((draft) => { - x.data!.forEach((node) => { - if (node.path in draft) return - draft[node.path] = node - }) - }), - ) - }) + return sdk.client.file + .list({ path: path + "/" }) + .then((x) => { + setStore( + "node", + produce((draft) => { + x.data!.forEach((node) => { + if (node.path in draft) return + draft[node.path] = node + }) + }), + ) + }) + .catch(() => {}) } const searchFiles = (query: string) => sdk.client.find.files({ query, dirs: "false" }).then((x) => x.data!) |
