Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .pnpm-store/v11/index.db
Binary file not shown.
4 changes: 2 additions & 2 deletions apps/web/src/components/ComposerCitationNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ function ComposerCitationDecorator(props: { citation: AssistantCitation; nodeKey
);
return accepted;
};
/** Cancelling a comment on a just-created citation removes the chip the cite action added. */
const onRemove = () => {
if (!editor.isEditable()) return;
editor.update(
Expand All @@ -114,7 +115,6 @@ function ComposerCitationDecorator(props: { citation: AssistantCitation; nodeKey
);
editor.getRootElement()?.focus({ preventScroll: true });
};

return (
<span
className="inline-flex min-w-0 max-w-full"
Expand All @@ -124,6 +124,7 @@ function ComposerCitationDecorator(props: { citation: AssistantCitation; nodeKey
>
<AssistantCitationChip
citation={props.citation}
composer
commentEditor={{
open: commentTarget !== null,
sourceAnchor: commentTarget?.sourceAnchor,
Expand All @@ -139,7 +140,6 @@ function ComposerCitationDecorator(props: { citation: AssistantCitation; nodeKey
return true;
},
}}
onRemove={onRemove}
/>
</span>
);
Expand Down
25 changes: 25 additions & 0 deletions apps/web/src/components/PullRequestContextDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { PullRequestContextMetadata } from "@t3tools/contracts";
import { ArrowRightIcon } from "lucide-react";

import { cn } from "~/lib/utils";

import { resolvePullRequestState } from "./pullRequest/pullRequestPresentation";

export function PullRequestContextDetails({ metadata }: { metadata: PullRequestContextMetadata }) {
const state = resolvePullRequestState(metadata);
return (
<div className="max-w-80 space-y-1 overflow-hidden py-0.5 text-left">
<div className="flex items-center gap-1.5 text-xs font-medium">
<state.Icon className={cn("size-3.5 shrink-0", state.toneClassName)} />
<span className="text-foreground">Pull request #{metadata.number}</span>
<span className={state.toneClassName}>{state.label}</span>
</div>
<div className="wrap-break-word text-foreground">{metadata.title}</div>
<div className="flex min-w-0 items-center gap-1 text-secondary-label text-[10px]">
<code className="truncate">{metadata.headBranch}</code>
<ArrowRightIcon className="size-3 shrink-0" aria-hidden="true" />
<code className="truncate">{metadata.baseBranch}</code>
</div>
</div>
);
}
32 changes: 10 additions & 22 deletions apps/web/src/components/chat/AssistantCitationChip.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { AssistantCitation } from "@t3tools/contracts";
import { serializeAssistantCitation } from "@t3tools/shared/assistantCitations";
import { Link, useNavigate } from "@tanstack/react-router";
import { PencilIcon, QuoteIcon, XIcon } from "lucide-react";
import { PencilIcon, QuoteIcon } from "lucide-react";
import { useEffect, useEffectEvent, useRef, type MouseEvent as ReactMouseEvent } from "react";
import {
findAssistantCitationSourceAnchor,
Expand All @@ -18,6 +18,7 @@ import {
COMPOSER_INLINE_CHIP_DISMISS_BUTTON_CLASS_NAME,
COMPOSER_INLINE_CHIP_ICON_CLASS_NAME,
COMPOSER_INLINE_CHIP_LABEL_CLASS_NAME,
CONTEXT_INLINE_CHIP_TONE_CLASS_NAMES,
} from "../composerInlineChip";
import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
import { Popover, PopoverPopup, PopoverTrigger } from "../ui/popover";
Expand All @@ -27,16 +28,16 @@ import { composerFloatingLayerProps } from "./composerEventScope";

const CITATION_ACTION_BUTTON_CLASS_NAME = cn(
COMPOSER_INLINE_CHIP_DISMISS_BUTTON_CLASS_NAME,
"text-primary/80 hover:bg-primary/10 hover:text-primary",
"text-current hover:bg-[color-mix(in_oklab,var(--context-chip-accent)_17%,transparent)] hover:text-current",
);

export function AssistantCitationChip({
citation,
onRemove,
composer = false,
commentEditor,
}: {
citation: AssistantCitation;
onRemove?: () => void;
composer?: boolean;
commentEditor?: {
open: boolean;
sourceAnchor?: AssistantCitationSourceAnchor | undefined;
Expand Down Expand Up @@ -93,7 +94,7 @@ export function AssistantCitationChip({
const composerSourceLink = (
<Link
{...sourceLinkProps}
className="inline-flex h-full min-w-0 items-center gap-[0.33em] rounded-sm text-inherit no-underline focus-visible:outline-2 focus-visible:outline-primary"
className="inline-flex h-full min-w-0 items-center gap-[0.33em] rounded-sm text-inherit no-underline focus-visible:outline-2 focus-visible:outline-[var(--contrast-foreground)]"
aria-label={`View cited assistant text: ${label}`}
>
<QuoteIcon aria-hidden="true" className={COMPOSER_INLINE_CHIP_ICON_CLASS_NAME} />
Expand All @@ -103,7 +104,7 @@ export function AssistantCitationChip({
const chatSourceLink = (
<Link
{...sourceLinkProps}
className="inline-flex h-full min-w-0 items-center gap-[0.33em] rounded-sm text-inherit no-underline hover:bg-primary/10 focus-visible:outline-2 focus-visible:outline-primary"
className="inline-flex h-full min-w-0 items-center gap-[0.33em] rounded-sm text-inherit no-underline hover:bg-[color-mix(in_oklab,var(--context-chip-accent)_17%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--contrast-foreground)]"
aria-label={`View cited assistant text: ${label}`}
>
<QuoteIcon aria-hidden="true" className={COMPOSER_INLINE_CHIP_ICON_CLASS_NAME} />
Expand All @@ -113,14 +114,14 @@ export function AssistantCitationChip({
return (
<span
className={cn(
onRemove ? COMPOSER_INLINE_CHIP_CLASS_NAME : CHAT_INLINE_CHIP_CLASS_NAME,
"border-primary/20 bg-primary/8 text-primary",
composer ? COMPOSER_INLINE_CHIP_CLASS_NAME : CHAT_INLINE_CHIP_CLASS_NAME,
CONTEXT_INLINE_CHIP_TONE_CLASS_NAMES.citation,
)}
contentEditable={false}
data-assistant-citation-chip="true"
data-markdown-copy={serializeAssistantCitation(citation)}
>
{onRemove ? (
{composer ? (
composerSourceLink
) : (
<Tooltip>
Expand Down Expand Up @@ -181,19 +182,6 @@ export function AssistantCitationChip({
) : null}
</Popover>
) : null}
{onRemove ? (
<button
type="button"
onClick={onRemove}
aria-label="Remove assistant citation"
className={cn(
COMPOSER_INLINE_CHIP_DISMISS_BUTTON_CLASS_NAME,
"text-primary/85 hover:bg-primary/10 hover:text-primary",
)}
>
<XIcon aria-hidden="true" className="size-[0.85em]" />
</button>
) : null}
</span>
);
}
29 changes: 28 additions & 1 deletion apps/web/src/components/chat/ChatComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ import {
composerContextRecordsFromDraft,
uploadedContextRecordFromDraft,
} from "../composerContextPresentation";
import { useOpenPrLink } from "~/lib/openPullRequestLink";
import {
collectInlineContextIds,
type ComposerContextReference,
Expand Down Expand Up @@ -243,6 +244,7 @@ import {
} from "./ContextWindowMeter.logic";
import {
attachVideoThumbnail,
buildAttachmentVideoPreview,
buildExpandedImagePreview,
type ExpandedImagePreview,
} from "./ExpandedImagePreview";
Expand Down Expand Up @@ -906,6 +908,7 @@ import {
import { type AppModelOption, getAppModelOptionsForInstance } from "../../modelSelection";
import type { UnifiedSettings } from "@t3tools/contracts/settings";
import {
isVideoAttachment,
type ChatMessage,
type SessionPhase,
type Thread,
Expand Down Expand Up @@ -1566,14 +1569,38 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
}, [composerImages, composerPreviewAnnotations]);
const nonPersistedComposerImageIds = attachmentDraft.nonPersistedImageIds;
const uploadsByImageId = useAttachmentUploadStore((state) => state.uploadsByImageId);
const openPrLink = useOpenPrLink(routeKind === "server" ? routeThreadRef : undefined);
const composerContextActions = useMemo(
() => ({
expandImage: (imageId: string) => {
const preview = buildExpandedImagePreview(composerImages, imageId);
if (preview) onExpandImage(preview);
},
expandVideo: (fileId: string) => {
const file = composerFiles.find((candidate) => candidate.id === fileId);
if (!file || !isVideoAttachment(file)) return;
const localPreview = buildExpandedImagePreview([file], file.id);
if (localPreview) {
onExpandImage(localPreview);
return;
}
if (file.uploadedAttachmentId === undefined || file.uploadEnvironmentId !== environmentId) {
return;
}
const persistedPreview = buildAttachmentVideoPreview(environmentId, {
type: "file",
id: file.uploadedAttachmentId,
name: file.name,
mimeType: file.mimeType,
sizeBytes: file.sizeBytes,
});
if (persistedPreview) onExpandImage(persistedPreview);
},
openPullRequest: (event: React.MouseEvent<HTMLElement>, url: string) => {
openPrLink(event, url);
},
}),
[composerImages, onExpandImage],
[composerFiles, composerImages, environmentId, onExpandImage, openPrLink],
);
const composerContextRecords = useMemo(
() =>
Expand Down
18 changes: 14 additions & 4 deletions apps/web/src/components/chat/ComposerPendingTerminalContexts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,30 @@ import {
formatTerminalContextLabel,
isTerminalContextExpired,
} from "~/lib/terminalContext";
import type { ContextPresentationCapability } from "../contextPresentationRegistry";
import { TerminalContextInlineChip } from "./TerminalContextInlineChip";

interface ComposerPendingTerminalContextChipProps {
context: TerminalContextDraft;
detailsMode: ContextPresentationCapability["details"];
}

export function ComposerPendingTerminalContextChip({
context,
detailsMode,
}: ComposerPendingTerminalContextChipProps) {
const label = formatTerminalContextLabel(context);
const expired = isTerminalContextExpired(context);
const tooltipText = expired
? `Terminal context expired. Remove and re-add ${label} to include it in your message.`
: context.text;

return <TerminalContextInlineChip label={label} tooltipText={tooltipText} expired={expired} />;
return (
<TerminalContextInlineChip
label={label}
terminalLabel={context.terminalLabel}
lineStart={context.lineStart}
lineEnd={context.lineEnd}
text={context.text}
expired={expired}
detailsMode={detailsMode}
/>
);
}
Loading
Loading