mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-20 09:14:22 +01:00
Feat: Render tool metadata after permission rejection. (#1949)
Signed-off-by: jmug <u.g.a.mariano@gmail.com>
This commit is contained in:
@@ -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.`)
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -2025,6 +2025,7 @@ func (r toolStateCompletedTimeJSON) RawJSON() string {
|
||||
type ToolStateError struct {
|
||||
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:"-"`
|
||||
@@ -2034,6 +2035,7 @@ type ToolStateError struct {
|
||||
type toolStateErrorJSON struct {
|
||||
Error apijson.Field
|
||||
Input apijson.Field
|
||||
Metadata apijson.Field
|
||||
Status apijson.Field
|
||||
Time apijson.Field
|
||||
raw string
|
||||
|
||||
@@ -347,6 +347,9 @@ export type ToolStateError = {
|
||||
input: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
metadata: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
error: string
|
||||
time: {
|
||||
start: number
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user