Dax Raad 3 months ago
parent
commit
82a8ba6822

+ 1 - 0
.opencode/opencode.jsonc

@@ -10,6 +10,7 @@
       "options": {},
     },
   },
+  "permission": "ask",
   "mcp": {
     "context7": {
       "type": "remote",

+ 14 - 17
packages/opencode/src/acp/agent.ts

@@ -71,19 +71,19 @@ export namespace ACP {
       this.config.sdk.event.subscribe({ directory }).then(async (events) => {
         for await (const event of events.stream) {
           switch (event.type) {
-            case "permission.updated":
+            case "permission.asked":
               try {
                 const permission = event.properties
                 const res = await this.connection
                   .requestPermission({
                     sessionId,
                     toolCall: {
-                      toolCallId: permission.callID ?? permission.id,
+                      toolCallId: permission.tool?.callID ?? permission.id,
                       status: "pending",
-                      title: permission.message,
+                      title: permission.permission,
                       rawInput: permission.metadata,
-                      kind: toToolKind(permission.type),
-                      locations: toLocations(permission.type, permission.metadata),
+                      kind: toToolKind(permission.permission),
+                      locations: toLocations(permission.permission, permission.metadata),
                     },
                     options,
                   })
@@ -93,28 +93,25 @@ export namespace ACP {
                       permissionID: permission.id,
                       sessionID: permission.sessionID,
                     })
-                    await this.config.sdk.permission.respond({
-                      sessionID: permission.sessionID,
-                      permissionID: permission.id,
-                      response: "reject",
+                    await this.config.sdk.permission.reply({
+                      requestID: permission.id,
+                      reply: "reject",
                       directory,
                     })
                     return
                   })
                 if (!res) return
                 if (res.outcome.outcome !== "selected") {
-                  await this.config.sdk.permission.respond({
-                    sessionID: permission.sessionID,
-                    permissionID: permission.id,
-                    response: "reject",
+                  await this.config.sdk.permission.reply({
+                    requestID: permission.id,
+                    reply: "reject",
                     directory,
                   })
                   return
                 }
-                await this.config.sdk.permission.respond({
-                  sessionID: permission.sessionID,
-                  permissionID: permission.id,
-                  response: res.outcome.optionId as "once" | "always" | "reject",
+                await this.config.sdk.permission.reply({
+                  requestID: permission.id,
+                  reply: res.outcome.optionId as "once" | "always" | "reject",
                   directory,
                 })
               } catch (err) {

+ 1 - 1
packages/opencode/src/cli/cmd/run.ts

@@ -202,7 +202,7 @@ export const RunCommand = cmd({
             break
           }
 
-          if (event.type === "permission.next.asked") {
+          if (event.type === "permission.asked") {
             const permission = event.properties
             if (permission.sessionID !== sessionID) continue
             const result = await select({

+ 2 - 2
packages/opencode/src/cli/cmd/tui/context/sync.tsx

@@ -97,7 +97,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
     sdk.event.listen((e) => {
       const event = e.details
       switch (event.type) {
-        case "permission.next.replied": {
+        case "permission.replied": {
           const requests = store.permission[event.properties.sessionID]
           if (!requests) break
           const match = Binary.search(requests, event.properties.requestID, (r) => r.id)
@@ -112,7 +112,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
           break
         }
 
-        case "permission.next.asked": {
+        case "permission.asked": {
           const request = event.properties
           const requests = store.permission[request.sessionID]
           if (!requests) {

+ 16 - 33
packages/opencode/src/cli/cmd/tui/routes/session/index.tsx

@@ -107,8 +107,17 @@ export function Session() {
   const { theme } = useTheme()
   const promptRef = usePromptRef()
   const session = createMemo(() => sync.session.get(route.sessionID)!)
+  const children = createMemo(() => {
+    const parentID = session()?.parentID ?? session()?.id
+    return sync.data.session
+      .filter((x) => x.parentID === parentID || x.id === parentID)
+      .toSorted((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))
+  })
   const messages = createMemo(() => sync.data.message[route.sessionID] ?? [])
-  const permissions = createMemo(() => sync.data.permission[route.sessionID] ?? [])
+  const permissions = createMemo(() => {
+    if (session().parentID) return sync.data.permission[route.sessionID] ?? []
+    return children().flatMap((x) => sync.data.permission[x.id] ?? [])
+  })
 
   const pending = createMemo(() => {
     return messages().findLast((x) => x.role === "assistant" && !x.time.completed)?.id
@@ -176,28 +185,6 @@ export function Session() {
     }
   })
 
-  // Auto-navigate to whichever session currently needs permission input
-  createEffect(() => {
-    const currentSession = session()
-    if (!currentSession) return
-    const currentPermissions = permissions()
-    let targetID = currentPermissions.length > 0 ? currentSession.id : undefined
-
-    if (!targetID) {
-      const child = sync.data.session.find(
-        (x) => x.parentID === currentSession.id && (sync.data.permission[x.id]?.length ?? 0) > 0,
-      )
-      if (child) targetID = child.id
-    }
-
-    if (targetID && targetID !== currentSession.id) {
-      navigate({
-        type: "session",
-        sessionID: targetID,
-      })
-    }
-  })
-
   let scroll: ScrollBoxRenderable
   let prompt: PromptRef
   const keybind = useKeybind()
@@ -257,18 +244,14 @@ export function Session() {
   const local = useLocal()
 
   function moveChild(direction: number) {
-    const parentID = session()?.parentID ?? session()?.id
-    let children = sync.data.session
-      .filter((x) => x.parentID === parentID || x.id === parentID)
-      .toSorted((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))
-    if (children.length === 1) return
-    let next = children.findIndex((x) => x.id === session()?.id) + direction
-    if (next >= children.length) next = 0
-    if (next < 0) next = children.length - 1
-    if (children[next]) {
+    if (children().length === 1) return
+    let next = children().findIndex((x) => x.id === session()?.id) + direction
+    if (next >= children().length) next = 0
+    if (next < 0) next = children().length - 1
+    if (children()[next]) {
       navigate({
         type: "session",
-        sessionID: children[next].id,
+        sessionID: children()[next].id,
       })
     }
   }

+ 1 - 1
packages/opencode/src/session/prompt.ts

@@ -646,7 +646,7 @@ export namespace SessionPrompt {
       async ask(req) {
         await PermissionNext.ask({
           ...req,
-          sessionID: input.session.parentID ?? input.session.id,
+          sessionID: input.session.id,
           tool: { messageID: input.processor.message.id, callID: options.toolCallId },
           ruleset: PermissionNext.merge(input.agent.permission, input.session.permission ?? []),
         })