mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-11-08 12:00:36 +00:00
* feat(subagents): continue native batches and honor item dependencies * docs: link native batch follow-up changelog entries * test(migrations): pin isolated history-seed upgrade to 0050 * fix(subagents): preserve follow-up scope, blockers and fair scheduling * test(memory): freeze capacity evaluation time * fix(subagents): guard follow-up admission and retain run controls * fix(subagents): enforce runs:cancel on tool cancellation of follow-up batches * style(tests): format test_batch_followup_host with ruff * fix(subagents): drop the admission checkpoint check and keep SDK cancel compatible The checkpoint check inside run admission waited on the checkpoint saver's lock while holding the SQLite write lock, which could make another chat's checkpoint write fail. Remove it; dispatch still checks the conversation before admission. A follow-up waiting for an unanswered question now keeps its claim until the lease expires instead of rereading the conversation every poll. Cancel passes the caller's run authority only to submitters that take it, so existing SDK submitters keep the two-argument call. Document that retrying a prerequisite by hand does not requeue its blocked items, and list 0052 as the migration head. --------- Co-authored-by: Totoro-qaq <279883115+Totoro-qaq@users.noreply.github.com> Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
68 lines
1.8 KiB
Python
68 lines
1.8 KiB
Python
"""Process-local bridge from harness tools to the Gateway batch service."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import threading
|
|
from dataclasses import dataclass
|
|
from typing import Any, NotRequired, Protocol, TypedDict
|
|
|
|
BATCH_CONTINUATION_NAMESPACE = "native-subagent-batches"
|
|
|
|
|
|
def batch_continuation_key(batch_id: str) -> str:
|
|
return "native-batch-followup:" + batch_id
|
|
|
|
|
|
class BatchItemInput(TypedDict):
|
|
key: str
|
|
prompt: str
|
|
acceptance_criteria: NotRequired[list[str] | None]
|
|
depends_on: NotRequired[list[str]]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class BatchSubmitRequest:
|
|
user_id: str
|
|
thread_id: str
|
|
run_id: str | None
|
|
tool_call_id: str
|
|
submission_key: str
|
|
title: str
|
|
subagent_type: str
|
|
items: list[BatchItemInput]
|
|
max_live_items: int | None
|
|
max_running_items: int | None
|
|
execution_spec: dict[str, Any]
|
|
continuation: str | None = None
|
|
continuation_authority: Any = None
|
|
continuation_context: dict[str, Any] | None = None
|
|
|
|
|
|
class SubagentBatchSubmitter(Protocol):
|
|
async def submit(self, request: BatchSubmitRequest) -> dict[str, Any]: ...
|
|
|
|
async def get_batch(self, *, batch_id: str, user_id: str) -> dict[str, Any] | None: ...
|
|
|
|
async def read_batch_item(self, *, batch_id: str, user_id: str, thread_id: str, position: int) -> dict[str, Any] | None: ...
|
|
|
|
async def cancel_batch(self, *, batch_id: str, user_id: str) -> dict[str, Any] | None: ...
|
|
|
|
|
|
_submitter: SubagentBatchSubmitter | None = None
|
|
_lock = threading.Lock()
|
|
|
|
|
|
def set_subagent_batch_submitter(submitter: SubagentBatchSubmitter | None) -> None:
|
|
global _submitter
|
|
with _lock:
|
|
_submitter = submitter
|
|
|
|
|
|
def get_subagent_batch_submitter() -> SubagentBatchSubmitter | None:
|
|
with _lock:
|
|
return _submitter
|
|
|
|
|
|
def is_subagent_batch_runtime_available() -> bool:
|
|
return get_subagent_batch_submitter() is not None
|