@josephyan/qingflow-cli 0.2.0-beta.63 → 0.2.0-beta.65
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 +2 -2
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/qingflow_mcp/builder_facade/models.py +5 -0
- package/src/qingflow_mcp/builder_facade/service.py +560 -26
- package/src/qingflow_mcp/cli/commands/builder.py +4 -0
- package/src/qingflow_mcp/server_app_builder.py +4 -0
- package/src/qingflow_mcp/solution/compiler/icon_utils.py +71 -0
- package/src/qingflow_mcp/tools/ai_builder_tools.py +36 -2
- package/src/qingflow_mcp/tools/custom_button_tools.py +2 -0
|
@@ -93,6 +93,8 @@ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) ->
|
|
|
93
93
|
schema_apply_apply.add_argument("--package-tag-id", type=int)
|
|
94
94
|
schema_apply_apply.add_argument("--app-name", default="")
|
|
95
95
|
schema_apply_apply.add_argument("--app-title", default="")
|
|
96
|
+
schema_apply_apply.add_argument("--icon")
|
|
97
|
+
schema_apply_apply.add_argument("--color")
|
|
96
98
|
schema_apply_apply.add_argument("--create-if-missing", action="store_true")
|
|
97
99
|
schema_apply_apply.add_argument("--publish", action=argparse.BooleanOptionalAction, default=True)
|
|
98
100
|
schema_apply_apply.add_argument("--add-fields-file")
|
|
@@ -198,6 +200,8 @@ def _handle_schema_apply(args: argparse.Namespace, context: CliContext) -> dict:
|
|
|
198
200
|
package_tag_id=args.package_tag_id,
|
|
199
201
|
app_name=args.app_name,
|
|
200
202
|
app_title=args.app_title,
|
|
203
|
+
icon=args.icon,
|
|
204
|
+
color=args.color,
|
|
201
205
|
create_if_missing=bool(args.create_if_missing),
|
|
202
206
|
publish=bool(args.publish),
|
|
203
207
|
add_fields=load_list_arg(args.add_fields_file, option_name="--add-fields-file"),
|
|
@@ -280,6 +280,8 @@ def build_builder_server() -> FastMCP:
|
|
|
280
280
|
package_tag_id: int | None = None,
|
|
281
281
|
app_name: str = "",
|
|
282
282
|
app_title: str = "",
|
|
283
|
+
icon: str = "",
|
|
284
|
+
color: str = "",
|
|
283
285
|
create_if_missing: bool = False,
|
|
284
286
|
publish: bool = True,
|
|
285
287
|
add_fields: list[dict] | None = None,
|
|
@@ -292,6 +294,8 @@ def build_builder_server() -> FastMCP:
|
|
|
292
294
|
package_tag_id=package_tag_id,
|
|
293
295
|
app_name=app_name,
|
|
294
296
|
app_title=app_title,
|
|
297
|
+
icon=icon,
|
|
298
|
+
color=color,
|
|
295
299
|
create_if_missing=create_if_missing,
|
|
296
300
|
publish=publish,
|
|
297
301
|
add_fields=add_fields or [],
|
|
@@ -4,6 +4,18 @@ import json
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
DEFAULT_ICON_COLOR = "qing-orange"
|
|
7
|
+
DEFAULT_ICON_STYLE_POOL: tuple[tuple[str, str], ...] = (
|
|
8
|
+
("briefcase", "qing-orange"),
|
|
9
|
+
("calendar", "emerald"),
|
|
10
|
+
("folder", "azure"),
|
|
11
|
+
("shield-check", "indigo"),
|
|
12
|
+
("user-group", "qing-purple"),
|
|
13
|
+
("chart-square-bar", "blue"),
|
|
14
|
+
("clock", "pink"),
|
|
15
|
+
("document-text", "green"),
|
|
16
|
+
("home", "orange"),
|
|
17
|
+
("globe", "red"),
|
|
18
|
+
)
|
|
7
19
|
SUPPORTED_EX_ICONS = {
|
|
8
20
|
"ex-alert-outlined",
|
|
9
21
|
"ex-clock-outlined",
|
|
@@ -78,6 +90,65 @@ def encode_workspace_icon(
|
|
|
78
90
|
)
|
|
79
91
|
|
|
80
92
|
|
|
93
|
+
def choose_default_workspace_icon_style(*, title: str) -> tuple[str, str]:
|
|
94
|
+
seed_text = (title or "未命名").strip() or "未命名"
|
|
95
|
+
digest = 0
|
|
96
|
+
for index, char in enumerate(seed_text):
|
|
97
|
+
digest = (digest * 131 + ord(char) + index) % 1_000_003
|
|
98
|
+
return DEFAULT_ICON_STYLE_POOL[digest % len(DEFAULT_ICON_STYLE_POOL)]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def parse_workspace_icon(value: str | None) -> tuple[str | None, str | None, str | None]:
|
|
102
|
+
if not value:
|
|
103
|
+
return None, None, None
|
|
104
|
+
stripped = str(value).strip()
|
|
105
|
+
if not stripped:
|
|
106
|
+
return None, None, None
|
|
107
|
+
if _looks_like_icon_json(stripped):
|
|
108
|
+
try:
|
|
109
|
+
payload = json.loads(stripped)
|
|
110
|
+
except Exception:
|
|
111
|
+
return normalize_workspace_icon_name(stripped), None, None
|
|
112
|
+
icon_name = normalize_workspace_icon_name(payload.get("iconName"))
|
|
113
|
+
icon_color = str(payload.get("iconColor") or "").strip() or None
|
|
114
|
+
icon_text = str(payload.get("iconText") or "").strip() or None
|
|
115
|
+
return icon_name, icon_color, icon_text
|
|
116
|
+
return normalize_workspace_icon_name(stripped), None, None
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def encode_workspace_icon_with_defaults(
|
|
120
|
+
*,
|
|
121
|
+
icon: str | None,
|
|
122
|
+
color: str | None,
|
|
123
|
+
title: str,
|
|
124
|
+
fallback_icon_name: str | None = None,
|
|
125
|
+
existing_icon: str | None = None,
|
|
126
|
+
) -> str:
|
|
127
|
+
if icon and _looks_like_icon_json(icon):
|
|
128
|
+
return icon
|
|
129
|
+
if not icon and not color and existing_icon:
|
|
130
|
+
existing_payload = str(existing_icon).strip()
|
|
131
|
+
if existing_payload:
|
|
132
|
+
return existing_payload
|
|
133
|
+
existing_icon_name, existing_icon_color, _ = parse_workspace_icon(existing_icon)
|
|
134
|
+
default_icon, default_color = choose_default_workspace_icon_style(title=title)
|
|
135
|
+
resolved_icon = icon or existing_icon_name
|
|
136
|
+
resolved_color = color or existing_icon_color
|
|
137
|
+
if not resolved_icon:
|
|
138
|
+
if icon is None and color is None:
|
|
139
|
+
resolved_icon = default_icon
|
|
140
|
+
else:
|
|
141
|
+
resolved_icon = fallback_icon_name or default_icon
|
|
142
|
+
if not resolved_color:
|
|
143
|
+
resolved_color = default_color
|
|
144
|
+
return encode_workspace_icon(
|
|
145
|
+
icon=resolved_icon,
|
|
146
|
+
color=resolved_color,
|
|
147
|
+
title=title,
|
|
148
|
+
fallback_icon_name=fallback_icon_name,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
81
152
|
def normalize_workspace_icon_name(icon: str | None) -> str | None:
|
|
82
153
|
if not icon:
|
|
83
154
|
return None
|
|
@@ -228,6 +228,8 @@ class AiBuilderTools(ToolBase):
|
|
|
228
228
|
package_tag_id: int | None = None,
|
|
229
229
|
app_name: str = "",
|
|
230
230
|
app_title: str = "",
|
|
231
|
+
icon: str = "",
|
|
232
|
+
color: str = "",
|
|
231
233
|
create_if_missing: bool = False,
|
|
232
234
|
publish: bool = True,
|
|
233
235
|
add_fields: list[JSONObject] | None = None,
|
|
@@ -240,6 +242,8 @@ class AiBuilderTools(ToolBase):
|
|
|
240
242
|
package_tag_id=package_tag_id,
|
|
241
243
|
app_name=app_name,
|
|
242
244
|
app_title=app_title,
|
|
245
|
+
icon=icon,
|
|
246
|
+
color=color,
|
|
243
247
|
create_if_missing=create_if_missing,
|
|
244
248
|
publish=publish,
|
|
245
249
|
add_fields=add_fields or [],
|
|
@@ -713,6 +717,8 @@ class AiBuilderTools(ToolBase):
|
|
|
713
717
|
app_key: str = "",
|
|
714
718
|
package_tag_id: int | None = None,
|
|
715
719
|
app_name: str = "",
|
|
720
|
+
icon: str = "",
|
|
721
|
+
color: str = "",
|
|
716
722
|
create_if_missing: bool = False,
|
|
717
723
|
add_fields: list[JSONObject],
|
|
718
724
|
update_fields: list[JSONObject],
|
|
@@ -724,6 +730,8 @@ class AiBuilderTools(ToolBase):
|
|
|
724
730
|
"app_key": app_key,
|
|
725
731
|
"package_tag_id": package_tag_id,
|
|
726
732
|
"app_name": app_name,
|
|
733
|
+
"icon": icon,
|
|
734
|
+
"color": color,
|
|
727
735
|
"create_if_missing": create_if_missing,
|
|
728
736
|
"add_fields": add_fields,
|
|
729
737
|
"update_fields": update_fields,
|
|
@@ -742,6 +750,8 @@ class AiBuilderTools(ToolBase):
|
|
|
742
750
|
"app_key": app_key,
|
|
743
751
|
"package_tag_id": package_tag_id,
|
|
744
752
|
"app_name": app_name,
|
|
753
|
+
"icon": icon,
|
|
754
|
+
"color": color,
|
|
745
755
|
"create_if_missing": create_if_missing,
|
|
746
756
|
"add_fields": [{"name": "字段名称", "type": "text"}],
|
|
747
757
|
"update_fields": [],
|
|
@@ -889,6 +899,8 @@ class AiBuilderTools(ToolBase):
|
|
|
889
899
|
package_tag_id: int | None = None,
|
|
890
900
|
app_name: str = "",
|
|
891
901
|
app_title: str = "",
|
|
902
|
+
icon: str = "",
|
|
903
|
+
color: str = "",
|
|
892
904
|
create_if_missing: bool = False,
|
|
893
905
|
publish: bool = True,
|
|
894
906
|
add_fields: list[JSONObject],
|
|
@@ -901,6 +913,8 @@ class AiBuilderTools(ToolBase):
|
|
|
901
913
|
package_tag_id=package_tag_id,
|
|
902
914
|
app_name=app_name,
|
|
903
915
|
app_title=app_title,
|
|
916
|
+
icon=icon,
|
|
917
|
+
color=color,
|
|
904
918
|
create_if_missing=create_if_missing,
|
|
905
919
|
publish=publish,
|
|
906
920
|
add_fields=add_fields,
|
|
@@ -916,6 +930,8 @@ class AiBuilderTools(ToolBase):
|
|
|
916
930
|
package_tag_id=package_tag_id,
|
|
917
931
|
app_name=app_name,
|
|
918
932
|
app_title=app_title,
|
|
933
|
+
icon=icon,
|
|
934
|
+
color=color,
|
|
919
935
|
create_if_missing=create_if_missing,
|
|
920
936
|
publish=publish,
|
|
921
937
|
add_fields=add_fields,
|
|
@@ -932,6 +948,8 @@ class AiBuilderTools(ToolBase):
|
|
|
932
948
|
package_tag_id: int | None = None,
|
|
933
949
|
app_name: str = "",
|
|
934
950
|
app_title: str = "",
|
|
951
|
+
icon: str = "",
|
|
952
|
+
color: str = "",
|
|
935
953
|
create_if_missing: bool = False,
|
|
936
954
|
publish: bool = True,
|
|
937
955
|
add_fields: list[JSONObject],
|
|
@@ -945,6 +963,8 @@ class AiBuilderTools(ToolBase):
|
|
|
945
963
|
app_key=app_key,
|
|
946
964
|
package_tag_id=package_tag_id,
|
|
947
965
|
app_name=effective_app_name,
|
|
966
|
+
icon=icon,
|
|
967
|
+
color=color,
|
|
948
968
|
create_if_missing=create_if_missing,
|
|
949
969
|
add_fields=add_fields,
|
|
950
970
|
update_fields=update_fields,
|
|
@@ -976,6 +996,8 @@ class AiBuilderTools(ToolBase):
|
|
|
976
996
|
"app_key": str(plan_args.get("app_key") or app_key),
|
|
977
997
|
"package_tag_id": plan_args.get("package_tag_id", package_tag_id),
|
|
978
998
|
"app_name": str(plan_args.get("app_name") or effective_app_name),
|
|
999
|
+
"icon": str(plan_args.get("icon") or icon),
|
|
1000
|
+
"color": str(plan_args.get("color") or color),
|
|
979
1001
|
"create_if_missing": bool(plan_args.get("create_if_missing", create_if_missing)),
|
|
980
1002
|
"publish": publish,
|
|
981
1003
|
"add_fields": plan_args.get("add_fields") or [{"name": "字段名称", "type": "text", "required": False}],
|
|
@@ -988,6 +1010,8 @@ class AiBuilderTools(ToolBase):
|
|
|
988
1010
|
"app_key": str(plan_args.get("app_key") or app_key),
|
|
989
1011
|
"package_tag_id": plan_args.get("package_tag_id", package_tag_id),
|
|
990
1012
|
"app_name": str(plan_args.get("app_name") or effective_app_name),
|
|
1013
|
+
"icon": str(plan_args.get("icon") or icon or ""),
|
|
1014
|
+
"color": str(plan_args.get("color") or color or ""),
|
|
991
1015
|
"create_if_missing": bool(plan_args.get("create_if_missing", create_if_missing)),
|
|
992
1016
|
"publish": publish,
|
|
993
1017
|
"add_fields": [patch.model_dump(mode="json") for patch in parsed_add],
|
|
@@ -1000,6 +1024,8 @@ class AiBuilderTools(ToolBase):
|
|
|
1000
1024
|
app_key=str(plan_args.get("app_key") or app_key),
|
|
1001
1025
|
package_tag_id=plan_args.get("package_tag_id", package_tag_id),
|
|
1002
1026
|
app_name=str(plan_args.get("app_name") or effective_app_name),
|
|
1027
|
+
icon=str(plan_args.get("icon") or icon or ""),
|
|
1028
|
+
color=str(plan_args.get("color") or color or ""),
|
|
1003
1029
|
create_if_missing=bool(plan_args.get("create_if_missing", create_if_missing)),
|
|
1004
1030
|
publish=publish,
|
|
1005
1031
|
add_fields=parsed_add,
|
|
@@ -1744,6 +1770,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
1744
1770
|
"payload.backgroundColor": "payload.background_color",
|
|
1745
1771
|
"payload.textColor": "payload.text_color",
|
|
1746
1772
|
"payload.buttonIcon": "payload.button_icon",
|
|
1773
|
+
"payload.iconColor": "payload.icon_color",
|
|
1747
1774
|
"payload.triggerAction": "payload.trigger_action",
|
|
1748
1775
|
"payload.triggerLinkUrl": "payload.trigger_link_url",
|
|
1749
1776
|
"payload.triggerAddDataConfig": "payload.trigger_add_data_config",
|
|
@@ -1762,6 +1789,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
1762
1789
|
"background_color": "#FFFFFF",
|
|
1763
1790
|
"text_color": "#494F57",
|
|
1764
1791
|
"button_icon": "ex-add-outlined",
|
|
1792
|
+
"icon_color": "#494F57",
|
|
1765
1793
|
"trigger_action": "link",
|
|
1766
1794
|
"trigger_link_url": "https://example.com",
|
|
1767
1795
|
},
|
|
@@ -1775,6 +1803,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
1775
1803
|
"payload.backgroundColor": "payload.background_color",
|
|
1776
1804
|
"payload.textColor": "payload.text_color",
|
|
1777
1805
|
"payload.buttonIcon": "payload.button_icon",
|
|
1806
|
+
"payload.iconColor": "payload.icon_color",
|
|
1778
1807
|
"payload.triggerAction": "payload.trigger_action",
|
|
1779
1808
|
"payload.triggerLinkUrl": "payload.trigger_link_url",
|
|
1780
1809
|
"payload.triggerAddDataConfig": "payload.trigger_add_data_config",
|
|
@@ -1794,6 +1823,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
1794
1823
|
"background_color": "#FFFFFF",
|
|
1795
1824
|
"text_color": "#494F57",
|
|
1796
1825
|
"button_icon": "ex-link-outlined",
|
|
1826
|
+
"icon_color": "#494F57",
|
|
1797
1827
|
"trigger_action": "link",
|
|
1798
1828
|
"trigger_link_url": "https://example.com/detail",
|
|
1799
1829
|
},
|
|
@@ -1810,7 +1840,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
1810
1840
|
},
|
|
1811
1841
|
},
|
|
1812
1842
|
"app_schema_plan": {
|
|
1813
|
-
"allowed_keys": ["app_key", "package_tag_id", "app_name", "create_if_missing", "add_fields", "update_fields", "remove_fields"],
|
|
1843
|
+
"allowed_keys": ["app_key", "package_tag_id", "app_name", "icon", "color", "create_if_missing", "add_fields", "update_fields", "remove_fields"],
|
|
1814
1844
|
"aliases": {
|
|
1815
1845
|
"app_title": "app_name",
|
|
1816
1846
|
"title": "app_name",
|
|
@@ -1835,6 +1865,8 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
1835
1865
|
"profile": "default",
|
|
1836
1866
|
"app_name": "研发项目管理",
|
|
1837
1867
|
"package_tag_id": 1001,
|
|
1868
|
+
"icon": "template",
|
|
1869
|
+
"color": "emerald",
|
|
1838
1870
|
"create_if_missing": True,
|
|
1839
1871
|
"add_fields": [{"name": "项目名称", "type": "text"}],
|
|
1840
1872
|
"update_fields": [],
|
|
@@ -1858,7 +1890,7 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
1858
1890
|
},
|
|
1859
1891
|
},
|
|
1860
1892
|
"app_schema_apply": {
|
|
1861
|
-
"allowed_keys": ["app_key", "package_tag_id", "app_name", "create_if_missing", "publish", "add_fields", "update_fields", "remove_fields"],
|
|
1893
|
+
"allowed_keys": ["app_key", "package_tag_id", "app_name", "icon", "color", "create_if_missing", "publish", "add_fields", "update_fields", "remove_fields"],
|
|
1862
1894
|
"aliases": {
|
|
1863
1895
|
"app_title": "app_name",
|
|
1864
1896
|
"title": "app_name",
|
|
@@ -1888,6 +1920,8 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
1888
1920
|
"profile": "default",
|
|
1889
1921
|
"app_name": "研发项目管理",
|
|
1890
1922
|
"package_tag_id": 1001,
|
|
1923
|
+
"icon": "template",
|
|
1924
|
+
"color": "emerald",
|
|
1891
1925
|
"create_if_missing": True,
|
|
1892
1926
|
"publish": True,
|
|
1893
1927
|
"add_fields": [{"name": "项目名称", "type": "text"}],
|
|
@@ -147,6 +147,7 @@ class CustomButtonTools(ToolBase):
|
|
|
147
147
|
"button_id": item.get("buttonId"),
|
|
148
148
|
"button_text": item.get("buttonText"),
|
|
149
149
|
"button_icon": item.get("buttonIcon"),
|
|
150
|
+
"icon_color": item.get("iconColor"),
|
|
150
151
|
"background_color": item.get("backgroundColor"),
|
|
151
152
|
"text_color": item.get("textColor"),
|
|
152
153
|
"creator_user_info": {
|
|
@@ -165,6 +166,7 @@ class CustomButtonTools(ToolBase):
|
|
|
165
166
|
"button_id": item.get("buttonId"),
|
|
166
167
|
"button_text": item.get("buttonText"),
|
|
167
168
|
"button_icon": item.get("buttonIcon"),
|
|
169
|
+
"icon_color": item.get("iconColor"),
|
|
168
170
|
"background_color": item.get("backgroundColor"),
|
|
169
171
|
"text_color": item.get("textColor"),
|
|
170
172
|
"trigger_action": item.get("triggerAction"),
|