parallel-codex-tui 0.3.1 → 0.3.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/README.md +11 -5
- package/dist/cli.js +3 -1
- package/dist/core/session-index.js +123 -10
- package/dist/core/session-manager.js +15 -4
- package/dist/core/task-report.js +510 -0
- package/dist/core/task-search.js +142 -0
- package/dist/tui/App.js +62 -5
- package/dist/tui/InputBar.js +12 -4
- package/dist/tui/TaskSessionsView.js +30 -9
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/tui/App.js
CHANGED
|
@@ -119,6 +119,7 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
119
119
|
const [taskSessionsError, setTaskSessionsError] = useState(null);
|
|
120
120
|
const [taskSessionsNotice, setTaskSessionsNotice] = useState(null);
|
|
121
121
|
const [taskSessionsIncludeArchived, setTaskSessionsIncludeArchived] = useState(false);
|
|
122
|
+
const [taskSessionQuery, setTaskSessionQuery] = useState("");
|
|
122
123
|
const [taskSessionAction, setTaskSessionAction] = useState(null);
|
|
123
124
|
const [taskSessionDetails, setTaskSessionDetails] = useState(null);
|
|
124
125
|
const [taskSessionDetailSelectedWorkerIndex, setTaskSessionDetailSelectedWorkerIndex] = useState(0);
|
|
@@ -174,6 +175,7 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
174
175
|
const mainConversationActionRef = useRef(mainConversationAction);
|
|
175
176
|
const taskSessionsLoadingRef = useRef(taskSessionsLoading);
|
|
176
177
|
const taskSessionsIncludeArchivedRef = useRef(taskSessionsIncludeArchived);
|
|
178
|
+
const taskSessionQueryRef = useRef("");
|
|
177
179
|
const taskSessionActionRef = useRef(taskSessionAction);
|
|
178
180
|
const taskSessionDetailsRef = useRef(null);
|
|
179
181
|
const taskSessionDetailSelectedWorkerIndexRef = useRef(0);
|
|
@@ -453,6 +455,9 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
453
455
|
useEffect(() => {
|
|
454
456
|
taskSessionsIncludeArchivedRef.current = taskSessionsIncludeArchived;
|
|
455
457
|
}, [taskSessionsIncludeArchived]);
|
|
458
|
+
useEffect(() => {
|
|
459
|
+
taskSessionQueryRef.current = taskSessionQuery;
|
|
460
|
+
}, [taskSessionQuery]);
|
|
456
461
|
useEffect(() => {
|
|
457
462
|
taskSessionActionRef.current = taskSessionAction;
|
|
458
463
|
}, [taskSessionAction]);
|
|
@@ -1246,10 +1251,38 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
1246
1251
|
const sessionAction = taskSessionActionRef.current;
|
|
1247
1252
|
if (sessionAction) {
|
|
1248
1253
|
if (chunk === "\x1b") {
|
|
1254
|
+
if (sessionAction.type === "search") {
|
|
1255
|
+
const preferred = taskSessionsRef.current[selectedTaskSessionIndexRef.current]?.id ?? null;
|
|
1256
|
+
updateTaskSessionAction(null);
|
|
1257
|
+
setTaskSessionsError(null);
|
|
1258
|
+
void refreshTaskSessionsRef.current(preferred, sessionAction.previousQuery);
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1249
1261
|
updateTaskSessionAction(null);
|
|
1250
1262
|
setTaskSessionsError(null);
|
|
1251
1263
|
return;
|
|
1252
1264
|
}
|
|
1265
|
+
if (sessionAction.type === "search") {
|
|
1266
|
+
const update = applyChatInputChunk(sessionAction.value, chunk, sessionAction.cursor);
|
|
1267
|
+
const preferred = taskSessionsRef.current[selectedTaskSessionIndexRef.current]?.id ?? null;
|
|
1268
|
+
if (update.submit !== null) {
|
|
1269
|
+
updateTaskSessionAction(null);
|
|
1270
|
+
setTaskSessionsError(null);
|
|
1271
|
+
void refreshTaskSessionsRef.current(preferred, update.submit);
|
|
1272
|
+
}
|
|
1273
|
+
else {
|
|
1274
|
+
updateTaskSessionAction({
|
|
1275
|
+
...sessionAction,
|
|
1276
|
+
value: update.value,
|
|
1277
|
+
cursor: update.cursor
|
|
1278
|
+
});
|
|
1279
|
+
if (update.value !== sessionAction.value) {
|
|
1280
|
+
setTaskSessionsError(null);
|
|
1281
|
+
void refreshTaskSessionsRef.current(preferred, update.value);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1253
1286
|
if (taskSessionsLoadingRef.current) {
|
|
1254
1287
|
return;
|
|
1255
1288
|
}
|
|
@@ -1286,6 +1319,17 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
1286
1319
|
if (taskSessionsLoadingRef.current) {
|
|
1287
1320
|
return;
|
|
1288
1321
|
}
|
|
1322
|
+
if (isWorkerSearchShortcut(chunk, {})) {
|
|
1323
|
+
updateTaskSessionAction({
|
|
1324
|
+
type: "search",
|
|
1325
|
+
value: taskSessionQueryRef.current,
|
|
1326
|
+
cursor: Array.from(taskSessionQueryRef.current).length,
|
|
1327
|
+
previousQuery: taskSessionQueryRef.current
|
|
1328
|
+
});
|
|
1329
|
+
setTaskSessionsError(null);
|
|
1330
|
+
setTaskSessionsNotice(null);
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1289
1333
|
if (isRouterDiagnosticsShortcut(chunk, {})) {
|
|
1290
1334
|
void openRouterDiagnosticsRef.current();
|
|
1291
1335
|
return;
|
|
@@ -1303,6 +1347,11 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
1303
1347
|
return;
|
|
1304
1348
|
}
|
|
1305
1349
|
const selectedSession = taskSessionsRef.current[selectedTaskSessionIndexRef.current];
|
|
1350
|
+
if ((chunk === "x" || chunk === "X") && taskSessionQueryRef.current.trim()) {
|
|
1351
|
+
void refreshTaskSessionsRef.current(selectedSession?.id ?? null, "");
|
|
1352
|
+
setTaskSessionsNotice("Task search cleared");
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1306
1355
|
if (chunk === "r" || chunk === "R") {
|
|
1307
1356
|
if (selectedSession) {
|
|
1308
1357
|
updateTaskSessionAction({
|
|
@@ -2656,11 +2705,16 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
2656
2705
|
setTaskSessionDetailNotice(null);
|
|
2657
2706
|
updateTaskSessionAction(null);
|
|
2658
2707
|
updateMainConversationAction(null);
|
|
2708
|
+
taskSessionQueryRef.current = "";
|
|
2709
|
+
setTaskSessionQuery("");
|
|
2659
2710
|
sessionCenterModeRef.current = "tasks";
|
|
2660
2711
|
setSessionCenterMode("tasks");
|
|
2661
2712
|
await refreshTaskSessions(activeTaskIdRef.current);
|
|
2662
2713
|
}
|
|
2663
|
-
async function refreshTaskSessions(preferredTaskId = null) {
|
|
2714
|
+
async function refreshTaskSessions(preferredTaskId = null, query = taskSessionQueryRef.current) {
|
|
2715
|
+
const normalizedQuery = query.replace(/[\u0000-\u001f\u007f]/g, " ").slice(0, 1000);
|
|
2716
|
+
taskSessionQueryRef.current = normalizedQuery;
|
|
2717
|
+
setTaskSessionQuery(normalizedQuery);
|
|
2664
2718
|
taskSessionsLoadingRef.current = true;
|
|
2665
2719
|
setTaskSessionsLoading(true);
|
|
2666
2720
|
const sequence = taskSessionsLoadSequenceRef.current + 1;
|
|
@@ -2670,7 +2724,8 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
2670
2724
|
throw new Error("Task sessions are unavailable");
|
|
2671
2725
|
}
|
|
2672
2726
|
const tasks = await loadTaskSessions({
|
|
2673
|
-
includeArchived: taskSessionsIncludeArchivedRef.current
|
|
2727
|
+
includeArchived: taskSessionsIncludeArchivedRef.current,
|
|
2728
|
+
...(normalizedQuery.trim() ? { query: normalizedQuery } : {})
|
|
2674
2729
|
});
|
|
2675
2730
|
if (taskSessionsLoadSequenceRef.current !== sequence) {
|
|
2676
2731
|
return;
|
|
@@ -3529,9 +3584,11 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
3529
3584
|
? { type: "rename", value: taskSessionAction.value, cursor: taskSessionAction.cursor }
|
|
3530
3585
|
: taskSessionAction?.type === "delete"
|
|
3531
3586
|
? { type: "delete", title: taskSessionAction.title }
|
|
3532
|
-
:
|
|
3587
|
+
: taskSessionAction?.type === "search"
|
|
3588
|
+
? { type: "search", value: taskSessionAction.value, cursor: taskSessionAction.cursor }
|
|
3589
|
+
: null, taskSessionsIncludeArchived: sessionCenterMode === "conversations"
|
|
3533
3590
|
? mainConversationsIncludeArchived
|
|
3534
|
-
: taskSessionsIncludeArchived, mainConversationSessions: sessionCenterMode === "conversations" && !taskSessionDetails, taskSessionDetail: Boolean(taskSessionDetails), taskSessionDetailHasNative: taskSessionDetailHasNative, taskSessionDetailCanFork: taskSessionDetailCanFork, canRetry: canRetryTask, hasWorkers: workers.length > 0, hasActiveTask: Boolean(activeTaskId), hasTaskResult: hasTaskResult, taskResultExpanded: taskResultExpanded, chatScrollOffset: chatScrollOffset, chatMaxScrollOffset: chatMaxScrollOffset, nativeClosed: view === "native" && nativeAttach?.closedCode !== null, searchMatchIndex: workerSearch.matchIndex, searchMatchCount: workerNavigationTargets.searchOffsets.length, clipboardNotice: clipboardNotice, roleScope: roleConfigurationScope, roleEditingModel: roleModelEdit, roleCanApply: roleConfigurationScope !== "task" || Boolean(activeTaskId), roleSaving: roleConfigurationSaving, roleHasOverride: roleConfigurationHasOverride, value: workerSearch.open && view === "worker"
|
|
3591
|
+
: taskSessionsIncludeArchived, taskSessionQuery: taskSessionQuery, mainConversationSessions: sessionCenterMode === "conversations" && !taskSessionDetails, taskSessionDetail: Boolean(taskSessionDetails), taskSessionDetailHasNative: taskSessionDetailHasNative, taskSessionDetailCanFork: taskSessionDetailCanFork, canRetry: canRetryTask, hasWorkers: workers.length > 0, hasActiveTask: Boolean(activeTaskId), hasTaskResult: hasTaskResult, taskResultExpanded: taskResultExpanded, chatScrollOffset: chatScrollOffset, chatMaxScrollOffset: chatMaxScrollOffset, nativeClosed: view === "native" && nativeAttach?.closedCode !== null, searchMatchIndex: workerSearch.matchIndex, searchMatchCount: workerNavigationTargets.searchOffsets.length, clipboardNotice: clipboardNotice, roleScope: roleConfigurationScope, roleEditingModel: roleModelEdit, roleCanApply: roleConfigurationScope !== "task" || Boolean(activeTaskId), roleSaving: roleConfigurationSaving, roleHasOverride: roleConfigurationHasOverride, value: workerSearch.open && view === "worker"
|
|
3535
3592
|
? workerSearch.query
|
|
3536
3593
|
: view === "native" || view === "router" || view === "workers" || view === "features" || view === "sessions" || view === "collaboration" || view === "status" || view === "roles" ? "" : input, cursor: workerSearch.open && view === "worker"
|
|
3537
3594
|
? workerSearch.cursor
|
|
@@ -3539,7 +3596,7 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
3539
3596
|
? { type: "rename", title: mainConversationAction.title }
|
|
3540
3597
|
: mainConversationAction?.type === "delete"
|
|
3541
3598
|
? { type: "delete", title: mainConversationAction.title }
|
|
3542
|
-
: null, loading: taskSessionsLoading, error: taskSessionsError, height: contentHeight, terminalWidth: terminalWidth })) : (_jsx(TaskSessionsView, { tasks: taskSessions, activeTaskId: activeTaskId, selectedIndex: selectedTaskSessionIndex, includeArchived: taskSessionsIncludeArchived, notice: taskSessionsNotice, action: taskSessionAction?.type === "rename"
|
|
3599
|
+
: null, loading: taskSessionsLoading, error: taskSessionsError, height: contentHeight, terminalWidth: terminalWidth })) : (_jsx(TaskSessionsView, { tasks: taskSessions, activeTaskId: activeTaskId, selectedIndex: selectedTaskSessionIndex, includeArchived: taskSessionsIncludeArchived, query: taskSessionQuery, notice: taskSessionsNotice, action: taskSessionAction?.type === "rename"
|
|
3543
3600
|
? { type: "rename", title: taskSessionAction.title }
|
|
3544
3601
|
: taskSessionAction?.type === "delete"
|
|
3545
3602
|
? { type: "delete", title: taskSessionAction.title }
|
package/dist/tui/InputBar.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { compactEndByDisplayWidth, compactTailByDisplayWidth, displayWidth } from "./display-width.js";
|
|
4
4
|
import { TUI_THEME } from "./theme.js";
|
|
5
|
-
export function InputBar({ mode, ready = true, busy = false, routeFallback = false, collaborationDetail = false, collaborationUnresolved = false, collaborationBack = "workers", featureCanCancel = false, featureCanPause = false, featureCanReassign = false, featureCancelConfirm = false, featurePauseConfirm = false, featureAssignment = false, featureEditingModel = null, taskSessionAction = null, taskSessionsIncludeArchived = false, mainConversationSessions = false, taskSessionDetail = false, taskSessionDetailHasNative = false, taskSessionDetailCanFork = false, canRetry = false, hasWorkers = false, hasActiveTask = false, hasTaskResult = false, taskResultExpanded = false, chatScrollOffset = 0, chatMaxScrollOffset = 0, nativeClosed = false, searchMatchIndex = 0, searchMatchCount = 0, clipboardNotice = null, roleScope = "next", roleEditingModel = null, roleCanApply = true, roleSaving = false, roleHasOverride = false, value, cursor, terminalWidth: providedTerminalWidth, onChange, onSubmit }) {
|
|
5
|
+
export function InputBar({ mode, ready = true, busy = false, routeFallback = false, collaborationDetail = false, collaborationUnresolved = false, collaborationBack = "workers", featureCanCancel = false, featureCanPause = false, featureCanReassign = false, featureCancelConfirm = false, featurePauseConfirm = false, featureAssignment = false, featureEditingModel = null, taskSessionAction = null, taskSessionsIncludeArchived = false, taskSessionQuery = "", mainConversationSessions = false, taskSessionDetail = false, taskSessionDetailHasNative = false, taskSessionDetailCanFork = false, canRetry = false, hasWorkers = false, hasActiveTask = false, hasTaskResult = false, taskResultExpanded = false, chatScrollOffset = 0, chatMaxScrollOffset = 0, nativeClosed = false, searchMatchIndex = 0, searchMatchCount = 0, clipboardNotice = null, roleScope = "next", roleEditingModel = null, roleCanApply = true, roleSaving = false, roleHasOverride = false, value, cursor, terminalWidth: providedTerminalWidth, onChange, onSubmit }) {
|
|
6
6
|
const terminalWidth = providedTerminalWidth ?? process.stdout.columns ?? 120;
|
|
7
7
|
const fillRail = providedTerminalWidth !== undefined || typeof process.stdout.columns === "number";
|
|
8
8
|
if (clipboardNotice) {
|
|
@@ -42,6 +42,13 @@ export function InputBar({ mode, ready = true, busy = false, routeFallback = fal
|
|
|
42
42
|
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
43
43
|
}
|
|
44
44
|
if (mode === "sessions") {
|
|
45
|
+
if (taskSessionAction?.type === "search") {
|
|
46
|
+
const prefix = terminalWidth < 12 ? "/ " : "find > ";
|
|
47
|
+
const valueWidth = Math.max(1, terminalWidth - displayWidth(prefix) - 3);
|
|
48
|
+
const display = chatInputDisplayParts(taskSessionAction.value, taskSessionAction.cursor, valueWidth);
|
|
49
|
+
const textWidth = displayWidth(`${prefix}${display.before}|${display.after}`);
|
|
50
|
+
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: textWidth, fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: prefix }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.text, children: display.before }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: "|" }), _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.text, children: display.after })] }));
|
|
51
|
+
}
|
|
45
52
|
if (taskSessionAction?.type === "rename") {
|
|
46
53
|
const prefix = terminalWidth < 12 ? "> " : "rename > ";
|
|
47
54
|
const valueWidth = Math.max(1, terminalWidth - displayWidth(prefix) - 3);
|
|
@@ -61,7 +68,7 @@ export function InputBar({ mode, ready = true, busy = false, routeFallback = fal
|
|
|
61
68
|
const hints = mainConversationSessionsInputHints(terminalWidth, taskSessionsIncludeArchived);
|
|
62
69
|
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
63
70
|
}
|
|
64
|
-
const hints = taskSessionsInputHints(terminalWidth, taskSessionsIncludeArchived);
|
|
71
|
+
const hints = taskSessionsInputHints(terminalWidth, taskSessionsIncludeArchived, Boolean(taskSessionQuery.trim()));
|
|
65
72
|
return (_jsxs(InputRail, { terminalWidth: terminalWidth, textWidth: displayWidth(`${hints.label}${hints.detail}`), fill: fillRail, children: [_jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.accent, bold: true, children: hints.label }), hints.detail ? _jsx(Text, { backgroundColor: TUI_THEME.rail, color: TUI_THEME.muted, children: hints.detail }) : null] }));
|
|
66
73
|
}
|
|
67
74
|
if (mode === "collaboration") {
|
|
@@ -596,10 +603,11 @@ function collaborationDetailInputHints(width) {
|
|
|
596
603
|
{ label: "e", detail: "" }
|
|
597
604
|
]);
|
|
598
605
|
}
|
|
599
|
-
function taskSessionsInputHints(width, includeArchived) {
|
|
606
|
+
function taskSessionsInputHints(width, includeArchived, hasQuery) {
|
|
600
607
|
const archivedAction = includeArchived ? "H hide archived" : "H archived";
|
|
608
|
+
const searchAction = hasQuery ? "^F edit · X clear" : "^F find";
|
|
601
609
|
return selectInputHints(width, [
|
|
602
|
-
{ label: "sessions", detail: ` · Up/Dn select · Enter restore · C conversations · I inspect · R rename · A archive · D delete · E export · ${archivedAction} · Esc back` },
|
|
610
|
+
{ label: "sessions", detail: ` · Up/Dn select · Enter restore · C conversations · I inspect · R rename · A archive · D delete · E export · ${archivedAction} · Esc back · ${searchAction}` },
|
|
603
611
|
{ label: "sessions", detail: " · Up/Dn select · Enter restore · C conversations · I inspect · R rename · A archive · D delete · E export · Esc back" },
|
|
604
612
|
{ label: "sessions", detail: " · Up/Dn select · Enter restore · C chats · I inspect · R rename · A archive · D delete · Esc back" },
|
|
605
613
|
{ label: "sessions", detail: " · Up/Dn select · Enter restore · C chats · I inspect · R rename · A archive · Esc back" },
|
|
@@ -2,13 +2,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { compactEndByDisplayWidth, displayWidth } from "./display-width.js";
|
|
4
4
|
import { TUI_THEME } from "./theme.js";
|
|
5
|
-
export function TaskSessionsView({ tasks, activeTaskId, selectedIndex, includeArchived = false, notice = null, action = null, loading = false, error = null, height = 20, terminalWidth = process.stdout.columns || 120 }) {
|
|
5
|
+
export function TaskSessionsView({ tasks, activeTaskId, selectedIndex, includeArchived = false, query = "", notice = null, action = null, loading = false, error = null, height = 20, terminalWidth = process.stdout.columns || 120 }) {
|
|
6
6
|
const viewportHeight = Math.max(1, height);
|
|
7
7
|
const width = taskSessionsContentWidth(terminalWidth);
|
|
8
8
|
const lines = taskSessionsDisplayLines(tasks, activeTaskId, selectedIndex, viewportHeight, terminalWidth, {
|
|
9
9
|
loading,
|
|
10
10
|
error,
|
|
11
11
|
includeArchived,
|
|
12
|
+
query,
|
|
12
13
|
notice,
|
|
13
14
|
action
|
|
14
15
|
});
|
|
@@ -21,7 +22,10 @@ export function taskSessionsDisplayLines(tasks, activeTaskId, selectedIndex, hei
|
|
|
21
22
|
const lines = [
|
|
22
23
|
{
|
|
23
24
|
text: fitTaskSessionCandidates([
|
|
24
|
-
state.includeArchived
|
|
25
|
+
taskSessionsHeading(Boolean(state.includeArchived), state.query ?? ""),
|
|
26
|
+
...((state.query ?? "").trim()
|
|
27
|
+
? [`Find · ${safeTaskSessionText(state.query ?? "")}`, `/ ${safeTaskSessionText(state.query ?? "")}`]
|
|
28
|
+
: []),
|
|
25
29
|
state.includeArchived ? "Sessions · all" : "Sessions",
|
|
26
30
|
"Tasks",
|
|
27
31
|
"T"
|
|
@@ -30,7 +34,7 @@ export function taskSessionsDisplayLines(tasks, activeTaskId, selectedIndex, hei
|
|
|
30
34
|
}
|
|
31
35
|
];
|
|
32
36
|
if (viewportHeight >= 3) {
|
|
33
|
-
lines.push({ text: taskSessionSummary(tasks, width), tone: "muted" });
|
|
37
|
+
lines.push({ text: taskSessionSummary(tasks, width, state.query ?? ""), tone: "muted" });
|
|
34
38
|
}
|
|
35
39
|
if (viewportHeight >= 4 && state.action) {
|
|
36
40
|
lines.push({
|
|
@@ -58,7 +62,10 @@ export function taskSessionsDisplayLines(tasks, activeTaskId, selectedIndex, hei
|
|
|
58
62
|
}
|
|
59
63
|
if (tasks.length === 0) {
|
|
60
64
|
if (slots > 0) {
|
|
61
|
-
lines.push({
|
|
65
|
+
lines.push({
|
|
66
|
+
text: fitTaskSessionText(state.query?.trim() ? "No matching task sessions" : "No saved task sessions", width),
|
|
67
|
+
tone: "muted"
|
|
68
|
+
});
|
|
62
69
|
}
|
|
63
70
|
return lines;
|
|
64
71
|
}
|
|
@@ -94,7 +101,7 @@ function TaskSessionRow({ line, width }) {
|
|
|
94
101
|
const theme = taskSessionLineTheme(line.tone);
|
|
95
102
|
return (_jsxs(Text, { children: [_jsx(Text, { ...theme, children: line.text }), trailingWidth > 0 ? _jsx(Text, { backgroundColor: TUI_THEME.surface, children: " ".repeat(trailingWidth) }) : null] }));
|
|
96
103
|
}
|
|
97
|
-
function taskSessionSummary(tasks, width) {
|
|
104
|
+
function taskSessionSummary(tasks, width, query) {
|
|
98
105
|
const counts = new Map();
|
|
99
106
|
let archived = 0;
|
|
100
107
|
for (const task of tasks) {
|
|
@@ -112,11 +119,16 @@ function taskSessionSummary(tasks, width) {
|
|
|
112
119
|
if (archived > 0) {
|
|
113
120
|
parts.push(`${archived} archived`);
|
|
114
121
|
}
|
|
122
|
+
const searching = Boolean(query.trim());
|
|
123
|
+
const prefix = searching
|
|
124
|
+
? `${tasks.length} ${tasks.length === 1 ? "match" : "matches"}`
|
|
125
|
+
: `${tasks.length} ${tasks.length === 1 ? "task" : "tasks"}`;
|
|
126
|
+
const compactPrefix = searching ? `${tasks.length} matches` : `${tasks.length} tasks`;
|
|
115
127
|
return fitTaskSessionCandidates([
|
|
116
|
-
[
|
|
117
|
-
`${
|
|
118
|
-
|
|
119
|
-
`${tasks.length}t`
|
|
128
|
+
[prefix, ...parts].join(" · "),
|
|
129
|
+
`${compactPrefix} · ${counts.get("running") ?? 0} active · ${counts.get("failed") ?? 0} failed`,
|
|
130
|
+
compactPrefix,
|
|
131
|
+
`${tasks.length}${searching ? "m" : "t"}`
|
|
120
132
|
], width);
|
|
121
133
|
}
|
|
122
134
|
function taskSessionRowText(task, selected, active, width) {
|
|
@@ -130,7 +142,9 @@ function taskSessionRowText(task, selected, active, width) {
|
|
|
130
142
|
const workers = `${task.workerCount} ${task.workerCount === 1 ? "worker" : "workers"}`;
|
|
131
143
|
const native = `${task.nativeSessionCount} native`;
|
|
132
144
|
const compactId = task.id.replace(/^task-/, "#");
|
|
145
|
+
const match = safeTaskSessionText(task.searchMatch?.summary ?? "");
|
|
133
146
|
return fitTaskSessionCandidates([
|
|
147
|
+
...(match ? [[marker + title, status, match].join(" · ")] : []),
|
|
134
148
|
[marker + title, status, turns, workers, native, date].join(" · "),
|
|
135
149
|
[marker + title, status, turns, workers, native].join(" · "),
|
|
136
150
|
[marker + title, status, turns, workers].join(" · "),
|
|
@@ -139,6 +153,13 @@ function taskSessionRowText(task, selected, active, width) {
|
|
|
139
153
|
marker.trimEnd()
|
|
140
154
|
], width);
|
|
141
155
|
}
|
|
156
|
+
function taskSessionsHeading(includeArchived, query) {
|
|
157
|
+
const scope = includeArchived ? "archived shown" : "active";
|
|
158
|
+
const cleanQuery = safeTaskSessionText(query);
|
|
159
|
+
return cleanQuery
|
|
160
|
+
? `Task sessions · ${scope} · find ${cleanQuery}`
|
|
161
|
+
: includeArchived ? "Task sessions · archived shown" : "Task sessions";
|
|
162
|
+
}
|
|
142
163
|
function taskSessionWindowStart(selected, count, visibleCount) {
|
|
143
164
|
if (visibleCount <= 0 || count <= visibleCount) {
|
|
144
165
|
return 0;
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "0.3.
|
|
1
|
+
export const version = "0.3.2";
|