@josephyan/qingflow-cli 1.1.14 → 1.1.16
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/skills/qingflow-cli/reference/builder/30-schema-fields.md +3 -3
- package/skills/qingflow-cli/reference/builder/reference/app-delivery-sop.md +3 -5
- package/src/qingflow_mcp/cli/commands/builder.py +2 -2
- package/src/qingflow_mcp/server_app_builder.py +8 -7
- package/src/qingflow_mcp/tools/ai_builder_tools.py +17 -17
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Install:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npm install @josephyan/qingflow-cli@1.1.
|
|
6
|
+
npm install @josephyan/qingflow-cli@1.1.16
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
Run:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y -p @josephyan/qingflow-cli@1.1.
|
|
12
|
+
npx -y -p @josephyan/qingflow-cli@1.1.16 qingflow
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Environment:
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -112,7 +112,7 @@ Example patch:
|
|
|
112
112
|
|------|----------------|------|
|
|
113
113
|
| 编辑已有应用 | `--app-key`;可选 `--no-publish` | **不要**与 `--package-id`、`--create-if-missing` 同用 |
|
|
114
114
|
| 包内新建应用 | `--package-id`、`--app-name`(或 title 映射)、**`--create-if-missing`**;初始 `add-fields-file` 至少包含一个 `as_data_title: true` 字段 | 创建后可得到新 **`app_key`**(以响应为准) |
|
|
115
|
-
| 多应用一次性新建 | `--
|
|
115
|
+
| 多应用一次性新建 | `--apps-file`,文件顶层写 `package_id` + `apps` | 应用包/系统里有 2 个以上应用,或同批应用之间有 `relation` 时使用;多应用默认按 `app_name` 创建或复用缺失应用,不要求额外写 `create_if_missing`;raw apps array / singleton wrapper array 仅兼容;`apps[].client_key` 可被 `target_app_ref` 引用,`apps[].app_name` 可被 `target_app` 引用 |
|
|
116
116
|
| 仅增字段 | `--add-fields-file`(JSON 数组) | 与 **`update_fields`/`remove_fields`** 可同次组合(以契约为准) |
|
|
117
117
|
| 改字段 | `--update-fields-file` | 每项 **`selector`**(`name`/`que_id`/`field_id`)+ **`set`** |
|
|
118
118
|
| 删字段 | `--remove-fields-file` | 每项至少 **`name`/`que_id`/`field_id`** 之一 |
|
|
@@ -136,9 +136,9 @@ Example patch:
|
|
|
136
136
|
|
|
137
137
|
**一次性新建应用**:`--package-id` + `--app-name` + `--create-if-missing` + [schema_apply_add_fields_all_types.json](../examples/schema/schema_apply_add_fields_all_types.json) 是当前推荐示例;它已包含唯一数据标题和可选数据封面(`q_linker` 使用 `https://httpbin.org/get`,`relation` 指向可读模板应用 `ead8ims5i401`)。
|
|
138
138
|
|
|
139
|
-
**一次性新建多个应用**:用 `builder schema apply --
|
|
139
|
+
**一次性新建多个应用**:用 `builder schema apply --apps-file tmp/apps.json`,其中 `tmp/apps.json` 主写法为 `{ "package_id": 123, "apps": [...] }`,每个 `apps[]` 写顶层 `icon + color`;多应用模式默认按 `app_name` 创建或复用应用。`apps[].client_key` 可被同批 relation 字段的 `target_app_ref` 引用,`apps[].app_name` 可被 `target_app` 引用,工具会编译成真实 `target_app_key`。这是应用包/系统搭建的默认路径,尤其适合“商机 + 订单 + 回款”“花名册 + 工时”等互相关联场景;不要为了拿 `app_key` 先逐个创建再二次补关联字段。
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
**限制(平台硬性)**:`--app-key` 向已有应用追加字段时须 **字段名不重复**;`relation` 字段数量不做“每应用只能一个”的智能体侧限制,按后端实际校验和写后读回为准。**`example.com`** 作 `q_linker` URL 易触发 **`46031`**,本清单改用 httpbin。**读回缺 `outputs[].target_field` 的 `q_linker`** 会拖死后续 `schema apply`,须修复或删除该题。
|
|
142
142
|
|
|
143
143
|
**排障**:`--json`;**`DUPLICATE_FIELD`**;**`MULTIPLE_RELATION_FIELDS_UNSUPPORTED`(49614)**。
|
|
144
144
|
|
|
@@ -130,7 +130,7 @@ qingflow builder schema apply \
|
|
|
130
130
|
|
|
131
131
|
- **`--icon` / `--color`**:取值以 `builder contract --tool-name app_schema_apply` / 当前 CLI 契约候选为准;不要自造 `sales-*`、`crm-*` 等业务语义 key。契约未返回候选值时省略该参数,不要猜测写入。
|
|
132
132
|
|
|
133
|
-
-
|
|
133
|
+
- **单应用创建模式要件**(与契约一致):**`package_id` + `app_name`(或 CLI 的 app-title 映射到 app_name)+ `create_if_missing`**。
|
|
134
134
|
- **图标必填**:创建应用必须显式传合法的 **`icon + color`**;不要用 `template`。CLI 只校验候选,不根据应用名称自动猜图标。多应用批量创建时,每个新应用应使用不同 `icon`。
|
|
135
135
|
- **数据标题必填**:最终表单必须有且仅有一个顶层可读字段标记 `as_data_title: true`;数据封面可选,必须是顶层 `attachment` 字段标记 `as_data_cover: true`。
|
|
136
136
|
- **编辑模式**:**仅** **`--app-key`**(可选改名 `--app-name`),**不要**与 `package_id` / `create_if_missing` 混用。
|
|
@@ -141,12 +141,10 @@ qingflow builder schema apply \
|
|
|
141
141
|
|
|
142
142
|
```bash
|
|
143
143
|
qingflow builder schema apply \
|
|
144
|
-
--package-id <TAG_ID> \
|
|
145
|
-
--create-if-missing \
|
|
146
144
|
--apps-file tmp/apps.json
|
|
147
145
|
```
|
|
148
146
|
|
|
149
|
-
`apps.json` 主写法是对象形态 `{ "package_id": 123, "apps": [...] }`。CLI 兼容 raw apps array 和 singleton wrapper array,但不作为智能体主示例;不要把多个 `{package_id, apps}` wrapper 放进数组里。每个 `apps[]` 是一个应用 schema 配置,写自己的 `client_key`、`app_name`、`icon`、`color`、`add_fields`;同批应用之间的关联字段主写 **`target_app_ref`** 指向另一个应用的 `client_key`。只有目标应用已经存在或已被读回确认时,才使用真实 `target_app_key`;不要因为同批创建时还不知道真实 `app_key` 就放弃 `target_app_ref`。写入前 CLI 会先做静态预校验,`client_key/app_name` 重复、缺少 `as_data_title
|
|
147
|
+
`apps.json` 主写法是对象形态 `{ "package_id": 123, "apps": [...] }`,多应用模式默认允许按 `app_name` 创建或复用应用,不要求智能体额外写 `create_if_missing`。CLI 兼容 raw apps array 和 singleton wrapper array,但不作为智能体主示例;不要把多个 `{package_id, apps}` wrapper 放进数组里。每个 `apps[]` 是一个应用 schema 配置,写自己的 `client_key`、`app_name`、`icon`、`color`、`add_fields`;同批应用之间的关联字段主写 **`target_app_ref`** 指向另一个应用的 `client_key`。只有目标应用已经存在或已被读回确认时,才使用真实 `target_app_key`;不要因为同批创建时还不知道真实 `app_key` 就放弃 `target_app_ref`。写入前 CLI 会先做静态预校验,`client_key/app_name` 重复、缺少 `as_data_title`、显式 `create_if_missing:false` 但 `apps[]` 仍用 `app_name` 省略 `app_key`、`target_app_ref/target_app` 无法解析都会以 `MULTI_APP_STATIC_VALIDATION_FAILED` 返回,不会先创建半成品应用:
|
|
150
148
|
|
|
151
149
|
```json
|
|
152
150
|
{
|
|
@@ -257,7 +255,7 @@ qingflow builder schema apply \
|
|
|
257
255
|
(路径以 `qingflow-cli/` 技能根目录为基准;执行时可解析为该技能目录下的实际文件。)
|
|
258
256
|
|
|
259
257
|
- **`name`** 须为当前应用内 **唯一** 的控件显示名;若报重名,改 **`示例搭建_CLI单行`** 后再执行。
|
|
260
|
-
- 本文件对应契约 **`app_schema_apply`** 中 **`add_fields`** 的 **最小 `text`** 项;更多 **`type`** 见 **§6**;完整创建应用:单应用见 **§3.2**(**`package_id` + `app_name` + `create_if_missing`**),多应用/跨应用引用见 **§3.3**(**`--apps-file` + `client_key` / `target_app_ref
|
|
258
|
+
- 本文件对应契约 **`app_schema_apply`** 中 **`add_fields`** 的 **最小 `text`** 项;更多 **`type`** 见 **§6**;完整创建应用:单应用见 **§3.2**(**`package_id` + `app_name` + `create_if_missing`**),多应用/跨应用引用见 **§3.3**(**`--apps-file` + `client_key` / `target_app_ref`**,默认创建或复用缺失应用)。
|
|
261
259
|
|
|
262
260
|
```bash
|
|
263
261
|
qingflow builder schema apply \
|
|
@@ -563,7 +563,7 @@ def _handle_schema_apply(args: argparse.Namespace, context: CliContext) -> dict:
|
|
|
563
563
|
file_create_if_missing = _coerce_apps_file_bool(
|
|
564
564
|
apps_payload.get("create_if_missing"),
|
|
565
565
|
field_name="create_if_missing",
|
|
566
|
-
default=
|
|
566
|
+
default=True,
|
|
567
567
|
)
|
|
568
568
|
file_publish = _coerce_apps_file_bool(
|
|
569
569
|
apps_payload.get("publish"),
|
|
@@ -580,7 +580,7 @@ def _handle_schema_apply(args: argparse.Namespace, context: CliContext) -> dict:
|
|
|
580
580
|
)
|
|
581
581
|
if args.app_key or args.app_name or args.app_title or args.add_fields_file or args.update_fields_file or args.remove_fields_file:
|
|
582
582
|
raise_config_error(
|
|
583
|
-
"schema apply multi-app mode accepts --package-id
|
|
583
|
+
"schema apply multi-app mode accepts --package-id plus --apps-file only; --create-if-missing is optional.",
|
|
584
584
|
fix_hint="Use `--apps-file` for batch mode, or remove `--apps-file` and use the single-app arguments.",
|
|
585
585
|
)
|
|
586
586
|
if package_id is None:
|
|
@@ -197,7 +197,7 @@ def build_builder_server() -> FastMCP:
|
|
|
197
197
|
profile: str = DEFAULT_PROFILE,
|
|
198
198
|
package_id: int | None = None,
|
|
199
199
|
package_name: str | None = None,
|
|
200
|
-
create_if_missing: bool =
|
|
200
|
+
create_if_missing: bool | None = None,
|
|
201
201
|
icon: str | None = None,
|
|
202
202
|
color: str | None = None,
|
|
203
203
|
visibility: dict | None = None,
|
|
@@ -426,7 +426,7 @@ def build_builder_server() -> FastMCP:
|
|
|
426
426
|
icon: str = "",
|
|
427
427
|
color: str = "",
|
|
428
428
|
visibility: dict | None = None,
|
|
429
|
-
create_if_missing: bool =
|
|
429
|
+
create_if_missing: bool | None = None,
|
|
430
430
|
publish: bool = True,
|
|
431
431
|
add_fields: list[dict] | None = None,
|
|
432
432
|
update_fields: list[dict] | None = None,
|
|
@@ -436,7 +436,7 @@ def build_builder_server() -> FastMCP:
|
|
|
436
436
|
if apps:
|
|
437
437
|
if app_key or app_name or app_title or add_fields or update_fields or remove_fields:
|
|
438
438
|
return _config_failure(
|
|
439
|
-
"app_schema_apply multi-app mode accepts package_id
|
|
439
|
+
"app_schema_apply multi-app mode accepts package_id plus apps only; create_if_missing is optional.",
|
|
440
440
|
fix_hint="Use `apps` for batch mode, or use the single-app arguments without `apps`.",
|
|
441
441
|
)
|
|
442
442
|
if package_id is None:
|
|
@@ -448,7 +448,7 @@ def build_builder_server() -> FastMCP:
|
|
|
448
448
|
profile=profile,
|
|
449
449
|
package_id=package_id,
|
|
450
450
|
visibility=visibility,
|
|
451
|
-
create_if_missing=create_if_missing,
|
|
451
|
+
create_if_missing=True if create_if_missing is None else bool(create_if_missing),
|
|
452
452
|
publish=publish,
|
|
453
453
|
add_fields=[],
|
|
454
454
|
update_fields=[],
|
|
@@ -459,13 +459,14 @@ def build_builder_server() -> FastMCP:
|
|
|
459
459
|
has_app_name = bool((app_name or "").strip())
|
|
460
460
|
has_app_title = bool((app_title or "").strip())
|
|
461
461
|
has_package_id = package_id is not None
|
|
462
|
+
effective_create_if_missing = bool(create_if_missing)
|
|
462
463
|
if has_app_key:
|
|
463
|
-
if
|
|
464
|
+
if effective_create_if_missing or has_package_id:
|
|
464
465
|
return _config_failure(
|
|
465
466
|
"app_schema_apply edit mode accepts app_key and optional app_name rename only.",
|
|
466
467
|
fix_hint="For existing apps, use `app_key` and optionally `app_name`. For create mode, use `package_id + app_name + create_if_missing=true`.",
|
|
467
468
|
)
|
|
468
|
-
elif not (
|
|
469
|
+
elif not (effective_create_if_missing and has_package_id and (has_app_name or has_app_title)):
|
|
469
470
|
return _config_failure(
|
|
470
471
|
"app_schema_apply create mode requires package_id, app_name, and create_if_missing=true.",
|
|
471
472
|
fix_hint="Use `app_key` for existing apps, or pass `package_id + app_name + create_if_missing=true` to create a new app.",
|
|
@@ -479,7 +480,7 @@ def build_builder_server() -> FastMCP:
|
|
|
479
480
|
icon=icon,
|
|
480
481
|
color=color,
|
|
481
482
|
visibility=visibility,
|
|
482
|
-
create_if_missing=
|
|
483
|
+
create_if_missing=effective_create_if_missing,
|
|
483
484
|
publish=publish,
|
|
484
485
|
add_fields=add_fields or [],
|
|
485
486
|
update_fields=update_fields or [],
|
|
@@ -330,7 +330,7 @@ class AiBuilderTools(ToolBase):
|
|
|
330
330
|
profile: str = DEFAULT_PROFILE,
|
|
331
331
|
package_id: int | None = None,
|
|
332
332
|
package_name: str | None = None,
|
|
333
|
-
create_if_missing: bool =
|
|
333
|
+
create_if_missing: bool | None = None,
|
|
334
334
|
icon: str | JSONObject | None = None,
|
|
335
335
|
color: str | None = None,
|
|
336
336
|
icon_name: str | None = None,
|
|
@@ -573,7 +573,7 @@ class AiBuilderTools(ToolBase):
|
|
|
573
573
|
icon_color: str | None = None,
|
|
574
574
|
icon_config: JSONObject | None = None,
|
|
575
575
|
visibility: JSONObject | None = None,
|
|
576
|
-
create_if_missing: bool =
|
|
576
|
+
create_if_missing: bool | None = None,
|
|
577
577
|
publish: bool = True,
|
|
578
578
|
add_fields: list[JSONObject] | None = None,
|
|
579
579
|
update_fields: list[JSONObject] | None = None,
|
|
@@ -584,7 +584,7 @@ class AiBuilderTools(ToolBase):
|
|
|
584
584
|
if app_key or app_name or app_title or add_fields or update_fields or remove_fields:
|
|
585
585
|
return _config_failure(
|
|
586
586
|
tool_name="app_schema_apply",
|
|
587
|
-
message="app_schema_apply multi-app mode accepts package_id
|
|
587
|
+
message="app_schema_apply multi-app mode accepts package_id plus apps only; create_if_missing is optional.",
|
|
588
588
|
fix_hint="Use `apps` for batch mode, or use the single-app arguments without `apps`.",
|
|
589
589
|
)
|
|
590
590
|
if package_id is None:
|
|
@@ -597,7 +597,7 @@ class AiBuilderTools(ToolBase):
|
|
|
597
597
|
profile=profile,
|
|
598
598
|
package_id=package_id,
|
|
599
599
|
visibility=visibility,
|
|
600
|
-
create_if_missing=create_if_missing,
|
|
600
|
+
create_if_missing=True if create_if_missing is None else bool(create_if_missing),
|
|
601
601
|
publish=publish,
|
|
602
602
|
apps=apps,
|
|
603
603
|
add_fields=[],
|
|
@@ -608,14 +608,15 @@ class AiBuilderTools(ToolBase):
|
|
|
608
608
|
has_app_name = bool((app_name or "").strip())
|
|
609
609
|
has_app_title = bool((app_title or "").strip())
|
|
610
610
|
has_package_id = package_id is not None
|
|
611
|
+
effective_create_if_missing = bool(create_if_missing)
|
|
611
612
|
if has_app_key:
|
|
612
|
-
if
|
|
613
|
+
if effective_create_if_missing or has_package_id:
|
|
613
614
|
return _config_failure(
|
|
614
615
|
tool_name="app_schema_apply",
|
|
615
616
|
message="app_schema_apply edit mode accepts app_key and optional app_name rename only.",
|
|
616
617
|
fix_hint="For existing apps, use `app_key` and optionally `app_name`. For create mode, use `package_id + app_name + create_if_missing=true`.",
|
|
617
618
|
)
|
|
618
|
-
elif not (
|
|
619
|
+
elif not (effective_create_if_missing and has_package_id and (has_app_name or has_app_title)):
|
|
619
620
|
return _config_failure(
|
|
620
621
|
tool_name="app_schema_apply",
|
|
621
622
|
message="app_schema_apply create mode requires package_id, app_name, and create_if_missing=true.",
|
|
@@ -633,7 +634,7 @@ class AiBuilderTools(ToolBase):
|
|
|
633
634
|
icon_color=icon_color,
|
|
634
635
|
icon_config=icon_config,
|
|
635
636
|
visibility=visibility,
|
|
636
|
-
create_if_missing=
|
|
637
|
+
create_if_missing=effective_create_if_missing,
|
|
637
638
|
publish=publish,
|
|
638
639
|
add_fields=add_fields or [],
|
|
639
640
|
update_fields=update_fields or [],
|
|
@@ -979,7 +980,7 @@ class AiBuilderTools(ToolBase):
|
|
|
979
980
|
profile: str,
|
|
980
981
|
package_id: int | None = None,
|
|
981
982
|
package_name: str | None = None,
|
|
982
|
-
create_if_missing: bool =
|
|
983
|
+
create_if_missing: bool | None = None,
|
|
983
984
|
icon: str | JSONObject | None = None,
|
|
984
985
|
color: str | None = None,
|
|
985
986
|
icon_name: str | None = None,
|
|
@@ -1849,7 +1850,7 @@ class AiBuilderTools(ToolBase):
|
|
|
1849
1850
|
icon: str = "",
|
|
1850
1851
|
color: str = "",
|
|
1851
1852
|
visibility: JSONObject | None = None,
|
|
1852
|
-
create_if_missing: bool =
|
|
1853
|
+
create_if_missing: bool | None = None,
|
|
1853
1854
|
add_fields: list[JSONObject],
|
|
1854
1855
|
update_fields: list[JSONObject],
|
|
1855
1856
|
remove_fields: list[JSONObject],
|
|
@@ -2077,7 +2078,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2077
2078
|
icon_color: str | None = None,
|
|
2078
2079
|
icon_config: JSONObject | None = None,
|
|
2079
2080
|
visibility: JSONObject | None = None,
|
|
2080
|
-
create_if_missing: bool =
|
|
2081
|
+
create_if_missing: bool | None = None,
|
|
2081
2082
|
publish: bool = True,
|
|
2082
2083
|
add_fields: list[JSONObject],
|
|
2083
2084
|
update_fields: list[JSONObject],
|
|
@@ -2108,7 +2109,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2108
2109
|
profile=profile,
|
|
2109
2110
|
package_id=package_id,
|
|
2110
2111
|
visibility=visibility,
|
|
2111
|
-
create_if_missing=create_if_missing,
|
|
2112
|
+
create_if_missing=True if create_if_missing is None else bool(create_if_missing),
|
|
2112
2113
|
publish=publish,
|
|
2113
2114
|
apps=apps,
|
|
2114
2115
|
)
|
|
@@ -2126,7 +2127,7 @@ class AiBuilderTools(ToolBase):
|
|
|
2126
2127
|
icon=icon,
|
|
2127
2128
|
color=color,
|
|
2128
2129
|
visibility=visibility,
|
|
2129
|
-
create_if_missing=create_if_missing,
|
|
2130
|
+
create_if_missing=bool(create_if_missing),
|
|
2130
2131
|
publish=publish,
|
|
2131
2132
|
add_fields=add_fields,
|
|
2132
2133
|
update_fields=update_fields,
|
|
@@ -3745,8 +3746,8 @@ def _multi_app_static_validation_failure(
|
|
|
3745
3746
|
"row_number": index + 1,
|
|
3746
3747
|
"path": f"apps[{index}]",
|
|
3747
3748
|
"error_code": "CREATE_IF_MISSING_REQUIRED",
|
|
3748
|
-
"message": "
|
|
3749
|
-
"fix_hint": "
|
|
3749
|
+
"message": "apps[] item with app_name but no app_key cannot run when create_if_missing=false",
|
|
3750
|
+
"fix_hint": "Omit create_if_missing in multi-app mode, set it to true, or pass app_key for every existing app item.",
|
|
3750
3751
|
}
|
|
3751
3752
|
)
|
|
3752
3753
|
|
|
@@ -6092,9 +6093,9 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6092
6093
|
"edit mode: app_key, optional app_name to rename the existing app",
|
|
6093
6094
|
"create mode: package_id + app_name + create_if_missing=true",
|
|
6094
6095
|
"create mode follows backend CreateAppBean: package add_app permission is checked on the target package; package edit_app is not required for the create precheck",
|
|
6095
|
-
"multi-app mode: pass package_id +
|
|
6096
|
+
"multi-app mode: pass package_id + apps[]; create_if_missing defaults to true for app_name items and may be set false only when every item uses app_key",
|
|
6096
6097
|
"CLI --apps-file primary shape is {package_id, apps:[...]}; raw app arrays and singleton wrapper arrays are compatibility paths, not recommended examples",
|
|
6097
|
-
"multi-app mode preflights static errors before writing: duplicate client_key/app_name, missing data title on new apps, create_if_missing
|
|
6098
|
+
"multi-app mode preflights static errors before writing: duplicate client_key/app_name, missing data title on new apps, explicit create_if_missing=false with app_name items, and unresolved target_app_ref/target_app",
|
|
6098
6099
|
"multi-app relation fields may use target_app_ref to point at another apps[].client_key; the tool creates/resolves app shells first and compiles it to target_app_key",
|
|
6099
6100
|
"multi-app relation fields may also use target_app with another apps[].app_name; prefer target_app_ref/client_key when names may collide",
|
|
6100
6101
|
"multi-app mode is not transactional; read created_app_keys and apps[].status before retrying, and retry only failed app items",
|
|
@@ -6147,7 +6148,6 @@ _BUILDER_TOOL_CONTRACTS: dict[str, JSONObject] = {
|
|
|
6147
6148
|
"multi_app_example": {
|
|
6148
6149
|
"profile": "default",
|
|
6149
6150
|
"package_id": 1001,
|
|
6150
|
-
"create_if_missing": True,
|
|
6151
6151
|
"publish": True,
|
|
6152
6152
|
"apps": [
|
|
6153
6153
|
{
|