Add git-like file commit API (#15978)

### What problem does this PR solve?

| # | Method | Endpoint | Description | Git Equivalent |
|---|--------|----------|-------------|----------------|
| 1 | `POST` | `/api/v1/{prefix}/{folder_id}/commits` | Create a
snapshot commit with file changes (add/modify/delete/rename) | `git add`
+ `git commit` |
| 2 | `GET` | `/api/v1/{prefix}/{folder_id}/commits` | List commit
history (paginated) | `git log` |
| 3 | `GET` | `/api/v1/{prefix}/{folder_id}/commits/{commit_id}` | Get
commit detail with file changes | `git show` |
| 4 | `GET` | `/api/v1/{prefix}/{folder_id}/commits/{commit_id}/files` |
List file changes in a commit | `git show --name-status` |
| 5 | `GET` |
`/api/v1/{prefix}/{folder_id}/commits/diff?from=...&to=...` | Compare
two commits and return differences | `git diff` |
| 6 | `GET` | `/api/v1/{prefix}/{folder_id}/changes` | Get uncommitted
changes (add/modify/delete) | `git status` |
| 7 | `GET` | `/api/v1/{prefix}/{folder_id}/commits/{commit_id}/tree` |
Get the folder tree snapshot at commit time | `git ls-tree` |
| 8 | `GET` |
`/api/v1/{prefix}/{folder_id}/commits/{commit_id}/files/{file_id}/content`
| Get a file's content as it existed in a specific commit | `git show
HEAD:file` |
| 9 | `GET` | `/api/v1/{prefix}/{file_id}/versions` | Get version
history for a specific file across all commits | `git log -- file` |

Where `{prefix}/{id}` can be:
- `folders/{folder_id}` — direct folder access
- `workspaces/{workspace_id}` — alias of `folders/{folder_id}`
- `datasets/{dataset_id}` — resolves to the dataset's folder
- `memories/{memory_id}` — resolves to the memory's folder
- `skills/{skill_id}` — resolves to the skill's folder

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
- [x] Documentation Update
This commit is contained in:
Yingfeng
2026-06-15 11:19:56 +08:00
committed by GitHub
parent 83e2180e80
commit b5bea72e4b
15 changed files with 4244 additions and 7 deletions

View File

@@ -7544,6 +7544,568 @@ or
The commit message.
- `'files'`: `list[object]` (required)
The list of file changes. Each file change is an object with the following fields:
##### Request example
```bash
curl --request POST \
--url http://{address}/api/v1/folders/{folder_id}/commits \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <YOUR_API_KEY>' \
--data '{
"message": "update config files",
"files": [
{"file_id": "file_uuid", "file_name": "config.json", "operation": "modify", "content": "{\"key\": \"value\"}"},
{"file_id": "file_uuid", "file_name": "readme.md", "operation": "add", "content": "# New README"}
]
}'
```
##### Request parameters
- `"message"`: (*Body parameter*), `string`, *Required*
The commit message describing the changes.
- `"files"`: (*Body parameter*), `list[object]`, *Required*
Each file change object supports the following fields:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `file_id` | `string` | Yes | The file ID |
| `file_name` | `string` | Only for add/rename | The file name |
| `operation` | `string` | Yes | `"add"`, `"modify"`, `"delete"`, or `"rename"` |
| `content` | `string` | Only for add/modify | The file content |
| `old_name` | `string` | Only for rename | The old file name |
| `new_name` | `string` | Only for rename | The new file name |
#### Response
Success:
```json
{
"code": 0,
"data": {
"id": "commit_uuid",
"folder_id": "folder_uuid",
"parent_id": null,
"message": "update config files",
"author_id": "user_uuid",
"file_count": 2,
"tree_state": "{\"file_uuid\": {\"hash\": \"abcd1234\", \"location\": \".objects/abcd1234\", \"name\": \"config.json\", \"size\": 1024, \"status\": \"1\", \"parent_id\": \"folder_uuid\"}}",
"create_time": 1718200000000
}
}
```
:::note
`tree_state` is a JSON string containing a flat map of file entries. Each entry includes `parent_id` to track which sub-folder the file belonged to at commit time. Sub-folders are inferred from `parent_id` values.
:::
Failure:
```json
{
"code": 101,
"message": "required argument are missing: message"
}
```
---
### List commits
**GET** `/api/v1/folders/{folder_id}/commits`
Lists all commits for the specified folder with pagination.
Also available at:
- `/api/v1/workspace/{workspace_id}/commits`
- `/api/v1/datasets/{dataset_id}/commits`
#### Request
- Method: GET
- URL: `/api/v1/folders/{folder_id}/commits`
- Headers:
- `'Authorization: Bearer <YOUR_API_KEY>'`
- Query:
- `'page'`: `int` (optional, default: 1)
- `'page_size'`: `int` (optional, default: 15)
- `'order_by'`: `string` (optional, default: `"create_time"`)
- `'desc'`: `bool` (optional, default: `true`)
##### Request example
```bash
curl --request GET \
--url 'http://{address}/api/v1/folders/{folder_id}/commits?page=1&page_size=15' \
--header 'Authorization: Bearer <YOUR_API_KEY>'
```
##### Request parameters
- `"page"`: (*Query parameter*), `int`, *Optional*
Page number. Defaults to 1.
- `"page_size"`: (*Query parameter*), `int`, *Optional*
Number of items per page. Defaults to 15.
- `"order_by"`: (*Query parameter*), `string`, *Optional*
Sort field. Defaults to `"create_time"`.
- `"desc"`: (*Query parameter*), `bool`, *Optional*
Sort descending. Defaults to `true`.
#### Response
Success:
```json
{
"code": 0,
"data": {
"total": 2,
"page": 1,
"page_size": 15,
"commits": [
{
"id": "commit_uuid",
"folder_id": "folder_uuid",
"parent_id": null,
"message": "first commit",
"author_id": "user_uuid",
"file_count": 3,
"create_time": 1718200000000
}
]
}
}
```
---
### Get commit
**GET** `/api/v1/folders/{folder_id}/commits/{commit_id}`
Retrieves the details of a specific commit, including its file changes.
Also available at:
- `/api/v1/workspace/{workspace_id}/commits/{commit_id}`
- `/api/v1/datasets/{dataset_id}/commits/{commit_id}`
#### Request
- Method: GET
- URL: `/api/v1/folders/{folder_id}/commits/{commit_id}`
- Headers:
- `'Authorization: Bearer <YOUR_API_KEY>'`
##### Request example
```bash
curl --request GET \
--url http://{address}/api/v1/folders/{folder_id}/commits/{commit_id} \
--header 'Authorization: Bearer <YOUR_API_KEY>'
```
##### Request parameters
- `"folder_id"`: (*Path parameter*), `string`, *Required*
The folder ID.
- `"commit_id"`: (*Path parameter*), `string`, *Required*
The commit ID.
#### Response
Success:
```json
{
"code": 0,
"data": {
"id": "commit_uuid",
"folder_id": "folder_uuid",
"parent_id": null,
"message": "added config files",
"author_id": "user_uuid",
"file_count": 2,
"create_time": 1718200000000,
"files": [
{
"file_id": "file_uuid",
"operation": "add",
"old_hash": null,
"new_hash": "abcd1234",
"old_name": null,
"new_name": null
}
]
}
}
```
Failure:
```json
{
"code": 102,
"message": "Commit not found in workspace"
}
```
---
### List commit files
**GET** `/api/v1/folders/{folder_id}/commits/{commit_id}/files`
Lists the file changes associated with a specific commit.
Also available at:
- `/api/v1/workspace/{workspace_id}/commits/{commit_id}/files`
- `/api/v1/datasets/{dataset_id}/commits/{commit_id}/files`
#### Request
- Method: GET
- URL: `/api/v1/folders/{folder_id}/commits/{commit_id}/files`
- Headers:
- `'Authorization: Bearer <YOUR_API_KEY>'`
##### Request example
```bash
curl --request GET \
--url http://{address}/api/v1/folders/{folder_id}/commits/{commit_id}/files \
--header 'Authorization: Bearer <YOUR_API_KEY>'
```
#### Response
Success:
```json
{
"code": 0,
"data": [
{
"id": "item_uuid",
"file_id": "file_uuid",
"operation": "add",
"old_hash": null,
"new_hash": "abcd1234",
"old_location": null,
"new_location": ".objects/abcd1234",
"old_name": null,
"new_name": null
}
]
}
```
---
### Diff commits
**GET** `/api/v1/folders/{folder_id}/commits/diff?from={commit_id}&to={commit_id}`
Compares two commits and returns the differences.
Also available at:
- `/api/v1/workspace/{workspace_id}/commits/diff?from=...&to=...`
- `/api/v1/datasets/{dataset_id}/commits/diff?from=...&to=...`
#### Request
- Method: GET
- URL: `/api/v1/folders/{folder_id}/commits/diff`
- Headers:
- `'Authorization: Bearer <YOUR_API_KEY>'`
- Query:
- `'from'`: `string` (required)
The source commit ID.
- `'to'`: `string` (required)
The target commit ID.
##### Request example
```bash
curl --request GET \
--url 'http://{address}/api/v1/folders/{folder_id}/commits/diff?from=from_commit_id&to=to_commit_id' \
--header 'Authorization: Bearer <YOUR_API_KEY>'
```
##### Request parameters
- `"from"`: (*Query parameter*), `string`, *Required*
The source commit ID.
- `"to"`: (*Query parameter*), `string`, *Required*
The target commit ID.
#### Response
Success:
```json
{
"code": 0,
"data": [
{
"file_id": "file_uuid",
"file_name": "config.json",
"operation": "modify",
"old_hash": "abc123",
"new_hash": "def456",
"old_location": ".objects/abc123",
"new_location": ".objects/def456"
}
]
}
```
Failure:
```json
{
"code": 102,
"message": "Commit not found in workspace"
}
```
---
### Get uncommitted changes
**GET** `/api/v1/folders/{folder_id}/changes`
Returns the uncommitted changes for the specified folder (similar to `git status`).
Also available at:
- `/api/v1/workspace/{workspace_id}/changes`
- `/api/v1/datasets/{dataset_id}/changes`
#### Request
- Method: GET
- URL: `/api/v1/folders/{folder_id}/changes`
- Headers:
- `'Authorization: Bearer <YOUR_API_KEY>'`
##### Request example
```bash
curl --request GET \
--url http://{address}/api/v1/folders/{folder_id}/changes \
--header 'Authorization: Bearer <YOUR_API_KEY>'
```
#### Response
Success:
```json
{
"code": 0,
"data": [
{
"file_id": "file_uuid",
"file_name": "new.txt",
"operation": "add"
},
{
"file_id": "file_uuid",
"file_name": "config.json",
"operation": "modify"
},
{
"file_id": "file_uuid",
"file_name": "old.md",
"operation": "delete"
}
]
}
```
---
### Get commit tree
**GET** `/api/v1/folders/{folder_id}/commits/{commit_id}/tree`
Retrieves the full folder tree snapshot as it existed at a specific commit.
Also available at:
- `/api/v1/workspace/{workspace_id}/commits/{commit_id}/tree`
- `/api/v1/datasets/{dataset_id}/commits/{commit_id}/tree`
#### Request
- Method: GET
- URL: `/api/v1/folders/{folder_id}/commits/{commit_id}/tree`
- Headers:
- `'Authorization: Bearer <YOUR_API_KEY>'`
##### Request example
```bash
curl --request GET \
--url http://{address}/api/v1/folders/{folder_id}/commits/{commit_id}/tree \
--header 'Authorization: Bearer <YOUR_API_KEY>'
```
#### Response
Success:
```json
{
"code": 0,
"data": {
"id": "folder_uuid",
"name": "workspace_name",
"type": "folder",
"children": [
{
"id": "file_uuid",
"name": "config.json",
"type": "file",
"hash": "abcd1234",
"size": 1024,
"status": "1",
"location": ".objects/abcd1234"
},
{
"id": "sub_folder_uuid",
"name": "sub_folder_name",
"type": "folder",
"children": [
{
"id": "file_uuid_2",
"name": "nested.txt",
"type": "file",
"hash": "ef5678",
"size": 512,
"status": "1",
"location": ".objects/ef5678"
}
]
}
]
}
}
```
---
### Get commit file content
**GET** `/api/v1/folders/{folder_id}/commits/{commit_id}/files/{file_id}/content`
Retrieves the file content as it existed at a specific commit.
Also available at:
- `/api/v1/workspace/{workspace_id}/commits/{commit_id}/files/{file_id}/content`
- `/api/v1/datasets/{dataset_id}/commits/{commit_id}/files/{file_id}/content`
#### Request
- Method: GET
- URL: `/api/v1/folders/{folder_id}/commits/{commit_id}/files/{file_id}/content`
- Headers:
- `'Authorization: Bearer <YOUR_API_KEY>'`
##### Request example
```bash
curl --request GET \
--url http://{address}/api/v1/folders/{folder_id}/commits/{commit_id}/files/{file_id}/content \
--header 'Authorization: Bearer <YOUR_API_KEY>'
```
#### Response
Success:
```json
{
"code": 0,
"data": {
"content": "file content as it existed in that commit"
}
}
```
Failure:
```json
{
"code": 102,
"message": "File not found in this commit"
}
```
---
### Get file version history
**GET** `/api/v1/files/{file_id}/versions`
Returns the version history for a specific file across all commits.
#### Request
- Method: GET
- URL: `/api/v1/files/{file_id}/versions`
- Headers:
- `'Authorization: Bearer <YOUR_API_KEY>'`
##### Request example
```bash
curl --request GET \
--url http://{address}/api/v1/files/{file_id}/versions \
--header 'Authorization: Bearer <YOUR_API_KEY>'
```
#### Response
Success:
```json
{
"code": 0,
"data": [
{
"commit_id": "commit_uuid",
"operation": "modify",
"hash": "def456",
"create_time": 1718200000000,
"message": "updated file"
},
{
"commit_id": "commit_uuid",
"operation": "add",
"hash": "abc123",
"create_time": 1718100000000,
"message": "initial commit"
}
]
}
```
---
## SEARCH APP MANAGEMENT
### Create search app
**POST** `/api/v1/searches`
Creates a search app.
#### Request
- Method: POST
- URL: `/api/v1/searches`
- Headers:
- `'Content-Type: application/json'`
- `'Authorization: Bearer <YOUR_API_KEY>'`
- Body:
```json
{
"name": "my_search_app",
"description": "optional description"
}
```