@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.
@@ -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"),