-
Notifications
You must be signed in to change notification settings - Fork 9.2k
Feat: Agent api #14157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat: Agent api #14157
Changes from 1 commit
add88ca
5f5225f
a256811
2514218
9c85418
7a4f2fd
09c3aff
f4134ab
bc23e54
daa4755
35679df
415d6d9
b81584a
9b4ad62
14e40b0
c181dc7
9dc8786
2c8fe74
1dd53a0
a2e129b
539d5b2
31b3af6
88b7291
0d3bf28
5993433
f9e532a
5b8802a
5ea5cdd
cd1ce9a
5844c52
1fc3dca
37e2083
b84d27d
47f1bc3
d9946b9
5617bda
c93e86c
b9cac2e
b711765
916c2d8
055de1e
179e581
f1049c1
9241719
00175af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| # | ||
| # Copyright 2026 The InfiniFlow Authors. All Rights Reserved. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| # | ||
|
|
||
| from quart import request | ||
|
|
||
| from agent.dsl_migration import normalize_chunker_dsl | ||
| from api.apps import current_user, login_required | ||
| from api.apps.services.canvas_replica_service import CanvasReplicaService | ||
| from api.db import CanvasCategory | ||
| from api.db.services.canvas_service import UserCanvasService | ||
| from api.db.services.knowledgebase_service import KnowledgebaseService | ||
| from api.db.services.user_service import TenantService | ||
| from api.db.services.user_canvas_version import UserCanvasVersionService | ||
| from api.utils.api_utils import add_tenant_id_to_kwargs, get_data_error_result, get_json_result | ||
|
|
||
|
|
||
| @manager.route("/agents", methods=["GET"]) # noqa: F821 | ||
| @login_required | ||
| @add_tenant_id_to_kwargs | ||
| def list_agents(tenant_id): | ||
| keywords = request.args.get("keywords", "") | ||
| canvas_category = request.args.get("canvas_category") | ||
| owner_ids = [item for item in request.args.get("owner_ids", "").strip().split(",") if item] | ||
|
|
||
| page_number = int(request.args.get("page", 0)) | ||
| items_per_page = int(request.args.get("page_size", 0)) | ||
| order_by = request.args.get("orderby", "create_time") | ||
| desc = str(request.args.get("desc", "true")).lower() != "false" | ||
|
|
||
| if not owner_ids: | ||
| tenants = TenantService.get_joined_tenants_by_user_id(current_user.id) | ||
| tenants = [member["tenant_id"] for member in tenants] | ||
| tenants.append(current_user.id) | ||
| canvas, total = UserCanvasService.get_by_tenant_ids( | ||
| tenants, | ||
| current_user.id, | ||
| page_number, | ||
| items_per_page, | ||
| order_by, | ||
| desc, | ||
| keywords, | ||
| canvas_category, | ||
| ) | ||
| else: | ||
| canvas, total = UserCanvasService.get_by_tenant_ids( | ||
| owner_ids, | ||
| current_user.id, | ||
| 0, | ||
| 0, | ||
| order_by, | ||
| desc, | ||
| keywords, | ||
| canvas_category, | ||
| ) | ||
|
|
||
| return get_json_result(data={"canvas": canvas, "total": total}) | ||
|
Comment on lines
+294
to
+331
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add server-side logging for these new agent flows. The new list/get endpoints have no logs for request scope, access denials, or bootstrap failures, which will make production debugging and audit trails much harder. As per coding guidelines, "Add logging for new flows". Also applies to: 75-110 🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| @manager.route("/agents/<agent_id>", methods=["GET"]) # noqa: F821 | ||
| @login_required | ||
| @add_tenant_id_to_kwargs | ||
| def get_agent(agent_id, tenant_id): | ||
| if not UserCanvasService.accessible(agent_id, current_user.id): | ||
| return get_data_error_result(message="canvas not found.") | ||
|
|
||
| exists, canvas = UserCanvasService.get_by_canvas_id(agent_id) | ||
| if not exists: | ||
| return get_data_error_result(message="canvas not found.") | ||
|
|
||
| try: | ||
| CanvasReplicaService.bootstrap( | ||
| canvas_id=agent_id, | ||
| tenant_id=str(tenant_id), | ||
| runtime_user_id=str(current_user.id), | ||
| dsl=canvas.get("dsl"), | ||
| canvas_category=canvas.get("canvas_category", CanvasCategory.Agent), | ||
| title=canvas.get("title", ""), | ||
| ) | ||
| except ValueError as exc: | ||
| return get_data_error_result(message=str(exc)) | ||
|
|
||
| last_publish_time = None | ||
| versions = UserCanvasVersionService.list_by_canvas_id(agent_id) | ||
| if versions: | ||
| released_versions = [version for version in versions if version.release] | ||
| if released_versions: | ||
| released_versions.sort(key=lambda version: version.update_time, reverse=True) | ||
| last_publish_time = released_versions[0].update_time | ||
|
|
||
| canvas["dsl"] = normalize_chunker_dsl(canvas.get("dsl", {})) | ||
| canvas["last_publish_time"] = last_publish_time | ||
|
|
||
| if canvas.get("canvas_category") == CanvasCategory.DataFlow: | ||
| datasets = list(KnowledgebaseService.query(pipeline_id=agent_id)) | ||
| canvas["datasets"] = [{"id": item.id, "name": item.name, "avatar": item.avatar} for item in datasets] | ||
|
|
||
| return get_json_result(data=canvas) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -231,25 +231,39 @@ def retrieve( | |
| raise Exception(res.get("message")) | ||
|
|
||
| def list_agents(self, page: int = 1, page_size: int = 30, orderby: str = "update_time", desc: bool = True, id: str | None = None, title: str | None = None) -> list[Agent]: | ||
| if id is not None: | ||
| agent = self.get_agent(id) | ||
| if title is not None and agent.title != title: | ||
| return [] | ||
| return [agent] | ||
|
|
||
| res = self.get( | ||
| "/agents", | ||
| { | ||
| "page": page, | ||
| "page_size": page_size, | ||
| "orderby": orderby, | ||
| "desc": desc, | ||
| "id": id, | ||
| "title": title, | ||
| }, | ||
| ) | ||
| res = res.json() | ||
| result_list = [] | ||
| if res.get("code") == 0: | ||
| for data in res["data"]: | ||
| data_list = res.get("data", {}).get("canvas", []) | ||
| for data in data_list: | ||
| if title is not None and data.get("title") != title: | ||
| continue | ||
| result_list.append(Agent(self, data)) | ||
|
Comment on lines
+246
to
249
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new The current backend snippet in Suggested fix- data = res.get("data") or {}
- data_list = data.get("canvas", [])
- for data in data_list:
- if title is not None and data.get("title") != title:
+ payload = res.get("data") or []
+ data_list = payload.get("canvas", []) if isinstance(payload, dict) else payload
+ for data in data_list:
+ if title is not None and data.get("title") != title:
continue
result_list.append(Agent(self, data))🤖 Prompt for AI Agents |
||
| return result_list | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| raise Exception(res["message"]) | ||
|
|
||
| def get_agent(self, agent_id: str) -> Agent: | ||
| res = self.get(f"/agents/{agent_id}") | ||
| res = res.json() | ||
| if res.get("code") == 0: | ||
| return Agent(self, res["data"]) | ||
| raise Exception(res["message"]) | ||
|
|
||
| def create_agent(self, title: str, dsl: dict, description: str | None = None) -> None: | ||
| req = {"title": title, "dsl": dsl} | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.