deepflow-openagent-cli 0.1.7__tar.gz → 0.1.8__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.
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/PKG-INFO +91 -1
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/README.md +90 -0
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/pyproject.toml +1 -1
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli/__init__.py +1 -1
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli/cli.py +92 -0
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli.egg-info/PKG-INFO +91 -1
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/tests/test_cloudpc_cli.py +100 -0
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/setup.cfg +0 -0
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli/__main__.py +0 -0
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli.egg-info/SOURCES.txt +0 -0
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli.egg-info/dependency_links.txt +0 -0
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli.egg-info/entry_points.txt +0 -0
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli.egg-info/requires.txt +0 -0
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli.egg-info/top_level.txt +0 -0
- {deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/tests/test_cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepflow-openagent-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: Command-line client for OpenAgent OpenAPI (agents, conversations, SSE chat, tools, channels, knowledge bases).
|
|
5
5
|
Author: DeepFlow AI
|
|
6
6
|
Project-URL: Repository, https://github.com/DeepFlowAI/OpenAgent
|
|
@@ -280,3 +280,93 @@ After installation or Agent edits, use `cloudpc versions save` and optionally
|
|
|
280
280
|
`versions publish` to preserve and publish the environment. Deploy the updated
|
|
281
281
|
OpenAgent backend, cloudpc VM service, and bridge bundle together; update the CLI
|
|
282
282
|
package as well. No database migration is required.
|
|
283
|
+
|
|
284
|
+
### Cloud PC channels
|
|
285
|
+
|
|
286
|
+
Cloud PC channel settings use `cloudpc channels`, separately from Agent settings
|
|
287
|
+
(`cloudpc config`) and Web SDK channels (`channels`). These commands require an
|
|
288
|
+
API key with `config` scope and Cloud PC enabled for the tenant. The backend must
|
|
289
|
+
also include support for API key authentication on `/api/v1/cloudpc/channels`;
|
|
290
|
+
older backends accept administrator sessions only.
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
deepflow_openagent_cli cloudpc channels list --page 1 --per-page 20
|
|
294
|
+
deepflow_openagent_cli cloudpc channels create --name "Cloud workspace"
|
|
295
|
+
deepflow_openagent_cli cloudpc channels agent-options
|
|
296
|
+
deepflow_openagent_cli cloudpc channels get 7
|
|
297
|
+
deepflow_openagent_cli docs show cloudpc.channels.update --json
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Update uses the existing PUT replacement contract. Read the current channel
|
|
301
|
+
first and prepare `channel.json` with the complete name, description, ordered
|
|
302
|
+
`agent_ids` and `appearance`. Convert the returned `bindings` to their `id`
|
|
303
|
+
values; the GET response is not itself an update payload.
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
{
|
|
307
|
+
"name": "Cloud workspace",
|
|
308
|
+
"description": "Team assistant",
|
|
309
|
+
"agent_ids": [123, 456],
|
|
310
|
+
"appearance": {
|
|
311
|
+
"pageTitle": "Workspace",
|
|
312
|
+
"title": "Assistant",
|
|
313
|
+
"embedButtonBgColor": "#18181B",
|
|
314
|
+
"embedButtonIconColor": "#FFFFFF",
|
|
315
|
+
"userMessageStyle": {
|
|
316
|
+
"backgroundColor": "#1A1A1A",
|
|
317
|
+
"borderColor": "#CCCCCC",
|
|
318
|
+
"textColor": "#FFFFFF",
|
|
319
|
+
"borderRadius": {
|
|
320
|
+
"topLeft": 14,
|
|
321
|
+
"topRight": 14,
|
|
322
|
+
"bottomLeft": 14,
|
|
323
|
+
"bottomRight": 4
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
"require_auth": false,
|
|
328
|
+
"file_upload": {
|
|
329
|
+
"enabled": true,
|
|
330
|
+
"allowed_extensions": [".pdf", ".txt"]
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
deepflow_openagent_cli cloudpc channels update 7 --json-file ./channel.json
|
|
337
|
+
deepflow_openagent_cli cloudpc channels get 7
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
`--json` also accepts an inline JSON object. `name` is required; omitted
|
|
341
|
+
`description`, `agent_ids` and `appearance` reset to null, an empty list and
|
|
342
|
+
empty appearance respectively. Omitted/null `require_auth` and `file_upload`
|
|
343
|
+
preserve the current values. Enabling uploads requires at least one extension.
|
|
344
|
+
Only Cloud PCs belonging to the current tenant can be bound (up to 20).
|
|
345
|
+
|
|
346
|
+
User message styles are configured under `appearance.userMessageStyle` in the
|
|
347
|
+
same update payload. They apply to both main and follow-up messages, including
|
|
348
|
+
history and SDK embeds, after opening or refreshing the channel. They do not
|
|
349
|
+
change Agent replies or the admin workbench.
|
|
350
|
+
|
|
351
|
+
| Field | Value | Reset behavior |
|
|
352
|
+
| --- | --- | --- |
|
|
353
|
+
| `backgroundColor` | `#RRGGBB` | Empty string, null or omission restores each bubble's default |
|
|
354
|
+
| `borderColor` | `#RRGGBB`, rendered as a 1px solid border | Empty string, null or omission removes the border |
|
|
355
|
+
| `textColor` | `#RRGGBB`, also applied to the follow-up label | Empty string, null or omission restores the default |
|
|
356
|
+
| `borderRadius` | Object containing all four integer corners, 0–100 px | Null or omission restores each bubble's default |
|
|
357
|
+
|
|
358
|
+
The server trims and uppercases colors. Radius keys are `topLeft`, `topRight`,
|
|
359
|
+
`bottomLeft`, and `bottomRight`; partial groups, negative/fractional/out-of-range
|
|
360
|
+
values, strings and booleans are rejected with HTTP 422 (CLI exits nonzero).
|
|
361
|
+
To clear only one override, set that field to null while retaining the other
|
|
362
|
+
settings. To reset all user message styles, set `"userMessageStyle": null` in
|
|
363
|
+
the complete `channel.json`, then run the same update command. The outer PUT
|
|
364
|
+
still replaces `appearance` and bindings: keep all unrelated settings from the
|
|
365
|
+
GET response in the payload. Reading the channel returns the saved style under
|
|
366
|
+
`appearance.userMessageStyle`.
|
|
367
|
+
|
|
368
|
+
`deepflow_openagent_cli cloudpc channels delete 7` deletes the channel and
|
|
369
|
+
destroys its instances. The server entry point
|
|
370
|
+
`python -m app.openapi_cli cloudpc channels ...` supports the same commands.
|
|
371
|
+
This feature requires updating the backend and CLI; no database migration or
|
|
372
|
+
Cloud PC sandbox image update is needed.
|
|
@@ -259,3 +259,93 @@ After installation or Agent edits, use `cloudpc versions save` and optionally
|
|
|
259
259
|
`versions publish` to preserve and publish the environment. Deploy the updated
|
|
260
260
|
OpenAgent backend, cloudpc VM service, and bridge bundle together; update the CLI
|
|
261
261
|
package as well. No database migration is required.
|
|
262
|
+
|
|
263
|
+
### Cloud PC channels
|
|
264
|
+
|
|
265
|
+
Cloud PC channel settings use `cloudpc channels`, separately from Agent settings
|
|
266
|
+
(`cloudpc config`) and Web SDK channels (`channels`). These commands require an
|
|
267
|
+
API key with `config` scope and Cloud PC enabled for the tenant. The backend must
|
|
268
|
+
also include support for API key authentication on `/api/v1/cloudpc/channels`;
|
|
269
|
+
older backends accept administrator sessions only.
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
deepflow_openagent_cli cloudpc channels list --page 1 --per-page 20
|
|
273
|
+
deepflow_openagent_cli cloudpc channels create --name "Cloud workspace"
|
|
274
|
+
deepflow_openagent_cli cloudpc channels agent-options
|
|
275
|
+
deepflow_openagent_cli cloudpc channels get 7
|
|
276
|
+
deepflow_openagent_cli docs show cloudpc.channels.update --json
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Update uses the existing PUT replacement contract. Read the current channel
|
|
280
|
+
first and prepare `channel.json` with the complete name, description, ordered
|
|
281
|
+
`agent_ids` and `appearance`. Convert the returned `bindings` to their `id`
|
|
282
|
+
values; the GET response is not itself an update payload.
|
|
283
|
+
|
|
284
|
+
```json
|
|
285
|
+
{
|
|
286
|
+
"name": "Cloud workspace",
|
|
287
|
+
"description": "Team assistant",
|
|
288
|
+
"agent_ids": [123, 456],
|
|
289
|
+
"appearance": {
|
|
290
|
+
"pageTitle": "Workspace",
|
|
291
|
+
"title": "Assistant",
|
|
292
|
+
"embedButtonBgColor": "#18181B",
|
|
293
|
+
"embedButtonIconColor": "#FFFFFF",
|
|
294
|
+
"userMessageStyle": {
|
|
295
|
+
"backgroundColor": "#1A1A1A",
|
|
296
|
+
"borderColor": "#CCCCCC",
|
|
297
|
+
"textColor": "#FFFFFF",
|
|
298
|
+
"borderRadius": {
|
|
299
|
+
"topLeft": 14,
|
|
300
|
+
"topRight": 14,
|
|
301
|
+
"bottomLeft": 14,
|
|
302
|
+
"bottomRight": 4
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
"require_auth": false,
|
|
307
|
+
"file_upload": {
|
|
308
|
+
"enabled": true,
|
|
309
|
+
"allowed_extensions": [".pdf", ".txt"]
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
deepflow_openagent_cli cloudpc channels update 7 --json-file ./channel.json
|
|
316
|
+
deepflow_openagent_cli cloudpc channels get 7
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
`--json` also accepts an inline JSON object. `name` is required; omitted
|
|
320
|
+
`description`, `agent_ids` and `appearance` reset to null, an empty list and
|
|
321
|
+
empty appearance respectively. Omitted/null `require_auth` and `file_upload`
|
|
322
|
+
preserve the current values. Enabling uploads requires at least one extension.
|
|
323
|
+
Only Cloud PCs belonging to the current tenant can be bound (up to 20).
|
|
324
|
+
|
|
325
|
+
User message styles are configured under `appearance.userMessageStyle` in the
|
|
326
|
+
same update payload. They apply to both main and follow-up messages, including
|
|
327
|
+
history and SDK embeds, after opening or refreshing the channel. They do not
|
|
328
|
+
change Agent replies or the admin workbench.
|
|
329
|
+
|
|
330
|
+
| Field | Value | Reset behavior |
|
|
331
|
+
| --- | --- | --- |
|
|
332
|
+
| `backgroundColor` | `#RRGGBB` | Empty string, null or omission restores each bubble's default |
|
|
333
|
+
| `borderColor` | `#RRGGBB`, rendered as a 1px solid border | Empty string, null or omission removes the border |
|
|
334
|
+
| `textColor` | `#RRGGBB`, also applied to the follow-up label | Empty string, null or omission restores the default |
|
|
335
|
+
| `borderRadius` | Object containing all four integer corners, 0–100 px | Null or omission restores each bubble's default |
|
|
336
|
+
|
|
337
|
+
The server trims and uppercases colors. Radius keys are `topLeft`, `topRight`,
|
|
338
|
+
`bottomLeft`, and `bottomRight`; partial groups, negative/fractional/out-of-range
|
|
339
|
+
values, strings and booleans are rejected with HTTP 422 (CLI exits nonzero).
|
|
340
|
+
To clear only one override, set that field to null while retaining the other
|
|
341
|
+
settings. To reset all user message styles, set `"userMessageStyle": null` in
|
|
342
|
+
the complete `channel.json`, then run the same update command. The outer PUT
|
|
343
|
+
still replaces `appearance` and bindings: keep all unrelated settings from the
|
|
344
|
+
GET response in the payload. Reading the channel returns the saved style under
|
|
345
|
+
`appearance.userMessageStyle`.
|
|
346
|
+
|
|
347
|
+
`deepflow_openagent_cli cloudpc channels delete 7` deletes the channel and
|
|
348
|
+
destroys its instances. The server entry point
|
|
349
|
+
`python -m app.openapi_cli cloudpc channels ...` supports the same commands.
|
|
350
|
+
This feature requires updating the backend and CLI; no database migration or
|
|
351
|
+
Cloud PC sandbox image update is needed.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "deepflow-openagent-cli"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.8"
|
|
8
8
|
description = "Command-line client for OpenAgent OpenAPI (agents, conversations, SSE chat, tools, channels, knowledge bases)."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
{deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli/cli.py
RENAMED
|
@@ -130,6 +130,61 @@ def _param(name: str, type_: str, required: bool, description: str) -> ParamDoc:
|
|
|
130
130
|
|
|
131
131
|
|
|
132
132
|
ENDPOINTS: tuple[EndpointDoc, ...] = (
|
|
133
|
+
EndpointDoc(
|
|
134
|
+
key="cloudpc.channels.list", method="GET", path="/api/v1/cloudpc/channels", scope="config",
|
|
135
|
+
summary="List Cloud PC channels for the current tenant.",
|
|
136
|
+
query_params=[_param("page", "integer", False, "Page number (default 1)."), _param("per_page", "integer", False, "Page size, 1-100 (default 20).")],
|
|
137
|
+
response="CloudPcChannelListResponse.",
|
|
138
|
+
example="deepflow_openagent_cli cloudpc channels list --page 1 --per-page 20",
|
|
139
|
+
),
|
|
140
|
+
EndpointDoc(
|
|
141
|
+
key="cloudpc.channels.create", method="POST", path="/api/v1/cloudpc/channels", scope="config",
|
|
142
|
+
summary="Create a Cloud PC channel; use update to configure bindings and appearance.",
|
|
143
|
+
body_fields=[_param("name", "string", True, "Channel name, 1-64 characters."), _param("description", "string", False, "Description, max 500 characters.")],
|
|
144
|
+
response="CloudPcChannelDetail, HTTP 201.",
|
|
145
|
+
example='deepflow_openagent_cli cloudpc channels create --name "Cloud workspace"',
|
|
146
|
+
),
|
|
147
|
+
EndpointDoc(
|
|
148
|
+
key="cloudpc.channels.agent_options", method="GET", path="/api/v1/cloudpc/channels/agent-options", scope="config",
|
|
149
|
+
summary="List enabled Cloud PCs available for binding, including unpublished ones.",
|
|
150
|
+
response="CloudPcAgentOptionList: items with id, name, description, version and status.",
|
|
151
|
+
example="deepflow_openagent_cli cloudpc channels agent-options",
|
|
152
|
+
),
|
|
153
|
+
EndpointDoc(
|
|
154
|
+
key="cloudpc.channels.get", method="GET", path="/api/v1/cloudpc/channels/{channel_id}", scope="config",
|
|
155
|
+
summary="Get Cloud PC channel settings and ordered bindings.",
|
|
156
|
+
path_params=[_param("channel_id", "integer", True, "Cloud PC channel ID.")],
|
|
157
|
+
response="CloudPcChannelDetail: id, name, description, token, appearance, bindings, require_auth, has_secret_key, file_upload and timestamps.",
|
|
158
|
+
example="deepflow_openagent_cli cloudpc channels get 1",
|
|
159
|
+
),
|
|
160
|
+
EndpointDoc(
|
|
161
|
+
key="cloudpc.channels.update", method="PUT", path="/api/v1/cloudpc/channels/{channel_id}", scope="config",
|
|
162
|
+
summary="Replace channel name, description, bindings and appearance; omitted require_auth/file_upload are preserved.",
|
|
163
|
+
path_params=[_param("channel_id", "integer", True, "Cloud PC channel ID.")],
|
|
164
|
+
body_fields=[
|
|
165
|
+
_param("name", "string", True, "Channel name, 1-64 characters."),
|
|
166
|
+
_param("description", "string", False, "Description, max 500 characters; omitted resets to null."),
|
|
167
|
+
_param("agent_ids", "array", False, "Complete ordered list of Cloud PC Agent IDs, max 20 unique IDs; omitted clears bindings. Convert GET bindings to their id values."),
|
|
168
|
+
_param("appearance", "object", False, "Complete appearance: favicon, pageTitle, logo, title, embedButtonBgColor, embedButtonIconColor, userMessageStyle; omitted clears appearance. Titles max 32 characters; colors #RRGGBB."),
|
|
169
|
+
_param("appearance.userMessageStyle", "object|null", False, "Overrides main and follow-up user bubbles in this channel, including history and embeds. Omitted/null restores defaults; other appearance fields must still be supplied."),
|
|
170
|
+
_param("appearance.userMessageStyle.backgroundColor", "string|null", False, "Background #RRGGBB. Server trims and uppercases; empty string/null restores each bubble's default."),
|
|
171
|
+
_param("appearance.userMessageStyle.borderColor", "string|null", False, "Border #RRGGBB; 1px solid when set. Empty string/null removes the border."),
|
|
172
|
+
_param("appearance.userMessageStyle.textColor", "string|null", False, "Text #RRGGBB, including the follow-up label. Empty string/null restores the default."),
|
|
173
|
+
_param("appearance.userMessageStyle.borderRadius", "object|null", False, "All four corners are required when set: topLeft, topRight, bottomLeft, bottomRight, each an integer 0-100 px. Null restores each bubble's default; partial groups, strings, floats and booleans are rejected."),
|
|
174
|
+
_param("require_auth", "boolean", False, "Require signed visitor authentication; omitted/null preserves current value."),
|
|
175
|
+
_param("file_upload", "object", False, "enabled and allowed_extensions; enabled uploads require at least one extension. Omitted/null preserves current value."),
|
|
176
|
+
],
|
|
177
|
+
response="CloudPcChannelDetail.",
|
|
178
|
+
errors=["400 invalid bindings or duplicate name", "401 invalid API key", "403 config scope missing, non-admin session or Cloud PC disabled", "404 channel not found in current tenant", "422 validation error"],
|
|
179
|
+
example="deepflow_openagent_cli cloudpc channels update 1 --json-file channel.json",
|
|
180
|
+
),
|
|
181
|
+
EndpointDoc(
|
|
182
|
+
key="cloudpc.channels.delete", method="DELETE", path="/api/v1/cloudpc/channels/{channel_id}", scope="config",
|
|
183
|
+
summary="Delete a Cloud PC channel and destroy its instances.",
|
|
184
|
+
path_params=[_param("channel_id", "integer", True, "Cloud PC channel ID.")],
|
|
185
|
+
response="Deletion message.",
|
|
186
|
+
example="deepflow_openagent_cli cloudpc channels delete 1",
|
|
187
|
+
),
|
|
133
188
|
EndpointDoc(
|
|
134
189
|
key="cloudpc.files.upload", method="POST",
|
|
135
190
|
path="/api/v1/cloudpc/agents/{agent_id}/dev-sandbox/files/upload", scope="config",
|
|
@@ -1925,9 +1980,32 @@ def handle_cloudpc_chat(args: argparse.Namespace) -> int:
|
|
|
1925
1980
|
raise
|
|
1926
1981
|
|
|
1927
1982
|
|
|
1983
|
+
def handle_cloudpc_channels(args: argparse.Namespace) -> int:
|
|
1984
|
+
"""Manage Cloud PC channels through their dedicated API."""
|
|
1985
|
+
action = args.cloudpc_action
|
|
1986
|
+
endpoint = f"cloudpc.channels.{action.replace('-', '_')}"
|
|
1987
|
+
if action == "list":
|
|
1988
|
+
return run_request(args, endpoint, query={"page": args.page, "per_page": args.per_page})
|
|
1989
|
+
if action == "agent-options":
|
|
1990
|
+
return run_request(args, endpoint)
|
|
1991
|
+
if action == "create":
|
|
1992
|
+
return run_request(args, endpoint, body={"name": args.name, "description": args.description})
|
|
1993
|
+
body = None
|
|
1994
|
+
if action == "update":
|
|
1995
|
+
try:
|
|
1996
|
+
body = merge_payload(args)
|
|
1997
|
+
except (OSError, UnicodeError) as exc:
|
|
1998
|
+
raise CliError(f"Cannot read channel configuration file: {exc}") from exc
|
|
1999
|
+
if not body.get("name"):
|
|
2000
|
+
raise CliError("Channel update requires name in --json or --json-file.")
|
|
2001
|
+
return run_request(args, endpoint, {"channel_id": args.channel_id}, body=body)
|
|
2002
|
+
|
|
2003
|
+
|
|
1928
2004
|
def handle_cloudpc(args: argparse.Namespace) -> int:
|
|
1929
2005
|
"""Manage Cloud PC configuration, development files and saved versions."""
|
|
1930
2006
|
group = args.cloudpc_group
|
|
2007
|
+
if group == "channels":
|
|
2008
|
+
return handle_cloudpc_channels(args)
|
|
1931
2009
|
if group == "capability":
|
|
1932
2010
|
return run_request(args, "cloudpc.capability")
|
|
1933
2011
|
if group == "create":
|
|
@@ -2139,6 +2217,20 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
2139
2217
|
|
|
2140
2218
|
cloudpc = subparsers.add_parser("cloudpc", help="Cloud PC management (requires config scope).")
|
|
2141
2219
|
cloudpc_sub = cloudpc.add_subparsers(dest="cloudpc_group", required=True)
|
|
2220
|
+
cloudpc_channels = cloudpc_sub.add_parser("channels", help="Cloud PC channel configuration.").add_subparsers(dest="cloudpc_action", required=True)
|
|
2221
|
+
channel_list = cloudpc_channels.add_parser("list")
|
|
2222
|
+
channel_list.add_argument("--page", type=int)
|
|
2223
|
+
channel_list.add_argument("--per-page", type=int)
|
|
2224
|
+
cloudpc_channels.add_parser("agent-options")
|
|
2225
|
+
channel_create = cloudpc_channels.add_parser("create")
|
|
2226
|
+
channel_create.add_argument("--name", required=True)
|
|
2227
|
+
channel_create.add_argument("--description")
|
|
2228
|
+
for action in ("get", "delete"):
|
|
2229
|
+
cloudpc_channels.add_parser(action).add_argument("channel_id", type=int)
|
|
2230
|
+
channel_update_help = "Replace name/description/bindings/appearance; omitted bindings/appearance are cleared. Omitted require_auth/file_upload are preserved. Set appearance.userMessageStyle in --json or --json-file for user bubble colors and four-corner radius; null restores defaults. See docs show cloudpc.channels.update."
|
|
2231
|
+
channel_update = cloudpc_channels.add_parser("update", help=channel_update_help, description=channel_update_help)
|
|
2232
|
+
channel_update.add_argument("channel_id", type=int)
|
|
2233
|
+
add_json_args(channel_update)
|
|
2142
2234
|
cloudpc_sub.add_parser("capability")
|
|
2143
2235
|
cloudpc_create = cloudpc_sub.add_parser("create")
|
|
2144
2236
|
cloudpc_create.add_argument("--name", required=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepflow-openagent-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: Command-line client for OpenAgent OpenAPI (agents, conversations, SSE chat, tools, channels, knowledge bases).
|
|
5
5
|
Author: DeepFlow AI
|
|
6
6
|
Project-URL: Repository, https://github.com/DeepFlowAI/OpenAgent
|
|
@@ -280,3 +280,93 @@ After installation or Agent edits, use `cloudpc versions save` and optionally
|
|
|
280
280
|
`versions publish` to preserve and publish the environment. Deploy the updated
|
|
281
281
|
OpenAgent backend, cloudpc VM service, and bridge bundle together; update the CLI
|
|
282
282
|
package as well. No database migration is required.
|
|
283
|
+
|
|
284
|
+
### Cloud PC channels
|
|
285
|
+
|
|
286
|
+
Cloud PC channel settings use `cloudpc channels`, separately from Agent settings
|
|
287
|
+
(`cloudpc config`) and Web SDK channels (`channels`). These commands require an
|
|
288
|
+
API key with `config` scope and Cloud PC enabled for the tenant. The backend must
|
|
289
|
+
also include support for API key authentication on `/api/v1/cloudpc/channels`;
|
|
290
|
+
older backends accept administrator sessions only.
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
deepflow_openagent_cli cloudpc channels list --page 1 --per-page 20
|
|
294
|
+
deepflow_openagent_cli cloudpc channels create --name "Cloud workspace"
|
|
295
|
+
deepflow_openagent_cli cloudpc channels agent-options
|
|
296
|
+
deepflow_openagent_cli cloudpc channels get 7
|
|
297
|
+
deepflow_openagent_cli docs show cloudpc.channels.update --json
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Update uses the existing PUT replacement contract. Read the current channel
|
|
301
|
+
first and prepare `channel.json` with the complete name, description, ordered
|
|
302
|
+
`agent_ids` and `appearance`. Convert the returned `bindings` to their `id`
|
|
303
|
+
values; the GET response is not itself an update payload.
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
{
|
|
307
|
+
"name": "Cloud workspace",
|
|
308
|
+
"description": "Team assistant",
|
|
309
|
+
"agent_ids": [123, 456],
|
|
310
|
+
"appearance": {
|
|
311
|
+
"pageTitle": "Workspace",
|
|
312
|
+
"title": "Assistant",
|
|
313
|
+
"embedButtonBgColor": "#18181B",
|
|
314
|
+
"embedButtonIconColor": "#FFFFFF",
|
|
315
|
+
"userMessageStyle": {
|
|
316
|
+
"backgroundColor": "#1A1A1A",
|
|
317
|
+
"borderColor": "#CCCCCC",
|
|
318
|
+
"textColor": "#FFFFFF",
|
|
319
|
+
"borderRadius": {
|
|
320
|
+
"topLeft": 14,
|
|
321
|
+
"topRight": 14,
|
|
322
|
+
"bottomLeft": 14,
|
|
323
|
+
"bottomRight": 4
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
"require_auth": false,
|
|
328
|
+
"file_upload": {
|
|
329
|
+
"enabled": true,
|
|
330
|
+
"allowed_extensions": [".pdf", ".txt"]
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
deepflow_openagent_cli cloudpc channels update 7 --json-file ./channel.json
|
|
337
|
+
deepflow_openagent_cli cloudpc channels get 7
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
`--json` also accepts an inline JSON object. `name` is required; omitted
|
|
341
|
+
`description`, `agent_ids` and `appearance` reset to null, an empty list and
|
|
342
|
+
empty appearance respectively. Omitted/null `require_auth` and `file_upload`
|
|
343
|
+
preserve the current values. Enabling uploads requires at least one extension.
|
|
344
|
+
Only Cloud PCs belonging to the current tenant can be bound (up to 20).
|
|
345
|
+
|
|
346
|
+
User message styles are configured under `appearance.userMessageStyle` in the
|
|
347
|
+
same update payload. They apply to both main and follow-up messages, including
|
|
348
|
+
history and SDK embeds, after opening or refreshing the channel. They do not
|
|
349
|
+
change Agent replies or the admin workbench.
|
|
350
|
+
|
|
351
|
+
| Field | Value | Reset behavior |
|
|
352
|
+
| --- | --- | --- |
|
|
353
|
+
| `backgroundColor` | `#RRGGBB` | Empty string, null or omission restores each bubble's default |
|
|
354
|
+
| `borderColor` | `#RRGGBB`, rendered as a 1px solid border | Empty string, null or omission removes the border |
|
|
355
|
+
| `textColor` | `#RRGGBB`, also applied to the follow-up label | Empty string, null or omission restores the default |
|
|
356
|
+
| `borderRadius` | Object containing all four integer corners, 0–100 px | Null or omission restores each bubble's default |
|
|
357
|
+
|
|
358
|
+
The server trims and uppercases colors. Radius keys are `topLeft`, `topRight`,
|
|
359
|
+
`bottomLeft`, and `bottomRight`; partial groups, negative/fractional/out-of-range
|
|
360
|
+
values, strings and booleans are rejected with HTTP 422 (CLI exits nonzero).
|
|
361
|
+
To clear only one override, set that field to null while retaining the other
|
|
362
|
+
settings. To reset all user message styles, set `"userMessageStyle": null` in
|
|
363
|
+
the complete `channel.json`, then run the same update command. The outer PUT
|
|
364
|
+
still replaces `appearance` and bindings: keep all unrelated settings from the
|
|
365
|
+
GET response in the payload. Reading the channel returns the saved style under
|
|
366
|
+
`appearance.userMessageStyle`.
|
|
367
|
+
|
|
368
|
+
`deepflow_openagent_cli cloudpc channels delete 7` deletes the channel and
|
|
369
|
+
destroys its instances. The server entry point
|
|
370
|
+
`python -m app.openapi_cli cloudpc channels ...` supports the same commands.
|
|
371
|
+
This feature requires updating the backend and CLI; no database migration or
|
|
372
|
+
Cloud PC sandbox image update is needed.
|
|
@@ -44,6 +44,12 @@ def run(cli, *args):
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
@pytest.mark.parametrize(("arguments", "method", "suffix", "body"), [
|
|
47
|
+
(["channels", "list", "--page", "2", "--per-page", "5"], "GET", "/channels?page=2&per_page=5", None),
|
|
48
|
+
(["channels", "create", "--name", "渠道", "--description", "Demo"], "POST", "/channels", {"name": "渠道", "description": "Demo"}),
|
|
49
|
+
(["channels", "agent-options"], "GET", "/channels/agent-options", None),
|
|
50
|
+
(["channels", "get", "7"], "GET", "/channels/7", None),
|
|
51
|
+
(["channels", "update", "7", "--json", '{"name":"渠道","agent_ids":[3,2],"appearance":{"title":"助手"},"require_auth":false,"file_upload":{"enabled":true,"allowed_extensions":[".pdf"]}}'], "PUT", "/channels/7", {"name": "渠道", "agent_ids": [3, 2], "appearance": {"title": "助手"}, "require_auth": False, "file_upload": {"enabled": True, "allowed_extensions": [".pdf"]}}),
|
|
52
|
+
(["channels", "delete", "7"], "DELETE", "/channels/7", None),
|
|
47
53
|
(["capability"], "GET", "/capability", None),
|
|
48
54
|
(["create", "--name", "Test"], "POST", "/agents", {"name": "Test", "description": None}),
|
|
49
55
|
(["config", "get", "7"], "GET", "/agents/7/config", None),
|
|
@@ -79,6 +85,100 @@ def test_agents_kind_filter(cli, transport):
|
|
|
79
85
|
assert "kind=cloudpc" in calls[0][0].full_url
|
|
80
86
|
|
|
81
87
|
|
|
88
|
+
def test_channel_update_from_file(cli, transport, tmp_path):
|
|
89
|
+
payload = {"name": "渠道", "description": None, "agent_ids": [], "appearance": {}}
|
|
90
|
+
source = tmp_path / "channel.json"
|
|
91
|
+
source.write_text(json.dumps(payload), encoding="utf-8")
|
|
92
|
+
assert run(cli, "cloudpc", "channels", "update", "7", "--json-file", str(source)) == 0
|
|
93
|
+
calls, _ = transport
|
|
94
|
+
assert len(calls) == 1
|
|
95
|
+
assert json.loads(calls[0][0].data) == payload
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@pytest.mark.parametrize("payload", ["{}", "[]", "{invalid"])
|
|
99
|
+
def test_invalid_channel_update_does_not_send_request(cli, transport, payload):
|
|
100
|
+
assert run(cli, "cloudpc", "channels", "update", "7", "--json", payload) == 1
|
|
101
|
+
assert transport[0] == []
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_missing_channel_file_has_clean_error(cli, transport, tmp_path, capsys):
|
|
105
|
+
assert run(cli, "cloudpc", "channels", "update", "7", "--json-file", str(tmp_path / "missing.json")) == 1
|
|
106
|
+
assert transport[0] == []
|
|
107
|
+
assert "Cannot read channel configuration file" in capsys.readouterr().err
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_channel_docs_describe_replacement(cli, capsys):
|
|
111
|
+
assert cli.main(["docs", "show", "cloudpc.channels.update", "--json"]) == 0
|
|
112
|
+
doc = json.loads(capsys.readouterr().out)
|
|
113
|
+
assert doc["scope"] == "config"
|
|
114
|
+
assert doc["path"] == "/api/v1/cloudpc/channels/{channel_id}"
|
|
115
|
+
fields = {field["name"]: field for field in doc["body_fields"]}
|
|
116
|
+
assert fields["name"]["required"]
|
|
117
|
+
assert "omitted clears" in fields["agent_ids"]["description"]
|
|
118
|
+
assert "preserves" in fields["file_upload"]["description"]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@pytest.mark.parametrize("source", ["--json", "--json-file"])
|
|
122
|
+
@pytest.mark.parametrize("style", [
|
|
123
|
+
{"backgroundColor": "#123456", "borderColor": "#ABCDEF", "textColor": "#FFFFFF",
|
|
124
|
+
"borderRadius": {"topLeft": 0, "topRight": 100, "bottomLeft": 12, "bottomRight": 4}},
|
|
125
|
+
{"textColor": " #aabbcc "},
|
|
126
|
+
{"backgroundColor": "#123456", "borderColor": None, "textColor": "", "borderRadius": None},
|
|
127
|
+
None,
|
|
128
|
+
])
|
|
129
|
+
def test_channel_message_style_update_payload(cli, transport, tmp_path, source, style):
|
|
130
|
+
payload = {
|
|
131
|
+
"name": "Workspace", "description": "Keep", "agent_ids": [3, 2],
|
|
132
|
+
"appearance": {"title": "Assistant", "embedButtonBgColor": "#1A1A1A", "userMessageStyle": style},
|
|
133
|
+
"require_auth": True, "file_upload": {"enabled": True, "allowed_extensions": [".pdf"]},
|
|
134
|
+
}
|
|
135
|
+
value = json.dumps(payload)
|
|
136
|
+
if source == "--json-file":
|
|
137
|
+
path = tmp_path / "channel.json"
|
|
138
|
+
path.write_text(value, encoding="utf-8")
|
|
139
|
+
value = str(path)
|
|
140
|
+
assert run(cli, "cloudpc", "channels", "update", "7", source, value) == 0
|
|
141
|
+
calls, _ = transport
|
|
142
|
+
assert len(calls) == 1
|
|
143
|
+
assert calls[0][0].method == "PUT"
|
|
144
|
+
assert json.loads(calls[0][0].data) == payload
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_channel_message_style_read(cli, transport, capsys):
|
|
148
|
+
detail = {"id": 7, "appearance": {"userMessageStyle": {"textColor": "#AABBCC", "borderRadius": None}}}
|
|
149
|
+
transport[1]["http://test/api/v1/cloudpc/channels/7"] = json.dumps(detail).encode()
|
|
150
|
+
assert run(cli, "cloudpc", "channels", "get", "7") == 0
|
|
151
|
+
assert json.loads(capsys.readouterr().out) == detail
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def test_channel_message_style_validation_failure_is_reported_without_retry(cli, transport, capsys):
|
|
155
|
+
url = "http://test/api/v1/cloudpc/channels/7"
|
|
156
|
+
body = {"detail": [{"loc": ["body", "appearance", "userMessageStyle", "borderRadius", "topRight"], "msg": "Field required"}]}
|
|
157
|
+
transport[1][url] = HTTPError(url, 422, "Unprocessable Entity", {}, io.BytesIO(json.dumps(body).encode()))
|
|
158
|
+
payload = {"name": "Workspace", "appearance": {"userMessageStyle": {"borderRadius": {"topLeft": 1}}}}
|
|
159
|
+
assert run(cli, "cloudpc", "channels", "update", "7", "--json", json.dumps(payload)) == 1
|
|
160
|
+
assert len(transport[0]) == 1
|
|
161
|
+
error = capsys.readouterr().err
|
|
162
|
+
assert "HTTP 422" in error and "userMessageStyle" in error and "topRight" in error
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def test_channel_message_style_docs_and_help(cli, capsys):
|
|
166
|
+
assert cli.main(["docs", "show", "cloudpc.channels.update", "--json"]) == 0
|
|
167
|
+
fields = {field["name"]: field for field in json.loads(capsys.readouterr().out)["body_fields"]}
|
|
168
|
+
assert "userMessageStyle" in fields["appearance"]["description"]
|
|
169
|
+
prefix = "appearance.userMessageStyle"
|
|
170
|
+
for key in ["backgroundColor", "borderColor", "textColor", "borderRadius"]:
|
|
171
|
+
assert not fields[f"{prefix}.{key}"]["required"]
|
|
172
|
+
assert "null" in fields[f"{prefix}.{key}"]["description"].lower()
|
|
173
|
+
radius = fields[f"{prefix}.borderRadius"]["description"]
|
|
174
|
+
for key in ["topLeft", "topRight", "bottomLeft", "bottomRight", "0-100"]:
|
|
175
|
+
assert key in radius
|
|
176
|
+
with pytest.raises(SystemExit) as exc:
|
|
177
|
+
cli.main(["cloudpc", "channels", "update", "--help"])
|
|
178
|
+
assert exc.value.code == 0
|
|
179
|
+
assert "appearance.userMessageStyle" in capsys.readouterr().out
|
|
180
|
+
|
|
181
|
+
|
|
82
182
|
@pytest.mark.parametrize(("source", "expected"), [("latest", 23), ("published", 19)])
|
|
83
183
|
def test_resolve_version_and_report_actual_source(cli, transport, capsys, source, expected):
|
|
84
184
|
calls, responses = transport
|
|
File without changes
|
{deepflow_openagent_cli-0.1.7 → deepflow_openagent_cli-0.1.8}/src/deepflow_openagent_cli/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|