conductor-oss 0.2.16 → 0.2.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +4 -2
  3. package/dist/index.js.map +1 -1
  4. package/node_modules/@conductor-oss/plugin-agent-amp/package.json +1 -1
  5. package/node_modules/@conductor-oss/plugin-agent-ccr/package.json +1 -1
  6. package/node_modules/@conductor-oss/plugin-agent-claude-code/package.json +1 -1
  7. package/node_modules/@conductor-oss/plugin-agent-codex/package.json +1 -1
  8. package/node_modules/@conductor-oss/plugin-agent-cursor-cli/package.json +1 -1
  9. package/node_modules/@conductor-oss/plugin-agent-droid/package.json +1 -1
  10. package/node_modules/@conductor-oss/plugin-agent-gemini/package.json +1 -1
  11. package/node_modules/@conductor-oss/plugin-agent-github-copilot/package.json +1 -1
  12. package/node_modules/@conductor-oss/plugin-agent-opencode/package.json +1 -1
  13. package/node_modules/@conductor-oss/plugin-agent-qwen-code/package.json +1 -1
  14. package/node_modules/@conductor-oss/plugin-mcp-server/package.json +1 -1
  15. package/node_modules/@conductor-oss/plugin-notifier-desktop/package.json +1 -1
  16. package/node_modules/@conductor-oss/plugin-notifier-discord/package.json +1 -1
  17. package/node_modules/@conductor-oss/plugin-runtime-tmux/package.json +1 -1
  18. package/node_modules/@conductor-oss/plugin-scm-github/package.json +1 -1
  19. package/node_modules/@conductor-oss/plugin-terminal-web/package.json +1 -1
  20. package/node_modules/@conductor-oss/plugin-tracker-github/package.json +1 -1
  21. package/node_modules/@conductor-oss/plugin-webhook/package.json +1 -1
  22. package/node_modules/@conductor-oss/plugin-workspace-worktree/package.json +1 -1
  23. package/package.json +21 -21
  24. package/web/.next/standalone/packages/web/.next/BUILD_ID +1 -1
  25. package/web/.next/standalone/packages/web/.next/app-path-routes-manifest.json +1 -0
  26. package/web/.next/standalone/packages/web/.next/build-manifest.json +2 -2
  27. package/web/.next/standalone/packages/web/.next/prerender-manifest.json +3 -3
  28. package/web/.next/standalone/packages/web/.next/routes-manifest.json +8 -0
  29. package/web/.next/standalone/packages/web/.next/server/app/_global-error.html +2 -2
  30. package/web/.next/standalone/packages/web/.next/server/app/_global-error.rsc +1 -1
  31. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  32. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  33. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  34. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  35. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  36. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page/server-reference-manifest.json +7 -7
  37. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  38. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  39. package/web/.next/standalone/packages/web/.next/server/app/_not-found.html +1 -1
  40. package/web/.next/standalone/packages/web/.next/server/app/_not-found.rsc +3 -3
  41. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  42. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  43. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  44. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  45. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  46. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  47. package/web/.next/standalone/packages/web/.next/server/app/api/access/route.js.nft.json +1 -1
  48. package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route.js.nft.json +1 -1
  49. package/web/.next/standalone/packages/web/.next/server/app/api/boards/route.js.nft.json +1 -1
  50. package/web/.next/standalone/packages/web/.next/server/app/api/config/route.js.nft.json +1 -1
  51. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route.js.nft.json +1 -1
  52. package/web/.next/standalone/packages/web/.next/server/app/api/events/route.js.nft.json +1 -1
  53. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route.js.nft.json +1 -1
  54. package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route.js.nft.json +1 -1
  55. package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route.js.nft.json +1 -1
  56. package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route.js.nft.json +1 -1
  57. package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route.js.nft.json +1 -1
  58. package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route.js.nft.json +1 -1
  59. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route.js.nft.json +1 -1
  60. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route.js.nft.json +1 -1
  61. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route.js.nft.json +1 -1
  62. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route.js.nft.json +1 -1
  63. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route/app-paths-manifest.json +3 -0
  64. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route/build-manifest.json +11 -0
  65. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route/server-reference-manifest.json +4 -0
  66. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route.js +10 -0
  67. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route.js.map +5 -0
  68. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route.js.nft.json +1 -0
  69. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route_client-reference-manifest.js +2 -0
  70. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route.js.nft.json +1 -1
  71. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route.js.nft.json +1 -1
  72. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route.js.nft.json +1 -1
  73. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route.js.nft.json +1 -1
  74. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route.js.nft.json +1 -1
  75. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route.js.nft.json +1 -1
  76. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route.js.nft.json +1 -1
  77. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  78. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route.js.nft.json +1 -1
  79. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route.js.nft.json +1 -1
  80. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route.js +1 -1
  81. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route.js.nft.json +1 -1
  82. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route.js.nft.json +1 -1
  83. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  84. package/web/.next/standalone/packages/web/.next/server/app/index.html +1 -1
  85. package/web/.next/standalone/packages/web/.next/server/app/index.rsc +4 -4
  86. package/web/.next/standalone/packages/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  87. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_full.segment.rsc +4 -4
  88. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  89. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_index.segment.rsc +3 -3
  90. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  91. package/web/.next/standalone/packages/web/.next/server/app/page/react-loadable-manifest.json +1 -1
  92. package/web/.next/standalone/packages/web/.next/server/app/page/server-reference-manifest.json +7 -7
  93. package/web/.next/standalone/packages/web/.next/server/app/page.js.nft.json +1 -1
  94. package/web/.next/standalone/packages/web/.next/server/app/page_client-reference-manifest.js +1 -1
  95. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page/server-reference-manifest.json +7 -7
  96. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  97. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  98. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page/server-reference-manifest.json +7 -7
  99. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page.js.nft.json +1 -1
  100. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page_client-reference-manifest.js +1 -1
  101. package/web/.next/standalone/packages/web/.next/server/app/unlock/page/server-reference-manifest.json +7 -7
  102. package/web/.next/standalone/packages/web/.next/server/app/unlock/page.js.nft.json +1 -1
  103. package/web/.next/standalone/packages/web/.next/server/app/unlock/page_client-reference-manifest.js +1 -1
  104. package/web/.next/standalone/packages/web/.next/server/app-paths-manifest.json +1 -0
  105. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_feed_route_actions_d88aaa25.js +3 -0
  106. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__346d9484._.js +3 -0
  107. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__53385c40._.js +3 -0
  108. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__98c6a6f3._.js → [root-of-the-server]__6c10c03b._.js} +2 -2
  109. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__9726f664._.js → [root-of-the-server]__12eb9005._.js} +2 -2
  110. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__6622b514._.js +1 -1
  111. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__869d9ac0._.js +1 -1
  112. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__9dc23e5a._.js +1 -1
  113. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__b388693f._.js +1 -1
  114. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_0e1412de._.js +1 -1
  115. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{_b0abbdd9._.js → _20a4007d._.js} +2 -2
  116. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_69e05fca._.js +1 -1
  117. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_80efe193._.js +1 -1
  118. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_b6d31783._.js +1 -1
  119. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{_0973acf3._.js → _b88bcf2c._.js} +2 -2
  120. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_c0f0e227._.js +1 -1
  121. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_f36ddaa9._.js +1 -1
  122. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{node_modules_@clerk_nextjs_dist_esm_app-router_bf11b471._.js → node_modules_@clerk_nextjs_dist_esm_app-router_78af9fdf._.js} +2 -2
  123. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_c4bad84a._.js +3 -0
  124. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_f2ebd7a9._.js +1 -1
  125. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_79316445._.js +1 -1
  126. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_a078c137._.js +1 -1
  127. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_app_page_tsx_cd282e82._.js +1 -1
  128. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{packages_web_src_components_dd296b40._.js → packages_web_src_components_3809c507._.js} +1 -1
  129. package/web/.next/standalone/packages/web/.next/server/pages/404.html +1 -1
  130. package/web/.next/standalone/packages/web/.next/server/pages/500.html +2 -2
  131. package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.js +1 -1
  132. package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.json +8 -8
  133. package/web/.next/standalone/packages/web/.next/static/chunks/1e67fbc3874d3f51.js +1 -0
  134. package/web/.next/{static/chunks/e88fa6d41d743b9e.js → standalone/packages/web/.next/static/chunks/28dd6ef2af62b509.js} +2 -2
  135. package/web/.next/standalone/packages/web/.next/static/chunks/2b2a24dff50e7dc9.js +1 -0
  136. package/web/.next/standalone/packages/web/.next/static/chunks/483eb2824f5282c7.js +1 -0
  137. package/web/.next/standalone/packages/web/.next/static/chunks/695b7cb206c6dadd.js +1 -0
  138. package/web/.next/standalone/packages/web/.next/static/chunks/860d84e1f09476a4.css +3 -0
  139. package/web/.next/standalone/packages/web/.next/static/chunks/{86bce89c37cf6212.js → c959976264f14eba.js} +1 -1
  140. package/web/.next/standalone/packages/web/.next/static/chunks/{4c566fd1e4a92935.js → d9d05e7b540400af.js} +1 -1
  141. package/web/.next/standalone/packages/web/.next/static/chunks/e862e73b22fe29c2.js +1 -0
  142. package/web/.next/{static/chunks/719697e99b51d55b.js → standalone/packages/web/.next/static/chunks/f5d9ad0f62ede339.js} +1 -1
  143. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/feed/route.ts +97 -0
  144. package/web/.next/standalone/packages/web/src/app/page.tsx +3 -4555
  145. package/web/.next/standalone/packages/web/src/app/sessions/[id]/page.tsx +2 -115
  146. package/web/.next/standalone/packages/web/src/components/layout/AppShell.tsx +62 -2
  147. package/web/.next/standalone/packages/web/src/components/layout/TopBar.tsx +13 -11
  148. package/web/.next/standalone/packages/web/src/components/layout/WorkspaceSidebarPanel.tsx +68 -10
  149. package/web/.next/standalone/packages/web/src/features/dashboard/DashboardClient.tsx +4571 -0
  150. package/web/.next/standalone/packages/web/src/features/dashboard/components/WorkspaceOverview.tsx +296 -0
  151. package/web/.next/standalone/packages/web/src/features/sessions/SessionPageClient.tsx +125 -0
  152. package/web/.next/standalone/packages/web/src/hooks/useSessionFeed.ts +17 -13
  153. package/web/.next/standalone/packages/web/src/hooks/useSessions.ts +37 -7
  154. package/web/.next/static/chunks/1e67fbc3874d3f51.js +1 -0
  155. package/web/.next/{standalone/packages/web/.next/static/chunks/e88fa6d41d743b9e.js → static/chunks/28dd6ef2af62b509.js} +2 -2
  156. package/web/.next/static/chunks/2b2a24dff50e7dc9.js +1 -0
  157. package/web/.next/static/chunks/483eb2824f5282c7.js +1 -0
  158. package/web/.next/static/chunks/695b7cb206c6dadd.js +1 -0
  159. package/web/.next/static/chunks/860d84e1f09476a4.css +3 -0
  160. package/web/.next/static/chunks/{86bce89c37cf6212.js → c959976264f14eba.js} +1 -1
  161. package/web/.next/static/chunks/{4c566fd1e4a92935.js → d9d05e7b540400af.js} +1 -1
  162. package/web/.next/static/chunks/e862e73b22fe29c2.js +1 -0
  163. package/web/.next/{standalone/packages/web/.next/static/chunks/719697e99b51d55b.js → static/chunks/f5d9ad0f62ede339.js} +1 -1
  164. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_8a444735._.js +0 -3
  165. package/web/.next/standalone/packages/web/.next/static/chunks/1867dba46fcc022e.js +0 -1
  166. package/web/.next/standalone/packages/web/.next/static/chunks/19d7d4e2cfe3261a.js +0 -1
  167. package/web/.next/standalone/packages/web/.next/static/chunks/ab8ef6c7dfc78082.js +0 -1
  168. package/web/.next/standalone/packages/web/.next/static/chunks/b5e2d1ef92e508a0.js +0 -1
  169. package/web/.next/standalone/packages/web/.next/static/chunks/e8283780c26eaa91.js +0 -1
  170. package/web/.next/standalone/packages/web/.next/static/chunks/fe557eb4039d8a8d.css +0 -3
  171. package/web/.next/static/chunks/1867dba46fcc022e.js +0 -1
  172. package/web/.next/static/chunks/19d7d4e2cfe3261a.js +0 -1
  173. package/web/.next/static/chunks/ab8ef6c7dfc78082.js +0 -1
  174. package/web/.next/static/chunks/b5e2d1ef92e508a0.js +0 -1
  175. package/web/.next/static/chunks/e8283780c26eaa91.js +0 -1
  176. package/web/.next/static/chunks/fe557eb4039d8a8d.css +0 -3
  177. /package/web/.next/standalone/packages/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_buildManifest.js +0 -0
  178. /package/web/.next/standalone/packages/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_clientMiddlewareManifest.json +0 -0
  179. /package/web/.next/standalone/packages/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_ssgManifest.js +0 -0
  180. /package/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_buildManifest.js +0 -0
  181. /package/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_clientMiddlewareManifest.json +0 -0
  182. /package/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_ssgManifest.js +0 -0
