Skip to content

Commit dd26333

Browse files
committed
feat: integrate browser live view with canvas panel
1 parent 4659bae commit dd26333

33 files changed

+1373
-602
lines changed

chatbot-app/agentcore/src/agent/config/swarm_config.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@
7474
"browser_extract",
7575
"browser_get_page_info",
7676
"browser_manage_tabs",
77-
"browser_drag",
7877
"browser_save_screenshot",
7978
],
8079
"weather_agent": [

chatbot-app/agentcore/src/agent/gateway/mcp_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def call_tool_sync(self, tool_use_id: str, name: str, arguments: dict):
154154
# Inject user API keys into arguments (Lambda will extract these)
155155
if self.api_keys:
156156
arguments = {**arguments, '__user_api_keys': self.api_keys}
157-
logger.debug(f"Injected user API keys into tool arguments: {list(self.api_keys.keys())}")
157+
logger.debug("Injected user API keys into tool arguments")
158158

159159
return super().call_tool_sync(tool_use_id, actual_name, arguments)
160160

@@ -304,7 +304,7 @@ def create_filtered_gateway_client(
304304
# Create FilteredMCPClient with tool filtering and API keys
305305
logger.debug(f"Creating FilteredMCPClient with {len(gateway_tool_ids)} enabled tool IDs")
306306
if api_keys:
307-
logger.debug(f" User API keys provided: {list(api_keys.keys())}")
307+
logger.debug(f" User API keys provided: {len(api_keys)} key(s)")
308308

309309
mcp_client = FilteredMCPClient(
310310
lambda: streamablehttp_client(

chatbot-app/agentcore/src/agent/session/local_session_buffer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,11 @@ def append_message(self, message, agent, **kwargs):
8282

8383
# Add to buffer
8484
self.pending_messages.append(message_dict)
85-
logger.debug(f"📝 Buffered message (role={message_dict['role']}, total={len(self.pending_messages)})")
85+
logger.debug(f"Buffered message (role={message_dict['role']}, total={len(self.pending_messages)})")
8686

8787
# Periodic flush to prevent data loss
8888
if len(self.pending_messages) >= self.batch_size:
89-
logger.info(f"Batch size ({self.batch_size}) reached, flushing buffer")
89+
logger.info(f"Batch size ({self.batch_size}) reached, flushing buffer")
9090
self.flush()
9191

9292
def flush(self):

chatbot-app/agentcore/src/agents/chat_agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ async def stream_async(self, message: str, session_id: str = None, files: Option
327327
effective_api_keys = api_keys or self.api_keys
328328
if effective_api_keys:
329329
invocation_state['api_keys'] = effective_api_keys
330-
logger.debug(f"Added API keys to invocation_state: {list(effective_api_keys.keys())}")
330+
logger.debug(f"Added API keys to invocation_state: {len(effective_api_keys)} key(s)")
331331

332332
# Update Gateway client's api_keys for tool calls
333333
if self.gateway_client and hasattr(self.gateway_client, 'api_keys'):

chatbot-app/agentcore/src/builtin_tools/__init__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
- Excel Spreadsheets: Create, modify, and manage Excel spreadsheets with persistent storage
88
- PowerPoint Presentations: Create, modify, and manage PowerPoint presentations with persistent storage
99
10-
⚠️ IMPORTANT: When adding a NEW TOOL, you MUST complete ALL 3 steps:
10+
IMPORTANT: When adding a NEW TOOL, you MUST complete ALL 3 steps:
1111
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1212
1. Add tool import and export in THIS file (__init__.py)
1313
2. Add tool definition in: chatbot-app/frontend/src/config/tools-config.json
@@ -26,7 +26,7 @@
2626
from .artifact_editor_tool import update_artifact
2727

2828
# Nova Act browser tools
29-
from .nova_act_browser_tools import browser_navigate, browser_act, browser_extract, browser_get_page_info, browser_manage_tabs, browser_drag, browser_save_screenshot
29+
from .nova_act_browser_tools import browser_navigate, browser_act, browser_extract, browser_get_page_info, browser_manage_tabs, browser_save_screenshot
3030

3131
from .word_document_tool import (
3232
create_word_document,
@@ -64,7 +64,6 @@
6464
'browser_extract',
6565
'browser_get_page_info',
6666
'browser_manage_tabs',
67-
'browser_drag',
6867
'browser_save_screenshot',
6968
'create_word_document',
7069
'modify_word_document',
@@ -124,6 +123,5 @@
124123
browser_extract,
125124
browser_get_page_info,
126125
browser_manage_tabs,
127-
browser_drag,
128126
browser_save_screenshot,
129127
])

chatbot-app/agentcore/src/builtin_tools/diagram_tool.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def generate_diagram_and_validate(
7979
Diagram as image in ToolResult format:
8080
{
8181
"content": [
82-
{"text": "Diagram generated: ..."},
82+
{"text": "Diagram generated: ..."},
8383
{"image": {"format": "png", "source": {"bytes": b"..."}}}
8484
],
8585
"status": "success"
@@ -94,7 +94,7 @@ def generate_diagram_and_validate(
9494
if not diagram_filename or not diagram_filename.endswith('.png'):
9595
return {
9696
"content": [{
97-
"text": f"Invalid filename. Must end with .png (e.g., 'my_diagram.png')\nYou provided: {diagram_filename}"
97+
"text": f"Invalid filename. Must end with .png (e.g., 'my_diagram.png')\nYou provided: {diagram_filename}"
9898
}],
9999
"status": "error"
100100
}
@@ -108,7 +108,7 @@ def generate_diagram_and_validate(
108108
if not code_interpreter_id:
109109
return {
110110
"content": [{
111-
"text": """Custom Code Interpreter ID not found.
111+
"text": """Custom Code Interpreter ID not found.
112112
113113
Code Interpreter tools require Custom Code Interpreter.
114114
Please deploy AgentCore Runtime Stack to create Custom Code Interpreter."""
@@ -147,7 +147,7 @@ def generate_diagram_and_validate(
147147

148148
return {
149149
"content": [{
150-
"text": f"""Python code execution failed
150+
"text": f"""Python code execution failed
151151
152152
**Error Output:**
153153
```
@@ -172,7 +172,7 @@ def generate_diagram_and_validate(
172172
code_interpreter.stop()
173173
return {
174174
"content": [{
175-
"text": """No result from Bedrock Code Interpreter
175+
"text": """No result from Bedrock Code Interpreter
176176
177177
The code was sent but no result was returned.
178178
Please try again or simplify your code."""
@@ -236,7 +236,7 @@ def generate_diagram_and_validate(
236236

237237
return {
238238
"content": [{
239-
"text": f"""Failed to download diagram file
239+
"text": f"""Failed to download diagram file
240240
241241
**Error:** Could not download '{diagram_filename}'
242242
**Exception:** {str(e)}
@@ -269,7 +269,7 @@ def generate_diagram_and_validate(
269269
return {
270270
"content": [
271271
{
272-
"text": f"""**Diagram generated: {diagram_filename}**
272+
"text": f"""**Diagram generated: {diagram_filename}**
273273
274274
Saved to workspace for reuse in documents.
275275
**Size:** {file_size_kb:.1f} KB
@@ -295,7 +295,7 @@ def generate_diagram_and_validate(
295295

296296
return {
297297
"content": [{
298-
"text": f"""Failed to generate diagram
298+
"text": f"""Failed to generate diagram
299299
300300
**Error:** {str(e)}
301301

chatbot-app/agentcore/src/builtin_tools/excel_spreadsheet_tool.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ def create_excel_spreadsheet(
354354
if not is_valid:
355355
return {
356356
"content": [{
357-
"text": f"**Invalid spreadsheet name**: {spreadsheet_name}\n\n{error_msg}\n\n**Examples of valid names:**\n- sales-report\n- Q4-data\n- inventory-2024"
357+
"text": f"**Invalid spreadsheet name**: {spreadsheet_name}\n\n{error_msg}\n\n**Examples of valid names:**\n- sales-report\n- Q4-data\n- inventory-2024"
358358
}],
359359
"status": "error"
360360
}
@@ -374,7 +374,7 @@ def create_excel_spreadsheet(
374374
if not code_interpreter_id:
375375
return {
376376
"content": [{
377-
"text": "**Code Interpreter not configured**\n\nCODE_INTERPRETER_ID not found in environment or Parameter Store."
377+
"text": "**Code Interpreter not configured**\n\nCODE_INTERPRETER_ID not found in environment or Parameter Store."
378378
}],
379379
"status": "error"
380380
}
@@ -427,7 +427,7 @@ def create_excel_spreadsheet(
427427
code_interpreter.stop()
428428
return {
429429
"content": [{
430-
"text": f"**Failed to create spreadsheet**\n\n```\n{error_msg[:1000]}\n```\n\n💡 Check your openpyxl code for syntax errors or incorrect API usage."
430+
"text": f"**Failed to create spreadsheet**\n\n```\n{error_msg[:1000]}\n```\n\nTip:Check your openpyxl code for syntax errors or incorrect API usage."
431431
}],
432432
"status": "error"
433433
}
@@ -459,7 +459,7 @@ def create_excel_spreadsheet(
459459
workspace_docs = doc_manager.list_s3_documents()
460460
other_files_count = len([d for d in workspace_docs if d['filename'] != spreadsheet_filename])
461461

462-
message = f"""**Spreadsheet created successfully**
462+
message = f"""**Spreadsheet created successfully**
463463
464464
**File**: {spreadsheet_filename} ({s3_info['size_kb']})
465465
**Other files in workspace**: {other_files_count} spreadsheet{'s' if other_files_count != 1 else ''}"""
@@ -483,7 +483,7 @@ def create_excel_spreadsheet(
483483
logger.error(f"create_excel_spreadsheet failed: {e}")
484484
return {
485485
"content": [{
486-
"text": f"**Failed to create spreadsheet**\n\n{str(e)}"
486+
"text": f"**Failed to create spreadsheet**\n\n{str(e)}"
487487
}],
488488
"status": "error"
489489
}
@@ -595,7 +595,7 @@ def modify_excel_spreadsheet(
595595
if not is_valid:
596596
return {
597597
"content": [{
598-
"text": f"**Invalid output name**: {output_name}\n\n{error_msg}\n\n**Examples of valid names:**\n- sales-report-v2\n- Q4-data-final\n- report-revised"
598+
"text": f"**Invalid output name**: {output_name}\n\n{error_msg}\n\n**Examples of valid names:**\n- sales-report-v2\n- Q4-data-final\n- report-revised"
599599
}],
600600
"status": "error"
601601
}
@@ -604,7 +604,7 @@ def modify_excel_spreadsheet(
604604
if source_name == output_name:
605605
return {
606606
"content": [{
607-
"text": f"**Invalid name**\n\nOutput name must be different from source name to preserve the original.\n\nSource: {source_name}\nOutput: {output_name}\n\n💡 Try: \"{source_name}-v2\""
607+
"text": f"**Invalid name**\n\nOutput name must be different from source name to preserve the original.\n\nSource: {source_name}\nOutput: {output_name}\n\nTip:Try: \"{source_name}-v2\""
608608
}],
609609
"status": "error"
610610
}
@@ -625,7 +625,7 @@ def modify_excel_spreadsheet(
625625
if not code_interpreter_id:
626626
return {
627627
"content": [{
628-
"text": "**Code Interpreter not configured**\n\nCODE_INTERPRETER_ID not found in environment or Parameter Store."
628+
"text": "**Code Interpreter not configured**\n\nCODE_INTERPRETER_ID not found in environment or Parameter Store."
629629
}],
630630
"status": "error"
631631
}
@@ -680,7 +680,7 @@ def modify_excel_spreadsheet(
680680
code_interpreter.stop()
681681
return {
682682
"content": [{
683-
"text": f"**Modification failed**\n\n```\n{error_msg[:1000]}\n```\n\n💡 Check your openpyxl code for syntax errors or incorrect API usage."
683+
"text": f"**Modification failed**\n\n```\n{error_msg[:1000]}\n```\n\nTip:Check your openpyxl code for syntax errors or incorrect API usage."
684684
}],
685685
"status": "error"
686686
}
@@ -717,7 +717,7 @@ def modify_excel_spreadsheet(
717717
other_files_count = len([d for d in workspace_docs if d['filename'] != output_filename])
718718

719719
# Build success message
720-
message = f"""**Spreadsheet modified successfully**
720+
message = f"""**Spreadsheet modified successfully**
721721
722722
**Source**: {source_filename}
723723
**Saved as**: {output_filename} ({s3_info['size_kb']})
@@ -742,15 +742,15 @@ def modify_excel_spreadsheet(
742742
logger.error(f"Spreadsheet not found: {e}")
743743
return {
744744
"content": [{
745-
"text": f"**Spreadsheet not found**: {source_filename}"
745+
"text": f"**Spreadsheet not found**: {source_filename}"
746746
}],
747747
"status": "error"
748748
}
749749
except Exception as e:
750750
logger.error(f"modify_excel_spreadsheet failed: {e}")
751751
return {
752752
"content": [{
753-
"text": f"**Failed to modify spreadsheet**\n\n{str(e)}"
753+
"text": f"**Failed to modify spreadsheet**\n\n{str(e)}"
754754
}],
755755
"status": "error"
756756
}
@@ -791,7 +791,7 @@ def list_my_excel_spreadsheets(
791791
AI: "I found these spreadsheets: ... Which one should I modify?"
792792
793793
Example Output:
794-
📁 Workspace (3 spreadsheets):
794+
Workspace (3 spreadsheets):
795795
- sales-report.xlsx (52.3 KB) - Modified: 2025-01-15
796796
- inventory.xlsx (41.8 KB) - Modified: 2025-01-14
797797
- Q4-analysis.xlsx (89.2 KB) - Modified: 2025-01-13
@@ -843,7 +843,7 @@ def list_my_excel_spreadsheets(
843843
logger.error(f"list_my_excel_spreadsheets failed: {e}")
844844
return {
845845
"content": [{
846-
"text": f"**Failed to list spreadsheets**\n\n{str(e)}"
846+
"text": f"**Failed to list spreadsheets**\n\n{str(e)}"
847847
}],
848848
"status": "error"
849849
}
@@ -922,7 +922,7 @@ def read_excel_spreadsheet(
922922
if not code_interpreter_id:
923923
return {
924924
"content": [{
925-
"text": "**Code Interpreter not configured**\n\nCODE_INTERPRETER_ID not found in environment or Parameter Store."
925+
"text": "**Code Interpreter not configured**\n\nCODE_INTERPRETER_ID not found in environment or Parameter Store."
926926
}],
927927
"status": "error"
928928
}
@@ -993,7 +993,7 @@ def read_excel_spreadsheet(
993993
code_interpreter.stop()
994994
return {
995995
"content": [{
996-
"text": f"**Failed to read spreadsheet**\n\n```\n{error_msg[:1000]}\n```"
996+
"text": f"**Failed to read spreadsheet**\n\n```\n{error_msg[:1000]}\n```"
997997
}],
998998
"status": "error"
999999
}
@@ -1009,7 +1009,7 @@ def read_excel_spreadsheet(
10091009
# Format output text
10101010
output_parts = []
10111011
props = spreadsheet_content.get("properties", {})
1012-
output_parts.append(f"📊 **Spreadsheet Content**: {spreadsheet_filename} ({doc_info['size_kb']})")
1012+
output_parts.append(f"**Spreadsheet Content**: {spreadsheet_filename} ({doc_info['size_kb']})")
10131013
output_parts.append(f"**Sheets**: {', '.join(props.get('sheet_names', []))}")
10141014
output_parts.append("")
10151015

@@ -1069,15 +1069,15 @@ def read_excel_spreadsheet(
10691069
logger.error(f"Spreadsheet not found: {e}")
10701070
return {
10711071
"content": [{
1072-
"text": f"**Spreadsheet not found**: {spreadsheet_filename}"
1072+
"text": f"**Spreadsheet not found**: {spreadsheet_filename}"
10731073
}],
10741074
"status": "error"
10751075
}
10761076
except Exception as e:
10771077
logger.error(f"read_excel_spreadsheet failed: {e}")
10781078
return {
10791079
"content": [{
1080-
"text": f"**Failed to read spreadsheet**\n\n{str(e)}"
1080+
"text": f"**Failed to read spreadsheet**\n\n{str(e)}"
10811081
}],
10821082
"status": "error"
10831083
}
@@ -1132,7 +1132,7 @@ def preview_excel_sheets(
11321132
available = [d['filename'] for d in documents]
11331133
return {
11341134
"content": [{
1135-
"text": f"**Spreadsheet not found**: {spreadsheet_filename}\n\n"
1135+
"text": f"**Spreadsheet not found**: {spreadsheet_filename}\n\n"
11361136
f"Available spreadsheets: {', '.join(available) if available else 'None'}"
11371137
}],
11381138
"status": "error"
@@ -1162,7 +1162,7 @@ def preview_excel_sheets(
11621162
if invalid_sheets:
11631163
return {
11641164
"content": [{
1165-
"text": f"**Sheet(s) not found**: {', '.join(invalid_sheets)}\n\n"
1165+
"text": f"**Sheet(s) not found**: {', '.join(invalid_sheets)}\n\n"
11661166
f"Available sheets: {', '.join(all_sheet_names)}"
11671167
}],
11681168
"status": "error"
@@ -1182,7 +1182,7 @@ def preview_excel_sheets(
11821182
logger.error(f"LibreOffice conversion failed: {result.stderr}")
11831183
return {
11841184
"content": [{
1185-
"text": f"**PDF conversion failed**\n\n{result.stderr}"
1185+
"text": f"**PDF conversion failed**\n\n{result.stderr}"
11861186
}],
11871187
"status": "error"
11881188
}
@@ -1192,7 +1192,7 @@ def preview_excel_sheets(
11921192
if not os.path.exists(pdf_path):
11931193
return {
11941194
"content": [{
1195-
"text": "**PDF file not created**\n\nLibreOffice conversion may have failed silently."
1195+
"text": "**PDF file not created**\n\nLibreOffice conversion may have failed silently."
11961196
}],
11971197
"status": "error"
11981198
}
@@ -1260,15 +1260,15 @@ def preview_excel_sheets(
12601260
logger.error("LibreOffice conversion timed out")
12611261
return {
12621262
"content": [{
1263-
"text": "**Conversion timed out**\n\nThe spreadsheet may be too large or complex."
1263+
"text": "**Conversion timed out**\n\nThe spreadsheet may be too large or complex."
12641264
}],
12651265
"status": "error"
12661266
}
12671267
except Exception as e:
12681268
logger.error(f"preview_excel_sheets failed: {e}")
12691269
return {
12701270
"content": [{
1271-
"text": f"**Failed to generate preview**\n\n{str(e)}"
1271+
"text": f"**Failed to generate preview**\n\n{str(e)}"
12721272
}],
12731273
"status": "error"
12741274
}

0 commit comments

Comments
 (0)