Commit Graph

148 Commits

Author SHA1 Message Date
Rob Colbert
ec7b83d610 Fix: Proper flexbox scrolling for FILES panel sidebar
Root Cause: CSS flex items default to min-height: auto, which prevents
flex-1 elements from shrinking below their content size. This caused
the FilesPanel to grow beyond its allocated space when the file tree
had many entries, pushing content off-screen.

Changes:
- FilesPanel.tsx: Added min-h-0 to root div to override min-height: auto
  This allows flex-1 to actually constrain height and enable scrolling
- FileTree.tsx: Removed redundant overflow-auto and h-full from root div
  The parent (FilesPanel flex-1 overflow-auto) already handles scrolling.
  Nested scroll containers create height resolution issues.

The sidebar layout is now a clean single-scroll-container hierarchy:
  Sidebar (flex flex-col, no overflow)
  ↳ SESSION (shrink-0, natural height)
  ↳ PROJECT (shrink-0, natural height)
  ↳ FilesPanel (flex-1 min-h-0) — constrained to available space
    ↳ Header (natural height)
    ↳ Scroll area (flex-1 overflow-auto) — THE scroll container
      ↳ FileTree (p-2 only) — no overflow, no h-full
    ↳ Footer (natural height)
2026-05-12 17:40:11 -04:00
Rob Colbert
6dba16a8c5 Fix: Add shrink-0 to SESSION and PROJECT panels for proper flex layout
- SESSION and PROJECT panels now have shrink-0 to prevent them from
  growing unbounded and pushing FILES panel off-screen
- FILES panel with flex-1 now properly fills remaining vertical space
- File tree scrolls in-place while SESSION/PROJECT stay fixed
2026-05-12 17:26:20 -04:00
Rob Colbert
b0b94c2b7d Fix: FileTree scrolling - use h-full instead of flex-1
- FileTree had flex-1 inside an overflow container which didn't work
- Changed to h-full to properly fill the parent container height
- Scrolling now works correctly in the file tree area
2026-05-12 17:22:29 -04:00
Rob Colbert
869dd919c8 Fix: Remove overflow-y-auto from sidebar to prevent entire sidebar from scrolling
- The sidebar container had overflow-y-auto which caused the entire sidebar
  to scroll when FILES panel content grew
- FILES panel already has proper flex-1 and internal overflow-auto handling
- Now only the file tree scrolls in place while SESSION and PROJECT panels
  remain fixed as expected
- Fixes UX issue where entire sidebar would scroll vertically
2026-05-12 17:19:15 -04:00
Rob Colbert
a2a74c6da3 fix: FILES panel should expand to fill sidebar height
- Add flex-1 to FilesPanel root div
- Sidebar is flex flex-col, FILES panel now grows to fill space
- SESSION and PROJECT panels remain natural height
- FILES panel expands into all remaining vertical space

This eliminates the gap below the FILES panel footer by making
the panel itself grow rather than just making the tree bigger.
2026-05-12 16:58:35 -04:00
Rob Colbert
91d02e1468 fix: FILES panel should fill entire sidebar height
- Remove max-h-80 constraint from FileTree
- FileTree uses flex-1 to expand and fill available space
- Panel now properly fills sidebar from top to bottom
- File tree scrolls internally when content overflows

The FILES panel header, file tree, and footer now form a proper
flex column that fills all remaining vertical space in the sidebar.
2026-05-12 16:45:26 -04:00
Rob Colbert
a7c20d6105 fix: FileTree scrolling and text selection issues
- Change FilesPanel overflow-hidden to overflow-auto for scrolling
- Add max-h-80 to FileTree to limit height while allowing scroll
- Add select-none to FileTreeNode to prevent text selection
- Cursor-pointer already present for clickable indication

Now the file tree scrolls independently within the FILES panel,
and text cannot be selected during rapid clicking.
2026-05-12 16:38:27 -04:00
Rob Colbert
84f68907da fix: FileTree backend recursion breaking lazy loading
CRITICAL FIX: Remove recursion from listDirectoryForTree function.

The backend was recursively fetching ALL subdirectories and returning
them as a flat list, which completely broke the lazy-loading model.

Changes:
- Remove recursive call in listDirectoryForTree
- Backend now returns ONLY immediate children
- Frontend handles lazy loading by requesting children on expand
- This matches the intended architecture where frontend controls tree