@@ -1,120 +1,7 @@
1
1
  "use client";
2
2
 
3
- import { useEffect, useMemo, useState } from "react";
4
- import { useParams, useRouter } from "next/navigation";
5
- import { AppShell } from "@/components/layout/AppShell";
6
- import { WorkspaceSidebarPanel } from "@/components/layout/WorkspaceSidebarPanel";
7
- import { SessionDetail } from "@/components/sessions/SessionDetail";
8
- import { useConfig } from "@/hooks/useConfig";
9
- import { useSessions } from "@/hooks/useSessions";
10
- import type { DashboardSession } from "@/lib/types";
3
+ import SessionPageClient from "@/features/sessions/SessionPageClient";
11
4
 
12
5
  export default function SessionPage() {
13
- const params = useParams<{ id: string }>();
14
- const router = useRouter();
15
- const { projects } = useConfig();
16
- const { sessions, refresh } = useSessions();
17
- const dashboardSessions = sessions as unknown as DashboardSession[];
18
- const [sidebarOpen, setSidebarOpen] = useState(true);
19
- const [selectedProjectId, setSelectedProjectId] = useState<string | null>(null);
20
-
21
- useEffect(() => {
22
- if (typeof window === "undefined") return;
23
- if (window.innerWidth < 1024) {
24
- setSidebarOpen(false);
25
- }
26
- }, []);
27
-
28
- const selectedSession = useMemo(
29
- () => dashboardSessions.find((session) => session.id === params.id) ?? null,
30
- [dashboardSessions, params.id],
31
- );
32
-
33
- useEffect(() => {
34
- if (selectedSession?.projectId) {
35
- setSelectedProjectId(selectedSession.projectId);
36
- return;
37
- }
38
- if (!selectedProjectId && projects.length > 0) {
39
- setSelectedProjectId(projects[0]?.id ?? null);
40
- }
41
- }, [projects, selectedProjectId, selectedSession?.projectId]);
42
-
43
- const toggleSidebar = () => setSidebarOpen((prev) => !prev);
44
-
45
- const closeSidebarOnMobile = () => {
46
- if (typeof window !== "undefined" && window.innerWidth < 1024) {
47
- setSidebarOpen(false);
48
- }
49
- };
50
-
51
- async function handleArchiveSession(sessionId: string) {
52
- let res = await fetch(`/api/sessions/${encodeURIComponent(sessionId)}/archive`, {
53
- method: "POST",
54
- });
55
- let data = (await res.json().catch(() => null)) as
56
- | { ok?: boolean; error?: string }
57
- | null;
58
-
59
- if (res.status === 404) {
60
- res = await fetch(`/api/sessions/${encodeURIComponent(sessionId)}/actions`, {
61
- method: "POST",
62
- headers: { "Content-Type": "application/json" },
63
- body: JSON.stringify({ action: "archive" }),
64
- });
65
- data = (await res.json().catch(() => null)) as
66
- | { ok?: boolean; error?: string }
67
- | null;
68
- }
69
-
70
- if (!res.ok) {
71
- throw new Error(data?.error ?? `Failed to archive session: ${res.status}`);
72
- }
73
-
74
- if (sessionId === params.id) {
75
- router.push("/");
76
- return;
77
- }
78
-
79
- await refresh();
80
- }
81
-
82
- if (!params.id) {
83
- return (
84
- <div className="flex h-dvh min-h-[100dvh] items-center justify-center">
85
- <span className="text-[13px] text-[var(--text-muted)]">No session ID provided</span>
86
- </div>
87
- );
88
- }
89
-
90
- return (
91
- <AppShell
92
- sidebarOpen={sidebarOpen}
93
- onToggleSidebar={toggleSidebar}
94
- sidebar={
95
- <WorkspaceSidebarPanel
96
- orgLabel="conductor-oss"
97
- projects={projects}
98
- selectedProjectId={selectedProjectId}
99
- onSelectProject={(projectId) => {
100
- setSelectedProjectId(projectId);
101
- }}
102
- sessions={dashboardSessions}
103
- selectedSessionId={params.id}
104
- onSelectSession={(sessionId) => {
105
- router.push(`/sessions/${encodeURIComponent(sessionId)}?tab=chat`);
106
- closeSidebarOnMobile();
107
- }}
108
- onArchiveSession={handleArchiveSession}
109
- onCreateWorkspace={() => {
110
- router.push("/");
111
- }}
112
- />
113
- }
114
- >
115
- <div className="min-h-0 flex-1 overflow-hidden">
116
- <SessionDetail sessionId={params.id} />
117
- </div>
118
- </AppShell>
119
- );
6
+ return <SessionPageClient />;
120
7
  }
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import type { CSSProperties, ReactNode } from "react";
3
+ import { useEffect, useState, type CSSProperties, type ReactNode } from "react";
4
4
  import { PanelLeftOpen, PanelRightClose } from "lucide-react";
