@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,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safely require an optional dependency.
|
|
3
|
+
* Returns the module if available, or null if not installed.
|
|
4
|
+
* Logs an actionable install message on failure.
|
|
5
|
+
*/
|
|
6
|
+
declare function optionalRequire(moduleName: string, featureName: string): unknown;
|
|
7
|
+
/**
|
|
8
|
+
* Get a uuid.v4-compatible function using Node's built-in crypto module.
|
|
9
|
+
* Returns a RFC 4122 v4 UUID generator (no external dependency needed).
|
|
10
|
+
*/
|
|
11
|
+
declare function getUUID(): () => string;
|
|
12
|
+
export { optionalRequire, getUUID };
|
|
13
|
+
//# sourceMappingURL=optional-require.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optional-require.d.ts","sourceRoot":"","sources":["../../../src/utils/optional-require.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,iBAAS,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAczE;AAED;;;GAGG;AACH,iBAAS,OAAO,IAAI,MAAM,MAAM,CAQ/B;AAED,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.optionalRequire = optionalRequire;
|
|
4
|
+
exports.getUUID = getUUID;
|
|
5
|
+
/**
|
|
6
|
+
* Safely require an optional dependency.
|
|
7
|
+
* Returns the module if available, or null if not installed.
|
|
8
|
+
* Logs an actionable install message on failure.
|
|
9
|
+
*/
|
|
10
|
+
function optionalRequire(moduleName, featureName) {
|
|
11
|
+
try {
|
|
12
|
+
return require(moduleName);
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
if (err && typeof err === 'object' && 'code' in err && err.code === 'MODULE_NOT_FOUND') {
|
|
16
|
+
console.warn(`[ccgram] Optional dependency "${moduleName}" not installed. ` +
|
|
17
|
+
`Feature "${featureName}" will be unavailable. ` +
|
|
18
|
+
`Install with: npm install ${moduleName}`);
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
throw err;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get a uuid.v4-compatible function using Node's built-in crypto module.
|
|
26
|
+
* Returns a RFC 4122 v4 UUID generator (no external dependency needed).
|
|
27
|
+
*/
|
|
28
|
+
function getUUID() {
|
|
29
|
+
return function uuidv4() {
|
|
30
|
+
const bytes = require('crypto').randomBytes(16);
|
|
31
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
|
|
32
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 1
|
|
33
|
+
const hex = bytes.toString('hex');
|
|
34
|
+
return [hex.slice(0, 8), hex.slice(8, 12), hex.slice(12, 16), hex.slice(16, 20), hex.slice(20)].join('-');
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=optional-require.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optional-require.js","sourceRoot":"","sources":["../../../src/utils/optional-require.ts"],"names":[],"mappings":";;AAmCS,0CAAe;AAAE,0BAAO;AAnCjC;;;;GAIG;AACH,SAAS,eAAe,CAAC,UAAkB,EAAE,WAAmB;IAC5D,IAAI,CAAC;QACD,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;YACrF,OAAO,CAAC,IAAI,CACR,iCAAiC,UAAU,mBAAmB;gBAC9D,YAAY,WAAW,yBAAyB;gBAChD,6BAA6B,UAAU,EAAE,CAC5C,CAAC;YACF,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,GAAG,CAAC;IACd,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO;IACZ,OAAO,SAAS,MAAM;QAClB,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAChD,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,YAAY;QACjD,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,YAAY;QACjD,MAAM,GAAG,GAAW,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9G,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project root directory ā walks up from __dirname to find package.json.
|
|
3
|
+
* Works from any depth in dist/ after TypeScript compilation.
|
|
4
|
+
*/
|
|
5
|
+
export declare const PROJECT_ROOT: string;
|
|
6
|
+
/**
|
|
7
|
+
* Persistent install directory for ccgram.
|
|
8
|
+
* `ccgram init` copies the package here so hook paths survive npx cleanup.
|
|
9
|
+
*/
|
|
10
|
+
export declare const CCGRAM_HOME: string;
|
|
11
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/utils/paths.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,MAOvB,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,MAA2C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CCGRAM_HOME = exports.PROJECT_ROOT = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const os_1 = __importDefault(require("os"));
|
|
10
|
+
/**
|
|
11
|
+
* Project root directory ā walks up from __dirname to find package.json.
|
|
12
|
+
* Works from any depth in dist/ after TypeScript compilation.
|
|
13
|
+
*/
|
|
14
|
+
exports.PROJECT_ROOT = (() => {
|
|
15
|
+
let dir = __dirname;
|
|
16
|
+
while (dir !== path_1.default.dirname(dir)) {
|
|
17
|
+
if (fs_1.default.existsSync(path_1.default.join(dir, 'package.json')))
|
|
18
|
+
return dir;
|
|
19
|
+
dir = path_1.default.dirname(dir);
|
|
20
|
+
}
|
|
21
|
+
return process.cwd();
|
|
22
|
+
})();
|
|
23
|
+
/**
|
|
24
|
+
* Persistent install directory for ccgram.
|
|
25
|
+
* `ccgram init` copies the package here so hook paths survive npx cleanup.
|
|
26
|
+
*/
|
|
27
|
+
exports.CCGRAM_HOME = path_1.default.join(os_1.default.homedir(), '.ccgram');
|
|
28
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/utils/paths.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,4CAAoB;AACpB,4CAAoB;AAEpB;;;GAGG;AACU,QAAA,YAAY,GAAW,CAAC,GAAG,EAAE;IACxC,IAAI,GAAG,GAAG,SAAS,CAAC;IACpB,OAAO,GAAG,KAAK,cAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,IAAI,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QAC9D,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;AACvB,CAAC,CAAC,EAAE,CAAC;AAEL;;;GAGG;AACU,QAAA,WAAW,GAAW,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PTY Session Manager ā manages headless node-pty sessions for tmux-less operation.
|
|
3
|
+
*
|
|
4
|
+
* When tmux is unavailable, /new spawns Claude via node-pty instead of tmux.
|
|
5
|
+
* CCGram owns the PTY master, so all Telegram features (permissions, questions,
|
|
6
|
+
* commands, /status, /stop) work without tmux. Sessions are not attachable from
|
|
7
|
+
* a terminal.
|
|
8
|
+
*
|
|
9
|
+
* Uses optionalRequire so the bot starts normally even when node-pty is not installed.
|
|
10
|
+
*/
|
|
11
|
+
export declare class PtySessionManager {
|
|
12
|
+
private ptyModule;
|
|
13
|
+
private handles;
|
|
14
|
+
private buffers;
|
|
15
|
+
constructor();
|
|
16
|
+
/** Whether node-pty is loadable on this machine. */
|
|
17
|
+
isAvailable(): boolean;
|
|
18
|
+
/** Whether a live PTY handle exists for this session name. */
|
|
19
|
+
has(sessionName: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Spawn a new headless PTY session running the claude CLI.
|
|
22
|
+
* @returns true on success, false on failure
|
|
23
|
+
*/
|
|
24
|
+
spawn(name: string, cwd: string): boolean;
|
|
25
|
+
/** Write raw bytes directly to the PTY master fd. */
|
|
26
|
+
write(name: string, data: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Translate a tmux-style key name to its escape sequence and write to PTY.
|
|
29
|
+
* Supported: Down, Up, Enter, C-m, C-c, C-u, Space.
|
|
30
|
+
*/
|
|
31
|
+
sendKey(name: string, key: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Return the last N lines of buffered output, or null if session unknown.
|
|
34
|
+
*/
|
|
35
|
+
capture(name: string, lines?: number): string | null;
|
|
36
|
+
/** Send Ctrl+C interrupt to the session. */
|
|
37
|
+
interrupt(name: string): boolean;
|
|
38
|
+
/** Kill the PTY process and remove from tracking maps. */
|
|
39
|
+
kill(name: string): boolean;
|
|
40
|
+
}
|
|
41
|
+
export declare const ptySessionManager: PtySessionManager;
|
|
42
|
+
//# sourceMappingURL=pty-session-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pty-session-manager.d.ts","sourceRoot":"","sources":["../../../src/utils/pty-session-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyCH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAgC;IAC/C,OAAO,CAAC,OAAO,CAAoC;;IAMnD,oDAAoD;IACpD,WAAW,IAAI,OAAO;IAItB,8DAA8D;IAC9D,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIjC;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAmEzC,qDAAqD;IACrD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAW1C;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAS3C;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAY,GAAG,MAAM,GAAG,IAAI;IAMzD,4CAA4C;IAC5C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIhC,0DAA0D;IAC1D,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAY5B;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PTY Session Manager ā manages headless node-pty sessions for tmux-less operation.
|
|
4
|
+
*
|
|
5
|
+
* When tmux is unavailable, /new spawns Claude via node-pty instead of tmux.
|
|
6
|
+
* CCGram owns the PTY master, so all Telegram features (permissions, questions,
|
|
7
|
+
* commands, /status, /stop) work without tmux. Sessions are not attachable from
|
|
8
|
+
* a terminal.
|
|
9
|
+
*
|
|
10
|
+
* Uses optionalRequire so the bot starts normally even when node-pty is not installed.
|
|
11
|
+
*/
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.ptySessionManager = exports.PtySessionManager = void 0;
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const fs_1 = __importDefault(require("fs"));
|
|
19
|
+
const optional_require_1 = require("./optional-require");
|
|
20
|
+
const paths_1 = require("./paths");
|
|
21
|
+
// Key name ā raw escape sequence (mirrors tmux key names used throughout the bot)
|
|
22
|
+
const KEY_SEQUENCES = {
|
|
23
|
+
'Down': '\x1B[B',
|
|
24
|
+
'Up': '\x1B[A',
|
|
25
|
+
'Enter': '\r',
|
|
26
|
+
'C-m': '\r',
|
|
27
|
+
'C-c': '\x03',
|
|
28
|
+
'C-u': '\x15',
|
|
29
|
+
'Space': ' ',
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Strip ANSI escape sequences from terminal output for clean line buffering.
|
|
33
|
+
*/
|
|
34
|
+
function stripAnsi(str) {
|
|
35
|
+
return str
|
|
36
|
+
.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '') // CSI sequences (colors, cursor)
|
|
37
|
+
.replace(/\x1B\][^\x07]*\x07/g, '') // OSC sequences (window title)
|
|
38
|
+
.replace(/\x1B[()][AB012]/g, '') // character set
|
|
39
|
+
.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/g, ''); // control chars
|
|
40
|
+
}
|
|
41
|
+
class PtySessionManager {
|
|
42
|
+
ptyModule;
|
|
43
|
+
handles = new Map();
|
|
44
|
+
buffers = new Map();
|
|
45
|
+
constructor() {
|
|
46
|
+
this.ptyModule = (0, optional_require_1.optionalRequire)('node-pty', 'PTY sessions');
|
|
47
|
+
}
|
|
48
|
+
/** Whether node-pty is loadable on this machine. */
|
|
49
|
+
isAvailable() {
|
|
50
|
+
return this.ptyModule !== null;
|
|
51
|
+
}
|
|
52
|
+
/** Whether a live PTY handle exists for this session name. */
|
|
53
|
+
has(sessionName) {
|
|
54
|
+
return this.handles.has(sessionName);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Spawn a new headless PTY session running the claude CLI.
|
|
58
|
+
* @returns true on success, false on failure
|
|
59
|
+
*/
|
|
60
|
+
spawn(name, cwd) {
|
|
61
|
+
if (!this.ptyModule)
|
|
62
|
+
return false;
|
|
63
|
+
// Kill any existing handle for this name to avoid orphaned processes
|
|
64
|
+
if (this.handles.has(name)) {
|
|
65
|
+
this.kill(name);
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const claudePath = process.env.CLAUDE_CLI_PATH || 'claude';
|
|
69
|
+
const pty = this.ptyModule.spawn(claudePath, [], {
|
|
70
|
+
name: 'xterm-256color',
|
|
71
|
+
cols: 220,
|
|
72
|
+
rows: 50,
|
|
73
|
+
cwd,
|
|
74
|
+
env: { ...process.env },
|
|
75
|
+
});
|
|
76
|
+
this.handles.set(name, pty);
|
|
77
|
+
this.buffers.set(name, []);
|
|
78
|
+
// Ensure logs directory exists
|
|
79
|
+
const logsDir = path_1.default.join(paths_1.CCGRAM_HOME, 'logs');
|
|
80
|
+
try {
|
|
81
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
82
|
+
}
|
|
83
|
+
catch { }
|
|
84
|
+
const logFile = path_1.default.join(logsDir, `pty-${name}.log`);
|
|
85
|
+
pty.onData((data) => {
|
|
86
|
+
// Append raw data to session log
|
|
87
|
+
try {
|
|
88
|
+
fs_1.default.appendFileSync(logFile, data);
|
|
89
|
+
}
|
|
90
|
+
catch { }
|
|
91
|
+
// Strip ANSI and buffer as lines
|
|
92
|
+
const clean = stripAnsi(data);
|
|
93
|
+
const parts = clean.split(/\r?\n/);
|
|
94
|
+
const buf = this.buffers.get(name) || [];
|
|
95
|
+
for (let i = 0; i < parts.length; i++) {
|
|
96
|
+
if (i === 0) {
|
|
97
|
+
// First part continues the last buffered (partial) line
|
|
98
|
+
if (buf.length === 0) {
|
|
99
|
+
buf.push(parts[0]);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
buf[buf.length - 1] += parts[0];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
buf.push(parts[i]);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Keep last 100 lines
|
|
110
|
+
if (buf.length > 100) {
|
|
111
|
+
buf.splice(0, buf.length - 100);
|
|
112
|
+
}
|
|
113
|
+
this.buffers.set(name, buf);
|
|
114
|
+
});
|
|
115
|
+
pty.onExit(() => {
|
|
116
|
+
this.handles.delete(name);
|
|
117
|
+
this.buffers.delete(name);
|
|
118
|
+
});
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
process.stderr.write(`[pty-session-manager] Failed to spawn ${name}: ${err.message}\n`);
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** Write raw bytes directly to the PTY master fd. */
|
|
127
|
+
write(name, data) {
|
|
128
|
+
const pty = this.handles.get(name);
|
|
129
|
+
if (!pty)
|
|
130
|
+
return false;
|
|
131
|
+
try {
|
|
132
|
+
pty.write(data);
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Translate a tmux-style key name to its escape sequence and write to PTY.
|
|
141
|
+
* Supported: Down, Up, Enter, C-m, C-c, C-u, Space.
|
|
142
|
+
*/
|
|
143
|
+
sendKey(name, key) {
|
|
144
|
+
const seq = KEY_SEQUENCES[key];
|
|
145
|
+
if (seq === undefined) {
|
|
146
|
+
// Unknown key ā pass through as-is (shouldn't happen in normal usage)
|
|
147
|
+
return this.write(name, key);
|
|
148
|
+
}
|
|
149
|
+
return this.write(name, seq);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Return the last N lines of buffered output, or null if session unknown.
|
|
153
|
+
*/
|
|
154
|
+
capture(name, lines = 100) {
|
|
155
|
+
const buf = this.buffers.get(name);
|
|
156
|
+
if (!buf)
|
|
157
|
+
return null;
|
|
158
|
+
return buf.slice(-lines).join('\n');
|
|
159
|
+
}
|
|
160
|
+
/** Send Ctrl+C interrupt to the session. */
|
|
161
|
+
interrupt(name) {
|
|
162
|
+
return this.write(name, '\x03');
|
|
163
|
+
}
|
|
164
|
+
/** Kill the PTY process and remove from tracking maps. */
|
|
165
|
+
kill(name) {
|
|
166
|
+
const pty = this.handles.get(name);
|
|
167
|
+
if (!pty)
|
|
168
|
+
return false;
|
|
169
|
+
try {
|
|
170
|
+
pty.kill();
|
|
171
|
+
this.handles.delete(name);
|
|
172
|
+
this.buffers.delete(name);
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
exports.PtySessionManager = PtySessionManager;
|
|
181
|
+
exports.ptySessionManager = new PtySessionManager();
|
|
182
|
+
//# sourceMappingURL=pty-session-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pty-session-manager.js","sourceRoot":"","sources":["../../../src/utils/pty-session-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagent Activity Tracker
|
|
3
|
+
* Tracks subagent activities for including in completion emails
|
|
4
|
+
*/
|
|
5
|
+
interface ActivityDetails {
|
|
6
|
+
userQuestion?: string;
|
|
7
|
+
claudeResponse?: string;
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
}
|
|
10
|
+
interface Activity {
|
|
11
|
+
timestamp: string;
|
|
12
|
+
type: string;
|
|
13
|
+
description: string;
|
|
14
|
+
details: ActivityDetails;
|
|
15
|
+
}
|
|
16
|
+
interface ActivityInput {
|
|
17
|
+
type?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
details?: ActivityDetails;
|
|
20
|
+
}
|
|
21
|
+
interface SessionActivities {
|
|
22
|
+
startTime: string;
|
|
23
|
+
activities: Activity[];
|
|
24
|
+
}
|
|
25
|
+
interface ActivitiesMap {
|
|
26
|
+
[sessionId: string]: SessionActivities;
|
|
27
|
+
}
|
|
28
|
+
declare class SubagentTracker {
|
|
29
|
+
dataDir: string;
|
|
30
|
+
trackingFile: string;
|
|
31
|
+
constructor();
|
|
32
|
+
_escapeHtml(text: string): string;
|
|
33
|
+
_ensureDataDir(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Load existing activities
|
|
36
|
+
*/
|
|
37
|
+
_loadActivities(): ActivitiesMap;
|
|
38
|
+
/**
|
|
39
|
+
* Save activities to file
|
|
40
|
+
*/
|
|
41
|
+
_saveActivities(activities: ActivitiesMap): void;
|
|
42
|
+
/**
|
|
43
|
+
* Add a subagent activity
|
|
44
|
+
*/
|
|
45
|
+
addActivity(sessionId: string, activity: ActivityInput): void;
|
|
46
|
+
/**
|
|
47
|
+
* Get activities for a session
|
|
48
|
+
*/
|
|
49
|
+
getActivities(sessionId: string): SessionActivities | null;
|
|
50
|
+
/**
|
|
51
|
+
* Clear activities for a session
|
|
52
|
+
*/
|
|
53
|
+
clearActivities(sessionId: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Clean up old activities (older than 24 hours)
|
|
56
|
+
*/
|
|
57
|
+
cleanupOldActivities(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Format activities for email
|
|
60
|
+
*/
|
|
61
|
+
formatActivitiesForEmail(sessionId: string): string;
|
|
62
|
+
}
|
|
63
|
+
export = SubagentTracker;
|
|
64
|
+
//# sourceMappingURL=subagent-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-tracker.d.ts","sourceRoot":"","sources":["../../../src/utils/subagent-tracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,UAAU,eAAe;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,UAAU,QAAQ;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,eAAe,CAAC;CAC5B;AAED,UAAU,aAAa;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,UAAU,iBAAiB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,QAAQ,EAAE,CAAC;CAC1B;AAED,UAAU,aAAa;IACnB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAAC;CAC1C;AAMD,cAAM,eAAe;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;;IAQrB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAYjC,cAAc,IAAI,IAAI;IAMtB;;OAEG;IACH,eAAe,IAAI,aAAa;IAYhC;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,aAAa,GAAG,IAAI;IAQhD;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAoB7D;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI;IAK1D;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAMxC;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAe5B;;OAEG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAmFtD;AAED,SAAS,eAAe,CAAC"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Subagent Activity Tracker
|
|
4
|
+
* Tracks subagent activities for including in completion emails
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const paths_1 = require("./paths");
|
|
12
|
+
class SubagentTracker {
|
|
13
|
+
dataDir;
|
|
14
|
+
trackingFile;
|
|
15
|
+
constructor() {
|
|
16
|
+
this.dataDir = path_1.default.join(paths_1.PROJECT_ROOT, 'src/data');
|
|
17
|
+
this.trackingFile = path_1.default.join(this.dataDir, 'subagent-activities.json');
|
|
18
|
+
this._ensureDataDir();
|
|
19
|
+
}
|
|
20
|
+
_escapeHtml(text) {
|
|
21
|
+
if (!text)
|
|
22
|
+
return '';
|
|
23
|
+
const htmlEntities = {
|
|
24
|
+
'&': '&',
|
|
25
|
+
'<': '<',
|
|
26
|
+
'>': '>',
|
|
27
|
+
'"': '"',
|
|
28
|
+
"'": '''
|
|
29
|
+
};
|
|
30
|
+
return String(text).replace(/[&<>"']/g, char => htmlEntities[char]);
|
|
31
|
+
}
|
|
32
|
+
_ensureDataDir() {
|
|
33
|
+
if (!fs_1.default.existsSync(this.dataDir)) {
|
|
34
|
+
fs_1.default.mkdirSync(this.dataDir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Load existing activities
|
|
39
|
+
*/
|
|
40
|
+
_loadActivities() {
|
|
41
|
+
if (!fs_1.default.existsSync(this.trackingFile)) {
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
return JSON.parse(fs_1.default.readFileSync(this.trackingFile, 'utf8'));
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error('Failed to load subagent activities:', error);
|
|
49
|
+
return {};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Save activities to file
|
|
54
|
+
*/
|
|
55
|
+
_saveActivities(activities) {
|
|
56
|
+
try {
|
|
57
|
+
fs_1.default.writeFileSync(this.trackingFile, JSON.stringify(activities, null, 2));
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error('Failed to save subagent activities:', error);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Add a subagent activity
|
|
65
|
+
*/
|
|
66
|
+
addActivity(sessionId, activity) {
|
|
67
|
+
const activities = this._loadActivities();
|
|
68
|
+
if (!activities[sessionId]) {
|
|
69
|
+
activities[sessionId] = {
|
|
70
|
+
startTime: new Date().toISOString(),
|
|
71
|
+
activities: []
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
activities[sessionId].activities.push({
|
|
75
|
+
timestamp: new Date().toISOString(),
|
|
76
|
+
type: activity.type || 'subagent',
|
|
77
|
+
description: activity.description || 'Subagent activity',
|
|
78
|
+
details: activity.details || {}
|
|
79
|
+
});
|
|
80
|
+
this._saveActivities(activities);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get activities for a session
|
|
84
|
+
*/
|
|
85
|
+
getActivities(sessionId) {
|
|
86
|
+
const activities = this._loadActivities();
|
|
87
|
+
return activities[sessionId] || null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Clear activities for a session
|
|
91
|
+
*/
|
|
92
|
+
clearActivities(sessionId) {
|
|
93
|
+
const activities = this._loadActivities();
|
|
94
|
+
delete activities[sessionId];
|
|
95
|
+
this._saveActivities(activities);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Clean up old activities (older than 24 hours)
|
|
99
|
+
*/
|
|
100
|
+
cleanupOldActivities() {
|
|
101
|
+
const activities = this._loadActivities();
|
|
102
|
+
const now = new Date();
|
|
103
|
+
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
|
104
|
+
for (const sessionId in activities) {
|
|
105
|
+
const startTime = new Date(activities[sessionId].startTime);
|
|
106
|
+
if (startTime < oneDayAgo) {
|
|
107
|
+
delete activities[sessionId];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this._saveActivities(activities);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Format activities for email
|
|
114
|
+
*/
|
|
115
|
+
formatActivitiesForEmail(sessionId) {
|
|
116
|
+
const sessionData = this.getActivities(sessionId);
|
|
117
|
+
if (!sessionData || sessionData.activities.length === 0) {
|
|
118
|
+
return '';
|
|
119
|
+
}
|
|
120
|
+
const activities = sessionData.activities;
|
|
121
|
+
const grouped = {};
|
|
122
|
+
// Group activities by type
|
|
123
|
+
activities.forEach(activity => {
|
|
124
|
+
const type = activity.type;
|
|
125
|
+
if (!grouped[type]) {
|
|
126
|
+
grouped[type] = [];
|
|
127
|
+
}
|
|
128
|
+
grouped[type].push(activity);
|
|
129
|
+
});
|
|
130
|
+
// Format as HTML
|
|
131
|
+
let html = `
|
|
132
|
+
<!-- Subagent Activities -->
|
|
133
|
+
<div style="margin: 20px 0; padding: 15px; background-color: #1f1f1f; border: 1px solid #444; border-radius: 4px;">
|
|
134
|
+
<div style="color: #ff9800; margin-bottom: 10px; font-weight: bold;">š Subagent Activities Summary</div>
|
|
135
|
+
<div style="color: #ccc; font-size: 13px; line-height: 1.6;">`;
|
|
136
|
+
for (const [type, items] of Object.entries(grouped)) {
|
|
137
|
+
html += `<div style="margin-bottom: 10px;">`;
|
|
138
|
+
html += `<div style="color: #00bcd4; font-weight: bold;">${type} (${items.length} activities)</div>`;
|
|
139
|
+
html += `<ul style="margin: 5px 0 0 20px; padding: 0;">`;
|
|
140
|
+
items.forEach((item, index) => {
|
|
141
|
+
const time = new Date(item.timestamp).toLocaleTimeString();
|
|
142
|
+
html += `<li style="color: #ccc; margin: 8px 0; list-style-type: none;">`;
|
|
143
|
+
html += `<div style="background-color: #262626; padding: 10px; border-left: 3px solid #00bcd4; margin: 5px 0;">`;
|
|
144
|
+
html += `<div><span style="color: #999;">[${time}]</span> <strong style="color: #fff;">${this._escapeHtml(item.description || 'Subagent task')}</strong></div>`;
|
|
145
|
+
if (item.details) {
|
|
146
|
+
// Show the question if available
|
|
147
|
+
if (item.details.userQuestion && item.details.userQuestion !== item.description) {
|
|
148
|
+
html += `<div style="color: #00ff00; margin-top: 5px; font-size: 12px;">ā Question: ${this._escapeHtml(item.details.userQuestion)}</div>`;
|
|
149
|
+
}
|
|
150
|
+
// Show the response
|
|
151
|
+
if (item.details.claudeResponse) {
|
|
152
|
+
const response = item.details.claudeResponse;
|
|
153
|
+
// Check if this is just initialization text
|
|
154
|
+
if (response.includes('Initializing...') || response.includes('Concocting...')) {
|
|
155
|
+
html += `<div style="color: #ff9800; margin-top: 5px; font-size: 12px; font-style: italic;">ā³ Subagent was processing... (full output available in tmux session)</div>`;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
html += `<div style="color: #ccc; margin-top: 5px; margin-left: 20px; font-size: 12px; white-space: pre-wrap; max-height: 200px; overflow-y: auto; background-color: #1a1a1a; padding: 8px; border-radius: 4px;">`;
|
|
159
|
+
html += this._escapeHtml(response);
|
|
160
|
+
html += `</div>`;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
html += `</div>`;
|
|
165
|
+
html += `</li>`;
|
|
166
|
+
});
|
|
167
|
+
html += `</ul>`;
|
|
168
|
+
html += `</div>`;
|
|
169
|
+
}
|
|
170
|
+
html += `
|
|
171
|
+
</div>
|
|
172
|
+
</div>`;
|
|
173
|
+
// Also format as plain text for text email
|
|
174
|
+
let text = '\nš Subagent Activities Summary\n\n';
|
|
175
|
+
for (const [type, items] of Object.entries(grouped)) {
|
|
176
|
+
text += `${type} (${items.length} activities)\n`;
|
|
177
|
+
items.forEach((item, index) => {
|
|
178
|
+
const time = new Date(item.timestamp).toLocaleTimeString();
|
|
179
|
+
text += ` ${index + 1}. [${time}] ${item.description}\n`;
|
|
180
|
+
if (item.details && item.details.claudeResponse) {
|
|
181
|
+
text += ` ${item.details.claudeResponse}\n`;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
text += '\n';
|
|
185
|
+
}
|
|
186
|
+
// Return HTML for email (the email sender will use it appropriately)
|
|
187
|
+
return html;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
module.exports = SubagentTracker;
|
|
191
|
+
//# sourceMappingURL=subagent-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-tracker.js","sourceRoot":"","sources":["../../../src/utils/subagent-tracker.ts"],"names":[],"mappings":"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"}
|