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.
| Method | Path | Description |
|---|---|---|
| GET | /api/projects/{projectId}/chat-sessions/{sessionId}/preview/diff/comments | List the review comments left on the diff. |
| POST | /api/projects/{projectId}/chat-sessions/{sessionId}/preview/diff/comments | Leave 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/commits | List 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/files | List 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.
scope | What the diff shows |
|---|---|
last-turn | The default. What the agent's last turn changed. |
uncommitted | The changes in the working tree that nobody committed. |
branch | Everything 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. |
committed | One 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.
| Parameter | What it does |
|---|---|
cursor | The next page, from meta.pagination.nextCursor. Leave it out for the first page. Cannot be combined with path. |
path | One file. Cannot be combined with cursor. |
hunkOffset | With path, the first hunk to return. Pass the file's nextHunkOffset to read on. |
hunkEnd | With path, the hunk to stop before. |
contents | 1 with path returns both sides of the file in meta.fileContents, without the patch. |
paths | A JSON array of up to 50 paths to read again. Cannot be combined with path or cursor. |
afterPath | With paths, carries on paging after this path. |
base, head | The base and head from an earlier answer. They keep a single-file request on the same comparison. Send both or neither. |
scope, commit | Which 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.
| Field | Type | What it does |
|---|---|---|
filePath | string, up to 1,024 characters | Required. The file, as the diff names it. |
side | old or new | Required. new for lines of the changed file, old for lines as they were before. |
startLineNumber | integer, 1 or more | Required. The first commented line on that side. |
endLineNumber | integer | Required. The last commented line. At least startLineNumber. |
body | string, up to 4,000 characters | Required. The comment. |
lineSnapshot | string | Required. 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.
| Body | What it does | Who 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
| Status | Code | When |
|---|---|---|
| 400 | BAD_REQUEST | scope, commit, cursor, base, head or paths is not valid, or the project has no branch to compare against. |
| 400 | VALIDATION_ERROR | A comment field is missing or too long. |
| 402 | CREDIT_LIMIT_REACHED | The workspace is blocked on billing. |
| 403 | FORBIDDEN | Editing the text of, or deleting, another member's comment. |
| 404 | NOT_FOUND | The session or comment does not exist, or path is not in the diff. |
| 503 | SERVICE_UNAVAILABLE | The 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.