Handle legacy Codex approval requests

This commit is contained in:
Codex
2026-05-25 05:43:43 +00:00
parent 9dbf7727c5
commit b46c4beb86
2 changed files with 83 additions and 13 deletions

View File

@@ -1714,23 +1714,29 @@ func (b *Bot) handleCodexServerRequest(ctx context.Context, event codexapp.Event
}
switch event.Method {
case "item/commandExecution/requestApproval", "item/fileChange/requestApproval", "item/permissions/requestApproval":
case "execCommandApproval", "applyPatchApproval":
default:
b.logger.Printf("unhandled server request: %s", event.Method)
return nil
}
var params struct {
ThreadID string `json:"threadId"`
TurnID string `json:"turnId"`
ItemID string `json:"itemId"`
Reason string `json:"reason"`
ThreadID string `json:"threadId"`
ConversationID string `json:"conversationId"`
TurnID string `json:"turnId"`
ItemID string `json:"itemId"`
CallID string `json:"callId"`
ApprovalID string `json:"approvalId"`
Reason string `json:"reason"`
}
if err := json.Unmarshal(event.Params, &params); err != nil {
return err
}
if params.ThreadID == "" {
threadID := firstNonEmpty(params.ThreadID, params.ConversationID)
if threadID == "" {
return errors.New("approval request missing threadId")
}
thread, err := b.store.GetThreadByCodexID(ctx, params.ThreadID)
itemID := firstNonEmpty(params.ItemID, params.ApprovalID, params.CallID)
thread, err := b.store.GetThreadByCodexID(ctx, threadID)
if err != nil {
return err
}
@@ -1742,9 +1748,9 @@ func (b *Bot) handleCodexServerRequest(ctx context.Context, event codexapp.Event
approval, err := b.store.UpsertPendingApproval(ctx, store.PendingApproval{
TelegramUserID: thread.TelegramUserID,
CodexRequestID: strconv.FormatInt(*event.ID, 10),
CodexThreadID: params.ThreadID,
CodexThreadID: threadID,
TurnID: params.TurnID,
ItemID: params.ItemID,
ItemID: itemID,
Kind: kind,
PayloadJSON: string(pretty),
})
@@ -1756,7 +1762,7 @@ func (b *Bot) handleCodexServerRequest(ctx context.Context, event codexapp.Event
}
text := renderApprovalHTML(kind, event.Params, "")
markup := approvalMarkup(approval.ID)
if msg, ok, err := b.attachApprovalToToolMessage(ctx, params.ThreadID, params.ItemID, text, markup); err != nil {
if msg, ok, err := b.attachApprovalToToolMessage(ctx, threadID, itemID, text, markup); err != nil {
return err
} else if ok {
return b.store.UpdatePendingApprovalMessage(ctx, approval.ID, msg.Chat.ID, msg.MessageID)
@@ -1772,6 +1778,15 @@ func (b *Bot) handleCodexServerRequest(ctx context.Context, event codexapp.Event
return b.store.UpdatePendingApprovalMessage(ctx, approval.ID, msg.Chat.ID, msg.MessageID)
}
func firstNonEmpty(values ...string) string {
for _, value := range values {
if trimmed := strings.TrimSpace(value); trimmed != "" {
return trimmed
}
}
return ""
}
func (b *Bot) newOutputState(chatID int64) *outputState {
return &outputState{
chatID: chatID,
@@ -2722,6 +2737,9 @@ func approvalMarkup(id int64) *InlineKeyboardMarkup {
}
func approvalResponse(approval store.PendingApproval, decision string) any {
if isLegacyApprovalKind(approval.Kind) {
return map[string]any{"decision": legacyApprovalDecision(decision)}
}
if approval.Kind != "item/permissions/requestApproval" {
return map[string]any{"decision": decision}
}
@@ -2746,12 +2764,36 @@ func approvalResponse(approval store.PendingApproval, decision string) any {
}
}
func isLegacyApprovalKind(kind string) bool {
switch kind {
case "execCommandApproval", "applyPatchApproval":
return true
default:
return false
}
}
func legacyApprovalDecision(decision string) string {
switch decision {
case "accept":
return "approved"
case "acceptForSession":
return "approved_for_session"
case "decline":
return "denied"
case "cancel":
return "abort"
default:
return decision
}
}
func renderApprovalHTML(kind string, raw json.RawMessage, status string) string {
title := "Codex approval requested"
if strings.Contains(kind, "commandExecution") {
if strings.Contains(kind, "commandExecution") || kind == "execCommandApproval" {
title = "Codex requests command approval"
}
if strings.Contains(kind, "fileChange") {
if strings.Contains(kind, "fileChange") || kind == "applyPatchApproval" {
title = "Codex requests file change approval"
}
if strings.Contains(kind, "permissions") {
@@ -2764,7 +2806,7 @@ func renderApprovalHTML(kind string, raw json.RawMessage, status string) string
if reason, _ := params["reason"].(string); reason != "" {
lines = append(lines, "", reason)
}
for _, key := range []string{"command", "cwd", "grantRoot", "permissions"} {
for _, key := range []string{"command", "cwd", "grantRoot", "permissions", "fileChanges"} {
if value, ok := params[key]; ok {
lines = append(lines, fmt.Sprintf("%s: %s", argumentLabel(key), conciseValue(value)))
}
@@ -2806,7 +2848,7 @@ func renderApprovalDetailsHTML(kind string, raw json.RawMessage) string {
}
parts = append(parts, FieldHTML(label, text))
}
for _, key := range []string{"command", "cwd", "grantRoot", "permissions", "reason"} {
for _, key := range []string{"command", "cwd", "grantRoot", "permissions", "fileChanges", "parsedCmd", "reason"} {
if value, ok := params[key]; ok {
appendValue(argumentLabel(key), value)
}