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,216 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared workspace lifecycle orchestration used by CLI, TUI, and remote flows.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
checkAndRefreshBundle,
|
|
7
|
-
detectBundleChanges,
|
|
8
|
-
formatBundleChangeDetails,
|
|
9
|
-
getBundleRefreshPlan,
|
|
10
|
-
syncBundleWorkspaceState,
|
|
11
|
-
} from './bundle-refresh.js';
|
|
12
|
-
import { readProjectConfig } from './config.js';
|
|
13
|
-
import { logger } from '../utils/logger.js';
|
|
14
|
-
import { preloadProjectSecrets } from '../utils/secrets.js';
|
|
15
|
-
import { shouldSkipSecretDependentScripts } from './secret-runtime.js';
|
|
16
|
-
import {
|
|
17
|
-
runWorkspaceScripts,
|
|
18
|
-
type RunWorkspaceScriptsResult,
|
|
19
|
-
type ScriptPhase,
|
|
20
|
-
} from '../utils/run-workspace-scripts.js';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* How to handle bundle changes before running workspace scripts.
|
|
24
|
-
*/
|
|
25
|
-
export type BundlePreparationMode =
|
|
26
|
-
| 'prompt-refresh'
|
|
27
|
-
| 'error-if-changed'
|
|
28
|
-
| 'skip';
|
|
29
|
-
|
|
30
|
-
export interface PrepareWorkspaceForSessionOptions {
|
|
31
|
-
projectName: string;
|
|
32
|
-
workspacePath: string;
|
|
33
|
-
workspaceName: string;
|
|
34
|
-
/** Repository name (owner/repo). If omitted, read from project config. */
|
|
35
|
-
repository?: string;
|
|
36
|
-
/** If true, skip setup scripts on first run. */
|
|
37
|
-
noSetup?: boolean;
|
|
38
|
-
/** If true, script processes can prompt for input. */
|
|
39
|
-
interactiveScripts?: boolean;
|
|
40
|
-
/** Bundle readiness mode before running scripts. */
|
|
41
|
-
bundleMode?: BundlePreparationMode;
|
|
42
|
-
/** Stream script output (stdout/stderr). */
|
|
43
|
-
onOutput?: (data: Buffer) => void;
|
|
44
|
-
/** Called when script phase starts. */
|
|
45
|
-
onPhaseStart?: (phase: ScriptPhase) => void;
|
|
46
|
-
/** Script execution policy for attach attempts. */
|
|
47
|
-
scriptPolicy?: 'auto' | 'skip';
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export type PrepareWorkspaceForSessionResult =
|
|
51
|
-
| RunWorkspaceScriptsResult
|
|
52
|
-
| {
|
|
53
|
-
success: false;
|
|
54
|
-
phase: 'pre';
|
|
55
|
-
error: string;
|
|
56
|
-
bundleNeedsRefresh?: boolean;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const BUNDLE_REFRESH_REQUIRED_MESSAGE =
|
|
60
|
-
'Run "gssh bundle refresh" and retry.';
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Prepare a workspace for session use.
|
|
64
|
-
*
|
|
65
|
-
* This handles bundle readiness checks, secret preload, and script lifecycle
|
|
66
|
-
* execution (pre/setup/select).
|
|
67
|
-
*/
|
|
68
|
-
export async function prepareWorkspaceForSession(
|
|
69
|
-
options: PrepareWorkspaceForSessionOptions
|
|
70
|
-
): Promise<PrepareWorkspaceForSessionResult> {
|
|
71
|
-
const {
|
|
72
|
-
projectName,
|
|
73
|
-
workspacePath,
|
|
74
|
-
workspaceName,
|
|
75
|
-
repository,
|
|
76
|
-
noSetup = false,
|
|
77
|
-
interactiveScripts = false,
|
|
78
|
-
bundleMode = 'error-if-changed',
|
|
79
|
-
onOutput,
|
|
80
|
-
onPhaseStart,
|
|
81
|
-
scriptPolicy = 'auto',
|
|
82
|
-
} = options;
|
|
83
|
-
|
|
84
|
-
const projectConfig = readProjectConfig(projectName);
|
|
85
|
-
|
|
86
|
-
if (shouldSkipSecretDependentScripts(projectName, projectConfig.bundleSecretKeys)) {
|
|
87
|
-
const bundleReady = await ensureBundleReady({
|
|
88
|
-
projectName,
|
|
89
|
-
workspacePath,
|
|
90
|
-
mode: 'skip',
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
if (!bundleReady.success) {
|
|
94
|
-
return {
|
|
95
|
-
success: false,
|
|
96
|
-
phase: 'pre',
|
|
97
|
-
error: bundleReady.error,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
logger.warning(
|
|
102
|
-
`Skipping workspace scripts for "${workspaceName}" because --ignore-keychain-and-skip-secrets is enabled.`
|
|
103
|
-
);
|
|
104
|
-
return { success: true };
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const bundleReady = await ensureBundleReady({
|
|
108
|
-
projectName,
|
|
109
|
-
workspacePath,
|
|
110
|
-
mode: bundleMode,
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
if (!bundleReady.success) {
|
|
114
|
-
return {
|
|
115
|
-
success: false,
|
|
116
|
-
phase: 'pre',
|
|
117
|
-
error: bundleReady.error,
|
|
118
|
-
bundleNeedsRefresh: bundleReady.bundleNeedsRefresh,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (projectConfig.bundleSecretKeys && projectConfig.bundleSecretKeys.length > 0) {
|
|
123
|
-
await preloadProjectSecrets(projectName, projectConfig.bundleSecretKeys);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return runWorkspaceScripts({
|
|
127
|
-
projectName,
|
|
128
|
-
workspacePath,
|
|
129
|
-
workspaceName,
|
|
130
|
-
repository: repository || projectConfig.repository,
|
|
131
|
-
noSetup,
|
|
132
|
-
interactive: interactiveScripts,
|
|
133
|
-
onOutput,
|
|
134
|
-
onPhaseStart,
|
|
135
|
-
scriptPolicy,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
interface EnsureBundleReadyOptions {
|
|
140
|
-
projectName: string;
|
|
141
|
-
workspacePath: string;
|
|
142
|
-
mode: BundlePreparationMode;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
async function ensureBundleReady(
|
|
146
|
-
options: EnsureBundleReadyOptions
|
|
147
|
-
): Promise<{ success: true } | { success: false; error: string; bundleNeedsRefresh?: boolean }> {
|
|
148
|
-
const { projectName, workspacePath, mode } = options;
|
|
149
|
-
|
|
150
|
-
if (mode === 'skip') {
|
|
151
|
-
const syncResult = syncBundleWorkspaceState(projectName, workspacePath);
|
|
152
|
-
if (syncResult.parseError) {
|
|
153
|
-
return {
|
|
154
|
-
success: false,
|
|
155
|
-
error: `Bundle parse error: ${syncResult.parseError}`,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return { success: true };
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (mode === 'prompt-refresh') {
|
|
163
|
-
const ready = await checkAndRefreshBundle(projectName, workspacePath);
|
|
164
|
-
if (!ready) {
|
|
165
|
-
return {
|
|
166
|
-
success: false,
|
|
167
|
-
error: 'Bundle refresh was not completed',
|
|
168
|
-
bundleNeedsRefresh: true,
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return { success: true };
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// mode === 'error-if-changed'
|
|
176
|
-
const changes = detectBundleChanges(projectName, workspacePath);
|
|
177
|
-
if (changes.parseError) {
|
|
178
|
-
return {
|
|
179
|
-
success: false,
|
|
180
|
-
error: `Bundle parse error: ${changes.parseError}`,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (changes.hasBundle && changes.hasChanged) {
|
|
185
|
-
logger.info('Bundle configuration has changed for this workspace');
|
|
186
|
-
const details = formatBundleChangeDetails(changes);
|
|
187
|
-
return {
|
|
188
|
-
success: false,
|
|
189
|
-
error: `${details}\n${BUNDLE_REFRESH_REQUIRED_MESSAGE}`,
|
|
190
|
-
bundleNeedsRefresh: true,
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (changes.hasBundle) {
|
|
195
|
-
const plan = await getBundleRefreshPlan(projectName, workspacePath);
|
|
196
|
-
const hasRequiredSteps = plan.steps.some((step) => step.required !== false);
|
|
197
|
-
|
|
198
|
-
if (hasRequiredSteps) {
|
|
199
|
-
return {
|
|
200
|
-
success: false,
|
|
201
|
-
error: `${plan.details}\n${BUNDLE_REFRESH_REQUIRED_MESSAGE}`,
|
|
202
|
-
bundleNeedsRefresh: true,
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const syncResult = syncBundleWorkspaceState(projectName, workspacePath);
|
|
208
|
-
if (syncResult.parseError) {
|
|
209
|
-
return {
|
|
210
|
-
success: false,
|
|
211
|
-
error: `Bundle parse error: ${syncResult.parseError}`,
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return { success: true };
|
|
216
|
-
}
|
package/src/core/workspace.ts
DELETED
|
@@ -1,363 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core workspace and project deletion operations
|
|
3
|
-
* These functions contain the shared logic used by CLI, TUI, and remote handlers
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { existsSync, readdirSync, rmSync } from 'fs';
|
|
7
|
-
import { join } from 'path';
|
|
8
|
-
import {
|
|
9
|
-
readProjectConfig,
|
|
10
|
-
updateProjectConfig,
|
|
11
|
-
getProjectWorkspacesDir,
|
|
12
|
-
getProjectBaseDir,
|
|
13
|
-
getProjectDir,
|
|
14
|
-
readGlobalConfig,
|
|
15
|
-
updateGlobalConfig,
|
|
16
|
-
} from './config.js';
|
|
17
|
-
import {
|
|
18
|
-
removeWorktree,
|
|
19
|
-
deleteLocalBranch,
|
|
20
|
-
getWorktreeInfo,
|
|
21
|
-
} from './git.js';
|
|
22
|
-
import { runScriptsInTerminal } from '../utils/run-scripts.js';
|
|
23
|
-
import { getProjectSecrets } from '../utils/secrets.js';
|
|
24
|
-
import { shouldSkipSecretDependentScripts } from './secret-runtime.js';
|
|
25
|
-
import { logger } from '../utils/logger.js';
|
|
26
|
-
import {
|
|
27
|
-
listSessions,
|
|
28
|
-
killSession,
|
|
29
|
-
isServerRunning,
|
|
30
|
-
} from '../lib/tmux-lite/cli.js';
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Options for workspace deletion
|
|
34
|
-
*/
|
|
35
|
-
export interface DeleteWorkspaceOptions {
|
|
36
|
-
/**
|
|
37
|
-
* Run in non-interactive mode (for TUI/daemon/remote contexts).
|
|
38
|
-
* When true, remove scripts run with stdin closed.
|
|
39
|
-
*/
|
|
40
|
-
nonInteractive?: boolean;
|
|
41
|
-
/** Keep the local branch after removing worktree */
|
|
42
|
-
keepBranch?: boolean;
|
|
43
|
-
/**
|
|
44
|
-
* Callback to receive ANSI output from remove scripts (for TUI/Web terminal display).
|
|
45
|
-
* Called with raw output from stdout/stderr.
|
|
46
|
-
*/
|
|
47
|
-
onScriptOutput?: (data: Buffer) => void;
|
|
48
|
-
/**
|
|
49
|
-
* Callback to report progress on deletion steps (for TUI loading indicator).
|
|
50
|
-
* Called with a human-readable message for each step.
|
|
51
|
-
*/
|
|
52
|
-
onProgress?: (message: string) => void;
|
|
53
|
-
/**
|
|
54
|
-
* Controls remove-script behavior:
|
|
55
|
-
* - enforce: fail deletion when remove scripts fail
|
|
56
|
-
* - best-effort: log remove script failures and continue deletion
|
|
57
|
-
* - skip: do not run remove scripts
|
|
58
|
-
*/
|
|
59
|
-
removeScriptPolicy?: 'enforce' | 'best-effort' | 'skip';
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Result of workspace deletion
|
|
64
|
-
*/
|
|
65
|
-
export interface DeleteWorkspaceResult {
|
|
66
|
-
success: boolean;
|
|
67
|
-
workspaceName: string;
|
|
68
|
-
branch?: string;
|
|
69
|
-
branchDeleted: boolean;
|
|
70
|
-
sessionsKilled: number;
|
|
71
|
-
errorCode?: 'WORKSPACE_NOT_FOUND' | 'REMOVE_SCRIPT_FAILED' | 'WORKTREE_REMOVE_FAILED';
|
|
72
|
-
error?: string;
|
|
73
|
-
removeScriptError?: string;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Core workspace deletion logic
|
|
78
|
-
* Used by CLI, TUI, and remote session handlers
|
|
79
|
-
*
|
|
80
|
-
* @param projectName - Name of the project containing the workspace
|
|
81
|
-
* @param workspaceName - Name of the workspace to delete
|
|
82
|
-
* @param options - Deletion options
|
|
83
|
-
*/
|
|
84
|
-
export async function deleteWorkspaceCore(
|
|
85
|
-
projectName: string,
|
|
86
|
-
workspaceName: string,
|
|
87
|
-
options: DeleteWorkspaceOptions = {}
|
|
88
|
-
): Promise<DeleteWorkspaceResult> {
|
|
89
|
-
const workspacesDir = getProjectWorkspacesDir(projectName);
|
|
90
|
-
const baseDir = getProjectBaseDir(projectName);
|
|
91
|
-
const workspacePath = join(workspacesDir, workspaceName);
|
|
92
|
-
|
|
93
|
-
const result: DeleteWorkspaceResult = {
|
|
94
|
-
success: false,
|
|
95
|
-
workspaceName,
|
|
96
|
-
branchDeleted: false,
|
|
97
|
-
sessionsKilled: 0,
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
// Validate workspace exists before attempting deletion
|
|
101
|
-
if (!existsSync(workspacePath)) {
|
|
102
|
-
result.errorCode = 'WORKSPACE_NOT_FOUND';
|
|
103
|
-
result.error = `Workspace "${workspaceName}" does not exist`;
|
|
104
|
-
return result;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const removeScriptPolicy = options.removeScriptPolicy ?? 'enforce';
|
|
108
|
-
let projectConfig: ReturnType<typeof readProjectConfig> | null = null;
|
|
109
|
-
try {
|
|
110
|
-
projectConfig = readProjectConfig(projectName);
|
|
111
|
-
} catch (error) {
|
|
112
|
-
logger.debug(
|
|
113
|
-
`Failed to read project config for ${projectName} while preparing delete: ${error instanceof Error ? error.message : String(error)}`
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
const skipSecretScripts = shouldSkipSecretDependentScripts(
|
|
117
|
-
projectName,
|
|
118
|
-
projectConfig?.bundleSecretKeys
|
|
119
|
-
);
|
|
120
|
-
const effectiveRemoveScriptPolicy = skipSecretScripts ? 'skip' : removeScriptPolicy;
|
|
121
|
-
|
|
122
|
-
// Get workspace info before deletion
|
|
123
|
-
const info = await getWorktreeInfo(workspacePath);
|
|
124
|
-
if (info) {
|
|
125
|
-
result.branch = info.branch;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Kill any sessions running in this workspace
|
|
129
|
-
try {
|
|
130
|
-
if (await isServerRunning()) {
|
|
131
|
-
const sessions = await listSessions();
|
|
132
|
-
const workspaceSessions = sessions.filter(s => s.cwd === workspacePath);
|
|
133
|
-
if (workspaceSessions.length > 0) {
|
|
134
|
-
options.onProgress?.(`Killing ${workspaceSessions.length} session(s)...`);
|
|
135
|
-
}
|
|
136
|
-
for (const session of workspaceSessions) {
|
|
137
|
-
try {
|
|
138
|
-
await killSession(session.id);
|
|
139
|
-
result.sessionsKilled++;
|
|
140
|
-
logger.debug(`Killed session ${session.name} (${session.id})`);
|
|
141
|
-
} catch (e) {
|
|
142
|
-
logger.debug(`Failed to kill session ${session.id}: ${e}`);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
} catch (e) {
|
|
147
|
-
logger.debug(`Error checking/killing sessions: ${e}`);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Run remove scripts (cleanup before deletion)
|
|
151
|
-
if (effectiveRemoveScriptPolicy !== 'skip') {
|
|
152
|
-
try {
|
|
153
|
-
const config = projectConfig ?? readProjectConfig(projectName);
|
|
154
|
-
const removeScriptsDir = join(workspacePath, '.gitspace', 'scripts', 'remove');
|
|
155
|
-
const bundleSecrets = config.bundleSecretKeys && config.bundleSecretKeys.length > 0
|
|
156
|
-
? await getProjectSecrets(projectName, config.bundleSecretKeys)
|
|
157
|
-
: undefined;
|
|
158
|
-
|
|
159
|
-
options.onProgress?.('Running cleanup scripts...');
|
|
160
|
-
await runScriptsInTerminal(
|
|
161
|
-
removeScriptsDir,
|
|
162
|
-
workspacePath,
|
|
163
|
-
workspaceName,
|
|
164
|
-
config.repository,
|
|
165
|
-
{
|
|
166
|
-
bundleValues: config.bundleValues,
|
|
167
|
-
bundleSecrets,
|
|
168
|
-
nonInteractive: options.nonInteractive,
|
|
169
|
-
onOutput: options.onScriptOutput,
|
|
170
|
-
}
|
|
171
|
-
);
|
|
172
|
-
} catch (e) {
|
|
173
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
174
|
-
if (effectiveRemoveScriptPolicy === 'enforce') {
|
|
175
|
-
result.errorCode = 'REMOVE_SCRIPT_FAILED';
|
|
176
|
-
result.removeScriptError = message;
|
|
177
|
-
result.error = `Remove scripts failed: ${message}`;
|
|
178
|
-
return result;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
logger.debug(`Remove scripts failed for ${workspaceName}: ${e}`);
|
|
182
|
-
}
|
|
183
|
-
} else {
|
|
184
|
-
if (skipSecretScripts) {
|
|
185
|
-
options.onProgress?.('Skipping cleanup scripts (secret loading disabled)...');
|
|
186
|
-
} else {
|
|
187
|
-
options.onProgress?.('Skipping cleanup scripts...');
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Remove worktree
|
|
192
|
-
options.onProgress?.('Removing worktree...');
|
|
193
|
-
try {
|
|
194
|
-
await removeWorktree(baseDir, workspacePath, true);
|
|
195
|
-
} catch (e) {
|
|
196
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
197
|
-
const isNotWorkingTreeError = /not a working tree/i.test(message);
|
|
198
|
-
|
|
199
|
-
if (isNotWorkingTreeError) {
|
|
200
|
-
logger.debug(
|
|
201
|
-
`Worktree metadata missing for ${workspaceName}; removing directory directly.`
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
try {
|
|
205
|
-
rmSync(workspacePath, { recursive: true, force: true });
|
|
206
|
-
} catch (rmError) {
|
|
207
|
-
result.errorCode = 'WORKTREE_REMOVE_FAILED';
|
|
208
|
-
result.error =
|
|
209
|
-
rmError instanceof Error
|
|
210
|
-
? rmError.message
|
|
211
|
-
: 'Failed to remove orphaned workspace directory';
|
|
212
|
-
return result;
|
|
213
|
-
}
|
|
214
|
-
} else {
|
|
215
|
-
result.errorCode = 'WORKTREE_REMOVE_FAILED';
|
|
216
|
-
result.error = message || 'Failed to remove worktree';
|
|
217
|
-
return result;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Try to delete the local branch
|
|
222
|
-
if (!options.keepBranch && info?.branch) {
|
|
223
|
-
options.onProgress?.(`Deleting branch ${info.branch}...`);
|
|
224
|
-
try {
|
|
225
|
-
await deleteLocalBranch(baseDir, info.branch, true);
|
|
226
|
-
result.branchDeleted = true;
|
|
227
|
-
} catch (e) {
|
|
228
|
-
// Branch deletion is best-effort
|
|
229
|
-
logger.debug(`Could not delete branch ${info.branch}: ${e}`);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
result.success = true;
|
|
234
|
-
|
|
235
|
-
// Remove per-workspace bundle metadata for deleted workspace.
|
|
236
|
-
try {
|
|
237
|
-
const projectConfig = readProjectConfig(projectName);
|
|
238
|
-
if (projectConfig.bundleWorkspaceState && projectConfig.bundleWorkspaceState[workspaceName]) {
|
|
239
|
-
const nextState = { ...projectConfig.bundleWorkspaceState };
|
|
240
|
-
delete nextState[workspaceName];
|
|
241
|
-
|
|
242
|
-
updateProjectConfig(projectName, {
|
|
243
|
-
bundleWorkspaceState: Object.keys(nextState).length > 0 ? nextState : undefined,
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
} catch (e) {
|
|
247
|
-
logger.debug(`Failed to update bundle workspace metadata for ${workspaceName}: ${e}`);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return result;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Options for project deletion
|
|
255
|
-
*/
|
|
256
|
-
export interface DeleteProjectOptions {
|
|
257
|
-
/**
|
|
258
|
-
* Run in non-interactive mode (for TUI/daemon/remote contexts).
|
|
259
|
-
* When true, remove scripts run with stdin closed.
|
|
260
|
-
*/
|
|
261
|
-
nonInteractive?: boolean;
|
|
262
|
-
/**
|
|
263
|
-
* Callback to report progress on deletion steps (for TUI loading indicator).
|
|
264
|
-
* Called with a human-readable message for each step.
|
|
265
|
-
*/
|
|
266
|
-
onProgress?: (message: string) => void;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Result of project deletion
|
|
271
|
-
*/
|
|
272
|
-
export interface DeleteProjectResult {
|
|
273
|
-
success: boolean;
|
|
274
|
-
projectName: string;
|
|
275
|
-
workspacesDeleted: number;
|
|
276
|
-
sessionsKilled: number;
|
|
277
|
-
wasCurrentProject: boolean;
|
|
278
|
-
errors: string[];
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Core project deletion logic
|
|
283
|
-
* Tears down sessions, runs remove scripts for all workspaces, then deletes project
|
|
284
|
-
*
|
|
285
|
-
* @param projectName - Name of the project to delete
|
|
286
|
-
* @param options - Deletion options
|
|
287
|
-
*/
|
|
288
|
-
export async function deleteProjectCore(
|
|
289
|
-
projectName: string,
|
|
290
|
-
options: DeleteProjectOptions = {}
|
|
291
|
-
): Promise<DeleteProjectResult> {
|
|
292
|
-
const projectDir = getProjectDir(projectName);
|
|
293
|
-
const workspacesDir = getProjectWorkspacesDir(projectName);
|
|
294
|
-
|
|
295
|
-
const result: DeleteProjectResult = {
|
|
296
|
-
success: false,
|
|
297
|
-
projectName,
|
|
298
|
-
workspacesDeleted: 0,
|
|
299
|
-
sessionsKilled: 0,
|
|
300
|
-
wasCurrentProject: false,
|
|
301
|
-
errors: [],
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
// Validate project directory exists before attempting deletion
|
|
305
|
-
if (!existsSync(projectDir)) {
|
|
306
|
-
result.errors.push(`Project "${projectName}" does not exist`);
|
|
307
|
-
return result;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Get list of workspaces
|
|
311
|
-
let workspaceNames: string[] = [];
|
|
312
|
-
if (existsSync(workspacesDir)) {
|
|
313
|
-
try {
|
|
314
|
-
workspaceNames = readdirSync(workspacesDir);
|
|
315
|
-
} catch (e) {
|
|
316
|
-
logger.debug(`Could not read workspaces dir: ${e}`);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Delete each workspace (this handles session teardown and remove scripts)
|
|
321
|
-
for (let i = 0; i < workspaceNames.length; i++) {
|
|
322
|
-
const workspaceName = workspaceNames[i];
|
|
323
|
-
options.onProgress?.(`Removing workspace ${i + 1}/${workspaceNames.length}: ${workspaceName}...`);
|
|
324
|
-
try {
|
|
325
|
-
const wsResult = await deleteWorkspaceCore(projectName, workspaceName, {
|
|
326
|
-
nonInteractive: options.nonInteractive,
|
|
327
|
-
keepBranch: true, // Don't try to delete branches, we're removing the whole repo
|
|
328
|
-
onProgress: options.onProgress,
|
|
329
|
-
removeScriptPolicy: 'best-effort',
|
|
330
|
-
});
|
|
331
|
-
if (wsResult.success) {
|
|
332
|
-
result.workspacesDeleted++;
|
|
333
|
-
result.sessionsKilled += wsResult.sessionsKilled;
|
|
334
|
-
} else if (wsResult.error) {
|
|
335
|
-
result.errors.push(`${workspaceName}: ${wsResult.error}`);
|
|
336
|
-
}
|
|
337
|
-
} catch (e) {
|
|
338
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
339
|
-
result.errors.push(`${workspaceName}: ${msg}`);
|
|
340
|
-
logger.debug(`Failed to delete workspace ${workspaceName}: ${e}`);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
// Remove entire project directory
|
|
345
|
-
options.onProgress?.('Removing project directory...');
|
|
346
|
-
try {
|
|
347
|
-
rmSync(projectDir, { recursive: true, force: true });
|
|
348
|
-
} catch (e) {
|
|
349
|
-
const msg = e instanceof Error ? e.message : 'Failed to remove project directory';
|
|
350
|
-
result.errors.push(msg);
|
|
351
|
-
return result;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Update global config if this was the current project
|
|
355
|
-
const globalConfig = readGlobalConfig();
|
|
356
|
-
if (globalConfig.currentProject === projectName) {
|
|
357
|
-
updateGlobalConfig({ currentProject: null });
|
|
358
|
-
result.wasCurrentProject = true;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
result.success = true;
|
|
362
|
-
return result;
|
|
363
|
-
}
|