Skip to content

Commit f452cfc

Browse files
committed
Adding toggle for checkpointing and use LatestMessage to get message
1 parent 7acc355 commit f452cfc

10 files changed

Lines changed: 871 additions & 802 deletions

File tree

proto/gen/rill/runtime/v1/api.pb.go

Lines changed: 797 additions & 783 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/gen/rill/runtime/v1/api.pb.validate.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/gen/rill/runtime/v1/runtime.swagger.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4928,6 +4928,11 @@ definitions:
49284928
description: |-
49294929
Optional path to the file that the user is currently viewing/editing.
49304930
This helps the agent understand which file the user is referring to in their request.
4931+
enableCheckpointCommits:
4932+
type: boolean
4933+
description: |-
4934+
Optional toggle to enable checkpoint commit before any files are changed.
4935+
Can be used to undo the changes reverting to the commit.
49314936
description: Context for prompts handled by the developer_agent.
49324937
v1DirEntry:
49334938
type: object

proto/rill/runtime/v1/api.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,9 @@ message DeveloperAgentContext {
10851085
// Optional path to the file that the user is currently viewing/editing.
10861086
// This helps the agent understand which file the user is referring to in their request.
10871087
string current_file_path = 2;
1088+
// Optional toggle to enable checkpoint commit before any files are changed.
1089+
// Can be used to undo the changes reverting to the commit.
1090+
bool enable_checkpoint_commits = 3;
10881091
}
10891092

10901093
// Request message for RuntimeService.ListConversations