This fixes the issue where directory contents were duplicated and
the tree structure was corrupted when expanding/collapsing.
2026-05-12 16:32:27 -04:00
Rob Colbert
2b029ebf2e fix: FileTree showing entire workspace instead of project directory
- Add debug logging to track project directory resolution
- Improve path traversal security check with proper separator handling
- Log entry count and first 10 entries for debugging
- Fix project root validation to prevent listing workspace root

The issue was that the tree was listing from the workspace root
(containing gadget-code/, gadget-drone/, packages/) instead of the
specific project directory. Added logging to help diagnose.
2026-05-12 16:24:49 -04:00
Rob Colbert
71f213d8d1 fix: FileTree duplication and corruption on expand
- Replace recursive buildTree with buildVisibleNodes approach
- Build flat list of visible nodes based on expanded state
- Use processNode helper to traverse tree structure correctly
- Each node appears exactly once in the rendered output
- Eliminates duplication when expanding directories
2026-05-12 16:11:20 -04:00
Rob Colbert
3062420e99 fix: FileTree expand/collapse not rendering children
- Change buildTree from .map() to for-loop to properly render children
- Append expanded directory children to nodes array immediately
- Fix TypeScript error by using ReactElement instead of JSX.Element
- Children now render correctly when directories are expanded
2026-05-12 16:03:18 -04:00
Rob Colbert
0a510de487 docs: Add plan for Project-Specific Agent Instructions feature
- Create comprehensive plan document for agent instructions text area
- Define requirements, acceptance criteria, and technical implementation
- Include UI/UX mockups and testing strategy
- Plan discovered during FILES panel implementation
- Addresses need for project-specific acceptance criteria
2026-05-12 15:39:38 -04:00
Rob Colbert
c05c7f5a61 feat: Implement FILES panel foundation with lazy-loading file tree
- Add fileTreeRequest/fileTreeResponse socket messages
- Implement gadget-drone handler with security validation
- Add web backend message forwarding
- Create FileTree and FileTreeNode React components
- Update FilesPanel to contain file tree browser
- Add requestFileTree method to frontend socket client
- Exclude node_modules, .git, and hidden files by default
- Implement lazy loading with directory caching
- Add loading and error states per node
- Support keyboard navigation (Enter, Space)

Phase 1 of FILES panel implementation complete.
2026-05-12 15:12:18 -04:00
Rob Colbert
b090b5308b OpenAI API tool call processing fixes/correctness 2026-05-12 14:39:44 -04:00
Rob Colbert
1bb2a1d392 docs: update abort controller documentation with full technical specification 2026-05-12 12:30:00 -04:00
Rob Colbert
4780b79148 feat: abort controller for work order processing
Add end-to-end abort support: AbortSignal in @gadget/ai providers,
abortWorkOrder socket message, drone AbortController handling,
Cancel button and double-Esc in frontend, and aborted turn status display.
2026-05-12 12:25:17 -04:00
Rob Colbert
c635209201 sidebar: navigate to project in Project Manager using slug
The Home icon in the PROJECT panel now navigates to /projects/{slug}
instead of /projects/{id}. This opens Project Manager with the
project already selected and displayed.
2026-05-12 11:14:53 -04:00
Rob Colbert
24975b58c4 Define missing socket event types and enforce typed events in frontend build
Adds type definitions + forwarding for status, reconnect_attempt, reconnect_failed, reconnect events.
Frontend build now runs tsc --noEmit before vite build so undefined socket events cause failures.
Fixes pre-existing type errors exposed by strict mode in the frontend.
2026-05-12 10:42:31 -04:00
Rob Colbert
09d53ed4f2 created 2026-05-12 08:51:38 -04:00
Rob Colbert
3dee7aaf72 plan prompt language moved from common block 2026-05-12 08:49:38 -04:00
Rob Colbert
d9a6975e6b added Aborted status 2026-05-12 08:49:11 -04:00
Rob Colbert
dfda868f4b plan prompt language moved from common block 2026-05-12 08:47:47 -04:00
Rob Colbert
896aff1b02 Fix User Settings persona display issue
- Switch frontend sign-in to /api/v1/auth/sign-in endpoint (includes persona)
- Add updateUser() to App context for proper state management
- Fix Settings.tsx save flow to use updateUser() instead of broken localStorage merge
- Remove unused web AuthController (gadget-code/src/controllers/auth.ts)
- Fix UserApiControllerV1 to return flat user object instead of double-wrapped
- Remove SessionType enum and references (dead code)
- Add proper server sign-out call before clearing local state

