deepflow-openagent-cli 0.1.3__tar.gz → 0.1.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepflow-openagent-cli
3
- Version: 0.1.3
3
+ Version: 0.1.4
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
@@ -69,6 +69,12 @@ deepflow_openagent_cli knowledge query-document 6670 --slice-id 512208 --line 17
69
69
  deepflow_openagent_cli chat 1 --message "Hello"
70
70
  deepflow_openagent_cli steps 1 42
71
71
  deepflow_openagent_cli steps get 1 42 100
72
+ deepflow_openagent_cli steps feedback 1 42 100 --rating like --comment "Helpful answer"
73
+
74
+ # Python code tool (create → update config → debug execute)
75
+ deepflow_openagent_cli tools create 1 --name order_query --tool-type python_code
76
+ deepflow_openagent_cli tools update 1 2 --json '{"config":{"code":"import openagent\nopenagent.set_output(openagent.args)","parameters_json":"{\"type\":\"object\",\"properties\":{\"order_id\":{\"type\":\"string\"}},\"required\":[\"order_id\"]}"}}'
77
+ deepflow_openagent_cli tools execute 1 2 --json '{"brief":"查订单","order_id":"A1"}'
72
78
  ```
73
79
 
74
80
  ## Development (build wheel/sdist locally)
@@ -48,6 +48,12 @@ deepflow_openagent_cli knowledge query-document 6670 --slice-id 512208 --line 17
48
48
  deepflow_openagent_cli chat 1 --message "Hello"
49
49
  deepflow_openagent_cli steps 1 42
50
50
  deepflow_openagent_cli steps get 1 42 100
51
+ deepflow_openagent_cli steps feedback 1 42 100 --rating like --comment "Helpful answer"
52
+
53
+ # Python code tool (create → update config → debug execute)
54
+ deepflow_openagent_cli tools create 1 --name order_query --tool-type python_code
55
+ deepflow_openagent_cli tools update 1 2 --json '{"config":{"code":"import openagent\nopenagent.set_output(openagent.args)","parameters_json":"{\"type\":\"object\",\"properties\":{\"order_id\":{\"type\":\"string\"}},\"required\":[\"order_id\"]}"}}'
56
+ deepflow_openagent_cli tools execute 1 2 --json '{"brief":"查订单","order_id":"A1"}'
51
57
  ```
52
58
 
53
59
  ## Development (build wheel/sdist locally)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "deepflow-openagent-cli"
7
- version = "0.1.3"
7
+ version = "0.1.4"
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"
@@ -1,3 +1,3 @@
1
1
  """DeepFlow OpenAgent CLI — published PyPI package."""
2
2
 
3
- __version__ = "0.1.3"
3
+ __version__ = "0.1.4"
@@ -256,6 +256,25 @@ ENDPOINTS: tuple[EndpointDoc, ...] = (
256
256
  errors=["401 missing or invalid API key", "404 step not found"],
257
257
  example="deepflow_openagent_cli steps get 1 42 100",
258
258
  ),
