fix(attachments): preserve runtime files when syncing upload state
This commit is contained in:
parent
dcb3d2c939
commit
5b101bbbc9
@ -18,7 +18,6 @@ class AttachmentState(AgentState):
|
|||||||
"""扩展 AgentState 以支持附件"""
|
"""扩展 AgentState 以支持附件"""
|
||||||
|
|
||||||
attachments: NotRequired[list[dict]]
|
attachments: NotRequired[list[dict]]
|
||||||
files: NotRequired[dict[str, str]] # {"/attachments/xxx/file.md": content}
|
|
||||||
|
|
||||||
|
|
||||||
def _build_attachment_prompt(attachments: Sequence[dict]) -> str | None:
|
def _build_attachment_prompt(attachments: Sequence[dict]) -> str | None:
|
||||||
|
|||||||
@ -84,19 +84,24 @@ async def _sync_thread_attachment_state(
|
|||||||
if not isinstance(existing_files, dict):
|
if not isinstance(existing_files, dict):
|
||||||
existing_files = {}
|
existing_files = {}
|
||||||
|
|
||||||
attachment_files = _build_state_files(attachments)
|
# 仅对 /attachments 命名空间做增量更新,避免覆盖 agent 运行期生成的其它文件。
|
||||||
merged_files = {
|
next_attachment_files = _build_state_files(attachments)
|
||||||
path: file_data
|
prev_attachment_paths = {
|
||||||
for path, file_data in existing_files.items()
|
path
|
||||||
if isinstance(path, str) and not path.startswith("/attachments/")
|
for path in existing_files.keys()
|
||||||
|
if isinstance(path, str) and path.startswith("/attachments/")
|
||||||
}
|
}
|
||||||
merged_files.update(attachment_files)
|
next_attachment_paths = set(next_attachment_files.keys())
|
||||||
|
|
||||||
|
file_updates: dict[str, dict | None] = {**next_attachment_files}
|
||||||
|
for removed_path in prev_attachment_paths - next_attachment_paths:
|
||||||
|
file_updates[removed_path] = None
|
||||||
|
|
||||||
await graph.aupdate_state(
|
await graph.aupdate_state(
|
||||||
config=config,
|
config=config,
|
||||||
values={
|
values={
|
||||||
"attachments": attachments,
|
"attachments": attachments,
|
||||||
"files": merged_files,
|
"files": file_updates,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@ -80,8 +80,8 @@ async def test_sync_thread_attachment_state_updates_graph(monkeypatch: pytest.Mo
|
|||||||
assert captured["write_config"] == {"configurable": {"thread_id": "thread-1", "user_id": "u1"}}
|
assert captured["write_config"] == {"configurable": {"thread_id": "thread-1", "user_id": "u1"}}
|
||||||
assert captured["write_values"]["attachments"] == attachments
|
assert captured["write_values"]["attachments"] == attachments
|
||||||
assert "/attachments/resume.md" in captured["write_values"]["files"]
|
assert "/attachments/resume.md" in captured["write_values"]["files"]
|
||||||
assert "/attachments/old.md" not in captured["write_values"]["files"]
|
assert captured["write_values"]["files"]["/attachments/old.md"] is None
|
||||||
assert "/work/result.md" in captured["write_values"]["files"]
|
assert "/work/result.md" not in captured["write_values"]["files"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user