feat(composer): inline @file and /skill tags, commands anywhere, project drag-and-drop (#2066)

Closes #1981

@file references and /skill commands become inline tags anywhere in the prompt, in Home and in a conversation. Tags are edited as a unit (Backspace/Delete, arrows) and are not committed mid-IME composition. Files and folders dragged from the Project view become references, mapped into the task worktree; paths outside the project, traversal and relative paths are rejected, and a deleted reference can be dropped again.

Co-authored-by: panda-student <[email protected]>
Цей коміт міститься в:
SunZhiQiang authored and GitHub committed 2026-11-08 05:54:24 +08:00
1 джерело 45a1132ece
коміт ff7473a277
17 files changed
+545 -115

No files matched your search

+16
Переглянути файл
@@ -0,0 +1,16 @@
/* Equal negative margins preserve native textarea wrapping and caret positions. */
.tag {
padding: 1px 3px;
margin: 0 -3px;
border-radius: var(--radius-selection);
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
color: var(--fg-strong);
background: color-mix(in srgb, var(--fg) 12%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg) 20%, transparent);
}
.accent {
color: var(--accent);
background: color-mix(in srgb, var(--accent) 20%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent);
}
+8
Переглянути файл
@@ -0,0 +1,8 @@
import type { ReactNode } from "react";
import clsx from "clsx";
import styles from "./InlineTag.module.css";
/** A text-sized tag that preserves glyph positions in mirrored inputs. */
export function InlineTag({ children, accent = false }: { children: ReactNode; accent?: boolean }) {
return <span className={clsx(styles.tag, accent && styles.accent)}>{children}</span>;
}
+1
Переглянути файл
@@ -67,6 +67,7 @@ const ICONS = {
"file-json": "fileTypes/json",
"file-md": "fileTypes/markdown",
"file-image": "fileTypes/image",
paperclip: "openidea/general/paperclip",
"file-config": "fileTypes/config",
"file-python": "fileTypes/python",
"file-jupyter": "fileTypes/jupyter",
+1
Переглянути файл
@@ -40,3 +40,4 @@ export { useSelectionBoundary } from "./useSelectionBoundary";
export { useSanitizedField } from "./useSanitizedField";
export * from "./rowSelection";
export * from "./LogPane";
export * from "./InlineTag";
+4
Переглянути файл
@@ -0,0 +1,4 @@
<!-- OpenIDEA: attach / reference a file (paperclip) -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.29 7.37l-6.13 6.13a4 4 0 0 1-5.66-5.66l6.13-6.13a2.67 2.67 0 0 1 3.77 3.77l-6.13 6.13a1.33 1.33 0 0 1-1.89-1.89l5.66-5.65" stroke="#6C707E" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Після

Ширина:  |  Висота:  |  Розмір: 380 B

+1 -1
Переглянути файл
@@ -13,7 +13,7 @@ export interface DragData {
payload: string;
}
/** Project files dragged from the Project view: `payload` is the paths joined by `\n`. */
/** Project files dragged from the Project view: `payload` is the paths joined by `\n`, folders ending with `/`. */
export const FILES_DRAG = "application/x-openidea-files";
export interface DropTarget {