259
+ EndpointDoc(
260
+ key="steps.feedback",
261
+ method="POST",
262
+ path="/api/v1/agents/{agent_id}/conversations/{conversation_id}/steps/{step_id}/feedback",
263
+ scope="chat",
264
+ summary="Submit or overwrite like/dislike feedback for one completed assistant_message step.",
265
+ path_params=[
266
+ _param("agent_id", "integer", True, "Agent ID."),
267
+ _param("conversation_id", "integer", True, "Conversation ID."),
268
+ _param("step_id", "integer", True, "Assistant message Step ID."),
269
+ ],
270
+ body_fields=[
271
+ _param("rating", "string", True, "Feedback rating: like or dislike."),
272
+ _param("comment", "string", False, "Optional feedback comment, max 500 characters."),
273
+ ],
274
+ response="StepFeedbackResponse with step_id, feedback_rating, feedback_comment, and feedback_updated_at.",
275
+ errors=["400 invalid step state", "401 missing or invalid API key", "403 scope missing", "404 step not found", "422 validation error"],
276
+ example="deepflow_openagent_cli steps feedback 1 42 100 --rating like --comment 'Helpful answer'",
277
+ ),
259
278
  EndpointDoc(
260
279
  key="agents.list",
261
280
  method="GET",
@@ -360,14 +379,24 @@ ENDPOINTS: tuple[EndpointDoc, ...] = (
360
379
  summary="Create a custom tool for an agent.",
361
380
  path_params=[_param("agent_id", "integer", True, "Agent ID.")],
362
381
  body_fields=[
363
- _param("name", "string", True, "Tool name, 1-128 chars."),
382
+ _param("name", "string", True, "Tool name, 1-128 chars, pattern ^[a-zA-Z0-9_-]+$."),
364
383
  _param("description", "string", False, "Tool description."),
365
384
  _param("tool_type", "string", True, "search, doc_query, doc_grep, notebook, tool_response_fetch, or python_code."),
366
- _param("config", "object", False, "Tool config."),
385
+ _param(
386
+ "config",
387
+ "object",
388
+ False,
389
+ "Tool config. python_code uses code (Python source) and parameters_json (JSON Schema text string).",
390
+ ),
367
391
  ],
368
392
  response="AgentToolResponse.",
369
- errors=["401 missing or invalid API key", "403 scope missing", "404 agent not found", "422 validation error"],
370
- example="deepflow_openagent_cli tools create 1 --name Search --tool-type search --json '{\"config\":{\"kb_ids\":[1]}}'",
393
+ errors=["401 missing or invalid API key", "403 scope missing", "404 agent not found", "400/422 validation error"],
394
+ example=(
395
+ "deepflow_openagent_cli tools create 1 --name order_query --tool-type python_code "
396
+ "--json '{\"config\":{\"code\":\"import openagent\\nopenagent.set_output(openagent.args)\","
397
+ "\"parameters_json\":\"{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{\\\"order_id\\\":{\\\"type\\\":\\\"string\\\"}},"
398
+ "\\\"required\\\":[\\\"order_id\\\"]}\"}}'"
399
+ ),
371
400
  ),
372
401
  EndpointDoc(
373
402
  key="tools.get",
@@ -394,13 +423,22 @@ ENDPOINTS: tuple[EndpointDoc, ...] = (
394
423
  _param("tool_id", "integer", True, "Tool ID."),
395
424
  ],
396
425
  body_fields=[
397
- _param("name", "string", False, "Tool name."),
426
+ _param("name", "string", False, "Tool name, pattern ^[a-zA-Z0-9_-]+$."),
398
427
  _param("description", "string", False, "Tool description."),
399
- _param("config", "object", False, "Tool config."),
428
+ _param(
429
+ "config",
430
+ "object",
431
+ False,
432
+ "Tool config. python_code: {code, parameters_json}; search/doc_*: {kb_ids}; human_handoff: {service_hours_id, route_fields}.",
433
+ ),
400
434
  ],
401
435
  response="AgentToolResponse.",
402
- errors=["401 missing or invalid API key", "403 scope missing", "404 tool not found", "422 validation error"],
403
- example="deepflow_openagent_cli tools update 1 2 --json '{\"config\":{\"kb_ids\":[1,2]}}'",
436
+ errors=["401 missing or invalid API key", "403 scope missing", "404 tool not found", "400/422 validation error"],
437
+ example=(
438
+ "deepflow_openagent_cli tools update 1 2 --json "
439
+ "'{\"config\":{\"code\":\"import openagent\\nopenagent.set_output(\\\"ok\\\")\","
440
+ "\"parameters_json\":\"{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{}}\"}}'"
441
+ ),
404
442
  ),
405
443
  EndpointDoc(
406
444
  key="tools.toggle",
@@ -442,10 +480,12 @@ ENDPOINTS: tuple[EndpointDoc, ...] = (
442
480
  _param("tool_id", "integer", True, "Tool ID."),
443
481
  ],
444
482
  query_params=[_param("conversation_id", "integer", False, "Conversation ID for tool context.")],
445
- body_fields=[_param("*", "object", False, "Tool-specific arguments.")],
446
- response="ToolExecuteResponse.",
483
+ body_fields=[
484
+ _param("*", "object", False, "Tool-specific arguments. python_code example: brief + business params from parameters_json."),
485
+ ],
486
+ response="ToolExecuteResponse with tool_name, tool_type, arguments, result, duration_ms.",
447
487
  errors=["401 missing or invalid API key", "403 scope missing", "404 tool not found", "422 validation error"],
448
- example="deepflow_openagent_cli tools execute 1 2 --json '{\"query\":\"pricing\"}'",
488
+ example="deepflow_openagent_cli tools execute 1 2 --json '{\"brief\":\"查订单\",\"order_id\":\"A1\"}'",
449
489
  ),
450
490
  EndpointDoc(
451
491
  key="channels.list",
@@ -812,6 +852,21 @@ def handle_steps(args: argparse.Namespace) -> int:
812
852
  "step_id": step_id,
813
853
  },
814
854
  )