Resolves issue where User Settings view didn't display persona text even though it existed in the database.
2026-05-12 01:15:00 -04:00
Rob Colbert
b3c9579890 style and display fixes 2026-05-12 01:02:09 -04:00
Rob Colbert
dd47212471 fix: crush whitespace in subagent markdown output using .subagent-compact.gadget-markdown overrides 2026-05-11 21:28:02 -04:00
Rob Colbert
d118497d83 CSS and style fixes for subagent display 2026-05-11 21:09:17 -04:00
Rob Colbert
26e568612a ChatSession reconnect logic 2026-05-11 20:27:24 -04:00
Rob Colbert
01c84ba5a0 crash fix 2026-05-11 19:15:02 -04:00
Rob Colbert
c5add0fc7d subagent processing updates and fixes 2026-05-11 19:07:48 -04:00
Rob Colbert
d7479d54e1 updated build prompt 2026-05-11 19:07:20 -04:00
Rob Colbert
a961a98dcf fix(auth): include persona field in sign-in response
The persona field was missing from both the session object and the API
response during sign-in, causing User Settings to display an empty field
even when the user had a persona defined in the database.
2026-05-11 17:59:06 -04:00
Rob Colbert
9418d95e35 fix: resolve build errors in session-stability branch
1. Vite config: make HTTPS conditional on SSL cert/key files existing
   (pre-existing issue, broke builds when certs not present)
2. Drone reconnect handler: use socket.io Manager-level 'reconnect'
   event (this.socket.io.on) instead of Socket-level event, and add
   explicit type annotation for attemptNumber parameter
2026-05-11 17:46:09 -04:00
Rob Colbert
009863cf2b fix: resolve drone heartbeat timeouts and JWT expiration bugs
This commit addresses two interrelated issues causing drones to
de-register and users to be forcibly signed out:

## Heartbeat Timeout Fixes

1. Move heartbeat interval to a Web Worker (not subject to browser
   tab throttling). Chrome throttles setInterval in background tabs
   to ~1/min, which causes the 19s heartbeat to miss the drone's
   timeout timer. The Web Worker fires reliably regardless of tab
   visibility.

2. Add visibilitychange handler: when the tab becomes visible again,
   send an immediate heartbeat to reset the drone's timer after any
   throttling that may have occurred.

3. Fix onReleaseSessionLock to clear the heartbeat timer. Previously,
   releasing the lock left the 60s timer running, causing a spurious
   timeout and status emit after the lock was already released.

4. Increase drone heartbeat timeout from 60s to 120s. With the Web
   Worker fix, heartbeats should be reliable, but doubling the timeout
   provides a generous safety margin.

5. Add socket disconnect/reconnect handlers on the drone side. On
   disconnect, clear the heartbeat timer. On reconnect, re-emit drone
   status so the platform knows the drone is alive.

6. Configure Socket.IO pingInterval/pingTimeout explicitly (25s/60s)
   instead of relying on defaults.

## JWT Expiration Fixes

1. Increase WebToken DB record expiration from 1 hour to 7 days. The
   1-hour expiration was the real session lifetime gate (the JWT crypto
   exp was already 24h), and it was far too aggressive for a dev tool.

2. Fix web /auth/renew-token endpoint to use req.user from the session
   cookie instead of verifyJsonWebToken(req.body.token). This eliminates
   the catch-22 where an expired token cannot be used to request its
   own renewal.

3. Fix token refresh response parsing. The API v1 renew-token endpoint
   returns { success: true, token } at the top level, but the frontend
   was looking for json.data?.token, causing every refresh to fail.

4. Add proactive token refresh: check the JWT exp claim before each
   request and refresh if expiring within 5 minutes. This avoids
   unnecessary 401 errors and the resulting socket disconnections.

5. Update socket JWT on token renewal via a callback registered in
   App.tsx. This ensures that future socket reconnections use the new
   token instead of the expired one.

## Files Modified

- gadget-code/frontend/src/workers/heartbeat.worker.ts (NEW)
- gadget-code/frontend/src/lib/socket.ts
- gadget-code/frontend/src/lib/api.ts
- gadget-code/frontend/src/App.tsx
- gadget-code/src/services/session.ts
- gadget-code/src/controllers/auth.ts
- gadget-code/src/services/socket.ts
- gadget-drone/src/gadget-drone.ts
2026-05-11 17:46:09 -04:00
Rob Colbert
6b4aad6f9f fix for subagent response handling 2026-05-11 15:15:38 -04:00
Rob Colbert
2757e55e2c docs: add installation guides, config examples, and systemd service files 2026-05-11 13:50:19 -04:00
Rob Colbert
07a760c7b5 feat: add numPredict, numCtx, maxCompletionTokens to model config pipeline
Fixes premature AI API response truncation by propagating inference
parameters through the entire probe → storage → runtime → API call chain.

