@josephyan/qingflow-cli 0.2.0-beta.65 → 0.2.0-beta.67
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/service.py +42 -5
- package/src/qingflow_mcp/cli/commands/builder.py +23 -0
- package/src/qingflow_mcp/server_app_builder.py +7 -2
- package/src/qingflow_mcp/solution/compiler/icon_utils.py +49 -46
- package/src/qingflow_mcp/tools/ai_builder_tools.py +63 -6
- package/src/qingflow_mcp/tools/package_tools.py +1 -0
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Install:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npm install @josephyan/qingflow-cli@0.2.0-beta.
|
|
6
|
+
npm install @josephyan/qingflow-cli@0.2.0-beta.67
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
Run:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y -p @josephyan/qingflow-cli@0.2.0-beta.
|
|
12
|
+
npx -y -p @josephyan/qingflow-cli@0.2.0-beta.67 qingflow
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Environment:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@josephyan/qingflow-cli",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.67",
|
|
4
4
|
"description": "Human-friendly Qingflow command line interface for auth, record operations, import, tasks, and stable builder flows.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/pyproject.toml
CHANGED
|
@@ -192,7 +192,11 @@ class AiBuilderFacade:
|
|
|
192
192
|
)
|
|
193
193
|
items = listing.get("items") if isinstance(listing.get("items"), list) else []
|
|
194
194
|
matches = [
|
|
195
|
-
{
|
|
195
|
+
{
|
|
196
|
+
"tag_id": item.get("tagId"),
|
|
197
|
+
"tag_name": item.get("tagName"),
|
|
198
|
+
"tag_icon": str(item.get("tagIcon") or "").strip() or None,
|
|
199
|
+
}
|
|
196
200
|
for item in items
|
|
197
201
|
if isinstance(item, dict) and item.get("tagName") == requested and _coerce_positive_int(item.get("tagId")) is not None
|
|
198
202
|
]
|
|
@@ -226,12 +230,24 @@ class AiBuilderFacade:
|
|
|
226
230
|
"verification": {},
|
|
227
231
|
"tag_id": match["tag_id"],
|
|
228
232
|
"tag_name": match["tag_name"],
|
|
233
|
+
"tag_icon": match.get("tag_icon"),
|
|
229
234
|
"match_mode": "exact",
|
|
230
235
|
}
|
|
231
236
|
|
|
232
|
-
def package_create(
|
|
237
|
+
def package_create(
|
|
238
|
+
self,
|
|
239
|
+
*,
|
|
240
|
+
profile: str,
|
|
241
|
+
package_name: str,
|
|
242
|
+
icon: str | None = None,
|
|
243
|
+
color: str | None = None,
|
|
244
|
+
) -> JSONObject:
|
|
233
245
|
requested = str(package_name or "").strip()
|
|
234
|
-
normalized_args = {
|
|
246
|
+
normalized_args = {
|
|
247
|
+
"package_name": requested,
|
|
248
|
+
**({"icon": icon} if icon else {}),
|
|
249
|
+
**({"color": color} if color else {}),
|
|
250
|
+
}
|
|
235
251
|
if not requested:
|
|
236
252
|
return _failed(
|
|
237
253
|
"PACKAGE_NAME_REQUIRED",
|
|
@@ -239,6 +255,12 @@ class AiBuilderFacade:
|
|
|
239
255
|
normalized_args=normalized_args,
|
|
240
256
|
suggested_next_call=None,
|
|
241
257
|
)
|
|
258
|
+
desired_tag_icon = encode_workspace_icon_with_defaults(
|
|
259
|
+
icon=icon,
|
|
260
|
+
color=color,
|
|
261
|
+
title=requested,
|
|
262
|
+
fallback_icon_name="files-folder",
|
|
263
|
+
)
|
|
242
264
|
existing = self.package_resolve(profile=profile, package_name=requested)
|
|
243
265
|
lookup_permission_blocked = None
|
|
244
266
|
if existing.get("status") == "success":
|
|
@@ -257,6 +279,7 @@ class AiBuilderFacade:
|
|
|
257
279
|
"verification": {"existing_package_reused": True},
|
|
258
280
|
"tag_id": existing.get("tag_id"),
|
|
259
281
|
"tag_name": existing.get("tag_name"),
|
|
282
|
+
"tag_icon": existing.get("tag_icon"),
|
|
260
283
|
}
|
|
261
284
|
if existing.get("error_code") == "AMBIGUOUS_PACKAGE":
|
|
262
285
|
return existing
|
|
@@ -271,7 +294,10 @@ class AiBuilderFacade:
|
|
|
271
294
|
elif existing.get("error_code") not in {"PACKAGE_NOT_FOUND"}:
|
|
272
295
|
return existing
|
|
273
296
|
try:
|
|
274
|
-
created = self.packages.package_create(
|
|
297
|
+
created = self.packages.package_create(
|
|
298
|
+
profile=profile,
|
|
299
|
+
payload={"tagName": requested, "tagIcon": desired_tag_icon},
|
|
300
|
+
)
|
|
275
301
|
except (QingflowApiError, RuntimeError) as error:
|
|
276
302
|
api_error = _coerce_api_error(error)
|
|
277
303
|
return _failed_from_api_error(
|
|
@@ -282,16 +308,26 @@ class AiBuilderFacade:
|
|
|
282
308
|
"package_name": requested,
|
|
283
309
|
**({"lookup_permission_blocked": lookup_permission_blocked} if lookup_permission_blocked is not None else {}),
|
|
284
310
|
},
|
|
285
|
-
suggested_next_call={
|
|
311
|
+
suggested_next_call={
|
|
312
|
+
"tool_name": "package_create",
|
|
313
|
+
"arguments": {
|
|
314
|
+
"profile": profile,
|
|
315
|
+
"package_name": requested,
|
|
316
|
+
**({"icon": icon} if icon else {}),
|
|
317
|
+
**({"color": color} if color else {}),
|
|
318
|
+
},
|
|
319
|
+
},
|
|
286
320
|
)
|
|
287
321
|
result = created.get("result") if isinstance(created.get("result"), dict) else {}
|
|
288
322
|
tag_id = _coerce_positive_int(result.get("tagId"))
|
|
289
323
|
tag_name = str(result.get("tagName") or requested).strip() or requested
|
|
324
|
+
tag_icon = str(result.get("tagIcon") or desired_tag_icon or "").strip() or None
|
|
290
325
|
if tag_id is None:
|
|
291
326
|
resolved = self.package_resolve(profile=profile, package_name=requested)
|
|
292
327
|
if resolved.get("status") == "success":
|
|
293
328
|
tag_id = _coerce_positive_int(resolved.get("tag_id"))
|
|
294
329
|
tag_name = str(resolved.get("tag_name") or tag_name)
|
|
330
|
+
tag_icon = str(resolved.get("tag_icon") or tag_icon or "").strip() or None
|
|
295
331
|
verified = tag_id is not None
|
|
296
332
|
return {
|
|
297
333
|
"status": "success" if verified else "partial_success",
|
|
@@ -310,6 +346,7 @@ class AiBuilderFacade:
|
|
|
310
346
|
"verification": {"tag_id_verified": verified},
|
|
311
347
|
"tag_id": tag_id,
|
|
312
348
|
"tag_name": tag_name,
|
|
349
|
+
"tag_icon": tag_icon,
|
|
313
350
|
}
|
|
314
351
|
|
|
315
352
|
def package_list(self, *, profile: str, trial_status: str = "all") -> JSONObject:
|
|
@@ -12,10 +12,20 @@ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) ->
|
|
|
12
12
|
|
|
13
13
|
package = builder_subparsers.add_parser("package", help="应用包")
|
|
14
14
|
package_subparsers = package.add_subparsers(dest="builder_package_command", required=True)
|
|
15
|
+
package_list = package_subparsers.add_parser("list", help="列出应用包")
|
|
16
|
+
package_list.add_argument("--trial-status", default="all")
|
|
17
|
+
package_list.set_defaults(handler=_handle_package_list, format_hint="builder_summary")
|
|
18
|
+
|
|
15
19
|
package_resolve = package_subparsers.add_parser("resolve", help="解析应用包")
|
|
16
20
|
package_resolve.add_argument("--package-name", required=True)
|
|
17
21
|
package_resolve.set_defaults(handler=_handle_package_resolve, format_hint="builder_summary")
|
|
18
22
|
|
|
23
|
+
package_create = package_subparsers.add_parser("create", help="创建应用包")
|
|
24
|
+
package_create.add_argument("--package-name", required=True)
|
|
25
|
+
package_create.add_argument("--icon")
|
|
26
|
+
package_create.add_argument("--color")
|
|
27
|
+
package_create.set_defaults(handler=_handle_package_create, format_hint="builder_summary")
|
|
28
|
+
|
|
19
29
|
app = builder_subparsers.add_parser("app", help="应用")
|
|
20
30
|
app_subparsers = app.add_subparsers(dest="builder_app_command", required=True)
|
|
21
31
|
|
|
@@ -119,10 +129,23 @@ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) ->
|
|
|
119
129
|
publish_verify_verify.set_defaults(handler=_handle_publish_verify, format_hint="builder_summary")
|
|
120
130
|
|
|
121
131
|
|
|
132
|
+
def _handle_package_list(args: argparse.Namespace, context: CliContext) -> dict:
|
|
133
|
+
return context.builder.package_list(profile=args.profile, trial_status=args.trial_status)
|
|
134
|
+
|
|
135
|
+
|
|
122
136
|
def _handle_package_resolve(args: argparse.Namespace, context: CliContext) -> dict:
|
|
123
137
|
return context.builder.package_resolve(profile=args.profile, package_name=args.package_name)
|
|
124
138
|
|
|
125
139
|
|
|
140
|
+
def _handle_package_create(args: argparse.Namespace, context: CliContext) -> dict:
|
|
141
|
+
return context.builder.package_create(
|
|
142
|
+
profile=args.profile,
|
|
143
|
+
package_name=args.package_name,
|
|
144
|
+
icon=args.icon,
|
|
145
|
+
color=args.color,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
|
|
126
149
|
def _handle_app_resolve(args: argparse.Namespace, context: CliContext) -> dict:
|
|
127
150
|
return context.builder.app_resolve(
|
|
128
151
|
profile=args.profile,
|
|
@@ -138,8 +138,13 @@ def build_builder_server() -> FastMCP:
|
|
|
138
138
|
return ai_builder.builder_tool_contract(tool_name=tool_name)
|
|
139
139
|
|
|
140
140
|
@server.tool()
|
|
141
|
-
def package_create(
|
|
142
|
-
|
|
141
|
+
def package_create(
|
|
142
|
+
profile: str = DEFAULT_PROFILE,
|
|
143
|
+
package_name: str = "",
|
|
144
|
+
icon: str | None = None,
|
|
145
|
+
color: str | None = None,
|
|
146
|
+
) -> dict:
|
|
147
|
+
return ai_builder.package_create(profile=profile, package_name=package_name, icon=icon, color=color)
|
|
143
148
|
|
|
144
149
|
@server.tool()
|
|
145
150
|
def member_search(
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import re
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
DEFAULT_ICON_COLOR = "qing-orange"
|
|
7
8
|
DEFAULT_ICON_STYLE_POOL: tuple[tuple[str, str], ...] = (
|
|
8
9
|
("briefcase", "qing-orange"),
|
|
9
10
|
("calendar", "emerald"),
|
|
10
|
-
("folder", "azure"),
|
|
11
|
+
("files-folder", "azure"),
|
|
11
12
|
("shield-check", "indigo"),
|
|
12
13
|
("user-group", "qing-purple"),
|
|
13
14
|
("chart-square-bar", "blue"),
|
|
@@ -16,41 +17,41 @@ DEFAULT_ICON_STYLE_POOL: tuple[tuple[str, str], ...] = (
|
|
|
16
17
|
("home", "orange"),
|
|
17
18
|
("globe", "red"),
|
|
18
19
|
)
|
|
19
|
-
|
|
20
|
-
"ex-alert-outlined",
|
|
21
|
-
"ex-clock-outlined",
|
|
22
|
-
"ex-folder-outlined",
|
|
23
|
-
"ex-form-outlined",
|
|
24
|
-
"ex-home-outlined",
|
|
25
|
-
"ex-user-outlined",
|
|
20
|
+
LEGACY_EX_ICON_MAP = {
|
|
21
|
+
"ex-alert-outlined": "exclamation-circle",
|
|
22
|
+
"ex-clock-outlined": "clock",
|
|
23
|
+
"ex-folder-outlined": "folder",
|
|
24
|
+
"ex-form-outlined": "template",
|
|
25
|
+
"ex-home-outlined": "home",
|
|
26
|
+
"ex-user-outlined": "user",
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
ICON_ALIAS_MAP = {
|
|
29
|
-
"archive-box": "
|
|
30
|
-
"beaker": "
|
|
31
|
-
"briefcase": "
|
|
32
|
-
"building-office": "
|
|
33
|
-
"calendar": "
|
|
34
|
-
"chat": "
|
|
35
|
-
"chat-bubble-left-right": "
|
|
36
|
-
"chart-bar": "
|
|
37
|
-
"chart-square-bar": "
|
|
38
|
-
"check-badge": "
|
|
39
|
-
"check-circle": "
|
|
40
|
-
"clipboard-check": "
|
|
41
|
-
"clock": "
|
|
42
|
-
"cube": "
|
|
43
|
-
"document-text": "
|
|
44
|
-
"folder": "
|
|
45
|
-
"home": "
|
|
46
|
-
"office-building": "
|
|
47
|
-
"shield-check": "
|
|
48
|
-
"template": "
|
|
49
|
-
"user": "
|
|
50
|
-
"user-group": "
|
|
51
|
-
"users": "
|
|
52
|
-
"view-grid": "
|
|
53
|
-
"warning": "
|
|
30
|
+
"archive-box": "template",
|
|
31
|
+
"beaker": "beaker",
|
|
32
|
+
"briefcase": "briefcase",
|
|
33
|
+
"building-office": "office-building",
|
|
34
|
+
"calendar": "calendar",
|
|
35
|
+
"chat": "chat",
|
|
36
|
+
"chat-bubble-left-right": "chat",
|
|
37
|
+
"chart-bar": "chart-bar",
|
|
38
|
+
"chart-square-bar": "chart-square-bar",
|
|
39
|
+
"check-badge": "badge-check",
|
|
40
|
+
"check-circle": "check-circle",
|
|
41
|
+
"clipboard-check": "clipboard-check",
|
|
42
|
+
"clock": "clock",
|
|
43
|
+
"cube": "cube-transparent",
|
|
44
|
+
"document-text": "document-text",
|
|
45
|
+
"folder": "files-folder",
|
|
46
|
+
"home": "home",
|
|
47
|
+
"office-building": "office-building",
|
|
48
|
+
"shield-check": "shield-check",
|
|
49
|
+
"template": "template",
|
|
50
|
+
"user": "user",
|
|
51
|
+
"user-group": "user-group",
|
|
52
|
+
"users": "user-group",
|
|
53
|
+
"view-grid": "view-grid",
|
|
54
|
+
"warning": "exclamation-circle",
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
|
|
@@ -64,8 +65,6 @@ def encode_workspace_icon(
|
|
|
64
65
|
if icon and _looks_like_icon_json(icon):
|
|
65
66
|
return icon
|
|
66
67
|
normalized_icon_name = normalize_workspace_icon_name(icon or fallback_icon_name)
|
|
67
|
-
if normalized_icon_name and normalized_icon_name.startswith("ex-") and not color:
|
|
68
|
-
return normalized_icon_name
|
|
69
68
|
icon_name = normalized_icon_name
|
|
70
69
|
icon_color = color or DEFAULT_ICON_COLOR
|
|
71
70
|
if icon_name:
|
|
@@ -156,27 +155,31 @@ def normalize_workspace_icon_name(icon: str | None) -> str | None:
|
|
|
156
155
|
try:
|
|
157
156
|
payload = json.loads(icon)
|
|
158
157
|
except Exception:
|
|
159
|
-
return "
|
|
160
|
-
return normalize_workspace_icon_name(payload.get("iconName")) or "
|
|
161
|
-
if icon in SUPPORTED_EX_ICONS:
|
|
162
|
-
return icon
|
|
158
|
+
return "template"
|
|
159
|
+
return normalize_workspace_icon_name(payload.get("iconName")) or "template"
|
|
163
160
|
normalized = icon.strip().lower()
|
|
161
|
+
if normalized in LEGACY_EX_ICON_MAP:
|
|
162
|
+
return LEGACY_EX_ICON_MAP[normalized]
|
|
164
163
|
if normalized in ICON_ALIAS_MAP:
|
|
165
164
|
return ICON_ALIAS_MAP[normalized]
|
|
166
165
|
for token in normalized.replace("_", "-").split("-"):
|
|
167
166
|
if token in ICON_ALIAS_MAP:
|
|
168
167
|
return ICON_ALIAS_MAP[token]
|
|
169
168
|
if "folder" in normalized or "package" in normalized:
|
|
170
|
-
return "
|
|
171
|
-
if "home" in normalized
|
|
172
|
-
return "
|
|
169
|
+
return "files-folder"
|
|
170
|
+
if "home" in normalized:
|
|
171
|
+
return "home"
|
|
172
|
+
if "portal" in normalized or "dashboard" in normalized:
|
|
173
|
+
return "view-grid"
|
|
173
174
|
if "user" in normalized or "member" in normalized or "contact" in normalized:
|
|
174
|
-
return "
|
|
175
|
+
return "user"
|
|
175
176
|
if "clock" in normalized or "time" in normalized or "schedule" in normalized or "log" in normalized:
|
|
176
|
-
return "
|
|
177
|
+
return "clock"
|
|
177
178
|
if "risk" in normalized or "alert" in normalized or "warn" in normalized or "safety" in normalized:
|
|
178
|
-
return "
|
|
179
|
-
|
|
179
|
+
return "exclamation-circle"
|
|
180
|
+
if re.fullmatch(r"[a-z0-9-]+", normalized):
|
|
181
|
+
return normalized
|
|
182
|
+
return "template"
|
|
180
183
|
|
|
181
184
|
|
|
182
185
|
def _looks_like_icon_json(value: str) -> bool:
|
|
@@ -82,8 +82,13 @@ class AiBuilderTools(ToolBase):
|
|
|
82
82
|
return self.builder_tool_contract(tool_name=tool_name)
|
|
83
83
|
|
|
84
84
|
@mcp.tool()
|
|
85
|
-
def package_create(
|
|
86
|
-
|
|
85
|
+
def package_create(
|
|
86
|
+
profile: str = DEFAULT_PROFILE,
|
|
87
|
+
package_name: str = "",
|
|
88
|
+
icon: str | None = None,
|
|
89
|
+
color: str | None = None,
|
|
90
|
+
) -> JSONObject:
|
|
91
|
+
return self.package_create(profile=profile, package_name=package_name, icon=icon, color=color)
|
|
87
92
|
|
|
88
93
|
@mcp.tool()
|
|
89
94
|
def member_search(
|
|
@@ -425,13 +430,32 @@ class AiBuilderTools(ToolBase):
|
|
|
425
430
|
"contract": contract,
|
|
426
431
|
}
|
|
427
432
|
|
|
428
|
-
def package_create(
|
|
429
|
-
|
|
433
|
+
def package_create(
|
|
434
|
+
self,
|
|
435
|
+
*,
|
|
436
|
+
profile: str,
|
|
437
|
+
package_name: str,
|
|
438
|
+
icon: str | None = None,
|
|
439
|
+
color: str | None = None,
|
|
440
|
+
) -> JSONObject:
|
|
441
|
+
normalized_args = {
|
|
442
|
+
"package_name": package_name,
|
|
443
|
+
**({"icon": icon} if icon else {}),
|
|
444
|
+
**({"color": color} if color else {}),
|
|
445
|
+
}
|
|
430
446
|
return _safe_tool_call(
|
|
431
|
-
lambda: self._facade.package_create(profile=profile, package_name=package_name),
|
|
447
|
+
lambda: self._facade.package_create(profile=profile, package_name=package_name, icon=icon, color=color),
|
|
432
448
|
error_code="PACKAGE_CREATE_FAILED",
|
|
433
449
|
normalized_args=normalized_args,
|
|
434
|
-
suggested_next_call={
|
|
450
|
+
suggested_next_call={
|
|
451
|
+
"tool_name": "package_create",
|
|
452
|
+
"arguments": {
|
|
453
|
+
"profile": profile,
|
|
454
|
+
"package_name": package_name,
|
|
455
|
+
**({"icon": icon} if icon else {}),
|
|
456
|
+
**({"color": color} if color else {}),
|
|
457
|
+
},
|
|
458
|
+
},
|
|
435
459
|
)
|
|
436
460
|
|
|
437
461
|
def member_search(
|
|
@@ -1708,6 +1732,39 @@ def _public_error_message(error_code: str, error: QingflowApiError) -> str:
|
|
|
1708
1732
|
|
|
1709
1733
|
|
|
1710
1734
|
_BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
1735
|
+
"package_list": {
|
|
1736
|
+
"allowed_keys": ["trial_status"],
|
|
1737
|
+
"aliases": {"trialStatus": "trial_status"},
|
|
1738
|
+
"allowed_values": {"trial_status": ["all", "trial", "formal"]},
|
|
1739
|
+
"minimal_example": {
|
|
1740
|
+
"profile": "default",
|
|
1741
|
+
"trial_status": "all",
|
|
1742
|
+
},
|
|
1743
|
+
},
|
|
1744
|
+
"package_resolve": {
|
|
1745
|
+
"allowed_keys": ["package_name"],
|
|
1746
|
+
"aliases": {"packageName": "package_name"},
|
|
1747
|
+
"allowed_values": {},
|
|
1748
|
+
"minimal_example": {
|
|
1749
|
+
"profile": "default",
|
|
1750
|
+
"package_name": "PLM(备用,施工中)",
|
|
1751
|
+
},
|
|
1752
|
+
},
|
|
1753
|
+
"package_create": {
|
|
1754
|
+
"allowed_keys": ["package_name", "icon", "color"],
|
|
1755
|
+
"aliases": {
|
|
1756
|
+
"packageName": "package_name",
|
|
1757
|
+
"iconName": "icon",
|
|
1758
|
+
"iconColor": "color",
|
|
1759
|
+
},
|
|
1760
|
+
"allowed_values": {},
|
|
1761
|
+
"minimal_example": {
|
|
1762
|
+
"profile": "default",
|
|
1763
|
+
"package_name": "项目管理",
|
|
1764
|
+
"icon": "files-folder",
|
|
1765
|
+
"color": "azure",
|
|
1766
|
+
},
|
|
1767
|
+
},
|
|
1711
1768
|
"member_search": {
|
|
1712
1769
|
"allowed_keys": ["query", "page_num", "page_size", "contain_disable"],
|
|
1713
1770
|
"aliases": {},
|
|
@@ -200,6 +200,7 @@ class PackageTools(ToolBase):
|
|
|
200
200
|
compact = {
|
|
201
201
|
"tagId": result.get("tagId"),
|
|
202
202
|
"tagName": result.get("tagName"),
|
|
203
|
+
"tagIcon": result.get("tagIcon") if result.get("tagIcon") is not None else permission_source.get("tagIcon"),
|
|
203
204
|
"publishStatus": result.get("publishStatus") if result.get("publishStatus") is not None else permission_source.get("publishStatus"),
|
|
204
205
|
"beingTrial": result.get("beingTrial"),
|
|
205
206
|
"itemCount": len(tag_items),
|