Skip to main content

Diff

Read what a chat session's branch changes and leave review comments on specific lines. Start with GET .../preview/diff/files for the list of changed files, then read patches for the files you need. Reading the diff needs a running sandbox, so wake it first with GET /api/projects/{projectId}/preview?sessionId=. The comment endpoints work whether the sandbox runs or not.

MethodPathDescription
GET/api/projects/{projectId}/chat-sessions/{sessionId}/preview/diff/commentsList the review comments left on the diff.
POST/api/projects/{projectId}/chat-sessions/{sessionId}/preview/diff/commentsLeave a review comment on a range of lines in the diff.
PATCH/api/projects/{projectId}/chat-sessions/{sessionId}/preview/diff/comments/{commentId}Edit the body of your own comment, or resolve or reopen any comment. One of the two per call.
DELETE/api/projects/{projectId}/chat-sessions/{sessionId}/preview/diff/comments/{commentId}Delete your own comment.
GET/api/projects/{projectId}/chat-sessions/{sessionId}/preview/diff/commitsList the commits the session's branch adds over its pull request's base branch, or over the target branch before a pull request is open. Needs a running sandbox; otherwise commits is empty and unavailable says why.
GET/api/projects/{projectId}/chat-sessions/{sessionId}/preview/diff/filesList the files the session's branch changes against its base, with totals.
GET/api/projects/{projectId}/chat-sessions/{sessionId}/preview/diff/patch?path=&paths=&afterPath=&cursor=&contents=&base=&head=&hunkOffset=&hunkEnd=Read patches: a page (cursor), one file (path, with hunkOffset/hunkEnd), or one file with both sides (path and contents=1). path and cursor are mutually exclusive.

Choose what the diff shows​

GET .../preview/diff/files and GET .../preview/diff/patch take a scope that picks the changes to compare.

scopeWhat the diff shows
last-turnThe default. What the agent's last turn changed.
uncommittedThe changes in the working tree that nobody committed.
branchEverything the pushed branch changes against its pull request's base branch, or against the Target Branch before a pull request is open. The branch has to be pushed.
committedOne pushed commit. Send its sha in commit, taken from GET .../preview/diff/commits.

The CLI sends no scope, so kosuke sessions diff files list and kosuke sessions diff patch get show the last turn.

List changed files​

GET .../preview/diff/files lists every changed file with its status and line counts, without content.

curl -s "https://app.kosuke.ai/api/projects/$PROJECT_ID/chat-sessions/$SESSION_ID/preview/diff/files?scope=branch" \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"files": [
{ "path": "src/settings/page.tsx", "status": "modified", "additions": 24, "deletions": 3 },
{ "path": "src/theme.ts", "status": "added", "additions": 41, "deletions": 0 }
],
"base": "4b1d9e07c2a8f5b3e6d1904a7c3f8e2b5d6a9c10",
"head": "a93f27c5e8b1d4f60a7c2e9b3d5f8a1c4e7b0d26",
"totals": { "files": 2, "additions": 65, "deletions": 3 }
}
}

status is added, modified, deleted or renamed, and a renamed file carries oldPath. When the sandbox is not running, or the scope has nothing to compare yet, files is empty and unavailable says why. When the sandbox cannot read the diff, the answer is 503. The CLI command is kosuke sessions diff files list <projectId> <sessionId>.

GET .../preview/diff/commits lists the pushed commits the branch adds over the same branch the branch scope compares against, each with its sha, subject and committedAt.

Read patches​

GET .../preview/diff/patch returns patches, a page of files at a time or one file at a time.

ParameterWhat it does
cursorThe next page, from meta.pagination.nextCursor. Leave it out for the first page. Cannot be combined with path.
pathOne file. Cannot be combined with cursor.
hunkOffsetWith path, the first hunk to return. Pass the file's nextHunkOffset to read on.
hunkEndWith path, the hunk to stop before.
contents1 with path returns both sides of the file in meta.fileContents, without the patch.
pathsA JSON array of up to 50 paths to read again. Cannot be combined with path or cursor.
afterPathWith paths, carries on paging after this path.
base, headThe base and head from an earlier answer. They keep a single-file request on the same comparison. Send both or neither.
scope, commitWhich changes to compare, as above. A cursor stays tied to the scope it came from.

A page holds up to 50 files. Each file comes back as { path, header, windows, totalHunks, nextHunkOffset }. Each window holds hunkOffset, hunkCount and the hunk text in patch. A null nextHunkOffset means no hunks remain after the last window. When review comments sit on a file, its windows can leave hidden hunks between them. Compare each window's hunkOffset and hunkCount to find the gaps, then read them with hunkOffset and hunkEnd.

kosuke sessions diff patch get $PROJECT_ID $SESSION_ID --path src/theme.ts

When the sandbox is not running, the patch endpoint answers 503.

Comment on the diff​

POST .../preview/diff/comments leaves a review comment on a range of lines. Any member of the workspace can comment.

FieldTypeWhat it does
filePathstring, up to 1,024 charactersRequired. The file, as the diff names it.
sideold or newRequired. new for lines of the changed file, old for lines as they were before.
startLineNumberinteger, 1 or moreRequired. The first commented line on that side.
endLineNumberintegerRequired. The last commented line. At least startLineNumber.
bodystring, up to 4,000 charactersRequired. The comment.
lineSnapshotstringRequired. The text of the commented lines, joined with \n, with no newline at the end.

lineSnapshot is how Sensei tells a comment has gone stale. When the lines at that range no longer match it, the app marks the comment outdated. Send an empty string when that side has no lines, such as the new side of a deleted file. An empty snapshot is never compared, so it is marked outdated only when its file leaves the diff or its lines are gone.

curl -s -X POST "https://app.kosuke.ai/api/projects/$PROJECT_ID/chat-sessions/$SESSION_ID/preview/diff/comments" \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"filePath": "src/theme.ts", "side": "new", "startLineNumber": 12, "endLineNumber": 12, "body": "Read the saved theme before the first paint.", "lineSnapshot": "const theme = \"light\";"}'

The answer is 201 with the comment, including its id, author and resolvedAt. GET .../preview/diff/comments returns { "data": { "comments": [...], "sentCommentIds": [...] } } for the session: sentCommentIds names the comments a message of the session already carried in diffCommentsContext. The CLI group is kosuke sessions diff comments, with list, add, update and delete.

Edit or resolve a comment​

PATCH .../preview/diff/comments/{commentId} takes one of two bodies per call.

BodyWhat it doesWho can send it
{ "body": "..." }Replaces the comment's text.Its author.
{ "resolved": true } or { "resolved": false }Resolves or reopens the comment.Any member of the workspace.

DELETE .../preview/diff/comments/{commentId} removes a comment. Only its author can delete it, and the answer is 204.

Send comments to the agent​

To have the agent work through review comments, send them with your next message in diffCommentsContext on POST .../jobs/chat. Sensei leaves out resolved comments. Send review comments to the agent shows the whole flow, and Messages and turns has the field.

Errors​

StatusCodeWhen
400BAD_REQUESTscope, commit, cursor, base, head or paths is not valid, or the project has no branch to compare against.
400VALIDATION_ERRORA comment field is missing or too long.
402CREDIT_LIMIT_REACHEDThe workspace is blocked on billing.
403FORBIDDENEditing the text of, or deleting, another member's comment.
404NOT_FOUNDThe session or comment does not exist, or path is not in the diff.
503SERVICE_UNAVAILABLEThe diff could not be read from the sandbox. On the patch endpoint, also when the sandbox is not running or the scope has nothing to compare yet.

Responses and errors has the full table.

Next steps​