@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,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple Automation Solution
|
|
3
|
+
* Use simpler methods to handle email reply commands
|
|
4
|
+
*/
|
|
5
|
+
import Logger from '../core/logger';
|
|
6
|
+
interface SimpleAutomationStatus {
|
|
7
|
+
supported: boolean;
|
|
8
|
+
commandFile: string;
|
|
9
|
+
commandFileExists: boolean;
|
|
10
|
+
lastCommand: string | null;
|
|
11
|
+
}
|
|
12
|
+
declare class SimpleAutomation {
|
|
13
|
+
logger: Logger;
|
|
14
|
+
commandFile: string;
|
|
15
|
+
notificationSent: boolean;
|
|
16
|
+
constructor();
|
|
17
|
+
/**
|
|
18
|
+
* Send command - using multiple simple methods
|
|
19
|
+
*/
|
|
20
|
+
sendCommand(command: string, sessionId?: string): Promise<boolean>;
|
|
21
|
+
/**
|
|
22
|
+
* Save command to file
|
|
23
|
+
*/
|
|
24
|
+
_saveCommandToFile(command: string, sessionId: string): Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Copy to clipboard
|
|
27
|
+
*/
|
|
28
|
+
_copyToClipboard(command: string): Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* Send rich notification
|
|
31
|
+
*/
|
|
32
|
+
_sendRichNotification(command: string, sessionId: string): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Send simple notification
|
|
35
|
+
*/
|
|
36
|
+
_sendSimpleNotification(command: string): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Try simple automation (no complex permissions needed)
|
|
39
|
+
*/
|
|
40
|
+
_trySimpleAutomation(command: string): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* Open command file
|
|
43
|
+
*/
|
|
44
|
+
openCommandFile(): Promise<boolean>;
|
|
45
|
+
/**
|
|
46
|
+
* Clean up command files
|
|
47
|
+
*/
|
|
48
|
+
cleanupCommandFile(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Get status
|
|
51
|
+
*/
|
|
52
|
+
getStatus(): SimpleAutomationStatus;
|
|
53
|
+
_getLastCommand(): string | null;
|
|
54
|
+
}
|
|
55
|
+
export = SimpleAutomation;
|
|
56
|
+
//# sourceMappingURL=simple-automation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-automation.d.ts","sourceRoot":"","sources":["../../../src/automation/simple-automation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,MAAM,MAAM,gBAAgB,CAAC;AAEpC,UAAU,sBAAsB;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,cAAM,gBAAgB;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;;IAQ1B;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IA4B5E;;OAEG;IACG,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAwB9E;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BzD;;OAEG;IACG,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgDjF;;OAEG;IACG,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc7D;;OAEG;IACG,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqD7D;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBzC;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAW1B;;OAEG;IACH,SAAS,IAAI,sBAAsB;IASnC,eAAe,IAAI,MAAM,GAAG,IAAI;CAiBnC;AAED,SAAS,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Simple Automation Solution
|
|
4
|
+
* Use simpler methods to handle email reply commands
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const logger_1 = __importDefault(require("../core/logger"));
|
|
13
|
+
class SimpleAutomation {
|
|
14
|
+
logger;
|
|
15
|
+
commandFile;
|
|
16
|
+
notificationSent;
|
|
17
|
+
constructor() {
|
|
18
|
+
this.logger = new logger_1.default('SimpleAutomation');
|
|
19
|
+
this.commandFile = path_1.default.join(__dirname, '../data/current_command.txt');
|
|
20
|
+
this.notificationSent = false;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Send command - using multiple simple methods
|
|
24
|
+
*/
|
|
25
|
+
async sendCommand(command, sessionId = '') {
|
|
26
|
+
try {
|
|
27
|
+
// Method 1: Save to file, user can manually copy
|
|
28
|
+
await this._saveCommandToFile(command, sessionId);
|
|
29
|
+
// Method 2: Copy to clipboard
|
|
30
|
+
const clipboardSuccess = await this._copyToClipboard(command);
|
|
31
|
+
// Method 3: Send rich notification (including command content)
|
|
32
|
+
const notificationSuccess = await this._sendRichNotification(command, sessionId);
|
|
33
|
+
// Method 4: Try simple automation (no complex permissions needed)
|
|
34
|
+
const autoSuccess = await this._trySimpleAutomation(command);
|
|
35
|
+
if (clipboardSuccess || notificationSuccess || autoSuccess) {
|
|
36
|
+
this.logger.info('Command sent successfully via simple automation');
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
this.logger.warn('All simple automation methods failed');
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
this.logger.error('Simple automation failed:', error.message);
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Save command to file
|
|
51
|
+
*/
|
|
52
|
+
async _saveCommandToFile(command, sessionId) {
|
|
53
|
+
try {
|
|
54
|
+
const timestamp = new Date().toLocaleString('zh-CN');
|
|
55
|
+
const content = `# TaskPing Email Reply Command
|
|
56
|
+
# Time: ${timestamp}
|
|
57
|
+
# Session ID: ${sessionId}
|
|
58
|
+
#
|
|
59
|
+
# Please copy the command below to Claude Code for execution:
|
|
60
|
+
|
|
61
|
+
${command}
|
|
62
|
+
|
|
63
|
+
# ===============================
|
|
64
|
+
# This file can be deleted after execution
|
|
65
|
+
`;
|
|
66
|
+
fs_1.default.writeFileSync(this.commandFile, content, 'utf8');
|
|
67
|
+
this.logger.info(`Command saved to file: ${this.commandFile}`);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
this.logger.error('Failed to save command to file:', error.message);
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Copy to clipboard
|
|
77
|
+
*/
|
|
78
|
+
async _copyToClipboard(command) {
|
|
79
|
+
try {
|
|
80
|
+
if (process.platform === 'darwin') {
|
|
81
|
+
const pbcopy = (0, child_process_1.spawn)('pbcopy');
|
|
82
|
+
pbcopy.stdin.write(command);
|
|
83
|
+
pbcopy.stdin.end();
|
|
84
|
+
return new Promise((resolve) => {
|
|
85
|
+
pbcopy.on('close', (code) => {
|
|
86
|
+
if (code === 0) {
|
|
87
|
+
this.logger.info('Command copied to clipboard');
|
|
88
|
+
resolve(true);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
resolve(false);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
pbcopy.on('error', () => resolve(false));
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
this.logger.error('Failed to copy to clipboard:', error.message);
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Send rich notification
|
|
106
|
+
*/
|
|
107
|
+
async _sendRichNotification(command, sessionId) {
|
|
108
|
+
try {
|
|
109
|
+
if (process.platform === 'darwin') {
|
|
110
|
+
const shortCommand = command.length > 50 ? command.substring(0, 50) + '...' : command;
|
|
111
|
+
// Create detailed notification
|
|
112
|
+
const script = `
|
|
113
|
+
set commandText to "${command.replace(/"/g, '\\"').replace(/\n/g, '\\n')}"
|
|
114
|
+
|
|
115
|
+
display notification "Command copied to clipboard, please paste to Claude Code" with title "TaskPing - New Email Command" subtitle "${shortCommand.replace(/"/g, '\\"')}" sound name "default"
|
|
116
|
+
|
|
117
|
+
-- Also show dialog (optional, user can cancel)
|
|
118
|
+
try
|
|
119
|
+
set userChoice to display dialog "Received new email command:" & return & return & commandText buttons {"Open Command File", "Cancel", "Pasted"} default button "Pasted" with title "TaskPing Email Relay" giving up after 10
|
|
120
|
+
|
|
121
|
+
if button returned of userChoice is "Open Command File" then
|
|
122
|
+
do shell script "open -t '${this.commandFile}'"
|
|
123
|
+
end if
|
|
124
|
+
end try
|
|
125
|
+
`;
|
|
126
|
+
const osascript = (0, child_process_1.spawn)('osascript', ['-e', script]);
|
|
127
|
+
return new Promise((resolve) => {
|
|
128
|
+
osascript.on('close', (code) => {
|
|
129
|
+
if (code === 0) {
|
|
130
|
+
this.logger.info('Rich notification sent successfully');
|
|
131
|
+
resolve(true);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
this.logger.warn('Rich notification failed, trying simple notification');
|
|
135
|
+
this._sendSimpleNotification(command);
|
|
136
|
+
resolve(true); // Consider successful even if failed, because there are backup options
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
osascript.on('error', () => {
|
|
140
|
+
this._sendSimpleNotification(command);
|
|
141
|
+
resolve(true);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
this.logger.error('Failed to send rich notification:', error.message);
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Send simple notification
|
|
154
|
+
*/
|
|
155
|
+
async _sendSimpleNotification(command) {
|
|
156
|
+
try {
|
|
157
|
+
const shortCommand = command.length > 50 ? command.substring(0, 50) + '...' : command;
|
|
158
|
+
const script = `display notification "Command: ${shortCommand.replace(/"/g, '\\"')}" with title "TaskPing - Email Command" sound name "default"`;
|
|
159
|
+
const osascript = (0, child_process_1.spawn)('osascript', ['-e', script]);
|
|
160
|
+
osascript.on('close', () => {
|
|
161
|
+
this.logger.info('Simple notification sent');
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
this.logger.warn('Simple notification also failed:', error.message);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Try simple automation (no complex permissions needed)
|
|
170
|
+
*/
|
|
171
|
+
async _trySimpleAutomation(command) {
|
|
172
|
+
try {
|
|
173
|
+
if (process.platform === 'darwin') {
|
|
174
|
+
// Only try basic operations, don't force permissions
|
|
175
|
+
const script = `
|
|
176
|
+
try
|
|
177
|
+
tell application "System Events"
|
|
178
|
+
-- Try to get frontmost application
|
|
179
|
+
set frontApp to name of first application process whose frontmost is true
|
|
180
|
+
|
|
181
|
+
-- If it's terminal or code editor, try to paste
|
|
182
|
+
if frontApp contains "Terminal" or frontApp contains "iTerm" or frontApp contains "Code" or frontApp contains "Claude" then
|
|
183
|
+
keystroke "v" using command down
|
|
184
|
+
delay 0.2
|
|
185
|
+
keystroke return
|
|
186
|
+
return "success"
|
|
187
|
+
else
|
|
188
|
+
return "not_target_app"
|
|
189
|
+
end if
|
|
190
|
+
end tell
|
|
191
|
+
on error
|
|
192
|
+
return "no_permission"
|
|
193
|
+
end try
|
|
194
|
+
`;
|
|
195
|
+
const osascript = (0, child_process_1.spawn)('osascript', ['-e', script]);
|
|
196
|
+
let output = '';
|
|
197
|
+
osascript.stdout.on('data', (data) => {
|
|
198
|
+
output += data.toString().trim();
|
|
199
|
+
});
|
|
200
|
+
return new Promise((resolve) => {
|
|
201
|
+
osascript.on('close', (code) => {
|
|
202
|
+
if (code === 0 && output === 'success') {
|
|
203
|
+
this.logger.info('Simple automation succeeded');
|
|
204
|
+
resolve(true);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
this.logger.debug(`Simple automation result: ${output}`);
|
|
208
|
+
resolve(false);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
osascript.on('error', () => resolve(false));
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
this.logger.error('Simple automation error:', error.message);
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Open command file
|
|
223
|
+
*/
|
|
224
|
+
async openCommandFile() {
|
|
225
|
+
try {
|
|
226
|
+
if (fs_1.default.existsSync(this.commandFile)) {
|
|
227
|
+
if (process.platform === 'darwin') {
|
|
228
|
+
(0, child_process_1.spawn)('open', ['-t', this.commandFile]);
|
|
229
|
+
this.logger.info('Command file opened');
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
this.logger.error('Failed to open command file:', error.message);
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Clean up command files
|
|
242
|
+
*/
|
|
243
|
+
cleanupCommandFile() {
|
|
244
|
+
try {
|
|
245
|
+
if (fs_1.default.existsSync(this.commandFile)) {
|
|
246
|
+
fs_1.default.unlinkSync(this.commandFile);
|
|
247
|
+
this.logger.info('Command file cleaned up');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
this.logger.error('Failed to cleanup command file:', error.message);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Get status
|
|
256
|
+
*/
|
|
257
|
+
getStatus() {
|
|
258
|
+
return {
|
|
259
|
+
supported: process.platform === 'darwin',
|
|
260
|
+
commandFile: this.commandFile,
|
|
261
|
+
commandFileExists: fs_1.default.existsSync(this.commandFile),
|
|
262
|
+
lastCommand: this._getLastCommand()
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
_getLastCommand() {
|
|
266
|
+
try {
|
|
267
|
+
if (fs_1.default.existsSync(this.commandFile)) {
|
|
268
|
+
const content = fs_1.default.readFileSync(this.commandFile, 'utf8');
|
|
269
|
+
const lines = content.split('\n');
|
|
270
|
+
const commandLines = lines.filter((line) => !line.startsWith('#') &&
|
|
271
|
+
!line.startsWith('=') &&
|
|
272
|
+
line.trim().length > 0);
|
|
273
|
+
return commandLines.join('\n').trim();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
this.logger.error('Failed to get last command:', error.message);
|
|
278
|
+
}
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
module.exports = SimpleAutomation;
|
|
283
|
+
//# sourceMappingURL=simple-automation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-automation.js","sourceRoot":"","sources":["../../../src/automation/simple-automation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Notification Channel
|
|
3
|
+
* Abstract base class for all notification channels
|
|
4
|
+
*/
|
|
5
|
+
import Logger from '../../core/logger';
|
|
6
|
+
import type { Notification } from '../../types';
|
|
7
|
+
interface ChannelStatus {
|
|
8
|
+
name: string;
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
configured: boolean | {
|
|
11
|
+
valid: boolean;
|
|
12
|
+
error?: string;
|
|
13
|
+
};
|
|
14
|
+
supportsRelay: boolean;
|
|
15
|
+
}
|
|
16
|
+
interface ChannelConfig {
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
declare abstract class NotificationChannel {
|
|
21
|
+
name: string;
|
|
22
|
+
config: ChannelConfig;
|
|
23
|
+
logger: Logger;
|
|
24
|
+
enabled: boolean;
|
|
25
|
+
constructor(name: string, config?: ChannelConfig);
|
|
26
|
+
/**
|
|
27
|
+
* Send a notification
|
|
28
|
+
*/
|
|
29
|
+
send(notification: Notification): Promise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* Test the channel configuration
|
|
32
|
+
*/
|
|
33
|
+
test(): Promise<boolean>;
|
|
34
|
+
/**
|
|
35
|
+
* Check if the channel supports command relay
|
|
36
|
+
*/
|
|
37
|
+
supportsRelay(): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Handle incoming command from this channel (if supported)
|
|
40
|
+
*/
|
|
41
|
+
handleCommand(command: string, context?: Record<string, unknown>): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* Implementation-specific send logic
|
|
44
|
+
* Must be implemented by subclasses
|
|
45
|
+
*/
|
|
46
|
+
abstract _sendImpl(notification: Notification): Promise<boolean>;
|
|
47
|
+
/**
|
|
48
|
+
* Validate channel configuration
|
|
49
|
+
*/
|
|
50
|
+
validateConfig(): boolean | {
|
|
51
|
+
valid: boolean;
|
|
52
|
+
error?: string;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Get channel status
|
|
56
|
+
*/
|
|
57
|
+
getStatus(): ChannelStatus;
|
|
58
|
+
}
|
|
59
|
+
export = NotificationChannel;
|
|
60
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../../src/channels/base/channel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,MAAM,MAAM,mBAAmB,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,UAAU,aAAa;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,aAAa,EAAE,OAAO,CAAC;CAC1B;AAED,UAAU,aAAa;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,uBAAe,mBAAmB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;gBAEL,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,aAAkB;IAOpD;;OAEG;IACG,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAsBxD;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAc9B;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW7F;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhE;;OAEG;IACH,cAAc,IAAI,OAAO,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAI9D;;OAEG;IACH,SAAS,IAAI,aAAa;CAQ7B;AAED,SAAS,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Base Notification Channel
|
|
4
|
+
* Abstract base class for all notification channels
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
const logger_1 = __importDefault(require("../../core/logger"));
|
|
10
|
+
class NotificationChannel {
|
|
11
|
+
name;
|
|
12
|
+
config;
|
|
13
|
+
logger;
|
|
14
|
+
enabled;
|
|
15
|
+
constructor(name, config = {}) {
|
|
16
|
+
this.name = name;
|
|
17
|
+
this.config = config;
|
|
18
|
+
this.logger = new logger_1.default(`Channel:${name}`);
|
|
19
|
+
this.enabled = config.enabled !== false;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Send a notification
|
|
23
|
+
*/
|
|
24
|
+
async send(notification) {
|
|
25
|
+
if (!this.enabled) {
|
|
26
|
+
this.logger.debug('Channel disabled, skipping notification');
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
this.logger.debug('Sending notification:', notification.type);
|
|
30
|
+
try {
|
|
31
|
+
const result = await this._sendImpl(notification);
|
|
32
|
+
if (result) {
|
|
33
|
+
this.logger.info(`Notification sent successfully: ${notification.type}`);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.logger.warn(`Failed to send notification: ${notification.type}`);
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
this.logger.error('Error sending notification:', error.message);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Test the channel configuration
|
|
47
|
+
*/
|
|
48
|
+
async test() {
|
|
49
|
+
this.logger.debug('Testing channel...');
|
|
50
|
+
const testNotification = {
|
|
51
|
+
type: 'completed',
|
|
52
|
+
title: 'CCGram Test',
|
|
53
|
+
message: `Test notification from ${this.name} channel`,
|
|
54
|
+
project: 'test-project',
|
|
55
|
+
metadata: { test: true, timestamp: new Date().toISOString(), language: 'en' }
|
|
56
|
+
};
|
|
57
|
+
return await this.send(testNotification);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check if the channel supports command relay
|
|
61
|
+
*/
|
|
62
|
+
supportsRelay() {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Handle incoming command from this channel (if supported)
|
|
67
|
+
*/
|
|
68
|
+
async handleCommand(command, context = {}) {
|
|
69
|
+
if (!this.supportsRelay()) {
|
|
70
|
+
this.logger.warn('Channel does not support command relay');
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
this.logger.info('Received command:', command);
|
|
74
|
+
// Implemented by subclasses
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Validate channel configuration
|
|
79
|
+
*/
|
|
80
|
+
validateConfig() {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get channel status
|
|
85
|
+
*/
|
|
86
|
+
getStatus() {
|
|
87
|
+
return {
|
|
88
|
+
name: this.name,
|
|
89
|
+
enabled: this.enabled,
|
|
90
|
+
configured: this.validateConfig(),
|
|
91
|
+
supportsRelay: this.supportsRelay()
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
module.exports = NotificationChannel;
|
|
96
|
+
//# sourceMappingURL=channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../../../../src/channels/base/channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email Notification Channel
|
|
3
|
+
* Sends notifications via email with reply support
|
|
4
|
+
*/
|
|
5
|
+
import NotificationChannel from '../base/channel';
|
|
6
|
+
import TmuxMonitor from '../../utils/tmux-monitor';
|
|
7
|
+
import type { Notification } from '../../types';
|
|
8
|
+
interface SmtpAuth {
|
|
9
|
+
user: string;
|
|
10
|
+
pass: string;
|
|
11
|
+
}
|
|
12
|
+
interface SmtpConfig {
|
|
13
|
+
host?: string;
|
|
14
|
+
port?: number;
|
|
15
|
+
secure?: boolean;
|
|
16
|
+
auth: SmtpAuth;
|
|
17
|
+
}
|
|
18
|
+
interface EmailConfig {
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
smtp?: SmtpConfig;
|
|
21
|
+
from?: string;
|
|
22
|
+
to?: string;
|
|
23
|
+
includeExecutionTrace?: boolean;
|
|
24
|
+
sentMessagesPath?: string;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
interface EmailContent {
|
|
28
|
+
subject: string;
|
|
29
|
+
html: string;
|
|
30
|
+
text: string;
|
|
31
|
+
}
|
|
32
|
+
interface TemplateSet {
|
|
33
|
+
subject: string;
|
|
34
|
+
html: string;
|
|
35
|
+
text: string;
|
|
36
|
+
}
|
|
37
|
+
declare class EmailChannel extends NotificationChannel {
|
|
38
|
+
transporter: any;
|
|
39
|
+
sessionsDir: string;
|
|
40
|
+
templatesDir: string;
|
|
41
|
+
sentMessagesPath: string;
|
|
42
|
+
tmuxMonitor: TmuxMonitor;
|
|
43
|
+
constructor(config?: EmailConfig);
|
|
44
|
+
_escapeHtml(text: string): string;
|
|
45
|
+
_ensureDirectories(): void;
|
|
46
|
+
_generateToken(): string;
|
|
47
|
+
_initializeTransporter(): void;
|
|
48
|
+
_getCurrentTmuxSession(): string | null;
|
|
49
|
+
_sendImpl(notification: Notification): Promise<boolean>;
|
|
50
|
+
_createSession(sessionId: string, notification: Notification, token: string): Promise<void>;
|
|
51
|
+
_removeSession(sessionId: string): Promise<void>;
|
|
52
|
+
_trackSentMessage(messageId: string, sessionId: string, token: string): Promise<void>;
|
|
53
|
+
_generateEmailContent(notification: Notification, sessionId: string, token: string): EmailContent;
|
|
54
|
+
_getTemplate(type: string): TemplateSet;
|
|
55
|
+
validateConfig(): {
|
|
56
|
+
valid: boolean;
|
|
57
|
+
error?: string;
|
|
58
|
+
};
|
|
59
|
+
test(): Promise<boolean>;
|
|
60
|
+
getStatus(): {
|
|
61
|
+
configured: boolean;
|
|
62
|
+
supportsRelay: boolean;
|
|
63
|
+
smtp: {
|
|
64
|
+
host: string;
|
|
65
|
+
port: string | number;
|
|
66
|
+
secure: boolean;
|
|
67
|
+
};
|
|
68
|
+
recipient: string;
|
|
69
|
+
name: string;
|
|
70
|
+
enabled: boolean;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export = EmailChannel;
|
|
74
|
+
//# sourceMappingURL=smtp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smtp.d.ts","sourceRoot":"","sources":["../../../../src/channels/email/smtp.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,mBAAmB,MAAM,iBAAiB,CAAC;AAMlD,OAAO,WAAW,MAAM,0BAA0B,CAAC;AAEnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,UAAU,QAAQ;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,UAAU;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;CAClB;AAED,UAAU,WAAW;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,UAAU,YAAY;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB;AA2CD,UAAU,WAAW;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,cAAM,YAAa,SAAQ,mBAAmB;IAC1C,WAAW,EAAE,GAAG,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;gBAEb,MAAM,GAAE,WAA+B;IAYnD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAYjC,kBAAkB,IAAI,IAAI;IAS1B,cAAc,IAAI,MAAM;IAUxB,sBAAsB,IAAI,IAAI;IAkC9B,sBAAsB,IAAI,MAAM,GAAG,IAAI;IAejC,SAAS,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAqEvD,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0D3F,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQhD,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC3F,qBAAqB,CAAC,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY;IAuGjG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IAyLvC,cAAc,IAAI;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAsB9C,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAoD9B,SAAS;;;;;;;;;;;;CAeZ;AAED,SAAS,YAAY,CAAC"}
|