mirror of
https://github.com/langbot-app/LangBot.git
synced 2025-11-25 19:37:36 +08:00
* Initial plan * Add package structure and resource path utilities - Created langbot/ package with __init__.py and __main__.py entry point - Added paths utility to find frontend and resource files from package installation - Updated config loading to use resource paths - Updated frontend serving to use resource paths - Added MANIFEST.in for package data inclusion - Updated pyproject.toml with build system and entry points Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * Add PyPI publishing workflow and update license - Created GitHub Actions workflow to build frontend and publish to PyPI - Added license field to pyproject.toml to fix deprecation warning - Updated .gitignore to exclude build artifacts - Tested package building successfully Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * Add PyPI installation documentation - Created PYPI_INSTALLATION.md with detailed installation and usage instructions - Updated README.md to feature uvx/pip installation as recommended method - Updated README_EN.md with same changes for English documentation Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * Address code review feedback - Made package-data configuration more specific to langbot package only - Improved path detection with caching to avoid repeated file I/O - Removed sys.path searching which was incorrect for package data - Removed interactive input() call for non-interactive environment compatibility - Simplified error messages for version check Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * Fix code review issues - Use specific exception types instead of bare except - Fix misleading comments about directory levels - Remove redundant existence check before makedirs with exist_ok=True - Use context manager for file opening to ensure proper cleanup Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * Simplify package configuration and document behavioral differences - Removed redundant package-data configuration, relying on MANIFEST.in - Added documentation about behavioral differences between package and source installation - Clarified that include-package-data=true uses MANIFEST.in for data files Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * chore: update pyproject.toml * chore: try pack templates in langbot/ * chore: update * chore: update * chore: update * chore: update * chore: update * chore: adjust dir structure * chore: fix imports * fix: read default-pipeline-config.json * fix: read default-pipeline-config.json * fix: tests * ci: publish pypi * chore: bump version 4.6.0-beta.1 for testing * chore: add templates/** * fix: send adapters and requesters icons * chore: bump version 4.6.0b2 for testing * chore: add platform field for docker-compose.yaml --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> Co-authored-by: Junyan Qin <rockchinq@gmail.com>
110 lines
4.6 KiB
Python
110 lines
4.6 KiB
Python
import json
|
|
|
|
import quart
|
|
|
|
from ... import group
|
|
|
|
|
|
@group.group_class('webchat', '/api/v1/pipelines/<pipeline_uuid>/chat')
|
|
class WebChatDebugRouterGroup(group.RouterGroup):
|
|
async def initialize(self) -> None:
|
|
@self.route('/send', methods=['POST'])
|
|
async def send_message(pipeline_uuid: str) -> str:
|
|
"""Send a message to the pipeline for debugging"""
|
|
|
|
async def stream_generator(generator):
|
|
yield 'data: {"type": "start"}\n\n'
|
|
async for message in generator:
|
|
yield f'data: {json.dumps({"message": message})}\n\n'
|
|
yield 'data: {"type": "end"}\n\n'
|
|
|
|
try:
|
|
data = await quart.request.get_json()
|
|
session_type = data.get('session_type', 'person')
|
|
message_chain_obj = data.get('message', [])
|
|
is_stream = data.get('is_stream', False)
|
|
|
|
if not message_chain_obj:
|
|
return self.http_status(400, -1, 'message is required')
|
|
|
|
if session_type not in ['person', 'group']:
|
|
return self.http_status(400, -1, 'session_type must be person or group')
|
|
|
|
webchat_adapter = self.ap.platform_mgr.webchat_proxy_bot.adapter
|
|
|
|
if not webchat_adapter:
|
|
return self.http_status(404, -1, 'WebChat adapter not found')
|
|
|
|
if is_stream:
|
|
generator = webchat_adapter.send_webchat_message(
|
|
pipeline_uuid, session_type, message_chain_obj, is_stream
|
|
)
|
|
# 设置正确的响应头
|
|
headers = {
|
|
'Content-Type': 'text/event-stream',
|
|
'Transfer-Encoding': 'chunked',
|
|
'Cache-Control': 'no-cache',
|
|
'Connection': 'keep-alive',
|
|
}
|
|
return quart.Response(stream_generator(generator), mimetype='text/event-stream', headers=headers)
|
|
|
|
else: # non-stream
|
|
result = None
|
|
async for message in webchat_adapter.send_webchat_message(
|
|
pipeline_uuid, session_type, message_chain_obj
|
|
):
|
|
result = message
|
|
if result is not None:
|
|
return self.success(
|
|
data={
|
|
'message': result,
|
|
}
|
|
)
|
|
else:
|
|
return self.http_status(400, -1, 'message is required')
|
|
|
|
except Exception as e:
|
|
return self.http_status(500, -1, f'Internal server error: {str(e)}')
|
|
|
|
@self.route('/messages/<session_type>', methods=['GET'])
|
|
async def get_messages(pipeline_uuid: str, session_type: str) -> str:
|
|
"""Get the message history of the pipeline for debugging"""
|
|
try:
|
|
if session_type not in ['person', 'group']:
|
|
return self.http_status(400, -1, 'session_type must be person or group')
|
|
|
|
webchat_adapter = self.ap.platform_mgr.webchat_proxy_bot.adapter
|
|
|
|
if not webchat_adapter:
|
|
return self.http_status(404, -1, 'WebChat adapter not found')
|
|
|
|
messages = webchat_adapter.get_webchat_messages(pipeline_uuid, session_type)
|
|
|
|
return self.success(data={'messages': messages})
|
|
|
|
except Exception as e:
|
|
return self.http_status(500, -1, f'Internal server error: {str(e)}')
|
|
|
|
@self.route('/reset/<session_type>', methods=['POST'])
|
|
async def reset_session(session_type: str) -> str:
|
|
"""Reset the debug session"""
|
|
try:
|
|
if session_type not in ['person', 'group']:
|
|
return self.http_status(400, -1, 'session_type must be person or group')
|
|
|
|
webchat_adapter = None
|
|
for bot in self.ap.platform_mgr.bots:
|
|
if hasattr(bot.adapter, '__class__') and bot.adapter.__class__.__name__ == 'WebChatAdapter':
|
|
webchat_adapter = bot.adapter
|
|
break
|
|
|
|
if not webchat_adapter:
|
|
return self.http_status(404, -1, 'WebChat adapter not found')
|
|
|
|
webchat_adapter.reset_debug_session(session_type)
|
|
|
|
return self.success(data={'message': 'Session reset successfully'})
|
|
|
|
except Exception as e:
|
|
return self.http_status(500, -1, f'Internal server error: {str(e)}')
|