Compare commits

..

3 Commits

5 changed files with 529 additions and 565 deletions

View File

@ -92,10 +92,6 @@ def _build_llm_result_from_first_chunk(
Build a single `LLMResult` from the first returned chunk.
This is used for `stream=False` because the plugin side may still implement the response via a chunked stream.
Note:
This function always drains the `chunks` iterator after reading the first chunk to ensure any underlying
streaming resources are released (e.g., HTTP connections owned by the plugin runtime).
"""
content = ""
content_list: list[PromptMessageContentUnionTypes] = []
@ -103,25 +99,18 @@ def _build_llm_result_from_first_chunk(
system_fingerprint: str | None = None
tools_calls: list[AssistantPromptMessage.ToolCall] = []
try:
first_chunk = next(chunks, None)
if first_chunk is not None:
if isinstance(first_chunk.delta.message.content, str):
content += first_chunk.delta.message.content
elif isinstance(first_chunk.delta.message.content, list):
content_list.extend(first_chunk.delta.message.content)
first_chunk = next(chunks, None)
if first_chunk is not None:
if isinstance(first_chunk.delta.message.content, str):
content += first_chunk.delta.message.content
elif isinstance(first_chunk.delta.message.content, list):
content_list.extend(first_chunk.delta.message.content)
if first_chunk.delta.message.tool_calls:
_increase_tool_call(first_chunk.delta.message.tool_calls, tools_calls)
if first_chunk.delta.message.tool_calls:
_increase_tool_call(first_chunk.delta.message.tool_calls, tools_calls)
usage = first_chunk.delta.usage or LLMUsage.empty_usage()
system_fingerprint = first_chunk.system_fingerprint
finally:
try:
for _ in chunks:
pass
except Exception:
logger.debug("Failed to drain non-stream plugin chunk iterator.", exc_info=True)
usage = first_chunk.delta.usage or LLMUsage.empty_usage()
system_fingerprint = first_chunk.system_fingerprint
return LLMResult(
model=model,

View File

@ -101,26 +101,3 @@ def test__normalize_non_stream_plugin_result__empty_iterator_defaults():
assert result.message.tool_calls == []
assert result.usage == LLMUsage.empty_usage()
assert result.system_fingerprint is None
def test__normalize_non_stream_plugin_result__closes_chunk_iterator():
prompt_messages = [UserPromptMessage(content="hi")]
chunk = _make_chunk(content="hello", usage=LLMUsage.empty_usage())
closed: list[bool] = []
def _chunk_iter():
try:
yield chunk
yield _make_chunk(content="ignored", usage=LLMUsage.empty_usage())
finally:
closed.append(True)
result = _normalize_non_stream_plugin_result(
model="test-model",
prompt_messages=prompt_messages,
result=_chunk_iter(),
)
assert result.message.content == "hello"
assert closed == [True]

View File

@ -119,15 +119,15 @@
"mime": "4.1.0",
"mitt": "3.0.1",
"negotiator": "1.0.0",
"next": "16.1.4",
"next": "16.1.5",
"next-themes": "0.4.6",
"nuqs": "2.8.6",
"pinyin-pro": "3.27.0",
"qrcode.react": "4.2.0",
"qs": "6.14.1",
"react": "19.2.3",
"react": "19.2.4",
"react-18-input-autosize": "3.0.0",
"react-dom": "19.2.3",
"react-dom": "19.2.4",
"react-easy-crop": "5.5.3",
"react-hotkeys-hook": "4.6.2",
"react-i18next": "16.5.0",
@ -165,9 +165,9 @@
"@eslint-react/eslint-plugin": "2.7.0",
"@mdx-js/loader": "3.1.1",
"@mdx-js/react": "3.1.1",
"@next/bundle-analyzer": "16.1.4",
"@next/eslint-plugin-next": "16.1.4",
"@next/mdx": "16.1.4",
"@next/bundle-analyzer": "16.1.5",
"@next/eslint-plugin-next": "16.1.5",
"@next/mdx": "16.1.5",
"@rgrove/parse-xml": "4.2.0",
"@serwist/turbopack": "9.5.0",
"@storybook/addon-docs": "10.2.0",

1024
web/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,6 @@ import type {
} from '@/types/workflow'
import { get, post } from './base'
import { getFlowPrefix } from './utils'
import { sanitizeWorkflowDraftPayload } from './workflow-payload'
export const fetchWorkflowDraft = (url: string) => {
return get(url, {}, { silent: true }) as Promise<FetchWorkflowDraftResponse>
@ -19,8 +18,7 @@ export const syncWorkflowDraft = ({ url, params }: {
url: string
params: Pick<FetchWorkflowDraftResponse, 'graph' | 'features' | 'environment_variables' | 'conversation_variables'>
}) => {
const sanitized = sanitizeWorkflowDraftPayload(params)
return post<CommonResponse & { updated_at: number, hash: string }>(url, { body: sanitized }, { silent: true })
return post<CommonResponse & { updated_at: number, hash: string }>(url, { body: params }, { silent: true })
}
export const fetchNodesDefaultConfigs = (url: string) => {