Ctrl K
ComunidadGuías…

internal/approvalgate/schedule_answer.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package approvalgate

import (
	"context"
	"log/slog"
	"strings"

	acp "github.com/coder/acp-go-sdk"

	"github.com/yeomyeonggeori/blueclaw/internal/mcpserver"
	"github.com/yeomyeonggeori/blueclaw/internal/task"
	"github.com/yeomyeonggeori/blueprotocol/agentcontract"
	"github.com/yeomyeonggeori/blueprotocol/holdrecord"
)

const scheduleApprovalSource = "schedule"

type Schedules interface {
	ScheduleApprovedCall(context.Context, task.ApprovedCallScheduleRequest) (task.Schedule, error)
	ScheduleByID(scheduleID string) (task.Schedule, bool, error)
}

func (gate *Gate) UseSchedules(schedules Schedules) {
	gate.schedules = schedules
}

func (gate *Gate) isAnsweredByItsSchedule(approvalRequest mcpserver.ApprovalRequest) bool {
	scheduleID, isScheduleRun := task.ScheduleIDOfSession(approvalRequest.ConversationID)
	if !isScheduleRun || gate.schedules == nil || strings.TrimSpace(approvalRequest.TaskRunID) == "" {
		return false
	}
	schedule, isFound, errorValue := gate.schedules.ScheduleByID(scheduleID)
	if errorValue != nil {
		slog.Warn("approvalgate.schedule_unreadable", "scheduleID", scheduleID, "reason", errorValue.Error())
		return false
	}
	return isFound && schedule.IsApproved() && schedule.CreatorPersonID == strings.TrimSpace(approvalRequest.RequesterPersonID)
}

func (gate *Gate) approvedByItsSchedule(taskRunID string, approvalRequest mcpserver.ApprovalRequest, resolution ApprovalTargetResolution) mcpserver.ApprovalOutcome {
	gate.holdApprovedByItsSchedule(taskRunID, agentcontract.HeldCall{
		ToolName:          approvalRequest.ToolName,
		ToolInput:         approvalRequest.ToolInput,
		ApprovedToolInput: narrowedToolInput(approvalRequest.ToolInput, resolution.Target),
		HarnessSession:    approvalRequest.HarnessSession,
	})
	return gate.approvedOutcome(taskRunID, approvalRequest)
}

func (gate *Gate) harnessAllowedByItsSchedule(taskRunID string, heldCall agentcontract.HeldCall, options []acp.PermissionOption) (acp.RequestPermissionOutcome, bool) {
	allowOnce, isOffered := optionOfKind(options, acp.PermissionOptionKindAllowOnce)
	if !isOffered {
		return acp.RequestPermissionOutcome{}, false
	}
	gate.holdApprovedByItsSchedule(taskRunID, heldCall)
	return acp.RequestPermissionOutcome{Selected: &acp.RequestPermissionOutcomeSelected{Outcome: "selected", OptionId: allowOnce.OptionId}}, true
}

func (gate *Gate) holdApprovedByItsSchedule(taskRunID string, heldCall agentcontract.HeldCall) {
	hold := holdrecord.Open(gate.taskRunService, taskRunID, heldCall, nil)
	holdrecord.Decide(gate.taskRunService, taskRunID, hold.ID, holdrecord.DecisionApprove, scheduleApprovalSource)
}