@pennyfarthing/cyclist 10.2.0 → 10.3.1
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/LICENSE +14 -0
- package/dist/api/agent-load.js +1 -1
- package/dist/api/agent-load.js.map +1 -1
- package/dist/api/theme-agents.js +2 -2
- package/dist/api/theme-agents.js.map +1 -1
- package/dist/bikerack.d.ts +2 -0
- package/dist/bikerack.d.ts.map +1 -0
- package/dist/bikerack.js +43 -0
- package/dist/bikerack.js.map +1 -0
- package/dist/hooks/cyclist-pretooluse-hook.d.ts +60 -0
- package/dist/hooks/cyclist-pretooluse-hook.d.ts.map +1 -0
- package/dist/hooks/cyclist-pretooluse-hook.js +57 -0
- package/dist/hooks/cyclist-pretooluse-hook.js.map +1 -0
- package/dist/hooks/pretooluse-hook.d.ts +89 -0
- package/dist/hooks/pretooluse-hook.d.ts.map +1 -0
- package/dist/hooks/pretooluse-hook.js +235 -0
- package/dist/hooks/pretooluse-hook.js.map +1 -0
- package/dist/notification-sound.d.ts +59 -0
- package/dist/notification-sound.d.ts.map +1 -0
- package/dist/notification-sound.js +219 -0
- package/dist/notification-sound.js.map +1 -0
- package/dist/plugin-loader.test.d.ts +17 -0
- package/dist/plugin-loader.test.d.ts.map +1 -0
- package/dist/plugin-loader.test.js +407 -0
- package/dist/plugin-loader.test.js.map +1 -0
- package/dist/public/css/react.css +1 -1
- package/dist/public/js/react/react.js +32 -32
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +9 -0
- package/dist/server.js.map +1 -1
- package/dist/sprint-data.d.ts +21 -0
- package/dist/sprint-data.d.ts.map +1 -1
- package/dist/sprint-data.js +26 -1
- package/dist/sprint-data.js.map +1 -1
- package/dist/theme-metadata.js +1 -1
- package/dist/theme-metadata.js.map +1 -1
- package/dist/websocket.js +2 -2
- package/dist/websocket.js.map +1 -1
- package/package.json +32 -33
- package/portraits/a-team/large/face-44442.png +0 -0
- package/portraits/a-team/medium/face-44442.png +0 -0
- package/portraits/alice-in-wonderland/large/tweedles-44342.png +0 -0
- package/portraits/alice-in-wonderland/medium/tweedles-44342.png +0 -0
- package/portraits/battlestar-galactica/large/baltar-53343.png +0 -0
- package/portraits/battlestar-galactica/medium/baltar-53343.png +0 -0
- package/portraits/blade-runner/large/tyrell-54232.png +0 -0
- package/portraits/blade-runner/medium/tyrell-54232.png +0 -0
- package/portraits/catch-22/large/major-34253.png +0 -0
- package/portraits/catch-22/medium/major-34253.png +0 -0
- package/portraits/control/large/burt-44342.png +0 -0
- package/portraits/control/medium/burt-44342.png +0 -0
- package/portraits/cowboy-bebop/large/ed-54342.png +0 -0
- package/portraits/cowboy-bebop/medium/ed-54342.png +0 -0
- package/portraits/discworld/large/moist-44342.png +0 -0
- package/portraits/discworld/medium/moist-44342.png +0 -0
- package/portraits/doctor-who/large/sarah-jane-44342.png +0 -0
- package/portraits/doctor-who/medium/sarah-jane-44342.png +0 -0
- package/portraits/dune/large/thufir-44342.png +0 -0
- package/portraits/dune/medium/thufir-44342.png +0 -0
- package/portraits/fifth-element/large/cornelius-54343.png +0 -0
- package/portraits/fifth-element/large/diva-53453.png +0 -0
- package/portraits/fifth-element/large/korben-34232.png +0 -0
- package/portraits/fifth-element/large/leeloo-54333.png +0 -0
- package/portraits/fifth-element/large/lindberg-34432.png +0 -0
- package/portraits/fifth-element/large/lindberg-44342.png +0 -0
- package/portraits/fifth-element/large/mondoshawan-55131.png +0 -0
- package/portraits/fifth-element/large/munro-25321.png +0 -0
- package/portraits/fifth-element/large/pacoli-45232.png +0 -0
- package/portraits/fifth-element/large/ruby-53544.png +0 -0
- package/portraits/fifth-element/large/zorg-45312.png +0 -0
- package/portraits/fifth-element/medium/cornelius-54343.png +0 -0
- package/portraits/fifth-element/medium/diva-53453.png +0 -0
- package/portraits/fifth-element/medium/korben-34232.png +0 -0
- package/portraits/fifth-element/medium/leeloo-54333.png +0 -0
- package/portraits/fifth-element/medium/lindberg-34432.png +0 -0
- package/portraits/fifth-element/medium/lindberg-44342.png +0 -0
- package/portraits/fifth-element/medium/mondoshawan-55131.png +0 -0
- package/portraits/fifth-element/medium/munro-25321.png +0 -0
- package/portraits/fifth-element/medium/pacoli-45232.png +0 -0
- package/portraits/fifth-element/medium/ruby-53544.png +0 -0
- package/portraits/fifth-element/medium/zorg-45312.png +0 -0
- package/portraits/firefly/large/book-44342.png +0 -0
- package/portraits/firefly/medium/book-44342.png +0 -0
- package/portraits/game-of-thrones/large/varys-44342.png +0 -0
- package/portraits/game-of-thrones/medium/varys-44342.png +0 -0
- package/portraits/harry-potter/large/hermione-44342.png +0 -0
- package/portraits/harry-potter/medium/hermione-44342.png +0 -0
- package/portraits/hitchhikers-guide/large/trillian-44342.png +0 -0
- package/portraits/hitchhikers-guide/medium/trillian-44342.png +0 -0
- package/portraits/lord-of-the-rings/large/elrond-44342.png +0 -0
- package/portraits/lord-of-the-rings/medium/elrond-44342.png +0 -0
- package/portraits/mad-max/large/the-dag-44342.png +0 -0
- package/portraits/mad-max/medium/the-dag-44342.png +0 -0
- package/portraits/mash/large/hawkeye-52544.png +0 -0
- package/portraits/mash/large/klinger-33543.png +0 -0
- package/portraits/mash/large/margaret-34343.png +0 -0
- package/portraits/mash/large/margaret-45443.png +0 -0
- package/portraits/mash/large/mulcahy-34352.png +0 -0
- package/portraits/mash/large/potter-44443.png +0 -0
- package/portraits/mash/large/potter-45342.png +0 -0
- package/portraits/mash/large/radar-24342.png +0 -0
- package/portraits/mash/large/radar-35254.png +0 -0
- package/portraits/mash/large/radar-45242.png +0 -0
- package/portraits/mash/large/winchester-55322.png +0 -0
- package/portraits/mash/medium/hawkeye-52544.png +0 -0
- package/portraits/mash/medium/klinger-33543.png +0 -0
- package/portraits/mash/medium/margaret-34343.png +0 -0
- package/portraits/mash/medium/margaret-45443.png +0 -0
- package/portraits/mash/medium/mulcahy-34352.png +0 -0
- package/portraits/mash/medium/potter-44443.png +0 -0
- package/portraits/mash/medium/potter-45342.png +0 -0
- package/portraits/mash/medium/radar-24342.png +0 -0
- package/portraits/mash/medium/radar-35254.png +0 -0
- package/portraits/mash/medium/radar-45242.png +0 -0
- package/portraits/mash/medium/winchester-55322.png +0 -0
- package/portraits/princess-bride/large/vizzini-54342.png +0 -0
- package/portraits/princess-bride/medium/vizzini-54342.png +0 -0
- package/portraits/sandman/large/lucien-54342.png +0 -0
- package/portraits/sandman/medium/lucien-54342.png +0 -0
- package/portraits/star-trek-tng/large/troi-44352.png +0 -0
- package/portraits/star-trek-tng/medium/troi-44352.png +0 -0
- package/portraits/star-wars/large/mothma-44342.png +0 -0
- package/portraits/star-wars/medium/mothma-44342.png +0 -0
- package/portraits/the-expanse/large/avasarala-44342.png +0 -0
- package/portraits/the-expanse/medium/avasarala-44342.png +0 -0
- package/portraits/the-matrix/large/oracle-44342.png +0 -0
- package/portraits/the-matrix/medium/oracle-44342.png +0 -0
- package/portraits/watchmen/large/veidt-44342.png +0 -0
- package/portraits/watchmen/medium/veidt-44342.png +0 -0
- package/portraits/west-wing/large/c-j-44342.png +0 -0
- package/portraits/west-wing/medium/c-j-44342.png +0 -0
- package/portraits/x-files/large/gunmen-44342.png +0 -0
- package/portraits/x-files/medium/gunmen-44342.png +0 -0
- package/src/public/App.tsx +34 -0
- package/src/public/components/AgentPopup.tsx +1 -0
- package/src/public/components/BikeRackIndex.tsx +54 -0
- package/src/public/components/BikeRackWorkspace.tsx +142 -0
- package/src/public/components/DockviewWorkspace.tsx +5 -6
- package/src/public/components/MessageView.tsx +2 -1
- package/src/public/components/PersonaHeader.tsx +2 -0
- package/src/public/components/StandalonePanel.tsx +84 -0
- package/src/public/components/TandemPortrait.tsx +1 -0
- package/src/public/components/panel-registry.ts +11 -0
- package/src/public/styles/dockview-theme.css +1 -1
- package/src/public/types/electron.d.ts +18 -0
- package/src/public/utils/messageFilters.ts +1 -0
- package/src/public/utils/slash-commands.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pennyfarthing/cyclist",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.3.1",
|
|
4
4
|
"description": "Visual terminal interface for Claude Code",
|
|
5
5
|
"author": "1898andCo",
|
|
6
6
|
"type": "module",
|
|
@@ -19,37 +19,7 @@
|
|
|
19
19
|
"src/public/",
|
|
20
20
|
"portraits/"
|
|
21
21
|
],
|
|
22
|
-
"scripts": {
|
|
23
|
-
"dev": "npm run build && concurrently -k -n tsc,preload,vite,electron -c blue,cyan,magenta,green \"tsc --watch --preserveWatchOutput\" \"tsc -p tsconfig.preload.json --watch --preserveWatchOutput\" \"vite build --watch\" \"electron dist/main.js\"",
|
|
24
|
-
"dev:cdp": "npm run build && concurrently -k -n tsc,preload,vite,electron -c blue,cyan,magenta,green \"tsc --watch --preserveWatchOutput\" \"tsc -p tsconfig.preload.json --watch --preserveWatchOutput\" \"vite build --watch\" \"electron --remote-debugging-port=9222 dist/main.js\"",
|
|
25
|
-
"dev:once": "npm run build && electron dist/main.js",
|
|
26
|
-
"dev:web": "CYCLIST_ELECTRON_MODE= CYCLIST_DEV_WEB=1 CYCLIST_PROJECT_DIR=${CYCLIST_PROJECT_DIR:-$PWD} tsx watch src/server.ts",
|
|
27
|
-
"dev:server": "tsx watch src/server.ts",
|
|
28
|
-
"dev:debug": "CYCLIST_DEV_WEB=1 OTEL_DEBUG=true CYCLIST_PROJECT_DIR=${CYCLIST_PROJECT_DIR:-$PWD} node --inspect src/server.ts",
|
|
29
|
-
"dev:debug-brk": "CYCLIST_DEV_WEB=1 OTEL_DEBUG=true CYCLIST_PROJECT_DIR=${CYCLIST_PROJECT_DIR:-$PWD} node --inspect-brk src/server.ts",
|
|
30
|
-
"dev:electron-debug": "npm run build && concurrently -k -n tsc,preload,vite,electron -c blue,cyan,magenta,green \"tsc --watch --preserveWatchOutput\" \"tsc -p tsconfig.preload.json --watch --preserveWatchOutput\" \"vite build --watch\" \"electron --inspect=9229 dist/main.js\"",
|
|
31
|
-
"dev:vite": "vite --config vite.config.ts",
|
|
32
|
-
"lint": "eslint src/",
|
|
33
|
-
"build": "npm run build:commands && tsc --build && tsc -p tsconfig.preload.json && npm run build:react",
|
|
34
|
-
"build:react": "vite build",
|
|
35
|
-
"build:commands": "node scripts/generate-slash-commands.js",
|
|
36
|
-
"build:electron": "npm run build && electron-builder -c.npmRebuild=false",
|
|
37
|
-
"start": "node dist/server.js",
|
|
38
|
-
"test": "vitest run",
|
|
39
|
-
"test:watch": "vitest",
|
|
40
|
-
"test:e2e": "playwright test",
|
|
41
|
-
"test:e2e:web": "playwright test --project=web-chromium",
|
|
42
|
-
"test:e2e:ui": "playwright test --ui",
|
|
43
|
-
"test:e2e:debug": "playwright test --debug",
|
|
44
|
-
"test:e2e:trace": "playwright show-trace",
|
|
45
|
-
"prepack": "./scripts/copy-portraits.sh",
|
|
46
|
-
"install:app": "./scripts/install-app.sh",
|
|
47
|
-
"install:cli": "./scripts/install-cli.sh",
|
|
48
|
-
"install:all": "npm run install:app && npm run install:cli"
|
|
49
|
-
},
|
|
50
22
|
"dependencies": {
|
|
51
|
-
"@pennyfarthing/core": "workspace:^",
|
|
52
|
-
"@pennyfarthing/shared": "workspace:^",
|
|
53
23
|
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
54
24
|
"@radix-ui/react-checkbox": "^1.3.3",
|
|
55
25
|
"@radix-ui/react-collapsible": "^1.1.12",
|
|
@@ -79,7 +49,9 @@
|
|
|
79
49
|
"ws": "^8.19.0",
|
|
80
50
|
"xterm": "^5.3.0",
|
|
81
51
|
"xterm-addon-fit": "^0.8.0",
|
|
82
|
-
"yaml": "^2.8.2"
|
|
52
|
+
"yaml": "^2.8.2",
|
|
53
|
+
"@pennyfarthing/core": "^10.3.1",
|
|
54
|
+
"@pennyfarthing/shared": "^10.3.1"
|
|
83
55
|
},
|
|
84
56
|
"devDependencies": {
|
|
85
57
|
"@electron/rebuild": "^3.6.0",
|
|
@@ -187,5 +159,32 @@
|
|
|
187
159
|
],
|
|
188
160
|
"category": "Development"
|
|
189
161
|
}
|
|
162
|
+
},
|
|
163
|
+
"scripts": {
|
|
164
|
+
"dev": "npm run build && concurrently -k -n tsc,preload,vite,electron -c blue,cyan,magenta,green \"tsc --watch --preserveWatchOutput\" \"tsc -p tsconfig.preload.json --watch --preserveWatchOutput\" \"vite build --watch\" \"electron dist/main.js\"",
|
|
165
|
+
"dev:cdp": "npm run build && concurrently -k -n tsc,preload,vite,electron -c blue,cyan,magenta,green \"tsc --watch --preserveWatchOutput\" \"tsc -p tsconfig.preload.json --watch --preserveWatchOutput\" \"vite build --watch\" \"electron --remote-debugging-port=9222 dist/main.js\"",
|
|
166
|
+
"dev:once": "npm run build && electron dist/main.js",
|
|
167
|
+
"dev:web": "CYCLIST_ELECTRON_MODE= CYCLIST_DEV_WEB=1 CYCLIST_PROJECT_DIR=${CYCLIST_PROJECT_DIR:-$PWD} tsx watch src/server.ts",
|
|
168
|
+
"dev:server": "tsx watch src/server.ts",
|
|
169
|
+
"dev:debug": "CYCLIST_DEV_WEB=1 OTEL_DEBUG=true CYCLIST_PROJECT_DIR=${CYCLIST_PROJECT_DIR:-$PWD} node --inspect src/server.ts",
|
|
170
|
+
"dev:debug-brk": "CYCLIST_DEV_WEB=1 OTEL_DEBUG=true CYCLIST_PROJECT_DIR=${CYCLIST_PROJECT_DIR:-$PWD} node --inspect-brk src/server.ts",
|
|
171
|
+
"dev:electron-debug": "npm run build && concurrently -k -n tsc,preload,vite,electron -c blue,cyan,magenta,green \"tsc --watch --preserveWatchOutput\" \"tsc -p tsconfig.preload.json --watch --preserveWatchOutput\" \"vite build --watch\" \"electron --inspect=9229 dist/main.js\"",
|
|
172
|
+
"dev:vite": "vite --config vite.config.ts",
|
|
173
|
+
"lint": "eslint src/",
|
|
174
|
+
"build": "npm run build:commands && tsc --build && tsc -p tsconfig.preload.json && npm run build:react",
|
|
175
|
+
"build:react": "vite build",
|
|
176
|
+
"build:commands": "node scripts/generate-slash-commands.js",
|
|
177
|
+
"build:electron": "npm run build && electron-builder -c.npmRebuild=false",
|
|
178
|
+
"start": "node dist/server.js",
|
|
179
|
+
"test": "vitest run",
|
|
180
|
+
"test:watch": "vitest",
|
|
181
|
+
"test:e2e": "playwright test",
|
|
182
|
+
"test:e2e:web": "playwright test --project=web-chromium",
|
|
183
|
+
"test:e2e:ui": "playwright test --ui",
|
|
184
|
+
"test:e2e:debug": "playwright test --debug",
|
|
185
|
+
"test:e2e:trace": "playwright show-trace",
|
|
186
|
+
"install:app": "./scripts/install-app.sh",
|
|
187
|
+
"install:cli": "./scripts/install-cli.sh",
|
|
188
|
+
"install:all": "npm run install:app && npm run install:cli"
|
|
190
189
|
}
|
|
191
|
-
}
|
|
190
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/public/App.tsx
CHANGED
|
@@ -17,11 +17,14 @@ import {
|
|
|
17
17
|
} from './components/DockviewWorkspace';
|
|
18
18
|
import { CommandPaletteProvider } from './components/CommandPalette';
|
|
19
19
|
import { ClaudeProvider } from './contexts/ClaudeContext';
|
|
20
|
+
import ClaudeContext from './contexts/ClaudeContext';
|
|
20
21
|
import { MessageQueueProvider } from './contexts/MessageQueueContext';
|
|
21
22
|
import { useLayoutPersistence } from './hooks/useLayoutPersistence';
|
|
22
23
|
import { loadFontSettings, applyFontSettings } from './utils/font-presets';
|
|
23
24
|
import { loadPresetFromProject, applyPreset } from './utils/color-presets';
|
|
24
25
|
import { ErrorBoundary } from './components/ErrorBoundary';
|
|
26
|
+
import { StandalonePanel, getStandalonePanelName } from './components/StandalonePanel';
|
|
27
|
+
import { BikeRackWorkspace } from './components/BikeRackWorkspace';
|
|
25
28
|
import ApprovalModal, { useApprovalModal } from './components/ApprovalModal';
|
|
26
29
|
import { subscribeToPermissionRequests, sendPermissionResponse, createApprovalResponse } from './components/ApprovalModal';
|
|
27
30
|
import type { ApprovalRequest, GrantScope } from './components/ApprovalModal';
|
|
@@ -198,6 +201,12 @@ function RootErrorFallback(): React.ReactElement {
|
|
|
198
201
|
// =============================================================================
|
|
199
202
|
|
|
200
203
|
export default function App(): React.ReactElement {
|
|
204
|
+
// Detect route mode (computed before hooks, used after)
|
|
205
|
+
const isBikeRackIndex = window.location.pathname === '/bikerack';
|
|
206
|
+
const standalonePanelName = getStandalonePanelName();
|
|
207
|
+
|
|
208
|
+
// --- All hooks called unconditionally (React rules of hooks) ---
|
|
209
|
+
|
|
201
210
|
const { layout, isLoading, saveLayout } = useLayoutPersistence();
|
|
202
211
|
|
|
203
212
|
// Set up reduced motion support
|
|
@@ -254,6 +263,31 @@ export default function App(): React.ReactElement {
|
|
|
254
263
|
hide();
|
|
255
264
|
}, [request, hide]);
|
|
256
265
|
|
|
266
|
+
// --- BikeRack routes (after all hooks) ---
|
|
267
|
+
|
|
268
|
+
// BikeRack Dockview workspace (MSSCI-14877) — /bikerack renders Dockview layout
|
|
269
|
+
// No-op ClaudeContext: BikeRack has no Claude CLI subprocess, skip WebSocket
|
|
270
|
+
if (isBikeRackIndex) {
|
|
271
|
+
const noop = () => () => {};
|
|
272
|
+
return (
|
|
273
|
+
<ClaudeContext.Provider value={{
|
|
274
|
+
send: () => {}, abort: () => {}, clear: () => {},
|
|
275
|
+
clearAndReload: () => {}, setMode: () => {},
|
|
276
|
+
isConnected: false, mode: 'default',
|
|
277
|
+
onMessage: noop, onComplete: noop, onError: noop,
|
|
278
|
+
onUserMessage: noop, onClear: noop,
|
|
279
|
+
}}>
|
|
280
|
+
<BikeRackWorkspace />
|
|
281
|
+
</ClaudeContext.Provider>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// BikeRack standalone panel routing (MSSCI-14821)
|
|
286
|
+
// URL-based detection only (Rule 10) — ?panel=X renders single panel full-screen
|
|
287
|
+
if (standalonePanelName) {
|
|
288
|
+
return <StandalonePanel />;
|
|
289
|
+
}
|
|
290
|
+
|
|
257
291
|
return (
|
|
258
292
|
<ErrorBoundary fallback={<RootErrorFallback />} panelName="App">
|
|
259
293
|
<ClaudeProvider>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BikeRackIndex - Index page listing all available panels
|
|
3
|
+
*
|
|
4
|
+
* Story MSSCI-14822: BikeRackIndex panel listing page
|
|
5
|
+
* Epic: 101 (BikeRack Mode)
|
|
6
|
+
*
|
|
7
|
+
* Lists all 13 panels with links to standalone mode via ?panel=X.
|
|
8
|
+
* Styled with Tailwind dark mode, consistent with Cyclist.
|
|
9
|
+
*
|
|
10
|
+
* Rules:
|
|
11
|
+
* - No dockview-react imports (Rule 7)
|
|
12
|
+
* - No BikeRack-specific props (Rule 2)
|
|
13
|
+
* - URL-based detection only (Rule 10)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import React from 'react';
|
|
17
|
+
|
|
18
|
+
const PANELS = [
|
|
19
|
+
{ id: 'sprint', label: 'Sprint', description: 'Story tracking and sprint progress' },
|
|
20
|
+
{ id: 'git', label: 'Git', description: 'Repository status and branches' },
|
|
21
|
+
{ id: 'diffs', label: 'Diffs', description: 'Code changes and diffs' },
|
|
22
|
+
{ id: 'todos', label: 'Todos', description: 'Acceptance criteria tracking' },
|
|
23
|
+
{ id: 'workflow', label: 'Workflow', description: 'Current workflow state' },
|
|
24
|
+
{ id: 'background', label: 'Background', description: 'Background tasks' },
|
|
25
|
+
{ id: 'audit', label: 'Audit', description: 'OTEL spans and logs' },
|
|
26
|
+
{ id: 'changed', label: 'Changed', description: 'Changed files' },
|
|
27
|
+
{ id: 'ac', label: 'AC', description: 'Acceptance criteria detail' },
|
|
28
|
+
{ id: 'tty', label: 'TTY', description: 'Terminal output' },
|
|
29
|
+
{ id: 'debug', label: 'Debug', description: 'Debug information' },
|
|
30
|
+
{ id: 'bikelane', label: 'BikeLane', description: 'Workflow visualization' },
|
|
31
|
+
{ id: 'settings', label: 'Settings', description: 'Theme, fonts, and display preferences' },
|
|
32
|
+
] as const;
|
|
33
|
+
|
|
34
|
+
export function BikeRackIndex(): React.ReactElement {
|
|
35
|
+
return (
|
|
36
|
+
<div className="bg-slate-900 min-h-screen text-gray-200 p-8">
|
|
37
|
+
<div className="max-w-4xl mx-auto">
|
|
38
|
+
<h1 className="text-3xl font-bold text-white mb-8">BikeRack</h1>
|
|
39
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
40
|
+
{PANELS.map((panel) => (
|
|
41
|
+
<a
|
|
42
|
+
key={panel.id}
|
|
43
|
+
href={`/?panel=${panel.id}`}
|
|
44
|
+
className="block border border-slate-700 rounded-lg p-4 hover:bg-slate-800 hover:text-cyan-400 transition-colors"
|
|
45
|
+
>
|
|
46
|
+
<div className="text-lg font-semibold text-white mb-1">{panel.label}</div>
|
|
47
|
+
<p className="text-sm text-gray-400">{panel.description}</p>
|
|
48
|
+
</a>
|
|
49
|
+
))}
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BikeRackWorkspace - Dockview-based panel layout for BikeRack mode
|
|
3
|
+
*
|
|
4
|
+
* Story MSSCI-14877: Migrate BikeRack from index page to Dockview layout
|
|
5
|
+
* Epic: 102 (BikeRack Follow-up)
|
|
6
|
+
*
|
|
7
|
+
* Replaces BikeRackIndex with a proper Dockview layout.
|
|
8
|
+
* No MessagePanel (sacred center) — BikeRack is a monitoring dashboard.
|
|
9
|
+
* Single Dockview group — users can freely rearrange panels.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import React, { useCallback, useRef } from 'react';
|
|
13
|
+
import {
|
|
14
|
+
DockviewReact,
|
|
15
|
+
DockviewReadyEvent,
|
|
16
|
+
DockviewApi,
|
|
17
|
+
IDockviewPanelProps,
|
|
18
|
+
} from 'dockview-react';
|
|
19
|
+
import 'dockview-react/dist/styles/dockview.css';
|
|
20
|
+
import { ErrorBoundary } from './ErrorBoundary';
|
|
21
|
+
import { panelRegistry } from './panel-registry';
|
|
22
|
+
import PersonaHeader from './PersonaHeader.js';
|
|
23
|
+
import '../styles/dockview-theme.css';
|
|
24
|
+
|
|
25
|
+
// =============================================================================
|
|
26
|
+
// BikeRack Panel Definitions
|
|
27
|
+
// =============================================================================
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Panels included in BikeRack Dockview mode.
|
|
31
|
+
* Unlike base Cyclist, BikeRack does NOT include MessagePanel.
|
|
32
|
+
*/
|
|
33
|
+
export const BIKERACK_PANELS: string[] = [
|
|
34
|
+
'sprint',
|
|
35
|
+
'git',
|
|
36
|
+
'diffs',
|
|
37
|
+
'todo',
|
|
38
|
+
'workflow',
|
|
39
|
+
'background',
|
|
40
|
+
'audit-log',
|
|
41
|
+
'changed',
|
|
42
|
+
'ac',
|
|
43
|
+
'debug',
|
|
44
|
+
'settings',
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
const PANEL_TITLES: Record<string, string> = {
|
|
48
|
+
sprint: 'Sprint',
|
|
49
|
+
git: 'Git',
|
|
50
|
+
diffs: 'Diffs',
|
|
51
|
+
todo: 'Todo',
|
|
52
|
+
workflow: 'Workflow',
|
|
53
|
+
background: 'Subagents',
|
|
54
|
+
'audit-log': 'Audit Log',
|
|
55
|
+
changed: 'Changed',
|
|
56
|
+
ac: 'AC',
|
|
57
|
+
debug: 'Debug',
|
|
58
|
+
settings: 'Settings',
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// =============================================================================
|
|
62
|
+
// Panel Adapter
|
|
63
|
+
// =============================================================================
|
|
64
|
+
|
|
65
|
+
interface PanelAdapterParams {
|
|
66
|
+
panelId: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function PanelAdapter({ params }: IDockviewPanelProps<PanelAdapterParams>): React.ReactElement | null {
|
|
70
|
+
const Component = panelRegistry.get(params.panelId);
|
|
71
|
+
|
|
72
|
+
if (!Component) {
|
|
73
|
+
return (
|
|
74
|
+
<div data-testid={`panel-${params.panelId}`} className="dockview-panel-content">
|
|
75
|
+
<div style={{ padding: '16px', color: 'var(--text-secondary, #94a3b8)' }}>
|
|
76
|
+
{PANEL_TITLES[params.panelId] || params.panelId}
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<div data-testid={`panel-${params.panelId}`} className="dockview-panel-content">
|
|
84
|
+
<ErrorBoundary panelName={params.panelId}>
|
|
85
|
+
<div className="error-boundary-wrapper">
|
|
86
|
+
<Component />
|
|
87
|
+
</div>
|
|
88
|
+
</ErrorBoundary>
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// =============================================================================
|
|
94
|
+
// BikeRackWorkspace Component
|
|
95
|
+
// =============================================================================
|
|
96
|
+
|
|
97
|
+
export function BikeRackWorkspace(): React.ReactElement {
|
|
98
|
+
const apiRef = useRef<DockviewApi | null>(null);
|
|
99
|
+
|
|
100
|
+
const onReady = useCallback((event: DockviewReadyEvent) => {
|
|
101
|
+
const api = event.api;
|
|
102
|
+
apiRef.current = api;
|
|
103
|
+
|
|
104
|
+
// Single group — all panels as tabs, user can rearrange freely
|
|
105
|
+
const first = api.addPanel({
|
|
106
|
+
id: BIKERACK_PANELS[0],
|
|
107
|
+
component: 'PanelAdapter',
|
|
108
|
+
params: { panelId: BIKERACK_PANELS[0] },
|
|
109
|
+
title: PANEL_TITLES[BIKERACK_PANELS[0]],
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
for (let i = 1; i < BIKERACK_PANELS.length; i++) {
|
|
113
|
+
api.addPanel({
|
|
114
|
+
id: BIKERACK_PANELS[i],
|
|
115
|
+
component: 'PanelAdapter',
|
|
116
|
+
params: { panelId: BIKERACK_PANELS[i] },
|
|
117
|
+
position: { referencePanel: first.id },
|
|
118
|
+
title: PANEL_TITLES[BIKERACK_PANELS[i]],
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}, []);
|
|
122
|
+
|
|
123
|
+
const components = { PanelAdapter };
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<div className="cyclist-app cyclist-dockview" style={{ height: '100vh', width: '100vw', display: 'flex', flexDirection: 'column' }}>
|
|
127
|
+
<div data-testid="bikerack-portrait-anchor" style={{ flexShrink: 0 }}>
|
|
128
|
+
<PersonaHeader />
|
|
129
|
+
</div>
|
|
130
|
+
<div className="flex-1" style={{ flexGrow: 1, minHeight: 0 }}>
|
|
131
|
+
<DockviewReact
|
|
132
|
+
className="dockview-container"
|
|
133
|
+
onReady={onReady}
|
|
134
|
+
components={components}
|
|
135
|
+
watermarkComponent={() => null}
|
|
136
|
+
/>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export default BikeRackWorkspace;
|