@josephyan/qingflow-cli 0.2.0-beta.77 → 0.2.0-beta.79
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/__init__.py +1 -1
- package/src/qingflow_mcp/builder_facade/models.py +110 -1
- package/src/qingflow_mcp/builder_facade/service.py +800 -33
- package/src/qingflow_mcp/cli/commands/builder.py +33 -0
- package/src/qingflow_mcp/cli/main.py +29 -0
- package/src/qingflow_mcp/public_surface.py +63 -52
- package/src/qingflow_mcp/server_app_builder.py +28 -1
- package/src/qingflow_mcp/tools/ai_builder_tools.py +280 -19
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.79
|
|
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.79 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.79",
|
|
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
|
@@ -40,6 +40,18 @@ class PublicDepartmentScopeMode(str, Enum):
|
|
|
40
40
|
custom = "custom"
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
class PublicVisibilityMode(str, Enum):
|
|
44
|
+
workspace = "workspace"
|
|
45
|
+
everyone = "everyone"
|
|
46
|
+
specific = "specific"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class PublicExternalVisibilityMode(str, Enum):
|
|
50
|
+
not_ = "not"
|
|
51
|
+
workspace = "workspace"
|
|
52
|
+
specific = "specific"
|
|
53
|
+
|
|
54
|
+
|
|
43
55
|
FIELD_TYPE_ALIASES: dict[str, PublicFieldType] = {
|
|
44
56
|
"textarea": PublicFieldType.long_text,
|
|
45
57
|
"amount": PublicFieldType.amount,
|
|
@@ -291,7 +303,7 @@ class FieldSelector(StrictModel):
|
|
|
291
303
|
|
|
292
304
|
@model_validator(mode="after")
|
|
293
305
|
def validate_selector(self) -> "FieldSelector":
|
|
294
|
-
if
|
|
306
|
+
if self.field_id is None and self.que_id is None and self.name is None:
|
|
295
307
|
raise ValueError("selector must include field_id, que_id, or name")
|
|
296
308
|
return self
|
|
297
309
|
|
|
@@ -346,6 +358,93 @@ class DepartmentScopePatch(StrictModel):
|
|
|
346
358
|
return self
|
|
347
359
|
|
|
348
360
|
|
|
361
|
+
class VisibilitySelectorsPatch(StrictModel):
|
|
362
|
+
member_uids: list[int] = Field(default_factory=list, validation_alias=AliasChoices("member_uids", "memberUids"))
|
|
363
|
+
member_emails: list[str] = Field(default_factory=list, validation_alias=AliasChoices("member_emails", "memberEmails"))
|
|
364
|
+
member_names: list[str] = Field(default_factory=list, validation_alias=AliasChoices("member_names", "memberNames"))
|
|
365
|
+
dept_ids: list[int] = Field(default_factory=list, validation_alias=AliasChoices("dept_ids", "deptIds"))
|
|
366
|
+
dept_names: list[str] = Field(default_factory=list, validation_alias=AliasChoices("dept_names", "deptNames"))
|
|
367
|
+
role_ids: list[int] = Field(default_factory=list, validation_alias=AliasChoices("role_ids", "roleIds"))
|
|
368
|
+
role_names: list[str] = Field(default_factory=list, validation_alias=AliasChoices("role_names", "roleNames"))
|
|
369
|
+
include_sub_departs: bool | None = Field(
|
|
370
|
+
default=None,
|
|
371
|
+
validation_alias=AliasChoices("include_sub_departs", "includeSubDeparts"),
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
def has_any_selector(self) -> bool:
|
|
375
|
+
return any(
|
|
376
|
+
(
|
|
377
|
+
self.member_uids,
|
|
378
|
+
self.member_emails,
|
|
379
|
+
self.member_names,
|
|
380
|
+
self.dept_ids,
|
|
381
|
+
self.dept_names,
|
|
382
|
+
self.role_ids,
|
|
383
|
+
self.role_names,
|
|
384
|
+
)
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class ExternalVisibilitySelectorsPatch(StrictModel):
|
|
389
|
+
member_ids: list[int] = Field(default_factory=list, validation_alias=AliasChoices("member_ids", "memberIds"))
|
|
390
|
+
member_emails: list[str] = Field(default_factory=list, validation_alias=AliasChoices("member_emails", "memberEmails"))
|
|
391
|
+
dept_ids: list[int] = Field(default_factory=list, validation_alias=AliasChoices("dept_ids", "deptIds"))
|
|
392
|
+
|
|
393
|
+
def has_any_selector(self) -> bool:
|
|
394
|
+
return any((self.member_ids, self.member_emails, self.dept_ids))
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
class VisibilityPatch(StrictModel):
|
|
398
|
+
mode: PublicVisibilityMode | None = None
|
|
399
|
+
selectors: VisibilitySelectorsPatch = Field(default_factory=VisibilitySelectorsPatch)
|
|
400
|
+
external_mode: PublicExternalVisibilityMode | None = Field(
|
|
401
|
+
default=None,
|
|
402
|
+
validation_alias=AliasChoices("external_mode", "externalMode"),
|
|
403
|
+
)
|
|
404
|
+
external_selectors: ExternalVisibilitySelectorsPatch = Field(
|
|
405
|
+
default_factory=ExternalVisibilitySelectorsPatch,
|
|
406
|
+
validation_alias=AliasChoices("external_selectors", "externalSelectors"),
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
@model_validator(mode="before")
|
|
410
|
+
@classmethod
|
|
411
|
+
def normalize_aliases(cls, value: Any) -> Any:
|
|
412
|
+
if not isinstance(value, dict):
|
|
413
|
+
return value
|
|
414
|
+
payload = dict(value)
|
|
415
|
+
selectors = payload.get("selectors")
|
|
416
|
+
external_selectors = payload.get("external_selectors", payload.get("externalSelectors"))
|
|
417
|
+
if payload.get("mode") is None:
|
|
418
|
+
if isinstance(selectors, dict) and selectors:
|
|
419
|
+
payload["mode"] = PublicVisibilityMode.specific.value
|
|
420
|
+
else:
|
|
421
|
+
payload["mode"] = PublicVisibilityMode.workspace.value
|
|
422
|
+
if payload.get("mode") == PublicVisibilityMode.everyone.value and payload.get("external_mode", payload.get("externalMode")) is None:
|
|
423
|
+
payload["external_mode"] = PublicExternalVisibilityMode.workspace.value
|
|
424
|
+
if payload.get("external_mode", payload.get("externalMode")) is None:
|
|
425
|
+
if isinstance(external_selectors, dict) and external_selectors:
|
|
426
|
+
payload["external_mode"] = PublicExternalVisibilityMode.specific.value
|
|
427
|
+
else:
|
|
428
|
+
payload["external_mode"] = PublicExternalVisibilityMode.not_.value
|
|
429
|
+
return payload
|
|
430
|
+
|
|
431
|
+
@model_validator(mode="after")
|
|
432
|
+
def validate_shape(self) -> "VisibilityPatch":
|
|
433
|
+
if self.mode == PublicVisibilityMode.specific and not self.selectors.has_any_selector():
|
|
434
|
+
raise ValueError("specific visibility requires selectors")
|
|
435
|
+
if self.mode != PublicVisibilityMode.specific and self.selectors.has_any_selector():
|
|
436
|
+
raise ValueError("selectors are only allowed when mode=specific")
|
|
437
|
+
if self.mode == PublicVisibilityMode.everyone and self.external_mode != PublicExternalVisibilityMode.workspace:
|
|
438
|
+
raise ValueError("mode=everyone requires external_mode=workspace")
|
|
439
|
+
if self.mode == PublicVisibilityMode.everyone and self.external_selectors.has_any_selector():
|
|
440
|
+
raise ValueError("external_selectors are not allowed when mode=everyone")
|
|
441
|
+
if self.external_mode == PublicExternalVisibilityMode.specific and not self.external_selectors.has_any_selector():
|
|
442
|
+
raise ValueError("external_mode=specific requires external_selectors")
|
|
443
|
+
if self.external_mode != PublicExternalVisibilityMode.specific and self.external_selectors.has_any_selector():
|
|
444
|
+
raise ValueError("external_selectors are only allowed when external_mode=specific")
|
|
445
|
+
return self
|
|
446
|
+
|
|
447
|
+
|
|
349
448
|
class CodeBlockAliasPathPatch(StrictModel):
|
|
350
449
|
alias_name: str = Field(validation_alias=AliasChoices("alias_name", "aliasName"))
|
|
351
450
|
alias_path: str = Field(validation_alias=AliasChoices("alias_path", "aliasPath"))
|
|
@@ -916,6 +1015,7 @@ class ViewUpsertPatch(StrictModel):
|
|
|
916
1015
|
end_field: str | None = Field(default=None, validation_alias=AliasChoices("end_field", "endField"))
|
|
917
1016
|
title_field: str | None = Field(default=None, validation_alias=AliasChoices("title_field", "titleField"))
|
|
918
1017
|
buttons: list["ViewButtonBindingPatch"] | None = None
|
|
1018
|
+
visibility: VisibilityPatch | None = None
|
|
919
1019
|
|
|
920
1020
|
@model_validator(mode="before")
|
|
921
1021
|
@classmethod
|
|
@@ -1237,6 +1337,7 @@ class ChartUpsertPatch(StrictModel):
|
|
|
1237
1337
|
question_config: list[dict[str, Any]] = Field(default_factory=list)
|
|
1238
1338
|
user_config: list[dict[str, Any]] = Field(default_factory=list)
|
|
1239
1339
|
config: dict[str, Any] = Field(default_factory=dict)
|
|
1340
|
+
visibility: VisibilityPatch | None = None
|
|
1240
1341
|
|
|
1241
1342
|
@model_validator(mode="before")
|
|
1242
1343
|
@classmethod
|
|
@@ -1413,6 +1514,7 @@ class PortalApplyRequest(StrictModel):
|
|
|
1413
1514
|
package_tag_id: int | None = None
|
|
1414
1515
|
publish: bool = True
|
|
1415
1516
|
sections: list[PortalSectionPatch] = Field(default_factory=list)
|
|
1517
|
+
visibility: VisibilityPatch | None = None
|
|
1416
1518
|
auth: dict[str, Any] | None = None
|
|
1417
1519
|
icon: str | None = None
|
|
1418
1520
|
color: str | None = None
|
|
@@ -1428,6 +1530,8 @@ class PortalApplyRequest(StrictModel):
|
|
|
1428
1530
|
raise ValueError("dash_name is required when creating a portal")
|
|
1429
1531
|
if not self.sections:
|
|
1430
1532
|
raise ValueError("portal apply requires a non-empty sections list")
|
|
1533
|
+
if self.visibility is not None and self.auth is not None:
|
|
1534
|
+
raise ValueError("visibility and auth cannot be provided together")
|
|
1431
1535
|
return self
|
|
1432
1536
|
|
|
1433
1537
|
|
|
@@ -1438,6 +1542,7 @@ class AppGetResponse(StrictModel):
|
|
|
1438
1542
|
app_key: str
|
|
1439
1543
|
title: str | None = None
|
|
1440
1544
|
app_icon: str | None = None
|
|
1545
|
+
visibility: dict[str, Any] = Field(default_factory=dict)
|
|
1441
1546
|
tag_ids: list[int] = Field(default_factory=list)
|
|
1442
1547
|
publish_status: int | None = None
|
|
1443
1548
|
field_count: int = 0
|
|
@@ -1512,6 +1617,7 @@ class PortalGetResponse(StrictModel):
|
|
|
1512
1617
|
package_tag_ids: list[int] = Field(default_factory=list)
|
|
1513
1618
|
dash_icon: str | None = None
|
|
1514
1619
|
hide_copyright: bool | None = None
|
|
1620
|
+
visibility: dict[str, Any] = Field(default_factory=dict)
|
|
1515
1621
|
auth: dict[str, Any] = Field(default_factory=dict)
|
|
1516
1622
|
config: dict[str, Any] = Field(default_factory=dict)
|
|
1517
1623
|
dash_global_config: dict[str, Any] = Field(default_factory=dict)
|
|
@@ -1522,6 +1628,7 @@ class PortalGetResponse(StrictModel):
|
|
|
1522
1628
|
class ViewGetResponse(StrictModel):
|
|
1523
1629
|
view_key: str
|
|
1524
1630
|
base_info: dict[str, Any] = Field(default_factory=dict)
|
|
1631
|
+
visibility: dict[str, Any] = Field(default_factory=dict)
|
|
1525
1632
|
config: dict[str, Any] = Field(default_factory=dict)
|
|
1526
1633
|
questions: list[dict[str, Any]] = Field(default_factory=list)
|
|
1527
1634
|
associations: list[dict[str, Any]] = Field(default_factory=list)
|
|
@@ -1530,6 +1637,7 @@ class ViewGetResponse(StrictModel):
|
|
|
1530
1637
|
class ChartGetResponse(StrictModel):
|
|
1531
1638
|
chart_id: str
|
|
1532
1639
|
base: dict[str, Any] = Field(default_factory=dict)
|
|
1640
|
+
visibility: dict[str, Any] = Field(default_factory=dict)
|
|
1533
1641
|
config: dict[str, Any] = Field(default_factory=dict)
|
|
1534
1642
|
|
|
1535
1643
|
|
|
@@ -1539,6 +1647,7 @@ class SchemaPlanRequest(StrictModel):
|
|
|
1539
1647
|
app_name: str = Field(default="", validation_alias=AliasChoices("app_name", "app_title", "title"))
|
|
1540
1648
|
icon: str | None = None
|
|
1541
1649
|
color: str | None = None
|
|
1650
|
+
visibility: VisibilityPatch | None = None
|
|
1542
1651
|
create_if_missing: bool = False
|
|
1543
1652
|
add_fields: list[FieldPatch] = Field(default_factory=list)
|
|
1544
1653
|
update_fields: list[FieldUpdatePatch] = Field(default_factory=list)
|