855
+ if action == "feedback":
856
+ agent_id, conversation_id, step_id = values
857
+ body = merge_payload(args, {"rating": args.rating, "comment": args.comment})
858
+ if "rating" not in body:
859
+ raise CliError("Missing feedback rating. Pass --rating like|dislike or include rating in --json.")
860
+ return run_request(
861
+ args,
862
+ "steps.feedback",
863
+ {
864
+ "agent_id": agent_id,
865
+ "conversation_id": conversation_id,
866
+ "step_id": step_id,
867
+ },
868
+ body=body,
869
+ )
815
870
 
816
871
  agent_id, conversation_id = values
817
872
  return run_request(
@@ -998,14 +1053,18 @@ def build_parser() -> argparse.ArgumentParser:
998
1053
 
999
1054
  steps = subparsers.add_parser(
1000
1055
  "steps",
1001
- help="List conversation execution steps or get full step detail.",
1056
+ help="List, inspect, or submit feedback for conversation execution steps.",
1002
1057
  description=(
1003
- "List conversation execution steps or get full step detail. "
1058
+ "List conversation execution steps, get full step detail, or submit feedback. "
1004
1059
  "Forms: steps <agent_id> <conversation_id>; "
1005
- "steps get <agent_id> <conversation_id> <step_id>."
1060
+ "steps get <agent_id> <conversation_id> <step_id>; "
1061
+ "steps feedback <agent_id> <conversation_id> <step_id> --rating like."
1006
1062
  ),
1007
1063
  )
1008
1064
  steps.add_argument("steps_args", nargs="+", metavar="ARGS")
1065
+ steps.add_argument("--rating", choices=["like", "dislike"])
1066
+ steps.add_argument("--comment")
1067
+ add_json_args(steps)
1009
1068
  steps.set_defaults(handler=handle_steps)
1010
1069
 
1011
1070
  agents = subparsers.add_parser("agents", help="Agent endpoints.")
@@ -1102,17 +1161,18 @@ def parse_bool(value: str) -> bool:
1102
1161
  def parse_steps_args(values: list[str]) -> tuple[str, tuple[int, ...]]:
1103
1162
  action = "list"
1104
1163
  raw_values = values
1105
- if values[0] in {"list", "get", "detail"}:
1164
+ if values[0] in {"list", "get", "detail", "feedback"}:
1106
1165
  action = "get" if values[0] == "detail" else values[0]
1107
1166
  raw_values = values[1:]
1108
1167
  elif len(values) == 3:
1109
1168
  action = "get"
1110
1169
 
1111
- expected = 3 if action == "get" else 2
1170
+ expected = 3 if action in {"get", "feedback"} else 2
1112
1171
  if len(raw_values) != expected:
1113
1172
  raise CliError(
1114
1173
  "Usage: steps <agent_id> <conversation_id> or "
1115
- "steps get <agent_id> <conversation_id> <step_id>."
1174
+ "steps get <agent_id> <conversation_id> <step_id> or "
1175
+ "steps feedback <agent_id> <conversation_id> <step_id> --rating like|dislike."
1116
1176
  )
1117
1177
 
1118
1178
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepflow-openagent-cli
3
- Version: 0.1.3
3
+ Version: 0.1.4
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
@@ -69,6 +69,12 @@ deepflow_openagent_cli knowledge query-document 6670 --slice-id 512208 --line 17
69
69
  deepflow_openagent_cli chat 1 --message "Hello"
70
70
  deepflow_openagent_cli steps 1 42
71
71
  deepflow_openagent_cli steps get 1 42 100
72
+ deepflow_openagent_cli steps feedback 1 42 100 --rating like --comment "Helpful answer"
73
+
74
+ # Python code tool (create → update config → debug execute)
75
+ deepflow_openagent_cli tools create 1 --name order_query --tool-type python_code
76
+ deepflow_openagent_cli tools update 1 2 --json '{"config":{"code":"import openagent\nopenagent.set_output(openagent.args)","parameters_json":"{\"type\":\"object\",\"properties\":{\"order_id\":{\"type\":\"string\"}},\"required\":[\"order_id\"]}"}}'
77
+ deepflow_openagent_cli tools execute 1 2 --json '{"brief":"查订单","order_id":"A1"}'
72
78
  ```
73
79
 
74
80
  ## Development (build wheel/sdist locally)
@@ -247,3 +247,108 @@ def test_tools_create_accepts_doc_grep(
247
247
  assert calls[0][0] == "tools.create"
248
248
  assert calls[0][1] == {"agent_id": 1}
249
249
  assert calls[0][3]["tool_type"] == "doc_grep"
250
+
251
+
252
+ def test_tools_create_accepts_python_code(
253
+ monkeypatch: pytest.MonkeyPatch,
254
+ capsys: pytest.CaptureFixture[str],
255
+ ) -> None:
256
+ calls = []
257
+
258
+ def fake_request(self, endpoint_key, path_params=None, query=None, body=None, *, stream=False):
259
+ calls.append((endpoint_key, path_params, query, body, stream))
260
+ return b'{"ok": true}'
261
+
262
+ monkeypatch.setattr(OpenApiClient, "request", fake_request)
263
+
264
+ config = {
265
+ "code": "import openagent\nopenagent.set_output(openagent.args)",
266
+ "parameters_json": '{"type":"object","properties":{"order_id":{"type":"string"}},"required":["order_id"]}',
267
+ }
268
+ exit_code = main(
269
+ [
270
+ "--host",
271
+ "http://localhost:5001",
272
+ "--api-key",
273
+ "sk-test",
274
+ "tools",
275
+ "create",
276
+ "1",
277
+ "--name",
278
+ "order_query",
279
+ "--tool-type",
280
+ "python_code",
281
+ "--json",
282
+ json.dumps({"config": config}),
283
+ ]
284
+ )
285
+
286
+ captured = capsys.readouterr()
287
+ assert exit_code == 0
288
+ assert json.loads(captured.out) == {"ok": True}
289
+ assert calls[0][0] == "tools.create"
290
+ assert calls[0][1] == {"agent_id": 1}
291
+ assert calls[0][3]["tool_type"] == "python_code"
292
+ assert calls[0][3]["name"] == "order_query"
293
+ assert calls[0][3]["config"] == config
294
+
295
+
296
+ def test_tools_update_and_execute_python_code(
297
+ monkeypatch: pytest.MonkeyPatch,
298
+ capsys: pytest.CaptureFixture[str],
299
+ ) -> None:
300
+ calls = []
301
+
302
+ def fake_request(self, endpoint_key, path_params=None, query=None, body=None, *, stream=False):
303
+ calls.append((endpoint_key, path_params, query, body, stream))
304
+ return b'{"ok": true}'
305
+
306
+ monkeypatch.setattr(OpenApiClient, "request", fake_request)
307
+
308
+ update_body = {
309
+ "config": {
310
+ "code": "import openagent\nopenagent.set_output('ok')",
311
+ "parameters_json": '{"type":"object","properties":{}}',
312
+ }
313
+ }
314
+ exit_code = main(
315
+ [
316
+ "--host",
317
+ "http://localhost:5001",
318
+ "--api-key",
319
+ "sk-test",
320
+ "tools",
321
+ "update",
322
+ "1",
323
+ "2",
324
+ "--json",
325
+ json.dumps(update_body),
326
+ ]
327
+ )
328
+ captured = capsys.readouterr()
329
+ assert exit_code == 0
330
+ assert json.loads(captured.out) == {"ok": True}
331
+ assert calls[0][0] == "tools.update"
332
+ assert calls[0][1] == {"agent_id": 1, "tool_id": 2}
333
+ assert calls[0][3] == update_body
334
+
335
+ exit_code = main(
336
+ [
337
+ "--host",
338
+ "http://localhost:5001",
339
+ "--api-key",
340
+ "sk-test",
341
+ "tools",
342
+ "execute",
343
+ "1",
344
+ "2",
345
+ "--json",
346
+ '{"brief":"查订单","order_id":"A1"}',
347
+ ]
348
+ )
349
+ captured = capsys.readouterr()
350
+ assert exit_code == 0
351
+ assert json.loads(captured.out) == {"ok": True}
352
+ assert calls[1][0] == "tools.execute"
353
+ assert calls[1][1] == {"agent_id": 1, "tool_id": 2}
354
+ assert calls[1][3] == {"brief": "查订单", "order_id": "A1"}