gitspace 0.2.0-rc.20 → 0.2.0-rc.21
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/package.json +11 -6
- package/.claude/settings.local.json +0 -10
- package/.gitspace/bundle.json +0 -50
- package/.gitspace/events.json +0 -11
- package/.gitspace/processes.json +0 -23
- package/.gitspace/scripts/select/01-status.sh +0 -39
- package/.gitspace/scripts/setup/01-install-deps.sh +0 -12
- package/.gitspace/scripts/setup/02-typecheck.sh +0 -16
- package/AGENTS.md +0 -469
- package/CLAUDE.md +0 -1
- package/bun.lock +0 -794
- package/docs/CONNECTION.md +0 -623
- package/docs/GATEWAY-WORKER.md +0 -319
- package/docs/GETTING-STARTED.md +0 -448
- package/docs/GITSPACE-PLATFORM.md +0 -1819
- package/docs/INFRASTRUCTURE.md +0 -1347
- package/docs/PROTOCOL.md +0 -619
- package/docs/QUICKSTART.md +0 -183
- package/docs/RELAY.md +0 -327
- package/docs/REMOTE-DESIGN.md +0 -554
- package/docs/ROADMAP.md +0 -564
- package/docs/SITE_DOCS_FIGMA_MAKE.md +0 -1176
- package/docs/STACK-DESIGN.md +0 -588
- package/docs/UNIFIED_ARCHITECTURE.md +0 -138
- package/experiments/pty-benchmark.ts +0 -148
- package/experiments/pty-latency.ts +0 -100
- package/experiments/router/client.ts +0 -199
- package/experiments/router/protocol.ts +0 -74
- package/experiments/router/router.ts +0 -217
- package/experiments/router/session.ts +0 -180
- package/experiments/router/test.ts +0 -133
- package/experiments/socket-bandwidth.ts +0 -77
- package/homebrew/gitspace.rb +0 -45
- package/landing-page/ATTRIBUTIONS.md +0 -3
- package/landing-page/README.md +0 -11
- package/landing-page/bun.lock +0 -801
- package/landing-page/guidelines/Guidelines.md +0 -61
- package/landing-page/index.html +0 -37
- package/landing-page/package.json +0 -90
- package/landing-page/postcss.config.mjs +0 -15
- package/landing-page/public/_redirects +0 -1
- package/landing-page/public/favicon.png +0 -0
- package/landing-page/src/app/App.tsx +0 -53
- package/landing-page/src/app/components/figma/ImageWithFallback.tsx +0 -27
- package/landing-page/src/app/components/ui/accordion.tsx +0 -66
- package/landing-page/src/app/components/ui/alert-dialog.tsx +0 -157
- package/landing-page/src/app/components/ui/alert.tsx +0 -66
- package/landing-page/src/app/components/ui/aspect-ratio.tsx +0 -11
- package/landing-page/src/app/components/ui/avatar.tsx +0 -53
- package/landing-page/src/app/components/ui/badge.tsx +0 -46
- package/landing-page/src/app/components/ui/breadcrumb.tsx +0 -109
- package/landing-page/src/app/components/ui/button.tsx +0 -57
- package/landing-page/src/app/components/ui/calendar.tsx +0 -75
- package/landing-page/src/app/components/ui/card.tsx +0 -92
- package/landing-page/src/app/components/ui/carousel.tsx +0 -241
- package/landing-page/src/app/components/ui/chart.tsx +0 -353
- package/landing-page/src/app/components/ui/checkbox.tsx +0 -32
- package/landing-page/src/app/components/ui/collapsible.tsx +0 -33
- package/landing-page/src/app/components/ui/command.tsx +0 -177
- package/landing-page/src/app/components/ui/context-menu.tsx +0 -252
- package/landing-page/src/app/components/ui/dialog.tsx +0 -135
- package/landing-page/src/app/components/ui/drawer.tsx +0 -132
- package/landing-page/src/app/components/ui/dropdown-menu.tsx +0 -257
- package/landing-page/src/app/components/ui/form.tsx +0 -168
- package/landing-page/src/app/components/ui/hover-card.tsx +0 -44
- package/landing-page/src/app/components/ui/input-otp.tsx +0 -77
- package/landing-page/src/app/components/ui/input.tsx +0 -21
- package/landing-page/src/app/components/ui/label.tsx +0 -24
- package/landing-page/src/app/components/ui/menubar.tsx +0 -276
- package/landing-page/src/app/components/ui/navigation-menu.tsx +0 -168
- package/landing-page/src/app/components/ui/pagination.tsx +0 -127
- package/landing-page/src/app/components/ui/popover.tsx +0 -48
- package/landing-page/src/app/components/ui/progress.tsx +0 -31
- package/landing-page/src/app/components/ui/radio-group.tsx +0 -45
- package/landing-page/src/app/components/ui/resizable.tsx +0 -56
- package/landing-page/src/app/components/ui/scroll-area.tsx +0 -58
- package/landing-page/src/app/components/ui/select.tsx +0 -189
- package/landing-page/src/app/components/ui/separator.tsx +0 -28
- package/landing-page/src/app/components/ui/sheet.tsx +0 -139
- package/landing-page/src/app/components/ui/sidebar.tsx +0 -726
- package/landing-page/src/app/components/ui/skeleton.tsx +0 -13
- package/landing-page/src/app/components/ui/slider.tsx +0 -63
- package/landing-page/src/app/components/ui/sonner.tsx +0 -25
- package/landing-page/src/app/components/ui/switch.tsx +0 -31
- package/landing-page/src/app/components/ui/table.tsx +0 -116
- package/landing-page/src/app/components/ui/tabs.tsx +0 -66
- package/landing-page/src/app/components/ui/textarea.tsx +0 -18
- package/landing-page/src/app/components/ui/toggle-group.tsx +0 -73
- package/landing-page/src/app/components/ui/toggle.tsx +0 -47
- package/landing-page/src/app/components/ui/tooltip.tsx +0 -61
- package/landing-page/src/app/components/ui/use-mobile.ts +0 -21
- package/landing-page/src/app/components/ui/utils.ts +0 -6
- package/landing-page/src/components/docs/DocsContent.tsx +0 -801
- package/landing-page/src/components/docs/DocsSidebar.tsx +0 -90
- package/landing-page/src/components/landing/CTA.tsx +0 -59
- package/landing-page/src/components/landing/Comparison.tsx +0 -84
- package/landing-page/src/components/landing/FaultyTerminal.tsx +0 -424
- package/landing-page/src/components/landing/Features.tsx +0 -201
- package/landing-page/src/components/landing/Hero.tsx +0 -142
- package/landing-page/src/components/landing/Pricing.tsx +0 -140
- package/landing-page/src/components/landing/Roadmap.tsx +0 -86
- package/landing-page/src/components/landing/Security.tsx +0 -81
- package/landing-page/src/components/landing/TerminalWindow.tsx +0 -27
- package/landing-page/src/components/landing/UseCases.tsx +0 -55
- package/landing-page/src/components/landing/Workflow.tsx +0 -101
- package/landing-page/src/components/layout/DashboardNavbar.tsx +0 -37
- package/landing-page/src/components/layout/Footer.tsx +0 -55
- package/landing-page/src/components/layout/LandingNavbar.tsx +0 -82
- package/landing-page/src/components/ui/badge.tsx +0 -39
- package/landing-page/src/components/ui/breadcrumb.tsx +0 -115
- package/landing-page/src/components/ui/button.tsx +0 -57
- package/landing-page/src/components/ui/card.tsx +0 -79
- package/landing-page/src/components/ui/mock-terminal.tsx +0 -68
- package/landing-page/src/components/ui/separator.tsx +0 -28
- package/landing-page/src/lib/utils.ts +0 -6
- package/landing-page/src/main.tsx +0 -10
- package/landing-page/src/pages/Dashboard.tsx +0 -133
- package/landing-page/src/pages/DocsPage.tsx +0 -79
- package/landing-page/src/pages/LandingPage.tsx +0 -31
- package/landing-page/src/pages/TerminalView.tsx +0 -106
- package/landing-page/src/styles/fonts.css +0 -0
- package/landing-page/src/styles/index.css +0 -3
- package/landing-page/src/styles/tailwind.css +0 -4
- package/landing-page/src/styles/theme.css +0 -181
- package/landing-page/vite.config.ts +0 -19
- package/scripts/GHOSTTY_TAB_BUG.md +0 -106
- package/scripts/build.ts +0 -298
- package/scripts/migrate-secrets.ts +0 -77
- package/scripts/release.ts +0 -140
- package/scripts/sample-events.ts +0 -263
- package/scripts/test-tabs-minimal.ts +0 -68
- package/scripts/test-tabs-workaround.ts +0 -95
- package/scripts/test-tabs.ts +0 -171
- package/src/__tests__/test-utils.ts +0 -298
- package/src/app/input/__tests__/sessionCommands.test.ts +0 -40
- package/src/app/input/sessionCommands.ts +0 -94
- package/src/app/session/__tests__/useAttachController.test.ts +0 -229
- package/src/app/session/createSessionBackend.bun.ts +0 -76
- package/src/app/session/createSessionBackend.web.ts +0 -104
- package/src/app/session/types.ts +0 -16
- package/src/app/session/useAttachController.ts +0 -220
- package/src/app/session/useProcessActions.ts +0 -201
- package/src/app/session/useSessionClient.ts +0 -35
- package/src/app/session/useWorkspaceDeleteFlow.ts +0 -170
- package/src/app.tui.tsx +0 -2929
- package/src/app.web.tsx +0 -1454
- package/src/commands/__tests__/connect-key.test.ts +0 -10
- package/src/commands/__tests__/events.test.ts +0 -201
- package/src/commands/__tests__/notifications.test.ts +0 -349
- package/src/commands/__tests__/process.test.ts +0 -251
- package/src/commands/__tests__/serve-messages.test.ts +0 -190
- package/src/commands/__tests__/serve-process-hosting.test.ts +0 -63
- package/src/commands/access.ts +0 -298
- package/src/commands/add.ts +0 -455
- package/src/commands/auth.ts +0 -369
- package/src/commands/bundle.ts +0 -232
- package/src/commands/config.ts +0 -242
- package/src/commands/connect-key.ts +0 -1
- package/src/commands/connect.ts +0 -576
- package/src/commands/directory.ts +0 -16
- package/src/commands/events.ts +0 -157
- package/src/commands/host.ts +0 -566
- package/src/commands/identity.ts +0 -184
- package/src/commands/linear.ts +0 -717
- package/src/commands/list.ts +0 -181
- package/src/commands/migrate.ts +0 -52
- package/src/commands/notifications.ts +0 -351
- package/src/commands/process.ts +0 -104
- package/src/commands/relay.ts +0 -315
- package/src/commands/remove.ts +0 -279
- package/src/commands/review.ts +0 -787
- package/src/commands/serve.ts +0 -1946
- package/src/commands/share.ts +0 -451
- package/src/commands/status.ts +0 -125
- package/src/commands/switch.ts +0 -361
- package/src/commands/tmux.ts +0 -317
- package/src/components/DPad.web.tsx +0 -343
- package/src/components/DiffViewer.web.tsx +0 -1192
- package/src/components/Events.tsx +0 -137
- package/src/components/Events.tui.tsx +0 -129
- package/src/components/Events.web.tsx +0 -386
- package/src/components/FloatingControls.web.tsx +0 -112
- package/src/components/FloatingJogWheel.web.tsx +0 -240
- package/src/components/Flow.tsx +0 -458
- package/src/components/Flow.tui.tsx +0 -343
- package/src/components/Flow.web.tsx +0 -442
- package/src/components/Inbox.tsx +0 -448
- package/src/components/Inbox.tui.tsx +0 -262
- package/src/components/Inbox.web.tsx +0 -329
- package/src/components/MachineList.tsx +0 -187
- package/src/components/MachineList.tui.tsx +0 -161
- package/src/components/MachineList.web.tsx +0 -210
- package/src/components/NumPad.web.tsx +0 -270
- package/src/components/ProjectList.tsx +0 -175
- package/src/components/ProjectList.tui.tsx +0 -109
- package/src/components/ProjectList.web.tsx +0 -143
- package/src/components/ProjectOnboardingStep.ts +0 -23
- package/src/components/ProjectOnboardingStep.tui.tsx +0 -88
- package/src/components/ProjectOnboardingStep.web.tsx +0 -59
- package/src/components/RemoteMachineScreen.tui.tsx +0 -690
- package/src/components/ScriptTerminal.tui.tsx +0 -160
- package/src/components/ScriptTerminal.web.tsx +0 -89
- package/src/components/SessionTerminal.tui.tsx +0 -406
- package/src/components/SessionTerminal.web.tsx +0 -467
- package/src/components/SpacesBrowser.tsx +0 -540
- package/src/components/SpacesBrowser.tui.tsx +0 -258
- package/src/components/SpacesBrowser.web.tsx +0 -332
- package/src/components/TerminalControls.web.tsx +0 -464
- package/src/components/ThreadPanel.web.tsx +0 -798
- package/src/components/__tests__/SpacesBrowser.test.ts +0 -541
- package/src/components/__tests__/SpacesBrowser.tui.test.tsx +0 -249
- package/src/components/__tests__/script-terminal-buffer.tui.test.ts +0 -72
- package/src/components/index.ts +0 -105
- package/src/components/review-decision-colors.ts +0 -11
- package/src/components/script-terminal-buffer.tui.ts +0 -37
- package/src/components/session-terminal-page-navigation.ts +0 -48
- package/src/components/terminal-bracketed-paste.tui.test.ts +0 -43
- package/src/components/terminal-bracketed-paste.tui.ts +0 -46
- package/src/core/__tests__/access.test.ts +0 -240
- package/src/core/__tests__/bundle-refresh.test.ts +0 -567
- package/src/core/__tests__/bundle.test.ts +0 -209
- package/src/core/__tests__/github-review.test.ts +0 -781
- package/src/core/__tests__/project-lifecycle.test.ts +0 -137
- package/src/core/__tests__/workspace-lifecycle.test.ts +0 -159
- package/src/core/__tests__/workspace.test.ts +0 -149
- package/src/core/access.ts +0 -277
- package/src/core/bundle-refresh.ts +0 -1064
- package/src/core/bundle.ts +0 -326
- package/src/core/config.ts +0 -405
- package/src/core/git.ts +0 -768
- package/src/core/github-review.ts +0 -761
- package/src/core/github.ts +0 -151
- package/src/core/identity.ts +0 -631
- package/src/core/linear.ts +0 -403
- package/src/core/preferences-service.ts +0 -17
- package/src/core/project-catalog.ts +0 -52
- package/src/core/project-lifecycle.ts +0 -163
- package/src/core/review-executor.ts +0 -316
- package/src/core/review.ts +0 -407
- package/src/core/secret-runtime.ts +0 -167
- package/src/core/shell.ts +0 -117
- package/src/core/trusted-relays.ts +0 -315
- package/src/core/workspace-lifecycle.ts +0 -216
- package/src/core/workspace.ts +0 -363
- package/src/hooks/__tests__/useLocalSession.tui.test.ts +0 -557
- package/src/hooks/index.ts +0 -8
- package/src/hooks/index.tui.ts +0 -32
- package/src/hooks/useDaemonStatus.tui.ts +0 -174
- package/src/hooks/useLocalSession.tui.ts +0 -395
- package/src/hooks/useRelayConnection.web.ts +0 -54
- package/src/hooks/useRemoteMachines.tui.ts +0 -166
- package/src/hooks/useRemoteTerminal.tui.ts +0 -22
- package/src/hooks/useReview.web.ts +0 -248
- package/src/hooks/useTerminal.web.ts +0 -36
- package/src/hooks/useUserActivity.ts +0 -61
- package/src/hooks/useVisualViewport.web.ts +0 -104
- package/src/index.ts +0 -1376
- package/src/lib/events/__tests__/collector-filter.test.ts +0 -105
- package/src/lib/events/__tests__/store-query.test.ts +0 -103
- package/src/lib/events/collector.ts +0 -494
- package/src/lib/events/filters.ts +0 -26
- package/src/lib/events/index.ts +0 -11
- package/src/lib/events/indexer.ts +0 -14
- package/src/lib/events/paths.ts +0 -69
- package/src/lib/events/reader.ts +0 -212
- package/src/lib/events/store.ts +0 -141
- package/src/lib/invite.web.ts +0 -58
- package/src/lib/preferences-service.web.ts +0 -41
- package/src/lib/processes/__tests__/config.test.ts +0 -83
- package/src/lib/processes/__tests__/names.test.ts +0 -125
- package/src/lib/processes/__tests__/schema.test.ts +0 -208
- package/src/lib/processes/__tests__/watchdog.test.ts +0 -210
- package/src/lib/processes/autostart.ts +0 -16
- package/src/lib/processes/config.ts +0 -187
- package/src/lib/processes/control.ts +0 -53
- package/src/lib/processes/editor.ts +0 -32
- package/src/lib/processes/events-config.ts +0 -37
- package/src/lib/processes/index.ts +0 -14
- package/src/lib/processes/instances.ts +0 -20
- package/src/lib/processes/manager.ts +0 -131
- package/src/lib/processes/names.ts +0 -71
- package/src/lib/processes/registry.ts +0 -26
- package/src/lib/processes/runner.ts +0 -211
- package/src/lib/processes/scheduler.ts +0 -17
- package/src/lib/processes/schema.ts +0 -74
- package/src/lib/processes/session-list.ts +0 -15
- package/src/lib/processes/state.ts +0 -82
- package/src/lib/processes/watchdog.test.ts +0 -79
- package/src/lib/processes/watchdog.ts +0 -106
- package/src/lib/remote-session/__tests__/protocol.test.ts +0 -291
- package/src/lib/remote-session/index.ts +0 -7
- package/src/lib/remote-session/protocol.ts +0 -443
- package/src/lib/remote-session/session-handler.ts +0 -1298
- package/src/lib/remote-session/workspace-scanner.ts +0 -161
- package/src/lib/sonner.web.ts +0 -1
- package/src/lib/storage/identity-store.web.ts +0 -94
- package/src/lib/tmux-lite/README.md +0 -81
- package/src/lib/tmux-lite/cli.ts +0 -855
- package/src/lib/tmux-lite/crypto/__tests__/helpers/handshake-runner.ts +0 -349
- package/src/lib/tmux-lite/crypto/__tests__/helpers/mock-relay.ts +0 -291
- package/src/lib/tmux-lite/crypto/__tests__/helpers/test-identities.ts +0 -142
- package/src/lib/tmux-lite/crypto/__tests__/integration/authorization.integration.test.ts +0 -339
- package/src/lib/tmux-lite/crypto/__tests__/integration/e2e-communication.integration.test.ts +0 -477
- package/src/lib/tmux-lite/crypto/__tests__/integration/error-handling.integration.test.ts +0 -499
- package/src/lib/tmux-lite/crypto/__tests__/integration/handshake.integration.test.ts +0 -371
- package/src/lib/tmux-lite/crypto/__tests__/integration/security.integration.test.ts +0 -573
- package/src/lib/tmux-lite/crypto/access-control.test.ts +0 -512
- package/src/lib/tmux-lite/crypto/access-control.ts +0 -320
- package/src/lib/tmux-lite/crypto/frames.test.ts +0 -262
- package/src/lib/tmux-lite/crypto/frames.ts +0 -141
- package/src/lib/tmux-lite/crypto/handshake.ts +0 -894
- package/src/lib/tmux-lite/crypto/identity.test.ts +0 -220
- package/src/lib/tmux-lite/crypto/identity.ts +0 -286
- package/src/lib/tmux-lite/crypto/index.ts +0 -51
- package/src/lib/tmux-lite/crypto/invites.test.ts +0 -381
- package/src/lib/tmux-lite/crypto/invites.ts +0 -215
- package/src/lib/tmux-lite/crypto/keyexchange.ts +0 -435
- package/src/lib/tmux-lite/crypto/keys.test.ts +0 -58
- package/src/lib/tmux-lite/crypto/keys.ts +0 -47
- package/src/lib/tmux-lite/crypto/secretbox.test.ts +0 -169
- package/src/lib/tmux-lite/crypto/secretbox.ts +0 -124
- package/src/lib/tmux-lite/handshake-handler.ts +0 -451
- package/src/lib/tmux-lite/process-run.integration.test.ts +0 -266
- package/src/lib/tmux-lite/protocol.test.ts +0 -307
- package/src/lib/tmux-lite/protocol.ts +0 -291
- package/src/lib/tmux-lite/relay-client.ts +0 -506
- package/src/lib/tmux-lite/server-lifecycle.test.ts +0 -212
- package/src/lib/tmux-lite/server.ts +0 -1412
- package/src/lib/tmux-lite/shell-integration.sh +0 -37
- package/src/lib/tmux-lite/terminal-queries.test.ts +0 -54
- package/src/lib/tmux-lite/terminal-queries.ts +0 -49
- package/src/notifications/__tests__/useNotifications.test.ts +0 -739
- package/src/notifications/index.ts +0 -32
- package/src/notifications/policy.test.ts +0 -424
- package/src/notifications/policy.ts +0 -139
- package/src/notifications/types.ts +0 -82
- package/src/notifications/useNotifications.ts +0 -350
- package/src/pages/ReviewPage.web.tsx +0 -511
- package/src/preferences/index.ts +0 -1
- package/src/preferences/types.ts +0 -9
- package/src/relay/__tests__/e2e-flow.test.ts +0 -1284
- package/src/relay/__tests__/helpers/auth.ts +0 -354
- package/src/relay/__tests__/helpers/ports.ts +0 -51
- package/src/relay/__tests__/protocol-validation.test.ts +0 -265
- package/src/relay/authorization.ts +0 -303
- package/src/relay/embedded-assets.generated.d.ts +0 -15
- package/src/relay/identity.ts +0 -352
- package/src/relay/index.ts +0 -57
- package/src/relay/pipes.test.ts +0 -427
- package/src/relay/pipes.ts +0 -195
- package/src/relay/protocol.ts +0 -804
- package/src/relay/registries.test.ts +0 -437
- package/src/relay/registries.ts +0 -593
- package/src/relay/server.test.ts +0 -1323
- package/src/relay/server.ts +0 -1128
- package/src/relay/signing.ts +0 -238
- package/src/relay/types.ts +0 -69
- package/src/relay-client/__tests__/machine-directory-client.test.ts +0 -152
- package/src/relay-client/__tests__/useMachineDirectory.test.ts +0 -172
- package/src/relay-client/adapters/browser.ts +0 -27
- package/src/relay-client/adapters/node.ts +0 -29
- package/src/relay-client/index.ts +0 -33
- package/src/relay-client/machine-directory-client.ts +0 -244
- package/src/relay-client/useMachineDirectory.ts +0 -175
- package/src/serve/client-session-manager.ts +0 -635
- package/src/serve/daemon.ts +0 -497
- package/src/serve/pty-session.ts +0 -236
- package/src/serve/types.ts +0 -174
- package/src/session/__tests__/backend-manager.test.ts +0 -101
- package/src/session/__tests__/local-session-backend.test.ts +0 -1129
- package/src/session/__tests__/reducer.test.ts +0 -80
- package/src/session/__tests__/remote-session-backend.test.ts +0 -995
- package/src/session/__tests__/session-name.test.ts +0 -35
- package/src/session/__tests__/useBundleRefreshAttachFlow.test.ts +0 -431
- package/src/session/__tests__/useRemoteSessionClient.test.ts +0 -424
- package/src/session/__tests__/workspace-shell-hooks.integration.test.ts +0 -268
- package/src/session/__tests__/workspace-shell-hooks.test.ts +0 -24
- package/src/session/adapters/browser-remote.ts +0 -101
- package/src/session/adapters/node-remote.ts +0 -135
- package/src/session/backend-key.ts +0 -5
- package/src/session/backend-manager.ts +0 -80
- package/src/session/backend.ts +0 -93
- package/src/session/backends/local-session-backend.ts +0 -1119
- package/src/session/backends/remote-session-backend.ts +0 -1378
- package/src/session/crypto/__tests__/web-terminal.test.ts +0 -1158
- package/src/session/crypto/frames.web.ts +0 -205
- package/src/session/crypto/handshake.web.ts +0 -396
- package/src/session/crypto/identity.web.ts +0 -133
- package/src/session/crypto/keyexchange.web.ts +0 -246
- package/src/session/crypto/relay-signing.web.ts +0 -53
- package/src/session/events.ts +0 -38
- package/src/session/index.ts +0 -116
- package/src/session/reducer.ts +0 -274
- package/src/session/selectors.ts +0 -28
- package/src/session/session-name.ts +0 -50
- package/src/session/types.ts +0 -101
- package/src/session/useBundleRefreshAttachFlow.ts +0 -608
- package/src/session/useRemoteSessionClient.ts +0 -424
- package/src/session/useSessionEngine.ts +0 -432
- package/src/session/workspace-shell-hooks.ts +0 -35
- package/src/tui/__tests__/input-text.test.ts +0 -24
- package/src/tui/__tests__/local-terminal-sync.test.ts +0 -82
- package/src/tui/__tests__/session-terminal-page-navigation.test.ts +0 -94
- package/src/tui/app.tsx +0 -2
- package/src/tui/index.ts +0 -18
- package/src/tui/input-text.ts +0 -38
- package/src/tui/local-terminal-sync.ts +0 -41
- package/src/types/bundle-refresh.ts +0 -42
- package/src/types/bundle.ts +0 -130
- package/src/types/config.ts +0 -287
- package/src/types/errors.ts +0 -292
- package/src/types/events.ts +0 -91
- package/src/types/identity.ts +0 -284
- package/src/types/processes.ts +0 -45
- package/src/types/review.ts +0 -349
- package/src/types/script-phase.ts +0 -3
- package/src/types/workspace-fuzzy.ts +0 -49
- package/src/types/workspace.ts +0 -151
- package/src/utils/__tests__/onboarding.test.ts +0 -358
- package/src/utils/__tests__/run-scripts.test.ts +0 -535
- package/src/utils/__tests__/run-workspace-scripts.test.ts +0 -406
- package/src/utils/__tests__/workspace-setup.integration.test.ts +0 -633
- package/src/utils/__tests__/workspace-state.test.ts +0 -78
- package/src/utils/bun-socket-writer.ts +0 -80
- package/src/utils/clipboard.ts +0 -53
- package/src/utils/deps.test.ts +0 -31
- package/src/utils/deps.ts +0 -145
- package/src/utils/device.web.ts +0 -163
- package/src/utils/fuzzy-match.ts +0 -125
- package/src/utils/hostnames.ts +0 -43
- package/src/utils/hunk-header.ts +0 -17
- package/src/utils/id.ts +0 -9
- package/src/utils/logger.ts +0 -127
- package/src/utils/markdown.ts +0 -254
- package/src/utils/normalize-env-key.ts +0 -13
- package/src/utils/onboarding.ts +0 -279
- package/src/utils/prompts.ts +0 -176
- package/src/utils/run-commands.ts +0 -112
- package/src/utils/run-scripts.ts +0 -337
- package/src/utils/run-workspace-scripts.ts +0 -355
- package/src/utils/sanitize.test.ts +0 -149
- package/src/utils/sanitize.ts +0 -162
- package/src/utils/secrets.ts +0 -836
- package/src/utils/shell-escape.ts +0 -40
- package/src/utils/utf8.ts +0 -79
- package/src/utils/workspace-id.ts +0 -55
- package/src/utils/workspace-state.ts +0 -427
- package/src/version.generated.d.ts +0 -2
- package/todo-security.md +0 -92
- package/tsconfig.json +0 -29
- package/web/README.md +0 -73
- package/web/bun.lock +0 -675
- package/web/eslint.config.js +0 -23
- package/web/index.css +0 -249
- package/web/index.html +0 -16
- package/web/main.tsx +0 -10
- package/web/package.json +0 -39
- package/web/public/vite.svg +0 -1
- package/web/tsconfig.app.json +0 -35
- package/web/tsconfig.json +0 -7
- package/web/tsconfig.node.json +0 -26
- package/web/vite.config.ts +0 -39
- package/worker/bun.lock +0 -237
- package/worker/package.json +0 -22
- package/worker/schema.sql +0 -96
- package/worker/src/handlers/auth.ts +0 -451
- package/worker/src/handlers/subdomains.ts +0 -376
- package/worker/src/handlers/user.ts +0 -98
- package/worker/src/index.ts +0 -70
- package/worker/src/middleware/auth.ts +0 -152
- package/worker/src/services/cloudflare.ts +0 -609
- package/worker/src/types.ts +0 -96
- package/worker/tsconfig.json +0 -15
- package/worker/wrangler.toml +0 -26
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Utilities for Type-Safe Mocking
|
|
3
|
-
*
|
|
4
|
-
* Provides type-safe mock factories and type guards for testing.
|
|
5
|
-
* Avoids the need for `as any` casts in test files.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type {
|
|
9
|
-
ProcessResult,
|
|
10
|
-
HandshakeMessage,
|
|
11
|
-
EstablishedSession,
|
|
12
|
-
} from "../lib/tmux-lite/handshake-handler.js";
|
|
13
|
-
|
|
14
|
-
// ============================================================================
|
|
15
|
-
// WebSocket Mocks
|
|
16
|
-
// ============================================================================
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* WebSocket data interface used by the relay server
|
|
20
|
-
*/
|
|
21
|
-
export interface WebSocketData {
|
|
22
|
-
machineId: string;
|
|
23
|
-
role: "machine" | "client";
|
|
24
|
-
connectionId: string;
|
|
25
|
-
accountId: string;
|
|
26
|
-
clientIdentityId?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Mock WebSocket configuration
|
|
31
|
-
*/
|
|
32
|
-
export interface MockWebSocketConfig {
|
|
33
|
-
data?: Partial<WebSocketData>;
|
|
34
|
-
sendMock?: (data: string) => void;
|
|
35
|
-
closeMock?: (code?: number, reason?: string) => void;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Type-safe mock WebSocket interface
|
|
40
|
-
*/
|
|
41
|
-
export interface MockWebSocket {
|
|
42
|
-
data: WebSocketData;
|
|
43
|
-
send: MockFn<[string], void>;
|
|
44
|
-
close: MockFn<[number?, string?], void>;
|
|
45
|
-
readyState: number;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Mock function type with call tracking
|
|
50
|
-
*/
|
|
51
|
-
interface MockFn<Args extends unknown[] = unknown[], Return = void> {
|
|
52
|
-
(...args: Args): Return;
|
|
53
|
-
calls: Args[];
|
|
54
|
-
callCount: number;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Create a mock function that tracks calls
|
|
59
|
-
*/
|
|
60
|
-
function createMockFn<Args extends unknown[] = unknown[], Return = void>(
|
|
61
|
-
impl?: (...args: Args) => Return
|
|
62
|
-
): MockFn<Args, Return> {
|
|
63
|
-
const calls: Args[] = [];
|
|
64
|
-
const fn = ((...args: Args) => {
|
|
65
|
-
calls.push(args);
|
|
66
|
-
return impl?.(...args) as Return;
|
|
67
|
-
}) as MockFn<Args, Return>;
|
|
68
|
-
fn.calls = calls;
|
|
69
|
-
Object.defineProperty(fn, "callCount", {
|
|
70
|
-
get() {
|
|
71
|
-
return calls.length;
|
|
72
|
-
},
|
|
73
|
-
});
|
|
74
|
-
return fn;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Create a type-safe mock WebSocket for testing
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* const mockWs = createMockWebSocket({
|
|
82
|
-
* data: { machineId: "test-machine", role: "machine" },
|
|
83
|
-
* });
|
|
84
|
-
* expect(mockWs.send.callCount).toBe(0);
|
|
85
|
-
*/
|
|
86
|
-
export function createMockWebSocket(config: MockWebSocketConfig = {}): MockWebSocket {
|
|
87
|
-
return {
|
|
88
|
-
data: {
|
|
89
|
-
machineId: config.data?.machineId ?? "test-machine",
|
|
90
|
-
role: config.data?.role ?? "machine",
|
|
91
|
-
connectionId: config.data?.connectionId ?? "conn-1",
|
|
92
|
-
accountId: config.data?.accountId ?? "test-account",
|
|
93
|
-
clientIdentityId: config.data?.clientIdentityId,
|
|
94
|
-
},
|
|
95
|
-
send: createMockFn<[string], void>(config.sendMock),
|
|
96
|
-
close: createMockFn<[number?, string?], void>(config.closeMock),
|
|
97
|
-
readyState: 1, // OPEN
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Cast a mock WebSocket to any type for use with functions that expect
|
|
103
|
-
* specific WebSocket types (like ServerWebSocket<WebSocketData>).
|
|
104
|
-
*
|
|
105
|
-
* This is a deliberate type assertion for testing purposes - the mock
|
|
106
|
-
* implements the minimal interface needed for the tests.
|
|
107
|
-
*
|
|
108
|
-
* @example
|
|
109
|
-
* const mockWs = asMockWs(createMockWebSocket({ data: { machineId: "test" } }));
|
|
110
|
-
* registerMachine("id", "account", "key", "kxKey", mockWs);
|
|
111
|
-
*/
|
|
112
|
-
export function asMockWs<T>(mock: MockWebSocket): T {
|
|
113
|
-
return mock as unknown as T;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// ============================================================================
|
|
117
|
-
// Handler Result Type Guards
|
|
118
|
-
// ============================================================================
|
|
119
|
-
|
|
120
|
-
// Re-export types from handshake-handler for convenience
|
|
121
|
-
export type { ProcessResult, HandshakeMessage, EstablishedSession };
|
|
122
|
-
|
|
123
|
-
/** Reply result from handshake processing */
|
|
124
|
-
export type ReplyResult = Extract<ProcessResult, { type: "reply" }>;
|
|
125
|
-
|
|
126
|
-
/** Established result from handshake processing */
|
|
127
|
-
export type EstablishedResult = Extract<ProcessResult, { type: "established" }>;
|
|
128
|
-
|
|
129
|
-
/** Error result from handshake processing */
|
|
130
|
-
export type ErrorResult = Extract<ProcessResult, { type: "error" }>;
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Type guard for reply results
|
|
134
|
-
*/
|
|
135
|
-
export function isReplyResult(result: ProcessResult): result is ReplyResult {
|
|
136
|
-
return result.type === "reply";
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Type guard for established results
|
|
141
|
-
*/
|
|
142
|
-
export function isEstablishedResult(result: ProcessResult): result is EstablishedResult {
|
|
143
|
-
return result.type === "established";
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Type guard for error results
|
|
148
|
-
*/
|
|
149
|
-
export function isErrorResult(result: ProcessResult): result is ErrorResult {
|
|
150
|
-
return result.type === "error";
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Extract message data from a reply result with proper typing
|
|
155
|
-
*/
|
|
156
|
-
export function getReplyData<T>(result: ProcessResult): T {
|
|
157
|
-
if (!isReplyResult(result)) {
|
|
158
|
-
throw new Error(`Expected reply result, got: ${result.type}`);
|
|
159
|
-
}
|
|
160
|
-
return result.message.data as T;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Get error reason from an error result
|
|
165
|
-
*/
|
|
166
|
-
export function getErrorReason(result: ProcessResult): string {
|
|
167
|
-
if (!isErrorResult(result)) {
|
|
168
|
-
throw new Error(`Expected error result, got: ${result.type}`);
|
|
169
|
-
}
|
|
170
|
-
return result.reason;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// ============================================================================
|
|
174
|
-
// Object Utilities
|
|
175
|
-
// ============================================================================
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Create a copy of an object with specific properties omitted.
|
|
179
|
-
* Safer alternative to `delete (obj as any).prop`.
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* const authWithoutSignature = omit(clientAuth, 'identitySignature');
|
|
183
|
-
*/
|
|
184
|
-
export function omit<T extends object, K extends keyof T>(
|
|
185
|
-
obj: T,
|
|
186
|
-
...keys: K[]
|
|
187
|
-
): Omit<T, K> {
|
|
188
|
-
const result = { ...obj };
|
|
189
|
-
for (const key of keys) {
|
|
190
|
-
delete result[key];
|
|
191
|
-
}
|
|
192
|
-
return result;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Create a copy of an object with only specific properties included.
|
|
197
|
-
*
|
|
198
|
-
* @example
|
|
199
|
-
* const minimalAuth = pick(clientAuth, 'version', 'identityKey');
|
|
200
|
-
*/
|
|
201
|
-
export function pick<T extends object, K extends keyof T>(
|
|
202
|
-
obj: T,
|
|
203
|
-
...keys: K[]
|
|
204
|
-
): Pick<T, K> {
|
|
205
|
-
const result = {} as Pick<T, K>;
|
|
206
|
-
for (const key of keys) {
|
|
207
|
-
if (key in obj) {
|
|
208
|
-
result[key] = obj[key];
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return result;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// ============================================================================
|
|
215
|
-
// Private Property Access for Testing
|
|
216
|
-
// ============================================================================
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Interface for accessing RelayClient internal state in tests.
|
|
220
|
-
* This should only be used for test verification, not production code.
|
|
221
|
-
*/
|
|
222
|
-
export interface RelayClientTestAccess {
|
|
223
|
-
readKey: Buffer | null;
|
|
224
|
-
writeKey: Buffer | null;
|
|
225
|
-
handshakeState: unknown;
|
|
226
|
-
sessionKeys: unknown;
|
|
227
|
-
peerIdentityId: string | null;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Get test access to RelayClient private properties.
|
|
232
|
-
* This uses a type assertion to access private fields for testing verification.
|
|
233
|
-
*
|
|
234
|
-
* @example
|
|
235
|
-
* const testAccess = getRelayClientTestAccess(client);
|
|
236
|
-
* expect(testAccess.writeKey).toBeDefined();
|
|
237
|
-
*/
|
|
238
|
-
export function getRelayClientTestAccess(client: object): RelayClientTestAccess {
|
|
239
|
-
// This is a deliberate type assertion for test purposes
|
|
240
|
-
// RelayClient has private properties that we need to verify in tests
|
|
241
|
-
const internal = client as {
|
|
242
|
-
readKey: Buffer | null;
|
|
243
|
-
writeKey: Buffer | null;
|
|
244
|
-
handshakeState: unknown;
|
|
245
|
-
sessionKeys: unknown;
|
|
246
|
-
peerIdentityId: string | null;
|
|
247
|
-
};
|
|
248
|
-
return {
|
|
249
|
-
readKey: internal.readKey,
|
|
250
|
-
writeKey: internal.writeKey,
|
|
251
|
-
handshakeState: internal.handshakeState,
|
|
252
|
-
sessionKeys: internal.sessionKeys,
|
|
253
|
-
peerIdentityId: internal.peerIdentityId,
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// ============================================================================
|
|
258
|
-
// Assertion Helpers
|
|
259
|
-
// ============================================================================
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Assert that a value is defined (not null or undefined)
|
|
263
|
-
*/
|
|
264
|
-
export function assertDefined<T>(
|
|
265
|
-
value: T | null | undefined,
|
|
266
|
-
message = "Expected value to be defined"
|
|
267
|
-
): asserts value is T {
|
|
268
|
-
if (value === null || value === undefined) {
|
|
269
|
-
throw new Error(message);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Assert that a result is a reply type
|
|
275
|
-
*/
|
|
276
|
-
export function assertReply(result: ProcessResult): asserts result is ReplyResult {
|
|
277
|
-
if (!isReplyResult(result)) {
|
|
278
|
-
throw new Error(`Expected reply result, got: ${result.type}`);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Assert that a result is an established type
|
|
284
|
-
*/
|
|
285
|
-
export function assertEstablished(result: ProcessResult): asserts result is EstablishedResult {
|
|
286
|
-
if (!isEstablishedResult(result)) {
|
|
287
|
-
throw new Error(`Expected established result, got: ${result.type}`);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Assert that a result is an error type
|
|
293
|
-
*/
|
|
294
|
-
export function assertError(result: ProcessResult): asserts result is ErrorResult {
|
|
295
|
-
if (!isErrorResult(result)) {
|
|
296
|
-
throw new Error(`Expected error result, got: ${result.type}`);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'bun:test'
|
|
2
|
-
import {
|
|
3
|
-
resolveInboxCommand,
|
|
4
|
-
resolveMachineListCommand,
|
|
5
|
-
resolveSessionBrowserCommand,
|
|
6
|
-
} from '../sessionCommands.js'
|
|
7
|
-
|
|
8
|
-
describe('sessionCommands', () => {
|
|
9
|
-
it('resolves machine list commands for web and tui inputs', () => {
|
|
10
|
-
expect(resolveMachineListCommand({ key: 'ArrowUp' })).toBe('move-up')
|
|
11
|
-
expect(resolveMachineListCommand({ name: 'down' })).toBe('move-down')
|
|
12
|
-
expect(resolveMachineListCommand({ key: 'Enter' })).toBe('activate')
|
|
13
|
-
expect(resolveMachineListCommand({ raw: 'r' })).toBe('refresh')
|
|
14
|
-
expect(resolveMachineListCommand({ key: 'c' })).toBe('copy')
|
|
15
|
-
expect(resolveMachineListCommand({ key: '?' })).toBe('help')
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
it('resolves inbox commands for web and tui inputs', () => {
|
|
19
|
-
expect(resolveInboxCommand({ key: 'ArrowUp' })).toBe('move-up')
|
|
20
|
-
expect(resolveInboxCommand({ raw: 'j' })).toBe('move-down')
|
|
21
|
-
expect(resolveInboxCommand({ key: 'Enter' })).toBe('activate')
|
|
22
|
-
expect(resolveInboxCommand({ key: 'Escape' })).toBe('back')
|
|
23
|
-
expect(resolveInboxCommand({ key: 'x' })).toBe('delete')
|
|
24
|
-
expect(resolveInboxCommand({ key: 'c' })).toBe('clear')
|
|
25
|
-
expect(resolveInboxCommand({ key: 'a' })).toBe('attach')
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
it('resolves session browser commands for web and tui inputs', () => {
|
|
29
|
-
expect(resolveSessionBrowserCommand({ key: 'ArrowUp' })).toBe('move-up')
|
|
30
|
-
expect(resolveSessionBrowserCommand({ raw: 'j' })).toBe('move-down')
|
|
31
|
-
expect(resolveSessionBrowserCommand({ key: 'Enter' })).toBe('activate')
|
|
32
|
-
expect(resolveSessionBrowserCommand({ key: 'n' })).toBe('new')
|
|
33
|
-
expect(resolveSessionBrowserCommand({ key: 'r' })).toBe('refresh')
|
|
34
|
-
expect(resolveSessionBrowserCommand({ key: 'q' })).toBe('back')
|
|
35
|
-
expect(resolveSessionBrowserCommand({ key: '?' })).toBe('help')
|
|
36
|
-
expect(resolveSessionBrowserCommand({ key: 'x' })).toBe('kill')
|
|
37
|
-
expect(resolveSessionBrowserCommand({ key: 'd' })).toBe('delete')
|
|
38
|
-
expect(resolveSessionBrowserCommand({ key: 'i' })).toBe('open-inbox')
|
|
39
|
-
})
|
|
40
|
-
})
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
export interface SessionCommandKeyInput {
|
|
2
|
-
key?: string | null
|
|
3
|
-
name?: string | null
|
|
4
|
-
raw?: string | null
|
|
5
|
-
shift?: boolean
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export type SessionUiCommand =
|
|
9
|
-
| 'move-up'
|
|
10
|
-
| 'move-down'
|
|
11
|
-
| 'activate'
|
|
12
|
-
| 'back'
|
|
13
|
-
| 'new'
|
|
14
|
-
| 'refresh'
|
|
15
|
-
| 'help'
|
|
16
|
-
| 'delete'
|
|
17
|
-
| 'clear'
|
|
18
|
-
| 'attach'
|
|
19
|
-
| 'kill'
|
|
20
|
-
| 'open-inbox'
|
|
21
|
-
| 'copy'
|
|
22
|
-
|
|
23
|
-
function normalizeCommandKey(input: SessionCommandKeyInput): string | null {
|
|
24
|
-
const key = input.key?.toLowerCase()
|
|
25
|
-
if (key) {
|
|
26
|
-
if (key === 'arrowup') return 'up'
|
|
27
|
-
if (key === 'arrowdown') return 'down'
|
|
28
|
-
if (key === 'enter') return 'return'
|
|
29
|
-
if (key === 'escape') return 'escape'
|
|
30
|
-
return key
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const name = input.name?.toLowerCase()
|
|
34
|
-
if (name === 'up' || name === 'down' || name === 'return' || name === 'escape') {
|
|
35
|
-
return name
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const raw = input.raw
|
|
39
|
-
if (!raw) {
|
|
40
|
-
return null
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return raw.toLowerCase()
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function resolveMachineListCommand(input: SessionCommandKeyInput): SessionUiCommand | null {
|
|
47
|
-
const key = normalizeCommandKey(input)
|
|
48
|
-
if (!key) {
|
|
49
|
-
return null
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (key === 'up' || key === 'k') return 'move-up'
|
|
53
|
-
if (key === 'down' || key === 'j') return 'move-down'
|
|
54
|
-
if (key === 'return') return 'activate'
|
|
55
|
-
if (key === 'r') return 'refresh'
|
|
56
|
-
if (key === 'c') return 'copy'
|
|
57
|
-
if (key === '?') return 'help'
|
|
58
|
-
return null
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function resolveInboxCommand(input: SessionCommandKeyInput): SessionUiCommand | null {
|
|
62
|
-
const key = normalizeCommandKey(input)
|
|
63
|
-
if (!key) {
|
|
64
|
-
return null
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (key === 'up' || key === 'k') return 'move-up'
|
|
68
|
-
if (key === 'down' || key === 'j') return 'move-down'
|
|
69
|
-
if (key === 'return') return 'activate'
|
|
70
|
-
if (key === 'escape' || key === 'q') return 'back'
|
|
71
|
-
if (key === 'x') return 'delete'
|
|
72
|
-
if (key === 'c') return 'clear'
|
|
73
|
-
if (key === 'a') return 'attach'
|
|
74
|
-
return null
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function resolveSessionBrowserCommand(input: SessionCommandKeyInput): SessionUiCommand | null {
|
|
78
|
-
const key = normalizeCommandKey(input)
|
|
79
|
-
if (!key) {
|
|
80
|
-
return null
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (key === 'up' || key === 'k') return 'move-up'
|
|
84
|
-
if (key === 'down' || key === 'j') return 'move-down'
|
|
85
|
-
if (key === 'return') return 'activate'
|
|
86
|
-
if (key === 'n') return 'new'
|
|
87
|
-
if (key === 'r') return 'refresh'
|
|
88
|
-
if (key === 'escape' || key === 'q') return 'back'
|
|
89
|
-
if (key === '?') return 'help'
|
|
90
|
-
if (key === 'x') return 'kill'
|
|
91
|
-
if (key === 'd') return 'delete'
|
|
92
|
-
if (key === 'i') return 'open-inbox'
|
|
93
|
-
return null
|
|
94
|
-
}
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import { afterAll, beforeAll, describe, expect, it, mock } from 'bun:test'
|
|
2
|
-
import { renderHook } from '@testing-library/react'
|
|
3
|
-
import { Window } from 'happy-dom'
|
|
4
|
-
import { useAttachController } from '../useAttachController.js'
|
|
5
|
-
|
|
6
|
-
const domWindow = new Window()
|
|
7
|
-
const originalWindow = globalThis.window
|
|
8
|
-
const originalDocument = globalThis.document
|
|
9
|
-
|
|
10
|
-
beforeAll(() => {
|
|
11
|
-
// @ts-expect-error test DOM setup
|
|
12
|
-
globalThis.window = domWindow
|
|
13
|
-
// @ts-expect-error test DOM setup
|
|
14
|
-
globalThis.document = domWindow.document
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
afterAll(() => {
|
|
18
|
-
globalThis.window = originalWindow
|
|
19
|
-
globalThis.document = originalDocument
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
describe('useAttachController', () => {
|
|
23
|
-
it('prompts for session name and attaches workspace after submit', async () => {
|
|
24
|
-
const close = mock(() => {})
|
|
25
|
-
const showInputCalls: Array<{
|
|
26
|
-
onSubmit: (value: string) => Promise<void> | void
|
|
27
|
-
}> = []
|
|
28
|
-
|
|
29
|
-
const attachSessionWithBundleRefresh = mock(async () => true)
|
|
30
|
-
|
|
31
|
-
const { result } = renderHook(() =>
|
|
32
|
-
useAttachController({
|
|
33
|
-
flow: {
|
|
34
|
-
showInput: (opts) => {
|
|
35
|
-
showInputCalls.push({ onSubmit: opts.onSubmit })
|
|
36
|
-
},
|
|
37
|
-
showMessage: () => {},
|
|
38
|
-
close,
|
|
39
|
-
},
|
|
40
|
-
attachSessionWithBundleRefresh,
|
|
41
|
-
})
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
await result.current.attachFromSelection({ workspaceId: 'my-project:my-workspace' })
|
|
45
|
-
expect(showInputCalls.length).toBe(1)
|
|
46
|
-
|
|
47
|
-
await showInputCalls[0]?.onSubmit('custom-name')
|
|
48
|
-
|
|
49
|
-
expect(close).toHaveBeenCalledTimes(1)
|
|
50
|
-
expect(attachSessionWithBundleRefresh).toHaveBeenCalledTimes(1)
|
|
51
|
-
expect(attachSessionWithBundleRefresh).toHaveBeenCalledWith(
|
|
52
|
-
{
|
|
53
|
-
workspaceId: 'my-project:my-workspace',
|
|
54
|
-
sessionName: 'custom-name',
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
projectName: 'my-project',
|
|
58
|
-
}
|
|
59
|
-
)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('uses preflight gate for existing session attaches', async () => {
|
|
63
|
-
const attachSessionWithBundleRefresh = mock(async () => true)
|
|
64
|
-
const preflightSessionAttach = mock(async () => false)
|
|
65
|
-
|
|
66
|
-
const { result } = renderHook(() =>
|
|
67
|
-
useAttachController({
|
|
68
|
-
flow: {
|
|
69
|
-
showInput: () => {},
|
|
70
|
-
showMessage: () => {},
|
|
71
|
-
close: () => {},
|
|
72
|
-
},
|
|
73
|
-
attachSessionWithBundleRefresh,
|
|
74
|
-
preflightSessionAttach,
|
|
75
|
-
})
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
await result.current.attachFromSelection({ sessionId: 'session-1' })
|
|
79
|
-
|
|
80
|
-
expect(preflightSessionAttach).toHaveBeenCalledTimes(1)
|
|
81
|
-
expect(attachSessionWithBundleRefresh).toHaveBeenCalledTimes(0)
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('waits for async preflight approval before attaching existing session', async () => {
|
|
85
|
-
const attachSessionWithBundleRefresh = mock(async () => true)
|
|
86
|
-
const resolver: { current: ((value: boolean) => void) | null } = { current: null }
|
|
87
|
-
const preflightSessionAttach = mock(() =>
|
|
88
|
-
new Promise<boolean>((resolve) => {
|
|
89
|
-
resolver.current = resolve
|
|
90
|
-
})
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
const { result } = renderHook(() =>
|
|
94
|
-
useAttachController({
|
|
95
|
-
flow: {
|
|
96
|
-
showInput: () => {},
|
|
97
|
-
showMessage: () => {},
|
|
98
|
-
close: () => {},
|
|
99
|
-
},
|
|
100
|
-
attachSessionWithBundleRefresh,
|
|
101
|
-
preflightSessionAttach,
|
|
102
|
-
})
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
const attachPromise = result.current.attachFromSelection({ sessionId: 'session-2' })
|
|
106
|
-
await Promise.resolve()
|
|
107
|
-
expect(attachSessionWithBundleRefresh).toHaveBeenCalledTimes(0)
|
|
108
|
-
|
|
109
|
-
if (!resolver.current) {
|
|
110
|
-
throw new Error('Expected preflight resolver to be set')
|
|
111
|
-
}
|
|
112
|
-
resolver.current(true)
|
|
113
|
-
await attachPromise
|
|
114
|
-
|
|
115
|
-
expect(preflightSessionAttach).toHaveBeenCalledTimes(1)
|
|
116
|
-
expect(attachSessionWithBundleRefresh).toHaveBeenCalledTimes(1)
|
|
117
|
-
expect(attachSessionWithBundleRefresh).toHaveBeenCalledWith(
|
|
118
|
-
{
|
|
119
|
-
sessionId: 'session-2',
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
projectName: null,
|
|
123
|
-
}
|
|
124
|
-
)
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('passes through viewOnly on existing session attaches', async () => {
|
|
128
|
-
const attachSessionWithBundleRefresh = mock(async () => true)
|
|
129
|
-
|
|
130
|
-
const { result } = renderHook(() =>
|
|
131
|
-
useAttachController({
|
|
132
|
-
flow: {
|
|
133
|
-
showInput: () => {},
|
|
134
|
-
showMessage: () => {},
|
|
135
|
-
close: () => {},
|
|
136
|
-
},
|
|
137
|
-
attachSessionWithBundleRefresh,
|
|
138
|
-
})
|
|
139
|
-
)
|
|
140
|
-
|
|
141
|
-
await result.current.attachFromSelection({ sessionId: 'session-view', viewOnly: true })
|
|
142
|
-
|
|
143
|
-
expect(attachSessionWithBundleRefresh).toHaveBeenCalledWith(
|
|
144
|
-
{
|
|
145
|
-
sessionId: 'session-view',
|
|
146
|
-
viewOnly: true,
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
projectName: null,
|
|
150
|
-
}
|
|
151
|
-
)
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
it('runs lifecycle callbacks for cancelled and failed attach attempts', async () => {
|
|
155
|
-
const onAttachCancelled = mock(() => {})
|
|
156
|
-
const onAttachError = mock(() => {})
|
|
157
|
-
const attachSessionWithBundleRefresh = mock(async (params: { sessionId?: string }) => {
|
|
158
|
-
if (params.sessionId === 'cancelled') {
|
|
159
|
-
return false
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
throw new Error('boom')
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
const { result } = renderHook(() =>
|
|
166
|
-
useAttachController({
|
|
167
|
-
flow: {
|
|
168
|
-
showInput: () => {},
|
|
169
|
-
showMessage: () => {},
|
|
170
|
-
close: () => {},
|
|
171
|
-
},
|
|
172
|
-
attachSessionWithBundleRefresh,
|
|
173
|
-
onAttachCancelled,
|
|
174
|
-
onAttachError,
|
|
175
|
-
})
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
const cancelled = await result.current.attach({ sessionId: 'cancelled' })
|
|
179
|
-
const failed = await result.current.attach({ sessionId: 'failed' })
|
|
180
|
-
|
|
181
|
-
expect(cancelled).toBe(false)
|
|
182
|
-
expect(failed).toBe(false)
|
|
183
|
-
expect(onAttachCancelled).toHaveBeenCalledTimes(1)
|
|
184
|
-
expect(onAttachError).toHaveBeenCalledTimes(1)
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
it('injects terminal size into attach params when available', async () => {
|
|
188
|
-
const attachSessionWithBundleRefresh = mock(async () => true)
|
|
189
|
-
|
|
190
|
-
const { result } = renderHook(() =>
|
|
191
|
-
useAttachController({
|
|
192
|
-
flow: {
|
|
193
|
-
showInput: () => {},
|
|
194
|
-
showMessage: () => {},
|
|
195
|
-
close: () => {},
|
|
196
|
-
},
|
|
197
|
-
attachSessionWithBundleRefresh,
|
|
198
|
-
getAttachSize: () => ({ cols: 132, rows: 41 }),
|
|
199
|
-
})
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
await result.current.attach({ sessionId: 'session-3' })
|
|
203
|
-
await result.current.attach({ sessionId: 'session-4', cols: 90, rows: 22 })
|
|
204
|
-
|
|
205
|
-
expect(attachSessionWithBundleRefresh).toHaveBeenNthCalledWith(
|
|
206
|
-
1,
|
|
207
|
-
{
|
|
208
|
-
sessionId: 'session-3',
|
|
209
|
-
cols: 132,
|
|
210
|
-
rows: 41,
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
projectName: null,
|
|
214
|
-
}
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
expect(attachSessionWithBundleRefresh).toHaveBeenNthCalledWith(
|
|
218
|
-
2,
|
|
219
|
-
{
|
|
220
|
-
sessionId: 'session-4',
|
|
221
|
-
cols: 90,
|
|
222
|
-
rows: 22,
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
projectName: null,
|
|
226
|
-
}
|
|
227
|
-
)
|
|
228
|
-
})
|
|
229
|
-
})
|