Skip to content

Commit ab25b88

Browse files
Common File Handling and Attachments as Part of User Message (#530)
Most of the new logic was implemented in `assistants/document-assistant/assistant/response/responder.py`
1 parent 33bbd66 commit ab25b88

27 files changed

Lines changed: 2779 additions & 1687 deletions

assistants/document-assistant/assistant/chat.py

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@
77

88
import logging
99
import pathlib
10+
from textwrap import dedent
1011
from typing import Any
1112

1213
import deepmerge
1314
from assistant_extensions import dashboard_card
14-
from assistant_extensions.attachments import AttachmentsExtension
15-
from assistant_extensions.document_editor import DocumentEditorConfigModel, DocumentEditorExtension
1615
from assistant_extensions.mcp import MCPServerConfig
1716
from content_safety.evaluators import CombinedContentSafetyEvaluator
1817
from semantic_workbench_api_model.workbench_model import (
@@ -29,12 +28,11 @@
2928
ConversationContext,
3029
)
3130

31+
from assistant.config import AssistantConfigModel
32+
from assistant.filesystem import AttachmentsExtension, DocumentEditorConfigModel
3233
from assistant.guidance.dynamic_ui_inspector import DynamicUIInspector
33-
34-
from . import helpers
35-
from .config import AssistantConfigModel
36-
from .response import respond_to_conversation
37-
from .whiteboard import WhiteboardInspector
34+
from assistant.response.responder import ConversationResponder
35+
from assistant.whiteboard import WhiteboardInspector
3836

3937
logger = logging.getLogger(__name__)
4038

@@ -45,7 +43,7 @@
4543
# the service id to be registered in the workbench to identify the assistant
4644
service_id = "document-assistant.made-exploration-team"
4745
# the name of the assistant service, as it will appear in the workbench UI
48-
service_name = "Document Assistant (new)"
46+
service_name = "Document Assistant"
4947
# a description of the assistant service, as it will appear in the workbench UI
5048
service_description = "An assistant for writing documents."
5149

@@ -81,7 +79,14 @@ async def content_evaluator_factory(context: ConversationContext) -> ContentSafe
8179
background_color="rgb(155,217,219)",
8280
card_content=dashboard_card.CardContent(
8381
content_type="text/markdown",
84-
content=helpers.load_text_include("card_content.md"),
82+
content=dedent(
83+
"""
84+
General assistant focused on document creation and editing.\n
85+
- Side by side doc editing
86+
- Provides guidance through generated UI elements
87+
- Autonomously executes tools to complete tasks.
88+
- Local-only options for Office integration via MCP"""
89+
),
8590
),
8691
)
8792
),
@@ -92,28 +97,21 @@ async def content_evaluator_factory(context: ConversationContext) -> ContentSafe
9297
async def document_editor_config_provider(ctx: ConversationContext) -> DocumentEditorConfigModel:
9398
config = await assistant_config.get(ctx.assistant)
9499
# Get either the hosted or personal config based on which one is enabled. Priority is given to the personal config.
95-
personal_filesystem_edit = [x for x in config.tools.personal_mcp_servers if x.key == "filesystem-edit"]
100+
personal_filesystem_edit = [x for x in config.orchestration.personal_mcp_servers if x.key == "filesystem-edit"]
96101
if len(personal_filesystem_edit) > 0:
97102
return personal_filesystem_edit[0]
98-
return config.tools.hosted_mcp_servers.filesystem_edit
99-
100-
101-
document_editor_extension = DocumentEditorExtension(
102-
app=assistant,
103-
config_provider=document_editor_config_provider,
104-
storage_directory="documents",
105-
)
103+
return config.orchestration.hosted_mcp_servers.filesystem_edit
106104

107105

108106
async def whiteboard_config_provider(ctx: ConversationContext) -> MCPServerConfig:
109107
config = await assistant_config.get(ctx.assistant)
110-
return config.tools.hosted_mcp_servers.memory_whiteboard
108+
return config.orchestration.hosted_mcp_servers.memory_whiteboard
111109

112110

113111
_ = WhiteboardInspector(state_id="whiteboard", app=assistant, server_config_provider=whiteboard_config_provider)
114112
_ = DynamicUIInspector(state_id="dynamic_ui", app=assistant)
115113

116-
attachments_extension = AttachmentsExtension(assistant)
114+
attachments_extension = AttachmentsExtension(assistant, config_provider=document_editor_config_provider)
117115

118116
#
119117
# create the FastAPI app instance
@@ -164,20 +162,20 @@ async def on_message_created(
164162
# update the participant status to indicate the assistant is thinking
165163
async with (
166164
context.set_status("thinking..."),
167-
document_editor_extension.lock_document_edits(context),
165+
attachments_extension.lock_document_edits(context),
168166
):
169167
config = await assistant_config.get(context.assistant)
170168
metadata: dict[str, Any] = {"debug": {"content_safety": event.data.get(content_safety.metadata_key, {})}}
171169

172170
try:
173-
await respond_to_conversation(
171+
responder = await ConversationResponder.create(
174172
message=message,
175-
attachments_extension=attachments_extension,
176-
document_editor_extension=document_editor_extension,
177173
context=context,
178174
config=config,
179175
metadata=metadata,
176+
attachments_extension=attachments_extension,
180177
)
178+
await responder.respond_to_conversation()
181179
except Exception as e:
182180
logger.exception(f"Exception occurred responding to conversation: {e}")
183181
deepmerge.always_merger.merge(metadata, {"debug": {"error": str(e)}})
@@ -211,7 +209,7 @@ async def should_respond_to_message(context: ConversationContext, message: Conve
211209
return False
212210

213211
# if configure to only respond to mentions, ignore messages where the content does not mention the assistant somewhere in the message
214-
if config.response_behavior.only_respond_to_mentions and f"@{context.assistant.name}" not in message.content:
212+
if config.orchestration.options.only_respond_to_mentions and f"@{context.assistant.name}" not in message.content:
215213
# check to see if there are any other assistants in the conversation
216214
participant_list = await context.get_participants()
217215
other_assistants = [
@@ -256,7 +254,7 @@ async def on_conversation_created(context: ConversationContext) -> None:
256254

257255
# send a welcome message to the conversation
258256
config = await assistant_config.get(context.assistant)
259-
welcome_message = config.response_behavior.welcome_message
257+
welcome_message = config.orchestration.prompts.welcome_message
260258
await context.send_messages(
261259
NewConversationMessage(
262260
content=welcome_message,

0 commit comments

Comments
 (0)