Compare commits

...

2 Commits

Author SHA1 Message Date
huanghuoguoguo
3ceb0c6829 fix(pipeline): preserve routed flag when aggregating 2026-05-16 11:03:24 +08:00
RockChinQ
b251fc4b89 fix(plugin): resolve plugin page asset origin 2026-05-14 15:39:17 +08:00
4 changed files with 57 additions and 1 deletions

View File

@@ -39,6 +39,16 @@ def _normalize_plugin_asset_path(filepath: str) -> str | None:
return f'assets/{normalized}'
def _get_request_origin() -> str:
"""Return the public request origin, respecting reverse-proxy headers."""
forwarded_proto = quart.request.headers.get('X-Forwarded-Proto', '').split(',')[0].strip()
forwarded_host = quart.request.headers.get('X-Forwarded-Host', '').split(',')[0].strip()
scheme = forwarded_proto or quart.request.scheme
host = forwarded_host or quart.request.host
return f'{scheme}://{host}'
@group.group_class('plugins', '/api/v1/plugins')
class PluginsRouterGroup(group.RouterGroup):
async def _check_extensions_limit(self) -> str | None:
@@ -189,7 +199,7 @@ class PluginsRouterGroup(group.RouterGroup):
# CSP for HTML pages served to sandboxed iframes (opaque origin).
# 'self' doesn't work in sandboxed iframes — use actual server origin.
if mime_type and mime_type.startswith('text/html'):
origin = f'{quart.request.scheme}://{quart.request.host}'
origin = _get_request_origin()
resp.headers['Content-Security-Policy'] = (
f'default-src {origin}; '
f"script-src {origin} 'unsafe-inline'; "

View File

@@ -275,6 +275,7 @@ class MessageAggregator:
message_chain=merged_chain,
adapter=base_msg.adapter,
pipeline_uuid=base_msg.pipeline_uuid,
routed_by_rule=any(msg.routed_by_rule for msg in messages),
)
async def flush_all(self) -> None:

View File

@@ -0,0 +1,42 @@
"""
MessageAggregator unit tests.
"""
from importlib import import_module
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.provider.session as provider_session
def test_merge_messages_preserves_routed_by_rule_if_any_input_matches(sample_message_event, mock_adapter):
"""Merged PendingMessage should keep routed_by_rule when any input was rule-routed."""
aggregator = import_module('langbot.pkg.pipeline.aggregator')
message_aggregator = aggregator.MessageAggregator(ap=None)
first_message = aggregator.PendingMessage(
bot_uuid='test-bot-uuid',
launcher_type=provider_session.LauncherTypes.PERSON,
launcher_id=12345,
sender_id=12345,
message_event=sample_message_event,
message_chain=platform_message.MessageChain([platform_message.Plain(text='first')]),
adapter=mock_adapter,
pipeline_uuid='test-pipeline-uuid',
routed_by_rule=False,
)
second_message = aggregator.PendingMessage(
bot_uuid='test-bot-uuid',
launcher_type=provider_session.LauncherTypes.PERSON,
launcher_id=12345,
sender_id=12345,
message_event=sample_message_event,
message_chain=platform_message.MessageChain([platform_message.Plain(text='second')]),
adapter=mock_adapter,
pipeline_uuid='test-pipeline-uuid',
routed_by_rule=True,
)
merged_message = message_aggregator._merge_messages([first_message, second_message])
assert merged_message.routed_by_rule is True
assert str(merged_message.message_chain) == 'first\nsecond'

View File

@@ -590,6 +590,9 @@ export class BackendClient extends BaseHttpClient {
name: string,
filepath: string,
): string {
if (this.instance.defaults.baseURL === '/') {
return `${window.location.origin}/api/v1/plugins/${author}/${name}/assets/${filepath}`;
}
return (
this.instance.defaults.baseURL +
`/api/v1/plugins/${author}/${name}/assets/${filepath}`