tycono 0.3.12 → 0.3.13-beta.1
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
|
@@ -11,6 +11,7 @@ if (!process.env.__TYCONO_HEAP_SET && !process.execArgv.some(a => a.includes('ma
|
|
|
11
11
|
try {
|
|
12
12
|
execFileSync(process.execPath, [
|
|
13
13
|
'--max-old-space-size=8192',
|
|
14
|
+
'--expose-gc',
|
|
14
15
|
...process.execArgv,
|
|
15
16
|
fileURLToPath(import.meta.url),
|
|
16
17
|
...process.argv.slice(2),
|
package/bin/tycono.ts
CHANGED
|
@@ -270,11 +270,37 @@ async function startServerForTui(): Promise<void> {
|
|
|
270
270
|
origLog(` API server started on port ${port}`);
|
|
271
271
|
origLog(` Logs: ${logFile}`);
|
|
272
272
|
|
|
273
|
-
// Memory monitor —
|
|
273
|
+
// Memory monitor — 10s interval, with spike detection + forced GC
|
|
274
|
+
let lastHeap = 0;
|
|
274
275
|
setInterval(() => {
|
|
275
276
|
const mem = process.memoryUsage();
|
|
276
|
-
|
|
277
|
-
|
|
277
|
+
const heapMB = Math.round(mem.heapUsed / 1024 / 1024);
|
|
278
|
+
const heapTotalMB = Math.round(mem.heapTotal / 1024 / 1024);
|
|
279
|
+
const rssMB = Math.round(mem.rss / 1024 / 1024);
|
|
280
|
+
const spike = heapMB - lastHeap;
|
|
281
|
+
|
|
282
|
+
// Always log
|
|
283
|
+
logStream.write(`[MEM] heap=${heapMB}MB/${heapTotalMB}MB rss=${rssMB}MB${spike > 50 ? ` ⚠️ SPIKE +${spike}MB` : ''}\n`);
|
|
284
|
+
|
|
285
|
+
// Spike detection: >100MB jump in 10s
|
|
286
|
+
if (spike > 100) {
|
|
287
|
+
logStream.write(`[MEM] ⛔ MEMORY SPIKE: +${spike}MB in 10s (${lastHeap}MB → ${heapMB}MB)\n`);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Warning at 2GB
|
|
291
|
+
if (heapMB > 2048 && lastHeap <= 2048) {
|
|
292
|
+
logStream.write(`[MEM] ⚠️ HEAP WARNING: ${heapMB}MB — approaching limit. Forcing GC.\n`);
|
|
293
|
+
if (global.gc) global.gc();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Critical at 4GB — force GC
|
|
297
|
+
if (heapMB > 4096) {
|
|
298
|
+
logStream.write(`[MEM] ⛔ HEAP CRITICAL: ${heapMB}MB — forcing GC\n`);
|
|
299
|
+
if (global.gc) global.gc();
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
lastHeap = heapMB;
|
|
303
|
+
}, 10_000).unref();
|
|
278
304
|
|
|
279
305
|
// Graceful shutdown — mark active sessions as interrupted
|
|
280
306
|
const shutdown = () => {
|
package/package.json
CHANGED
|
@@ -176,7 +176,7 @@ class ExecutionManager {
|
|
|
176
176
|
orgTree: ReturnType<typeof buildOrgTree>,
|
|
177
177
|
): Promise<void> {
|
|
178
178
|
try {
|
|
179
|
-
const ports = await portRegistry.allocate(execution.id, params.roleId, params.task);
|
|
179
|
+
const ports = await portRegistry.allocate(execution.sessionId || execution.id, params.roleId, params.task);
|
|
180
180
|
execution.ports = ports;
|
|
181
181
|
console.log(`[ExecMgr] Allocated ports for ${execution.id} (${params.roleId}): API :${ports.api}, Vite :${ports.vite}`);
|
|
182
182
|
} catch (err) {
|
|
@@ -534,7 +534,7 @@ class ExecutionManager {
|
|
|
534
534
|
})
|
|
535
535
|
.finally(() => {
|
|
536
536
|
if (execution.ports) {
|
|
537
|
-
const released = portRegistry.release(execution.id);
|
|
537
|
+
const released = portRegistry.release(execution.sessionId || execution.id);
|
|
538
538
|
if (released) {
|
|
539
539
|
console.log(`[ExecMgr] Released ports for ${execution.id}: API :${execution.ports.api}, Vite :${execution.ports.vite}`);
|
|
540
540
|
}
|
|
@@ -156,7 +156,9 @@ export const PanelMode: React.FC<PanelModeProps> = ({
|
|
|
156
156
|
return () => { process.stdout.off('resize', onResize); };
|
|
157
157
|
}, []);
|
|
158
158
|
|
|
159
|
-
|
|
159
|
+
// OOM fix: single separator character instead of repeated newlines
|
|
160
|
+
// Previous: '│\n'.repeat(30) created 30 yoga nodes → layout explosion on large terminals
|
|
161
|
+
const separatorStr = '\u2502';
|
|
160
162
|
|
|
161
163
|
const waveScopedStatuses = useMemo(
|
|
162
164
|
() => getWaveScopedStatuses(allSessions, focusedWaveId),
|
|
@@ -379,10 +381,8 @@ export const PanelMode: React.FC<PanelModeProps> = ({
|
|
|
379
381
|
)}
|
|
380
382
|
</Box>
|
|
381
383
|
|
|
382
|
-
{/* Vertical separator */}
|
|
383
|
-
<
|
|
384
|
-
<Text color="gray">{separatorStr}</Text>
|
|
385
|
-
</Box>
|
|
384
|
+
{/* Vertical separator — single character, not repeated newlines */}
|
|
385
|
+
<Text color="gray">{separatorStr}</Text>
|
|
386
386
|
|
|
387
387
|
{/* Right: Tabbed panel */}
|
|
388
388
|
<Box flexGrow={1} flexDirection="column" overflow="hidden">
|