on main help sign in
fix: properly follow the `Assisted-by` header spec (#2871)
24da509Andrey Nering
README.md+1−2
@@ -548,8 +548,7 @@ it creates. You can customize this behavior with the `attribution` option:
548
548
549- `trailer_style`: Controls the attribution trailer added to commit messages
549- `trailer_style`: Controls the attribution trailer added to commit messages
550 (default: `assisted-by`)
550 (default: `assisted-by`)
551− - `assisted-by`: Adds `Assisted-by: [Model Name] via Crush <crush@charm.land>`
551+ - `assisted-by`: Adds `Assisted-by: Crush:[ModelID]` as specified in [the convention](https://docs.kernel.org/process/coding-assistants.html#attribution)
552− (includes the model name)
553 - `co-authored-by`: Adds `Co-Authored-By: Crush <crush@charm.land>`
552 - `co-authored-by`: Adds `Co-Authored-By: Crush <crush@charm.land>`
554 - `none`: No attribution trailer
553 - `none`: No attribution trailer
555- `generated_with`: When true (default), adds `💘 Generated with Crush` line to
554- `generated_with`: When true (default), adds `💘 Generated with Crush` line to
internal/agent/coordinator.go+3−3
@@ -458,10 +458,10 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent, isSubA
458 }
458 }
459
459
460 // Get the model name for the agent
460 // Get the model name for the agent
461− modelName := ""
461+ modelID := ""
462 if modelCfg, ok := c.cfg.Config().Models[agent.Model]; ok {
462 if modelCfg, ok := c.cfg.Config().Models[agent.Model]; ok {
463 if model := c.cfg.Config().GetModel(modelCfg.Provider, modelCfg.Model); model != nil {
463 if model := c.cfg.Config().GetModel(modelCfg.Provider, modelCfg.Model); model != nil {
464− modelName = model.Name
464+ modelID = model.ID
465 }
465 }
466 }
466 }
467
467
@@ -474,7 +474,7 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent, isSubA
474 }
474 }
475
475
476 allTools = append(allTools,
476 allTools = append(allTools,
477− tools.NewBashTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Config().Options.Attribution, modelName),
477+ tools.NewBashTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Config().Options.Attribution, modelID),
478 tools.NewCrushInfoTool(c.cfg, c.lspManager, c.allSkills, c.activeSkills, c.skillTracker),
478 tools.NewCrushInfoTool(c.cfg, c.lspManager, c.allSkills, c.activeSkills, c.skillTracker),
479 tools.NewCrushLogsTool(logFile),
479 tools.NewCrushLogsTool(logFile),
480 tools.NewJobOutputTool(),
480 tools.NewJobOutputTool(),
internal/agent/tools/bash.go+5−5
@@ -65,7 +65,7 @@ type bashDescriptionData struct {
65 BannedCommands string
65 BannedCommands string
66 MaxOutputLength int
66 MaxOutputLength int
67 Attribution config.Attribution
67 Attribution config.Attribution
68− ModelName string
68+ ModelID string
69}
69}
70
70
71var bannedCommands = []string{
71var bannedCommands = []string{
@@ -141,14 +141,14 @@ var bannedCommands = []string{
141 "ufw",
141 "ufw",
142}
142}
143
143
144−func bashDescription(attribution *config.Attribution, modelName string) string {
144+func bashDescription(attribution *config.Attribution, modelID string) string {
145 bannedCommandsStr := strings.Join(bannedCommands, ", ")
145 bannedCommandsStr := strings.Join(bannedCommands, ", ")
146 var out bytes.Buffer
146 var out bytes.Buffer
147 if err := bashDescriptionTpl.Execute(&out, bashDescriptionData{
147 if err := bashDescriptionTpl.Execute(&out, bashDescriptionData{
148 BannedCommands: bannedCommandsStr,
148 BannedCommands: bannedCommandsStr,
149 MaxOutputLength: MaxOutputLength,
149 MaxOutputLength: MaxOutputLength,
150 Attribution: *attribution,
150 Attribution: *attribution,
151− ModelName: modelName,
151+ ModelID: modelID,
152 }); err != nil {
152 }); err != nil {
153 // this should never happen.
153 // this should never happen.
154 panic("failed to execute bash description template: " + err.Error())
154 panic("failed to execute bash description template: " + err.Error())
@@ -188,10 +188,10 @@ func blockFuncs() []shell.BlockFunc {
188 }
188 }
189}
189}
190
190
191−func NewBashTool(permissions permission.Service, workingDir string, attribution *config.Attribution, modelName string) fantasy.AgentTool {
191+func NewBashTool(permissions permission.Service, workingDir string, attribution *config.Attribution, modelID string) fantasy.AgentTool {
192 return fantasy.NewAgentTool(
192 return fantasy.NewAgentTool(
193 BashToolName,
193 BashToolName,
194− string(bashDescription(attribution, modelName)),
194+ string(bashDescription(attribution, modelID)),
195 func(ctx context.Context, params BashParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
195 func(ctx context.Context, params BashParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
196 if params.Command == "" {
196 if params.Command == "" {
197 return fantasy.NewTextErrorResponse("missing command"), nil
197 return fantasy.NewTextErrorResponse("missing command"), nil
internal/agent/tools/bash.tpl+1−1
@@ -69,7 +69,7 @@ When user asks to create git commit:
69{{ end}}
69{{ end}}
70{{if eq .Attribution.TrailerStyle "assisted-by" }}
70{{if eq .Attribution.TrailerStyle "assisted-by" }}
71
71
72− Assisted-by: {{ .ModelName }} via Crush <crush@charm.land>
72+ Assisted-by: Crush:{{ .ModelID }}
73{{ else if eq .Attribution.TrailerStyle "co-authored-by" }}
73{{ else if eq .Attribution.TrailerStyle "co-authored-by" }}
74
74
75 Co-Authored-By: Crush <crush@charm.land>
75 Co-Authored-By: Crush <crush@charm.land>