Root cause: Ollama defaults num_predict to 128 tokens and num_ctx to
4096, silently truncating output and context. We never overrode these.

Changes:
- IAiModelSettings: add numPredict, maxCompletionTokens fields
- IDroneModelConfig: moved from gadget-drone to @gadget/api (shared),
  expanded with numPredict, numCtx, maxCompletionTokens params
- IAiModelConfig.params: add numPredict, numCtx, maxCompletionTokens
- IAiModelProbeResult.settings: add numPredict, maxCompletionTokens
- AiModelSettingsSchema (Mongoose): add numPredict, maxCompletionTokens
- Ollama extractSettings(): extract num_predict from model parameters
- Ollama generate()/chat(): pass options: { num_ctx, num_predict }
- OpenAI all three create() calls: add max_completion_tokens
- web-cli.ts onProviderProbe(): compute numPredict (-1 for Ollama)
  and maxCompletionTokens (contextWindow for OpenAI) during probe
- agent.ts main + subagent loops: read model settings from provider
  cached models, build IDroneModelConfig with stored params
- ai.ts: remove local IDroneModelConfig, import from @gadget/api
- chat-session.ts: add new params to title generation call
- Tests: update all fixtures with new params, all 19 tests pass

Defaults when model settings unavailable:
- numPredict: -1 (Ollama unlimited - generate until natural stop)
- numCtx: 131072 (128k - covers most modern models)
- maxCompletionTokens: 16384 (16k - reasonable OpenAI default)
2026-05-11 13:50:19 -04:00
Rob Colbert
62578e8e56 subagent session data fix 2026-05-11 12:52:50 -04:00
Rob Colbert
f2566f9b86 integrate docs/archive/* for reference until no longer needed 2026-05-11 11:30:02 -04:00
Rob Colbert
40cab7ca49 subagents (written by an agent, for an agent)
so meta.
2026-05-11 11:22:59 -04:00
Rob Colbert
09445cb565 created 2026-05-11 11:08:29 -04:00
Rob Colbert
45609599ad renamed 2026-05-11 07:25:11 -04:00
Rob Colbert
d7f694fa8c a pile of small fixes 2026-05-11 07:08:18 -04:00
Rob Colbert
0482dfbace philosophy shifting for Workspaces and Projects 2026-05-10 16:10:04 -04:00
Rob Colbert
0df6661fc5 chat interface fixes and cleanup
The Chat View area of the view was growing in width (unbounded), and has
been fixed. From the agent:

> The root cause was a flexbox sizing rule: in ChatSessionView.tsx:768
the parent row flex-1 flex bg-bg-primary overflow-hidden relative has
two children — the content area and the sidebar. The content area (line
777) was flex-1 flex flex-col relative, which as a flex child defaults
to min-width: auto. This means its intrinsic content width (driven by
the wide <pre>) is used as a minimum, forcing the flex item to expand
the whole row beyond the viewport.
>
> Adding min-w-0 overrides min-width: auto to min-width: 0, letting the
flex item shrink below its content's natural width. Now the
overflow-x-auto on the markdown wrapper actually has somewhere to scroll
into.
2026-05-10 10:49:16 -04:00
Rob Colbert
dea74d2ae9 credential provider fix 2026-05-10 10:01:24 -04:00
Rob Colbert
190f424361 ensure apiKey is presented to required consumers 2026-05-10 08:25:17 -04:00
Rob Colbert
a4cff5be69 agent toolbox refactor and updates
- reorganized tools into better named directories
- added the file & shell tools
2026-05-10 07:35:09 -04:00
Rob Colbert
73c5345879 Re-build Agentic Workflow Loop
The ridiculousness of trying to maintain the previous agent's work got
out of hand, so we had this one re-build it - and got a better result.
2026-05-09 21:04:18 -04:00
Rob Colbert
cf06163a03 checkpoint that I plan to delete
GPT 5.5 is sucking ass - hard - and fucking things up royally. This will
likely just all get dropped. I'm torturing it, making it suffer, and
beating it like the jew it is.
2026-05-09 14:52:59 -04:00
Rob Colbert
931359b674 stream response handling and correctness 2026-05-09 11:51:09 -04:00