5
5
  import { cn } from "@/lib/cn";
6
6
 
@@ -11,13 +11,63 @@ interface AppShellProps {
11
11
  onToggleSidebar: () => void;
12
12
  }
13
13
 
14
+ const DEFAULT_SIDEBAR_WIDTH = 356;
15
+ const MIN_SIDEBAR_WIDTH = 296;
16
+ const MAX_SIDEBAR_WIDTH = 460;
17
+ const SIDEBAR_WIDTH_STORAGE_KEY = "conductor-workspace-sidebar-width";
18
+
14
19
  export function AppShell({
15
20
  sidebar,
16
21
  children,
17
22
  sidebarOpen,
18
23
  onToggleSidebar,
19
24
  }: AppShellProps) {
20
- const shellStyle = { "--workspace-sidebar-width": "356px" } as CSSProperties;
25
+ const [sidebarWidth, setSidebarWidth] = useState(DEFAULT_SIDEBAR_WIDTH);
26
+ const [resizing, setResizing] = useState(false);
27
+
28
+ useEffect(() => {
29
+ try {
30
+ const stored = window.localStorage.getItem(SIDEBAR_WIDTH_STORAGE_KEY);
31
+ const parsed = stored ? Number.parseInt(stored, 10) : Number.NaN;
32
+ if (Number.isFinite(parsed)) {
33
+ setSidebarWidth(Math.min(MAX_SIDEBAR_WIDTH, Math.max(MIN_SIDEBAR_WIDTH, parsed)));
34
+ }
35
+ } catch {
36
+ // Ignore invalid persisted width values.
37
+ }
38
+ }, []);
39
+
40
+ useEffect(() => {
41
+ if (!resizing) return;
42
+
43
+ const handlePointerMove = (event: MouseEvent) => {
44
+ const nextWidth = Math.min(MAX_SIDEBAR_WIDTH, Math.max(MIN_SIDEBAR_WIDTH, event.clientX));
45
+ setSidebarWidth(nextWidth);
46
+ };
47
+
48
+ const handlePointerUp = () => {
49
+ setResizing(false);
50
+ };
51
+
52
+ window.addEventListener("mousemove", handlePointerMove);
53
+ window.addEventListener("mouseup", handlePointerUp);
54
+ document.body.style.userSelect = "none";
55
+ document.body.style.cursor = "col-resize";
56
+
57
+ return () => {
58
+ window.removeEventListener("mousemove", handlePointerMove);
59
+ window.removeEventListener("mouseup", handlePointerUp);
60
+ document.body.style.userSelect = "";
61
+ document.body.style.cursor = "";
62
+ try {
63
+ window.localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(sidebarWidth));
64
+ } catch {
65
+ // Ignore storage write failures.
66
+ }
67
+ };
68
+ }, [resizing, sidebarWidth]);
69
+
70
+ const shellStyle = { "--workspace-sidebar-width": `${sidebarWidth}px` } as CSSProperties;
21
71
 
