234 lines
6.7 KiB
Go
234 lines
6.7 KiB
Go
package cli
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
|
|
"gitea.maximumdirect.net/eric/audita/internal/core/schema"
|
|
"gitea.maximumdirect.net/eric/audita/internal/framework/llm"
|
|
)
|
|
|
|
func sourceToCanonicalTranscript(source *schema.SourceTranscript) *schema.Transcript {
|
|
segments := make([]schema.Segment, len(source.Segments))
|
|
for i, s := range source.Segments {
|
|
id := i + 1
|
|
if s.ID != nil {
|
|
id = *s.ID
|
|
}
|
|
segments[i] = schema.Segment{
|
|
ID: id,
|
|
Speaker: s.Speaker,
|
|
Start: s.Start,
|
|
End: s.End,
|
|
Text: s.Text,
|
|
Categories: s.Categories,
|
|
}
|
|
}
|
|
return &schema.Transcript{Segments: segments}
|
|
}
|
|
|
|
// Run executes the Audita CLI with the provided arguments and streams.
|
|
func Run(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
|
if len(args) == 0 {
|
|
writeRootUsage(stdout)
|
|
return 0
|
|
}
|
|
if len(args) == 2 && args[0] == "help" {
|
|
switch args[1] {
|
|
case "process":
|
|
writeProcessUsage(stdout)
|
|
return 0
|
|
case "config":
|
|
writeConfigUsage(stdout)
|
|
return 0
|
|
}
|
|
}
|
|
|
|
if isHelpCommand(args) {
|
|
writeRootUsage(stdout)
|
|
return 0
|
|
}
|
|
|
|
if args[0] == "process" {
|
|
return runProcess(ctx, args[1:], stdout, stderr)
|
|
}
|
|
if args[0] == "config" {
|
|
return runConfig(ctx, args[1:], stdout, stderr)
|
|
}
|
|
|
|
fmt.Fprintf(stderr, "audita: unknown command %q\n\n", args[0])
|
|
writeRootUsage(stderr)
|
|
return 2
|
|
}
|
|
|
|
func runConfig(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
|
if len(args) == 0 || isHelpCommand(args) || args[0] == "--help" || args[0] == "-h" {
|
|
writeConfigUsage(stdout)
|
|
return 0
|
|
}
|
|
|
|
switch args[0] {
|
|
case "validate":
|
|
return runConfigValidate(ctx, args[1:], stdout, stderr)
|
|
case "print-effective":
|
|
return runConfigPrintEffective(ctx, args[1:], stdout, stderr)
|
|
default:
|
|
fmt.Fprintf(stderr, "audita config: unknown command %q\n\n", args[0])
|
|
writeConfigUsage(stderr)
|
|
return 2
|
|
}
|
|
}
|
|
|
|
func runConfigValidate(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
|
input, help, err := parseConfigInput("validate", args, stderr)
|
|
if err != nil {
|
|
fmt.Fprintf(stderr, "audita config validate: %s\n", configInputError(err))
|
|
return 2
|
|
}
|
|
if help {
|
|
writeConfigValidateUsage(stdout)
|
|
return 0
|
|
}
|
|
selected, err := loadConfigInput(input, "validate")
|
|
if err != nil {
|
|
fmt.Fprintf(stderr, "audita config validate: %s\n", configInputError(err))
|
|
return 2
|
|
}
|
|
if _, err := llm.NewRuntime(ctx, selected.Result.Config, selected.Path, nil); err != nil {
|
|
fmt.Fprintf(stderr, "audita config validate: %s\n", llm.RedactError(err, selected.Result.Config))
|
|
if llm.IsAssetError(err) {
|
|
return 1
|
|
}
|
|
return 2
|
|
}
|
|
fmt.Fprintln(stdout, "config is valid")
|
|
return 0
|
|
}
|
|
|
|
func runConfigPrintEffective(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
|
input, help, err := parseConfigInput("print-effective", args, stderr)
|
|
if err != nil {
|
|
fmt.Fprintf(stderr, "audita config print-effective: %s\n", configInputError(err))
|
|
return 2
|
|
}
|
|
if help {
|
|
writeConfigPrintEffectiveUsage(stdout)
|
|
return 0
|
|
}
|
|
selected, err := loadConfigInput(input, "print-effective")
|
|
if err != nil {
|
|
fmt.Fprintf(stderr, "audita config print-effective: %s\n", configInputError(err))
|
|
return 2
|
|
}
|
|
llmRuntime, err := llm.NewRuntime(ctx, selected.Result.Config, selected.Path, nil)
|
|
if err != nil {
|
|
fmt.Fprintf(stderr, "audita config print-effective: %s\n", llm.RedactError(err, selected.Result.Config))
|
|
if llm.IsAssetError(err) {
|
|
return 1
|
|
}
|
|
return 2
|
|
}
|
|
if input.View == "settings" {
|
|
err = selected.Result.WriteEffective(stdout)
|
|
} else {
|
|
var output []byte
|
|
if input.View == "profiles" {
|
|
output, err = llmRuntime.SelectedProfilesYAML()
|
|
} else {
|
|
output, err = llm.ExplanationYAML(selected.Result)
|
|
}
|
|
if err == nil {
|
|
_, err = stdout.Write(output)
|
|
}
|
|
}
|
|
if err != nil {
|
|
fmt.Fprintf(stderr, "audita config print-effective: %v\n", err)
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func isHelpCommand(args []string) bool {
|
|
if len(args) == 0 {
|
|
return false
|
|
}
|
|
if len(args) == 1 {
|
|
switch args[0] {
|
|
case "help", "-h", "--help":
|
|
return true
|
|
}
|
|
}
|
|
if len(args) == 2 && args[0] == "help" {
|
|
switch args[1] {
|
|
case "process":
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func writeRootUsage(w io.Writer) {
|
|
fmt.Fprintln(w, "Audita is a transcript processing CLI.")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "Usage:")
|
|
fmt.Fprintln(w, " audita <command> [options]")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "Commands:")
|
|
fmt.Fprintln(w, " process Process a transcript JSON file")
|
|
fmt.Fprintln(w, " config Validate and inspect config")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "Example:")
|
|
fmt.Fprintln(w, " audita process transcript.json --glossary glossary.yaml --output corrected.json")
|
|
}
|
|
|
|
func writeConfigUsage(w io.Writer) {
|
|
fmt.Fprintln(w, "Validate and inspect Audita config.")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "Usage:")
|
|
fmt.Fprintln(w, " audita config <command> [flags]")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "Commands:")
|
|
fmt.Fprintln(w, " validate Validate a versioned YAML config file")
|
|
fmt.Fprintln(w, " print-effective Print redacted effective settings YAML")
|
|
}
|
|
|
|
func writeConfigValidateUsage(w io.Writer) {
|
|
fmt.Fprintln(w, "Validate a versioned YAML config file.")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "Usage:")
|
|
fmt.Fprintln(w, " audita config validate --config <path> [--overlay <name>] [setting flags]")
|
|
}
|
|
|
|
func writeConfigPrintEffectiveUsage(w io.Writer) {
|
|
fmt.Fprintln(w, "Print redacted effective settings YAML.")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "Usage:")
|
|
fmt.Fprintln(w, " audita config print-effective [--config <path>] [--overlay <name>] [setting flags]")
|
|
}
|
|
|
|
func writeProcessUsage(w io.Writer) {
|
|
fmt.Fprintln(w, "Process a transcript JSON file.")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "Usage:")
|
|
fmt.Fprintln(w, " audita process <transcript.json> [flags]")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "Flags:")
|
|
for _, name := range []string{
|
|
"config", "overlay", "glossary", "output",
|
|
"proposal-profile", "validation-profile", "modules", "output-schema",
|
|
"validation-max-prompt-tokens", "target-sections", "max-section-tokens", "min-section-tokens",
|
|
"normalize-max-segment-gap", "normalize-ellipsis-gap", "normalize-max-segment-duration", "normalize-max-segment-tokens",
|
|
"glossary-confidence-threshold", "homophones-confidence-threshold", "spoken-word-confidence-threshold", "grammar-confidence-threshold",
|
|
"transcript-description", "work-dir",
|
|
} {
|
|
fmt.Fprintf(w, " --%s\n", name)
|
|
}
|
|
fmt.Fprintln(w, " --reporting[=true|false] Write the three-file report bundle (default true)")
|
|
fmt.Fprintln(w, " --report-dir DIR Select the report directory (stdout setting for stdout; output parent by default for files)")
|
|
fmt.Fprintln(w, " --debug[=true|false] Persist detailed diagnostics (default false)")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "Example:")
|
|
fmt.Fprintln(w, " audita process transcript.json --glossary glossary.yaml --output corrected.json")
|
|
}
|