aidev-bkplugin 2.2.0.post2__tar.gz → 2.2.0.post3__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.
Files changed (79) hide show
  1. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/PKG-INFO +2 -2
  2. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/services/agent_execution.py +12 -18
  3. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/pyproject.toml +2 -2
  4. aidev_bkplugin-2.2.0.post3/tests/services/test_agent_completion.py +58 -0
  5. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/__init__.py +0 -0
  6. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/apps.py +0 -0
  7. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/constants.py +0 -0
  8. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/enums.py +0 -0
  9. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/management/__init__.py +0 -0
  10. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/management/commands/__init__.py +0 -0
  11. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/management/commands/upgrade_sessions.py +0 -0
  12. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/migrations/0001_initial.py +0 -0
  13. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/migrations/__init__.py +0 -0
  14. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/models.py +0 -0
  15. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/openapi/__init__.py +0 -0
  16. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/openapi/urls.py +0 -0
  17. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/openapi/views.py +0 -0
  18. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/packages/__init__.py +0 -0
  19. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/packages/apigw/__init__.py +0 -0
  20. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/packages/apigw/permissions.py +0 -0
  21. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/packages/checkpoint/__init__.py +0 -0
  22. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/packages/checkpoint/bk_django_saver.py +0 -0
  23. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/packages/drf/__init__.py +0 -0
  24. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/packages/drf/authentication.py +0 -0
  25. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/packages/drf/decorators.py +0 -0
  26. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/packages/drf/exception.py +0 -0
  27. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/packages/drf/renderers.py +0 -0
  28. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/permissions.py +0 -0
  29. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/private/__init__.py +0 -0
  30. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/private/permissions.py +0 -0
  31. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/private/urls.py +0 -0
  32. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/private/views.py +0 -0
  33. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/serializers/__init__.py +0 -0
  34. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/serializers/agent.py +0 -0
  35. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/serializers/chat_completion.py +0 -0
  36. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/serializers/user_operation.py +0 -0
  37. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/services/__init__.py +0 -0
  38. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/services/agent_bkplugin.py +0 -0
  39. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/services/agent_builder.py +0 -0
  40. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/services/agent_config.py +0 -0
  41. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/services/agent_helpers.py +0 -0
  42. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/services/agent_session.py +0 -0
  43. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/services/approval_resume.py +0 -0
  44. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/services/user_operation.py +0 -0
  45. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/settings.py +0 -0
  46. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/tasks.py +0 -0
  47. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/urls.py +0 -0
  48. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/utils.py +0 -0
  49. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/views/__init__.py +0 -0
  50. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/views/agent.py +0 -0
  51. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/views/base.py +0 -0
  52. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/views/chat.py +0 -0
  53. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/views/chat_group.py +0 -0
  54. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/views/flow_agent.py +0 -0
  55. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/views/session.py +0 -0
  56. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/aidev_bkplugin/views/user_operation.py +0 -0
  57. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/readme.md +0 -0
  58. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/__init__.py +0 -0
  59. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/conftest.py +0 -0
  60. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/packages/__init__.py +0 -0
  61. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/packages/test_bk_django_saver.py +0 -0
  62. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/private/__init__.py +0 -0
  63. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/private/test_private_views.py +0 -0
  64. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/services/__init__.py +0 -0
  65. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/services/agent/__init__.py +0 -0
  66. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/services/agent/conftest.py +0 -0
  67. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/services/agent/test_agent_config_fetcher.py +0 -0
  68. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/services/agent/test_builder.py +0 -0
  69. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/services/agent/test_session_manager.py +0 -0
  70. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/services/test_agui_handler.py +0 -0
  71. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/services/test_bkplugin.py +0 -0
  72. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/services/test_thread_chat_completion.py +0 -0
  73. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/services/test_user_operation.py +0 -0
  74. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/settings.py +0 -0
  75. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/test_constants.py +0 -0
  76. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/test_utils_otel.py +0 -0
  77. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/views/__init__.py +0 -0
  78. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/views/test_chat_completion_serializer.py +0 -0
  79. {aidev_bkplugin-2.2.0.post2 → aidev_bkplugin-2.2.0.post3}/tests/views/test_chat_flow_agent.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: aidev-bkplugin
3
- Version: 2.2.0.post2
3
+ Version: 2.2.0.post3
4
4
  Summary: AiDev Agent Bkplugin builtin functions
5
5
  Requires-Python: <3.12,>=3.11
6
- Requires-Dist: aidev-agent>=2.2.0post2
6
+ Requires-Dist: aidev-agent>=2.2.0post3
7
7
  Requires-Dist: blueapps<5.0,>=4.15.1
8
8
  Requires-Dist: django<5.0,>=4.2.28
9
9
  Description-Content-Type: text/markdown
@@ -89,7 +89,7 @@ class AgentExecutor:
89
89
  *,
90
90
  turn_id: str = "",
91
91
  ):
92
- """执行 agent 直至结束;AG-UI 流式负责事件落库并收尾会话状态。"""
92
+ """执行 agent 直至结束;后台消费者完整 drain 后统一收尾会话状态。"""
93
93
  # 后台 drain(for _ in out: pass,无 SSE 下游):标记为 background_only,