22
72
  return (
23
73
  <div
@@ -45,6 +95,16 @@ export function AppShell({
45
95
  {sidebar}
46
96
  </aside>
47
97
 
98
+ {sidebarOpen ? (
99
+ <div
100
+ className="absolute bottom-0 left-[var(--workspace-sidebar-width)] top-0 z-30 hidden w-2 -translate-x-1/2 cursor-col-resize lg:block"
101
+ onMouseDown={() => setResizing(true)}
102
+ aria-hidden="true"
103
+ >
104
+ <div className="mx-auto h-full w-px bg-transparent transition-colors hover:bg-[var(--vk-border)]" />
105
+ </div>
106
+ ) : null}
107
+
48
108
  {sidebarOpen && (
49
109
  <button
50
110
  type="button"
@@ -18,17 +18,19 @@ export const TopBar = memo(function TopBar({ session, fallbackTitle, onOpenPrefe
18
18
  <div className="min-w-0 flex-1 text-center">
19
19
  <span className="block truncate">{title}</span>
20
20
  </div>
21
- <div className="ml-1 flex shrink-0">
22
- <button
23
- type="button"
24
- onClick={onOpenPreferences}
25
- className="inline-flex h-6 w-6 items-center justify-center rounded-[4px] text-[var(--vk-text-muted)] hover:bg-[var(--vk-bg-hover)] hover:text-[var(--vk-text-normal)]"
26
- aria-label="Open preferences"
27
- title="Preferences"
28
- >
29
- <Settings className="h-3.5 w-3.5" />
30
- </button>
31
- </div>
21
+ {onOpenPreferences ? (
22
+ <div className="ml-1 flex shrink-0">
23
+ <button
24
+ type="button"
25
+ onClick={onOpenPreferences}
26
+ className="inline-flex h-6 w-6 items-center justify-center rounded-[4px] text-[var(--vk-text-muted)] hover:bg-[var(--vk-bg-hover)] hover:text-[var(--vk-text-normal)]"
27
+ aria-label="Open preferences"
28
+ title="Preferences"
29
+ >
30
+ <Settings className="h-3.5 w-3.5" />
31
+ </button>
32
+ </div>
33
+ ) : null}
32
34
  </header>
33
35
  );
34
36
  });
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
 
3
- import { memo } from "react";
4
- import { Plus } from "lucide-react";
3
+ import { memo, useMemo } from "react";
4
+ import { Layers3, Plus } from "lucide-react";
5
5
  import { cn } from "@/lib/cn";
6
- import type { DashboardSession } from "@/lib/types";
6
+ import { getAttentionLevel, type DashboardSession } from "@/lib/types";
7
7
  import { Sidebar } from "@/components/layout/Sidebar";
8
8
 
9
9
  interface ProjectItem {
@@ -34,16 +34,47 @@ export const WorkspaceSidebarPanel = memo(function WorkspaceSidebarPanel({
34
34
  onArchiveSession,
35
35
  onCreateWorkspace,
36
36
  }: WorkspaceSidebarPanelProps) {
37
+ const sessionCountByProject = useMemo(() => {
38
+ const counts = new Map<string, { total: number; active: number }>();
39
+
40
+ for (const session of sessions) {
41
+ if (session.status === "archived") continue;
42
+ const current = counts.get(session.projectId) ?? { total: 0, active: 0 };
43
+ current.total += 1;
44
+ if (getAttentionLevel(session) !== "done") {
45
+ current.active += 1;
46
+ }
47
+ counts.set(session.projectId, current);
48
+ }
49
+
50
+ return counts;
51
+ }, [sessions]);
52
+
53
+ const totalActiveSessions = useMemo(() => {
54
+ return sessions.filter((session) => session.status !== "archived" && getAttentionLevel(session) !== "done").length;
55
+ }, [sessions]);
56
+
37
57
  return (
38
58
  <div className="flex h-full min-h-0 w-full flex-col bg-[var(--vk-bg-panel)]">
39
- <section className="flex h-[57px] items-center border-b border-[var(--vk-border)] px-4">
40
- <p className="truncate text-[15px] font-medium leading-[21px] text-[var(--vk-text-strong)]">
41
- {orgLabel}
42
- </p>
59
+ <section className="border-b border-[var(--vk-border)] px-4 py-4">
60
+ <div className="flex items-start gap-3">
61
+ <span className="inline-flex h-10 w-10 items-center justify-center rounded-[10px] border border-[var(--vk-border)] bg-[var(--vk-bg-main)] text-[var(--vk-text-normal)]">
62
+ <Layers3 className="h-4 w-4" />
63
+ </span>
64
+ <div className="min-w-0 flex-1">
65
+ <p className="truncate text-[15px] font-medium leading-[21px] text-[var(--vk-text-strong)]">
66
+ {orgLabel}
67
+ </p>
68
+ <p className="mt-1 text-[12px] text-[var(--vk-text-muted)]">
69
+ {projects.length} projects, {totalActiveSessions} active sessions
70
+ </p>
71
+ </div>
72
+ </div>
73
+
43
74
  <button
44
75
  type="button"
45
76
  onClick={onCreateWorkspace}
46
- className="ml-auto inline-flex h-7 items-center gap-1 rounded-[4px] border border-[var(--vk-border)] px-2 text-[12px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)]"
77
+ className="mt-3 inline-flex h-8 w-full items-center justify-center gap-1 rounded-[6px] border border-[var(--vk-border)] px-2 text-[12px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)]"
47
78
  aria-label="Add workspace"
48
79
  >
49
80
  <Plus className="h-3.5 w-3.5" />
@@ -56,8 +87,24 @@ export const WorkspaceSidebarPanel = memo(function WorkspaceSidebarPanel({
56
87
  <p className="text-[11px] uppercase tracking-[0.08em] text-[var(--vk-text-muted)]">Projects</p>
57
88
  </div>
58
89
  <div className="max-h-[260px] overflow-y-auto px-2">
90
+ <button
91
+ type="button"
92
+ onClick={() => onSelectProject(null)}
93
+ className={cn(
94
+ "mb-1.5 flex w-full items-center gap-3 rounded-[6px] px-3 py-2.5 text-left text-[14px] leading-[21px]",
95
+ selectedProjectId === null
96
+ ? "bg-[var(--vk-bg-hover)] text-[var(--vk-text-normal)]"
97
+ : "text-[var(--vk-text-muted)] hover:bg-[var(--vk-bg-hover)]",
98
+ )}
99
+ >
100
+ <span className="h-2.5 w-2.5 rounded-full bg-[var(--vk-text-muted)]" />
101
+ <span className="truncate">All projects</span>
102
+ <span className="ml-auto text-[11px] text-[var(--vk-text-muted)]">{sessions.length}</span>
103
+ </button>
104
+
59
105
  {projects.map((project) => {
60
106
  const selected = selectedProjectId === project.id;
107
+ const counts = sessionCountByProject.get(project.id) ?? { total: 0, active: 0 };
61
108
  return (
62
109
  <button
63
110
  key={project.id}
@@ -70,8 +117,19 @@ export const WorkspaceSidebarPanel = memo(function WorkspaceSidebarPanel({
70
117
  : "text-[var(--vk-text-muted)] hover:bg-[var(--vk-bg-hover)]",
71
118
  )}
72
119
  >
73
- <span className="h-2.5 w-2.5 rounded-full bg-[#3c83f6]" />
74
- <span className="truncate">{project.id}</span>
120
+ <span className="mt-1 h-2.5 w-2.5 shrink-0 rounded-full bg-[#3c83f6]" />
121
+ <span className="min-w-0 flex-1">
122
+ <span className="block truncate">{project.id}</span>
123
+ {project.description ? (
124
+ <span className="block truncate text-[11px] text-[var(--vk-text-muted)]">
125
+ {project.description}
126
+ </span>
127
+ ) : null}
128
+ </span>
129
+ <span className="shrink-0 text-right">
130
+ <span className="block text-[11px] text-[var(--vk-text-normal)]">{counts.active} active</span>
131
+ <span className="block text-[10px] text-[var(--vk-text-muted)]">{counts.total} total</span>
132
+ </span>
75
133
  </button>
76
134
  );
77
135
  })}