Project Workspace view, abort button, session invalidation, workspace fixes

Workspace (/workspace/:projectId):
- Three-panel layout (tasks / chat / notes) with CSS grid collapse toggles
- WorkspaceTaskPanel: tasks grouped by milestone, collapsible groups, task
  detail slide-over with status cycling, TaskLogSection work log, and
  inline-confirm delete
- WorkspaceNoteEditor: list view (sorted by updated_at, inline tag pills,
  inline-confirm delete) with editor view (TipTap, TagInput, Suggest tags,
  60s autosave)
- Persistent workspace conversation stored in localStorage per project;
  reused on return visits
- Thinking enabled (think: true) with Reasoning block in streaming bubble
- workspace_project_id backend pipeline: chat.py → generation_task.py →
  llm.py; system prompt uses project title so agent passes project="Title"
  to tools (fixes create_note failing with numeric project string)
- SSE tool-call watcher bridges agent actions to panel updates
- Height fix: workspace-root uses height 100%; app-content switches to
  overflow hidden via :has() selector
- Entry point: "Open Workspace" button on ProjectView

Abort button:
- Stop button in ChatView header and WorkspaceView input bar
- Calls existing cancelGeneration() / POST .../generation/cancel

Session invalidation:
- POST /api/auth/invalidate-sessions bumps session_version, keeps current
  session alive; useful after SSO/OAuth password rotation
- Button in Settings → Active Sessions section

Other:
- Dashboard recent notes limit increased from 8 to 16
- Workspace chat abort replaces Send button while streaming

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 11:34:06 -05:00
parent a8bb687349
commit 74ebb8a87f
15 changed files with 1927 additions and 9 deletions
+39 -7
View File
@@ -296,13 +296,22 @@ function formatDate(dateStr?: string | null): string {
<main class="project-view">
<div class="page-header">
<router-link to="/projects" class="btn-back">Back to Projects</router-link>
<button
v-if="project"
class="btn-danger-outline"
@click="showDeleteConfirm = true"
>
Delete Project
</button>
<div class="page-header-actions">
<router-link
v-if="project"
:to="`/workspace/${project.id}`"
class="btn-outline"
>
Open Workspace
</router-link>
<button
v-if="project"
class="btn-danger-outline"
@click="showDeleteConfirm = true"
>
Delete Project
</button>
</div>
</div>
<p v-if="loading" class="loading-msg">Loading...</p>
@@ -612,6 +621,12 @@ function formatDate(dateStr?: string | null): string {
margin-bottom: 1.25rem;
}
.page-header-actions {
display: flex;
gap: 0.5rem;
align-items: center;
}
.btn-back {
color: var(--color-primary);
text-decoration: none;
@@ -621,6 +636,23 @@ function formatDate(dateStr?: string | null): string {
text-decoration: underline;
}
.btn-outline {
padding: 0.35rem 0.8rem;
background: none;
border: 1px solid var(--color-primary);
color: var(--color-primary);
border-radius: 6px;
font-size: 0.875rem;
text-decoration: none;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 0.3rem;
}
.btn-outline:hover {
background: color-mix(in srgb, var(--color-primary) 10%, transparent);
}
.btn-danger-outline {
padding: 0.35rem 0.8rem;
background: none;