@josephyan/qingflow-cli 0.2.0-beta.1000
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/docs/local-agent-install.md +309 -0
- package/entry_point.py +13 -0
- package/npm/bin/qingflow.mjs +5 -0
- package/npm/lib/runtime.mjs +346 -0
- package/npm/scripts/postinstall.mjs +16 -0
- package/package.json +34 -0
- package/pyproject.toml +67 -0
- package/qingflow +15 -0
- package/src/qingflow_mcp/__init__.py +37 -0
- package/src/qingflow_mcp/__main__.py +5 -0
- package/src/qingflow_mcp/backend_client.py +649 -0
- package/src/qingflow_mcp/builder_facade/__init__.py +3 -0
- package/src/qingflow_mcp/builder_facade/models.py +1846 -0
- package/src/qingflow_mcp/builder_facade/service.py +16502 -0
- package/src/qingflow_mcp/cli/__init__.py +1 -0
- package/src/qingflow_mcp/cli/commands/__init__.py +18 -0
- package/src/qingflow_mcp/cli/commands/app.py +40 -0
- package/src/qingflow_mcp/cli/commands/auth.py +112 -0
- package/src/qingflow_mcp/cli/commands/builder.py +539 -0
- package/src/qingflow_mcp/cli/commands/chart.py +18 -0
- package/src/qingflow_mcp/cli/commands/common.py +62 -0
- package/src/qingflow_mcp/cli/commands/imports.py +96 -0
- package/src/qingflow_mcp/cli/commands/portal.py +25 -0
- package/src/qingflow_mcp/cli/commands/record.py +331 -0
- package/src/qingflow_mcp/cli/commands/repo.py +80 -0
- package/src/qingflow_mcp/cli/commands/task.py +141 -0
- package/src/qingflow_mcp/cli/commands/view.py +18 -0
- package/src/qingflow_mcp/cli/commands/workspace.py +110 -0
- package/src/qingflow_mcp/cli/context.py +60 -0
- package/src/qingflow_mcp/cli/formatters.py +573 -0
- package/src/qingflow_mcp/cli/json_io.py +50 -0
- package/src/qingflow_mcp/cli/main.py +186 -0
- package/src/qingflow_mcp/cli/qingflow_login.py +116 -0
- package/src/qingflow_mcp/cli/terminal_ui.py +173 -0
- package/src/qingflow_mcp/config.py +407 -0
- package/src/qingflow_mcp/errors.py +66 -0
- package/src/qingflow_mcp/id_utils.py +49 -0
- package/src/qingflow_mcp/import_store.py +121 -0
- package/src/qingflow_mcp/json_types.py +18 -0
- package/src/qingflow_mcp/list_type_labels.py +76 -0
- package/src/qingflow_mcp/public_surface.py +243 -0
- package/src/qingflow_mcp/repository_store.py +71 -0
- package/src/qingflow_mcp/response_trim.py +841 -0
- package/src/qingflow_mcp/server.py +216 -0
- package/src/qingflow_mcp/server_app_builder.py +543 -0
- package/src/qingflow_mcp/server_app_user.py +386 -0
- package/src/qingflow_mcp/session_store.py +369 -0
- package/src/qingflow_mcp/solution/__init__.py +6 -0
- package/src/qingflow_mcp/solution/build_assembly_store.py +181 -0
- package/src/qingflow_mcp/solution/compiler/__init__.py +282 -0
- package/src/qingflow_mcp/solution/compiler/chart_compiler.py +96 -0
- package/src/qingflow_mcp/solution/compiler/form_compiler.py +495 -0
- package/src/qingflow_mcp/solution/compiler/icon_utils.py +187 -0
- package/src/qingflow_mcp/solution/compiler/navigation_compiler.py +57 -0
- package/src/qingflow_mcp/solution/compiler/package_compiler.py +19 -0
- package/src/qingflow_mcp/solution/compiler/portal_compiler.py +60 -0
- package/src/qingflow_mcp/solution/compiler/view_compiler.py +51 -0
- package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +173 -0
- package/src/qingflow_mcp/solution/design_session.py +222 -0
- package/src/qingflow_mcp/solution/design_store.py +100 -0
- package/src/qingflow_mcp/solution/executor.py +2398 -0
- package/src/qingflow_mcp/solution/normalizer.py +23 -0
- package/src/qingflow_mcp/solution/requirements_builder.py +536 -0
- package/src/qingflow_mcp/solution/run_store.py +244 -0
- package/src/qingflow_mcp/solution/spec_models.py +855 -0
- package/src/qingflow_mcp/tools/__init__.py +1 -0
- package/src/qingflow_mcp/tools/ai_builder_tools.py +3449 -0
- package/src/qingflow_mcp/tools/app_tools.py +926 -0
- package/src/qingflow_mcp/tools/approval_tools.py +1062 -0
- package/src/qingflow_mcp/tools/auth_tools.py +1133 -0
- package/src/qingflow_mcp/tools/base.py +281 -0
- package/src/qingflow_mcp/tools/code_block_tools.py +777 -0
- package/src/qingflow_mcp/tools/custom_button_tools.py +202 -0
- package/src/qingflow_mcp/tools/directory_tools.py +675 -0
- package/src/qingflow_mcp/tools/feedback_tools.py +238 -0
- package/src/qingflow_mcp/tools/file_tools.py +409 -0
- package/src/qingflow_mcp/tools/import_tools.py +2223 -0
- package/src/qingflow_mcp/tools/navigation_tools.py +210 -0
- package/src/qingflow_mcp/tools/package_tools.py +326 -0
- package/src/qingflow_mcp/tools/portal_tools.py +158 -0
- package/src/qingflow_mcp/tools/qingbi_report_tools.py +374 -0
- package/src/qingflow_mcp/tools/record_tools.py +14291 -0
- package/src/qingflow_mcp/tools/repository_dev_tools.py +552 -0
- package/src/qingflow_mcp/tools/resource_read_tools.py +503 -0
- package/src/qingflow_mcp/tools/role_tools.py +112 -0
- package/src/qingflow_mcp/tools/solution_tools.py +4054 -0
- package/src/qingflow_mcp/tools/task_context_tools.py +2986 -0
- package/src/qingflow_mcp/tools/task_tools.py +889 -0
- package/src/qingflow_mcp/tools/view_tools.py +335 -0
- package/src/qingflow_mcp/tools/workflow_tools.py +376 -0
- package/src/qingflow_mcp/tools/workspace_tools.py +266 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
|
|
5
|
+
from ..config import DEFAULT_PROFILE
|
|
6
|
+
from ..errors import QingflowApiError, raise_tool_error
|
|
7
|
+
from ..json_types import JSONObject
|
|
8
|
+
from .base import ToolBase, tool_cn_name
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CustomButtonTools(ToolBase):
|
|
12
|
+
"""自定义按钮工具(中文名:按钮配置管理)。
|
|
13
|
+
|
|
14
|
+
类型:应用配置工具。
|
|
15
|
+
主要职责:
|
|
16
|
+
1. 查询应用自定义按钮;
|
|
17
|
+
2. 创建、更新、删除按钮配置;
|
|
18
|
+
3. 支持草稿与发布态按钮配置维护。
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
@tool_cn_name("自定义按钮列表")
|
|
22
|
+
def custom_button_list(
|
|
23
|
+
self,
|
|
24
|
+
*,
|
|
25
|
+
profile: str,
|
|
26
|
+
app_key: str,
|
|
27
|
+
being_draft: bool = True,
|
|
28
|
+
include_raw: bool = False,
|
|
29
|
+
) -> JSONObject:
|
|
30
|
+
"""执行工具方法逻辑。"""
|
|
31
|
+
self._require_app_key(app_key)
|
|
32
|
+
|
|
33
|
+
def runner(session_profile, context):
|
|
34
|
+
result = self.backend.request(
|
|
35
|
+
"GET",
|
|
36
|
+
context,
|
|
37
|
+
f"/app/{app_key}/customButton",
|
|
38
|
+
params={"beingDraft": being_draft},
|
|
39
|
+
)
|
|
40
|
+
items = []
|
|
41
|
+
raw_items = result.get("result") if isinstance(result, dict) and isinstance(result.get("result"), list) else []
|
|
42
|
+
for item in raw_items:
|
|
43
|
+
if not isinstance(item, dict):
|
|
44
|
+
continue
|
|
45
|
+
items.append(self._compact_button_base_info(item))
|
|
46
|
+
response = {
|
|
47
|
+
"profile": profile,
|
|
48
|
+
"ws_id": session_profile.selected_ws_id,
|
|
49
|
+
"app_key": app_key,
|
|
50
|
+
"being_draft": being_draft,
|
|
51
|
+
"items": result if include_raw else items,
|
|
52
|
+
"count": len(items),
|
|
53
|
+
"compact": not include_raw,
|
|
54
|
+
}
|
|
55
|
+
if include_raw:
|
|
56
|
+
response["summary"] = items
|
|
57
|
+
return response
|
|
58
|
+
|
|
59
|
+
return self._run(profile, runner)
|
|
60
|
+
|
|
61
|
+
@tool_cn_name("自定义按钮详情")
|
|
62
|
+
def custom_button_get(
|
|
63
|
+
self,
|
|
64
|
+
*,
|
|
65
|
+
profile: str,
|
|
66
|
+
app_key: str,
|
|
67
|
+
button_id: int,
|
|
68
|
+
being_draft: bool = True,
|
|
69
|
+
include_raw: bool = False,
|
|
70
|
+
) -> JSONObject:
|
|
71
|
+
"""执行工具方法逻辑。"""
|
|
72
|
+
self._require_app_key(app_key)
|
|
73
|
+
self._require_button_id(button_id)
|
|
74
|
+
|
|
75
|
+
def runner(session_profile, context):
|
|
76
|
+
params = {"beingDraft": being_draft}
|
|
77
|
+
result = self.backend.request("GET", context, f"/app/{app_key}/customButton/{button_id}", params=params)
|
|
78
|
+
response = {
|
|
79
|
+
"profile": profile,
|
|
80
|
+
"ws_id": session_profile.selected_ws_id,
|
|
81
|
+
"app_key": app_key,
|
|
82
|
+
"button_id": button_id,
|
|
83
|
+
"being_draft": being_draft,
|
|
84
|
+
"result": result if include_raw else self._compact_button_detail(result if isinstance(result, dict) else {}),
|
|
85
|
+
"compact": not include_raw,
|
|
86
|
+
}
|
|
87
|
+
if include_raw:
|
|
88
|
+
response["summary"] = self._compact_button_detail(result if isinstance(result, dict) else {})
|
|
89
|
+
return response
|
|
90
|
+
|
|
91
|
+
return self._run(profile, runner)
|
|
92
|
+
|
|
93
|
+
@tool_cn_name("创建自定义按钮")
|
|
94
|
+
def custom_button_create(self, *, profile: str, app_key: str, payload: JSONObject) -> JSONObject:
|
|
95
|
+
"""执行工具方法逻辑。"""
|
|
96
|
+
self._require_app_key(app_key)
|
|
97
|
+
body = self._require_dict(payload)
|
|
98
|
+
|
|
99
|
+
def runner(session_profile, context):
|
|
100
|
+
result = self.backend.request("POST", context, f"/app/{app_key}/customButton", json_body=deepcopy(body))
|
|
101
|
+
return {"profile": profile, "ws_id": session_profile.selected_ws_id, "app_key": app_key, "result": result}
|
|
102
|
+
|
|
103
|
+
return self._run(profile, runner)
|
|
104
|
+
|
|
105
|
+
@tool_cn_name("更新自定义按钮")
|
|
106
|
+
def custom_button_update(self, *, profile: str, app_key: str, button_id: int, payload: JSONObject) -> JSONObject:
|
|
107
|
+
"""执行工具方法逻辑。"""
|
|
108
|
+
self._require_app_key(app_key)
|
|
109
|
+
self._require_button_id(button_id)
|
|
110
|
+
body = self._require_dict(payload)
|
|
111
|
+
|
|
112
|
+
def runner(session_profile, context):
|
|
113
|
+
result = self.backend.request(
|
|
114
|
+
"POST",
|
|
115
|
+
context,
|
|
116
|
+
f"/app/{app_key}/customButton/{button_id}",
|
|
117
|
+
json_body=deepcopy(body),
|
|
118
|
+
)
|
|
119
|
+
return self._attach_human_review_notice(
|
|
120
|
+
{
|
|
121
|
+
"profile": profile,
|
|
122
|
+
"ws_id": session_profile.selected_ws_id,
|
|
123
|
+
"app_key": app_key,
|
|
124
|
+
"button_id": button_id,
|
|
125
|
+
"result": result,
|
|
126
|
+
},
|
|
127
|
+
operation="update",
|
|
128
|
+
target="custom button configuration",
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
return self._run(profile, runner)
|
|
132
|
+
|
|
133
|
+
@tool_cn_name("删除自定义按钮")
|
|
134
|
+
def custom_button_delete(self, *, profile: str, app_key: str, button_id: int) -> JSONObject:
|
|
135
|
+
"""执行工具方法逻辑。"""
|
|
136
|
+
self._require_app_key(app_key)
|
|
137
|
+
self._require_button_id(button_id)
|
|
138
|
+
|
|
139
|
+
def runner(session_profile, context):
|
|
140
|
+
result = self.backend.request("DELETE", context, f"/app/{app_key}/customButton/{button_id}")
|
|
141
|
+
return self._attach_human_review_notice(
|
|
142
|
+
{
|
|
143
|
+
"profile": profile,
|
|
144
|
+
"ws_id": session_profile.selected_ws_id,
|
|
145
|
+
"app_key": app_key,
|
|
146
|
+
"button_id": button_id,
|
|
147
|
+
"result": result,
|
|
148
|
+
},
|
|
149
|
+
operation="delete",
|
|
150
|
+
target="custom button configuration",
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
return self._run(profile, runner)
|
|
154
|
+
|
|
155
|
+
def _require_app_key(self, app_key: str) -> None:
|
|
156
|
+
"""执行内部辅助逻辑。"""
|
|
157
|
+
if not str(app_key or "").strip():
|
|
158
|
+
raise_tool_error(QingflowApiError.config_error("app_key is required"))
|
|
159
|
+
|
|
160
|
+
def _require_button_id(self, button_id: int) -> None:
|
|
161
|
+
"""执行内部辅助逻辑。"""
|
|
162
|
+
if not isinstance(button_id, int) or isinstance(button_id, bool) or button_id <= 0:
|
|
163
|
+
raise_tool_error(QingflowApiError.config_error("button_id must be a positive integer"))
|
|
164
|
+
|
|
165
|
+
def _compact_button_base_info(self, item: dict[str, object]) -> JSONObject:
|
|
166
|
+
"""执行内部辅助逻辑。"""
|
|
167
|
+
creator = item.get("creatorUserInfo") if isinstance(item.get("creatorUserInfo"), dict) else {}
|
|
168
|
+
return {
|
|
169
|
+
"button_id": item.get("buttonId"),
|
|
170
|
+
"button_text": item.get("buttonText"),
|
|
171
|
+
"button_icon": item.get("buttonIcon"),
|
|
172
|
+
"icon_color": item.get("iconColor"),
|
|
173
|
+
"background_color": item.get("backgroundColor"),
|
|
174
|
+
"text_color": item.get("textColor"),
|
|
175
|
+
"creator_user_info": {
|
|
176
|
+
"uid": creator.get("uid"),
|
|
177
|
+
"name": creator.get("name"),
|
|
178
|
+
"email": creator.get("email"),
|
|
179
|
+
}
|
|
180
|
+
if creator
|
|
181
|
+
else None,
|
|
182
|
+
"used_in_chart_count": item.get("userInChartCount"),
|
|
183
|
+
"being_effective_external_qrobot": item.get("beingEffectiveExternalQRobot"),
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
def _compact_button_detail(self, item: dict[str, object]) -> JSONObject:
|
|
187
|
+
"""执行内部辅助逻辑。"""
|
|
188
|
+
return {
|
|
189
|
+
"button_id": item.get("buttonId"),
|
|
190
|
+
"button_text": item.get("buttonText"),
|
|
191
|
+
"button_icon": item.get("buttonIcon"),
|
|
192
|
+
"icon_color": item.get("iconColor"),
|
|
193
|
+
"background_color": item.get("backgroundColor"),
|
|
194
|
+
"text_color": item.get("textColor"),
|
|
195
|
+
"trigger_action": item.get("triggerAction"),
|
|
196
|
+
"trigger_link_url": item.get("triggerLinkUrl"),
|
|
197
|
+
"trigger_add_data_config": deepcopy(item.get("triggerAddDataConfig")) if isinstance(item.get("triggerAddDataConfig"), dict) else None,
|
|
198
|
+
"external_qrobot_config": deepcopy(item.get("customButtonExternalQRobotRelationVO"))
|
|
199
|
+
if isinstance(item.get("customButtonExternalQRobotRelationVO"), dict)
|
|
200
|
+
else None,
|
|
201
|
+
"trigger_wings_config": deepcopy(item.get("triggerWingsConfig")) if isinstance(item.get("triggerWingsConfig"), dict) else None,
|
|
202
|
+
}
|