diff --git a/environment/environment.go b/environment/environment.go index 0a01005f..ad30cc7c 100644 --- a/environment/environment.go +++ b/environment/environment.go @@ -35,7 +35,7 @@ type Environment struct { mu sync.RWMutex } -func New(ctx context.Context, dag *dagger.Client, id, title, worktree string, initialSourceDir *dagger.Directory) (*Environment, error) { +func New(ctx context.Context, dag *dagger.Client, id, title, summary, worktree string, initialSourceDir *dagger.Directory) (*Environment, error) { env := &Environment{ EnvironmentInfo: &EnvironmentInfo{ ID: id, @@ -43,6 +43,7 @@ func New(ctx context.Context, dag *dagger.Client, id, title, worktree string, in Config: DefaultConfig(), State: &State{ Title: title, + Summary: summary, CreatedAt: time.Now(), UpdatedAt: time.Now(), }, diff --git a/environment/state.go b/environment/state.go index a564d588..b71060ab 100644 --- a/environment/state.go +++ b/environment/state.go @@ -11,6 +11,7 @@ import ( type State struct { Container string `json:"container,omitempty"` Title string `json:"title,omitempty"` + Summary string `json:"summary,omitempty"` CreatedAt time.Time `json:"created_at,omitempty"` UpdatedAt time.Time `json:"updated_at,omitempty"` } diff --git a/mcpserver/tools.go b/mcpserver/tools.go index dae30e86..6568321b 100644 --- a/mcpserver/tools.go +++ b/mcpserver/tools.go @@ -121,6 +121,7 @@ func init() { type EnvironmentResponse struct { ID string `json:"id"` Title string `json:"title"` + Summary string `json:"summary"` BaseImage string `json:"base_image"` SetupCommands []string `json:"setup_commands"` Instructions string `json:"instructions"` @@ -157,6 +158,7 @@ func marshalEnvironmentInfo(envInfo *environment.EnvironmentInfo) (string, error resp := &EnvironmentResponse{ ID: envInfo.ID, Title: envInfo.State.Title, + Summary: envInfo.State.Summary, Instructions: envInfo.Config.Instructions, BaseImage: envInfo.Config.BaseImage, SetupCommands: envInfo.Config.SetupCommands, @@ -227,6 +229,10 @@ DO NOT manually install toolchains inside the environment, instead explicitly ca mcp.Description("Short description of the work that is happening in this environment. Keep this title updated using `environment_update`."), mcp.Required(), ), + mcp.WithString("summary", + mcp.Description("Summary of all the changes that happened in this environment. MUST be in the format of Conventional Commits. Add a body with further details if needed. MUST BE kept up to date with `environment_update`."), + mcp.Required(), + ), mcp.WithString("environment_source", mcp.Description("Absolute path to the source git repository for the environment."), mcp.Required(), @@ -241,13 +247,17 @@ DO NOT manually install toolchains inside the environment, instead explicitly ca if err != nil { return nil, err } + summary, err := request.RequireString("summary") + if err != nil { + return nil, err + } dag, ok := ctx.Value("dagger_client").(*dagger.Client) if !ok { return mcp.NewToolResultErrorFromErr("dagger client not found in context", nil), nil } - env, err := repo.Create(ctx, dag, title, request.GetString("explanation", "")) + env, err := repo.Create(ctx, dag, title, summary, request.GetString("explanation", "")) if err != nil { return mcp.NewToolResultErrorFromErr("failed to create environment", err), nil } @@ -280,6 +290,10 @@ var EnvironmentUpdateTool = &Tool{ mcp.Description("Short description of the work that is happening in this environment."), mcp.Required(), ), + mcp.WithString("summary", + mcp.Description("Summary of all the changes that happened in this environment. This should be formatted like a commit message and always kept up to date `environment_update`."), + mcp.Required(), + ), mcp.WithString("base_image", mcp.Description("Change the base image for the environment."), mcp.Required(), @@ -350,6 +364,10 @@ Supported schemas are: env.State.Title = title } + if summary := request.GetString("summary", ""); summary != "" { + env.State.Summary = summary + } + if err := env.UpdateConfig(ctx, request.GetString("explanation", ""), config); err != nil { return mcp.NewToolResultErrorFromErr("unable to update the environment", err), nil } @@ -503,7 +521,7 @@ Background commands are unaffected by filesystem and any other kind of changes. return mcp.NewToolResultErrorFromErr("failed to run command", runErr), nil } - return mcp.NewToolResultText(fmt.Sprintf("%s\n\nAny changes to the container workdir (%s) have been committed and pushed to container-use/ remote", stdout, env.Config.Workdir)), nil + return mcp.NewToolResultText(fmt.Sprintf("%s\n\nAny changes to the container workdir (%s) have been committed and pushed to container-use/ remote.\nMake sure to update the summary with `environment_update` if necessary. Current summary: %q", stdout, env.Config.Workdir, env.State.Summary)), nil }, } @@ -643,7 +661,7 @@ var EnvironmentFileWriteTool = &Tool{ return mcp.NewToolResultErrorFromErr("unable to update the environment", err), nil } - return mcp.NewToolResultText(fmt.Sprintf("file %s written successfully and committed to container-use/ remote", targetFile)), nil + return mcp.NewToolResultText(fmt.Sprintf("file %s written successfully and committed to container-use/ remote.\nMake sure to update the summary with `environment_update` if necessary. Current summary: %q", targetFile, env.State.Summary)), nil }, } diff --git a/repository/repository.go b/repository/repository.go index 860d1cff..045a3a02 100644 --- a/repository/repository.go +++ b/repository/repository.go @@ -144,7 +144,7 @@ func (r *Repository) exists(ctx context.Context, id string) error { // Create creates a new environment with the given description and explanation. // Requires a dagger client for container operations during environment initialization. -func (r *Repository) Create(ctx context.Context, dag *dagger.Client, description, explanation string) (*environment.Environment, error) { +func (r *Repository) Create(ctx context.Context, dag *dagger.Client, title, summary, explanation string) (*environment.Environment, error) { id := petname.Generate(2, "-") worktree, err := r.initializeWorktree(ctx, id) if err != nil { @@ -172,7 +172,7 @@ func (r *Repository) Create(ctx context.Context, dag *dagger.Client, description return nil, fmt.Errorf("failed loading initial source directory: %w", err) } - env, err := environment.New(ctx, dag, id, description, worktree, baseSourceDir) + env, err := environment.New(ctx, dag, id, title, summary, worktree, baseSourceDir) if err != nil { return nil, err }