@alivault/pico 0.10.0 → 0.10.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/.output/nitro.json +1 -1
- package/.output/public/assets/{index-Cv9CWbsI.js → index-CEN6xdm0.js} +10 -10
- package/.output/public/assets/routes-YDDOri73.js +2195 -0
- package/.output/public/assets/styles-hk0oLlcJ.css +2 -0
- package/.output/server/_libs/@pierre/diffs+[...].mjs +322 -165
- package/.output/server/_libs/hast-util-from-parse5+[...].mjs +1 -1
- package/.output/server/_libs/hast-util-raw+[...].mjs +1 -1
- package/.output/server/_libs/hast-util-to-jsx-runtime+[...].mjs +1 -1
- package/.output/server/_libs/lucide-react.mjs +27 -1
- package/.output/server/_libs/mdast-util-gfm+[...].mjs +1 -1
- package/.output/server/_ssr/{router-BfWi4RfZ.mjs → router-CphHgwo2.mjs} +236 -99
- package/.output/server/_ssr/{routes-CSvcOSyF.mjs → routes-CELGJtcT.mjs} +1369 -377
- package/.output/server/_ssr/{routes-D6yf6dMU.mjs → routes-CHNxptm_.mjs} +1924 -41
- package/.output/server/_ssr/ssr.mjs +2 -2
- package/.output/server/{_tanstack-start-manifest_v-Am6Tm4xr.mjs → _tanstack-start-manifest_v-CIqGA3U0.mjs} +4 -4
- package/.output/server/index.mjs +486 -486
- package/package.json +2 -2
- package/.output/public/assets/routes-FmISceu0.js +0 -2160
- package/.output/public/assets/styles-DgbW000h.css +0 -2
- package/.output/server/_libs/sugar-high.mjs +0 -1036
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { i as __toESM } from "../_runtime.mjs";
|
|
2
2
|
import { $ as require_react, A as TabsTab, B as Input, C as MenuPositioner, D as MenuGroupLabel, E as MenuItem, F as DialogPopup, H as useRender, I as DialogDescription$1, L as DialogClose, M as DialogTitle$1, N as DialogRoot, O as MenuGroup, P as DialogPortal$1, Q as require_jsx_runtime, R as DialogBackdrop, S as MenuRoot, T as MenuPopup, V as Button, Y as mergeProps, _ as AccordionItem$1, a as ContextMenuRoot, b as MenuTrigger, c as CollapsibleRoot, d as PopoverPortal, f as PopoverTrigger$1, g as AccordionHeader, h as AccordionTrigger$1, i as ContextMenuTrigger$1, j as TabsRoot, k as TabsList$1, l as PopoverPopup, m as AccordionPanel, n as ToggleGroup, o as CollapsiblePanel, p as PopoverRoot, r as Toggle, s as CollapsibleTrigger$1, t as AlertDialogRoot, u as PopoverPositioner, v as AccordionRoot, w as MenuPortal, x as MenuSubmenuRoot, y as MenuSubmenuTrigger, z as Separator } from "../_libs/@base-ui/react+[...].mjs";
|
|
3
3
|
import { t as cva } from "../_libs/class-variance-authority+clsx.mjs";
|
|
4
|
-
import { A as
|
|
5
|
-
import { $ as
|
|
4
|
+
import { A as ExternalLink, B as ChevronRight, C as ImagePlus, D as Folder, E as GitCommitHorizontal, F as Command, G as ArrowUpRight, H as Check, J as ArrowDown, L as ChevronsUpDown, M as EllipsisVertical, N as Download, O as FolderPlus, P as Copy, R as ChevronsDownUp, T as GitBranch, U as ArrowUp, V as ChevronDown, W as ArrowUpToLine, _ as OctagonX, a as TriangleAlert, b as ListStart, c as SquarePen, d as Plus, f as PanelRight, h as PanelLeftClose, i as Undo2, j as Ellipsis, k as FileDiff, l as Settings2, m as PanelLeftOpen, n as WandSparkles, o as Tag, p as PanelLeft, q as ArrowLeft, r as Upload, s as Square, t as X, u as Search, v as Minimize2, w as GitPullRequestArrow, x as ListEnd, y as Maximize2 } from "../_libs/lucide-react.mjs";
|
|
5
|
+
import { $ as normalizeThemeFamily, A as Tooltip$1, C as SESSION_DONE_SOUND_ENABLED_STORAGE_KEY, Ct as themeFamilyDescription, D as THEME_FAMILIES, Dt as themeFamilySupportsColorMode, E as THEME_COLOR_MODE_STORAGE_KEY, Et as themeFamilyLabel, F as appliedThemeClass, H as createInitialSessionState, I as appliedThemeClassColorMode, K as flattenTree, N as TooltipTrigger, O as THEME_STORAGE_KEY, Ot as thinkingSummaryText, P as VIEWER_CONTEXT_STORAGE_KEY, Q as normalizeThemeColorMode, R as buildItemsFromSync, S as SESSION_DONE_DESKTOP_NOTIFICATIONS_ENABLED_STORAGE_KEY, St as themeColorModeLabel, T as Spinner, Tt as themeFamilyKeywords, V as createContextId, X as normalizeSessionSelectionKeys, Y as normalizePromptImage, Z as normalizeStoredDirectoryList, _ as RIGHT_SIDEBAR_HISTORY_HEIGHT_STORAGE_KEY, _t as rememberStoredPromptDraft, a as COLLAPSED_DIRECTORIES_STORAGE_KEY, at as readStoredCollapsedDirectories, b as RIGHT_SIDEBAR_WIDTHS_STORAGE_KEY, bt as sameContextUsage, c as Kbd, ct as readStoredPinnedSessionKeys, d as PICO_DIFF_SHIKI_THEMES, dt as readStoredRightSidebarOpen, et as previewUrlForImage, f as PICO_SHIKI_VARIABLE_DEFAULTS, ft as readStoredSessionDoneDesktopNotificationsEnabled, g as RIGHT_SIDEBAR_FILE_TREE_WIDTH_STORAGE_KEY, gt as readStoredThemeColorMode, h as RIGHT_SIDEBAR_ACTIVE_TAB_STORAGE_KEY, ht as readStoredTheme, i as CENTER_MESSAGES_STORAGE_KEY, it as readStoredCenterMessages, j as TooltipContent, k as TitleTooltip, l as KeyboardShortcutContent, lt as readStoredPromptDraft, m as RECENT_DIRECTORIES_STORAGE_KEY, mt as readStoredSidebarDirectories, n as APPLIED_THEME_STORAGE_KEY, nt as promptDraftKeyMatchesOwner, o as DRAFT_DIRECTORY_STORAGE_KEY, ot as readStoredDraftDirectory, p as PINNED_SESSIONS_STORAGE_KEY, pt as readStoredSessionDoneSoundEnabled, q as getSessionTitle, r as AUTO_SCROLL_ENABLED_STORAGE_KEY, rt as readStoredAutoScrollEnabled, s as HIDE_TOOL_BLOCKS_STORAGE_KEY, st as readStoredHideToolBlocks, tt as promptDraftKey, ut as readStoredRecentDirectories, v as RIGHT_SIDEBAR_HISTORY_TAB_STORAGE_KEY, vt as safeLocalStorageGetItem, w as SIDEBAR_DIRECTORIES_STORAGE_KEY, wt as themeFamilyFixedMode, x as Route, xt as sessionListEntryKey, y as RIGHT_SIDEBAR_OPEN_STORAGE_KEY, yt as safeLocalStorageSetItem, z as cn } from "./routes-CHNxptm_.mjs";
|
|
6
6
|
import { i as useQuery, n as useIsMutating, o as useQueryClient, r as useIsFetching, t as useMutation } from "../_libs/tanstack__react-query.mjs";
|
|
7
7
|
import { t as useHotkeys } from "../_libs/tanstack__react-hotkeys.mjs";
|
|
8
8
|
import { a as matchesKeyboardEvent, i as batch, o as formatForDisplay, r as createStore } from "../_libs/@tanstack/hotkeys+[...].mjs";
|
|
@@ -10,10 +10,10 @@ import { t as shallow } from "../_libs/tanstack__store.mjs";
|
|
|
10
10
|
import { t as useSelector } from "../_libs/tanstack__react-store.mjs";
|
|
11
11
|
import { n as z } from "../_libs/next-themes.mjs";
|
|
12
12
|
import { n as toast } from "../_libs/sonner.mjs";
|
|
13
|
+
import { a as registerCustomTheme, i as parsePatchFiles, n as MultiFileDiff, o as RegisteredCustomThemes, r as FileDiff$1, t as PatchDiff, u as createCssVariablesTheme } from "../_libs/@pierre/diffs+[...].mjs";
|
|
13
14
|
import { i as AsyncDebouncer, r as Batcher, t as Throttler } from "../_libs/tanstack__pacer.mjs";
|
|
14
15
|
import { t as _e } from "../_libs/cmdk.mjs";
|
|
15
16
|
import { t as Drawer } from "../_libs/vaul.mjs";
|
|
16
|
-
import { i as parsePatchFiles, n as MultiFileDiff, r as FileDiff$1, t as PatchDiff } from "../_libs/@pierre/diffs+[...].mjs";
|
|
17
17
|
import { t as Markdown } from "../_libs/react-markdown+[...].mjs";
|
|
18
18
|
import { t as rehypeRaw } from "../_libs/rehype-raw.mjs";
|
|
19
19
|
import { n as defaultSchema } from "../_libs/hast-util-sanitize.mjs";
|
|
@@ -22,7 +22,7 @@ import { t as remarkGfm } from "../_libs/remark-gfm.mjs";
|
|
|
22
22
|
import { a as getBuiltInSpriteSheet, i as getBuiltInFileIconColor, n as FileTree, r as createFileTreeIconResolver, t as useFileTree } from "../_libs/@pierre/trees+[...].mjs";
|
|
23
23
|
import { a as closestCenter, c as useDraggable, d as useSensors, f as CSS$1, i as PointerSensor, n as DragOverlay, t as DndContext, u as useSensor } from "../_libs/@dnd-kit/core+[...].mjs";
|
|
24
24
|
import { a as verticalListSortingStrategy, i as useSortable, n as arrayMove, r as horizontalListSortingStrategy, t as SortableContext } from "../_libs/dnd-kit__sortable.mjs";
|
|
25
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/routes-
|
|
25
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/routes-CELGJtcT.js
|
|
26
26
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
27
27
|
var import_jsx_runtime = require_jsx_runtime();
|
|
28
28
|
var MOBILE_BREAKPOINT = 768;
|
|
@@ -980,7 +980,7 @@ function CommandGroup({ className, ...props }) {
|
|
|
980
980
|
function CommandItem({ className, children, ...props }) {
|
|
981
981
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(_e.Item, {
|
|
982
982
|
"data-slot": "command-item",
|
|
983
|
-
className: cn("group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-
|
|
983
|
+
className: cn("group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-accent data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-selected:*:[svg]:text-foreground", className),
|
|
984
984
|
...props,
|
|
985
985
|
children: [children, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" })]
|
|
986
986
|
});
|
|
@@ -3100,19 +3100,84 @@ function AppShellSessionsDialogController({ ref, openStateRef, ...props }) {
|
|
|
3100
3100
|
});
|
|
3101
3101
|
}
|
|
3102
3102
|
var THEME_OPTIONS = [...THEME_FAMILIES];
|
|
3103
|
-
var
|
|
3104
|
-
|
|
3103
|
+
var THEME_SELECTION_SECTIONS = [
|
|
3104
|
+
{
|
|
3105
|
+
heading: "Auto",
|
|
3106
|
+
colorMode: "auto"
|
|
3107
|
+
},
|
|
3108
|
+
{
|
|
3109
|
+
heading: "Dark",
|
|
3110
|
+
colorMode: "dark"
|
|
3111
|
+
},
|
|
3112
|
+
{
|
|
3113
|
+
heading: "Light",
|
|
3114
|
+
colorMode: "light"
|
|
3115
|
+
}
|
|
3116
|
+
].map((section) => ({
|
|
3117
|
+
...section,
|
|
3118
|
+
themes: THEME_OPTIONS.filter((theme) => themeFamilySupportsColorMode(theme, section.colorMode))
|
|
3119
|
+
}));
|
|
3120
|
+
var SETTINGS_DIALOG_AUTO_FOCUS_MEDIA = "(min-width: 768px)";
|
|
3121
|
+
function shouldAutoFocusSettingsDialogInput() {
|
|
3122
|
+
return typeof window !== "undefined" && window.matchMedia(SETTINGS_DIALOG_AUTO_FOCUS_MEDIA).matches;
|
|
3123
|
+
}
|
|
3124
|
+
function isThemeColorMode(value) {
|
|
3125
|
+
return value === "auto" || value === "light" || value === "dark";
|
|
3126
|
+
}
|
|
3127
|
+
function themeSelectionKey(selection) {
|
|
3128
|
+
return `${selection.colorMode}:${selection.theme}`;
|
|
3129
|
+
}
|
|
3130
|
+
function themeSelectionFromKey(value) {
|
|
3131
|
+
const separatorIndex = value.indexOf(":");
|
|
3132
|
+
if (separatorIndex < 0) return void 0;
|
|
3133
|
+
const colorMode = value.slice(0, separatorIndex);
|
|
3134
|
+
const theme = value.slice(separatorIndex + 1);
|
|
3135
|
+
if (!isThemeColorMode(colorMode)) return void 0;
|
|
3136
|
+
if (!THEME_OPTIONS.includes(theme)) return void 0;
|
|
3137
|
+
const normalizedTheme = theme;
|
|
3138
|
+
if (!themeFamilySupportsColorMode(normalizedTheme, colorMode)) return;
|
|
3139
|
+
return {
|
|
3140
|
+
theme: normalizedTheme,
|
|
3141
|
+
colorMode
|
|
3142
|
+
};
|
|
3143
|
+
}
|
|
3144
|
+
function themeSelectionForCurrent(theme, colorMode) {
|
|
3145
|
+
return {
|
|
3146
|
+
theme,
|
|
3147
|
+
colorMode: themeFamilyFixedMode(theme) ?? colorMode
|
|
3148
|
+
};
|
|
3149
|
+
}
|
|
3150
|
+
function themeSelectionModeLabel(selection, systemTheme) {
|
|
3151
|
+
if (selection.colorMode === "auto") return themeColorModeLabel(selection.colorMode, systemTheme);
|
|
3152
|
+
return selection.colorMode === "light" ? "Light" : "Dark";
|
|
3153
|
+
}
|
|
3154
|
+
function themeSelectionValueLabel(selection, systemTheme) {
|
|
3155
|
+
return `${themeFamilyLabel(selection.theme)} · ${themeSelectionModeLabel(selection, systemTheme)}`;
|
|
3156
|
+
}
|
|
3157
|
+
function themeSelectionDescription(selection) {
|
|
3158
|
+
if (selection.colorMode === "auto") return `Auto: ${themeFamilyDescription(selection.theme)}`;
|
|
3159
|
+
if (themeFamilyFixedMode(selection.theme)) return `${themeSelectionModeLabel(selection)} only: ${themeFamilyDescription(selection.theme)}`;
|
|
3160
|
+
return themeFamilyDescription(selection.theme);
|
|
3161
|
+
}
|
|
3162
|
+
function themeSelectionKeywords(selection) {
|
|
3163
|
+
return [
|
|
3164
|
+
selection.colorMode,
|
|
3165
|
+
themeSelectionModeLabel(selection),
|
|
3166
|
+
...themeFamilyKeywords(selection.theme)
|
|
3167
|
+
];
|
|
3168
|
+
}
|
|
3169
|
+
function createInitialSettingsDialogState(currentTheme, currentThemeColorMode) {
|
|
3105
3170
|
return {
|
|
3106
3171
|
query: "",
|
|
3107
3172
|
themeQuery: "",
|
|
3108
3173
|
stage: "browse",
|
|
3109
3174
|
selectedCommandId: "theme",
|
|
3110
|
-
selectedTheme: currentTheme
|
|
3175
|
+
selectedTheme: themeSelectionForCurrent(currentTheme, currentThemeColorMode)
|
|
3111
3176
|
};
|
|
3112
3177
|
}
|
|
3113
3178
|
function settingsDialogReducer(state, action) {
|
|
3114
3179
|
switch (action.type) {
|
|
3115
|
-
case "reset": return createInitialSettingsDialogState(action.currentTheme);
|
|
3180
|
+
case "reset": return createInitialSettingsDialogState(action.currentTheme, action.currentThemeColorMode);
|
|
3116
3181
|
case "set-query": return {
|
|
3117
3182
|
...state,
|
|
3118
3183
|
query: action.query
|
|
@@ -3128,7 +3193,7 @@ function settingsDialogReducer(state, action) {
|
|
|
3128
3193
|
case "open-theme": return {
|
|
3129
3194
|
...state,
|
|
3130
3195
|
stage: "theme",
|
|
3131
|
-
selectedTheme: action.currentTheme
|
|
3196
|
+
selectedTheme: themeSelectionForCurrent(action.currentTheme, action.currentThemeColorMode)
|
|
3132
3197
|
};
|
|
3133
3198
|
case "close-theme": return {
|
|
3134
3199
|
...state,
|
|
@@ -3150,23 +3215,6 @@ function desktopNotificationPermissionLabel(permission) {
|
|
|
3150
3215
|
function formatToggleValue(enabled) {
|
|
3151
3216
|
return enabled ? "On" : "Off";
|
|
3152
3217
|
}
|
|
3153
|
-
function nextThemeColorMode(currentMode) {
|
|
3154
|
-
return THEME_COLOR_MODE_OPTIONS[(THEME_COLOR_MODE_OPTIONS.indexOf(currentMode) + 1) % THEME_COLOR_MODE_OPTIONS.length] ?? "auto";
|
|
3155
|
-
}
|
|
3156
|
-
function themeDescription(theme) {
|
|
3157
|
-
switch (theme) {
|
|
3158
|
-
case "default": return "Use Pico's default palette.";
|
|
3159
|
-
case "flexoki": return "Use Flexoki's warm paper and inky dark palettes.";
|
|
3160
|
-
default: return "Use this theme.";
|
|
3161
|
-
}
|
|
3162
|
-
}
|
|
3163
|
-
function themeKeywords(theme) {
|
|
3164
|
-
return [
|
|
3165
|
-
theme,
|
|
3166
|
-
themeFamilyLabel(theme),
|
|
3167
|
-
themeDescription(theme)
|
|
3168
|
-
];
|
|
3169
|
-
}
|
|
3170
3218
|
function settingsCommandKeywords(command) {
|
|
3171
3219
|
return [
|
|
3172
3220
|
command.title,
|
|
@@ -3180,7 +3228,7 @@ function settingsCommandFilter(value, search, keywords) {
|
|
|
3180
3228
|
if (!query) return 1;
|
|
3181
3229
|
return [value, ...keywords ?? []].join(" ").toLowerCase().includes(query) ? 1 : 0;
|
|
3182
3230
|
}
|
|
3183
|
-
function getSettingsCommandGroups({ currentTheme, currentThemeColorMode, systemTheme, hideThinkingBlocks, onHideThinkingBlocksChange, hideToolBlocks, onHideToolBlocksChange, centerMessages, onCenterMessagesChange, autoScrollEnabled, onAutoScrollEnabledChange, sessionDoneSoundEnabled, onSessionDoneSoundEnabledChange, sessionDoneDesktopNotificationsEnabled, onSessionDoneDesktopNotificationsEnabledChange, desktopNotificationPermission, onLoginProviders, onLogoutProviders, onThemeCommand
|
|
3231
|
+
function getSettingsCommandGroups({ currentTheme, currentThemeColorMode, systemTheme, hideThinkingBlocks, onHideThinkingBlocksChange, hideToolBlocks, onHideToolBlocksChange, centerMessages, onCenterMessagesChange, autoScrollEnabled, onAutoScrollEnabledChange, sessionDoneSoundEnabled, onSessionDoneSoundEnabledChange, sessionDoneDesktopNotificationsEnabled, onSessionDoneDesktopNotificationsEnabledChange, desktopNotificationPermission, onLoginProviders, onLogoutProviders, onThemeCommand }) {
|
|
3184
3232
|
const desktopNotificationDescription = desktopNotificationPermissionLabel(desktopNotificationPermission);
|
|
3185
3233
|
return [
|
|
3186
3234
|
{
|
|
@@ -3188,29 +3236,19 @@ function getSettingsCommandGroups({ currentTheme, currentThemeColorMode, systemT
|
|
|
3188
3236
|
commands: [{
|
|
3189
3237
|
id: "theme",
|
|
3190
3238
|
title: "Theme",
|
|
3191
|
-
description: "Choose
|
|
3192
|
-
valueLabel:
|
|
3193
|
-
keywords: [
|
|
3194
|
-
"color",
|
|
3195
|
-
"mode",
|
|
3196
|
-
"default",
|
|
3197
|
-
"flexoki"
|
|
3198
|
-
],
|
|
3199
|
-
onSelect: onThemeCommand
|
|
3200
|
-
}, {
|
|
3201
|
-
id: "theme-color-mode",
|
|
3202
|
-
title: "Light/dark mode",
|
|
3203
|
-
description: "Follow OS appearance, or force light or dark mode.",
|
|
3204
|
-
valueLabel: themeColorModeLabel(currentThemeColorMode, systemTheme),
|
|
3239
|
+
description: "Choose an auto, dark, or light color palette.",
|
|
3240
|
+
valueLabel: themeSelectionValueLabel(themeSelectionForCurrent(currentTheme, currentThemeColorMode), systemTheme),
|
|
3205
3241
|
keywords: [
|
|
3206
3242
|
"auto",
|
|
3207
3243
|
"system",
|
|
3208
3244
|
"light",
|
|
3209
3245
|
"dark",
|
|
3246
|
+
"color",
|
|
3210
3247
|
"mode",
|
|
3211
|
-
"
|
|
3248
|
+
"palette",
|
|
3249
|
+
...THEME_OPTIONS.flatMap((theme) => themeFamilyKeywords(theme))
|
|
3212
3250
|
],
|
|
3213
|
-
onSelect:
|
|
3251
|
+
onSelect: onThemeCommand
|
|
3214
3252
|
}]
|
|
3215
3253
|
},
|
|
3216
3254
|
{
|
|
@@ -3334,6 +3372,11 @@ function getSettingsCommandGroups({ currentTheme, currentThemeColorMode, systemT
|
|
|
3334
3372
|
];
|
|
3335
3373
|
}
|
|
3336
3374
|
function SettingsBrowseBody({ query, selectedCommandId, settingGroups, onQueryChange, onSelectedCommandIdChange, onSelectCommand }) {
|
|
3375
|
+
const inputRef = import_react.useRef(null);
|
|
3376
|
+
import_react.useEffect(() => {
|
|
3377
|
+
if (!shouldAutoFocusSettingsDialogInput()) return;
|
|
3378
|
+
inputRef.current?.focus();
|
|
3379
|
+
}, []);
|
|
3337
3380
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Command$1, {
|
|
3338
3381
|
shouldFilter: true,
|
|
3339
3382
|
filter: settingsCommandFilter,
|
|
@@ -3343,6 +3386,7 @@ function SettingsBrowseBody({ query, selectedCommandId, settingGroups, onQueryCh
|
|
|
3343
3386
|
className: "min-h-0 flex-1",
|
|
3344
3387
|
children: [
|
|
3345
3388
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandInput, {
|
|
3389
|
+
ref: inputRef,
|
|
3346
3390
|
value: query,
|
|
3347
3391
|
onValueChange: onQueryChange,
|
|
3348
3392
|
placeholder: "Search settings",
|
|
@@ -3380,7 +3424,12 @@ function SettingsBrowseBody({ query, selectedCommandId, settingGroups, onQueryCh
|
|
|
3380
3424
|
]
|
|
3381
3425
|
});
|
|
3382
3426
|
}
|
|
3383
|
-
function SettingsThemeBody({ currentTheme, selectedTheme, themeQuery, onThemeQueryChange, onThemePreview, onThemeSelect, onCancelThemePreview }) {
|
|
3427
|
+
function SettingsThemeBody({ currentTheme, currentThemeColorMode, selectedTheme, systemTheme, themeQuery, onThemeQueryChange, onThemePreview, onThemeSelect, onCancelThemePreview }) {
|
|
3428
|
+
const inputRef = import_react.useRef(null);
|
|
3429
|
+
import_react.useEffect(() => {
|
|
3430
|
+
if (!shouldAutoFocusSettingsDialogInput()) return;
|
|
3431
|
+
inputRef.current?.focus();
|
|
3432
|
+
}, []);
|
|
3384
3433
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
3385
3434
|
role: "presentation",
|
|
3386
3435
|
className: "flex min-h-0 flex-1 flex-col",
|
|
@@ -3406,17 +3455,25 @@ function SettingsThemeBody({ currentTheme, selectedTheme, themeQuery, onThemeQue
|
|
|
3406
3455
|
children: "Choose theme"
|
|
3407
3456
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
3408
3457
|
className: "truncate text-xs text-muted-foreground",
|
|
3409
|
-
children: [
|
|
3458
|
+
children: [
|
|
3459
|
+
"Current:",
|
|
3460
|
+
" ",
|
|
3461
|
+
themeSelectionValueLabel(themeSelectionForCurrent(currentTheme, currentThemeColorMode), systemTheme)
|
|
3462
|
+
]
|
|
3410
3463
|
})]
|
|
3411
3464
|
})]
|
|
3412
3465
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Command$1, {
|
|
3413
3466
|
shouldFilter: true,
|
|
3414
3467
|
loop: true,
|
|
3415
|
-
value: selectedTheme,
|
|
3416
|
-
onValueChange: (value) =>
|
|
3468
|
+
value: themeSelectionKey(selectedTheme),
|
|
3469
|
+
onValueChange: (value) => {
|
|
3470
|
+
const selection = themeSelectionFromKey(value);
|
|
3471
|
+
if (selection) onThemePreview(selection);
|
|
3472
|
+
},
|
|
3417
3473
|
className: "min-h-0 flex-1 rounded-none!",
|
|
3418
3474
|
children: [
|
|
3419
3475
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandInput, {
|
|
3476
|
+
ref: inputRef,
|
|
3420
3477
|
value: themeQuery,
|
|
3421
3478
|
onValueChange: onThemeQueryChange,
|
|
3422
3479
|
placeholder: "Search themes",
|
|
@@ -3424,27 +3481,35 @@ function SettingsThemeBody({ currentTheme, selectedTheme, themeQuery, onThemeQue
|
|
|
3424
3481
|
}),
|
|
3425
3482
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CommandList, {
|
|
3426
3483
|
className: "max-h-none min-h-0 flex-1 md:max-h-[min(70vh,28rem)]",
|
|
3427
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandEmpty, { children: "No themes found." }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandGroup, {
|
|
3428
|
-
heading:
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3484
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandEmpty, { children: "No themes found." }), THEME_SELECTION_SECTIONS.map((section) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandGroup, {
|
|
3485
|
+
heading: section.heading,
|
|
3486
|
+
className: "**:[[cmdk-group-heading]]:sticky **:[[cmdk-group-heading]]:top-0 **:[[cmdk-group-heading]]:z-10 **:[[cmdk-group-heading]]:bg-popover",
|
|
3487
|
+
children: section.themes.map((theme) => {
|
|
3488
|
+
const selection = {
|
|
3489
|
+
theme,
|
|
3490
|
+
colorMode: section.colorMode
|
|
3491
|
+
};
|
|
3492
|
+
const selectionKey = themeSelectionKey(selection);
|
|
3493
|
+
const currentSelection = themeSelectionForCurrent(currentTheme, currentThemeColorMode);
|
|
3494
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandItem, {
|
|
3495
|
+
value: selectionKey,
|
|
3496
|
+
keywords: themeSelectionKeywords(selection),
|
|
3497
|
+
onSelect: () => onThemeSelect(selection),
|
|
3498
|
+
"data-checked": selectionKey === themeSelectionKey(currentSelection) ? true : void 0,
|
|
3499
|
+
className: "items-start py-2",
|
|
3500
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
3501
|
+
className: "flex min-w-0 flex-1 flex-col gap-0.5",
|
|
3502
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
3503
|
+
className: "truncate font-medium",
|
|
3504
|
+
children: themeFamilyLabel(theme)
|
|
3505
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
3506
|
+
className: "line-clamp-2 text-xs text-muted-foreground",
|
|
3507
|
+
children: themeSelectionDescription(selection)
|
|
3508
|
+
})]
|
|
3509
|
+
})
|
|
3510
|
+
}, selectionKey);
|
|
3511
|
+
})
|
|
3512
|
+
}, section.colorMode))]
|
|
3448
3513
|
}),
|
|
3449
3514
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
3450
3515
|
className: "hidden border-t border-border/70 px-3 py-2 text-xs text-muted-foreground md:block",
|
|
@@ -3459,18 +3524,23 @@ function SettingsDialogBody({ stage, browseBodyProps, themeBodyProps }) {
|
|
|
3459
3524
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SettingsBrowseBody, { ...browseBodyProps });
|
|
3460
3525
|
}
|
|
3461
3526
|
function AppShellSettingsDialog({ open, onOpenChange, currentTheme, currentThemeColorMode, onThemeChange, onThemeColorModeChange, onThemePreviewChange, systemTheme, hideThinkingBlocks, onHideThinkingBlocksChange, hideToolBlocks, onHideToolBlocksChange, centerMessages, onCenterMessagesChange, autoScrollEnabled, onAutoScrollEnabledChange, sessionDoneSoundEnabled, onSessionDoneSoundEnabledChange, sessionDoneDesktopNotificationsEnabled, onSessionDoneDesktopNotificationsEnabledChange, desktopNotificationPermission, onLoginProviders, onLogoutProviders }) {
|
|
3462
|
-
const [state, dispatch] = import_react.useReducer(settingsDialogReducer,
|
|
3463
|
-
|
|
3527
|
+
const [state, dispatch] = import_react.useReducer(settingsDialogReducer, {
|
|
3528
|
+
currentTheme,
|
|
3529
|
+
currentThemeColorMode
|
|
3530
|
+
}, ({ currentTheme: initialTheme, currentThemeColorMode: initialColorMode }) => createInitialSettingsDialogState(initialTheme, initialColorMode));
|
|
3531
|
+
const themePreviewInitialRef = import_react.useRef(themeSelectionForCurrent(currentTheme, currentThemeColorMode));
|
|
3464
3532
|
const isMobile = useIsMobile();
|
|
3465
3533
|
import_react.useEffect(() => {
|
|
3466
3534
|
if (open) return;
|
|
3467
|
-
if (state.stage === "theme") onThemePreviewChange(themePreviewInitialRef.current);
|
|
3535
|
+
if (state.stage === "theme") onThemePreviewChange(themePreviewInitialRef.current.theme, themePreviewInitialRef.current.colorMode);
|
|
3468
3536
|
dispatch({
|
|
3469
3537
|
type: "reset",
|
|
3470
|
-
currentTheme
|
|
3538
|
+
currentTheme,
|
|
3539
|
+
currentThemeColorMode
|
|
3471
3540
|
});
|
|
3472
3541
|
}, [
|
|
3473
3542
|
currentTheme,
|
|
3543
|
+
currentThemeColorMode,
|
|
3474
3544
|
onThemePreviewChange,
|
|
3475
3545
|
open,
|
|
3476
3546
|
state.stage
|
|
@@ -3480,21 +3550,24 @@ function AppShellSettingsDialog({ open, onOpenChange, currentTheme, currentTheme
|
|
|
3480
3550
|
console.error(error);
|
|
3481
3551
|
});
|
|
3482
3552
|
};
|
|
3483
|
-
const handleThemePreview = (
|
|
3484
|
-
if (!THEME_OPTIONS.includes(theme)) return;
|
|
3553
|
+
const handleThemePreview = (selection) => {
|
|
3554
|
+
if (!THEME_OPTIONS.includes(selection.theme)) return;
|
|
3555
|
+
if (!themeFamilySupportsColorMode(selection.theme, selection.colorMode)) return;
|
|
3485
3556
|
dispatch({
|
|
3486
3557
|
type: "preview-theme",
|
|
3487
|
-
selectedTheme:
|
|
3558
|
+
selectedTheme: selection
|
|
3488
3559
|
});
|
|
3489
|
-
onThemePreviewChange(theme);
|
|
3560
|
+
onThemePreviewChange(selection.theme, selection.colorMode);
|
|
3490
3561
|
};
|
|
3491
|
-
const handleThemeSelect = (
|
|
3562
|
+
const handleThemeSelect = (selection) => {
|
|
3492
3563
|
dispatch({
|
|
3493
3564
|
type: "preview-theme",
|
|
3494
|
-
selectedTheme:
|
|
3565
|
+
selectedTheme: selection
|
|
3495
3566
|
});
|
|
3496
|
-
themePreviewInitialRef.current =
|
|
3497
|
-
|
|
3567
|
+
themePreviewInitialRef.current = selection;
|
|
3568
|
+
onThemeColorModeChange(selection.colorMode);
|
|
3569
|
+
onThemeChange(selection.theme);
|
|
3570
|
+
onOpenChange(false);
|
|
3498
3571
|
};
|
|
3499
3572
|
const cancelThemePreview = () => {
|
|
3500
3573
|
const initialTheme = themePreviewInitialRef.current;
|
|
@@ -3502,7 +3575,7 @@ function AppShellSettingsDialog({ open, onOpenChange, currentTheme, currentTheme
|
|
|
3502
3575
|
type: "close-theme",
|
|
3503
3576
|
selectedTheme: initialTheme
|
|
3504
3577
|
});
|
|
3505
|
-
onThemePreviewChange(initialTheme);
|
|
3578
|
+
onThemePreviewChange(initialTheme.theme, initialTheme.colorMode);
|
|
3506
3579
|
};
|
|
3507
3580
|
const settingGroups = getSettingsCommandGroups({
|
|
3508
3581
|
currentTheme,
|
|
@@ -3524,13 +3597,13 @@ function AppShellSettingsDialog({ open, onOpenChange, currentTheme, currentTheme
|
|
|
3524
3597
|
onLoginProviders,
|
|
3525
3598
|
onLogoutProviders,
|
|
3526
3599
|
onThemeCommand: () => {
|
|
3527
|
-
themePreviewInitialRef.current = currentTheme;
|
|
3600
|
+
themePreviewInitialRef.current = themeSelectionForCurrent(currentTheme, currentThemeColorMode);
|
|
3528
3601
|
dispatch({
|
|
3529
3602
|
type: "open-theme",
|
|
3530
|
-
currentTheme
|
|
3603
|
+
currentTheme,
|
|
3604
|
+
currentThemeColorMode
|
|
3531
3605
|
});
|
|
3532
|
-
}
|
|
3533
|
-
onThemeColorModeCommand: () => onThemeColorModeChange(nextThemeColorMode(currentThemeColorMode))
|
|
3606
|
+
}
|
|
3534
3607
|
});
|
|
3535
3608
|
const settingsCommandBody = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SettingsDialogBody, {
|
|
3536
3609
|
stage: state.stage,
|
|
@@ -3550,7 +3623,9 @@ function AppShellSettingsDialog({ open, onOpenChange, currentTheme, currentTheme
|
|
|
3550
3623
|
},
|
|
3551
3624
|
themeBodyProps: {
|
|
3552
3625
|
currentTheme,
|
|
3626
|
+
currentThemeColorMode,
|
|
3553
3627
|
selectedTheme: state.selectedTheme,
|
|
3628
|
+
systemTheme,
|
|
3554
3629
|
themeQuery: state.themeQuery,
|
|
3555
3630
|
onThemeQueryChange: (themeQuery) => dispatch({
|
|
3556
3631
|
type: "set-theme-query",
|
|
@@ -5286,8 +5361,8 @@ function AppShellTreeDialogController({ ref, openStateRef, viewerContextId, sess
|
|
|
5286
5361
|
})
|
|
5287
5362
|
});
|
|
5288
5363
|
},
|
|
5289
|
-
onSuccess:
|
|
5290
|
-
|
|
5364
|
+
onSuccess: () => {
|
|
5365
|
+
queryClient.invalidateQueries({
|
|
5291
5366
|
queryKey,
|
|
5292
5367
|
exact: true,
|
|
5293
5368
|
refetchType: "active"
|
|
@@ -5318,6 +5393,7 @@ function AppShellTreeDialogController({ ref, openStateRef, viewerContextId, sess
|
|
|
5318
5393
|
};
|
|
5319
5394
|
const navigateTreeNode = async (targetId, options) => {
|
|
5320
5395
|
if (!viewerContextId) return;
|
|
5396
|
+
setOpenState(false);
|
|
5321
5397
|
try {
|
|
5322
5398
|
const response = await navigateTreeNodeMutation.mutateAsync({
|
|
5323
5399
|
targetId,
|
|
@@ -5332,7 +5408,6 @@ function AppShellTreeDialogController({ ref, openStateRef, viewerContextId, sess
|
|
|
5332
5408
|
toast.info("Tree navigation cancelled");
|
|
5333
5409
|
return;
|
|
5334
5410
|
}
|
|
5335
|
-
setOpenState(false);
|
|
5336
5411
|
toast.success(options?.summarize ? "Continued from summarized branch" : "Moved session tree cursor");
|
|
5337
5412
|
} catch (error) {
|
|
5338
5413
|
toast.error(error instanceof Error ? error.message : "Failed to navigate tree");
|
|
@@ -6068,6 +6143,74 @@ function updateDirectoryIndexLoadingState(current, directories, loading) {
|
|
|
6068
6143
|
}
|
|
6069
6144
|
return changed ? next : current;
|
|
6070
6145
|
}
|
|
6146
|
+
function upsertOptimisticSidebarSessionEntry(current, entry) {
|
|
6147
|
+
const directory = entry.cwd.trim();
|
|
6148
|
+
const optimisticId = entry.id.trim();
|
|
6149
|
+
if (!directory || !optimisticId) return current;
|
|
6150
|
+
const currentSnapshot = current[directory];
|
|
6151
|
+
const currentSessions = currentSnapshot?.sessions || [];
|
|
6152
|
+
const existingEntry = currentSessions.find((session) => session.id === optimisticId);
|
|
6153
|
+
const nextSessions = [{
|
|
6154
|
+
...existingEntry,
|
|
6155
|
+
...entry,
|
|
6156
|
+
id: optimisticId,
|
|
6157
|
+
cwd: directory,
|
|
6158
|
+
optimistic: true
|
|
6159
|
+
}, ...currentSessions.filter((session) => session.id !== optimisticId)];
|
|
6160
|
+
const totalCountBaseline = Math.max(currentSnapshot?.totalCount ?? 0, currentSessions.length);
|
|
6161
|
+
return {
|
|
6162
|
+
...current,
|
|
6163
|
+
[directory]: {
|
|
6164
|
+
directory,
|
|
6165
|
+
totalCount: existingEntry ? totalCountBaseline : totalCountBaseline + 1,
|
|
6166
|
+
revision: `optimistic:${optimisticId}:${currentSnapshot?.revision || "initial"}:${entry.modified || ""}`,
|
|
6167
|
+
sessions: nextSessions
|
|
6168
|
+
}
|
|
6169
|
+
};
|
|
6170
|
+
}
|
|
6171
|
+
function removeOptimisticSidebarSessionEntry(current, optimisticId) {
|
|
6172
|
+
const targetId = optimisticId?.trim() || "";
|
|
6173
|
+
if (!targetId) return current;
|
|
6174
|
+
let changed = false;
|
|
6175
|
+
const next = { ...current };
|
|
6176
|
+
for (const [directory, snapshot] of Object.entries(current)) {
|
|
6177
|
+
const nextSessions = snapshot.sessions.filter((entry) => entry.id !== targetId);
|
|
6178
|
+
if (nextSessions.length === snapshot.sessions.length) continue;
|
|
6179
|
+
changed = true;
|
|
6180
|
+
next[directory] = {
|
|
6181
|
+
...snapshot,
|
|
6182
|
+
totalCount: Math.max(0, snapshot.totalCount - 1),
|
|
6183
|
+
revision: `remove-optimistic:${targetId}:${snapshot.revision}`,
|
|
6184
|
+
sessions: nextSessions
|
|
6185
|
+
};
|
|
6186
|
+
}
|
|
6187
|
+
return changed ? next : current;
|
|
6188
|
+
}
|
|
6189
|
+
function isOptimisticSidebarSessionEntry(entry) {
|
|
6190
|
+
return Boolean(entry.optimistic || entry.id?.startsWith("optimistic:") && !entry.path);
|
|
6191
|
+
}
|
|
6192
|
+
function mergeDirectoryIndexDataPreservingOptimistic(current, next) {
|
|
6193
|
+
let merged = mergeDirectoryIndexData(current, next);
|
|
6194
|
+
for (const [directory, snapshot] of Object.entries(current)) {
|
|
6195
|
+
const optimisticSessions = snapshot.sessions.filter(isOptimisticSidebarSessionEntry);
|
|
6196
|
+
if (optimisticSessions.length === 0) continue;
|
|
6197
|
+
const targetSnapshot = merged[directory];
|
|
6198
|
+
if (!targetSnapshot) continue;
|
|
6199
|
+
const targetIds = new Set(targetSnapshot.sessions.flatMap((entry) => entry.id ? [entry.id] : []));
|
|
6200
|
+
const missingOptimisticSessions = optimisticSessions.filter((entry) => entry.id && !targetIds.has(entry.id));
|
|
6201
|
+
if (missingOptimisticSessions.length === 0) continue;
|
|
6202
|
+
merged = {
|
|
6203
|
+
...merged,
|
|
6204
|
+
[directory]: {
|
|
6205
|
+
...targetSnapshot,
|
|
6206
|
+
totalCount: targetSnapshot.totalCount + missingOptimisticSessions.length,
|
|
6207
|
+
revision: `preserve-optimistic:${targetSnapshot.revision}`,
|
|
6208
|
+
sessions: [...missingOptimisticSessions, ...targetSnapshot.sessions]
|
|
6209
|
+
}
|
|
6210
|
+
};
|
|
6211
|
+
}
|
|
6212
|
+
return merged;
|
|
6213
|
+
}
|
|
6071
6214
|
function sameSessionEntryRecord(left, right) {
|
|
6072
6215
|
const leftKeys = Object.keys(left);
|
|
6073
6216
|
const rightKeys = Object.keys(right);
|
|
@@ -6239,11 +6382,11 @@ function computeAppShellSidebarDerived(state) {
|
|
|
6239
6382
|
const sidebarSessions = Array.from(sidebarSessionEntriesByKey.values());
|
|
6240
6383
|
const pinnedSidebarSessions = state.pinnedSidebarSessionKeys.flatMap((key) => {
|
|
6241
6384
|
const entry = sidebarSessionEntriesByKey.get(key);
|
|
6242
|
-
return entry?.path || entry?.id ? [entry] : [];
|
|
6385
|
+
return entry?.path || entry?.id && !isOptimisticSidebarSessionEntry(entry) ? [entry] : [];
|
|
6243
6386
|
});
|
|
6244
6387
|
const selectedSidebarSessions = state.selectedSidebarSessionKeys.flatMap((key) => {
|
|
6245
6388
|
const entry = sidebarSessionEntriesByKey.get(key);
|
|
6246
|
-
return entry?.path || entry?.id ? [entry] : [];
|
|
6389
|
+
return entry?.path || entry?.id && !isOptimisticSidebarSessionEntry(entry) ? [entry] : [];
|
|
6247
6390
|
});
|
|
6248
6391
|
const workspaceVersion = [
|
|
6249
6392
|
baseSidebarDirectories.join("\n"),
|
|
@@ -7383,54 +7526,98 @@ function FooterKbd({ children }) {
|
|
|
7383
7526
|
}
|
|
7384
7527
|
function RenameSessionDialog({ open, onOpenChange, renameValue, onRenameValueChange, onRenameSession }) {
|
|
7385
7528
|
const isMobile = useIsMobile();
|
|
7386
|
-
const
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7529
|
+
const renameInputRef = import_react.useRef(null);
|
|
7530
|
+
import_react.useEffect(() => {
|
|
7531
|
+
if (!open) return;
|
|
7532
|
+
const frame = window.requestAnimationFrame(() => {
|
|
7533
|
+
renameInputRef.current?.focus();
|
|
7534
|
+
renameInputRef.current?.select();
|
|
7535
|
+
});
|
|
7536
|
+
return () => {
|
|
7537
|
+
window.cancelAnimationFrame(frame);
|
|
7538
|
+
};
|
|
7539
|
+
}, [open]);
|
|
7540
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
7541
|
+
className: "flex min-h-0 flex-1 flex-col",
|
|
7542
|
+
children: [
|
|
7543
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
7544
|
+
className: "border-b border-border/70 px-3 py-2",
|
|
7545
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
7546
|
+
className: "truncate text-sm font-medium",
|
|
7547
|
+
children: "Rename session"
|
|
7548
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
7549
|
+
className: "truncate text-xs text-muted-foreground",
|
|
7550
|
+
children: "Update the display name shown in the sidebar."
|
|
7551
|
+
})]
|
|
7552
|
+
}),
|
|
7553
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
7554
|
+
className: "flex min-h-0 flex-1 items-center p-3",
|
|
7555
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Input$1, {
|
|
7556
|
+
ref: renameInputRef,
|
|
7557
|
+
value: renameValue,
|
|
7558
|
+
onChange: (event) => onRenameValueChange(event.target.value),
|
|
7559
|
+
onKeyDown: (event) => {
|
|
7560
|
+
if (event.key === "Escape") {
|
|
7561
|
+
event.preventDefault();
|
|
7562
|
+
event.stopPropagation();
|
|
7563
|
+
onOpenChange(false);
|
|
7564
|
+
return;
|
|
7565
|
+
}
|
|
7566
|
+
if (event.key !== "Enter" || event.nativeEvent.isComposing) return;
|
|
7567
|
+
event.preventDefault();
|
|
7568
|
+
event.stopPropagation();
|
|
7569
|
+
onRenameSession();
|
|
7570
|
+
},
|
|
7571
|
+
placeholder: "Session name",
|
|
7572
|
+
className: "min-w-0 flex-1"
|
|
7573
|
+
})
|
|
7574
|
+
}),
|
|
7575
|
+
isMobile ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
7576
|
+
className: "hidden flex-wrap items-center gap-x-3 gap-y-1 border-t border-border/70 px-3 py-2 text-xs text-muted-foreground md:flex",
|
|
7577
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
7578
|
+
className: "inline-flex items-center gap-1",
|
|
7579
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FooterKbd, { children: "Enter" }), " Save"]
|
|
7580
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
7581
|
+
className: "inline-flex items-center gap-1",
|
|
7582
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FooterKbd, { children: "Esc" }), " Cancel"]
|
|
7583
|
+
})]
|
|
7584
|
+
})
|
|
7585
|
+
]
|
|
7395
7586
|
});
|
|
7396
7587
|
if (isMobile) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Drawer$1, {
|
|
7397
7588
|
open,
|
|
7398
7589
|
onOpenChange,
|
|
7399
7590
|
autoFocus: false,
|
|
7400
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerContent, {
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7591
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerContent, {
|
|
7592
|
+
className: "max-h-[90svh] overflow-hidden",
|
|
7593
|
+
children: [
|
|
7594
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DrawerTitle, { children: "Rename session" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DrawerDescription, { children: "Update the display name shown in the sidebar." })] }),
|
|
7595
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
7596
|
+
className: "flex min-h-0 flex-1 flex-col overflow-hidden px-4 pb-4",
|
|
7597
|
+
children: body
|
|
7598
|
+
}),
|
|
7599
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerFooter, {
|
|
7600
|
+
className: "border-t border-border/70",
|
|
7601
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
7602
|
+
variant: "outline",
|
|
7603
|
+
onClick: () => onOpenChange(false),
|
|
7604
|
+
children: "Cancel"
|
|
7605
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
7606
|
+
onClick: onRenameSession,
|
|
7607
|
+
children: "Save"
|
|
7608
|
+
})]
|
|
7609
|
+
})
|
|
7610
|
+
]
|
|
7611
|
+
})
|
|
7418
7612
|
});
|
|
7419
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
7613
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandDialog, {
|
|
7420
7614
|
open,
|
|
7421
7615
|
onOpenChange,
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
onClick: () => onOpenChange(false),
|
|
7428
|
-
children: "Cancel"
|
|
7429
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
7430
|
-
onClick: onRenameSession,
|
|
7431
|
-
children: "Save"
|
|
7432
|
-
})] })
|
|
7433
|
-
] })
|
|
7616
|
+
title: "Rename session",
|
|
7617
|
+
description: "Update the display name shown in the sidebar.",
|
|
7618
|
+
className: "sm:max-w-md",
|
|
7619
|
+
initialFocus: true,
|
|
7620
|
+
children: body
|
|
7434
7621
|
});
|
|
7435
7622
|
}
|
|
7436
7623
|
function RenameSessionDialogController({ ref, openStateRef, onRenameSession }) {
|
|
@@ -7480,35 +7667,138 @@ function RenameSessionDialogController({ ref, openStateRef, onRenameSession }) {
|
|
|
7480
7667
|
}
|
|
7481
7668
|
});
|
|
7482
7669
|
}
|
|
7483
|
-
function DeleteSessionsDialog({ open, onOpenChange, title, description, onDeleteSession }) {
|
|
7484
|
-
|
|
7670
|
+
function DeleteSessionsDialog({ open, onOpenChange, title, description, targets, onDeleteSession }) {
|
|
7671
|
+
const isMobile = useIsMobile();
|
|
7672
|
+
const deletePanelRef = import_react.useRef(null);
|
|
7673
|
+
import_react.useEffect(() => {
|
|
7674
|
+
if (!open || isMobile) return;
|
|
7675
|
+
const frame = window.requestAnimationFrame(() => {
|
|
7676
|
+
deletePanelRef.current?.focus();
|
|
7677
|
+
});
|
|
7678
|
+
return () => {
|
|
7679
|
+
window.cancelAnimationFrame(frame);
|
|
7680
|
+
};
|
|
7681
|
+
}, [isMobile, open]);
|
|
7682
|
+
import_react.useEffect(() => {
|
|
7683
|
+
if (!open || isMobile) return;
|
|
7684
|
+
const handleDeleteKeyDown = (event) => {
|
|
7685
|
+
if (event.key === "Escape") {
|
|
7686
|
+
event.preventDefault();
|
|
7687
|
+
event.stopPropagation();
|
|
7688
|
+
onOpenChange(false);
|
|
7689
|
+
return;
|
|
7690
|
+
}
|
|
7691
|
+
if (event.key !== "Enter" || event.isComposing) return;
|
|
7692
|
+
event.preventDefault();
|
|
7693
|
+
event.stopPropagation();
|
|
7694
|
+
onDeleteSession();
|
|
7695
|
+
};
|
|
7696
|
+
window.addEventListener("keydown", handleDeleteKeyDown, true);
|
|
7697
|
+
return () => {
|
|
7698
|
+
window.removeEventListener("keydown", handleDeleteKeyDown, true);
|
|
7699
|
+
};
|
|
7700
|
+
}, [
|
|
7701
|
+
isMobile,
|
|
7702
|
+
onDeleteSession,
|
|
7703
|
+
onOpenChange,
|
|
7704
|
+
open
|
|
7705
|
+
]);
|
|
7706
|
+
const previewTargets = targets.slice(0, 8);
|
|
7707
|
+
const remainingTargetCount = Math.max(0, targets.length - previewTargets.length);
|
|
7708
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
7709
|
+
ref: deletePanelRef,
|
|
7710
|
+
role: "presentation",
|
|
7711
|
+
tabIndex: -1,
|
|
7712
|
+
className: "flex min-h-0 flex-1 flex-col outline-none",
|
|
7713
|
+
onKeyDown: (event) => {
|
|
7714
|
+
if (event.key === "Escape") {
|
|
7715
|
+
event.preventDefault();
|
|
7716
|
+
event.stopPropagation();
|
|
7717
|
+
onOpenChange(false);
|
|
7718
|
+
return;
|
|
7719
|
+
}
|
|
7720
|
+
if (event.key !== "Enter" || event.nativeEvent.isComposing) return;
|
|
7721
|
+
event.preventDefault();
|
|
7722
|
+
event.stopPropagation();
|
|
7723
|
+
onDeleteSession();
|
|
7724
|
+
},
|
|
7725
|
+
children: [
|
|
7726
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
7727
|
+
className: "border-b border-border/70 px-3 py-2",
|
|
7728
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
7729
|
+
className: "truncate text-sm font-medium",
|
|
7730
|
+
children: title
|
|
7731
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
7732
|
+
className: "truncate text-xs text-muted-foreground",
|
|
7733
|
+
children: description
|
|
7734
|
+
})]
|
|
7735
|
+
}),
|
|
7736
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
7737
|
+
className: "flex min-h-0 flex-1 flex-col gap-3 p-3",
|
|
7738
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
7739
|
+
className: "text-sm text-muted-foreground",
|
|
7740
|
+
children: "This cannot be undone."
|
|
7741
|
+
}), targets.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
7742
|
+
className: "max-h-48 space-y-1 overflow-y-auto rounded-lg border bg-muted/30 p-2 text-sm",
|
|
7743
|
+
children: [previewTargets.map((target) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
7744
|
+
className: "truncate",
|
|
7745
|
+
children: target.title || "New session"
|
|
7746
|
+
}, target.path || target.id)), remainingTargetCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
7747
|
+
className: "text-muted-foreground",
|
|
7748
|
+
children: [
|
|
7749
|
+
"…and ",
|
|
7750
|
+
remainingTargetCount,
|
|
7751
|
+
" more"
|
|
7752
|
+
]
|
|
7753
|
+
}) : null]
|
|
7754
|
+
}) : null]
|
|
7755
|
+
}),
|
|
7756
|
+
isMobile ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
7757
|
+
className: "hidden flex-wrap items-center gap-x-3 gap-y-1 border-t border-border/70 px-3 py-2 text-xs text-muted-foreground md:flex",
|
|
7758
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
7759
|
+
className: "inline-flex items-center gap-1",
|
|
7760
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FooterKbd, { children: "Enter" }), " Delete"]
|
|
7761
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
7762
|
+
className: "inline-flex items-center gap-1",
|
|
7763
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FooterKbd, { children: "Esc" }), " Cancel"]
|
|
7764
|
+
})]
|
|
7765
|
+
})
|
|
7766
|
+
]
|
|
7767
|
+
});
|
|
7768
|
+
if (isMobile) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Drawer$1, {
|
|
7485
7769
|
open,
|
|
7486
7770
|
onOpenChange,
|
|
7487
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerContent, {
|
|
7488
|
-
className: "
|
|
7489
|
-
children: [
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7771
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerContent, {
|
|
7772
|
+
className: "max-h-[90svh] overflow-hidden",
|
|
7773
|
+
children: [
|
|
7774
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DrawerTitle, { children: title }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DrawerDescription, { children: description })] }),
|
|
7775
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
7776
|
+
className: "flex min-h-0 flex-1 flex-col overflow-hidden px-4 pb-4",
|
|
7777
|
+
children: body
|
|
7778
|
+
}),
|
|
7779
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerFooter, {
|
|
7780
|
+
className: "border-t border-border/70",
|
|
7781
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
7782
|
+
variant: "outline",
|
|
7783
|
+
onClick: () => onOpenChange(false),
|
|
7784
|
+
children: "Cancel"
|
|
7785
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
7786
|
+
variant: "destructive",
|
|
7787
|
+
onClick: onDeleteSession,
|
|
7788
|
+
children: "Delete"
|
|
7789
|
+
})]
|
|
7790
|
+
})
|
|
7791
|
+
]
|
|
7792
|
+
})
|
|
7499
7793
|
});
|
|
7500
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
7794
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommandDialog, {
|
|
7501
7795
|
open,
|
|
7502
7796
|
onOpenChange,
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
variant: "destructive",
|
|
7509
|
-
onClick: onDeleteSession,
|
|
7510
|
-
children: "Delete"
|
|
7511
|
-
})] })] })
|
|
7797
|
+
title,
|
|
7798
|
+
description,
|
|
7799
|
+
className: "sm:max-w-md",
|
|
7800
|
+
initialFocus: true,
|
|
7801
|
+
children: body
|
|
7512
7802
|
});
|
|
7513
7803
|
}
|
|
7514
7804
|
function DeleteOldDirectorySessionsDialog({ open, onOpenChange, directory, daysValue, preview, previewLoading, deleteLoading, onDaysValueChange, onPreview, onDelete }) {
|
|
@@ -7750,6 +8040,7 @@ function DeleteSessionsDialogController({ ref, openStateRef, onDeleteSession })
|
|
|
7750
8040
|
onOpenChange: setOpenState,
|
|
7751
8041
|
title: targets.length === 1 ? "Delete session" : "Delete sessions",
|
|
7752
8042
|
description: targets.length === 1 ? `Delete "${targets[0]?.title || "New session"}" from disk?` : `Delete ${targets.length} selected sessions from disk?`,
|
|
8043
|
+
targets,
|
|
7753
8044
|
onDeleteSession: () => {
|
|
7754
8045
|
submitDelete();
|
|
7755
8046
|
}
|
|
@@ -9409,6 +9700,24 @@ function formatComposerSkillName(skillName = "") {
|
|
|
9409
9700
|
return [`${part.charAt(0).toUpperCase()}${part.slice(1)}`];
|
|
9410
9701
|
}).join(" ");
|
|
9411
9702
|
}
|
|
9703
|
+
function formatComposerDiffLineCommentReference(comment) {
|
|
9704
|
+
const sideLabel = comment.side === "deletions" ? "old" : "new";
|
|
9705
|
+
return `${comment.path}:L${comment.lineNumber} (${sideLabel})`;
|
|
9706
|
+
}
|
|
9707
|
+
function formatComposerDiffLineCommentForPrompt(comment) {
|
|
9708
|
+
const sourceLabel = comment.commit === "working-tree" ? "working tree changes" : comment.shortHash;
|
|
9709
|
+
return `- ${formatComposerDiffLineCommentReference(comment)} in ${sourceLabel}: ${comment.text}`;
|
|
9710
|
+
}
|
|
9711
|
+
function buildComposerPromptMessage({ diffLineComments, skillName, text }) {
|
|
9712
|
+
const baseMessage = serializeComposerDraft({
|
|
9713
|
+
text,
|
|
9714
|
+
skillName
|
|
9715
|
+
}).trim();
|
|
9716
|
+
const comments = diffLineComments?.filter((comment) => comment.text.trim().length > 0);
|
|
9717
|
+
if (!comments || comments.length === 0) return baseMessage;
|
|
9718
|
+
const commentBlock = `Diff comments:\n${comments.map(formatComposerDiffLineCommentForPrompt).join("\n")}`;
|
|
9719
|
+
return baseMessage ? `${baseMessage}\n\n${commentBlock}` : commentBlock;
|
|
9720
|
+
}
|
|
9412
9721
|
function parseSlashCommandInput(value = "") {
|
|
9413
9722
|
const rawValue = typeof value === "string" ? value : "";
|
|
9414
9723
|
const trimmedStart = rawValue.trimStart();
|
|
@@ -9653,9 +9962,12 @@ function readQuotedAttribute(tag, name) {
|
|
|
9653
9962
|
}
|
|
9654
9963
|
function normalizeHighlightClassName(value) {
|
|
9655
9964
|
if (!value) return void 0;
|
|
9656
|
-
const classNames = value.split(/\s+/).filter((className) =>
|
|
9965
|
+
const classNames = value.split(/\s+/).filter((className) => className === "line");
|
|
9657
9966
|
return classNames.length > 0 ? classNames.join(" ") : void 0;
|
|
9658
9967
|
}
|
|
9968
|
+
function isSafeCssVariableColor(value) {
|
|
9969
|
+
return /^var\(--[A-Za-z0-9-]+(?:,\s*var\(--[A-Za-z0-9-]+\))?\)$/.test(value);
|
|
9970
|
+
}
|
|
9659
9971
|
function normalizeHighlightStyle(value) {
|
|
9660
9972
|
if (!value) return void 0;
|
|
9661
9973
|
for (const declaration of value.split(";")) {
|
|
@@ -9663,7 +9975,7 @@ function normalizeHighlightStyle(value) {
|
|
|
9663
9975
|
const property = rawProperty?.trim().toLowerCase();
|
|
9664
9976
|
const color = rawValueParts.join(":").trim();
|
|
9665
9977
|
if (property !== "color") continue;
|
|
9666
|
-
if (
|
|
9978
|
+
if (!isSafeCssVariableColor(color)) continue;
|
|
9667
9979
|
return { color };
|
|
9668
9980
|
}
|
|
9669
9981
|
}
|
|
@@ -9709,7 +10021,7 @@ function renderHighlightedChild(child) {
|
|
|
9709
10021
|
}
|
|
9710
10022
|
function HighlightedCode({ className, html, language }) {
|
|
9711
10023
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
|
|
9712
|
-
className: cn(language && `language-${language}`, className),
|
|
10024
|
+
className: cn("shiki", language && `language-${language}`, className),
|
|
9713
10025
|
children: parseHighlightedHtml(html).map(renderHighlightedChild)
|
|
9714
10026
|
});
|
|
9715
10027
|
}
|
|
@@ -10013,6 +10325,78 @@ var MarkdownBlock = import_react.memo(function MarkdownBlock({ streaming = false
|
|
|
10013
10325
|
})
|
|
10014
10326
|
});
|
|
10015
10327
|
});
|
|
10328
|
+
var PICO_DIFF_THEME_PAIR = {
|
|
10329
|
+
light: PICO_DIFF_SHIKI_THEMES.light,
|
|
10330
|
+
dark: PICO_DIFF_SHIKI_THEMES.dark
|
|
10331
|
+
};
|
|
10332
|
+
var PICO_DIFF_COLOR_CSS = `
|
|
10333
|
+
:host {
|
|
10334
|
+
--diffs-addition-color-override: var(--success);
|
|
10335
|
+
--diffs-deletion-color-override: var(--danger);
|
|
10336
|
+
--diffs-modified-color-override: var(--primary);
|
|
10337
|
+
--diffs-bg-addition-emphasis-override: color-mix(in lab, var(--diffs-bg) 42%, var(--diffs-addition-base));
|
|
10338
|
+
--diffs-bg-deletion-emphasis-override: color-mix(in lab, var(--diffs-bg) 42%, var(--diffs-deletion-base));
|
|
10339
|
+
}
|
|
10340
|
+
|
|
10341
|
+
@media (max-width: 640px) {
|
|
10342
|
+
[data-annotation-content] {
|
|
10343
|
+
inline-size: min(100%, calc(100vw - var(--diffs-column-number-width, 0px) - 1rem));
|
|
10344
|
+
}
|
|
10345
|
+
}
|
|
10346
|
+
|
|
10347
|
+
[data-line-type="change-addition"]:is(
|
|
10348
|
+
[data-gutter-buffer],
|
|
10349
|
+
[data-column-number],
|
|
10350
|
+
[data-line],
|
|
10351
|
+
[data-no-newline]
|
|
10352
|
+
) {
|
|
10353
|
+
--mix-light: 84%;
|
|
10354
|
+
--mix-dark: 76%;
|
|
10355
|
+
}
|
|
10356
|
+
|
|
10357
|
+
[data-line-type="change-deletion"]:is(
|
|
10358
|
+
[data-gutter-buffer],
|
|
10359
|
+
[data-column-number],
|
|
10360
|
+
[data-line],
|
|
10361
|
+
[data-no-newline]
|
|
10362
|
+
) {
|
|
10363
|
+
--mix-light: 84%;
|
|
10364
|
+
--mix-dark: 76%;
|
|
10365
|
+
}
|
|
10366
|
+
`;
|
|
10367
|
+
function registerPicoDiffTheme(name, type) {
|
|
10368
|
+
if (RegisteredCustomThemes.has(name)) return;
|
|
10369
|
+
const theme = createCssVariablesTheme({
|
|
10370
|
+
name,
|
|
10371
|
+
variablePrefix: "--diffs-",
|
|
10372
|
+
variableDefaults: { ...PICO_SHIKI_VARIABLE_DEFAULTS },
|
|
10373
|
+
fontStyle: false
|
|
10374
|
+
});
|
|
10375
|
+
registerCustomTheme(name, () => Promise.resolve({
|
|
10376
|
+
...theme,
|
|
10377
|
+
type
|
|
10378
|
+
}));
|
|
10379
|
+
}
|
|
10380
|
+
function ensurePicoDiffThemes() {
|
|
10381
|
+
registerPicoDiffTheme(PICO_DIFF_SHIKI_THEMES.light, "light");
|
|
10382
|
+
registerPicoDiffTheme(PICO_DIFF_SHIKI_THEMES.dark, "dark");
|
|
10383
|
+
}
|
|
10384
|
+
function resolvePicoDiffThemeType({ resolvedTheme, systemTheme, theme }) {
|
|
10385
|
+
return appliedThemeClassColorMode(theme) ?? appliedThemeClassColorMode(resolvedTheme) ?? (resolvedTheme === "dark" || systemTheme === "dark" ? "dark" : "light");
|
|
10386
|
+
}
|
|
10387
|
+
ensurePicoDiffThemes();
|
|
10388
|
+
function usePicoDiffThemeOptions() {
|
|
10389
|
+
const { resolvedTheme, systemTheme, theme } = z();
|
|
10390
|
+
return {
|
|
10391
|
+
theme: PICO_DIFF_THEME_PAIR,
|
|
10392
|
+
themeType: resolvePicoDiffThemeType({
|
|
10393
|
+
resolvedTheme,
|
|
10394
|
+
systemTheme,
|
|
10395
|
+
theme
|
|
10396
|
+
}),
|
|
10397
|
+
unsafeCSS: PICO_DIFF_COLOR_CSS
|
|
10398
|
+
};
|
|
10399
|
+
}
|
|
10016
10400
|
function Collapsible$1({ ...props }) {
|
|
10017
10401
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollapsibleRoot, {
|
|
10018
10402
|
"data-slot": "collapsible",
|
|
@@ -11033,6 +11417,7 @@ function EditDiffStatCountsView({ stats }) {
|
|
|
11033
11417
|
});
|
|
11034
11418
|
}
|
|
11035
11419
|
function EditDiffBlock({ isBorderless = false, patch }) {
|
|
11420
|
+
const themeOptions = usePicoDiffThemeOptions();
|
|
11036
11421
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
11037
11422
|
className: cn("overflow-hidden text-xs", !isBorderless && "rounded-md border bg-background"),
|
|
11038
11423
|
style: { "--diffs-font-family": "var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace)" },
|
|
@@ -11040,6 +11425,7 @@ function EditDiffBlock({ isBorderless = false, patch }) {
|
|
|
11040
11425
|
patch,
|
|
11041
11426
|
disableWorkerPool: true,
|
|
11042
11427
|
options: {
|
|
11428
|
+
...themeOptions,
|
|
11043
11429
|
diffStyle: "unified",
|
|
11044
11430
|
disableFileHeader: true,
|
|
11045
11431
|
lineDiffType: "word-alt",
|
|
@@ -11210,11 +11596,11 @@ function ToolBlockCardBody({ block }) {
|
|
|
11210
11596
|
const isSelfContainedWriteTool = block.name === "write" && !block.isError && getWriteToolPayload(block)?.content !== void 0;
|
|
11211
11597
|
const hasSelfContainedToolOutput = isSuccessfulEditTool || isSelfContainedWriteTool;
|
|
11212
11598
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
11213
|
-
className: "border-t pt-3",
|
|
11599
|
+
className: cn("border-t", !isSuccessfulEditTool && "pt-3"),
|
|
11214
11600
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
11215
11601
|
ref: block.name === "bash" ? autoScroll.ref : void 0,
|
|
11216
11602
|
onScroll: block.name === "bash" ? autoScroll.onScroll : void 0,
|
|
11217
|
-
className: cn(isSelfContainedWriteTool ? "overflow-hidden rounded-lg" : "max-h-96 overflow-auto", hasSelfContainedToolOutput ? "rounded-lg" : "rounded-lg border bg-background/80 p-3"),
|
|
11603
|
+
className: cn(isSelfContainedWriteTool ? "overflow-hidden rounded-lg" : "max-h-96 overflow-auto", isSuccessfulEditTool ? "rounded-t-none rounded-b-xl" : hasSelfContainedToolOutput ? "rounded-lg" : "rounded-lg border bg-background/80 p-3"),
|
|
11218
11604
|
children: block.name === "bash" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
|
|
11219
11605
|
className: cn("overflow-x-auto font-mono text-xs leading-5 break-words whitespace-pre-wrap", block.isError && "text-destructive"),
|
|
11220
11606
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AnsiText, { text: shellBodyText })
|
|
@@ -11268,6 +11654,7 @@ var ToolBlockCard = import_react.memo(function ToolBlockCard({ blockKey, store }
|
|
|
11268
11654
|
function ToolBlockCardContent({ blockKey, header, store }) {
|
|
11269
11655
|
const [isOpen, setIsOpen] = useRememberedToolCollapsibleOpen(header.openStateKey);
|
|
11270
11656
|
const bodyBlock = useAssistantToolBlockBody(store, blockKey, isOpen);
|
|
11657
|
+
const isSuccessfulEditTool = header.name === "edit" && !header.running && !header.isError;
|
|
11271
11658
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Collapsible$1, {
|
|
11272
11659
|
open: isOpen,
|
|
11273
11660
|
onOpenChange: setIsOpen,
|
|
@@ -11293,7 +11680,7 @@ function ToolBlockCardContent({ blockKey, header, store }) {
|
|
|
11293
11680
|
}), isOpen && bodyBlock ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollapsibleContent, {
|
|
11294
11681
|
className: "overflow-hidden text-sm data-open:animate-accordion-down data-closed:animate-accordion-up",
|
|
11295
11682
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
11296
|
-
className: "h-(--collapsible-panel-height)
|
|
11683
|
+
className: cn("h-(--collapsible-panel-height) data-ending-style:h-0 data-starting-style:h-0", !isSuccessfulEditTool && "px-3 pt-0 pb-3"),
|
|
11297
11684
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToolBlockCardBody, { block: bodyBlock })
|
|
11298
11685
|
})
|
|
11299
11686
|
}) : null]
|
|
@@ -12074,7 +12461,7 @@ function getClipboardImageFiles(data) {
|
|
|
12074
12461
|
if (itemFiles.length > 0) return itemFiles;
|
|
12075
12462
|
return Array.from(data.files).filter((file) => file.type.startsWith("image/"));
|
|
12076
12463
|
}
|
|
12077
|
-
function ComposerPanel({ activeSessionId, currentPendingMessages, composerImages, composerText, composerSkill, composerSyncNonce, centerMessages, contextUsageStore, displaySettingsStore, sessionStore, isSubmitting, isStreaming, awaitingFirstTurn, disabled = false, flush = false, topContent, viewerContextId, fileInputRef, onComposerTextChange, onPickImages, onRemoveComposerImage, onSubmitPrompt, onAbort, onEditPendingMessage, onRemovePendingMessage, onReorderPending, onRunBuiltinSlashCommand, onSelectModel, onSelectThinkingLevel, requestPathCompletions, requestFileCompletions, ref }) {
|
|
12464
|
+
function ComposerPanel({ activeSessionId, currentPendingMessages, composerDiffLineComments, composerImages, composerText, composerSkill, composerSyncNonce, centerMessages, contextUsageStore, displaySettingsStore, sessionStore, isSubmitting, isStreaming, awaitingFirstTurn, disabled = false, flush = false, topContent, viewerContextId, fileInputRef, onComposerTextChange, onPickImages, onRemoveComposerDiffLineComment, onRemoveComposerImage, onSubmitPrompt, onAbort, onEditPendingMessage, onRemovePendingMessage, onReorderPending, onRunBuiltinSlashCommand, onSelectModel, onSelectThinkingLevel, requestPathCompletions, requestFileCompletions, ref }) {
|
|
12078
12465
|
const promptRef = import_react.useRef(null);
|
|
12079
12466
|
const [pickerState, dispatchPickerState] = import_react.useReducer(composerPickerReducer, INITIAL_COMPOSER_PICKER_STATE);
|
|
12080
12467
|
const { modelPickerOpen, thinkingPickerOpen, modelQuery } = pickerState;
|
|
@@ -12108,6 +12495,7 @@ function ComposerPanel({ activeSessionId, currentPendingMessages, composerImages
|
|
|
12108
12495
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
12109
12496
|
className: "overflow-visible rounded-[18px] border bg-card",
|
|
12110
12497
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComposerPromptEditor, {
|
|
12498
|
+
composerDiffLineComments,
|
|
12111
12499
|
composerImages,
|
|
12112
12500
|
composerText,
|
|
12113
12501
|
composerSkill,
|
|
@@ -12122,6 +12510,7 @@ function ComposerPanel({ activeSessionId, currentPendingMessages, composerImages
|
|
|
12122
12510
|
sessionStore,
|
|
12123
12511
|
onComposerTextChange,
|
|
12124
12512
|
onPickImages,
|
|
12513
|
+
onRemoveComposerDiffLineComment,
|
|
12125
12514
|
onRemoveComposerImage,
|
|
12126
12515
|
onSubmitPrompt,
|
|
12127
12516
|
onAbort,
|
|
@@ -12195,7 +12584,7 @@ var ComposerAttachments = import_react.memo(function ComposerAttachments({ image
|
|
|
12195
12584
|
}, promptImageKey(image)))
|
|
12196
12585
|
});
|
|
12197
12586
|
});
|
|
12198
|
-
var ComposerPromptEditor = import_react.memo(function ComposerPromptEditor({ composerImages, composerText, composerSkill, composerSyncNonce, isSubmitting, isStreaming, awaitingFirstTurn, disabled = false, fileInputRef, promptRef, displaySettingsStore, sessionStore, onComposerTextChange, onPickImages, onRemoveComposerImage, onSubmitPrompt, onAbort, onRunBuiltinSlashCommand, requestPathCompletions, requestFileCompletions }) {
|
|
12587
|
+
var ComposerPromptEditor = import_react.memo(function ComposerPromptEditor({ composerDiffLineComments, composerImages, composerText, composerSkill, composerSyncNonce, isSubmitting, isStreaming, awaitingFirstTurn, disabled = false, fileInputRef, promptRef, displaySettingsStore, sessionStore, onComposerTextChange, onPickImages, onRemoveComposerDiffLineComment, onRemoveComposerImage, onSubmitPrompt, onAbort, onRunBuiltinSlashCommand, requestPathCompletions, requestFileCompletions }) {
|
|
12199
12588
|
const slashCommands = useComposerSlashCommands({
|
|
12200
12589
|
displaySettingsStore,
|
|
12201
12590
|
sessionStore
|
|
@@ -12282,8 +12671,9 @@ var ComposerPromptEditor = import_react.memo(function ComposerPromptEditor({ com
|
|
|
12282
12671
|
dismissMenus,
|
|
12283
12672
|
promptRef
|
|
12284
12673
|
]);
|
|
12285
|
-
const hasSubmittableContent = hasDraftText || composerImages.length > 0;
|
|
12286
|
-
const
|
|
12674
|
+
const hasSubmittableContent = hasDraftText || composerDiffLineComments.length > 0 || composerImages.length > 0;
|
|
12675
|
+
const responseInFlight = isStreaming || awaitingFirstTurn || isSubmitting;
|
|
12676
|
+
const acceptFollowUps = responseInFlight;
|
|
12287
12677
|
const setAssistPointerSelectionSuppressedValue = (next) => {
|
|
12288
12678
|
assistPointerSelectionSuppressedRef.current = next;
|
|
12289
12679
|
setAssistPointerSelectionSuppressed(next);
|
|
@@ -12358,6 +12748,11 @@ var ComposerPromptEditor = import_react.memo(function ComposerPromptEditor({ com
|
|
|
12358
12748
|
applyDraft("", void 0, { immediate: true });
|
|
12359
12749
|
return;
|
|
12360
12750
|
}
|
|
12751
|
+
if (event.key === "Backspace" && !draftText && !currentDraftSkill && composerDiffLineComments.length > 0) {
|
|
12752
|
+
const lastComment = composerDiffLineComments.at(-1);
|
|
12753
|
+
if (lastComment) onRemoveComposerDiffLineComment(lastComment.id);
|
|
12754
|
+
return;
|
|
12755
|
+
}
|
|
12361
12756
|
if (visibleCompletion && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
|
|
12362
12757
|
event.preventDefault();
|
|
12363
12758
|
setAssistPointerSelectionSuppressedValue(true);
|
|
@@ -12416,7 +12811,7 @@ var ComposerPromptEditor = import_react.memo(function ComposerPromptEditor({ com
|
|
|
12416
12811
|
dismissMenus();
|
|
12417
12812
|
return;
|
|
12418
12813
|
}
|
|
12419
|
-
if (
|
|
12814
|
+
if (responseInFlight && !event.repeat) {
|
|
12420
12815
|
event.preventDefault();
|
|
12421
12816
|
event.stopPropagation();
|
|
12422
12817
|
onAbort();
|
|
@@ -12463,39 +12858,62 @@ var ComposerPromptEditor = import_react.memo(function ComposerPromptEditor({ com
|
|
|
12463
12858
|
className: "min-w-0",
|
|
12464
12859
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
12465
12860
|
className: "flex min-w-0 flex-wrap items-start gap-2",
|
|
12466
|
-
children: [
|
|
12467
|
-
|
|
12468
|
-
|
|
12469
|
-
|
|
12470
|
-
|
|
12471
|
-
|
|
12472
|
-
|
|
12473
|
-
|
|
12474
|
-
|
|
12475
|
-
|
|
12861
|
+
children: [
|
|
12862
|
+
draftSkill ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
12863
|
+
className: "inline-flex h-7 max-w-[45%] shrink-0 items-center gap-0 overflow-hidden rounded-full bg-primary/10 pr-0.5 pl-2 text-sm font-medium text-primary",
|
|
12864
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
12865
|
+
className: "truncate",
|
|
12866
|
+
children: ["Skill: ", formatComposerSkillName(draftSkill)]
|
|
12867
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
12868
|
+
size: "icon-sm",
|
|
12869
|
+
variant: "ghost",
|
|
12870
|
+
className: "ml-1 rounded-full text-primary hover:bg-primary/10 hover:text-primary",
|
|
12871
|
+
"aria-label": `Remove skill ${formatComposerSkillName(draftSkill)}`,
|
|
12872
|
+
disabled,
|
|
12873
|
+
onClick: () => applyDraft(draftTextRef.current, void 0, { immediate: true }),
|
|
12874
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "size-3.5" })
|
|
12875
|
+
})]
|
|
12876
|
+
}) : null,
|
|
12877
|
+
composerDiffLineComments.map((comment) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
12878
|
+
title: `${formatComposerDiffLineCommentReference(comment)}: ${comment.text}`,
|
|
12879
|
+
className: "inline-flex h-7 max-w-[45%] shrink-0 items-center gap-1 overflow-hidden rounded-full bg-amber-500/10 pr-0.5 pl-2 text-sm font-medium text-amber-700 dark:text-amber-300",
|
|
12880
|
+
children: [
|
|
12881
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitPullRequestArrow, { className: "size-3.5 shrink-0" }),
|
|
12882
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
12883
|
+
className: "truncate",
|
|
12884
|
+
children: ["Diff: ", formatComposerDiffLineCommentReference(comment)]
|
|
12885
|
+
}),
|
|
12886
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
12887
|
+
size: "icon-sm",
|
|
12888
|
+
variant: "ghost",
|
|
12889
|
+
className: "ml-1 rounded-full text-amber-700 hover:bg-amber-500/10 hover:text-amber-700 dark:text-amber-300 dark:hover:text-amber-300",
|
|
12890
|
+
"aria-label": `Remove diff comment for ${formatComposerDiffLineCommentReference(comment)}`,
|
|
12891
|
+
disabled,
|
|
12892
|
+
onClick: () => onRemoveComposerDiffLineComment(comment.id),
|
|
12893
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "size-3.5" })
|
|
12894
|
+
})
|
|
12895
|
+
]
|
|
12896
|
+
}, comment.id)),
|
|
12897
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Textarea, {
|
|
12898
|
+
ref: promptRef,
|
|
12899
|
+
name: "prompt",
|
|
12900
|
+
rows: 1,
|
|
12901
|
+
autoComplete: "off",
|
|
12902
|
+
"data-1p-ignore": "true",
|
|
12903
|
+
"data-form-type": "other",
|
|
12904
|
+
"data-lpignore": "true",
|
|
12905
|
+
defaultValue: composerText,
|
|
12906
|
+
onChange: handleTextChange,
|
|
12907
|
+
onClick: syncSelection,
|
|
12908
|
+
onKeyUp: syncSelection,
|
|
12909
|
+
onSelect: syncSelection,
|
|
12910
|
+
onKeyDown: handleKeyDown,
|
|
12911
|
+
onPaste: handlePaste,
|
|
12476
12912
|
disabled,
|
|
12477
|
-
|
|
12478
|
-
|
|
12479
|
-
})
|
|
12480
|
-
|
|
12481
|
-
ref: promptRef,
|
|
12482
|
-
name: "prompt",
|
|
12483
|
-
rows: 1,
|
|
12484
|
-
autoComplete: "off",
|
|
12485
|
-
"data-1p-ignore": "true",
|
|
12486
|
-
"data-form-type": "other",
|
|
12487
|
-
"data-lpignore": "true",
|
|
12488
|
-
defaultValue: composerText,
|
|
12489
|
-
onChange: handleTextChange,
|
|
12490
|
-
onClick: syncSelection,
|
|
12491
|
-
onKeyUp: syncSelection,
|
|
12492
|
-
onSelect: syncSelection,
|
|
12493
|
-
onKeyDown: handleKeyDown,
|
|
12494
|
-
onPaste: handlePaste,
|
|
12495
|
-
disabled,
|
|
12496
|
-
placeholder: acceptFollowUps ? "Add a message to the queue..." : draftSkill ? `Ask with ${formatComposerSkillName(draftSkill)}…` : "Ask anything…",
|
|
12497
|
-
className: "max-h-[min(40dvh,18rem)] min-h-[22px] max-w-full min-w-0 flex-1 basis-[min(240px,100%)] resize-none overflow-y-auto rounded-none border-0 bg-transparent p-0 text-base shadow-none ring-0 focus-visible:border-transparent focus-visible:ring-0 disabled:cursor-text disabled:bg-transparent disabled:opacity-60 md:text-sm dark:bg-transparent dark:disabled:bg-transparent"
|
|
12498
|
-
})]
|
|
12913
|
+
placeholder: acceptFollowUps ? "Add a message to the queue..." : draftSkill ? `Ask with ${formatComposerSkillName(draftSkill)}…` : "Ask anything…",
|
|
12914
|
+
className: "max-h-[min(40dvh,18rem)] min-h-[22px] max-w-full min-w-0 flex-1 basis-[min(240px,100%)] resize-none overflow-y-auto rounded-none border-0 bg-transparent p-0 text-base shadow-none ring-0 focus-visible:border-transparent focus-visible:ring-0 disabled:cursor-text disabled:bg-transparent disabled:opacity-60 md:text-sm dark:bg-transparent dark:disabled:bg-transparent"
|
|
12915
|
+
})
|
|
12916
|
+
]
|
|
12499
12917
|
})
|
|
12500
12918
|
})]
|
|
12501
12919
|
}),
|
|
@@ -12550,7 +12968,7 @@ var ComposerPromptEditor = import_react.memo(function ComposerPromptEditor({ com
|
|
|
12550
12968
|
onClick: () => runPrimaryComposerAction("steer"),
|
|
12551
12969
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ListStart, { "data-icon": "inline-start" }), "Steer"]
|
|
12552
12970
|
}),
|
|
12553
|
-
|
|
12971
|
+
responseInFlight ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
12554
12972
|
title: "Abort",
|
|
12555
12973
|
kbd: "Esc",
|
|
12556
12974
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
@@ -12929,6 +13347,7 @@ var AppShellComposerController = import_react.memo(function AppShellComposerCont
|
|
|
12929
13347
|
ref: composerPanelRef,
|
|
12930
13348
|
activeSessionId: snapshot.activeSessionId,
|
|
12931
13349
|
currentPendingMessages: snapshot.currentPendingMessages,
|
|
13350
|
+
composerDiffLineComments: snapshot.composerDiffLineComments,
|
|
12932
13351
|
composerImages: snapshot.composerImages,
|
|
12933
13352
|
composerText: snapshot.composerText,
|
|
12934
13353
|
composerSkill: snapshot.composerSkill,
|
|
@@ -12947,6 +13366,7 @@ var AppShellComposerController = import_react.memo(function AppShellComposerCont
|
|
|
12947
13366
|
fileInputRef,
|
|
12948
13367
|
onComposerTextChange,
|
|
12949
13368
|
onPickImages,
|
|
13369
|
+
onRemoveComposerDiffLineComment: actionsRef.current.removeDiffLineComment,
|
|
12950
13370
|
onRemoveComposerImage,
|
|
12951
13371
|
onSubmitPrompt,
|
|
12952
13372
|
onAbort,
|
|
@@ -13892,21 +14312,29 @@ function ConversationScrollRevisionObserver({ conversationItemsStore, disabled,
|
|
|
13892
14312
|
}, [conversationRevision, disabled]);
|
|
13893
14313
|
return null;
|
|
13894
14314
|
}
|
|
13895
|
-
function ConversationPreviousMessageButton({ onClick, scrollStateStore }) {
|
|
14315
|
+
function ConversationPreviousMessageButton({ centerMessages, onClick, scrollStateStore }) {
|
|
13896
14316
|
const isDisabled = useMessageScrollValue(scrollStateStore, (snapshot) => !snapshot.hasPreviousMessageJumpTarget);
|
|
13897
|
-
|
|
14317
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
13898
14318
|
title: "Jump to previous message",
|
|
13899
14319
|
kbd: formatShortcutLabel("Control+ArrowLeft"),
|
|
13900
14320
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
13901
14321
|
variant: "secondary",
|
|
13902
14322
|
size: "icon-lg",
|
|
13903
14323
|
disabled: isDisabled,
|
|
13904
|
-
className: "
|
|
14324
|
+
className: cn("rounded-full border-0 shadow-[0_10px_24px_rgba(0,0,0,0.28)] disabled:pointer-events-none disabled:opacity-0", centerMessages ? "pointer-events-auto" : "absolute right-4 bottom-4 z-10 md:right-[18px] md:bottom-[18px]"),
|
|
13905
14325
|
"aria-label": "Jump to previous message",
|
|
13906
14326
|
onClick,
|
|
13907
14327
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowUpToLine, { className: "size-4" })
|
|
13908
14328
|
})
|
|
13909
14329
|
});
|
|
14330
|
+
if (!centerMessages) return button;
|
|
14331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
14332
|
+
className: "pointer-events-none absolute inset-x-4 bottom-4 z-10 md:bottom-[18px]",
|
|
14333
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
14334
|
+
className: "mx-auto flex w-full max-w-[80ch] justify-end",
|
|
14335
|
+
children: button
|
|
14336
|
+
})
|
|
14337
|
+
});
|
|
13910
14338
|
}
|
|
13911
14339
|
var ConversationContentChangeContext = import_react.createContext(null);
|
|
13912
14340
|
function useAppShellConversationSessionState(store) {
|
|
@@ -13918,7 +14346,7 @@ function useAppShellConversationSessionState(store) {
|
|
|
13918
14346
|
streaming: sessionState.streaming
|
|
13919
14347
|
}), { compare: shallowRecordEqual });
|
|
13920
14348
|
}
|
|
13921
|
-
function AppShellConversationFrame({ autoScrollEnabled, children, conversationItemsStore, isSessionViewLoading, ref, sessionState }) {
|
|
14349
|
+
function AppShellConversationFrame({ autoScrollEnabled, children, centerMessages, conversationItemsStore, isSessionViewLoading, ref, sessionState }) {
|
|
13922
14350
|
const { bottomRef, jumpToNextMessage, jumpToPreviousMessage, messagesContentRef, messagesScrollAreaRef, scrollConversationToBottom, scrollConversationToTop, scrollStateStore, syncAfterConversationChange } = useAppShellMessageScroll({
|
|
13923
14351
|
autoScrollEnabled,
|
|
13924
14352
|
isSessionViewLoading,
|
|
@@ -13966,6 +14394,7 @@ function AppShellConversationFrame({ autoScrollEnabled, children, conversationIt
|
|
|
13966
14394
|
onClick: scrollConversationToBottom,
|
|
13967
14395
|
scrollStateStore
|
|
13968
14396
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConversationPreviousMessageButton, {
|
|
14397
|
+
centerMessages,
|
|
13969
14398
|
onClick: jumpToPreviousMessage,
|
|
13970
14399
|
scrollStateStore
|
|
13971
14400
|
})] }) : null]
|
|
@@ -13973,9 +14402,11 @@ function AppShellConversationFrame({ autoScrollEnabled, children, conversationIt
|
|
|
13973
14402
|
}
|
|
13974
14403
|
function AppShellWorkingIndicatorLabel({ fallbackLabel, hiddenThinkingPreviewStore, useHiddenThinkingPreview }) {
|
|
13975
14404
|
const hiddenThinkingPreview = useSelector(hiddenThinkingPreviewStore);
|
|
14405
|
+
const visibleLabel = useHiddenThinkingPreview && hiddenThinkingPreview ? hiddenThinkingPreview : fallbackLabel;
|
|
14406
|
+
if (!visibleLabel.trim()) return null;
|
|
13976
14407
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
13977
14408
|
className: "font-medium text-foreground",
|
|
13978
|
-
children:
|
|
14409
|
+
children: visibleLabel
|
|
13979
14410
|
});
|
|
13980
14411
|
}
|
|
13981
14412
|
function AppShellMessagesWorkingIndicator({ hiddenThinkingPreviewStore, onCancel, state, useHiddenThinkingPreview }) {
|
|
@@ -14113,7 +14544,7 @@ function AppShellConversationEmptyState({ awaitingFirstTurn, conversationItemsSt
|
|
|
14113
14544
|
const conversationLoadingLabel = isSessionViewLoading ? "Loading session…" : displayedWorkingState && !displayedWorkingState.done ? displayedWorkingState.label : "Loading…";
|
|
14114
14545
|
if (showConversationLoadingState) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
14115
14546
|
className: "flex flex-1 flex-col items-center justify-center gap-3 py-10 text-sm text-muted-foreground",
|
|
14116
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: conversationLoadingLabel })]
|
|
14547
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {}), conversationLoadingLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: conversationLoadingLabel }) : null]
|
|
14117
14548
|
});
|
|
14118
14549
|
if (hasMessages) return null;
|
|
14119
14550
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Empty, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(EmptyHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyTitle, { children: draft ? "New session" : "Start a new conversation" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyDescription, { children: draft ? void 0 : "This is the native Pico session view backed by the new TypeScript runtime." })] }), draft ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(EmptyContent, {
|
|
@@ -14179,6 +14610,7 @@ var AppShellSessionConversation = import_react.memo(function AppShellSessionConv
|
|
|
14179
14610
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AppShellConversationFrame, {
|
|
14180
14611
|
ref: conversationFrameRef,
|
|
14181
14612
|
autoScrollEnabled,
|
|
14613
|
+
centerMessages,
|
|
14182
14614
|
conversationItemsStore,
|
|
14183
14615
|
isSessionViewLoading,
|
|
14184
14616
|
sessionState,
|
|
@@ -16327,7 +16759,7 @@ var GIT_GRAPH_LANE_COLORS = [
|
|
|
16327
16759
|
];
|
|
16328
16760
|
var GIT_GRAPH_NULL_VERTEX_ID = -1;
|
|
16329
16761
|
var GIT_GRAPH_ROW_HEIGHT = 32;
|
|
16330
|
-
var GIT_GRAPH_COMMIT_DETAILS_HEIGHT =
|
|
16762
|
+
var GIT_GRAPH_COMMIT_DETAILS_HEIGHT = 200;
|
|
16331
16763
|
var GIT_GRAPH_LANE_WIDTH = 14;
|
|
16332
16764
|
var GIT_GRAPH_OFFSET_X = 12;
|
|
16333
16765
|
var initialGitCommitRowState = {
|
|
@@ -17361,7 +17793,7 @@ function useGitCommitRowView({ viewerContextId, cwd, graphWidth, line, value, on
|
|
|
17361
17793
|
}, contextMenuKey)
|
|
17362
17794
|
}),
|
|
17363
17795
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AccordionContent, {
|
|
17364
|
-
className: "relative h-[
|
|
17796
|
+
className: "relative h-[200px] border-b border-border/70 bg-muted/50 p-0",
|
|
17365
17797
|
children: [
|
|
17366
17798
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
17367
17799
|
ref: commitBodyScrollRef,
|
|
@@ -17767,6 +18199,124 @@ function GitFileDiff({ file }) {
|
|
|
17767
18199
|
}) : null]
|
|
17768
18200
|
});
|
|
17769
18201
|
}
|
|
18202
|
+
function reviewDiffCommentSideLabel(side) {
|
|
18203
|
+
return side === "deletions" ? "old" : "new";
|
|
18204
|
+
}
|
|
18205
|
+
function reviewDiffCommentLineFromRange(range) {
|
|
18206
|
+
return Math.min(range.start, range.end);
|
|
18207
|
+
}
|
|
18208
|
+
function reviewDiffCommentSideFromRange(range) {
|
|
18209
|
+
return range.side || range.endSide || "additions";
|
|
18210
|
+
}
|
|
18211
|
+
function reviewDiffCommentPath(file, side) {
|
|
18212
|
+
return side === "deletions" ? file.previousPath || file.path : file.path;
|
|
18213
|
+
}
|
|
18214
|
+
function reviewDiffCommentTabKey(file) {
|
|
18215
|
+
return `changes:${reviewFileValue(file)}`;
|
|
18216
|
+
}
|
|
18217
|
+
function reviewDiffLineCommentAnnotations({ comments, pendingComment }) {
|
|
18218
|
+
const annotations = comments.map((comment) => ({
|
|
18219
|
+
lineNumber: comment.lineNumber,
|
|
18220
|
+
metadata: comment,
|
|
18221
|
+
side: comment.side
|
|
18222
|
+
}));
|
|
18223
|
+
if (pendingComment) annotations.push({
|
|
18224
|
+
lineNumber: pendingComment.lineNumber,
|
|
18225
|
+
metadata: pendingComment,
|
|
18226
|
+
side: pendingComment.side
|
|
18227
|
+
});
|
|
18228
|
+
return annotations;
|
|
18229
|
+
}
|
|
18230
|
+
function ReviewDiffPendingLineComment({ comment }) {
|
|
18231
|
+
const [text, setText] = import_react.useState("");
|
|
18232
|
+
const textareaRef = import_react.useRef(null);
|
|
18233
|
+
import_react.useEffect(() => {
|
|
18234
|
+
textareaRef.current?.focus();
|
|
18235
|
+
}, []);
|
|
18236
|
+
const submit = () => {
|
|
18237
|
+
const normalizedText = text.trim();
|
|
18238
|
+
if (!normalizedText) return;
|
|
18239
|
+
comment.onSubmit(normalizedText);
|
|
18240
|
+
};
|
|
18241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", {
|
|
18242
|
+
className: "m-2 w-[min(38rem,calc(100vw_-_5rem))] max-w-[calc(100%_-_1rem)] rounded-lg border border-border/70 bg-background p-2 shadow-sm",
|
|
18243
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
18244
|
+
onSubmit: (event) => {
|
|
18245
|
+
event.preventDefault();
|
|
18246
|
+
submit();
|
|
18247
|
+
},
|
|
18248
|
+
children: [
|
|
18249
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18250
|
+
className: "mb-2 flex min-w-0 items-center justify-between gap-2 text-xs text-muted-foreground",
|
|
18251
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
18252
|
+
className: "min-w-0 truncate",
|
|
18253
|
+
children: [
|
|
18254
|
+
"Comment on ",
|
|
18255
|
+
comment.path,
|
|
18256
|
+
":L",
|
|
18257
|
+
comment.lineNumber,
|
|
18258
|
+
" (",
|
|
18259
|
+
reviewDiffCommentSideLabel(comment.side),
|
|
18260
|
+
")"
|
|
18261
|
+
]
|
|
18262
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
18263
|
+
type: "button",
|
|
18264
|
+
variant: "ghost",
|
|
18265
|
+
size: "icon-sm",
|
|
18266
|
+
"aria-label": "Cancel line comment",
|
|
18267
|
+
onClick: comment.onCancel,
|
|
18268
|
+
children: "×"
|
|
18269
|
+
})]
|
|
18270
|
+
}),
|
|
18271
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Textarea, {
|
|
18272
|
+
ref: textareaRef,
|
|
18273
|
+
value: text,
|
|
18274
|
+
rows: 2,
|
|
18275
|
+
placeholder: "Add a note for the prompt…",
|
|
18276
|
+
className: "min-h-16 resize-none text-sm",
|
|
18277
|
+
onChange: (event) => setText(event.target.value),
|
|
18278
|
+
onKeyDown: (event) => {
|
|
18279
|
+
if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
|
|
18280
|
+
event.preventDefault();
|
|
18281
|
+
submit();
|
|
18282
|
+
}
|
|
18283
|
+
if (event.key === "Escape") {
|
|
18284
|
+
event.preventDefault();
|
|
18285
|
+
comment.onCancel();
|
|
18286
|
+
}
|
|
18287
|
+
}
|
|
18288
|
+
}),
|
|
18289
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18290
|
+
className: "mt-2 flex flex-wrap justify-end gap-2",
|
|
18291
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
18292
|
+
type: "button",
|
|
18293
|
+
variant: "ghost",
|
|
18294
|
+
onClick: comment.onCancel,
|
|
18295
|
+
children: "Cancel"
|
|
18296
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
18297
|
+
type: "submit",
|
|
18298
|
+
disabled: !text.trim(),
|
|
18299
|
+
children: "Add to prompt"
|
|
18300
|
+
})]
|
|
18301
|
+
})
|
|
18302
|
+
]
|
|
18303
|
+
});
|
|
18304
|
+
}
|
|
18305
|
+
function ReviewDiffLineAnnotation({ annotation }) {
|
|
18306
|
+
const comment = annotation.metadata;
|
|
18307
|
+
if (!comment) return null;
|
|
18308
|
+
if (comment.kind === "pending") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReviewDiffPendingLineComment, { comment });
|
|
18309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18310
|
+
className: "my-1 ml-2 inline-flex max-w-[min(32rem,calc(100vw_-_5rem),90%)] items-center gap-1 rounded-full border border-amber-500/20 bg-amber-500/10 px-2 py-1 text-[11px] text-amber-800 dark:text-amber-200",
|
|
18311
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
18312
|
+
className: "shrink-0",
|
|
18313
|
+
children: "💬"
|
|
18314
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
18315
|
+
className: "truncate",
|
|
18316
|
+
children: comment.text
|
|
18317
|
+
})]
|
|
18318
|
+
});
|
|
18319
|
+
}
|
|
17770
18320
|
var GIT_HISTORY_PANEL_MIN_HEIGHT = 160;
|
|
17771
18321
|
var GIT_HISTORY_PANEL_MAX_STORED_HEIGHT = 1600;
|
|
17772
18322
|
function clampStoredGitHistoryPanelHeight(height) {
|
|
@@ -17866,7 +18416,7 @@ function gitFileShouldPreviewPatch(file) {
|
|
|
17866
18416
|
function FileReviewContent(props) {
|
|
17867
18417
|
return useFileReviewContentView(props);
|
|
17868
18418
|
}
|
|
17869
|
-
function useFileReviewContentView({ viewerContextId, cwd, active, onMaximizeHistory, onOpenCommitDiff, onOpenFile, showEmbeddedHistory = true }) {
|
|
18419
|
+
function useFileReviewContentView({ viewerContextId, cwd, active, diffLineComments = [], onAddDiffLineComment, onMaximizeHistory, onOpenCommitDiff, onOpenFile, showEmbeddedHistory = true }) {
|
|
17870
18420
|
const normalizedCwd = normalizeCwd(cwd);
|
|
17871
18421
|
const isMobile = useIsMobile();
|
|
17872
18422
|
const [state, dispatch] = import_react.useReducer(fileReviewReducer, initialFileReviewState, (initialState) => ({
|
|
@@ -18102,10 +18652,12 @@ function useFileReviewContentView({ viewerContextId, cwd, active, onMaximizeHist
|
|
|
18102
18652
|
viewerContextId,
|
|
18103
18653
|
cwd: normalizedCwd,
|
|
18104
18654
|
active,
|
|
18655
|
+
diffLineComments,
|
|
18105
18656
|
diffStyle,
|
|
18106
18657
|
file,
|
|
18107
18658
|
open: openFiles.includes(reviewFileValue(file)),
|
|
18108
18659
|
stuck: stickyReviewFileValue === reviewFileValue(file),
|
|
18660
|
+
onAddDiffLineComment,
|
|
18109
18661
|
onOpenFile
|
|
18110
18662
|
}, reviewFileValue(file)))
|
|
18111
18663
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
|
|
@@ -18174,10 +18726,12 @@ function useFileReviewContentView({ viewerContextId, cwd, active, onMaximizeHist
|
|
|
18174
18726
|
]
|
|
18175
18727
|
});
|
|
18176
18728
|
}
|
|
18177
|
-
function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffStyle, file, open, stuck, onOpenFile }) {
|
|
18729
|
+
function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffLineComments = [], diffStyle, file, open, stuck, onAddDiffLineComment, onOpenFile }) {
|
|
18178
18730
|
const normalizedCwd = normalizeCwd(cwd);
|
|
18179
18731
|
const queryClient = useQueryClient();
|
|
18180
18732
|
const value = reviewFileValue(file);
|
|
18733
|
+
const commentTabKey = reviewDiffCommentTabKey(file);
|
|
18734
|
+
const [commentTarget, setCommentTarget] = import_react.useState(null);
|
|
18181
18735
|
const [fullContextRequested, setFullContextRequested] = import_react.useState(false);
|
|
18182
18736
|
const previewPatch = gitFileShouldPreviewPatch(file) && !fullContextRequested;
|
|
18183
18737
|
const diffQuery = useQuery({
|
|
@@ -18210,6 +18764,41 @@ function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffStyle, file
|
|
|
18210
18764
|
const oldContent = reviewQuery.data?.oldContent ?? "";
|
|
18211
18765
|
const newContent = reviewQuery.data?.newContent ?? "";
|
|
18212
18766
|
const patch = diffQuery.data?.patch ?? "";
|
|
18767
|
+
const commentsForFile = diffLineComments.filter((comment) => comment.cwd === normalizedCwd && comment.tabKey === commentTabKey);
|
|
18768
|
+
const startLineComment = (range) => {
|
|
18769
|
+
if (!onAddDiffLineComment) return;
|
|
18770
|
+
const side = reviewDiffCommentSideFromRange(range);
|
|
18771
|
+
setCommentTarget({
|
|
18772
|
+
commit: "working-tree",
|
|
18773
|
+
lineNumber: reviewDiffCommentLineFromRange(range),
|
|
18774
|
+
mode: "head",
|
|
18775
|
+
path: reviewDiffCommentPath(file, side),
|
|
18776
|
+
shortHash: "working tree",
|
|
18777
|
+
side,
|
|
18778
|
+
tabKey: commentTabKey,
|
|
18779
|
+
tabTitle: "Working tree changes"
|
|
18780
|
+
});
|
|
18781
|
+
};
|
|
18782
|
+
const lineAnnotations = reviewDiffLineCommentAnnotations({
|
|
18783
|
+
comments: commentsForFile,
|
|
18784
|
+
pendingComment: commentTarget ? {
|
|
18785
|
+
...commentTarget,
|
|
18786
|
+
kind: "pending",
|
|
18787
|
+
onCancel: () => setCommentTarget(null),
|
|
18788
|
+
onSubmit: (text) => {
|
|
18789
|
+
onAddDiffLineComment?.({
|
|
18790
|
+
...commentTarget,
|
|
18791
|
+
text
|
|
18792
|
+
});
|
|
18793
|
+
setCommentTarget(null);
|
|
18794
|
+
}
|
|
18795
|
+
} : null
|
|
18796
|
+
});
|
|
18797
|
+
const commentableOptions = onAddDiffLineComment ? {
|
|
18798
|
+
enableGutterUtility: true,
|
|
18799
|
+
onGutterUtilityClick: startLineComment
|
|
18800
|
+
} : {};
|
|
18801
|
+
const themeOptions = usePicoDiffThemeOptions();
|
|
18213
18802
|
const [indexStatus, worktreeStatus] = gitFileStatusCharacters(file.status);
|
|
18214
18803
|
const canStage = worktreeStatus !== " " || indexStatus === "?";
|
|
18215
18804
|
const invalidateChangedFileQueries = async () => {
|
|
@@ -18267,6 +18856,15 @@ function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffStyle, file
|
|
|
18267
18856
|
}
|
|
18268
18857
|
});
|
|
18269
18858
|
const actionPending = stageMutation.isPending || discardMutation.isPending;
|
|
18859
|
+
import_react.useEffect(() => {
|
|
18860
|
+
setCommentTarget(null);
|
|
18861
|
+
}, [
|
|
18862
|
+
value,
|
|
18863
|
+
previewPatch,
|
|
18864
|
+
patch,
|
|
18865
|
+
oldContent,
|
|
18866
|
+
newContent
|
|
18867
|
+
]);
|
|
18270
18868
|
const openFile = (event) => {
|
|
18271
18869
|
event?.stopPropagation();
|
|
18272
18870
|
onOpenFile?.(file.path, { pin: true });
|
|
@@ -18375,9 +18973,13 @@ function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffStyle, file
|
|
|
18375
18973
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PatchDiff, {
|
|
18376
18974
|
patch,
|
|
18377
18975
|
disableWorkerPool: true,
|
|
18976
|
+
lineAnnotations,
|
|
18977
|
+
renderAnnotation: (annotation) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReviewDiffLineAnnotation, { annotation }),
|
|
18378
18978
|
options: {
|
|
18979
|
+
...themeOptions,
|
|
18379
18980
|
diffStyle,
|
|
18380
18981
|
disableFileHeader: true,
|
|
18982
|
+
...commentableOptions,
|
|
18381
18983
|
overflow: "wrap"
|
|
18382
18984
|
}
|
|
18383
18985
|
})] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
@@ -18402,9 +19004,13 @@ function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffStyle, file
|
|
|
18402
19004
|
contents: newContent
|
|
18403
19005
|
},
|
|
18404
19006
|
disableWorkerPool: true,
|
|
19007
|
+
lineAnnotations,
|
|
19008
|
+
renderAnnotation: (annotation) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReviewDiffLineAnnotation, { annotation }),
|
|
18405
19009
|
options: {
|
|
19010
|
+
...themeOptions,
|
|
18406
19011
|
diffStyle,
|
|
18407
19012
|
disableFileHeader: true,
|
|
19013
|
+
...commentableOptions,
|
|
18408
19014
|
overflow: "wrap"
|
|
18409
19015
|
}
|
|
18410
19016
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
@@ -18414,6 +19020,7 @@ function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffStyle, file
|
|
|
18414
19020
|
})]
|
|
18415
19021
|
});
|
|
18416
19022
|
}
|
|
19023
|
+
var EMPTY_RIGHT_SIDEBAR_DIFF_LINE_COMMENTS = [];
|
|
18417
19024
|
var EMPTY_RIGHT_SIDEBAR_FILE_TABS = [];
|
|
18418
19025
|
function readStoredHistoryAsTab() {
|
|
18419
19026
|
return safeLocalStorageGetItem(RIGHT_SIDEBAR_HISTORY_TAB_STORAGE_KEY) === "1";
|
|
@@ -18535,7 +19142,160 @@ function commitFileDiffLineCounts(fileDiff) {
|
|
|
18535
19142
|
deletions: 0
|
|
18536
19143
|
});
|
|
18537
19144
|
}
|
|
18538
|
-
function
|
|
19145
|
+
function commitDiffCommentSideLabel(side) {
|
|
19146
|
+
return side === "deletions" ? "old" : "new";
|
|
19147
|
+
}
|
|
19148
|
+
function commitDiffLineCommentAnnotations({ comments, pendingComment }) {
|
|
19149
|
+
const annotations = comments.map((comment) => ({
|
|
19150
|
+
lineNumber: comment.lineNumber,
|
|
19151
|
+
metadata: comment,
|
|
19152
|
+
side: comment.side
|
|
19153
|
+
}));
|
|
19154
|
+
if (pendingComment) annotations.push({
|
|
19155
|
+
lineNumber: pendingComment.lineNumber,
|
|
19156
|
+
metadata: pendingComment,
|
|
19157
|
+
side: pendingComment.side
|
|
19158
|
+
});
|
|
19159
|
+
return annotations;
|
|
19160
|
+
}
|
|
19161
|
+
function assignClassName(element, className) {
|
|
19162
|
+
for (const classItem of className.split(/\s+/)) if (classItem) element.classList.add(classItem);
|
|
19163
|
+
}
|
|
19164
|
+
function renderPendingCommitDiffLineComment(pendingComment) {
|
|
19165
|
+
const form = document.createElement("form");
|
|
19166
|
+
assignClassName(form, "m-2 w-[min(38rem,calc(100vw_-_5rem))] max-w-[calc(100%_-_1rem)] rounded-lg border border-border/70 bg-background p-2 shadow-sm");
|
|
19167
|
+
const header = document.createElement("div");
|
|
19168
|
+
assignClassName(header, "mb-2 flex min-w-0 items-center justify-between gap-2 text-xs text-muted-foreground");
|
|
19169
|
+
const label = document.createElement("span");
|
|
19170
|
+
label.textContent = `Comment on ${pendingComment.path}:L${pendingComment.lineNumber} (${commitDiffCommentSideLabel(pendingComment.side)})`;
|
|
19171
|
+
assignClassName(label, "min-w-0 truncate");
|
|
19172
|
+
const cancelButton = document.createElement("button");
|
|
19173
|
+
cancelButton.type = "button";
|
|
19174
|
+
cancelButton.textContent = "×";
|
|
19175
|
+
cancelButton.setAttribute("aria-label", "Cancel line comment");
|
|
19176
|
+
assignClassName(cancelButton, "inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground");
|
|
19177
|
+
cancelButton.addEventListener("click", () => pendingComment.onCancel());
|
|
19178
|
+
header.append(label, cancelButton);
|
|
19179
|
+
const textarea = document.createElement("textarea");
|
|
19180
|
+
textarea.rows = 2;
|
|
19181
|
+
textarea.placeholder = "Add a note for the prompt…";
|
|
19182
|
+
assignClassName(textarea, "flex min-h-16 w-full resize-none rounded-lg border border-input bg-transparent px-2.5 py-2 text-sm outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50");
|
|
19183
|
+
textarea.addEventListener("keydown", (event) => {
|
|
19184
|
+
if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
|
|
19185
|
+
event.preventDefault();
|
|
19186
|
+
submit();
|
|
19187
|
+
}
|
|
19188
|
+
if (event.key === "Escape") {
|
|
19189
|
+
event.preventDefault();
|
|
19190
|
+
pendingComment.onCancel();
|
|
19191
|
+
}
|
|
19192
|
+
});
|
|
19193
|
+
const footer = document.createElement("div");
|
|
19194
|
+
assignClassName(footer, "mt-2 flex flex-wrap justify-end gap-2");
|
|
19195
|
+
const secondaryCancelButton = document.createElement("button");
|
|
19196
|
+
secondaryCancelButton.type = "button";
|
|
19197
|
+
secondaryCancelButton.textContent = "Cancel";
|
|
19198
|
+
assignClassName(secondaryCancelButton, "inline-flex h-8 items-center rounded-md px-3 text-sm hover:bg-muted");
|
|
19199
|
+
secondaryCancelButton.addEventListener("click", () => pendingComment.onCancel());
|
|
19200
|
+
const submitButton = document.createElement("button");
|
|
19201
|
+
submitButton.type = "submit";
|
|
19202
|
+
submitButton.textContent = "Add to prompt";
|
|
19203
|
+
assignClassName(submitButton, "inline-flex h-8 items-center rounded-md bg-primary px-3 text-sm font-medium text-primary-foreground disabled:pointer-events-none disabled:opacity-50");
|
|
19204
|
+
function syncSubmitDisabled() {
|
|
19205
|
+
submitButton.disabled = textarea.value.trim().length === 0;
|
|
19206
|
+
}
|
|
19207
|
+
function submit() {
|
|
19208
|
+
const text = textarea.value.trim();
|
|
19209
|
+
if (!text) return;
|
|
19210
|
+
pendingComment.onSubmit(text);
|
|
19211
|
+
}
|
|
19212
|
+
textarea.addEventListener("input", syncSubmitDisabled);
|
|
19213
|
+
form.addEventListener("submit", (event) => {
|
|
19214
|
+
event.preventDefault();
|
|
19215
|
+
submit();
|
|
19216
|
+
});
|
|
19217
|
+
footer.append(secondaryCancelButton, submitButton);
|
|
19218
|
+
form.append(header, textarea, footer);
|
|
19219
|
+
syncSubmitDisabled();
|
|
19220
|
+
window.setTimeout(() => textarea.focus(), 0);
|
|
19221
|
+
return form;
|
|
19222
|
+
}
|
|
19223
|
+
function renderCommitDiffLineAnnotation(annotation) {
|
|
19224
|
+
const comment = annotation.metadata;
|
|
19225
|
+
if (!comment) return void 0;
|
|
19226
|
+
if (comment.kind === "pending") return renderPendingCommitDiffLineComment(comment);
|
|
19227
|
+
const savedComment = comment;
|
|
19228
|
+
const wrapper = document.createElement("div");
|
|
19229
|
+
assignClassName(wrapper, "my-1 ml-2 inline-flex max-w-[min(32rem,calc(100vw_-_5rem),90%)] items-center gap-1 rounded-full border border-amber-500/20 bg-amber-500/10 px-2 py-1 text-[11px] text-amber-800 dark:text-amber-200");
|
|
19230
|
+
const icon = document.createElement("span");
|
|
19231
|
+
icon.textContent = "💬";
|
|
19232
|
+
assignClassName(icon, "shrink-0");
|
|
19233
|
+
const text = document.createElement("span");
|
|
19234
|
+
text.textContent = savedComment.text;
|
|
19235
|
+
assignClassName(text, "truncate");
|
|
19236
|
+
wrapper.append(icon, text);
|
|
19237
|
+
return wrapper;
|
|
19238
|
+
}
|
|
19239
|
+
function CommitDiffFileRenderer({ comments, diffStyle, disableFileHeader = false, fileDiff, onStartComment, pendingComment }) {
|
|
19240
|
+
const [container, setContainer] = import_react.useState(null);
|
|
19241
|
+
const instanceRef = import_react.useRef(null);
|
|
19242
|
+
const lineAnnotations = commitDiffLineCommentAnnotations({
|
|
19243
|
+
comments,
|
|
19244
|
+
pendingComment
|
|
19245
|
+
});
|
|
19246
|
+
const options = {
|
|
19247
|
+
...usePicoDiffThemeOptions(),
|
|
19248
|
+
diffStyle,
|
|
19249
|
+
disableFileHeader,
|
|
19250
|
+
enableGutterUtility: true,
|
|
19251
|
+
lineDiffType: "word-alt",
|
|
19252
|
+
lineHoverHighlight: "both",
|
|
19253
|
+
maxLineDiffLength: 1e3,
|
|
19254
|
+
onGutterUtilityClick: (range) => {
|
|
19255
|
+
onStartComment({
|
|
19256
|
+
lineNumber: Math.min(range.start, range.end),
|
|
19257
|
+
path: fileDiff.name,
|
|
19258
|
+
side: range.side || range.endSide || "additions"
|
|
19259
|
+
});
|
|
19260
|
+
},
|
|
19261
|
+
onLineNumberClick: (props) => {
|
|
19262
|
+
onStartComment({
|
|
19263
|
+
lineNumber: props.lineNumber,
|
|
19264
|
+
path: fileDiff.name,
|
|
19265
|
+
side: props.annotationSide
|
|
19266
|
+
});
|
|
19267
|
+
},
|
|
19268
|
+
overflow: "wrap",
|
|
19269
|
+
renderAnnotation: renderCommitDiffLineAnnotation
|
|
19270
|
+
};
|
|
19271
|
+
import_react.useLayoutEffect(() => {
|
|
19272
|
+
if (!container) return;
|
|
19273
|
+
const existing = instanceRef.current;
|
|
19274
|
+
if (existing) {
|
|
19275
|
+
existing.setOptions(options);
|
|
19276
|
+
existing.render({
|
|
19277
|
+
containerWrapper: container,
|
|
19278
|
+
fileDiff,
|
|
19279
|
+
forceRender: true,
|
|
19280
|
+
lineAnnotations
|
|
19281
|
+
});
|
|
19282
|
+
return;
|
|
19283
|
+
}
|
|
19284
|
+
const instance = new FileDiff$1(options, void 0, false);
|
|
19285
|
+
instanceRef.current = instance;
|
|
19286
|
+
instance.render({
|
|
19287
|
+
containerWrapper: container,
|
|
19288
|
+
fileDiff,
|
|
19289
|
+
lineAnnotations
|
|
19290
|
+
});
|
|
19291
|
+
});
|
|
19292
|
+
import_react.useLayoutEffect(() => () => {
|
|
19293
|
+
instanceRef.current?.cleanUp();
|
|
19294
|
+
instanceRef.current = null;
|
|
19295
|
+
}, []);
|
|
19296
|
+
return import_react.createElement("div", { ref: setContainer });
|
|
19297
|
+
}
|
|
19298
|
+
function CommitFileDiffAccordionItem({ comments, diffStyle, fileDiff, index, onStartComment, pendingComment, stuck }) {
|
|
18539
19299
|
const value = commitFileDiffValue(fileDiff, index);
|
|
18540
19300
|
const counts = commitFileDiffLineCounts(fileDiff);
|
|
18541
19301
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AccordionItem, {
|
|
@@ -18586,21 +19346,18 @@ function CommitFileDiffAccordionItem({ diffStyle, fileDiff, index, stuck }) {
|
|
|
18586
19346
|
})
|
|
18587
19347
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionContent, {
|
|
18588
19348
|
className: "bg-background p-0",
|
|
18589
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
19349
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitDiffFileRenderer, {
|
|
19350
|
+
comments,
|
|
19351
|
+
diffStyle,
|
|
19352
|
+
disableFileHeader: true,
|
|
18590
19353
|
fileDiff,
|
|
18591
|
-
|
|
18592
|
-
|
|
18593
|
-
diffStyle,
|
|
18594
|
-
disableFileHeader: true,
|
|
18595
|
-
lineDiffType: "word-alt",
|
|
18596
|
-
maxLineDiffLength: 1e3,
|
|
18597
|
-
overflow: "wrap"
|
|
18598
|
-
}
|
|
19354
|
+
onStartComment,
|
|
19355
|
+
pendingComment
|
|
18599
19356
|
})
|
|
18600
19357
|
})]
|
|
18601
19358
|
});
|
|
18602
19359
|
}
|
|
18603
|
-
function CommitSingleFileDiff({ diffStyle, patch }) {
|
|
19360
|
+
function CommitSingleFileDiff({ comments, diffStyle, onStartComment, patch, pendingComment }) {
|
|
18604
19361
|
const fileDiff = parsePatchFiles(patch).flatMap((parsed) => parsed.files)[0];
|
|
18605
19362
|
if (!fileDiff) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
18606
19363
|
className: "p-4",
|
|
@@ -18609,19 +19366,16 @@ function CommitSingleFileDiff({ diffStyle, patch }) {
|
|
|
18609
19366
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
18610
19367
|
className: "min-h-full text-xs",
|
|
18611
19368
|
style: { "--diffs-font-family": "var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace)" },
|
|
18612
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
19369
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitDiffFileRenderer, {
|
|
19370
|
+
comments,
|
|
19371
|
+
diffStyle,
|
|
18613
19372
|
fileDiff,
|
|
18614
|
-
|
|
18615
|
-
|
|
18616
|
-
diffStyle,
|
|
18617
|
-
lineDiffType: "word-alt",
|
|
18618
|
-
maxLineDiffLength: 1e3,
|
|
18619
|
-
overflow: "wrap"
|
|
18620
|
-
}
|
|
19373
|
+
onStartComment,
|
|
19374
|
+
pendingComment
|
|
18621
19375
|
})
|
|
18622
19376
|
});
|
|
18623
19377
|
}
|
|
18624
|
-
function CommitPatchDiffs({ diffStyle, patch, stuckFileValue }) {
|
|
19378
|
+
function CommitPatchDiffs({ comments, diffStyle, onStartComment, patch, pendingComment, stuckFileValue }) {
|
|
18625
19379
|
const fileDiffs = parsePatchFiles(patch).flatMap((parsed) => parsed.files);
|
|
18626
19380
|
const firstValue = fileDiffs[0] ? commitFileDiffValue(fileDiffs[0], 0) : void 0;
|
|
18627
19381
|
if (fileDiffs.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
@@ -18636,9 +19390,12 @@ function CommitPatchDiffs({ diffStyle, patch, stuckFileValue }) {
|
|
|
18636
19390
|
defaultValue: firstValue ? [firstValue] : [],
|
|
18637
19391
|
className: "border-b border-border/80",
|
|
18638
19392
|
children: fileDiffs.map((fileDiff, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitFileDiffAccordionItem, {
|
|
19393
|
+
comments: comments.filter((comment) => comment.path === fileDiff.name),
|
|
18639
19394
|
diffStyle,
|
|
18640
19395
|
fileDiff,
|
|
18641
19396
|
index,
|
|
19397
|
+
onStartComment,
|
|
19398
|
+
pendingComment: pendingComment?.path === fileDiff.name ? pendingComment : null,
|
|
18642
19399
|
stuck: stuckFileValue === commitFileDiffValue(fileDiff, index)
|
|
18643
19400
|
}, commitFileDiffValue(fileDiff, index)))
|
|
18644
19401
|
})
|
|
@@ -18684,9 +19441,10 @@ function CommitDiffHeaderTitle({ tab }) {
|
|
|
18684
19441
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitDiffPathBreadcrumb, { path: tab.path })
|
|
18685
19442
|
});
|
|
18686
19443
|
}
|
|
18687
|
-
function CommitDiffContent({ viewerContextId, cwd, active, tab }) {
|
|
19444
|
+
function CommitDiffContent({ viewerContextId, cwd, active, diffLineComments, onAddDiffLineComment, tab }) {
|
|
18688
19445
|
const [diffStyle, setDiffStyle] = import_react.useState("unified");
|
|
18689
19446
|
const [stickyCommitFileValue, setStickyCommitFileValue] = import_react.useState("");
|
|
19447
|
+
const [commentTarget, setCommentTarget] = import_react.useState(null);
|
|
18690
19448
|
const diffScrollRef = import_react.useRef(null);
|
|
18691
19449
|
const updateStickyCommitFileHeader = (scrollElement) => {
|
|
18692
19450
|
setDerivedScrollState(setStickyCommitFileValue, getStuckScrollTriggerValue({
|
|
@@ -18712,7 +19470,34 @@ function CommitDiffContent({ viewerContextId, cwd, active, tab }) {
|
|
|
18712
19470
|
"error"
|
|
18713
19471
|
]
|
|
18714
19472
|
});
|
|
19473
|
+
const commentsForTab = tab ? diffLineComments.filter((comment) => comment.tabKey === tab.key && comment.commit === tab.commit && comment.mode === tab.mode) : EMPTY_RIGHT_SIDEBAR_DIFF_LINE_COMMENTS;
|
|
19474
|
+
const startLineComment = (lineTarget) => {
|
|
19475
|
+
if (!tab || !onAddDiffLineComment) return;
|
|
19476
|
+
setCommentTarget({
|
|
19477
|
+
commit: tab.commit,
|
|
19478
|
+
lineNumber: lineTarget.lineNumber,
|
|
19479
|
+
mode: tab.mode,
|
|
19480
|
+
path: lineTarget.path,
|
|
19481
|
+
shortHash: tab.shortHash,
|
|
19482
|
+
side: lineTarget.side,
|
|
19483
|
+
tabKey: tab.key,
|
|
19484
|
+
tabTitle: tab.title
|
|
19485
|
+
});
|
|
19486
|
+
};
|
|
19487
|
+
const pendingComment = commentTarget ? {
|
|
19488
|
+
...commentTarget,
|
|
19489
|
+
kind: "pending",
|
|
19490
|
+
onCancel: () => setCommentTarget(null),
|
|
19491
|
+
onSubmit: (text) => {
|
|
19492
|
+
onAddDiffLineComment?.({
|
|
19493
|
+
...commentTarget,
|
|
19494
|
+
text
|
|
19495
|
+
});
|
|
19496
|
+
setCommentTarget(null);
|
|
19497
|
+
}
|
|
19498
|
+
} : null;
|
|
18715
19499
|
import_react.useEffect(() => {
|
|
19500
|
+
setCommentTarget(null);
|
|
18716
19501
|
setDerivedScrollState(setStickyCommitFileValue, "");
|
|
18717
19502
|
updateStickyCommitFileHeader(diffScrollRef.current);
|
|
18718
19503
|
}, [tab?.key, diffQuery.data?.patch]);
|
|
@@ -18755,11 +19540,20 @@ function CommitDiffContent({ viewerContextId, cwd, active, tab }) {
|
|
|
18755
19540
|
children: getErrorMessage(diffQuery.error, "Failed to load commit diff")
|
|
18756
19541
|
})
|
|
18757
19542
|
}) : diffQuery.data?.patch && tab.path ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitSingleFileDiff, {
|
|
19543
|
+
comments: commentsForTab.filter((comment) => {
|
|
19544
|
+
if (!tab.path) return true;
|
|
19545
|
+
return comment.path === tab.path || comment.path === tab.previousPath;
|
|
19546
|
+
}),
|
|
18758
19547
|
diffStyle,
|
|
18759
|
-
|
|
19548
|
+
onStartComment: startLineComment,
|
|
19549
|
+
patch: diffQuery.data.patch,
|
|
19550
|
+
pendingComment
|
|
18760
19551
|
}) : diffQuery.data?.patch ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitPatchDiffs, {
|
|
19552
|
+
comments: commentsForTab,
|
|
18761
19553
|
diffStyle,
|
|
19554
|
+
onStartComment: startLineComment,
|
|
18762
19555
|
patch: diffQuery.data.patch,
|
|
19556
|
+
pendingComment,
|
|
18763
19557
|
stuckFileValue: stickyCommitFileValue
|
|
18764
19558
|
}, `${diffQuery.data.commit}:${diffQuery.data.mode}`) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
18765
19559
|
className: "p-4",
|
|
@@ -18768,7 +19562,7 @@ function CommitDiffContent({ viewerContextId, cwd, active, tab }) {
|
|
|
18768
19562
|
})]
|
|
18769
19563
|
});
|
|
18770
19564
|
}
|
|
18771
|
-
function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activeTab: controlledActiveTab, filePreviewPath = "", fileTabs = EMPTY_RIGHT_SIDEBAR_FILE_TABS, fileTreeCollapsed = false, onActiveFileChange, onActiveTabChange, onCloseAllFiles, onCloseFile, onCloseFilesToRight, onCloseOtherFiles, onFileTreeCollapsedChange, onOpenFile, onReorderFiles, showToolbar = true }) {
|
|
19565
|
+
function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activeTab: controlledActiveTab, diffLineComments = EMPTY_RIGHT_SIDEBAR_DIFF_LINE_COMMENTS, filePreviewPath = "", fileTabs = EMPTY_RIGHT_SIDEBAR_FILE_TABS, fileTreeCollapsed = false, onActiveFileChange, onActiveTabChange, onAddDiffLineComment, onCloseAllFiles, onCloseFile, onCloseFilesToRight, onCloseOtherFiles, onFileTreeCollapsedChange, onOpenFile, onReorderFiles, showToolbar = true }) {
|
|
18772
19566
|
const normalizedCwd = normalizeCwd(cwd);
|
|
18773
19567
|
const isMobile = useIsMobile();
|
|
18774
19568
|
const [localState, dispatchLocal] = import_react.useReducer(rightSidebarLocalReducer, initialRightSidebarLocalState);
|
|
@@ -18912,96 +19706,88 @@ function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activ
|
|
|
18912
19706
|
showHistory: historyAsTab,
|
|
18913
19707
|
showReview: true
|
|
18914
19708
|
}),
|
|
18915
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
18916
|
-
|
|
18917
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
18918
|
-
|
|
18919
|
-
|
|
18920
|
-
|
|
18921
|
-
|
|
18922
|
-
|
|
18923
|
-
|
|
18924
|
-
|
|
18925
|
-
|
|
18926
|
-
|
|
18927
|
-
|
|
18928
|
-
|
|
18929
|
-
|
|
18930
|
-
})
|
|
19709
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
19710
|
+
className: activeTab === "review" ? "min-h-0 flex-1 overflow-hidden" : "hidden",
|
|
19711
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileReviewContent, {
|
|
19712
|
+
viewerContextId,
|
|
19713
|
+
cwd: normalizedCwd,
|
|
19714
|
+
active: active && activeTab === "review",
|
|
19715
|
+
diffLineComments,
|
|
19716
|
+
onMaximizeHistory: () => {
|
|
19717
|
+
setHistoryAsTab(true);
|
|
19718
|
+
setActiveTab("history");
|
|
19719
|
+
},
|
|
19720
|
+
onAddDiffLineComment,
|
|
19721
|
+
onOpenCommitDiff: openCommitDiff,
|
|
19722
|
+
onOpenFile: openFile,
|
|
19723
|
+
showEmbeddedHistory: !historyAsTab
|
|
18931
19724
|
})
|
|
18932
19725
|
}),
|
|
18933
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
18934
|
-
|
|
18935
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
18936
|
-
|
|
18937
|
-
|
|
18938
|
-
|
|
18939
|
-
|
|
18940
|
-
|
|
18941
|
-
|
|
18942
|
-
|
|
18943
|
-
|
|
18944
|
-
|
|
18945
|
-
setActiveTab("review");
|
|
18946
|
-
}
|
|
18947
|
-
})
|
|
19726
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
19727
|
+
className: activeTab === "history" ? "min-h-0 flex-1 overflow-hidden" : "hidden",
|
|
19728
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitCommitsSection, {
|
|
19729
|
+
viewerContextId,
|
|
19730
|
+
cwd: normalizedCwd,
|
|
19731
|
+
active: active && activeTab === "history",
|
|
19732
|
+
flush: true,
|
|
19733
|
+
onOpenCommitDiff: openCommitDiff,
|
|
19734
|
+
onRestoreEmbedded: () => {
|
|
19735
|
+
setHistoryAsTab(false);
|
|
19736
|
+
setActiveTab("review");
|
|
19737
|
+
}
|
|
18948
19738
|
})
|
|
18949
19739
|
}),
|
|
18950
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
18951
|
-
|
|
18952
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
18953
|
-
|
|
18954
|
-
|
|
18955
|
-
|
|
18956
|
-
|
|
18957
|
-
|
|
18958
|
-
|
|
18959
|
-
})
|
|
19740
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
19741
|
+
className: activeTab === "commit-diff" ? "min-h-0 flex-1 overflow-hidden" : "hidden",
|
|
19742
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitDiffContent, {
|
|
19743
|
+
viewerContextId,
|
|
19744
|
+
cwd: normalizedCwd,
|
|
19745
|
+
active: active && activeTab === "commit-diff",
|
|
19746
|
+
diffLineComments,
|
|
19747
|
+
onAddDiffLineComment,
|
|
19748
|
+
tab: activeCommitDiffTab
|
|
18960
19749
|
})
|
|
18961
19750
|
}),
|
|
18962
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
18963
|
-
|
|
18964
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.
|
|
18965
|
-
className: "min-h-0 flex-
|
|
18966
|
-
children:
|
|
18967
|
-
|
|
18968
|
-
|
|
18969
|
-
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
18973
|
-
|
|
18974
|
-
|
|
19751
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
19752
|
+
className: activeTab === "files" ? "min-h-0 flex-1 overflow-hidden" : "hidden",
|
|
19753
|
+
children: previewMode === "external" && hasOpenFileTabs ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
19754
|
+
className: "flex h-full min-h-0 min-w-0 flex-col overflow-hidden",
|
|
19755
|
+
children: [currentFilePath ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FilePathBreadcrumb, {
|
|
19756
|
+
path: currentFilePath,
|
|
19757
|
+
fileTreeCollapsed,
|
|
19758
|
+
onFileTreeCollapsedChange
|
|
19759
|
+
}) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
19760
|
+
className: "flex min-h-0 flex-1 overflow-hidden",
|
|
19761
|
+
children: [fileTreeCollapsed ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectFileTreePane, {
|
|
19762
|
+
viewerContextId,
|
|
19763
|
+
cwd: normalizedCwd,
|
|
19764
|
+
active: active && activeTab === "files",
|
|
19765
|
+
activeFilePath: currentFilePath,
|
|
19766
|
+
onOpenFile: openFile,
|
|
19767
|
+
previewMode
|
|
19768
|
+
}), currentFilePath ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
19769
|
+
className: "min-h-0 min-w-0 flex-1 overflow-hidden",
|
|
19770
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectFileContent, {
|
|
18975
19771
|
viewerContextId,
|
|
18976
19772
|
cwd: normalizedCwd,
|
|
18977
19773
|
active: active && activeTab === "files",
|
|
18978
|
-
|
|
18979
|
-
|
|
18980
|
-
|
|
18981
|
-
|
|
18982
|
-
|
|
18983
|
-
|
|
18984
|
-
|
|
18985
|
-
|
|
18986
|
-
|
|
18987
|
-
|
|
18988
|
-
|
|
18989
|
-
|
|
18990
|
-
|
|
18991
|
-
|
|
18992
|
-
|
|
18993
|
-
|
|
18994
|
-
|
|
18995
|
-
activeFilePath: currentFilePath,
|
|
18996
|
-
onCloseFile: () => {
|
|
18997
|
-
dispatchLocal({
|
|
18998
|
-
type: "set-inline-active-file",
|
|
18999
|
-
path: ""
|
|
19000
|
-
});
|
|
19001
|
-
},
|
|
19002
|
-
onOpenFile: openFile,
|
|
19003
|
-
previewMode
|
|
19004
|
-
})
|
|
19774
|
+
path: currentFilePath
|
|
19775
|
+
})
|
|
19776
|
+
}) : null]
|
|
19777
|
+
})]
|
|
19778
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectFilesWorkspace, {
|
|
19779
|
+
viewerContextId,
|
|
19780
|
+
cwd: normalizedCwd,
|
|
19781
|
+
active: active && activeTab === "files",
|
|
19782
|
+
activeFilePath: currentFilePath,
|
|
19783
|
+
onCloseFile: () => {
|
|
19784
|
+
dispatchLocal({
|
|
19785
|
+
type: "set-inline-active-file",
|
|
19786
|
+
path: ""
|
|
19787
|
+
});
|
|
19788
|
+
},
|
|
19789
|
+
onOpenFile: openFile,
|
|
19790
|
+
previewMode
|
|
19005
19791
|
})
|
|
19006
19792
|
}),
|
|
19007
19793
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectOpenFileDialog, {
|
|
@@ -19151,13 +19937,14 @@ function AppShellTabsList({ sessionStore, viewerContextId }) {
|
|
|
19151
19937
|
})]
|
|
19152
19938
|
});
|
|
19153
19939
|
}
|
|
19154
|
-
var AppShellGitPanelController = import_react.memo(function AppShellGitPanelController({ active, onCloseAllFiles, onCloseFile, onCloseFilesToRight, onCloseOtherFiles, onOpenFile, onReorderFiles, rightSidebarStore, sessionStore, viewerContextId }) {
|
|
19940
|
+
var AppShellGitPanelController = import_react.memo(function AppShellGitPanelController({ active, composerDiffLineComments, onAddDiffLineComment, onCloseAllFiles, onCloseFile, onCloseFilesToRight, onCloseOtherFiles, onOpenFile, onReorderFiles, rightSidebarStore, sessionStore, viewerContextId }) {
|
|
19155
19941
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RightSidebar, {
|
|
19156
19942
|
viewerContextId,
|
|
19157
19943
|
cwd: useSelector(sessionStore, (sessionState) => sessionState.cwd),
|
|
19158
19944
|
active,
|
|
19159
19945
|
activeFilePath: useSelector(rightSidebarStore, (state) => state.fileActivePath),
|
|
19160
19946
|
activeTab: useSelector(rightSidebarStore, (state) => state.activeTab),
|
|
19947
|
+
diffLineComments: composerDiffLineComments,
|
|
19161
19948
|
filePreviewPath: useSelector(rightSidebarStore, (state) => state.filePreviewPath),
|
|
19162
19949
|
fileTabs: useSelector(rightSidebarStore, selectRightSidebarVisibleFileTabs, { compare: sameStringArray$3 }),
|
|
19163
19950
|
fileTreeCollapsed: useSelector(rightSidebarStore, (state) => state.fileTreeCollapsed),
|
|
@@ -19167,6 +19954,7 @@ var AppShellGitPanelController = import_react.memo(function AppShellGitPanelCont
|
|
|
19167
19954
|
onActiveTabChange: (tab) => {
|
|
19168
19955
|
setRightSidebarActiveTab(rightSidebarStore, tab);
|
|
19169
19956
|
},
|
|
19957
|
+
onAddDiffLineComment,
|
|
19170
19958
|
onCloseAllFiles,
|
|
19171
19959
|
onCloseFile,
|
|
19172
19960
|
onCloseFilesToRight,
|
|
@@ -19178,7 +19966,7 @@ var AppShellGitPanelController = import_react.memo(function AppShellGitPanelCont
|
|
|
19178
19966
|
onReorderFiles
|
|
19179
19967
|
});
|
|
19180
19968
|
});
|
|
19181
|
-
function AppShellDesktopGitPanel({ active, onCloseAllFiles, onCloseFile, onCloseFilesToRight, onCloseOtherFiles, onOpenFile, onReorderFiles, rightSidebarStore, sessionStore, viewerContextId }) {
|
|
19969
|
+
function AppShellDesktopGitPanel({ active, composerDiffLineComments, onAddDiffLineComment, onCloseAllFiles, onCloseFile, onCloseFilesToRight, onCloseOtherFiles, onOpenFile, onReorderFiles, rightSidebarStore, sessionStore, viewerContextId }) {
|
|
19182
19970
|
const cwd = useSelector(sessionStore, (sessionState) => sessionState.cwd);
|
|
19183
19971
|
const activeFilePath = useSelector(rightSidebarStore, (state) => state.fileActivePath);
|
|
19184
19972
|
const activeTab = useSelector(rightSidebarStore, (state) => state.activeTab);
|
|
@@ -19196,6 +19984,7 @@ function AppShellDesktopGitPanel({ active, onCloseAllFiles, onCloseFile, onClose
|
|
|
19196
19984
|
active,
|
|
19197
19985
|
activeFilePath,
|
|
19198
19986
|
activeTab,
|
|
19987
|
+
diffLineComments: composerDiffLineComments,
|
|
19199
19988
|
filePreviewPath,
|
|
19200
19989
|
fileTabs,
|
|
19201
19990
|
fileTreeCollapsed,
|
|
@@ -19205,6 +19994,7 @@ function AppShellDesktopGitPanel({ active, onCloseAllFiles, onCloseFile, onClose
|
|
|
19205
19994
|
onActiveTabChange: (tab) => {
|
|
19206
19995
|
setRightSidebarActiveTab(rightSidebarStore, tab);
|
|
19207
19996
|
},
|
|
19997
|
+
onAddDiffLineComment,
|
|
19208
19998
|
onCloseAllFiles,
|
|
19209
19999
|
onCloseFile,
|
|
19210
20000
|
onCloseFilesToRight,
|
|
@@ -19383,7 +20173,7 @@ function AppShellDesktopResizeHandle({ label, max, min, onResize, onResizeEnd, o
|
|
|
19383
20173
|
function AppShellTabsController(props) {
|
|
19384
20174
|
return useAppShellTabsControllerView(props);
|
|
19385
20175
|
}
|
|
19386
|
-
function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTurn, composerPanelRef, contextUsageStore, conversationFrameRef, conversationItemsStore, defaultNewSessionDirectory, displaySettingsStore, fileInputRef, gitPanelOpen, hiddenThinkingPreviewStore, isSessionViewLoading, isSubmitting, isMobile, newSessionDirectoryOptions, onCancelCompaction, onCreateSession, onOpenAddDirectoryDialog, onCloseAllFileViewTabs, onCloseFileViewTab, onCloseFileViewTabsToRight, onCloseOtherFileViewTabs, onOpenFileViewTab, onReorderFileViewTabs, onValueChange, rightSidebarStore, sessionStore, store, viewerContextId, workingStateStore }) {
|
|
20176
|
+
function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTurn, composerDiffLineComments, composerPanelRef, contextUsageStore, conversationFrameRef, conversationItemsStore, defaultNewSessionDirectory, displaySettingsStore, fileInputRef, gitPanelOpen, hiddenThinkingPreviewStore, isSessionViewLoading, isSubmitting, isMobile, newSessionDirectoryOptions, onCancelCompaction, onCreateSession, onOpenAddDirectoryDialog, onCloseAllFileViewTabs, onCloseFileViewTab, onCloseFileViewTabsToRight, onCloseOtherFileViewTabs, onAddDiffLineComment, onOpenFileViewTab, onReorderFileViewTabs, onValueChange, rightSidebarStore, sessionStore, store, viewerContextId, workingStateStore }) {
|
|
19387
20177
|
const currentTab = useSelector(appUiStore, (state) => state.currentTab);
|
|
19388
20178
|
const isDraftSession = useSelector(sessionStore, (sessionState) => sessionState.draft);
|
|
19389
20179
|
const showTabsList = isMobile || !isDraftSession || isSessionViewLoading;
|
|
@@ -19461,7 +20251,9 @@ function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTu
|
|
|
19461
20251
|
viewerContextId,
|
|
19462
20252
|
sessionStore,
|
|
19463
20253
|
active: currentTab === "git",
|
|
20254
|
+
composerDiffLineComments,
|
|
19464
20255
|
rightSidebarStore,
|
|
20256
|
+
onAddDiffLineComment,
|
|
19465
20257
|
onCloseAllFiles: onCloseAllFileViewTabs,
|
|
19466
20258
|
onCloseFile: onCloseFileViewTab,
|
|
19467
20259
|
onCloseFilesToRight: onCloseFileViewTabsToRight,
|
|
@@ -19564,7 +20356,9 @@ function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTu
|
|
|
19564
20356
|
viewerContextId,
|
|
19565
20357
|
sessionStore,
|
|
19566
20358
|
active: desktopGitPanelOpen,
|
|
20359
|
+
composerDiffLineComments,
|
|
19567
20360
|
rightSidebarStore,
|
|
20361
|
+
onAddDiffLineComment,
|
|
19568
20362
|
onCloseAllFiles: onCloseAllFileViewTabs,
|
|
19569
20363
|
onCloseFile: onCloseFileViewTab,
|
|
19570
20364
|
onCloseFilesToRight: onCloseFileViewTabsToRight,
|
|
@@ -20089,10 +20883,11 @@ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionSto
|
|
|
20089
20883
|
const pinnedDirectoryLabel = isPinned ? formatDisplayPath$1(entry.cwd?.trim() || entry.path?.trim() || "") : "";
|
|
20090
20884
|
const exactTimestamp = hasTimestamp && timestamp ? new Date(timestamp).toLocaleString() : void 0;
|
|
20091
20885
|
const showUnread = Boolean(entry.unread) && !entry.streaming;
|
|
20886
|
+
const isOptimisticSession = Boolean(entry.optimistic || entry.id?.startsWith("optimistic:") && !entry.path);
|
|
20092
20887
|
const availableMoveTargetDirectories = moveTargetDirectories.filter((directory) => directory && directory !== entry.cwd);
|
|
20093
20888
|
const canMoveAnyDirectory = Boolean(entry.path && onMoveSessionAnyDirectory);
|
|
20094
20889
|
const hasMoveActions = Boolean(entry.path && onMoveSession) && availableMoveTargetDirectories.length > 0 || canMoveAnyDirectory;
|
|
20095
|
-
const hasSessionActions = Boolean(onTogglePinnedSession || entry.path && (onRenameSession || onDeleteSession || onSetSessionUnread) || hasMoveActions) && !overlay;
|
|
20890
|
+
const hasSessionActions = Boolean(!isOptimisticSession && onTogglePinnedSession || entry.path && (onRenameSession || onDeleteSession || onSetSessionUnread) || hasMoveActions) && !overlay;
|
|
20096
20891
|
const sessionButton = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SidebarMenuButton, {
|
|
20097
20892
|
type: "button",
|
|
20098
20893
|
"data-sidebar-session-item": true,
|
|
@@ -20165,7 +20960,7 @@ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionSto
|
|
|
20165
20960
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarMenuItem, { children: hasSessionActions ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenu$1, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuTrigger, { render: sessionRow }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuContent, {
|
|
20166
20961
|
className: "w-44",
|
|
20167
20962
|
children: [
|
|
20168
|
-
onTogglePinnedSession ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuItem, {
|
|
20963
|
+
onTogglePinnedSession && !isOptimisticSession ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuItem, {
|
|
20169
20964
|
onClick: () => onTogglePinnedSession(entry),
|
|
20170
20965
|
children: isPinned ? "Unpin" : "Pin to sidebar"
|
|
20171
20966
|
}) : null,
|
|
@@ -20201,7 +20996,7 @@ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionSto
|
|
|
20201
20996
|
function sameDirectorySessionEntry(left, right) {
|
|
20202
20997
|
if (left === right) return true;
|
|
20203
20998
|
if (!left || !right) return false;
|
|
20204
|
-
return left.path === right.path && left.id === right.id && left.cwd === right.cwd && left.name === right.name && left.title === right.title && left.modified === right.modified && left.lastUserMessageAt === right.lastUserMessageAt && left.lastMessageAt === right.lastMessageAt && left.lastMessagePreview === right.lastMessagePreview && left.messageCount === right.messageCount && JSON.stringify(left.contextUsage ?? null) === JSON.stringify(right.contextUsage ?? null) && Boolean(left.streaming) === Boolean(right.streaming) && Boolean(left.unread) === Boolean(right.unread);
|
|
20999
|
+
return left.path === right.path && left.id === right.id && left.cwd === right.cwd && left.name === right.name && left.title === right.title && left.modified === right.modified && left.lastUserMessageAt === right.lastUserMessageAt && left.lastMessageAt === right.lastMessageAt && left.lastMessagePreview === right.lastMessagePreview && left.messageCount === right.messageCount && JSON.stringify(left.contextUsage ?? null) === JSON.stringify(right.contextUsage ?? null) && Boolean(left.streaming) === Boolean(right.streaming) && Boolean(left.unread) === Boolean(right.unread) && Boolean(left.optimistic) === Boolean(right.optimistic);
|
|
20205
21000
|
}
|
|
20206
21001
|
function buildDirectorySessionEntryMap(sessionsByDirectory) {
|
|
20207
21002
|
const entriesByKey = /* @__PURE__ */ new Map();
|
|
@@ -20259,7 +21054,7 @@ function useDirectorySessions(store, directory) {
|
|
|
20259
21054
|
function useDirectorySessionEntry(store, entryKey) {
|
|
20260
21055
|
return useSelector(store, (state) => state.entriesByKey.get(entryKey), { compare: sameDirectorySessionEntry });
|
|
20261
21056
|
}
|
|
20262
|
-
var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ directory, directorySessionsStore, collapsedDirectoryStore, searchActive,
|
|
21057
|
+
var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ directory, directorySessionsStore, collapsedDirectoryStore, searchActive, moveTargetDirectories, activeSessionStore, selectedSessionKeyStore, pinnedSessionKeys, isMobile, setOpenMobile, isDragging, isSessionDropTarget, overlay = false, attributes, listeners, onSessionClick, onRenameSession, onDeleteSession, onSetSessionUnread, onMoveSession, onMoveSessionAnyDirectory, onTogglePinnedSession, onCreateSessionInDirectory, onDeleteOldSessionsInDirectory, onRemoveDirectory }) {
|
|
20263
21058
|
const [renderCount, setRenderCount] = import_react.useState(5);
|
|
20264
21059
|
const { isLoadingSessions, sessionKeys } = useDirectorySessions(directorySessionsStore, directory);
|
|
20265
21060
|
const collapsed = useDirectoryCollapsed(collapsedDirectoryStore, directory, searchActive);
|
|
@@ -20277,7 +21072,7 @@ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ d
|
|
|
20277
21072
|
children: [
|
|
20278
21073
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CollapsibleTrigger, {
|
|
20279
21074
|
type: "button",
|
|
20280
|
-
className: cn("group/directory-label flex min-w-0 flex-1 items-center gap-2 text-left text-sm text-sidebar-foreground"
|
|
21075
|
+
className: cn("group/directory-label flex min-w-0 flex-1 cursor-default items-center gap-2 text-left text-sm text-sidebar-foreground"),
|
|
20281
21076
|
disabled: searchActive || overlay,
|
|
20282
21077
|
...attributes ?? {},
|
|
20283
21078
|
...listeners ?? {},
|
|
@@ -20724,7 +21519,6 @@ function useAppSidebarView({ sessionSearch, onOpenSessionsDialog, visibleDirecto
|
|
|
20724
21519
|
directorySessionsStore,
|
|
20725
21520
|
collapsedDirectoryStore,
|
|
20726
21521
|
searchActive,
|
|
20727
|
-
directoryOrderingEnabled,
|
|
20728
21522
|
moveTargetDirectories: visibleDirectories,
|
|
20729
21523
|
activeSessionStore,
|
|
20730
21524
|
selectedSessionKeyStore,
|
|
@@ -20756,7 +21550,6 @@ function useAppSidebarView({ sessionSearch, onOpenSessionsDialog, visibleDirecto
|
|
|
20756
21550
|
directorySessionsStore,
|
|
20757
21551
|
collapsedDirectoryStore,
|
|
20758
21552
|
searchActive,
|
|
20759
|
-
directoryOrderingEnabled,
|
|
20760
21553
|
moveTargetDirectories: visibleDirectories,
|
|
20761
21554
|
activeSessionStore,
|
|
20762
21555
|
selectedSessionKeyStore,
|
|
@@ -21004,7 +21797,7 @@ function useAppShellSidebarControllerView({ viewerContextId, sidebarStore, sessi
|
|
|
21004
21797
|
return indexData ? [[directory, indexData]] : [];
|
|
21005
21798
|
}));
|
|
21006
21799
|
sidebarStore.setSidebarState((current) => {
|
|
21007
|
-
const nextDirectoryIndexDataByPath = Object.keys(activeDirectoryIndexes).length > 0 ?
|
|
21800
|
+
const nextDirectoryIndexDataByPath = Object.keys(activeDirectoryIndexes).length > 0 ? mergeDirectoryIndexDataPreservingOptimistic(current.directoryIndexDataByPath, activeDirectoryIndexes) : current.directoryIndexDataByPath;
|
|
21008
21801
|
const nextDirectoryIndexLoading = updateDirectoryIndexLoadingState(current.directoryIndexLoading, activeDirectories, false);
|
|
21009
21802
|
if (nextDirectoryIndexDataByPath === current.directoryIndexDataByPath && nextDirectoryIndexLoading === current.directoryIndexLoading) return current;
|
|
21010
21803
|
return {
|
|
@@ -21094,7 +21887,7 @@ function useAppShellSidebarControllerView({ viewerContextId, sidebarStore, sessi
|
|
|
21094
21887
|
return indexData ? [[directory, indexData]] : [];
|
|
21095
21888
|
}));
|
|
21096
21889
|
sidebarStore.setSidebarState((current) => {
|
|
21097
|
-
const nextDirectoryIndexDataByPath = Object.keys(activeDirectoryIndexes).length > 0 ?
|
|
21890
|
+
const nextDirectoryIndexDataByPath = Object.keys(activeDirectoryIndexes).length > 0 ? mergeDirectoryIndexDataPreservingOptimistic(current.directoryIndexDataByPath, activeDirectoryIndexes) : current.directoryIndexDataByPath;
|
|
21098
21891
|
const nextDirectoryIndexLoading = updateDirectoryIndexLoadingState(current.directoryIndexLoading, activeDirectories, false);
|
|
21099
21892
|
if (nextDirectoryIndexDataByPath === current.directoryIndexDataByPath && nextDirectoryIndexLoading === current.directoryIndexLoading) return current;
|
|
21100
21893
|
return {
|
|
@@ -21185,7 +21978,7 @@ function useAppShellSidebarControllerView({ viewerContextId, sidebarStore, sessi
|
|
|
21185
21978
|
return;
|
|
21186
21979
|
}
|
|
21187
21980
|
setSidebarSelection([key], key);
|
|
21188
|
-
if (entry.id) sessionWorkspaceRef.current?.selectSession(entry.id, { sessionPath: entry.path });
|
|
21981
|
+
if (entry.id && !isOptimisticSidebarSessionEntry(entry)) sessionWorkspaceRef.current?.selectSession(entry.id, { sessionPath: entry.path });
|
|
21189
21982
|
};
|
|
21190
21983
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppSidebar, {
|
|
21191
21984
|
sessionSearch,
|
|
@@ -21626,8 +22419,30 @@ function movePendingDraftFollowUpMessage(messages, pendingId, direction) {
|
|
|
21626
22419
|
next.splice(targetIndex, 0, movedItem);
|
|
21627
22420
|
return next;
|
|
21628
22421
|
}
|
|
22422
|
+
var EMPTY_COMPOSER_DIFF_LINE_COMMENTS = [];
|
|
21629
22423
|
var EMPTY_COMPOSER_IMAGES = [];
|
|
21630
22424
|
var EMPTY_COMPOSER_PENDING_MESSAGES = [];
|
|
22425
|
+
function sameComposerDiffLineComments(left, right) {
|
|
22426
|
+
if (left === right) return true;
|
|
22427
|
+
if (left.length !== right.length) return false;
|
|
22428
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
22429
|
+
const leftComment = left[index];
|
|
22430
|
+
const rightComment = right[index];
|
|
22431
|
+
if (!leftComment || !rightComment) return false;
|
|
22432
|
+
if (leftComment.id !== rightComment.id) return false;
|
|
22433
|
+
if (leftComment.cwd !== rightComment.cwd) return false;
|
|
22434
|
+
if (leftComment.path !== rightComment.path) return false;
|
|
22435
|
+
if (leftComment.lineNumber !== rightComment.lineNumber) return false;
|
|
22436
|
+
if (leftComment.side !== rightComment.side) return false;
|
|
22437
|
+
if (leftComment.text !== rightComment.text) return false;
|
|
22438
|
+
if (leftComment.tabKey !== rightComment.tabKey) return false;
|
|
22439
|
+
if (leftComment.tabTitle !== rightComment.tabTitle) return false;
|
|
22440
|
+
if (leftComment.commit !== rightComment.commit) return false;
|
|
22441
|
+
if (leftComment.shortHash !== rightComment.shortHash) return false;
|
|
22442
|
+
if (leftComment.mode !== rightComment.mode) return false;
|
|
22443
|
+
}
|
|
22444
|
+
return true;
|
|
22445
|
+
}
|
|
21631
22446
|
function sameComposerPromptImages(left, right) {
|
|
21632
22447
|
if (left === right) return true;
|
|
21633
22448
|
if (left.length !== right.length) return false;
|
|
@@ -21656,13 +22471,14 @@ function sameComposerPendingMessages(left, right) {
|
|
|
21656
22471
|
return true;
|
|
21657
22472
|
}
|
|
21658
22473
|
function sameAppShellComposerSnapshot(left, right) {
|
|
21659
|
-
return left.activeSessionId === right.activeSessionId && left.awaitingFirstTurn === right.awaitingFirstTurn && left.centerMessages === right.centerMessages && left.composerSkill === right.composerSkill && left.composerSyncNonce === right.composerSyncNonce && left.composerText === right.composerText && left.disabled === right.disabled && left.isStreaming === right.isStreaming && left.isSubmitting === right.isSubmitting && left.viewerContextId === right.viewerContextId && sameComposerPromptImages(left.composerImages, right.composerImages) && sameComposerPendingMessages(left.currentPendingMessages, right.currentPendingMessages);
|
|
22474
|
+
return left.activeSessionId === right.activeSessionId && left.awaitingFirstTurn === right.awaitingFirstTurn && left.centerMessages === right.centerMessages && sameComposerDiffLineComments(left.composerDiffLineComments, right.composerDiffLineComments) && left.composerSkill === right.composerSkill && left.composerSyncNonce === right.composerSyncNonce && left.composerText === right.composerText && left.disabled === right.disabled && left.isStreaming === right.isStreaming && left.isSubmitting === right.isSubmitting && left.viewerContextId === right.viewerContextId && sameComposerPromptImages(left.composerImages, right.composerImages) && sameComposerPendingMessages(left.currentPendingMessages, right.currentPendingMessages);
|
|
21660
22475
|
}
|
|
21661
22476
|
function createInitialAppShellComposerSnapshot(viewerContextId) {
|
|
21662
22477
|
return {
|
|
21663
22478
|
activeSessionId: void 0,
|
|
21664
22479
|
awaitingFirstTurn: false,
|
|
21665
22480
|
centerMessages: false,
|
|
22481
|
+
composerDiffLineComments: EMPTY_COMPOSER_DIFF_LINE_COMMENTS,
|
|
21666
22482
|
composerImages: EMPTY_COMPOSER_IMAGES,
|
|
21667
22483
|
composerSkill: void 0,
|
|
21668
22484
|
composerSyncNonce: 0,
|
|
@@ -21732,10 +22548,23 @@ function createPicoLatestThrottler(options) {
|
|
|
21732
22548
|
};
|
|
21733
22549
|
}
|
|
21734
22550
|
function samePromptMutationSessionSnapshot(left, right) {
|
|
21735
|
-
return left.cwd === right.cwd && left.draft === right.draft && left.sessionFile === right.sessionFile && left.sessionId === right.sessionId && left.sessionKey === right.sessionKey && left.streaming === right.streaming;
|
|
22551
|
+
return left.assistantOutputSignature === right.assistantOutputSignature && left.cwd === right.cwd && left.draft === right.draft && left.sessionFile === right.sessionFile && left.sessionId === right.sessionId && left.sessionKey === right.sessionKey && left.streaming === right.streaming;
|
|
22552
|
+
}
|
|
22553
|
+
function sessionAssistantOutputSignature(items) {
|
|
22554
|
+
let outputCount = 0;
|
|
22555
|
+
let lastOutputKey = "";
|
|
22556
|
+
for (let index = 0; index < items.length; index += 1) {
|
|
22557
|
+
const item = items[index];
|
|
22558
|
+
if (!item || item.kind !== "assistant") continue;
|
|
22559
|
+
if (!item.blocks.some((block) => block.type === "text" && block.text.trim())) continue;
|
|
22560
|
+
outputCount += 1;
|
|
22561
|
+
lastOutputKey = item.itemKey || item.renderKey || `index:${index}`;
|
|
22562
|
+
}
|
|
22563
|
+
return `${outputCount}:${lastOutputKey}`;
|
|
21736
22564
|
}
|
|
21737
22565
|
function usePromptMutationSessionSnapshot(store) {
|
|
21738
22566
|
return useSelector(store, (sessionState) => ({
|
|
22567
|
+
assistantOutputSignature: sessionAssistantOutputSignature(sessionState.items),
|
|
21739
22568
|
cwd: sessionState.cwd,
|
|
21740
22569
|
draft: sessionState.draft,
|
|
21741
22570
|
sessionFile: sessionState.sessionFile,
|
|
@@ -21756,7 +22585,7 @@ function buildCurrentSessionRequestUrl(path, { contextId, sessionState, fallback
|
|
|
21756
22585
|
const shouldUseSessionKey = Boolean(sessionKey && (sessionState.draft || !sessionState.sessionId));
|
|
21757
22586
|
return buildRequestUrl(path, {
|
|
21758
22587
|
contextId,
|
|
21759
|
-
sessionId: shouldUseSessionKey ? void 0 : sessionState.sessionId ?? fallbackSessionId,
|
|
22588
|
+
sessionId: shouldUseSessionKey || sessionState.draft ? void 0 : sessionState.sessionId ?? fallbackSessionId,
|
|
21760
22589
|
searchParams: shouldUseSessionKey ? { sessionKey } : void 0
|
|
21761
22590
|
});
|
|
21762
22591
|
}
|
|
@@ -21809,13 +22638,14 @@ function movePendingComposerMessage(messages, pendingId, direction) {
|
|
|
21809
22638
|
next.splice(targetIndex, 0, movedItem);
|
|
21810
22639
|
return next;
|
|
21811
22640
|
}
|
|
21812
|
-
function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultNewSessionDirectory, sessionStore, sessionStateRef, draftSessionLoadingOwnerKey, pendingDraftPrompt, pendingDraftFollowUps, awaitingFirstTurn, pendingMessages, composerImagesRef, composerTextRef, composerSkillRef, replaceComposerDraft, lastSyncedEditorTextRef, rememberRecentDirectory, prefetchDirectorySessionsIndex, addOptimisticUserMessage, removeOptimisticUserMessage, setSidebarDirectories, setStoredDraftDirectory, setDraftSessionLoadingOwnerKey, setPendingDraftPrompt, setPendingDraftFollowUps, setPendingMessages, setAwaitingFirstTurn, setIsSubmitting, setComposerImages }) {
|
|
22641
|
+
function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultNewSessionDirectory, sessionStore, sessionStateRef, draftSessionLoadingOwnerKey, pendingDraftPrompt, pendingDraftFollowUps, awaitingFirstTurn, pendingMessages, composerDiffLineCommentsRef, composerImagesRef, composerTextRef, composerSkillRef, replaceComposerDraft, lastSyncedEditorTextRef, rememberRecentDirectory, prefetchDirectorySessionsIndex, addOptimisticUserMessage, removeOptimisticUserMessage, addOptimisticSidebarSession, removeOptimisticSidebarSession, setSidebarDirectories, setStoredDraftDirectory, setDraftSessionLoadingOwnerKey, setPendingDraftPrompt, setPendingDraftFollowUps, setPendingMessages, setAwaitingFirstTurn, setIsSubmitting, setComposerDiffLineComments, setComposerImages }) {
|
|
21813
22642
|
const queryClient = useQueryClient();
|
|
21814
22643
|
const draftSessionLoadingOwnerKeyRef = import_react.useRef(draftSessionLoadingOwnerKey);
|
|
21815
22644
|
const pendingDraftPromptRef = import_react.useRef(pendingDraftPrompt);
|
|
21816
22645
|
const pendingDraftFollowUpsRef = import_react.useRef(pendingDraftFollowUps);
|
|
21817
22646
|
const pendingMessagesRef = import_react.useRef(pendingMessages);
|
|
21818
22647
|
const awaitingFirstTurnRef = import_react.useRef(awaitingFirstTurn);
|
|
22648
|
+
const awaitingFirstTurnAssistantOutputSignatureRef = import_react.useRef(null);
|
|
21819
22649
|
const sessionSnapshot = usePromptMutationSessionSnapshot(sessionStore);
|
|
21820
22650
|
const sessionStreamingRef = import_react.useRef(sessionSnapshot.streaming);
|
|
21821
22651
|
import_react.useEffect(() => {
|
|
@@ -21888,16 +22718,19 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
21888
22718
|
const nextPrompt = pendingDraftPromptRef.current;
|
|
21889
22719
|
if (!nextPrompt || nextPrompt.ownerKey !== ownerKey) return false;
|
|
21890
22720
|
removeOptimisticUserMessage(nextPrompt.optimisticId);
|
|
22721
|
+
removeOptimisticSidebarSession(nextPrompt.optimisticSidebarSessionId);
|
|
21891
22722
|
for (const followUp of pendingDraftFollowUpsRef.current) removeOptimisticUserMessage(followUp.optimisticId);
|
|
21892
22723
|
pendingDraftPromptRef.current = null;
|
|
21893
22724
|
pendingDraftFollowUpsRef.current = [];
|
|
21894
22725
|
setPendingDraftPrompt(null);
|
|
21895
22726
|
setPendingDraftFollowUps([]);
|
|
22727
|
+
awaitingFirstTurnAssistantOutputSignatureRef.current = null;
|
|
21896
22728
|
awaitingFirstTurnRef.current = false;
|
|
21897
22729
|
setAwaitingFirstTurn(false);
|
|
21898
22730
|
return applyPendingDraftPromptToComposer(nextPrompt);
|
|
21899
22731
|
}, [
|
|
21900
22732
|
applyPendingDraftPromptToComposer,
|
|
22733
|
+
removeOptimisticSidebarSession,
|
|
21901
22734
|
removeOptimisticUserMessage,
|
|
21902
22735
|
setAwaitingFirstTurn,
|
|
21903
22736
|
setPendingDraftFollowUps,
|
|
@@ -21930,15 +22763,20 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
21930
22763
|
]);
|
|
21931
22764
|
const createSessionRequest = import_react.useCallback(async ({ cwd }) => {
|
|
21932
22765
|
if (!viewerContextId) throw new Error("Viewer context unavailable");
|
|
21933
|
-
return await fetchJson(
|
|
22766
|
+
return await fetchJson(buildCurrentSessionRequestUrl("/api/session/new", {
|
|
21934
22767
|
contextId: viewerContextId,
|
|
21935
|
-
|
|
22768
|
+
sessionState: sessionStateRef.current,
|
|
22769
|
+
fallbackSessionId: activeSessionId
|
|
21936
22770
|
}), {
|
|
21937
22771
|
method: "POST",
|
|
21938
22772
|
headers: { "content-type": "application/json" },
|
|
21939
22773
|
body: JSON.stringify({ cwd })
|
|
21940
22774
|
});
|
|
21941
|
-
}, [
|
|
22775
|
+
}, [
|
|
22776
|
+
activeSessionId,
|
|
22777
|
+
sessionStateRef,
|
|
22778
|
+
viewerContextId
|
|
22779
|
+
]);
|
|
21942
22780
|
const createSession = import_react.useCallback(async (cwdOverride) => {
|
|
21943
22781
|
if (!viewerContextId) return false;
|
|
21944
22782
|
const nextCwd = resolveNewSessionCwd({
|
|
@@ -21977,9 +22815,10 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
21977
22815
|
const queuePendingDraftPrompt = import_react.useCallback((streamingBehavior) => {
|
|
21978
22816
|
const ownerKey = draftSessionLoadingOwnerKeyRef.current;
|
|
21979
22817
|
if (!ownerKey) return false;
|
|
21980
|
-
const message =
|
|
22818
|
+
const message = buildComposerPromptMessage({
|
|
21981
22819
|
text: composerTextRef.current,
|
|
21982
|
-
skillName: composerSkillRef.current
|
|
22820
|
+
skillName: composerSkillRef.current,
|
|
22821
|
+
diffLineComments: composerDiffLineCommentsRef.current
|
|
21983
22822
|
}).trim();
|
|
21984
22823
|
const images = composerImagesRef.current.map((image) => ({ ...image }));
|
|
21985
22824
|
if (!message && images.length === 0) return false;
|
|
@@ -21992,7 +22831,8 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
21992
22831
|
message,
|
|
21993
22832
|
images,
|
|
21994
22833
|
queued: false
|
|
21995
|
-
})
|
|
22834
|
+
}),
|
|
22835
|
+
optimisticSidebarSessionId: addOptimisticSidebarSession()
|
|
21996
22836
|
};
|
|
21997
22837
|
pendingDraftPromptRef.current = nextPrompt;
|
|
21998
22838
|
setPendingDraftPrompt(nextPrompt);
|
|
@@ -22012,17 +22852,21 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22012
22852
|
setPendingDraftFollowUps(nextFollowUps);
|
|
22013
22853
|
}
|
|
22014
22854
|
replaceComposerDraft("", void 0, { forceSync: true });
|
|
22855
|
+
setComposerDiffLineComments([]);
|
|
22015
22856
|
setComposerImages([]);
|
|
22016
22857
|
lastSyncedEditorTextRef.current = "";
|
|
22017
22858
|
return true;
|
|
22018
22859
|
}, [
|
|
22860
|
+
addOptimisticSidebarSession,
|
|
22019
22861
|
addOptimisticUserMessage,
|
|
22862
|
+
composerDiffLineCommentsRef,
|
|
22020
22863
|
composerImagesRef,
|
|
22021
22864
|
composerSkillRef,
|
|
22022
22865
|
composerTextRef,
|
|
22023
22866
|
lastSyncedEditorTextRef,
|
|
22024
22867
|
replaceComposerDraft,
|
|
22025
22868
|
setAwaitingFirstTurn,
|
|
22869
|
+
setComposerDiffLineComments,
|
|
22026
22870
|
setComposerImages,
|
|
22027
22871
|
setPendingDraftFollowUps,
|
|
22028
22872
|
setPendingDraftPrompt
|
|
@@ -22056,32 +22900,37 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22056
22900
|
const submitPrompt = import_react.useCallback(async (streamingBehavior, options) => {
|
|
22057
22901
|
if (!viewerContextId) return false;
|
|
22058
22902
|
if (draftSessionLoadingOwnerKeyRef.current) return queuePendingDraftPrompt(streamingBehavior);
|
|
22059
|
-
const
|
|
22903
|
+
const submittedDiffLineComments = composerDiffLineCommentsRef.current.map((comment) => ({ ...comment }));
|
|
22904
|
+
const message = buildComposerPromptMessage({
|
|
22060
22905
|
text: composerTextRef.current,
|
|
22061
|
-
skillName: composerSkillRef.current
|
|
22906
|
+
skillName: composerSkillRef.current,
|
|
22907
|
+
diffLineComments: submittedDiffLineComments
|
|
22062
22908
|
}).trim();
|
|
22063
22909
|
if (!message && composerImagesRef.current.length === 0) return false;
|
|
22064
22910
|
const treatAsQueuedPrompt = options?.forceFirstPrompt ? false : Boolean(sessionStreamingRef.current || awaitingFirstTurnRef.current);
|
|
22065
22911
|
const normalizedStreamingBehavior = treatAsQueuedPrompt ? normalizeQueuedStreamingBehavior(streamingBehavior) : void 0;
|
|
22066
22912
|
const submittedImages = composerImagesRef.current.map((image) => ({ ...image }));
|
|
22067
22913
|
const queuedPendingId = treatAsQueuedPrompt ? createLocalPendingId() : void 0;
|
|
22914
|
+
if (!treatAsQueuedPrompt) {
|
|
22915
|
+
awaitingFirstTurnAssistantOutputSignatureRef.current = sessionAssistantOutputSignature(sessionStateRef.current.items);
|
|
22916
|
+
awaitingFirstTurnRef.current = true;
|
|
22917
|
+
setAwaitingFirstTurn(true);
|
|
22918
|
+
}
|
|
22068
22919
|
const optimisticId = options?.optimisticId ?? (treatAsQueuedPrompt ? void 0 : addOptimisticUserMessage({
|
|
22069
22920
|
message,
|
|
22070
22921
|
images: submittedImages,
|
|
22071
22922
|
queued: false
|
|
22072
22923
|
}));
|
|
22924
|
+
const optimisticSidebarSessionId = options?.optimisticSidebarSessionId ?? (!treatAsQueuedPrompt && sessionStateRef.current.draft ? addOptimisticSidebarSession() : void 0);
|
|
22073
22925
|
if (queuedPendingId && normalizedStreamingBehavior) addOptimisticPendingMessage({
|
|
22074
22926
|
pendingId: queuedPendingId,
|
|
22075
22927
|
text: message,
|
|
22076
22928
|
images: submittedImages.map((image) => ({ ...image })),
|
|
22077
22929
|
streamingBehavior: normalizedStreamingBehavior
|
|
22078
22930
|
});
|
|
22079
|
-
if (!treatAsQueuedPrompt) {
|
|
22080
|
-
awaitingFirstTurnRef.current = true;
|
|
22081
|
-
setAwaitingFirstTurn(true);
|
|
22082
|
-
}
|
|
22083
22931
|
setIsSubmitting(true);
|
|
22084
22932
|
replaceComposerDraft("", void 0, { forceSync: true });
|
|
22933
|
+
setComposerDiffLineComments([]);
|
|
22085
22934
|
setComposerImages([]);
|
|
22086
22935
|
lastSyncedEditorTextRef.current = "";
|
|
22087
22936
|
try {
|
|
@@ -22097,15 +22946,18 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22097
22946
|
} catch (error) {
|
|
22098
22947
|
if (queuedPendingId) removeOptimisticPendingMessage(queuedPendingId);
|
|
22099
22948
|
removeOptimisticUserMessage(optimisticId);
|
|
22949
|
+
removeOptimisticSidebarSession(optimisticSidebarSessionId);
|
|
22100
22950
|
if (!treatAsQueuedPrompt) {
|
|
22951
|
+
awaitingFirstTurnAssistantOutputSignatureRef.current = null;
|
|
22101
22952
|
awaitingFirstTurnRef.current = false;
|
|
22102
22953
|
setAwaitingFirstTurn(false);
|
|
22103
22954
|
}
|
|
22104
22955
|
if (!serializeComposerDraft({
|
|
22105
22956
|
text: composerTextRef.current,
|
|
22106
22957
|
skillName: composerSkillRef.current
|
|
22107
|
-
}).trim()) {
|
|
22958
|
+
}).trim() && composerDiffLineCommentsRef.current.length === 0) {
|
|
22108
22959
|
replaceComposerDraft(message);
|
|
22960
|
+
setComposerDiffLineComments((current) => current.length === 0 ? submittedDiffLineComments.map((comment) => ({ ...comment })) : current);
|
|
22109
22961
|
setComposerImages((current) => current.length === 0 ? submittedImages.map((image) => ({ ...image })) : current);
|
|
22110
22962
|
}
|
|
22111
22963
|
toast.error(error instanceof Error ? error.message : "Failed to submit prompt");
|
|
@@ -22115,7 +22967,9 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22115
22967
|
}
|
|
22116
22968
|
}, [
|
|
22117
22969
|
addOptimisticPendingMessage,
|
|
22970
|
+
addOptimisticSidebarSession,
|
|
22118
22971
|
addOptimisticUserMessage,
|
|
22972
|
+
composerDiffLineCommentsRef,
|
|
22119
22973
|
composerImagesRef,
|
|
22120
22974
|
composerSkillRef,
|
|
22121
22975
|
composerTextRef,
|
|
@@ -22124,9 +22978,11 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22124
22978
|
queuePendingDraftPrompt,
|
|
22125
22979
|
sessionStateRef,
|
|
22126
22980
|
removeOptimisticPendingMessage,
|
|
22981
|
+
removeOptimisticSidebarSession,
|
|
22127
22982
|
removeOptimisticUserMessage,
|
|
22128
22983
|
replaceComposerDraft,
|
|
22129
22984
|
setAwaitingFirstTurn,
|
|
22985
|
+
setComposerDiffLineComments,
|
|
22130
22986
|
setComposerImages,
|
|
22131
22987
|
setIsSubmitting,
|
|
22132
22988
|
viewerContextId
|
|
@@ -22183,8 +23039,10 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22183
23039
|
applyPendingDraftPromptToComposer(nextPrompt);
|
|
22184
23040
|
if (!await submitPrompt(nextPrompt.streamingBehavior, {
|
|
22185
23041
|
forceFirstPrompt: true,
|
|
22186
|
-
optimisticId: nextPrompt.optimisticId
|
|
23042
|
+
optimisticId: nextPrompt.optimisticId,
|
|
23043
|
+
optimisticSidebarSessionId: nextPrompt.optimisticSidebarSessionId
|
|
22187
23044
|
})) {
|
|
23045
|
+
removeOptimisticSidebarSession(nextPrompt.optimisticSidebarSessionId);
|
|
22188
23046
|
for (const followUp of pendingDraftFollowUpsRef.current) removeOptimisticUserMessage(followUp.optimisticId);
|
|
22189
23047
|
pendingDraftFollowUpsRef.current = [];
|
|
22190
23048
|
setPendingDraftFollowUps([]);
|
|
@@ -22195,6 +23053,7 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22195
23053
|
}, [
|
|
22196
23054
|
applyPendingDraftPromptToComposer,
|
|
22197
23055
|
flushPendingDraftFollowUps,
|
|
23056
|
+
removeOptimisticSidebarSession,
|
|
22198
23057
|
removeOptimisticUserMessage,
|
|
22199
23058
|
setPendingDraftFollowUps,
|
|
22200
23059
|
setPendingDraftPrompt,
|
|
@@ -22205,7 +23064,7 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22205
23064
|
const currentSessionState = sessionStateRef.current;
|
|
22206
23065
|
if (currentSessionState.sessionKey?.startsWith("optimistic:")) return;
|
|
22207
23066
|
const currentOwnerKey = promptDraftKey(currentSessionState);
|
|
22208
|
-
if (!currentSessionState.draft || currentOwnerKey
|
|
23067
|
+
if (!currentSessionState.draft || !promptDraftKeyMatchesOwner(currentOwnerKey, draftSessionLoadingOwnerKey)) return;
|
|
22209
23068
|
draftSessionLoadingOwnerKeyRef.current = null;
|
|
22210
23069
|
setDraftSessionLoadingOwnerKey(null);
|
|
22211
23070
|
if (pendingDraftPromptRef.current?.ownerKey === draftSessionLoadingOwnerKey) flushPendingDraftPrompt(draftSessionLoadingOwnerKey);
|
|
@@ -22218,15 +23077,17 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22218
23077
|
]);
|
|
22219
23078
|
import_react.useEffect(() => {
|
|
22220
23079
|
if (!awaitingFirstTurn) return;
|
|
22221
|
-
const
|
|
22222
|
-
const
|
|
22223
|
-
if (
|
|
23080
|
+
const baselineAssistantOutputSignature = awaitingFirstTurnAssistantOutputSignatureRef.current;
|
|
23081
|
+
const assistantOutputStarted = baselineAssistantOutputSignature !== null && sessionSnapshot.assistantOutputSignature !== baselineAssistantOutputSignature;
|
|
23082
|
+
if (sessionStateRef.current.streaming || assistantOutputStarted || pendingMessages.length > 0) {
|
|
23083
|
+
awaitingFirstTurnAssistantOutputSignatureRef.current = null;
|
|
22224
23084
|
awaitingFirstTurnRef.current = false;
|
|
22225
23085
|
setAwaitingFirstTurn(false);
|
|
22226
23086
|
}
|
|
22227
23087
|
}, [
|
|
22228
23088
|
awaitingFirstTurn,
|
|
22229
23089
|
pendingMessages.length,
|
|
23090
|
+
sessionSnapshot.assistantOutputSignature,
|
|
22230
23091
|
sessionSnapshot.streaming,
|
|
22231
23092
|
sessionStateRef,
|
|
22232
23093
|
setAwaitingFirstTurn
|
|
@@ -22370,20 +23231,33 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22370
23231
|
}
|
|
22371
23232
|
function usePicoTheme() {
|
|
22372
23233
|
const { setTheme, systemTheme } = z();
|
|
22373
|
-
const
|
|
22374
|
-
const
|
|
23234
|
+
const initialThemeRef = import_react.useRef(void 0);
|
|
23235
|
+
const initialTheme = initialThemeRef.current ?? readStoredTheme();
|
|
23236
|
+
initialThemeRef.current = initialTheme;
|
|
23237
|
+
const [themeFamily, setThemeFamilyState] = import_react.useState(initialTheme);
|
|
23238
|
+
const [colorMode, setColorModeState] = import_react.useState(() => themeFamilyFixedMode(initialTheme) ?? readStoredThemeColorMode());
|
|
22375
23239
|
const appliedTheme = appliedThemeClass(themeFamily, colorMode, systemTheme);
|
|
22376
23240
|
import_react.useEffect(() => {
|
|
22377
23241
|
setTheme(appliedTheme);
|
|
22378
23242
|
safeLocalStorageSetItem(APPLIED_THEME_STORAGE_KEY, appliedTheme);
|
|
23243
|
+
const appliedThemeMode = appliedThemeClassColorMode(appliedTheme);
|
|
23244
|
+
if (appliedThemeMode) document.documentElement.dataset.picoThemeMode = appliedThemeMode;
|
|
22379
23245
|
}, [appliedTheme, setTheme]);
|
|
22380
|
-
const previewThemeFamily = (value) => {
|
|
22381
|
-
|
|
23246
|
+
const previewThemeFamily = (value, nextColorMode) => {
|
|
23247
|
+
const nextTheme = normalizeThemeFamily(value);
|
|
23248
|
+
const fixedMode = themeFamilyFixedMode(nextTheme);
|
|
23249
|
+
setThemeFamilyState(nextTheme);
|
|
23250
|
+
if (nextColorMode || fixedMode) setColorModeState(normalizeThemeColorMode(nextColorMode ?? fixedMode));
|
|
22382
23251
|
};
|
|
22383
23252
|
const setThemeFamily = (value) => {
|
|
22384
23253
|
const nextTheme = normalizeThemeFamily(value);
|
|
23254
|
+
const fixedMode = themeFamilyFixedMode(nextTheme);
|
|
22385
23255
|
setThemeFamilyState(nextTheme);
|
|
22386
23256
|
safeLocalStorageSetItem(THEME_STORAGE_KEY, nextTheme);
|
|
23257
|
+
if (fixedMode) {
|
|
23258
|
+
setColorModeState(fixedMode);
|
|
23259
|
+
safeLocalStorageSetItem(THEME_COLOR_MODE_STORAGE_KEY, fixedMode);
|
|
23260
|
+
}
|
|
22387
23261
|
};
|
|
22388
23262
|
const setColorMode = (value) => {
|
|
22389
23263
|
const nextMode = normalizeThemeColorMode(value);
|
|
@@ -23096,6 +23970,7 @@ function sameSessionListEntries(left = [], right = []) {
|
|
|
23096
23970
|
if (!sameContextUsage(leftEntry.contextUsage, rightEntry.contextUsage)) return false;
|
|
23097
23971
|
if (Boolean(leftEntry.streaming) !== Boolean(rightEntry.streaming)) return false;
|
|
23098
23972
|
if (Boolean(leftEntry.unread) !== Boolean(rightEntry.unread)) return false;
|
|
23973
|
+
if (Boolean(leftEntry.optimistic) !== Boolean(rightEntry.optimistic)) return false;
|
|
23099
23974
|
}
|
|
23100
23975
|
return true;
|
|
23101
23976
|
}
|
|
@@ -23169,20 +24044,28 @@ function shouldPublishSessionState(previous, next) {
|
|
|
23169
24044
|
if (previous === next) return false;
|
|
23170
24045
|
return !sameSessionStateExceptConversation(previous, next) || !samePublishableUiState(previous.uiState, next.uiState) || previous.items.length === 0 !== (next.items.length === 0);
|
|
23171
24046
|
}
|
|
23172
|
-
function
|
|
23173
|
-
if (!ownerKey || payload.draft !== true) return false;
|
|
24047
|
+
function stateSyncPayloadDraftKey(payload) {
|
|
23174
24048
|
return promptDraftKey({
|
|
23175
24049
|
cwd: typeof payload.cwd === "string" ? payload.cwd : void 0,
|
|
23176
24050
|
sessionFile: typeof payload.sessionFile === "string" ? payload.sessionFile : void 0,
|
|
23177
24051
|
sessionId: typeof payload.sessionId === "string" ? payload.sessionId : void 0
|
|
23178
|
-
})
|
|
24052
|
+
});
|
|
24053
|
+
}
|
|
24054
|
+
function stateSyncPayloadConfirmsPendingDraft(payload, ownerKey) {
|
|
24055
|
+
if (!ownerKey || payload.draft !== true) return false;
|
|
24056
|
+
return promptDraftKeyMatchesOwner(stateSyncPayloadDraftKey(payload), ownerKey);
|
|
24057
|
+
}
|
|
24058
|
+
function stateSyncPayloadConfirmsOptimisticDraft(payload, previousState) {
|
|
24059
|
+
if (payload.draft !== true) return false;
|
|
24060
|
+
return promptDraftKeyMatchesOwner(stateSyncPayloadDraftKey(payload), promptDraftKey(previousState));
|
|
23179
24061
|
}
|
|
23180
24062
|
function shouldIgnoreOptimisticDraftStateSync(options) {
|
|
23181
24063
|
const previousSessionKey = options.previousState.sessionKey || "";
|
|
23182
24064
|
const payloadSessionKey = typeof options.payload.sessionKey === "string" ? options.payload.sessionKey : "";
|
|
23183
24065
|
if (!previousSessionKey.startsWith("optimistic:")) return false;
|
|
23184
24066
|
if (!payloadSessionKey || payloadSessionKey === previousSessionKey) return false;
|
|
23185
|
-
|
|
24067
|
+
if (stateSyncPayloadConfirmsPendingDraft(options.payload, options.ownerKey) || stateSyncPayloadConfirmsOptimisticDraft(options.payload, options.previousState)) return false;
|
|
24068
|
+
return true;
|
|
23186
24069
|
}
|
|
23187
24070
|
function useAppShellSessionSync({ viewerContextId, sessionId, draftSessionLoadingOwnerKey, bootstrapSidebarDirectories, hideToolBlocksRef, sessionStore, sessionStateRef, composerTextRef, composerSkillRef, replaceComposerDraftRef, handleSelectSessionRef, pendingRouteSessionIdRef, pendingRouteSessionPathRef, setSessionState, setConversationItems, setHiddenThinkingPreview, setWorkingState, setCompactRunningState, setComposerContextUsage, setComposerStreaming, setSessionsEvent, setSessionDoneEvents, applySidebarSessionStatusRef, setComposerImages, setPendingMessages, pendingUiRequestHandlerRef, lastSyncedEditorTextRef }) {
|
|
23188
24071
|
const queryClient = useQueryClient();
|
|
@@ -23191,6 +24074,7 @@ function useAppShellSessionSync({ viewerContextId, sessionId, draftSessionLoadin
|
|
|
23191
24074
|
const draftSessionLoadingOwnerKeyRef = import_react.useRef(draftSessionLoadingOwnerKey);
|
|
23192
24075
|
const currentSourceRef = import_react.useRef(null);
|
|
23193
24076
|
const hasReceivedStateSyncRef = import_react.useRef(false);
|
|
24077
|
+
const [hasReceivedStateSync, setHasReceivedStateSync] = import_react.useState(false);
|
|
23194
24078
|
const backgroundedAtRef = import_react.useRef(null);
|
|
23195
24079
|
const wasBackgroundedRef = import_react.useRef(false);
|
|
23196
24080
|
const [eventsReconnectNonce, setEventsReconnectNonce] = import_react.useState(0);
|
|
@@ -23205,8 +24089,8 @@ function useAppShellSessionSync({ viewerContextId, sessionId, draftSessionLoadin
|
|
|
23205
24089
|
initialEventsSessionIdRef.current = sessionId;
|
|
23206
24090
|
}, [sessionId]);
|
|
23207
24091
|
const syncedSessionId = useSelector(sessionStore, (sessionState) => sessionState.sessionId);
|
|
23208
|
-
const syncedSessionIdRef = import_react.useRef(syncedSessionId);
|
|
23209
24092
|
const latestActivationRevisionRef = import_react.useRef(0);
|
|
24093
|
+
const sessionSelectNonceRef = import_react.useRef(Date.now() * 1e3);
|
|
23210
24094
|
const observedRouteSessionIdRef = import_react.useRef(void 0);
|
|
23211
24095
|
const syncedSessionDraft = useSelector(sessionStore, (sessionState) => sessionState.draft);
|
|
23212
24096
|
import_react.useEffect(() => {
|
|
@@ -23320,7 +24204,10 @@ function useAppShellSessionSync({ viewerContextId, sessionId, draftSessionLoadin
|
|
|
23320
24204
|
const activationRevision = payload.activationRevision;
|
|
23321
24205
|
if (typeof activationRevision === "number" && activationRevision < latestActivationRevisionRef.current) return;
|
|
23322
24206
|
if (typeof activationRevision === "number") latestActivationRevisionRef.current = activationRevision;
|
|
23323
|
-
hasReceivedStateSyncRef.current
|
|
24207
|
+
if (!hasReceivedStateSyncRef.current) {
|
|
24208
|
+
hasReceivedStateSyncRef.current = true;
|
|
24209
|
+
setHasReceivedStateSync(true);
|
|
24210
|
+
}
|
|
23324
24211
|
const previousState = sessionStateRef.current;
|
|
23325
24212
|
if (shouldIgnoreOptimisticDraftStateSync({
|
|
23326
24213
|
ownerKey: draftSessionLoadingOwnerKeyRef.current,
|
|
@@ -23339,7 +24226,7 @@ function useAppShellSessionSync({ viewerContextId, sessionId, draftSessionLoadin
|
|
|
23339
24226
|
const currentDraftOwnerKey = draftSessionLoadingOwnerKeyRef.current;
|
|
23340
24227
|
const confirmedDraft = nextState.draft && !nextState.sessionKey?.startsWith("optimistic:");
|
|
23341
24228
|
const previousWasOptimisticDraft = previousState.draft && previousState.sessionKey?.startsWith("optimistic:");
|
|
23342
|
-
const draftMatchesPendingOwner =
|
|
24229
|
+
const draftMatchesPendingOwner = promptDraftKeyMatchesOwner(promptDraftKey(nextState), currentDraftOwnerKey);
|
|
23343
24230
|
const shouldClearDraftRoute = Boolean(currentRouteSessionId && !pendingRouteSessionIdRef.current && confirmedDraft && (draftMatchesPendingOwner || previousWasOptimisticDraft));
|
|
23344
24231
|
const preserveLocalPrompt = !sessionChanged && localPromptText !== previousEditorText;
|
|
23345
24232
|
const nextPromptText = preserveLocalPrompt ? localPromptText : readStoredPromptDraft(nextState) ?? nextState.uiState.editorText ?? "";
|
|
@@ -23455,6 +24342,8 @@ function useAppShellSessionSync({ viewerContextId, sessionId, draftSessionLoadin
|
|
|
23455
24342
|
import_react.useEffect(() => {
|
|
23456
24343
|
if (!viewerContextId) return;
|
|
23457
24344
|
hasReceivedStateSyncRef.current = false;
|
|
24345
|
+
setHasReceivedStateSync(false);
|
|
24346
|
+
latestActivationRevisionRef.current = 0;
|
|
23458
24347
|
const gitInvalidationBatcher = new Batcher((items) => {
|
|
23459
24348
|
const scopesByCwd = /* @__PURE__ */ new Map();
|
|
23460
24349
|
for (const item of items) {
|
|
@@ -23528,21 +24417,23 @@ function useAppShellSessionSync({ viewerContextId, sessionId, draftSessionLoadin
|
|
|
23528
24417
|
queryClient,
|
|
23529
24418
|
viewerContextId
|
|
23530
24419
|
]);
|
|
23531
|
-
import_react.useEffect(() => {
|
|
23532
|
-
syncedSessionIdRef.current = syncedSessionId;
|
|
23533
|
-
}, [syncedSessionId]);
|
|
23534
24420
|
import_react.useEffect(() => {
|
|
23535
24421
|
if (!viewerContextId || !sessionId) return;
|
|
23536
24422
|
if (draftSessionLoadingOwnerKey) return;
|
|
23537
|
-
if (!
|
|
23538
|
-
if (sessionId ===
|
|
24423
|
+
if (!hasReceivedStateSync) return;
|
|
24424
|
+
if (sessionId === syncedSessionId) return;
|
|
23539
24425
|
if (pendingRouteSessionIdRef.current !== sessionId) return;
|
|
23540
24426
|
const abortController = new AbortController();
|
|
23541
24427
|
const sessionPath = pendingRouteSessionPathRef.current;
|
|
24428
|
+
const selectionNonce = Math.max(sessionSelectNonceRef.current + 1, Date.now() * 1e3);
|
|
24429
|
+
sessionSelectNonceRef.current = selectionNonce;
|
|
23542
24430
|
fetchJson(buildRequestUrl("/api/session/select", {
|
|
23543
24431
|
contextId: viewerContextId,
|
|
23544
24432
|
sessionId,
|
|
23545
|
-
searchParams: {
|
|
24433
|
+
searchParams: {
|
|
24434
|
+
selectionNonce,
|
|
24435
|
+
sessionPath
|
|
24436
|
+
}
|
|
23546
24437
|
}), {
|
|
23547
24438
|
method: "POST",
|
|
23548
24439
|
signal: abortController.signal
|
|
@@ -23555,8 +24446,10 @@ function useAppShellSessionSync({ viewerContextId, sessionId, draftSessionLoadin
|
|
|
23555
24446
|
};
|
|
23556
24447
|
}, [
|
|
23557
24448
|
draftSessionLoadingOwnerKey,
|
|
24449
|
+
hasReceivedStateSync,
|
|
23558
24450
|
pendingRouteSessionIdRef,
|
|
23559
24451
|
pendingRouteSessionPathRef,
|
|
24452
|
+
syncedSessionId,
|
|
23560
24453
|
viewerContextId,
|
|
23561
24454
|
sessionId
|
|
23562
24455
|
]);
|
|
@@ -23654,13 +24547,12 @@ function useAppShellShortcuts({ addDirectoryOpenRef, commandPaletteOpenRef, comp
|
|
|
23654
24547
|
event.preventDefault();
|
|
23655
24548
|
sessionButtons[nextIndex]?.focus();
|
|
23656
24549
|
};
|
|
23657
|
-
const
|
|
24550
|
+
const handleSidebarBackspaceDelete = (event) => {
|
|
23658
24551
|
const context = getShortcutContext(event);
|
|
23659
24552
|
if (context.modalOpen || isEditableTarget(event.target) && !context.targetIsSessionSearch) return;
|
|
23660
|
-
|
|
23661
|
-
if (targetsToDelete.length === 0) return;
|
|
24553
|
+
if (context.selectedSidebarSessions.length <= 1) return;
|
|
23662
24554
|
event.preventDefault();
|
|
23663
|
-
shortcutActionsRef.current.openDeleteDialog(
|
|
24555
|
+
shortcutActionsRef.current.openDeleteDialog(context.selectedSidebarSessions);
|
|
23664
24556
|
};
|
|
23665
24557
|
const handleFocusPrompt = (event) => {
|
|
23666
24558
|
const context = getShortcutContext(event);
|
|
@@ -23832,11 +24724,11 @@ function useAppShellShortcuts({ addDirectoryOpenRef, commandPaletteOpenRef, comp
|
|
|
23832
24724
|
} }
|
|
23833
24725
|
})),
|
|
23834
24726
|
{
|
|
23835
|
-
hotkey: "
|
|
23836
|
-
callback:
|
|
24727
|
+
hotkey: "Backspace",
|
|
24728
|
+
callback: handleSidebarBackspaceDelete,
|
|
23837
24729
|
options: { meta: {
|
|
23838
24730
|
name: "Delete selected sidebar sessions",
|
|
23839
|
-
description: "Open the delete dialog for
|
|
24731
|
+
description: "Open the delete dialog for multiple selected sidebar sessions."
|
|
23840
24732
|
} }
|
|
23841
24733
|
},
|
|
23842
24734
|
{
|
|
@@ -23965,6 +24857,8 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
23965
24857
|
if (!composerImagesStoreRef.current) composerImagesStoreRef.current = createPicoStore([]);
|
|
23966
24858
|
const composerImagesStore = composerImagesStoreRef.current;
|
|
23967
24859
|
const composerImagesRef = import_react.useRef([]);
|
|
24860
|
+
const composerDiffLineCommentsRef = import_react.useRef([]);
|
|
24861
|
+
const [composerDiffLineComments, setComposerDiffLineCommentsState] = import_react.useState([]);
|
|
23968
24862
|
const displaySettingsStoreRef = import_react.useRef(null);
|
|
23969
24863
|
if (!displaySettingsStoreRef.current) displaySettingsStoreRef.current = createPicoStore({
|
|
23970
24864
|
autoScrollEnabled: true,
|
|
@@ -24070,6 +24964,18 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
24070
24964
|
const composerStoreRef = import_react.useRef(null);
|
|
24071
24965
|
if (!composerStoreRef.current) composerStoreRef.current = createPicoStore(createInitialAppShellComposerSnapshot(viewerContextId), sameAppShellComposerSnapshot);
|
|
24072
24966
|
const composerStore = composerStoreRef.current;
|
|
24967
|
+
const setComposerDiffLineComments = import_react.useCallback((action) => {
|
|
24968
|
+
const current = composerDiffLineCommentsRef.current;
|
|
24969
|
+
const next = applyStoreAction(current, action);
|
|
24970
|
+
if (next === current) return;
|
|
24971
|
+
composerDiffLineCommentsRef.current = next;
|
|
24972
|
+
setComposerDiffLineCommentsState(next);
|
|
24973
|
+
const currentComposerSnapshot = composerStore.state;
|
|
24974
|
+
setStoreState(composerStore, {
|
|
24975
|
+
...currentComposerSnapshot,
|
|
24976
|
+
composerDiffLineComments: currentComposerSnapshot.disabled ? [] : next
|
|
24977
|
+
});
|
|
24978
|
+
}, [composerStore]);
|
|
24073
24979
|
const contextUsageStoreRef = import_react.useRef(null);
|
|
24074
24980
|
if (!contextUsageStoreRef.current) contextUsageStoreRef.current = createPicoStore(void 0);
|
|
24075
24981
|
const contextUsageStore = contextUsageStoreRef.current;
|
|
@@ -24217,8 +25123,8 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
24217
25123
|
...currentComposerSnapshot,
|
|
24218
25124
|
awaitingFirstTurn: currentComposerSnapshot.disabled ? false : next
|
|
24219
25125
|
});
|
|
24220
|
-
if (next && !sessionStateRef.current.streaming) setStoreState(workingStateStore, { label: "
|
|
24221
|
-
else if (!next && workingStateStore.state?.label === "
|
|
25126
|
+
if (next && !sessionStateRef.current.streaming) setStoreState(workingStateStore, { label: "" });
|
|
25127
|
+
else if (!next && workingStateStore.state?.label === "") setStoreState(workingStateStore, null);
|
|
24222
25128
|
});
|
|
24223
25129
|
}, [
|
|
24224
25130
|
awaitingFirstTurnStore,
|
|
@@ -24979,6 +25885,64 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
24979
25885
|
});
|
|
24980
25886
|
};
|
|
24981
25887
|
const prefetchDirectorySessionsIndex = import_react.useCallback((_directory) => {}, []);
|
|
25888
|
+
const addOptimisticSidebarSession = import_react.useCallback((options) => {
|
|
25889
|
+
const currentState = sessionStateRef.current;
|
|
25890
|
+
const optimisticId = (options?.id || currentState.sessionKey || `optimistic:${promptDraftKey(currentState)}`).trim();
|
|
25891
|
+
const cwd = (options?.cwd || currentState.cwd || defaultNewSessionDirectory).trim();
|
|
25892
|
+
if (!optimisticId || !cwd) return void 0;
|
|
25893
|
+
const modified = (/* @__PURE__ */ new Date()).toISOString();
|
|
25894
|
+
const entry = {
|
|
25895
|
+
id: optimisticId,
|
|
25896
|
+
cwd,
|
|
25897
|
+
title: "New session",
|
|
25898
|
+
modified,
|
|
25899
|
+
lastUserMessageAt: modified,
|
|
25900
|
+
streaming: true,
|
|
25901
|
+
unread: false,
|
|
25902
|
+
optimistic: true
|
|
25903
|
+
};
|
|
25904
|
+
const entryKey = sessionListEntryKey(entry);
|
|
25905
|
+
sidebarStore.setSidebarDirectories((current) => {
|
|
25906
|
+
const normalizedCurrent = normalizeStoredDirectoryList(current);
|
|
25907
|
+
if (normalizedCurrent.includes(cwd)) return current;
|
|
25908
|
+
const nextDirectories = normalizeStoredDirectoryList([cwd, ...normalizedCurrent]);
|
|
25909
|
+
safeLocalStorageSetItem(SIDEBAR_DIRECTORIES_STORAGE_KEY, JSON.stringify(nextDirectories));
|
|
25910
|
+
return nextDirectories;
|
|
25911
|
+
});
|
|
25912
|
+
const optimisticEntry = {
|
|
25913
|
+
...entry,
|
|
25914
|
+
id: optimisticId,
|
|
25915
|
+
cwd
|
|
25916
|
+
};
|
|
25917
|
+
sidebarStore.setDirectoryIndexDataByPath((current) => upsertOptimisticSidebarSessionEntry(current, optimisticEntry));
|
|
25918
|
+
sidebarStore.setSessionsEvent((current) => current ? {
|
|
25919
|
+
...current,
|
|
25920
|
+
directoryIndexes: upsertOptimisticSidebarSessionEntry(current.directoryIndexes || {}, optimisticEntry)
|
|
25921
|
+
} : current);
|
|
25922
|
+
if (entryKey) {
|
|
25923
|
+
sidebarStore.setSelectedSidebarSessionKeys((current) => sameStringArray$3(current, [entryKey]) ? current : [entryKey]);
|
|
25924
|
+
sidebarStore.setSidebarSessionSelectionAnchor((current) => current === entryKey ? current : entryKey);
|
|
25925
|
+
}
|
|
25926
|
+
return optimisticId;
|
|
25927
|
+
}, [
|
|
25928
|
+
defaultNewSessionDirectory,
|
|
25929
|
+
sessionStateRef,
|
|
25930
|
+
sidebarStore
|
|
25931
|
+
]);
|
|
25932
|
+
const removeOptimisticSidebarSession = import_react.useCallback((optimisticId) => {
|
|
25933
|
+
const targetId = optimisticId?.trim() || "";
|
|
25934
|
+
if (!targetId) return;
|
|
25935
|
+
const entryKey = sessionListEntryKey({ id: targetId });
|
|
25936
|
+
sidebarStore.setDirectoryIndexDataByPath((current) => removeOptimisticSidebarSessionEntry(current, targetId));
|
|
25937
|
+
sidebarStore.setSessionsEvent((current) => current?.directoryIndexes ? {
|
|
25938
|
+
...current,
|
|
25939
|
+
directoryIndexes: removeOptimisticSidebarSessionEntry(current.directoryIndexes, targetId)
|
|
25940
|
+
} : current);
|
|
25941
|
+
if (entryKey) {
|
|
25942
|
+
sidebarStore.setSelectedSidebarSessionKeys((current) => current.filter((key) => key !== entryKey));
|
|
25943
|
+
sidebarStore.setSidebarSessionSelectionAnchor((current) => current === entryKey ? "" : current);
|
|
25944
|
+
}
|
|
25945
|
+
}, [sidebarStore]);
|
|
24982
25946
|
const clearSelectedSidebarSelection = import_react.useCallback(() => {
|
|
24983
25947
|
sidebarStore.setSelectedSidebarSessionKeys((current) => current.length === 0 ? current : []);
|
|
24984
25948
|
sidebarStore.setSidebarSessionSelectionAnchor((current) => current ? "" : current);
|
|
@@ -24999,6 +25963,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
24999
25963
|
pendingDraftFollowUps,
|
|
25000
25964
|
awaitingFirstTurn,
|
|
25001
25965
|
pendingMessages,
|
|
25966
|
+
composerDiffLineCommentsRef,
|
|
25002
25967
|
composerImagesRef,
|
|
25003
25968
|
composerTextRef,
|
|
25004
25969
|
composerSkillRef,
|
|
@@ -25008,6 +25973,8 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25008
25973
|
prefetchDirectorySessionsIndex,
|
|
25009
25974
|
addOptimisticUserMessage,
|
|
25010
25975
|
removeOptimisticUserMessage,
|
|
25976
|
+
addOptimisticSidebarSession,
|
|
25977
|
+
removeOptimisticSidebarSession,
|
|
25011
25978
|
setSidebarDirectories: sidebarStore.setSidebarDirectories,
|
|
25012
25979
|
setStoredDraftDirectory,
|
|
25013
25980
|
setDraftSessionLoadingOwnerKey,
|
|
@@ -25016,6 +25983,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25016
25983
|
setPendingMessages,
|
|
25017
25984
|
setAwaitingFirstTurn,
|
|
25018
25985
|
setIsSubmitting,
|
|
25986
|
+
setComposerDiffLineComments,
|
|
25019
25987
|
setComposerImages
|
|
25020
25988
|
});
|
|
25021
25989
|
const switchEmptyDraftDirectory = import_react.useCallback((directory) => {
|
|
@@ -25060,6 +26028,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25060
26028
|
const ownerKey = promptDraftKey({ cwd: nextCwd });
|
|
25061
26029
|
const optimisticSessionKey = `optimistic:${ownerKey}`;
|
|
25062
26030
|
const shouldCloseMobileSidebar = Boolean(options?.closeMobileSidebar) && isMobile && openMobile;
|
|
26031
|
+
const createSessionPromise = requestCreateSession(nextCwd);
|
|
25063
26032
|
handleSelectSession(void 0);
|
|
25064
26033
|
clearSelectedSidebarSelection();
|
|
25065
26034
|
if (shouldCloseMobileSidebar) {
|
|
@@ -25076,7 +26045,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25076
26045
|
sessionStateRef.current = nextState;
|
|
25077
26046
|
conversationItemsStore.setItems(nextState.items);
|
|
25078
26047
|
setSessionState(nextState);
|
|
25079
|
-
if (await
|
|
26048
|
+
if (await createSessionPromise) return;
|
|
25080
26049
|
if (sessionStateRef.current.sessionKey !== optimisticSessionKey) return;
|
|
25081
26050
|
sessionStateRef.current = previousState;
|
|
25082
26051
|
conversationItemsStore.setItems(previousState.items);
|
|
@@ -25096,6 +26065,22 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25096
26065
|
setPendingMessages,
|
|
25097
26066
|
setSessionState
|
|
25098
26067
|
]);
|
|
26068
|
+
const createDiffLineCommentId = () => {
|
|
26069
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return `diff-comment:${crypto.randomUUID()}`;
|
|
26070
|
+
return `diff-comment:${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
26071
|
+
};
|
|
26072
|
+
const addComposerDiffLineComment = (comment) => {
|
|
26073
|
+
const text = comment.text.trim();
|
|
26074
|
+
const cwd = sessionStateRef.current.cwd?.trim() || "";
|
|
26075
|
+
if (!text || !cwd) return;
|
|
26076
|
+
setComposerDiffLineComments((current) => [...current, {
|
|
26077
|
+
...comment,
|
|
26078
|
+
id: createDiffLineCommentId(),
|
|
26079
|
+
cwd,
|
|
26080
|
+
text
|
|
26081
|
+
}]);
|
|
26082
|
+
composerPanelRef.current?.focusPrompt({ preventScroll: true });
|
|
26083
|
+
};
|
|
25099
26084
|
const onPickImages = async (files) => {
|
|
25100
26085
|
if (!files || files.length === 0) return;
|
|
25101
26086
|
const imageFiles = Array.from(files).filter((file) => file.type.startsWith("image/"));
|
|
@@ -25113,6 +26098,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25113
26098
|
}));
|
|
25114
26099
|
const currentPendingMessages = pendingDraftFollowUpMessages.length > 0 || pendingMessages.length > 0 ? [...pendingDraftFollowUpMessages, ...pendingMessages] : EMPTY_COMPOSER_PENDING_MESSAGES;
|
|
25115
26100
|
const composerDisabled = isSessionViewLoading;
|
|
26101
|
+
const displayedDiffLineComments = composerDisabled ? EMPTY_COMPOSER_DIFF_LINE_COMMENTS : composerDiffLineComments;
|
|
25116
26102
|
const displayedPendingMessages = composerDisabled ? EMPTY_COMPOSER_PENDING_MESSAGES : currentPendingMessages;
|
|
25117
26103
|
const displayedComposerImages = composerDisabled ? EMPTY_COMPOSER_IMAGES : composerImages;
|
|
25118
26104
|
const displayedComposerText = composerDisabled ? "" : composerDraftSeed.text;
|
|
@@ -25395,8 +26381,8 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25395
26381
|
const handleThemeChange = (value) => {
|
|
25396
26382
|
setThemeFamily(value);
|
|
25397
26383
|
};
|
|
25398
|
-
const handleThemePreviewChange = (value) => {
|
|
25399
|
-
previewThemeFamily(value);
|
|
26384
|
+
const handleThemePreviewChange = (value, colorMode) => {
|
|
26385
|
+
previewThemeFamily(value, colorMode);
|
|
25400
26386
|
};
|
|
25401
26387
|
const handleThemeColorModeChange = (value) => {
|
|
25402
26388
|
setColorMode(value);
|
|
@@ -25405,6 +26391,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25405
26391
|
activeSessionId,
|
|
25406
26392
|
awaitingFirstTurn: composerDisabled ? false : awaitingFirstTurn,
|
|
25407
26393
|
centerMessages: displaySettingsRef.current.centerMessages,
|
|
26394
|
+
composerDiffLineComments: displayedDiffLineComments,
|
|
25408
26395
|
composerImages: displayedComposerImages,
|
|
25409
26396
|
composerSkill: displayedComposerSkill,
|
|
25410
26397
|
composerSyncNonce: composerDraftSeed.syncNonce,
|
|
@@ -25421,6 +26408,9 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25421
26408
|
const composerActionsRef = useLatestRef({
|
|
25422
26409
|
abortSession,
|
|
25423
26410
|
onPickImages,
|
|
26411
|
+
removeDiffLineComment: (id) => {
|
|
26412
|
+
setComposerDiffLineComments((current) => current.filter((comment) => comment.id !== id));
|
|
26413
|
+
},
|
|
25424
26414
|
onRemoveComposerImage: (index) => {
|
|
25425
26415
|
setComposerImages((current) => current.filter((_, imageIndex) => imageIndex !== index));
|
|
25426
26416
|
},
|
|
@@ -26012,6 +27002,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
26012
27002
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppShellTabsController, {
|
|
26013
27003
|
actionsRef: composerActionsRef,
|
|
26014
27004
|
appUiStore,
|
|
27005
|
+
composerDiffLineComments: displayedDiffLineComments,
|
|
26015
27006
|
composerPanelRef,
|
|
26016
27007
|
contextUsageStore,
|
|
26017
27008
|
conversationFrameRef,
|
|
@@ -26034,6 +27025,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
26034
27025
|
onCloseFileViewTab: closeFileViewTab,
|
|
26035
27026
|
onCloseFileViewTabsToRight: closeFileViewTabsToRight,
|
|
26036
27027
|
onCloseOtherFileViewTabs: closeOtherFileViewTabs,
|
|
27028
|
+
onAddDiffLineComment: addComposerDiffLineComment,
|
|
26037
27029
|
onOpenFileViewTab: openFileViewTab,
|
|
26038
27030
|
onReorderFileViewTabs: reorderFileViewTabs,
|
|
26039
27031
|
rightSidebarStore,
|