@cueloop/client 0.1.0-alpha.69 → 0.1.0-alpha.70
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/package.json +5 -5
- package/src/App.appearance.test.tsx +2 -2
- package/src/App.autoclose.test.tsx +2 -2
- package/src/App.diff.test.tsx +2 -2
- package/src/App.export.test.tsx +2 -2
- package/src/App.plan-review.test.tsx +2 -2
- package/src/App.prototype-markdown.test.tsx +2 -2
- package/src/App.prototype.test.tsx +2 -2
- package/src/App.readonly.test.tsx +2 -2
- package/src/App.rendering.test.tsx +2 -2
- package/src/App.submit-confirm.test.tsx +2 -2
- package/src/App.test.tsx +2 -2
- package/src/App.toast.test.tsx +3 -3
- package/src/App.tsx +240 -228
- package/src/App.walk.test.tsx +2 -2
- package/src/App.workbench.test.tsx +2 -2
- package/src/app-key-state.ts +3 -3
- package/src/app-screens.tsx +4 -4
- package/src/app-view-model.ts +6 -6
- package/src/components/AnnotatableFileView.stories.tsx +2 -2
- package/src/components/AnnotatableFileView.test.tsx +2 -2
- package/src/components/AnnotatableFileView.tsx +2 -2
- package/src/components/BareWorkbenchFileView.tsx +2 -7
- package/src/components/ChangesColumn.tsx +2 -2
- package/src/components/DiffContentView.tsx +2 -2
- package/src/components/ThreadView.selection.test.tsx +5 -5
- package/src/components/ThreadView.slash.test.tsx +49 -4
- package/src/components/ThreadView.tsx +2 -2
- package/src/components/WelcomePlayground.tsx +2 -2
- package/src/components/__snapshots__/stories.test.tsx.snap +6 -6
- package/src/components/agent-launcher.tsx +2 -2
- package/src/components/quick-actions-editor.test.tsx +49 -0
- package/src/components/quick-actions-editor.tsx +32 -20
- package/src/components/session-tree.test.ts +2 -2
- package/src/components/session-tree.ts +10 -10
- package/src/components/story-fixtures.ts +3 -3
- package/src/config.test.ts +30 -1
- package/src/config.ts +19 -0
- package/src/discussions.ts +2 -2
- package/src/intent-dispatch.test.ts +3 -6
- package/src/intent-dispatch.ts +6 -6
- package/src/serve.test.ts +2 -2
- package/src/share.ts +9 -14
- package/src/skills.test.ts +74 -0
- package/src/skills.ts +68 -0
- package/src/slash-palette.ts +10 -3
- package/src/{session-controller.curate.test.ts → thread-controller.curate.test.ts} +8 -7
- package/src/{session-controller.live-diff.test.ts → thread-controller.live-diff.test.ts} +7 -6
- package/src/{session-controller.share.test.ts → thread-controller.share.test.ts} +14 -13
- package/src/{session-controller.tree.test.ts → thread-controller.tree.test.ts} +8 -7
- package/src/{session-controller.ts → thread-controller.ts} +18 -22
- package/src/use-annotation-surface.tsx +14 -10
- package/src/view-diff.ts +2 -2
package/src/App.tsx
CHANGED
|
@@ -21,6 +21,8 @@ import {
|
|
|
21
21
|
type DiffViewMode,
|
|
22
22
|
type QuickAction,
|
|
23
23
|
} from "./config";
|
|
24
|
+
import { loadSkills, SlashSkillsContext } from "./skills";
|
|
25
|
+
import type { SlashItem } from "./slash-palette";
|
|
24
26
|
import {
|
|
25
27
|
composeTheme,
|
|
26
28
|
DEFAULT_THEME_NAME,
|
|
@@ -29,7 +31,7 @@ import {
|
|
|
29
31
|
type ThemeName,
|
|
30
32
|
} from "./theme-presets";
|
|
31
33
|
import type { Theme } from "./theme";
|
|
32
|
-
import { createReviewController, type ShareTransport } from "./
|
|
34
|
+
import { createReviewController, type ShareTransport } from "./thread-controller";
|
|
33
35
|
import type { SessionClient } from "@cueloop/daemon/client";
|
|
34
36
|
import { createIntentDispatch, type Mode, type RailTab } from "./intent-dispatch";
|
|
35
37
|
import { reduceKey, type KeyState } from "./keymap";
|
|
@@ -64,7 +66,7 @@ import {
|
|
|
64
66
|
} from "./components/DiffContentView";
|
|
65
67
|
import { commentCountsByFile, fileTargetMarks, marksByRows, type DiffRow } from "./view-diff";
|
|
66
68
|
import { annotationTarget, type Anchor } from "@cueloop/schema";
|
|
67
|
-
import type { DiffFileContents,
|
|
69
|
+
import type { DiffFileContents, Thread } from "@cueloop/schema";
|
|
68
70
|
import { PrototypePixels } from "./prototype-pixels";
|
|
69
71
|
import type { PrototypeElement } from "./prototype-browser";
|
|
70
72
|
import {
|
|
@@ -355,8 +357,8 @@ function ProjectPanelBody(props: {
|
|
|
355
357
|
/** The render tree has left the connecting screen: an error, a session, or the no-thread shell. */
|
|
356
358
|
function usableScreenReached(
|
|
357
359
|
error: string | null,
|
|
358
|
-
session:
|
|
359
|
-
inbox:
|
|
360
|
+
session: Thread | null,
|
|
361
|
+
inbox: Thread[] | null,
|
|
360
362
|
): boolean {
|
|
361
363
|
return Boolean(error) || session !== null || inbox !== null;
|
|
362
364
|
}
|
|
@@ -487,6 +489,7 @@ export function App({
|
|
|
487
489
|
const [themeOverrides, setThemeOverrides] = useState<Partial<Theme>>({});
|
|
488
490
|
const [authorNames, setAuthorNames] = useState<Record<string, string>>({});
|
|
489
491
|
const [quickActions, setQuickActions] = useState<QuickAction[]>(DEFAULT_QUICK_ACTIONS);
|
|
492
|
+
const [skills, setSkills] = useState<SlashItem[]>([]);
|
|
490
493
|
// opt-in: render a prototype as a kitty pixel mockup instead of the markdown doc
|
|
491
494
|
const [prototypePixels, setPrototypePixels] = useState(false);
|
|
492
495
|
|
|
@@ -501,6 +504,7 @@ export function App({
|
|
|
501
504
|
setThemeOverrides(config.themeOverrides);
|
|
502
505
|
setAuthorNames(config.authors);
|
|
503
506
|
setQuickActions(config.actions);
|
|
507
|
+
setSkills(loadSkills(config.skillsPath));
|
|
504
508
|
setAutoClose(config.ui.autoClose);
|
|
505
509
|
setDiffView(config.ui.diffView);
|
|
506
510
|
setPinnedIds(new Set(config.ui.pins));
|
|
@@ -787,23 +791,25 @@ export function App({
|
|
|
787
791
|
if (error) return <ErrorScreen error={error} theme={theme} />;
|
|
788
792
|
if (!session)
|
|
789
793
|
return inbox ? (
|
|
790
|
-
<
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
794
|
+
<SlashSkillsContext.Provider value={skills}>
|
|
795
|
+
<NoThreadShell
|
|
796
|
+
rows={grouped.rows}
|
|
797
|
+
inboxCursor={inboxCursor}
|
|
798
|
+
mode={mode}
|
|
799
|
+
theme={theme}
|
|
800
|
+
controller={controller}
|
|
801
|
+
setMode={setMode}
|
|
802
|
+
menuChrome={menuChrome}
|
|
803
|
+
onOpenMenu={() => setMenuDialog("settings")}
|
|
804
|
+
sidebarOpen={sidebarOpen}
|
|
805
|
+
onToggleSidebar={() => setSidebarOpen((open) => !open)}
|
|
806
|
+
pinnedIds={pinnedIds}
|
|
807
|
+
onPin={togglePin}
|
|
808
|
+
onRename={(id, title) => setMode({ type: "renameThread", sessionId: id, text: title })}
|
|
809
|
+
quickActions={quickActions}
|
|
810
|
+
onWelcomeComposingChange={setWelcomeComposing}
|
|
811
|
+
/>
|
|
812
|
+
</SlashSkillsContext.Provider>
|
|
807
813
|
) : (
|
|
808
814
|
<ConnectingScreen theme={theme} />
|
|
809
815
|
);
|
|
@@ -873,221 +879,227 @@ export function App({
|
|
|
873
879
|
};
|
|
874
880
|
|
|
875
881
|
return (
|
|
876
|
-
<
|
|
877
|
-
<
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
<
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
<
|
|
903
|
-
{
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
{
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
<box style={{ flexGrow: 1, flexDirection: "
|
|
914
|
-
{
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
<
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
882
|
+
<SlashSkillsContext.Provider value={skills}>
|
|
883
|
+
<ThemeProvider theme={theme}>
|
|
884
|
+
<AppShell
|
|
885
|
+
sidebarOpen={sidebarOpen}
|
|
886
|
+
onToggleSidebar={() => setSidebarOpen((open) => !open)}
|
|
887
|
+
onOpenMenu={() => setMenuDialog("settings")}
|
|
888
|
+
threadsPanel={
|
|
889
|
+
<scrollbox style={{ flexGrow: 1 }} focused={false}>
|
|
890
|
+
<ThreadTree
|
|
891
|
+
rows={grouped.rows}
|
|
892
|
+
cursor={inboxCursor}
|
|
893
|
+
activeId={activeSession.id}
|
|
894
|
+
pinnedIds={pinnedIds}
|
|
895
|
+
width={30}
|
|
896
|
+
onSelect={(id) => controller.open(id)}
|
|
897
|
+
onPin={togglePin}
|
|
898
|
+
onRename={(id, title) =>
|
|
899
|
+
setMode({ type: "renameThread", sessionId: id, text: title })
|
|
900
|
+
}
|
|
901
|
+
theme={theme}
|
|
902
|
+
/>
|
|
903
|
+
</scrollbox>
|
|
904
|
+
}
|
|
905
|
+
threadTitle={threadTitle(activeSession)}
|
|
906
|
+
threadActions={
|
|
907
|
+
showOwnerActions ? (
|
|
908
|
+
<Toolbar>
|
|
909
|
+
<Button onPress={onEditRequest} theme={theme}>
|
|
910
|
+
{" edit "}
|
|
911
|
+
</Button>
|
|
912
|
+
<Button onPress={onShareRequest} theme={theme}>
|
|
913
|
+
{" share "}
|
|
914
|
+
</Button>
|
|
915
|
+
</Toolbar>
|
|
916
|
+
) : undefined
|
|
917
|
+
}
|
|
918
|
+
threadPanel={
|
|
919
|
+
<box style={{ flexGrow: 1, flexDirection: "column" }}>
|
|
920
|
+
<box style={{ flexGrow: 1, flexDirection: "row" }}>
|
|
921
|
+
{isPixelPrototype ? (
|
|
922
|
+
<PrototypePixels
|
|
923
|
+
prototypePath={prototypePath}
|
|
924
|
+
canComment={prototypeCanComment}
|
|
925
|
+
onCommentElement={onCommentPrototype}
|
|
926
|
+
onComposingChange={setPrototypeComposing}
|
|
927
|
+
hidden={chromeHidden}
|
|
928
|
+
/>
|
|
929
|
+
) : isDiff ? (
|
|
930
|
+
<box style={{ flexGrow: 1, paddingLeft: 2, paddingTop: 1 }}>
|
|
931
|
+
<text fg={theme.textDim}>review the changes on the right</text>
|
|
932
|
+
</box>
|
|
933
|
+
) : (
|
|
934
|
+
<ThreadView
|
|
935
|
+
session={activeSession}
|
|
936
|
+
suspended={threadViewSuspended}
|
|
937
|
+
editOrphanCount={editOrphanCount}
|
|
938
|
+
onComposingChange={setThreadComposing}
|
|
939
|
+
resolved={resolved}
|
|
940
|
+
onObserverBlocked={(reason) =>
|
|
941
|
+
controller.setStatus(
|
|
942
|
+
reason === "observer"
|
|
943
|
+
? "observer - read-only"
|
|
944
|
+
: "review submitted - read-only",
|
|
945
|
+
)
|
|
946
|
+
}
|
|
947
|
+
onCursorChange={setCursor}
|
|
948
|
+
focusedAnnotationId={focusedAnnotationId}
|
|
949
|
+
onFocusAnnotation={setFocusedAnnotationId}
|
|
950
|
+
display={display}
|
|
951
|
+
marks={marks}
|
|
952
|
+
quickActions={quickActions}
|
|
953
|
+
observer={observer}
|
|
954
|
+
onAnnotate={(span, body) =>
|
|
955
|
+
void controller.annotate(
|
|
956
|
+
"comment",
|
|
957
|
+
span.start.blockIndex,
|
|
958
|
+
span.start.char,
|
|
959
|
+
span.end.char,
|
|
960
|
+
body,
|
|
961
|
+
span.end.blockIndex,
|
|
962
|
+
)
|
|
963
|
+
}
|
|
964
|
+
onReply={(rootAnnotationId, body) =>
|
|
965
|
+
void controller.reply(rootAnnotationId, body)
|
|
966
|
+
}
|
|
967
|
+
onUpdateAnnotation={(id, body) => controller.updateAnnotation(id, body)}
|
|
968
|
+
onExit={() => onExit?.(0)}
|
|
969
|
+
/>
|
|
970
|
+
)}
|
|
971
|
+
</box>
|
|
972
|
+
<ThreadFooter
|
|
973
|
+
repo={projectName(activeSession.workspace)}
|
|
974
|
+
branch={activeSession.workspace.branch}
|
|
975
|
+
onSubmit={onSubmitRequest}
|
|
976
|
+
canSubmit={canSubmitReview(isOwner, resolved, observer)}
|
|
977
|
+
theme={theme}
|
|
978
|
+
/>
|
|
979
|
+
</box>
|
|
980
|
+
}
|
|
981
|
+
changesOpen={workbench.changesOpen}
|
|
982
|
+
projectOpen={workbench.projectOpen}
|
|
983
|
+
onToggleChanges={workbench.toggleChanges}
|
|
984
|
+
onToggleProject={workbench.toggleProject}
|
|
985
|
+
onToggleRight={workbench.toggleRight}
|
|
986
|
+
projectMode={workbench.projectMode}
|
|
987
|
+
zoomHideThread={workbench.zoomed}
|
|
988
|
+
changesPanel={
|
|
989
|
+
<EditorGrid
|
|
990
|
+
tree={workbench.grid}
|
|
991
|
+
focusedGroupId={workbench.activeGroup}
|
|
992
|
+
commentCounts={diffCommentCounts}
|
|
993
|
+
onFocusGroup={workbench.focusGroup}
|
|
994
|
+
onActivateTab={workbench.activate}
|
|
995
|
+
onCloseTab={workbench.close}
|
|
996
|
+
onSplit={workbench.split}
|
|
997
|
+
onZoom={workbench.toggleZoom}
|
|
998
|
+
zoomed={workbench.zoomed}
|
|
999
|
+
renderTab={(tab, groupFocused) => (
|
|
1000
|
+
<GridTabContent
|
|
1001
|
+
tab={tab}
|
|
1002
|
+
rows={rows}
|
|
1003
|
+
surface={{
|
|
1004
|
+
session: activeSession,
|
|
1005
|
+
quickActions,
|
|
1006
|
+
observer,
|
|
1007
|
+
commentsEnabled: true,
|
|
1008
|
+
resolved,
|
|
1009
|
+
suspended: threadViewSuspended || !groupFocused,
|
|
1010
|
+
onComposingChange: setThreadComposing,
|
|
1011
|
+
onObserverBlocked: (reason) =>
|
|
1012
|
+
controller.setStatus(
|
|
1013
|
+
reason === "observer"
|
|
1014
|
+
? "observer - read-only"
|
|
1015
|
+
: "review submitted - read-only",
|
|
1016
|
+
),
|
|
1017
|
+
onCursorChange: setCursor,
|
|
1018
|
+
focusedAnnotationId,
|
|
1019
|
+
onFocusAnnotation: setFocusedAnnotationId,
|
|
1020
|
+
// a diff thread's Changes view is the artifact itself; any other thread's is the
|
|
1021
|
+
// live working-tree diff, so its notes carry a file target and anchor there
|
|
1022
|
+
onAnnotate: (span, body) =>
|
|
1023
|
+
void controller.annotate(
|
|
1024
|
+
"comment",
|
|
1025
|
+
span.start.blockIndex,
|
|
1026
|
+
span.start.char,
|
|
1027
|
+
span.end.char,
|
|
1028
|
+
body,
|
|
1029
|
+
span.end.blockIndex,
|
|
1030
|
+
isDiff ? { kind: "artifact" } : { kind: "file", path: "", rev: "worktree" },
|
|
1031
|
+
),
|
|
1032
|
+
onReply: (rootAnnotationId, body) =>
|
|
1033
|
+
void controller.reply(rootAnnotationId, body),
|
|
1034
|
+
onUpdateAnnotation: (id, body) => controller.updateAnnotation(id, body),
|
|
1035
|
+
onExit: () => onExit?.(0),
|
|
1036
|
+
}}
|
|
1037
|
+
rejectedRows={rejectedRows}
|
|
1038
|
+
fold={diffFold}
|
|
1039
|
+
fileStats={controller.fileStats()}
|
|
1040
|
+
split={diffView === "split" && workbench.zoomed}
|
|
1041
|
+
dimmed={walking}
|
|
1042
|
+
readFile={(path) => controller.repoReadFile(path)}
|
|
1043
|
+
onAddFileComment={(path, anchor, body) =>
|
|
1044
|
+
void controller.addComment(
|
|
1045
|
+
anchor,
|
|
1046
|
+
{ kind: "file", path, rev: "worktree" },
|
|
953
1047
|
body,
|
|
954
|
-
span.end.blockIndex,
|
|
955
1048
|
)
|
|
956
1049
|
}
|
|
957
|
-
|
|
958
|
-
void controller.reply(rootAnnotationId, body)
|
|
959
|
-
}
|
|
960
|
-
onUpdateAnnotation={(id, body) => controller.updateAnnotation(id, body)}
|
|
961
|
-
onExit={() => onExit?.(0)}
|
|
1050
|
+
theme={theme}
|
|
962
1051
|
/>
|
|
963
1052
|
)}
|
|
964
|
-
</box>
|
|
965
|
-
<ThreadFooter
|
|
966
|
-
repo={projectName(activeSession.workspace)}
|
|
967
|
-
branch={activeSession.workspace.branch}
|
|
968
|
-
onSubmit={onSubmitRequest}
|
|
969
|
-
canSubmit={canSubmitReview(isOwner, resolved, observer)}
|
|
970
1053
|
theme={theme}
|
|
971
1054
|
/>
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
surface={{
|
|
997
|
-
session: activeSession,
|
|
998
|
-
quickActions,
|
|
999
|
-
observer,
|
|
1000
|
-
commentsEnabled: true,
|
|
1001
|
-
resolved,
|
|
1002
|
-
suspended: threadViewSuspended || !groupFocused,
|
|
1003
|
-
onComposingChange: setThreadComposing,
|
|
1004
|
-
onObserverBlocked: (reason) =>
|
|
1005
|
-
controller.setStatus(
|
|
1006
|
-
reason === "observer"
|
|
1007
|
-
? "observer - read-only"
|
|
1008
|
-
: "review submitted - read-only",
|
|
1009
|
-
),
|
|
1010
|
-
onCursorChange: setCursor,
|
|
1011
|
-
focusedAnnotationId,
|
|
1012
|
-
onFocusAnnotation: setFocusedAnnotationId,
|
|
1013
|
-
// a diff thread's Changes view is the artifact itself; any other thread's is the
|
|
1014
|
-
// live working-tree diff, so its notes carry a file target and anchor there
|
|
1015
|
-
onAnnotate: (span, body) =>
|
|
1016
|
-
void controller.annotate(
|
|
1017
|
-
"comment",
|
|
1018
|
-
span.start.blockIndex,
|
|
1019
|
-
span.start.char,
|
|
1020
|
-
span.end.char,
|
|
1021
|
-
body,
|
|
1022
|
-
span.end.blockIndex,
|
|
1023
|
-
isDiff ? { kind: "artifact" } : { kind: "file", path: "", rev: "worktree" },
|
|
1024
|
-
),
|
|
1025
|
-
onReply: (rootAnnotationId, body) =>
|
|
1026
|
-
void controller.reply(rootAnnotationId, body),
|
|
1027
|
-
onUpdateAnnotation: (id, body) => controller.updateAnnotation(id, body),
|
|
1028
|
-
onExit: () => onExit?.(0),
|
|
1029
|
-
}}
|
|
1030
|
-
rejectedRows={rejectedRows}
|
|
1031
|
-
fold={diffFold}
|
|
1032
|
-
fileStats={controller.fileStats()}
|
|
1033
|
-
split={diffView === "split" && workbench.zoomed}
|
|
1034
|
-
dimmed={walking}
|
|
1035
|
-
readFile={(path) => controller.repoReadFile(path)}
|
|
1036
|
-
onAddFileComment={(path, anchor, body) =>
|
|
1037
|
-
void controller.addComment(anchor, { kind: "file", path, rev: "worktree" }, body)
|
|
1038
|
-
}
|
|
1039
|
-
theme={theme}
|
|
1040
|
-
/>
|
|
1041
|
-
)}
|
|
1042
|
-
theme={theme}
|
|
1043
|
-
/>
|
|
1044
|
-
}
|
|
1045
|
-
projectPanel={
|
|
1046
|
-
<ProjectPanelBody
|
|
1047
|
-
mode={workbench.projectMode}
|
|
1048
|
-
loadChanges={() => controller.repoChanges()}
|
|
1049
|
-
loadProjectFiles={() => controller.repoFiles()}
|
|
1050
|
-
reloadKey={activeSession.id}
|
|
1051
|
-
// the Changes navigator always opens a changed file as a diff - a diff review shows its
|
|
1052
|
-
// captured snapshot, every other thread the live working-tree diff
|
|
1053
|
-
onOpenChangedFile={(path) => workbench.openFile(path, "diff")}
|
|
1054
|
-
onOpenProjectFile={(path) => workbench.openFile(path, "contents")}
|
|
1055
|
-
commentCounts={diffCommentCounts}
|
|
1055
|
+
}
|
|
1056
|
+
projectPanel={
|
|
1057
|
+
<ProjectPanelBody
|
|
1058
|
+
mode={workbench.projectMode}
|
|
1059
|
+
loadChanges={() => controller.repoChanges()}
|
|
1060
|
+
loadProjectFiles={() => controller.repoFiles()}
|
|
1061
|
+
reloadKey={activeSession.id}
|
|
1062
|
+
// the Changes navigator always opens a changed file as a diff - a diff review shows its
|
|
1063
|
+
// captured snapshot, every other thread the live working-tree diff
|
|
1064
|
+
onOpenChangedFile={(path) => workbench.openFile(path, "diff")}
|
|
1065
|
+
onOpenProjectFile={(path) => workbench.openFile(path, "contents")}
|
|
1066
|
+
commentCounts={diffCommentCounts}
|
|
1067
|
+
theme={theme}
|
|
1068
|
+
/>
|
|
1069
|
+
}
|
|
1070
|
+
theme={theme}
|
|
1071
|
+
>
|
|
1072
|
+
<TrailingOverlays
|
|
1073
|
+
walking={walking}
|
|
1074
|
+
walk={walk}
|
|
1075
|
+
walkFileList={walkFileList}
|
|
1076
|
+
viewedPaths={viewedPaths}
|
|
1077
|
+
session={activeSession}
|
|
1078
|
+
terminalWidth={terminalWidth}
|
|
1056
1079
|
theme={theme}
|
|
1080
|
+
mode={mode}
|
|
1081
|
+
toast={toast}
|
|
1082
|
+
setMode={setMode}
|
|
1083
|
+
dispatch={dispatch}
|
|
1057
1084
|
/>
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
position: "absolute",
|
|
1078
|
-
left: 0,
|
|
1079
|
-
top: 0,
|
|
1080
|
-
width: "100%",
|
|
1081
|
-
height: "100%",
|
|
1082
|
-
justifyContent: "center",
|
|
1083
|
-
alignItems: "center",
|
|
1084
|
-
}}
|
|
1085
|
-
>
|
|
1086
|
-
<ConfirmCard {...submitConfirmState} theme={theme} />
|
|
1087
|
-
</box>
|
|
1088
|
-
) : null}
|
|
1089
|
-
{menuChrome}
|
|
1090
|
-
</AppShell>
|
|
1091
|
-
</ThemeProvider>
|
|
1085
|
+
{submitConfirmState !== null ? (
|
|
1086
|
+
<box
|
|
1087
|
+
style={{
|
|
1088
|
+
position: "absolute",
|
|
1089
|
+
left: 0,
|
|
1090
|
+
top: 0,
|
|
1091
|
+
width: "100%",
|
|
1092
|
+
height: "100%",
|
|
1093
|
+
justifyContent: "center",
|
|
1094
|
+
alignItems: "center",
|
|
1095
|
+
}}
|
|
1096
|
+
>
|
|
1097
|
+
<ConfirmCard {...submitConfirmState} theme={theme} />
|
|
1098
|
+
</box>
|
|
1099
|
+
) : null}
|
|
1100
|
+
{menuChrome}
|
|
1101
|
+
</AppShell>
|
|
1102
|
+
</ThemeProvider>
|
|
1103
|
+
</SlashSkillsContext.Provider>
|
|
1092
1104
|
);
|
|
1093
1105
|
}
|
package/src/App.walk.test.tsx
CHANGED
|
@@ -6,7 +6,7 @@ import { tmpdir } from "node:os";
|
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
import React from "react";
|
|
8
8
|
import { DaemonServer } from "@cueloop/daemon";
|
|
9
|
-
import type {
|
|
9
|
+
import type { Thread } from "@cueloop/schema";
|
|
10
10
|
import { App } from "./App";
|
|
11
11
|
import { DARK } from "./theme";
|
|
12
12
|
import {
|
|
@@ -47,7 +47,7 @@ index 555..666 100644
|
|
|
47
47
|
let home: string;
|
|
48
48
|
let restoreUserConfig: () => void;
|
|
49
49
|
let server: DaemonServer;
|
|
50
|
-
let session:
|
|
50
|
+
let session: Thread;
|
|
51
51
|
|
|
52
52
|
beforeEach(() => {
|
|
53
53
|
home = mkdtempSync(join(tmpdir(), "cueloop-walk-"));
|
|
@@ -13,7 +13,7 @@ import { join } from "node:path";
|
|
|
13
13
|
import React from "react";
|
|
14
14
|
import { testRender } from "@opentui/react/test-utils";
|
|
15
15
|
import { DaemonServer } from "@cueloop/daemon";
|
|
16
|
-
import type {
|
|
16
|
+
import type { Thread } from "@cueloop/schema";
|
|
17
17
|
import { App } from "./App";
|
|
18
18
|
import {
|
|
19
19
|
dragText,
|
|
@@ -42,7 +42,7 @@ let home: string;
|
|
|
42
42
|
let repo: string;
|
|
43
43
|
let restoreUserConfig: () => void;
|
|
44
44
|
let server: DaemonServer;
|
|
45
|
-
let session:
|
|
45
|
+
let session: Thread;
|
|
46
46
|
|
|
47
47
|
/** A throwaway git repo so the Project tree (git ls-files) and file contents resolve without a real checkout. */
|
|
48
48
|
function makeRepo(): string {
|
package/src/app-key-state.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Thread } from "@cueloop/schema";
|
|
2
2
|
import type { Mode } from "./intent-dispatch";
|
|
3
3
|
import type { KeyState } from "./keymap";
|
|
4
4
|
import type { DisplayBlock } from "./view-plan";
|
|
@@ -10,11 +10,11 @@ export function buildKeyState(params: {
|
|
|
10
10
|
observer: boolean;
|
|
11
11
|
isOwner: boolean;
|
|
12
12
|
overlay: KeyState["overlay"];
|
|
13
|
-
session:
|
|
13
|
+
session: Thread | null;
|
|
14
14
|
isDiff: boolean;
|
|
15
15
|
mode: Mode;
|
|
16
16
|
resolved: boolean;
|
|
17
|
-
inbox:
|
|
17
|
+
inbox: Thread[] | null;
|
|
18
18
|
focusedAnnotationId: string | undefined;
|
|
19
19
|
walk: { index: number } | null;
|
|
20
20
|
walkFileList: WalkFile[];
|
package/src/app-screens.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ScrollArea } from "./components/ScrollArea";
|
|
2
2
|
import React, { useEffect, useState, type Dispatch, type SetStateAction } from "react";
|
|
3
|
-
import type { DiffFileContents,
|
|
3
|
+
import type { DiffFileContents, Thread, VerdictKind } from "@cueloop/schema";
|
|
4
4
|
import { returnPaneFor } from "@cueloop/schema";
|
|
5
5
|
import type { Theme } from "./theme";
|
|
6
6
|
import type { QuickAction } from "./config";
|
|
7
7
|
import type { Mode, TreeAsk } from "./intent-dispatch";
|
|
8
8
|
import type { Intent } from "./keymap";
|
|
9
|
-
import type { ReviewController, ToastState } from "./
|
|
9
|
+
import type { ReviewController, ToastState } from "./thread-controller";
|
|
10
10
|
import { noteForFile } from "./walk";
|
|
11
11
|
import type { WalkFile } from "./walk";
|
|
12
12
|
import type { CheatsheetSection } from "./key-bindings";
|
|
@@ -297,7 +297,7 @@ export function NoThreadShell(props: {
|
|
|
297
297
|
|
|
298
298
|
export function CompletionScreen(props: {
|
|
299
299
|
theme: Theme;
|
|
300
|
-
session:
|
|
300
|
+
session: Thread;
|
|
301
301
|
verdict: VerdictKind;
|
|
302
302
|
completion: { phase: "prompt" } | { phase: "counting"; remaining: number };
|
|
303
303
|
status: string;
|
|
@@ -340,7 +340,7 @@ export function TrailingOverlays(props: {
|
|
|
340
340
|
walk: { index: number } | null;
|
|
341
341
|
walkFileList: WalkFile[];
|
|
342
342
|
viewedPaths: Set<string>;
|
|
343
|
-
session:
|
|
343
|
+
session: Thread;
|
|
344
344
|
terminalWidth: number;
|
|
345
345
|
theme: Theme;
|
|
346
346
|
mode: Mode;
|