kanbaii 0.1.2 → 0.2.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/dashboard/404.html +1 -1
- package/dashboard/_next/static/chunks/23-74779bf2fc2560e3.js +1 -0
- package/dashboard/_next/static/chunks/app/layout-c4919caf1b2a656c.js +1 -0
- package/dashboard/_next/static/chunks/app/page-0cbaeeff2545315a.js +1 -0
- package/dashboard/_next/static/css/7669ae094c660f9a.css +1 -0
- package/dashboard/index.html +1 -1
- package/dashboard/index.txt +3 -3
- package/dist/cli/banner.d.ts +0 -1
- package/dist/cli/banner.js +0 -1
- package/dist/cli/doctor.d.ts +0 -1
- package/dist/cli/doctor.js +0 -1
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +0 -1
- package/dist/server/engines/claudeRunner.d.ts +0 -1
- package/dist/server/engines/claudeRunner.js +9 -3
- package/dist/server/engines/coordinator.d.ts +0 -1
- package/dist/server/engines/coordinator.js +0 -1
- package/dist/server/engines/coordinatorPrompt.d.ts +0 -1
- package/dist/server/engines/coordinatorPrompt.js +2 -2
- package/dist/server/engines/dependencyResolver.d.ts +0 -1
- package/dist/server/engines/dependencyResolver.js +0 -1
- package/dist/server/engines/planner.d.ts +0 -1
- package/dist/server/engines/planner.js +0 -1
- package/dist/server/engines/plannerStore.d.ts +0 -1
- package/dist/server/engines/plannerStore.js +0 -1
- package/dist/server/engines/ralph.d.ts +0 -1
- package/dist/server/engines/ralph.js +0 -1
- package/dist/server/engines/runStore.d.ts +0 -1
- package/dist/server/engines/runStore.js +0 -1
- package/dist/server/engines/taskRouter.d.ts +0 -1
- package/dist/server/engines/taskRouter.js +3 -3
- package/dist/server/engines/teams.d.ts +0 -1
- package/dist/server/engines/teams.js +0 -1
- package/dist/server/engines/workerPool.d.ts +0 -1
- package/dist/server/engines/workerPool.js +16 -1
- package/dist/server/index.d.ts +0 -1
- package/dist/server/index.js +72 -8
- package/dist/server/lib/authMiddleware.d.ts +0 -1
- package/dist/server/lib/authMiddleware.js +0 -1
- package/dist/server/lib/fileWatcher.d.ts +0 -1
- package/dist/server/lib/fileWatcher.js +0 -1
- package/dist/server/lib/generateId.d.ts +0 -1
- package/dist/server/lib/generateId.js +0 -1
- package/dist/server/lib/promptSanitizer.d.ts +5 -0
- package/dist/server/lib/promptSanitizer.js +23 -0
- package/dist/server/lib/rateLimiter.d.ts +4 -0
- package/dist/server/lib/rateLimiter.js +33 -0
- package/dist/server/lib/requestLogger.d.ts +2 -0
- package/dist/server/lib/requestLogger.js +23 -0
- package/dist/server/lib/safePath.d.ts +5 -0
- package/dist/server/lib/safePath.js +24 -0
- package/dist/server/lib/schemas.d.ts +0 -1
- package/dist/server/lib/schemas.js +0 -1
- package/dist/server/lib/secretsEncryption.d.ts +3 -0
- package/dist/server/lib/secretsEncryption.js +38 -0
- package/dist/server/lib/typedEmit.d.ts +0 -1
- package/dist/server/lib/typedEmit.js +0 -1
- package/dist/server/routes/agents.d.ts +0 -1
- package/dist/server/routes/agents.js +0 -1
- package/dist/server/routes/auth.d.ts +0 -1
- package/dist/server/routes/auth.js +0 -1
- package/dist/server/routes/costs.d.ts +0 -1
- package/dist/server/routes/costs.js +0 -1
- package/dist/server/routes/escalation.d.ts +0 -1
- package/dist/server/routes/escalation.js +0 -1
- package/dist/server/routes/generate.d.ts +0 -1
- package/dist/server/routes/generate.js +1 -3
- package/dist/server/routes/mcp.d.ts +0 -1
- package/dist/server/routes/mcp.js +0 -1
- package/dist/server/routes/planner.d.ts +0 -1
- package/dist/server/routes/planner.js +0 -1
- package/dist/server/routes/plugins.d.ts +0 -1
- package/dist/server/routes/plugins.js +0 -1
- package/dist/server/routes/projects.d.ts +0 -1
- package/dist/server/routes/projects.js +0 -1
- package/dist/server/routes/ralph.d.ts +0 -1
- package/dist/server/routes/ralph.js +0 -1
- package/dist/server/routes/scheduler.d.ts +0 -1
- package/dist/server/routes/scheduler.js +0 -1
- package/dist/server/routes/settings.d.ts +0 -1
- package/dist/server/routes/settings.js +0 -1
- package/dist/server/routes/skills.d.ts +0 -1
- package/dist/server/routes/skills.js +0 -1
- package/dist/server/routes/soul.d.ts +0 -1
- package/dist/server/routes/soul.js +0 -1
- package/dist/server/routes/system.d.ts +0 -1
- package/dist/server/routes/system.js +15 -12
- package/dist/server/routes/tasks.d.ts +0 -1
- package/dist/server/routes/tasks.js +0 -1
- package/dist/server/routes/teams.d.ts +0 -1
- package/dist/server/routes/teams.js +0 -1
- package/dist/server/routes/terminal.d.ts +0 -1
- package/dist/server/routes/terminal.js +0 -1
- package/dist/server/routes/voice.d.ts +0 -1
- package/dist/server/routes/voice.js +0 -1
- package/dist/server/routes/workItems.d.ts +0 -1
- package/dist/server/routes/workItems.js +11 -1
- package/dist/server/services/agentRegistry.d.ts +0 -1
- package/dist/server/services/agentRegistry.js +0 -1
- package/dist/server/services/authService.d.ts +0 -1
- package/dist/server/services/authService.js +9 -2
- package/dist/server/services/claudeUsage.d.ts +0 -1
- package/dist/server/services/claudeUsage.js +32 -7
- package/dist/server/services/costTracker.d.ts +0 -1
- package/dist/server/services/costTracker.js +0 -1
- package/dist/server/services/escalationService.d.ts +0 -1
- package/dist/server/services/escalationService.js +5 -2
- package/dist/server/services/mcpConfig.d.ts +0 -1
- package/dist/server/services/mcpConfig.js +1 -2
- package/dist/server/services/pluginLoader.d.ts +0 -1
- package/dist/server/services/pluginLoader.js +19 -1
- package/dist/server/services/projectStore.d.ts +0 -1
- package/dist/server/services/projectStore.js +2 -2
- package/dist/server/services/schedulerService.d.ts +0 -1
- package/dist/server/services/schedulerService.js +0 -1
- package/dist/server/services/settingsService.d.ts +0 -1
- package/dist/server/services/settingsService.js +34 -3
- package/dist/server/services/skillsRegistry.d.ts +0 -1
- package/dist/server/services/skillsRegistry.js +0 -1
- package/dist/server/services/soulStore.d.ts +0 -1
- package/dist/server/services/soulStore.js +0 -1
- package/dist/server/services/telegramService.d.ts +0 -1
- package/dist/server/services/telegramService.js +0 -1
- package/dist/server/services/terminalManager.d.ts +0 -1
- package/dist/server/services/terminalManager.js +3 -2
- package/dist/server/services/workItemStore.d.ts +10 -4
- package/dist/server/services/workItemStore.js +57 -20
- package/dist/shared/types.d.ts +1 -1
- package/dist/shared/types.js +0 -1
- package/package.json +15 -4
- package/dashboard/_next/static/chunks/722-5d5f6d00bb07f427.js +0 -1
- package/dashboard/_next/static/chunks/app/layout-f76af5203e5cab0e.js +0 -1
- package/dashboard/_next/static/chunks/app/page-e5035f252913cddb.js +0 -1
- package/dashboard/_next/static/css/1a1fb46093561e14.css +0 -1
- package/dist/cli/banner.d.ts.map +0 -1
- package/dist/cli/banner.js.map +0 -1
- package/dist/cli/doctor.d.ts.map +0 -1
- package/dist/cli/doctor.js.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/server/__tests__/api.test.d.ts +0 -2
- package/dist/server/__tests__/api.test.d.ts.map +0 -1
- package/dist/server/__tests__/api.test.js +0 -279
- package/dist/server/__tests__/api.test.js.map +0 -1
- package/dist/server/__tests__/projectStore.test.d.ts +0 -2
- package/dist/server/__tests__/projectStore.test.d.ts.map +0 -1
- package/dist/server/__tests__/projectStore.test.js +0 -153
- package/dist/server/__tests__/projectStore.test.js.map +0 -1
- package/dist/server/__tests__/setup.d.ts +0 -2
- package/dist/server/__tests__/setup.d.ts.map +0 -1
- package/dist/server/__tests__/setup.js +0 -14
- package/dist/server/__tests__/setup.js.map +0 -1
- package/dist/server/__tests__/workItemStore.test.d.ts +0 -2
- package/dist/server/__tests__/workItemStore.test.d.ts.map +0 -1
- package/dist/server/__tests__/workItemStore.test.js +0 -323
- package/dist/server/__tests__/workItemStore.test.js.map +0 -1
- package/dist/server/engines/claudeRunner.d.ts.map +0 -1
- package/dist/server/engines/claudeRunner.js.map +0 -1
- package/dist/server/engines/coordinator.d.ts.map +0 -1
- package/dist/server/engines/coordinator.js.map +0 -1
- package/dist/server/engines/coordinatorPrompt.d.ts.map +0 -1
- package/dist/server/engines/coordinatorPrompt.js.map +0 -1
- package/dist/server/engines/dependencyResolver.d.ts.map +0 -1
- package/dist/server/engines/dependencyResolver.js.map +0 -1
- package/dist/server/engines/planner.d.ts.map +0 -1
- package/dist/server/engines/planner.js.map +0 -1
- package/dist/server/engines/plannerStore.d.ts.map +0 -1
- package/dist/server/engines/plannerStore.js.map +0 -1
- package/dist/server/engines/ralph.d.ts.map +0 -1
- package/dist/server/engines/ralph.js.map +0 -1
- package/dist/server/engines/runStore.d.ts.map +0 -1
- package/dist/server/engines/runStore.js.map +0 -1
- package/dist/server/engines/taskRouter.d.ts.map +0 -1
- package/dist/server/engines/taskRouter.js.map +0 -1
- package/dist/server/engines/teams.d.ts.map +0 -1
- package/dist/server/engines/teams.js.map +0 -1
- package/dist/server/engines/workerPool.d.ts.map +0 -1
- package/dist/server/engines/workerPool.js.map +0 -1
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js.map +0 -1
- package/dist/server/lib/authMiddleware.d.ts.map +0 -1
- package/dist/server/lib/authMiddleware.js.map +0 -1
- package/dist/server/lib/fileWatcher.d.ts.map +0 -1
- package/dist/server/lib/fileWatcher.js.map +0 -1
- package/dist/server/lib/generateId.d.ts.map +0 -1
- package/dist/server/lib/generateId.js.map +0 -1
- package/dist/server/lib/schemas.d.ts.map +0 -1
- package/dist/server/lib/schemas.js.map +0 -1
- package/dist/server/lib/typedEmit.d.ts.map +0 -1
- package/dist/server/lib/typedEmit.js.map +0 -1
- package/dist/server/routes/agents.d.ts.map +0 -1
- package/dist/server/routes/agents.js.map +0 -1
- package/dist/server/routes/auth.d.ts.map +0 -1
- package/dist/server/routes/auth.js.map +0 -1
- package/dist/server/routes/costs.d.ts.map +0 -1
- package/dist/server/routes/costs.js.map +0 -1
- package/dist/server/routes/escalation.d.ts.map +0 -1
- package/dist/server/routes/escalation.js.map +0 -1
- package/dist/server/routes/generate.d.ts.map +0 -1
- package/dist/server/routes/generate.js.map +0 -1
- package/dist/server/routes/mcp.d.ts.map +0 -1
- package/dist/server/routes/mcp.js.map +0 -1
- package/dist/server/routes/planner.d.ts.map +0 -1
- package/dist/server/routes/planner.js.map +0 -1
- package/dist/server/routes/plugins.d.ts.map +0 -1
- package/dist/server/routes/plugins.js.map +0 -1
- package/dist/server/routes/projects.d.ts.map +0 -1
- package/dist/server/routes/projects.js.map +0 -1
- package/dist/server/routes/ralph.d.ts.map +0 -1
- package/dist/server/routes/ralph.js.map +0 -1
- package/dist/server/routes/scheduler.d.ts.map +0 -1
- package/dist/server/routes/scheduler.js.map +0 -1
- package/dist/server/routes/settings.d.ts.map +0 -1
- package/dist/server/routes/settings.js.map +0 -1
- package/dist/server/routes/skills.d.ts.map +0 -1
- package/dist/server/routes/skills.js.map +0 -1
- package/dist/server/routes/soul.d.ts.map +0 -1
- package/dist/server/routes/soul.js.map +0 -1
- package/dist/server/routes/system.d.ts.map +0 -1
- package/dist/server/routes/system.js.map +0 -1
- package/dist/server/routes/tasks.d.ts.map +0 -1
- package/dist/server/routes/tasks.js.map +0 -1
- package/dist/server/routes/teams.d.ts.map +0 -1
- package/dist/server/routes/teams.js.map +0 -1
- package/dist/server/routes/terminal.d.ts.map +0 -1
- package/dist/server/routes/terminal.js.map +0 -1
- package/dist/server/routes/voice.d.ts.map +0 -1
- package/dist/server/routes/voice.js.map +0 -1
- package/dist/server/routes/workItems.d.ts.map +0 -1
- package/dist/server/routes/workItems.js.map +0 -1
- package/dist/server/services/agentRegistry.d.ts.map +0 -1
- package/dist/server/services/agentRegistry.js.map +0 -1
- package/dist/server/services/authService.d.ts.map +0 -1
- package/dist/server/services/authService.js.map +0 -1
- package/dist/server/services/claudeUsage.d.ts.map +0 -1
- package/dist/server/services/claudeUsage.js.map +0 -1
- package/dist/server/services/costTracker.d.ts.map +0 -1
- package/dist/server/services/costTracker.js.map +0 -1
- package/dist/server/services/escalationService.d.ts.map +0 -1
- package/dist/server/services/escalationService.js.map +0 -1
- package/dist/server/services/mcpConfig.d.ts.map +0 -1
- package/dist/server/services/mcpConfig.js.map +0 -1
- package/dist/server/services/pluginLoader.d.ts.map +0 -1
- package/dist/server/services/pluginLoader.js.map +0 -1
- package/dist/server/services/projectStore.d.ts.map +0 -1
- package/dist/server/services/projectStore.js.map +0 -1
- package/dist/server/services/schedulerService.d.ts.map +0 -1
- package/dist/server/services/schedulerService.js.map +0 -1
- package/dist/server/services/settingsService.d.ts.map +0 -1
- package/dist/server/services/settingsService.js.map +0 -1
- package/dist/server/services/skillsRegistry.d.ts.map +0 -1
- package/dist/server/services/skillsRegistry.js.map +0 -1
- package/dist/server/services/soulStore.d.ts.map +0 -1
- package/dist/server/services/soulStore.js.map +0 -1
- package/dist/server/services/telegramService.d.ts.map +0 -1
- package/dist/server/services/telegramService.js.map +0 -1
- package/dist/server/services/terminalManager.d.ts.map +0 -1
- package/dist/server/services/terminalManager.js.map +0 -1
- package/dist/server/services/workItemStore.d.ts.map +0 -1
- package/dist/server/services/workItemStore.js.map +0 -1
- package/dist/shared/types.d.ts.map +0 -1
- package/dist/shared/types.js.map +0 -1
- /package/dashboard/_next/static/{WZgWWvl5DWIMdBOLDHyIK → U_eLKLn69LJkGH6AtpAhH}/_buildManifest.js +0 -0
- /package/dashboard/_next/static/{WZgWWvl5DWIMdBOLDHyIK → U_eLKLn69LJkGH6AtpAhH}/_ssgManifest.js +0 -0
|
@@ -48,6 +48,8 @@ const projectStore = __importStar(require("../services/projectStore"));
|
|
|
48
48
|
const soulStore_1 = require("../services/soulStore");
|
|
49
49
|
const escalationService_1 = require("../services/escalationService");
|
|
50
50
|
const costTracker_1 = require("../services/costTracker");
|
|
51
|
+
const MAX_COMPLETED_RESULTS = 100;
|
|
52
|
+
const MAX_WORKER_AGE_MS = 30 * 60 * 1000; // 30 minutes
|
|
51
53
|
let _workers = new Map();
|
|
52
54
|
let _completedResults = [];
|
|
53
55
|
let _maxWorkers = 3;
|
|
@@ -230,6 +232,7 @@ async function assignTask(opts) {
|
|
|
230
232
|
totalFailed: _completedResults.filter(r => !r.success).length,
|
|
231
233
|
totalTasks: _completedResults.length,
|
|
232
234
|
});
|
|
235
|
+
cleanup();
|
|
233
236
|
})();
|
|
234
237
|
return { workerId };
|
|
235
238
|
}
|
|
@@ -241,4 +244,16 @@ function stopAllWorkers() {
|
|
|
241
244
|
catch { }
|
|
242
245
|
}
|
|
243
246
|
}
|
|
244
|
-
|
|
247
|
+
function cleanup() {
|
|
248
|
+
const now = Date.now();
|
|
249
|
+
for (const [id, { info }] of _workers) {
|
|
250
|
+
if (info.status !== 'running' && info.completedAt) {
|
|
251
|
+
const age = now - new Date(info.completedAt).getTime();
|
|
252
|
+
if (age > MAX_WORKER_AGE_MS)
|
|
253
|
+
_workers.delete(id);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (_completedResults.length > MAX_COMPLETED_RESULTS) {
|
|
257
|
+
_completedResults = _completedResults.slice(-MAX_COMPLETED_RESULTS);
|
|
258
|
+
}
|
|
259
|
+
}
|
package/dist/server/index.d.ts
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -68,6 +68,8 @@ const voice_1 = __importDefault(require("./routes/voice"));
|
|
|
68
68
|
const escalation_1 = __importDefault(require("./routes/escalation"));
|
|
69
69
|
const planner_1 = __importDefault(require("./routes/planner"));
|
|
70
70
|
const authMiddleware_1 = require("./lib/authMiddleware");
|
|
71
|
+
const requestLogger_1 = require("./lib/requestLogger");
|
|
72
|
+
const rateLimiter_1 = require("./lib/rateLimiter");
|
|
71
73
|
const claudeUsage_1 = require("./services/claudeUsage");
|
|
72
74
|
const schedulerService_1 = require("./services/schedulerService");
|
|
73
75
|
const PORT = parseInt(process.env.KANBAII_PORT || '5555', 10);
|
|
@@ -76,19 +78,43 @@ function createApp() {
|
|
|
76
78
|
const app = (0, express_1.default)();
|
|
77
79
|
const httpServer = (0, http_1.createServer)(app);
|
|
78
80
|
// Socket.IO
|
|
81
|
+
const allowedOrigins = [
|
|
82
|
+
'http://localhost:3000',
|
|
83
|
+
'http://localhost:5555',
|
|
84
|
+
`http://localhost:${PORT}`,
|
|
85
|
+
];
|
|
79
86
|
const io = new socket_io_1.Server(httpServer, {
|
|
80
|
-
cors: { origin:
|
|
87
|
+
cors: { origin: allowedOrigins, methods: ['GET', 'POST', 'PATCH', 'DELETE'] },
|
|
81
88
|
serveClient: false,
|
|
82
89
|
});
|
|
83
90
|
(0, typedEmit_1.setIO)(io);
|
|
84
91
|
// Middleware
|
|
85
|
-
app.use((0, cors_1.default)());
|
|
86
|
-
app.use(express_1.default.json());
|
|
92
|
+
app.use((0, cors_1.default)({ origin: allowedOrigins }));
|
|
93
|
+
app.use(express_1.default.json({ limit: '2mb' }));
|
|
94
|
+
app.use(requestLogger_1.requestLogger);
|
|
87
95
|
// Auth middleware (only enforces when enabled in settings)
|
|
88
96
|
app.use(authMiddleware_1.authMiddleware);
|
|
97
|
+
// Rate limiting
|
|
98
|
+
app.use('/api/', rateLimiter_1.apiLimiter);
|
|
99
|
+
app.use('/api/auth', rateLimiter_1.authLimiter);
|
|
100
|
+
app.use('/api/ralph/start', rateLimiter_1.executionLimiter);
|
|
101
|
+
app.use('/api/teams/start', rateLimiter_1.executionLimiter);
|
|
102
|
+
app.use('/api/voice', rateLimiter_1.voiceLimiter);
|
|
89
103
|
// Health
|
|
90
104
|
app.get('/api/health', (_req, res) => {
|
|
91
|
-
|
|
105
|
+
const mem = process.memoryUsage();
|
|
106
|
+
res.json({
|
|
107
|
+
ok: true,
|
|
108
|
+
version: require('../../package.json').version,
|
|
109
|
+
uptime: Math.floor(process.uptime()),
|
|
110
|
+
memory: {
|
|
111
|
+
heapUsedMB: Math.round(mem.heapUsed / 1024 / 1024),
|
|
112
|
+
heapTotalMB: Math.round(mem.heapTotal / 1024 / 1024),
|
|
113
|
+
rssMB: Math.round(mem.rss / 1024 / 1024),
|
|
114
|
+
},
|
|
115
|
+
node: process.version,
|
|
116
|
+
platform: process.platform,
|
|
117
|
+
});
|
|
92
118
|
});
|
|
93
119
|
// API Routes
|
|
94
120
|
app.use('/api/projects', projects_1.default);
|
|
@@ -111,6 +137,11 @@ function createApp() {
|
|
|
111
137
|
app.use('/api/voice', voice_1.default);
|
|
112
138
|
app.use('/api/escalation', escalation_1.default);
|
|
113
139
|
app.use('/api/planner', planner_1.default);
|
|
140
|
+
// Global error handler — catches unhandled errors in routes
|
|
141
|
+
app.use((err, _req, res, _next) => {
|
|
142
|
+
console.error('[server] Unhandled error:', err.message);
|
|
143
|
+
res.status(500).json({ ok: false, error: 'Internal server error' });
|
|
144
|
+
});
|
|
114
145
|
// Static frontend (production)
|
|
115
146
|
// Dashboard path: works in both dev (src/server/) and prod (dist/server/)
|
|
116
147
|
const dashboardDir = path_1.default.resolve(__dirname, '..', '..', 'dashboard');
|
|
@@ -176,20 +207,53 @@ function createApp() {
|
|
|
176
207
|
}
|
|
177
208
|
// Start server when run directly
|
|
178
209
|
if (require.main === module) {
|
|
179
|
-
const { httpServer, watcher } = createApp();
|
|
210
|
+
const { httpServer, io, watcher } = createApp();
|
|
180
211
|
watcher.start();
|
|
181
212
|
(0, claudeUsage_1.startPolling)(60000);
|
|
182
213
|
(0, schedulerService_1.startSchedulerLoop)();
|
|
183
214
|
httpServer.listen(PORT, () => {
|
|
184
215
|
console.log(`\n ⬡ KANBAII server running on http://localhost:${PORT}\n`);
|
|
185
216
|
});
|
|
186
|
-
// Graceful shutdown
|
|
217
|
+
// Graceful shutdown (guarded against multiple calls)
|
|
218
|
+
let _shuttingDown = false;
|
|
187
219
|
const shutdown = () => {
|
|
220
|
+
if (_shuttingDown) {
|
|
221
|
+
process.exit(1);
|
|
222
|
+
return;
|
|
223
|
+
} // Second Ctrl+C = force kill
|
|
224
|
+
_shuttingDown = true;
|
|
188
225
|
console.log('\n Shutting down...');
|
|
226
|
+
// Stop background services FIRST (prevents new work)
|
|
227
|
+
try {
|
|
228
|
+
require('./services/claudeUsage').stopPolling();
|
|
229
|
+
}
|
|
230
|
+
catch { }
|
|
231
|
+
try {
|
|
232
|
+
require('./services/schedulerService').stopSchedulerLoop();
|
|
233
|
+
}
|
|
234
|
+
catch { }
|
|
235
|
+
// Stop active executions
|
|
236
|
+
try {
|
|
237
|
+
require('./engines/coordinator').stopCoordinator();
|
|
238
|
+
}
|
|
239
|
+
catch { }
|
|
240
|
+
try {
|
|
241
|
+
require('./engines/workerPool').stopAllWorkers();
|
|
242
|
+
}
|
|
243
|
+
catch { }
|
|
244
|
+
try {
|
|
245
|
+
require('./engines/ralph').stopRalph();
|
|
246
|
+
}
|
|
247
|
+
catch { }
|
|
189
248
|
watcher.stop();
|
|
190
|
-
|
|
249
|
+
io.close();
|
|
250
|
+
httpServer.close(() => {
|
|
251
|
+
console.log(' Server closed.');
|
|
252
|
+
process.exit(0);
|
|
253
|
+
});
|
|
254
|
+
// Force exit after 3 seconds
|
|
255
|
+
setTimeout(() => { console.log(' Force exit.'); process.exit(1); }, 3000).unref();
|
|
191
256
|
};
|
|
192
257
|
process.on('SIGINT', shutdown);
|
|
193
258
|
process.on('SIGTERM', shutdown);
|
|
194
259
|
}
|
|
195
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sanitizeForPrompt = sanitizeForPrompt;
|
|
4
|
+
/**
|
|
5
|
+
* Sanitize user-controlled text before injecting into Claude prompts.
|
|
6
|
+
* Strips prompt injection patterns without altering normal text.
|
|
7
|
+
*/
|
|
8
|
+
function sanitizeForPrompt(text) {
|
|
9
|
+
if (!text || typeof text !== 'string')
|
|
10
|
+
return '';
|
|
11
|
+
let sanitized = text;
|
|
12
|
+
// Strip system/assistant role markers that could override prompt structure
|
|
13
|
+
sanitized = sanitized.replace(/^(system|assistant|human|user):/gim, '[role]:');
|
|
14
|
+
// Strip XML-like tags that Claude interprets specially
|
|
15
|
+
sanitized = sanitized.replace(/<\/?(?:system|instructions|context|prompt|tool_use|tool_result|thinking)[^>]*>/gi, '');
|
|
16
|
+
// Strip markdown heading overrides that look like injection
|
|
17
|
+
sanitized = sanitized.replace(/^#{1,3}\s*(system|instructions|role|override|ignore|forget)/gim, '[$1]');
|
|
18
|
+
// Limit length to prevent context flooding
|
|
19
|
+
if (sanitized.length > 10000) {
|
|
20
|
+
sanitized = sanitized.slice(0, 10000) + '\n[truncated]';
|
|
21
|
+
}
|
|
22
|
+
return sanitized;
|
|
23
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const apiLimiter: import("express-rate-limit").RateLimitRequestHandler;
|
|
2
|
+
export declare const authLimiter: import("express-rate-limit").RateLimitRequestHandler;
|
|
3
|
+
export declare const executionLimiter: import("express-rate-limit").RateLimitRequestHandler;
|
|
4
|
+
export declare const voiceLimiter: import("express-rate-limit").RateLimitRequestHandler;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.voiceLimiter = exports.executionLimiter = exports.authLimiter = exports.apiLimiter = void 0;
|
|
7
|
+
const express_rate_limit_1 = __importDefault(require("express-rate-limit"));
|
|
8
|
+
// General API: 100 requests per minute
|
|
9
|
+
exports.apiLimiter = (0, express_rate_limit_1.default)({
|
|
10
|
+
windowMs: 60 * 1000,
|
|
11
|
+
max: 100,
|
|
12
|
+
standardHeaders: true,
|
|
13
|
+
legacyHeaders: false,
|
|
14
|
+
message: { ok: false, error: 'Too many requests, try again later' },
|
|
15
|
+
});
|
|
16
|
+
// Auth endpoints: 10 attempts per 15 minutes
|
|
17
|
+
exports.authLimiter = (0, express_rate_limit_1.default)({
|
|
18
|
+
windowMs: 15 * 60 * 1000,
|
|
19
|
+
max: 10,
|
|
20
|
+
message: { ok: false, error: 'Too many login attempts' },
|
|
21
|
+
});
|
|
22
|
+
// Execution endpoints (ralph/teams/start): 5 per minute
|
|
23
|
+
exports.executionLimiter = (0, express_rate_limit_1.default)({
|
|
24
|
+
windowMs: 60 * 1000,
|
|
25
|
+
max: 5,
|
|
26
|
+
message: { ok: false, error: 'Too many execution requests' },
|
|
27
|
+
});
|
|
28
|
+
// Voice transcription: 10 per minute
|
|
29
|
+
exports.voiceLimiter = (0, express_rate_limit_1.default)({
|
|
30
|
+
windowMs: 60 * 1000,
|
|
31
|
+
max: 10,
|
|
32
|
+
message: { ok: false, error: 'Too many transcription requests' },
|
|
33
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.requestLogger = requestLogger;
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
function requestLogger(req, res, next) {
|
|
9
|
+
const id = crypto_1.default.randomBytes(4).toString('hex');
|
|
10
|
+
const start = Date.now();
|
|
11
|
+
req.requestId = id;
|
|
12
|
+
res.on('finish', () => {
|
|
13
|
+
const duration = Date.now() - start;
|
|
14
|
+
if (req.path.startsWith('/api/') && req.path !== '/api/health') {
|
|
15
|
+
const status = res.statusCode;
|
|
16
|
+
const level = status >= 500 ? 'ERROR' : status >= 400 ? 'WARN' : 'INFO';
|
|
17
|
+
if (level !== 'INFO' || duration > 1000) {
|
|
18
|
+
console.log(`[${level}] ${id} ${req.method} ${req.path} ${status} ${duration}ms`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
next();
|
|
23
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.safePath = safePath;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
/**
|
|
9
|
+
* Validate that a slug/filename doesn't escape the base directory.
|
|
10
|
+
* Throws if path traversal detected.
|
|
11
|
+
*/
|
|
12
|
+
function safePath(baseDir, ...segments) {
|
|
13
|
+
for (const seg of segments) {
|
|
14
|
+
if (typeof seg !== 'string' || seg.includes('..') || seg.includes('\0') || /[<>:"|?*]/.test(seg)) {
|
|
15
|
+
throw new Error(`Invalid path segment: ${seg}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const resolved = path_1.default.resolve(baseDir, ...segments);
|
|
19
|
+
const normalizedBase = path_1.default.resolve(baseDir);
|
|
20
|
+
if (!resolved.startsWith(normalizedBase + path_1.default.sep) && resolved !== normalizedBase) {
|
|
21
|
+
throw new Error(`Path escapes base directory`);
|
|
22
|
+
}
|
|
23
|
+
return resolved;
|
|
24
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.encrypt = encrypt;
|
|
7
|
+
exports.decrypt = decrypt;
|
|
8
|
+
exports.isEncrypted = isEncrypted;
|
|
9
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
11
|
+
const ALGORITHM = 'aes-256-gcm';
|
|
12
|
+
function deriveKey() {
|
|
13
|
+
const material = [os_1.default.hostname(), os_1.default.homedir(), 'kanbaii-v1'].join(':');
|
|
14
|
+
return crypto_1.default.scryptSync(material, 'kanbaii-salt', 32);
|
|
15
|
+
}
|
|
16
|
+
function encrypt(text) {
|
|
17
|
+
const key = deriveKey();
|
|
18
|
+
const iv = crypto_1.default.randomBytes(16);
|
|
19
|
+
const cipher = crypto_1.default.createCipheriv(ALGORITHM, key, iv);
|
|
20
|
+
let encrypted = cipher.update(text, 'utf-8', 'hex');
|
|
21
|
+
encrypted += cipher.final('hex');
|
|
22
|
+
const tag = cipher.getAuthTag().toString('hex');
|
|
23
|
+
return `enc:${iv.toString('hex')}:${tag}:${encrypted}`;
|
|
24
|
+
}
|
|
25
|
+
function decrypt(encoded) {
|
|
26
|
+
if (!encoded.startsWith('enc:'))
|
|
27
|
+
return encoded;
|
|
28
|
+
const [, ivHex, tagHex, data] = encoded.split(':');
|
|
29
|
+
const key = deriveKey();
|
|
30
|
+
const decipher = crypto_1.default.createDecipheriv(ALGORITHM, key, Buffer.from(ivHex, 'hex'));
|
|
31
|
+
decipher.setAuthTag(Buffer.from(tagHex, 'hex'));
|
|
32
|
+
let decrypted = decipher.update(data, 'hex', 'utf-8');
|
|
33
|
+
decrypted += decipher.final('utf-8');
|
|
34
|
+
return decrypted;
|
|
35
|
+
}
|
|
36
|
+
function isEncrypted(value) {
|
|
37
|
+
return typeof value === 'string' && value.startsWith('enc:');
|
|
38
|
+
}
|
|
@@ -4,4 +4,3 @@ export type TypedServer = Server<ClientToServerEvents, ServerToClientEvents>;
|
|
|
4
4
|
export declare function setIO(server: TypedServer): void;
|
|
5
5
|
export declare function getIO(): TypedServer;
|
|
6
6
|
export declare function emit<E extends keyof ServerToClientEvents>(event: E, ...args: Parameters<ServerToClientEvents[E]>): void;
|
|
7
|
-
//# sourceMappingURL=typedEmit.d.ts.map
|
|
@@ -11,8 +11,7 @@ function callClaude(prompt) {
|
|
|
11
11
|
return new Promise((resolve, reject) => {
|
|
12
12
|
const proc = (0, child_process_1.spawn)('claude', ['-p', '--output-format', 'text'], {
|
|
13
13
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
14
|
-
|
|
15
|
-
timeout: 120000,
|
|
14
|
+
windowsHide: true,
|
|
16
15
|
});
|
|
17
16
|
let stdout = '';
|
|
18
17
|
let stderr = '';
|
|
@@ -121,4 +120,3 @@ Order tasks by execution order (dependencies first). Generate 3-8 tasks.`;
|
|
|
121
120
|
}
|
|
122
121
|
});
|
|
123
122
|
exports.default = router;
|
|
124
|
-
//# sourceMappingURL=generate.js.map
|
|
@@ -87,4 +87,3 @@ router.post('/update-item', (req, res) => {
|
|
|
87
87
|
res.json({ ok: true, data: { itemId: item.id, status: item.status, message: `Item "${item.title}" updated to ${item.status}. ${item.tasks.length} tasks.` } });
|
|
88
88
|
});
|
|
89
89
|
exports.default = router;
|
|
90
|
-
//# sourceMappingURL=planner.js.map
|
|
@@ -6,33 +6,36 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const express_1 = require("express");
|
|
7
7
|
const child_process_1 = require("child_process");
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
9
10
|
const router = (0, express_1.Router)();
|
|
10
|
-
// POST /api/open-folder — Open a folder in the system file explorer
|
|
11
11
|
router.post('/open-folder', (req, res) => {
|
|
12
12
|
const { path: folderPath } = req.body;
|
|
13
|
-
if (!folderPath) {
|
|
13
|
+
if (!folderPath || typeof folderPath !== 'string') {
|
|
14
14
|
return res.status(400).json({ ok: false, error: 'path is required' });
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
const resolved = path_1.default.resolve(folderPath);
|
|
17
|
+
if (!fs_1.default.existsSync(resolved) || !fs_1.default.statSync(resolved).isDirectory()) {
|
|
18
|
+
return res.status(404).json({ ok: false, error: 'Directory not found' });
|
|
18
19
|
}
|
|
19
20
|
const platform = process.platform;
|
|
20
21
|
let cmd;
|
|
22
|
+
let args;
|
|
21
23
|
if (platform === 'win32') {
|
|
22
|
-
cmd =
|
|
24
|
+
cmd = 'explorer';
|
|
25
|
+
args = [resolved];
|
|
23
26
|
}
|
|
24
27
|
else if (platform === 'darwin') {
|
|
25
|
-
cmd =
|
|
28
|
+
cmd = 'open';
|
|
29
|
+
args = [resolved];
|
|
26
30
|
}
|
|
27
31
|
else {
|
|
28
|
-
cmd =
|
|
32
|
+
cmd = 'xdg-open';
|
|
33
|
+
args = [resolved];
|
|
29
34
|
}
|
|
30
|
-
(0, child_process_1.
|
|
31
|
-
if (err)
|
|
32
|
-
return res.status(500).json({ ok: false, error:
|
|
33
|
-
}
|
|
35
|
+
(0, child_process_1.execFile)(cmd, args, (err) => {
|
|
36
|
+
if (err)
|
|
37
|
+
return res.status(500).json({ ok: false, error: 'Failed to open folder' });
|
|
34
38
|
res.json({ ok: true });
|
|
35
39
|
});
|
|
36
40
|
});
|
|
37
41
|
exports.default = router;
|
|
38
|
-
//# sourceMappingURL=system.js.map
|