codekin 0.1.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.
Potentially problematic release.
This version of codekin might be problematic. Click here for more details.
- package/README.md +83 -0
- package/bin/codekin.mjs +372 -0
- package/dist/assets/index-BrKgETi_.css +1 -0
- package/dist/assets/index-C8gwtjTl.js +105 -0
- package/dist/data/repos.json +33 -0
- package/dist/favicon.svg +15 -0
- package/dist/index.html +14 -0
- package/package.json +53 -0
- package/server/dist/auth-routes.d.ts +12 -0
- package/server/dist/auth-routes.js +29 -0
- package/server/dist/auth-routes.js.map +1 -0
- package/server/dist/claude-process.d.ts +103 -0
- package/server/dist/claude-process.js +524 -0
- package/server/dist/claude-process.js.map +1 -0
- package/server/dist/config.d.ts +27 -0
- package/server/dist/config.js +54 -0
- package/server/dist/config.js.map +1 -0
- package/server/dist/crypto-utils.d.ts +12 -0
- package/server/dist/crypto-utils.js +22 -0
- package/server/dist/crypto-utils.js.map +1 -0
- package/server/dist/session-archive.d.ts +53 -0
- package/server/dist/session-archive.js +160 -0
- package/server/dist/session-archive.js.map +1 -0
- package/server/dist/session-manager.d.ts +226 -0
- package/server/dist/session-manager.js +1476 -0
- package/server/dist/session-manager.js.map +1 -0
- package/server/dist/session-routes.d.ts +12 -0
- package/server/dist/session-routes.js +207 -0
- package/server/dist/session-routes.js.map +1 -0
- package/server/dist/stepflow-handler.d.ts +141 -0
- package/server/dist/stepflow-handler.js +445 -0
- package/server/dist/stepflow-handler.js.map +1 -0
- package/server/dist/stepflow-prompt.d.ts +29 -0
- package/server/dist/stepflow-prompt.js +119 -0
- package/server/dist/stepflow-prompt.js.map +1 -0
- package/server/dist/stepflow-types.d.ts +249 -0
- package/server/dist/stepflow-types.js +30 -0
- package/server/dist/stepflow-types.js.map +1 -0
- package/server/dist/types.d.ts +362 -0
- package/server/dist/types.js +9 -0
- package/server/dist/types.js.map +1 -0
- package/server/dist/upload-routes.d.ts +12 -0
- package/server/dist/upload-routes.js +217 -0
- package/server/dist/upload-routes.js.map +1 -0
- package/server/dist/webhook-config.d.ts +9 -0
- package/server/dist/webhook-config.js +55 -0
- package/server/dist/webhook-config.js.map +1 -0
- package/server/dist/webhook-dedup.d.ts +21 -0
- package/server/dist/webhook-dedup.js +122 -0
- package/server/dist/webhook-dedup.js.map +1 -0
- package/server/dist/webhook-github.d.ts +50 -0
- package/server/dist/webhook-github.js +175 -0
- package/server/dist/webhook-github.js.map +1 -0
- package/server/dist/webhook-handler.d.ts +69 -0
- package/server/dist/webhook-handler.js +368 -0
- package/server/dist/webhook-handler.js.map +1 -0
- package/server/dist/webhook-prompt.d.ts +5 -0
- package/server/dist/webhook-prompt.js +67 -0
- package/server/dist/webhook-prompt.js.map +1 -0
- package/server/dist/webhook-rate-limiter.d.ts +30 -0
- package/server/dist/webhook-rate-limiter.js +78 -0
- package/server/dist/webhook-rate-limiter.js.map +1 -0
- package/server/dist/webhook-routes.d.ts +16 -0
- package/server/dist/webhook-routes.js +58 -0
- package/server/dist/webhook-routes.js.map +1 -0
- package/server/dist/webhook-types.d.ts +98 -0
- package/server/dist/webhook-types.js +2 -0
- package/server/dist/webhook-types.js.map +1 -0
- package/server/dist/webhook-workspace.d.ts +11 -0
- package/server/dist/webhook-workspace.js +124 -0
- package/server/dist/webhook-workspace.js.map +1 -0
- package/server/dist/workflow-config.d.ts +24 -0
- package/server/dist/workflow-config.js +66 -0
- package/server/dist/workflow-config.js.map +1 -0
- package/server/dist/workflow-engine.d.ts +130 -0
- package/server/dist/workflow-engine.js +529 -0
- package/server/dist/workflow-engine.js.map +1 -0
- package/server/dist/workflow-loader.d.ts +31 -0
- package/server/dist/workflow-loader.js +297 -0
- package/server/dist/workflow-loader.js.map +1 -0
- package/server/dist/workflow-routes.d.ts +14 -0
- package/server/dist/workflow-routes.js +222 -0
- package/server/dist/workflow-routes.js.map +1 -0
- package/server/dist/ws-server.d.ts +14 -0
- package/server/dist/ws-server.js +441 -0
- package/server/dist/ws-server.js.map +1 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main entry point for the Codekin WebSocket server.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - WebSocket server for real-time browser↔session communication
|
|
6
|
+
* - REST API for session CRUD, health checks, tool approval, and hook endpoints
|
|
7
|
+
* - File upload, repo listing, and clone endpoints (merged from upload-server)
|
|
8
|
+
* - GitHub webhook endpoint for automated CI/CD event handling
|
|
9
|
+
* - Stepflow webhook endpoint for workflow-orchestrated Claude sessions
|
|
10
|
+
* - Token-based authentication (via AUTH_TOKEN env var or --auth-file)
|
|
11
|
+
*
|
|
12
|
+
* Single-process server on PORT (default 32352), behind nginx reverse proxy at /cc.
|
|
13
|
+
*/
|
|
14
|
+
import express from 'express';
|
|
15
|
+
import { createServer } from 'http';
|
|
16
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
17
|
+
import { readFileSync, existsSync } from 'fs';
|
|
18
|
+
import { join } from 'path';
|
|
19
|
+
import { execSync } from 'child_process';
|
|
20
|
+
import { randomUUID } from 'crypto';
|
|
21
|
+
import { SessionManager } from './session-manager.js';
|
|
22
|
+
import { loadWebhookConfig } from './webhook-config.js';
|
|
23
|
+
import { WebhookHandler } from './webhook-handler.js';
|
|
24
|
+
import { createWebhookRateLimiter } from './webhook-rate-limiter.js';
|
|
25
|
+
import { StepflowHandler, loadStepflowConfig } from './stepflow-handler.js';
|
|
26
|
+
import { initWorkflowEngine, shutdownWorkflowEngine } from './workflow-engine.js';
|
|
27
|
+
import { loadMdWorkflows } from './workflow-loader.js';
|
|
28
|
+
import { createWorkflowRouter, syncSchedules } from './workflow-routes.js';
|
|
29
|
+
import { createAuthRouter } from './auth-routes.js';
|
|
30
|
+
import { createSessionRouter } from './session-routes.js';
|
|
31
|
+
import { createWebhookRouter } from './webhook-routes.js';
|
|
32
|
+
import { createUploadRouter } from './upload-routes.js';
|
|
33
|
+
import { PORT as CONFIG_PORT, AUTH_TOKEN as configAuthToken, CORS_ORIGIN, FRONTEND_DIST } from './config.js';
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// CLI args (legacy bare-metal compat) and auth setup
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
const args = process.argv.slice(2);
|
|
38
|
+
let port = CONFIG_PORT;
|
|
39
|
+
let authToken = configAuthToken;
|
|
40
|
+
for (let i = 0; i < args.length; i++) {
|
|
41
|
+
if (args[i] === '--port' && args[i + 1])
|
|
42
|
+
port = parseInt(args[i + 1], 10);
|
|
43
|
+
if (args[i] === '--auth-file' && args[i + 1]) {
|
|
44
|
+
const authFile = args[i + 1];
|
|
45
|
+
if (existsSync(authFile)) {
|
|
46
|
+
authToken = readFileSync(authFile, 'utf-8').trim();
|
|
47
|
+
console.log(`Auth token loaded from ${authFile}`);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.error(`Auth file not found: ${authFile}`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (authToken) {
|
|
56
|
+
console.log('Auth token configured');
|
|
57
|
+
}
|
|
58
|
+
/** Check if a token matches the configured auth token (passes if no auth configured). */
|
|
59
|
+
function verifyToken(token) {
|
|
60
|
+
if (!authToken)
|
|
61
|
+
return true; // No auth configured
|
|
62
|
+
return token === authToken;
|
|
63
|
+
}
|
|
64
|
+
/** Extract auth token from query string, Authorization header, or request body. */
|
|
65
|
+
function extractToken(req) {
|
|
66
|
+
const qToken = req.query.token;
|
|
67
|
+
if (qToken)
|
|
68
|
+
return qToken;
|
|
69
|
+
// Check Authorization header
|
|
70
|
+
const authHeader = req.headers.authorization;
|
|
71
|
+
if (authHeader?.startsWith('Bearer ')) {
|
|
72
|
+
return authHeader.slice(7);
|
|
73
|
+
}
|
|
74
|
+
// Check body
|
|
75
|
+
if (req.body?.token)
|
|
76
|
+
return req.body.token;
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Startup checks
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
let claudeAvailable = false;
|
|
83
|
+
let claudeVersion = '';
|
|
84
|
+
const apiKeySet = !!(process.env.ANTHROPIC_API_KEY || process.env.CLAUDE_CODE_API_KEY);
|
|
85
|
+
try {
|
|
86
|
+
claudeVersion = execSync('claude --version', { timeout: 5000 }).toString().trim();
|
|
87
|
+
claudeAvailable = true;
|
|
88
|
+
console.log(`Claude CLI found: ${claudeVersion}`);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
console.warn('Claude CLI not found or not working');
|
|
92
|
+
}
|
|
93
|
+
if (!apiKeySet) {
|
|
94
|
+
console.warn('No API key configured (ANTHROPIC_API_KEY or CLAUDE_CODE_API_KEY)');
|
|
95
|
+
}
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Core services
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
const sessions = new SessionManager();
|
|
100
|
+
sessions._serverPort = port;
|
|
101
|
+
sessions._authToken = authToken;
|
|
102
|
+
// GitHub webhook handler
|
|
103
|
+
const webhookConfig = loadWebhookConfig();
|
|
104
|
+
const webhookHandler = new WebhookHandler(webhookConfig, sessions);
|
|
105
|
+
// Run gh health check asynchronously at startup
|
|
106
|
+
if (webhookConfig.enabled) {
|
|
107
|
+
if (!webhookConfig.secret) {
|
|
108
|
+
console.warn('[webhook] GITHUB_WEBHOOK_SECRET not set — webhook signature validation will fail');
|
|
109
|
+
}
|
|
110
|
+
webhookHandler.checkHealth().then(healthy => {
|
|
111
|
+
if (healthy) {
|
|
112
|
+
console.log('[webhook] Webhook processing enabled');
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.log('[webhook] Webhook processing disabled (GITHUB_WEBHOOK_ENABLED != true)');
|
|
118
|
+
}
|
|
119
|
+
// Stepflow webhook handler
|
|
120
|
+
// Receives claude.session.requested events from Stepflow WebhookEventTransport.
|
|
121
|
+
// See stepflow-handler.ts and stepflow-types.ts for integration details.
|
|
122
|
+
const stepflowConfig = loadStepflowConfig();
|
|
123
|
+
const stepflowHandler = new StepflowHandler(stepflowConfig, sessions);
|
|
124
|
+
if (stepflowConfig.enabled) {
|
|
125
|
+
if (!stepflowConfig.secret) {
|
|
126
|
+
console.warn('[stepflow] STEPFLOW_WEBHOOK_SECRET not set — signature validation will fail');
|
|
127
|
+
}
|
|
128
|
+
console.log('[stepflow] Stepflow webhook integration enabled');
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.log('[stepflow] Stepflow webhook integration disabled (STEPFLOW_WEBHOOK_ENABLED != true)');
|
|
132
|
+
}
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Express app and REST API
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
const app = express();
|
|
137
|
+
// In Docker / standalone mode (FRONTEND_DIST set), the server is reached directly without nginx.
|
|
138
|
+
// nginx normally strips the /cc prefix before proxying; we replicate that here so the frontend
|
|
139
|
+
// (which hardcodes BASE = '/cc') works against the Node server without modification.
|
|
140
|
+
if (FRONTEND_DIST && existsSync(FRONTEND_DIST)) {
|
|
141
|
+
app.use((req, _res, next) => {
|
|
142
|
+
if (req.url.startsWith('/cc/'))
|
|
143
|
+
req.url = req.url.slice(3);
|
|
144
|
+
else if (req.url === '/cc')
|
|
145
|
+
req.url = '/';
|
|
146
|
+
next();
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
// Both webhook endpoints use raw body for HMAC verification — register BEFORE express.json().
|
|
150
|
+
// express.raw() must run before any rate limiter so req.body is a Buffer.
|
|
151
|
+
const githubRateLimiter = createWebhookRateLimiter();
|
|
152
|
+
app.post('/api/webhooks/github', express.raw({ type: 'application/json', limit: '5mb' }), githubRateLimiter, async (req, res) => {
|
|
153
|
+
const rawBody = req.body;
|
|
154
|
+
if (!Buffer.isBuffer(rawBody) || rawBody.length === 0) {
|
|
155
|
+
return res.status(400).json({ error: 'Empty or non-JSON body' });
|
|
156
|
+
}
|
|
157
|
+
const result = await webhookHandler.handleWebhook(rawBody, {
|
|
158
|
+
event: req.headers['x-github-event'] || '',
|
|
159
|
+
delivery: req.headers['x-github-delivery'] || '',
|
|
160
|
+
signature: req.headers['x-hub-signature-256'] || '',
|
|
161
|
+
});
|
|
162
|
+
res.status(result.statusCode).json(result.body);
|
|
163
|
+
});
|
|
164
|
+
// Stepflow webhook endpoint.
|
|
165
|
+
// Stepflow signs with X-Webhook-Signature (HMAC-SHA256, format: sha256=<hex>).
|
|
166
|
+
// Rate-limited per workflow kind; no gh CLI health check needed.
|
|
167
|
+
const stepflowRateLimiter = createWebhookRateLimiter(30, (body) => body?.event?.kind);
|
|
168
|
+
app.post('/api/webhooks/stepflow', express.raw({ type: 'application/json', limit: '1mb' }), stepflowRateLimiter, async (req, res) => {
|
|
169
|
+
const rawBody = req.body;
|
|
170
|
+
if (!Buffer.isBuffer(rawBody) || rawBody.length === 0) {
|
|
171
|
+
return res.status(400).json({ error: 'Empty or non-JSON body' });
|
|
172
|
+
}
|
|
173
|
+
const signature = req.headers['x-webhook-signature'] || '';
|
|
174
|
+
const result = await stepflowHandler.handleWebhook(rawBody, signature);
|
|
175
|
+
res.status(result.statusCode).json(result.body);
|
|
176
|
+
});
|
|
177
|
+
// JSON body parser for all other routes
|
|
178
|
+
app.use(express.json());
|
|
179
|
+
// CORS — restrict to configured origin (default: allow all for local dev)
|
|
180
|
+
app.use((_req, res, next) => {
|
|
181
|
+
res.header('Access-Control-Allow-Origin', CORS_ORIGIN);
|
|
182
|
+
res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
183
|
+
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
184
|
+
if (_req.method === 'OPTIONS')
|
|
185
|
+
return res.sendStatus(204);
|
|
186
|
+
next();
|
|
187
|
+
});
|
|
188
|
+
// --- Serve frontend static files (Docker / standalone mode) ---
|
|
189
|
+
if (FRONTEND_DIST && existsSync(FRONTEND_DIST)) {
|
|
190
|
+
app.use(express.static(FRONTEND_DIST));
|
|
191
|
+
console.log(`Serving frontend from ${FRONTEND_DIST}`);
|
|
192
|
+
}
|
|
193
|
+
// --- REST API routes (delegated to dedicated routers) ---
|
|
194
|
+
app.use(createAuthRouter(verifyToken, extractToken, sessions, claudeAvailable, claudeVersion, apiKeySet));
|
|
195
|
+
app.use(createSessionRouter(verifyToken, extractToken, sessions));
|
|
196
|
+
app.use(createWebhookRouter(verifyToken, extractToken, webhookHandler, stepflowHandler));
|
|
197
|
+
app.use(createUploadRouter(verifyToken, extractToken));
|
|
198
|
+
app.use('/api/workflows', createWorkflowRouter(verifyToken, extractToken));
|
|
199
|
+
// --- SPA fallback: serve index.html for non-API routes (client-side routing) ---
|
|
200
|
+
if (FRONTEND_DIST && existsSync(FRONTEND_DIST)) {
|
|
201
|
+
const indexPath = join(FRONTEND_DIST, 'index.html');
|
|
202
|
+
if (existsSync(indexPath)) {
|
|
203
|
+
app.get('*', (req, res) => {
|
|
204
|
+
if (req.path.startsWith('/api/')) {
|
|
205
|
+
res.status(404).json({ error: 'Not found' });
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
res.sendFile(indexPath);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// ---------------------------------------------------------------------------
|
|
213
|
+
// WebSocket server
|
|
214
|
+
// ---------------------------------------------------------------------------
|
|
215
|
+
const server = createServer(app);
|
|
216
|
+
const wss = new WebSocketServer({ server });
|
|
217
|
+
// Wire up global broadcast so session manager can notify ALL connected clients
|
|
218
|
+
// (e.g. when a webhook creates a new session that all UIs should show)
|
|
219
|
+
sessions._globalBroadcast = (msg) => {
|
|
220
|
+
const data = JSON.stringify(msg);
|
|
221
|
+
for (const ws of wss.clients) {
|
|
222
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
223
|
+
ws.send(data);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
/** Maps each WebSocket connection to its current session ID. */
|
|
228
|
+
const clientSessions = new Map();
|
|
229
|
+
wss.on('connection', (ws, req) => {
|
|
230
|
+
// Authenticate
|
|
231
|
+
const url = new URL(req.url || '/', `http://${req.headers.host}`);
|
|
232
|
+
const token = url.searchParams.get('token') || undefined;
|
|
233
|
+
if (!verifyToken(token)) {
|
|
234
|
+
ws.close(4001, 'Unauthorized');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const connectionId = randomUUID();
|
|
238
|
+
const send = (msg) => {
|
|
239
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
240
|
+
ws.send(JSON.stringify(msg));
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
send({ type: 'connected', connectionId, claudeAvailable, claudeVersion, apiKeySet });
|
|
244
|
+
ws.on('message', (raw) => {
|
|
245
|
+
let msg;
|
|
246
|
+
try {
|
|
247
|
+
msg = JSON.parse(raw.toString());
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
switch (msg.type) {
|
|
253
|
+
case 'create_session': {
|
|
254
|
+
const session = sessions.create(msg.name, msg.workingDir, { model: msg.model });
|
|
255
|
+
session.clients.add(ws);
|
|
256
|
+
clientSessions.set(ws, session.id);
|
|
257
|
+
send({
|
|
258
|
+
type: 'session_created',
|
|
259
|
+
sessionId: session.id,
|
|
260
|
+
sessionName: session.name,
|
|
261
|
+
workingDir: session.workingDir,
|
|
262
|
+
});
|
|
263
|
+
// Auto-start Claude immediately
|
|
264
|
+
sessions.startClaude(session.id);
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
case 'join_session': {
|
|
268
|
+
// Leave current session first
|
|
269
|
+
const currentId = clientSessions.get(ws);
|
|
270
|
+
if (currentId) {
|
|
271
|
+
sessions.leave(currentId, ws);
|
|
272
|
+
}
|
|
273
|
+
const session = sessions.join(msg.sessionId, ws);
|
|
274
|
+
if (session) {
|
|
275
|
+
clientSessions.set(ws, session.id);
|
|
276
|
+
send({
|
|
277
|
+
type: 'session_joined',
|
|
278
|
+
sessionId: session.id,
|
|
279
|
+
sessionName: session.name,
|
|
280
|
+
workingDir: session.workingDir,
|
|
281
|
+
active: session.claudeProcess?.isAlive() ?? false,
|
|
282
|
+
outputBuffer: session.outputHistory.slice(-500),
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
send({ type: 'error', message: 'Session not found' });
|
|
287
|
+
}
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
case 'leave_session': {
|
|
291
|
+
const currentId = clientSessions.get(ws);
|
|
292
|
+
if (currentId) {
|
|
293
|
+
sessions.leave(currentId, ws);
|
|
294
|
+
clientSessions.delete(ws);
|
|
295
|
+
send({ type: 'session_left' });
|
|
296
|
+
}
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
case 'start_claude': {
|
|
300
|
+
const sessionId = clientSessions.get(ws);
|
|
301
|
+
if (sessionId) {
|
|
302
|
+
sessions.startClaude(sessionId);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
send({ type: 'error', message: 'Not in a session' });
|
|
306
|
+
}
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
case 'stop': {
|
|
310
|
+
const sessionId = clientSessions.get(ws);
|
|
311
|
+
if (sessionId) {
|
|
312
|
+
sessions.stopClaude(sessionId);
|
|
313
|
+
}
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
case 'input': {
|
|
317
|
+
const sessionId = clientSessions.get(ws);
|
|
318
|
+
if (sessionId) {
|
|
319
|
+
const session = sessions.get(sessionId);
|
|
320
|
+
if (session) {
|
|
321
|
+
const displayText = typeof msg.displayText === 'string' ? msg.displayText : undefined;
|
|
322
|
+
const echoMsg = { type: 'user_echo', text: displayText || msg.data };
|
|
323
|
+
sessions.addToHistory(session, echoMsg);
|
|
324
|
+
sessions.broadcast(session, echoMsg);
|
|
325
|
+
}
|
|
326
|
+
sessions.sendInput(sessionId, msg.data);
|
|
327
|
+
}
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
case 'prompt_response': {
|
|
331
|
+
const sessionId = clientSessions.get(ws);
|
|
332
|
+
console.log(`[prompt_response] sessionId=${sessionId} value=${JSON.stringify(msg.value)} requestId=${msg.requestId}`);
|
|
333
|
+
if (sessionId) {
|
|
334
|
+
sessions.sendPromptResponse(sessionId, msg.value, msg.requestId);
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
console.warn('[prompt_response] no session found for client');
|
|
338
|
+
}
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
case 'set_model': {
|
|
342
|
+
const sessionId = clientSessions.get(ws);
|
|
343
|
+
if (sessionId) {
|
|
344
|
+
sessions.setModel(sessionId, msg.model);
|
|
345
|
+
}
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
case 'resize':
|
|
349
|
+
// stream-json mode doesn't use PTY, so resize is a no-op
|
|
350
|
+
break;
|
|
351
|
+
case 'ping':
|
|
352
|
+
send({ type: 'pong' });
|
|
353
|
+
break;
|
|
354
|
+
case 'get_usage':
|
|
355
|
+
// TODO: track usage
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
ws.on('close', () => {
|
|
360
|
+
const sessionId = clientSessions.get(ws);
|
|
361
|
+
if (sessionId) {
|
|
362
|
+
sessions.leave(sessionId, ws);
|
|
363
|
+
}
|
|
364
|
+
clientSessions.delete(ws);
|
|
365
|
+
});
|
|
366
|
+
ws.on('error', (err) => {
|
|
367
|
+
console.error('[ws error]', err.message);
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
// Heartbeat pings to detect dead connections (30s interval)
|
|
371
|
+
const heartbeat = setInterval(() => {
|
|
372
|
+
wss.clients.forEach((ws) => {
|
|
373
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
374
|
+
ws.ping();
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
}, 30000);
|
|
378
|
+
wss.on('close', () => clearInterval(heartbeat));
|
|
379
|
+
// ---------------------------------------------------------------------------
|
|
380
|
+
// Start server and handle graceful shutdown
|
|
381
|
+
// ---------------------------------------------------------------------------
|
|
382
|
+
server.listen(port, '0.0.0.0', () => {
|
|
383
|
+
console.log(`Codekin WebSocket server listening on port ${port}`);
|
|
384
|
+
// Auto-restart sessions that were active before the server went down
|
|
385
|
+
sessions.restoreActiveSessions();
|
|
386
|
+
// Initialize workflow engine
|
|
387
|
+
try {
|
|
388
|
+
const engine = initWorkflowEngine();
|
|
389
|
+
loadMdWorkflows(engine, sessions);
|
|
390
|
+
engine.resumeInterrupted().catch(err => {
|
|
391
|
+
console.error('[workflow] Failed to resume interrupted runs:', err);
|
|
392
|
+
});
|
|
393
|
+
// Broadcast workflow events to all WebSocket clients
|
|
394
|
+
engine.on('workflow_event', (event) => {
|
|
395
|
+
const msg = {
|
|
396
|
+
type: 'workflow_event',
|
|
397
|
+
eventType: event.eventType,
|
|
398
|
+
runId: event.runId,
|
|
399
|
+
kind: event.kind,
|
|
400
|
+
stepKey: event.stepKey,
|
|
401
|
+
status: event.status,
|
|
402
|
+
};
|
|
403
|
+
const data = JSON.stringify(msg);
|
|
404
|
+
for (const ws of wss.clients) {
|
|
405
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
406
|
+
ws.send(data);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
// Sync cron schedules with config and start scheduler
|
|
411
|
+
syncSchedules();
|
|
412
|
+
engine.startCronScheduler();
|
|
413
|
+
console.log('[workflow] Workflow engine ready');
|
|
414
|
+
}
|
|
415
|
+
catch (err) {
|
|
416
|
+
console.error('[workflow] Failed to initialize workflow engine:', err);
|
|
417
|
+
console.warn('[workflow] Server will continue without workflow support');
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
// Graceful shutdown
|
|
421
|
+
process.on('SIGTERM', () => {
|
|
422
|
+
console.log('SIGTERM received, shutting down...');
|
|
423
|
+
shutdownWorkflowEngine();
|
|
424
|
+
webhookHandler.shutdown();
|
|
425
|
+
stepflowHandler.shutdown();
|
|
426
|
+
sessions.shutdown();
|
|
427
|
+
wss.close();
|
|
428
|
+
server.close();
|
|
429
|
+
process.exit(0);
|
|
430
|
+
});
|
|
431
|
+
process.on('SIGINT', () => {
|
|
432
|
+
console.log('SIGINT received, shutting down...');
|
|
433
|
+
shutdownWorkflowEngine();
|
|
434
|
+
webhookHandler.shutdown();
|
|
435
|
+
stepflowHandler.shutdown();
|
|
436
|
+
sessions.shutdown();
|
|
437
|
+
wss.close();
|
|
438
|
+
server.close();
|
|
439
|
+
process.exit(0);
|
|
440
|
+
});
|
|
441
|
+
//# sourceMappingURL=ws-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-server.js","sourceRoot":"","sources":["../ws-server.ts"],"names":[],"mappings":"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"}
|