ttyd-mux 0.4.1 → 0.4.3
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/README.md +276 -47
- package/dist/commands/share.d.ts +25 -0
- package/dist/commands/share.d.ts.map +1 -0
- package/dist/commands/share.js +108 -0
- package/dist/commands/share.js.map +1 -0
- package/dist/config/state-store.d.ts +9 -1
- package/dist/config/state-store.d.ts.map +1 -1
- package/dist/config/state-store.js +30 -2
- package/dist/config/state-store.js.map +1 -1
- package/dist/config/state.d.ts +9 -1
- package/dist/config/state.d.ts.map +1 -1
- package/dist/config/state.js +67 -1
- package/dist/config/state.js.map +1 -1
- package/dist/config/types.d.ts +52 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +23 -1
- package/dist/config/types.js.map +1 -1
- package/dist/daemon/api-handler.d.ts.map +1 -1
- package/dist/daemon/api-handler.js +180 -2
- package/dist/daemon/api-handler.js.map +1 -1
- package/dist/daemon/http-proxy.d.ts +3 -2
- package/dist/daemon/http-proxy.d.ts.map +1 -1
- package/dist/daemon/http-proxy.js +7 -4
- package/dist/daemon/http-proxy.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +22 -2
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/notification/index.d.ts +42 -0
- package/dist/daemon/notification/index.d.ts.map +1 -0
- package/dist/daemon/notification/index.js +83 -0
- package/dist/daemon/notification/index.js.map +1 -0
- package/dist/daemon/notification/matcher.d.ts +30 -0
- package/dist/daemon/notification/matcher.d.ts.map +1 -0
- package/dist/daemon/notification/matcher.js +72 -0
- package/dist/daemon/notification/matcher.js.map +1 -0
- package/dist/daemon/notification/sender.d.ts +38 -0
- package/dist/daemon/notification/sender.d.ts.map +1 -0
- package/dist/daemon/notification/sender.js +74 -0
- package/dist/daemon/notification/sender.js.map +1 -0
- package/dist/daemon/notification/subscription.d.ts +35 -0
- package/dist/daemon/notification/subscription.d.ts.map +1 -0
- package/dist/daemon/notification/subscription.js +52 -0
- package/dist/daemon/notification/subscription.js.map +1 -0
- package/dist/daemon/notification/types.d.ts +70 -0
- package/dist/daemon/notification/types.d.ts.map +1 -0
- package/dist/daemon/notification/types.js +5 -0
- package/dist/daemon/notification/types.js.map +1 -0
- package/dist/daemon/notification/vapid.d.ts +25 -0
- package/dist/daemon/notification/vapid.d.ts.map +1 -0
- package/dist/daemon/notification/vapid.js +56 -0
- package/dist/daemon/notification/vapid.js.map +1 -0
- package/dist/daemon/pwa.d.ts +2 -1
- package/dist/daemon/pwa.d.ts.map +1 -1
- package/dist/daemon/pwa.js +51 -0
- package/dist/daemon/pwa.js.map +1 -1
- package/dist/daemon/router.d.ts +10 -0
- package/dist/daemon/router.d.ts.map +1 -1
- package/dist/daemon/router.js +122 -10
- package/dist/daemon/router.js.map +1 -1
- package/dist/daemon/share-manager.d.ts +55 -0
- package/dist/daemon/share-manager.d.ts.map +1 -0
- package/dist/daemon/share-manager.js +115 -0
- package/dist/daemon/share-manager.js.map +1 -0
- package/dist/daemon/toolbar/index.d.ts +4 -12
- package/dist/daemon/toolbar/index.d.ts.map +1 -1
- package/dist/daemon/toolbar/index.js +6 -794
- package/dist/daemon/toolbar/index.js.map +1 -1
- package/dist/daemon/toolbar/styles.d.ts +1 -1
- package/dist/daemon/toolbar/styles.d.ts.map +1 -1
- package/dist/daemon/toolbar/styles.js +106 -0
- package/dist/daemon/toolbar/styles.js.map +1 -1
- package/dist/daemon/toolbar/template.d.ts +1 -1
- package/dist/daemon/toolbar/template.d.ts.map +1 -1
- package/dist/daemon/toolbar/template.js +11 -0
- package/dist/daemon/toolbar/template.js.map +1 -1
- package/dist/daemon/ws-proxy.d.ts +21 -1
- package/dist/daemon/ws-proxy.d.ts.map +1 -1
- package/dist/daemon/ws-proxy.js +107 -5
- package/dist/daemon/ws-proxy.js.map +1 -1
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/toolbar.js +2 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-proxy.js","sourceRoot":"","sources":["../../src/daemon/http-proxy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;AAElC;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAsD;IAEtD,MAAM,YAAY,GAAsC,EAAE,CAAC;IAC3D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,KAAK,kBAAkB,IAAI,GAAG,KAAK,mBAAmB,EAAE,CAAC;YACrF,YAAY,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,YAAoB,EACpB,YAAqB,EACrB,QAAgB;
|
|
1
|
+
{"version":3,"file":"http-proxy.js","sourceRoot":"","sources":["../../src/daemon/http-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA0CD,wBAAsB,WAAW,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6M5E"}
|
package/dist/daemon/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, unlinkSync } from 'node:fs';
|
|
2
2
|
import { createServer as createUnixServer } from 'node:net';
|
|
3
|
-
import { clearDaemonState, getSocketPath, getStateDir, setDaemonState } from '../config/state.js';
|
|
3
|
+
import { addPushSubscription, clearDaemonState, getAllPushSubscriptions, getSocketPath, getStateDir, removePushSubscription, setDaemonState } from '../config/state.js';
|
|
4
4
|
import { createLogger } from '../utils/logger.js';
|
|
5
5
|
import { getCurrentConfig, initConfigManager, reloadConfig } from './config-manager.js';
|
|
6
|
+
import { createNotificationService } from './notification/index.js';
|
|
6
7
|
import { createDaemonServer, setConfigGetter } from './server.js';
|
|
7
8
|
import { sessionManager } from './session-manager.js';
|
|
9
|
+
import { setNotificationService } from './ws-proxy.js';
|
|
8
10
|
const log = createLogger('daemon');
|
|
9
11
|
/**
|
|
10
12
|
* Clean up a socket file if it exists
|
|
@@ -60,9 +62,27 @@ export async function startDaemon(options = {}) {
|
|
|
60
62
|
log.info(`Config loaded: port=${config.daemon_port}, base_path=${config.base_path}`);
|
|
61
63
|
// Set up config getter for hot-reload support
|
|
62
64
|
setConfigGetter(getCurrentConfig);
|
|
65
|
+
// Initialize notification service if configured
|
|
66
|
+
const stateDir = getStateDir();
|
|
67
|
+
if (config.notifications?.enabled !== false) {
|
|
68
|
+
try {
|
|
69
|
+
const notificationService = createNotificationService(config.notifications ?? { enabled: true, patterns: [], default_cooldown: 300 }, stateDir, {
|
|
70
|
+
getSubscriptions: getAllPushSubscriptions,
|
|
71
|
+
addSubscription: addPushSubscription,
|
|
72
|
+
removeSubscription: removePushSubscription
|
|
73
|
+
});
|
|
74
|
+
setNotificationService(notificationService);
|
|
75
|
+
log.info('Notification service initialized');
|
|
76
|
+
if (config.notifications?.patterns?.length) {
|
|
77
|
+
log.info(`Watching ${config.notifications.patterns.length} pattern(s) for notifications`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
log.error(`Failed to initialize notification service: ${String(error)}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
63
84
|
const socketPath = getSocketPath();
|
|
64
85
|
// Ensure state directory exists
|
|
65
|
-
const stateDir = getStateDir();
|
|
66
86
|
if (!existsSync(stateDir)) {
|
|
67
87
|
mkdirSync(stateDir, { recursive: true });
|
|
68
88
|
log.info(`Created state directory: ${stateDir}`);
|
package/dist/daemon/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification module - Push notifications for terminal output patterns
|
|
3
|
+
*/
|
|
4
|
+
export * from './types.js';
|
|
5
|
+
export * from './matcher.js';
|
|
6
|
+
export * from './sender.js';
|
|
7
|
+
export * from './subscription.js';
|
|
8
|
+
export * from './vapid.js';
|
|
9
|
+
import { type NotificationMatcher } from './matcher.js';
|
|
10
|
+
import { type NotificationSender } from './sender.js';
|
|
11
|
+
import { type SubscriptionManager } from './subscription.js';
|
|
12
|
+
import type { NotificationConfig, PushSubscription } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* NotificationService - main notification system
|
|
15
|
+
*/
|
|
16
|
+
export interface NotificationService {
|
|
17
|
+
/** Pattern matcher */
|
|
18
|
+
matcher: NotificationMatcher;
|
|
19
|
+
/** Subscription manager */
|
|
20
|
+
subscriptions: SubscriptionManager;
|
|
21
|
+
/** Notification sender */
|
|
22
|
+
sender: NotificationSender;
|
|
23
|
+
/** VAPID public key for client subscription */
|
|
24
|
+
vapidPublicKey: string;
|
|
25
|
+
/** Process terminal output and send notifications if patterns match */
|
|
26
|
+
processOutput(sessionName: string, text: string): Promise<void>;
|
|
27
|
+
/** Check if notifications are enabled */
|
|
28
|
+
isEnabled(): boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Persistence interface for notification data
|
|
32
|
+
*/
|
|
33
|
+
export interface NotificationStore {
|
|
34
|
+
getSubscriptions(): PushSubscription[];
|
|
35
|
+
addSubscription(subscription: PushSubscription): void;
|
|
36
|
+
removeSubscription(id: string): void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create the notification service
|
|
40
|
+
*/
|
|
41
|
+
export declare function createNotificationService(config: NotificationConfig, stateDir: string, store: NotificationStore): NotificationService;
|
|
42
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/daemon/notification/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAG3B,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAA4B,KAAK,kBAAkB,EAA0B,MAAM,aAAa,CAAC;AACxG,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExF,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAa,MAAM,YAAY,CAAC;AAIlF;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,sBAAsB;IACtB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,2BAA2B;IAC3B,aAAa,EAAE,mBAAmB,CAAC;IACnC,0BAA0B;IAC1B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,+CAA+C;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,yCAAyC;IACzC,SAAS,IAAI,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,IAAI,gBAAgB,EAAE,CAAC;IACvC,eAAe,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACtD,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AASD;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,iBAAiB,GACvB,mBAAmB,CAmErB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification module - Push notifications for terminal output patterns
|
|
3
|
+
*/
|
|
4
|
+
export * from './types.js';
|
|
5
|
+
export * from './matcher.js';
|
|
6
|
+
export * from './sender.js';
|
|
7
|
+
export * from './subscription.js';
|
|
8
|
+
export * from './vapid.js';
|
|
9
|
+
import { createLogger } from '../../utils/logger.js';
|
|
10
|
+
import { createNotificationMatcher } from './matcher.js';
|
|
11
|
+
import { createNotificationSender } from './sender.js';
|
|
12
|
+
import { createSubscriptionManager } from './subscription.js';
|
|
13
|
+
import { loadOrGenerateVapidKeys } from './vapid.js';
|
|
14
|
+
const log = createLogger('notification');
|
|
15
|
+
/** Default bell pattern for terminal bell notification */
|
|
16
|
+
const BELL_PATTERN = {
|
|
17
|
+
regex: '\x07',
|
|
18
|
+
message: 'Terminal bell',
|
|
19
|
+
cooldown: 10
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Create the notification service
|
|
23
|
+
*/
|
|
24
|
+
export function createNotificationService(config, stateDir, store) {
|
|
25
|
+
const enabled = config.enabled !== false;
|
|
26
|
+
const bellEnabled = config.bell_notification !== false; // Default: true
|
|
27
|
+
const bellCooldown = config.bell_cooldown ?? 10;
|
|
28
|
+
const userPatterns = config.patterns ?? [];
|
|
29
|
+
const defaultCooldown = config.default_cooldown ?? 300;
|
|
30
|
+
const contactEmail = config.contact_email ?? 'webmaster@localhost';
|
|
31
|
+
// Build patterns: bell pattern (for client-side onBell trigger) + user patterns
|
|
32
|
+
// Note: Bell detection is primarily done client-side via xterm.js onBell event,
|
|
33
|
+
// which sends a POST to /api/notifications/bell. The bell pattern here handles
|
|
34
|
+
// that trigger and applies cooldown.
|
|
35
|
+
const patterns = bellEnabled
|
|
36
|
+
? [{ ...BELL_PATTERN, cooldown: bellCooldown }, ...userPatterns]
|
|
37
|
+
: userPatterns;
|
|
38
|
+
// Load or generate VAPID keys
|
|
39
|
+
let vapidKeys;
|
|
40
|
+
try {
|
|
41
|
+
vapidKeys = loadOrGenerateVapidKeys(stateDir);
|
|
42
|
+
log.info('VAPID keys loaded');
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
log.error(`Failed to load VAPID keys: ${String(error)}`);
|
|
46
|
+
// Generate ephemeral keys
|
|
47
|
+
vapidKeys = { publicKey: '', privateKey: '' };
|
|
48
|
+
}
|
|
49
|
+
// Create matcher
|
|
50
|
+
const matcher = createNotificationMatcher({
|
|
51
|
+
patterns,
|
|
52
|
+
defaultCooldown
|
|
53
|
+
});
|
|
54
|
+
// Create subscription manager
|
|
55
|
+
const subscriptions = createSubscriptionManager(store);
|
|
56
|
+
// Create sender (wraps subscription manager)
|
|
57
|
+
const subscriptionStore = {
|
|
58
|
+
getSubscriptions: () => store.getSubscriptions(),
|
|
59
|
+
getSubscriptionsForSession: (sessionName) => subscriptions.getForSession(sessionName),
|
|
60
|
+
removeSubscription: (id) => store.removeSubscription(id)
|
|
61
|
+
};
|
|
62
|
+
const sender = createNotificationSender(vapidKeys, contactEmail, subscriptionStore);
|
|
63
|
+
return {
|
|
64
|
+
matcher,
|
|
65
|
+
subscriptions,
|
|
66
|
+
sender,
|
|
67
|
+
vapidPublicKey: vapidKeys.publicKey,
|
|
68
|
+
async processOutput(sessionName, text) {
|
|
69
|
+
if (!enabled || patterns.length === 0) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const match = matcher.match(sessionName, text);
|
|
73
|
+
if (match) {
|
|
74
|
+
log.info(`Pattern matched: "${match.pattern.message}" in session ${sessionName}`);
|
|
75
|
+
await sender.sendNotification(match);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
isEnabled() {
|
|
79
|
+
return enabled && patterns.length > 0;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/daemon/notification/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern matcher for notification triggers
|
|
3
|
+
*/
|
|
4
|
+
import type { MatchResult, PatternConfig } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Matcher configuration
|
|
7
|
+
*/
|
|
8
|
+
export interface MatcherConfig {
|
|
9
|
+
patterns: PatternConfig[];
|
|
10
|
+
defaultCooldown: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* NotificationMatcher interface
|
|
14
|
+
*/
|
|
15
|
+
export interface NotificationMatcher {
|
|
16
|
+
/** Match text against patterns, respecting cooldowns */
|
|
17
|
+
match(sessionName: string, text: string): MatchResult | null;
|
|
18
|
+
/** Check if text matches a specific pattern (ignores cooldown) */
|
|
19
|
+
matchesPattern(regex: string, text: string): boolean;
|
|
20
|
+
/** Clear cooldown for a specific session and pattern */
|
|
21
|
+
clearCooldown(sessionName: string, regex: string): void;
|
|
22
|
+
/** Reset all cooldowns */
|
|
23
|
+
reset(): void;
|
|
24
|
+
}
|
|
25
|
+
export type { PatternConfig, MatchResult };
|
|
26
|
+
/**
|
|
27
|
+
* Create a notification matcher
|
|
28
|
+
*/
|
|
29
|
+
export declare function createNotificationMatcher(config: MatcherConfig): NotificationMatcher;
|
|
30
|
+
//# sourceMappingURL=matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../../src/daemon/notification/matcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IAC7D,kEAAkE;IAClE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACrD,wDAAwD;IACxD,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACxD,0BAA0B;IAC1B,KAAK,IAAI,IAAI,CAAC;CACf;AAGD,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC;AAS3C;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,GAAG,mBAAmB,CAmEpF"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern matcher for notification triggers
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Create a cooldown key for tracking
|
|
6
|
+
*/
|
|
7
|
+
function getCooldownKey(sessionName, regex) {
|
|
8
|
+
return `${sessionName}:${regex}`;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Create a notification matcher
|
|
12
|
+
*/
|
|
13
|
+
export function createNotificationMatcher(config) {
|
|
14
|
+
const { patterns, defaultCooldown } = config;
|
|
15
|
+
// Map of cooldown key -> timestamp when cooldown expires
|
|
16
|
+
const cooldowns = new Map();
|
|
17
|
+
// Pre-compile regexes
|
|
18
|
+
const compiledPatterns = [];
|
|
19
|
+
for (const pattern of patterns) {
|
|
20
|
+
try {
|
|
21
|
+
compiledPatterns.push({
|
|
22
|
+
config: pattern,
|
|
23
|
+
regex: new RegExp(pattern.regex)
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Skip invalid regex
|
|
28
|
+
console.error(`[Notification] Invalid regex: ${pattern.regex}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
match(sessionName, text) {
|
|
33
|
+
const now = Date.now();
|
|
34
|
+
for (const { config: pattern, regex } of compiledPatterns) {
|
|
35
|
+
if (regex.test(text)) {
|
|
36
|
+
const key = getCooldownKey(sessionName, pattern.regex);
|
|
37
|
+
const cooldownExpires = cooldowns.get(key);
|
|
38
|
+
// Check if in cooldown period
|
|
39
|
+
if (cooldownExpires && now < cooldownExpires) {
|
|
40
|
+
continue; // Still in cooldown, try next pattern
|
|
41
|
+
}
|
|
42
|
+
// Set cooldown
|
|
43
|
+
const cooldownSeconds = pattern.cooldown ?? defaultCooldown;
|
|
44
|
+
cooldowns.set(key, now + cooldownSeconds * 1000);
|
|
45
|
+
return {
|
|
46
|
+
pattern,
|
|
47
|
+
matchedText: text,
|
|
48
|
+
sessionName,
|
|
49
|
+
timestamp: new Date().toISOString()
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
},
|
|
55
|
+
matchesPattern(regex, text) {
|
|
56
|
+
try {
|
|
57
|
+
return new RegExp(regex).test(text);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
clearCooldown(sessionName, regex) {
|
|
64
|
+
const key = getCooldownKey(sessionName, regex);
|
|
65
|
+
cooldowns.delete(key);
|
|
66
|
+
},
|
|
67
|
+
reset() {
|
|
68
|
+
cooldowns.clear();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../../src/daemon/notification/matcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AA6BH;;GAEG;AACH,SAAS,cAAc,CAAC,WAAmB,EAAE,KAAa;IACxD,OAAO,GAAG,WAAW,IAAI,KAAK,EAAE,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAqB;IAC7D,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC;IAE7C,yDAAyD;IACzD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE5C,sBAAsB;IACtB,MAAM,gBAAgB,GAAoD,EAAE,CAAC;IAC7E,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,gBAAgB,CAAC,IAAI,CAAC;gBACpB,MAAM,EAAE,OAAO;gBACf,KAAK,EAAE,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;aACjC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,qBAAqB;YACrB,OAAO,CAAC,KAAK,CAAC,iCAAiC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,CAAC,WAAmB,EAAE,IAAY;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAEvB,KAAK,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,gBAAgB,EAAE,CAAC;gBAC1D,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrB,MAAM,GAAG,GAAG,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;oBACvD,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBAE3C,8BAA8B;oBAC9B,IAAI,eAAe,IAAI,GAAG,GAAG,eAAe,EAAE,CAAC;wBAC7C,SAAS,CAAC,sCAAsC;oBAClD,CAAC;oBAED,eAAe;oBACf,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,IAAI,eAAe,CAAC;oBAC5D,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,eAAe,GAAG,IAAI,CAAC,CAAC;oBAEjD,OAAO;wBACL,OAAO;wBACP,WAAW,EAAE,IAAI;wBACjB,WAAW;wBACX,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;qBACpC,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAED,cAAc,CAAC,KAAa,EAAE,IAAY;YACxC,IAAI,CAAC;gBACH,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,aAAa,CAAC,WAAmB,EAAE,KAAa;YAC9C,MAAM,GAAG,GAAG,cAAc,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YAC/C,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;QAED,KAAK;YACH,SAAS,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push notification sender
|
|
3
|
+
*/
|
|
4
|
+
import type { MatchResult, PushSubscription, VapidKeys } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Notification payload sent to client
|
|
7
|
+
*/
|
|
8
|
+
export interface NotificationPayload {
|
|
9
|
+
title: string;
|
|
10
|
+
body: string;
|
|
11
|
+
sessionName: string;
|
|
12
|
+
matchedText: string;
|
|
13
|
+
timestamp: string;
|
|
14
|
+
icon?: string;
|
|
15
|
+
tag?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Subscription store interface
|
|
19
|
+
*/
|
|
20
|
+
export interface SubscriptionStore {
|
|
21
|
+
getSubscriptions(): PushSubscription[];
|
|
22
|
+
getSubscriptionsForSession(sessionName: string): PushSubscription[];
|
|
23
|
+
removeSubscription(id: string): void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* NotificationSender interface
|
|
27
|
+
*/
|
|
28
|
+
export interface NotificationSender {
|
|
29
|
+
/** Send notification to all relevant subscribers */
|
|
30
|
+
sendNotification(match: MatchResult): Promise<number>;
|
|
31
|
+
/** Send notification to a specific subscription */
|
|
32
|
+
sendToSubscription(subscription: PushSubscription, payload: NotificationPayload): Promise<boolean>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Create a notification sender
|
|
36
|
+
*/
|
|
37
|
+
export declare function createNotificationSender(vapidKeys: VapidKeys, contactEmail: string, store: SubscriptionStore): NotificationSender;
|
|
38
|
+
//# sourceMappingURL=sender.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sender.d.ts","sourceRoot":"","sources":["../../../src/daemon/notification/sender.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAI3E;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,IAAI,gBAAgB,EAAE,CAAC;IACvC,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAAC;IACpE,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,mDAAmD;IACnD,kBAAkB,CAAC,YAAY,EAAE,gBAAgB,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpG;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,iBAAiB,GACvB,kBAAkB,CA0EpB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push notification sender
|
|
3
|
+
*/
|
|
4
|
+
import webpush from 'web-push';
|
|
5
|
+
import { createLogger } from '../../utils/logger.js';
|
|
6
|
+
const log = createLogger('notification');
|
|
7
|
+
/**
|
|
8
|
+
* Create a notification sender
|
|
9
|
+
*/
|
|
10
|
+
export function createNotificationSender(vapidKeys, contactEmail, store) {
|
|
11
|
+
// Configure web-push with VAPID details
|
|
12
|
+
webpush.setVapidDetails(`mailto:${contactEmail}`, vapidKeys.publicKey, vapidKeys.privateKey);
|
|
13
|
+
return {
|
|
14
|
+
async sendNotification(match) {
|
|
15
|
+
const payload = {
|
|
16
|
+
title: match.pattern.message,
|
|
17
|
+
body: match.matchedText.slice(0, 200), // Truncate long text
|
|
18
|
+
sessionName: match.sessionName,
|
|
19
|
+
matchedText: match.matchedText,
|
|
20
|
+
timestamp: match.timestamp,
|
|
21
|
+
tag: `ttyd-mux-${match.sessionName}`
|
|
22
|
+
};
|
|
23
|
+
// Get subscriptions for this session (or all if no session filter)
|
|
24
|
+
const subscriptions = store.getSubscriptionsForSession(match.sessionName);
|
|
25
|
+
if (subscriptions.length === 0) {
|
|
26
|
+
log.debug(`No subscriptions for session: ${match.sessionName}`);
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
let sent = 0;
|
|
30
|
+
const invalidSubscriptions = [];
|
|
31
|
+
for (const subscription of subscriptions) {
|
|
32
|
+
try {
|
|
33
|
+
await webpush.sendNotification({
|
|
34
|
+
endpoint: subscription.endpoint,
|
|
35
|
+
keys: subscription.keys
|
|
36
|
+
}, JSON.stringify(payload));
|
|
37
|
+
sent++;
|
|
38
|
+
log.debug(`Sent notification to subscription: ${subscription.id}`);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const err = error;
|
|
42
|
+
if (err.statusCode === 410 || err.statusCode === 404) {
|
|
43
|
+
// Subscription no longer valid
|
|
44
|
+
invalidSubscriptions.push(subscription.id);
|
|
45
|
+
log.debug(`Subscription expired: ${subscription.id}`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
log.error(`Failed to send notification: ${String(error)}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Remove invalid subscriptions
|
|
53
|
+
for (const id of invalidSubscriptions) {
|
|
54
|
+
store.removeSubscription(id);
|
|
55
|
+
}
|
|
56
|
+
log.info(`Sent ${sent}/${subscriptions.length} notifications for pattern: ${match.pattern.message}`);
|
|
57
|
+
return sent;
|
|
58
|
+
},
|
|
59
|
+
async sendToSubscription(subscription, payload) {
|
|
60
|
+
try {
|
|
61
|
+
await webpush.sendNotification({
|
|
62
|
+
endpoint: subscription.endpoint,
|
|
63
|
+
keys: subscription.keys
|
|
64
|
+
}, JSON.stringify(payload));
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
log.error(`Failed to send notification: ${String(error)}`);
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=sender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sender.js","sourceRoot":"","sources":["../../../src/daemon/notification/sender.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push subscription management
|
|
3
|
+
*/
|
|
4
|
+
import type { PushSubscription } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Subscription store with persistence
|
|
7
|
+
*/
|
|
8
|
+
export interface SubscriptionStoreConfig {
|
|
9
|
+
getSubscriptions(): PushSubscription[];
|
|
10
|
+
addSubscription(subscription: PushSubscription): void;
|
|
11
|
+
removeSubscription(id: string): void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Subscription manager interface
|
|
15
|
+
*/
|
|
16
|
+
export interface SubscriptionManager {
|
|
17
|
+
/** Add a new subscription */
|
|
18
|
+
subscribe(endpoint: string, keys: {
|
|
19
|
+
p256dh: string;
|
|
20
|
+
auth: string;
|
|
21
|
+
}, sessionName?: string): PushSubscription;
|
|
22
|
+
/** Remove a subscription by ID */
|
|
23
|
+
unsubscribe(id: string): boolean;
|
|
24
|
+
/** Get all subscriptions */
|
|
25
|
+
getAll(): PushSubscription[];
|
|
26
|
+
/** Get subscriptions for a specific session (includes global subscriptions) */
|
|
27
|
+
getForSession(sessionName: string): PushSubscription[];
|
|
28
|
+
/** Check if a subscription exists by endpoint */
|
|
29
|
+
hasSubscription(endpoint: string): boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create a subscription manager
|
|
33
|
+
*/
|
|
34
|
+
export declare function createSubscriptionManager(store: SubscriptionStoreConfig): SubscriptionManager;
|
|
35
|
+
//# sourceMappingURL=subscription.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../../src/daemon/notification/subscription.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,IAAI,gBAAgB,EAAE,CAAC;IACvC,eAAe,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACtD,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,6BAA6B;IAC7B,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC5G,kCAAkC;IAClC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,4BAA4B;IAC5B,MAAM,IAAI,gBAAgB,EAAE,CAAC;IAC7B,+EAA+E;IAC/E,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAAC;IACvD,iDAAiD;IACjD,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5C;AASD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,uBAAuB,GAAG,mBAAmB,CAiD7F"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push subscription management
|
|
3
|
+
*/
|
|
4
|
+
import { randomBytes } from 'node:crypto';
|
|
5
|
+
/**
|
|
6
|
+
* Generate a subscription ID
|
|
7
|
+
*/
|
|
8
|
+
function generateSubscriptionId() {
|
|
9
|
+
return randomBytes(8).toString('hex');
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create a subscription manager
|
|
13
|
+
*/
|
|
14
|
+
export function createSubscriptionManager(store) {
|
|
15
|
+
return {
|
|
16
|
+
subscribe(endpoint, keys, sessionName) {
|
|
17
|
+
// Check if already subscribed
|
|
18
|
+
const existing = store.getSubscriptions().find((s) => s.endpoint === endpoint);
|
|
19
|
+
if (existing) {
|
|
20
|
+
return existing;
|
|
21
|
+
}
|
|
22
|
+
const subscription = {
|
|
23
|
+
id: generateSubscriptionId(),
|
|
24
|
+
endpoint,
|
|
25
|
+
keys,
|
|
26
|
+
sessionName,
|
|
27
|
+
createdAt: new Date().toISOString()
|
|
28
|
+
};
|
|
29
|
+
store.addSubscription(subscription);
|
|
30
|
+
return subscription;
|
|
31
|
+
},
|
|
32
|
+
unsubscribe(id) {
|
|
33
|
+
const subscriptions = store.getSubscriptions();
|
|
34
|
+
const exists = subscriptions.some((s) => s.id === id);
|
|
35
|
+
if (exists) {
|
|
36
|
+
store.removeSubscription(id);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
},
|
|
41
|
+
getAll() {
|
|
42
|
+
return store.getSubscriptions();
|
|
43
|
+
},
|
|
44
|
+
getForSession(sessionName) {
|
|
45
|
+
return store.getSubscriptions().filter((s) => !s.sessionName || s.sessionName === sessionName);
|
|
46
|
+
},
|
|
47
|
+
hasSubscription(endpoint) {
|
|
48
|
+
return store.getSubscriptions().some((s) => s.endpoint === endpoint);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=subscription.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription.js","sourceRoot":"","sources":["../../../src/daemon/notification/subscription.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA4B1C;;GAEG;AACH,SAAS,sBAAsB;IAC7B,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAA8B;IACtE,OAAO;QACL,SAAS,CACP,QAAgB,EAChB,IAAsC,EACtC,WAAoB;YAEpB,8BAA8B;YAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;YAC/E,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,QAAQ,CAAC;YAClB,CAAC;YAED,MAAM,YAAY,GAAqB;gBACrC,EAAE,EAAE,sBAAsB,EAAE;gBAC5B,QAAQ;gBACR,IAAI;gBACJ,WAAW;gBACX,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC;YAEF,KAAK,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;YACpC,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,WAAW,CAAC,EAAU;YACpB,MAAM,aAAa,GAAG,KAAK,CAAC,gBAAgB,EAAE,CAAC;YAC/C,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YACtD,IAAI,MAAM,EAAE,CAAC;gBACX,KAAK,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;gBAC7B,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM;YACJ,OAAO,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAClC,CAAC;QAED,aAAa,CAAC,WAAmB;YAC/B,OAAO,KAAK,CAAC,gBAAgB,EAAE,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,KAAK,WAAW,CACvD,CAAC;QACJ,CAAC;QAED,eAAe,CAAC,QAAgB;YAC9B,OAAO,KAAK,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QACvE,CAAC;KACF,CAAC;AACJ,CAAC"}
|