Procházet zdrojové kódy

Feat: Render tool metadata after permission rejection. (#1949)

Signed-off-by: jmug <[email protected]>
Mariano Uvalle před 6 měsíci
rodič
revize
0befc5d602

+ 4 - 3
packages/opencode/src/permission/index.ts

@@ -62,7 +62,7 @@ export namespace Permission {
     async (state) => {
       for (const pending of Object.values(state.pending)) {
         for (const item of Object.values(pending)) {
-          item.reject(new RejectedError(item.info.sessionID, item.info.id, item.info.callID))
+          item.reject(new RejectedError(item.info.sessionID, item.info.id, item.info.callID, item.info.metadata))
         }
       }
     },
@@ -105,7 +105,7 @@ export namespace Permission {
       }).then((x) => x.status)
     ) {
       case "deny":
-        throw new RejectedError(info.sessionID, info.id, info.callID)
+        throw new RejectedError(info.sessionID, info.id, info.callID, info.metadata)
       case "allow":
         return
     }
@@ -131,7 +131,7 @@ export namespace Permission {
     if (!match) return
     delete pending[input.sessionID][input.permissionID]
     if (input.response === "reject") {
-      match.reject(new RejectedError(input.sessionID, input.permissionID, match.info.callID))
+      match.reject(new RejectedError(input.sessionID, input.permissionID, match.info.callID, match.info.metadata))
       return
     }
     match.resolve()
@@ -156,6 +156,7 @@ export namespace Permission {
       public readonly sessionID: string,
       public readonly permissionID: string,
       public readonly toolCallID?: string,
+      public readonly metadata?: Record<string, any>,
     ) {
       super(`The user rejected permission to use this specific tool call. You may try again with different parameters.`)
     }

+ 1 - 0
packages/opencode/src/session/index.ts

@@ -1268,6 +1268,7 @@ export namespace Session {
                       status: "error",
                       input: value.input,
                       error: (value.error as any).toString(),
+                      metadata: value.error instanceof Permission.RejectedError ? value.error.metadata : undefined,
                       time: {
                         start: match.state.time.start,
                         end: Date.now(),

+ 1 - 0
packages/opencode/src/session/message-v2.ts

@@ -64,6 +64,7 @@ export namespace MessageV2 {
       status: z.literal("error"),
       input: z.record(z.any()),
       error: z.string(),
+      metadata: z.record(z.any()).optional(),
       time: z.object({
         start: z.number(),
         end: z.number(),

+ 7 - 5
packages/sdk/go/session.go

@@ -2023,17 +2023,19 @@ func (r toolStateCompletedTimeJSON) RawJSON() string {
 }
 
 type ToolStateError struct {
-	Error  string                 `json:"error,required"`
-	Input  map[string]interface{} `json:"input,required"`
-	Status ToolStateErrorStatus   `json:"status,required"`
-	Time   ToolStateErrorTime     `json:"time,required"`
-	JSON   toolStateErrorJSON     `json:"-"`
+	Error    string                 `json:"error,required"`
+	Input    map[string]interface{} `json:"input,required"`
+	Metadata map[string]interface{} `json:"metadata"`
+	Status   ToolStateErrorStatus   `json:"status,required"`
+	Time     ToolStateErrorTime     `json:"time,required"`
+	JSON     toolStateErrorJSON     `json:"-"`
 }
 
 // toolStateErrorJSON contains the JSON metadata for the struct [ToolStateError]
 type toolStateErrorJSON struct {
 	Error       apijson.Field
 	Input       apijson.Field
+	Metadata    apijson.Field
 	Status      apijson.Field
 	Time        apijson.Field
 	raw         string

+ 3 - 0
packages/sdk/js/src/gen/types.gen.ts

@@ -347,6 +347,9 @@ export type ToolStateError = {
   input: {
     [key: string]: unknown
   }
+  metadata: {
+    [key: string]: unknown
+  }
   error: string
   time: {
     start: number

+ 18 - 1
packages/tui/internal/components/chat/message.go

@@ -554,6 +554,17 @@ func renderToolDetails(
 					title := renderToolTitle(toolCall, width)
 					title = style.Render(title)
 					content := title + "\n" + body
+
+					if toolCall.State.Status == opencode.ToolPartStateStatusError {
+						errorStyle := styles.NewStyle().
+							Background(backgroundColor).
+							Foreground(t.Error()).
+							Padding(1, 2).
+							Width(width - 4)
+						errorContent := errorStyle.Render(toolCall.State.Error)
+						content += "\n" + errorContent
+					}
+
 					if permissionContent != "" {
 						permissionContent = styles.NewStyle().
 							Background(backgroundColor).
@@ -652,11 +663,17 @@ func renderToolDetails(
 	}
 
 	if error != "" {
-		body = styles.NewStyle().
+		errorContent := styles.NewStyle().
 			Width(width - 6).
 			Foreground(t.Error()).
 			Background(backgroundColor).
 			Render(error)
+
+		if body == "" {
+			body = errorContent
+		} else {
+			body += "\n\n" + errorContent
+		}
 	}
 
 	if body == "" && error == "" && result != nil {