diff --git a/internal/model/mock/mock.go b/internal/model/mock/mock.go index dfd6f19..bac52bd 100644 --- a/internal/model/mock/mock.go +++ b/internal/model/mock/mock.go @@ -26,12 +26,13 @@ func (b *Backend) Available(ctx context.Context) error { return nil } func (b *Backend) Complete(ctx context.Context, req model.CompleteRequest) (*model.Response, error) { if cmd := os.Getenv("INTENT_MOCK_CMD"); cmd != "" { return &model.Response{ - IntentSummary: "test-override", - Approach: model.ApproachCommand, - Command: cmd, - Description: "test-override command", - Risk: model.RiskDestructive, - Confidence: model.ConfidenceHigh, + IntentSummary: "test-override", + Approach: model.ApproachCommand, + Command: cmd, + Description: "test-override command", + Risk: model.RiskDestructive, + ExpectedRuntime: model.RuntimeInstant, + Confidence: model.ConfidenceHigh, }, nil } prompt := lastUser(req.Messages) diff --git a/internal/model/schema.go b/internal/model/schema.go index fccfe36..597ba0b 100644 --- a/internal/model/schema.go +++ b/internal/model/schema.go @@ -19,7 +19,7 @@ const SchemaJSON = `{ { "type": "object", "additionalProperties": false, - "required": ["approach", "command", "description", "risk"], + "required": ["approach", "command", "description", "risk", "expected_runtime", "confidence"], "properties": { "approach": { "const": "command" }, "command": { "type": "string", "minLength": 1 }, @@ -33,7 +33,7 @@ const SchemaJSON = `{ { "type": "object", "additionalProperties": false, - "required": ["approach", "script", "description", "risk"], + "required": ["approach", "script", "description", "risk", "expected_runtime", "confidence"], "properties": { "approach": { "const": "script" }, "script": { diff --git a/internal/model/types.go b/internal/model/types.go index 7bdead4..737bc87 100644 --- a/internal/model/types.go +++ b/internal/model/types.go @@ -127,6 +127,12 @@ func (r *Response) Validate() error { if r.Risk == "" { return fmt.Errorf("approach=command requires risk") } + if r.ExpectedRuntime == "" { + return fmt.Errorf("approach=command requires expected_runtime") + } + if r.Confidence == "" { + return fmt.Errorf("approach=command requires confidence") + } case ApproachScript: if r.Script == nil || r.Script.Body == "" { return fmt.Errorf("approach=script requires script.body") @@ -137,6 +143,12 @@ func (r *Response) Validate() error { if r.Risk == "" { return fmt.Errorf("approach=script requires risk") } + if r.ExpectedRuntime == "" { + return fmt.Errorf("approach=script requires expected_runtime") + } + if r.Confidence == "" { + return fmt.Errorf("approach=script requires confidence") + } case ApproachToolCall: if r.ToolCall == nil || r.ToolCall.Name == "" { return fmt.Errorf("approach=tool_call requires tool_call.name") diff --git a/internal/model/types_test.go b/internal/model/types_test.go new file mode 100644 index 0000000..608d76a --- /dev/null +++ b/internal/model/types_test.go @@ -0,0 +1,49 @@ +package model + +import "testing" + +func TestResponseValidateCommandRequiresRuntimeAndConfidence(t *testing.T) { + base := &Response{ + Approach: ApproachCommand, + Command: "ls -la", + Description: "List files.", + Risk: RiskSafe, + } + + if err := base.Validate(); err == nil || err.Error() != "approach=command requires expected_runtime" { + t.Fatalf("expected missing-runtime error, got: %v", err) + } + + base.ExpectedRuntime = RuntimeInstant + if err := base.Validate(); err == nil || err.Error() != "approach=command requires confidence" { + t.Fatalf("expected missing-confidence error, got: %v", err) + } + + base.Confidence = ConfidenceHigh + if err := base.Validate(); err != nil { + t.Fatalf("expected command response to validate, got: %v", err) + } +} + +func TestResponseValidateScriptRequiresRuntimeAndConfidence(t *testing.T) { + base := &Response{ + Approach: ApproachScript, + Script: &Script{Interpreter: "bash", Body: "echo hi"}, + Description: "Print text.", + Risk: RiskSafe, + } + + if err := base.Validate(); err == nil || err.Error() != "approach=script requires expected_runtime" { + t.Fatalf("expected missing-runtime error, got: %v", err) + } + + base.ExpectedRuntime = RuntimeInstant + if err := base.Validate(); err == nil || err.Error() != "approach=script requires confidence" { + t.Fatalf("expected missing-confidence error, got: %v", err) + } + + base.Confidence = ConfidenceMedium + if err := base.Validate(); err != nil { + t.Fatalf("expected script response to validate, got: %v", err) + } +}