Skip to content

Commit 6a84c49

Browse files
committed
excuse tool
1 parent de9df2a commit 6a84c49

18 files changed

Lines changed: 175 additions & 5 deletions

File tree

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ DEBUG_AGENTS=false
8585
FRONTEND_URL=https://chitchats-iota.vercel.app/
8686
# Vercel automatically sets VERCEL_URL environment variable
8787
# Default allowed origins: localhost:5173, localhost:5174
88+
# Community Features
89+
# Set to "true" to enable community social tools (Moltbook)
90+
ENABLE_COMMUNITY=false
91+
8892
EXPERIMENTAL_ASSISTANT_PRIMING=false # it's problematic so make this as false plz
8993

9094
# Codex App Server Mode

backend/chatroom_orchestration/handlers.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ async def save_agent_message(context: MessageContext, message_data: AgentMessage
3131
agent_id=context.agent.id,
3232
thinking=message_data.thinking if message_data.thinking else None,
3333
anthropic_calls=message_data.anthropic_calls if message_data.anthropic_calls else None,
34+
excuse_reasons=message_data.excuse_reasons if message_data.excuse_reasons else None,
3435
)
3536
# Update room activity for agent messages so unread notifications appear
3637
saved_msg = await crud.create_message(context.db, context.room_id, agent_message, update_room_activity=True)

backend/core/manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ async def generate_sdk_response(self, context: AgentResponseContext) -> AsyncIte
382382
base_options = AIClientOptions.from_context(context, final_system_prompt, provider_type)
383383

384384
# Build provider-specific options with tool capture hooks
385-
options = provider.build_options(base_options, accumulator.anthropic_calls, accumulator.skip_tool_capture)
385+
options = provider.build_options(base_options, accumulator.anthropic_calls, accumulator.skip_tool_capture, accumulator.excuse_reasons)
386386

387387
# Build the message content using helper
388388
message_to_send = self._build_message_content(context)

backend/core/response_generator.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ async def generate_response(
154154
new_session_id = session_id
155155
memory_entries = []
156156
anthropic_calls = []
157+
excuse_reasons = []
157158
skipped = False
158159
stream_started = False
159160
end_event = None # Store the end event for later SSE broadcast
@@ -179,6 +180,7 @@ async def generate_response(
179180
new_session_id = end.session_id or session_id
180181
memory_entries = end.memory_entries
181182
anthropic_calls = end.anthropic_calls
183+
excuse_reasons = end.excuse_reasons
182184
skipped = end.skipped
183185

184186
except SessionRecoveryError as e:
@@ -237,6 +239,7 @@ async def generate_response(
237239
new_session_id = end.session_id or session_id
238240
memory_entries = end.memory_entries
239241
anthropic_calls = end.anthropic_calls
242+
excuse_reasons = end.excuse_reasons
240243
skipped = end.skipped
241244

242245
# Memory entries are now written directly by the memorize tool
@@ -317,6 +320,7 @@ async def broadcast_stream_end(is_skipped: bool):
317320
content=response_text,
318321
thinking=thinking_text,
319322
anthropic_calls=anthropic_calls if anthropic_calls else None,
323+
excuse_reasons=excuse_reasons if excuse_reasons else None,
320324
)
321325
await save_agent_message(msg_context, message_data)
322326

backend/core/settings.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ class Settings(BaseSettings):
106106
# Voice server configuration
107107
voice_server_url: str = "http://localhost:8002" # Voice TTS server URL
108108

109+
# Tool toggles
110+
enable_excuse: bool = True # Enable excuse tool for agents
111+
enable_community: bool = False # Enable community social tools (Moltbook)
112+
109113
# Moltbook API configuration
110114
moltbook_api_key: Optional[str] = None # API key for Moltbook social network
111115

backend/crud/messages.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ async def create_message(
4949
participant_type=message.participant_type,
5050
participant_name=message.participant_name,
5151
thinking=message.thinking,
52+
excuse_reasons=json.dumps(message.excuse_reasons) if message.excuse_reasons else None,
5253
images=images_json, # Store as JSON string
5354
# Keep deprecated fields for backward compatibility during transition
5455
image_data=message.image_data,

backend/domain/contexts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class AgentMessageData:
4949
content: str
5050
thinking: Optional[str] = None
5151
anthropic_calls: Optional[list[str]] = None
52+
excuse_reasons: Optional[list[str]] = None
5253

5354

5455
@dataclass

backend/domain/streaming.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class StreamEndEvent:
6969
memory_entries: list[str]
7070
anthropic_calls: list[str]
7171
skipped: bool
72+
excuse_reasons: list[str] = field(default_factory=list)
7273

7374
def to_dict(self) -> dict:
7475
"""Convert to dict for backward compatibility with existing consumers."""
@@ -81,6 +82,7 @@ def to_dict(self) -> dict:
8182
"memory_entries": self.memory_entries,
8283
"anthropic_calls": self.anthropic_calls,
8384
"skipped": self.skipped,
85+
"excuse_reasons": self.excuse_reasons,
8486
}
8587

8688

@@ -106,6 +108,7 @@ class ResponseAccumulator:
106108
skip_tool_called: bool = False
107109
memory_entries: list[str] = field(default_factory=list)
108110
anthropic_calls: list[str] = field(default_factory=list)
111+
excuse_reasons: list[str] = field(default_factory=list)
109112
# Hook capture lists - these get mutated by PostToolUse hooks
110113
skip_tool_capture: list[bool] = field(default_factory=list)
111114

@@ -207,6 +210,7 @@ def create_end_event(
207210
memory_entries=self.memory_entries,
208211
anthropic_calls=self.anthropic_calls,
209212
skipped=skipped,
213+
excuse_reasons=self.excuse_reasons,
210214
)
211215

212216
def create_interrupted_end_event(

backend/infrastructure/database/migrations.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ async def _migrate_messages_table(conn):
148148
("image_data", "TEXT", None),
149149
("image_media_type", "VARCHAR", None),
150150
("anthropic_calls", "TEXT", None),
151+
("excuse_reasons", "TEXT", None), # JSON array of excuse tool reasons
151152
("images", "TEXT", None), # JSON array for multiple images
152153
("provider", "VARCHAR", None), # v9: AI provider used ('claude' or 'codex')
153154
]

backend/infrastructure/database/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class Message(Base):
135135
participant_name = Column(String, nullable=True) # Custom name for 'character' mode
136136
thinking = Column(Text, nullable=True) # Agent's thinking process (for assistant messages)
137137
anthropic_calls = Column(Text, nullable=True) # JSON array of anthropic tool call situations
138+
excuse_reasons = Column(Text, nullable=True) # JSON array of excuse tool reasons
138139
timestamp = Column(DateTime, default=datetime.utcnow)
139140
image_data = Column(Text, nullable=True) # DEPRECATED: Use images column instead
140141
image_media_type = Column(String, nullable=True) # DEPRECATED: Use images column instead

0 commit comments

Comments
 (0)