@josephyan/qingflow-cli 0.2.0-beta.74 → 0.2.0-beta.76

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.
@@ -0,0 +1,230 @@
1
+ from __future__ import annotations
2
+
3
+ from argparse import Namespace
4
+ from dataclasses import dataclass
5
+
6
+
7
+ USER_DOMAIN = "user"
8
+ BUILDER_DOMAIN = "builder"
9
+
10
+
11
+ @dataclass(frozen=True, slots=True)
12
+ class PublicToolSpec:
13
+ domain: str
14
+ tool_name: str
15
+ method_names: tuple[str, ...] = ()
16
+ cli_route: tuple[str, ...] | None = None
17
+ mcp_public: bool = True
18
+ cli_public: bool = True
19
+ has_contract: bool = False
20
+
21
+ @property
22
+ def trim_key(self) -> str:
23
+ return tool_key(self.domain, self.tool_name)
24
+
25
+
26
+ def tool_key(domain: str, tool_name: str) -> str:
27
+ return f"{domain}:{tool_name}"
28
+
29
+
30
+ USER_PUBLIC_TOOL_SPECS: tuple[PublicToolSpec, ...] = (
31
+ PublicToolSpec(USER_DOMAIN, "auth_login", ("auth_login",), ("auth", "login")),
32
+ PublicToolSpec(USER_DOMAIN, "auth_use_token", ("auth_use_token",), ("auth", "use-token")),
33
+ PublicToolSpec(USER_DOMAIN, "auth_whoami", ("auth_whoami",), ("auth", "whoami")),
34
+ PublicToolSpec(USER_DOMAIN, "auth_logout", ("auth_logout",), ("auth", "logout")),
35
+ PublicToolSpec(USER_DOMAIN, "workspace_list", ("workspace_list",), ("workspace", "list")),
36
+ PublicToolSpec(USER_DOMAIN, "workspace_select", ("workspace_select",), ("workspace", "select")),
37
+ PublicToolSpec(USER_DOMAIN, "app_list", ("app_list",), ("app", "list")),
38
+ PublicToolSpec(USER_DOMAIN, "app_search", ("app_search",), ("app", "search")),
39
+ PublicToolSpec(USER_DOMAIN, "app_get", ("app_get",), ("app", "get")),
40
+ PublicToolSpec(USER_DOMAIN, "portal_list", ("portal_list",), ("portal", "list")),
41
+ PublicToolSpec(USER_DOMAIN, "portal_get", ("portal_get",), ("portal", "get")),
42
+ PublicToolSpec(USER_DOMAIN, "view_get", ("view_get",), ("view", "get")),
43
+ PublicToolSpec(USER_DOMAIN, "chart_get", ("chart_get",), ("chart", "get")),
44
+ PublicToolSpec(USER_DOMAIN, "file_get_upload_info", ("file_get_upload_info",), cli_public=False),
45
+ PublicToolSpec(USER_DOMAIN, "file_upload_local", ("file_upload_local",), cli_public=False),
46
+ PublicToolSpec(USER_DOMAIN, "feedback_submit", ("feedback_submit",), cli_public=False),
47
+ PublicToolSpec(
48
+ USER_DOMAIN,
49
+ "record_schema_get",
50
+ cli_route=("record", "schema", "applicant"),
51
+ mcp_public=False,
52
+ ),
53
+ PublicToolSpec(
54
+ USER_DOMAIN,
55
+ "record_browse_schema_get",
56
+ ("record_browse_schema_get_public",),
57
+ ("record", "schema", "browse"),
58
+ ),
59
+ PublicToolSpec(
60
+ USER_DOMAIN,
61
+ "record_insert_schema_get",
62
+ ("record_insert_schema_get_public",),
63
+ ("record", "schema", "insert"),
64
+ ),
65
+ PublicToolSpec(
66
+ USER_DOMAIN,
67
+ "record_update_schema_get",
68
+ ("record_update_schema_get_public",),
69
+ ("record", "schema", "update"),
70
+ ),
71
+ PublicToolSpec(USER_DOMAIN, "record_import_schema_get", ("record_import_schema_get",), ("record", "schema", "import")),
72
+ PublicToolSpec(
73
+ USER_DOMAIN,
74
+ "record_code_block_schema_get",
75
+ ("record_code_block_schema_get_public",),
76
+ ("record", "schema", "code-block"),
77
+ ),
78
+ PublicToolSpec(USER_DOMAIN, "record_member_candidates", ("record_member_candidates",), cli_public=False),
79
+ PublicToolSpec(USER_DOMAIN, "record_department_candidates", ("record_department_candidates",), cli_public=False),
80
+ PublicToolSpec(USER_DOMAIN, "record_analyze", ("record_analyze",), ("record", "analyze")),
81
+ PublicToolSpec(USER_DOMAIN, "record_list", ("record_list",), ("record", "list")),
82
+ PublicToolSpec(USER_DOMAIN, "record_get", ("record_get_public",), ("record", "get")),
83
+ PublicToolSpec(USER_DOMAIN, "record_insert", ("record_insert_public",), ("record", "insert")),
84
+ PublicToolSpec(USER_DOMAIN, "record_update", ("record_update_public",), ("record", "update")),
85
+ PublicToolSpec(USER_DOMAIN, "record_delete", ("record_delete_public",), ("record", "delete")),
86
+ PublicToolSpec(USER_DOMAIN, "record_import_template_get", ("record_import_template_get",), ("import", "template")),
87
+ PublicToolSpec(USER_DOMAIN, "record_import_verify", ("record_import_verify",), ("import", "verify")),
88
+ PublicToolSpec(USER_DOMAIN, "record_import_repair_local", ("record_import_repair_local",), ("import", "repair")),
89
+ PublicToolSpec(USER_DOMAIN, "record_import_start", ("record_import_start",), ("import", "start")),
90
+ PublicToolSpec(USER_DOMAIN, "record_import_status_get", ("record_import_status_get",), ("import", "status")),
91
+ PublicToolSpec(USER_DOMAIN, "record_code_block_run", ("record_code_block_run",), ("record", "code-block-run")),
92
+ PublicToolSpec(USER_DOMAIN, "task_list", ("task_list",), ("task", "list")),
93
+ PublicToolSpec(USER_DOMAIN, "task_get", ("task_get",), ("task", "get")),
94
+ PublicToolSpec(USER_DOMAIN, "task_action_execute", ("task_action_execute",), ("task", "action")),
95
+ PublicToolSpec(USER_DOMAIN, "task_associated_report_detail_get", ("task_associated_report_detail_get",), cli_public=False),
96
+ PublicToolSpec(USER_DOMAIN, "task_workflow_log_get", ("task_workflow_log_get",), ("task", "log")),
97
+ PublicToolSpec(USER_DOMAIN, "directory_search", ("directory_search",), cli_public=False),
98
+ PublicToolSpec(USER_DOMAIN, "directory_list_internal_users", ("directory_list_internal_users",), cli_public=False),
99
+ PublicToolSpec(USER_DOMAIN, "directory_list_all_internal_users", ("directory_list_all_internal_users",), cli_public=False),
100
+ PublicToolSpec(USER_DOMAIN, "directory_list_internal_departments", ("directory_list_internal_departments",), cli_public=False),
101
+ PublicToolSpec(USER_DOMAIN, "directory_list_all_departments", ("directory_list_all_departments",), cli_public=False),
102
+ PublicToolSpec(USER_DOMAIN, "directory_list_sub_departments", ("directory_list_sub_departments",), cli_public=False),
103
+ PublicToolSpec(USER_DOMAIN, "directory_list_external_members", ("directory_list_external_members",), cli_public=False),
104
+ )
105
+
106
+
107
+ BUILDER_PUBLIC_TOOL_SPECS: tuple[PublicToolSpec, ...] = (
108
+ PublicToolSpec(BUILDER_DOMAIN, "auth_login", ("auth_login",), ("builder", "auth", "login"), cli_public=False),
109
+ PublicToolSpec(BUILDER_DOMAIN, "auth_use_token", ("auth_use_token",), ("builder", "auth", "use-token"), cli_public=False),
110
+ PublicToolSpec(BUILDER_DOMAIN, "auth_whoami", ("auth_whoami",), ("builder", "auth", "whoami"), cli_public=False),
111
+ PublicToolSpec(BUILDER_DOMAIN, "auth_logout", ("auth_logout",), ("builder", "auth", "logout"), cli_public=False),
112
+ PublicToolSpec(BUILDER_DOMAIN, "workspace_list", ("workspace_list",), ("builder", "workspace", "list"), cli_public=False),
113
+ PublicToolSpec(BUILDER_DOMAIN, "workspace_select", ("workspace_select",), ("builder", "workspace", "select"), cli_public=False),
114
+ PublicToolSpec(BUILDER_DOMAIN, "file_upload_local", ("file_upload_local",), ("builder", "file", "upload-local"), has_contract=True),
115
+ PublicToolSpec(BUILDER_DOMAIN, "feedback_submit", ("feedback_submit",), ("builder", "feedback", "submit"), has_contract=True),
116
+ PublicToolSpec(BUILDER_DOMAIN, "package_list", ("package_list",), ("builder", "package", "list"), has_contract=True),
117
+ PublicToolSpec(BUILDER_DOMAIN, "package_resolve", ("package_resolve",), ("builder", "package", "resolve"), has_contract=True),
118
+ PublicToolSpec(BUILDER_DOMAIN, "builder_tool_contract", ("builder_tool_contract",), ("builder", "contract"), has_contract=False),
119
+ PublicToolSpec(BUILDER_DOMAIN, "package_create", ("package_create",), ("builder", "package", "create"), has_contract=True),
120
+ PublicToolSpec(BUILDER_DOMAIN, "solution_install", ("solution_install",), ("builder", "solution", "install"), has_contract=True),
121
+ PublicToolSpec(BUILDER_DOMAIN, "member_search", ("member_search",), ("builder", "member", "search"), has_contract=True),
122
+ PublicToolSpec(BUILDER_DOMAIN, "role_search", ("role_search",), ("builder", "role", "search"), has_contract=True),
123
+ PublicToolSpec(BUILDER_DOMAIN, "role_create", ("role_create",), ("builder", "role", "create"), has_contract=True),
124
+ PublicToolSpec(BUILDER_DOMAIN, "package_attach_app", ("package_attach_app",), ("builder", "package", "attach-app"), has_contract=True),
125
+ PublicToolSpec(BUILDER_DOMAIN, "app_release_edit_lock_if_mine", ("app_release_edit_lock_if_mine",), ("builder", "app", "release-edit-lock-if-mine"), has_contract=True),
126
+ PublicToolSpec(BUILDER_DOMAIN, "app_resolve", ("app_resolve",), ("builder", "app", "resolve"), has_contract=True),
127
+ PublicToolSpec(BUILDER_DOMAIN, "app_custom_button_list", ("app_custom_button_list",), ("builder", "button", "list"), has_contract=True),
128
+ PublicToolSpec(BUILDER_DOMAIN, "app_custom_button_get", ("app_custom_button_get",), ("builder", "button", "get"), has_contract=True),
129
+ PublicToolSpec(BUILDER_DOMAIN, "app_custom_button_create", ("app_custom_button_create",), ("builder", "button", "create"), has_contract=True),
130
+ PublicToolSpec(BUILDER_DOMAIN, "app_custom_button_update", ("app_custom_button_update",), ("builder", "button", "update"), has_contract=True),
131
+ PublicToolSpec(BUILDER_DOMAIN, "app_custom_button_delete", ("app_custom_button_delete",), ("builder", "button", "delete"), has_contract=True),
132
+ PublicToolSpec(BUILDER_DOMAIN, "app_get", ("app_get",), ("builder", "app", "get", "summary"), has_contract=True),
133
+ PublicToolSpec(BUILDER_DOMAIN, "app_get_fields", ("app_get_fields",), ("builder", "app", "get", "fields"), has_contract=True),
134
+ PublicToolSpec(BUILDER_DOMAIN, "app_repair_code_blocks", ("app_repair_code_blocks",), ("builder", "app", "repair-code-blocks"), has_contract=True),
135
+ PublicToolSpec(BUILDER_DOMAIN, "app_get_layout", ("app_get_layout",), ("builder", "app", "get", "layout"), has_contract=True),
136
+ PublicToolSpec(BUILDER_DOMAIN, "app_get_views", ("app_get_views",), ("builder", "app", "get", "views"), has_contract=True),
137
+ PublicToolSpec(BUILDER_DOMAIN, "app_get_flow", ("app_get_flow",), ("builder", "app", "get", "flow"), has_contract=True),
138
+ PublicToolSpec(BUILDER_DOMAIN, "app_get_charts", ("app_get_charts",), ("builder", "app", "get", "charts"), has_contract=True),
139
+ PublicToolSpec(BUILDER_DOMAIN, "portal_list", ("portal_list",), ("builder", "portal", "list"), has_contract=True),
140
+ PublicToolSpec(BUILDER_DOMAIN, "portal_get", ("portal_get",), ("builder", "portal", "get"), has_contract=True),
141
+ PublicToolSpec(BUILDER_DOMAIN, "view_get", ("view_get",), ("builder", "view", "get"), has_contract=True),
142
+ PublicToolSpec(BUILDER_DOMAIN, "chart_get", ("chart_get",), ("builder", "chart", "get"), has_contract=True),
143
+ PublicToolSpec(BUILDER_DOMAIN, "app_schema_apply", ("app_schema_apply",), ("builder", "schema", "apply"), has_contract=True),
144
+ PublicToolSpec(BUILDER_DOMAIN, "app_layout_apply", ("app_layout_apply",), ("builder", "layout", "apply"), has_contract=True),
145
+ PublicToolSpec(BUILDER_DOMAIN, "app_flow_apply", ("app_flow_apply",), ("builder", "flow", "apply"), has_contract=True),
146
+ PublicToolSpec(BUILDER_DOMAIN, "app_views_apply", ("app_views_apply",), ("builder", "views", "apply"), has_contract=True),
147
+ PublicToolSpec(BUILDER_DOMAIN, "app_charts_apply", ("app_charts_apply",), ("builder", "charts", "apply"), has_contract=True),
148
+ PublicToolSpec(BUILDER_DOMAIN, "portal_apply", ("portal_apply",), ("builder", "portal", "apply"), has_contract=True),
149
+ PublicToolSpec(BUILDER_DOMAIN, "app_publish_verify", ("app_publish_verify",), ("builder", "publish", "verify"), has_contract=True),
150
+ )
151
+
152
+
153
+ ALL_PUBLIC_TOOL_SPECS: tuple[PublicToolSpec, ...] = USER_PUBLIC_TOOL_SPECS + BUILDER_PUBLIC_TOOL_SPECS
154
+ PUBLIC_TOOL_BY_KEY: dict[str, PublicToolSpec] = {spec.trim_key: spec for spec in ALL_PUBLIC_TOOL_SPECS}
155
+ PUBLIC_TOOL_BY_CLI_ROUTE: dict[tuple[str, ...], PublicToolSpec] = {
156
+ spec.cli_route: spec
157
+ for spec in ALL_PUBLIC_TOOL_SPECS
158
+ if spec.cli_public and spec.cli_route is not None
159
+ }
160
+
161
+
162
+ def public_tool_specs(domain: str | None = None) -> tuple[PublicToolSpec, ...]:
163
+ if domain is None:
164
+ return ALL_PUBLIC_TOOL_SPECS
165
+ return tuple(spec for spec in ALL_PUBLIC_TOOL_SPECS if spec.domain == domain)
166
+
167
+
168
+ def public_mcp_tool_names(domain: str) -> set[str]:
169
+ return {spec.tool_name for spec in public_tool_specs(domain) if spec.mcp_public}
170
+
171
+
172
+ def public_builder_contract_tool_names() -> list[str]:
173
+ return sorted(
174
+ spec.tool_name
175
+ for spec in BUILDER_PUBLIC_TOOL_SPECS
176
+ if spec.has_contract and (spec.mcp_public or spec.cli_public)
177
+ )
178
+
179
+
180
+ def server_method_map(domain: str) -> dict[str, str]:
181
+ mapping: dict[str, str] = {}
182
+ for spec in public_tool_specs(domain):
183
+ if not spec.mcp_public:
184
+ continue
185
+ for method_name in spec.method_names:
186
+ mapping[method_name] = spec.trim_key
187
+ return mapping
188
+
189
+
190
+ def cli_trim_key_from_namespace(args: Namespace) -> str | None:
191
+ route = cli_route_from_namespace(args)
192
+ if route is None:
193
+ return None
194
+ spec = PUBLIC_TOOL_BY_CLI_ROUTE.get(route)
195
+ return spec.trim_key if spec is not None else None
196
+
197
+
198
+ def cli_route_from_namespace(args: Namespace) -> tuple[str, ...] | None:
199
+ command = getattr(args, "command", None)
200
+ if not isinstance(command, str) or not command:
201
+ return None
202
+ command = "builder" if command == "build" else command
203
+ if command == "record":
204
+ record_command = getattr(args, "record_command", None)
205
+ if record_command == "schema":
206
+ schema_command = getattr(args, "record_schema_command", None)
207
+ return (command, "schema", schema_command) if isinstance(schema_command, str) and schema_command else None
208
+ return (command, record_command) if isinstance(record_command, str) and record_command else None
209
+ if command == "task":
210
+ task_command = getattr(args, "task_command", None)
211
+ return (command, task_command) if isinstance(task_command, str) and task_command else None
212
+ if command != "builder":
213
+ child_attr = f"{command}_command"
214
+ child = getattr(args, child_attr, None)
215
+ return (command, child) if isinstance(child, str) and child else None
216
+
217
+ builder_command = getattr(args, "builder_command", None)
218
+ if not isinstance(builder_command, str) or not builder_command:
219
+ return None
220
+ if builder_command == "contract":
221
+ return ("builder", "contract")
222
+ if builder_command == "app":
223
+ app_command = getattr(args, "builder_app_command", None)
224
+ if app_command == "get":
225
+ section = getattr(args, "builder_app_get_section", "summary") or "summary"
226
+ return ("builder", "app", "get", str(section))
227
+ return ("builder", "app", app_command) if isinstance(app_command, str) and app_command else None
228
+ child_attr = f"builder_{builder_command.replace('-', '_')}_command"
229
+ child = getattr(args, child_attr, None)
230
+ return ("builder", builder_command, child) if isinstance(child, str) and child else None
@@ -5,11 +5,17 @@ from copy import deepcopy
5
5
  from functools import wraps
