tycono 0.1.103 → 0.1.104

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/bin/tycono.ts CHANGED
@@ -270,6 +270,12 @@ async function startServerForTui(): Promise<void> {
270
270
  origLog(` API server started on port ${port}`);
271
271
  origLog(` Logs: ${logFile}`);
272
272
 
273
+ // Memory monitor — log heap usage every 30s to detect leaks
274
+ setInterval(() => {
275
+ const mem = process.memoryUsage();
276
+ logStream.write(`[MEM] heap=${Math.round(mem.heapUsed / 1024 / 1024)}MB/${Math.round(mem.heapTotal / 1024 / 1024)}MB rss=${Math.round(mem.rss / 1024 / 1024)}MB\n`);
277
+ }, 30_000).unref();
278
+
273
279
  // Graceful shutdown — mark active sessions as interrupted
274
280
  const shutdown = () => {
275
281
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tycono",
3
- "version": "0.1.103",
3
+ "version": "0.1.104",
4
4
  "description": "Build an AI company. Watch them work.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -58,6 +58,19 @@ export function createApp() {
58
58
  res.json({ status: 'ok', companyRoot: COMPANY_ROOT });
59
59
  });
60
60
 
61
+ // Debug: memory stats for leak detection
62
+ app.get('/api/debug/memory', (_req, res) => {
63
+ const { executionManager } = require('./services/execution-manager.js');
64
+ const { listSessions } = require('./services/session-store.js');
65
+ const mem = process.memoryUsage();
66
+ res.json({
67
+ heap: { used: Math.round(mem.heapUsed / 1024 / 1024), total: Math.round(mem.heapTotal / 1024 / 1024) },
68
+ rss: Math.round(mem.rss / 1024 / 1024),
69
+ execManager: executionManager.getMemoryStats(),
70
+ sessions: listSessions().length,
71
+ });
72
+ });
73
+
61
74
  app.use((err: Error, _req: express.Request, res: express.Response, _next: express.NextFunction) => {
62
75
  const status = err.name === 'FileNotFoundError' ? 404 : 500;
63
76
  res.status(status).json({ error: err.message });
@@ -540,22 +540,30 @@ class ExecutionManager {
540
540
  }
541
541
  }
542
542
 
543
- // Memory cleanup: remove completed execution after 60s
544
- // Keep briefly for status queries, then GC
545
- setTimeout(() => {
546
- this.executions.delete(execution.id);
547
- // Clean up any leaked sessionMsgContent
548
- if (execution.sessionId) {
549
- for (const key of this.sessionMsgContent.keys()) {
550
- if (key.startsWith(execution.sessionId + ':')) {
551
- this.sessionMsgContent.delete(key);
552
- }
543
+ // Clean up sessionMsgContent immediately (no longer needed after finalize)
544
+ if (execution.sessionId) {
545
+ for (const key of this.sessionMsgContent.keys()) {
546
+ if (key.startsWith(execution.sessionId + ':')) {
547
+ this.sessionMsgContent.delete(key);
553
548
  }
554
549
  }
555
- }, 60_000);
550
+ }
556
551
  });
557
552
  }
558
553
 
554
+ /** Debug: return memory stats for monitoring */
555
+ getMemoryStats(): { executions: number; msgContentKeys: number; msgContentSize: number } {
556
+ let msgContentSize = 0;
557
+ for (const v of this.sessionMsgContent.values()) {
558
+ msgContentSize += v.length;
559
+ }
560
+ return {
561
+ executions: this.executions.size,
562
+ msgContentKeys: this.sessionMsgContent.size,
563
+ msgContentSize,
564
+ };
565
+ }
566
+
559
567
  /* ─── Session ↔ Execution bridge ───────── */
560
568
 
561
569
  private sessionMsgContent = new Map<string, string>();
@@ -252,12 +252,6 @@ export function updateSession(id: string, updates: Partial<Pick<Session, 'title'
252
252
  session.updatedAt = new Date().toISOString();
253
253
  writeImmediate(session);
254
254
 
255
- // Memory: evict done/interrupted sessions from cache after write
256
- // They're persisted to disk and can be re-loaded on demand
257
- if (session.status === 'done' || session.status === 'interrupted') {
258
- setTimeout(() => { cache.delete(id); }, 30_000);
259
- }
260
-
261
255
  return session;
262
256
  }
263
257