runtime/ai/developer_agent.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ type DeveloperAgent struct {
2020
var _ Tool[*DeveloperAgentArgs, *DeveloperAgentResult] = (*DeveloperAgent)(nil)
2121

2222
type DeveloperAgentArgs struct {
23-
Prompt string `json:"prompt" jsonschema:"User prompt for the developer agent."`
24-
InitProject bool `json:"init_project,omitempty" jsonschema:"Set to true if the prompt is provided as part of project initialization. Should only be used when the project directory contains an empty project (except for the boilerplate generated by UnpackEmpty)."`
25-
CurrentFilePath string `json:"current_file_path,omitempty" jsonschema:"Optional path to the file that the user is currently viewing/editing."`
23+
Prompt string `json:"prompt" jsonschema:"User prompt for the developer agent."`
24+
InitProject bool `json:"init_project,omitempty" jsonschema:"Set to true if the prompt is provided as part of project initialization. Should only be used when the project directory contains an empty project (except for the boilerplate generated by UnpackEmpty)."`
25+
CurrentFilePath string `json:"current_file_path,omitempty" jsonschema:"Optional path to the file that the user is currently viewing/editing."`
26+
EnableCheckpointCommits bool `json:"enable_checkpoint_commits,omitempty" jsonschema:"If true, the developer agent will automatically commit checkpoints before any write is triggered."`
2627
}
2728

2829
type DeveloperAgentResult struct {

runtime/ai/file_write.go

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/modelcontextprotocol/go-sdk/mcp"
1111
"github.com/pmezard/go-difflib/difflib"
1212
"github.com/rilldata/rill/runtime"
13+
"github.com/rilldata/rill/runtime/pkg/mapstructureutil"
1314
)
1415

1516
const WriteFileName = "write_file"
@@ -167,22 +168,45 @@ func (t *WriteFile) reconcileAndGetStatus(ctx context.Context, path string) (res
167168

168169
// maybeCreateCheckpoint creates a checkpoint if this is the 1st write file message in the current message chain.
169170
func (t *WriteFile) maybeCreateCheckpoint(ctx context.Context, s *Session, path string) (string, error) {
170-
// Find a write file message in the current message chain.
171-
var msg *Message
172-
for i := len(s.messages) - 1; i >= 0; i-- {
173-
if s.messages[i].Tool == WriteFileName && s.messages[i].Type == MessageTypeResult {
174-
msg = s.messages[i]
171+
// Find the nearest developer agent call and make sure checkpointing is enabled.
172+
nearestDevAgentCall, ok := s.LatestMessage(FilterByTool(DeveloperAgentName), FilterByType(MessageTypeCall))
173+
if ok {
174+
rawReq, err := s.UnmarshalMessageContent(nearestDevAgentCall)
175+
if err != nil {
176+
return "", err
175177
}
176-
177-
if s.messages[i].Role == RoleUser {
178-
break
178+
var req DeveloperAgentArgs
179+
err = mapstructureutil.WeakDecode(rawReq, &req)
180+
if err != nil {
181+
return "", err
182+
}
183+
if !req.EnableCheckpointCommits {
184+
return "", nil
179185
}
180186
}
181187

182-
// If there is already a write file message then we dont need to create a checkpoint.
183-
if msg != nil {
184-
return "", nil
188+
// Find a write file message in the current message chain.
189+
previousWriteResult, ok := s.LatestMessage(FilterByTool(WriteFileName), FilterByType(MessageTypeResult))
190+
// If there is already a write file message then make sure it has a checkpoint commit.
191+
if ok {
192+
nearestRoot, ok := s.LatestMessage(FilterByRoot())
193+
// If the nearest root message is before the previous write file message, then there hasn't been a commit yet for this loop.
194+
if !ok || nearestRoot.Time.Before(previousWriteResult.Time) {
195+
rawRes, err := s.UnmarshalMessageContent(previousWriteResult)
196+
if err != nil {
197+
return "", err
198+
}
199+
var res WriteFileResult
200+
err = mapstructureutil.WeakDecode(rawRes, &res)
201+
if err != nil {
202+
return "", err
203+
}
204+
if res.CheckpointCommitHash != "" {
205+
return res.CheckpointCommitHash, nil
206+
}
207+
}
185208
}
209+
// Else, create a checkpoint commit.
186210

187211
repo, release, err := t.Runtime.Repo(ctx, s.InstanceID())
188212
if err != nil {

runtime/server/chat.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,9 @@ func (s *Server) Complete(ctx context.Context, req *runtimev1.CompleteRequest) (
258258
var developerAgentArgs *ai.DeveloperAgentArgs
259259
if req.DeveloperAgentContext != nil {
260260
developerAgentArgs = &ai.DeveloperAgentArgs{
261-
InitProject: req.DeveloperAgentContext.InitProject,
262-
CurrentFilePath: req.DeveloperAgentContext.CurrentFilePath,
261+
InitProject: req.DeveloperAgentContext.InitProject,
262+
CurrentFilePath: req.DeveloperAgentContext.CurrentFilePath,
263+
EnableCheckpointCommits: req.DeveloperAgentContext.EnableCheckpointCommits,
263264
}
264265
}
265266

@@ -379,8 +380,9 @@ func (s *Server) CompleteStreaming(req *runtimev1.CompleteStreamingRequest, stre
379380
var developerAgentArgs *ai.DeveloperAgentArgs
380381
if req.DeveloperAgentContext != nil {
381382
developerAgentArgs = &ai.DeveloperAgentArgs{
382-
InitProject: req.DeveloperAgentContext.InitProject,
383-
CurrentFilePath: req.DeveloperAgentContext.CurrentFilePath,
383+
InitProject: req.DeveloperAgentContext.InitProject,
384+
CurrentFilePath: req.DeveloperAgentContext.CurrentFilePath,
385+
EnableCheckpointCommits: req.DeveloperAgentContext.EnableCheckpointCommits,
384386
}
385387
}
386388

web-common/src/features/editor/chat-context.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,17 @@ export const developerChatConfig = {
2121
function getActiveFileContext(): Readable<Partial<RuntimeServiceCompleteBody>> {
2222
return derived(page, (pageState) => {
2323
const filePath = pageState.params?.file;
24-
if (!filePath) return {} satisfies Partial<RuntimeServiceCompleteBody>;
24+
// TODO: toggle for this checkpoints
25+
if (!filePath) {
26+
return {
27+
developerAgentContext: { enableCheckpointCommits: true },
28+
} satisfies Partial<RuntimeServiceCompleteBody>;
29+
}
2530

2631
return {
2732
developerAgentContext: {
2833
currentFilePath: filePath,
34+
enableCheckpointCommits: true,
2935
},
3036
} satisfies Partial<RuntimeServiceCompleteBody>;
3137
});

web-common/src/proto/gen/rill/runtime/v1/api_pb.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4590,6 +4590,14 @@ export class DeveloperAgentContext extends Message$1<DeveloperAgentContext> {
45904590
*/
45914591
currentFilePath = "";
45924592

4593+
/**
4594+
* Optional toggle to enable checkpoint commit before any files are changed.
4595+
* Can be used to undo the changes reverting to the commit.
4596+
*
4597+
* @generated from field: bool enable_checkpoint_commits = 3;
4598+
*/
4599+
enableCheckpointCommits = false;
4600+
45934601
constructor(data?: PartialMessage<DeveloperAgentContext>) {
45944602
super();
45954603
proto3.util.initPartial(data, this);
@@ -4600,6 +4608,7 @@ export class DeveloperAgentContext extends Message$1<DeveloperAgentContext> {
46004608
static readonly fields: FieldList = proto3.util.newFieldList(() => [
46014609
{ no: 1, name: "init_project", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
46024610
{ no: 2, name: "current_file_path", kind: "scalar", T: 9 /* ScalarType.STRING */ },
4611+
{ no: 3, name: "enable_checkpoint_commits", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
46034612
]);
46044613

46054614
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): DeveloperAgentContext {

web-common/src/runtime-client/gen/index.schemas.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,9 @@ This should only be used when the project directory contains an empty project (e
823823
/** Optional path to the file that the user is currently viewing/editing.
824824
This helps the agent understand which file the user is referring to in their request. */
825825
currentFilePath?: string;
826+
/** Optional toggle to enable checkpoint commit before any files are changed.
827+
Can be used to undo the changes reverting to the commit. */
828+
enableCheckpointCommits?: boolean;
826829
}
827830

828831
export interface V1DirEntry {

0 commit comments

Comments
 (0)