deepcell-cli 0.6.1__py3-none-any.whl
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.
- deepcell_cli/__init__.py +12 -0
- deepcell_cli/__main__.py +5 -0
- deepcell_cli/_findings.py +84 -0
- deepcell_cli/capabilities.py +560 -0
- deepcell_cli/capability-contract.json +15622 -0
- deepcell_cli/client.py +503 -0
- deepcell_cli/commands/__init__.py +1 -0
- deepcell_cli/commands/_batch_input.py +29 -0
- deepcell_cli/commands/_datatypes.py +56 -0
- deepcell_cli/commands/_negative_args.py +133 -0
- deepcell_cli/commands/_swapped_args.py +153 -0
- deepcell_cli/commands/_version_display.py +40 -0
- deepcell_cli/commands/_write_opts.py +139 -0
- deepcell_cli/commands/account.py +123 -0
- deepcell_cli/commands/auth.py +610 -0
- deepcell_cli/commands/changes.py +307 -0
- deepcell_cli/commands/deck.py +594 -0
- deepcell_cli/commands/defs.py +3890 -0
- deepcell_cli/commands/describe.py +902 -0
- deepcell_cli/commands/doc.py +529 -0
- deepcell_cli/commands/doctor.py +257 -0
- deepcell_cli/commands/download.py +36 -0
- deepcell_cli/commands/edit.py +384 -0
- deepcell_cli/commands/example.py +161 -0
- deepcell_cli/commands/export.py +81 -0
- deepcell_cli/commands/export_docx.py +57 -0
- deepcell_cli/commands/export_pdf.py +66 -0
- deepcell_cli/commands/export_pptx.py +45 -0
- deepcell_cli/commands/files.py +386 -0
- deepcell_cli/commands/grep.py +90 -0
- deepcell_cli/commands/guide.py +431 -0
- deepcell_cli/commands/help_cmd.py +348 -0
- deepcell_cli/commands/impact.py +382 -0
- deepcell_cli/commands/import_cmd.py +208 -0
- deepcell_cli/commands/ingest.py +110 -0
- deepcell_cli/commands/merge.py +399 -0
- deepcell_cli/commands/query.py +718 -0
- deepcell_cli/commands/reasoning.py +2981 -0
- deepcell_cli/commands/ref.py +279 -0
- deepcell_cli/commands/replace.py +326 -0
- deepcell_cli/commands/rules.py +206 -0
- deepcell_cli/commands/share.py +186 -0
- deepcell_cli/commands/sync.py +804 -0
- deepcell_cli/commands/upgrade.py +185 -0
- deepcell_cli/commands/variant.py +353 -0
- deepcell_cli/commands/version.py +445 -0
- deepcell_cli/commands/viewer.py +54 -0
- deepcell_cli/commands/workspace.py +101 -0
- deepcell_cli/config.py +352 -0
- deepcell_cli/context.py +187 -0
- deepcell_cli/errors.py +141 -0
- deepcell_cli/logging_setup.py +161 -0
- deepcell_cli/main.py +518 -0
- deepcell_cli/mcp_server.py +906 -0
- deepcell_cli/oauth_provider.py +580 -0
- deepcell_cli/output.py +503 -0
- deepcell_cli/revision.py +164 -0
- deepcell_cli/stages.py +223 -0
- deepcell_cli/surface.py +628 -0
- deepcell_cli/sync_state.py +120 -0
- deepcell_cli/upgrade_check.py +399 -0
- deepcell_cli/xml_replace.py +89 -0
- deepcell_cli-0.6.1.dist-info/METADATA +264 -0
- deepcell_cli-0.6.1.dist-info/RECORD +67 -0
- deepcell_cli-0.6.1.dist-info/WHEEL +5 -0
- deepcell_cli-0.6.1.dist-info/entry_points.txt +3 -0
- deepcell_cli-0.6.1.dist-info/top_level.txt +1 -0
deepcell_cli/__init__.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""DeepCell CLI — command-line interface for the DeepCell platform.
|
|
2
|
+
|
|
3
|
+
``__version__`` is the *runtime* version — what `--version` prints, what the
|
|
4
|
+
client header sends, and what the upgrade check compares against PyPI. The
|
|
5
|
+
packaging version in ``cli/pyproject.toml`` is a second copy that must say the
|
|
6
|
+
same thing, and a third is stamped into ``docs/cli-surface.json`` by
|
|
7
|
+
``scripts/gen_cli_surface.py``. All three are pinned together by
|
|
8
|
+
``cli/tests/test_version_parity.py`` — bumping one alone ships a build that
|
|
9
|
+
reports a version it is not, and skipping the regen lands a red build.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__version__ = "0.6.1"
|
deepcell_cli/__main__.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Shared rendering for lint findings that cite a house rule.
|
|
2
|
+
|
|
3
|
+
The highest-leverage place to put a cross-reference is the failure site: the
|
|
4
|
+
agent is already there and already paying attention, so a rule id printed
|
|
5
|
+
beside the finding costs zero navigation. This module is the one place that
|
|
6
|
+
decides how that citation looks, so the three CLI surfaces that render
|
|
7
|
+
findings — ``describe --lint``, ``reasoning lint``, and the post-write findings
|
|
8
|
+
from ``reasoning add-*`` — cannot drift into three notations.
|
|
9
|
+
|
|
10
|
+
Findings carry ``house_rule`` (e.g. ``"R8"``) only when their lint code
|
|
11
|
+
enforces one. Most codes are structural checks no house rule claims, so an
|
|
12
|
+
unstamped finding is normal and renders exactly as it did before.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import Any, Iterable
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def rule_citation(finding: dict[str, Any]) -> str:
|
|
21
|
+
"""Return ``" rule:R2"`` for a stamped finding, or ``""`` for the rest.
|
|
22
|
+
|
|
23
|
+
Includes its own leading space so callers can append unconditionally
|
|
24
|
+
without emitting a trailing space when there is no rule.
|
|
25
|
+
"""
|
|
26
|
+
rule_id = finding.get("house_rule")
|
|
27
|
+
return f" rule:{rule_id}" if rule_id else ""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def provenance(finding: dict[str, Any]) -> str:
|
|
31
|
+
"""Return ``" (pre-existing)"`` / ``" (new)"``, or ``""`` when unknown.
|
|
32
|
+
|
|
33
|
+
A finding on its own does not say whether the change that surfaced it is
|
|
34
|
+
what caused it, and a caller who cannot tell reads every finding as damage
|
|
35
|
+
they just did. The 2026-08-02 CLI eval has the shape on tape: a worker
|
|
36
|
+
fixed one warning, the response came back carrying an `orphan_claim` that
|
|
37
|
+
had been true all along, and it spent four commands chasing a problem its
|
|
38
|
+
edit had not introduced.
|
|
39
|
+
|
|
40
|
+
Both states are labelled rather than only the surprising one. Marking just
|
|
41
|
+
the pre-existing ones would leave an unlabelled finding ambiguous between
|
|
42
|
+
"new" and "this surface does not know", which is the ambiguity the stamp
|
|
43
|
+
exists to remove. Surfaces with no baseline to compare against (the
|
|
44
|
+
read-only `reasoning lint`) send no stamp and render exactly as before.
|
|
45
|
+
"""
|
|
46
|
+
pre_existing = finding.get("pre_existing")
|
|
47
|
+
if pre_existing is None:
|
|
48
|
+
return ""
|
|
49
|
+
return " (pre-existing)" if pre_existing else " (new)"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def cited_rules_footer(findings: Iterable[dict[str, Any]]) -> str | None:
|
|
53
|
+
"""Return one line telling the reader how to read the rules just cited.
|
|
54
|
+
|
|
55
|
+
One footer rather than a pointer per finding: a forty-finding lint would
|
|
56
|
+
otherwise repeat the same instruction forty times, which trains the reader
|
|
57
|
+
to skip it. ``None`` when there is nothing to point at.
|
|
58
|
+
|
|
59
|
+
Two lines at most — the house rules cited, and how to explain a lint code.
|
|
60
|
+
The second is capped at three codes because the footer is an affordance,
|
|
61
|
+
not a second copy of the findings list.
|
|
62
|
+
"""
|
|
63
|
+
seen: list[str] = []
|
|
64
|
+
codes: list[str] = []
|
|
65
|
+
for finding in findings:
|
|
66
|
+
rule_id = finding.get("house_rule")
|
|
67
|
+
if rule_id and rule_id not in seen:
|
|
68
|
+
seen.append(rule_id)
|
|
69
|
+
code = finding.get("rule")
|
|
70
|
+
if code and code not in codes:
|
|
71
|
+
codes.append(code)
|
|
72
|
+
|
|
73
|
+
parts: list[str] = []
|
|
74
|
+
if seen:
|
|
75
|
+
parts.append("Cited rules: " + " · ".join(f"deepcell rules {r}" for r in seen))
|
|
76
|
+
# Every finding has a code, and `deepcell ref lint/<code>` explains what it
|
|
77
|
+
# flags and the fix — so this line is useful even when no house rule was
|
|
78
|
+
# cited, which is the majority case.
|
|
79
|
+
if codes:
|
|
80
|
+
parts.append(
|
|
81
|
+
"Explain a code: " + " · ".join(f"deepcell ref lint/{c}" for c in codes[:3])
|
|
82
|
+
+ (" …" if len(codes) > 3 else "")
|
|
83
|
+
)
|
|
84
|
+
return "\n".join(parts) if parts else None
|
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
"""Authoritative cross-surface capability policy.
|
|
2
|
+
|
|
3
|
+
The Click tree owns command syntax and ``backend/openapi.json`` owns Jingwei
|
|
4
|
+
methods, paths, and schemas. This module owns the facts neither source can
|
|
5
|
+
express by itself: which operations a CLI command reaches, which transports
|
|
6
|
+
can run a command, and why an operation deliberately has no CLI route.
|
|
7
|
+
|
|
8
|
+
``scripts/gen_cli_surface.py`` expands this policy against both authorities and
|
|
9
|
+
writes the resulting contract into every runtime that needs it. Keep entries
|
|
10
|
+
keyed by OpenAPI ``operationId`` rather than copying paths or request schemas;
|
|
11
|
+
codegen fails when an id disappears, a new operation is unclassified, or a
|
|
12
|
+
command pattern matches nothing.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
from functools import lru_cache
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# ---------------------------------------------------------------------------
|
|
23
|
+
# Transport policy
|
|
24
|
+
# ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
# Every top-level Click command is listed exactly once across these two
|
|
27
|
+
# collections. Default-allow would make a newly added destructive command
|
|
28
|
+
# remotely callable until somebody happened to audit it.
|
|
29
|
+
MCP_ALLOWED_COMMANDS = frozenset(
|
|
30
|
+
{
|
|
31
|
+
"assumption",
|
|
32
|
+
"cat",
|
|
33
|
+
"cell-meta",
|
|
34
|
+
"changes",
|
|
35
|
+
"claim",
|
|
36
|
+
"deck",
|
|
37
|
+
"defs",
|
|
38
|
+
"describe",
|
|
39
|
+
"diff",
|
|
40
|
+
"doc",
|
|
41
|
+
"doctor",
|
|
42
|
+
"download",
|
|
43
|
+
"edit",
|
|
44
|
+
"example",
|
|
45
|
+
"grep",
|
|
46
|
+
"guide",
|
|
47
|
+
"help",
|
|
48
|
+
"impact",
|
|
49
|
+
"import",
|
|
50
|
+
"ingest",
|
|
51
|
+
"log",
|
|
52
|
+
"ls",
|
|
53
|
+
"project",
|
|
54
|
+
"query",
|
|
55
|
+
"reasoning",
|
|
56
|
+
"reasoning-diff",
|
|
57
|
+
"ref",
|
|
58
|
+
"relationships",
|
|
59
|
+
"replace",
|
|
60
|
+
"restore",
|
|
61
|
+
"rm",
|
|
62
|
+
"rules",
|
|
63
|
+
"share",
|
|
64
|
+
"variant",
|
|
65
|
+
"viewer",
|
|
66
|
+
"whoami",
|
|
67
|
+
"write",
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Reason codes are stable data rendered into help, guide, MCP errors, and the
|
|
72
|
+
# for-agent page. The detail is for maintainers and structured clients; user
|
|
73
|
+
# prose remains translated at its own surface.
|
|
74
|
+
MCP_BLOCKED_COMMANDS: dict[str, dict[str, str]] = {
|
|
75
|
+
"account": {
|
|
76
|
+
"reason": "identity_destructive",
|
|
77
|
+
"detail": "exports or irreversibly deletes the caller's account",
|
|
78
|
+
},
|
|
79
|
+
"clone": {
|
|
80
|
+
"reason": "local_checkout",
|
|
81
|
+
"detail": "creates and updates a local Git working copy",
|
|
82
|
+
},
|
|
83
|
+
"commit": {
|
|
84
|
+
"reason": "local_checkout",
|
|
85
|
+
"detail": "reads local sync state and commits a working copy",
|
|
86
|
+
},
|
|
87
|
+
"login": {
|
|
88
|
+
"reason": "interactive_auth",
|
|
89
|
+
"detail": "opens or polls an interactive browser authentication flow",
|
|
90
|
+
},
|
|
91
|
+
"logout": {
|
|
92
|
+
"reason": "shared_credentials",
|
|
93
|
+
"detail": "mutates process-global CLI credentials on the MCP host",
|
|
94
|
+
},
|
|
95
|
+
"merge": {
|
|
96
|
+
"reason": "local_checkout",
|
|
97
|
+
"detail": "reads and mutates local sync and conflict state",
|
|
98
|
+
},
|
|
99
|
+
"pull": {
|
|
100
|
+
"reason": "local_checkout",
|
|
101
|
+
"detail": "updates files in a local Git working copy",
|
|
102
|
+
},
|
|
103
|
+
"push": {
|
|
104
|
+
"reason": "local_checkout",
|
|
105
|
+
"detail": "reads and uploads files from a local Git working copy",
|
|
106
|
+
},
|
|
107
|
+
"register": {
|
|
108
|
+
"reason": "interactive_auth",
|
|
109
|
+
"detail": "creates identity-bearing credentials through prompts",
|
|
110
|
+
},
|
|
111
|
+
"status": {
|
|
112
|
+
"reason": "local_checkout",
|
|
113
|
+
"detail": "compares the remote workspace with local sync state",
|
|
114
|
+
},
|
|
115
|
+
"to-docx": {
|
|
116
|
+
"reason": "binary_download",
|
|
117
|
+
"detail": "writes a binary export to the MCP server's filesystem",
|
|
118
|
+
},
|
|
119
|
+
"to-excel": {
|
|
120
|
+
"reason": "binary_download",
|
|
121
|
+
"detail": "writes a binary export to the MCP server's filesystem",
|
|
122
|
+
},
|
|
123
|
+
"to-pdf": {
|
|
124
|
+
"reason": "binary_download",
|
|
125
|
+
"detail": "writes a binary export to the MCP server's filesystem",
|
|
126
|
+
},
|
|
127
|
+
"to-pptx": {
|
|
128
|
+
"reason": "binary_download",
|
|
129
|
+
"detail": "writes a binary export to the MCP server's filesystem",
|
|
130
|
+
},
|
|
131
|
+
"upgrade": {
|
|
132
|
+
"reason": "shared_host_install",
|
|
133
|
+
"detail": "would inspect or replace the CLI installed on the MCP host",
|
|
134
|
+
},
|
|
135
|
+
"verify-email": {
|
|
136
|
+
"reason": "interactive_auth",
|
|
137
|
+
"detail": "prompts for a verification token sent out of band",
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
# The LangGraph in-process tool deliberately exposes a smaller service-layer
|
|
142
|
+
# subset. Its implementation table is checked against this declaration in
|
|
143
|
+
# both directions; this list is the cross-surface availability decision, while
|
|
144
|
+
# ``deepcell_tool._COMMANDS`` remains the parser/dispatcher implementation.
|
|
145
|
+
IN_PROCESS_COMMANDS = frozenset(
|
|
146
|
+
{
|
|
147
|
+
"cat",
|
|
148
|
+
"defs apply",
|
|
149
|
+
"describe",
|
|
150
|
+
"example",
|
|
151
|
+
"guide",
|
|
152
|
+
"help",
|
|
153
|
+
"ls",
|
|
154
|
+
"query",
|
|
155
|
+
"ref",
|
|
156
|
+
"rules",
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
# ---------------------------------------------------------------------------
|
|
162
|
+
# Jingwei operation -> CLI command mapping
|
|
163
|
+
# ---------------------------------------------------------------------------
|
|
164
|
+
|
|
165
|
+
# Values are fnmatch patterns over leaf command paths in the generated Click
|
|
166
|
+
# surface. The generator expands them to exact names and rejects a pattern
|
|
167
|
+
# that matches nothing. An operation may support several commands and a
|
|
168
|
+
# command may use several operations.
|
|
169
|
+
ENDPOINT_COMMANDS: dict[str, tuple[str, ...]] = {
|
|
170
|
+
# Service/auth lifecycle.
|
|
171
|
+
"health_check_health_get": ("doctor",),
|
|
172
|
+
"claim_demo_auth_claim_demo_post": ("login", "register"),
|
|
173
|
+
"device_code_auth_device_code_post": ("login",),
|
|
174
|
+
"device_token_auth_device_token_post": ("login",),
|
|
175
|
+
"login_auth_login_post": ("login",),
|
|
176
|
+
"register_auth_register_post": ("register",),
|
|
177
|
+
"revoke_token_auth_revoke_token_post": ("logout",),
|
|
178
|
+
"send_verification_auth_send_verification_post": ("verify-email",),
|
|
179
|
+
"verify_email_auth_verify_email_post": ("verify-email",),
|
|
180
|
+
"get_me_auth_me_get": ("whoami",),
|
|
181
|
+
"export_me_auth_me_export_get": ("account export",),
|
|
182
|
+
"delete_me_auth_me_delete": ("account delete",),
|
|
183
|
+
|
|
184
|
+
# Primary document/query/edit routes.
|
|
185
|
+
"apply_defs_ops_endpoint_apply_defs_ops_post": (
|
|
186
|
+
"defs add-*",
|
|
187
|
+
"defs update-*",
|
|
188
|
+
"defs delete-*",
|
|
189
|
+
"defs rename-*",
|
|
190
|
+
"defs reorder-*",
|
|
191
|
+
"defs set-*",
|
|
192
|
+
"defs header *",
|
|
193
|
+
"defs apply",
|
|
194
|
+
# The Deck surface's structural ops. Same endpoint as `defs` — a deck
|
|
195
|
+
# op is a defs op; `deepcell deck` is a front door onto the flag-shaped
|
|
196
|
+
# subset of them, not a second route.
|
|
197
|
+
"deck add",
|
|
198
|
+
"deck add-slide",
|
|
199
|
+
"deck rename",
|
|
200
|
+
"deck rename-slide",
|
|
201
|
+
"deck reorder",
|
|
202
|
+
"deck reorder-slide",
|
|
203
|
+
"deck delete",
|
|
204
|
+
"deck delete-slide",
|
|
205
|
+
"deck bind",
|
|
206
|
+
"deck unbind",
|
|
207
|
+
"deck brand",
|
|
208
|
+
"doc stamp-ids",
|
|
209
|
+
"doc replace-block",
|
|
210
|
+
"doc insert-block",
|
|
211
|
+
"doc move-block",
|
|
212
|
+
"doc delete-block",
|
|
213
|
+
"doc set-body",
|
|
214
|
+
"doc patch-body",
|
|
215
|
+
"doc set-notation",
|
|
216
|
+
),
|
|
217
|
+
"batch_edit_values_batch_edit_post": ("edit",),
|
|
218
|
+
"get_cell_meta_cell_meta_post": ("cell-meta",),
|
|
219
|
+
"list_defs_endpoint_defs_list_post": ("defs list",),
|
|
220
|
+
"show_defs_endpoint_defs_show_post": ("defs show",),
|
|
221
|
+
"describe_document_describe_post": ("describe",),
|
|
222
|
+
"query_deepcell_query_post": ("query",),
|
|
223
|
+
"get_relationships_relationships_post": ("relationships",),
|
|
224
|
+
"document_backlinks_document_backlinks_post": ("doc backlinks",),
|
|
225
|
+
"impact_impact_post": ("impact show",),
|
|
226
|
+
"review_impact_review_post": ("impact review",),
|
|
227
|
+
"apply_impact_apply_post": ("impact apply",),
|
|
228
|
+
"reopen_impact_reopen_post": ("impact reopen",),
|
|
229
|
+
"document_blocks_document_blocks_post": ("doc blocks",),
|
|
230
|
+
"document_links_document_links_post": ("doc links",),
|
|
231
|
+
"document_lint_document_lint_post": ("doc lint",),
|
|
232
|
+
"list_documents_document_list_post": ("doc list",),
|
|
233
|
+
"document_outline_document_outline_post": ("doc outline",),
|
|
234
|
+
"show_document_document_show_post": ("doc show",),
|
|
235
|
+
|
|
236
|
+
# Reasoning graph.
|
|
237
|
+
"edit_reasoning_edit_post": (
|
|
238
|
+
"reasoning add-*",
|
|
239
|
+
"reasoning update-*",
|
|
240
|
+
"reasoning delete-*",
|
|
241
|
+
"reasoning supersede-*",
|
|
242
|
+
"reasoning set-conclusion",
|
|
243
|
+
),
|
|
244
|
+
"reasoning_graph_reasoning_graph_post": ("reasoning graph",),
|
|
245
|
+
"reasoning_lint_reasoning_lint_post": ("reasoning lint",),
|
|
246
|
+
"query_reasoning_query_post": ("reasoning impact",),
|
|
247
|
+
|
|
248
|
+
# Generated reference surfaces.
|
|
249
|
+
"list_all_examples_examples_get": ("example", "example list"),
|
|
250
|
+
"get_example_layer_examples__name__layer__layer__get": (
|
|
251
|
+
"example show",
|
|
252
|
+
"example get",
|
|
253
|
+
),
|
|
254
|
+
"list_guide_topics_guide_get": ("guide",),
|
|
255
|
+
"list_domain_packs_guide_packs_index_get": ("guide",),
|
|
256
|
+
"get_capability_index_guide_capabilities_index_get": ("guide",),
|
|
257
|
+
"get_topic_guide__topic__get": ("guide",),
|
|
258
|
+
"list_ref_namespaces_ref_get": ("ref",),
|
|
259
|
+
"resolve_id_ref_resolve_get": ("ref",),
|
|
260
|
+
"search_surfaces_ref_search_get": ("ref",),
|
|
261
|
+
"list_namespace_entries_ref__namespace__get": ("ref",),
|
|
262
|
+
"get_namespace_entry_ref__namespace___name__get": ("ref",),
|
|
263
|
+
"list_house_rules_rules_get": ("rules",),
|
|
264
|
+
"get_house_rule_rules__rule_id__get": ("rules",),
|
|
265
|
+
|
|
266
|
+
# Import, ingestion, and export.
|
|
267
|
+
"import_file_import_post": ("import",),
|
|
268
|
+
"cn_extract_ingest_cn_extract_get": ("ingest cn extract",),
|
|
269
|
+
"cn_filings_ingest_cn_filings_get": ("ingest cn filings",),
|
|
270
|
+
"cn_search_ingest_cn_search_get": ("ingest cn search",),
|
|
271
|
+
"cn_statements_ingest_cn_statements_get": ("ingest cn statements",),
|
|
272
|
+
"to_docx_to_docx_post": ("to-docx",),
|
|
273
|
+
"to_excel_to_excel_post": ("to-excel",),
|
|
274
|
+
"to_pdf_to_pdf_post": ("to-pdf",),
|
|
275
|
+
"to_pptx_to_pptx_post": ("to-pptx",),
|
|
276
|
+
|
|
277
|
+
# Workspace files, history, variants, sync, and sharing.
|
|
278
|
+
"list_workspaces_workspaces_get": ("project list",),
|
|
279
|
+
"create_workspace_workspaces_post": ("project create",),
|
|
280
|
+
"get_workspace_workspaces__slug__get": (
|
|
281
|
+
"project use",
|
|
282
|
+
"project info",
|
|
283
|
+
"clone",
|
|
284
|
+
"pull",
|
|
285
|
+
"push",
|
|
286
|
+
"status",
|
|
287
|
+
),
|
|
288
|
+
"list_workspace_files_workspaces__slug__files_get": (
|
|
289
|
+
"ls",
|
|
290
|
+
"grep",
|
|
291
|
+
"clone",
|
|
292
|
+
"pull",
|
|
293
|
+
"push",
|
|
294
|
+
"status",
|
|
295
|
+
"doctor",
|
|
296
|
+
),
|
|
297
|
+
"get_workspace_file_workspaces__slug__files__filename__get": (
|
|
298
|
+
"cat",
|
|
299
|
+
"download",
|
|
300
|
+
"grep",
|
|
301
|
+
"query",
|
|
302
|
+
"claim *",
|
|
303
|
+
"assumption *",
|
|
304
|
+
"reasoning *",
|
|
305
|
+
"merge *",
|
|
306
|
+
"clone",
|
|
307
|
+
"pull",
|
|
308
|
+
"push",
|
|
309
|
+
"status",
|
|
310
|
+
),
|
|
311
|
+
"create_or_update_workspace_file_workspaces__slug__files__filename__post": (
|
|
312
|
+
"write",
|
|
313
|
+
"replace",
|
|
314
|
+
"reasoning add-*",
|
|
315
|
+
"reasoning update-*",
|
|
316
|
+
"reasoning delete-*",
|
|
317
|
+
"reasoning supersede-*",
|
|
318
|
+
"reasoning set-conclusion",
|
|
319
|
+
),
|
|
320
|
+
"delete_workspace_file_workspaces__slug__files__filename__delete": ("rm",),
|
|
321
|
+
"batch_commit_workspace_files_workspaces__slug__files_batch_post": ("push",),
|
|
322
|
+
"replace_in_workspace_file_workspaces__slug__files_replace_post": ("replace",),
|
|
323
|
+
"list_workspace_versions_workspaces__slug__versions_get": (
|
|
324
|
+
"log",
|
|
325
|
+
"clone",
|
|
326
|
+
"pull",
|
|
327
|
+
"push",
|
|
328
|
+
"status",
|
|
329
|
+
),
|
|
330
|
+
"workspace_commit_pending_workspaces__slug__versions_commit_post": ("commit",),
|
|
331
|
+
"workspace_version_diff_workspaces__slug__versions_diff_get": ("diff",),
|
|
332
|
+
"workspace_version_restore_workspaces__slug__versions_restore_post": ("restore",),
|
|
333
|
+
"list_workspace_changes_workspaces__slug__changes_get": ("changes list",),
|
|
334
|
+
"workspace_change_diff_workspaces__slug__changes_diff_get": ("changes diff",),
|
|
335
|
+
"revert_workspace_change_workspaces__slug__changes_revert_post": (
|
|
336
|
+
"changes revert",
|
|
337
|
+
),
|
|
338
|
+
"list_workspace_variants_workspaces__slug__variants_get": ("variant list",),
|
|
339
|
+
"get_variant_workspaces__slug__variants__name__get": (
|
|
340
|
+
"variant checkout",
|
|
341
|
+
"clone",
|
|
342
|
+
"pull",
|
|
343
|
+
"push",
|
|
344
|
+
"status",
|
|
345
|
+
),
|
|
346
|
+
"create_workspace_variant_workspaces__slug__variants__name__post": ("variant create",),
|
|
347
|
+
"get_variant_diff_workspaces__slug__variants__name__diff_get": ("variant diff",),
|
|
348
|
+
"list_variant_files_workspaces__slug__variants__name__files_get": (
|
|
349
|
+
"clone",
|
|
350
|
+
"pull",
|
|
351
|
+
"push",
|
|
352
|
+
"status",
|
|
353
|
+
),
|
|
354
|
+
"get_variant_file_workspaces__slug__variants__name__files__filename__get": (
|
|
355
|
+
"clone",
|
|
356
|
+
"pull",
|
|
357
|
+
"push",
|
|
358
|
+
"status",
|
|
359
|
+
),
|
|
360
|
+
"create_or_update_variant_file_workspaces__slug__variants__name__files__filename__post": ("push",),
|
|
361
|
+
"merge_variant_into_main_workspaces__slug__variants__name__merge_post": ("variant merge",),
|
|
362
|
+
"merge_preview_merge_preview_post": ("merge *", "pull"),
|
|
363
|
+
"resolve_conflicts_merge_resolve_post": ("merge resolve",),
|
|
364
|
+
"list_share_links_workspaces__slug__shares_get": ("share list",),
|
|
365
|
+
"create_share_link_workspaces__slug__shares_post": ("share create",),
|
|
366
|
+
"revoke_share_link_workspaces__slug__shares__share_id__delete": ("share revoke",),
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
# ---------------------------------------------------------------------------
|
|
371
|
+
# Explicit operations without a CLI route
|
|
372
|
+
# ---------------------------------------------------------------------------
|
|
373
|
+
|
|
374
|
+
# Every operation not in ENDPOINT_COMMANDS must appear here. Grouped values
|
|
375
|
+
# remain exact operation ids: adding a route under an existing tag still fails
|
|
376
|
+
# codegen until somebody classifies that route deliberately.
|
|
377
|
+
ENDPOINT_EXCEPTIONS: dict[str, tuple[str, str]] = {
|
|
378
|
+
# Service metadata, cache, telemetry, and server-owned lifecycle.
|
|
379
|
+
"root__get": ("service_metadata", "HTTP landing response, not an analytical capability"),
|
|
380
|
+
"version_info_version_get": ("service_metadata", "frontend/service version probe; CLI reports its installed version locally"),
|
|
381
|
+
"clear_cache_cache_clear_post": ("internal_ops", "operator-only cache maintenance"),
|
|
382
|
+
"get_cache_stats_cache_stats_get": ("internal_ops", "operator-only cache diagnostics"),
|
|
383
|
+
"record_unknown_command_cli_unknown_commands_post": ("implicit_client", "CLI telemetry emitted automatically, never invoked directly"),
|
|
384
|
+
"record_web_events_signals_web_post": ("frontend_only", "browser analytics collector"),
|
|
385
|
+
"create_demo_session_demo_session_post": ("implicit_client", "anonymous CLI session bootstrap performed by DeepCellClient"),
|
|
386
|
+
# The /demo gallery's preview panel. A CLI caller has the fixture itself —
|
|
387
|
+
# `deepcell example` and the shipped files — so a route whose whole job is
|
|
388
|
+
# to show a browser what is inside one before opening it has no verb.
|
|
389
|
+
"demo_example_preview_demo_examples__filename__preview_get": ("frontend_only", "gallery preview panel: which surfaces an example carries"),
|
|
390
|
+
"demo_example_thumbnail_demo_examples__filename__thumbnail_png_get": ("frontend_only", "gallery preview panel: the example's opening slide, rasterized"),
|
|
391
|
+
# The example as plain XML, for an agent that is NOT this CLI. A caller who
|
|
392
|
+
# has `deepcell` has the fixtures already (`deepcell example get`), so there
|
|
393
|
+
# is nothing here to wrap in a verb. What this route is for is the agent on
|
|
394
|
+
# the other side of a copied prompt — one that has never heard of DeepCell
|
|
395
|
+
# and needs a URL it can fetch to see the shape it is being asked to copy.
|
|
396
|
+
"demo_example_raw_demo_examples__filename__raw_get": ("frontend_only", "public example XML, for an outside agent handed a URL"),
|
|
397
|
+
"ensure_demo_workspace_demo_workspace_post": ("agent_runtime", "hosted-agent workspace bootstrap"),
|
|
398
|
+
"get_quota_agent_runs_quota_get": ("agent_runtime", "hosted chat run quota"),
|
|
399
|
+
"reserve_thread_agent_threads_reserve_post": ("agent_runtime", "hosted chat thread bookkeeping"),
|
|
400
|
+
# The anonymous run allowance, spent on every submit to the HOSTED agent.
|
|
401
|
+
# A CLI caller drives their own agent and their own model, so there is
|
|
402
|
+
# nothing here for a verb to wrap — the runs this counts are the ones the
|
|
403
|
+
# hosted chat makes on the caller's behalf, which the CLI never issues.
|
|
404
|
+
"reserve_run_agent_runs_reserve_post": ("agent_runtime", "hosted chat run reservation"),
|
|
405
|
+
# The same allowance, spent by a visitor on a share link. Doubly not a CLI
|
|
406
|
+
# surface: it is reached with a share token rather than a user identity.
|
|
407
|
+
"reserve_share_run_share__token__runs_reserve_post": ("agent_runtime", "hosted share-visitor run reservation"),
|
|
408
|
+
|
|
409
|
+
# The task record, which belongs to the workbench rail and its inspectors.
|
|
410
|
+
#
|
|
411
|
+
# A task is one CONVERSATION with the agent, and the CLI does not have
|
|
412
|
+
# conversations: its own writes are stamped with an operation id and a
|
|
413
|
+
# `DeepCell-Command` trailer, so `changes list` already says what was run
|
|
414
|
+
# and what it touched, without a thread to hang it from. A CLI mirror of
|
|
415
|
+
# these was built and removed — it could only report on work done in the
|
|
416
|
+
# browser, which is where the reader already is when they ask.
|
|
417
|
+
"list_workspace_tasks_workspaces__slug__tasks_get": ("frontend_only", "workbench task rail; a CLI session is not a task"),
|
|
418
|
+
"update_workspace_task_workspaces__slug__tasks__thread_id__patch": ("frontend_only", "task rename and scope, set from the rail and the composer shelf"),
|
|
419
|
+
|
|
420
|
+
# Browser/MCP authentication and account management not exposed as CLI verbs.
|
|
421
|
+
"claim_anonymous_auth_claim_anonymous_post": ("frontend_only", "browser anonymous-session claim flow"),
|
|
422
|
+
# Reads the HttpOnly ``browser_id`` cookie and nothing else, on purpose:
|
|
423
|
+
# accepting an identity from the request body would let anyone who guesses
|
|
424
|
+
# a visitor's browser_id probe their demo state from another machine. A CLI
|
|
425
|
+
# caller has no such cookie — its half of the claim flow is the
|
|
426
|
+
# ``device_id`` + ``anon_access_token`` body variant of /auth/claim-demo,
|
|
427
|
+
# which is already mapped above.
|
|
428
|
+
"pending_anonymous_work_auth_pending_anonymous_work_get": ("frontend_only", "browser claim prompt: does this browser still hold claimable demo work"),
|
|
429
|
+
"device_authorize_auth_device_authorize_post": ("frontend_only", "browser approval half of the device flow"),
|
|
430
|
+
"forgot_password_auth_forgot_password_post": ("frontend_only", "browser password recovery"),
|
|
431
|
+
"google_callback_auth_google_callback_get": ("frontend_only", "browser OAuth callback"),
|
|
432
|
+
"google_login_auth_google_login_get": ("frontend_only", "browser OAuth entry"),
|
|
433
|
+
"google_status_auth_google_status_get": ("frontend_only", "browser sign-in capability probe"),
|
|
434
|
+
"logout_auth_logout_post": ("frontend_only", "cookie logout; CLI uses the refresh-token revocation route"),
|
|
435
|
+
"update_me_auth_me_put": ("frontend_only", "account settings editor"),
|
|
436
|
+
"change_password_auth_me_password_put": ("frontend_only", "account settings editor"),
|
|
437
|
+
"get_my_quota_auth_me_quota_get": ("frontend_only", "account quota display"),
|
|
438
|
+
"password_requirements_auth_password_requirements_get": ("frontend_only", "registration/password form metadata"),
|
|
439
|
+
"refresh_auth_refresh_post": ("implicit_client", "DeepCellClient refreshes credentials automatically"),
|
|
440
|
+
"reset_password_auth_reset_password_post": ("frontend_only", "browser password recovery"),
|
|
441
|
+
"join_waitlist_auth_waitlist_post": ("frontend_only", "website waitlist form"),
|
|
442
|
+
"list_api_keys_auth_api_keys_get": ("frontend_only", "API keys are managed in account settings"),
|
|
443
|
+
"create_api_key_auth_api_keys_post": ("frontend_only", "API keys are managed in account settings"),
|
|
444
|
+
"revoke_api_key_auth_api_keys__key_id__delete": ("frontend_only", "API keys are managed in account settings"),
|
|
445
|
+
"verify_api_key_auth_api_keys_verify_post": ("mcp_auth", "MCP bearer verification performed by the server"),
|
|
446
|
+
# Frontend configuration, dashboards, uploads, and preview/share viewers.
|
|
447
|
+
"get_export_formats_config_export_formats_get": ("frontend_only", "download-menu capability metadata"),
|
|
448
|
+
"get_import_sources_config_import_sources_get": ("frontend_only", "browser import-menu metadata"),
|
|
449
|
+
"dashboard_snapshot_dashboard_snapshot_post": ("frontend_only", "project dashboard aggregation"),
|
|
450
|
+
"download_file_files_download__object_name__get": ("attachment_transport", "uploaded attachment download, distinct from workspace document files"),
|
|
451
|
+
"upload_file_files_upload_post": ("attachment_transport", "uploaded attachment storage, distinct from workspace document files"),
|
|
452
|
+
"get_download_url_files_url__object_name__get": ("attachment_transport", "presigned attachment URL for browser/agent tools"),
|
|
453
|
+
"import_from_url_import_from_url_post": ("agent_runtime", "hosted agent URL-ingestion helper"),
|
|
454
|
+
"cn_source_pdf_ingest_cn_source__source_id__pdf_get": ("frontend_only", "inline filing PDF viewer"),
|
|
455
|
+
"get_one_example_examples__name__get": ("published_reference", "published example envelope; CLI reads the index and individual layers"),
|
|
456
|
+
"render_plan_render_plan_post": ("frontend_only", "grid render-plan fetch"),
|
|
457
|
+
"edit_inline_edit_inline_post": ("deprecated_alias", "legacy frontend alias; CLI uses files:replace or batch-edit"),
|
|
458
|
+
"upload_workspace_file_workspaces__slug__files_upload_post": ("frontend_only", "browser attachment upload into a workspace"),
|
|
459
|
+
|
|
460
|
+
# Public preview is a cookie-free browser surface, not the authenticated CLI.
|
|
461
|
+
"preview_cell_meta_preview_cell_meta_post": ("public_preview", "public preview inspector"),
|
|
462
|
+
"preview_reasoning_enumerate_preview_reasoning_enumerate_post": ("public_preview", "public preview reasoning reader"),
|
|
463
|
+
"preview_reasoning_query_preview_reasoning_query_post": ("public_preview", "public preview reasoning reader"),
|
|
464
|
+
"preview_relationships_preview_relationships_post": ("public_preview", "public preview relationship graph"),
|
|
465
|
+
"preview_render_plan_preview_render_plan_post": ("public_preview", "public preview renderer"),
|
|
466
|
+
"preview_source_preview_source_post": ("public_preview", "public preview source reader"),
|
|
467
|
+
"preview_to_docx_preview_to_docx_post": ("public_preview", "public preview export"),
|
|
468
|
+
"preview_to_excel_preview_to_excel_post": ("public_preview", "public preview export"),
|
|
469
|
+
"preview_to_pptx_preview_to_pptx_post": ("public_preview", "public preview export"),
|
|
470
|
+
|
|
471
|
+
# Browser share capabilities are token-scoped mirrors of authenticated APIs.
|
|
472
|
+
"get_share_info_share__token__get": ("share_viewer", "browser share metadata"),
|
|
473
|
+
"create_share_agent_session_share__token__agent_session_post": ("share_viewer", "share-assistant bootstrap"),
|
|
474
|
+
"share_apply_defs_ops_share__token__apply_defs_ops_post": ("share_viewer", "token-scoped browser/assistant edit route"),
|
|
475
|
+
"share_batch_edit_share__token__batch_edit_post": ("share_viewer", "token-scoped browser/assistant edit route"),
|
|
476
|
+
"share_cell_meta_share__token__cell_meta_post": ("share_viewer", "token-scoped browser inspector"),
|
|
477
|
+
"get_share_content_share__token__content_get": ("share_viewer", "token-scoped browser document fetch"),
|
|
478
|
+
"edit_shared_file_share__token__edit_post": ("share_viewer", "token-scoped browser/assistant edit route"),
|
|
479
|
+
"share_edit_inline_share__token__edit_inline_post": ("deprecated_alias", "legacy token-scoped frontend edit alias"),
|
|
480
|
+
"get_share_membership_share__token__membership_get": ("share_viewer", "browser ownership banner"),
|
|
481
|
+
"share_document_meta_share__token__meta_get": ("share_viewer", "browser share metadata"),
|
|
482
|
+
"share_head_share__token__head_get": ("share_viewer", "browser revision poll"),
|
|
483
|
+
"share_latest_share__token__latest_get": ("share_viewer", "browser document refresh"),
|
|
484
|
+
"share_og_image_share__token__og_image_png_get": ("share_viewer", "social preview image"),
|
|
485
|
+
"share_query_share__token__query_post": ("share_viewer", "token-scoped browser query"),
|
|
486
|
+
"share_reasoning_edit_share__token__reasoning_edit_post": ("share_viewer", "token-scoped browser/assistant reasoning edit"),
|
|
487
|
+
"share_reasoning_enumerate_share__token__reasoning_enumerate_post": ("share_viewer", "token-scoped browser reasoning reader"),
|
|
488
|
+
"share_reasoning_query_share__token__reasoning_query_post": ("share_viewer", "token-scoped browser reasoning reader"),
|
|
489
|
+
"share_relationships_share__token__relationships_post": ("share_viewer", "token-scoped browser relationship graph"),
|
|
490
|
+
"share_render_plan_share__token__render_plan_post": ("share_viewer", "token-scoped browser renderer"),
|
|
491
|
+
"share_to_docx_share__token__to_docx_post": ("share_viewer", "token-scoped browser export"),
|
|
492
|
+
"share_to_excel_share__token__to_excel_post": ("share_viewer", "token-scoped browser export"),
|
|
493
|
+
"share_to_pptx_share__token__to_pptx_post": ("share_viewer", "token-scoped browser export"),
|
|
494
|
+
"verify_password_share__token__verify_password_post": ("share_viewer", "browser share-password session"),
|
|
495
|
+
"list_shared_file_versions_share__token__versions_get": ("share_viewer", "browser share history"),
|
|
496
|
+
"get_shared_file_at_version_share__token__versions_content_get": ("share_viewer", "browser share history"),
|
|
497
|
+
"shared_file_version_diff_share__token__versions_diff_get": ("share_viewer", "browser share history"),
|
|
498
|
+
|
|
499
|
+
# Reasoning routes used by the web viewer; the CLI has different or local readers.
|
|
500
|
+
"diff_reasoning_diff_post": ("frontend_only", "browser comparison; reasoning-diff is deliberately Git-local"),
|
|
501
|
+
"enumerate_reasoning_reasoning_enumerate_post": ("frontend_only", "browser reasoning panel enumeration"),
|
|
502
|
+
|
|
503
|
+
# Workspace collaboration and hosted-agent state have no CLI owner today.
|
|
504
|
+
"accept_invitation_invitations_accept_post": ("frontend_only", "browser invitation acceptance"),
|
|
505
|
+
"get_thread_workspace_threads__thread_id__workspace_get": ("agent_runtime", "hosted thread/workspace binding"),
|
|
506
|
+
"delete_workspace_workspaces__slug__delete": ("frontend_only", "project settings destructive action"),
|
|
507
|
+
"update_workspace_workspaces__slug__put": ("frontend_only", "project settings editor"),
|
|
508
|
+
"list_invitations_workspaces__slug__invitations_get": ("frontend_only", "project invitation settings"),
|
|
509
|
+
"create_invitation_workspaces__slug__invitations_post": ("frontend_only", "project invitation settings"),
|
|
510
|
+
"revoke_invitation_workspaces__slug__invitations__invitation_id__delete": ("frontend_only", "project invitation settings"),
|
|
511
|
+
"list_members_workspaces__slug__members_get": ("frontend_only", "project membership settings"),
|
|
512
|
+
"add_member_workspaces__slug__members_post": ("frontend_only", "project membership settings"),
|
|
513
|
+
"remove_member_workspaces__slug__members__user_id__delete": ("frontend_only", "project membership settings"),
|
|
514
|
+
"update_member_role_workspaces__slug__members__user_id__put": ("frontend_only", "project membership settings"),
|
|
515
|
+
"list_workspace_threads_workspaces__slug__threads_get": ("agent_runtime", "hosted workspace thread list"),
|
|
516
|
+
"move_thread_to_workspace_workspaces__slug__threads_post": ("agent_runtime", "hosted thread/workspace binding"),
|
|
517
|
+
"transfer_ownership_workspaces__slug__transfer_post": ("frontend_only", "project ownership settings"),
|
|
518
|
+
"workspace_pending_changes_workspaces__slug__versions_pending_get": ("frontend_only", "browser pending-change indicator"),
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
# Commands that intentionally do not own a Jingwei operation. Everything else
|
|
523
|
+
# in the Click tree must be reached by at least one ENDPOINT_COMMANDS pattern.
|
|
524
|
+
COMMAND_ENDPOINT_EXCEPTIONS: dict[str, tuple[str, str]] = {
|
|
525
|
+
"help": ("cli_local", "reads the local Click tree and generated contract"),
|
|
526
|
+
"reasoning-diff": ("cli_local", "compares a local working-tree file with Git HEAD"),
|
|
527
|
+
"upgrade*": ("external_service", "checks and installs a CLI release from the package service"),
|
|
528
|
+
"viewer": ("cli_local", "constructs the signed-in frontend URL without a Jingwei request"),
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
# ---------------------------------------------------------------------------
|
|
533
|
+
# Generated runtime contract
|
|
534
|
+
# ---------------------------------------------------------------------------
|
|
535
|
+
|
|
536
|
+
_ARTIFACT = Path(__file__).with_name("capability-contract.json")
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
@lru_cache(maxsize=1)
|
|
540
|
+
def load_capability_contract() -> dict:
|
|
541
|
+
"""Return the generated contract shipped with the CLI package."""
|
|
542
|
+
return json.loads(_ARTIFACT.read_text(encoding="utf-8"))
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
def get_command_capability(name: str) -> dict | None:
|
|
546
|
+
"""Return one exact leaf command's generated capability record."""
|
|
547
|
+
wanted = " ".join((name or "").split())
|
|
548
|
+
if not wanted:
|
|
549
|
+
return None
|
|
550
|
+
return (load_capability_contract().get("commands") or {}).get(wanted)
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def blocked_mcp_commands() -> frozenset[str]:
|
|
554
|
+
"""The top-level commands runtime MCP enforcement must reject."""
|
|
555
|
+
return frozenset(MCP_BLOCKED_COMMANDS)
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
def mcp_blocked_summary() -> str:
|
|
559
|
+
"""Stable comma-separated block list for generated/user-facing prose."""
|
|
560
|
+
return ", ".join(sorted(MCP_BLOCKED_COMMANDS))
|