Commit graph

872 commits

Author SHA1 Message Date
dotta
dde4cc070e Add blocker relations and dependency wakeups
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-06 09:03:13 -05:00
Dotta
ed97432fae
Merge pull request #2654 from plind-dm/fix/kanban-collapse-empty-columns
fix(ui): collapse empty kanban columns to save horizontal space
2026-04-06 08:54:30 -05:00
Dotta
0593b9b0c5
Merge pull request #2655 from plind-dm/fix/goal-description-scroll
fix(ui): make goal description area scrollable in create dialog
2026-04-06 08:54:05 -05:00
Dotta
855d895a12
Merge pull request #2650 from plind-dm/fix/paused-agent-visual-indicator
fix(ui): dim paused agents in list and org chart views
2026-04-06 08:53:34 -05:00
Dotta
39d001c9b5
Merge pull request #2651 from plind-dm/fix/clear-extra-args-config
fix(ui): use null instead of undefined when clearing extra args
2026-04-06 08:51:43 -05:00
plind
23eea392c8
Merge branch 'master' into fix/clear-extra-args-config 2026-04-05 22:23:50 +09:00
Darren Davison
42989115a7 fix: re-open panel when childIssues changes to prevent stale sub-task list
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>
2026-04-05 12:02:49 +01:00
Darren Davison
7623f679cf fix: count all descendants in collapsed badge and prune stale localStorage IDs
Address two Greptile review comments:

1. Collapsed parent badge now shows total descendant count at all depths
   rather than direct-child count only. Add `countDescendants` utility to
   issue-tree.ts (recursive, uses existing childMap) and replace
   `children.length` with it in the titleSuffix badge.

2. Add a useEffect that prunes stale IDs from `collapsedParents` whenever
   the issues prop changes. Deleted or reassigned issues previously left
   orphan IDs in localStorage indefinitely; the effect filters to only IDs
   that appear as a parentId in the current issue list and persists the
   cleaned array via updateView.

Add four unit tests for countDescendants: leaf node, single-level,
multi-level, and unknown ID.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 12:02:49 +01:00
Darren Davison
9be1b3f8a9 test: extract buildIssueTree utility and add tests for hierarchy logic
Extract the inline tree-building logic from IssuesList into a pure
`buildIssueTree` function in lib/issue-tree.ts so it can be unit tested.
Add six tests covering: flat lists, parent-child grouping, multi-level
nesting, orphaned sub-tasks promoted to root, empty input, and list
order preservation.

Add two tests to IssueRow.test.tsx covering the new titleSuffix prop:
renders inline after the title when provided, and renders cleanly when
omitted.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 12:02:12 +01:00
Darren Davison
b380d6000f feat: show parent task and sub-tasks at bottom of issue properties panel
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>
2026-04-05 12:02:12 +01:00
Darren Davison
e23d148be1 feat: persist collapse/expand state across navigation via localStorage
Move collapsedParents from ephemeral useState into IssueViewState,
which is already serialised to localStorage under the scoped key.
Navigating away and back now restores the exact collapsed/expanded
state the user left the list in.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 12:02:12 +01:00
Darren Davison
58a1a20f5b fix: indent nested sub-tasks at all depths using depth-based padding
Replace the boolean isChild flag with a numeric depth counter.
Each depth level adds 16px left padding via inline style on the
wrapper div, so sub-tasks of sub-tasks (and deeper) are indented
proportionally rather than all aligning at the same level.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 12:02:12 +01:00
Darren Davison
12011fa9de feat: show sub-task count in title when parent is collapsed
When a parent issue is collapsed, its title is suffixed with
"(N sub-tasks)" so the count remains visible at a glance.
The suffix disappears when the parent is expanded.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 12:02:12 +01:00
Darren Davison
11643941e6 fix: add sm:pl-7 to ensure child indentation is visible on desktop
The base IssueRow has sm:pl-1 which overrides pl-6 at sm+ breakpoints.
Adding sm:pl-7 ensures the indent is visible at all screen sizes.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 12:02:12 +01:00
Darren Davison
8cdb65febb feat: show sub-tasks indented under parent in issue list with collapse/expand
Sub-tasks are now grouped under their parent issue in the list view.
Parent issues with children show a chevron to collapse/expand their subtasks.
Child issues are visually indented to indicate hierarchy.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 12:02:12 +01:00
dotta
4dea302791 Speed up issues-page search
Keep issue search local to the loaded list, defer heavy result updates, and memoize the rendered list body so typing stays responsive.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 18:14:19 -05:00
dotta
94d4a01b76 Add skill slash-command autocomplete
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 17:48:54 -05:00
dotta
fe61e650c2 Avoid blur-save during mention selection
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 17:48:54 -05:00
dotta
c89349687f feat(ui): improve routines list and recent runs
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 17:48:54 -05:00
dotta
f515f2aa12 Fix workspace runtime state reconciliation
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 17:48:54 -05:00
dotta
5a9a2a9112 Fix mobile mention menu placement
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 17:48:54 -05:00
dotta
65818c3447 Guard closed isolated workspaces on issues
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 17:48:54 -05:00
dotta
4993b5338c Fix horizontal scroll overflow in close workspace modal
Root cause: CSS Grid items default to min-width:auto, allowing content
to push the dialog wider than the viewport on mobile.

