@josephyan/qingflow-cli 1.1.14 → 1.1.15

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 CHANGED
@@ -3,13 +3,13 @@
3
3
  Install:
4
4
 
5
5
  ```bash
6
- npm install @josephyan/qingflow-cli@1.1.14
6
+ npm install @josephyan/qingflow-cli@1.1.15
7
7
  ```
8
8
 
9
9
  Run:
10
10
 
11
11
  ```bash
12
- npx -y -p @josephyan/qingflow-cli@1.1.14 qingflow
12
+ npx -y -p @josephyan/qingflow-cli@1.1.15 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": "1.1.14",
3
+ "version": "1.1.15",
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qingflow-mcp"
7
- version = "1.1.14"
7
+ version = "1.1.15"
8
8
  description = "User-authenticated MCP server for Qingflow"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -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
- | 多应用一次性新建 | `--package-id`、**`--create-if-missing`**、`--apps-file` | 应用包/系统里有 2 个以上应用,或同批应用之间有 `relation` 时使用;`--apps-file` 主写法为 `{package_id, apps}` 对象,raw apps array / singleton wrapper array 仅兼容;`apps[].client_key` 可被 `target_app_ref` 引用,`apps[].app_name` 可被 `target_app` 引用 |
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,7 +136,7 @@ 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 --package-id <TAG_ID> --create-if-missing --apps-file tmp/apps.json`,其中 `tmp/apps.json` 主写法为 `{ "package_id": 123, "apps": [...] }`,每个 `apps[]` 写顶层 `icon + color`;`apps[].client_key` 可被同批 relation 字段的 `target_app_ref` 引用,`apps[].app_name` 可被 `target_app` 引用,工具会编译成真实 `target_app_key`。这是应用包/系统搭建的默认路径,尤其适合“商机 + 订单 + 回款”“花名册 + 工时”等互相关联场景;不要为了拿 `app_key` 先逐个创建再二次补关联字段。
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
  **限制(平台硬性)**:每应用 **至多一个** `relation`;`--app-key` 向已有应用追加时须 **字段名不重复**、且 **不能**在已有 relation 上再增第二个。**`example.com`** 作 `q_linker` URL 易触发 **`46031`**,本清单改用 httpbin。**读回缺 `outputs[].target_field` 的 `q_linker`** 会拖死后续 `schema apply`,须修复或删除该题。
142
142
 
@@ -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
- - **创建模式要件**(与契约一致):**`package_id` + `app_name`(或 CLI 的 app-title 映射到 app_name)+ `create_if_missing`**。
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`、未开 `create_if_missing`、`target_app_ref/target_app` 无法解析都会以 `MULTI_APP_STATIC_VALIDATION_FAILED` 返回,不会先创建半成品应用:
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=False,
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/--create-if-missing plus --apps-file only.",
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 = False,
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 = False,
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/create_if_missing plus apps only.",
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 create_if_missing or has_package_id:
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 (create_if_missing and has_package_id and (has_app_name or has_app_title)):
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=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 = False,
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 = False,
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/create_if_missing plus apps only.",
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 create_if_missing or has_package_id:
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 (create_if_missing and has_package_id and (has_app_name or has_app_title)):
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=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 = False,
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 = False,
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 = False,
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": "new multi-app items require create_if_missing=true",
3749
- "fix_hint": "Set create_if_missing=true, or pass app_key for an existing app.",
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 + create_if_missing + apps[]; do not mix apps with top-level app_key/app_name/add_fields/update_fields/remove_fields",
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 omissions, and unresolved target_app_ref/target_app",
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
  {