Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
f967ea9
add initial implementation of harness creation helper. Created 'Creat…
richardw19 Apr 1, 2026
8969e1b
made ui changes for harness logo, creating harness page, etc.
jon3350 Apr 1, 2026
5c8663e
Merge pull request #25 from DIodide/feat/ui_changes
jon3350 Apr 6, 2026
59f602c
skills search improvement
cole-ramer Apr 6, 2026
5651b7f
buggy markdown viewer
cole-ramer Apr 6, 2026
4574086
improved skills viewer
cole-ramer Apr 6, 2026
43f97bd
skills viewer fix and lint fixes
cole-ramer Apr 6, 2026
d3e06eb
some skilll and minor bug fixes
cole-ramer Apr 6, 2026
763f7ad
html nesting fix
cole-ramer Apr 6, 2026
5cea48c
search authentication fix
cole-ramer Apr 6, 2026
73e7603
made ui changes for harness logo, creating harness page, etc.
jon3350 Apr 1, 2026
9fab805
fixes
cole-ramer Apr 7, 2026
c789d68
Merge pull request #29 from DIodide/fix/skills-search-improvement
cole-ramer Apr 7, 2026
365fbc0
feat: add TigerPath MCP and fix netid resolution
DIodide Apr 8, 2026
56b6c41
feat: require CLERK_SECRET_KEY at startup
DIodide Apr 8, 2026
58afc84
Merge pull request #30 from DIodide/feat/add-tigerpath
DIodide Apr 8, 2026
9c5ccec
add arcjet to CD
DIodide Apr 8, 2026
cffb2b7
Add Arcjet integration for usage tracking and rate limiting
DIodide Apr 8, 2026
11d789d
Merge remote-tracking branch 'origin/staging' into feat/add-arcjet-ra…
DIodide Apr 8, 2026
dab47ec
Enhance usage display and rate limiting functionality
DIodide Apr 8, 2026
db4fdaa
Make ARCJET_KEY optional so app starts without it
github-actions[bot] Apr 8, 2026
4a179c1
Revert "Make ARCJET_KEY optional so app starts without it"
DIodide Apr 8, 2026
7fa1df7
fix: fail-open on Arcjet outage so chat isn't blocked
DIodide Apr 8, 2026
98b2e5f
persistence refactor to remove extraneous orphan conversations
richardw19 Apr 8, 2026
5fc2ec1
Merge pull request #31 from DIodide/feat/add-arcjet-ratelimits
DIodide Apr 8, 2026
96cec09
improve the system prompt for the AI harness creation helper. better …
richardw19 Apr 8, 2026
f5ecfdf
fix: set ARCJET_KEY as Cloudflare Worker secret in CD
DIodide Apr 8, 2026
91ab9a9
fix: read ARCJET_KEY from import.meta.env for Cloudflare Workers
DIodide Apr 8, 2026
4060e0e
fix: inline ARCJET_KEY via Vite define for Cloudflare Workers
DIodide Apr 8, 2026
3afc8bf
system prompt
cole-ramer Apr 13, 2026
4053d4c
small fixes
cole-ramer Apr 13, 2026
855062c
added trim to edit page
cole-ramer Apr 13, 2026
4703eec
Merge pull request #32 from DIodide/feat/system-prompt
cole-ramer Apr 13, 2026
6bbe0d0
implemented MCP tool call commands
abubahmed Apr 14, 2026
611667c
Merge branch 'staging' into feat/harness_creation_helper
richardw19 Apr 15, 2026
3b1d095
Merge pull request #33 from DIodide/feat/add-commands
abubahmed Apr 15, 2026
9f5ec11
decoupled harness from sandbox. There is a manage harness and manage …
jon3350 Apr 18, 2026
c6e60bb
removed short cut to create sandbox with harness. made the panel resp…
jon3350 Apr 18, 2026
2a9219d
added workspaces
jon3350 Apr 18, 2026
05fa86f
edit mcps, remove slack and jira
richardw19 Apr 18, 2026
a48db83
Merge branch 'feat/harness_creation_helper' of https://github.com/DIo…
richardw19 Apr 18, 2026
a788aea
Merge branch 'staging' into feat/harness_creation_helper
richardw19 Apr 18, 2026
49fb4b4
add duplicate harness check warning, and fix small UX
richardw19 Apr 18, 2026
f196b64
Merge branch 'feat/harness_creation_helper' of https://github.com/DIo…
richardw19 Apr 18, 2026
b349501
refactor mcps, added feedback ratings to AI harness creation, added u…
richardw19 Apr 18, 2026
aeaf3b8
add sandbox and skills integration to Harness Creation AI, improved s…
richardw19 Apr 19, 2026
445d52f
feat: rose curve spinner replacing Loader2 and custom spinners
DIodide Apr 20, 2026
be337e6
Merge pull request #36 from DIodide/feat/rose-curve-spinner
DIodide Apr 20, 2026
4c4baa9
Merge remote-tracking branch 'origin/staging' into feat/workspaces
DIodide Apr 20, 2026
6552779
chore: drop unused Globe/HardDrive imports after merge
DIodide Apr 20, 2026
8292433
feat(workspaces): color picker, SSR-safe spinners, and quick-switch s…
DIodide Apr 20, 2026
5ee3554
feat: command palette (Cmd+K / Cmd+Shift+P) and onboarding race fix
DIodide Apr 21, 2026
fd3147f
fixed auth for user ratings, added limit to backend context length, f…
richardw19 Apr 21, 2026
8f80871
fix spoof bug and other minor bugs.
richardw19 Apr 21, 2026
d5ad2aa
sanitize skills prompt
richardw19 Apr 21, 2026
317f257
Merge pull request #34 from DIodide/feat/harness_creation_helper
richardw19 Apr 21, 2026
28ecbec
feat: header skills dropdown, combined sandbox selector, and Cmd+Shif…
DIodide Apr 21, 2026
e6a9147
delete workspace feature. added none as harness or sandbox option in …
jon3350 Apr 21, 2026
470d63d
fixed claude code review issues
jon3350 Apr 21, 2026
3a97b46
Revert "Feat/harness creation helper"
jon3350 Apr 21, 2026
bf3e4c6
Merge pull request #37 from DIodide/revert-34-feat/harness_creation_h…
jon3350 Apr 21, 2026
c475ebf
Merge pull request #35 from DIodide/feat/workspaces
jon3350 Apr 21, 2026
63439a6
test: add unit test suite and CI across frontend, convex, and fastapi
DIodide Apr 21, 2026
d7cbe30
ci: cache bun install dependencies across Tests workflow runs
DIodide Apr 21, 2026
cd9c6fd
Merge pull request #38 from DIodide/feat/test-coverage
DIodide Apr 21, 2026
3470561
fix: batch of 8 onboarding, MCP, harness, chat, and auth bug fixes
DIodide Apr 21, 2026
455d7dc
fix(workspaces): wire refreshHealth through MCP reconnect surface
DIodide Apr 21, 2026
d71b9a6
Merge pull request #39 from DIodide/fix/ui-chat-bug-batch
DIodide Apr 21, 2026
dc0f3c8
added harness creation shortcut
jon3350 Apr 22, 2026
5df1338
updated feat/workspaces-sandbox-creation-shortcut with staging
jon3350 Apr 22, 2026
60280d5
merge harness creation helper with workspaces.
richardw19 Apr 22, 2026
b6a2a78
fix skills prompt injection
richardw19 Apr 22, 2026
3b04c49
Merge pull request #41 from DIodide/feat/workspaces-sandbox-creation-…
richardw19 Apr 22, 2026
a006c9d
ci: route frontend CD through per-env GH Environments (#42)
DIodide Apr 23, 2026
28ffd44
feat: restore last chat on workspace switch (8h window) (#43)
DIodide Apr 23, 2026
c8fd664
chore: 10x default daily/weekly cost limits (#47)
DIodide Apr 28, 2026
7e97be6
test: update default cost limit assertions to match 10x bump (#48)
DIodide Apr 28, 2026
ddfc1b1
feat(usage): add internal resetAllCostLimits mutation (#49)
DIodide Apr 28, 2026
0f3bedb
fix(convex): exclude test files from convex tsconfig (#50)
DIodide Apr 28, 2026
387862b
added, removed, and edited models list and config
abubahmed Apr 28, 2026
1061684
feat(mcp): inline add-MCP flow from chat header tooltip (#51)
DIodide Apr 28, 2026
d94817f
fix(chat): continue on max_tokens truncation, raise token limits (#52)
DIodide Apr 28, 2026
de488cb
fix(chat): detect truncation by usage, bump thinking cap, bail on rep…
DIodide Apr 28, 2026
0c9b3f0
fix(skills): cap Manage-skills modal height on short viewports (#54)
DIodide Apr 28, 2026
eed8e1e
feat(landing): redesign with accurate copy and product mocks (#55)
DIodide Apr 28, 2026
3bc8f58
feat(seed): add seedDemoForUser internal mutation (#56)
DIodide Apr 28, 2026
b8523f7
feat(seed): add seedConversationsForUser internal mutation (#57)
DIodide Apr 28, 2026
80fb9a3
fix intermediate chat manage harness
jon3350 Apr 28, 2026
39288b1
same fix on worksacpes
jon3350 Apr 28, 2026
f7618f0
fixed code review bug with multiple side effects
jon3350 Apr 28, 2026
7ca9458
Merge pull request #58 from DIodide/fix/intermediate-chat-manage-harness
jon3350 Apr 28, 2026
a40f92b
fix(chat): raise MAX_CONSECUTIVE_TRUNCATIONS 5 → 20 (#59)
DIodide Apr 29, 2026
053d9ee
Revert "fix(chat): raise MAX_CONSECUTIVE_TRUNCATIONS 5 → 20 (#59)" (#60)
DIodide Apr 29, 2026
82627fd
fix(chat): raise MAX_CONSECUTIVE_TRUNCATIONS 5 → 20 (#61)
DIodide Apr 29, 2026
21523f5
added opus 4.6 fast
abubahmed Apr 29, 2026
abc0aee
fix markdown styling
richardw19 Apr 30, 2026
f84a39b
Merge pull request #63 from DIodide/fix/harness_creation_style
richardw19 Apr 30, 2026
2a17e19
fix(workspaces): empty state + disabled input when workspace has no h…
DIodide Apr 30, 2026
2776b3f
landing: drop integrations strip, generalize hero example, broaden st…
DIodide Apr 30, 2026
8322d98
MCP auth fix
cole-ramer May 8, 2026
0a42c42
supresses pop-up fix
cole-ramer May 9, 2026
cf25e4c
Merge pull request #66 from DIodide/fix/princeton-mcps-auth
cole-ramer May 9, 2026
8f84fbd
bug/polish fixes. max sandboxes = 5, harness editing status location,…
jon3350 May 9, 2026
2870fee
max chat input length = 16k chars
jon3350 May 9, 2026
1356675
workspaces polish
jon3350 May 9, 2026
9df6d61
fixed review changes
jon3350 May 10, 2026
21942f0
Merge pull request #67 from DIodide/feat/final-polish
jon3350 May 10, 2026
5898e37
removed bad mcps
cole-ramer May 10, 2026
4dacc8e
updated stale tests
jon3350 May 10, 2026
a542cf6
Merge pull request #68 from DIodide/feat/final-polish
jon3350 May 10, 2026
4b0863b
removed sandboxes, patched emphermial sandboxes
jon3350 May 10, 2026
6013ea7
Merge pull request #69 from DIodide/feat/final-polish
jon3350 May 10, 2026
e7d9641
staging fix
cole-ramer May 10, 2026
0a59853
Merge branch 'main' into staging
cole-ramer May 10, 2026
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
21 changes: 5 additions & 16 deletions .github/workflows/backend-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Deploy Backend

on:
push:
branches: [staging, main]
branches: [staging]
paths:
- "packages/fastapi/**"
- ".github/workflows/backend-cd.yml"
Expand All @@ -18,17 +18,6 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Determine environment
id: env
run: |
if [ "${{ github.ref }}" = "refs/heads/main" ]; then
echo "deploy_path=/opt/harness-api" >> "$GITHUB_OUTPUT"
echo "service=harness-api" >> "$GITHUB_OUTPUT"
else
echo "deploy_path=/opt/harness-api-staging" >> "$GITHUB_OUTPUT"
echo "service=harness-api-staging" >> "$GITHUB_OUTPUT"
fi

- name: Set up SSH
run: |
mkdir -p ~/.ssh
Expand All @@ -44,15 +33,15 @@ jobs:
--exclude='__pycache__' \
--exclude='.git' \
-e "ssh -i ~/.ssh/harness.pem" \
packages/fastapi/ ec2-user@52.45.218.243:${{ steps.env.outputs.deploy_path }}/
packages/fastapi/ ec2-user@52.45.218.243:/opt/harness-api-staging/

- name: Install dependencies and restart
run: |
ssh -i ~/.ssh/harness.pem ec2-user@52.45.218.243 << EOF
cd ${{ steps.env.outputs.deploy_path }}
cd /opt/harness-api-staging
python3.11 -m venv .venv 2>/dev/null || true
.venv/bin/pip install -q -r requirements.txt
sudo systemctl restart ${{ steps.env.outputs.service }}
sudo systemctl restart harness-api-staging
sleep 2
sudo systemctl is-active ${{ steps.env.outputs.service }}
sudo systemctl is-active harness-api-staging
EOF
29 changes: 11 additions & 18 deletions .github/workflows/frontend-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Deploy Frontend

on:
push:
branches: [staging, main]
branches: [staging]
paths:
- "apps/web/**"
- "packages/convex-backend/**"
Expand All @@ -15,7 +15,7 @@ concurrency:
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
environment: staging
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -31,33 +31,26 @@ jobs:
env:
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}

- name: Determine environment
id: env
run: |
if [ "${{ github.ref }}" = "refs/heads/main" ]; then
echo "env_name=production" >> "$GITHUB_OUTPUT"
echo "fastapi_url=${{ secrets.FASTAPI_URL_PROD }}" >> "$GITHUB_OUTPUT"
else
echo "env_name=staging" >> "$GITHUB_OUTPUT"
echo "fastapi_url=${{ secrets.FASTAPI_URL_STAGING }}" >> "$GITHUB_OUTPUT"
fi

- name: Build frontend
run: cd apps/web && bun run build
env:
VITE_CONVEX_URL: ${{ secrets.VITE_CONVEX_URL }}
VITE_CLERK_PUBLISHABLE_KEY: ${{ secrets.VITE_CLERK_PUBLISHABLE_KEY }}
CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }}
VITE_FASTAPI_URL: ${{ steps.env.outputs.fastapi_url }}
VITE_FASTAPI_URL: ${{ secrets.FASTAPI_URL_STAGING }}
ARCJET_KEY: ${{ secrets.ARCJET_KEY }}

- name: Set Cloudflare Worker secrets
run: |
echo "${{ secrets.ARCJET_KEY }}" | cd apps/web && npx wrangler secret put ARCJET_KEY --name harness-web-staging
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

# The @cloudflare/vite-plugin flattens only top-level vars into the
# generated dist/server/wrangler.json and drops env.* blocks, so
# `--env` alone picks the right Worker name but leaves runtime vars
# pointing at the top-level defaults. Override at deploy time.
- name: Deploy to Cloudflare Workers
run: |
cd apps/web && npx wrangler deploy --env ${{ steps.env.outputs.env_name }} \
--var VITE_CONVEX_URL:"${{ secrets.VITE_CONVEX_URL }}" \
--var VITE_CLERK_PUBLISHABLE_KEY:"${{ secrets.VITE_CLERK_PUBLISHABLE_KEY }}"
run: cd apps/web && npx wrangler deploy --name harness-web-staging
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
109 changes: 109 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Tests

on:
push:
branches: [main, staging]
pull_request:
branches: [main, staging]

concurrency:
group: tests-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
frontend:
name: Frontend (vitest)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Cache Bun install
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Run tests with coverage
working-directory: apps/web
run: bun run test:coverage

- name: Upload coverage artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: frontend-coverage
path: apps/web/coverage
retention-days: 14

convex:
name: Convex (vitest)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Cache Bun install
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Run tests with coverage
working-directory: packages/convex-backend
run: bun run test:coverage

- name: Upload coverage artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: convex-coverage
path: packages/convex-backend/coverage
retention-days: 14

fastapi:
name: FastAPI (pytest)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: pip
cache-dependency-path: packages/fastapi/requirements-dev.txt

- name: Install dependencies
working-directory: packages/fastapi
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt

- name: Run tests with coverage
working-directory: packages/fastapi
run: pytest --cov --cov-report=term --cov-report=xml --cov-report=html

- name: Upload coverage artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: fastapi-coverage
path: |
packages/fastapi/htmlcov
packages/fastapi/coverage.xml
retention-days: 14
3 changes: 3 additions & 0 deletions apps/web/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ VITE_CONVEX_URL=https://your-project.convex.cloud

# FastAPI backend URL
VITE_FASTAPI_URL=http://localhost:8000

# Arcjet (server-only rate limiting / shield — copy from Arcjet dashboard)
ARCJET_KEY=
13 changes: 13 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@
"deploy:staging": "vite build && wrangler deploy --env staging",
"deploy:production": "vite build && wrangler deploy --env production",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"format": "biome format --write",
"lint": "biome lint",
"check": "biome check",
"check-types": "tsc --noEmit"
},
"dependencies": {
"@arcjet/headers": "^1.3.1",
"@arcjet/ip": "^1.3.1",
"@arcjet/protocol": "^1.3.1",
"@arcjet/transport": "^1.3.1",
"@clerk/clerk-react": "^5.60.0",
"@clerk/tanstack-react-start": "^0.29.1",
"@convex-dev/react-query": "^0.1.0",
"@harness/convex-backend": "workspace:*",
Expand All @@ -33,8 +40,10 @@
"@xterm/addon-fit": "^0.11.0",
"@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0",
"arcjet": "^1.3.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"convex": "^1.31.7",
"geist": "^1.7.0",
"highlight.js": "^11.11.1",
Expand All @@ -51,6 +60,7 @@
"tailwindcss": "^4.1.18",
"tw-animate-css": "^1.3.6",
"use-sync-external-store": "^1.6.0",
"vinxi": "^0.5.11",
"vite-tsconfig-paths": "^6.0.2",
"zod": "^4.1.11"
},
Expand All @@ -59,11 +69,14 @@
"@cloudflare/vite-plugin": "^1.30.3",
"@tanstack/devtools-vite": "^0.3.11",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.1",
"@types/node": "^22.10.2",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
"@vitejs/plugin-react": "^5.0.4",
"@vitest/coverage-v8": "^3.0.5",
"jsdom": "^27.0.0",
"typescript": "5.9.2",
"vite": "^7.1.7",
Expand Down
77 changes: 77 additions & 0 deletions apps/web/src/components/attachment-chip.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import type { PendingAttachment } from "../hooks/use-file-attachments";
import { AttachmentChip } from "./attachment-chip";

function makeAttachment(
partial: Partial<PendingAttachment> = {},
): PendingAttachment {
return {
localId: "id-1",
previewUrl: null,
mimeType: "image/png",
status: "ready",
fileName: "file.png",
fileSize: 100,
...partial,
};
}

describe("AttachmentChip", () => {
it("renders an image preview when previewUrl is set and mime is image/*", () => {
const att = makeAttachment({
mimeType: "image/png",
previewUrl: "blob:abc",
fileName: "pic.png",
});
render(<AttachmentChip attachment={att} onRemove={() => {}} />);
const img = screen.getByAltText("pic.png") as HTMLImageElement;
expect(img).toBeInTheDocument();
expect(img.src).toContain("blob:abc");
});

it("renders a file-name label with icon for PDFs", () => {
const att = makeAttachment({
mimeType: "application/pdf",
fileName: "notes.pdf",
});
render(<AttachmentChip attachment={att} onRemove={() => {}} />);
expect(screen.getByText("notes.pdf")).toBeInTheDocument();
});

it("renders a file-name label with icon for audio", () => {
const att = makeAttachment({
mimeType: "audio/wav",
fileName: "sound.wav",
});
render(<AttachmentChip attachment={att} onRemove={() => {}} />);
expect(screen.getByText("sound.wav")).toBeInTheDocument();
});

it("shows an uploading overlay when status is uploading", () => {
const att = makeAttachment({ status: "uploading" });
const { container } = render(
<AttachmentChip attachment={att} onRemove={() => {}} />,
);
// Overlay uses bg-background/70 — spinner is rendered inside it.
expect(container.querySelector(".bg-background\\/70")).toBeTruthy();
});

it("shows an 'Error' label when status is error", () => {
const att = makeAttachment({ status: "error" });
render(<AttachmentChip attachment={att} onRemove={() => {}} />);
expect(screen.getByText("Error")).toBeInTheDocument();
});

it("calls onRemove when the X button is clicked", () => {
const onRemove = vi.fn();
const att = makeAttachment({
mimeType: "application/pdf",
fileName: "a.pdf",
});
render(<AttachmentChip attachment={att} onRemove={onRemove} />);
// The X button is the only <button> in the chip.
fireEvent.click(screen.getByRole("button"));
expect(onRemove).toHaveBeenCalledTimes(1);
});
});
5 changes: 3 additions & 2 deletions apps/web/src/components/attachment-chip.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FileText, Loader2, Music, X } from "lucide-react";
import { FileText, Music, X } from "lucide-react";
import type { PendingAttachment } from "../hooks/use-file-attachments";
import { RoseCurveSpinner } from "./rose-curve-spinner";

export function AttachmentChip({
attachment,
Expand Down Expand Up @@ -33,7 +34,7 @@ export function AttachmentChip({

{attachment.status === "uploading" && (
<div className="absolute inset-0 flex items-center justify-center bg-background/70">
<Loader2 size={10} className="animate-spin text-foreground" />
<RoseCurveSpinner size={10} className="text-foreground" />
</div>
)}

Expand Down
Loading
Loading