parallel-codex-tui 0.2.8 → 0.2.10
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 +9 -7
- package/dist/cli.js +11 -1
- package/dist/core/session-manager.js +569 -13
- package/dist/domain/schemas.js +8 -0
- package/dist/tui/App.js +399 -9
- package/dist/tui/InputBar.js +30 -4
- package/dist/tui/MainConversationsView.js +162 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/tui/App.js
CHANGED
|
@@ -29,6 +29,7 @@ import { moveWorkerSelection, WorkerOverviewView } from "./WorkerOverviewView.js
|
|
|
29
29
|
import { FeatureBoardView, moveFeatureBoardSelection } from "./FeatureBoardView.js";
|
|
30
30
|
import { CollaborationTimelineView, collaborationSelectionScrollOffset, collaborationTimelineEvents, moveCollaborationEventSelection, nextCollaborationFeatureIndex } from "./CollaborationTimelineView.js";
|
|
31
31
|
import { moveTaskSessionSelection, TaskSessionsView } from "./TaskSessionsView.js";
|
|
32
|
+
import { MainConversationsView, moveMainConversationSelection } from "./MainConversationsView.js";
|
|
32
33
|
import { moveTaskSessionDetailSelection, TaskSessionDetailView } from "./TaskSessionDetailView.js";
|
|
33
34
|
import { latestTaskResultMessageIndex, parseTaskResultSummary } from "./task-result.js";
|
|
34
35
|
import { buildNativeAttachLaunch, buildNativeForkLaunch, startNativeAttachProcess } from "../workers/native-attach.js";
|
|
@@ -49,7 +50,7 @@ const EMPTY_WORKER_NAVIGATION_TARGETS = {
|
|
|
49
50
|
errorOffsets: [],
|
|
50
51
|
diffOffsets: []
|
|
51
52
|
};
|
|
52
|
-
export function App({ config, orchestrator, cwd, initialTaskId = null, initialRoute = null, initialWorkers, initialCanRetryTask = false, initialMessages = [], persistChatMessage, reloadConfig, workspaceChoices = [], switchWorkspace, loadRouterDiagnostics, loadTaskSessions, loadTaskSessionDetails, renameTaskSession, setTaskSessionArchived, deleteTaskSession, exportTaskSession, exportDiagnostics, loadCollaborationTimeline, activateTaskSession, startMainConversation, prepareNativeAttach, prepareNativeFork, startNativeAttach, copyToClipboard = copyTextToClipboard, shutdownSignal }) {
|
|
53
|
+
export function App({ config, orchestrator, cwd, initialTaskId = null, initialRoute = null, initialWorkers, initialCanRetryTask = false, initialMessages = [], persistChatMessage, reloadConfig, workspaceChoices = [], switchWorkspace, loadRouterDiagnostics, loadTaskSessions, loadMainConversations, activateMainConversation, renameMainConversation, setMainConversationArchived, deleteMainConversation, exportMainConversation, loadTaskSessionDetails, renameTaskSession, setTaskSessionArchived, deleteTaskSession, exportTaskSession, exportDiagnostics, loadCollaborationTimeline, activateTaskSession, startMainConversation, prepareNativeAttach, prepareNativeFork, startNativeAttach, copyToClipboard = copyTextToClipboard, shutdownSignal }) {
|
|
53
54
|
configureTuiTheme({
|
|
54
55
|
theme: config.ui.theme,
|
|
55
56
|
colors: config.ui.colors
|
|
@@ -97,6 +98,11 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
97
98
|
const [routerMaxScrollOffset, setRouterMaxScrollOffset] = useState(0);
|
|
98
99
|
const [taskSessions, setTaskSessions] = useState([]);
|
|
99
100
|
const [selectedTaskSessionIndex, setSelectedTaskSessionIndex] = useState(0);
|
|
101
|
+
const [sessionCenterMode, setSessionCenterMode] = useState("tasks");
|
|
102
|
+
const [mainConversations, setMainConversations] = useState([]);
|
|
103
|
+
const [selectedMainConversationIndex, setSelectedMainConversationIndex] = useState(0);
|
|
104
|
+
const [mainConversationsIncludeArchived, setMainConversationsIncludeArchived] = useState(false);
|
|
105
|
+
const [mainConversationAction, setMainConversationAction] = useState(null);
|
|
100
106
|
const [taskSessionsLoading, setTaskSessionsLoading] = useState(false);
|
|
101
107
|
const [taskSessionsError, setTaskSessionsError] = useState(null);
|
|
102
108
|
const [taskSessionsNotice, setTaskSessionsNotice] = useState(null);
|
|
@@ -149,6 +155,11 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
149
155
|
const routerMaxScrollOffsetRef = useRef(routerMaxScrollOffset);
|
|
150
156
|
const taskSessionsRef = useRef(taskSessions);
|
|
151
157
|
const selectedTaskSessionIndexRef = useRef(selectedTaskSessionIndex);
|
|
158
|
+
const sessionCenterModeRef = useRef("tasks");
|
|
159
|
+
const mainConversationsRef = useRef(mainConversations);
|
|
160
|
+
const selectedMainConversationIndexRef = useRef(selectedMainConversationIndex);
|
|
161
|
+
const mainConversationsIncludeArchivedRef = useRef(mainConversationsIncludeArchived);
|
|
162
|
+
const mainConversationActionRef = useRef(mainConversationAction);
|
|
152
163
|
const taskSessionsLoadingRef = useRef(taskSessionsLoading);
|
|
153
164
|
const taskSessionsIncludeArchivedRef = useRef(taskSessionsIncludeArchived);
|
|
154
165
|
const taskSessionActionRef = useRef(taskSessionAction);
|
|
@@ -180,6 +191,13 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
180
191
|
const refreshCollaborationTimelineRef = useRef(refreshCollaborationTimeline);
|
|
181
192
|
const activateSelectedTaskSessionRef = useRef(activateSelectedTaskSession);
|
|
182
193
|
const refreshTaskSessionsRef = useRef(refreshTaskSessions);
|
|
194
|
+
const openMainConversationsRef = useRef(openMainConversations);
|
|
195
|
+
const refreshMainConversationsRef = useRef(refreshMainConversations);
|
|
196
|
+
const restoreSelectedMainConversationRef = useRef(restoreSelectedMainConversation);
|
|
197
|
+
const renameSelectedMainConversationRef = useRef(renameSelectedMainConversation);
|
|
198
|
+
const archiveSelectedMainConversationRef = useRef(archiveSelectedMainConversation);
|
|
199
|
+
const deleteSelectedMainConversationRef = useRef(deleteSelectedMainConversation);
|
|
200
|
+
const exportSelectedMainConversationRef = useRef(exportSelectedMainConversation);
|
|
183
201
|
const renameSelectedTaskSessionRef = useRef(renameSelectedTaskSession);
|
|
184
202
|
const archiveSelectedTaskSessionRef = useRef(archiveSelectedTaskSession);
|
|
185
203
|
const deleteSelectedTaskSessionRef = useRef(deleteSelectedTaskSession);
|
|
@@ -334,6 +352,21 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
334
352
|
useEffect(() => {
|
|
335
353
|
selectedTaskSessionIndexRef.current = selectedTaskSessionIndex;
|
|
336
354
|
}, [selectedTaskSessionIndex]);
|
|
355
|
+
useEffect(() => {
|
|
356
|
+
sessionCenterModeRef.current = sessionCenterMode;
|
|
357
|
+
}, [sessionCenterMode]);
|
|
358
|
+
useEffect(() => {
|
|
359
|
+
mainConversationsRef.current = mainConversations;
|
|
360
|
+
}, [mainConversations]);
|
|
361
|
+
useEffect(() => {
|
|
362
|
+
selectedMainConversationIndexRef.current = selectedMainConversationIndex;
|
|
363
|
+
}, [selectedMainConversationIndex]);
|
|
364
|
+
useEffect(() => {
|
|
365
|
+
mainConversationsIncludeArchivedRef.current = mainConversationsIncludeArchived;
|
|
366
|
+
}, [mainConversationsIncludeArchived]);
|
|
367
|
+
useEffect(() => {
|
|
368
|
+
mainConversationActionRef.current = mainConversationAction;
|
|
369
|
+
}, [mainConversationAction]);
|
|
337
370
|
useEffect(() => {
|
|
338
371
|
taskSessionsLoadingRef.current = taskSessionsLoading;
|
|
339
372
|
}, [taskSessionsLoading]);
|
|
@@ -405,6 +438,13 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
405
438
|
refreshCollaborationTimelineRef.current = refreshCollaborationTimeline;
|
|
406
439
|
activateSelectedTaskSessionRef.current = activateSelectedTaskSession;
|
|
407
440
|
refreshTaskSessionsRef.current = refreshTaskSessions;
|
|
441
|
+
openMainConversationsRef.current = openMainConversations;
|
|
442
|
+
refreshMainConversationsRef.current = refreshMainConversations;
|
|
443
|
+
restoreSelectedMainConversationRef.current = restoreSelectedMainConversation;
|
|
444
|
+
renameSelectedMainConversationRef.current = renameSelectedMainConversation;
|
|
445
|
+
archiveSelectedMainConversationRef.current = archiveSelectedMainConversation;
|
|
446
|
+
deleteSelectedMainConversationRef.current = deleteSelectedMainConversation;
|
|
447
|
+
exportSelectedMainConversationRef.current = exportSelectedMainConversation;
|
|
408
448
|
renameSelectedTaskSessionRef.current = renameSelectedTaskSession;
|
|
409
449
|
archiveSelectedTaskSessionRef.current = archiveSelectedTaskSession;
|
|
410
450
|
deleteSelectedTaskSessionRef.current = deleteSelectedTaskSession;
|
|
@@ -685,6 +725,13 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
685
725
|
setTaskSessionsError(null);
|
|
686
726
|
setSelectedTaskSessionIndex(nextIndex);
|
|
687
727
|
};
|
|
728
|
+
const moveSelectedMainConversation = (delta, wrap = false) => {
|
|
729
|
+
const nextIndex = moveMainConversationSelection(selectedMainConversationIndexRef.current, delta, mainConversationsRef.current.length, wrap);
|
|
730
|
+
selectedMainConversationIndexRef.current = nextIndex;
|
|
731
|
+
setTaskSessionsError(null);
|
|
732
|
+
setTaskSessionsNotice(null);
|
|
733
|
+
setSelectedMainConversationIndex(nextIndex);
|
|
734
|
+
};
|
|
688
735
|
const moveSelectedTaskSessionDetailWorker = (delta, wrap = false) => {
|
|
689
736
|
const nextIndex = moveTaskSessionDetailSelection(taskSessionDetailSelectedWorkerIndexRef.current, delta, taskSessionDetailsRef.current?.workers.length ?? 0, wrap);
|
|
690
737
|
taskSessionDetailSelectedWorkerIndexRef.current = nextIndex;
|
|
@@ -847,6 +894,141 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
847
894
|
}
|
|
848
895
|
return;
|
|
849
896
|
}
|
|
897
|
+
if (sessionCenterModeRef.current === "conversations") {
|
|
898
|
+
const conversationAction = mainConversationActionRef.current;
|
|
899
|
+
if (conversationAction) {
|
|
900
|
+
if (chunk === "\x1b") {
|
|
901
|
+
updateMainConversationAction(null);
|
|
902
|
+
setTaskSessionsError(null);
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
if (taskSessionsLoadingRef.current) {
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
if (conversationAction.type === "rename") {
|
|
909
|
+
const update = applyChatInputChunk(conversationAction.value, chunk, conversationAction.cursor);
|
|
910
|
+
if (update.submit !== null) {
|
|
911
|
+
void renameSelectedMainConversationRef.current({
|
|
912
|
+
...conversationAction,
|
|
913
|
+
value: update.submit,
|
|
914
|
+
cursor: Array.from(update.submit).length
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
updateMainConversationAction({
|
|
919
|
+
...conversationAction,
|
|
920
|
+
value: update.value,
|
|
921
|
+
cursor: update.cursor
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
if (chunk === "d" || chunk === "D") {
|
|
927
|
+
void deleteSelectedMainConversationRef.current(conversationAction);
|
|
928
|
+
}
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
if (isTaskSessionsShortcut(chunk, {}) || chunk === "\x1b") {
|
|
932
|
+
updateMainConversationAction(null);
|
|
933
|
+
setTaskSessionsError(null);
|
|
934
|
+
setTaskSessionsNotice(null);
|
|
935
|
+
viewRef.current = taskSessionsReturnViewRef.current;
|
|
936
|
+
setView(taskSessionsReturnViewRef.current);
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
if (taskSessionsLoadingRef.current) {
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
if (isNewConversationShortcut(chunk, {}) || chunk === "n" || chunk === "N") {
|
|
943
|
+
void newConversationRef.current();
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
if (chunk === "t" || chunk === "T") {
|
|
947
|
+
updateMainConversationAction(null);
|
|
948
|
+
sessionCenterModeRef.current = "tasks";
|
|
949
|
+
setSessionCenterMode("tasks");
|
|
950
|
+
setTaskSessionsError(null);
|
|
951
|
+
setTaskSessionsNotice(null);
|
|
952
|
+
void refreshTaskSessionsRef.current(activeTaskIdRef.current);
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
if (chunk === "c" || chunk === "C") {
|
|
956
|
+
void openMainConversationsRef.current();
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
const selectedConversation = mainConversationsRef.current[selectedMainConversationIndexRef.current];
|
|
960
|
+
if (chunk === "r" || chunk === "R") {
|
|
961
|
+
if (selectedConversation) {
|
|
962
|
+
updateMainConversationAction({
|
|
963
|
+
type: "rename",
|
|
964
|
+
conversationId: selectedConversation.id,
|
|
965
|
+
title: selectedConversation.title,
|
|
966
|
+
value: selectedConversation.title,
|
|
967
|
+
cursor: Array.from(selectedConversation.title).length
|
|
968
|
+
});
|
|
969
|
+
setTaskSessionsError(null);
|
|
970
|
+
setTaskSessionsNotice(null);
|
|
971
|
+
}
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
if (chunk === "a" || chunk === "A") {
|
|
975
|
+
void archiveSelectedMainConversationRef.current();
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
if (chunk === "d" || chunk === "D") {
|
|
979
|
+
if (selectedConversation) {
|
|
980
|
+
if (selectedConversation.current) {
|
|
981
|
+
setTaskSessionsError("Restore another Main conversation before deleting the current one");
|
|
982
|
+
}
|
|
983
|
+
else {
|
|
984
|
+
updateMainConversationAction({
|
|
985
|
+
type: "delete",
|
|
986
|
+
conversationId: selectedConversation.id,
|
|
987
|
+
title: selectedConversation.title
|
|
988
|
+
});
|
|
989
|
+
setTaskSessionsError(null);
|
|
990
|
+
setTaskSessionsNotice(null);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
if (chunk === "e" || chunk === "E") {
|
|
996
|
+
void exportSelectedMainConversationRef.current();
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
if (chunk === "h" || chunk === "H") {
|
|
1000
|
+
const includeArchived = !mainConversationsIncludeArchivedRef.current;
|
|
1001
|
+
mainConversationsIncludeArchivedRef.current = includeArchived;
|
|
1002
|
+
setMainConversationsIncludeArchived(includeArchived);
|
|
1003
|
+
setTaskSessionsError(null);
|
|
1004
|
+
setTaskSessionsNotice(null);
|
|
1005
|
+
void (async () => {
|
|
1006
|
+
await refreshMainConversationsRef.current(selectedConversation?.id);
|
|
1007
|
+
if (sessionCenterModeRef.current === "conversations"
|
|
1008
|
+
&& mainConversationsIncludeArchivedRef.current === includeArchived) {
|
|
1009
|
+
setTaskSessionsNotice(includeArchived
|
|
1010
|
+
? "Archived conversations shown"
|
|
1011
|
+
: "Archived conversations hidden");
|
|
1012
|
+
}
|
|
1013
|
+
})();
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
if (chunk === "\r" || chunk === "\n") {
|
|
1017
|
+
void restoreSelectedMainConversationRef.current();
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
if (chunk === "\t") {
|
|
1021
|
+
moveSelectedMainConversation(1, true);
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
const conversationSelectionDelta = -(rawHistoryDelta(chunk)
|
|
1025
|
+
+ rawPageScrollDelta(chunk, Math.max(1, outputHeight - 2))
|
|
1026
|
+
+ mouseScrollDelta(chunk, 1));
|
|
1027
|
+
if (conversationSelectionDelta !== 0) {
|
|
1028
|
+
moveSelectedMainConversation(conversationSelectionDelta);
|
|
1029
|
+
}
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
850
1032
|
const sessionAction = taskSessionActionRef.current;
|
|
851
1033
|
if (sessionAction) {
|
|
852
1034
|
if (chunk === "\x1b") {
|
|
@@ -902,6 +1084,10 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
902
1084
|
void newConversationRef.current();
|
|
903
1085
|
return;
|
|
904
1086
|
}
|
|
1087
|
+
if (chunk === "c" || chunk === "C") {
|
|
1088
|
+
void openMainConversationsRef.current();
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
905
1091
|
const selectedSession = taskSessionsRef.current[selectedTaskSessionIndexRef.current];
|
|
906
1092
|
if (chunk === "r" || chunk === "R") {
|
|
907
1093
|
if (selectedSession) {
|
|
@@ -1682,7 +1868,15 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
1682
1868
|
label: "sessions",
|
|
1683
1869
|
text: details
|
|
1684
1870
|
? details.workers.map((worker) => [worker.id, worker.role, worker.engine, worker.state].join(" · ")).join("\n")
|
|
1685
|
-
:
|
|
1871
|
+
: sessionCenterModeRef.current === "conversations"
|
|
1872
|
+
? mainConversationsRef.current.map((conversation) => [
|
|
1873
|
+
conversation.current ? "current" : "saved",
|
|
1874
|
+
conversation.id ?? "legacy",
|
|
1875
|
+
conversation.title,
|
|
1876
|
+
`${conversation.messageCount} messages`,
|
|
1877
|
+
`${conversation.nativeSessionCount} native`
|
|
1878
|
+
].join(" · ")).join("\n")
|
|
1879
|
+
: taskSessionsRef.current.map((task) => [task.id, task.title, task.status].join(" · ")).join("\n")
|
|
1686
1880
|
};
|
|
1687
1881
|
}
|
|
1688
1882
|
if (currentView === "router") {
|
|
@@ -2110,6 +2304,10 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
2110
2304
|
setAttachError(error instanceof Error ? error.message : String(error));
|
|
2111
2305
|
return;
|
|
2112
2306
|
}
|
|
2307
|
+
resetActiveTaskUiForMainConversation();
|
|
2308
|
+
await appendVisibleMessage({ from: "system", text: "new conversation · ready" });
|
|
2309
|
+
}
|
|
2310
|
+
function resetActiveTaskUiForMainConversation() {
|
|
2113
2311
|
const nextMemory = newTaskMemoryState();
|
|
2114
2312
|
activeTaskIdRef.current = nextMemory.activeTaskId;
|
|
2115
2313
|
setActiveTaskId(nextMemory.activeTaskId);
|
|
@@ -2134,7 +2332,6 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
2134
2332
|
offset: 0,
|
|
2135
2333
|
draft: { value: inputRef.current, cursor: inputCursorRef.current }
|
|
2136
2334
|
};
|
|
2137
|
-
await appendVisibleMessage({ from: "system", text: "new conversation · ready" });
|
|
2138
2335
|
}
|
|
2139
2336
|
async function openRouterDiagnostics() {
|
|
2140
2337
|
const currentView = viewRef.current;
|
|
@@ -2200,6 +2397,9 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
2200
2397
|
setTaskSessionDetailSelectedWorkerIndex(0);
|
|
2201
2398
|
setTaskSessionDetailNotice(null);
|
|
2202
2399
|
updateTaskSessionAction(null);
|
|
2400
|
+
updateMainConversationAction(null);
|
|
2401
|
+
sessionCenterModeRef.current = "tasks";
|
|
2402
|
+
setSessionCenterMode("tasks");
|
|
2203
2403
|
await refreshTaskSessions(activeTaskIdRef.current);
|
|
2204
2404
|
}
|
|
2205
2405
|
async function refreshTaskSessions(preferredTaskId = null) {
|
|
@@ -2240,6 +2440,184 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
2240
2440
|
}
|
|
2241
2441
|
}
|
|
2242
2442
|
}
|
|
2443
|
+
async function openMainConversations() {
|
|
2444
|
+
const currentView = viewRef.current;
|
|
2445
|
+
if (busyRef.current || currentView === "native" || currentView === "workspace") {
|
|
2446
|
+
return;
|
|
2447
|
+
}
|
|
2448
|
+
if (currentView !== "sessions") {
|
|
2449
|
+
taskSessionsReturnViewRef.current = currentView === "worker" || currentView === "workers" || currentView === "router"
|
|
2450
|
+
? currentView
|
|
2451
|
+
: "chat";
|
|
2452
|
+
viewRef.current = "sessions";
|
|
2453
|
+
setView("sessions");
|
|
2454
|
+
}
|
|
2455
|
+
const previousId = sessionCenterModeRef.current === "conversations"
|
|
2456
|
+
? mainConversationsRef.current[selectedMainConversationIndexRef.current]?.id
|
|
2457
|
+
: undefined;
|
|
2458
|
+
sessionCenterModeRef.current = "conversations";
|
|
2459
|
+
setSessionCenterMode("conversations");
|
|
2460
|
+
taskSessionDetailsRef.current = null;
|
|
2461
|
+
setTaskSessionDetails(null);
|
|
2462
|
+
updateTaskSessionAction(null);
|
|
2463
|
+
updateMainConversationAction(null);
|
|
2464
|
+
setTaskSessionsError(null);
|
|
2465
|
+
setTaskSessionsNotice(null);
|
|
2466
|
+
await refreshMainConversations(previousId);
|
|
2467
|
+
}
|
|
2468
|
+
async function refreshMainConversations(preferredConversationId, manageLoading = true) {
|
|
2469
|
+
if (manageLoading) {
|
|
2470
|
+
taskSessionsLoadingRef.current = true;
|
|
2471
|
+
setTaskSessionsLoading(true);
|
|
2472
|
+
}
|
|
2473
|
+
const sequence = taskSessionsLoadSequenceRef.current + 1;
|
|
2474
|
+
taskSessionsLoadSequenceRef.current = sequence;
|
|
2475
|
+
try {
|
|
2476
|
+
if (!loadMainConversations) {
|
|
2477
|
+
throw new Error("Main conversations are unavailable");
|
|
2478
|
+
}
|
|
2479
|
+
const conversations = await loadMainConversations({
|
|
2480
|
+
includeArchived: mainConversationsIncludeArchivedRef.current
|
|
2481
|
+
});
|
|
2482
|
+
if (taskSessionsLoadSequenceRef.current !== sequence) {
|
|
2483
|
+
return;
|
|
2484
|
+
}
|
|
2485
|
+
mainConversationsRef.current = conversations;
|
|
2486
|
+
setMainConversations(conversations);
|
|
2487
|
+
const preservedIndex = preferredConversationId !== undefined
|
|
2488
|
+
? conversations.findIndex((conversation) => conversation.id === preferredConversationId)
|
|
2489
|
+
: -1;
|
|
2490
|
+
const currentIndex = conversations.findIndex((conversation) => conversation.current);
|
|
2491
|
+
const selectedIndex = preservedIndex >= 0
|
|
2492
|
+
? preservedIndex
|
|
2493
|
+
: currentIndex >= 0
|
|
2494
|
+
? currentIndex
|
|
2495
|
+
: 0;
|
|
2496
|
+
selectedMainConversationIndexRef.current = selectedIndex;
|
|
2497
|
+
setSelectedMainConversationIndex(selectedIndex);
|
|
2498
|
+
}
|
|
2499
|
+
catch (error) {
|
|
2500
|
+
if (taskSessionsLoadSequenceRef.current === sequence) {
|
|
2501
|
+
setTaskSessionsError(error instanceof Error ? error.message : String(error));
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
finally {
|
|
2505
|
+
if (manageLoading && taskSessionsLoadSequenceRef.current === sequence) {
|
|
2506
|
+
taskSessionsLoadingRef.current = false;
|
|
2507
|
+
setTaskSessionsLoading(false);
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
async function restoreSelectedMainConversation() {
|
|
2512
|
+
if (busyRef.current || taskSessionsLoadingRef.current) {
|
|
2513
|
+
return;
|
|
2514
|
+
}
|
|
2515
|
+
const selected = mainConversationsRef.current[selectedMainConversationIndexRef.current];
|
|
2516
|
+
if (!selected) {
|
|
2517
|
+
return;
|
|
2518
|
+
}
|
|
2519
|
+
taskSessionsLoadingRef.current = true;
|
|
2520
|
+
setTaskSessionsLoading(true);
|
|
2521
|
+
setTaskSessionsError(null);
|
|
2522
|
+
setTaskSessionsNotice(null);
|
|
2523
|
+
try {
|
|
2524
|
+
if (!activateMainConversation) {
|
|
2525
|
+
throw new Error("Main conversation restore is unavailable");
|
|
2526
|
+
}
|
|
2527
|
+
const result = await activateMainConversation(selected.id);
|
|
2528
|
+
if (!result.changed) {
|
|
2529
|
+
setTaskSessionsNotice(`Already current · ${result.conversation.title}`);
|
|
2530
|
+
await refreshMainConversations(result.conversation.id, false);
|
|
2531
|
+
return;
|
|
2532
|
+
}
|
|
2533
|
+
await activateTaskSession?.(null);
|
|
2534
|
+
resetActiveTaskUiForMainConversation();
|
|
2535
|
+
await appendVisibleMessage({
|
|
2536
|
+
from: "system",
|
|
2537
|
+
text: `conversation restored · ${result.conversation.title} · ${result.restoredNativeSessions} native`
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
catch (error) {
|
|
2541
|
+
setTaskSessionsError(error instanceof Error ? error.message : String(error));
|
|
2542
|
+
}
|
|
2543
|
+
finally {
|
|
2544
|
+
taskSessionsLoadingRef.current = false;
|
|
2545
|
+
setTaskSessionsLoading(false);
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
function updateMainConversationAction(next) {
|
|
2549
|
+
mainConversationActionRef.current = next;
|
|
2550
|
+
setMainConversationAction(next);
|
|
2551
|
+
}
|
|
2552
|
+
async function runMainConversationOperation(run, notice, preferredConversationId) {
|
|
2553
|
+
if (taskSessionsLoadingRef.current) {
|
|
2554
|
+
return;
|
|
2555
|
+
}
|
|
2556
|
+
taskSessionsLoadingRef.current = true;
|
|
2557
|
+
setTaskSessionsLoading(true);
|
|
2558
|
+
setTaskSessionsError(null);
|
|
2559
|
+
setTaskSessionsNotice(null);
|
|
2560
|
+
try {
|
|
2561
|
+
const result = await run();
|
|
2562
|
+
updateMainConversationAction(null);
|
|
2563
|
+
await refreshMainConversations(preferredConversationId, false);
|
|
2564
|
+
taskSessionsLoadingRef.current = false;
|
|
2565
|
+
setTaskSessionsLoading(false);
|
|
2566
|
+
setTaskSessionsNotice(typeof notice === "function" ? notice(result) : notice);
|
|
2567
|
+
}
|
|
2568
|
+
catch (error) {
|
|
2569
|
+
taskSessionsLoadingRef.current = false;
|
|
2570
|
+
setTaskSessionsLoading(false);
|
|
2571
|
+
setTaskSessionsError(error instanceof Error ? error.message : String(error));
|
|
2572
|
+
}
|
|
2573
|
+
finally {
|
|
2574
|
+
taskSessionsLoadingRef.current = false;
|
|
2575
|
+
setTaskSessionsLoading(false);
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
async function renameSelectedMainConversation(action) {
|
|
2579
|
+
await runMainConversationOperation(async () => {
|
|
2580
|
+
if (!renameMainConversation) {
|
|
2581
|
+
throw new Error("Main conversation rename is unavailable");
|
|
2582
|
+
}
|
|
2583
|
+
const title = action.value.trim();
|
|
2584
|
+
await renameMainConversation(action.conversationId, title);
|
|
2585
|
+
return title;
|
|
2586
|
+
}, (title) => `Renamed · ${title}`, action.conversationId);
|
|
2587
|
+
}
|
|
2588
|
+
async function archiveSelectedMainConversation() {
|
|
2589
|
+
const selected = mainConversationsRef.current[selectedMainConversationIndexRef.current];
|
|
2590
|
+
if (!selected) {
|
|
2591
|
+
return;
|
|
2592
|
+
}
|
|
2593
|
+
const archived = !selected.archivedAt;
|
|
2594
|
+
await runMainConversationOperation(async () => {
|
|
2595
|
+
if (!setMainConversationArchived) {
|
|
2596
|
+
throw new Error("Main conversation archive is unavailable");
|
|
2597
|
+
}
|
|
2598
|
+
await setMainConversationArchived(selected.id, archived);
|
|
2599
|
+
}, archived ? `Archived · ${selected.title}` : `Unarchived · ${selected.title}`, selected.id);
|
|
2600
|
+
}
|
|
2601
|
+
async function deleteSelectedMainConversation(action) {
|
|
2602
|
+
await runMainConversationOperation(async () => {
|
|
2603
|
+
if (!deleteMainConversation) {
|
|
2604
|
+
throw new Error("Main conversation deletion is unavailable");
|
|
2605
|
+
}
|
|
2606
|
+
await deleteMainConversation(action.conversationId);
|
|
2607
|
+
}, `Deleted · ${action.title}`);
|
|
2608
|
+
}
|
|
2609
|
+
async function exportSelectedMainConversation() {
|
|
2610
|
+
const selected = mainConversationsRef.current[selectedMainConversationIndexRef.current];
|
|
2611
|
+
if (!selected) {
|
|
2612
|
+
return;
|
|
2613
|
+
}
|
|
2614
|
+
await runMainConversationOperation(async () => {
|
|
2615
|
+
if (!exportMainConversation) {
|
|
2616
|
+
throw new Error("Main conversation export is unavailable");
|
|
2617
|
+
}
|
|
2618
|
+
return exportMainConversation(selected.id);
|
|
2619
|
+
}, (path) => `Exported · ${path}`, selected.id);
|
|
2620
|
+
}
|
|
2243
2621
|
function updateTaskSessionAction(next) {
|
|
2244
2622
|
taskSessionActionRef.current = next;
|
|
2245
2623
|
setTaskSessionAction(next);
|
|
@@ -2723,15 +3101,27 @@ export function App({ config, orchestrator, cwd, initialTaskId = null, initialRo
|
|
|
2723
3101
|
if (view === "workspace") {
|
|
2724
3102
|
return (_jsx(Box, { flexDirection: "column", height: terminalSize.rows, children: _jsx(WorkspacePicker, { cwd: cwd, choices: workspaceChoices, terminalHeight: terminalSize.rows, terminalWidth: terminalWidth, onCancel: closeWorkspacePicker, onSelect: (workspace) => void selectWorkspace(workspace) }) }));
|
|
2725
3103
|
}
|
|
2726
|
-
return (_jsx(AppShell, { view: view, cwd: cwd, taskId: activeTaskId, statusText: [visibleTaskStatus, visibleRouteSummary, configChange?.compact].filter(Boolean).join(" | "), contentHeight: contentHeight, showStatusBar: config.ui.showStatusBar, input: _jsx(InputBar, { mode: view === "worker" && workerSearch.open ? "worker-search" : view, ready: inputReady, busy: busy, routeFallback: Boolean(routeFallbackPrompt), collaborationDetail: collaborationDetailOpen, collaborationUnresolved: collaborationUnresolvedOnly, collaborationBack: collaborationReturnViewRef.current, featureCanCancel: featureCanCancel, featureCanPause: featureCanCancel, featureCanReassign: featureCanReassign, featureCancelConfirm: featureCancelPrompt?.action === "cancel", featurePauseConfirm: featureCancelPrompt?.action === "pause", featureAssignment: Boolean(featureAssignmentPrompt), taskSessionAction:
|
|
2727
|
-
?
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
3104
|
+
return (_jsx(AppShell, { view: view, cwd: cwd, taskId: activeTaskId, statusText: [visibleTaskStatus, visibleRouteSummary, configChange?.compact].filter(Boolean).join(" | "), contentHeight: contentHeight, showStatusBar: config.ui.showStatusBar, input: _jsx(InputBar, { mode: view === "worker" && workerSearch.open ? "worker-search" : view, ready: inputReady, busy: busy, routeFallback: Boolean(routeFallbackPrompt), collaborationDetail: collaborationDetailOpen, collaborationUnresolved: collaborationUnresolvedOnly, collaborationBack: collaborationReturnViewRef.current, featureCanCancel: featureCanCancel, featureCanPause: featureCanCancel, featureCanReassign: featureCanReassign, featureCancelConfirm: featureCancelPrompt?.action === "cancel", featurePauseConfirm: featureCancelPrompt?.action === "pause", featureAssignment: Boolean(featureAssignmentPrompt), taskSessionAction: sessionCenterMode === "conversations"
|
|
3105
|
+
? mainConversationAction?.type === "rename"
|
|
3106
|
+
? { type: "rename", value: mainConversationAction.value, cursor: mainConversationAction.cursor }
|
|
3107
|
+
: mainConversationAction?.type === "delete"
|
|
3108
|
+
? { type: "delete", title: mainConversationAction.title }
|
|
3109
|
+
: null
|
|
3110
|
+
: taskSessionAction?.type === "rename"
|
|
3111
|
+
? { type: "rename", value: taskSessionAction.value, cursor: taskSessionAction.cursor }
|
|
3112
|
+
: taskSessionAction?.type === "delete"
|
|
3113
|
+
? { type: "delete", title: taskSessionAction.title }
|
|
3114
|
+
: null, taskSessionsIncludeArchived: sessionCenterMode === "conversations"
|
|
3115
|
+
? mainConversationsIncludeArchived
|
|
3116
|
+
: 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, value: workerSearch.open && view === "worker"
|
|
2731
3117
|
? workerSearch.query
|
|
2732
3118
|
: view === "native" || view === "router" || view === "workers" || view === "features" || view === "sessions" || view === "collaboration" || view === "status" ? "" : input, cursor: workerSearch.open && view === "worker"
|
|
2733
3119
|
? workerSearch.cursor
|
|
2734
|
-
: view === "chat" ? inputCursor : undefined, terminalWidth: terminalWidth, onChange: view === "native" ? setNativeInput : setInput, onSubmit: view === "native" ? undefined : submit }), error: attachError, children: view === "status" ? (_jsx(StatusDetailView, { cwd: cwd, taskId: activeTaskId, mode: activeMode, busy: busy, canRetry: canRetryTask, taskStatus: visibleTaskStatus, routeStatus: visibleRouteStatus, routeReason: routePending ? undefined : lastRoute?.reason, pairing: config.pairing, configStatus: configChange?.detail, configRestartRequired: configChange?.kind === "restart", workers: workers, selectedWorkerIndex: selectedWorkerIndex, height: contentHeight, terminalWidth: terminalWidth })) : view === "native" ? (_jsx(NativeAttachView, { attach: nativeAttach, viewportHeight: contentHeight })) : view === "sessions" ? (taskSessionDetails ? (_jsx(TaskSessionDetailView, { details: taskSessionDetails, selectedWorkerIndex: taskSessionDetailSelectedWorkerIndex, loading: taskSessionsLoading, error: taskSessionsError, notice: taskSessionDetailNotice, height: contentHeight, terminalWidth: terminalWidth })) : (_jsx(
|
|
3120
|
+
: view === "chat" ? inputCursor : undefined, terminalWidth: terminalWidth, onChange: view === "native" ? setNativeInput : setInput, onSubmit: view === "native" ? undefined : submit }), error: attachError, children: view === "status" ? (_jsx(StatusDetailView, { cwd: cwd, taskId: activeTaskId, mode: activeMode, busy: busy, canRetry: canRetryTask, taskStatus: visibleTaskStatus, routeStatus: visibleRouteStatus, routeReason: routePending ? undefined : lastRoute?.reason, pairing: config.pairing, configStatus: configChange?.detail, configRestartRequired: configChange?.kind === "restart", workers: workers, selectedWorkerIndex: selectedWorkerIndex, height: contentHeight, terminalWidth: terminalWidth })) : view === "native" ? (_jsx(NativeAttachView, { attach: nativeAttach, viewportHeight: contentHeight })) : view === "sessions" ? (taskSessionDetails ? (_jsx(TaskSessionDetailView, { details: taskSessionDetails, selectedWorkerIndex: taskSessionDetailSelectedWorkerIndex, loading: taskSessionsLoading, error: taskSessionsError, notice: taskSessionDetailNotice, height: contentHeight, terminalWidth: terminalWidth })) : sessionCenterMode === "conversations" ? (_jsx(MainConversationsView, { conversations: mainConversations, selectedIndex: selectedMainConversationIndex, includeArchived: mainConversationsIncludeArchived, notice: taskSessionsNotice, action: mainConversationAction?.type === "rename"
|
|
3121
|
+
? { type: "rename", title: mainConversationAction.title }
|
|
3122
|
+
: mainConversationAction?.type === "delete"
|
|
3123
|
+
? { type: "delete", title: mainConversationAction.title }
|
|
3124
|
+
: 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"
|
|
2735
3125
|
? { type: "rename", title: taskSessionAction.title }
|
|
2736
3126
|
: taskSessionAction?.type === "delete"
|
|
2737
3127
|
? { 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, taskSessionAction = null, taskSessionsIncludeArchived = 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, 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, 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, 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) {
|
|
@@ -39,6 +39,10 @@ export function InputBar({ mode, ready = true, busy = false, routeFallback = fal
|
|
|
39
39
|
const hints = taskSessionDetailInputHints(terminalWidth, taskSessionDetailHasNative, taskSessionDetailCanFork);
|
|
40
40
|
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] }));
|
|
41
41
|
}
|
|
42
|
+
if (mainConversationSessions) {
|
|
43
|
+
const hints = mainConversationSessionsInputHints(terminalWidth, taskSessionsIncludeArchived);
|
|
44
|
+
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] }));
|
|
45
|
+
}
|
|
42
46
|
const hints = taskSessionsInputHints(terminalWidth, taskSessionsIncludeArchived);
|
|
43
47
|
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] }));
|
|
44
48
|
}
|
|
@@ -564,9 +568,13 @@ function collaborationDetailInputHints(width) {
|
|
|
564
568
|
function taskSessionsInputHints(width, includeArchived) {
|
|
565
569
|
const archivedAction = includeArchived ? "H hide archived" : "H archived";
|
|
566
570
|
return selectInputHints(width, [
|
|
567
|
-
{ label: "sessions", detail: ` · Up/Dn select · Enter restore · I inspect · R rename · A archive · D delete · E export · ${archivedAction} · Esc back` },
|
|
568
|
-
{ label: "sessions", detail: " · Up/Dn select · Enter restore · I inspect · R rename · A archive · D delete · E export · Esc back" },
|
|
569
|
-
{ label: "sessions", detail: " · Up/Dn select · Enter restore · I inspect · R rename · A archive · D delete · Esc back" },
|
|
571
|
+
{ label: "sessions", detail: ` · Up/Dn select · Enter restore · C conversations · I inspect · R rename · A archive · D delete · E export · ${archivedAction} · Esc back` },
|
|
572
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · C conversations · I inspect · R rename · A archive · D delete · E export · Esc back" },
|
|
573
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · C chats · I inspect · R rename · A archive · D delete · Esc back" },
|
|
574
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · C chats · I inspect · R rename · A archive · Esc back" },
|
|
575
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · C chats · I inspect · R rename · Esc back" },
|
|
576
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · C chats · R rename · Esc back" },
|
|
577
|
+
{ label: "sessions", detail: " · Up/Dn select · Enter restore · C chats · Esc back" },
|
|
570
578
|
{ label: "sessions", detail: " · Up/Dn select · Enter restore · I inspect · R rename · A archive · Esc back" },
|
|
571
579
|
{ label: "sessions", detail: " · Up/Dn select · Enter restore · I inspect · R rename · Esc back" },
|
|
572
580
|
{ label: "sessions", detail: " · Up/Dn select · Enter restore · R rename · Esc back" },
|
|
@@ -580,6 +588,24 @@ function taskSessionsInputHints(width, includeArchived) {
|
|
|
580
588
|
{ label: "s", detail: "" }
|
|
581
589
|
]);
|
|
582
590
|
}
|
|
591
|
+
export function mainConversationSessionsInputHints(width, includeArchived) {
|
|
592
|
+
const archivedAction = includeArchived ? "H hide archived" : "H archived";
|
|
593
|
+
return selectInputHints(width, [
|
|
594
|
+
{ label: "conversations", detail: ` · Up/Dn select · Enter restore · R rename · A archive · D delete · E export · ${archivedAction} · N new · T tasks · Esc back` },
|
|
595
|
+
{ label: "conversations", detail: " · Up/Dn select · Enter restore · R rename · A archive · D delete · E export · N new · T tasks · Esc back" },
|
|
596
|
+
{ label: "conversations", detail: " · Up/Dn select · Enter restore · R rename · A archive · D delete · N new · T tasks · Esc back" },
|
|
597
|
+
{ label: "conversations", detail: " · Up/Dn select · Enter restore · R rename · A archive · N new · T tasks · Esc back" },
|
|
598
|
+
{ label: "conversations", detail: " · Up/Dn select · Enter restore · R rename · N new · T tasks · Esc back" },
|
|
599
|
+
{ label: "conversations", detail: " · Up/Dn select · Enter restore · N new · T tasks · Esc back" },
|
|
600
|
+
{ label: "conversations", detail: " · Up/Dn select · Enter restore · T tasks · Esc back" },
|
|
601
|
+
{ label: "conversations", detail: " · Up/Dn select · Enter restore · Esc back" },
|
|
602
|
+
{ label: "conversations", detail: " · Up/Dn select · Esc back" },
|
|
603
|
+
{ label: "conversations", detail: " · Esc back" },
|
|
604
|
+
{ label: "Esc back", detail: "" },
|
|
605
|
+
{ label: "chats", detail: "" },
|
|
606
|
+
{ label: "c", detail: "" }
|
|
607
|
+
]);
|
|
608
|
+
}
|
|
583
609
|
function taskSessionDetailInputHints(width, hasNative, canFork) {
|
|
584
610
|
const nativeActions = hasNative
|
|
585
611
|
? `${canFork ? "C continue · B branch" : "C continue"} · `
|