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.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/node_modules/@conductor-oss/plugin-agent-amp/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-ccr/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-claude-code/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-codex/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-cursor-cli/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-droid/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-gemini/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-github-copilot/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-opencode/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-agent-qwen-code/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-mcp-server/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-notifier-desktop/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-notifier-discord/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-runtime-tmux/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-scm-github/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-terminal-web/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-tracker-github/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-webhook/package.json +1 -1
- package/node_modules/@conductor-oss/plugin-workspace-worktree/package.json +1 -1
- package/package.json +21 -21
- package/web/.next/standalone/packages/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/packages/web/.next/app-path-routes-manifest.json +1 -0
- package/web/.next/standalone/packages/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/packages/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/packages/web/.next/routes-manifest.json +8 -0
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/api/access/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/boards/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/config/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/events/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route/app-paths-manifest.json +3 -0
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route/build-manifest.json +11 -0
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route/server-reference-manifest.json +4 -0
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route.js +10 -0
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route.js.map +5 -0
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route.js.nft.json +1 -0
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route_client-reference-manifest.js +2 -0
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/index.rsc +4 -4
- package/web/.next/standalone/packages/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/web/.next/standalone/packages/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/page/react-loadable-manifest.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app-paths-manifest.json +1 -0
- 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
- package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__346d9484._.js +3 -0
- package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__53385c40._.js +3 -0
- package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__98c6a6f3._.js → [root-of-the-server]__6c10c03b._.js} +2 -2
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__9726f664._.js → [root-of-the-server]__12eb9005._.js} +2 -2
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__6622b514._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__869d9ac0._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__9dc23e5a._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__b388693f._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_0e1412de._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{_b0abbdd9._.js → _20a4007d._.js} +2 -2
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_69e05fca._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_80efe193._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_b6d31783._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{_0973acf3._.js → _b88bcf2c._.js} +2 -2
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_c0f0e227._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_f36ddaa9._.js +1 -1
- 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
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_c4bad84a._.js +3 -0
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_f2ebd7a9._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_79316445._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_a078c137._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_app_page_tsx_cd282e82._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{packages_web_src_components_dd296b40._.js → packages_web_src_components_3809c507._.js} +1 -1
- package/web/.next/standalone/packages/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/packages/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.json +8 -8
- package/web/.next/standalone/packages/web/.next/static/chunks/1e67fbc3874d3f51.js +1 -0
- package/web/.next/{static/chunks/e88fa6d41d743b9e.js → standalone/packages/web/.next/static/chunks/28dd6ef2af62b509.js} +2 -2
- package/web/.next/standalone/packages/web/.next/static/chunks/2b2a24dff50e7dc9.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/483eb2824f5282c7.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/695b7cb206c6dadd.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/860d84e1f09476a4.css +3 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/{86bce89c37cf6212.js → c959976264f14eba.js} +1 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/{4c566fd1e4a92935.js → d9d05e7b540400af.js} +1 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/e862e73b22fe29c2.js +1 -0
- package/web/.next/{static/chunks/719697e99b51d55b.js → standalone/packages/web/.next/static/chunks/f5d9ad0f62ede339.js} +1 -1
- package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/feed/route.ts +97 -0
- package/web/.next/standalone/packages/web/src/app/page.tsx +3 -4555
- package/web/.next/standalone/packages/web/src/app/sessions/[id]/page.tsx +2 -115
- package/web/.next/standalone/packages/web/src/components/layout/AppShell.tsx +62 -2
- package/web/.next/standalone/packages/web/src/components/layout/TopBar.tsx +13 -11
- package/web/.next/standalone/packages/web/src/components/layout/WorkspaceSidebarPanel.tsx +68 -10
- package/web/.next/standalone/packages/web/src/features/dashboard/DashboardClient.tsx +4571 -0
- package/web/.next/standalone/packages/web/src/features/dashboard/components/WorkspaceOverview.tsx +296 -0
- package/web/.next/standalone/packages/web/src/features/sessions/SessionPageClient.tsx +125 -0
- package/web/.next/standalone/packages/web/src/hooks/useSessionFeed.ts +17 -13
- package/web/.next/standalone/packages/web/src/hooks/useSessions.ts +37 -7
- package/web/.next/static/chunks/1e67fbc3874d3f51.js +1 -0
- package/web/.next/{standalone/packages/web/.next/static/chunks/e88fa6d41d743b9e.js → static/chunks/28dd6ef2af62b509.js} +2 -2
- package/web/.next/static/chunks/2b2a24dff50e7dc9.js +1 -0
- package/web/.next/static/chunks/483eb2824f5282c7.js +1 -0
- package/web/.next/static/chunks/695b7cb206c6dadd.js +1 -0
- package/web/.next/static/chunks/860d84e1f09476a4.css +3 -0
- package/web/.next/static/chunks/{86bce89c37cf6212.js → c959976264f14eba.js} +1 -1
- package/web/.next/static/chunks/{4c566fd1e4a92935.js → d9d05e7b540400af.js} +1 -1
- package/web/.next/static/chunks/e862e73b22fe29c2.js +1 -0
- package/web/.next/{standalone/packages/web/.next/static/chunks/719697e99b51d55b.js → static/chunks/f5d9ad0f62ede339.js} +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_8a444735._.js +0 -3
- package/web/.next/standalone/packages/web/.next/static/chunks/1867dba46fcc022e.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/19d7d4e2cfe3261a.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/ab8ef6c7dfc78082.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/b5e2d1ef92e508a0.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/e8283780c26eaa91.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/fe557eb4039d8a8d.css +0 -3
- package/web/.next/static/chunks/1867dba46fcc022e.js +0 -1
- package/web/.next/static/chunks/19d7d4e2cfe3261a.js +0 -1
- package/web/.next/static/chunks/ab8ef6c7dfc78082.js +0 -1
- package/web/.next/static/chunks/b5e2d1ef92e508a0.js +0 -1
- package/web/.next/static/chunks/e8283780c26eaa91.js +0 -1
- package/web/.next/static/chunks/fe557eb4039d8a8d.css +0 -3
- /package/web/.next/standalone/packages/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_buildManifest.js +0 -0
- /package/web/.next/standalone/packages/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/packages/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_ssgManifest.js +0 -0
- /package/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_buildManifest.js +0 -0
- /package/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{7KQ5wRS3BC3qvrkz8yxuS → eSF3qxz6RT8UXiwr-uibJ}/_ssgManifest.js +0 -0
|
@@ -1,120 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
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="
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
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="
|
|
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="
|
|
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
|
})}
|