current-cli 0.1.35__tar.gz → 0.1.37__tar.gz
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.
- {current_cli-0.1.35 → current_cli-0.1.37}/PKG-INFO +1 -1
- {current_cli-0.1.35 → current_cli-0.1.37}/current_cli/build.py +7 -1
- {current_cli-0.1.35 → current_cli-0.1.37}/current_cli/schema.py +4 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/current_cli/schema.yml +38 -2
- {current_cli-0.1.35 → current_cli-0.1.37}/llms.txt +19 -2
- {current_cli-0.1.35 → current_cli-0.1.37}/pyproject.toml +1 -1
- {current_cli-0.1.35 → current_cli-0.1.37}/tests/test_requests.py +34 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/.gitignore +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/README.md +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/current_cli/__init__.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/current_cli/config.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/current_cli/docs.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/current_cli/http.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/current_cli/main.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/scripts/bump_version.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/tests/__init__.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/tests/conftest.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/tests/test_auth.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/tests/test_bump_version.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/tests/test_command_tree.py +0 -0
- {current_cli-0.1.35 → current_cli-0.1.37}/tests/test_docs.py +0 -0
|
@@ -16,9 +16,14 @@ def _make_callback(op: Operation):
|
|
|
16
16
|
for param in op.path_params:
|
|
17
17
|
path = path.replace("{" + param.name + "}", str(kwargs.pop(param.name)))
|
|
18
18
|
|
|
19
|
-
params: dict[str, str] = {}
|
|
19
|
+
params: dict[str, str | list[str]] = {}
|
|
20
20
|
for param in op.query_params:
|
|
21
21
|
value = kwargs.pop(param.name, None)
|
|
22
|
+
# click gives a repeatable option an empty tuple, not None, when
|
|
23
|
+
# it is absent; treat that as "not given" so it never becomes an
|
|
24
|
+
# empty query key.
|
|
25
|
+
if param.is_array:
|
|
26
|
+
value = list(value) if value else None
|
|
22
27
|
if value is None and param.name == "workspace":
|
|
23
28
|
value = config.get("default_workspace")
|
|
24
29
|
if value is None:
|
|
@@ -48,6 +53,7 @@ def _make_command(op: Operation) -> click.Command:
|
|
|
48
53
|
click.Option(
|
|
49
54
|
[f"--{param.name.replace('_', '-')}"],
|
|
50
55
|
required=False,
|
|
56
|
+
multiple=param.is_array,
|
|
51
57
|
help=param.description or None,
|
|
52
58
|
)
|
|
53
59
|
)
|
|
@@ -21,6 +21,9 @@ class Parameter:
|
|
|
21
21
|
location: str # "path" or "query"
|
|
22
22
|
required: bool
|
|
23
23
|
description: str
|
|
24
|
+
# An array query param is sent as the repeated key the API reads with
|
|
25
|
+
# getlist (?fields=a&fields=b), so its option has to be repeatable too.
|
|
26
|
+
is_array: bool = False
|
|
24
27
|
|
|
25
28
|
|
|
26
29
|
@dataclass(frozen=True)
|
|
@@ -90,6 +93,7 @@ def extract_operations(spec: dict) -> list[Operation]:
|
|
|
90
93
|
location=raw["in"],
|
|
91
94
|
required=raw.get("required", False),
|
|
92
95
|
description=raw.get("description", ""),
|
|
96
|
+
is_array=raw.get("schema", {}).get("type") == "array",
|
|
93
97
|
)
|
|
94
98
|
if param.location == "path":
|
|
95
99
|
path_params.append(param)
|
|
@@ -1053,6 +1053,16 @@ paths:
|
|
|
1053
1053
|
definition the agent declares no inputs, so it gets the company tree
|
|
1054
1054
|
plus every project tree and decides for itself what it needs.
|
|
1055
1055
|
|
|
1056
|
+
An index, not a copy: the sandbox fetches a file's bytes only when the
|
|
1057
|
+
model reads that file. That is what lets this stay workspace-wide now
|
|
1058
|
+
that a workspace mirrors its Sitetracker documents — gigabytes of
|
|
1059
|
+
scans that ``read_file`` could only refuse, and that an attachment
|
|
1060
|
+
reads here from object storage rather than from the sandbox.
|
|
1061
|
+
|
|
1062
|
+
``truncated`` says the workspace holds more than this answer names, so
|
|
1063
|
+
the agent can tell a user "I cannot see all of your files" instead of
|
|
1064
|
+
reporting a file it was never given as one the workspace does not have.
|
|
1065
|
+
|
|
1056
1066
|
POST, for a read, because the job-token permission class reads the
|
|
1057
1067
|
workspace id out of the request body — the same contract every other
|
|
1058
1068
|
messaging-job endpoint uses.
|
|
@@ -1841,12 +1851,17 @@ paths:
|
|
|
1841
1851
|
get:
|
|
1842
1852
|
operationId: projects_projects_inventory_retrieve
|
|
1843
1853
|
description: |-
|
|
1844
|
-
Page current field values, optionally narrowed to named keys
|
|
1854
|
+
Page current field values, optionally narrowed to named keys and
|
|
1855
|
+
to projects whose values match.
|
|
1845
1856
|
|
|
1846
1857
|
The full project list serializes every field of every project —
|
|
1847
1858
|
megabytes at production scale. This page is the compact census a
|
|
1848
1859
|
chat agent can scan: identity plus the keys it asked for, no
|
|
1849
|
-
timeline, no provenance.
|
|
1860
|
+
timeline, no provenance.
|
|
1861
|
+
|
|
1862
|
+
Filter here rather than page-and-sift: a caller that reads every
|
|
1863
|
+
page and picks the matches by eye miscounts, and "total" under a
|
|
1864
|
+
filter is the count it was really after. See state.list_projects.
|
|
1850
1865
|
parameters:
|
|
1851
1866
|
- in: query
|
|
1852
1867
|
name: fields
|
|
@@ -1855,6 +1870,16 @@ paths:
|
|
|
1855
1870
|
items:
|
|
1856
1871
|
type: string
|
|
1857
1872
|
description: Field keys to keep; omit to return every current value
|
|
1873
|
+
- in: query
|
|
1874
|
+
name: filter
|
|
1875
|
+
schema:
|
|
1876
|
+
type: array
|
|
1877
|
+
items:
|
|
1878
|
+
type: string
|
|
1879
|
+
description: Keep only projects whose current value matches, as 'key:value'
|
|
1880
|
+
(for example 'status:Active'). Repeat for more fields; repeating one key
|
|
1881
|
+
accepts any of its values. An option matches by label, value, or ID. 'total'
|
|
1882
|
+
counts the matching projects.
|
|
1858
1883
|
- in: query
|
|
1859
1884
|
name: limit
|
|
1860
1885
|
schema:
|
|
@@ -1865,6 +1890,14 @@ paths:
|
|
|
1865
1890
|
schema:
|
|
1866
1891
|
type: integer
|
|
1867
1892
|
description: Number of projects to skip (default 0)
|
|
1893
|
+
- in: query
|
|
1894
|
+
name: values
|
|
1895
|
+
schema:
|
|
1896
|
+
type: string
|
|
1897
|
+
enum:
|
|
1898
|
+
- ids
|
|
1899
|
+
- labels
|
|
1900
|
+
description: Read option values as labels (default) or as option IDs
|
|
1868
1901
|
- in: query
|
|
1869
1902
|
name: workspace
|
|
1870
1903
|
schema:
|
|
@@ -4218,6 +4251,9 @@ components:
|
|
|
4218
4251
|
type: array
|
|
4219
4252
|
items:
|
|
4220
4253
|
$ref: '#/components/schemas/ManifestEntry'
|
|
4254
|
+
truncated:
|
|
4255
|
+
type: boolean
|
|
4256
|
+
default: false
|
|
4221
4257
|
required:
|
|
4222
4258
|
- files
|
|
4223
4259
|
Me:
|
|
@@ -383,6 +383,16 @@ message can turn out to be about any project, and unlike a workflow
|
|
|
383
383
|
definition the agent declares no inputs, so it gets the company tree
|
|
384
384
|
plus every project tree and decides for itself what it needs.
|
|
385
385
|
|
|
386
|
+
An index, not a copy: the sandbox fetches a file's bytes only when the
|
|
387
|
+
model reads that file. That is what lets this stay workspace-wide now
|
|
388
|
+
that a workspace mirrors its Sitetracker documents — gigabytes of
|
|
389
|
+
scans that ``read_file`` could only refuse, and that an attachment
|
|
390
|
+
reads here from object storage rather than from the sandbox.
|
|
391
|
+
|
|
392
|
+
``truncated`` says the workspace holds more than this answer names, so
|
|
393
|
+
the agent can tell a user "I cannot see all of your files" instead of
|
|
394
|
+
reporting a file it was never given as one the workspace does not have.
|
|
395
|
+
|
|
386
396
|
POST, for a read, because the job-token permission class reads the
|
|
387
397
|
workspace id out of the request body — the same contract every other
|
|
388
398
|
messaging-job endpoint uses.
|
|
@@ -617,19 +627,26 @@ Options:
|
|
|
617
627
|
|
|
618
628
|
### current projects inventory retrieve
|
|
619
629
|
|
|
620
|
-
Page current field values, optionally narrowed to named keys
|
|
630
|
+
Page current field values, optionally narrowed to named keys and
|
|
631
|
+
to projects whose values match.
|
|
621
632
|
|
|
622
633
|
The full project list serializes every field of every project —
|
|
623
634
|
megabytes at production scale. This page is the compact census a
|
|
624
635
|
chat agent can scan: identity plus the keys it asked for, no
|
|
625
|
-
timeline, no provenance.
|
|
636
|
+
timeline, no provenance.
|
|
637
|
+
|
|
638
|
+
Filter here rather than page-and-sift: a caller that reads every
|
|
639
|
+
page and picks the matches by eye miscounts, and "total" under a
|
|
640
|
+
filter is the count it was really after. See state.list_projects.
|
|
626
641
|
|
|
627
642
|
GET /api/projects/projects/inventory/
|
|
628
643
|
|
|
629
644
|
Options:
|
|
630
645
|
- `--fields` - Field keys to keep; omit to return every current value
|
|
646
|
+
- `--filter` - Keep only projects whose current value matches, as 'key:value' (for example 'status:Active'). Repeat for more fields; repeating one key accepts any of its values. An option matches by label, value, or ID. 'total' counts the matching projects.
|
|
631
647
|
- `--limit` - Max projects per page (default 100, max 200)
|
|
632
648
|
- `--offset` - Number of projects to skip (default 0)
|
|
649
|
+
- `--values` - Read option values as labels (default) or as option IDs
|
|
633
650
|
- `--workspace` - Workspace UUID
|
|
634
651
|
|
|
635
652
|
### current projects list
|
|
@@ -60,6 +60,40 @@ def test_create_sends_json_body(cli, runner, transport_factory):
|
|
|
60
60
|
assert json.loads(request.content) == {"name": "Order beams", "workspace": "w1"}
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
def test_array_query_param_repeats(cli, runner, transport_factory):
|
|
64
|
+
"""An array param must repeat its key, the shape the API reads with
|
|
65
|
+
getlist — one AND-ed filter per --filter."""
|
|
66
|
+
transport = transport_factory(ok({}))
|
|
67
|
+
|
|
68
|
+
result = runner.invoke(
|
|
69
|
+
cli,
|
|
70
|
+
[
|
|
71
|
+
"projects",
|
|
72
|
+
"inventory",
|
|
73
|
+
"retrieve",
|
|
74
|
+
"--workspace",
|
|
75
|
+
"ws-uuid",
|
|
76
|
+
"--filter",
|
|
77
|
+
"status:Active",
|
|
78
|
+
"--filter",
|
|
79
|
+
"site_type:Garden Style",
|
|
80
|
+
],
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
assert result.exit_code == 0, result.output
|
|
84
|
+
params = transport.requests[0].url.params
|
|
85
|
+
assert params.get_list("filter") == ["status:Active", "site_type:Garden Style"]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_array_query_param_is_absent_when_not_given(cli, runner, transport_factory):
|
|
89
|
+
transport = transport_factory(ok({}))
|
|
90
|
+
|
|
91
|
+
result = runner.invoke(cli, ["projects", "inventory", "retrieve", "--workspace", "ws-uuid"])
|
|
92
|
+
|
|
93
|
+
assert result.exit_code == 0, result.output
|
|
94
|
+
assert "filter" not in transport.requests[0].url.params
|
|
95
|
+
|
|
96
|
+
|
|
63
97
|
def test_default_workspace_fallback(cli, runner, transport_factory):
|
|
64
98
|
config.set_value("default_workspace", "default-ws")
|
|
65
99
|
transport = transport_factory(ok({}))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|