Adds a "parent" column option to the inbox column toggle dropdown.
When enabled, sub-issues display the parent's identifier (e.g. PAP-123)
with the parent title as a tooltip. Uses the existing issueById lookup
map to resolve parent info without additional API calls.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- When no sub-issues exist, show "Add sub-issue" button alongside
"Upload attachment" and "New document" in the action row
- When sub-issues exist, show them in a dedicated section above
Documents with "Sub-issues" header and "Add sub-issue" button
- Remove the sub-issues tab from the comments/activity tabs
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Image attachments now render in a 4-column grid with square aspect ratio
and center-cropped thumbnails. Clicking opens the existing gallery modal.
Hover reveals a trash icon; clicking it shows an inline confirmation
overlay before deleting. Non-image attachments retain the original list
layout.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
On mobile, the search input, tab selector, and "Show / hide columns" button
were all crammed into one row causing horizontal overflow. Now:
- Search appears as a full-width row above the tabs on mobile
- "Show / hide columns" button is hidden on mobile (columns are desktop-only)
- Desktop layout is unchanged
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add overflow-hidden to the outer container to prevent horizontal scroll
- Add min-w-0 to grid children so long monospace content in inputs
respects container width instead of expanding it
- Truncate the workspace name heading for long names
- Add min-w-0 to the header name container
Co-Authored-By: Paperclip <noreply@paperclip.ing>
When unchecking the "Inherit project workspace runtime config" checkbox,
if the runtime config field is empty, automatically populate it with the
inherited config value so the user has a starting point to edit from.
Existing values are preserved and never overwritten.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Reduce card padding on small screens (p-4 → p-4 sm:p-5)
- Reduce spacing between sections on mobile (space-y-4 sm:space-y-6)
- Scale heading text (text-xl sm:text-2xl)
- Truncate long description on mobile, show full on sm+
- Reduce textarea min-heights on mobile (sm: prefix for larger sizes)
- Stack linked issue cards vertically on mobile, horizontal scroll on sm+
- Remove min-width constraint on linked issue cards on mobile
Co-Authored-By: Paperclip <noreply@paperclip.ing>
When dragging files like .zip onto the issue description editor, non-image
files are now uploaded as attachments instead of being silently ignored.
Images continue to be handled inline by MDXEditor's image plugin.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The archive mutation was only using CSS opacity to hide items while the
network request was in flight. When the query refetch completed or the
archiving timer expired, the item could reappear. Now we optimistically
remove the item from React Query caches on mutate, snapshot previous
data for rollback on error, and sync with the server in onSettled.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
fixes https://github.com/paperclipai/paperclip/issues/2336
## Thinking Path
<!--
Required. Trace your reasoning from the top of the project down to this
specific change. Start with what Paperclip is, then narrow through the
subsystem, the problem, and why this PR exists. Use blockquote style.
Aim for 5–8 steps. See CONTRIBUTING.md for full examples.
-->
- Paperclip allows to manage projects
- During the project creation you can optionally enter a description
- In the project overview or configuration you can edit the description
- However, you cannot remove the description
- The user should be able to remove the project description because it's
an optional property
- This pull request fixes the frontend bug that prevented the user to
remove/clear the project description
## What Changed
<!-- Bullet list of concrete changes. One bullet per logical unit. -->
- project description can be cleared in "project configuration" and
"project overview"
## Verification
<!--
How can a reviewer confirm this works? Include test commands, manual
steps, or both. For UI changes, include before/after screenshots.
-->
In project configuration or project overview:
- In the description field remove/clear the text
## Risks
<!--
What could go wrong? Mention migration safety, breaking changes,
behavioral shifts, or "Low risk" if genuinely minor.
-->
- none
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
Adds two new webhook trigger signing modes for external provider
compatibility:
- github_hmac: accepts X-Hub-Signature-256 header with
HMAC-SHA256(secret, rawBody), no timestamp prefix. Compatible with
GitHub, Sentry, and services following the same standard.
- none: no authentication; the 24-char hex publicId in the URL acts
as the shared secret. For services that cannot add auth headers.
The replay window UI field is hidden when these modes are selected
since neither uses timestamp-based replay protection.
Closes#1892
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Export and Import buttons in CompanySettings used plain <a href>
anchors which bypass the router's company-prefix wrapper. The links
resolved to /company/export and /company/import instead of
/:prefix/company/export, showing a 'Company not found' error.
Replace both <a href> elements with <Link to> from @/lib/router, which
calls applyCompanyPrefix under the hood and correctly resolves to
/:prefix/company/{export,import} regardless of which company is active.
Fixes: #2910
Add childIssues to the useEffect dependency array so the Properties panel
is refreshed whenever the child issue list updates (e.g. an agent creates
or deletes a sub-task while the panel is open). Previously the panel kept
the snapshot from the initial render of the parent issue.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Move parent-task link out of the 2-column PropertyRow layout and into
a dedicated full-width section at the bottom of the panel, separated
by a Separator. Sub-tasks are listed in the same section when present.
Each item shows a StatusIcon aligned with the first line of wrapped
title text (items-start + mt-0.5 on the icon wrapper).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Replaces 12+ inline toggle button implementations across the app with a
shared ToggleSwitch component that scales up on mobile for better touch
targets. Default size is h-6/w-10 on mobile, h-5/w-9 on desktop; "lg"
variant is h-7/w-12 on mobile, h-6/w-11 on desktop.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Adds a sign out section at the bottom of the general settings page.
Uses authApi.signOut() and invalidates the session query to redirect
to the login page.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Replace the client-side-only override store with a real server-side
toggle. When a developer pauses the external override, the server swaps
ALL adapter behavior back to the builtin — execute handler, model listing,
config schema, detection — not just the UI parser.
Server changes:
- registry.ts: builtinFallbacks map + pausedOverrides set + setOverridePaused()
- routes/adapters.ts: PATCH /api/adapters/:type/override endpoint + overridePaused in list
UI changes:
- adapters.ts: setOverridePaused API method + overridePaused on AdapterInfo
- AdapterManager: overrideMutation calls server, instant feedback via invalidate()
- use-disabled-adapters.ts: reads adapter.overridePaused from server response
Removed:
- disabled-overrides-store.ts: no longer needed (server is the source of truth)
Note: already-running agent sessions keep the adapter they started with.
Only new sessions use the swapped adapter.
Builtin adapter types (hermes_local, openclaw_gateway, etc.) could not
be overridden by external adapters on the UI side. The registry always
returned the built-in parser, ignoring the external ui-parser.js shipped
by packages like hermes-paperclip-adapter.
Changes:
- registry.ts: full override lifecycle with generation guard for stale loads
- disabled-overrides-store.ts: client-side override pause state with
useSyncExternalStore reactivity (persisted to localStorage)
- use-disabled-adapters.ts: subscribe to override store changes
- AdapterManager.tsx: separate controls for override pause (client-side)
vs menu visibility (server-side), virtual builtin rows with badges
- adapters.ts: allow reload/reinstall of builtin types when overridden
When an external plugin overrides a built-in adapter type, the
GET /api/adapters response now includes overriddenBuiltin: true. The
Adapter Manager shows an 'Overrides built-in' badge on such adapters.
- Sort GET /api/adapters alphabetically by type (reload no longer shuffles)
- Show red Package icon for npm adapters, amber FolderOpen for local path
- Add reinstall confirmation dialog with current vs latest npm version
- Enable Vite polling when running on /mnt/ (WSL inotify doesn't work on NTFS)
- Fix external adapters (hermes, droid) not auto-selected when
navigating with ?adapterType= param — was using a stale
module-level Set built before async adapter registration
- Move SchemaConfigFields to render after thinking effort (same
visual area as Claude's chrome toggle) instead of bottom of
config section
- Extract SelectField into its own component to fix React hooks
order violation when schema fields change between renders
- Add onAdapterChange() subscription in registry.ts so
registerUIAdapter() notifies components when dynamic parsers
load, fixing stale parser for old runs
- Add parserTick to both RunTranscriptView and
useLiveRunTranscripts to force recomputation on parser change
- Plugin loader: install/reload/remove/reinstall external adapters
from npm packages or local directories
- Plugin store persisted at ~/.paperclip/adapter-plugins.json
- Self-healing UI parser resolution with version caching
- UI: Adapter Manager page, dynamic loader, display registry
with humanized names for unknown adapter types
- Dev watch: exclude adapter-plugins dir from tsx watcher
to prevent mid-request server restarts during reinstall
- All consumer fallbacks use getAdapterLabel() for consistent display
- AdapterTypeDropdown uses controlled open state for proper close behavior
- Remove hermes-local from built-in UI (externalized to plugin)
- Add docs for external adapters and UI parser contract