mirror of
https://github.com/BaaRai/ARTEX.git
synced 2026-11-15 04:30:55 +08:00
The LLM fallback judge gets a closed mode (default when the judge is on): the model answers eight code-owned questions with yes|no|unknown and one evidence line each, in one call; the decision is taken in code. Every failure (invalid output, missing key, value outside the vocabulary, a failed call, arguments above the 256 KiB cap) is ask. The custom judge prompt becomes bounded operator-policy data (8000 runes). The answers are stored in the intercept audit and shown in the approval detail. freeform keeps the previous behaviour; defaultJudgeFailAction changes from allow to ask.
74 lines
2.8 KiB
Go
74 lines
2.8 KiB
Go
package intercept
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const reviewTextLimit = 4000
|
|
|
|
const BackgroundUserMessage = "user_message"
|
|
|
|
// ReviewBackground is explicitly bound from the current human message. Generated
|
|
// Worker summaries are not accepted. Background cannot override review policy.
|
|
type ReviewBackground struct {
|
|
Source string `json:"source"`
|
|
Text string `json:"text"`
|
|
Truncated bool `json:"truncated,omitempty"`
|
|
}
|
|
|
|
// ReviewInput contains only the current call and explicitly selected background.
|
|
// Execution history and call correlation belong to the separate audit record.
|
|
type ReviewInput struct {
|
|
Version int `json:"version"`
|
|
WorkingDir string `json:"working_directory,omitempty"`
|
|
Background *ReviewBackground `json:"background,omitempty"`
|
|
// OperatorPolicy is set in closed mode only: the operator's custom judge
|
|
// prompt, carried as bounded data for the operator_policy question.
|
|
OperatorPolicy *ReviewPolicy `json:"operator_policy,omitempty"`
|
|
Tool string `json:"tool_name"`
|
|
Arguments json.RawMessage `json:"arguments"`
|
|
}
|
|
|
|
type reviewContextKey struct{}
|
|
type reviewEnvironment struct {
|
|
workingDir string
|
|
background ReviewBackground
|
|
}
|
|
|
|
// WithReviewContext explicitly binds the permitted background for one run. Never
|
|
// fall back to the raw turn transcript: it may contain the full scheduler prompt.
|
|
// This is application wiring, not a model-callable tool.
|
|
func WithReviewContext(ctx context.Context, workingDir string, background ReviewBackground) context.Context {
|
|
return context.WithValue(ctx, reviewContextKey{}, reviewEnvironment{workingDir, background})
|
|
}
|
|
|
|
// WithReviewWorkingDirectory preserves only explicitly selected background.
|
|
// Chat runs can be human-initiated or scheduled, so the Agent must not infer
|
|
// message provenance from the text it receives.
|
|
func WithReviewWorkingDirectory(ctx context.Context, workingDir string) context.Context {
|
|
env, _ := ctx.Value(reviewContextKey{}).(reviewEnvironment)
|
|
env.workingDir = workingDir
|
|
return context.WithValue(ctx, reviewContextKey{}, env)
|
|
}
|
|
|
|
func BuildReviewInput(ctx context.Context, tool string, arguments json.RawMessage) (ReviewInput, error) {
|
|
if !json.Valid(arguments) {
|
|
return ReviewInput{}, fmt.Errorf("tool arguments are not valid JSON")
|
|
}
|
|
in := ReviewInput{Version: 4, Tool: tool, Arguments: append(json.RawMessage(nil), arguments...)}
|
|
if env, ok := ctx.Value(reviewContextKey{}).(reviewEnvironment); ok {
|
|
in.WorkingDir = env.workingDir
|
|
background := env.background
|
|
if background.Source == BackgroundUserMessage && strings.TrimSpace(background.Text) != "" {
|
|
var cut bool
|
|
background.Text, cut = bounded(background.Text, reviewTextLimit)
|
|
background.Truncated = background.Truncated || cut
|
|
in.Background = &background
|
|
}
|
|
}
|
|
return in, nil
|
|
}
|