cvc-tui 0.4.0 → 0.4.2
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/entry.js +71148 -61
- package/package.json +2 -2
- package/dist/app/completion.js +0 -102
- package/dist/app/createGatewayEventHandler.js +0 -508
- package/dist/app/createSlashHandler.js +0 -101
- package/dist/app/delegationStore.js +0 -51
- package/dist/app/gatewayContext.js +0 -17
- package/dist/app/historyStore.js +0 -123
- package/dist/app/inputBuffer.js +0 -120
- package/dist/app/inputSelectionStore.js +0 -8
- package/dist/app/inputStore.js +0 -28
- package/dist/app/interfaces.js +0 -6
- package/dist/app/overlayStore.js +0 -40
- package/dist/app/promptStore.js +0 -44
- package/dist/app/queueStore.js +0 -25
- package/dist/app/scroll.js +0 -44
- package/dist/app/setupHandoff.js +0 -28
- package/dist/app/slash/commands/core.js +0 -479
- package/dist/app/slash/commands/debug.js +0 -44
- package/dist/app/slash/commands/ops.js +0 -498
- package/dist/app/slash/commands/session.js +0 -431
- package/dist/app/slash/commands/setup.js +0 -20
- package/dist/app/slash/commands/toggles.js +0 -40
- package/dist/app/slash/registry.js +0 -18
- package/dist/app/slash/types.js +0 -1
- package/dist/app/spawnHistoryStore.js +0 -105
- package/dist/app/turnController.js +0 -650
- package/dist/app/turnStore.js +0 -48
- package/dist/app/uiStore.js +0 -36
- package/dist/app/useComposerState.js +0 -265
- package/dist/app/useConfigSync.js +0 -144
- package/dist/app/useInputHandlers.js +0 -403
- package/dist/app/useLongRunToolCharms.js +0 -50
- package/dist/app/useMainApp.js +0 -629
- package/dist/app/useSessionLifecycle.js +0 -175
- package/dist/app/useSubmission.js +0 -287
- package/dist/app.js +0 -15
- package/dist/banner.js +0 -57
- package/dist/components/agentsOverlay.js +0 -474
- package/dist/components/appChrome.js +0 -252
- package/dist/components/appLayout.js +0 -121
- package/dist/components/appOverlays.js +0 -65
- package/dist/components/branding.js +0 -97
- package/dist/components/fpsOverlay.js +0 -22
- package/dist/components/helpHint.js +0 -21
- package/dist/components/markdown.js +0 -501
- package/dist/components/maskedPrompt.js +0 -12
- package/dist/components/messageLine.js +0 -82
- package/dist/components/modelPicker.js +0 -254
- package/dist/components/overlayControls.js +0 -30
- package/dist/components/overlays/confirmPrompt.js +0 -25
- package/dist/components/overlays/helpOverlay.js +0 -76
- package/dist/components/overlays/historySearch.js +0 -49
- package/dist/components/overlays/modelPicker.js +0 -60
- package/dist/components/overlays/overlayUtils.js +0 -19
- package/dist/components/overlays/secretPrompt.js +0 -36
- package/dist/components/overlays/sessionPicker.js +0 -93
- package/dist/components/overlays/skillsHub.js +0 -71
- package/dist/components/prompts.js +0 -95
- package/dist/components/queuedMessages.js +0 -24
- package/dist/components/sessionPicker.js +0 -130
- package/dist/components/skillsHub.js +0 -165
- package/dist/components/streamingAssistant.js +0 -35
- package/dist/components/streamingMarkdown.js +0 -144
- package/dist/components/textInput.js +0 -794
- package/dist/components/themed.js +0 -12
- package/dist/components/thinking.js +0 -496
- package/dist/components/todoPanel.js +0 -40
- package/dist/components/transcript.js +0 -22
- package/dist/config/env.js +0 -18
- package/dist/config/limits.js +0 -22
- package/dist/config/timing.js +0 -18
- package/dist/content/charms.js +0 -5
- package/dist/content/faces.js +0 -21
- package/dist/content/fortunes.js +0 -29
- package/dist/content/hotkeys.js +0 -38
- package/dist/content/placeholders.js +0 -15
- package/dist/content/setup.js +0 -14
- package/dist/content/verbs.js +0 -41
- package/dist/domain/details.js +0 -53
- package/dist/domain/messages.js +0 -63
- package/dist/domain/paths.js +0 -16
- package/dist/domain/providers.js +0 -11
- package/dist/domain/roles.js +0 -6
- package/dist/domain/slash.js +0 -11
- package/dist/domain/usage.js +0 -1
- package/dist/domain/viewport.js +0 -33
- package/dist/gateway/client.js +0 -312
- package/dist/gatewayClient.js +0 -574
- package/dist/gatewayTypes.js +0 -1
- package/dist/hooks/useCompletion.js +0 -86
- package/dist/hooks/useGitBranch.js +0 -58
- package/dist/hooks/useInputHistory.js +0 -12
- package/dist/hooks/useQueue.js +0 -57
- package/dist/hooks/useVirtualHistory.js +0 -401
- package/dist/lib/circularBuffer.js +0 -43
- package/dist/lib/clipboard.js +0 -126
- package/dist/lib/editor.js +0 -41
- package/dist/lib/editor.test.js +0 -58
- package/dist/lib/emoji.js +0 -49
- package/dist/lib/externalCli.js +0 -11
- package/dist/lib/forceTruecolor.js +0 -26
- package/dist/lib/fpsStore.js +0 -36
- package/dist/lib/gracefulExit.js +0 -29
- package/dist/lib/history.js +0 -69
- package/dist/lib/inputMetrics.js +0 -143
- package/dist/lib/liveProgress.js +0 -51
- package/dist/lib/liveProgress.test.js +0 -89
- package/dist/lib/mathUnicode.js +0 -685
- package/dist/lib/memory.js +0 -123
- package/dist/lib/memoryMonitor.js +0 -76
- package/dist/lib/messages.js +0 -3
- package/dist/lib/messages.test.js +0 -25
- package/dist/lib/osc52.js +0 -53
- package/dist/lib/perfPane.js +0 -94
- package/dist/lib/platform.js +0 -312
- package/dist/lib/precisionWheel.js +0 -25
- package/dist/lib/reasoning.js +0 -39
- package/dist/lib/rpc.js +0 -26
- package/dist/lib/subagentTree.js +0 -287
- package/dist/lib/syntax.js +0 -89
- package/dist/lib/terminalModes.js +0 -46
- package/dist/lib/terminalParity.js +0 -48
- package/dist/lib/terminalSetup.js +0 -321
- package/dist/lib/text.js +0 -203
- package/dist/lib/text.test.js +0 -18
- package/dist/lib/todo.js +0 -2
- package/dist/lib/todo.test.js +0 -22
- package/dist/lib/viewportStore.js +0 -82
- package/dist/lib/virtualHeights.js +0 -61
- package/dist/lib/wheelAccel.js +0 -143
- package/dist/theme.js +0 -398
- package/dist/types.js +0 -1
package/dist/lib/memory.js
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
// SPDX-License-Identifier: MIT
|
|
3
|
-
// Ported from CVC Agent (https://github.com/NousResearch/cvc)
|
|
4
|
-
// Original Copyright (c) 2025 Nous Research. CVC adaptations (c) 2026 Jai Kumar Meena.
|
|
5
|
-
import { createWriteStream } from 'node:fs';
|
|
6
|
-
import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
|
|
7
|
-
import { homedir, tmpdir } from 'node:os';
|
|
8
|
-
import { join } from 'node:path';
|
|
9
|
-
import { pipeline } from 'node:stream/promises';
|
|
10
|
-
import { getHeapSnapshot, getHeapSpaceStatistics, getHeapStatistics } from 'node:v8';
|
|
11
|
-
export async function captureMemoryDiagnostics(trigger) {
|
|
12
|
-
const usage = process.memoryUsage();
|
|
13
|
-
const heapStats = getHeapStatistics();
|
|
14
|
-
const resourceUsage = process.resourceUsage();
|
|
15
|
-
const uptimeSeconds = process.uptime();
|
|
16
|
-
// Not available on Bun / older Node.
|
|
17
|
-
let heapSpaces;
|
|
18
|
-
try {
|
|
19
|
-
heapSpaces = getHeapSpaceStatistics();
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
/* noop */
|
|
23
|
-
}
|
|
24
|
-
const internals = process;
|
|
25
|
-
const activeHandles = internals._getActiveHandles().length;
|
|
26
|
-
const activeRequests = internals._getActiveRequests().length;
|
|
27
|
-
const openFileDescriptors = await swallow(async () => (await readdir('/proc/self/fd')).length);
|
|
28
|
-
const smapsRollup = await swallow(() => readFile('/proc/self/smaps_rollup', 'utf8'));
|
|
29
|
-
const nativeMemory = usage.rss - usage.heapUsed;
|
|
30
|
-
// Real growth rate since STARTED_AT (captured at module load) — NOT a lifetime
|
|
31
|
-
// average of rss/uptime, which would report phantom "growth" for a stable process.
|
|
32
|
-
const elapsed = Math.max(0, uptimeSeconds - STARTED_AT.uptime);
|
|
33
|
-
const bytesPerSecond = elapsed > 0 ? (usage.rss - STARTED_AT.rss) / elapsed : 0;
|
|
34
|
-
const mbPerHour = (bytesPerSecond * 3600) / (1024 * 1024);
|
|
35
|
-
const potentialLeaks = [
|
|
36
|
-
heapStats.number_of_detached_contexts > 0 &&
|
|
37
|
-
`${heapStats.number_of_detached_contexts} detached context(s) — possible component/closure leak`,
|
|
38
|
-
activeHandles > 100 && `${activeHandles} active handles — possible timer/socket leak`,
|
|
39
|
-
nativeMemory > usage.heapUsed && 'Native memory > heap — leak may be in native addons',
|
|
40
|
-
mbPerHour > 100 && `High memory growth rate: ${mbPerHour.toFixed(1)} MB/hour`,
|
|
41
|
-
openFileDescriptors && openFileDescriptors > 500 && `${openFileDescriptors} open FDs — possible file/socket leak`
|
|
42
|
-
].filter((s) => typeof s === 'string');
|
|
43
|
-
return {
|
|
44
|
-
activeHandles,
|
|
45
|
-
activeRequests,
|
|
46
|
-
analysis: {
|
|
47
|
-
potentialLeaks,
|
|
48
|
-
recommendation: potentialLeaks.length
|
|
49
|
-
? `WARNING: ${potentialLeaks.length} potential leak indicator(s). See potentialLeaks.`
|
|
50
|
-
: 'No obvious leak indicators. Inspect heap snapshot for retained objects.'
|
|
51
|
-
},
|
|
52
|
-
memoryGrowthRate: { bytesPerSecond, mbPerHour },
|
|
53
|
-
memoryUsage: {
|
|
54
|
-
arrayBuffers: usage.arrayBuffers,
|
|
55
|
-
external: usage.external,
|
|
56
|
-
heapTotal: usage.heapTotal,
|
|
57
|
-
heapUsed: usage.heapUsed,
|
|
58
|
-
rss: usage.rss
|
|
59
|
-
},
|
|
60
|
-
nodeVersion: process.version,
|
|
61
|
-
openFileDescriptors,
|
|
62
|
-
platform: process.platform,
|
|
63
|
-
resourceUsage: {
|
|
64
|
-
maxRSS: resourceUsage.maxRSS * 1024,
|
|
65
|
-
systemCPUTime: resourceUsage.systemCPUTime,
|
|
66
|
-
userCPUTime: resourceUsage.userCPUTime
|
|
67
|
-
},
|
|
68
|
-
smapsRollup,
|
|
69
|
-
timestamp: new Date().toISOString(),
|
|
70
|
-
trigger,
|
|
71
|
-
uptimeSeconds,
|
|
72
|
-
v8HeapSpaces: heapSpaces?.map(s => ({
|
|
73
|
-
available: s.space_available_size,
|
|
74
|
-
name: s.space_name,
|
|
75
|
-
size: s.space_size,
|
|
76
|
-
used: s.space_used_size
|
|
77
|
-
})),
|
|
78
|
-
v8HeapStats: {
|
|
79
|
-
detachedContexts: heapStats.number_of_detached_contexts,
|
|
80
|
-
heapSizeLimit: heapStats.heap_size_limit,
|
|
81
|
-
mallocedMemory: heapStats.malloced_memory,
|
|
82
|
-
nativeContexts: heapStats.number_of_native_contexts,
|
|
83
|
-
peakMallocedMemory: heapStats.peak_malloced_memory
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
export async function performHeapDump(trigger = 'manual') {
|
|
88
|
-
try {
|
|
89
|
-
// Diagnostics first — heap-snapshot serialization can crash on very large
|
|
90
|
-
// heaps, and the JSON sidecar is the most actionable artifact if so.
|
|
91
|
-
const diagnostics = await captureMemoryDiagnostics(trigger);
|
|
92
|
-
const dir = process.env.HERMES_HEAPDUMP_DIR?.trim() || join(homedir() || tmpdir(), '.hermes', 'heapdumps');
|
|
93
|
-
await mkdir(dir, { recursive: true });
|
|
94
|
-
const base = `hermes-${new Date().toISOString().replace(/[:.]/g, '-')}-${process.pid}-${trigger}`;
|
|
95
|
-
const heapPath = join(dir, `${base}.heapsnapshot`);
|
|
96
|
-
const diagPath = join(dir, `${base}.diagnostics.json`);
|
|
97
|
-
await writeFile(diagPath, JSON.stringify(diagnostics, null, 2), { mode: 0o600 });
|
|
98
|
-
await pipeline(getHeapSnapshot(), createWriteStream(heapPath, { mode: 0o600 }));
|
|
99
|
-
return { diagPath, heapPath, success: true };
|
|
100
|
-
}
|
|
101
|
-
catch (e) {
|
|
102
|
-
return { error: e instanceof Error ? e.message : String(e), success: false };
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
export function formatBytes(bytes) {
|
|
106
|
-
if (!Number.isFinite(bytes) || bytes <= 0) {
|
|
107
|
-
return '0B';
|
|
108
|
-
}
|
|
109
|
-
const exp = Math.min(UNITS.length - 1, Math.floor(Math.log10(bytes) / 3));
|
|
110
|
-
const value = bytes / 1024 ** exp;
|
|
111
|
-
return `${value >= 100 ? value.toFixed(0) : value.toFixed(1)}${UNITS[exp]}`;
|
|
112
|
-
}
|
|
113
|
-
const UNITS = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
114
|
-
const STARTED_AT = { rss: process.memoryUsage().rss, uptime: process.uptime() };
|
|
115
|
-
// Returns undefined when the probe isn't available (non-Linux paths, sandboxed FS).
|
|
116
|
-
const swallow = async (fn) => {
|
|
117
|
-
try {
|
|
118
|
-
return await fn();
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
return undefined;
|
|
122
|
-
}
|
|
123
|
-
};
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
// SPDX-License-Identifier: MIT
|
|
3
|
-
// Ported from CVC Agent (https://github.com/NousResearch/cvc)
|
|
4
|
-
// Original Copyright (c) 2025 Nous Research. CVC adaptations (c) 2026 Jai Kumar Meena.
|
|
5
|
-
import { performHeapDump } from './memory.js';
|
|
6
|
-
const GB = 1024 ** 3;
|
|
7
|
-
// Deferred @cvc/ink import: loading `@cvc/ink` at module top-level
|
|
8
|
-
// pulls the full ~414KB Ink bundle (React, renderer, components, hooks) onto
|
|
9
|
-
// the critical path before the Python gateway can even be spawned. That
|
|
10
|
-
// serialised roughly 150ms of Node work in front of gw.start() on every
|
|
11
|
-
// cold `hermes --tui` launch.
|
|
12
|
-
//
|
|
13
|
-
// evictInkCaches only runs inside `tick()`, which fires on a 10s timer and
|
|
14
|
-
// only when heap pressure crosses the high-water mark — by then Ink has
|
|
15
|
-
// long since been loaded by the app entry. This dynamic import is a no-op
|
|
16
|
-
// on the hot path (module is already in the ESM cache); when a startup
|
|
17
|
-
// spike somehow trips the threshold before the app registers its own Ink
|
|
18
|
-
// import, we pay the load cost exactly once, inside the tick that needs it.
|
|
19
|
-
let _evictInkCaches = null;
|
|
20
|
-
let _evictInkCachesPromise = null;
|
|
21
|
-
async function _ensureEvictInkCaches() {
|
|
22
|
-
if (_evictInkCaches) {
|
|
23
|
-
return _evictInkCaches;
|
|
24
|
-
}
|
|
25
|
-
_evictInkCachesPromise ??= import('@cvc/ink')
|
|
26
|
-
.then(mod => {
|
|
27
|
-
_evictInkCaches = mod.evictInkCaches;
|
|
28
|
-
return _evictInkCaches;
|
|
29
|
-
})
|
|
30
|
-
.catch(err => {
|
|
31
|
-
_evictInkCachesPromise = null;
|
|
32
|
-
throw err;
|
|
33
|
-
});
|
|
34
|
-
return _evictInkCachesPromise;
|
|
35
|
-
}
|
|
36
|
-
export function startMemoryMonitor({ criticalBytes = 2.5 * GB, highBytes = 1.5 * GB, intervalMs = 10_000, onCritical, onHigh } = {}) {
|
|
37
|
-
const dumped = new Set();
|
|
38
|
-
const inFlight = new Set();
|
|
39
|
-
const tick = async () => {
|
|
40
|
-
const { heapUsed, rss } = process.memoryUsage();
|
|
41
|
-
const level = heapUsed >= criticalBytes ? 'critical' : heapUsed >= highBytes ? 'high' : 'normal';
|
|
42
|
-
if (level === 'normal') {
|
|
43
|
-
dumped.clear();
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
if (dumped.has(level) || inFlight.has(level)) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
inFlight.add(level);
|
|
50
|
-
// Prune Ink content caches before dump/exit — half on 'high' (recoverable),
|
|
51
|
-
// full on 'critical' (post-dump RSS reduction, keeps user running).
|
|
52
|
-
// Deferred import keeps `@cvc/ink` off the cold-start critical path;
|
|
53
|
-
// by the time a tick fires 10s after launch the app has already loaded
|
|
54
|
-
// the same module, so this resolves instantly from the ESM cache.
|
|
55
|
-
try {
|
|
56
|
-
try {
|
|
57
|
-
const evictInkCaches = await _ensureEvictInkCaches();
|
|
58
|
-
evictInkCaches(level === 'critical' ? 'all' : 'half');
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
// Best-effort: if the dynamic import fails for any reason we still
|
|
62
|
-
// continue to the heap dump below so the user gets diagnostics.
|
|
63
|
-
}
|
|
64
|
-
dumped.add(level);
|
|
65
|
-
const dump = await performHeapDump(level === 'critical' ? 'auto-critical' : 'auto-high').catch(() => null);
|
|
66
|
-
const snap = { heapUsed, level, rss };
|
|
67
|
-
(level === 'critical' ? onCritical : onHigh)?.(snap, dump);
|
|
68
|
-
}
|
|
69
|
-
finally {
|
|
70
|
-
inFlight.delete(level);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
const handle = setInterval(() => void tick(), intervalMs);
|
|
74
|
-
handle.unref?.();
|
|
75
|
-
return () => clearInterval(handle);
|
|
76
|
-
}
|
package/dist/lib/messages.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { appendToolShelfMessage } from './liveProgress.js';
|
|
2
|
-
export const appendTranscriptMessage = (prev, msg) => appendToolShelfMessage(prev, msg);
|
|
3
|
-
export const upsert = (prev, role, text) => prev.at(-1)?.role === role ? [...prev.slice(0, -1), { role, text }] : [...prev, { role, text }];
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
// SPDX-License-Identifier: MIT
|
|
3
|
-
// Ported from CVC Agent (https://github.com/NousResearch/cvc)
|
|
4
|
-
// Original Copyright (c) 2025 Nous Research. CVC adaptations (c) 2026 Jai Kumar Meena.
|
|
5
|
-
import { describe, expect, it } from 'vitest';
|
|
6
|
-
import { appendTranscriptMessage } from './messages.js';
|
|
7
|
-
describe('appendTranscriptMessage', () => {
|
|
8
|
-
it('merges adjacent tool-only shelves into one transcript row', () => {
|
|
9
|
-
const out = appendTranscriptMessage([{ kind: 'trail', role: 'system', text: '', tools: ['Terminal("one") ✓'] }], {
|
|
10
|
-
kind: 'trail',
|
|
11
|
-
role: 'system',
|
|
12
|
-
text: '',
|
|
13
|
-
tools: ['Terminal("two") ✓']
|
|
14
|
-
});
|
|
15
|
-
expect(out).toEqual([
|
|
16
|
-
{ kind: 'trail', role: 'system', text: '', tools: ['Terminal("one") ✓', 'Terminal("two") ✓'] }
|
|
17
|
-
]);
|
|
18
|
-
});
|
|
19
|
-
it('merges tool shelves into the nearest thinking shelf', () => {
|
|
20
|
-
const out = appendTranscriptMessage([{ kind: 'trail', role: 'system', text: '', thinking: 'plan', tools: ['Terminal("one") ✓'] }], { kind: 'trail', role: 'system', text: '', tools: ['Terminal("two") ✓'] });
|
|
21
|
-
expect(out).toEqual([
|
|
22
|
-
{ kind: 'trail', role: 'system', text: '', thinking: 'plan', tools: ['Terminal("one") ✓', 'Terminal("two") ✓'] }
|
|
23
|
-
]);
|
|
24
|
-
});
|
|
25
|
-
});
|
package/dist/lib/osc52.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
// SPDX-License-Identifier: MIT
|
|
3
|
-
// Ported from CVC Agent (https://github.com/NousResearch/cvc)
|
|
4
|
-
// Original Copyright (c) 2025 Nous Research. CVC adaptations (c) 2026 Jai Kumar Meena.
|
|
5
|
-
const ESC = '\x1b';
|
|
6
|
-
const BEL = '\x07';
|
|
7
|
-
const ST = `${ESC}\\`;
|
|
8
|
-
export const OSC52_CLIPBOARD_QUERY = `${ESC}]52;c;?${BEL}`;
|
|
9
|
-
function wrapForMultiplexer(sequence) {
|
|
10
|
-
if (process.env['TMUX']) {
|
|
11
|
-
return `${ESC}Ptmux;${sequence.split(ESC).join(ESC + ESC)}${ST}`;
|
|
12
|
-
}
|
|
13
|
-
if (process.env['STY']) {
|
|
14
|
-
return `${ESC}P${sequence}${ST}`;
|
|
15
|
-
}
|
|
16
|
-
return sequence;
|
|
17
|
-
}
|
|
18
|
-
export function buildOsc52ClipboardQuery() {
|
|
19
|
-
return wrapForMultiplexer(OSC52_CLIPBOARD_QUERY);
|
|
20
|
-
}
|
|
21
|
-
export function parseOsc52ClipboardData(data) {
|
|
22
|
-
const firstSep = data.indexOf(';');
|
|
23
|
-
if (firstSep === -1) {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
const selection = data.slice(0, firstSep);
|
|
27
|
-
const payload = data.slice(firstSep + 1);
|
|
28
|
-
if ((selection !== 'c' && selection !== 'p') || !payload || payload === '?') {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
try {
|
|
32
|
-
return Buffer.from(payload, 'base64').toString('utf8');
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
export async function readOsc52Clipboard(querier, timeoutMs = 500) {
|
|
39
|
-
if (!querier) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
const timeout = new Promise(resolve => setTimeout(resolve, timeoutMs));
|
|
43
|
-
const query = querier.send({
|
|
44
|
-
request: buildOsc52ClipboardQuery(),
|
|
45
|
-
match: (r) => {
|
|
46
|
-
return !!r && typeof r === 'object' && r.type === 'osc' && r.code === 52;
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
const response = await Promise.race([query, timeout]);
|
|
50
|
-
await querier.flush();
|
|
51
|
-
return response ? parseOsc52ClipboardData(response.data) : null;
|
|
52
|
-
}
|
|
53
|
-
export const writeOsc52Clipboard = (s) => process.stdout.write(`\x1b]52;c;${Buffer.from(s, 'utf8').toString('base64')}\x07`);
|
package/dist/lib/perfPane.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
// @ts-nocheck
|
|
3
|
-
// SPDX-License-Identifier: MIT
|
|
4
|
-
// Ported from CVC Agent (https://github.com/NousResearch/cvc)
|
|
5
|
-
// Original Copyright (c) 2025 Nous Research. CVC adaptations (c) 2026 Jai Kumar Meena.
|
|
6
|
-
// Perf instrumentation for the full render pipeline.
|
|
7
|
-
//
|
|
8
|
-
// PerfPane (React.Profiler) → per-pane commit times
|
|
9
|
-
// logFrameEvent (ink.onFrame) → yoga / renderer / diff / optimize / write
|
|
10
|
-
// phases + yoga counters + scroll fast-path
|
|
11
|
-
//
|
|
12
|
-
// Both gate on HERMES_DEV_PERF=1 and dump JSON-lines (default ~/.hermes/perf.log,
|
|
13
|
-
// override HERMES_DEV_PERF_LOG). Tagged { src: 'react' | 'frame' } for jq.
|
|
14
|
-
// HERMES_DEV_PERF_MS (default 2) skips sub-ms idle frames; set 0 to capture all.
|
|
15
|
-
//
|
|
16
|
-
// Zero cost when unset: PerfPane returns children directly, logFrameEvent is
|
|
17
|
-
// undefined so ink doesn't pay the timing cost.
|
|
18
|
-
import { appendFileSync, mkdirSync } from 'node:fs';
|
|
19
|
-
import { homedir } from 'node:os';
|
|
20
|
-
import { dirname, join } from 'node:path';
|
|
21
|
-
import { scrollFastPathStats } from '@cvc/ink';
|
|
22
|
-
import { Profiler } from 'react';
|
|
23
|
-
const ENABLED = /^(?:1|true|yes|on)$/i.test((process.env.HERMES_DEV_PERF ?? '').trim());
|
|
24
|
-
const THRESHOLD_MS = Number(process.env.HERMES_DEV_PERF_MS ?? '2') || 0;
|
|
25
|
-
const LOG_PATH = process.env.HERMES_DEV_PERF_LOG?.trim() || join(homedir(), '.hermes', 'perf.log');
|
|
26
|
-
let logReady = false;
|
|
27
|
-
const writeRow = (row) => {
|
|
28
|
-
if (!logReady) {
|
|
29
|
-
logReady = true;
|
|
30
|
-
try {
|
|
31
|
-
mkdirSync(dirname(LOG_PATH), { recursive: true });
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
// Best-effort — never crash the TUI to log a sample.
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
appendFileSync(LOG_PATH, `${JSON.stringify(row)}\n`);
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
/* best-effort */
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
const round2 = (n) => Math.round(n * 100) / 100;
|
|
45
|
-
const onRender = (id, phase, actualMs, baseMs, startTime, commitTime) => {
|
|
46
|
-
if (actualMs < THRESHOLD_MS) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
writeRow({
|
|
50
|
-
actualMs: round2(actualMs),
|
|
51
|
-
baseMs: round2(baseMs),
|
|
52
|
-
commitTimeMs: round2(commitTime),
|
|
53
|
-
id,
|
|
54
|
-
phase,
|
|
55
|
-
src: 'react',
|
|
56
|
-
startTimeMs: round2(startTime),
|
|
57
|
-
ts: Date.now()
|
|
58
|
-
});
|
|
59
|
-
};
|
|
60
|
-
export function PerfPane({ children, id }) {
|
|
61
|
-
if (!ENABLED) {
|
|
62
|
-
return children;
|
|
63
|
-
}
|
|
64
|
-
return (_jsx(Profiler, { id: id, onRender: onRender, children: children }));
|
|
65
|
-
}
|
|
66
|
-
export const logFrameEvent = ENABLED
|
|
67
|
-
? (event) => {
|
|
68
|
-
if (event.durationMs < THRESHOLD_MS) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
writeRow({
|
|
72
|
-
durationMs: round2(event.durationMs),
|
|
73
|
-
// Cumulative counters — consumers diff pairs to get per-frame deltas.
|
|
74
|
-
fastPath: { ...scrollFastPathStats, declined: { ...scrollFastPathStats.declined } },
|
|
75
|
-
flickers: event.flickers.length ? event.flickers : undefined,
|
|
76
|
-
phases: event.phases
|
|
77
|
-
? {
|
|
78
|
-
...event.phases,
|
|
79
|
-
commit: round2(event.phases.commit),
|
|
80
|
-
diff: round2(event.phases.diff),
|
|
81
|
-
optimize: round2(event.phases.optimize),
|
|
82
|
-
prevFrameDrainMs: round2(event.phases.prevFrameDrainMs),
|
|
83
|
-
renderer: round2(event.phases.renderer),
|
|
84
|
-
write: round2(event.phases.write),
|
|
85
|
-
yoga: round2(event.phases.yoga)
|
|
86
|
-
}
|
|
87
|
-
: undefined,
|
|
88
|
-
src: 'frame',
|
|
89
|
-
ts: Date.now()
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
: undefined;
|
|
93
|
-
export const PERF_ENABLED = ENABLED;
|
|
94
|
-
export const PERF_LOG_PATH = LOG_PATH;
|