@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.
Files changed (53) hide show
  1. package/package.json +5 -5
  2. package/src/App.appearance.test.tsx +2 -2
  3. package/src/App.autoclose.test.tsx +2 -2
  4. package/src/App.diff.test.tsx +2 -2
  5. package/src/App.export.test.tsx +2 -2
  6. package/src/App.plan-review.test.tsx +2 -2
  7. package/src/App.prototype-markdown.test.tsx +2 -2
  8. package/src/App.prototype.test.tsx +2 -2
  9. package/src/App.readonly.test.tsx +2 -2
  10. package/src/App.rendering.test.tsx +2 -2
  11. package/src/App.submit-confirm.test.tsx +2 -2
  12. package/src/App.test.tsx +2 -2
  13. package/src/App.toast.test.tsx +3 -3
  14. package/src/App.tsx +240 -228
  15. package/src/App.walk.test.tsx +2 -2
  16. package/src/App.workbench.test.tsx +2 -2
  17. package/src/app-key-state.ts +3 -3
  18. package/src/app-screens.tsx +4 -4
  19. package/src/app-view-model.ts +6 -6
  20. package/src/components/AnnotatableFileView.stories.tsx +2 -2
  21. package/src/components/AnnotatableFileView.test.tsx +2 -2
  22. package/src/components/AnnotatableFileView.tsx +2 -2
  23. package/src/components/BareWorkbenchFileView.tsx +2 -7
  24. package/src/components/ChangesColumn.tsx +2 -2
  25. package/src/components/DiffContentView.tsx +2 -2
  26. package/src/components/ThreadView.selection.test.tsx +5 -5
  27. package/src/components/ThreadView.slash.test.tsx +49 -4
  28. package/src/components/ThreadView.tsx +2 -2
  29. package/src/components/WelcomePlayground.tsx +2 -2
  30. package/src/components/__snapshots__/stories.test.tsx.snap +6 -6
  31. package/src/components/agent-launcher.tsx +2 -2
  32. package/src/components/quick-actions-editor.test.tsx +49 -0
  33. package/src/components/quick-actions-editor.tsx +32 -20
  34. package/src/components/session-tree.test.ts +2 -2
  35. package/src/components/session-tree.ts +10 -10
  36. package/src/components/story-fixtures.ts +3 -3
  37. package/src/config.test.ts +30 -1
  38. package/src/config.ts +19 -0
  39. package/src/discussions.ts +2 -2
  40. package/src/intent-dispatch.test.ts +3 -6
  41. package/src/intent-dispatch.ts +6 -6
  42. package/src/serve.test.ts +2 -2
  43. package/src/share.ts +9 -14
  44. package/src/skills.test.ts +74 -0
  45. package/src/skills.ts +68 -0
  46. package/src/slash-palette.ts +10 -3
  47. package/src/{session-controller.curate.test.ts → thread-controller.curate.test.ts} +8 -7
  48. package/src/{session-controller.live-diff.test.ts → thread-controller.live-diff.test.ts} +7 -6
  49. package/src/{session-controller.share.test.ts → thread-controller.share.test.ts} +14 -13
  50. package/src/{session-controller.tree.test.ts → thread-controller.tree.test.ts} +8 -7
  51. package/src/{session-controller.ts → thread-controller.ts} +18 -22
  52. package/src/use-annotation-surface.tsx +14 -10
  53. 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 "./session-controller";
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, ReviewSession } from "@cueloop/schema";
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: ReviewSession | null,
359
- inbox: ReviewSession[] | null,
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
- <NoThreadShell
791
- rows={grouped.rows}
792
- inboxCursor={inboxCursor}
793
- mode={mode}
794
- theme={theme}
795
- controller={controller}
796
- setMode={setMode}
797
- menuChrome={menuChrome}
798
- onOpenMenu={() => setMenuDialog("settings")}
799
- sidebarOpen={sidebarOpen}
800
- onToggleSidebar={() => setSidebarOpen((open) => !open)}
801
- pinnedIds={pinnedIds}
802
- onPin={togglePin}
803
- onRename={(id, title) => setMode({ type: "renameThread", sessionId: id, text: title })}
804
- quickActions={quickActions}
805
- onWelcomeComposingChange={setWelcomeComposing}
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
- <ThemeProvider theme={theme}>
877
- <AppShell
878
- sidebarOpen={sidebarOpen}
879
- onToggleSidebar={() => setSidebarOpen((open) => !open)}
880
- onOpenMenu={() => setMenuDialog("settings")}
881
- threadsPanel={
882
- <scrollbox style={{ flexGrow: 1 }} focused={false}>
883
- <ThreadTree
884
- rows={grouped.rows}
885
- cursor={inboxCursor}
886
- activeId={activeSession.id}
887
- pinnedIds={pinnedIds}
888
- width={30}
889
- onSelect={(id) => controller.open(id)}
890
- onPin={togglePin}
891
- onRename={(id, title) =>
892
- setMode({ type: "renameThread", sessionId: id, text: title })
893
- }
894
- theme={theme}
895
- />
896
- </scrollbox>
897
- }
898
- threadTitle={threadTitle(activeSession)}
899
- threadActions={
900
- showOwnerActions ? (
901
- <Toolbar>
902
- <Button onPress={onEditRequest} theme={theme}>
903
- {" edit "}
904
- </Button>
905
- <Button onPress={onShareRequest} theme={theme}>
906
- {" share "}
907
- </Button>
908
- </Toolbar>
909
- ) : undefined
910
- }
911
- threadPanel={
912
- <box style={{ flexGrow: 1, flexDirection: "column" }}>
913
- <box style={{ flexGrow: 1, flexDirection: "row" }}>
914
- {isPixelPrototype ? (
915
- <PrototypePixels
916
- prototypePath={prototypePath}
917
- canComment={prototypeCanComment}
918
- onCommentElement={onCommentPrototype}
919
- onComposingChange={setPrototypeComposing}
920
- hidden={chromeHidden}
921
- />
922
- ) : isDiff ? (
923
- <box style={{ flexGrow: 1, paddingLeft: 2, paddingTop: 1 }}>
924
- <text fg={theme.textDim}>review the changes on the right</text>
925
- </box>
926
- ) : (
927
- <ThreadView
928
- session={activeSession}
929
- suspended={threadViewSuspended}
930
- editOrphanCount={editOrphanCount}
931
- onComposingChange={setThreadComposing}
932
- resolved={resolved}
933
- onObserverBlocked={(reason) =>
934
- controller.setStatus(
935
- reason === "observer"
936
- ? "observer - read-only"
937
- : "review submitted - read-only",
938
- )
939
- }
940
- onCursorChange={setCursor}
941
- focusedAnnotationId={focusedAnnotationId}
942
- onFocusAnnotation={setFocusedAnnotationId}
943
- display={display}
944
- marks={marks}
945
- quickActions={quickActions}
946
- observer={observer}
947
- onAnnotate={(span, body) =>
948
- void controller.annotate(
949
- "comment",
950
- span.start.blockIndex,
951
- span.start.char,
952
- span.end.char,
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
- onReply={(rootAnnotationId, body) =>
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
- </box>
973
- }
974
- changesOpen={workbench.changesOpen}
975
- projectOpen={workbench.projectOpen}
976
- onToggleChanges={workbench.toggleChanges}
977
- onToggleProject={workbench.toggleProject}
978
- onToggleRight={workbench.toggleRight}
979
- projectMode={workbench.projectMode}
980
- zoomHideThread={workbench.zoomed}
981
- changesPanel={
982
- <EditorGrid
983
- tree={workbench.grid}
984
- focusedGroupId={workbench.activeGroup}
985
- commentCounts={diffCommentCounts}
986
- onFocusGroup={workbench.focusGroup}
987
- onActivateTab={workbench.activate}
988
- onCloseTab={workbench.close}
989
- onSplit={workbench.split}
990
- onZoom={workbench.toggleZoom}
991
- zoomed={workbench.zoomed}
992
- renderTab={(tab, groupFocused) => (
993
- <GridTabContent
994
- tab={tab}
995
- rows={rows}
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
- theme={theme}
1060
- >
1061
- <TrailingOverlays
1062
- walking={walking}
1063
- walk={walk}
1064
- walkFileList={walkFileList}
1065
- viewedPaths={viewedPaths}
1066
- session={activeSession}
1067
- terminalWidth={terminalWidth}
1068
- theme={theme}
1069
- mode={mode}
1070
- toast={toast}
1071
- setMode={setMode}
1072
- dispatch={dispatch}
1073
- />
1074
- {submitConfirmState !== null ? (
1075
- <box
1076
- style={{
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
  }
@@ -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 { ReviewSession } from "@cueloop/schema";
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: ReviewSession;
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 { ReviewSession } from "@cueloop/schema";
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: ReviewSession;
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 {
@@ -1,4 +1,4 @@
1
- import type { ReviewSession } from "@cueloop/schema";
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: ReviewSession | null;
13
+ session: Thread | null;
14
14
  isDiff: boolean;
15
15
  mode: Mode;
16
16
  resolved: boolean;
17
- inbox: ReviewSession[] | null;
17
+ inbox: Thread[] | null;
18
18
  focusedAnnotationId: string | undefined;
19
19
  walk: { index: number } | null;
20
20
  walkFileList: WalkFile[];
@@ -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, ReviewSession, VerdictKind } from "@cueloop/schema";
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 "./session-controller";
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: ReviewSession;
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: ReviewSession;
343
+ session: Thread;
344
344
  terminalWidth: number;
345
345
  theme: Theme;
346
346
  mode: Mode;