@vibelet/cli 0.1.37 → 1.0.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/README.md +80 -0
- package/bin/cloudflared-quick-tunnel.mjs +11 -0
- package/bin/cloudflared-resolver.mjs +171 -0
- package/bin/vibelet-runtime-policy.mjs +36 -0
- package/bin/vibelet.cjs +12 -0
- package/bin/vibelet.mjs +1062 -0
- package/dist/index.cjs +126 -0
- package/package.json +25 -24
- package/app.json +0 -5
- package/dist/advertised-hosts.d.ts +0 -34
- package/dist/advertised-hosts.d.ts.map +0 -1
- package/dist/advertised-hosts.js +0 -176
- package/dist/advertised-hosts.js.map +0 -1
- package/dist/advertised-hosts.test.d.ts +0 -2
- package/dist/advertised-hosts.test.d.ts.map +0 -1
- package/dist/advertised-hosts.test.js +0 -96
- package/dist/advertised-hosts.test.js.map +0 -1
- package/dist/audit.d.ts +0 -30
- package/dist/audit.d.ts.map +0 -1
- package/dist/audit.js +0 -73
- package/dist/audit.js.map +0 -1
- package/dist/audit.test.d.ts +0 -2
- package/dist/audit.test.d.ts.map +0 -1
- package/dist/audit.test.js +0 -33
- package/dist/audit.test.js.map +0 -1
- package/dist/auth.d.ts +0 -6
- package/dist/auth.d.ts.map +0 -1
- package/dist/auth.js +0 -27
- package/dist/auth.js.map +0 -1
- package/dist/claude-hooks.d.ts +0 -58
- package/dist/claude-hooks.d.ts.map +0 -1
- package/dist/claude-hooks.js +0 -129
- package/dist/claude-hooks.js.map +0 -1
- package/dist/cli-version.d.ts +0 -3
- package/dist/cli-version.d.ts.map +0 -1
- package/dist/cli-version.js +0 -35
- package/dist/cli-version.js.map +0 -1
- package/dist/cli-version.test.d.ts +0 -2
- package/dist/cli-version.test.d.ts.map +0 -1
- package/dist/cli-version.test.js +0 -38
- package/dist/cli-version.test.js.map +0 -1
- package/dist/config.d.ts +0 -30
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -327
- package/dist/config.js.map +0 -1
- package/dist/config.test.d.ts +0 -2
- package/dist/config.test.d.ts.map +0 -1
- package/dist/config.test.js +0 -184
- package/dist/config.test.js.map +0 -1
- package/dist/dev-auth.test.d.ts +0 -2
- package/dist/dev-auth.test.d.ts.map +0 -1
- package/dist/dev-auth.test.js +0 -154
- package/dist/dev-auth.test.js.map +0 -1
- package/dist/dev-script.test.d.ts +0 -2
- package/dist/dev-script.test.d.ts.map +0 -1
- package/dist/dev-script.test.js +0 -412
- package/dist/dev-script.test.js.map +0 -1
- package/dist/drivers/claude.d.ts +0 -34
- package/dist/drivers/claude.d.ts.map +0 -1
- package/dist/drivers/claude.js +0 -413
- package/dist/drivers/claude.js.map +0 -1
- package/dist/drivers/claude.test.d.ts +0 -2
- package/dist/drivers/claude.test.d.ts.map +0 -1
- package/dist/drivers/claude.test.js +0 -951
- package/dist/drivers/claude.test.js.map +0 -1
- package/dist/drivers/codex.d.ts +0 -38
- package/dist/drivers/codex.d.ts.map +0 -1
- package/dist/drivers/codex.js +0 -771
- package/dist/drivers/codex.js.map +0 -1
- package/dist/drivers/codex.test.d.ts +0 -2
- package/dist/drivers/codex.test.d.ts.map +0 -1
- package/dist/drivers/codex.test.js +0 -939
- package/dist/drivers/codex.test.js.map +0 -1
- package/dist/drivers/types.d.ts +0 -14
- package/dist/drivers/types.d.ts.map +0 -1
- package/dist/drivers/types.js +0 -2
- package/dist/drivers/types.js.map +0 -1
- package/dist/e2e.test.d.ts +0 -2
- package/dist/e2e.test.d.ts.map +0 -1
- package/dist/e2e.test.js +0 -111
- package/dist/e2e.test.js.map +0 -1
- package/dist/identity.d.ts +0 -10
- package/dist/identity.d.ts.map +0 -1
- package/dist/identity.js +0 -66
- package/dist/identity.js.map +0 -1
- package/dist/identity.test.d.ts +0 -2
- package/dist/identity.test.d.ts.map +0 -1
- package/dist/identity.test.js +0 -25
- package/dist/identity.test.js.map +0 -1
- package/dist/index-entry.test.d.ts +0 -2
- package/dist/index-entry.test.d.ts.map +0 -1
- package/dist/index-entry.test.js +0 -272
- package/dist/index-entry.test.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -707
- package/dist/index.js.map +0 -1
- package/dist/logger.d.ts +0 -31
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -75
- package/dist/logger.js.map +0 -1
- package/dist/metrics.d.ts +0 -52
- package/dist/metrics.d.ts.map +0 -1
- package/dist/metrics.js +0 -89
- package/dist/metrics.js.map +0 -1
- package/dist/pairing-store.d.ts +0 -29
- package/dist/pairing-store.d.ts.map +0 -1
- package/dist/pairing-store.js +0 -131
- package/dist/pairing-store.js.map +0 -1
- package/dist/pairing-store.test.d.ts +0 -2
- package/dist/pairing-store.test.d.ts.map +0 -1
- package/dist/pairing-store.test.js +0 -47
- package/dist/pairing-store.test.js.map +0 -1
- package/dist/paths.d.ts +0 -16
- package/dist/paths.d.ts.map +0 -1
- package/dist/paths.js +0 -18
- package/dist/paths.js.map +0 -1
- package/dist/perf-compare.d.ts +0 -13
- package/dist/perf-compare.d.ts.map +0 -1
- package/dist/perf-compare.js +0 -125
- package/dist/perf-compare.js.map +0 -1
- package/dist/port-conflict.d.ts +0 -9
- package/dist/port-conflict.d.ts.map +0 -1
- package/dist/port-conflict.js +0 -33
- package/dist/port-conflict.js.map +0 -1
- package/dist/port-conflict.test.d.ts +0 -2
- package/dist/port-conflict.test.d.ts.map +0 -1
- package/dist/port-conflict.test.js +0 -38
- package/dist/port-conflict.test.js.map +0 -1
- package/dist/process-scanner.d.ts +0 -43
- package/dist/process-scanner.d.ts.map +0 -1
- package/dist/process-scanner.js +0 -453
- package/dist/process-scanner.js.map +0 -1
- package/dist/process-scanner.perf.test.d.ts +0 -2
- package/dist/process-scanner.perf.test.d.ts.map +0 -1
- package/dist/process-scanner.perf.test.js +0 -186
- package/dist/process-scanner.perf.test.js.map +0 -1
- package/dist/process-scanner.test.d.ts +0 -2
- package/dist/process-scanner.test.d.ts.map +0 -1
- package/dist/process-scanner.test.js +0 -399
- package/dist/process-scanner.test.js.map +0 -1
- package/dist/push-protocol.d.ts +0 -15
- package/dist/push-protocol.d.ts.map +0 -1
- package/dist/push-protocol.js +0 -23
- package/dist/push-protocol.js.map +0 -1
- package/dist/push-protocol.test.d.ts +0 -2
- package/dist/push-protocol.test.d.ts.map +0 -1
- package/dist/push-protocol.test.js +0 -57
- package/dist/push-protocol.test.js.map +0 -1
- package/dist/push-store.d.ts +0 -22
- package/dist/push-store.d.ts.map +0 -1
- package/dist/push-store.js +0 -103
- package/dist/push-store.js.map +0 -1
- package/dist/push-store.test.d.ts +0 -2
- package/dist/push-store.test.d.ts.map +0 -1
- package/dist/push-store.test.js +0 -79
- package/dist/push-store.test.js.map +0 -1
- package/dist/push.d.ts +0 -65
- package/dist/push.d.ts.map +0 -1
- package/dist/push.js +0 -202
- package/dist/push.js.map +0 -1
- package/dist/push.test.d.ts +0 -2
- package/dist/push.test.d.ts.map +0 -1
- package/dist/push.test.js +0 -199
- package/dist/push.test.js.map +0 -1
- package/dist/safe-stdio.d.ts +0 -3
- package/dist/safe-stdio.d.ts.map +0 -1
- package/dist/safe-stdio.js +0 -46
- package/dist/safe-stdio.js.map +0 -1
- package/dist/scanner.d.ts +0 -30
- package/dist/scanner.d.ts.map +0 -1
- package/dist/scanner.js +0 -859
- package/dist/scanner.js.map +0 -1
- package/dist/scanner.perf.test.d.ts +0 -2
- package/dist/scanner.perf.test.d.ts.map +0 -1
- package/dist/scanner.perf.test.js +0 -320
- package/dist/scanner.perf.test.js.map +0 -1
- package/dist/scanner.test.d.ts +0 -2
- package/dist/scanner.test.d.ts.map +0 -1
- package/dist/scanner.test.js +0 -948
- package/dist/scanner.test.js.map +0 -1
- package/dist/session-inventory.d.ts +0 -63
- package/dist/session-inventory.d.ts.map +0 -1
- package/dist/session-inventory.js +0 -525
- package/dist/session-inventory.js.map +0 -1
- package/dist/session-inventory.perf.test.d.ts +0 -2
- package/dist/session-inventory.perf.test.d.ts.map +0 -1
- package/dist/session-inventory.perf.test.js +0 -220
- package/dist/session-inventory.perf.test.js.map +0 -1
- package/dist/session-inventory.test.d.ts +0 -2
- package/dist/session-inventory.test.d.ts.map +0 -1
- package/dist/session-inventory.test.js +0 -712
- package/dist/session-inventory.test.js.map +0 -1
- package/dist/session-manager.d.ts +0 -75
- package/dist/session-manager.d.ts.map +0 -1
- package/dist/session-manager.js +0 -1515
- package/dist/session-manager.js.map +0 -1
- package/dist/session-manager.test.d.ts +0 -2
- package/dist/session-manager.test.d.ts.map +0 -1
- package/dist/session-manager.test.js +0 -2861
- package/dist/session-manager.test.js.map +0 -1
- package/dist/session-store.d.ts +0 -42
- package/dist/session-store.d.ts.map +0 -1
- package/dist/session-store.js +0 -163
- package/dist/session-store.js.map +0 -1
- package/dist/session-store.test.d.ts +0 -2
- package/dist/session-store.test.d.ts.map +0 -1
- package/dist/session-store.test.js +0 -236
- package/dist/session-store.test.js.map +0 -1
- package/dist/session-title.d.ts +0 -6
- package/dist/session-title.d.ts.map +0 -1
- package/dist/session-title.js +0 -105
- package/dist/session-title.js.map +0 -1
- package/dist/session-title.perf.test.d.ts +0 -2
- package/dist/session-title.perf.test.d.ts.map +0 -1
- package/dist/session-title.perf.test.js +0 -99
- package/dist/session-title.perf.test.js.map +0 -1
- package/dist/session-title.test.d.ts +0 -2
- package/dist/session-title.test.d.ts.map +0 -1
- package/dist/session-title.test.js +0 -199
- package/dist/session-title.test.js.map +0 -1
- package/dist/shutdown-endpoint.test.d.ts +0 -2
- package/dist/shutdown-endpoint.test.d.ts.map +0 -1
- package/dist/shutdown-endpoint.test.js +0 -93
- package/dist/shutdown-endpoint.test.js.map +0 -1
- package/dist/storage-housekeeping.d.ts +0 -28
- package/dist/storage-housekeeping.d.ts.map +0 -1
- package/dist/storage-housekeeping.js +0 -76
- package/dist/storage-housekeeping.js.map +0 -1
- package/dist/storage-housekeeping.test.d.ts +0 -2
- package/dist/storage-housekeeping.test.d.ts.map +0 -1
- package/dist/storage-housekeeping.test.js +0 -65
- package/dist/storage-housekeeping.test.js.map +0 -1
- package/dist/test-daemon-harness.d.ts +0 -31
- package/dist/test-daemon-harness.d.ts.map +0 -1
- package/dist/test-daemon-harness.js +0 -337
- package/dist/test-daemon-harness.js.map +0 -1
- package/dist/token-auth.test.d.ts +0 -2
- package/dist/token-auth.test.d.ts.map +0 -1
- package/dist/token-auth.test.js +0 -52
- package/dist/token-auth.test.js.map +0 -1
- package/dist/utils.d.ts +0 -4
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -40
- package/dist/utils.js.map +0 -1
- package/dist/utils.test.d.ts +0 -2
- package/dist/utils.test.d.ts.map +0 -1
- package/dist/utils.test.js +0 -54
- package/dist/utils.test.js.map +0 -1
- package/dist/ws-data.d.ts +0 -4
- package/dist/ws-data.d.ts.map +0 -1
- package/dist/ws-data.js +0 -20
- package/dist/ws-data.js.map +0 -1
- package/dist/ws-data.test.d.ts +0 -2
- package/dist/ws-data.test.d.ts.map +0 -1
- package/dist/ws-data.test.js +0 -17
- package/dist/ws-data.test.js.map +0 -1
- package/perf-reporter.mjs +0 -138
- package/scripts/build-release.mjs +0 -41
- package/scripts/dev.mjs +0 -537
- package/src/advertised-hosts.test.ts +0 -125
- package/src/advertised-hosts.ts +0 -225
- package/src/audit.test.ts +0 -38
- package/src/audit.ts +0 -117
- package/src/auth.ts +0 -31
- package/src/claude-hooks.ts +0 -195
- package/src/cli-version.test.ts +0 -36
- package/src/cli-version.ts +0 -46
- package/src/config.test.ts +0 -254
- package/src/config.ts +0 -324
- package/src/dev-auth.test.ts +0 -183
- package/src/dev-script.test.ts +0 -511
- package/src/drivers/claude.test.ts +0 -1186
- package/src/drivers/claude.ts +0 -443
- package/src/drivers/codex.test.ts +0 -1096
- package/src/drivers/codex.ts +0 -879
- package/src/drivers/types.ts +0 -15
- package/src/e2e.test.ts +0 -139
- package/src/identity.test.ts +0 -26
- package/src/identity.ts +0 -82
- package/src/index-entry.test.ts +0 -336
- package/src/index.ts +0 -781
- package/src/logger.ts +0 -112
- package/src/metrics.ts +0 -117
- package/src/pairing-store.test.ts +0 -53
- package/src/pairing-store.ts +0 -154
- package/src/paths.ts +0 -19
- package/src/perf-compare.ts +0 -164
- package/src/port-conflict.test.ts +0 -45
- package/src/port-conflict.ts +0 -44
- package/src/process-scanner.perf.test.ts +0 -222
- package/src/process-scanner.test.ts +0 -575
- package/src/process-scanner.ts +0 -514
- package/src/push-protocol.test.ts +0 -74
- package/src/push-protocol.ts +0 -36
- package/src/push-store.test.ts +0 -89
- package/src/push-store.ts +0 -126
- package/src/push.test.ts +0 -234
- package/src/push.ts +0 -318
- package/src/safe-stdio.ts +0 -51
- package/src/scanner.perf.test.ts +0 -359
- package/src/scanner.test.ts +0 -1045
- package/src/scanner.ts +0 -924
- package/src/session-inventory.perf.test.ts +0 -250
- package/src/session-inventory.test.ts +0 -1002
- package/src/session-inventory.ts +0 -721
- package/src/session-manager.test.ts +0 -3430
- package/src/session-manager.ts +0 -1775
- package/src/session-store.test.ts +0 -276
- package/src/session-store.ts +0 -202
- package/src/session-title.perf.test.ts +0 -118
- package/src/session-title.test.ts +0 -286
- package/src/session-title.ts +0 -108
- package/src/shutdown-endpoint.test.ts +0 -95
- package/src/storage-housekeeping.test.ts +0 -78
- package/src/storage-housekeeping.ts +0 -111
- package/src/test-daemon-harness.ts +0 -410
- package/src/token-auth.test.ts +0 -67
- package/src/utils.test.ts +0 -65
- package/src/utils.ts +0 -47
- package/src/ws-data.test.ts +0 -20
- package/src/ws-data.ts +0 -26
- package/tsconfig.json +0 -12
package/src/scanner.perf.test.ts
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { writeFileSync, mkdirSync, rmSync } from 'fs';
|
|
4
|
-
import { join } from 'path';
|
|
5
|
-
import { tmpdir } from 'os';
|
|
6
|
-
import { readSessionFileMeta, extractSessionIdFromSessionFile, listSessions, listClaudeSessions, searchSessionContent, invalidateScannerCache } from './scanner.js';
|
|
7
|
-
|
|
8
|
-
function measure(fn: () => void, iterations: number): { totalMs: number; avgMs: number } {
|
|
9
|
-
fn(); // warmup
|
|
10
|
-
const start = performance.now();
|
|
11
|
-
for (let i = 0; i < iterations; i++) fn();
|
|
12
|
-
const totalMs = performance.now() - start;
|
|
13
|
-
return { totalMs, avgMs: totalMs / iterations };
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async function measureAsync(fn: () => Promise<void>, iterations: number): Promise<{ totalMs: number; avgMs: number }> {
|
|
17
|
-
await fn(); // warmup
|
|
18
|
-
const start = performance.now();
|
|
19
|
-
for (let i = 0; i < iterations; i++) await fn();
|
|
20
|
-
const totalMs = performance.now() - start;
|
|
21
|
-
return { totalMs, avgMs: totalMs / iterations };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const ITERATIONS = 10_000;
|
|
25
|
-
|
|
26
|
-
describe('scanner performance', () => {
|
|
27
|
-
|
|
28
|
-
describe('extractSessionIdFromSessionFile', () => {
|
|
29
|
-
|
|
30
|
-
it(`claude session ID extraction × ${ITERATIONS} < 20ms`, () => {
|
|
31
|
-
const { totalMs } = measure(() => {
|
|
32
|
-
extractSessionIdFromSessionFile('claude', '/Users/test/.claude/projects/-repo/abc123.jsonl');
|
|
33
|
-
}, ITERATIONS);
|
|
34
|
-
console.log(` claude ID: ${totalMs.toFixed(2)}ms for ${ITERATIONS} calls`);
|
|
35
|
-
assert.ok(totalMs < 20, `took ${totalMs.toFixed(2)}ms, expected < 20ms`);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it(`codex UUID extraction × ${ITERATIONS} < 50ms`, () => {
|
|
39
|
-
const { totalMs } = measure(() => {
|
|
40
|
-
extractSessionIdFromSessionFile('codex', '/Users/test/.codex/sessions/2026/03/20/rollout-019d08ac-c265-7270-9497-d14125228a50.jsonl');
|
|
41
|
-
}, ITERATIONS);
|
|
42
|
-
console.log(` codex UUID: ${totalMs.toFixed(2)}ms for ${ITERATIONS} calls`);
|
|
43
|
-
assert.ok(totalMs < 50, `took ${totalMs.toFixed(2)}ms, expected < 50ms`);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it(`codex non-matching filename × ${ITERATIONS} < 50ms`, () => {
|
|
47
|
-
const { totalMs } = measure(() => {
|
|
48
|
-
extractSessionIdFromSessionFile('codex', '/Users/test/.codex/sessions/2026/03/20/no-uuid-here.jsonl');
|
|
49
|
-
}, ITERATIONS);
|
|
50
|
-
console.log(` codex no-match: ${totalMs.toFixed(2)}ms for ${ITERATIONS} calls`);
|
|
51
|
-
assert.ok(totalMs < 50, `took ${totalMs.toFixed(2)}ms, expected < 50ms`);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
describe('readSessionFileMeta - Claude JSONL', () => {
|
|
56
|
-
const testDir = join(tmpdir(), `scanner-perf-test-${Date.now()}`);
|
|
57
|
-
|
|
58
|
-
function createClaudeSessionFile(name: string, lines: number): string {
|
|
59
|
-
const filePath = join(testDir, `${name}.jsonl`);
|
|
60
|
-
const content: string[] = [];
|
|
61
|
-
content.push(JSON.stringify({
|
|
62
|
-
cwd: '/repo',
|
|
63
|
-
sessionId: name,
|
|
64
|
-
customTitle: 'Test session title',
|
|
65
|
-
}));
|
|
66
|
-
for (let i = 1; i < lines; i++) {
|
|
67
|
-
content.push(JSON.stringify({
|
|
68
|
-
type: i % 2 === 0 ? 'user' : 'assistant',
|
|
69
|
-
message: {
|
|
70
|
-
role: i % 2 === 0 ? 'user' : 'assistant',
|
|
71
|
-
content: [{ type: 'text', text: `Message line ${i} with some content padding to simulate real data ${'x'.repeat(100)}` }],
|
|
72
|
-
},
|
|
73
|
-
}));
|
|
74
|
-
}
|
|
75
|
-
writeFileSync(filePath, content.join('\n'));
|
|
76
|
-
return filePath;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function createCodexSessionFile(name: string, lines: number): string {
|
|
80
|
-
const filePath = join(testDir, `${name}.jsonl`);
|
|
81
|
-
const content: string[] = [];
|
|
82
|
-
content.push(JSON.stringify({
|
|
83
|
-
type: 'session_start',
|
|
84
|
-
payload: { id: name, cwd: '/repo', title: 'Codex test session' },
|
|
85
|
-
}));
|
|
86
|
-
for (let i = 1; i < lines; i++) {
|
|
87
|
-
content.push(JSON.stringify({
|
|
88
|
-
type: 'response_item',
|
|
89
|
-
payload: {
|
|
90
|
-
type: 'message',
|
|
91
|
-
role: i % 2 === 0 ? 'user' : 'assistant',
|
|
92
|
-
content: [{ type: 'text', text: `Codex message ${i} ${'y'.repeat(100)}` }],
|
|
93
|
-
},
|
|
94
|
-
}));
|
|
95
|
-
}
|
|
96
|
-
writeFileSync(filePath, content.join('\n'));
|
|
97
|
-
return filePath;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// setup
|
|
101
|
-
it('setup test directory', () => {
|
|
102
|
-
mkdirSync(testDir, { recursive: true });
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('small Claude file (10 lines) × 100 < 200ms', async () => {
|
|
106
|
-
const filePath = createClaudeSessionFile('small-claude', 10);
|
|
107
|
-
const { totalMs, avgMs } = await measureAsync(async () => {
|
|
108
|
-
await readSessionFileMeta(filePath, 'claude');
|
|
109
|
-
}, 100);
|
|
110
|
-
console.log(` small (10 lines): ${totalMs.toFixed(2)}ms total, ${avgMs.toFixed(3)}ms avg`);
|
|
111
|
-
assert.ok(totalMs < 200, `took ${totalMs.toFixed(2)}ms, expected < 200ms`);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('medium Claude file (100 lines) × 50 < 200ms', async () => {
|
|
115
|
-
const filePath = createClaudeSessionFile('medium-claude', 100);
|
|
116
|
-
const { totalMs, avgMs } = await measureAsync(async () => {
|
|
117
|
-
await readSessionFileMeta(filePath, 'claude');
|
|
118
|
-
}, 50);
|
|
119
|
-
console.log(` medium (100 lines): ${totalMs.toFixed(2)}ms total, ${avgMs.toFixed(3)}ms avg`);
|
|
120
|
-
assert.ok(totalMs < 200, `took ${totalMs.toFixed(2)}ms, expected < 200ms`);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('large Claude file (1000 lines) - early exit × 20 < 200ms', async () => {
|
|
124
|
-
const filePath = createClaudeSessionFile('large-claude', 1000);
|
|
125
|
-
const { totalMs, avgMs } = await measureAsync(async () => {
|
|
126
|
-
await readSessionFileMeta(filePath, 'claude');
|
|
127
|
-
}, 20);
|
|
128
|
-
console.log(` large (1000 lines): ${totalMs.toFixed(2)}ms total, ${avgMs.toFixed(3)}ms avg`);
|
|
129
|
-
// Should exit early since cwd+title found in first few lines
|
|
130
|
-
assert.ok(totalMs < 200, `took ${totalMs.toFixed(2)}ms, expected < 200ms`);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('large Claude file without title (1000 lines) - scans 64 × 20 < 500ms', async () => {
|
|
134
|
-
// File without title - will scan up to 64 lines
|
|
135
|
-
const filePath = join(testDir, 'large-notitle-claude.jsonl');
|
|
136
|
-
const content: string[] = [];
|
|
137
|
-
content.push(JSON.stringify({ cwd: '/repo', sessionId: 'large-notitle' }));
|
|
138
|
-
for (let i = 1; i < 1000; i++) {
|
|
139
|
-
content.push(JSON.stringify({
|
|
140
|
-
type: 'assistant',
|
|
141
|
-
message: { role: 'assistant', content: 'No user message here' },
|
|
142
|
-
}));
|
|
143
|
-
}
|
|
144
|
-
writeFileSync(filePath, content.join('\n'));
|
|
145
|
-
|
|
146
|
-
const { totalMs, avgMs } = await measureAsync(async () => {
|
|
147
|
-
await readSessionFileMeta(filePath, 'claude');
|
|
148
|
-
}, 20);
|
|
149
|
-
console.log(` large no-title (1000 lines): ${totalMs.toFixed(2)}ms total, ${avgMs.toFixed(3)}ms avg`);
|
|
150
|
-
assert.ok(totalMs < 500, `took ${totalMs.toFixed(2)}ms, expected < 500ms`);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('small Codex file (10 lines) × 100 < 200ms', async () => {
|
|
154
|
-
const filePath = createCodexSessionFile('small-codex', 10);
|
|
155
|
-
const { totalMs, avgMs } = await measureAsync(async () => {
|
|
156
|
-
await readSessionFileMeta(filePath, 'codex');
|
|
157
|
-
}, 100);
|
|
158
|
-
console.log(` small codex (10 lines): ${totalMs.toFixed(2)}ms total, ${avgMs.toFixed(3)}ms avg`);
|
|
159
|
-
assert.ok(totalMs < 200, `took ${totalMs.toFixed(2)}ms, expected < 200ms`);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it('medium Codex file (100 lines) × 50 < 200ms', async () => {
|
|
163
|
-
const filePath = createCodexSessionFile('medium-codex', 100);
|
|
164
|
-
const { totalMs, avgMs } = await measureAsync(async () => {
|
|
165
|
-
await readSessionFileMeta(filePath, 'codex');
|
|
166
|
-
}, 50);
|
|
167
|
-
console.log(` medium codex (100 lines): ${totalMs.toFixed(2)}ms total, ${avgMs.toFixed(3)}ms avg`);
|
|
168
|
-
assert.ok(totalMs < 200, `took ${totalMs.toFixed(2)}ms, expected < 200ms`);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it('non-existent file × 100 < 200ms', async () => {
|
|
172
|
-
const filePath = join(testDir, 'nonexistent.jsonl');
|
|
173
|
-
const { totalMs, avgMs } = await measureAsync(async () => {
|
|
174
|
-
await readSessionFileMeta(filePath, 'claude');
|
|
175
|
-
}, 100);
|
|
176
|
-
console.log(` non-existent: ${totalMs.toFixed(2)}ms total, ${avgMs.toFixed(3)}ms avg`);
|
|
177
|
-
assert.ok(totalMs < 200, `took ${totalMs.toFixed(2)}ms, expected < 200ms`);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('batch read 50 Claude files sequentially < 2000ms', async () => {
|
|
181
|
-
// Create 50 files
|
|
182
|
-
const files: string[] = [];
|
|
183
|
-
for (let i = 0; i < 50; i++) {
|
|
184
|
-
files.push(createClaudeSessionFile(`batch-${i}`, 20));
|
|
185
|
-
}
|
|
186
|
-
const start = performance.now();
|
|
187
|
-
for (const filePath of files) {
|
|
188
|
-
await readSessionFileMeta(filePath, 'claude');
|
|
189
|
-
}
|
|
190
|
-
const totalMs = performance.now() - start;
|
|
191
|
-
console.log(` batch 50 files: ${totalMs.toFixed(2)}ms`);
|
|
192
|
-
assert.ok(totalMs < 2000, `took ${totalMs.toFixed(2)}ms, expected < 2000ms`);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('batch read 50 Claude files in parallel < 500ms', async () => {
|
|
196
|
-
const files: string[] = [];
|
|
197
|
-
for (let i = 0; i < 50; i++) {
|
|
198
|
-
files.push(createClaudeSessionFile(`batch-par-${i}`, 20));
|
|
199
|
-
}
|
|
200
|
-
const start = performance.now();
|
|
201
|
-
await Promise.all(files.map(f => readSessionFileMeta(f, 'claude')));
|
|
202
|
-
const totalMs = performance.now() - start;
|
|
203
|
-
console.log(` batch 50 parallel: ${totalMs.toFixed(2)}ms`);
|
|
204
|
-
assert.ok(totalMs < 500, `took ${totalMs.toFixed(2)}ms, expected < 500ms`);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
// cleanup
|
|
208
|
-
it('cleanup test directory', async () => {
|
|
209
|
-
invalidateScannerCache();
|
|
210
|
-
rmSync(testDir, { recursive: true, force: true });
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
describe('listSessions cache effectiveness', () => {
|
|
215
|
-
it('second call within TTL is near-instant', async () => {
|
|
216
|
-
invalidateScannerCache();
|
|
217
|
-
// First call (cold)
|
|
218
|
-
const coldStart = performance.now();
|
|
219
|
-
await listSessions();
|
|
220
|
-
const coldMs = performance.now() - coldStart;
|
|
221
|
-
|
|
222
|
-
// Second call (cached, should be < 1ms)
|
|
223
|
-
const warmStart = performance.now();
|
|
224
|
-
await listSessions();
|
|
225
|
-
const warmMs = performance.now() - warmStart;
|
|
226
|
-
|
|
227
|
-
console.log(` listSessions cold: ${coldMs.toFixed(2)}ms, cached: ${warmMs.toFixed(3)}ms`);
|
|
228
|
-
assert.ok(warmMs < 1, `cached call took ${warmMs.toFixed(3)}ms, expected < 1ms`);
|
|
229
|
-
|
|
230
|
-
invalidateScannerCache();
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
it('invalidateScannerCache forces re-scan', async () => {
|
|
234
|
-
invalidateScannerCache();
|
|
235
|
-
await listSessions();
|
|
236
|
-
|
|
237
|
-
// Invalidate and re-call — should take real scan time, not near-zero
|
|
238
|
-
invalidateScannerCache();
|
|
239
|
-
const start = performance.now();
|
|
240
|
-
await listSessions();
|
|
241
|
-
const ms = performance.now() - start;
|
|
242
|
-
// Just verify it doesn't crash and returns in reasonable time
|
|
243
|
-
console.log(` after invalidation: ${ms.toFixed(2)}ms`);
|
|
244
|
-
assert.ok(ms >= 0);
|
|
245
|
-
|
|
246
|
-
invalidateScannerCache();
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
describe('searchSessionContent cache effectiveness', () => {
|
|
251
|
-
it('second identical search within TTL is near-instant', async () => {
|
|
252
|
-
invalidateScannerCache();
|
|
253
|
-
const query = `perf-test-unique-${Date.now()}`;
|
|
254
|
-
|
|
255
|
-
const coldStart = performance.now();
|
|
256
|
-
await searchSessionContent(query);
|
|
257
|
-
const coldMs = performance.now() - coldStart;
|
|
258
|
-
|
|
259
|
-
const warmStart = performance.now();
|
|
260
|
-
await searchSessionContent(query);
|
|
261
|
-
const warmMs = performance.now() - warmStart;
|
|
262
|
-
|
|
263
|
-
console.log(` searchSessionContent cold: ${coldMs.toFixed(2)}ms, cached: ${warmMs.toFixed(3)}ms`);
|
|
264
|
-
assert.ok(warmMs < 1, `cached call took ${warmMs.toFixed(3)}ms, expected < 1ms`);
|
|
265
|
-
|
|
266
|
-
invalidateScannerCache();
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
describe('listClaudeSessions with withFileTypes + parallel read', () => {
|
|
271
|
-
const testHome = join(tmpdir(), `scanner-wft-perf-${Date.now()}`);
|
|
272
|
-
const projectsDir = join(testHome, '.claude', 'projects');
|
|
273
|
-
|
|
274
|
-
it('setup: create 5 project dirs with 10 session files each', () => {
|
|
275
|
-
for (let d = 0; d < 5; d++) {
|
|
276
|
-
const dir = join(projectsDir, `-project-${d}`);
|
|
277
|
-
mkdirSync(dir, { recursive: true });
|
|
278
|
-
for (let f = 0; f < 10; f++) {
|
|
279
|
-
writeFileSync(join(dir, `session-${d}-${f}.jsonl`), JSON.stringify({
|
|
280
|
-
cwd: `/repo/project-${d}`,
|
|
281
|
-
sessionId: `session-${d}-${f}`,
|
|
282
|
-
customTitle: `Session ${d}-${f}`,
|
|
283
|
-
}) + '\n');
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it('50 files across 5 dirs < 500ms', async () => {
|
|
289
|
-
const originalHome = process.env.HOME;
|
|
290
|
-
process.env.HOME = testHome;
|
|
291
|
-
try {
|
|
292
|
-
invalidateScannerCache();
|
|
293
|
-
const start = performance.now();
|
|
294
|
-
const sessions = await listClaudeSessions();
|
|
295
|
-
const totalMs = performance.now() - start;
|
|
296
|
-
console.log(` 50 files / 5 dirs: ${totalMs.toFixed(2)}ms, ${sessions.length} sessions`);
|
|
297
|
-
assert.equal(sessions.length, 50);
|
|
298
|
-
assert.ok(totalMs < 500, `took ${totalMs.toFixed(2)}ms, expected < 500ms`);
|
|
299
|
-
} finally {
|
|
300
|
-
process.env.HOME = originalHome;
|
|
301
|
-
invalidateScannerCache();
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
it('parallel must be faster than sequential threshold', async () => {
|
|
306
|
-
const originalHome = process.env.HOME;
|
|
307
|
-
process.env.HOME = testHome;
|
|
308
|
-
try {
|
|
309
|
-
invalidateScannerCache();
|
|
310
|
-
// Parallel (actual implementation)
|
|
311
|
-
const parallelStart = performance.now();
|
|
312
|
-
await listClaudeSessions();
|
|
313
|
-
const parallelMs = performance.now() - parallelStart;
|
|
314
|
-
|
|
315
|
-
console.log(` parallel read: ${parallelMs.toFixed(2)}ms`);
|
|
316
|
-
// Should complete in well under 1 second for 50 small files
|
|
317
|
-
assert.ok(parallelMs < 1000, `parallel took ${parallelMs.toFixed(2)}ms, expected < 1000ms`);
|
|
318
|
-
} finally {
|
|
319
|
-
process.env.HOME = originalHome;
|
|
320
|
-
invalidateScannerCache();
|
|
321
|
-
}
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
it('cleanup', () => {
|
|
325
|
-
rmSync(testHome, { recursive: true, force: true });
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
describe('iterateFirstLines regression guard', () => {
|
|
330
|
-
it('readSessionFileMeta on 1000-line file reads only first lines < 10ms avg', async () => {
|
|
331
|
-
// A large file where cwd+title are in line 1 — should NOT read all 1000 lines
|
|
332
|
-
const tempDir = join(tmpdir(), `ifl-perf-${Date.now()}`);
|
|
333
|
-
mkdirSync(tempDir, { recursive: true });
|
|
334
|
-
const lines: string[] = [];
|
|
335
|
-
lines.push(JSON.stringify({ cwd: '/repo', sessionId: 'ifl-test', customTitle: 'Title here' }));
|
|
336
|
-
for (let i = 1; i < 1000; i++) {
|
|
337
|
-
lines.push(JSON.stringify({
|
|
338
|
-
type: 'assistant',
|
|
339
|
-
message: { role: 'assistant', content: [{ type: 'text', text: 'x'.repeat(500) }] },
|
|
340
|
-
}));
|
|
341
|
-
}
|
|
342
|
-
const filePath = join(tempDir, 'ifl-test.jsonl');
|
|
343
|
-
writeFileSync(filePath, lines.join('\n'));
|
|
344
|
-
|
|
345
|
-
// Should read file but only parse first line before exiting
|
|
346
|
-
const runs = 50;
|
|
347
|
-
const start = performance.now();
|
|
348
|
-
for (let i = 0; i < runs; i++) await readSessionFileMeta(filePath, 'claude');
|
|
349
|
-
const totalMs = performance.now() - start;
|
|
350
|
-
const avgMs = totalMs / runs;
|
|
351
|
-
|
|
352
|
-
console.log(` 1000-line early-exit: ${totalMs.toFixed(2)}ms total, ${avgMs.toFixed(3)}ms avg`);
|
|
353
|
-
// Even though the file is ~500KB, readFile is fast and we only parse 1 line
|
|
354
|
-
assert.ok(avgMs < 10, `avg ${avgMs.toFixed(3)}ms, expected < 10ms`);
|
|
355
|
-
|
|
356
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
357
|
-
});
|
|
358
|
-
});
|
|
359
|
-
});
|