standout 0.5.28 → 0.5.29
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/dist/ai-usage.d.ts +1 -1
- package/dist/ai-usage.js +13 -10
- package/dist/cli.js +2 -0
- package/dist/heap.d.ts +1 -0
- package/dist/heap.js +25 -0
- package/package.json +1 -1
package/dist/ai-usage.d.ts
CHANGED
package/dist/ai-usage.js
CHANGED
|
@@ -305,13 +305,14 @@ function registerFile(raw, filePath) {
|
|
|
305
305
|
raw.filePaths.add(filePath);
|
|
306
306
|
}
|
|
307
307
|
function recordSessionMeta(raw, sessionId, ts, cwd, model, version) {
|
|
308
|
+
const minute = Math.floor(ts / 60_000);
|
|
308
309
|
const existing = raw.sessions.get(sessionId);
|
|
309
310
|
if (existing) {
|
|
310
311
|
if (ts < existing.firstTs)
|
|
311
312
|
existing.firstTs = ts;
|
|
312
313
|
if (ts > existing.lastTs)
|
|
313
314
|
existing.lastTs = ts;
|
|
314
|
-
existing.eventTimestamps.
|
|
315
|
+
existing.eventTimestamps.add(minute);
|
|
315
316
|
if (!existing.cwd && cwd)
|
|
316
317
|
existing.cwd = cwd;
|
|
317
318
|
if (model)
|
|
@@ -323,7 +324,7 @@ function recordSessionMeta(raw, sessionId, ts, cwd, model, version) {
|
|
|
323
324
|
raw.sessions.set(sessionId, {
|
|
324
325
|
firstTs: ts,
|
|
325
326
|
lastTs: ts,
|
|
326
|
-
eventTimestamps: [
|
|
327
|
+
eventTimestamps: new Set([minute]),
|
|
327
328
|
cwd,
|
|
328
329
|
models: model ? new Set([model]) : new Set(),
|
|
329
330
|
modelTurnCounts: new Map(),
|
|
@@ -804,10 +805,11 @@ export function computeStreaks(activeDays) {
|
|
|
804
805
|
current = 0;
|
|
805
806
|
return { longest, current };
|
|
806
807
|
}
|
|
807
|
-
function estimateActiveDurationMs(
|
|
808
|
-
const sorted = [...new Set(
|
|
809
|
-
.filter((
|
|
810
|
-
.sort((a, b) => a - b)
|
|
808
|
+
function estimateActiveDurationMs(minuteBuckets) {
|
|
809
|
+
const sorted = [...new Set(minuteBuckets)]
|
|
810
|
+
.filter((m) => Number.isFinite(m))
|
|
811
|
+
.sort((a, b) => a - b)
|
|
812
|
+
.map((m) => m * 60_000);
|
|
811
813
|
if (sorted.length === 0)
|
|
812
814
|
return 0;
|
|
813
815
|
if (sorted.length === 1)
|
|
@@ -840,10 +842,11 @@ function compactCwd(cwd) {
|
|
|
840
842
|
}
|
|
841
843
|
// Split a session's events into active segments (consecutive events <= 15min
|
|
842
844
|
// apart), so concurrency reflects real work, not a tab idle for days.
|
|
843
|
-
function activeSegments(
|
|
844
|
-
const sorted = [...new Set(
|
|
845
|
-
.filter((
|
|
846
|
-
.sort((a, b) => a - b)
|
|
845
|
+
function activeSegments(minuteBuckets) {
|
|
846
|
+
const sorted = [...new Set(minuteBuckets)]
|
|
847
|
+
.filter((m) => Number.isFinite(m))
|
|
848
|
+
.sort((a, b) => a - b)
|
|
849
|
+
.map((m) => m * 60_000);
|
|
847
850
|
if (sorted.length === 0)
|
|
848
851
|
return [];
|
|
849
852
|
const maxGapMs = MAX_ACTIVE_GAP_MINUTES * 60 * 1000;
|
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import chalk from "chalk";
|
|
|
4
4
|
import { createInterface } from "readline";
|
|
5
5
|
import { markWrappedShared, STANDOUT_API_URL } from "./api.js";
|
|
6
6
|
import { gatherFullEnrichment, gatherProfileBasics, gatherUsageStats, } from "./gather.js";
|
|
7
|
+
import { ensureHeapHeadroom } from "./heap.js";
|
|
7
8
|
import { startMcpServer } from "./mcp.js";
|
|
8
9
|
import { configureProxyFromEnv } from "./proxy.js";
|
|
9
10
|
import { SYSTEM_PROMPT } from "./prompt.js";
|
|
@@ -326,6 +327,7 @@ async function runAgent(jobId) {
|
|
|
326
327
|
console.log(` Tokens: ${totalInputTokens.toLocaleString()} in / ${totalOutputTokens.toLocaleString()} out${cacheNote} in ${elapsed}s\n`);
|
|
327
328
|
}
|
|
328
329
|
async function main() {
|
|
330
|
+
ensureHeapHeadroom();
|
|
329
331
|
const args = process.argv.slice(2);
|
|
330
332
|
// Route fetch through a configured proxy before any network call — Node's fetch
|
|
331
333
|
// ignores HTTP(S)_PROXY otherwise, which breaks users behind a corporate proxy.
|
package/dist/heap.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ensureHeapHeadroom(): void;
|
package/dist/heap.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
|
+
import { totalmem } from "os";
|
|
3
|
+
// Node caps old-space at ~4GB by default regardless of physical RAM, so a big
|
|
4
|
+
// machine OOMs at the same point as a small one. On machines with headroom,
|
|
5
|
+
// re-exec once with a higher --max-old-space-size (half of RAM, capped at 8GB)
|
|
6
|
+
// so heavy log archives have room. The real bound is algorithmic (see
|
|
7
|
+
// ai-usage.ts); this is just a safety net.
|
|
8
|
+
export function ensureHeapHeadroom() {
|
|
9
|
+
if (process.env.STANDOUT_HEAP_BOOSTED === "1")
|
|
10
|
+
return;
|
|
11
|
+
if (process.execArgv.some((a) => a.startsWith("--max-old-space-size")))
|
|
12
|
+
return;
|
|
13
|
+
const totalMb = Math.floor(totalmem() / (1024 * 1024));
|
|
14
|
+
const desiredMb = Math.min(8192, Math.floor(totalMb / 2));
|
|
15
|
+
if (desiredMb <= 4096)
|
|
16
|
+
return;
|
|
17
|
+
const entry = process.argv[1];
|
|
18
|
+
if (!entry)
|
|
19
|
+
return;
|
|
20
|
+
const res = spawnSync(process.execPath, [`--max-old-space-size=${desiredMb}`, entry, ...process.argv.slice(2)], {
|
|
21
|
+
stdio: "inherit",
|
|
22
|
+
env: { ...process.env, STANDOUT_HEAP_BOOSTED: "1" },
|
|
23
|
+
});
|
|
24
|
+
process.exit(res.status ?? 0);
|
|
25
|
+
}
|