@jsayubi/ccgram 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +19 -0
- package/LICENSE +21 -0
- package/README.md +338 -0
- package/ccgram.service +24 -0
- package/config/channels.json +58 -0
- package/config/default.json +27 -0
- package/config/defaults/config.json +16 -0
- package/config/defaults/i18n.json +32 -0
- package/config/email-template.json +31 -0
- package/config/test-with-subagent.json +16 -0
- package/config/user.json +27 -0
- package/dist/claude-hook-notify.d.ts +7 -0
- package/dist/claude-hook-notify.d.ts.map +1 -0
- package/dist/claude-hook-notify.js +154 -0
- package/dist/claude-hook-notify.js.map +1 -0
- package/dist/claude-remote.d.ts +50 -0
- package/dist/claude-remote.d.ts.map +1 -0
- package/dist/claude-remote.js +927 -0
- package/dist/claude-remote.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +110 -0
- package/dist/cli.js.map +1 -0
- package/dist/enhanced-hook-notify.d.ts +16 -0
- package/dist/enhanced-hook-notify.d.ts.map +1 -0
- package/dist/enhanced-hook-notify.js +288 -0
- package/dist/enhanced-hook-notify.js.map +1 -0
- package/dist/permission-hook.d.ts +15 -0
- package/dist/permission-hook.d.ts.map +1 -0
- package/dist/permission-hook.js +357 -0
- package/dist/permission-hook.js.map +1 -0
- package/dist/prompt-bridge.d.ts +50 -0
- package/dist/prompt-bridge.d.ts.map +1 -0
- package/dist/prompt-bridge.js +173 -0
- package/dist/prompt-bridge.js.map +1 -0
- package/dist/question-notify.d.ts +16 -0
- package/dist/question-notify.d.ts.map +1 -0
- package/dist/question-notify.js +272 -0
- package/dist/question-notify.js.map +1 -0
- package/dist/setup.d.ts +10 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +649 -0
- package/dist/setup.js.map +1 -0
- package/dist/smart-monitor.d.ts +7 -0
- package/dist/smart-monitor.d.ts.map +1 -0
- package/dist/smart-monitor.js +256 -0
- package/dist/smart-monitor.js.map +1 -0
- package/dist/src/automation/claude-automation.d.ts +45 -0
- package/dist/src/automation/claude-automation.d.ts.map +1 -0
- package/dist/src/automation/claude-automation.js +367 -0
- package/dist/src/automation/claude-automation.js.map +1 -0
- package/dist/src/automation/clipboard-automation.d.ts +35 -0
- package/dist/src/automation/clipboard-automation.d.ts.map +1 -0
- package/dist/src/automation/clipboard-automation.js +242 -0
- package/dist/src/automation/clipboard-automation.js.map +1 -0
- package/dist/src/automation/simple-automation.d.ts +56 -0
- package/dist/src/automation/simple-automation.d.ts.map +1 -0
- package/dist/src/automation/simple-automation.js +283 -0
- package/dist/src/automation/simple-automation.js.map +1 -0
- package/dist/src/channels/base/channel.d.ts +60 -0
- package/dist/src/channels/base/channel.d.ts.map +1 -0
- package/dist/src/channels/base/channel.js +96 -0
- package/dist/src/channels/base/channel.js.map +1 -0
- package/dist/src/channels/email/smtp.d.ts +74 -0
- package/dist/src/channels/email/smtp.d.ts.map +1 -0
- package/dist/src/channels/email/smtp.js +605 -0
- package/dist/src/channels/email/smtp.js.map +1 -0
- package/dist/src/channels/line/line.d.ts +36 -0
- package/dist/src/channels/line/line.d.ts.map +1 -0
- package/dist/src/channels/line/line.js +180 -0
- package/dist/src/channels/line/line.js.map +1 -0
- package/dist/src/channels/line/webhook.d.ts +55 -0
- package/dist/src/channels/line/webhook.d.ts.map +1 -0
- package/dist/src/channels/line/webhook.js +191 -0
- package/dist/src/channels/line/webhook.js.map +1 -0
- package/dist/src/channels/local/desktop.d.ts +30 -0
- package/dist/src/channels/local/desktop.d.ts.map +1 -0
- package/dist/src/channels/local/desktop.js +161 -0
- package/dist/src/channels/local/desktop.js.map +1 -0
- package/dist/src/channels/telegram/telegram.d.ts +43 -0
- package/dist/src/channels/telegram/telegram.d.ts.map +1 -0
- package/dist/src/channels/telegram/telegram.js +223 -0
- package/dist/src/channels/telegram/telegram.js.map +1 -0
- package/dist/src/channels/telegram/webhook.d.ts +75 -0
- package/dist/src/channels/telegram/webhook.d.ts.map +1 -0
- package/dist/src/channels/telegram/webhook.js +278 -0
- package/dist/src/channels/telegram/webhook.js.map +1 -0
- package/dist/src/config-manager.d.ts +16 -0
- package/dist/src/config-manager.d.ts.map +1 -0
- package/dist/src/config-manager.js +152 -0
- package/dist/src/config-manager.js.map +1 -0
- package/dist/src/core/config.d.ts +28 -0
- package/dist/src/core/config.d.ts.map +1 -0
- package/dist/src/core/config.js +248 -0
- package/dist/src/core/config.js.map +1 -0
- package/dist/src/core/logger.d.ts +19 -0
- package/dist/src/core/logger.d.ts.map +1 -0
- package/dist/src/core/logger.js +47 -0
- package/dist/src/core/logger.js.map +1 -0
- package/dist/src/core/notifier.d.ts +45 -0
- package/dist/src/core/notifier.d.ts.map +1 -0
- package/dist/src/core/notifier.js +189 -0
- package/dist/src/core/notifier.js.map +1 -0
- package/dist/src/daemon/taskping-daemon.d.ts +38 -0
- package/dist/src/daemon/taskping-daemon.d.ts.map +1 -0
- package/dist/src/daemon/taskping-daemon.js +306 -0
- package/dist/src/daemon/taskping-daemon.js.map +1 -0
- package/dist/src/relay/claude-command-bridge.d.ts +57 -0
- package/dist/src/relay/claude-command-bridge.d.ts.map +1 -0
- package/dist/src/relay/claude-command-bridge.js +188 -0
- package/dist/src/relay/claude-command-bridge.js.map +1 -0
- package/dist/src/relay/command-relay.d.ts +94 -0
- package/dist/src/relay/command-relay.d.ts.map +1 -0
- package/dist/src/relay/command-relay.js +463 -0
- package/dist/src/relay/command-relay.js.map +1 -0
- package/dist/src/relay/email-listener.d.ts +65 -0
- package/dist/src/relay/email-listener.d.ts.map +1 -0
- package/dist/src/relay/email-listener.js +460 -0
- package/dist/src/relay/email-listener.js.map +1 -0
- package/dist/src/relay/relay-pty.d.ts +21 -0
- package/dist/src/relay/relay-pty.d.ts.map +1 -0
- package/dist/src/relay/relay-pty.js +696 -0
- package/dist/src/relay/relay-pty.js.map +1 -0
- package/dist/src/relay/smart-injector.d.ts +30 -0
- package/dist/src/relay/smart-injector.d.ts.map +1 -0
- package/dist/src/relay/smart-injector.js +233 -0
- package/dist/src/relay/smart-injector.js.map +1 -0
- package/dist/src/relay/tmux-injector.d.ts +46 -0
- package/dist/src/relay/tmux-injector.d.ts.map +1 -0
- package/dist/src/relay/tmux-injector.js +413 -0
- package/dist/src/relay/tmux-injector.js.map +1 -0
- package/dist/src/tools/config-manager.d.ts +33 -0
- package/dist/src/tools/config-manager.d.ts.map +1 -0
- package/dist/src/tools/config-manager.js +448 -0
- package/dist/src/tools/config-manager.js.map +1 -0
- package/dist/src/tools/installer.d.ts +38 -0
- package/dist/src/tools/installer.d.ts.map +1 -0
- package/dist/src/tools/installer.js +222 -0
- package/dist/src/tools/installer.js.map +1 -0
- package/dist/src/types/callbacks.d.ts +29 -0
- package/dist/src/types/callbacks.d.ts.map +1 -0
- package/dist/src/types/callbacks.js +7 -0
- package/dist/src/types/callbacks.js.map +1 -0
- package/dist/src/types/config.d.ts +56 -0
- package/dist/src/types/config.d.ts.map +1 -0
- package/dist/src/types/config.js +6 -0
- package/dist/src/types/config.js.map +1 -0
- package/dist/src/types/hooks.d.ts +47 -0
- package/dist/src/types/hooks.d.ts.map +1 -0
- package/dist/src/types/hooks.js +6 -0
- package/dist/src/types/hooks.js.map +1 -0
- package/dist/src/types/index.d.ts +7 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +23 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/ipc.d.ts +43 -0
- package/dist/src/types/ipc.d.ts.map +1 -0
- package/dist/src/types/ipc.js +7 -0
- package/dist/src/types/ipc.js.map +1 -0
- package/dist/src/types/session.d.ts +70 -0
- package/dist/src/types/session.d.ts.map +1 -0
- package/dist/src/types/session.js +9 -0
- package/dist/src/types/session.js.map +1 -0
- package/dist/src/types/telegram.d.ts +58 -0
- package/dist/src/types/telegram.d.ts.map +1 -0
- package/dist/src/types/telegram.js +6 -0
- package/dist/src/types/telegram.js.map +1 -0
- package/dist/src/utils/active-check.d.ts +19 -0
- package/dist/src/utils/active-check.d.ts.map +1 -0
- package/dist/src/utils/active-check.js +41 -0
- package/dist/src/utils/active-check.js.map +1 -0
- package/dist/src/utils/callback-parser.d.ts +21 -0
- package/dist/src/utils/callback-parser.d.ts.map +1 -0
- package/dist/src/utils/callback-parser.js +58 -0
- package/dist/src/utils/callback-parser.js.map +1 -0
- package/dist/src/utils/controller-injector.d.ts +21 -0
- package/dist/src/utils/controller-injector.d.ts.map +1 -0
- package/dist/src/utils/controller-injector.js +108 -0
- package/dist/src/utils/controller-injector.js.map +1 -0
- package/dist/src/utils/conversation-tracker.d.ts +32 -0
- package/dist/src/utils/conversation-tracker.d.ts.map +1 -0
- package/dist/src/utils/conversation-tracker.js +119 -0
- package/dist/src/utils/conversation-tracker.js.map +1 -0
- package/dist/src/utils/http-request.d.ts +25 -0
- package/dist/src/utils/http-request.d.ts.map +1 -0
- package/dist/src/utils/http-request.js +66 -0
- package/dist/src/utils/http-request.js.map +1 -0
- package/dist/src/utils/optional-require.d.ts +13 -0
- package/dist/src/utils/optional-require.d.ts.map +1 -0
- package/dist/src/utils/optional-require.js +37 -0
- package/dist/src/utils/optional-require.js.map +1 -0
- package/dist/src/utils/paths.d.ts +11 -0
- package/dist/src/utils/paths.d.ts.map +1 -0
- package/dist/src/utils/paths.js +28 -0
- package/dist/src/utils/paths.js.map +1 -0
- package/dist/src/utils/pty-session-manager.d.ts +42 -0
- package/dist/src/utils/pty-session-manager.d.ts.map +1 -0
- package/dist/src/utils/pty-session-manager.js +182 -0
- package/dist/src/utils/pty-session-manager.js.map +1 -0
- package/dist/src/utils/subagent-tracker.d.ts +64 -0
- package/dist/src/utils/subagent-tracker.d.ts.map +1 -0
- package/dist/src/utils/subagent-tracker.js +191 -0
- package/dist/src/utils/subagent-tracker.js.map +1 -0
- package/dist/src/utils/tmux-monitor.d.ts +102 -0
- package/dist/src/utils/tmux-monitor.d.ts.map +1 -0
- package/dist/src/utils/tmux-monitor.js +642 -0
- package/dist/src/utils/tmux-monitor.js.map +1 -0
- package/dist/src/utils/trace-capture.d.ts +42 -0
- package/dist/src/utils/trace-capture.d.ts.map +1 -0
- package/dist/src/utils/trace-capture.js +102 -0
- package/dist/src/utils/trace-capture.js.map +1 -0
- package/dist/start-all-webhooks.d.ts +7 -0
- package/dist/start-all-webhooks.d.ts.map +1 -0
- package/dist/start-all-webhooks.js +98 -0
- package/dist/start-all-webhooks.js.map +1 -0
- package/dist/start-line-webhook.d.ts +7 -0
- package/dist/start-line-webhook.d.ts.map +1 -0
- package/dist/start-line-webhook.js +59 -0
- package/dist/start-line-webhook.js.map +1 -0
- package/dist/start-relay-pty.d.ts +7 -0
- package/dist/start-relay-pty.d.ts.map +1 -0
- package/dist/start-relay-pty.js +173 -0
- package/dist/start-relay-pty.js.map +1 -0
- package/dist/start-telegram-webhook.d.ts +7 -0
- package/dist/start-telegram-webhook.d.ts.map +1 -0
- package/dist/start-telegram-webhook.js +80 -0
- package/dist/start-telegram-webhook.js.map +1 -0
- package/dist/user-prompt-hook.d.ts +13 -0
- package/dist/user-prompt-hook.d.ts.map +1 -0
- package/dist/user-prompt-hook.js +45 -0
- package/dist/user-prompt-hook.js.map +1 -0
- package/dist/workspace-router.d.ts +78 -0
- package/dist/workspace-router.d.ts.map +1 -0
- package/dist/workspace-router.js +408 -0
- package/dist/workspace-router.js.map +1 -0
- package/dist/workspace-telegram-bot.d.ts +3 -0
- package/dist/workspace-telegram-bot.d.ts.map +1 -0
- package/dist/workspace-telegram-bot.js +1172 -0
- package/dist/workspace-telegram-bot.js.map +1 -0
- package/package.json +80 -0
- package/src/types/callbacks.ts +39 -0
- package/src/types/config.ts +63 -0
- package/src/types/hooks.ts +50 -0
- package/src/types/index.ts +6 -0
- package/src/types/ipc.ts +55 -0
- package/src/types/session.ts +72 -0
- package/src/types/telegram.ts +66 -0
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Email Notification Channel
|
|
4
|
+
* Sends notifications via email with reply support
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
const channel_1 = __importDefault(require("../base/channel"));
|
|
10
|
+
const optional_require_1 = require("../../utils/optional-require");
|
|
11
|
+
const nodemailer = (0, optional_require_1.optionalRequire)('nodemailer', 'email notifications');
|
|
12
|
+
const uuidv4 = (0, optional_require_1.getUUID)();
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const fs_1 = __importDefault(require("fs"));
|
|
15
|
+
const tmux_monitor_1 = __importDefault(require("../../utils/tmux-monitor"));
|
|
16
|
+
const child_process_1 = require("child_process");
|
|
17
|
+
class EmailChannel extends channel_1.default {
|
|
18
|
+
transporter;
|
|
19
|
+
sessionsDir;
|
|
20
|
+
templatesDir;
|
|
21
|
+
sentMessagesPath;
|
|
22
|
+
tmuxMonitor;
|
|
23
|
+
constructor(config = {}) {
|
|
24
|
+
super('email', config);
|
|
25
|
+
this.transporter = null;
|
|
26
|
+
this.sessionsDir = path_1.default.join(__dirname, '../../data/sessions');
|
|
27
|
+
this.templatesDir = path_1.default.join(__dirname, '../../assets/email-templates');
|
|
28
|
+
this.sentMessagesPath = config.sentMessagesPath || path_1.default.join(__dirname, '../../data/sent-messages.json');
|
|
29
|
+
this.tmuxMonitor = new tmux_monitor_1.default();
|
|
30
|
+
this._ensureDirectories();
|
|
31
|
+
this._initializeTransporter();
|
|
32
|
+
}
|
|
33
|
+
_escapeHtml(text) {
|
|
34
|
+
if (!text)
|
|
35
|
+
return '';
|
|
36
|
+
const htmlEntities = {
|
|
37
|
+
'&': '&',
|
|
38
|
+
'<': '<',
|
|
39
|
+
'>': '>',
|
|
40
|
+
'"': '"',
|
|
41
|
+
"'": '''
|
|
42
|
+
};
|
|
43
|
+
return text.replace(/[&<>"']/g, char => htmlEntities[char]);
|
|
44
|
+
}
|
|
45
|
+
_ensureDirectories() {
|
|
46
|
+
if (!fs_1.default.existsSync(this.sessionsDir)) {
|
|
47
|
+
fs_1.default.mkdirSync(this.sessionsDir, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
if (!fs_1.default.existsSync(this.templatesDir)) {
|
|
50
|
+
fs_1.default.mkdirSync(this.templatesDir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
_generateToken() {
|
|
54
|
+
// Generate short Token (uppercase letters + numbers, 8 digits)
|
|
55
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
56
|
+
let token = '';
|
|
57
|
+
for (let i = 0; i < 8; i++) {
|
|
58
|
+
token += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
59
|
+
}
|
|
60
|
+
return token;
|
|
61
|
+
}
|
|
62
|
+
_initializeTransporter() {
|
|
63
|
+
if (!nodemailer) {
|
|
64
|
+
this.logger.warn('nodemailer not installed. Email notifications unavailable. Install with: npm install nodemailer');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const config = this.config;
|
|
68
|
+
if (!config.smtp) {
|
|
69
|
+
this.logger.warn('SMTP configuration not found');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
this.transporter = nodemailer.createTransport({
|
|
74
|
+
host: config.smtp.host,
|
|
75
|
+
port: config.smtp.port,
|
|
76
|
+
secure: config.smtp.secure || false,
|
|
77
|
+
auth: {
|
|
78
|
+
user: config.smtp.auth.user,
|
|
79
|
+
pass: config.smtp.auth.pass
|
|
80
|
+
},
|
|
81
|
+
// Add timeout settings
|
|
82
|
+
connectionTimeout: parseInt(process.env.SMTP_TIMEOUT) || 10000,
|
|
83
|
+
greetingTimeout: parseInt(process.env.SMTP_TIMEOUT) || 10000,
|
|
84
|
+
socketTimeout: parseInt(process.env.SMTP_TIMEOUT) || 10000
|
|
85
|
+
});
|
|
86
|
+
this.logger.debug('Email transporter initialized');
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
this.logger.error('Failed to initialize email transporter:', error.message);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
_getCurrentTmuxSession() {
|
|
93
|
+
try {
|
|
94
|
+
// Try to get current tmux session
|
|
95
|
+
const tmuxSession = (0, child_process_1.execSync)('tmux display-message -p "#S"', {
|
|
96
|
+
encoding: 'utf8',
|
|
97
|
+
stdio: ['ignore', 'pipe', 'ignore']
|
|
98
|
+
}).trim();
|
|
99
|
+
return tmuxSession || null;
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
// Not in a tmux session or tmux not available
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async _sendImpl(notification) {
|
|
107
|
+
if (!this.transporter) {
|
|
108
|
+
throw new Error('Email transporter not initialized');
|
|
109
|
+
}
|
|
110
|
+
const config = this.config;
|
|
111
|
+
if (!config.to) {
|
|
112
|
+
throw new Error('Email recipient not configured');
|
|
113
|
+
}
|
|
114
|
+
// Generate session ID and Token
|
|
115
|
+
const sessionId = uuidv4();
|
|
116
|
+
const token = this._generateToken();
|
|
117
|
+
// Get current tmux session and conversation content
|
|
118
|
+
const tmuxSession = this._getCurrentTmuxSession();
|
|
119
|
+
if (tmuxSession && !notification.metadata) {
|
|
120
|
+
const conversation = this.tmuxMonitor.getRecentConversation(tmuxSession);
|
|
121
|
+
const fullTrace = this.tmuxMonitor.getFullExecutionTrace(tmuxSession);
|
|
122
|
+
notification.metadata = {
|
|
123
|
+
userQuestion: conversation.userQuestion || notification.message,
|
|
124
|
+
claudeResponse: conversation.claudeResponse || notification.message,
|
|
125
|
+
tmuxSession: tmuxSession,
|
|
126
|
+
fullExecutionTrace: fullTrace,
|
|
127
|
+
timestamp: new Date().toISOString(),
|
|
128
|
+
language: 'en'
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// Create session record
|
|
132
|
+
await this._createSession(sessionId, notification, token);
|
|
133
|
+
// Generate email content
|
|
134
|
+
const emailContent = this._generateEmailContent(notification, sessionId, token);
|
|
135
|
+
// Generate unique Message-ID
|
|
136
|
+
const messageId = `<${sessionId}-${Date.now()}@ccgram>`;
|
|
137
|
+
const mailOptions = {
|
|
138
|
+
from: config.from || config.smtp.auth.user,
|
|
139
|
+
to: config.to,
|
|
140
|
+
subject: emailContent.subject,
|
|
141
|
+
html: emailContent.html,
|
|
142
|
+
text: emailContent.text,
|
|
143
|
+
messageId: messageId,
|
|
144
|
+
// Add custom headers for reply recognition
|
|
145
|
+
headers: {
|
|
146
|
+
'X-CCGram-Session-ID': sessionId,
|
|
147
|
+
'X-CCGram-Type': notification.type
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
try {
|
|
151
|
+
const result = await this.transporter.sendMail(mailOptions);
|
|
152
|
+
this.logger.info(`Email sent successfully to ${config.to}, Session: ${sessionId}`);
|
|
153
|
+
// Track sent message
|
|
154
|
+
await this._trackSentMessage(messageId, sessionId, token);
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
this.logger.error('Failed to send email:', error.message);
|
|
159
|
+
// Clean up failed session
|
|
160
|
+
await this._removeSession(sessionId);
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async _createSession(sessionId, notification, token) {
|
|
165
|
+
const session = {
|
|
166
|
+
id: sessionId,
|
|
167
|
+
token: token,
|
|
168
|
+
type: 'pty',
|
|
169
|
+
created: new Date().toISOString(),
|
|
170
|
+
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(), // Expires after 24 hours
|
|
171
|
+
createdAt: Math.floor(Date.now() / 1000),
|
|
172
|
+
expiresAt: Math.floor((Date.now() + 24 * 60 * 60 * 1000) / 1000),
|
|
173
|
+
cwd: process.cwd(),
|
|
174
|
+
notification: {
|
|
175
|
+
type: notification.type,
|
|
176
|
+
project: notification.project,
|
|
177
|
+
message: notification.message
|
|
178
|
+
},
|
|
179
|
+
status: 'waiting',
|
|
180
|
+
commandCount: 0,
|
|
181
|
+
maxCommands: 10
|
|
182
|
+
};
|
|
183
|
+
const sessionFile = path_1.default.join(this.sessionsDir, `${sessionId}.json`);
|
|
184
|
+
fs_1.default.writeFileSync(sessionFile, JSON.stringify(session, null, 2));
|
|
185
|
+
// Also save in PTY mapping format
|
|
186
|
+
const sessionMapPath = process.env.SESSION_MAP_PATH || path_1.default.join(__dirname, '../../data/session-map.json');
|
|
187
|
+
let sessionMap = {};
|
|
188
|
+
if (fs_1.default.existsSync(sessionMapPath)) {
|
|
189
|
+
try {
|
|
190
|
+
sessionMap = JSON.parse(fs_1.default.readFileSync(sessionMapPath, 'utf8'));
|
|
191
|
+
}
|
|
192
|
+
catch (e) {
|
|
193
|
+
sessionMap = {};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Use passed tmux session name or detect current session
|
|
197
|
+
const tmuxSession = notification.metadata?.tmuxSession || this._getCurrentTmuxSession() || 'ccgram';
|
|
198
|
+
sessionMap[token] = {
|
|
199
|
+
type: 'pty',
|
|
200
|
+
createdAt: Math.floor(Date.now() / 1000),
|
|
201
|
+
expiresAt: Math.floor((Date.now() + 24 * 60 * 60 * 1000) / 1000),
|
|
202
|
+
cwd: process.cwd(),
|
|
203
|
+
sessionId: sessionId,
|
|
204
|
+
tmuxSession: tmuxSession,
|
|
205
|
+
description: `${notification.type} - ${notification.project}`
|
|
206
|
+
};
|
|
207
|
+
// Ensure directory exists
|
|
208
|
+
const mapDir = path_1.default.dirname(sessionMapPath);
|
|
209
|
+
if (!fs_1.default.existsSync(mapDir)) {
|
|
210
|
+
fs_1.default.mkdirSync(mapDir, { recursive: true });
|
|
211
|
+
}
|
|
212
|
+
fs_1.default.writeFileSync(sessionMapPath, JSON.stringify(sessionMap, null, 2));
|
|
213
|
+
this.logger.debug(`Session created: ${sessionId}, Token: ${token}`);
|
|
214
|
+
}
|
|
215
|
+
async _removeSession(sessionId) {
|
|
216
|
+
const sessionFile = path_1.default.join(this.sessionsDir, `${sessionId}.json`);
|
|
217
|
+
if (fs_1.default.existsSync(sessionFile)) {
|
|
218
|
+
fs_1.default.unlinkSync(sessionFile);
|
|
219
|
+
this.logger.debug(`Session removed: ${sessionId}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
async _trackSentMessage(messageId, sessionId, token) {
|
|
223
|
+
let sentMessages = { messages: [] };
|
|
224
|
+
// Read existing data if file exists
|
|
225
|
+
if (fs_1.default.existsSync(this.sentMessagesPath)) {
|
|
226
|
+
try {
|
|
227
|
+
sentMessages = JSON.parse(fs_1.default.readFileSync(this.sentMessagesPath, 'utf8'));
|
|
228
|
+
}
|
|
229
|
+
catch (e) {
|
|
230
|
+
this.logger.warn('Failed to read sent-messages.json, creating new one');
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// Add new message
|
|
234
|
+
sentMessages.messages.push({
|
|
235
|
+
messageId: messageId,
|
|
236
|
+
sessionId: sessionId,
|
|
237
|
+
token: token,
|
|
238
|
+
type: 'notification',
|
|
239
|
+
sentAt: new Date().toISOString()
|
|
240
|
+
});
|
|
241
|
+
// Ensure directory exists
|
|
242
|
+
const dir = path_1.default.dirname(this.sentMessagesPath);
|
|
243
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
244
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
245
|
+
}
|
|
246
|
+
// Write updated data
|
|
247
|
+
fs_1.default.writeFileSync(this.sentMessagesPath, JSON.stringify(sentMessages, null, 2));
|
|
248
|
+
this.logger.debug(`Tracked sent message: ${messageId}`);
|
|
249
|
+
}
|
|
250
|
+
_generateEmailContent(notification, sessionId, token) {
|
|
251
|
+
const template = this._getTemplate(notification.type);
|
|
252
|
+
const timestamp = new Date().toLocaleString('zh-CN');
|
|
253
|
+
// Get project directory name (last level directory)
|
|
254
|
+
const projectDir = path_1.default.basename(process.cwd());
|
|
255
|
+
// Extract user question (from notification.metadata if available)
|
|
256
|
+
let userQuestion = '';
|
|
257
|
+
let claudeResponse = '';
|
|
258
|
+
if (notification.metadata) {
|
|
259
|
+
userQuestion = notification.metadata.userQuestion || '';
|
|
260
|
+
claudeResponse = notification.metadata.claudeResponse || '';
|
|
261
|
+
}
|
|
262
|
+
// Limit user question length for title
|
|
263
|
+
const maxQuestionLength = 30;
|
|
264
|
+
const shortQuestion = userQuestion.length > maxQuestionLength ?
|
|
265
|
+
userQuestion.substring(0, maxQuestionLength) + '...' : userQuestion;
|
|
266
|
+
// Generate more distinctive title
|
|
267
|
+
let enhancedSubject = template.subject;
|
|
268
|
+
if (shortQuestion) {
|
|
269
|
+
enhancedSubject = enhancedSubject.replace('{{project}}', `${projectDir} | ${shortQuestion}`);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
enhancedSubject = enhancedSubject.replace('{{project}}', projectDir);
|
|
273
|
+
}
|
|
274
|
+
// Check if execution trace should be included
|
|
275
|
+
const config = this.config;
|
|
276
|
+
const includeExecutionTrace = config.includeExecutionTrace !== false; // Default to true
|
|
277
|
+
// Generate execution trace section HTML
|
|
278
|
+
let executionTraceSection = '';
|
|
279
|
+
let executionTraceText = '';
|
|
280
|
+
if (includeExecutionTrace) {
|
|
281
|
+
executionTraceSection = `
|
|
282
|
+
<!-- Full Execution Trace (Terminal Style) -->
|
|
283
|
+
<div style="margin-top: 40px; border-top: 1px solid #333; padding-top: 30px;">
|
|
284
|
+
<div style="color: #666; margin-bottom: 15px;">
|
|
285
|
+
<span style="color: #666;">$</span> <span style="color: #666;">tail -n 1000 execution.log</span>
|
|
286
|
+
</div>
|
|
287
|
+
<div style="margin-left: 20px;">
|
|
288
|
+
<div style="color: #666; font-size: 12px; margin-bottom: 10px;">
|
|
289
|
+
<span style="color: #999;">[</span><span style="color: #666;">Execution Trace - Scroll to view</span><span style="color: #999;">]</span>
|
|
290
|
+
</div>
|
|
291
|
+
<div style="background-color: #0d0d0d; border: 1px solid #222; padding: 15px; max-height: 300px; overflow-y: auto; overflow-x: auto; scrollbar-width: thin; scrollbar-color: #444 #0d0d0d;">
|
|
292
|
+
<pre style="margin: 0; color: #888; font-size: 11px; line-height: 1.4; white-space: pre-wrap; word-wrap: break-word; font-family: 'Consolas', 'Monaco', 'Courier New', monospace;">{{fullExecutionTrace}}</pre>
|
|
293
|
+
</div>
|
|
294
|
+
</div>
|
|
295
|
+
</div>`;
|
|
296
|
+
executionTraceText = `
|
|
297
|
+
|
|
298
|
+
====== FULL EXECUTION TRACE ======
|
|
299
|
+
{{fullExecutionTrace}}
|
|
300
|
+
==================================`;
|
|
301
|
+
}
|
|
302
|
+
// Template variable replacement
|
|
303
|
+
const variables = {
|
|
304
|
+
project: projectDir,
|
|
305
|
+
message: notification.message,
|
|
306
|
+
timestamp: timestamp,
|
|
307
|
+
sessionId: sessionId,
|
|
308
|
+
token: token,
|
|
309
|
+
type: notification.type === 'completed' ? 'Task completed' : 'Waiting for input',
|
|
310
|
+
userQuestion: userQuestion || 'No specified task',
|
|
311
|
+
claudeResponse: claudeResponse || notification.message,
|
|
312
|
+
projectDir: projectDir,
|
|
313
|
+
shortQuestion: shortQuestion || 'No specific question',
|
|
314
|
+
subagentActivities: notification.metadata?.subagentActivities || '',
|
|
315
|
+
executionTraceSection: executionTraceSection,
|
|
316
|
+
executionTraceText: executionTraceText,
|
|
317
|
+
fullExecutionTrace: notification.metadata?.fullExecutionTrace ||
|
|
318
|
+
'No execution trace available. This may occur if the task completed very quickly or if tmux session logging is not enabled.'
|
|
319
|
+
};
|
|
320
|
+
let subject = enhancedSubject;
|
|
321
|
+
let html = template.html;
|
|
322
|
+
let text = template.text;
|
|
323
|
+
// Replace template variables
|
|
324
|
+
Object.keys(variables).forEach(key => {
|
|
325
|
+
const placeholder = new RegExp(`{{${key}}}`, 'g');
|
|
326
|
+
subject = subject.replace(placeholder, variables[key]);
|
|
327
|
+
// Special handling for HTML content - don't escape
|
|
328
|
+
if (key === 'subagentActivities' || key === 'executionTraceSection') {
|
|
329
|
+
html = html.replace(placeholder, variables[key]);
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
// Escape HTML entities for other content
|
|
333
|
+
html = html.replace(placeholder, this._escapeHtml(variables[key]));
|
|
334
|
+
}
|
|
335
|
+
// No escaping needed for plain text
|
|
336
|
+
text = text.replace(placeholder, variables[key]);
|
|
337
|
+
});
|
|
338
|
+
return { subject, html, text };
|
|
339
|
+
}
|
|
340
|
+
_getTemplate(type) {
|
|
341
|
+
// Default templates
|
|
342
|
+
const templates = {
|
|
343
|
+
completed: {
|
|
344
|
+
subject: '[CCGram #{{token}}] Claude Code Task Completed - {{project}}',
|
|
345
|
+
html: `
|
|
346
|
+
<div style="font-family: 'Consolas', 'Monaco', 'Courier New', monospace; background-color: #f5f5f5; padding: 0; margin: 0;">
|
|
347
|
+
<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);">
|
|
348
|
+
<!-- Terminal Header -->
|
|
349
|
+
<div style="background-color: #2d2d2d; padding: 10px 15px; border-bottom: 1px solid #444;">
|
|
350
|
+
<table style="display: inline-table; vertical-align: middle;" cellpadding="0" cellspacing="0">
|
|
351
|
+
<tr>
|
|
352
|
+
<td style="padding: 0;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ff5f56;"></div></td>
|
|
353
|
+
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ffbd2e;"></div></td>
|
|
354
|
+
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #27c93f;"></div></td>
|
|
355
|
+
<td style="padding: 0 0 0 12px; color: #999; font-size: 14px; white-space: nowrap;">ccgram@{{project}} - Task Completed</td>
|
|
356
|
+
</tr>
|
|
357
|
+
</table>
|
|
358
|
+
</div>
|
|
359
|
+
|
|
360
|
+
<!-- Terminal Content -->
|
|
361
|
+
<div style="padding: 20px; background-color: #1a1a1a; min-height: 400px;">
|
|
362
|
+
<!-- User Input (Terminal Style) -->
|
|
363
|
+
<div style="margin-bottom: 30px;">
|
|
364
|
+
<div style="color: #00ff00; margin-bottom: 10px;">
|
|
365
|
+
<span style="color: #999;">$</span> <span style="color: #00ff00;">cat user_request.txt</span>
|
|
366
|
+
</div>
|
|
367
|
+
<div style="background-color: #262626; border-left: 4px solid #ff9800; padding: 15px 20px; margin-left: 20px; color: #f0f0f0; font-size: 15px; line-height: 1.6; font-weight: 500;">{{userQuestion}}</div>
|
|
368
|
+
</div>
|
|
369
|
+
|
|
370
|
+
<!-- Claude Response (Terminal Style) -->
|
|
371
|
+
<div style="margin-bottom: 30px;">
|
|
372
|
+
<div style="color: #00ff00; margin-bottom: 10px;">
|
|
373
|
+
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code execute</span>
|
|
374
|
+
</div>
|
|
375
|
+
<div style="margin-left: 20px;">
|
|
376
|
+
<div style="color: #999; margin-bottom: 10px; font-size: 13px;">
|
|
377
|
+
<span style="color: #00bcd4;">[INFO]</span> Processing request...<br>
|
|
378
|
+
<span style="color: #00bcd4;">[INFO]</span> Task execution started at {{timestamp}}
|
|
379
|
+
</div>
|
|
380
|
+
<div style="background-color: #1f1f1f; border-left: 4px solid #00ff00; padding: 15px 20px; color: #f0f0f0; font-size: 14px; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">{{claudeResponse}}</div>
|
|
381
|
+
<div style="color: #00ff00; margin-top: 10px; font-size: 13px;">
|
|
382
|
+
<span style="color: #00bcd4;">[SUCCESS]</span> Task completed successfully ✓
|
|
383
|
+
</div>
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
|
|
387
|
+
{{subagentActivities}}
|
|
388
|
+
|
|
389
|
+
<!-- Continue Instructions (Terminal Style) -->
|
|
390
|
+
<div style="margin: 40px 0; padding-top: 30px; border-top: 1px solid #333;">
|
|
391
|
+
<div style="color: #ff9800; margin-bottom: 15px;">
|
|
392
|
+
<span style="color: #999;">$</span> <span style="color: #ff9800;">claude-code --help continue</span>
|
|
393
|
+
</div>
|
|
394
|
+
<div style="margin-left: 20px; background-color: #0d0d0d; padding: 15px; border: 1px solid #333;">
|
|
395
|
+
<div style="color: #00ff00; margin-bottom: 10px; font-weight: bold;">TO CONTINUE THIS SESSION:</div>
|
|
396
|
+
<div style="color: #ccc; font-size: 13px; line-height: 1.8;">
|
|
397
|
+
Reply to this email directly with your next instruction.<br><br>
|
|
398
|
+
<span style="color: #666;">Examples:</span><br>
|
|
399
|
+
<span style="color: #999;">•</span> <span style="color: #00ff00;">"Add error handling to the function"</span><br>
|
|
400
|
+
<span style="color: #999;">•</span> <span style="color: #00ff00;">"Write unit tests for this code"</span><br>
|
|
401
|
+
<span style="color: #999;">•</span> <span style="color: #00ff00;">"Optimize the performance"</span>
|
|
402
|
+
</div>
|
|
403
|
+
</div>
|
|
404
|
+
</div>
|
|
405
|
+
|
|
406
|
+
{{executionTraceSection}}
|
|
407
|
+
</div>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
`,
|
|
411
|
+
text: `
|
|
412
|
+
[CCGram #{{token}}] Claude Code Task Completed - {{projectDir}} | {{shortQuestion}}
|
|
413
|
+
|
|
414
|
+
Project: {{projectDir}}
|
|
415
|
+
Time: {{timestamp}}
|
|
416
|
+
Status: {{type}}
|
|
417
|
+
|
|
418
|
+
📝 Your Question:
|
|
419
|
+
{{userQuestion}}
|
|
420
|
+
|
|
421
|
+
🤖 Claude's Response:
|
|
422
|
+
{{claudeResponse}}
|
|
423
|
+
|
|
424
|
+
{{subagentActivities}}{{executionTraceText}}
|
|
425
|
+
|
|
426
|
+
How to Continue Conversation:
|
|
427
|
+
To continue conversation with Claude Code, please reply to this email directly and enter your instructions in the email body.
|
|
428
|
+
|
|
429
|
+
Example Replies:
|
|
430
|
+
• "Please continue optimizing the code"
|
|
431
|
+
• "Generate unit tests"
|
|
432
|
+
• "Explain the purpose of this function"
|
|
433
|
+
|
|
434
|
+
Session ID: {{sessionId}}
|
|
435
|
+
Security Note: Please do not forward this email, session will automatically expire after 24 hours
|
|
436
|
+
`
|
|
437
|
+
},
|
|
438
|
+
waiting: {
|
|
439
|
+
subject: '[CCGram #{{token}}] Claude Code Waiting for Input - {{project}}',
|
|
440
|
+
html: `
|
|
441
|
+
<div style="font-family: 'Consolas', 'Monaco', 'Courier New', monospace; background-color: #f5f5f5; padding: 0; margin: 0;">
|
|
442
|
+
<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);">
|
|
443
|
+
<!-- Terminal Header -->
|
|
444
|
+
<div style="background-color: #2d2d2d; padding: 10px 15px; border-bottom: 1px solid #444;">
|
|
445
|
+
<table style="display: inline-table; vertical-align: middle;" cellpadding="0" cellspacing="0">
|
|
446
|
+
<tr>
|
|
447
|
+
<td style="padding: 0;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ff5f56;"></div></td>
|
|
448
|
+
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ffbd2e;"></div></td>
|
|
449
|
+
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #27c93f;"></div></td>
|
|
450
|
+
<td style="padding: 0 0 0 12px; color: #999; font-size: 14px; white-space: nowrap;">ccgram@{{project}} - Waiting for Input</td>
|
|
451
|
+
</tr>
|
|
452
|
+
</table>
|
|
453
|
+
</div>
|
|
454
|
+
|
|
455
|
+
<!-- Terminal Content -->
|
|
456
|
+
<div style="padding: 20px; background-color: #1a1a1a; min-height: 400px;">
|
|
457
|
+
<!-- Session Info -->
|
|
458
|
+
<div style="color: #00ff00; margin-bottom: 20px;">
|
|
459
|
+
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code status</span><br>
|
|
460
|
+
<div style="margin-left: 20px; margin-top: 5px; color: #ccc;">
|
|
461
|
+
<span style="color: #ff9800;">PROJECT:</span> {{projectDir}}<br>
|
|
462
|
+
<span style="color: #ff9800;">SESSION:</span> #{{token}}<br>
|
|
463
|
+
<span style="color: #ff9800;">STATUS:</span> <span style="color: #ffeb3b;">⏳ Waiting for input</span><br>
|
|
464
|
+
<span style="color: #ff9800;">TIME:</span> {{timestamp}}
|
|
465
|
+
</div>
|
|
466
|
+
</div>
|
|
467
|
+
|
|
468
|
+
<!-- Waiting Message -->
|
|
469
|
+
<div style="margin: 20px 0;">
|
|
470
|
+
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code wait</span><br>
|
|
471
|
+
<div style="color: #ffeb3b; margin: 10px 0;">
|
|
472
|
+
<span style="color: #ff9800;">[WAITING]</span> Claude needs your input to continue...<br>
|
|
473
|
+
</div>
|
|
474
|
+
<div style="background-color: #262626; border-left: 3px solid #ffeb3b; padding: 15px; margin: 10px 0; color: #f0f0f0;">
|
|
475
|
+
{{message}}
|
|
476
|
+
</div>
|
|
477
|
+
</div>
|
|
478
|
+
|
|
479
|
+
<!-- Continue Instructions -->
|
|
480
|
+
<div style="margin: 30px 0 20px 0; border-top: 1px solid #333; padding-top: 20px;">
|
|
481
|
+
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code help --respond</span><br>
|
|
482
|
+
<div style="color: #f0f0f0; margin: 10px 0;">
|
|
483
|
+
<div style="color: #ff9800; margin-bottom: 10px;">→ ACTION REQUIRED:</div>
|
|
484
|
+
<div style="background-color: #262626; padding: 15px; border: 1px solid #333; margin: 10px 0;">
|
|
485
|
+
<span style="color: #ffeb3b;">Claude is waiting for your guidance.</span><br><br>
|
|
486
|
+
Reply to this email with your instructions to continue.
|
|
487
|
+
</div>
|
|
488
|
+
</div>
|
|
489
|
+
</div>
|
|
490
|
+
|
|
491
|
+
<!-- Session Footer -->
|
|
492
|
+
<div style="color: #666; font-size: 12px; margin-top: 30px; padding-top: 20px; border-top: 1px solid #333;">
|
|
493
|
+
<span style="color: #999;">$</span> <span style="color: #666;">echo $SESSION_INFO</span><br>
|
|
494
|
+
<div style="margin-left: 20px; margin-top: 5px;">
|
|
495
|
+
SESSION_ID={{sessionId}}<br>
|
|
496
|
+
EXPIRES_IN=24h<br>
|
|
497
|
+
SECURITY=Do not forward this email<br>
|
|
498
|
+
POWERED_BY=CCGram
|
|
499
|
+
</div>
|
|
500
|
+
</div>
|
|
501
|
+
</div>
|
|
502
|
+
</div>
|
|
503
|
+
</div>
|
|
504
|
+
`,
|
|
505
|
+
text: `
|
|
506
|
+
[CCGram #{{token}}] Claude Code Waiting for Input - {{projectDir}}
|
|
507
|
+
|
|
508
|
+
Project: {{projectDir}}
|
|
509
|
+
Time: {{timestamp}}
|
|
510
|
+
Status: {{type}}
|
|
511
|
+
|
|
512
|
+
⏳ Waiting for Processing: {{message}}
|
|
513
|
+
|
|
514
|
+
Claude needs your further guidance. Please reply to this email to tell Claude what to do next.
|
|
515
|
+
|
|
516
|
+
Session ID: {{sessionId}}
|
|
517
|
+
Security Note: Please do not forward this email, session will automatically expire after 24 hours
|
|
518
|
+
`
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
return templates[type] || templates.completed;
|
|
522
|
+
}
|
|
523
|
+
validateConfig() {
|
|
524
|
+
const config = this.config;
|
|
525
|
+
if (!config.smtp) {
|
|
526
|
+
return { valid: false, error: 'SMTP configuration required' };
|
|
527
|
+
}
|
|
528
|
+
if (!config.smtp.host) {
|
|
529
|
+
return { valid: false, error: 'SMTP host required' };
|
|
530
|
+
}
|
|
531
|
+
if (!config.smtp.auth || !config.smtp.auth.user || !config.smtp.auth.pass) {
|
|
532
|
+
return { valid: false, error: 'SMTP authentication required' };
|
|
533
|
+
}
|
|
534
|
+
if (!config.to) {
|
|
535
|
+
return { valid: false, error: 'Recipient email required' };
|
|
536
|
+
}
|
|
537
|
+
return { valid: true };
|
|
538
|
+
}
|
|
539
|
+
async test() {
|
|
540
|
+
try {
|
|
541
|
+
if (!this.transporter) {
|
|
542
|
+
throw new Error('Email transporter not initialized');
|
|
543
|
+
}
|
|
544
|
+
// Verify SMTP connection
|
|
545
|
+
await this.transporter.verify();
|
|
546
|
+
// Send test email
|
|
547
|
+
const testNotification = {
|
|
548
|
+
type: 'completed',
|
|
549
|
+
title: 'CCGram Test',
|
|
550
|
+
message: 'This is a test email to verify that the email notification function is working properly.',
|
|
551
|
+
project: 'CCGram-Test',
|
|
552
|
+
metadata: {
|
|
553
|
+
test: true,
|
|
554
|
+
timestamp: new Date().toISOString(),
|
|
555
|
+
language: 'en',
|
|
556
|
+
userQuestion: 'This is a test notification',
|
|
557
|
+
claudeResponse: 'Email notification system is working correctly.',
|
|
558
|
+
fullExecutionTrace: `> claude-remote test
|
|
559
|
+
|
|
560
|
+
🧪 Testing email notification system...
|
|
561
|
+
|
|
562
|
+
[2025-08-01T06:29:28.893Z] [Config] [INFO] Configuration loaded successfully
|
|
563
|
+
[2025-08-01T06:29:28.918Z] [Notifier] [INFO] Initialized 2 channels
|
|
564
|
+
[2025-08-01T06:29:29.015Z] [Channel:desktop] [INFO] Notification sent successfully
|
|
565
|
+
[2025-08-01T06:29:32.880Z] [Channel:email] [INFO] Email sent successfully
|
|
566
|
+
|
|
567
|
+
✅ Test completed successfully!
|
|
568
|
+
|
|
569
|
+
This is a test trace to demonstrate how the full execution trace will appear in actual usage.
|
|
570
|
+
When Claude Code completes a task, this section will contain the complete terminal output including:
|
|
571
|
+
- User commands
|
|
572
|
+
- Claude's responses
|
|
573
|
+
- Subagent activities
|
|
574
|
+
- Error messages
|
|
575
|
+
- Debug information
|
|
576
|
+
|
|
577
|
+
The trace provides complete transparency about what happened during task execution.`
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
const result = await this._sendImpl(testNotification);
|
|
581
|
+
return result;
|
|
582
|
+
}
|
|
583
|
+
catch (error) {
|
|
584
|
+
this.logger.error('Email test failed:', error.message);
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
getStatus() {
|
|
589
|
+
const baseStatus = super.getStatus();
|
|
590
|
+
const config = this.config;
|
|
591
|
+
return {
|
|
592
|
+
...baseStatus,
|
|
593
|
+
configured: this.validateConfig().valid,
|
|
594
|
+
supportsRelay: true,
|
|
595
|
+
smtp: {
|
|
596
|
+
host: config.smtp?.host || 'not configured',
|
|
597
|
+
port: config.smtp?.port || 'not configured',
|
|
598
|
+
secure: config.smtp?.secure || false
|
|
599
|
+
},
|
|
600
|
+
recipient: config.to || 'not configured'
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
module.exports = EmailChannel;
|
|
605
|
+
//# sourceMappingURL=smtp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smtp.js","sourceRoot":"","sources":["../../../../src/channels/email/smtp.ts"],"names":[],"mappings":"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"}
|