-
-
-
-
- Loading...
-
-
+
diff --git a/src/components/WorkspacePane.vue b/src/components/WorkspacePane.vue
new file mode 100644
index 0000000..155c734
--- /dev/null
+++ b/src/components/WorkspacePane.vue
@@ -0,0 +1,41 @@
+
+
+
+ Workspace
+ Dashboard, files, artifacts
+
+
+
+
+
+
+
diff --git a/src/composables/usePanels.ts b/src/composables/usePanels.ts
index 6a12cb2..9614c47 100644
--- a/src/composables/usePanels.ts
+++ b/src/composables/usePanels.ts
@@ -1,23 +1,22 @@
/**
- * usePanels.ts — Role-based panel system
+ * usePanels.ts — Pane + panel system
*
- * Determines which panels are available based on tenant features,
- * manages open/closed state persisted to localStorage.
+ * Three top-level panes: chat, workspace, debug
+ * Each pane toggles independently. Debug column contains stacked panels.
*
* Roles (future: from Zitadel JWT claims):
- * user — end consumer (default)
- * creator — content creator, agent designer
- * operator — monitors agents, runs tests
+ * user — end consumer (chat + workspace)
+ * creator — + graph, nodes
+ * operator — + trace, awareness
* dev — full access to all debug tools
- *
- * For now, role is derived from tenant.features.devTools:
- * devTools=true → dev role (all panels)
- * devTools=false → user role (no side/bottom panels)
*/
import { ref, computed, type Component } from 'vue';
import tenant from '../tenant';
+// Top-level panes (columns)
+export type PaneId = 'chat' | 'workspace';
+// Debug panels (stacked inside the debug column)
export type PanelId = 'graph' | 'trace' | 'nodes' | 'awareness';
export type PanelLocation = 'side' | 'bottom';
export type UserRole = 'user' | 'creator' | 'operator' | 'dev';
@@ -61,26 +60,27 @@ const PANELS: PanelDef[] = [
},
];
-const STORAGE_KEY = 'nyx_panels_open';
+const PANELS_KEY = 'nyx_panels_open';
+const PANES_KEY = 'nyx_panes_open';
-function loadOpenPanels(): Set
{
+function loadSet(key: string, defaults: T[]): Set {
try {
- const stored = localStorage.getItem(STORAGE_KEY);
+ const stored = localStorage.getItem(key);
if (stored) return new Set(JSON.parse(stored));
} catch { /* ignore */ }
- return new Set();
+ return new Set(defaults);
}
-function saveOpenPanels(ids: Set) {
- localStorage.setItem(STORAGE_KEY, JSON.stringify([...ids]));
+function saveSet(key: string, ids: Set) {
+ localStorage.setItem(key, JSON.stringify([...ids]));
}
// Module-level state (survives HMR)
-const openPanelIds = ref>(loadOpenPanels());
+const openPanelIds = ref>(loadSet(PANELS_KEY, []));
+const openPaneIds = ref>(loadSet(PANES_KEY, ['chat']));
export function usePanels() {
- // Current role — derived from tenant features for now.
- // Future: extract from JWT project roles via Zitadel.
+ // Current role
const role = computed(() => {
if (tenant.features.devTools) return 'dev';
return 'user';
@@ -104,16 +104,19 @@ export function usePanels() {
const hasSidePanels = computed(() => openSidePanels.value.length > 0);
const hasBottomPanels = computed(() => openBottomPanels.value.length > 0);
+ // Any debug panel open = debug column visible
+ const hasDebugColumn = hasSidePanels;
+
+ // Pane state
+ const isChatOpen = computed(() => openPaneIds.value.has('chat'));
+ const isWorkspaceOpen = computed(() => openPaneIds.value.has('workspace'));
function togglePanel(id: PanelId) {
const next = new Set(openPanelIds.value);
- if (next.has(id)) {
- next.delete(id);
- } else {
- next.add(id);
- }
+ if (next.has(id)) next.delete(id);
+ else next.add(id);
openPanelIds.value = next;
- saveOpenPanels(next);
+ saveSet(PANELS_KEY, next);
}
function isPanelOpen(id: PanelId): boolean {
@@ -125,19 +128,39 @@ export function usePanels() {
const next = new Set(openPanelIds.value);
next.delete(id);
openPanelIds.value = next;
- saveOpenPanels(next);
+ saveSet(PANELS_KEY, next);
+ }
+
+ function togglePane(id: PaneId) {
+ const next = new Set(openPaneIds.value);
+ if (next.has(id)) next.delete(id);
+ else next.add(id);
+ openPaneIds.value = next;
+ saveSet(PANES_KEY, next);
+ }
+
+ function isPaneOpen(id: PaneId): boolean {
+ return openPaneIds.value.has(id);
}
return {
role,
+ // Debug panels
availablePanels,
openSidePanels,
openBottomPanels,
hasSidePanels,
hasBottomPanels,
+ hasDebugColumn,
togglePanel,
isPanelOpen,
closePanel,
openPanelIds,
+ // Top-level panes
+ isChatOpen,
+ isWorkspaceOpen,
+ togglePane,
+ isPaneOpen,
+ openPaneIds,
};
}
diff --git a/src/views/AgentsView.vue b/src/views/AgentsView.vue
index fcad4df..8b22982 100644
--- a/src/views/AgentsView.vue
+++ b/src/views/AgentsView.vue
@@ -1,5 +1,4 @@
-