Handle legacy Codex approval requests
This commit is contained in:
@@ -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, ¶ms); 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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user