tycono 0.1.102 → 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/cli.js
CHANGED
|
@@ -3,12 +3,28 @@
|
|
|
3
3
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
4
4
|
import { dirname, join } from 'node:path';
|
|
5
5
|
import { createRequire } from 'node:module';
|
|
6
|
+
import { execFileSync } from 'node:child_process';
|
|
7
|
+
|
|
8
|
+
// Auto-increase heap if not already set (prevents OOM with server+TUI in same process)
|
|
9
|
+
if (!process.env.__TYCONO_HEAP_SET && !process.execArgv.some(a => a.includes('max-old-space-size'))) {
|
|
10
|
+
process.env.__TYCONO_HEAP_SET = '1';
|
|
11
|
+
try {
|
|
12
|
+
execFileSync(process.execPath, [
|
|
13
|
+
'--max-old-space-size=8192',
|
|
14
|
+
...process.execArgv,
|
|
15
|
+
fileURLToPath(import.meta.url),
|
|
16
|
+
...process.argv.slice(2),
|
|
17
|
+
], { stdio: 'inherit', env: process.env });
|
|
18
|
+
} catch (e) {
|
|
19
|
+
process.exit(e.status ?? 1);
|
|
20
|
+
}
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
6
23
|
|
|
7
24
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
25
|
const __dirname = dirname(__filename);
|
|
9
26
|
|
|
10
27
|
// Resolve tsx using createRequire from THIS file's location
|
|
11
|
-
// This traverses up node_modules correctly for both local and npx flat installs
|
|
12
28
|
const require = createRequire(import.meta.url);
|
|
13
29
|
const tsxApiPath = pathToFileURL(require.resolve('tsx/esm/api')).href;
|
|
14
30
|
const tsx = await import(tsxApiPath);
|
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.
|
|
3
|
+
"version": "0.1.104",
|
|
4
4
|
"description": "Build an AI company. Watch them work.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -45,7 +45,8 @@
|
|
|
45
45
|
"react": "^18.3.1",
|
|
46
46
|
"tsx": "^4.19.3",
|
|
47
47
|
"tyconoforge": "^0.1.0-beta.0",
|
|
48
|
-
"yaml": "^2.7.0"
|
|
48
|
+
"yaml": "^2.7.0",
|
|
49
|
+
"yoga-layout": "3.1.0"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
52
|
"@types/cors": "^2.8.17",
|
|
@@ -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
|
-
//
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
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
|
-
}
|
|
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
|
|