- Add [&>*]:min-w-0 on DialogContent to prevent grid children from
  expanding beyond the container width
- Keep overflow-x-hidden as safety net
- Remove negative-margin sticky footer that extended beyond bounds
- Revert to standard DialogFooter without negative margins

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 17:48:54 -05:00
dotta
d3401c0518 Fix horizontal scroll overflow in close workspace modal
- Add overflow-x-hidden on DialogContent to prevent horizontal scroll
- Truncate long monospace text (branch names, base refs) in git status grid
- Add min-w-0 on grid cells to allow truncation within CSS grid
- Add overflow-hidden on git status card and repo root section
- Add max-w-full + overflow-x-auto on pre blocks for long commands

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 17:48:54 -05:00
dotta
dbb5f0c4a9 Unify all toggle switches into a single responsive ToggleSwitch component
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>
2026-04-04 17:48:54 -05:00
dotta
3d685335eb Add sign out button to instance general settings
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>
2026-04-04 17:48:54 -05:00
dotta
2615450afc Make close workspace modal responsive for mobile
- Reduce padding and text sizes on small screens (p-4/text-xs -> sm:p-6/sm:text-sm)
- Tighter spacing between sections on mobile (space-y-3 -> sm:space-y-4)
- Sticky footer so action buttons stay visible while scrolling
- Grid layout stays 2-col on all sizes for git status
- Add shrink-0 to loading spinner

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 17:48:54 -05:00
Dotta
35f2fc7230
Merge pull request #2218 from HenkDz/feat/external-adapter-phase1
feat(adapters): external adapter plugin system with dynamic UI parser
2026-04-04 17:45:19 -05:00
dotta
d9476abecb fix(adapters): honor paused overrides and isolate UI parser state
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-04 14:04:33 -05:00
Devin Foley
d202631016
fix: autoformat pasted markdown in inline editor (#2673)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies
> - The inline markdown editor (MarkdownEditor / MDXEditor) is used to
edit agent instructions, issue descriptions, and other content
> - When users paste agent instructions copied from terminals or
consoles, extra leading whitespace is uniformly added to every line
> - PR #2572 fixed markdown structure preservation on paste but did not
address the leading whitespace (dedent) problem
> - This pull request adds a Lexical paste normalization plugin that
strips common leading whitespace and normalizes line endings before
MDXEditor processes pasted content
> - The benefit is that pasted content from terminals/consoles renders
correctly without manual cleanup

## What Changed

- **`ui/src/lib/normalize-markdown.ts`** — Pure utility that computes
minimum common indentation across non-empty lines and strips it
(dedent), plus CRLF → LF normalization
- **`ui/src/lib/paste-normalization.ts`** — Lexical `PASTE_COMMAND`
plugin at `CRITICAL` priority that intercepts plain-text pastes,
normalizes the markdown, and re-dispatches cleaned content for MDXEditor
to process. Skips HTML-rich pastes.
- **`ui/src/components/MarkdownEditor.tsx`** — Registers the new plugin;
updates PR #2572's `handlePasteCapture` to use `normalizeMarkdown()`
(dedent + CRLF) instead of `normalizePastedMarkdown()` (CRLF only) for
the markdown-routing path
- **`ui/src/lib/paste-normalization.test.ts`** — 9 unit tests covering
dedent, CRLF normalization, mixed indent, empty lines, single-line
passthrough, and edge cases

## Verification

- `pnpm --dir ui exec vitest run src/lib/paste-normalization.test.ts` —
9 tests pass
- Manual: paste indented agent instructions from a terminal into any
inline markdown editor and confirm leading whitespace is stripped

## Risks

- Low risk. The plugin only activates for plain-text pastes (no HTML
clipboard data). HTML/rich pastes pass through unchanged. Single-line
pastes are not modified. The dedent logic is conservative — it only
strips whitespace common to all non-empty lines.

## 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
- [ ] 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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-04 11:21:27 -07:00
HenkDz
c6d2dc8b56 fix(ui): narrow overridePaused to boolean in AdapterManager spread 2026-04-04 17:08:53 +01:00
HenkDz
b81d765d2e feat: server-side override pause/resume for builtin adapter types
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.
2026-04-04 13:17:21 +01:00
HenkDz
4efe018a8f fix(ui): external adapter UI parser can now override builtin parsers
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
2026-04-04 12:40:39 +01:00
HenkDz
0651f48f6c fix(ui): move reinstall button to end — power, reload, remove, reinstall 2026-04-03 23:09:30 +01:00
HenkDz
01c05b5f1b fix(ui): remove loaded badge, order badges — source, icon, version, override, disabled 2026-04-03 22:58:04 +01:00
HenkDz
c36ea1de6f fix(ui): reorder adapter badges — always-present first, conditional last 2026-04-03 22:51:49 +01:00
HenkDz
3c4b8711ec fix(ui): remove title prop from Lucide icons (not supported in this version) 2026-04-03 22:38:38 +01:00
HenkDz
fb3aabb743 feat(adapters): add overriddenBuiltin flag to API and Adapter Manager UI
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.
2026-04-03 22:25:58 +01:00
HenkDz
199a2178cf feat(ui): collapsible system_group block in transcript view
Batch consecutive system events into a single collapsible group
instead of rendering each as a separate warn-toned block. Shows
count in header, expands on click.
2026-04-03 21:52:36 +01:00
HenkDz
c757a07708 fix(adapters): stable sort order, npm/local icons, reinstall dialog, HMR polling on WSL
- 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)
2026-04-03 21:11:24 +01:00
HenkDz
acfd7c260a feat: add hermes_local session management and show provider/model in run details 2026-04-03 21:11:23 +01:00
HenkDz
388650afc7 fix: update tests for SchemaConfigFields and comingSoon logic
- registry.test: fallback now uses SchemaConfigFields, not ProcessConfigFields
- metadata.test: isEnabledAdapterType checks comingSoon first so
  intentionally withheld built-in adapters (process/http) stay disabled
