Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions internal/adapter/checkstyle/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,17 @@ func (c *Converter) ConvertRules(ctx context.Context, rules []schema.UserRule, l
// Separate modules into Checker-level and TreeWalker-level
// Checker-level modules (NOT under TreeWalker)
checkerLevelModules := map[string]bool{
"LineLength": true,
"FileLength": true,
"FileTabCharacter": true,
"NewlineAtEndOfFile": true,
"UniqueProperties": true,
"OrderedProperties": true,
"Translation": true,
"SuppressWarningsFilter": true,
"LineLength": true,
"FileLength": true,
"FileTabCharacter": true,
"NewlineAtEndOfFile": true,
"UniqueProperties": true,
"OrderedProperties": true,
"Translation": true,
"SuppressWarningsFilter": true,
"BeforeExecutionExclusionFileFilter": true,
"SuppressionFilter": true,
"SuppressionCommentFilter": true,
"SuppressionFilter": true,
"SuppressionCommentFilter": true,
}

var checkerModules []checkstyleModule
Expand Down Expand Up @@ -255,8 +255,8 @@ Output:

userPrompt := fmt.Sprintf("Convert this Java rule to Checkstyle module:\n\n%s", rule.Say)

// Call LLM with power model + low reasoning
response, err := llmClient.Request(systemPrompt, userPrompt).WithPower(llm.ReasoningMinimal).Execute(ctx)
// Call LLM with minimal complexity
response, err := llmClient.Request(systemPrompt, userPrompt).WithComplexity(llm.ComplexityMinimal).Execute(ctx)
if err != nil {
return nil, fmt.Errorf("LLM call failed: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/adapter/eslint/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ Output:
userPrompt += fmt.Sprintf("\nSeverity: %s", rule.Severity)
}

// Call LLM with power model + low reasoning
response, err := llmClient.Request(systemPrompt, userPrompt).WithPower(llm.ReasoningMinimal).Execute(ctx)
// Call LLM with minimal complexity
response, err := llmClient.Request(systemPrompt, userPrompt).WithComplexity(llm.ComplexityMinimal).Execute(ctx)
if err != nil {
return "", nil, fmt.Errorf("LLM call failed: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/adapter/pmd/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ IMPORTANT: Return ONLY the JSON object. Do NOT include description, message, or

userPrompt := fmt.Sprintf("Convert this Java rule to PMD rule reference:\n\n%s", rule.Say)

// Call LLM with power model + low reasoning
response, err := llmClient.Request(systemPrompt, userPrompt).WithPower(llm.ReasoningMinimal).Execute(ctx)
// Call LLM with minimal complexity
response, err := llmClient.Request(systemPrompt, userPrompt).WithComplexity(llm.ComplexityMinimal).Execute(ctx)
if err != nil {
return nil, fmt.Errorf("LLM call failed: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/adapter/prettier/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ Output:
userPrompt := fmt.Sprintf("Convert this rule to Prettier configuration:\n\n%s", rule.Say)

// Call LLM
response, err := llmClient.Request(systemPrompt, userPrompt).WithPower(llm.ReasoningMinimal).Execute(ctx)
response, err := llmClient.Request(systemPrompt, userPrompt).WithComplexity(llm.ComplexityMinimal).Execute(ctx)
if err != nil {
return nil, fmt.Errorf("LLM call failed: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/adapter/pylint/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ Output:
}

// Call LLM
response, err := llmClient.Request(systemPrompt, userPrompt).WithPower(llm.ReasoningMinimal).Execute(ctx)
response, err := llmClient.Request(systemPrompt, userPrompt).WithComplexity(llm.ComplexityMinimal).Execute(ctx)
if err != nil {
return "", nil, fmt.Errorf("LLM call failed: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/adapter/tsc/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Output:
userPrompt := fmt.Sprintf("Convert this rule to TypeScript compiler configuration:\n\n%s", rule.Say)

// Call LLM
response, err := llmClient.Request(systemPrompt, userPrompt).WithPower(llm.ReasoningMinimal).Execute(ctx)
response, err := llmClient.Request(systemPrompt, userPrompt).WithComplexity(llm.ComplexityMinimal).Execute(ctx)
if err != nil {
return nil, fmt.Errorf("LLM call failed: %w", err)
}
Expand Down
5 changes: 0 additions & 5 deletions internal/cmd/api_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ func promptAPIKeySetup() {
promptAPIKeyConfiguration(false)
}

// promptAPIKeyIfNeeded checks if OpenAI API key is configured and prompts if not
func promptAPIKeyIfNeeded() {
promptAPIKeyConfiguration(true)
}

// promptAPIKeyConfiguration handles API key configuration with optional existence check
func promptAPIKeyConfiguration(checkExisting bool) {
envPath := filepath.Join(".sym", ".env")
Expand Down
17 changes: 10 additions & 7 deletions internal/cmd/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ map them to appropriate linter rules.`,
# Convert for specific linter
sym convert -i user-policy.json --targets eslint

# Convert for Java with specific model
sym convert -i user-policy.json --targets checkstyle,pmd --openai-model gpt-5-mini
Comment on lines +45 to +46
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The help text still references a removed flag --openai-model gpt-5-mini. This flag was removed (as seen in the diff at line 58), but the example at line 44 still mentions it. Update the example to remove this reference.

Suggested change
# Convert for Java with specific model
sym convert -i user-policy.json --targets checkstyle,pmd --openai-model gpt-5-mini
# Convert for Java
sym convert -i user-policy.json --targets checkstyle,pmd

Copilot uses AI. Check for mistakes.
# Convert for Java with specific model
sym convert -i user-policy.json --targets checkstyle,pmd --openai-model gpt-5-mini

Expand Down Expand Up @@ -131,18 +133,19 @@ func runNewConverter(userPolicy *schema.UserPolicy) error {
convertOutputDir = ".sym"
}

// Setup OpenAI client
apiKey, err := getAPIKey()
if err != nil {
return fmt.Errorf("OpenAI API key required: %w", err)
}

timeout := time.Duration(convertTimeout) * time.Second
llmClient := llm.NewClient(
apiKey,
llm.WithTimeout(timeout),
)

// Ensure at least one backend is available (MCP/CLI/API)
availabilityCtx, cancelAvailability := context.WithTimeout(context.Background(), timeout)
defer cancelAvailability()

if err := llmClient.CheckAvailability(availabilityCtx); err != nil {
return fmt.Errorf("no available LLM backend for convert: %w\nTip: run 'sym init --setup-llm' or configure LLM_BACKEND / LLM_CLI / OPENAI_API_KEY in .sym/.env", err)
}

// Create new converter
conv := converter.NewConverter(llmClient, convertOutputDir)

Expand Down
33 changes: 22 additions & 11 deletions internal/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,23 @@ This command:
}

var (
initForce bool
skipMCPRegister bool
registerMCPOnly bool
skipAPIKey bool
setupAPIKeyOnly bool
initForce bool
skipMCPRegister bool
registerMCPOnly bool
skipAPIKey bool
setupAPIKeyOnly bool
skipLLMSetup bool
setupLLMOnly bool
)

func init() {
initCmd.Flags().BoolVarP(&initForce, "force", "f", false, "Overwrite existing roles.json")
initCmd.Flags().BoolVar(&skipMCPRegister, "skip-mcp", false, "Skip MCP server registration prompt")
initCmd.Flags().BoolVar(&registerMCPOnly, "register-mcp", false, "Register MCP server only (skip roles/policy init)")
initCmd.Flags().BoolVar(&skipAPIKey, "skip-api-key", false, "Skip OpenAI API key configuration prompt")
initCmd.Flags().BoolVar(&setupAPIKeyOnly, "setup-api-key", false, "Setup OpenAI API key only (skip roles/policy init)")
initCmd.Flags().BoolVar(&skipAPIKey, "skip-api-key", false, "Skip OpenAI API key configuration prompt (deprecated, use --skip-llm)")
initCmd.Flags().BoolVar(&setupAPIKeyOnly, "setup-api-key", false, "Setup OpenAI API key only (deprecated, use --setup-llm)")
initCmd.Flags().BoolVar(&skipLLMSetup, "skip-llm", false, "Skip LLM backend configuration prompt")
initCmd.Flags().BoolVar(&setupLLMOnly, "setup-llm", false, "Setup LLM backend only (skip roles/policy init)")
}

func runInit(cmd *cobra.Command, args []string) {
Expand All @@ -56,13 +60,20 @@ func runInit(cmd *cobra.Command, args []string) {
return
}

// API key setup only mode
// API key setup only mode (deprecated)
if setupAPIKeyOnly {
fmt.Println("🔑 Setting up OpenAI API key...")
promptAPIKeySetup()
return
}

// LLM setup only mode
if setupLLMOnly {
fmt.Println("🤖 Setting up LLM backend...")
promptLLMBackendSetup()
return
}

// Check if logged in
if !config.IsLoggedIn() {
fmt.Println("❌ Not logged in")
Expand Down Expand Up @@ -156,9 +167,9 @@ func runInit(cmd *cobra.Command, args []string) {
promptMCPRegistration()
}

// API key configuration prompt
if !skipAPIKey {
promptAPIKeyIfNeeded()
// LLM backend configuration prompt
if !skipLLMSetup && !skipAPIKey {
promptLLMBackendSetup()
}

// Show dashboard guide after all initialization is complete
Expand Down
Loading