Skip to content

Commit 19e4a41

Browse files
authored
refactor(tool): migrate ProjectVerify/Refactor/Schedule×3/SearchX/SessionQuery/SmartReader to typed schemas (#330)
1 parent dff69f6 commit 19e4a41

7 files changed

Lines changed: 353 additions & 264 deletions

File tree

‎internal/tool/project_verify.go‎

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,37 +19,41 @@ import (
1919
// to guess a build or test command.
2020
type ProjectVerifyTool struct{}
2121

22+
// ProjectVerifyInput is the typed input for ProjectVerifyTool.
23+
type ProjectVerifyInput struct {
24+
Action string `json:"action"`
25+
Path string `json:"path"`
26+
TimeoutSeconds int `json:"timeout_seconds"`
27+
}
28+
2229
func (ProjectVerifyTool) Name() string { return "ProjectVerify" }
2330
func (ProjectVerifyTool) RiskLevel() string { return "medium" }
2431
func (ProjectVerifyTool) Aliases() []string { return []string{"project-verify", "verify_project"} }
2532
func (ProjectVerifyTool) Description() string {
2633
return "Detect the project stack and run bounded build, test, lint, or format checks using fixed argument lists (no shell interpolation). Returns structured results with exit codes and durations."
2734
}
2835

29-
func (ProjectVerifyTool) Parameters() map[string]interface{} {
30-
return map[string]interface{}{
31-
"type": "object",
32-
"properties": map[string]interface{}{
33-
"action": map[string]interface{}{
34-
"type": "string",
35-
"enum": []string{"detect", "build", "test", "lint", "format", "all"},
36-
"description": "Verification action. detect only inspects files; all runs build, test, lint, and format checks that are available.",
37-
},
38-
"path": map[string]interface{}{
39-
"type": "string",
40-
"description": "Project directory (default: session working directory).",
41-
},
42-
"timeout_seconds": map[string]interface{}{
43-
"type": "integer",
44-
"minimum": 1,
45-
"maximum": 600,
46-
"description": "Per-command timeout (default 120 seconds, max 600).",
47-
},
36+
// Schema returns the typed input schema. Parameters() delegates to it so the
37+
// two cannot diverge.
38+
func (ProjectVerifyTool) Schema() ToolSchema {
39+
return ToolSchema{
40+
Type: "object",
41+
Properties: map[string]SchemaProperty{
42+
"action": {Type: "string", Enum: []interface{}{"detect", "build", "test", "lint", "format", "all"}, Description: "Verification action. detect only inspects files; all runs build, test, lint, and format checks that are available."},
43+
"path": {Type: "string", Description: "Project directory (default: session working directory)."},
44+
"timeout_seconds": {Type: "integer", Minimum: 1, Maximum: 600, Description: "Per-command timeout (default 120 seconds, max 600)."},
4845
},
49-
"required": []string{"action"},
46+
Required: []string{"action"},
5047
}
5148
}
5249

50+
func (ProjectVerifyTool) Parameters() map[string]interface{} {
51+
return projectVerifySchema.ToJSONSchema()
52+
}
53+
54+
// projectVerifySchema is the single source of truth for ProjectVerify's input schema.
55+
var projectVerifySchema = ProjectVerifyTool{}.Schema()
56+
5357
type projectStack struct {
5458
Root string `json:"root"`
5559
Markers []string `json:"markers"`
@@ -67,13 +71,9 @@ type verificationResult struct {
6771
}
6872

6973
func (ProjectVerifyTool) Execute(ctx context.Context, input json.RawMessage) (string, error) {
70-
var params struct {
71-
Action string `json:"action"`
72-
Path string `json:"path"`
73-
TimeoutSeconds int `json:"timeout_seconds"`
74-
}
75-
if err := json.Unmarshal(input, &params); err != nil {
76-
return "", fmt.Errorf("invalid input: %w", err)
74+
params, err := DecodeInput[ProjectVerifyInput]("ProjectVerify", input)
75+
if err != nil {
76+
return "", err
7777
}
7878
params.Action = strings.ToLower(strings.TrimSpace(params.Action))
7979
if params.Action == "" {

‎internal/tool/refactor.go‎

Lines changed: 46 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -772,95 +772,61 @@ func NewRefactorTool() *RefactorTool {
772772
}
773773

774774
func (RefactorTool) Name() string { return "Refactor" }
775+
776+
// RefactorInput is the typed input for RefactorTool.
777+
type RefactorInput struct {
778+
Action string `json:"action"`
779+
File string `json:"file"`
780+
StartLine int `json:"start_line"`
781+
EndLine int `json:"end_line"`
782+
NewName string `json:"new_name"`
783+
OldName string `json:"old_name"`
784+
Line int `json:"line"`
785+
Expr string `json:"expr"`
786+
VarName string `json:"var_name"`
787+
Context string `json:"context"`
788+
TestFunc string `json:"test_func"`
789+
FuncName string `json:"func_name"`
790+
}
791+
775792
func (RefactorTool) Description() string {
776793
return "Apply common refactoring patterns (extract function, rename symbol, inline variable, extract variable, add error check, wrap with context, convert to table test, sort imports, remove unused params) without LLM calls."
777794
}
778795

779-
func (RefactorTool) Parameters() map[string]interface{} {
780-
return map[string]interface{}{
781-
"type": "object",
782-
"properties": map[string]interface{}{
783-
"action": map[string]interface{}{
784-
"type": "string",
785-
"description": "Refactoring action: extract_function, rename_symbol, inline_variable, extract_variable, add_error_check, wrap_with_context, convert_table_test, sort_imports, remove_unused_params",
786-
"enum": []string{
787-
"extract_function",
788-
"rename_symbol",
789-
"inline_variable",
790-
"extract_variable",
791-
"add_error_check",
792-
"wrap_with_context",
793-
"convert_table_test",
794-
"sort_imports",
795-
"remove_unused_params",
796-
},
797-
},
798-
"file": map[string]interface{}{
799-
"type": "string",
800-
"description": "Absolute path to the file to refactor",
801-
},
802-
"start_line": map[string]interface{}{
803-
"type": "integer",
804-
"description": "Start line (1-based) for extract_function",
805-
},
806-
"end_line": map[string]interface{}{
807-
"type": "integer",
808-
"description": "End line (1-based) for extract_function",
809-
},
810-
"new_name": map[string]interface{}{
811-
"type": "string",
812-
"description": "New name for extract_function or rename_symbol",
813-
},
814-
"old_name": map[string]interface{}{
815-
"type": "string",
816-
"description": "Old symbol name for rename_symbol",
817-
},
818-
"line": map[string]interface{}{
819-
"type": "integer",
820-
"description": "Line number for inline_variable, extract_variable, add_error_check, or wrap_with_context",
821-
},
822-
"expr": map[string]interface{}{
823-
"type": "string",
824-
"description": "Expression to extract for extract_variable",
825-
},
826-
"var_name": map[string]interface{}{
827-
"type": "string",
828-
"description": "Variable name for extract_variable",
829-
},
830-
"context": map[string]interface{}{
831-
"type": "string",
832-
"description": "Context message for wrap_with_context",
833-
},
834-
"test_func": map[string]interface{}{
835-
"type": "string",
836-
"description": "Test function name for convert_table_test",
837-
},
838-
"func_name": map[string]interface{}{
839-
"type": "string",
840-
"description": "Function name for remove_unused_params",
841-
},
796+
// Schema returns the typed input schema. Parameters() delegates to it so the
797+
// two cannot diverge.
798+
func (RefactorTool) Schema() ToolSchema {
799+
return ToolSchema{
800+
Type: "object",
801+
Properties: map[string]SchemaProperty{
802+
"action": {Type: "string", Enum: []interface{}{"extract_function", "rename_symbol", "inline_variable", "extract_variable", "add_error_check", "wrap_with_context", "convert_table_test", "sort_imports", "remove_unused_params"}, Description: "Refactoring action: extract_function, rename_symbol, inline_variable, extract_variable, add_error_check, wrap_with_context, convert_table_test, sort_imports, remove_unused_params"},
803+
"file": {Type: "string", Description: "Absolute path to the file to refactor"},
804+
"start_line": {Type: "integer", Description: "Start line (1-based) for extract_function"},
805+
"end_line": {Type: "integer", Description: "End line (1-based) for extract_function"},
806+
"new_name": {Type: "string", Description: "New name for extract_function or rename_symbol"},
807+
"old_name": {Type: "string", Description: "Old symbol name for rename_symbol"},
808+
"line": {Type: "integer", Description: "Line number for inline_variable, extract_variable, add_error_check, or wrap_with_context"},
809+
"expr": {Type: "string", Description: "Expression to extract for extract_variable"},
810+
"var_name": {Type: "string", Description: "Variable name for extract_variable"},
811+
"context": {Type: "string", Description: "Context message for wrap_with_context"},
812+
"test_func": {Type: "string", Description: "Test function name for convert_table_test"},
813+
"func_name": {Type: "string", Description: "Function name for remove_unused_params"},
842814
},
843-
"required": []string{"action", "file"},
815+
Required: []string{"action", "file"},
844816
}
845817
}
846818

819+
func (RefactorTool) Parameters() map[string]interface{} {
820+
return refactorSchema.ToJSONSchema()
821+
}
822+
823+
// refactorSchema is the single source of truth for Refactor's input schema.
824+
var refactorSchema = RefactorTool{}.Schema()
825+
847826
func (rt RefactorTool) Execute(ctx context.Context, input json.RawMessage) (string, error) {
848-
var p struct {
849-
Action string `json:"action"`
850-
File string `json:"file"`
851-
StartLine int `json:"start_line"`
852-
EndLine int `json:"end_line"`
853-
NewName string `json:"new_name"`
854-
OldName string `json:"old_name"`
855-
Line int `json:"line"`
856-
Expr string `json:"expr"`
857-
VarName string `json:"var_name"`
858-
Context string `json:"context"`
859-
TestFunc string `json:"test_func"`
860-
FuncName string `json:"func_name"`
861-
}
862-
if err := json.Unmarshal(input, &p); err != nil {
863-
return "", fmt.Errorf("invalid input: %w", err)
827+
p, err := DecodeInput[RefactorInput]("Refactor", input)
828+
if err != nil {
829+
return "", err
864830
}
865831
if p.Action == "" {
866832
return "", fmt.Errorf("action is required")
@@ -874,7 +840,6 @@ func (rt RefactorTool) Execute(ctx context.Context, input json.RawMessage) (stri
874840

875841
ref := rt.refactorer
876842
var result *RefactoringResult
877-
var err error
878843

879844
switch p.Action {
880845
case "extract_function":

0 commit comments

Comments
 (0)