2026-04-03 21:11:23 +01:00
HenkDz
47f3cdc1bb fix(ui): external adapter selection, config field placement, and transcript parser freshness
- 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
2026-04-03 21:11:22 +01:00
HenkDz
69a1593ff8 feat(adapters): declarative config-schema API and UI for plugin adapters
Cherry-picked from feat/externalize-hermes-adapter.
Resolved conflicts: kept Hermes as built-in on phase1 branch.
2026-04-03 21:11:22 +01:00
HenkDz
f884cbab78 fix(adapters): restore built-in Hermes and sync lockfile with server
Re-align phase1 with upstream: hermes_local ships via hermes-paperclip-adapter on the server and UI (hermes-local module). Fixes ERR_PNPM_OUTDATED_LOCKFILE from server/package.json missing a dep still present in the lockfile.

Add shared BUILTIN_ADAPTER_TYPES and skip external plugin registration when it would override a built-in type. Docs list Hermes as built-in; Droid remains the primary external example.

Made-with: Cursor
2026-04-03 21:11:21 +01:00
HenkDz
14d59da316 feat(adapters): external adapter plugin system with dynamic UI parser
- 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
2026-04-03 21:11:20 +01:00
馨冉
728fbdd199
Fix markdown paste handling in document editor (#2572)
Supersedes #2499.

## Thinking Path

1. **Project context**: Paperclip uses a markdown editor
(`MarkdownEditor`) for document editing. Users expect to paste
markdown-formatted text from external sources (like code editors, other
documents) and have it render correctly.

2. **Problem identification**: When users paste plain text containing
markdown syntax (e.g., `# Heading`, `- list item`), the editor was
treating it as plain text, resulting in raw markdown syntax being
displayed rather than formatted content.

3. **Root cause**: The default browser paste behavior doesn't recognize
markdown syntax in plain text. The editor needed to intercept paste
events and detect when the clipboard content looks like markdown.

4. **Solution design**: 
- Create a utility (`markdownPaste.ts`) to detect markdown patterns in
plain text
- Add a paste capture handler in `MarkdownEditor` that intercepts paste
events
- When markdown is detected, prevent default paste and use
`insertMarkdown` instead
   - Handle edge cases (code blocks, file pastes, HTML content)

## What

- Added `ui/src/lib/markdownPaste.ts`: Utility to detect markdown
patterns and normalize line endings
- Added `ui/src/lib/markdownPaste.test.ts`: Test coverage for markdown
detection
- Modified `ui/src/components/MarkdownEditor.tsx`: Added paste capture
handler to intercept and handle markdown paste

## Why

Users frequently copy markdown content from various sources (GitHub,
documentation, notes) and expect it to render correctly when pasted into
the editor. Without this fix, users see raw markdown syntax (e.g., `#
Title` instead of a formatted heading), which degrades the editing
experience.

## How to Verify

1. Open any document in Paperclip
2. Copy markdown text from an external source (e.g., `# Heading\n\n-
Item 1\n- Item 2`)
3. Paste into the editor
4. **Expected**: The content should render as formatted markdown
(heading + bullet list), not as plain text with markdown syntax

### Test Coverage

```bash
cd ui
npm test -- markdownPaste.test.ts
```

All tests should pass, including:
- Windows line ending normalization (`\r\n` → `\n`)
- Old-Mac line ending normalization (`\r` → `\n`)
- Markdown block detection (headings, lists, code fences, etc.)
- Plain text rejection (non-markdown content)

## Risks

1. **False positives**: Plain text containing markdown-like characters
(e.g., a paragraph starting with `#` as a hashtag) may be incorrectly
treated as markdown. The detection uses a heuristic that requires
block-level markdown patterns, which reduces but doesn't eliminate this
risk.

2. **Removed focus guard**: The previous implementation used
`isFocusedRef` to prevent `onChange` from firing during programmatic
`setMarkdown` calls. This guard was removed as part of refactoring. The
assumption is that MDXEditor does not fire `onChange` during
`setMarkdown`, but this should be monitored for unexpected parent update
loops.

3. **Clipboard compatibility**: The paste handler specifically looks for
`text/plain` content and ignores `text/html` (to preserve existing HTML
paste behavior). This means pasting from rich text editors that provide
both HTML and plain text will continue to use the HTML path, which may
or may not be the desired behavior.

---------

Co-authored-by: 馨冉 <xinxincui239@gmail.com>
2026-04-03 08:50:48 -07:00
plind-dm
f749efd412 fix(ui): skip paused dimming on Paused filter tab
On the Paused tab every visible agent is paused, so applying
opacity-50 to all of them is redundant and makes the whole view
dim. Skip the dimming when tab === "paused" in both list and org
chart views. Pass tab prop through to OrgTreeNode for consistency.
2026-04-03 23:37:21 +09:00
plind
f2925ae0df
Update ui/src/components/KanbanBoard.tsx
LGTM

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-04-03 23:37:12 +09:00
plind
acb2bc6b3b
Update ui/src/pages/Agents.tsx
Approved

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-04-03 23:22:02 +09:00