aegis-bridge 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +404 -0
- package/dashboard/dist/assets/index-BoZwGLAx.css +32 -0
- package/dashboard/dist/assets/index-C61BkKH-.js +312 -0
- package/dashboard/dist/assets/index-C61BkKH-.js.map +1 -0
- package/dashboard/dist/index.html +14 -0
- package/dist/api-contracts.d.ts +229 -0
- package/dist/api-contracts.js +7 -0
- package/dist/api-contracts.typecheck.d.ts +14 -0
- package/dist/api-contracts.typecheck.js +1 -0
- package/dist/api-error-envelope.d.ts +15 -0
- package/dist/api-error-envelope.js +80 -0
- package/dist/auth.d.ts +87 -0
- package/dist/auth.js +276 -0
- package/dist/channels/index.d.ts +8 -0
- package/dist/channels/index.js +8 -0
- package/dist/channels/manager.d.ts +47 -0
- package/dist/channels/manager.js +115 -0
- package/dist/channels/telegram-style.d.ts +118 -0
- package/dist/channels/telegram-style.js +202 -0
- package/dist/channels/telegram.d.ts +91 -0
- package/dist/channels/telegram.js +1518 -0
- package/dist/channels/types.d.ts +77 -0
- package/dist/channels/types.js +8 -0
- package/dist/channels/webhook.d.ts +60 -0
- package/dist/channels/webhook.js +216 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +252 -0
- package/dist/config.d.ts +90 -0
- package/dist/config.js +214 -0
- package/dist/consensus.d.ts +16 -0
- package/dist/consensus.js +19 -0
- package/dist/continuation-pointer.d.ts +11 -0
- package/dist/continuation-pointer.js +65 -0
- package/dist/diagnostics.d.ts +27 -0
- package/dist/diagnostics.js +95 -0
- package/dist/error-categories.d.ts +39 -0
- package/dist/error-categories.js +73 -0
- package/dist/events.d.ts +133 -0
- package/dist/events.js +389 -0
- package/dist/fault-injection.d.ts +29 -0
- package/dist/fault-injection.js +115 -0
- package/dist/file-utils.d.ts +2 -0
- package/dist/file-utils.js +37 -0
- package/dist/handshake.d.ts +60 -0
- package/dist/handshake.js +124 -0
- package/dist/hook-settings.d.ts +80 -0
- package/dist/hook-settings.js +272 -0
- package/dist/hook.d.ts +19 -0
- package/dist/hook.js +231 -0
- package/dist/hooks.d.ts +32 -0
- package/dist/hooks.js +364 -0
- package/dist/jsonl-watcher.d.ts +59 -0
- package/dist/jsonl-watcher.js +166 -0
- package/dist/logger.d.ts +35 -0
- package/dist/logger.js +65 -0
- package/dist/mcp-server.d.ts +123 -0
- package/dist/mcp-server.js +869 -0
- package/dist/memory-bridge.d.ts +27 -0
- package/dist/memory-bridge.js +137 -0
- package/dist/memory-routes.d.ts +3 -0
- package/dist/memory-routes.js +100 -0
- package/dist/metrics.d.ts +126 -0
- package/dist/metrics.js +286 -0
- package/dist/model-router.d.ts +53 -0
- package/dist/model-router.js +150 -0
- package/dist/monitor.d.ts +103 -0
- package/dist/monitor.js +820 -0
- package/dist/path-utils.d.ts +11 -0
- package/dist/path-utils.js +21 -0
- package/dist/permission-evaluator.d.ts +10 -0
- package/dist/permission-evaluator.js +48 -0
- package/dist/permission-guard.d.ts +51 -0
- package/dist/permission-guard.js +196 -0
- package/dist/permission-request-manager.d.ts +12 -0
- package/dist/permission-request-manager.js +36 -0
- package/dist/permission-routes.d.ts +7 -0
- package/dist/permission-routes.js +28 -0
- package/dist/pipeline.d.ts +97 -0
- package/dist/pipeline.js +291 -0
- package/dist/process-utils.d.ts +4 -0
- package/dist/process-utils.js +73 -0
- package/dist/question-manager.d.ts +54 -0
- package/dist/question-manager.js +80 -0
- package/dist/retry.d.ts +11 -0
- package/dist/retry.js +34 -0
- package/dist/safe-json.d.ts +12 -0
- package/dist/safe-json.js +22 -0
- package/dist/screenshot.d.ts +28 -0
- package/dist/screenshot.js +60 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.js +1973 -0
- package/dist/session-cleanup.d.ts +18 -0
- package/dist/session-cleanup.js +11 -0
- package/dist/session.d.ts +379 -0
- package/dist/session.js +1568 -0
- package/dist/shutdown-utils.d.ts +5 -0
- package/dist/shutdown-utils.js +24 -0
- package/dist/signal-cleanup-helper.d.ts +48 -0
- package/dist/signal-cleanup-helper.js +117 -0
- package/dist/sse-limiter.d.ts +47 -0
- package/dist/sse-limiter.js +61 -0
- package/dist/sse-writer.d.ts +31 -0
- package/dist/sse-writer.js +94 -0
- package/dist/ssrf.d.ts +102 -0
- package/dist/ssrf.js +267 -0
- package/dist/startup.d.ts +6 -0
- package/dist/startup.js +162 -0
- package/dist/suppress.d.ts +33 -0
- package/dist/suppress.js +79 -0
- package/dist/swarm-monitor.d.ts +117 -0
- package/dist/swarm-monitor.js +300 -0
- package/dist/template-store.d.ts +45 -0
- package/dist/template-store.js +142 -0
- package/dist/terminal-parser.d.ts +16 -0
- package/dist/terminal-parser.js +346 -0
- package/dist/tmux-capture-cache.d.ts +18 -0
- package/dist/tmux-capture-cache.js +34 -0
- package/dist/tmux.d.ts +183 -0
- package/dist/tmux.js +906 -0
- package/dist/tool-registry.d.ts +40 -0
- package/dist/tool-registry.js +83 -0
- package/dist/transcript.d.ts +63 -0
- package/dist/transcript.js +284 -0
- package/dist/utils/circular-buffer.d.ts +11 -0
- package/dist/utils/circular-buffer.js +37 -0
- package/dist/utils/redact-headers.d.ts +13 -0
- package/dist/utils/redact-headers.js +54 -0
- package/dist/validation.d.ts +406 -0
- package/dist/validation.js +415 -0
- package/dist/verification.d.ts +2 -0
- package/dist/verification.js +72 -0
- package/dist/worktree-lookup.d.ts +24 -0
- package/dist/worktree-lookup.js +71 -0
- package/dist/ws-terminal.d.ts +32 -0
- package/dist/ws-terminal.js +348 -0
- package/package.json +83 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* model-router.ts — Issue #743: Tiered Model Routing
|
|
3
|
+
*
|
|
4
|
+
* Scores task complexity from metadata (title, labels, description) and routes
|
|
5
|
+
* to the optimal model tier: fast | standard | power.
|
|
6
|
+
*
|
|
7
|
+
* Scoring (0–100):
|
|
8
|
+
* 0–30 → fast (cheapest, e.g. Haiku-class)
|
|
9
|
+
* 31–70 → standard (balanced, e.g. Sonnet-class)
|
|
10
|
+
* 71–100 → power (most capable, e.g. Opus-class)
|
|
11
|
+
*
|
|
12
|
+
* Concrete model names are configurable via environment variables:
|
|
13
|
+
* MODEL_FAST, MODEL_STANDARD, MODEL_POWER
|
|
14
|
+
*/
|
|
15
|
+
import type { FastifyInstance } from 'fastify';
|
|
16
|
+
export type ModelTier = 'fast' | 'standard' | 'power';
|
|
17
|
+
export interface RoutingDecision {
|
|
18
|
+
tier: ModelTier;
|
|
19
|
+
model: string;
|
|
20
|
+
score: number;
|
|
21
|
+
reasoning: string[];
|
|
22
|
+
}
|
|
23
|
+
/** Default model names per tier (overridable via env vars). */
|
|
24
|
+
export declare const MODEL_TIERS: Record<ModelTier, string>;
|
|
25
|
+
/**
|
|
26
|
+
* Score a task 0–100 based on its metadata.
|
|
27
|
+
* Returns the score and a human-readable reasoning list.
|
|
28
|
+
*/
|
|
29
|
+
export declare function scoreTaskComplexity(title: string, labels: string[], description: string): {
|
|
30
|
+
score: number;
|
|
31
|
+
reasoning: string[];
|
|
32
|
+
};
|
|
33
|
+
/** Map a 0–100 score to a model tier. */
|
|
34
|
+
export declare function scoreToTier(score: number): ModelTier;
|
|
35
|
+
/**
|
|
36
|
+
* Route a task to the optimal model tier and concrete model name.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* routeTask({ title: 'fix typo in README', labels: ['docs'] })
|
|
40
|
+
* // → { tier: 'fast', model: 'claude-haiku-4-5', score: 15, reasoning: [...] }
|
|
41
|
+
*/
|
|
42
|
+
export declare function routeTask(opts: {
|
|
43
|
+
title: string;
|
|
44
|
+
labels?: string[];
|
|
45
|
+
description?: string;
|
|
46
|
+
}): RoutingDecision;
|
|
47
|
+
/**
|
|
48
|
+
* Register the model-routing endpoint on the Fastify app.
|
|
49
|
+
*
|
|
50
|
+
* POST /v1/dev/route-task — score a task and return model recommendation.
|
|
51
|
+
* GET /v1/dev/model-tiers — return current model-tier configuration.
|
|
52
|
+
*/
|
|
53
|
+
export declare function registerModelRouterRoutes(app: FastifyInstance): void;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* model-router.ts — Issue #743: Tiered Model Routing
|
|
3
|
+
*
|
|
4
|
+
* Scores task complexity from metadata (title, labels, description) and routes
|
|
5
|
+
* to the optimal model tier: fast | standard | power.
|
|
6
|
+
*
|
|
7
|
+
* Scoring (0–100):
|
|
8
|
+
* 0–30 → fast (cheapest, e.g. Haiku-class)
|
|
9
|
+
* 31–70 → standard (balanced, e.g. Sonnet-class)
|
|
10
|
+
* 71–100 → power (most capable, e.g. Opus-class)
|
|
11
|
+
*
|
|
12
|
+
* Concrete model names are configurable via environment variables:
|
|
13
|
+
* MODEL_FAST, MODEL_STANDARD, MODEL_POWER
|
|
14
|
+
*/
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
/** Keyword signals mapped to model tier. First match in each tier wins. */
|
|
17
|
+
const ROUTING_KEYWORDS = {
|
|
18
|
+
power: [
|
|
19
|
+
'security', 'auth', 'authentication', 'authorization',
|
|
20
|
+
'architecture', 'redesign', 'migration', 'critical',
|
|
21
|
+
'vulnerability', 'injection', 'cryptography', 'encryption',
|
|
22
|
+
'race condition', 'concurrency', 'breaking change',
|
|
23
|
+
'permission', 'privilege', 'escalation',
|
|
24
|
+
],
|
|
25
|
+
standard: [
|
|
26
|
+
'feature', 'enhancement', 'refactor', 'type-safety',
|
|
27
|
+
'integration', 'api', 'endpoint', 'validation',
|
|
28
|
+
'test', 'coverage', 'hook', 'pipeline', 'routing',
|
|
29
|
+
'module', 'performance', 'optimization',
|
|
30
|
+
],
|
|
31
|
+
fast: [
|
|
32
|
+
'typo', 'docs', 'documentation', 'label', 'rename',
|
|
33
|
+
'bump', 'chore', 'formatting', 'comment', 'readme',
|
|
34
|
+
'changelog', 'version', 'lint', 'whitespace',
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
/** Default model names per tier (overridable via env vars). */
|
|
38
|
+
export const MODEL_TIERS = {
|
|
39
|
+
fast: process.env.MODEL_FAST ?? 'claude-haiku-4-5',
|
|
40
|
+
standard: process.env.MODEL_STANDARD ?? 'claude-sonnet-4-6',
|
|
41
|
+
power: process.env.MODEL_POWER ?? 'claude-opus-4-6',
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Score a task 0–100 based on its metadata.
|
|
45
|
+
* Returns the score and a human-readable reasoning list.
|
|
46
|
+
*/
|
|
47
|
+
export function scoreTaskComplexity(title, labels, description) {
|
|
48
|
+
const reasoning = [];
|
|
49
|
+
let score = 35; // baseline: low-standard
|
|
50
|
+
const text = `${title} ${description}`.toLowerCase();
|
|
51
|
+
// Power keywords → raise score to at least power tier threshold
|
|
52
|
+
for (const kw of ROUTING_KEYWORDS.power) {
|
|
53
|
+
if (text.includes(kw)) {
|
|
54
|
+
score = Math.max(score, 75);
|
|
55
|
+
reasoning.push(`power keyword: "${kw}"`);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Fast keywords → lower score to at most fast tier threshold
|
|
60
|
+
for (const kw of ROUTING_KEYWORDS.fast) {
|
|
61
|
+
if (text.includes(kw)) {
|
|
62
|
+
score = Math.min(score, 20);
|
|
63
|
+
reasoning.push(`fast keyword: "${kw}"`);
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Standard keywords → minor boost (avoid staying at baseline)
|
|
68
|
+
if (reasoning.length === 0) {
|
|
69
|
+
for (const kw of ROUTING_KEYWORDS.standard) {
|
|
70
|
+
if (text.includes(kw)) {
|
|
71
|
+
score += 5;
|
|
72
|
+
reasoning.push(`standard keyword: "${kw}"`);
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Label overrides — applied after keyword signals
|
|
78
|
+
for (const label of labels) {
|
|
79
|
+
const l = label.toLowerCase();
|
|
80
|
+
if (l === 'security' || l === 'critical' || l === 'breaking-change') {
|
|
81
|
+
score = Math.max(score, 80);
|
|
82
|
+
reasoning.push(`label override: "${l}" → power tier`);
|
|
83
|
+
}
|
|
84
|
+
else if (l === 'docs' || l === 'documentation' || l === 'chore') {
|
|
85
|
+
score = Math.min(score, 20);
|
|
86
|
+
reasoning.push(`label override: "${l}" → fast tier`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Priority labels
|
|
90
|
+
for (const label of labels) {
|
|
91
|
+
if (label === 'P0' || label === 'P1') {
|
|
92
|
+
score = Math.max(score, 72);
|
|
93
|
+
reasoning.push(`priority label: "${label}" → elevate to power`);
|
|
94
|
+
}
|
|
95
|
+
else if (label === 'P3') {
|
|
96
|
+
score = Math.min(score, 55);
|
|
97
|
+
reasoning.push(`priority label: "P3" → cap at standard`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (reasoning.length === 0)
|
|
101
|
+
reasoning.push('baseline score — no keyword or label signals');
|
|
102
|
+
return { score: Math.max(0, Math.min(100, score)), reasoning };
|
|
103
|
+
}
|
|
104
|
+
/** Map a 0–100 score to a model tier. */
|
|
105
|
+
export function scoreToTier(score) {
|
|
106
|
+
if (score <= 30)
|
|
107
|
+
return 'fast';
|
|
108
|
+
if (score <= 70)
|
|
109
|
+
return 'standard';
|
|
110
|
+
return 'power';
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Route a task to the optimal model tier and concrete model name.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* routeTask({ title: 'fix typo in README', labels: ['docs'] })
|
|
117
|
+
* // → { tier: 'fast', model: 'claude-haiku-4-5', score: 15, reasoning: [...] }
|
|
118
|
+
*/
|
|
119
|
+
export function routeTask(opts) {
|
|
120
|
+
const { title, labels = [], description = '' } = opts;
|
|
121
|
+
const { score, reasoning } = scoreTaskComplexity(title, labels, description);
|
|
122
|
+
const tier = scoreToTier(score);
|
|
123
|
+
const model = MODEL_TIERS[tier];
|
|
124
|
+
return { tier, model, score, reasoning };
|
|
125
|
+
}
|
|
126
|
+
/** Zod schema for POST /v1/dev/route-task request body. */
|
|
127
|
+
const routeTaskSchema = z.object({
|
|
128
|
+
title: z.string().min(1).max(500),
|
|
129
|
+
labels: z.array(z.string().max(100)).max(50).optional(),
|
|
130
|
+
description: z.string().max(10_000).optional(),
|
|
131
|
+
});
|
|
132
|
+
/**
|
|
133
|
+
* Register the model-routing endpoint on the Fastify app.
|
|
134
|
+
*
|
|
135
|
+
* POST /v1/dev/route-task — score a task and return model recommendation.
|
|
136
|
+
* GET /v1/dev/model-tiers — return current model-tier configuration.
|
|
137
|
+
*/
|
|
138
|
+
export function registerModelRouterRoutes(app) {
|
|
139
|
+
app.post('/v1/dev/route-task', async (req, reply) => {
|
|
140
|
+
const parsed = routeTaskSchema.safeParse(req.body ?? {});
|
|
141
|
+
if (!parsed.success) {
|
|
142
|
+
return reply.status(400).send({ error: 'Invalid body', details: parsed.error.issues });
|
|
143
|
+
}
|
|
144
|
+
const { title, labels, description } = parsed.data;
|
|
145
|
+
return routeTask({ title, labels, description });
|
|
146
|
+
});
|
|
147
|
+
app.get('/v1/dev/model-tiers', async () => {
|
|
148
|
+
return { tiers: MODEL_TIERS };
|
|
149
|
+
});
|
|
150
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* monitor.ts — Background monitor that polls sessions and routes events to channels.
|
|
3
|
+
*
|
|
4
|
+
* Runs a polling loop that:
|
|
5
|
+
* 1. Checks each active session for new JSONL entries
|
|
6
|
+
* 2. Detects status changes (working → idle, permission prompts, etc.)
|
|
7
|
+
* 3. Routes events to the ChannelManager (which fans out to Telegram, webhooks, etc.)
|
|
8
|
+
*/
|
|
9
|
+
import { type SessionManager } from './session.js';
|
|
10
|
+
import { type TmuxManager } from './tmux.js';
|
|
11
|
+
import { type ChannelManager } from './channels/index.js';
|
|
12
|
+
import { type SessionEventBus } from './events.js';
|
|
13
|
+
import { type JsonlWatcher } from './jsonl-watcher.js';
|
|
14
|
+
export interface MonitorConfig {
|
|
15
|
+
pollIntervalMs: number;
|
|
16
|
+
fastPollIntervalMs: number;
|
|
17
|
+
hookQuietMs: number;
|
|
18
|
+
stallThresholdMs: number;
|
|
19
|
+
stallCheckIntervalMs: number;
|
|
20
|
+
deadCheckIntervalMs: number;
|
|
21
|
+
permissionStallMs: number;
|
|
22
|
+
unknownStallMs: number;
|
|
23
|
+
permissionTimeoutMs: number;
|
|
24
|
+
}
|
|
25
|
+
export declare const DEFAULT_MONITOR_CONFIG: MonitorConfig;
|
|
26
|
+
export declare class SessionMonitor {
|
|
27
|
+
private sessions;
|
|
28
|
+
private channels;
|
|
29
|
+
private config;
|
|
30
|
+
private running;
|
|
31
|
+
private lastStatus;
|
|
32
|
+
private lastBytesSeen;
|
|
33
|
+
private stallNotified;
|
|
34
|
+
/** Issue #663: O(1) stall notification check. */
|
|
35
|
+
private stallHas;
|
|
36
|
+
/** Issue #663: O(1) stall notification add. */
|
|
37
|
+
private stallAdd;
|
|
38
|
+
/** Issue #663: O(1) stall notification delete. */
|
|
39
|
+
private stallDelete;
|
|
40
|
+
/** Issue #663: Delete all stall notifications for a session. */
|
|
41
|
+
private stallDeleteAll;
|
|
42
|
+
/** Issue #663: Delete specific stall types for a session. */
|
|
43
|
+
private stallDeleteTypes;
|
|
44
|
+
private lastStallCheck;
|
|
45
|
+
private lastDeadCheck;
|
|
46
|
+
private idleNotified;
|
|
47
|
+
private idleSince;
|
|
48
|
+
private processedStopSignals;
|
|
49
|
+
private static readonly MAX_PROCESSED_STOP_SIGNALS;
|
|
50
|
+
private stateSince;
|
|
51
|
+
private deadNotified;
|
|
52
|
+
private prevStatusForStall;
|
|
53
|
+
private rateLimitedSessions;
|
|
54
|
+
private tmuxWasDown;
|
|
55
|
+
private lastTmuxHealthCheck;
|
|
56
|
+
private static readonly TMUX_HEALTH_CHECK_INTERVAL_MS;
|
|
57
|
+
/** Issue #89 L4: Debounce status change broadcasts per session.
|
|
58
|
+
* If multiple status changes happen within 500ms, only emit the last one.
|
|
59
|
+
* Prevents rapid-fire notifications during state transitions. */
|
|
60
|
+
private statusChangeDebounce;
|
|
61
|
+
/** Issue #32: Optional SSE event bus for real-time streaming. */
|
|
62
|
+
private eventBus?;
|
|
63
|
+
/** Issue #84: fs.watch-based JSONL watcher for near-instant message detection. */
|
|
64
|
+
private jsonlWatcher?;
|
|
65
|
+
constructor(sessions: SessionManager, channels: ChannelManager, config?: MonitorConfig);
|
|
66
|
+
/** Issue #32: Set the event bus for SSE streaming. */
|
|
67
|
+
setEventBus(bus: SessionEventBus): void;
|
|
68
|
+
/** Issue #397: Set the TmuxManager reference for tmux health checks. */
|
|
69
|
+
private tmux?;
|
|
70
|
+
setTmuxManager(tmuxManager: TmuxManager): void;
|
|
71
|
+
/** Issue #84: Set the JSONL watcher for fs.watch-based message detection. */
|
|
72
|
+
setJsonlWatcher(watcher: JsonlWatcher): void;
|
|
73
|
+
start(): void;
|
|
74
|
+
stop(): void;
|
|
75
|
+
private loop;
|
|
76
|
+
/** Check if any active session hasn't received a hook recently. */
|
|
77
|
+
private needsFastPolling;
|
|
78
|
+
private poll;
|
|
79
|
+
/** Smart stall detection: multiple stall types with graduated thresholds.
|
|
80
|
+
*
|
|
81
|
+
* Detects 4 types of stalls:
|
|
82
|
+
* 1. JSONL stall: "working" but no new JSONL bytes for stallThresholdMs
|
|
83
|
+
* 2. Permission stall: permission_prompt/bash_approval for permissionStallMs
|
|
84
|
+
* 3. Unknown stall: unknown state for unknownStallMs (CC stuck in transition)
|
|
85
|
+
* 4. State duration stall: any non-idle state for 2x its threshold
|
|
86
|
+
*/
|
|
87
|
+
private checkForStalls;
|
|
88
|
+
/** Issue #15: Check for Stop/StopFailure signals written by hook.ts. */
|
|
89
|
+
private checkStopSignals;
|
|
90
|
+
/** Issue #84: Handle new entries from the fs.watch-based JSONL watcher.
|
|
91
|
+
* Forwards messages to channels and updates stall tracking. */
|
|
92
|
+
private handleWatcherEvent;
|
|
93
|
+
private checkSession;
|
|
94
|
+
private forwardMessage;
|
|
95
|
+
private broadcastStatusChange;
|
|
96
|
+
private makePayload;
|
|
97
|
+
/** Check for dead tmux windows and notify via channels. */
|
|
98
|
+
private checkDeadSessions;
|
|
99
|
+
/** Issue #397: Check tmux server health. Detect crashes and trigger reconciliation. */
|
|
100
|
+
private checkTmuxHealth;
|
|
101
|
+
/** Clean up tracking for a killed session. */
|
|
102
|
+
removeSession(sessionId: string): void;
|
|
103
|
+
}
|