Commit Graph

92 Commits

Author SHA1 Message Date
João Salavisa 159f98efe6 feat(web): File browser with syntax-highlighted viewer (#13)
* feat(web): add file browser with syntax-highlighted viewer

- Add file browser component in right panel to browse workspace files
- Open files in left panel tabs alongside Notes/Changes/Chat
- Color-coded dots for file types (TS, JS, Go, Python, etc.)
- Visual separator between main tabs and file tabs
- Folders sorted to top in file tree view
- LRU eviction for max 4 open file tabs
- Backend handlers for workspace file tree and content via WebSocket

* fix(web): refresh file tree on filesystem changes via fsnotify

- Subscribe to file change notifications from agentctl's fsnotify watcher
- Backend lifecycle manager now connects to file changes stream
- Publishes FileChangeNotified events to event bus
- WebSocket broadcasts workspace.file.changes to task subscribers
- Frontend file browser refreshes tree when changes detected

* perf(agentctl): use fsnotify instead of polling for git status

- Replace 2-second polling with fsnotify-triggered updates
- Add debouncing (300ms) to batch rapid file changes
- Git status updates now triggered by actual filesystem changes
- More efficient and responsive than periodic polling

* refactor(agentctl): consolidate fs events into single debounced trigger

- Single fsChangeTrigger channel for all filesystem events
- After 300ms debounce: update git status, files, and notify subscribers
- Removed per-file notifications in favor of single 'refresh' event
- Simpler and more efficient than separate triggers

* refactor(agentctl): simplify file API - use HTTP for tree/content

- Remove unused filesConn, fileTreeConn, fileContentConn from Client struct
- Convert RequestFileTree and RequestFileContent from WebSocket to HTTP GET
- Remove StreamFiles and CloseFilesStream (redundant with file changes stream)
- Keep only fileChangesConn for the debounced refresh notification

HTTP is simpler than WebSocket for request/response patterns.

* feat(web): switch to CodeMirror for file viewer

- Replace react-syntax-highlighter with @uiw/react-codemirror
- Add language extensions for JS/TS, Python, Go, Rust, Java, C++, CSS, HTML, JSON, Markdown, YAML
- Use VS Code dark theme for consistent look
- Enable code folding and read-only mode
- Better performance and features than syntax highlighter

* refactor: consolidate duplicated types and extract shared constants

- Re-export file types from process package in agentctl/client.go instead of duplicating
- Move OpenFileTab type to lib/types/backend.ts (shared by file-browser and page-client)
- Extract FILE_EXTENSION_COLORS constant for file type color indicators
- Remove console.log statement and unused imports in file-browser.tsx
- Add 'refresh' operation to FileChangeNotificationPayload type

* refactor(agentctl): move Close() method from acp.go to client.go

Close() is a general client cleanup method that closes all streams
(ACP, permissions, git status, file changes). It belongs in client.go
since acp.go should only contain ACP-specific communication logic.

* fix(web): remove unused cn import in file-browser

* refactor(agentctl): consolidate duplicated types into process/types.go

- Create process/types.go with all workspace-related types
- Remove duplicate GitStatusUpdate, FileInfo from workspace_tracker.go
- Remove duplicate GitStatusUpdate, FileInfo from api/workspace.go
- Re-export all types from agent/agentctl/client.go for convenience

Types are now defined once and imported everywhere.

* chore: remove package-lock.json, add to .gitignore

Project uses pnpm (pnpm-lock.yaml), not npm.

* fix(orchestrator): probe agent before returning stale execution state

When checking task.execution, the backend now probes the actual agent:
- For tracked instances: health check via agentctl
- For Docker: verify container is running

If the agent is not running but DB says 'running', the session is
marked as stopped and false is returned. This fixes the UI showing
agents as running after backend restart when they're actually dead.

Changes:
- Add IsAgentRunningForTask to AgentManagerClient interface
- Add IsContainerRunning to docker client
- Update GetExecution to verify agent is actually running
- Clean up stale sessions in database when agent not found

* fix(orchestrator): use agentctl status to verify agent is running

Simplified approach - probe agentctl's /api/v1/status endpoint to check
if agent process is running. Same check for both Docker and standalone.

- Add IsAgentRunning() helper to StatusResponse
- Simplify IsAgentRunningForTask to just use agentctl.GetStatus()

* fix(orchestrator): also verify agent running for in-memory executions

The previous fix only checked agent status when loading from DB. But if
an execution is cached in memory and the agent process stops (while
agentctl stays running), the stale state was still returned.

Now both paths verify the agent is actually running by probing agentctl.
If agent stopped, clean up in-memory state and update DB session.

* chore(web): remove unused react-syntax-highlighter

Switched to CodeMirror for code viewing, no longer needed.

* fix(tests): add IsAgentRunningForTask to mock agent managers

Add the new interface method to test mocks:
- mockAgentManager in scheduler_test.go
- SimulatedAgentManagerClient in orchestrator_test.go

---------

Co-authored-by: Kandev Agent <kandev@example.com>
2026-01-14 01:24:05 +00:00
João Salavisa 2c1afd7701 feat(backend): auto-launch agentctl subprocess in standalone mode (#12) 2026-01-13 23:56:10 +00:00
Carlos Florêncio 6c50fef6fa feat: add defaults to workspace: env, executor, agent 2026-01-13 23:37:46 +00:00
Carlos Florêncio aed307d9b8 feat: simplify task creation 2026-01-13 22:41:52 +00:00
Carlos Florêncio aebcf5283f feat: display settings in kanban page 2026-01-13 22:37:36 +00:00
João Salavisa bfa22616f0 feat(worktree): semantic naming and branch cleanup on task deletion (#11) 2026-01-13 02:19:35 +00:00
João Salavisa 6d9f78b7b7 fix(agentctl): standalone mode workspace path and worktree lookup (#10) 2026-01-13 02:05:33 +00:00
Carlos Florêncio 084756c921 feat: agents discovery 2026-01-13 00:45:10 +00:00
Carlos Florêncio bcbe09fbb7 feat: add pre-commit hook 2026-01-13 00:40:23 +00:00
Carlos Florêncio f2aea364af feat: environments and executors 2026-01-13 00:28:25 +00:00
João Salavisa 3701d9057b feat(backend): build agentctl to bin/ and use pre-built binary in Dockerfile (#9) 2026-01-12 23:56:36 +00:00
João Salavisa a1013342a3 feat: Real-time Git Status Integration (#8)
* feat: implement real-time git status integration

- Add workspace tracker to monitor git changes every 2 seconds
- Implement WebSocket streaming for git status updates
- Add database persistence for git status in agent session metadata
- Compute diffs backend-side with additions/deletions per file
- Integrate git status into frontend UI (top bar, files panel, changes panel)
- Display real-time ahead/behind commits and line changes
- Show file diffs with syntax highlighting in task view
- Add retry logic for WebSocket connections during reconciliation
- Fix context lifecycle issue in workspace tracker

* refactor: remove debug and unnecessary logging

- Remove debug logs from workspace tracker
- Remove info logs from WebSocket handlers
- Remove verbose git status update logs
- Keep only essential error logs

* fix: compare git diff against remote branch instead of HEAD

- Changed git diff comparison from HEAD to remote tracking branch
- Now shows all changes including committed files that haven't been pushed
- Files committed locally but not pushed will appear in the diff
- Falls back to HEAD if no remote branch is configured

* fix: prevent stale git status when switching tasks

- Clear git status when switching to a new task
- Only accept git.status WebSocket updates for the current task
- Prevents showing git data from previous task when switching

* refactor: remove unused diff stream client code

- Remove diffConn field from agentctl Client struct
- Remove StreamDiff() method (never called)
- Remove CloseDiffStream() method
- Remove DiffUpdate type from client.go
- All diff data is already included in GitStatusUpdate.Files
- Keep server-side diff endpoint in agentctl for potential future use

* refactor: remove unused diff stream server-side code

- Remove /workspace/diff/stream endpoint from agentctl API
- Remove handleDiffStreamWS handler
- Remove DiffUpdate type from workspace_tracker.go
- Remove DiffSubscriber type
- Remove updateDiff() and getDiff() methods
- Remove SubscribeDiff(), UnsubscribeDiff() methods
- Remove notifyDiffSubscribers() method
- Remove GetCurrentDiff() method
- Remove currentDiff field and diffSubscribers map
- All diff data is already included in GitStatusUpdate.Files

* refactor: remove unused output stream code

- Remove /output and /output/stream endpoints from agentctl API
- Remove handleGetOutput and handleOutputStreamWS handlers
- Delete output.go file entirely
- Remove OutputBuffer and related code (buffer.go deleted)
- Remove outputConn field from agentctl Client
- Remove StreamOutput() and CloseOutputStream() methods
- Remove OutputLine type from client.go
- Remove OutputBufferSize config option
- Update readStderr to just log instead of buffering

Output data flows through ACP stream (StreamUpdates) which includes
all session notifications. The separate output stream was never used.
2026-01-12 23:44:29 +00:00
Carlos Florêncio c5eac3551a feat: improved settings repos, boards 2026-01-12 22:13:54 +00:00
Carlos Florêncio ce55dbf1c1 fix: go vet ci 2026-01-12 21:13:25 +00:00
Carlos Florêncio 0cbbeece07 feat: landing page and pnpm workspaces 2026-01-12 20:56:03 +00:00
jcfs c2d08271c9 fix: reconnect to agent streams after backend restart
- Add reconnectStreams() to reconnect WebSocket streams for recovered agents
- Reconnect updates stream (for agent responses)
- Reconnect permissions stream (for permission requests)
- Mark recovered agents as READY so they can accept prompts
- Fix worktree cleanup order: clean files before DB cascade deletes records
2026-01-12 17:14:17 +00:00
jcfs 74c020b371 feat: return worktree info in orchestrator.start response
- Add WorktreePath and WorktreeBranch to StartTaskResponse
- Add those fields to TaskExecution and LaunchAgentResponse
- Store worktree_path and worktree_branch in AgentInstance metadata
- Update frontend to use worktree info from start response directly
2026-01-12 16:28:56 +00:00
jcfs a7deb3300c fix: show worktree path in UI after agent starts
- Add local state for worktree path/branch
- Re-fetch task info 1s after agent starts to get worktree data
- Pass local state to TaskTopBar instead of static task prop
2026-01-12 16:20:11 +00:00
jcfs db454bec8e fix: only show active worktrees in task API response
- GetWorktreeByTaskID now filters by status = 'active'
- Deleted worktrees won't appear in task responses
2026-01-12 16:15:45 +00:00
jcfs 0b071782c0 feat: worktrees at agent session level with random suffix
- Branch name format: kandev/{task_id}_{random8chars}
- Worktree path: ~/.kandev/worktrees/{task_id}_{random}/
- Multiple worktrees per task allowed (one per agent session)
- WorktreeID stored in agent instance metadata for session resumption
- Pass WorktreeID in CreateRequest to reuse existing worktree
- OnTaskDeleted removes ALL worktrees for the task
- Added GetByID, GetAllByTaskID, RemoveByID methods
2026-01-12 16:12:34 +00:00
jcfs 3961afc29e feat: cleanup worktree and branch on task deletion
- Add WorktreeCleanup interface to task service
- Call OnTaskDeleted when a task is deleted to remove worktree dir and branch
- Wire worktree manager to task service in main.go

This ensures that when tasks are deleted, their associated worktrees
and git branches (kandev/{task_id}) are properly cleaned up.
2026-01-12 15:56:09 +00:00
jcfs 76e4221312 fix: configure git safe.directory in agent containers
Container runs as root but mounted files are owned by host user.
Git 2.35.2+ rejects this as 'dubious ownership'. Configure git via
environment variables to trust all directories in the container.
2026-01-12 15:48:41 +00:00
jcfs 3c460a694b fix: mount entire .git directory for worktree support in containers
Git worktree metadata in .git/worktrees/{name} has a 'commondir' file
that references back to the parent .git directory (typically '../..').

Mounting just the worktrees subdirectory wasn't sufficient - we need
to mount the entire .git directory so that:
1. The worktree's .git file can resolve to .git/worktrees/{name}
2. The commondir reference can resolve back to the main .git
3. Git objects, refs, and other shared data are accessible
2026-01-12 15:43:42 +00:00
jcfs c5769e9b6a fix: mount git worktree metadata directory into container
Git worktrees store their metadata in the parent repository's
.git/worktrees/{name} directory. The worktree's .git file contains
an absolute path to this directory.

When mounting a worktree into a container, git commands fail because
the .git file references a host path that doesn't exist in the container.

This fix mounts the git worktree metadata directory into the container
at the same path it exists on the host, so git commands work correctly.
2026-01-12 15:34:06 +00:00
jcfs b8eade8c26 fix: wire worktree manager to lifecycle manager for agent isolation
The worktree manager was created but never connected to the lifecycle
manager, so worktrees were never being created when agents launched.
2026-01-12 15:23:19 +00:00
jcfs 19ea7ddc4e feat: expose worktree path and branch in task API and UI
- Add WorktreePath and WorktreeBranch fields to TaskDTO
- Add WorktreeLookup interface to TaskController for enriching task responses
- Add GetWorktreeInfo method to worktree.Manager implementing WorktreeLookup
- Wire worktree manager to task controller in main.go
- Add worktree_path and worktree_branch to frontend Task type
- Display worktree path with copy button in TaskTopBar when worktree exists
- Show worktree branch in tooltip for easy reference
2026-01-12 15:19:11 +00:00
jcfs 20c456dc07 feat: implement Git worktrees for concurrent agent execution
- Add worktree package with Manager, Store, Config, and error types
- Integrate worktree creation/reuse into lifecycle manager
- Update executor to pass worktree configuration
- Add WorktreeConfig to common config package
- Enable worktrees by default for agent isolation
- Add unit tests for worktree manager

This allows multiple agents to work on the same repository simultaneously
by creating isolated worktrees for each task. Worktrees persist between
agent runs for task resumption and are only cleaned up when tasks are
explicitly deleted.
2026-01-12 15:04:16 +00:00
jcfs 8e01191c68 feat: enhance tool call display with payload details and typing indicator
- Add typing indicator in TaskChatPanel that shows when agent is working
- Enhanced ToolCallCard component with expandable details section
- Backend now passes tool call args (kind, path, locations, raw_input) to comments
- Add generateUUID fallback for non-secure contexts (HTTP non-localhost)
- Configure Next.js allowedDevOrigins for cross-origin dev access
- Bind dev server to 0.0.0.0 for network access

Backend changes:
- Extract Kind, Locations, RawInput from ACP ToolCall updates
- Add Args field to ToolCallData in watcher
- Pass args through CommentCreator interface to comment metadata

Frontend changes:
- ToolCallCard shows file path, status icons, expandable args
- getToolIcon matches ACP ToolKind values (read, edit, search, execute)
- Typing indicator with animated dots when awaiting agent response
- Replace crypto.randomUUID with fallback utility across all files
2026-01-12 14:21:26 +00:00
jcfs e012e070a9 fix: recover agent state from Docker on backend restart
- Add Docker reconciliation on lifecycle manager startup to find running containers
- Add container_id field to agent_sessions table for cleanup tracking
- Add GetRecoveredInstances to AgentManagerClient interface
- Sync executor cache with recovered Docker instances on startup
- Add task.execution WebSocket endpoint to check agent running state
- Fix Stop Agent button showing Start Agent after page refresh
- Ensure containers are not leaked when backend restarts
2026-01-12 03:42:54 +00:00
jcfs 3b1c6f14bf fix(backend): filter out internal ACP messages from WebSocket broadcast
Only broadcast message types that the frontend handles (progress, log, result,
error, status, heartbeat, input_required). Skip internal types like session/update.
2026-01-12 02:58:42 +00:00
jcfs ad2a0bd9d0 fix(web): fix real-time comments not appearing on first agent start
- Initialize comments.items array in setCommentsTaskId and addComment
- Fixes race condition where WebSocket notifications arrived before API call completed
2026-01-12 02:57:09 +00:00
jcfs 0ad5082a09 feat(backend): make repository_url optional when launching agents
- Remove validation requiring repository_url in lifecycleAdapter.LaunchAgent
- Skip workspace mounts in lifecycle manager when no workspace path is provided
- Agents can now run without a pre-existing workspace directory
2026-01-12 02:25:49 +00:00
jcfs 14e57bd8e3 Merge remote-tracking branch 'origin/main' into feat/frontend-improvements 2026-01-12 02:20:12 +00:00
João Salavisa 7ac25bfb66 Merge pull request #6 from kdlbs/feat/agent-session-persistence
feat(backend): Persistent Agent Session Tracking
2026-01-12 02:10:45 +00:00
jcfs 5381094bba feat(web): enhance WebSocket handling and chat panel improvements
- Add react-markdown with remark-breaks and remark-gfm for markdown rendering
- Improve WebSocket client with better reconnection handling
- Enhanced task chat panel with markdown support for comments
- Add comment type and metadata support for tool call rendering
- Improve connection status indicator
- Update task page with improved agent controls
- Add WebSocket router for better message handling
- Update state store with enhanced type safety
2026-01-12 02:05:30 +00:00
jcfs 7b3e94d6dc feat(backend): add persistent agent session tracking
- Add AgentSession database entity with SQLite persistence
- Implement AgentSession CRUD operations in repository layer
- Update executor to use hybrid cache + database approach
- Add session restoration on startup (LoadActiveSessionsFromDB)
- Link comments to agent sessions via agent_session_id
- Fix SQLite NULL handling for nullable task fields
- Add dev database setup with seed data (make dev, make dev-db-reset)
- Update Makefile with dev targets for development mode

This enables agent sessions to persist across backend restarts,
solving the 'execution not found' error for resumed conversations.
2026-01-12 02:02:47 +00:00
João Salavisa 00c0a0c529 Merge pull request #5 from kdlbs/feat/unify-ws-pattern-a
refactor: unify WebSocket patterns to Pattern A (handlers + controller + dto)
2026-01-11 22:53:09 +00:00
jcfs 0b8cd401c2 refactor: unify WebSocket patterns to Pattern A (handlers + controller + dto)
- Add missing repository action constants to pkg/websocket/actions.go
- Update repository_handlers.go to use action constants instead of string literals
- Refactor orchestrator module: create dto/, controller/, handlers/ packages
- Refactor agent module: create dto/, controller/, handlers/ packages
- Update main.go and integration tests to use new Pattern A wiring
- Remove old wshandlers/ directories from both modules

All modules now follow the same architecture:
  handlers/    → Parse WS messages, validate, call controller
  controller/  → Business logic coordination, convert to/from DTOs
  dto/         → Centralized request/response Data Transfer Objects
  service/     → Core business logic (unchanged)
2026-01-11 22:51:43 +00:00
Carlos Florêncio 4282d67910 fix: go tests 2026-01-11 22:44:10 +00:00
Carlos Florêncio 58ecd85885 fix: task page 2026-01-11 22:42:31 +00:00
Carlos Florêncio a9047cf823 feat: tasks crud 2026-01-11 22:32:04 +00:00
João Salavisa 4706e3be40 Merge pull request #4 from kdlbs/feat/acp-permission-requests
feat: implement ACP permission request flow
2026-01-11 22:26:10 +00:00
jcfs c1c9dfa2c1 docs: update WEBSOCKET_API.md with complete API reference
- Add Workspace Actions section (workspace.list, create, get, update, delete)
- Add Repository Actions section (repository.*, repository.script.*)
- Add Comment Actions section (comment.add, comment.list)
- Add Permission Actions section (permission.requested, permission.respond)
- Add comment.added notification documentation
- Update Quick Reference table with all actions organized by category
- Document all notification actions (ACP, task, workspace, board, column events)
2026-01-11 22:22:15 +00:00
jcfs fd98328058 chore: remove unused legacy agent.sh
- Remove agent.sh (was never actually used, entrypoint.sh handles both modes)
- Update Dockerfile to remove the copy of agent.sh
2026-01-11 22:15:11 +00:00
jcfs 15cf60edb9 merge: resolve conflicts with main
- Keep both RegisterRepositoryRoutes and RegisterCommentRoutes
- Merge permission actions with repository actions in websocket/actions.go
2026-01-11 22:12:16 +00:00
jcfs 195be5e575 feat: enhance comment system and e2e testing
- Add comment handlers for WebSocket API (comment.add, comment.list)
- Update e2e-test.sh to focus on comment system testing
- Test multi-turn conversation flow (3 turns)
- Display comment content and metadata in test output
- Reduce test timeouts for faster execution
- Fix various orchestrator and lifecycle manager issues
- Add CODE_REVIEW_ISSUES.md documenting known issues
2026-01-11 22:08:00 +00:00
jcfs 6dd0d7ffa4 feat: implement ACP permission request flow
- Add permission stream support to backend agentctl client
  - StreamPermissions() connects to permission WebSocket
  - RespondToPermission() sends responses via HTTP POST
  - PermissionNotification type for permission request data

- Connect lifecycle manager to permission stream
  - handlePermissionStream() receives permission requests
  - publishPermissionRequest() forwards to event bus
  - RespondToPermission() and RespondToPermissionByTaskID() methods

- Add WebSocket handler for permission.respond action
  - Validates task_id, pending_id, option_id
  - Routes response through orchestrator → executor → lifecycle manager

- Add permission WebSocket actions
  - ActionPermissionRequested for notifications
  - ActionPermissionRespond for user responses

- Update executor interface with RespondToPermissionByTaskID()
- Update mock implementations in tests
- Add permission response test to e2e-test.sh
- Fix e2e-test.sh ID extraction (strip newlines)

The full permission flow is now wired up:
agent → agentctl → backend → frontend → user → backend → agentctl → agent

Auto-approve mode is still enabled by default until frontend is ready.
2026-01-11 20:56:50 +00:00
Carlos Florêncio 473b336b13 feat: added repositories support 2026-01-11 19:59:28 +00:00
João Salavisa 00c65268bc Merge pull request #3 from kdlbs/feat/comments-input-request-flow
feat: add bidirectional comment system and agent input request flow
2026-01-11 19:38:54 +00:00
jcfs 0fdf18c37b feat: add bidirectional comment system and agent input request flow
- Add Comment model and CRUD operations (repository, service layers)
- Add WAITING_FOR_INPUT task state for agent input requests
- Add WebSocket actions for comment.add, comment.get, comment.list
- Add ActionCommentAdded and ActionInputRequested notifications
- Update PromptAgent to return PromptResult with stop reason
- Add e2e test for agent input request flow
- Add PR template for the repository

This enables agents to request input from users by returning
stopReason 'needs_input' which transitions the task to
WAITING_FOR_INPUT state and creates an agent comment.
2026-01-11 18:41:52 +00:00