6
6
  from typing import Any, Callable
7
7
 
8
+ from .public_surface import (
9
+ BUILDER_DOMAIN,
10
+ USER_DOMAIN,
11
+ cli_trim_key_from_namespace,
12
+ server_method_map,
13
+ tool_key,
14
+ )
15
+
8
16
 
9
17
  JSONObject = dict[str, Any]
10
18
  TransformFn = Callable[[JSONObject], None]
11
- USER_DOMAIN = "user"
12
- BUILDER_DOMAIN = "builder"
13
19
 
14
20
 
15
21
  COMMON_SUCCESS_DROP_TOP = {
@@ -47,10 +53,6 @@ COMMON_ERROR_DROP_TOP = {
47
53
  SUCCESS_POLICY_BY_TOOL: dict[str, TransformFn] = {}
48
54
 
49
55
 
50
- def _tool_key(domain: str, tool_name: str) -> str:
51
- return f"{domain}:{tool_name}"
52
-
53
-
54
56
  def trim_public_response(tool_name: str | None, payload: dict[str, Any]) -> dict[str, Any]:
55
57
  if not isinstance(payload, dict):
56
58
  return payload
@@ -100,248 +102,11 @@ def wrap_trimmed_methods(instance: object, method_map: dict[str, str]) -> object
100
102
 
101
103
 
102
104
  def resolve_cli_tool_name(args: Any) -> str | None:
103
- command = getattr(args, "command", None)
104
- if command == "auth":
105
- return {
106
- "login": _tool_key(USER_DOMAIN, "auth_login"),
107
- "use-token": _tool_key(USER_DOMAIN, "auth_use_token"),
108
- "whoami": _tool_key(USER_DOMAIN, "auth_whoami"),
109
- "logout": _tool_key(USER_DOMAIN, "auth_logout"),
110
- }.get(getattr(args, "auth_command", None))
111
- if command == "workspace":
112
- return {
113
- "list": _tool_key(USER_DOMAIN, "workspace_list"),
114
- "select": _tool_key(USER_DOMAIN, "workspace_select"),
115
- }.get(getattr(args, "workspace_command", None))
116
- if command == "app":
117
- return {
118
- "list": _tool_key(USER_DOMAIN, "app_list"),
119
- "search": _tool_key(USER_DOMAIN, "app_search"),
120
- "get": _tool_key(USER_DOMAIN, "app_get"),
121
- }.get(getattr(args, "app_command", None))
122
- if command == "portal":
123
- return {
124
- "list": _tool_key(USER_DOMAIN, "portal_list"),
125
- "get": _tool_key(USER_DOMAIN, "portal_get"),
126
- }.get(getattr(args, "portal_command", None))
127
- if command == "view":
128
- return {
129
- "get": _tool_key(USER_DOMAIN, "view_get"),
130
- }.get(getattr(args, "view_command", None))
131
- if command == "chart":
132
- return {
133
- "get": _tool_key(USER_DOMAIN, "chart_get"),
134
- }.get(getattr(args, "chart_command", None))
135
- if command == "record":
136
- record_command = getattr(args, "record_command", None)
137
- if record_command == "schema":
138
- return {
139
- "applicant": _tool_key(USER_DOMAIN, "record_schema_get"),
140
- "browse": _tool_key(USER_DOMAIN, "record_browse_schema_get"),
141
- "insert": _tool_key(USER_DOMAIN, "record_insert_schema_get"),
142
- "update": _tool_key(USER_DOMAIN, "record_update_schema_get"),
143
- "import": _tool_key(USER_DOMAIN, "record_import_schema_get"),
144
- "code-block": _tool_key(USER_DOMAIN, "record_code_block_schema_get"),
145
- }.get(getattr(args, "record_schema_command", None))
146
- return {
147
- "list": _tool_key(USER_DOMAIN, "record_list"),
148
- "get": _tool_key(USER_DOMAIN, "record_get"),
149
- "insert": _tool_key(USER_DOMAIN, "record_insert"),
150
- "update": _tool_key(USER_DOMAIN, "record_update"),
151
- "delete": _tool_key(USER_DOMAIN, "record_delete"),
152
- "analyze": _tool_key(USER_DOMAIN, "record_analyze"),
153
- "code-block-run": _tool_key(USER_DOMAIN, "record_code_block_run"),
154
- }.get(record_command)
155
- if command == "import":
156
- return {
157
- "template": _tool_key(USER_DOMAIN, "record_import_template_get"),
158
- "verify": _tool_key(USER_DOMAIN, "record_import_verify"),
159
- "repair": _tool_key(USER_DOMAIN, "record_import_repair_local"),
160
- "start": _tool_key(USER_DOMAIN, "record_import_start"),
161
- "status": _tool_key(USER_DOMAIN, "record_import_status_get"),
162
- }.get(getattr(args, "import_command", None))
163
- if command == "task":
164
- return {
165
- "list": _tool_key(USER_DOMAIN, "task_list"),
166
- "get": _tool_key(USER_DOMAIN, "task_get"),
167
- "action": _tool_key(USER_DOMAIN, "task_action_execute"),
168
- "log": _tool_key(USER_DOMAIN, "task_workflow_log_get"),
169
- }.get(getattr(args, "task_command", None))
170
- if command not in {"builder", "build"}:
171
- return None
172
- builder_command = getattr(args, "builder_command", None)
173
- if builder_command == "file":
174
- return {
175
- "upload-local": _tool_key(BUILDER_DOMAIN, "file_upload_local"),
176
- }.get(getattr(args, "builder_file_command", None))
177
- if builder_command == "feedback":
178
- return {
179
- "submit": _tool_key(BUILDER_DOMAIN, "feedback_submit"),
180
- }.get(getattr(args, "builder_feedback_command", None))
181
- if builder_command == "contract":
182
- return _tool_key(BUILDER_DOMAIN, "builder_tool_contract")
183
- if builder_command == "member":
184
- return {
185
- "search": _tool_key(BUILDER_DOMAIN, "member_search"),
186
- }.get(getattr(args, "builder_member_command", None))
187
- if builder_command == "role":
188
- return {
189
- "search": _tool_key(BUILDER_DOMAIN, "role_search"),
190
- "create": _tool_key(BUILDER_DOMAIN, "role_create"),
191
- }.get(getattr(args, "builder_role_command", None))
192
- if builder_command == "package":
193
- return {
194
- "list": _tool_key(BUILDER_DOMAIN, "package_list"),
195
- "resolve": _tool_key(BUILDER_DOMAIN, "package_resolve"),
196
- "create": _tool_key(BUILDER_DOMAIN, "package_create"),
197
- "attach-app": _tool_key(BUILDER_DOMAIN, "package_attach_app"),
198
- }.get(getattr(args, "builder_package_command", None))
199
- if builder_command == "app":
200
- app_command = getattr(args, "builder_app_command", None)
201
- if app_command == "get":
202
- return {
203
- "summary": _tool_key(BUILDER_DOMAIN, "app_get"),
204
- "fields": _tool_key(BUILDER_DOMAIN, "app_get_fields"),
205
- "layout": _tool_key(BUILDER_DOMAIN, "app_get_layout"),
206
- "views": _tool_key(BUILDER_DOMAIN, "app_get_views"),
207
- "flow": _tool_key(BUILDER_DOMAIN, "app_get_flow"),
208
- "charts": _tool_key(BUILDER_DOMAIN, "app_get_charts"),
209
- }.get(getattr(args, "builder_app_get_section", "summary"))
210
- return {
211
- "resolve": _tool_key(BUILDER_DOMAIN, "app_resolve"),
212
- "release-edit-lock-if-mine": _tool_key(BUILDER_DOMAIN, "app_release_edit_lock_if_mine"),
213
- "repair-code-blocks": _tool_key(BUILDER_DOMAIN, "app_repair_code_blocks"),
214
- }.get(app_command)
215
- if builder_command == "button":
216
- return {
217
- "list": _tool_key(BUILDER_DOMAIN, "app_custom_button_list"),
218
- "get": _tool_key(BUILDER_DOMAIN, "app_custom_button_get"),
219
- "create": _tool_key(BUILDER_DOMAIN, "app_custom_button_create"),
220
- "update": _tool_key(BUILDER_DOMAIN, "app_custom_button_update"),
221
- "delete": _tool_key(BUILDER_DOMAIN, "app_custom_button_delete"),
222
- }.get(getattr(args, "builder_button_command", None))
223
- if builder_command == "portal":
224
- return {
225
- "list": _tool_key(BUILDER_DOMAIN, "portal_list"),
226
- "get": _tool_key(BUILDER_DOMAIN, "portal_get"),
227
- "apply": _tool_key(BUILDER_DOMAIN, "portal_apply"),
228
- }.get(getattr(args, "builder_portal_command", None))
229
- if builder_command == "view":
230
- return {
231
- "get": _tool_key(BUILDER_DOMAIN, "view_get"),
232
- }.get(getattr(args, "builder_view_command", None))
233
- if builder_command == "chart":
234
- return {
235
- "get": _tool_key(BUILDER_DOMAIN, "chart_get"),
236
- }.get(getattr(args, "builder_chart_command", None))
237
- if builder_command == "schema":
238
- return {"apply": _tool_key(BUILDER_DOMAIN, "app_schema_apply")}.get(getattr(args, "builder_schema_command", None))
239
- if builder_command == "layout":
240
- return {"apply": _tool_key(BUILDER_DOMAIN, "app_layout_apply")}.get(getattr(args, "builder_layout_command", None))
241
- if builder_command == "views":
242
- return {"apply": _tool_key(BUILDER_DOMAIN, "app_views_apply")}.get(getattr(args, "builder_views_command", None))
243
- if builder_command == "flow":
244
- return {"apply": _tool_key(BUILDER_DOMAIN, "app_flow_apply")}.get(getattr(args, "builder_flow_command", None))
245
- if builder_command == "charts":
246
- return {"apply": _tool_key(BUILDER_DOMAIN, "app_charts_apply")}.get(getattr(args, "builder_charts_command", None))
247
- if builder_command == "publish":
248
- return {"verify": _tool_key(BUILDER_DOMAIN, "app_publish_verify")}.get(getattr(args, "builder_publish_command", None))
249
- return None
250
-
251
-
252
- USER_SERVER_METHOD_MAP = {
253
- "auth_login": _tool_key(USER_DOMAIN, "auth_login"),
254
- "auth_use_token": _tool_key(USER_DOMAIN, "auth_use_token"),
255
- "auth_whoami": _tool_key(USER_DOMAIN, "auth_whoami"),
256
- "auth_logout": _tool_key(USER_DOMAIN, "auth_logout"),
257
- "workspace_list": _tool_key(USER_DOMAIN, "workspace_list"),
258
- "workspace_select": _tool_key(USER_DOMAIN, "workspace_select"),
259
- "app_list": _tool_key(USER_DOMAIN, "app_list"),
260
- "app_search": _tool_key(USER_DOMAIN, "app_search"),
261
- "app_get": _tool_key(USER_DOMAIN, "app_get"),
262
- "portal_list": _tool_key(USER_DOMAIN, "portal_list"),
263
- "portal_get": _tool_key(USER_DOMAIN, "portal_get"),
264
- "view_get": _tool_key(USER_DOMAIN, "view_get"),
265
- "chart_get": _tool_key(USER_DOMAIN, "chart_get"),
266
- "file_get_upload_info": _tool_key(USER_DOMAIN, "file_get_upload_info"),
267
- "file_upload_local": _tool_key(USER_DOMAIN, "file_upload_local"),
268
- "feedback_submit": _tool_key(USER_DOMAIN, "feedback_submit"),
269
- "record_import_schema_get": _tool_key(USER_DOMAIN, "record_import_schema_get"),
270
- "record_import_template_get": _tool_key(USER_DOMAIN, "record_import_template_get"),
271
- "record_import_verify": _tool_key(USER_DOMAIN, "record_import_verify"),
272
- "record_import_repair_local": _tool_key(USER_DOMAIN, "record_import_repair_local"),
273
- "record_import_start": _tool_key(USER_DOMAIN, "record_import_start"),
274
- "record_import_status_get": _tool_key(USER_DOMAIN, "record_import_status_get"),
275
- "record_insert_schema_get_public": _tool_key(USER_DOMAIN, "record_insert_schema_get"),
276
- "record_member_candidates": _tool_key(USER_DOMAIN, "record_member_candidates"),
277
- "record_department_candidates": _tool_key(USER_DOMAIN, "record_department_candidates"),
278
- "record_analyze": _tool_key(USER_DOMAIN, "record_analyze"),
279
- "record_list": _tool_key(USER_DOMAIN, "record_list"),
280
- "record_get_public": _tool_key(USER_DOMAIN, "record_get"),
281
- "record_browse_schema_get_public": _tool_key(USER_DOMAIN, "record_browse_schema_get"),
282
- "record_update_schema_get_public": _tool_key(USER_DOMAIN, "record_update_schema_get"),
283
- "record_insert_public": _tool_key(USER_DOMAIN, "record_insert"),
284
- "record_update_public": _tool_key(USER_DOMAIN, "record_update"),
285
- "record_delete_public": _tool_key(USER_DOMAIN, "record_delete"),
286
- "record_code_block_schema_get_public": _tool_key(USER_DOMAIN, "record_code_block_schema_get"),
287
- "record_code_block_run": _tool_key(USER_DOMAIN, "record_code_block_run"),
288
- "task_list": _tool_key(USER_DOMAIN, "task_list"),
289
- "task_get": _tool_key(USER_DOMAIN, "task_get"),
290
- "task_action_execute": _tool_key(USER_DOMAIN, "task_action_execute"),
291
- "task_associated_report_detail_get": _tool_key(USER_DOMAIN, "task_associated_report_detail_get"),
292
- "task_workflow_log_get": _tool_key(USER_DOMAIN, "task_workflow_log_get"),
293
- "directory_search": _tool_key(USER_DOMAIN, "directory_search"),
294
- "directory_list_internal_users": _tool_key(USER_DOMAIN, "directory_list_internal_users"),
295
- "directory_list_all_internal_users": _tool_key(USER_DOMAIN, "directory_list_all_internal_users"),
296
- "directory_list_internal_departments": _tool_key(USER_DOMAIN, "directory_list_internal_departments"),
297
- "directory_list_all_departments": _tool_key(USER_DOMAIN, "directory_list_all_departments"),
298
- "directory_list_sub_departments": _tool_key(USER_DOMAIN, "directory_list_sub_departments"),
299
- "directory_list_external_members": _tool_key(USER_DOMAIN, "directory_list_external_members"),
300
- }
105
+ return cli_trim_key_from_namespace(args)
301
106
 
302
- BUILDER_SERVER_METHOD_MAP = {
303
- "auth_login": _tool_key(BUILDER_DOMAIN, "auth_login"),
304
- "auth_use_token": _tool_key(BUILDER_DOMAIN, "auth_use_token"),
305
- "auth_whoami": _tool_key(BUILDER_DOMAIN, "auth_whoami"),
306
- "auth_logout": _tool_key(BUILDER_DOMAIN, "auth_logout"),
307
- "workspace_list": _tool_key(BUILDER_DOMAIN, "workspace_list"),
308
- "workspace_select": _tool_key(BUILDER_DOMAIN, "workspace_select"),
309
- "file_upload_local": _tool_key(BUILDER_DOMAIN, "file_upload_local"),
310
- "feedback_submit": _tool_key(BUILDER_DOMAIN, "feedback_submit"),
311
- "package_list": _tool_key(BUILDER_DOMAIN, "package_list"),
312
- "package_resolve": _tool_key(BUILDER_DOMAIN, "package_resolve"),
313
- "builder_tool_contract": _tool_key(BUILDER_DOMAIN, "builder_tool_contract"),
314
- "package_create": _tool_key(BUILDER_DOMAIN, "package_create"),
315
- "member_search": _tool_key(BUILDER_DOMAIN, "member_search"),
316
- "role_search": _tool_key(BUILDER_DOMAIN, "role_search"),
317
- "role_create": _tool_key(BUILDER_DOMAIN, "role_create"),
318
- "package_attach_app": _tool_key(BUILDER_DOMAIN, "package_attach_app"),
319
- "app_release_edit_lock_if_mine": _tool_key(BUILDER_DOMAIN, "app_release_edit_lock_if_mine"),
320
- "app_resolve": _tool_key(BUILDER_DOMAIN, "app_resolve"),
321
- "app_custom_button_list": _tool_key(BUILDER_DOMAIN, "app_custom_button_list"),
322
- "app_custom_button_get": _tool_key(BUILDER_DOMAIN, "app_custom_button_get"),
323
- "app_custom_button_create": _tool_key(BUILDER_DOMAIN, "app_custom_button_create"),
324
- "app_custom_button_update": _tool_key(BUILDER_DOMAIN, "app_custom_button_update"),
325
- "app_custom_button_delete": _tool_key(BUILDER_DOMAIN, "app_custom_button_delete"),
326
- "app_get": _tool_key(BUILDER_DOMAIN, "app_get"),
327
- "app_get_fields": _tool_key(BUILDER_DOMAIN, "app_get_fields"),
328
- "app_repair_code_blocks": _tool_key(BUILDER_DOMAIN, "app_repair_code_blocks"),
329
- "app_get_layout": _tool_key(BUILDER_DOMAIN, "app_get_layout"),
330
- "app_get_views": _tool_key(BUILDER_DOMAIN, "app_get_views"),
331
- "app_get_flow": _tool_key(BUILDER_DOMAIN, "app_get_flow"),
332
- "app_get_charts": _tool_key(BUILDER_DOMAIN, "app_get_charts"),
333
- "portal_list": _tool_key(BUILDER_DOMAIN, "portal_list"),
334
- "portal_get": _tool_key(BUILDER_DOMAIN, "portal_get"),
335
- "view_get": _tool_key(BUILDER_DOMAIN, "view_get"),
336
- "chart_get": _tool_key(BUILDER_DOMAIN, "chart_get"),
337
- "app_schema_apply": _tool_key(BUILDER_DOMAIN, "app_schema_apply"),
338
- "app_layout_apply": _tool_key(BUILDER_DOMAIN, "app_layout_apply"),
339
- "app_flow_apply": _tool_key(BUILDER_DOMAIN, "app_flow_apply"),
340
- "app_views_apply": _tool_key(BUILDER_DOMAIN, "app_views_apply"),
341
- "app_charts_apply": _tool_key(BUILDER_DOMAIN, "app_charts_apply"),
342
- "portal_apply": _tool_key(BUILDER_DOMAIN, "portal_apply"),
343
- "app_publish_verify": _tool_key(BUILDER_DOMAIN, "app_publish_verify"),
344
- }
107
+
108
+ USER_SERVER_METHOD_MAP = server_method_map(USER_DOMAIN)
109
+ BUILDER_SERVER_METHOD_MAP = server_method_map(BUILDER_DOMAIN)
345
110
 
346
111
 
347
112
  def _wrap_callable(original: Callable[..., Any], tool_name: str) -> Callable[..., Any]:
@@ -602,7 +367,7 @@ def _trim_builder_list_like(payload: JSONObject) -> None:
602
367
  def _register_policy(domains: tuple[str, ...], names: tuple[str, ...], transform: TransformFn) -> None:
603
368
  for domain in domains:
604
369
  for name in names:
605
- SUCCESS_POLICY_BY_TOOL[_tool_key(domain, name)] = transform
370
+ SUCCESS_POLICY_BY_TOOL[tool_key(domain, name)] = transform
606
371
 
607
372
 
608
373
  _register_policy((USER_DOMAIN, BUILDER_DOMAIN), ("auth_login", "auth_use_token", "auth_whoami"), _trim_auth_payload)
@@ -683,6 +448,7 @@ _register_policy(
683
448
  "package_list",
684
449
  "package_resolve",
685
450
  "builder_tool_contract",
451
+ "solution_install",
686
452
  "package_create",
687
453
  "member_search",
688
454
  "role_search",
@@ -117,6 +117,7 @@ Analysis answers must include concrete numbers. When applicable, include percent
117
117
 
118
118
  - Read relation targets from `record_insert_schema_get` / `record_update_schema_get` relation metadata before preparing relation writes.
119
119
  - Member and department fields may be written with natural strings directly on `record_insert` / `record_update`; only fall back to `record_member_candidates` or `record_department_candidates` when the user wants explicit candidate browsing or the write returns ambiguity that needs confirmation.
120
+ - When candidate browsing must match a real update/write scope, pass `record_id`, `workflow_node_id`, and any pending `fields` context to the candidate tool; otherwise the candidate result is only a static applicant-node preview.
120
121
  - If explicit candidate browsing is needed for default-all member or department fields, prefer those field candidate tools instead of starting with `directory_*`.
121
122
 
122
123
  ## Code Block Path
@@ -148,6 +149,9 @@ Use `record_code_block_run` when the user wants to execute a form code-block fie
148
149
  - Use `task_associated_report_detail_get` for associated view or report details.
149
150
  - Use `task_workflow_log_get` for full workflow log history.
150
151
  - Task actions operate on `app_key + record_id + workflow_node_id`, not `task_id`.
152
+ - Treat `task_action_execute` as the tool-level action enum surface; the current task's real actions are only the ones listed in `task_get.capabilities.available_actions`.
153
+ - Use `task_action_execute(action="save_only", fields=...)` when the user wants to save editable field changes on the current node without advancing the workflow.
154
+ - `save_only` is exposed only when the backend current-node `editableQueIds` signal returns a non-empty result; MCP no longer infers `save_only` from local schema reconstruction.
151
155
 
152
156
  ## Time Handling
153
157