Detailed changes
@@ -345,14 +345,17 @@ it creates. You can customize this behavior with the `attribution` option:
"$schema": "https://charm.land/crush.json",
"options": {
"attribution": {
- "co_authored_by": true,
+ "trailer_style": "co-authored-by",
"generated_with": true
}
}
}
```
-- `co_authored_by`: When true (default), adds `Co-Authored-By: Crush <crush@charm.land>` to commit messages
+- `trailer_style`: Controls the attribution trailer added to commit messages (default: `co-authored-by`)
+ - `co-authored-by`: Adds `Co-Authored-By: Crush <crush@charm.land>`
+ - `assisted-by`: Adds `Assisted-by: [Model Name] via Crush` (includes the model name)
+ - `none`: No attribution trailer
- `generated_with`: When true (default), adds `💘 Generated with Crush` line to commit messages and PR descriptions
### Custom Providers
@@ -176,7 +176,7 @@ func coderAgent(r *recorder.Recorder, env fakeEnv, large, small fantasy.Language
return nil, err
}
allTools := []fantasy.AgentTool{
- tools.NewBashTool(env.permissions, env.workingDir, cfg.Options.Attribution),
+ tools.NewBashTool(env.permissions, env.workingDir, cfg.Options.Attribution, large.Model()),
tools.NewDownloadTool(env.permissions, env.workingDir, r.GetDefaultClient()),
tools.NewEditTool(env.lspClients, env.permissions, env.history, env.workingDir),
tools.NewMultiEditTool(env.lspClients, env.permissions, env.history, env.workingDir),
@@ -327,8 +327,14 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fan
allTools = append(allTools, agenticFetchTool)
}
+ // Get the model name for the agent
+ modelName := ""
+ if modelCfg, ok := c.cfg.Models[agent.Model]; ok {
+ modelName = modelCfg.Model
+ }
+
allTools = append(allTools,
- tools.NewBashTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Options.Attribution),
+ tools.NewBashTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Options.Attribution, modelName),
tools.NewJobOutputTool(),
tools.NewJobKillTool(),
tools.NewDownloadTool(c.permissions, c.cfg.WorkingDir(), nil),
@@ -63,6 +63,7 @@ type bashDescriptionData struct {
BannedCommands string
MaxOutputLength int
Attribution config.Attribution
+ ModelName string
}
var bannedCommands = []string{
@@ -138,13 +139,14 @@ var bannedCommands = []string{
"ufw",
}
-func bashDescription(attribution *config.Attribution) string {
+func bashDescription(attribution *config.Attribution, modelName string) string {
bannedCommandsStr := strings.Join(bannedCommands, ", ")
var out bytes.Buffer
if err := bashDescriptionTpl.Execute(&out, bashDescriptionData{
BannedCommands: bannedCommandsStr,
MaxOutputLength: MaxOutputLength,
Attribution: *attribution,
+ ModelName: modelName,
}); err != nil {
// this should never happen.
panic("failed to execute bash description template: " + err.Error())
@@ -184,10 +186,10 @@ func blockFuncs() []shell.BlockFunc {
}
}
-func NewBashTool(permissions permission.Service, workingDir string, attribution *config.Attribution) fantasy.AgentTool {
+func NewBashTool(permissions permission.Service, workingDir string, attribution *config.Attribution, modelName string) fantasy.AgentTool {
return fantasy.NewAgentTool(
BashToolName,
- string(bashDescription(attribution)),
+ string(bashDescription(attribution, modelName)),
func(ctx context.Context, params BashParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
if params.Command == "" {
return fantasy.NewTextErrorResponse("missing command"), nil
@@ -66,7 +66,9 @@ When user asks to create git commit:
{{ if .Attribution.GeneratedWith}}
💘 Generated with Crush
{{ end }}
-{{ if .Attribution.CoAuthoredBy}}
+{{ if eq .Attribution.TrailerStyle "assisted-by"}}
+ Assisted-by: {{ .ModelName }} via Crush
+{{ else if eq .Attribution.TrailerStyle "co-authored-by"}}
Co-Authored-By: Crush <crush@charm.land>
{{ end }}
EOF
@@ -166,9 +166,17 @@ type Permissions struct {
SkipRequests bool `json:"-"` // Automatically accept all permissions (YOLO mode)
}
+type TrailerStyle string
+
+const (
+ TrailerStyleNone TrailerStyle = "none"
+ TrailerStyleCoAuthoredBy TrailerStyle = "co-authored-by"
+ TrailerStyleAssistedBy TrailerStyle = "assisted-by"
+)
+
type Attribution struct {
- CoAuthoredBy bool `json:"co_authored_by,omitempty" jsonschema:"description=Add Co-Authored-By trailer to commit messages,default=true"`
- GeneratedWith bool `json:"generated_with,omitempty" jsonschema:"description=Add Generated with Crush line to commit messages and issues and PRs,default=true"`
+ TrailerStyle TrailerStyle `json:"trailer_style,omitempty" jsonschema:"description=Style of attribution trailer to add to commits,enum=none,enum=co-authored-by,enum=assisted-by,default=co-authored-by"`
+ GeneratedWith bool `json:"generated_with,omitempty" jsonschema:"description=Add Generated with Crush line to commit messages and issues and PRs,default=true"`
}
type Options struct {
@@ -353,7 +353,7 @@ func (c *Config) setDefaults(workingDir, dataDir string) {
if c.Options.Attribution == nil {
c.Options.Attribution = &Attribution{
- CoAuthoredBy: true,
+ TrailerStyle: TrailerStyleCoAuthoredBy,
GeneratedWith: true,
}
}
@@ -5,10 +5,15 @@
"$defs": {
"Attribution": {
"properties": {
- "co_authored_by": {
- "type": "boolean",
- "description": "Add Co-Authored-By trailer to commit messages",
- "default": true
+ "trailer_style": {
+ "type": "string",
+ "enum": [
+ "none",
+ "co-authored-by",
+ "assisted-by"
+ ],
+ "description": "Style of attribution trailer to add to commits",
+ "default": "co-authored-by"
},
"generated_with": {
"type": "boolean",