@dollhousemcp/mcp-server 2.0.0-rc.6 → 2.0.1
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/CHANGELOG.md +52 -61
- package/README.github.md +2 -2
- package/README.md +284 -224
- package/README.md.backup +284 -224
- package/README.npm.md +284 -224
- package/dist/cache/LRUCache.d.ts +3 -0
- package/dist/cache/LRUCache.d.ts.map +1 -1
- package/dist/cache/LRUCache.js +36 -26
- package/dist/config/env.d.ts +14 -4
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +20 -6
- package/dist/di/Container.d.ts +21 -0
- package/dist/di/Container.d.ts.map +1 -1
- package/dist/di/Container.js +250 -53
- package/dist/elements/BaseElement.d.ts.map +1 -1
- package/dist/elements/BaseElement.js +5 -10
- package/dist/elements/base/BaseElementManager.d.ts +22 -0
- package/dist/elements/base/BaseElementManager.d.ts.map +1 -1
- package/dist/elements/base/BaseElementManager.js +47 -7
- package/dist/elements/memories/Memory.d.ts +1 -0
- package/dist/elements/memories/Memory.d.ts.map +1 -1
- package/dist/elements/memories/Memory.js +12 -8
- package/dist/elements/memories/MemoryManager.d.ts.map +1 -1
- package/dist/elements/memories/MemoryManager.js +23 -42
- package/dist/elements/memories/MemorySearchIndex.js +2 -2
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.d.ts.map +1 -1
- package/dist/generated/version.js +3 -3
- package/dist/handlers/EnhancedIndexHandler.js +6 -6
- package/dist/handlers/element-crud/listElements.d.ts +2 -0
- package/dist/handlers/element-crud/listElements.d.ts.map +1 -1
- package/dist/handlers/element-crud/listElements.js +3 -1
- package/dist/handlers/mcp-aql/Gatekeeper.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/Gatekeeper.js +23 -17
- package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts +14 -0
- package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/MCPAQLHandler.js +110 -14
- package/dist/handlers/mcp-aql/OperationRouter.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/OperationRouter.js +13 -1
- package/dist/handlers/mcp-aql/OperationSchema.d.ts +7 -0
- package/dist/handlers/mcp-aql/OperationSchema.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/OperationSchema.js +52 -1
- package/dist/handlers/mcp-aql/evaluatePermission.d.ts +53 -0
- package/dist/handlers/mcp-aql/evaluatePermission.d.ts.map +1 -0
- package/dist/handlers/mcp-aql/evaluatePermission.js +132 -0
- package/dist/handlers/mcp-aql/policies/ToolClassification.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/policies/ToolClassification.js +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/logging/LogHooks.js +11 -11
- package/dist/logging/LogManager.d.ts +0 -2
- package/dist/logging/LogManager.d.ts.map +1 -1
- package/dist/logging/LogManager.js +1 -3
- package/dist/logging/sinks/MemoryLogSink.d.ts +2 -0
- package/dist/logging/sinks/MemoryLogSink.d.ts.map +1 -1
- package/dist/logging/sinks/MemoryLogSink.js +12 -3
- package/dist/logging/types.d.ts +0 -2
- package/dist/logging/types.d.ts.map +1 -1
- package/dist/logging/types.js +1 -1
- package/dist/metrics/GatekeeperMetricsTracker.d.ts +32 -0
- package/dist/metrics/GatekeeperMetricsTracker.d.ts.map +1 -0
- package/dist/metrics/GatekeeperMetricsTracker.js +42 -0
- package/dist/metrics/MetricsManager.d.ts +47 -0
- package/dist/metrics/MetricsManager.d.ts.map +1 -0
- package/dist/metrics/MetricsManager.js +232 -0
- package/dist/metrics/OperationMetricsTracker.d.ts +32 -0
- package/dist/metrics/OperationMetricsTracker.d.ts.map +1 -0
- package/dist/metrics/OperationMetricsTracker.js +53 -0
- package/dist/metrics/collectors/DefaultElementProviderCollector.d.ts +27 -0
- package/dist/metrics/collectors/DefaultElementProviderCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/DefaultElementProviderCollector.js +69 -0
- package/dist/metrics/collectors/FileLockManagerCollector.d.ts +16 -0
- package/dist/metrics/collectors/FileLockManagerCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/FileLockManagerCollector.js +51 -0
- package/dist/metrics/collectors/GatekeeperMetricsCollector.d.ts +16 -0
- package/dist/metrics/collectors/GatekeeperMetricsCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/GatekeeperMetricsCollector.js +76 -0
- package/dist/metrics/collectors/LRUCacheCollector.d.ts +18 -0
- package/dist/metrics/collectors/LRUCacheCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/LRUCacheCollector.js +95 -0
- package/dist/metrics/collectors/OperationMetricsCollector.d.ts +16 -0
- package/dist/metrics/collectors/OperationMetricsCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/OperationMetricsCollector.js +80 -0
- package/dist/metrics/collectors/OperationalTelemetryCollector.d.ts +17 -0
- package/dist/metrics/collectors/OperationalTelemetryCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/OperationalTelemetryCollector.js +26 -0
- package/dist/metrics/collectors/PerformanceMonitorCollector.d.ts +14 -0
- package/dist/metrics/collectors/PerformanceMonitorCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/PerformanceMonitorCollector.js +141 -0
- package/dist/metrics/collectors/SecurityMonitorCollector.d.ts +21 -0
- package/dist/metrics/collectors/SecurityMonitorCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/SecurityMonitorCollector.js +56 -0
- package/dist/metrics/collectors/SecurityTelemetryCollector.d.ts +15 -0
- package/dist/metrics/collectors/SecurityTelemetryCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/SecurityTelemetryCollector.js +112 -0
- package/dist/metrics/collectors/TriggerMetricsTrackerCollector.d.ts +16 -0
- package/dist/metrics/collectors/TriggerMetricsTrackerCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/TriggerMetricsTrackerCollector.js +26 -0
- package/dist/metrics/collectors/index.d.ts +11 -0
- package/dist/metrics/collectors/index.d.ts.map +1 -0
- package/dist/metrics/collectors/index.js +11 -0
- package/dist/metrics/sinks/MemoryMetricsSink.d.ts +22 -0
- package/dist/metrics/sinks/MemoryMetricsSink.d.ts.map +1 -0
- package/dist/metrics/sinks/MemoryMetricsSink.js +121 -0
- package/dist/metrics/types.d.ts +98 -0
- package/dist/metrics/types.d.ts.map +1 -0
- package/dist/metrics/types.js +24 -0
- package/dist/portfolio/DefaultElementProvider.d.ts.map +1 -1
- package/dist/portfolio/DefaultElementProvider.js +1 -7
- package/dist/portfolio/EnhancedIndexManager.d.ts.map +1 -1
- package/dist/portfolio/EnhancedIndexManager.js +18 -18
- package/dist/portfolio/NLPScoringManager.d.ts.map +1 -1
- package/dist/portfolio/NLPScoringManager.js +5 -9
- package/dist/portfolio/PortfolioIndexManager.js +2 -2
- package/dist/portfolio/RelationshipManager.js +2 -2
- package/dist/portfolio/VerbTriggerManager.d.ts.map +1 -1
- package/dist/portfolio/VerbTriggerManager.js +5 -19
- package/dist/portfolio/config/IndexConfig.d.ts.map +1 -1
- package/dist/portfolio/config/IndexConfig.js +1 -12
- package/dist/portfolio/enhanced-index/ElementDefinitionBuilder.d.ts.map +1 -1
- package/dist/portfolio/enhanced-index/ElementDefinitionBuilder.js +3 -15
- package/dist/portfolio/enhanced-index/SemanticRelationshipService.d.ts.map +1 -1
- package/dist/portfolio/enhanced-index/SemanticRelationshipService.js +2 -16
- package/dist/portfolio/types/RelationshipTypes.d.ts.map +1 -1
- package/dist/portfolio/types/RelationshipTypes.js +3 -17
- package/dist/security/audit/config/suppressions.d.ts.map +1 -1
- package/dist/security/audit/config/suppressions.js +36 -8
- package/dist/security/constants.d.ts.map +1 -1
- package/dist/security/constants.js +10 -6
- package/dist/security/fileLockManager.d.ts.map +1 -1
- package/dist/security/fileLockManager.js +8 -6
- package/dist/security/secureYamlParser.d.ts.map +1 -1
- package/dist/security/secureYamlParser.js +1 -13
- package/dist/security/securityMonitor.d.ts +2 -1
- package/dist/security/securityMonitor.d.ts.map +1 -1
- package/dist/security/securityMonitor.js +14 -3
- package/dist/security/telemetry/SecurityTelemetry.d.ts +16 -0
- package/dist/security/telemetry/SecurityTelemetry.d.ts.map +1 -1
- package/dist/security/telemetry/SecurityTelemetry.js +30 -2
- package/dist/security/tokenManager.d.ts +3 -0
- package/dist/security/tokenManager.d.ts.map +1 -1
- package/dist/security/tokenManager.js +13 -5
- package/dist/security/validation/BackgroundValidator.d.ts.map +1 -1
- package/dist/security/validation/BackgroundValidator.js +7 -7
- package/dist/server/startup.d.ts.map +1 -1
- package/dist/server/startup.js +8 -24
- package/dist/server/tools/MCPAQLTools.js +4 -1
- package/dist/services/ActivationStore.d.ts.map +1 -1
- package/dist/services/ActivationStore.js +9 -3
- package/dist/services/FileWatchService.d.ts +1 -0
- package/dist/services/FileWatchService.d.ts.map +1 -1
- package/dist/services/FileWatchService.js +83 -48
- package/dist/services/MetadataService.d.ts.map +1 -1
- package/dist/services/MetadataService.js +7 -2
- package/dist/services/query/ElementQueryService.d.ts.map +1 -1
- package/dist/services/query/ElementQueryService.js +1 -41
- package/dist/services/query/PaginationService.d.ts.map +1 -1
- package/dist/services/query/PaginationService.js +1 -14
- package/dist/services/query/SortService.d.ts.map +1 -1
- package/dist/services/query/SortService.js +1 -6
- package/dist/services/validation/ValidationService.d.ts.map +1 -1
- package/dist/services/validation/ValidationService.js +3 -8
- package/dist/storage/ElementStorageLayer.d.ts.map +1 -1
- package/dist/storage/ElementStorageLayer.js +5 -2
- package/dist/storage/MemoryStorageLayer.d.ts.map +1 -1
- package/dist/storage/MemoryStorageLayer.js +5 -2
- package/dist/telemetry/OperationalTelemetry.js +2 -2
- package/dist/utils/EventDeduplicator.d.ts +44 -0
- package/dist/utils/EventDeduplicator.d.ts.map +1 -0
- package/dist/utils/EventDeduplicator.js +93 -0
- package/dist/utils/FileLock.d.ts.map +1 -1
- package/dist/utils/FileLock.js +1 -9
- package/dist/utils/PerformanceMonitor.d.ts.map +1 -1
- package/dist/utils/PerformanceMonitor.js +5 -5
- package/dist/utils/SlidingWindowRateLimiter.d.ts +13 -0
- package/dist/utils/SlidingWindowRateLimiter.d.ts.map +1 -0
- package/dist/utils/SlidingWindowRateLimiter.js +23 -0
- package/dist/web/console/IngestRoutes.d.ts +84 -0
- package/dist/web/console/IngestRoutes.d.ts.map +1 -0
- package/dist/web/console/IngestRoutes.js +252 -0
- package/dist/web/console/LeaderElection.d.ts +89 -0
- package/dist/web/console/LeaderElection.d.ts.map +1 -0
- package/dist/web/console/LeaderElection.js +205 -0
- package/dist/web/console/LeaderForwardingSink.d.ts +61 -0
- package/dist/web/console/LeaderForwardingSink.d.ts.map +1 -0
- package/dist/web/console/LeaderForwardingSink.js +197 -0
- package/dist/web/console/SessionNames.d.ts +46 -0
- package/dist/web/console/SessionNames.d.ts.map +1 -0
- package/dist/web/console/SessionNames.js +257 -0
- package/dist/web/console/UnifiedConsole.d.ts +64 -0
- package/dist/web/console/UnifiedConsole.d.ts.map +1 -0
- package/dist/web/console/UnifiedConsole.js +119 -0
- package/dist/web/contentPipeline.d.ts +58 -0
- package/dist/web/contentPipeline.d.ts.map +1 -0
- package/dist/web/contentPipeline.js +112 -0
- package/dist/web/portDiscovery.d.ts +58 -0
- package/dist/web/portDiscovery.d.ts.map +1 -0
- package/dist/web/portDiscovery.js +143 -0
- package/dist/web/public/app.js +148 -60
- package/dist/web/public/logs.js +638 -0
- package/dist/web/public/metrics.js +682 -0
- package/dist/web/public/permissions.js +394 -0
- package/dist/web/public/sessions.js +369 -0
- package/dist/web/routes/healthRoutes.d.ts +16 -0
- package/dist/web/routes/healthRoutes.d.ts.map +1 -0
- package/dist/web/routes/healthRoutes.js +29 -0
- package/dist/web/routes/logRoutes.d.ts +18 -0
- package/dist/web/routes/logRoutes.d.ts.map +1 -0
- package/dist/web/routes/logRoutes.js +126 -0
- package/dist/web/routes/metricsRoutes.d.ts +17 -0
- package/dist/web/routes/metricsRoutes.d.ts.map +1 -0
- package/dist/web/routes/metricsRoutes.js +90 -0
- package/dist/web/routes/permissionRoutes.d.ts +16 -0
- package/dist/web/routes/permissionRoutes.d.ts.map +1 -0
- package/dist/web/routes/permissionRoutes.js +133 -0
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +309 -339
- package/dist/web/server.d.ts +21 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +42 -4
- package/dist/web/sinks/WebSSELogSink.d.ts +15 -0
- package/dist/web/sinks/WebSSELogSink.d.ts.map +1 -0
- package/dist/web/sinks/WebSSELogSink.js +22 -0
- package/dist/web/sinks/WebSSEMetricsSink.d.ts +16 -0
- package/dist/web/sinks/WebSSEMetricsSink.d.ts.map +1 -0
- package/dist/web/sinks/WebSSEMetricsSink.js +23 -0
- package/package.json +2 -2
- package/server.json +2 -2
- package/dist/web/public/public/app.js +0 -1878
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forwarding sinks for follower MCP servers.
|
|
3
|
+
*
|
|
4
|
+
* When a server becomes a follower in the unified console election, it
|
|
5
|
+
* registers these sinks with its LogManager and MetricsManager. Instead
|
|
6
|
+
* of broadcasting to local SSE clients, entries are batch-POSTed to
|
|
7
|
+
* the leader's ingestion endpoints.
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Batch buffering (50 entries or 1s flush, whichever comes first)
|
|
11
|
+
* - In-memory buffer up to 10,000 entries on leader failure
|
|
12
|
+
* - Exponential backoff on POST failure (1s → 2s → 4s, max 30s)
|
|
13
|
+
* - Automatic drain on leader recovery
|
|
14
|
+
*
|
|
15
|
+
* @since v2.1.0 — Issue #1700
|
|
16
|
+
*/
|
|
17
|
+
import type { ILogSink, UnifiedLogEntry } from '../../logging/types.js';
|
|
18
|
+
import type { MetricSnapshot } from '../../metrics/types.js';
|
|
19
|
+
/**
|
|
20
|
+
* ILogSink that batch-POSTs entries to the leader's /api/ingest/logs.
|
|
21
|
+
*/
|
|
22
|
+
export declare class LeaderForwardingLogSink implements ILogSink {
|
|
23
|
+
private readonly leaderUrl;
|
|
24
|
+
private readonly sessionId;
|
|
25
|
+
private readonly buffer;
|
|
26
|
+
private flushTimer;
|
|
27
|
+
private backoffMs;
|
|
28
|
+
private flushing;
|
|
29
|
+
constructor(leaderUrl: string, sessionId: string);
|
|
30
|
+
write(entry: UnifiedLogEntry): void;
|
|
31
|
+
flush(): Promise<void>;
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
private flushBuffer;
|
|
34
|
+
private requeueBatch;
|
|
35
|
+
private scheduleRetry;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Forwards metric snapshots to the leader's /api/ingest/metrics.
|
|
39
|
+
*/
|
|
40
|
+
export declare class LeaderForwardingMetricsSink {
|
|
41
|
+
private readonly leaderUrl;
|
|
42
|
+
private readonly sessionId;
|
|
43
|
+
constructor(leaderUrl: string, sessionId: string);
|
|
44
|
+
onSnapshot(snapshot: MetricSnapshot): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sends session lifecycle events to the leader.
|
|
48
|
+
*/
|
|
49
|
+
export declare class SessionHeartbeat {
|
|
50
|
+
private readonly leaderUrl;
|
|
51
|
+
private readonly sessionId;
|
|
52
|
+
private readonly pid;
|
|
53
|
+
private heartbeatTimer;
|
|
54
|
+
constructor(leaderUrl: string, sessionId: string, pid: number);
|
|
55
|
+
/** Notify the leader that this session has started */
|
|
56
|
+
start(): Promise<void>;
|
|
57
|
+
/** Notify the leader that this session is stopping */
|
|
58
|
+
stop(): Promise<void>;
|
|
59
|
+
private sendEvent;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=LeaderForwardingSink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LeaderForwardingSink.d.ts","sourceRoot":"","sources":["../../../src/web/console/LeaderForwardingSink.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAsB7D;;GAEG;AACH,qBAAa,uBAAwB,YAAW,QAAQ;IAOpD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAP5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,QAAQ,CAAS;gBAGN,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM;IAOpC,KAAK,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAkB7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAQd,WAAW;IA+BzB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,aAAa;CAItB;AAED;;GAEG;AACH,qBAAa,2BAA2B;IAEpC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM;IAG9B,UAAU,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAgB1D;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG;IALtB,OAAO,CAAC,cAAc,CAA+C;gBAGlD,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM;IAG9B,sDAAsD;IAChD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,sDAAsD;IAChD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAQb,SAAS;CAqBxB"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forwarding sinks for follower MCP servers.
|
|
3
|
+
*
|
|
4
|
+
* When a server becomes a follower in the unified console election, it
|
|
5
|
+
* registers these sinks with its LogManager and MetricsManager. Instead
|
|
6
|
+
* of broadcasting to local SSE clients, entries are batch-POSTed to
|
|
7
|
+
* the leader's ingestion endpoints.
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Batch buffering (50 entries or 1s flush, whichever comes first)
|
|
11
|
+
* - In-memory buffer up to 10,000 entries on leader failure
|
|
12
|
+
* - Exponential backoff on POST failure (1s → 2s → 4s, max 30s)
|
|
13
|
+
* - Automatic drain on leader recovery
|
|
14
|
+
*
|
|
15
|
+
* @since v2.1.0 — Issue #1700
|
|
16
|
+
*/
|
|
17
|
+
import { UnicodeValidator } from '../../security/validators/unicodeValidator.js';
|
|
18
|
+
import { logger } from '../../utils/logger.js';
|
|
19
|
+
/** Maximum entries to buffer when leader is unreachable */
|
|
20
|
+
const MAX_BUFFER_SIZE = 10_000;
|
|
21
|
+
/** Batch size before flushing */
|
|
22
|
+
const BATCH_SIZE = 50;
|
|
23
|
+
/** Time-based flush interval (ms) */
|
|
24
|
+
const FLUSH_INTERVAL_MS = 1_000;
|
|
25
|
+
/** Initial backoff delay on failure (ms) */
|
|
26
|
+
const INITIAL_BACKOFF_MS = 1_000;
|
|
27
|
+
/** Maximum backoff delay (ms) */
|
|
28
|
+
const MAX_BACKOFF_MS = 30_000;
|
|
29
|
+
/** HTTP request timeout (ms) */
|
|
30
|
+
const REQUEST_TIMEOUT_MS = 5_000;
|
|
31
|
+
/**
|
|
32
|
+
* ILogSink that batch-POSTs entries to the leader's /api/ingest/logs.
|
|
33
|
+
*/
|
|
34
|
+
export class LeaderForwardingLogSink {
|
|
35
|
+
leaderUrl;
|
|
36
|
+
sessionId;
|
|
37
|
+
buffer = [];
|
|
38
|
+
flushTimer = null;
|
|
39
|
+
backoffMs = INITIAL_BACKOFF_MS;
|
|
40
|
+
flushing = false;
|
|
41
|
+
constructor(leaderUrl, sessionId) {
|
|
42
|
+
this.leaderUrl = leaderUrl;
|
|
43
|
+
this.sessionId = sessionId;
|
|
44
|
+
this.sessionId = UnicodeValidator.normalize(sessionId).normalizedContent;
|
|
45
|
+
this.flushTimer = setInterval(() => this.flushBuffer(), FLUSH_INTERVAL_MS);
|
|
46
|
+
this.flushTimer.unref();
|
|
47
|
+
}
|
|
48
|
+
write(entry) {
|
|
49
|
+
// Stamp session ID before buffering
|
|
50
|
+
const stamped = {
|
|
51
|
+
...entry,
|
|
52
|
+
data: { ...entry.data, _sessionId: this.sessionId },
|
|
53
|
+
};
|
|
54
|
+
if (this.buffer.length >= MAX_BUFFER_SIZE) {
|
|
55
|
+
// Evict oldest entry (FIFO)
|
|
56
|
+
this.buffer.shift();
|
|
57
|
+
}
|
|
58
|
+
this.buffer.push(stamped);
|
|
59
|
+
if (this.buffer.length >= BATCH_SIZE) {
|
|
60
|
+
this.flushBuffer();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async flush() {
|
|
64
|
+
await this.flushBuffer();
|
|
65
|
+
}
|
|
66
|
+
async close() {
|
|
67
|
+
if (this.flushTimer) {
|
|
68
|
+
clearInterval(this.flushTimer);
|
|
69
|
+
this.flushTimer = null;
|
|
70
|
+
}
|
|
71
|
+
await this.flushBuffer();
|
|
72
|
+
}
|
|
73
|
+
async flushBuffer() {
|
|
74
|
+
if (this.flushing || this.buffer.length === 0)
|
|
75
|
+
return;
|
|
76
|
+
this.flushing = true;
|
|
77
|
+
const batch = this.buffer.splice(0, BATCH_SIZE);
|
|
78
|
+
try {
|
|
79
|
+
const controller = new AbortController();
|
|
80
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
81
|
+
const response = await fetch(`${this.leaderUrl}/api/ingest/logs`, {
|
|
82
|
+
method: 'POST',
|
|
83
|
+
headers: { 'Content-Type': 'application/json' },
|
|
84
|
+
body: JSON.stringify({ sessionId: this.sessionId, entries: batch }),
|
|
85
|
+
signal: controller.signal,
|
|
86
|
+
});
|
|
87
|
+
clearTimeout(timeout);
|
|
88
|
+
if (response.ok) {
|
|
89
|
+
this.backoffMs = INITIAL_BACKOFF_MS;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
this.requeueBatch(batch);
|
|
93
|
+
this.scheduleRetry();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
this.requeueBatch(batch);
|
|
98
|
+
this.scheduleRetry();
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
this.flushing = false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
requeueBatch(batch) {
|
|
105
|
+
const spaceAvailable = MAX_BUFFER_SIZE - this.buffer.length;
|
|
106
|
+
if (spaceAvailable > 0) {
|
|
107
|
+
const toRequeue = batch.slice(0, spaceAvailable);
|
|
108
|
+
this.buffer.unshift(...toRequeue);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
logger.warn(`[ForwardingSink] Buffer full (${MAX_BUFFER_SIZE}), dropping ${batch.length} entries`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
scheduleRetry() {
|
|
115
|
+
logger.debug(`[ForwardingSink] Leader unreachable, backoff ${this.backoffMs}ms (buffered: ${this.buffer.length})`);
|
|
116
|
+
this.backoffMs = Math.min(this.backoffMs * 2, MAX_BACKOFF_MS);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Forwards metric snapshots to the leader's /api/ingest/metrics.
|
|
121
|
+
*/
|
|
122
|
+
export class LeaderForwardingMetricsSink {
|
|
123
|
+
leaderUrl;
|
|
124
|
+
sessionId;
|
|
125
|
+
constructor(leaderUrl, sessionId) {
|
|
126
|
+
this.leaderUrl = leaderUrl;
|
|
127
|
+
this.sessionId = sessionId;
|
|
128
|
+
}
|
|
129
|
+
async onSnapshot(snapshot) {
|
|
130
|
+
try {
|
|
131
|
+
const controller = new AbortController();
|
|
132
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
133
|
+
await fetch(`${this.leaderUrl}/api/ingest/metrics`, {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
headers: { 'Content-Type': 'application/json' },
|
|
136
|
+
body: JSON.stringify({ sessionId: this.sessionId, snapshot }),
|
|
137
|
+
signal: controller.signal,
|
|
138
|
+
});
|
|
139
|
+
clearTimeout(timeout);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
logger.debug('[ForwardingSink] Failed to forward metrics snapshot');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Sends session lifecycle events to the leader.
|
|
148
|
+
*/
|
|
149
|
+
export class SessionHeartbeat {
|
|
150
|
+
leaderUrl;
|
|
151
|
+
sessionId;
|
|
152
|
+
pid;
|
|
153
|
+
heartbeatTimer = null;
|
|
154
|
+
constructor(leaderUrl, sessionId, pid) {
|
|
155
|
+
this.leaderUrl = leaderUrl;
|
|
156
|
+
this.sessionId = sessionId;
|
|
157
|
+
this.pid = pid;
|
|
158
|
+
}
|
|
159
|
+
/** Notify the leader that this session has started */
|
|
160
|
+
async start() {
|
|
161
|
+
await this.sendEvent('started');
|
|
162
|
+
this.heartbeatTimer = setInterval(() => {
|
|
163
|
+
this.sendEvent('heartbeat').catch(() => { });
|
|
164
|
+
}, 10_000);
|
|
165
|
+
this.heartbeatTimer.unref();
|
|
166
|
+
}
|
|
167
|
+
/** Notify the leader that this session is stopping */
|
|
168
|
+
async stop() {
|
|
169
|
+
if (this.heartbeatTimer) {
|
|
170
|
+
clearInterval(this.heartbeatTimer);
|
|
171
|
+
this.heartbeatTimer = null;
|
|
172
|
+
}
|
|
173
|
+
await this.sendEvent('stopped');
|
|
174
|
+
}
|
|
175
|
+
async sendEvent(event) {
|
|
176
|
+
try {
|
|
177
|
+
const controller = new AbortController();
|
|
178
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
179
|
+
await fetch(`${this.leaderUrl}/api/ingest/session`, {
|
|
180
|
+
method: 'POST',
|
|
181
|
+
headers: { 'Content-Type': 'application/json' },
|
|
182
|
+
body: JSON.stringify({
|
|
183
|
+
sessionId: this.sessionId,
|
|
184
|
+
event,
|
|
185
|
+
pid: this.pid,
|
|
186
|
+
startedAt: new Date().toISOString(),
|
|
187
|
+
}),
|
|
188
|
+
signal: controller.signal,
|
|
189
|
+
});
|
|
190
|
+
clearTimeout(timeout);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
logger.debug(`[SessionHeartbeat] Failed to send ${event} event`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTGVhZGVyRm9yd2FyZGluZ1NpbmsuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvd2ViL2NvbnNvbGUvTGVhZGVyRm9yd2FyZGluZ1NpbmsudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBSUgsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sK0NBQStDLENBQUM7QUFDakYsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRS9DLDJEQUEyRDtBQUMzRCxNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUM7QUFFL0IsaUNBQWlDO0FBQ2pDLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQztBQUV0QixxQ0FBcUM7QUFDckMsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUM7QUFFaEMsNENBQTRDO0FBQzVDLE1BQU0sa0JBQWtCLEdBQUcsS0FBSyxDQUFDO0FBRWpDLGlDQUFpQztBQUNqQyxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUM7QUFFOUIsZ0NBQWdDO0FBQ2hDLE1BQU0sa0JBQWtCLEdBQUcsS0FBSyxDQUFDO0FBRWpDOztHQUVHO0FBQ0gsTUFBTSxPQUFPLHVCQUF1QjtJQU9mO0lBQ0E7SUFQRixNQUFNLEdBQXNCLEVBQUUsQ0FBQztJQUN4QyxVQUFVLEdBQTBDLElBQUksQ0FBQztJQUN6RCxTQUFTLEdBQUcsa0JBQWtCLENBQUM7SUFDL0IsUUFBUSxHQUFHLEtBQUssQ0FBQztJQUV6QixZQUNtQixTQUFpQixFQUNqQixTQUFpQjtRQURqQixjQUFTLEdBQVQsU0FBUyxDQUFRO1FBQ2pCLGNBQVMsR0FBVCxTQUFTLENBQVE7UUFFbEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsaUJBQWlCLENBQUM7UUFDekUsSUFBSSxDQUFDLFVBQVUsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLGlCQUFpQixDQUFDLENBQUM7UUFDM0UsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRUQsS0FBSyxDQUFDLEtBQXNCO1FBQzFCLG9DQUFvQztRQUNwQyxNQUFNLE9BQU8sR0FBb0I7WUFDL0IsR0FBRyxLQUFLO1lBQ1IsSUFBSSxFQUFFLEVBQUUsR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFO1NBQ3BELENBQUM7UUFFRixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQzFDLDRCQUE0QjtZQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3RCLENBQUM7UUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUUxQixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ3JDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNyQixDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxLQUFLO1FBQ1QsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVELEtBQUssQ0FBQyxLQUFLO1FBQ1QsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDcEIsYUFBYSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN6QixDQUFDO1FBQ0QsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVPLEtBQUssQ0FBQyxXQUFXO1FBQ3ZCLElBQUksSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQUUsT0FBTztRQUN0RCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUVyQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxVQUFVLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztZQUN6QyxNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxFQUFFLGtCQUFrQixDQUFDLENBQUM7WUFFekUsTUFBTSxRQUFRLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxrQkFBa0IsRUFBRTtnQkFDaEUsTUFBTSxFQUFFLE1BQU07Z0JBQ2QsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFFO2dCQUMvQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQztnQkFDbkUsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNO2FBQzFCLENBQUMsQ0FBQztZQUNILFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUV0QixJQUFJLFFBQVEsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDaEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxrQkFBa0IsQ0FBQztZQUN0QyxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDekIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3ZCLENBQUM7UUFDSCxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN6QixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDdkIsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFDeEIsQ0FBQztJQUNILENBQUM7SUFFTyxZQUFZLENBQUMsS0FBd0I7UUFDM0MsTUFBTSxjQUFjLEdBQUcsZUFBZSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO1FBQzVELElBQUksY0FBYyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3ZCLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1lBQ2pELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUM7UUFDcEMsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLENBQUMsSUFBSSxDQUFDLGlDQUFpQyxlQUFlLGVBQWUsS0FBSyxDQUFDLE1BQU0sVUFBVSxDQUFDLENBQUM7UUFDckcsQ0FBQztJQUNILENBQUM7SUFFTyxhQUFhO1FBQ25CLE1BQU0sQ0FBQyxLQUFLLENBQUMsZ0RBQWdELElBQUksQ0FBQyxTQUFTLGlCQUFpQixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDbkgsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLDJCQUEyQjtJQUVuQjtJQUNBO0lBRm5CLFlBQ21CLFNBQWlCLEVBQ2pCLFNBQWlCO1FBRGpCLGNBQVMsR0FBVCxTQUFTLENBQVE7UUFDakIsY0FBUyxHQUFULFNBQVMsQ0FBUTtJQUNqQyxDQUFDO0lBRUosS0FBSyxDQUFDLFVBQVUsQ0FBQyxRQUF3QjtRQUN2QyxJQUFJLENBQUM7WUFDSCxNQUFNLFVBQVUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ3pDLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztZQUV6RSxNQUFNLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLHFCQUFxQixFQUFFO2dCQUNsRCxNQUFNLEVBQUUsTUFBTTtnQkFDZCxPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUU7Z0JBQy9DLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxFQUFFLENBQUM7Z0JBQzdELE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTTthQUMxQixDQUFDLENBQUM7WUFDSCxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDeEIsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE1BQU0sQ0FBQyxLQUFLLENBQUMscURBQXFELENBQUMsQ0FBQztRQUN0RSxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBSVI7SUFDQTtJQUNBO0lBTFgsY0FBYyxHQUEwQyxJQUFJLENBQUM7SUFFckUsWUFDbUIsU0FBaUIsRUFDakIsU0FBaUIsRUFDakIsR0FBVztRQUZYLGNBQVMsR0FBVCxTQUFTLENBQVE7UUFDakIsY0FBUyxHQUFULFNBQVMsQ0FBUTtRQUNqQixRQUFHLEdBQUgsR0FBRyxDQUFRO0lBQzNCLENBQUM7SUFFSixzREFBc0Q7SUFDdEQsS0FBSyxDQUFDLEtBQUs7UUFDVCxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFaEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFO1lBQ3JDLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzlDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNYLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVELHNEQUFzRDtJQUN0RCxLQUFLLENBQUMsSUFBSTtRQUNSLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3hCLGFBQWEsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDbkMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7UUFDN0IsQ0FBQztRQUNELE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRU8sS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUEwQztRQUNoRSxJQUFJLENBQUM7WUFDSCxNQUFNLFVBQVUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ3pDLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztZQUV6RSxNQUFNLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLHFCQUFxQixFQUFFO2dCQUNsRCxNQUFNLEVBQUUsTUFBTTtnQkFDZCxPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUU7Z0JBQy9DLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDO29CQUNuQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7b0JBQ3pCLEtBQUs7b0JBQ0wsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO29CQUNiLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTtpQkFDcEMsQ0FBQztnQkFDRixNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU07YUFDMUIsQ0FBQyxDQUFDO1lBQ0gsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3hCLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxNQUFNLENBQUMsS0FBSyxDQUFDLHFDQUFxQyxLQUFLLFFBQVEsQ0FBQyxDQUFDO1FBQ25FLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEZvcndhcmRpbmcgc2lua3MgZm9yIGZvbGxvd2VyIE1DUCBzZXJ2ZXJzLlxuICpcbiAqIFdoZW4gYSBzZXJ2ZXIgYmVjb21lcyBhIGZvbGxvd2VyIGluIHRoZSB1bmlmaWVkIGNvbnNvbGUgZWxlY3Rpb24sIGl0XG4gKiByZWdpc3RlcnMgdGhlc2Ugc2lua3Mgd2l0aCBpdHMgTG9nTWFuYWdlciBhbmQgTWV0cmljc01hbmFnZXIuIEluc3RlYWRcbiAqIG9mIGJyb2FkY2FzdGluZyB0byBsb2NhbCBTU0UgY2xpZW50cywgZW50cmllcyBhcmUgYmF0Y2gtUE9TVGVkIHRvXG4gKiB0aGUgbGVhZGVyJ3MgaW5nZXN0aW9uIGVuZHBvaW50cy5cbiAqXG4gKiBGZWF0dXJlczpcbiAqIC0gQmF0Y2ggYnVmZmVyaW5nICg1MCBlbnRyaWVzIG9yIDFzIGZsdXNoLCB3aGljaGV2ZXIgY29tZXMgZmlyc3QpXG4gKiAtIEluLW1lbW9yeSBidWZmZXIgdXAgdG8gMTAsMDAwIGVudHJpZXMgb24gbGVhZGVyIGZhaWx1cmVcbiAqIC0gRXhwb25lbnRpYWwgYmFja29mZiBvbiBQT1NUIGZhaWx1cmUgKDFzIOKGkiAycyDihpIgNHMsIG1heCAzMHMpXG4gKiAtIEF1dG9tYXRpYyBkcmFpbiBvbiBsZWFkZXIgcmVjb3ZlcnlcbiAqXG4gKiBAc2luY2UgdjIuMS4wIOKAlCBJc3N1ZSAjMTcwMFxuICovXG5cbmltcG9ydCB0eXBlIHsgSUxvZ1NpbmssIFVuaWZpZWRMb2dFbnRyeSB9IGZyb20gJy4uLy4uL2xvZ2dpbmcvdHlwZXMuanMnO1xuaW1wb3J0IHR5cGUgeyBNZXRyaWNTbmFwc2hvdCB9IGZyb20gJy4uLy4uL21ldHJpY3MvdHlwZXMuanMnO1xuaW1wb3J0IHsgVW5pY29kZVZhbGlkYXRvciB9IGZyb20gJy4uLy4uL3NlY3VyaXR5L3ZhbGlkYXRvcnMvdW5pY29kZVZhbGlkYXRvci5qcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi8uLi91dGlscy9sb2dnZXIuanMnO1xuXG4vKiogTWF4aW11bSBlbnRyaWVzIHRvIGJ1ZmZlciB3aGVuIGxlYWRlciBpcyB1bnJlYWNoYWJsZSAqL1xuY29uc3QgTUFYX0JVRkZFUl9TSVpFID0gMTBfMDAwO1xuXG4vKiogQmF0Y2ggc2l6ZSBiZWZvcmUgZmx1c2hpbmcgKi9cbmNvbnN0IEJBVENIX1NJWkUgPSA1MDtcblxuLyoqIFRpbWUtYmFzZWQgZmx1c2ggaW50ZXJ2YWwgKG1zKSAqL1xuY29uc3QgRkxVU0hfSU5URVJWQUxfTVMgPSAxXzAwMDtcblxuLyoqIEluaXRpYWwgYmFja29mZiBkZWxheSBvbiBmYWlsdXJlIChtcykgKi9cbmNvbnN0IElOSVRJQUxfQkFDS09GRl9NUyA9IDFfMDAwO1xuXG4vKiogTWF4aW11bSBiYWNrb2ZmIGRlbGF5IChtcykgKi9cbmNvbnN0IE1BWF9CQUNLT0ZGX01TID0gMzBfMDAwO1xuXG4vKiogSFRUUCByZXF1ZXN0IHRpbWVvdXQgKG1zKSAqL1xuY29uc3QgUkVRVUVTVF9USU1FT1VUX01TID0gNV8wMDA7XG5cbi8qKlxuICogSUxvZ1NpbmsgdGhhdCBiYXRjaC1QT1NUcyBlbnRyaWVzIHRvIHRoZSBsZWFkZXIncyAvYXBpL2luZ2VzdC9sb2dzLlxuICovXG5leHBvcnQgY2xhc3MgTGVhZGVyRm9yd2FyZGluZ0xvZ1NpbmsgaW1wbGVtZW50cyBJTG9nU2luayB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYnVmZmVyOiBVbmlmaWVkTG9nRW50cnlbXSA9IFtdO1xuICBwcml2YXRlIGZsdXNoVGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldEludGVydmFsPiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGJhY2tvZmZNcyA9IElOSVRJQUxfQkFDS09GRl9NUztcbiAgcHJpdmF0ZSBmbHVzaGluZyA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbGVhZGVyVXJsOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZXNzaW9uSWQ6IHN0cmluZyxcbiAgKSB7XG4gICAgdGhpcy5zZXNzaW9uSWQgPSBVbmljb2RlVmFsaWRhdG9yLm5vcm1hbGl6ZShzZXNzaW9uSWQpLm5vcm1hbGl6ZWRDb250ZW50O1xuICAgIHRoaXMuZmx1c2hUaW1lciA9IHNldEludGVydmFsKCgpID0+IHRoaXMuZmx1c2hCdWZmZXIoKSwgRkxVU0hfSU5URVJWQUxfTVMpO1xuICAgIHRoaXMuZmx1c2hUaW1lci51bnJlZigpO1xuICB9XG5cbiAgd3JpdGUoZW50cnk6IFVuaWZpZWRMb2dFbnRyeSk6IHZvaWQge1xuICAgIC8vIFN0YW1wIHNlc3Npb24gSUQgYmVmb3JlIGJ1ZmZlcmluZ1xuICAgIGNvbnN0IHN0YW1wZWQ6IFVuaWZpZWRMb2dFbnRyeSA9IHtcbiAgICAgIC4uLmVudHJ5LFxuICAgICAgZGF0YTogeyAuLi5lbnRyeS5kYXRhLCBfc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCB9LFxuICAgIH07XG5cbiAgICBpZiAodGhpcy5idWZmZXIubGVuZ3RoID49IE1BWF9CVUZGRVJfU0laRSkge1xuICAgICAgLy8gRXZpY3Qgb2xkZXN0IGVudHJ5IChGSUZPKVxuICAgICAgdGhpcy5idWZmZXIuc2hpZnQoKTtcbiAgICB9XG4gICAgdGhpcy5idWZmZXIucHVzaChzdGFtcGVkKTtcblxuICAgIGlmICh0aGlzLmJ1ZmZlci5sZW5ndGggPj0gQkFUQ0hfU0laRSkge1xuICAgICAgdGhpcy5mbHVzaEJ1ZmZlcigpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGZsdXNoKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuZmx1c2hCdWZmZXIoKTtcbiAgfVxuXG4gIGFzeW5jIGNsb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmZsdXNoVGltZXIpIHtcbiAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5mbHVzaFRpbWVyKTtcbiAgICAgIHRoaXMuZmx1c2hUaW1lciA9IG51bGw7XG4gICAgfVxuICAgIGF3YWl0IHRoaXMuZmx1c2hCdWZmZXIoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmx1c2hCdWZmZXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuZmx1c2hpbmcgfHwgdGhpcy5idWZmZXIubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgdGhpcy5mbHVzaGluZyA9IHRydWU7XG5cbiAgICBjb25zdCBiYXRjaCA9IHRoaXMuYnVmZmVyLnNwbGljZSgwLCBCQVRDSF9TSVpFKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICAgIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKSwgUkVRVUVTVF9USU1FT1VUX01TKTtcblxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHt0aGlzLmxlYWRlclVybH0vYXBpL2luZ2VzdC9sb2dzYCwge1xuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sXG4gICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHsgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCwgZW50cmllczogYmF0Y2ggfSksXG4gICAgICAgIHNpZ25hbDogY29udHJvbGxlci5zaWduYWwsXG4gICAgICB9KTtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcblxuICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICAgIHRoaXMuYmFja29mZk1zID0gSU5JVElBTF9CQUNLT0ZGX01TO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZXF1ZXVlQmF0Y2goYmF0Y2gpO1xuICAgICAgICB0aGlzLnNjaGVkdWxlUmV0cnkoKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIHRoaXMucmVxdWV1ZUJhdGNoKGJhdGNoKTtcbiAgICAgIHRoaXMuc2NoZWR1bGVSZXRyeSgpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmZsdXNoaW5nID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZXF1ZXVlQmF0Y2goYmF0Y2g6IFVuaWZpZWRMb2dFbnRyeVtdKTogdm9pZCB7XG4gICAgY29uc3Qgc3BhY2VBdmFpbGFibGUgPSBNQVhfQlVGRkVSX1NJWkUgLSB0aGlzLmJ1ZmZlci5sZW5ndGg7XG4gICAgaWYgKHNwYWNlQXZhaWxhYmxlID4gMCkge1xuICAgICAgY29uc3QgdG9SZXF1ZXVlID0gYmF0Y2guc2xpY2UoMCwgc3BhY2VBdmFpbGFibGUpO1xuICAgICAgdGhpcy5idWZmZXIudW5zaGlmdCguLi50b1JlcXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2dnZXIud2FybihgW0ZvcndhcmRpbmdTaW5rXSBCdWZmZXIgZnVsbCAoJHtNQVhfQlVGRkVSX1NJWkV9KSwgZHJvcHBpbmcgJHtiYXRjaC5sZW5ndGh9IGVudHJpZXNgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNjaGVkdWxlUmV0cnkoKTogdm9pZCB7XG4gICAgbG9nZ2VyLmRlYnVnKGBbRm9yd2FyZGluZ1NpbmtdIExlYWRlciB1bnJlYWNoYWJsZSwgYmFja29mZiAke3RoaXMuYmFja29mZk1zfW1zIChidWZmZXJlZDogJHt0aGlzLmJ1ZmZlci5sZW5ndGh9KWApO1xuICAgIHRoaXMuYmFja29mZk1zID0gTWF0aC5taW4odGhpcy5iYWNrb2ZmTXMgKiAyLCBNQVhfQkFDS09GRl9NUyk7XG4gIH1cbn1cblxuLyoqXG4gKiBGb3J3YXJkcyBtZXRyaWMgc25hcHNob3RzIHRvIHRoZSBsZWFkZXIncyAvYXBpL2luZ2VzdC9tZXRyaWNzLlxuICovXG5leHBvcnQgY2xhc3MgTGVhZGVyRm9yd2FyZGluZ01ldHJpY3NTaW5rIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBsZWFkZXJVcmw6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNlc3Npb25JZDogc3RyaW5nLFxuICApIHt9XG5cbiAgYXN5bmMgb25TbmFwc2hvdChzbmFwc2hvdDogTWV0cmljU25hcHNob3QpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICAgIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKSwgUkVRVUVTVF9USU1FT1VUX01TKTtcblxuICAgICAgYXdhaXQgZmV0Y2goYCR7dGhpcy5sZWFkZXJVcmx9L2FwaS9pbmdlc3QvbWV0cmljc2AsIHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7IHNlc3Npb25JZDogdGhpcy5zZXNzaW9uSWQsIHNuYXBzaG90IH0pLFxuICAgICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgfSk7XG4gICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBsb2dnZXIuZGVidWcoJ1tGb3J3YXJkaW5nU2lua10gRmFpbGVkIHRvIGZvcndhcmQgbWV0cmljcyBzbmFwc2hvdCcpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFNlbmRzIHNlc3Npb24gbGlmZWN5Y2xlIGV2ZW50cyB0byB0aGUgbGVhZGVyLlxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbkhlYXJ0YmVhdCB7XG4gIHByaXZhdGUgaGVhcnRiZWF0VGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldEludGVydmFsPiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbGVhZGVyVXJsOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZXNzaW9uSWQ6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBpZDogbnVtYmVyLFxuICApIHt9XG5cbiAgLyoqIE5vdGlmeSB0aGUgbGVhZGVyIHRoYXQgdGhpcyBzZXNzaW9uIGhhcyBzdGFydGVkICovXG4gIGFzeW5jIHN0YXJ0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuc2VuZEV2ZW50KCdzdGFydGVkJyk7XG5cbiAgICB0aGlzLmhlYXJ0YmVhdFRpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgdGhpcy5zZW5kRXZlbnQoJ2hlYXJ0YmVhdCcpLmNhdGNoKCgpID0+IHt9KTtcbiAgICB9LCAxMF8wMDApO1xuICAgIHRoaXMuaGVhcnRiZWF0VGltZXIudW5yZWYoKTtcbiAgfVxuXG4gIC8qKiBOb3RpZnkgdGhlIGxlYWRlciB0aGF0IHRoaXMgc2Vzc2lvbiBpcyBzdG9wcGluZyAqL1xuICBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmhlYXJ0YmVhdFRpbWVyKSB7XG4gICAgICBjbGVhckludGVydmFsKHRoaXMuaGVhcnRiZWF0VGltZXIpO1xuICAgICAgdGhpcy5oZWFydGJlYXRUaW1lciA9IG51bGw7XG4gICAgfVxuICAgIGF3YWl0IHRoaXMuc2VuZEV2ZW50KCdzdG9wcGVkJyk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHNlbmRFdmVudChldmVudDogJ3N0YXJ0ZWQnIHwgJ3N0b3BwZWQnIHwgJ2hlYXJ0YmVhdCcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICAgIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKSwgUkVRVUVTVF9USU1FT1VUX01TKTtcblxuICAgICAgYXdhaXQgZmV0Y2goYCR7dGhpcy5sZWFkZXJVcmx9L2FwaS9pbmdlc3Qvc2Vzc2lvbmAsIHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICBldmVudCxcbiAgICAgICAgICBwaWQ6IHRoaXMucGlkLFxuICAgICAgICAgIHN0YXJ0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICB9KSxcbiAgICAgICAgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcbiAgICAgIH0pO1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgbG9nZ2VyLmRlYnVnKGBbU2Vzc2lvbkhlYXJ0YmVhdF0gRmFpbGVkIHRvIHNlbmQgJHtldmVudH0gZXZlbnRgKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Friendly session names drawn from famous puppets, marionettes,
|
|
3
|
+
* and puppet characters throughout history.
|
|
4
|
+
*
|
|
5
|
+
* Names are assigned from a pool and returned after a cooldown period
|
|
6
|
+
* when sessions end. This keeps the active session list human-readable
|
|
7
|
+
* and on-brand for DollhouseMCP.
|
|
8
|
+
*
|
|
9
|
+
* @since v2.1.0 — Issue #1700
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Manages friendly session name assignment from the puppet name pool.
|
|
13
|
+
*/
|
|
14
|
+
export declare class SessionNamePool {
|
|
15
|
+
/** Names currently assigned to active sessions: sessionId → name */
|
|
16
|
+
private readonly assigned;
|
|
17
|
+
/** Reverse lookup: name → sessionId */
|
|
18
|
+
private readonly nameToSession;
|
|
19
|
+
/** Names in cooldown after session end */
|
|
20
|
+
private cooldown;
|
|
21
|
+
/**
|
|
22
|
+
* Assign a friendly name to a session.
|
|
23
|
+
* Returns an existing assignment if the session already has one.
|
|
24
|
+
*
|
|
25
|
+
* @param isLeader - If true, follower-only names (e.g., Punch) are excluded
|
|
26
|
+
*/
|
|
27
|
+
assign(sessionId: string, isLeader?: boolean): string;
|
|
28
|
+
/**
|
|
29
|
+
* Release a name back to the pool with a cooldown period.
|
|
30
|
+
*/
|
|
31
|
+
release(sessionId: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Get the friendly name for a session, or undefined if not assigned.
|
|
34
|
+
*/
|
|
35
|
+
getName(sessionId: string): string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Get the canonical color for an assigned session name.
|
|
38
|
+
*/
|
|
39
|
+
getColor(sessionId: string): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Get all current assignments.
|
|
42
|
+
*/
|
|
43
|
+
getAll(): Map<string, string>;
|
|
44
|
+
private flushCooldowns;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=SessionNames.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionNames.d.ts","sourceRoot":"","sources":["../../../src/web/console/SessionNames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyLH;;GAEG;AACH,qBAAa,eAAe;IAC1B,oEAAoE;IACpE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IACtD,uCAAuC;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAC3D,0CAA0C;IAC1C,OAAO,CAAC,QAAQ,CAAuB;IAEvC;;;;;OAKG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,MAAM;IAuCnD;;OAEG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAehC;;OAEG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI9C;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK/C;;OAEG;IACH,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAI7B,OAAO,CAAC,cAAc;CAIvB"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Friendly session names drawn from famous puppets, marionettes,
|
|
3
|
+
* and puppet characters throughout history.
|
|
4
|
+
*
|
|
5
|
+
* Names are assigned from a pool and returned after a cooldown period
|
|
6
|
+
* when sessions end. This keeps the active session list human-readable
|
|
7
|
+
* and on-brand for DollhouseMCP.
|
|
8
|
+
*
|
|
9
|
+
* @since v2.1.0 — Issue #1700
|
|
10
|
+
*/
|
|
11
|
+
import { randomInt } from 'node:crypto';
|
|
12
|
+
import { logger } from '../../utils/logger.js';
|
|
13
|
+
/**
|
|
14
|
+
* Famous puppets, marionettes, and puppet characters from around the world.
|
|
15
|
+
* Order doesn't matter — the pool is shuffled on startup.
|
|
16
|
+
*/
|
|
17
|
+
const ALL_PUPPET_NAMES = [
|
|
18
|
+
// Classic & traditional
|
|
19
|
+
'Punch',
|
|
20
|
+
'Judy',
|
|
21
|
+
'Pinocchio',
|
|
22
|
+
'Petrouchka',
|
|
23
|
+
'Pulcinella',
|
|
24
|
+
'Guignol',
|
|
25
|
+
'Kasperle',
|
|
26
|
+
// Muppets & Jim Henson
|
|
27
|
+
'Kermit',
|
|
28
|
+
'Piggy',
|
|
29
|
+
'Fozzie',
|
|
30
|
+
'Gonzo',
|
|
31
|
+
'Scooter',
|
|
32
|
+
'Rowlf',
|
|
33
|
+
'Waldorf',
|
|
34
|
+
'Statler',
|
|
35
|
+
// Kukla, Fran and Ollie
|
|
36
|
+
'Kukla',
|
|
37
|
+
'Ollie',
|
|
38
|
+
// Howdy Doody era
|
|
39
|
+
'Howdy',
|
|
40
|
+
'Clarabell',
|
|
41
|
+
// Sesame Street
|
|
42
|
+
'Grover',
|
|
43
|
+
'Elmo',
|
|
44
|
+
'Ernie',
|
|
45
|
+
'Bert',
|
|
46
|
+
'Oscar',
|
|
47
|
+
// Ventriloquist & variety
|
|
48
|
+
'Mortimer',
|
|
49
|
+
'Lambchop',
|
|
50
|
+
'Madame',
|
|
51
|
+
'Topo',
|
|
52
|
+
// International puppetry
|
|
53
|
+
'Bunraku',
|
|
54
|
+
'Wayang',
|
|
55
|
+
'Petrushka',
|
|
56
|
+
'Hanneschen',
|
|
57
|
+
'Vitezslav',
|
|
58
|
+
// Modern & pop culture
|
|
59
|
+
'Salem',
|
|
60
|
+
'Triumph',
|
|
61
|
+
'Peanut',
|
|
62
|
+
'Achmed',
|
|
63
|
+
// Marionette traditions
|
|
64
|
+
'Fantoccini',
|
|
65
|
+
'Saltimbanque',
|
|
66
|
+
'Burattino',
|
|
67
|
+
'Harlequin',
|
|
68
|
+
// Dollhouse (TV series)
|
|
69
|
+
'Echo',
|
|
70
|
+
// Inside jokes
|
|
71
|
+
'Spike',
|
|
72
|
+
'Angel',
|
|
73
|
+
// Classic dolls
|
|
74
|
+
'Barbie',
|
|
75
|
+
'Ken',
|
|
76
|
+
'Skipper',
|
|
77
|
+
'Midge',
|
|
78
|
+
'Christie',
|
|
79
|
+
'Annie',
|
|
80
|
+
'Andy',
|
|
81
|
+
'Cathy',
|
|
82
|
+
'Teddy',
|
|
83
|
+
'Xavier',
|
|
84
|
+
'Strawberry',
|
|
85
|
+
'Blythe',
|
|
86
|
+
'Ginny',
|
|
87
|
+
'Betsy',
|
|
88
|
+
'Madeline',
|
|
89
|
+
];
|
|
90
|
+
/** Names that can never be assigned to a leader session */
|
|
91
|
+
const FOLLOWER_ONLY_NAMES = new Set(['Punch']);
|
|
92
|
+
/** Fisher-Yates shuffle using crypto.randomInt (unbiased, no modulo) */
|
|
93
|
+
function shuffleArray(arr) {
|
|
94
|
+
for (let i = arr.length - 1; i > 0; i--) {
|
|
95
|
+
const j = randomInt(i + 1);
|
|
96
|
+
[arr[i], arr[j]] = [arr[j], arr[i]];
|
|
97
|
+
}
|
|
98
|
+
return arr;
|
|
99
|
+
}
|
|
100
|
+
/** Shuffled copy of the name pool — randomized on each process start */
|
|
101
|
+
const PUPPET_NAMES = shuffleArray([...ALL_PUPPET_NAMES]);
|
|
102
|
+
/**
|
|
103
|
+
* Canonical colors for each puppet character.
|
|
104
|
+
* Adjusted from true canonical colors for UI readability in both light/dark themes.
|
|
105
|
+
*/
|
|
106
|
+
const PUPPET_COLORS = {
|
|
107
|
+
'Punch': '#DC143C', // crimson red costume
|
|
108
|
+
'Judy': '#1E90FF', // blue dress
|
|
109
|
+
'Pinocchio': '#DAA520', // goldenrod (wooden, yellow hat)
|
|
110
|
+
'Petrouchka': '#B0BEC5', // blue-gray (white costume, adjusted for visibility)
|
|
111
|
+
'Pulcinella': '#90A4AE', // gray-blue (white costume, adjusted)
|
|
112
|
+
'Guignol': '#8B4513', // saddle brown
|
|
113
|
+
'Kasperle': '#FF0000', // red pointed cap
|
|
114
|
+
'Kermit': '#4CAF50', // green frog
|
|
115
|
+
'Piggy': '#E91E8C', // hot pink (glamorous pig)
|
|
116
|
+
'Fozzie': '#CC7722', // ochre brown bear
|
|
117
|
+
'Gonzo': '#4169E1', // royal blue
|
|
118
|
+
'Scooter': '#FF8C00', // dark orange
|
|
119
|
+
'Rowlf': '#8B6914', // dark goldenrod brown dog
|
|
120
|
+
'Waldorf': '#556B2F', // dark olive green
|
|
121
|
+
'Statler': '#708090', // slate gray
|
|
122
|
+
'Kukla': '#FF0000', // red nose and costume
|
|
123
|
+
'Ollie': '#228B22', // forest green dragon
|
|
124
|
+
'Howdy': '#E2725B', // terra cotta
|
|
125
|
+
'Clarabell': '#FFCC00', // bright yellow clown
|
|
126
|
+
'Grover': '#4682B4', // steel blue
|
|
127
|
+
'Elmo': '#FF2400', // scarlet red
|
|
128
|
+
'Ernie': '#F4A460', // sandy brown
|
|
129
|
+
'Bert': '#FFD700', // gold yellow
|
|
130
|
+
'Oscar': '#6B8E23', // olive drab green
|
|
131
|
+
'Mortimer': '#DEB887', // burlywood
|
|
132
|
+
'Lambchop': '#D4C5A9', // warm cream (adjusted from pure white)
|
|
133
|
+
'Madame': '#800080', // purple
|
|
134
|
+
'Topo': '#A0A0A0', // silver gray
|
|
135
|
+
'Bunraku': '#B22222', // firebrick red
|
|
136
|
+
'Wayang': '#6B4226', // dark leather brown (lightened for visibility)
|
|
137
|
+
'Petrushka': '#FF4500', // orange red
|
|
138
|
+
'Hanneschen': '#CD5C5C', // indian red
|
|
139
|
+
'Vitezslav': '#B8860B', // dark goldenrod
|
|
140
|
+
'Salem': '#4A4A4A', // dark gray (black cat, lightened for visibility)
|
|
141
|
+
'Triumph': '#6F4E37', // coffee brown
|
|
142
|
+
'Peanut': '#9370DB', // medium purple
|
|
143
|
+
'Achmed': '#C8BFA9', // bone/parchment (lightened from beige)
|
|
144
|
+
'Fantoccini': '#C41E3A', // cardinal red
|
|
145
|
+
'Saltimbanque': '#DAA520', // goldenrod
|
|
146
|
+
'Burattino': '#D2691E', // chocolate brown
|
|
147
|
+
'Harlequin': '#E60026', // diamond red
|
|
148
|
+
'Echo': '#5C6370', // slate (dark attire, lightened for visibility)
|
|
149
|
+
'Spike': '#E8DCC8', // platinum/bleach (lightened for readability)
|
|
150
|
+
'Angel': '#3D3D3D', // charcoal (black duster, lightened for visibility)
|
|
151
|
+
// Classic dolls
|
|
152
|
+
'Barbie': '#E91E90', // Barbie pink
|
|
153
|
+
'Ken': '#4A90D9', // Ken blue
|
|
154
|
+
'Skipper': '#FF6B6B', // coral red
|
|
155
|
+
'Midge': '#E87040', // warm auburn
|
|
156
|
+
'Christie': '#C06030', // warm brown
|
|
157
|
+
'Annie': '#E03030', // Raggedy Ann red yarn hair
|
|
158
|
+
'Andy': '#3070C0', // Raggedy Andy blue sailor outfit
|
|
159
|
+
'Cathy': '#D4A574', // Chatty Cathy vintage tan
|
|
160
|
+
'Teddy': '#A0784A', // Teddy Ruxpin bear brown
|
|
161
|
+
'Xavier': '#5AAF4A', // Xavier Roberts / Cabbage Patch green
|
|
162
|
+
'Strawberry': '#E8445A', // strawberry red-pink
|
|
163
|
+
'Blythe': '#7B68EE', // big-eyed purple
|
|
164
|
+
'Ginny': '#5B9BD5', // classic blue dress
|
|
165
|
+
'Betsy': '#DD7694', // rose pink
|
|
166
|
+
'Madeline': '#FFD700', // yellow hat
|
|
167
|
+
};
|
|
168
|
+
/** Cooldown period before a released name can be reused (ms) */
|
|
169
|
+
const NAME_COOLDOWN_MS = 5 * 60_000; // 5 minutes
|
|
170
|
+
/**
|
|
171
|
+
* Manages friendly session name assignment from the puppet name pool.
|
|
172
|
+
*/
|
|
173
|
+
export class SessionNamePool {
|
|
174
|
+
/** Names currently assigned to active sessions: sessionId → name */
|
|
175
|
+
assigned = new Map();
|
|
176
|
+
/** Reverse lookup: name → sessionId */
|
|
177
|
+
nameToSession = new Map();
|
|
178
|
+
/** Names in cooldown after session end */
|
|
179
|
+
cooldown = [];
|
|
180
|
+
/**
|
|
181
|
+
* Assign a friendly name to a session.
|
|
182
|
+
* Returns an existing assignment if the session already has one.
|
|
183
|
+
*
|
|
184
|
+
* @param isLeader - If true, follower-only names (e.g., Punch) are excluded
|
|
185
|
+
*/
|
|
186
|
+
assign(sessionId, isLeader = false) {
|
|
187
|
+
// Already assigned?
|
|
188
|
+
const existing = this.assigned.get(sessionId);
|
|
189
|
+
if (existing)
|
|
190
|
+
return existing;
|
|
191
|
+
// Flush expired cooldowns
|
|
192
|
+
this.flushCooldowns();
|
|
193
|
+
// Find an available name, respecting leader restrictions
|
|
194
|
+
const cooldownNames = new Set(this.cooldown.map(c => c.name));
|
|
195
|
+
const availableName = PUPPET_NAMES.find(name => !this.nameToSession.has(name) &&
|
|
196
|
+
!cooldownNames.has(name) &&
|
|
197
|
+
!(isLeader && FOLLOWER_ONLY_NAMES.has(name)));
|
|
198
|
+
if (availableName) {
|
|
199
|
+
this.assigned.set(sessionId, availableName);
|
|
200
|
+
this.nameToSession.set(availableName, sessionId);
|
|
201
|
+
logger.debug(`[SessionNames] Assigned '${availableName}' to ${sessionId}`);
|
|
202
|
+
return availableName;
|
|
203
|
+
}
|
|
204
|
+
// All names in use or cooling down — try cooldown names (oldest first)
|
|
205
|
+
if (this.cooldown.length > 0) {
|
|
206
|
+
const oldest = this.cooldown.shift();
|
|
207
|
+
this.assigned.set(sessionId, oldest.name);
|
|
208
|
+
this.nameToSession.set(oldest.name, sessionId);
|
|
209
|
+
logger.debug(`[SessionNames] Assigned '${oldest.name}' to ${sessionId} (early cooldown release)`);
|
|
210
|
+
return oldest.name;
|
|
211
|
+
}
|
|
212
|
+
// Truly exhausted — fall back to truncated session ID
|
|
213
|
+
const fallback = sessionId.split('-')[1] || sessionId.slice(0, 8);
|
|
214
|
+
this.assigned.set(sessionId, fallback);
|
|
215
|
+
logger.warn(`[SessionNames] Name pool exhausted, using fallback '${fallback}' for ${sessionId}`);
|
|
216
|
+
return fallback;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Release a name back to the pool with a cooldown period.
|
|
220
|
+
*/
|
|
221
|
+
release(sessionId) {
|
|
222
|
+
const name = this.assigned.get(sessionId);
|
|
223
|
+
if (!name)
|
|
224
|
+
return;
|
|
225
|
+
this.assigned.delete(sessionId);
|
|
226
|
+
this.nameToSession.delete(name);
|
|
227
|
+
// Only cooldown puppet names, not fallback IDs
|
|
228
|
+
if (PUPPET_NAMES.includes(name)) {
|
|
229
|
+
this.cooldown.push({ name, releasedAt: Date.now() });
|
|
230
|
+
}
|
|
231
|
+
logger.debug(`[SessionNames] Released '${name}' from ${sessionId} (cooldown ${NAME_COOLDOWN_MS / 1000}s)`);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get the friendly name for a session, or undefined if not assigned.
|
|
235
|
+
*/
|
|
236
|
+
getName(sessionId) {
|
|
237
|
+
return this.assigned.get(sessionId);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get the canonical color for an assigned session name.
|
|
241
|
+
*/
|
|
242
|
+
getColor(sessionId) {
|
|
243
|
+
const name = this.assigned.get(sessionId);
|
|
244
|
+
return name ? (PUPPET_COLORS[name] ?? undefined) : undefined;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Get all current assignments.
|
|
248
|
+
*/
|
|
249
|
+
getAll() {
|
|
250
|
+
return new Map(this.assigned);
|
|
251
|
+
}
|
|
252
|
+
flushCooldowns() {
|
|
253
|
+
const now = Date.now();
|
|
254
|
+
this.cooldown = this.cooldown.filter(c => (now - c.releasedAt) < NAME_COOLDOWN_MS);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2Vzc2lvbk5hbWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3dlYi9jb25zb2xlL1Nlc3Npb25OYW1lcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7O0dBU0c7QUFFSCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUvQzs7O0dBR0c7QUFDSCxNQUFNLGdCQUFnQixHQUFzQjtJQUMxQyx3QkFBd0I7SUFDeEIsT0FBTztJQUNQLE1BQU07SUFDTixXQUFXO0lBQ1gsWUFBWTtJQUNaLFlBQVk7SUFDWixTQUFTO0lBQ1QsVUFBVTtJQUVWLHVCQUF1QjtJQUN2QixRQUFRO0lBQ1IsT0FBTztJQUNQLFFBQVE7SUFDUixPQUFPO0lBQ1AsU0FBUztJQUNULE9BQU87SUFDUCxTQUFTO0lBQ1QsU0FBUztJQUVULHdCQUF3QjtJQUN4QixPQUFPO0lBQ1AsT0FBTztJQUVQLGtCQUFrQjtJQUNsQixPQUFPO0lBQ1AsV0FBVztJQUVYLGdCQUFnQjtJQUNoQixRQUFRO0lBQ1IsTUFBTTtJQUNOLE9BQU87SUFDUCxNQUFNO0lBQ04sT0FBTztJQUVQLDBCQUEwQjtJQUMxQixVQUFVO0lBQ1YsVUFBVTtJQUNWLFFBQVE7SUFDUixNQUFNO0lBRU4seUJBQXlCO0lBQ3pCLFNBQVM7SUFDVCxRQUFRO0lBQ1IsV0FBVztJQUNYLFlBQVk7SUFDWixXQUFXO0lBRVgsdUJBQXVCO0lBQ3ZCLE9BQU87SUFDUCxTQUFTO0lBQ1QsUUFBUTtJQUNSLFFBQVE7SUFFUix3QkFBd0I7SUFDeEIsWUFBWTtJQUNaLGNBQWM7SUFDZCxXQUFXO0lBQ1gsV0FBVztJQUVYLHdCQUF3QjtJQUN4QixNQUFNO0lBRU4sZUFBZTtJQUNmLE9BQU87SUFDUCxPQUFPO0lBRVAsZ0JBQWdCO0lBQ2hCLFFBQVE7SUFDUixLQUFLO0lBQ0wsU0FBUztJQUNULE9B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WyIvKipcbiAqIEZyaWVuZGx5IHNlc3Npb24gbmFtZXMgZHJhd24gZnJvbSBmYW1vdXMgcHVwcGV0cywgbWFyaW9uZXR0ZXMsXG4gKiBhbmQgcHVwcGV0IGNoYXJhY3RlcnMgdGhyb3VnaG91dCBoaXN0b3J5LlxuICpcbiAqIE5hbWVzIGFyZSBhc3NpZ25lZCBmcm9tIGEgcG9vbCBhbmQgcmV0dXJuZWQgYWZ0ZXIgYSBjb29sZG93biBwZXJpb2RcbiAqIHdoZW4gc2Vzc2lvbnMgZW5kLiBUaGlzIGtlZXBzIHRoZSBhY3RpdmUgc2Vzc2lvbiBsaXN0IGh1bWFuLXJlYWRhYmxlXG4gKiBhbmQgb24tYnJhbmQgZm9yIERvbGxob3VzZU1DUC5cbiAqXG4gKiBAc2luY2UgdjIuMS4wIOKAlCBJc3N1ZSAjMTcwMFxuICovXG5cbmltcG9ydCB7IHJhbmRvbUludCB9IGZyb20gJ25vZGU6Y3J5cHRvJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uLy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5cbi8qKlxuICogRmFtb3VzIHB1cHBldHMsIG1hcmlvbmV0dGVzLCBhbmQgcHVwcGV0IGNoYXJhY3RlcnMgZnJvbSBhcm91bmQgdGhlIHdvcmxkLlxuICogT3JkZXIgZG9lc24ndCBtYXR0ZXIg4oCUIHRoZSBwb29sIGlzIHNodWZmbGVkIG9uIHN0YXJ0dXAuXG4gKi9cbmNvbnN0IEFMTF9QVVBQRVRfTkFNRVM6IHJlYWRvbmx5IHN0cmluZ1tdID0gW1xuICAvLyBDbGFzc2ljICYgdHJhZGl0aW9uYWxcbiAgJ1B1bmNoJyxcbiAgJ0p1ZHknLFxuICAnUGlub2NjaGlvJyxcbiAgJ1BldHJvdWNoa2EnLFxuICAnUHVsY2luZWxsYScsXG4gICdHdWlnbm9sJyxcbiAgJ0thc3BlcmxlJyxcblxuICAvLyBNdXBwZXRzICYgSmltIEhlbnNvblxuICAnS2VybWl0JyxcbiAgJ1BpZ2d5JyxcbiAgJ0ZvenppZScsXG4gICdHb256bycsXG4gICdTY29vdGVyJyxcbiAgJ1Jvd2xmJyxcbiAgJ1dhbGRvcmYnLFxuICAnU3RhdGxlcicsXG5cbiAgLy8gS3VrbGEsIEZyYW4gYW5kIE9sbGllXG4gICdLdWtsYScsXG4gICdPbGxpZScsXG5cbiAgLy8gSG93ZHkgRG9vZHkgZXJhXG4gICdIb3dkeScsXG4gICdDbGFyYWJlbGwnLFxuXG4gIC8vIFNlc2FtZSBTdHJlZXRcbiAgJ0dyb3ZlcicsXG4gICdFbG1vJyxcbiAgJ0VybmllJyxcbiAgJ0JlcnQnLFxuICAnT3NjYXInLFxuXG4gIC8vIFZlbnRyaWxvcXVpc3QgJiB2YXJpZXR5XG4gICdNb3J0aW1lcicsXG4gICdMYW1iY2hvcCcsXG4gICdNYWRhbWUnLFxuICAnVG9wbycsXG5cbiAgLy8gSW50ZXJuYXRpb25hbCBwdXBwZXRyeVxuICAnQnVucmFrdScsXG4gICdXYXlhbmcnLFxuICAnUGV0cnVzaGthJyxcbiAgJ0hhbm5lc2NoZW4nLFxuICAnVml0ZXpzbGF2JyxcblxuICAvLyBNb2Rlcm4gJiBwb3AgY3VsdHVyZVxuICAnU2FsZW0nLFxuICAnVHJpdW1waCcsXG4gICdQZWFudXQnLFxuICAnQWNobWVkJyxcblxuICAvLyBNYXJpb25ldHRlIHRyYWRpdGlvbnNcbiAgJ0ZhbnRvY2NpbmknLFxuICAnU2FsdGltYmFucXVlJyxcbiAgJ0J1cmF0dGlubycsXG4gICdIYXJsZXF1aW4nLFxuXG4gIC8vIERvbGxob3VzZSAoVFYgc2VyaWVzKVxuICAnRWNobycsXG5cbiAgLy8gSW5zaWRlIGpva2VzXG4gICdTcGlrZScsXG4gICdBbmdlbCcsXG5cbiAgLy8gQ2xhc3NpYyBkb2xsc1xuICAnQmFyYmllJyxcbiAgJ0tlbicsXG4gICdTa2lwcGVyJyxcbiAgJ01pZGdlJyxcbiAgJ0NocmlzdGllJyxcbiAgJ0FubmllJyxcbiAgJ0FuZHknLFxuICAnQ2F0aHknLFxuICAnVGVkZHknLFxuICAnWGF2aWVyJyxcbiAgJ1N0cmF3YmVycnknLFxuICAnQmx5dGhlJyxcbiAgJ0dpbm55JyxcbiAgJ0JldHN5JyxcbiAgJ01hZGVsaW5lJyxcbl07XG5cbi8qKiBOYW1lcyB0aGF0IGNhbiBuZXZlciBiZSBhc3NpZ25lZCB0byBhIGxlYWRlciBzZXNzaW9uICovXG5jb25zdCBGT0xMT1dFUl9PTkxZX05BTUVTID0gbmV3IFNldChbJ1B1bmNoJ10pO1xuXG4vKiogRmlzaGVyLVlhdGVzIHNodWZmbGUgdXNpbmcgY3J5cHRvLnJhbmRvbUludCAodW5iaWFzZWQsIG5vIG1vZHVsbykgKi9cbmZ1bmN0aW9uIHNodWZmbGVBcnJheTxUPihhcnI6IFRbXSk6IFRbXSB7XG4gIGZvciAobGV0IGkgPSBhcnIubGVuZ3RoIC0gMTsgaSA+IDA7IGktLSkge1xuICAgIGNvbnN0IGogPSByYW5kb21JbnQoaSArIDEpO1xuICAgIFthcnJbaV0sIGFycltqXV0gPSBbYXJyW2pdLCBhcnJbaV1dO1xuICB9XG4gIHJldHVybiBhcnI7XG59XG5cbi8qKiBTaHVmZmxlZCBjb3B5IG9mIHRoZSBuYW1lIHBvb2wg4oCUIHJhbmRvbWl6ZWQgb24gZWFjaCBwcm9jZXNzIHN0YXJ0ICovXG5jb25zdCBQVVBQRVRfTkFNRVM6IHN0cmluZ1tdID0gc2h1ZmZsZUFycmF5KFsuLi5BTExfUFVQUEVUX05BTUVTXSk7XG5cbi8qKlxuICogQ2Fub25pY2FsIGNvbG9ycyBmb3IgZWFjaCBwdXBwZXQgY2hhcmFjdGVyLlxuICogQWRqdXN0ZWQgZnJvbSB0cnVlIGNhbm9uaWNhbCBjb2xvcnMgZm9yIFVJIHJlYWRhYmlsaXR5IGluIGJvdGggbGlnaHQvZGFyayB0aGVtZXMuXG4gKi9cbmNvbnN0IFBVUFBFVF9DT0xPUlM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICdQdW5jaCc6ICAgICAgICAnI0RDMTQzQycsIC8vIGNyaW1zb24gcmVkIGNvc3R1bWVcbiAgJ0p1ZHknOiAgICAgICAgICcjMUU5MEZGJywgLy8gYmx1ZSBkcmVzc1xuICAnUGlub2NjaGlvJzogICAgJyNEQUE1MjAnLCAvLyBnb2xkZW5yb2QgKHdvb2RlbiwgeWVsbG93IGhhdClcbiAgJ1BldHJvdWNoa2EnOiAgICcjQjBCRUM1JywgLy8gYmx1ZS1ncmF5ICh3aGl0ZSBjb3N0dW1lLCBhZGp1c3RlZCBmb3IgdmlzaWJpbGl0eSlcbiAgJ1B1bGNpbmVsbGEnOiAgICcjOTBBNEFFJywgLy8gZ3JheS1ibHVlICh3aGl0ZSBjb3N0dW1lLCBhZGp1c3RlZClcbiAgJ0d1aWdub2wnOiAgICAgICcjOEI0NTEzJywgLy8gc2FkZGxlIGJyb3duXG4gICdLYXNwZXJsZSc6ICAgICAnI0ZGMDAwMCcsIC8vIHJlZCBwb2ludGVkIGNhcFxuICAnS2VybWl0JzogICAgICAgJyM0Q0FGNTAnLCAvLyBncmVlbiBmcm9nXG4gICdQaWdneSc6ICAgICAgICAnI0U5MUU4QycsIC8vIGhvdCBwaW5rIChnbGFtb3JvdXMgcGlnKVxuICAnRm96emllJzogICAgICAgJyNDQzc3MjInLCAvLyBvY2hyZSBicm93biBiZWFyXG4gICdHb256byc6ICAgICAgICAnIzQxNjlFMScsIC8vIHJveWFsIGJsdWVcbiAgJ1Njb290ZXInOiAgICAgICcjRkY4QzAwJywgLy8gZGFyayBvcmFuZ2VcbiAgJ1Jvd2xmJzogICAgICAgICcjOEI2OTE0JywgLy8gZGFyayBnb2xkZW5yb2QgYnJvd24gZG9nXG4gICdXYWxkb3JmJzogICAgICAnIzU1NkIyRicsIC8vIGRhcmsgb2xpdmUgZ3JlZW5cbiAgJ1N0YXRsZXInOiAgICAgICcjNzA4MDkwJywgLy8gc2xhdGUgZ3JheVxuICAnS3VrbGEnOiAgICAgICAgJyNGRjAwMDAnLCAvLyByZWQgbm9zZSBhbmQgY29zdHVtZVxuICAnT2xsaWUnOiAgICAgICAgJyMyMjhCMjInLCAvLyBmb3Jlc3QgZ3JlZW4gZHJhZ29uXG4gICdIb3dkeSc6ICAgICAgICAnI0UyNzI1QicsIC8vIHRlcnJhIGNvdHRhXG4gICdDbGFyYWJlbGwnOiAgICAnI0ZGQ0MwMCcsIC8vIGJyaWdodCB5ZWxsb3cgY2xvd25cbiAgJ0dyb3Zlcic6ICAgICAgICcjNDY4MkI0JywgLy8gc3RlZWwgYmx1ZVxuICAnRWxtbyc6ICAgICAgICAgJyNGRjI0MDAnLCAvLyBzY2FybGV0IHJlZFxuICAnRXJuaWUnOiAgICAgICAgJyNGNEE0NjAnLCAvLyBzYW5keSBicm93blxuICAnQmVydCc6ICAgICAgICAgJyNGRkQ3MDAnLCAvLyBnb2xkIHllbGxvd1xuICAnT3NjYXInOiAgICAgICAgJyM2QjhFMjMnLCAvLyBvbGl2ZSBkcmFiIGdyZWVuXG4gICdNb3J0aW1lcic6ICAgICAnI0RFQjg4NycsIC8vIGJ1cmx5d29vZFxuICAnTGFtYmNob3AnOiAgICAgJyNENEM1QTknLCAvLyB3YXJtIGNyZWFtIChhZGp1c3RlZCBmcm9tIHB1cmUgd2hpdGUpXG4gICdNYWRhbWUnOiAgICAgICAnIzgwMDA4MCcsIC8vIHB1cnBsZVxuICAnVG9wbyc6ICAgICAgICAgJyNBMEEwQTAnLCAvLyBzaWx2ZXIgZ3JheVxuICAnQnVucmFrdSc6ICAgICAgJyNCMjIyMjInLCAvLyBmaXJlYnJpY2sgcmVkXG4gICdXYXlhbmcnOiAgICAgICAnIzZCNDIyNicsIC8vIGRhcmsgbGVhdGhlciBicm93biAobGlnaHRlbmVkIGZvciB2aXNpYmlsaXR5KVxuICAnUGV0cnVzaGthJzogICAgJyNGRjQ1MDAnLCAvLyBvcmFuZ2UgcmVkXG4gICdIYW5uZXNjaGVuJzogICAnI0NENUM1QycsIC8vIGluZGlhbiByZWRcbiAgJ1ZpdGV6c2xhdic6ICAgICcjQjg4NjBCJywgLy8gZGFyayBnb2xkZW5yb2RcbiAgJ1NhbGVtJzogICAgICAgICcjNEE0QTRBJywgLy8gZGFyayBncmF5IChibGFjayBjYXQsIGxpZ2h0ZW5lZCBmb3IgdmlzaWJpbGl0eSlcbiAgJ1RyaXVtcGgnOiAgICAgICcjNkY0RTM3JywgLy8gY29mZmVlIGJyb3duXG4gICdQZWFudXQnOiAgICAgICAnIzkzNzBEQicsIC8vIG1lZGl1bSBwdXJwbGVcbiAgJ0FjaG1lZCc6ICAgICAgICcjQzhCRkE5JywgLy8gYm9uZS9wYXJjaG1lbnQgKGxpZ2h0ZW5lZCBmcm9tIGJlaWdlKVxuICAnRmFudG9jY2luaSc6ICAgJyNDNDFFM0EnLCAvLyBjYXJkaW5hbCByZWRcbiAgJ1NhbHRpbWJhbnF1ZSc6ICcjREFBNTIwJywgLy8gZ29sZGVucm9kXG4gICdCdXJhdHRpbm8nOiAgICAnI0QyNjkxRScsIC8vIGNob2NvbGF0ZSBicm93blxuICAnSGFybGVxdWluJzogICAgJyNFNjAwMjYnLCAvLyBkaWFtb25kIHJlZFxuICAnRWNobyc6ICAgICAgICAgJyM1QzYzNzAnLCAvLyBzbGF0ZSAoZGFyayBhdHRpcmUsIGxpZ2h0ZW5lZCBmb3IgdmlzaWJpbGl0eSlcbiAgJ1NwaWtlJzogICAgICAgICcjRThEQ0M4JywgLy8gcGxhdGludW0vYmxlYWNoIChsaWdodGVuZWQgZm9yIHJlYWRhYmlsaXR5KVxuICAnQW5nZWwnOiAgICAgICAgJyMzRDNEM0QnLCAvLyBjaGFyY29hbCAoYmxhY2sgZHVzdGVyLCBsaWdodGVuZWQgZm9yIHZpc2liaWxpdHkpXG5cbiAgLy8gQ2xhc3NpYyBkb2xsc1xuICAnQmFyYmllJzogICAgICAgJyNFOTFFOTAnLCAvLyBCYXJiaWUgcGlua1xuICAnS2VuJzogICAgICAgICAgJyM0QTkwRDknLCAvLyBLZW4gYmx1ZVxuICAnU2tpcHBlcic6ICAgICAgJyNGRjZCNkInLCAvLyBjb3JhbCByZWRcbiAgJ01pZGdlJzogICAgICAgICcjRTg3MDQwJywgLy8gd2FybSBhdWJ1cm5cbiAgJ0NocmlzdGllJzogICAgICcjQzA2MDMwJywgLy8gd2FybSBicm93blxuICAnQW5uaWUnOiAgICAgICAgJyNFMDMwMzAnLCAvLyBSYWdnZWR5IEFubiByZWQgeWFybiBoYWlyXG4gICdBbmR5JzogICAgICAgICAnIzMwNzBDMCcsIC8vIFJhZ2dlZHkgQW5keSBibHVlIHNhaWxvciBvdXRmaXRcbiAgJ0NhdGh5JzogICAgICAgICcjRDRBNTc0JywgLy8gQ2hhdHR5IENhdGh5IHZpbnRhZ2UgdGFuXG4gICdUZWRkeSc6ICAgICAgICAnI0EwNzg0QScsIC8vIFRlZGR5IFJ1eHBpbiBiZWFyIGJyb3duXG4gICdYYXZpZXInOiAgICAgICAnIzVBQUY0QScsIC8vIFhhdmllciBSb2JlcnRzIC8gQ2FiYmFnZSBQYXRjaCBncmVlblxuICAnU3RyYXdiZXJyeSc6ICAgJyNFODQ0NUEnLCAvLyBzdHJhd2JlcnJ5IHJlZC1waW5rXG4gICdCbHl0aGUnOiAgICAgICAnIzdCNjhFRScsIC8vIGJpZy1leWVkIHB1cnBsZVxuICAnR2lubnknOiAgICAgICAgJyM1QjlCRDUnLCAvLyBjbGFzc2ljIGJsdWUgZHJlc3NcbiAgJ0JldHN5JzogICAgICAgICcjREQ3Njk0JywgLy8gcm9zZSBwaW5rXG4gICdNYWRlbGluZSc6ICAgICAnI0ZGRDcwMCcsIC8vIHllbGxvdyBoYXRcbn07XG5cbi8qKiBDb29sZG93biBwZXJpb2QgYmVmb3JlIGEgcmVsZWFzZWQgbmFtZSBjYW4gYmUgcmV1c2VkIChtcykgKi9cbmNvbnN0IE5BTUVfQ09PTERPV05fTVMgPSA1ICogNjBfMDAwOyAvLyA1IG1pbnV0ZXNcblxuaW50ZXJmYWNlIENvb2xkb3duRW50cnkge1xuICBuYW1lOiBzdHJpbmc7XG4gIHJlbGVhc2VkQXQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBNYW5hZ2VzIGZyaWVuZGx5IHNlc3Npb24gbmFtZSBhc3NpZ25tZW50IGZyb20gdGhlIHB1cHBldCBuYW1lIHBvb2wuXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXNzaW9uTmFtZVBvb2wge1xuICAvKiogTmFtZXMgY3VycmVudGx5IGFzc2lnbmVkIHRvIGFjdGl2ZSBzZXNzaW9uczogc2Vzc2lvbklkIOKGkiBuYW1lICovXG4gIHByaXZhdGUgcmVhZG9ubHkgYXNzaWduZWQgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAvKiogUmV2ZXJzZSBsb29rdXA6IG5hbWUg4oaSIHNlc3Npb25JZCAqL1xuICBwcml2YXRlIHJlYWRvbmx5IG5hbWVUb1Nlc3Npb24gPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAvKiogTmFtZXMgaW4gY29vbGRvd24gYWZ0ZXIgc2Vzc2lvbiBlbmQgKi9cbiAgcHJpdmF0ZSBjb29sZG93bjogQ29vbGRvd25FbnRyeVtdID0gW107XG5cbiAgLyoqXG4gICAqIEFzc2lnbiBhIGZyaWVuZGx5IG5hbWUgdG8gYSBzZXNzaW9uLlxuICAgKiBSZXR1cm5zIGFuIGV4aXN0aW5nIGFzc2lnbm1lbnQgaWYgdGhlIHNlc3Npb24gYWxyZWFkeSBoYXMgb25lLlxuICAgKlxuICAgKiBAcGFyYW0gaXNMZWFkZXIgLSBJZiB0cnVlLCBmb2xsb3dlci1vbmx5IG5hbWVzIChlLmcuLCBQdW5jaCkgYXJlIGV4Y2x1ZGVkXG4gICAqL1xuICBhc3NpZ24oc2Vzc2lvbklkOiBzdHJpbmcsIGlzTGVhZGVyID0gZmFsc2UpOiBzdHJpbmcge1xuICAgIC8vIEFscmVhZHkgYXNzaWduZWQ/XG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLmFzc2lnbmVkLmdldChzZXNzaW9uSWQpO1xuICAgIGlmIChleGlzdGluZykgcmV0dXJuIGV4aXN0aW5nO1xuXG4gICAgLy8gRmx1c2ggZXhwaXJlZCBjb29sZG93bnNcbiAgICB0aGlzLmZsdXNoQ29vbGRvd25zKCk7XG5cbiAgICAvLyBGaW5kIGFuIGF2YWlsYWJsZSBuYW1lLCByZXNwZWN0aW5nIGxlYWRlciByZXN0cmljdGlvbnNcbiAgICBjb25zdCBjb29sZG93bk5hbWVzID0gbmV3IFNldCh0aGlzLmNvb2xkb3duLm1hcChjID0+IGMubmFtZSkpO1xuICAgIGNvbnN0IGF2YWlsYWJsZU5hbWUgPSBQVVBQRVRfTkFNRVMuZmluZChcbiAgICAgIG5hbWUgPT4gIXRoaXMubmFtZVRvU2Vzc2lvbi5oYXMobmFtZSkgJiZcbiAgICAgICAgICAgICAgIWNvb2xkb3duTmFtZXMuaGFzKG5hbWUpICYmXG4gICAgICAgICAgICAgICEoaXNMZWFkZXIgJiYgRk9MTE9XRVJfT05MWV9OQU1FUy5oYXMobmFtZSkpXG4gICAgKTtcblxuICAgIGlmIChhdmFpbGFibGVOYW1lKSB7XG4gICAgICB0aGlzLmFzc2lnbmVkLnNldChzZXNzaW9uSWQsIGF2YWlsYWJsZU5hbWUpO1xuICAgICAgdGhpcy5uYW1lVG9TZXNzaW9uLnNldChhdmFpbGFibGVOYW1lLCBzZXNzaW9uSWQpO1xuICAgICAgbG9nZ2VyLmRlYnVnKGBbU2Vzc2lvbk5hbWVzXSBBc3NpZ25lZCAnJHthdmFpbGFibGVOYW1lfScgdG8gJHtzZXNzaW9uSWR9YCk7XG4gICAgICByZXR1cm4gYXZhaWxhYmxlTmFtZTtcbiAgICB9XG5cbiAgICAvLyBBbGwgbmFtZXMgaW4gdXNlIG9yIGNvb2xpbmcgZG93biDigJQgdHJ5IGNvb2xkb3duIG5hbWVzIChvbGRlc3QgZmlyc3QpXG4gICAgaWYgKHRoaXMuY29vbGRvd24ubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3Qgb2xkZXN0ID0gdGhpcy5jb29sZG93bi5zaGlmdCgpITtcbiAgICAgIHRoaXMuYXNzaWduZWQuc2V0KHNlc3Npb25JZCwgb2xkZXN0Lm5hbWUpO1xuICAgICAgdGhpcy5uYW1lVG9TZXNzaW9uLnNldChvbGRlc3QubmFtZSwgc2Vzc2lvbklkKTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgW1Nlc3Npb25OYW1lc10gQXNzaWduZWQgJyR7b2xkZXN0Lm5hbWV9JyB0byAke3Nlc3Npb25JZH0gKGVhcmx5IGNvb2xkb3duIHJlbGVhc2UpYCk7XG4gICAgICByZXR1cm4gb2xkZXN0Lm5hbWU7XG4gICAgfVxuXG4gICAgLy8gVHJ1bHkgZXhoYXVzdGVkIOKAlCBmYWxsIGJhY2sgdG8gdHJ1bmNhdGVkIHNlc3Npb24gSURcbiAgICBjb25zdCBmYWxsYmFjayA9IHNlc3Npb25JZC5zcGxpdCgnLScpWzFdIHx8IHNlc3Npb25JZC5zbGljZSgwLCA4KTtcbiAgICB0aGlzLmFzc2lnbmVkLnNldChzZXNzaW9uSWQsIGZhbGxiYWNrKTtcbiAgICBsb2dnZXIud2FybihgW1Nlc3Npb25OYW1lc10gTmFtZSBwb29sIGV4aGF1c3RlZCwgdXNpbmcgZmFsbGJhY2sgJyR7ZmFsbGJhY2t9JyBmb3IgJHtzZXNzaW9uSWR9YCk7XG4gICAgcmV0dXJuIGZhbGxiYWNrO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbGVhc2UgYSBuYW1lIGJhY2sgdG8gdGhlIHBvb2wgd2l0aCBhIGNvb2xkb3duIHBlcmlvZC5cbiAgICovXG4gIHJlbGVhc2Uoc2Vzc2lvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBuYW1lID0gdGhpcy5hc3NpZ25lZC5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIW5hbWUpIHJldHVybjtcblxuICAgIHRoaXMuYXNzaWduZWQuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgdGhpcy5uYW1lVG9TZXNzaW9uLmRlbGV0ZShuYW1lKTtcblxuICAgIC8vIE9ubHkgY29vbGRvd24gcHVwcGV0IG5hbWVzLCBub3QgZmFsbGJhY2sgSURzXG4gICAgaWYgKFBVUFBFVF9OQU1FUy5pbmNsdWRlcyhuYW1lKSkge1xuICAgICAgdGhpcy5jb29sZG93bi5wdXNoKHsgbmFtZSwgcmVsZWFzZWRBdDogRGF0ZS5ub3coKSB9KTtcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoYFtTZXNzaW9uTmFtZXNdIFJlbGVhc2VkICcke25hbWV9JyBmcm9tICR7c2Vzc2lvbklkfSAoY29vbGRvd24gJHtOQU1FX0NPT0xET1dOX01TIC8gMTAwMH1zKWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZnJpZW5kbHkgbmFtZSBmb3IgYSBzZXNzaW9uLCBvciB1bmRlZmluZWQgaWYgbm90IGFzc2lnbmVkLlxuICAgKi9cbiAgZ2V0TmFtZShzZXNzaW9uSWQ6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuYXNzaWduZWQuZ2V0KHNlc3Npb25JZCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBjYW5vbmljYWwgY29sb3IgZm9yIGFuIGFzc2lnbmVkIHNlc3Npb24gbmFtZS5cbiAgICovXG4gIGdldENvbG9yKHNlc3Npb25JZDogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBuYW1lID0gdGhpcy5hc3NpZ25lZC5nZXQoc2Vzc2lvbklkKTtcbiAgICByZXR1cm4gbmFtZSA/IChQVVBQRVRfQ09MT1JTW25hbWVdID8/IHVuZGVmaW5lZCkgOiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCBjdXJyZW50IGFzc2lnbm1lbnRzLlxuICAgKi9cbiAgZ2V0QWxsKCk6IE1hcDxzdHJpbmcsIHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgTWFwKHRoaXMuYXNzaWduZWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBmbHVzaENvb2xkb3ducygpOiB2b2lkIHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIHRoaXMuY29vbGRvd24gPSB0aGlzLmNvb2xkb3duLmZpbHRlcihjID0+IChub3cgLSBjLnJlbGVhc2VkQXQpIDwgTkFNRV9DT09MRE9XTl9NUyk7XG4gIH1cbn1cbiJdfQ==
|