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
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
// @ts-nocheck
|
|
3
|
-
// CVC skillsHub overlay — list skills (via gateway or supplied prop), search/filter,
|
|
4
|
-
// arrow-key navigable, Enter triggers an onActivate callback (e.g. to inject the
|
|
5
|
-
// skill into the next user message).
|
|
6
|
-
import { useEffect, useMemo, useState } from 'react';
|
|
7
|
-
import { Box, Text, useInput } from 'ink';
|
|
8
|
-
import { CVC_THEME } from '../../types.js';
|
|
9
|
-
import { filterRows, windowItems } from './overlayUtils.js';
|
|
10
|
-
const VISIBLE = 12;
|
|
11
|
-
export const SkillsHub = ({ skills, loadSkills, onActivate, onCancel, }) => {
|
|
12
|
-
const [all, setAll] = useState(skills ?? []);
|
|
13
|
-
const [loading, setLoading] = useState(!skills && Boolean(loadSkills));
|
|
14
|
-
const [query, setQuery] = useState('');
|
|
15
|
-
const [idx, setIdx] = useState(0);
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
if (skills || !loadSkills)
|
|
18
|
-
return;
|
|
19
|
-
let cancelled = false;
|
|
20
|
-
loadSkills()
|
|
21
|
-
.then(list => {
|
|
22
|
-
if (!cancelled) {
|
|
23
|
-
setAll(list);
|
|
24
|
-
setLoading(false);
|
|
25
|
-
}
|
|
26
|
-
})
|
|
27
|
-
.catch(() => {
|
|
28
|
-
if (!cancelled)
|
|
29
|
-
setLoading(false);
|
|
30
|
-
});
|
|
31
|
-
return () => {
|
|
32
|
-
cancelled = true;
|
|
33
|
-
};
|
|
34
|
-
}, [skills, loadSkills]);
|
|
35
|
-
const filtered = useMemo(() => filterRows(all, query, s => `${s.name} ${s.description ?? ''} ${s.category ?? ''}`), [all, query]);
|
|
36
|
-
const safeIdx = Math.min(idx, Math.max(0, filtered.length - 1));
|
|
37
|
-
useInput((input, key) => {
|
|
38
|
-
if (key.escape)
|
|
39
|
-
return onCancel();
|
|
40
|
-
if (key.upArrow && safeIdx > 0)
|
|
41
|
-
return setIdx(safeIdx - 1);
|
|
42
|
-
if (key.downArrow && safeIdx < filtered.length - 1)
|
|
43
|
-
return setIdx(safeIdx + 1);
|
|
44
|
-
if (key.return) {
|
|
45
|
-
const s = filtered[safeIdx];
|
|
46
|
-
if (s)
|
|
47
|
-
onActivate(s);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (key.backspace || key.delete) {
|
|
51
|
-
setQuery(q => q.slice(0, -1));
|
|
52
|
-
setIdx(0);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
if (input && !key.ctrl && !key.meta && !key.tab) {
|
|
56
|
-
setQuery(q => q + input);
|
|
57
|
-
setIdx(0);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
const rows = filtered.map(s => {
|
|
61
|
-
const cat = s.category ? `[${s.category}] ` : '';
|
|
62
|
-
const desc = s.description ? ` — ${s.description}` : '';
|
|
63
|
-
return `${cat}${s.name}${desc}`;
|
|
64
|
-
});
|
|
65
|
-
const { items, offset } = windowItems(rows, safeIdx, VISIBLE);
|
|
66
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: CVC_THEME.primary, bold: true, children: ["Skills Hub (", filtered.length, "/", all.length, ")"] }), _jsxs(Text, { dimColor: true, children: ["filter: ", query || '(none)'] }), loading ? (_jsx(Text, { dimColor: true, children: "loading skills\u2026" })) : items.length === 0 ? (_jsx(Text, { dimColor: true, children: "no skills match" })) : (_jsxs(_Fragment, { children: [offset > 0 ? _jsx(Text, { dimColor: true, children: ` ↑ ${offset} more` }) : _jsx(Text, { children: " " }), items.map((row, i) => {
|
|
67
|
-
const k = offset + i;
|
|
68
|
-
const active = safeIdx === k;
|
|
69
|
-
return (_jsxs(Text, { color: active ? CVC_THEME.primary : undefined, inverse: active, bold: active, children: [active ? '▸ ' : ' ', row] }, filtered[k]?.name ?? `sk-${k}`));
|
|
70
|
-
}), offset + VISIBLE < rows.length ? (_jsx(Text, { dimColor: true, children: ` ↓ ${rows.length - offset - VISIBLE} more` })) : (_jsx(Text, { children: " " }))] })), _jsx(Text, { dimColor: true, children: "type to filter \u00B7 \u2191/\u2193 select \u00B7 Enter activate \u00B7 Esc cancel" })] }));
|
|
71
|
-
};
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, 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
|
-
import { Box, Text, useInput } from '@cvc/ink';
|
|
7
|
-
import { useState } from 'react';
|
|
8
|
-
import { isMac } from '../lib/platform.js';
|
|
9
|
-
import { TextInput } from './textInput.js';
|
|
10
|
-
const OPTS = ['once', 'session', 'always', 'deny'];
|
|
11
|
-
const LABELS = { always: 'Always allow', deny: 'Deny', once: 'Allow once', session: 'Allow this session' };
|
|
12
|
-
const CMD_PREVIEW_LINES = 10;
|
|
13
|
-
export function ApprovalPrompt({ onChoice, req, t }) {
|
|
14
|
-
const [sel, setSel] = useState(0);
|
|
15
|
-
useInput((ch, key) => {
|
|
16
|
-
if (key.upArrow && sel > 0) {
|
|
17
|
-
setSel(s => s - 1);
|
|
18
|
-
}
|
|
19
|
-
if (key.downArrow && sel < OPTS.length - 1) {
|
|
20
|
-
setSel(s => s + 1);
|
|
21
|
-
}
|
|
22
|
-
const n = parseInt(ch, 10);
|
|
23
|
-
if (n >= 1 && n <= OPTS.length) {
|
|
24
|
-
onChoice(OPTS[n - 1]);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (key.return) {
|
|
28
|
-
onChoice(OPTS[sel]);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
const rawLines = req.command.split('\n');
|
|
32
|
-
const shown = rawLines.slice(0, CMD_PREVIEW_LINES);
|
|
33
|
-
const overflow = rawLines.length - shown.length;
|
|
34
|
-
return (_jsxs(Box, { borderColor: t.color.warn, borderStyle: "double", flexDirection: "column", paddingX: 1, children: [_jsxs(Text, { bold: true, color: t.color.warn, children: ["\u26A0 approval required \u00B7 ", req.description] }), _jsxs(Box, { flexDirection: "column", paddingLeft: 1, children: [shown.map((line, i) => (_jsx(Text, { color: t.color.text, wrap: "truncate-end", children: line || ' ' }, i))), overflow > 0 ? (_jsxs(Text, { color: t.color.muted, children: ["\u2026 +", overflow, " more line", overflow === 1 ? '' : 's', " (full text above)"] })) : null] }), _jsx(Text, {}), OPTS.map((o, i) => (_jsx(Text, { children: _jsxs(Text, { bold: sel === i, color: sel === i ? t.color.warn : t.color.muted, inverse: sel === i, children: [sel === i ? '▸ ' : ' ', i + 1, ". ", LABELS[o]] }) }, o))), _jsx(Text, { color: t.color.muted, children: "\u2191/\u2193 select \u00B7 Enter confirm \u00B7 1-4 quick pick \u00B7 Ctrl+C deny" })] }));
|
|
35
|
-
}
|
|
36
|
-
export function ClarifyPrompt({ cols = 80, onAnswer, onCancel, req, t }) {
|
|
37
|
-
const [sel, setSel] = useState(0);
|
|
38
|
-
const [custom, setCustom] = useState('');
|
|
39
|
-
const [typing, setTyping] = useState(false);
|
|
40
|
-
const choices = req.choices ?? [];
|
|
41
|
-
const heading = (_jsxs(Text, { bold: true, children: [_jsx(Text, { color: t.color.accent, children: "ask" }), _jsxs(Text, { color: t.color.text, children: [" ", req.question] })] }));
|
|
42
|
-
useInput((ch, key) => {
|
|
43
|
-
if (key.escape) {
|
|
44
|
-
typing && choices.length ? setTyping(false) : onCancel();
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (typing || !choices.length) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (key.upArrow && sel > 0) {
|
|
51
|
-
setSel(s => s - 1);
|
|
52
|
-
}
|
|
53
|
-
if (key.downArrow && sel < choices.length) {
|
|
54
|
-
setSel(s => s + 1);
|
|
55
|
-
}
|
|
56
|
-
if (key.return) {
|
|
57
|
-
sel === choices.length ? setTyping(true) : choices[sel] && onAnswer(choices[sel]);
|
|
58
|
-
}
|
|
59
|
-
const n = parseInt(ch);
|
|
60
|
-
if (n >= 1 && n <= choices.length) {
|
|
61
|
-
onAnswer(choices[n - 1]);
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
if (typing || !choices.length) {
|
|
65
|
-
return (_jsxs(Box, { flexDirection: "column", children: [heading, _jsxs(Box, { children: [_jsx(Text, { color: t.color.label, children: '> ' }), _jsx(TextInput, { columns: Math.max(20, cols - 6), onChange: setCustom, onSubmit: onAnswer, value: custom })] }), _jsxs(Text, { color: t.color.muted, children: ["Enter send \u00B7 Esc ", choices.length ? 'back' : 'cancel', " \u00B7", ' ', isMac ? 'Cmd+C copy · Cmd+V paste · Ctrl+C cancel' : 'Ctrl+C cancel'] })] }));
|
|
66
|
-
}
|
|
67
|
-
return (_jsxs(Box, { flexDirection: "column", children: [heading, [...choices, 'Other (type your answer)'].map((c, i) => (_jsx(Text, { children: _jsxs(Text, { bold: sel === i, color: sel === i ? t.color.label : t.color.muted, inverse: sel === i, children: [sel === i ? '▸ ' : ' ', i + 1, ". ", c] }) }, i))), _jsxs(Text, { color: t.color.muted, children: ["\u2191/\u2193 select \u00B7 Enter confirm \u00B7 1-", choices.length, " quick pick \u00B7 Esc/Ctrl+C cancel"] })] }));
|
|
68
|
-
}
|
|
69
|
-
export function ConfirmPrompt({ onCancel, onConfirm, req, t }) {
|
|
70
|
-
const [sel, setSel] = useState(0);
|
|
71
|
-
useInput((ch, key) => {
|
|
72
|
-
const lower = ch.toLowerCase();
|
|
73
|
-
if (key.escape || (key.ctrl && lower === 'c') || lower === 'n') {
|
|
74
|
-
return onCancel();
|
|
75
|
-
}
|
|
76
|
-
if (lower === 'y') {
|
|
77
|
-
return onConfirm();
|
|
78
|
-
}
|
|
79
|
-
if (key.upArrow) {
|
|
80
|
-
setSel(0);
|
|
81
|
-
}
|
|
82
|
-
if (key.downArrow) {
|
|
83
|
-
setSel(1);
|
|
84
|
-
}
|
|
85
|
-
if (key.return) {
|
|
86
|
-
sel === 0 ? onCancel() : onConfirm();
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
const accent = req.danger ? t.color.error : t.color.warn;
|
|
90
|
-
const rows = [
|
|
91
|
-
{ color: t.color.text, label: req.cancelLabel ?? 'No' },
|
|
92
|
-
{ color: req.danger ? t.color.error : t.color.text, label: req.confirmLabel ?? 'Yes' }
|
|
93
|
-
];
|
|
94
|
-
return (_jsxs(Box, { borderColor: accent, borderStyle: "double", flexDirection: "column", paddingX: 1, children: [_jsxs(Text, { bold: true, color: accent, children: [req.danger ? '⚠' : '?', " ", req.title] }), req.detail ? (_jsx(Box, { paddingLeft: 1, children: _jsx(Text, { color: t.color.text, wrap: "truncate-end", children: req.detail }) })) : null, _jsx(Text, {}), rows.map((row, i) => (_jsxs(Text, { children: [_jsx(Text, { color: sel === i ? accent : t.color.muted, children: sel === i ? '▸ ' : ' ' }), _jsx(Text, { color: sel === i ? row.color : t.color.muted, children: row.label })] }, row.label))), _jsx(Text, { color: t.color.muted, children: "\u2191/\u2193 select \u00B7 Enter confirm \u00B7 Y/N quick \u00B7 Esc cancel" })] }));
|
|
95
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } 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
|
-
import { Box, Text } from '@cvc/ink';
|
|
7
|
-
import { compactPreview } from '../lib/text.js';
|
|
8
|
-
export const QUEUE_WINDOW = 3;
|
|
9
|
-
export function getQueueWindow(queueLen, queueEditIdx) {
|
|
10
|
-
const start = queueEditIdx === null ? 0 : Math.max(0, Math.min(queueEditIdx - 1, Math.max(0, queueLen - QUEUE_WINDOW)));
|
|
11
|
-
const end = Math.min(queueLen, start + QUEUE_WINDOW);
|
|
12
|
-
return { end, showLead: start > 0, showTail: end < queueLen, start };
|
|
13
|
-
}
|
|
14
|
-
export function QueuedMessages({ cols, queueEditIdx, queued, t }) {
|
|
15
|
-
if (!queued.length) {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
const q = getQueueWindow(queued.length, queueEditIdx);
|
|
19
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: t.color.muted, dimColor: true, children: `queued (${queued.length})${queueEditIdx !== null ? ` · editing ${queueEditIdx + 1} · Ctrl+X delete · Esc cancel` : ''}` }), q.showLead && (_jsxs(Text, { color: t.color.muted, dimColor: true, children: [' ', "\u2026"] })), queued.slice(q.start, q.end).map((item, i) => {
|
|
20
|
-
const idx = q.start + i;
|
|
21
|
-
const active = queueEditIdx === idx;
|
|
22
|
-
return (_jsxs(Text, { color: active ? t.color.accent : t.color.muted, dimColor: true, children: [active ? '▸' : ' ', " ", idx + 1, ". ", compactPreview(item, Math.max(16, cols - 10))] }, `${idx}-${item.slice(0, 16)}`));
|
|
23
|
-
}), q.showTail && (_jsxs(Text, { color: t.color.muted, dimColor: true, children: [' ', "\u2026and ", queued.length - q.end, " more"] }))] }));
|
|
24
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } 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
|
-
import { Box, Text, useInput, useStdout } from '@cvc/ink';
|
|
7
|
-
import { useEffect, useState } from 'react';
|
|
8
|
-
import { asRpcResult, rpcErrorMessage } from '../lib/rpc.js';
|
|
9
|
-
import { OverlayHint, useOverlayKeys, windowOffset } from './overlayControls.js';
|
|
10
|
-
const VISIBLE = 15;
|
|
11
|
-
const MIN_WIDTH = 60;
|
|
12
|
-
const MAX_WIDTH = 120;
|
|
13
|
-
const age = (ts) => {
|
|
14
|
-
const d = (Date.now() / 1000 - ts) / 86400;
|
|
15
|
-
if (d < 1) {
|
|
16
|
-
return 'today';
|
|
17
|
-
}
|
|
18
|
-
if (d < 2) {
|
|
19
|
-
return 'yesterday';
|
|
20
|
-
}
|
|
21
|
-
return `${Math.floor(d)}d ago`;
|
|
22
|
-
};
|
|
23
|
-
export function SessionPicker({ gw, onCancel, onSelect, t }) {
|
|
24
|
-
const [items, setItems] = useState([]);
|
|
25
|
-
const [err, setErr] = useState('');
|
|
26
|
-
const [sel, setSel] = useState(0);
|
|
27
|
-
const [loading, setLoading] = useState(true);
|
|
28
|
-
// When non-null, the user pressed `d` on this index and we're waiting for
|
|
29
|
-
// a second `d`/`D` to confirm deletion. Any other key cancels the prompt.
|
|
30
|
-
const [confirmDelete, setConfirmDelete] = useState(null);
|
|
31
|
-
const [deleting, setDeleting] = useState(false);
|
|
32
|
-
const { stdout } = useStdout();
|
|
33
|
-
const width = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, (stdout?.columns ?? 80) - 6));
|
|
34
|
-
useOverlayKeys({ onClose: onCancel });
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
gw.request('session.list', { limit: 200 })
|
|
37
|
-
.then(raw => {
|
|
38
|
-
const r = asRpcResult(raw);
|
|
39
|
-
if (!r) {
|
|
40
|
-
setErr('invalid response: session.list');
|
|
41
|
-
setLoading(false);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
setItems(r.sessions ?? []);
|
|
45
|
-
setErr('');
|
|
46
|
-
setLoading(false);
|
|
47
|
-
})
|
|
48
|
-
.catch((e) => {
|
|
49
|
-
setErr(rpcErrorMessage(e));
|
|
50
|
-
setLoading(false);
|
|
51
|
-
});
|
|
52
|
-
}, [gw]);
|
|
53
|
-
const performDelete = (index) => {
|
|
54
|
-
const target = items[index];
|
|
55
|
-
if (!target || deleting) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
setDeleting(true);
|
|
59
|
-
gw.request('session.delete', { session_id: target.id })
|
|
60
|
-
.then(raw => {
|
|
61
|
-
const r = asRpcResult(raw);
|
|
62
|
-
if (!r || r.deleted !== target.id) {
|
|
63
|
-
setErr('invalid response: session.delete');
|
|
64
|
-
setDeleting(false);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
setItems(prev => {
|
|
68
|
-
const next = prev.filter((_, i) => i !== index);
|
|
69
|
-
setSel(s => Math.max(0, Math.min(s, next.length - 1)));
|
|
70
|
-
return next;
|
|
71
|
-
});
|
|
72
|
-
setErr('');
|
|
73
|
-
setDeleting(false);
|
|
74
|
-
})
|
|
75
|
-
.catch((e) => {
|
|
76
|
-
setErr(rpcErrorMessage(e));
|
|
77
|
-
setDeleting(false);
|
|
78
|
-
});
|
|
79
|
-
};
|
|
80
|
-
useInput((ch, key) => {
|
|
81
|
-
if (deleting) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
if (confirmDelete !== null) {
|
|
85
|
-
if (ch?.toLowerCase() === 'd') {
|
|
86
|
-
const idx = confirmDelete;
|
|
87
|
-
setConfirmDelete(null);
|
|
88
|
-
performDelete(idx);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
setConfirmDelete(null);
|
|
92
|
-
}
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
if (key.upArrow && sel > 0) {
|
|
96
|
-
setSel(s => s - 1);
|
|
97
|
-
}
|
|
98
|
-
if (key.downArrow && sel < items.length - 1) {
|
|
99
|
-
setSel(s => s + 1);
|
|
100
|
-
}
|
|
101
|
-
if (key.return && items[sel]) {
|
|
102
|
-
onSelect(items[sel].id);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
if (ch?.toLowerCase() === 'd' && items[sel]) {
|
|
106
|
-
setConfirmDelete(sel);
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
const n = parseInt(ch);
|
|
110
|
-
if (n >= 1 && n <= Math.min(9, items.length)) {
|
|
111
|
-
onSelect(items[n - 1].id);
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
if (loading) {
|
|
115
|
-
return _jsx(Text, { color: t.color.muted, children: "loading sessions\u2026" });
|
|
116
|
-
}
|
|
117
|
-
if (err && !items.length) {
|
|
118
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: t.color.label, children: ["error: ", err] }), _jsx(OverlayHint, { t: t, children: "Esc/q cancel" })] }));
|
|
119
|
-
}
|
|
120
|
-
if (!items.length) {
|
|
121
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: t.color.muted, children: "no previous sessions" }), _jsx(OverlayHint, { t: t, children: "Esc/q cancel" })] }));
|
|
122
|
-
}
|
|
123
|
-
const offset = windowOffset(items.length, sel, VISIBLE);
|
|
124
|
-
return (_jsxs(Box, { flexDirection: "column", width: width, children: [_jsx(Text, { bold: true, color: t.color.accent, children: "Resume Session" }), offset > 0 && _jsxs(Text, { color: t.color.muted, children: [" \u2191 ", offset, " more"] }), items.slice(offset, offset + VISIBLE).map((s, vi) => {
|
|
125
|
-
const i = offset + vi;
|
|
126
|
-
const selected = sel === i;
|
|
127
|
-
const pendingDelete = confirmDelete === i;
|
|
128
|
-
return (_jsxs(Box, { children: [_jsx(Text, { bold: selected, color: selected ? t.color.accent : t.color.muted, inverse: selected, children: selected ? '▸ ' : ' ' }), _jsx(Box, { width: 30, children: _jsxs(Text, { bold: selected, color: selected ? t.color.accent : t.color.muted, inverse: selected, children: [String(i + 1).padStart(2), ". [", s.id, "]"] }) }), _jsx(Box, { width: 30, children: _jsxs(Text, { bold: selected, color: selected ? t.color.accent : t.color.muted, inverse: selected, children: ["(", s.message_count, " msgs, ", age(s.started_at), ", ", s.source || 'tui', ")"] }) }), _jsx(Text, { bold: selected, color: pendingDelete ? t.color.label : selected ? t.color.accent : t.color.muted, inverse: selected, wrap: "truncate-end", children: pendingDelete ? 'press d again to delete' : s.title || s.preview || '(untitled)' })] }, s.id));
|
|
129
|
-
}), offset + VISIBLE < items.length && _jsxs(Text, { color: t.color.muted, children: [" \u2193 ", items.length - offset - VISIBLE, " more"] }), err && _jsxs(Text, { color: t.color.label, children: ["error: ", err] }), deleting ? (_jsx(OverlayHint, { t: t, children: "deleting\u2026" })) : (_jsx(OverlayHint, { t: t, children: "\u2191/\u2193 select \u00B7 Enter resume \u00B7 1-9 quick \u00B7 d delete \u00B7 Esc/q cancel" }))] }));
|
|
130
|
-
}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } 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
|
-
import { Box, Text, useInput, useStdout } from '@cvc/ink';
|
|
7
|
-
import { useEffect, useState } from 'react';
|
|
8
|
-
import { rpcErrorMessage } from '../lib/rpc.js';
|
|
9
|
-
import { OverlayHint, useOverlayKeys, windowItems, windowOffset } from './overlayControls.js';
|
|
10
|
-
const VISIBLE = 12;
|
|
11
|
-
const MIN_WIDTH = 40;
|
|
12
|
-
const MAX_WIDTH = 90;
|
|
13
|
-
export function SkillsHub({ gw, onClose, t }) {
|
|
14
|
-
const [skillsByCat, setSkillsByCat] = useState({});
|
|
15
|
-
const [selectedCat, setSelectedCat] = useState('');
|
|
16
|
-
const [catIdx, setCatIdx] = useState(0);
|
|
17
|
-
const [skillIdx, setSkillIdx] = useState(0);
|
|
18
|
-
const [stage, setStage] = useState('category');
|
|
19
|
-
const [info, setInfo] = useState(null);
|
|
20
|
-
const [installing, setInstalling] = useState(false);
|
|
21
|
-
const [err, setErr] = useState('');
|
|
22
|
-
const [loading, setLoading] = useState(true);
|
|
23
|
-
const { stdout } = useStdout();
|
|
24
|
-
const width = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, (stdout?.columns ?? 80) - 6));
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
gw.request('skills.manage', { action: 'list' })
|
|
27
|
-
.then(r => {
|
|
28
|
-
setSkillsByCat(r?.skills ?? {});
|
|
29
|
-
setErr('');
|
|
30
|
-
setLoading(false);
|
|
31
|
-
})
|
|
32
|
-
.catch((e) => {
|
|
33
|
-
setErr(rpcErrorMessage(e));
|
|
34
|
-
setLoading(false);
|
|
35
|
-
});
|
|
36
|
-
}, [gw]);
|
|
37
|
-
const cats = Object.keys(skillsByCat).sort();
|
|
38
|
-
const skills = selectedCat ? (skillsByCat[selectedCat] ?? []) : [];
|
|
39
|
-
const skillName = skills[skillIdx] ?? '';
|
|
40
|
-
const back = () => {
|
|
41
|
-
if (stage === 'actions') {
|
|
42
|
-
setStage('skill');
|
|
43
|
-
setInfo(null);
|
|
44
|
-
setErr('');
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (stage === 'skill') {
|
|
48
|
-
setStage('category');
|
|
49
|
-
setSkillIdx(0);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
onClose();
|
|
53
|
-
};
|
|
54
|
-
useOverlayKeys({ disabled: installing, onBack: back, onClose });
|
|
55
|
-
const inspect = (name) => {
|
|
56
|
-
setInfo(null);
|
|
57
|
-
setErr('');
|
|
58
|
-
gw.request('skills.manage', { action: 'inspect', query: name })
|
|
59
|
-
.then(r => setInfo(r?.info ?? { name }))
|
|
60
|
-
.catch((e) => setErr(rpcErrorMessage(e)));
|
|
61
|
-
};
|
|
62
|
-
const install = (name) => {
|
|
63
|
-
setInstalling(true);
|
|
64
|
-
setErr('');
|
|
65
|
-
gw.request('skills.manage', { action: 'install', query: name })
|
|
66
|
-
.then(() => onClose())
|
|
67
|
-
.catch((e) => setErr(rpcErrorMessage(e)))
|
|
68
|
-
.finally(() => setInstalling(false));
|
|
69
|
-
};
|
|
70
|
-
useInput((ch, key) => {
|
|
71
|
-
if (installing) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (stage === 'actions') {
|
|
75
|
-
if (key.return) {
|
|
76
|
-
setStage('skill');
|
|
77
|
-
setInfo(null);
|
|
78
|
-
setErr('');
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if (ch.toLowerCase() === 'x' && skillName) {
|
|
82
|
-
install(skillName);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
if (ch.toLowerCase() === 'i' && skillName) {
|
|
86
|
-
inspect(skillName);
|
|
87
|
-
}
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const count = stage === 'category' ? cats.length : skills.length;
|
|
91
|
-
const sel = stage === 'category' ? catIdx : skillIdx;
|
|
92
|
-
const setSel = stage === 'category' ? setCatIdx : setSkillIdx;
|
|
93
|
-
if (key.upArrow && sel > 0) {
|
|
94
|
-
setSel(v => v - 1);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
if (key.downArrow && sel < count - 1) {
|
|
98
|
-
setSel(v => v + 1);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
if (key.return) {
|
|
102
|
-
if (stage === 'category') {
|
|
103
|
-
const cat = cats[catIdx];
|
|
104
|
-
if (!cat) {
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
setSelectedCat(cat);
|
|
108
|
-
setSkillIdx(0);
|
|
109
|
-
setStage('skill');
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
const name = skills[skillIdx];
|
|
113
|
-
if (name) {
|
|
114
|
-
setStage('actions');
|
|
115
|
-
inspect(name);
|
|
116
|
-
}
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
const n = ch === '0' ? 10 : parseInt(ch, 10);
|
|
120
|
-
if (!Number.isNaN(n) && n >= 1 && n <= Math.min(10, count)) {
|
|
121
|
-
const next = windowOffset(count, sel, VISIBLE) + n - 1;
|
|
122
|
-
if (stage === 'category') {
|
|
123
|
-
const cat = cats[next];
|
|
124
|
-
if (cat) {
|
|
125
|
-
setSelectedCat(cat);
|
|
126
|
-
setCatIdx(next);
|
|
127
|
-
setSkillIdx(0);
|
|
128
|
-
setStage('skill');
|
|
129
|
-
}
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
const name = skills[next];
|
|
133
|
-
if (name) {
|
|
134
|
-
setSkillIdx(next);
|
|
135
|
-
setStage('actions');
|
|
136
|
-
inspect(name);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
if (loading) {
|
|
141
|
-
return _jsx(Text, { color: t.color.muted, children: "loading skills\u2026" });
|
|
142
|
-
}
|
|
143
|
-
if (err && stage === 'category') {
|
|
144
|
-
return (_jsxs(Box, { flexDirection: "column", width: width, children: [_jsxs(Text, { color: t.color.label, children: ["error: ", err] }), _jsx(OverlayHint, { t: t, children: "Esc/q cancel" })] }));
|
|
145
|
-
}
|
|
146
|
-
if (!cats.length) {
|
|
147
|
-
return (_jsxs(Box, { flexDirection: "column", width: width, children: [_jsx(Text, { color: t.color.muted, children: "no skills available" }), _jsx(OverlayHint, { t: t, children: "Esc/q cancel" })] }));
|
|
148
|
-
}
|
|
149
|
-
if (stage === 'category') {
|
|
150
|
-
const rows = cats.map(c => `${c} · ${skillsByCat[c]?.length ?? 0} skills`);
|
|
151
|
-
const { items, offset } = windowItems(rows, catIdx, VISIBLE);
|
|
152
|
-
return (_jsxs(Box, { flexDirection: "column", width: width, children: [_jsx(Text, { bold: true, color: t.color.accent, children: "Skills Hub" }), _jsx(Text, { color: t.color.muted, children: "select a category" }), offset > 0 && _jsxs(Text, { color: t.color.muted, children: [" \u2191 ", offset, " more"] }), items.map((row, i) => {
|
|
153
|
-
const idx = offset + i;
|
|
154
|
-
return (_jsxs(Text, { bold: catIdx === idx, color: catIdx === idx ? t.color.accent : t.color.muted, inverse: catIdx === idx, wrap: "truncate-end", children: [catIdx === idx ? '▸ ' : ' ', i + 1, ". ", row] }, row));
|
|
155
|
-
}), offset + VISIBLE < rows.length && _jsxs(Text, { color: t.color.muted, children: [" \u2193 ", rows.length - offset - VISIBLE, " more"] }), _jsx(OverlayHint, { t: t, children: "\u2191/\u2193 select \u00B7 Enter open \u00B7 1-9,0 quick \u00B7 Esc/q cancel" })] }));
|
|
156
|
-
}
|
|
157
|
-
if (stage === 'skill') {
|
|
158
|
-
const { items, offset } = windowItems(skills, skillIdx, VISIBLE);
|
|
159
|
-
return (_jsxs(Box, { flexDirection: "column", width: width, children: [_jsx(Text, { bold: true, color: t.color.accent, children: selectedCat }), _jsxs(Text, { color: t.color.muted, children: [skills.length, " skill(s)"] }), !skills.length ? _jsx(Text, { color: t.color.muted, children: "no skills in this category" }) : null, offset > 0 && _jsxs(Text, { color: t.color.muted, children: [" \u2191 ", offset, " more"] }), items.map((row, i) => {
|
|
160
|
-
const idx = offset + i;
|
|
161
|
-
return (_jsxs(Text, { bold: skillIdx === idx, color: skillIdx === idx ? t.color.accent : t.color.muted, inverse: skillIdx === idx, wrap: "truncate-end", children: [skillIdx === idx ? '▸ ' : ' ', i + 1, ". ", row] }, row));
|
|
162
|
-
}), offset + VISIBLE < skills.length && (_jsxs(Text, { color: t.color.muted, children: [" \u2193 ", skills.length - offset - VISIBLE, " more"] })), _jsx(OverlayHint, { t: t, children: skills.length ? '↑/↓ select · Enter open · 1-9,0 quick · Esc back · q close' : 'Esc back · q close' })] }));
|
|
163
|
-
}
|
|
164
|
-
return (_jsxs(Box, { flexDirection: "column", width: width, children: [_jsx(Text, { bold: true, color: t.color.accent, children: info?.name ?? skillName }), _jsx(Text, { color: t.color.muted, children: info?.category ?? selectedCat }), info?.description ? _jsx(Text, { color: t.color.text, children: info.description }) : null, info?.path ? _jsxs(Text, { color: t.color.muted, children: ["path: ", info.path] }) : null, !info && !err ? _jsx(Text, { color: t.color.muted, children: "loading\u2026" }) : null, err ? _jsxs(Text, { color: t.color.label, children: ["error: ", err] }) : null, installing ? _jsx(Text, { color: t.color.accent, children: "installing\u2026" }) : null, _jsx(OverlayHint, { t: t, children: "i reinspect \u00B7 x reinstall \u00B7 Enter/Esc back \u00B7 q close" })] }));
|
|
165
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } 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
|
-
import { useStore } from '@nanostores/react';
|
|
7
|
-
import { memo } from 'react';
|
|
8
|
-
import { toggleTodoCollapsed, useTurnSelector } from '../app/turnStore.js';
|
|
9
|
-
import { $uiState } from '../app/uiStore.js';
|
|
10
|
-
import { appendToolShelfMessage } from '../lib/liveProgress.js';
|
|
11
|
-
import { MessageLine } from './messageLine.js';
|
|
12
|
-
import { TodoPanel } from './todoPanel.js';
|
|
13
|
-
const groupedSegments = (segments) => segments.reduce((acc, msg) => appendToolShelfMessage(acc, msg), []);
|
|
14
|
-
export const StreamingAssistant = memo(function StreamingAssistant({ cols, compact, detailsMode, detailsModeCommandOverride, progress, sections }) {
|
|
15
|
-
const ui = useStore($uiState);
|
|
16
|
-
const streamSegments = useTurnSelector(state => state.streamSegments);
|
|
17
|
-
const streamPendingTools = useTurnSelector(state => state.streamPendingTools);
|
|
18
|
-
const streaming = useTurnSelector(state => state.streaming);
|
|
19
|
-
const activeTools = useTurnSelector(state => state.tools);
|
|
20
|
-
const showStreamingArea = Boolean(streaming);
|
|
21
|
-
if (!progress.showProgressArea && !showStreamingArea && !activeTools.length) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
return (_jsxs(_Fragment, { children: [groupedSegments(streamSegments).map((msg, i) => (_jsx(MessageLine, { cols: cols, compact: compact, detailsMode: detailsMode, detailsModeCommandOverride: detailsModeCommandOverride, msg: msg, sections: sections, t: ui.theme }, `seg:${i}`))), !!activeTools.length && (_jsx(MessageLine, { cols: cols, compact: compact, detailsMode: detailsMode, detailsModeCommandOverride: detailsModeCommandOverride, msg: { kind: 'trail', role: 'system', text: '' }, sections: sections, t: ui.theme, tools: activeTools })), showStreamingArea && (_jsx(MessageLine, { cols: cols, compact: compact, detailsMode: detailsMode, detailsModeCommandOverride: detailsModeCommandOverride, isStreaming: true, msg: {
|
|
25
|
-
role: 'assistant',
|
|
26
|
-
text: streaming,
|
|
27
|
-
...(streamPendingTools.length && { tools: streamPendingTools })
|
|
28
|
-
}, sections: sections, t: ui.theme })), !showStreamingArea && !!streamPendingTools.length && (_jsx(MessageLine, { cols: cols, compact: compact, detailsMode: detailsMode, detailsModeCommandOverride: detailsModeCommandOverride, msg: { kind: 'trail', role: 'system', text: '', tools: streamPendingTools }, sections: sections, t: ui.theme }))] }));
|
|
29
|
-
});
|
|
30
|
-
export const LiveTodoPanel = memo(function LiveTodoPanel() {
|
|
31
|
-
const ui = useStore($uiState);
|
|
32
|
-
const todos = useTurnSelector(state => state.todos);
|
|
33
|
-
const collapsed = useTurnSelector(state => state.todoCollapsed);
|
|
34
|
-
return _jsx(TodoPanel, { collapsed: collapsed, onToggle: toggleTodoCollapsed, t: ui.theme, todos: todos });
|
|
35
|
-
});
|