Add prompt inspection command
This commit is contained in:
71
internal/format/inspection.go
Normal file
71
internal/format/inspection.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package format
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"gitea.maximumdirect.net/eric/promptkit"
|
||||
)
|
||||
|
||||
type PromptInspection struct {
|
||||
PromptID string `json:"prompt_id"`
|
||||
PromptVersion string `json:"prompt_version"`
|
||||
PromptHash string `json:"prompt_hash"`
|
||||
DefaultProfileID string `json:"default_profile_id"`
|
||||
Inputs []PromptInspectionInput `json:"inputs"`
|
||||
OutputContract OutputContract `json:"output_contract"`
|
||||
}
|
||||
|
||||
type PromptInspectionInput struct {
|
||||
Name string `json:"name"`
|
||||
Required bool `json:"required"`
|
||||
ContentType string `json:"content_type"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type OutputContract struct {
|
||||
Format string `json:"format"`
|
||||
ValidationMode string `json:"validation_mode"`
|
||||
SchemaPath string `json:"schema_path"`
|
||||
RepairAttempts int `json:"repair_attempts"`
|
||||
}
|
||||
|
||||
func FormatPromptInspection(value *promptkit.PromptInspection, outputFormat OutputFormat) ([]byte, error) {
|
||||
if value == nil {
|
||||
return nil, errors.New("prompt inspection is nil")
|
||||
}
|
||||
dto := PromptInspection{
|
||||
PromptID: value.PromptID, PromptVersion: value.PromptVersion, PromptHash: value.PromptHash, DefaultProfileID: value.DefaultProfileID,
|
||||
Inputs: make([]PromptInspectionInput, len(value.Inputs)),
|
||||
OutputContract: OutputContract{Format: string(value.OutputContract.Format), ValidationMode: string(value.OutputContract.ValidationMode), SchemaPath: value.OutputContract.SchemaPath, RepairAttempts: value.OutputContract.RepairAttempts},
|
||||
}
|
||||
for i, input := range value.Inputs {
|
||||
dto.Inputs[i] = PromptInspectionInput{Name: input.Name, Required: input.Required, ContentType: input.ContentType, Description: input.Description}
|
||||
}
|
||||
switch outputFormat {
|
||||
case OutputFormatJSON:
|
||||
data, err := json.MarshalIndent(dto, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(data, '\n'), nil
|
||||
case OutputFormatText:
|
||||
var b bytes.Buffer
|
||||
fmt.Fprintf(&b, "prompt_id: %s\nprompt_version: %s\nprompt_hash: %s\ndefault_profile_id: %s\ninputs:", dto.PromptID, dto.PromptVersion, dto.PromptHash, dto.DefaultProfileID)
|
||||
if len(dto.Inputs) == 0 {
|
||||
fmt.Fprintln(&b, " []")
|
||||
} else {
|
||||
fmt.Fprintln(&b)
|
||||
for _, input := range dto.Inputs {
|
||||
fmt.Fprintf(&b, " - name: %s\n required: %t\n content_type: %s\n description: %s\n", input.Name, input.Required, input.ContentType, strconv.Quote(input.Description))
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(&b, "output_contract:\n format: %s\n validation_mode: %s\n schema_path: %s\n repair_attempts: %d\n", dto.OutputContract.Format, dto.OutputContract.ValidationMode, dto.OutputContract.SchemaPath, dto.OutputContract.RepairAttempts)
|
||||
return b.Bytes(), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: %q", ErrUnknownPreparedRunFormat, outputFormat)
|
||||
}
|
||||
}
|
||||
32
internal/format/inspection_test.go
Normal file
32
internal/format/inspection_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package format
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.maximumdirect.net/eric/promptkit"
|
||||
)
|
||||
|
||||
func TestFormatPromptInspectionPreservesDeclaredOrderAndEmptyValues(t *testing.T) {
|
||||
value := &promptkit.PromptInspection{PromptID: "p", PromptVersion: "1", PromptHash: "hash", Inputs: []promptkit.PromptInputDefinition{{Name: "first", Required: true, ContentType: "text/plain", Description: "first input"}, {Name: "second"}}, OutputContract: promptkit.OutputContract{Format: "text", ValidationMode: promptkit.ValidationNone}}
|
||||
text, err := FormatPromptInspection(value, OutputFormatText)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(string(text), "default_profile_id: \ninputs:\n - name: first") || strings.Index(string(text), "name: first") > strings.Index(string(text), "name: second") {
|
||||
t.Fatalf("unexpected text inspection: %s", text)
|
||||
}
|
||||
jsonOutput, err := FormatPromptInspection(value, OutputFormatJSON)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.HasSuffix(string(jsonOutput), "\n") || !strings.Contains(string(jsonOutput), `"default_profile_id": ""`) {
|
||||
t.Fatalf("unexpected json inspection: %s", jsonOutput)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatPromptInspectionRejectsNil(t *testing.T) {
|
||||
if _, err := FormatPromptInspection(nil, OutputFormatText); err == nil {
|
||||
t.Fatal("expected nil inspection error")
|
||||
}
|
||||
}
|
||||
@@ -14,14 +14,24 @@ import (
|
||||
|
||||
var ErrUnknownPreparedRunFormat = errors.New("unknown prepared run format")
|
||||
|
||||
// PreparedRunOutputFormat is the output format for prepared render data.
|
||||
type PreparedRunOutputFormat string
|
||||
// OutputFormat selects an application-owned textual or JSON representation.
|
||||
type OutputFormat string
|
||||
|
||||
const (
|
||||
PreparedRunFormatText PreparedRunOutputFormat = "text"
|
||||
PreparedRunFormatJSON PreparedRunOutputFormat = "json"
|
||||
OutputFormatText OutputFormat = "text"
|
||||
OutputFormatJSON OutputFormat = "json"
|
||||
|
||||
DefaultPreparedRunOutputFormat PreparedRunOutputFormat = PreparedRunFormatText
|
||||
DefaultOutputFormat OutputFormat = OutputFormatText
|
||||
)
|
||||
|
||||
// PreparedRunOutputFormat is the output format for prepared render data.
|
||||
type PreparedRunOutputFormat = OutputFormat
|
||||
|
||||
const (
|
||||
PreparedRunFormatText = OutputFormatText
|
||||
PreparedRunFormatJSON = OutputFormatJSON
|
||||
|
||||
DefaultPreparedRunOutputFormat = DefaultOutputFormat
|
||||
)
|
||||
|
||||
// PreparedRunFormatter serializes a prepared run without performing use case work.
|
||||
@@ -31,15 +41,20 @@ type PreparedRunFormatter interface {
|
||||
|
||||
// ParsePreparedRunOutputFormat parses a format name.
|
||||
func ParsePreparedRunOutputFormat(raw string) (PreparedRunOutputFormat, error) {
|
||||
switch PreparedRunOutputFormat(strings.ToLower(strings.TrimSpace(raw))) {
|
||||
return ParseOutputFormat(raw)
|
||||
}
|
||||
|
||||
// ParseOutputFormat parses the shared inspection and prepared-run format names.
|
||||
func ParseOutputFormat(raw string) (OutputFormat, error) {
|
||||
switch OutputFormat(strings.ToLower(strings.TrimSpace(raw))) {
|
||||
case "":
|
||||
return DefaultPreparedRunOutputFormat, nil
|
||||
case PreparedRunFormatText:
|
||||
return PreparedRunFormatText, nil
|
||||
case PreparedRunFormatJSON:
|
||||
return PreparedRunFormatJSON, nil
|
||||
return DefaultOutputFormat, nil
|
||||
case OutputFormatText:
|
||||
return OutputFormatText, nil
|
||||
case OutputFormatJSON:
|
||||
return OutputFormatJSON, nil
|
||||
default:
|
||||
return "", fmt.Errorf("%w: %q (supported: %s, %s)", ErrUnknownPreparedRunFormat, raw, PreparedRunFormatText, PreparedRunFormatJSON)
|
||||
return "", fmt.Errorf("%w: %q (supported: %s, %s)", ErrUnknownPreparedRunFormat, raw, OutputFormatText, OutputFormatJSON)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user