94
94
  # 使消费者读到 EOD 时不立即清理队列,保留 DLQ 历史供前端在清理窗口内接管续流。
95
95
  execute_kwargs.background_only = True
@@ -99,24 +99,18 @@ class AgentExecutor:
99
99
  handler.turn_id = turn_id
100
100
  if hasattr(handler, "set_streaming_started"):
101
101
  handler.set_streaming_started()
102
- try:
103
- out = cls(session_manager).execute_with_save(
104
- agent_instance,
105
- execute_kwargs,
106
- session_code,
107
- turn_id=turn_id,
108
- )
109
- if execute_kwargs.stream:
110
- for _ in out:
111
- pass
112
- return out
113
- finally:
114
- if (
115
- execute_kwargs.stream
116
- and isinstance(handler, BaseSessionWriter)
117
- and hasattr(handler, "set_streaming_finished")
118
- ):
102
+ out = cls(session_manager).execute_with_save(
103
+ agent_instance,
104
+ execute_kwargs,
105
+ session_code,
106
+ turn_id=turn_id,
107
+ )
108
+ if execute_kwargs.stream:
109
+ for _ in out:
110
+ pass
111
+ if isinstance(handler, BaseSessionWriter) and hasattr(handler, "set_streaming_finished"):
119
112
  handler.set_streaming_finished()
113
+ return out
120
114
 
121
115
  def wrap_generator(self, generator, session_code: str, *, turn_id: str = ""):
122
116
  """SSE 数据格式约定:
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "aidev-bkplugin"
3
- version = "2.2.0post2"
3
+ version = "2.2.0post3"
4
4
  description = "AiDev Agent Bkplugin builtin functions"
5
5
  readme = "readme.md"
6
6
  requires-python = "<3.12,>=3.11"
7
7
  dependencies = [
8
- "aidev-agent>=2.2.0post2",
8
+ "aidev-agent>=2.2.0post3",
9
9
  "blueapps>=4.15.1, <5.0",
10
10
  "django>=4.2.28,<5.0",
11
11
  ]
@@ -0,0 +1,58 @@
1
+ # -*- coding: utf-8 -*-
2
+ """后台 Agent 流式终态写入回归测试。"""
3
+
4
+ import sys
5
+ from unittest.mock import MagicMock, patch
6
+
7
+ import pytest
8
+
9
+ if "pkg_resources" not in sys.modules:
10
+ sys.modules["pkg_resources"] = MagicMock()
11
+
12
+ sys.modules.setdefault("aidev_bkplugin.models", MagicMock())
13
+ _bk_plugin_framework = MagicMock()
14
+ _bk_plugin_framework.kit.decorators.inject_user_token = lambda func: func
15
+ sys.modules.setdefault("bk_plugin_framework", _bk_plugin_framework)
16
+ sys.modules.setdefault("bk_plugin_framework.kit", _bk_plugin_framework.kit)
17
+ sys.modules.setdefault("bk_plugin_framework.kit.decorators", _bk_plugin_framework.kit.decorators)
18
+
19
+
20
+ class TestAgentExecutorCompletion:
21
+ def test_sets_finished_after_stream_is_drained(self):
22
+ from aidev_agent.services.event_handlers.base import BaseSessionWriter
23
+ from aidev_bkplugin.services.agent_execution import AgentExecutor
24
+
25
+ lifecycle = []
26
+
27
+ def stream():
28
+ yield "chunk"
29
+ lifecycle.append("drained")
30
+
31
+ handler = MagicMock(spec=BaseSessionWriter)
32
+ handler.set_streaming_finished.side_effect = lambda: lifecycle.append("finished")
33
+ agent = MagicMock(event_handler=handler)
34
+ execute_kwargs = MagicMock(stream=True)
35
+ with patch.object(AgentExecutor, "execute_with_save", return_value=stream()):
36
+ AgentExecutor.run_agent_to_completion(agent, execute_kwargs, "session-abc", MagicMock())
37
+
38
+ assert execute_kwargs.background_only is True
39
+ assert lifecycle == ["drained", "finished"]
40
+
41
+ def test_does_not_set_finished_when_stream_drain_fails(self):
42
+ from aidev_agent.services.event_handlers.base import BaseSessionWriter
43
+ from aidev_bkplugin.services.agent_execution import AgentExecutor
44
+
45
+ def failing_stream():
46
+ yield "chunk"
47
+ raise RuntimeError("producer heartbeat timeout")
48
+
49
+ handler = MagicMock(spec=BaseSessionWriter)
50
+ agent = MagicMock(event_handler=handler)
51
+ execute_kwargs = MagicMock(stream=True)
52
+ with (
53
+ patch.object(AgentExecutor, "execute_with_save", return_value=failing_stream()),
54
+ pytest.raises(RuntimeError, match="heartbeat timeout"),
55
+ ):
56
+ AgentExecutor.run_agent_to_completion(agent, execute_kwargs, "session-abc", MagicMock())
57
+
58
+ handler.set_streaming_finished.assert_not_called()