Layr-Labs / Layr-Labs/devkit-cli
Command Guardrails for handling out of sequence cli commands and context aware error messages
@supernovahs ci sta già lavorando.
Dal 21/5/2025.
- Lingua principale
- Go
- Stelle
- 27
- Fork
- 10
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
# Command Flow Guardrails: Dependency Management for CLI Commands
## Overview
Command Flow Guardrails detect when CLI commands are run out of expected sequence and provide context-aware error messages to guide users. This feature ensures commands like `avs call` (which depends on `avs contract-deploy`) fail gracefully with helpful guidance.
## Key Components
1. **Command Dependency Definitions**: Map of commands to their prerequisites
2. **Command History Tracking**: In-memory registry of executed commands
3. **Dependency Checking Middleware**: Validates dependencies before execution
4. **Contextual Error Messages**: Guides users to the correct next actions
## Implementation
### 1. Command Dependency Definition
```go
// CommandDependency defines a command dependency relationship
type CommandDependency struct {
Command string // Command that has dependencies
DependsOn []string // Commands that must be run before this command
ErrorMessage string // Helpful message when dependency isn't met
CheckFunc func() bool // Optional additional validation
}
// Sample dependencies
var CommandFlowDependencies = []CommandDependency{
{
Command: "call",
DependsOn: []string{"deploy-contracts"},
ErrorMessage: "The 'avs call' command requires contract deployment. " +
"Please run 'devkit avs devnet start' or 'devkit avs devnet deploy-contracts' first.",
CheckFunc: checkContractsDeployed,
},
// Other dependencies...
}
```
### 2. Command Execution Tracking
```go
// Track command execution history
var commandHistory = struct {
executedCommands map[string]bool
mu sync.Mutex
}{
executedCommands: make(map[string]bool),
}
// Record successful command execution
func recordCommandExecution(command string) {
commandHistory.mu.Lock()
defer commandHistory.mu.Unlock()
commandHistory.executedCommands[command] = true
}
```
### 3. Dependency Checking Middleware
```go
// Middleware that enforces command dependencies
func WithCommandDependencyCheck(action cli.ActionFunc) cli.ActionFunc {
return func(ctx *cli.Context) error {
cmdName := ctx.Command.Name
// Skip checks for create command (entry point)
if cmdName == "create" {
result := action(ctx)
if result == nil {
recordCommandExecution(cmdName)
}
return result
}
// Check dependencies
for _, dep := range CommandFlowDependencies {
if dep.Command == cmdName {
for _, depCmd := range dep.DependsOn {
if !hasCommandBeenExecuted(depCmd) &&
!(dep.CheckFunc != nil && dep.CheckFunc()) {
return errors.New(dep.ErrorMessage)
}
}
}
}
// Execute command and record success
result := action(ctx)
if result == nil {
recordCommandExecution(cmdName)
}
return result
}
}
```
### 4. Integration with CLI Framework
```go
func main() {
actionChain := hooks.NewActionChain()
actionChain.Use(WithCommandDependencyCheck)
hooks.ApplyMiddleware(app.Commands, actionChain)
}
```
## User Experience
When a user attempts to run a command before its prerequisites:
```bash
$ devkit avs call signature="(uint256)" args="(5)"
Error: The 'avs call' command requires contract deployment.
Please run 'devkit avs devnet start' or 'devkit avs devnet deploy-contracts' first.
```
- Users receive clear error message about the correct command sequence and next steps.
## Additional Validations
For complex dependencies that can't be verified by simple command history:
```go
// Validation function example
func checkContractsDeployed() bool {
// Check for config files with deployed contract addresses
contextPath := filepath.Join("config", "contexts", "devnet.yaml")
if _, err := os.Stat(contextPath); os.IsNotExist(err) {
return false
}
// Parse YAML and verify contract addresses exist
// [Implementation details...]
return contractsExist
}
```
## Open questions
- Is there any check that should be made for `create` command ?
## Example validations
- Check that fork url is set before devnet start is called in the context file
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Valutazione
Questa issue non è ancora stata valutata.