* Fix self-reply loop issue when using same email for send/receive - Add Message-ID tracking to prevent processing system-sent emails - Track sent emails in sent-messages.json with auto-cleanup - Skip system emails in both email-listener.js and relay-pty.js - Extract session from token/headers/body for proper reply routing - Reduce verbose logging in tmux-injector to debug level Fixes #3 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix working directory issue - enable claude-remote to run from any directory - Use absolute path to load .env file instead of relying on current working directory - Fix environment variable loading in both main program and relay service - Now claude-remote can be executed from any directory Fixes #5 * Fix issue #6: Implement terminal-style UI for email notifications - Redesigned email template with terminal/console aesthetic - Used monospace fonts and dark theme for tech look - Fixed Claude response truncation issue (removed 500 char limit) - Increased tmux buffer capture from 50 to 200 lines - Preserved code formatting (removed space collapsing) - Added terminal-style command prompts and colored output - Created test script for long content validation * Fix terminal UI visual issues - Fixed traffic light buttons spacing (now properly separated) - Changed background from pure black to lighter gray (#f5f5f5) - Terminal content background changed to softer dark (#1a1a1a) - Code blocks background changed to #262626 for better contrast - Improved overall visual hierarchy and readability * Fine-tune traffic light button spacing - Adjusted spacing between buttons from 8px to 6px - Reduced gap after buttons from 20px to 12px - Achieved more natural macOS-like appearance * Use table layout for better email client compatibility - Changed from inline-flex to table layout for traffic light buttons - Set explicit 5px spacing between buttons using table cells - This ensures consistent rendering across different email clients --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
b957cbbcc8
commit
0eb01e6e75
|
|
@ -310,47 +310,77 @@ class EmailChannel extends NotificationChannel {
|
|||
completed: {
|
||||
subject: '[Claude-Code-Remote #{{token}}] Claude Code Task Completed - {{project}}',
|
||||
html: `
|
||||
<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f9f9f9;">
|
||||
<div style="background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
|
||||
<h2 style="color: #2c3e50; margin-top: 0; border-bottom: 2px solid #3498db; padding-bottom: 10px;">
|
||||
🎉 Claude Code Task Completed
|
||||
</h2>
|
||||
<div style="font-family: 'Consolas', 'Monaco', 'Courier New', monospace; background-color: #f5f5f5; padding: 0; margin: 0;">
|
||||
<div style="max-width: 900px; margin: 0 auto; background-color: #1e1e1e; border: 1px solid #333; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);">
|
||||
<!-- Terminal Header -->
|
||||
<div style="background-color: #2d2d2d; padding: 10px 15px; border-bottom: 1px solid #444;">
|
||||
<table style="display: inline-table; vertical-align: middle;" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td style="padding: 0;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ff5f56;"></div></td>
|
||||
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ffbd2e;"></div></td>
|
||||
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #27c93f;"></div></td>
|
||||
<td style="padding: 0 0 0 12px; color: #999; font-size: 14px; white-space: nowrap;">claude-code-remote@{{project}} - Task Completed</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div style="background-color: #ecf0f1; padding: 15px; border-radius: 6px; margin: 20px 0;">
|
||||
<p style="margin: 0; color: #2c3e50;">
|
||||
<strong>Project:</strong> {{projectDir}}<br>
|
||||
<strong>Time:</strong> {{timestamp}}<br>
|
||||
<strong>Status:</strong> {{type}}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="background-color: #fff3e0; padding: 15px; border-radius: 6px; border-left: 4px solid #ff9800; margin: 20px 0;">
|
||||
<h4 style="margin-top: 0; color: #e65100;">📝 Your Question</h4>
|
||||
<p style="margin: 0; color: #2c3e50; font-style: italic;">{{userQuestion}}</p>
|
||||
</div>
|
||||
|
||||
<div style="background-color: #e8f5e8; padding: 15px; border-radius: 6px; border-left: 4px solid #27ae60;">
|
||||
<h4 style="margin-top: 0; color: #27ae60;">🤖 Claude's Response</h4>
|
||||
<p style="margin: 0; color: #2c3e50;">{{claudeResponse}}</p>
|
||||
</div>
|
||||
|
||||
<div style="margin: 25px 0; padding: 20px; background-color: #fff3cd; border-radius: 6px; border-left: 4px solid #ffc107;">
|
||||
<h3 style="margin-top: 0; color: #856404;">💡 How to Continue the Conversation</h3>
|
||||
<p style="margin: 10px 0; color: #856404;">
|
||||
To continue conversation with Claude Code, please <strong>reply to this email</strong> directly and enter your instructions in the email body.
|
||||
</p>
|
||||
<div style="background-color: white; padding: 10px; border-radius: 4px; font-family: monospace; color: #495057;">
|
||||
Example replies:<br>
|
||||
• "Please continue optimizing the code"<br>
|
||||
• "Generate unit tests"<br>
|
||||
• "Explain the purpose of this function"
|
||||
<!-- Terminal Content -->
|
||||
<div style="padding: 20px; background-color: #1a1a1a; min-height: 400px;">
|
||||
<!-- Session Info -->
|
||||
<div style="color: #00ff00; margin-bottom: 20px;">
|
||||
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code status</span><br>
|
||||
<div style="margin-left: 20px; margin-top: 5px; color: #ccc;">
|
||||
<span style="color: #ff9800;">PROJECT:</span> {{projectDir}}<br>
|
||||
<span style="color: #ff9800;">SESSION:</span> #{{token}}<br>
|
||||
<span style="color: #ff9800;">STATUS:</span> <span style="color: #00ff00;">✓ Task Completed</span><br>
|
||||
<span style="color: #ff9800;">TIME:</span> {{timestamp}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Input -->
|
||||
<div style="margin: 20px 0;">
|
||||
<span style="color: #999;">$</span> <span style="color: #00ff00;">cat user_input.txt</span><br>
|
||||
<div style="background-color: #262626; border-left: 3px solid #ff9800; padding: 10px 15px; margin: 10px 0; color: #f0f0f0; white-space: pre-wrap; word-wrap: break-word;">{{userQuestion}}</div>
|
||||
</div>
|
||||
|
||||
<!-- Claude Response -->
|
||||
<div style="margin: 20px 0;">
|
||||
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code execute</span><br>
|
||||
<div style="color: #999; margin: 5px 0;">
|
||||
<span style="color: #00bcd4;">[INFO]</span> Processing request...<br>
|
||||
<span style="color: #00bcd4;">[INFO]</span> Executing task...
|
||||
</div>
|
||||
<div style="background-color: #262626; border-left: 3px solid #00ff00; padding: 15px; margin: 10px 0; color: #f0f0f0; white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word; max-width: 100%; font-size: 14px; line-height: 1.6;">{{claudeResponse}}</div>
|
||||
<div style="color: #00ff00; margin-top: 10px;">
|
||||
<span style="color: #00bcd4;">[SUCCESS]</span> Task completed successfully ✓
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Continue Instructions -->
|
||||
<div style="margin: 30px 0 20px 0; border-top: 1px solid #333; padding-top: 20px;">
|
||||
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code help --continue</span><br>
|
||||
<div style="color: #f0f0f0; margin: 10px 0;">
|
||||
<div style="color: #ff9800; margin-bottom: 10px;">→ TO CONTINUE THIS SESSION:</div>
|
||||
<div style="background-color: #262626; padding: 15px; border: 1px solid #333; margin: 10px 0;">
|
||||
Reply to this email directly with your next instruction.<br><br>
|
||||
<span style="color: #999;">Examples:</span><br>
|
||||
<span style="color: #00ff00;"> • "Add error handling to the function"</span><br>
|
||||
<span style="color: #00ff00;"> • "Write unit tests for this code"</span><br>
|
||||
<span style="color: #00ff00;"> • "Optimize the performance"</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Session Footer -->
|
||||
<div style="color: #666; font-size: 12px; margin-top: 30px; padding-top: 20px; border-top: 1px solid #333;">
|
||||
<span style="color: #999;">$</span> <span style="color: #666;">echo $SESSION_INFO</span><br>
|
||||
<div style="margin-left: 20px; margin-top: 5px;">
|
||||
SESSION_ID={{sessionId}}<br>
|
||||
EXPIRES_IN=24h<br>
|
||||
SECURITY=Do not forward this email<br>
|
||||
POWERED_BY=Claude-Code-Remote
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #dee2e6; font-size: 12px; color: #6c757d;">
|
||||
<p style="margin: 5px 0;">Session ID: <code>{{sessionId}}</code></p>
|
||||
<p style="margin: 5px 0;">🔒 Security note: Please do not forward this email, session will automatically expire after 24 hours</p>
|
||||
<p style="margin: 5px 0;">📧 This is an automated email from Claude-Code-Remote</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -383,36 +413,66 @@ Security Note: Please do not forward this email, session will automatically expi
|
|||
waiting: {
|
||||
subject: '[Claude-Code-Remote #{{token}}] Claude Code Waiting for Input - {{project}}',
|
||||
html: `
|
||||
<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f9f9f9;">
|
||||
<div style="background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
|
||||
<h2 style="color: #2c3e50; margin-top: 0; border-bottom: 2px solid #e74c3c; padding-bottom: 10px;">
|
||||
⏳ Claude Code Waiting for Your Guidance
|
||||
</h2>
|
||||
<div style="font-family: 'Consolas', 'Monaco', 'Courier New', monospace; background-color: #f5f5f5; padding: 0; margin: 0;">
|
||||
<div style="max-width: 900px; margin: 0 auto; background-color: #1e1e1e; border: 1px solid #333; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);">
|
||||
<!-- Terminal Header -->
|
||||
<div style="background-color: #2d2d2d; padding: 10px 15px; border-bottom: 1px solid #444;">
|
||||
<table style="display: inline-table; vertical-align: middle;" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td style="padding: 0;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ff5f56;"></div></td>
|
||||
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ffbd2e;"></div></td>
|
||||
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #27c93f;"></div></td>
|
||||
<td style="padding: 0 0 0 12px; color: #999; font-size: 14px; white-space: nowrap;">claude-code-remote@{{project}} - Waiting for Input</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div style="background-color: #ecf0f1; padding: 15px; border-radius: 6px; margin: 20px 0;">
|
||||
<p style="margin: 0; color: #2c3e50;">
|
||||
<strong>Project:</strong> {{projectDir}}<br>
|
||||
<strong>Time:</strong> {{timestamp}}<br>
|
||||
<strong>Status:</strong> {{type}}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="background-color: #fdf2e9; padding: 15px; border-radius: 6px; border-left: 4px solid #e67e22;">
|
||||
<h4 style="margin-top: 0; color: #e67e22;">⏳ Waiting for Processing</h4>
|
||||
<p style="margin: 0; color: #2c3e50;">{{message}}</p>
|
||||
</div>
|
||||
|
||||
<div style="margin: 25px 0; padding: 20px; background-color: #d1ecf1; border-radius: 6px; border-left: 4px solid #17a2b8;">
|
||||
<h3 style="margin-top: 0; color: #0c5460;">💬 Please Provide Guidance</h3>
|
||||
<p style="margin: 10px 0; color: #0c5460;">
|
||||
Claude needs your further guidance. Please <strong>reply to this email</strong> to tell Claude what to do next.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #dee2e6; font-size: 12px; color: #6c757d;">
|
||||
<p style="margin: 5px 0;">Session ID: <code>{{sessionId}}</code></p>
|
||||
<p style="margin: 5px 0;">🔒 Security note: Please do not forward this email, session will automatically expire after 24 hours</p>
|
||||
<p style="margin: 5px 0;">📧 This is an automated email from Claude-Code-Remote</p>
|
||||
<!-- Terminal Content -->
|
||||
<div style="padding: 20px; background-color: #1a1a1a; min-height: 400px;">
|
||||
<!-- Session Info -->
|
||||
<div style="color: #00ff00; margin-bottom: 20px;">
|
||||
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code status</span><br>
|
||||
<div style="margin-left: 20px; margin-top: 5px; color: #ccc;">
|
||||
<span style="color: #ff9800;">PROJECT:</span> {{projectDir}}<br>
|
||||
<span style="color: #ff9800;">SESSION:</span> #{{token}}<br>
|
||||
<span style="color: #ff9800;">STATUS:</span> <span style="color: #ffeb3b;">⏳ Waiting for input</span><br>
|
||||
<span style="color: #ff9800;">TIME:</span> {{timestamp}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Waiting Message -->
|
||||
<div style="margin: 20px 0;">
|
||||
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code wait</span><br>
|
||||
<div style="color: #ffeb3b; margin: 10px 0;">
|
||||
<span style="color: #ff9800;">[WAITING]</span> Claude needs your input to continue...<br>
|
||||
</div>
|
||||
<div style="background-color: #262626; border-left: 3px solid #ffeb3b; padding: 15px; margin: 10px 0; color: #f0f0f0;">
|
||||
{{message}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Continue Instructions -->
|
||||
<div style="margin: 30px 0 20px 0; border-top: 1px solid #333; padding-top: 20px;">
|
||||
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code help --respond</span><br>
|
||||
<div style="color: #f0f0f0; margin: 10px 0;">
|
||||
<div style="color: #ff9800; margin-bottom: 10px;">→ ACTION REQUIRED:</div>
|
||||
<div style="background-color: #262626; padding: 15px; border: 1px solid #333; margin: 10px 0;">
|
||||
<span style="color: #ffeb3b;">Claude is waiting for your guidance.</span><br><br>
|
||||
Reply to this email with your instructions to continue.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Session Footer -->
|
||||
<div style="color: #666; font-size: 12px; margin-top: 30px; padding-top: 20px; border-top: 1px solid #333;">
|
||||
<span style="color: #999;">$</span> <span style="color: #666;">echo $SESSION_INFO</span><br>
|
||||
<div style="margin-left: 20px; margin-top: 5px;">
|
||||
SESSION_ID={{sessionId}}<br>
|
||||
EXPIRES_IN=24h<br>
|
||||
SECURITY=Do not forward this email<br>
|
||||
POWERED_BY=Claude-Code-Remote
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,38 +1,42 @@
|
|||
[
|
||||
{
|
||||
"id": 1312,
|
||||
"timestamp": 1753632056082
|
||||
"timestamp": 1754021490457
|
||||
},
|
||||
{
|
||||
"id": 1315,
|
||||
"timestamp": 1753632056082
|
||||
"timestamp": 1754021490457
|
||||
},
|
||||
{
|
||||
"id": 1310,
|
||||
"timestamp": 1753632056082
|
||||
"timestamp": 1754021490457
|
||||
},
|
||||
{
|
||||
"id": 1323,
|
||||
"timestamp": 1753632056082
|
||||
"timestamp": 1754021490457
|
||||
},
|
||||
{
|
||||
"id": 1331,
|
||||
"timestamp": 1753632056082
|
||||
"timestamp": 1754021490457
|
||||
},
|
||||
{
|
||||
"id": 1334,
|
||||
"timestamp": 1753632056082
|
||||
"timestamp": 1754021490457
|
||||
},
|
||||
{
|
||||
"id": 1342,
|
||||
"timestamp": 1753632056082
|
||||
"timestamp": 1754021490457
|
||||
},
|
||||
{
|
||||
"id": 1346,
|
||||
"timestamp": 1753632056082
|
||||
"timestamp": 1754021490457
|
||||
},
|
||||
{
|
||||
"id": 1348,
|
||||
"timestamp": 1753632056082
|
||||
"timestamp": 1754021490457
|
||||
},
|
||||
{
|
||||
"id": 180,
|
||||
"timestamp": 1754021490457
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"messages": [
|
||||
{
|
||||
"messageId": "<52d15aa1-d5a4-4d7d-8f01-4752d7d5fc6f-1754021037319@claude-code-remote>",
|
||||
"sessionId": "52d15aa1-d5a4-4d7d-8f01-4752d7d5fc6f",
|
||||
"token": "49WUF9NS",
|
||||
"type": "notification",
|
||||
"sentAt": "2025-08-01T04:03:59.850Z"
|
||||
},
|
||||
{
|
||||
"messageId": "<eba8744e-8cc1-4fad-9dc8-69d558c51cca-1754021210179@claude-code-remote>",
|
||||
"sessionId": "eba8744e-8cc1-4fad-9dc8-69d558c51cca",
|
||||
"token": "N9PHUN4Q",
|
||||
"type": "notification",
|
||||
"sentAt": "2025-08-01T04:06:52.776Z"
|
||||
},
|
||||
{
|
||||
"messageId": "<859daa99-1ea9-4c40-aa68-c3967a0d7e4e-1754021233658@claude-code-remote>",
|
||||
"sessionId": "859daa99-1ea9-4c40-aa68-c3967a0d7e4e",
|
||||
"token": "GXWFSL3S",
|
||||
"type": "notification",
|
||||
"sentAt": "2025-08-01T04:07:15.556Z"
|
||||
},
|
||||
{
|
||||
"messageId": "<a1ed6757-6782-4b22-a486-aab5a9d60a3c-1754021267945@claude-code-remote>",
|
||||
"sessionId": "a1ed6757-6782-4b22-a486-aab5a9d60a3c",
|
||||
"token": "6EZXA6IN",
|
||||
"type": "notification",
|
||||
"sentAt": "2025-08-01T04:07:49.959Z"
|
||||
},
|
||||
{
|
||||
"messageId": "<2122d57c-8434-44f0-b4e6-7eafb40ed49d-1754021285815@claude-code-remote>",
|
||||
"sessionId": "2122d57c-8434-44f0-b4e6-7eafb40ed49d",
|
||||
"token": "ZQY1UOIJ",
|
||||
"type": "notification",
|
||||
"sentAt": "2025-08-01T04:08:07.833Z"
|
||||
},
|
||||
{
|
||||
"messageId": "<2b30b1f7-b9c3-4cb4-b889-11c58009bd07-1754021533703@claude-code-remote>",
|
||||
"sessionId": "2b30b1f7-b9c3-4cb4-b889-11c58009bd07",
|
||||
"token": "L4KQ8DVJ",
|
||||
"type": "notification",
|
||||
"sentAt": "2025-08-01T04:12:15.795Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -529,5 +529,86 @@
|
|||
"sessionId": "4e67ac76-5c0a-4229-b3cd-c4ff865c9df3",
|
||||
"tmuxSession": "video",
|
||||
"description": "completed - Claude-Code-Remote"
|
||||
},
|
||||
"3E0T4KHA": {
|
||||
"type": "pty",
|
||||
"createdAt": 1754020190,
|
||||
"expiresAt": 1754106590,
|
||||
"cwd": "/Users/vaclis./Documents/project/Claude-Code-Remote",
|
||||
"sessionId": "1ce6c5e0-4151-4d51-9472-f481ed23f023",
|
||||
"tmuxSession": "WavJaby",
|
||||
"description": "completed - Claude-Code-Remote"
|
||||
},
|
||||
"8BIFRACK": {
|
||||
"type": "pty",
|
||||
"createdAt": 1754020301,
|
||||
"expiresAt": 1754106701,
|
||||
"cwd": "/Users/vaclis./Documents/project/ReThreads",
|
||||
"sessionId": "0fd97a36-da77-4c9b-917f-6963c0373458",
|
||||
"tmuxSession": "my-project",
|
||||
"description": "completed - ReThreads"
|
||||
},
|
||||
"OG1SS2R9": {
|
||||
"type": "pty",
|
||||
"createdAt": 1754020306,
|
||||
"expiresAt": 1754106706,
|
||||
"cwd": "/Users/vaclis./Documents/project/Claude-Code-Remote",
|
||||
"sessionId": "43b979a7-9039-4d0f-8c09-b86365ef0e61",
|
||||
"tmuxSession": "WavJaby",
|
||||
"description": "completed - Claude-Code-Remote"
|
||||
},
|
||||
"49WUF9NS": {
|
||||
"type": "pty",
|
||||
"createdAt": 1754021037,
|
||||
"expiresAt": 1754107437,
|
||||
"cwd": "/Users/vaclis./Documents/project/Claude-Code-Remote",
|
||||
"sessionId": "52d15aa1-d5a4-4d7d-8f01-4752d7d5fc6f",
|
||||
"tmuxSession": "WavJaby",
|
||||
"description": "completed - Claude-Code-Remote"
|
||||
},
|
||||
"N9PHUN4Q": {
|
||||
"type": "pty",
|
||||
"createdAt": 1754021210,
|
||||
"expiresAt": 1754107610,
|
||||
"cwd": "/Users/vaclis./Documents/project/Claude-Code-Remote",
|
||||
"sessionId": "eba8744e-8cc1-4fad-9dc8-69d558c51cca",
|
||||
"tmuxSession": "test-session",
|
||||
"description": "completed - Claude-Code-Remote-Test"
|
||||
},
|
||||
"GXWFSL3S": {
|
||||
"type": "pty",
|
||||
"createdAt": 1754021233,
|
||||
"expiresAt": 1754107633,
|
||||
"cwd": "/Users/vaclis./Documents/project/Claude-Code-Remote",
|
||||
"sessionId": "859daa99-1ea9-4c40-aa68-c3967a0d7e4e",
|
||||
"tmuxSession": "WavJaby",
|
||||
"description": "completed - Claude-Code-Remote"
|
||||
},
|
||||
"6EZXA6IN": {
|
||||
"type": "pty",
|
||||
"createdAt": 1754021267,
|
||||
"expiresAt": 1754107667,
|
||||
"cwd": "/Users/vaclis./Documents/project/Claude-Code-Remote",
|
||||
"sessionId": "a1ed6757-6782-4b22-a486-aab5a9d60a3c",
|
||||
"tmuxSession": "test-session",
|
||||
"description": "completed - Claude-Code-Remote-Test"
|
||||
},
|
||||
"ZQY1UOIJ": {
|
||||
"type": "pty",
|
||||
"createdAt": 1754021285,
|
||||
"expiresAt": 1754107685,
|
||||
"cwd": "/Users/vaclis./Documents/project/Claude-Code-Remote",
|
||||
"sessionId": "2122d57c-8434-44f0-b4e6-7eafb40ed49d",
|
||||
"tmuxSession": "WavJaby",
|
||||
"description": "completed - Claude-Code-Remote"
|
||||
},
|
||||
"L4KQ8DVJ": {
|
||||
"type": "pty",
|
||||
"createdAt": 1754021533,
|
||||
"expiresAt": 1754107933,
|
||||
"cwd": "/Users/vaclis./Documents/project/Claude-Code-Remote",
|
||||
"sessionId": "2b30b1f7-b9c3-4cb4-b889-11c58009bd07",
|
||||
"tmuxSession": "test-session",
|
||||
"description": "completed - Claude-Code-Remote-Test"
|
||||
}
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ class TmuxMonitor {
|
|||
* @param {number} lines - Number of lines to retrieve
|
||||
* @returns {Object} - { userQuestion, claudeResponse }
|
||||
*/
|
||||
getRecentConversation(sessionName, lines = 50) {
|
||||
getRecentConversation(sessionName, lines = 200) {
|
||||
try {
|
||||
const captureFile = path.join(this.captureDir, `${sessionName}.log`);
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ class TmuxMonitor {
|
|||
* @param {string} sessionName - The tmux session name
|
||||
* @param {number} lines - Number of lines to retrieve
|
||||
*/
|
||||
getFromTmuxBuffer(sessionName, lines = 50) {
|
||||
getFromTmuxBuffer(sessionName, lines = 200) {
|
||||
try {
|
||||
// Capture the pane contents
|
||||
const buffer = execSync(`tmux capture-pane -t ${sessionName} -p -S -${lines}`, {
|
||||
|
|
@ -150,17 +150,18 @@ class TmuxMonitor {
|
|||
// Join response lines and clean up
|
||||
claudeResponse = responseLines.join('\n').trim();
|
||||
|
||||
// Remove box characters and clean up formatting
|
||||
// Remove box characters but preserve formatting
|
||||
claudeResponse = claudeResponse
|
||||
.replace(/[╭╰│]/g, '')
|
||||
.replace(/^\s*│\s*/gm, '')
|
||||
.replace(/\s+/g, ' ')
|
||||
// Don't collapse multiple spaces - preserve code formatting
|
||||
// .replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
|
||||
// Limit response length
|
||||
if (claudeResponse.length > 500) {
|
||||
claudeResponse = claudeResponse.substring(0, 497) + '...';
|
||||
}
|
||||
// Don't limit response length - we want the full response
|
||||
// if (claudeResponse.length > 500) {
|
||||
// claudeResponse = claudeResponse.substring(0, 497) + '...';
|
||||
// }
|
||||
|
||||
// If we didn't find a question in the standard format, look for any recent text input
|
||||
if (!userQuestion) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,142 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Test script for long email content
|
||||
* Tests the new terminal-style email template with long Claude responses
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
require('dotenv').config({ path: path.join(__dirname, '.env') });
|
||||
|
||||
const EmailChannel = require('./src/channels/email/smtp');
|
||||
const ConfigManager = require('./src/core/config');
|
||||
|
||||
async function testLongEmail() {
|
||||
console.log('Testing long email content...\n');
|
||||
|
||||
// Load config
|
||||
const configManager = new ConfigManager();
|
||||
configManager.load();
|
||||
const emailConfig = configManager.getChannel('email');
|
||||
|
||||
if (!emailConfig || !emailConfig.enabled) {
|
||||
console.error('❌ Email channel not configured or disabled');
|
||||
console.log('Please configure email in config/channels.json first');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Create email channel
|
||||
const email = new EmailChannel(emailConfig.config);
|
||||
|
||||
// Create a test notification with very long content
|
||||
const longCodeExample = `
|
||||
function processData(inputArray) {
|
||||
// This is a sample function with detailed implementation
|
||||
const results = [];
|
||||
|
||||
for (let i = 0; i < inputArray.length; i++) {
|
||||
const item = inputArray[i];
|
||||
|
||||
// Validate input
|
||||
if (!item || typeof item !== 'object') {
|
||||
console.warn(\`Invalid item at index \${i}\`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Process each item
|
||||
const processed = {
|
||||
id: item.id || generateId(),
|
||||
name: item.name?.trim() || 'Unknown',
|
||||
timestamp: new Date().toISOString(),
|
||||
data: {
|
||||
original: item,
|
||||
processed: true,
|
||||
metadata: {
|
||||
source: 'test-system',
|
||||
version: '1.0.0',
|
||||
processingTime: Date.now()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Apply transformations
|
||||
if (item.transform) {
|
||||
processed.data.transformed = applyTransform(item.transform, item);
|
||||
}
|
||||
|
||||
results.push(processed);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
function generateId() {
|
||||
return 'id_' + Math.random().toString(36).substr(2, 9);
|
||||
}
|
||||
|
||||
function applyTransform(transformType, data) {
|
||||
switch (transformType) {
|
||||
case 'uppercase':
|
||||
return JSON.stringify(data).toUpperCase();
|
||||
case 'reverse':
|
||||
return JSON.stringify(data).split('').reverse().join('');
|
||||
default:
|
||||
return data;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const testNotification = {
|
||||
type: 'completed',
|
||||
title: 'Test Long Content',
|
||||
message: 'Testing terminal-style email with long Claude response',
|
||||
project: 'Claude-Code-Remote-Test',
|
||||
metadata: {
|
||||
userQuestion: 'Please help me implement a data processing function with error handling, validation, and transformation features',
|
||||
claudeResponse: `I'll help you implement a comprehensive data processing function. Here's a complete implementation with all the features you requested:
|
||||
|
||||
${longCodeExample}
|
||||
|
||||
This implementation includes:
|
||||
|
||||
1. **Input Validation**: The function checks each item to ensure it's a valid object before processing.
|
||||
|
||||
2. **Error Handling**: Uses try-catch blocks and console warnings for invalid items.
|
||||
|
||||
3. **Data Transformation**: Supports different transformation types through the \`applyTransform\` function.
|
||||
|
||||
4. **Metadata Tracking**: Each processed item includes metadata about when and how it was processed.
|
||||
|
||||
5. **ID Generation**: Automatically generates unique IDs for items that don't have one.
|
||||
|
||||
Additional features you might want to consider:
|
||||
|
||||
- **Async Processing**: For handling large datasets or async transformations
|
||||
- **Batch Processing**: Process items in chunks to avoid memory issues
|
||||
- **Progress Tracking**: Add callbacks or events to track processing progress
|
||||
- **Custom Validators**: Allow custom validation functions to be passed in
|
||||
- **Error Recovery**: Implement retry logic for failed items
|
||||
|
||||
The function is designed to be extensible and maintainable. You can easily add new transformation types or modify the processing logic as needed.`,
|
||||
tmuxSession: 'test-session'
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
console.log('Sending test email with long content...');
|
||||
const result = await email._sendImpl(testNotification);
|
||||
|
||||
if (result) {
|
||||
console.log('✅ Email sent successfully!');
|
||||
console.log('Check your inbox for the terminal-style email');
|
||||
} else {
|
||||
console.log('❌ Failed to send email');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Error:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Run test
|
||||
testLongEmail();
|
||||
Loading…
Reference in New Issue