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
package/src/utils/logger.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Logging utilities with chalk for colored output
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Log levels
|
|
9
|
-
*/
|
|
10
|
-
export type LogLevel = 'info' | 'success' | 'warning' | 'error' | 'debug';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Logger instance
|
|
14
|
-
*/
|
|
15
|
-
class Logger {
|
|
16
|
-
private debugMode: boolean = false;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Enable or disable debug mode
|
|
20
|
-
*/
|
|
21
|
-
setDebugMode(enabled: boolean): void {
|
|
22
|
-
this.debugMode = enabled;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Log an info message
|
|
27
|
-
*/
|
|
28
|
-
info(message: string): void {
|
|
29
|
-
console.log(chalk.blue('ℹ'), message);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Log a success message
|
|
34
|
-
*/
|
|
35
|
-
success(message: string): void {
|
|
36
|
-
console.log(chalk.green('✓'), message);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Log a warning message
|
|
41
|
-
*/
|
|
42
|
-
warning(message: string): void {
|
|
43
|
-
console.log(chalk.yellow('⚠'), message);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Log an error message
|
|
48
|
-
*/
|
|
49
|
-
error(message: string): void {
|
|
50
|
-
console.error(chalk.red('✗'), message);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Log a debug message (only if debug mode is enabled)
|
|
55
|
-
*/
|
|
56
|
-
debug(message: string): void {
|
|
57
|
-
if (this.debugMode) {
|
|
58
|
-
console.log(chalk.gray('DEBUG:'), message);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Log a message without any prefix
|
|
64
|
-
*/
|
|
65
|
-
log(message: string): void {
|
|
66
|
-
console.log(message);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Log a dim/muted message
|
|
71
|
-
*/
|
|
72
|
-
dim(message: string): void {
|
|
73
|
-
console.log(chalk.dim(message));
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Log a bold message
|
|
78
|
-
*/
|
|
79
|
-
bold(message: string): void {
|
|
80
|
-
console.log(chalk.bold(message));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Create a spinner-like loading message
|
|
85
|
-
*/
|
|
86
|
-
loading(message: string): () => void {
|
|
87
|
-
process.stdout.write(chalk.blue('⠋') + ' ' + message);
|
|
88
|
-
|
|
89
|
-
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
90
|
-
let i = 0;
|
|
91
|
-
|
|
92
|
-
const interval = setInterval(() => {
|
|
93
|
-
process.stdout.write('\r' + chalk.blue(frames[i]) + ' ' + message);
|
|
94
|
-
i = (i + 1) % frames.length;
|
|
95
|
-
}, 80);
|
|
96
|
-
|
|
97
|
-
// Return a function to stop the spinner
|
|
98
|
-
return () => {
|
|
99
|
-
clearInterval(interval);
|
|
100
|
-
process.stdout.write('\r' + ' '.repeat(message.length + 2) + '\r');
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Format a command for display
|
|
106
|
-
*/
|
|
107
|
-
command(cmd: string): string {
|
|
108
|
-
return chalk.cyan(cmd);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Format a path for display
|
|
113
|
-
*/
|
|
114
|
-
path(path: string): string {
|
|
115
|
-
return chalk.magenta(path);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Format a highlight for display
|
|
120
|
-
*/
|
|
121
|
-
highlight(text: string): string {
|
|
122
|
-
return chalk.yellow(text);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Export singleton instance
|
|
127
|
-
export const logger = new Logger();
|
package/src/utils/markdown.ts
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Markdown generation for Linear issues
|
|
3
|
-
* Generates markdown files in the specified template format
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { writeFileSync } from 'fs'
|
|
7
|
-
import { join, extname } from 'path'
|
|
8
|
-
import type { LinearIssue as Issue, LinearAttachment } from '../types/workspace'
|
|
9
|
-
import { logger } from './logger.js'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Convert a string to kebab-case for branch names
|
|
13
|
-
*/
|
|
14
|
-
function toKebabCase(str: string, maxLength = 60): string {
|
|
15
|
-
const kebab = str
|
|
16
|
-
.toLowerCase()
|
|
17
|
-
.replace(/[^\w\s-]/g, '') // Remove special chars
|
|
18
|
-
.replace(/\s+/g, '-') // Replace spaces with dashes
|
|
19
|
-
.replace(/-+/g, '-') // Collapse multiple dashes
|
|
20
|
-
.replace(/^-|-$/g, '') // Remove leading/trailing dashes
|
|
21
|
-
|
|
22
|
-
// Truncate to max length at word boundary
|
|
23
|
-
if (kebab.length <= maxLength) {
|
|
24
|
-
return kebab
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const truncated = kebab.substring(0, maxLength)
|
|
28
|
-
const lastDash = truncated.lastIndexOf('-')
|
|
29
|
-
|
|
30
|
-
return lastDash > 0 ? truncated.substring(0, lastDash) : truncated
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Clean markdown text to plaintext while preserving structure
|
|
35
|
-
* Keeps lists and code fences readable
|
|
36
|
-
*/
|
|
37
|
-
function cleanMarkdown(text: string): string {
|
|
38
|
-
// For now, just return the text as-is
|
|
39
|
-
// More sophisticated markdown-to-plaintext conversion can be added later
|
|
40
|
-
return text.trim()
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Download an image from a URL and save it to disk
|
|
45
|
-
* Supports authenticated Linear image downloads
|
|
46
|
-
*/
|
|
47
|
-
async function downloadImage(
|
|
48
|
-
url: string,
|
|
49
|
-
filepath: string,
|
|
50
|
-
linearApiKey?: string
|
|
51
|
-
): Promise<void> {
|
|
52
|
-
try {
|
|
53
|
-
// Check if this is a Linear upload URL that requires authentication
|
|
54
|
-
const isLinearUpload = url.includes('uploads.linear.app')
|
|
55
|
-
|
|
56
|
-
// Prepare fetch options
|
|
57
|
-
const fetchOptions: RequestInit = {}
|
|
58
|
-
|
|
59
|
-
if (isLinearUpload && linearApiKey) {
|
|
60
|
-
// Linear API keys (lin_api_...) don't use Bearer prefix
|
|
61
|
-
// Only OAuth tokens use Bearer prefix
|
|
62
|
-
const authHeader = linearApiKey.startsWith('lin_api_')
|
|
63
|
-
? linearApiKey
|
|
64
|
-
: `Bearer ${linearApiKey}`
|
|
65
|
-
|
|
66
|
-
fetchOptions.headers = {
|
|
67
|
-
Authorization: authHeader,
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const response = await fetch(url, fetchOptions)
|
|
72
|
-
|
|
73
|
-
if (!response.ok) {
|
|
74
|
-
throw new Error(
|
|
75
|
-
`Failed to download image: ${response.status} ${response.statusText}`
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const arrayBuffer = await response.arrayBuffer()
|
|
80
|
-
const buffer = Buffer.from(arrayBuffer)
|
|
81
|
-
|
|
82
|
-
writeFileSync(filepath, buffer)
|
|
83
|
-
logger.debug(`Downloaded image: ${url} -> ${filepath}`)
|
|
84
|
-
} catch (error) {
|
|
85
|
-
logger.warning(
|
|
86
|
-
`Failed to download image from ${url}: ${
|
|
87
|
-
error instanceof Error ? error.message : 'Unknown error'
|
|
88
|
-
}`
|
|
89
|
-
)
|
|
90
|
-
throw error
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Get file extension from URL or default to .png
|
|
96
|
-
*/
|
|
97
|
-
function getExtensionFromUrl(url: string): string {
|
|
98
|
-
try {
|
|
99
|
-
const urlObj = new URL(url)
|
|
100
|
-
const pathname = urlObj.pathname
|
|
101
|
-
const ext = extname(pathname)
|
|
102
|
-
|
|
103
|
-
// Common image extensions
|
|
104
|
-
if (
|
|
105
|
-
['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp'].includes(
|
|
106
|
-
ext.toLowerCase()
|
|
107
|
-
)
|
|
108
|
-
) {
|
|
109
|
-
return ext.toLowerCase()
|
|
110
|
-
}
|
|
111
|
-
} catch {
|
|
112
|
-
// Invalid URL, fall through to default
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return '.png'
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Download and localize images in markdown and from attachments
|
|
120
|
-
* Replaces image URLs with local file paths
|
|
121
|
-
*/
|
|
122
|
-
async function downloadAndLocalizeImages(
|
|
123
|
-
description: string,
|
|
124
|
-
attachments: LinearAttachment[],
|
|
125
|
-
promptDir: string,
|
|
126
|
-
linearApiKey?: string
|
|
127
|
-
): Promise<string> {
|
|
128
|
-
let localizedDescription = description
|
|
129
|
-
let imageCounter = 1
|
|
130
|
-
|
|
131
|
-
// Regular expression to match markdown images: 
|
|
132
|
-
const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g
|
|
133
|
-
|
|
134
|
-
// Extract all image URLs from markdown
|
|
135
|
-
const imageMatches = Array.from(description.matchAll(imageRegex))
|
|
136
|
-
|
|
137
|
-
// Download images from markdown description
|
|
138
|
-
for (const match of imageMatches) {
|
|
139
|
-
const [fullMatch, altText, imageUrl] = match
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
const ext = getExtensionFromUrl(imageUrl)
|
|
143
|
-
const filename = `image-${imageCounter}${ext}`
|
|
144
|
-
const filepath = join(promptDir, filename)
|
|
145
|
-
|
|
146
|
-
await downloadImage(imageUrl, filepath, linearApiKey)
|
|
147
|
-
|
|
148
|
-
// Replace URL with local path in markdown
|
|
149
|
-
localizedDescription = localizedDescription.replace(
|
|
150
|
-
fullMatch,
|
|
151
|
-
``
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
imageCounter++
|
|
155
|
-
} catch (error) {
|
|
156
|
-
logger.warning(`Skipping image: ${imageUrl}`)
|
|
157
|
-
// Keep original URL if download fails
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Download images from Linear attachments (if they're image URLs)
|
|
162
|
-
for (const attachment of attachments) {
|
|
163
|
-
// Check if attachment is an image based on URL
|
|
164
|
-
const isImage = /\.(png|jpg|jpeg|gif|svg|webp)$/i.test(attachment.url)
|
|
165
|
-
|
|
166
|
-
if (isImage) {
|
|
167
|
-
try {
|
|
168
|
-
const ext = getExtensionFromUrl(attachment.url)
|
|
169
|
-
const filename = `attachment-${imageCounter}${ext}`
|
|
170
|
-
const filepath = join(promptDir, filename)
|
|
171
|
-
|
|
172
|
-
await downloadImage(attachment.url, filepath, linearApiKey)
|
|
173
|
-
|
|
174
|
-
// Add attachment to markdown if not already present
|
|
175
|
-
const attachmentTitle = attachment.title || `Attachment ${imageCounter}`
|
|
176
|
-
const attachmentMarkdown = `\n\n`
|
|
177
|
-
|
|
178
|
-
// Only add if this URL isn't already in the description
|
|
179
|
-
if (!description.includes(attachment.url)) {
|
|
180
|
-
localizedDescription += attachmentMarkdown
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
imageCounter++
|
|
184
|
-
} catch (error) {
|
|
185
|
-
logger.warning(`Skipping attachment: ${attachment.url}`)
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return localizedDescription
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Generate markdown content for an issue
|
|
195
|
-
* Follows the exact template format from the specification
|
|
196
|
-
*
|
|
197
|
-
* @param issue - The issue to generate markdown for
|
|
198
|
-
* @param promptDir - Directory where images will be saved (optional, if provided downloads images)
|
|
199
|
-
* @param linearApiKey - Linear API key for authenticated image downloads (optional)
|
|
200
|
-
* @returns Markdown formatted string
|
|
201
|
-
*/
|
|
202
|
-
export async function generateMarkdown(
|
|
203
|
-
issue: Issue,
|
|
204
|
-
promptDir?: string,
|
|
205
|
-
linearApiKey?: string
|
|
206
|
-
): Promise<string> {
|
|
207
|
-
const assignee = await issue.assignee
|
|
208
|
-
const state = await issue.state
|
|
209
|
-
|
|
210
|
-
const assigneeName = assignee?.name || 'unassigned'
|
|
211
|
-
|
|
212
|
-
let description = issue.description || 'No description provided.'
|
|
213
|
-
|
|
214
|
-
// Download and localize images if promptDir is provided
|
|
215
|
-
if (promptDir && issue.description) {
|
|
216
|
-
try {
|
|
217
|
-
// Fetch attachments (lazy-loaded - only called when needed)
|
|
218
|
-
const attachments = await issue.attachments()
|
|
219
|
-
|
|
220
|
-
description = await downloadAndLocalizeImages(
|
|
221
|
-
issue.description,
|
|
222
|
-
attachments,
|
|
223
|
-
promptDir,
|
|
224
|
-
linearApiKey
|
|
225
|
-
)
|
|
226
|
-
} catch (error) {
|
|
227
|
-
logger.warning('Failed to download some images, using original URLs')
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const fullDescription = cleanMarkdown(description)
|
|
232
|
-
const branchName = `${issue.identifier}-${toKebabCase(issue.title)}`
|
|
233
|
-
|
|
234
|
-
return `# ${issue.identifier}: ${issue.title}
|
|
235
|
-
|
|
236
|
-
**linear url:** ${issue.url}
|
|
237
|
-
**assignee:** ${assigneeName}
|
|
238
|
-
**state:** ${state?.name ?? 'Unknown'}
|
|
239
|
-
|
|
240
|
-
## description
|
|
241
|
-
|
|
242
|
-
${fullDescription}
|
|
243
|
-
|
|
244
|
-
## acceptance criteria (fill in)
|
|
245
|
-
|
|
246
|
-
- [ ] criterion 1
|
|
247
|
-
- [ ] criterion 2
|
|
248
|
-
|
|
249
|
-
## implementation notes (auto-generated)
|
|
250
|
-
|
|
251
|
-
- branch name: \`${branchName}\`
|
|
252
|
-
- source issue id: \`${issue.id}\`
|
|
253
|
-
`
|
|
254
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export function normalizeEnvKey(key: string): string {
|
|
2
|
-
return key
|
|
3
|
-
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
|
|
4
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
5
|
-
.replace(/[^A-Za-z0-9]+/g, '_')
|
|
6
|
-
.replace(/_+/g, '_')
|
|
7
|
-
.replace(/^_+|_+$/g, '')
|
|
8
|
-
.toUpperCase();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function isShellEnvKey(key: string): boolean {
|
|
12
|
-
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
|
|
13
|
-
}
|
package/src/utils/onboarding.ts
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Onboarding step execution engine
|
|
3
|
-
* Runs interactive onboarding steps from bundle manifests
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { logger } from './logger.js';
|
|
7
|
-
import { promptInput, promptConfirm, promptPassword } from './prompts.js';
|
|
8
|
-
import { checkCommandExists } from './deps.js';
|
|
9
|
-
import type {
|
|
10
|
-
OnboardingStep,
|
|
11
|
-
OnboardingResult,
|
|
12
|
-
ConfirmStepResult,
|
|
13
|
-
ConfirmStep,
|
|
14
|
-
SecretStep,
|
|
15
|
-
InputStep,
|
|
16
|
-
} from '../types/bundle.js';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Marker value returned when user chooses to keep an existing secret
|
|
20
|
-
*/
|
|
21
|
-
export const KEEP_EXISTING_SECRET = '__KEEP_EXISTING_SECRET__';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Marker value returned when an optional confirm step is skipped.
|
|
25
|
-
*/
|
|
26
|
-
const SKIP_OPTIONAL_CONFIRM = '__SKIP_OPTIONAL_CONFIRM__';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Options for running onboarding
|
|
30
|
-
*/
|
|
31
|
-
export interface OnboardingOptions {
|
|
32
|
-
/** Previous values from a prior onboarding run (for refresh) */
|
|
33
|
-
previousValues?: Record<string, string>;
|
|
34
|
-
/** Previous secret keys that exist in keychain */
|
|
35
|
-
previousSecretKeys?: string[];
|
|
36
|
-
/** Title to show (default: "Project Onboarding") */
|
|
37
|
-
title?: string;
|
|
38
|
-
/** Whether this is a refresh (shows different messaging) */
|
|
39
|
-
isRefresh?: boolean;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Execute all onboarding steps
|
|
44
|
-
*/
|
|
45
|
-
export async function runOnboarding(
|
|
46
|
-
steps: OnboardingStep[],
|
|
47
|
-
options: OnboardingOptions = {}
|
|
48
|
-
): Promise<OnboardingResult> {
|
|
49
|
-
const result: OnboardingResult = {
|
|
50
|
-
inputValues: {},
|
|
51
|
-
secretValues: {},
|
|
52
|
-
confirmResults: {},
|
|
53
|
-
completed: false,
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const title = options.title || 'Project Onboarding';
|
|
57
|
-
const refreshNote = options.isRefresh ? ' (refreshing - press Enter to keep existing values)' : '';
|
|
58
|
-
logger.bold(`\n=== ${title}${refreshNote} ===\n`);
|
|
59
|
-
|
|
60
|
-
for (let i = 0; i < steps.length; i++) {
|
|
61
|
-
const step = steps[i];
|
|
62
|
-
const stepNumber = i + 1;
|
|
63
|
-
const totalSteps = steps.length;
|
|
64
|
-
|
|
65
|
-
logger.log(`\n[${stepNumber}/${totalSteps}] ${step.title}`);
|
|
66
|
-
logger.dim(step.description);
|
|
67
|
-
logger.log('');
|
|
68
|
-
|
|
69
|
-
const stepResult = await executeStep(step, options);
|
|
70
|
-
|
|
71
|
-
if (stepResult === null) {
|
|
72
|
-
// User cancelled
|
|
73
|
-
result.cancelledAt = step.id;
|
|
74
|
-
logger.warning('\nOnboarding cancelled');
|
|
75
|
-
return result;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Store values and metadata by step type
|
|
79
|
-
if (step.type === 'secret') {
|
|
80
|
-
result.secretValues[step.configKey] = stepResult;
|
|
81
|
-
} else if (step.type === 'input') {
|
|
82
|
-
result.inputValues[step.configKey] = stepResult;
|
|
83
|
-
} else if (step.type === 'confirm') {
|
|
84
|
-
const confirmResult: ConfirmStepResult = {
|
|
85
|
-
status: stepResult === SKIP_OPTIONAL_CONFIRM ? 'skipped' : 'passed',
|
|
86
|
-
checkCommand: step.checkCommand,
|
|
87
|
-
};
|
|
88
|
-
result.confirmResults[step.id] = confirmResult;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
result.completed = true;
|
|
93
|
-
logger.success('\nOnboarding complete!');
|
|
94
|
-
return result;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Execute a single onboarding step
|
|
99
|
-
* Returns collected value or null if cancelled
|
|
100
|
-
*/
|
|
101
|
-
async function executeStep(step: OnboardingStep, options: OnboardingOptions): Promise<string | null> {
|
|
102
|
-
switch (step.type) {
|
|
103
|
-
case 'info':
|
|
104
|
-
return executeInfoStep();
|
|
105
|
-
case 'confirm':
|
|
106
|
-
return executeConfirmStep(step);
|
|
107
|
-
case 'secret':
|
|
108
|
-
return executeSecretStep(step, options);
|
|
109
|
-
case 'input':
|
|
110
|
-
return executeInputStep(step, options);
|
|
111
|
-
default:
|
|
112
|
-
logger.warning('Unknown step type, skipping');
|
|
113
|
-
return '';
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Execute info step - just wait for acknowledgment
|
|
119
|
-
*/
|
|
120
|
-
async function executeInfoStep(): Promise<string | null> {
|
|
121
|
-
const confirmed = await promptConfirm('Press Enter to continue...', true);
|
|
122
|
-
return confirmed ? '' : null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Execute confirm step - optionally check command
|
|
127
|
-
*/
|
|
128
|
-
async function executeConfirmStep(step: ConfirmStep): Promise<string | null> {
|
|
129
|
-
// Check if command exists (if specified)
|
|
130
|
-
if (step.checkCommand) {
|
|
131
|
-
const exists = await checkCommandExists(step.checkCommand);
|
|
132
|
-
|
|
133
|
-
if (exists) {
|
|
134
|
-
logger.success(`✓ ${step.checkCommand} is installed`);
|
|
135
|
-
return '';
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
logger.warning(`✗ ${step.checkCommand} not found in PATH`);
|
|
139
|
-
|
|
140
|
-
if (step.installUrl) {
|
|
141
|
-
logger.log(`\nInstall instructions: ${step.installUrl}`);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Ask user to confirm they've installed it
|
|
145
|
-
const prompt = step.confirmPrompt || `Have you installed ${step.checkCommand}?`;
|
|
146
|
-
|
|
147
|
-
while (true) {
|
|
148
|
-
const confirmed = await promptConfirm(prompt, false);
|
|
149
|
-
|
|
150
|
-
if (!confirmed) {
|
|
151
|
-
// User said no or cancelled
|
|
152
|
-
if (step.required !== false) {
|
|
153
|
-
logger.warning('This step is required. Please install and try again.');
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
// Optional step - skip it
|
|
157
|
-
logger.dim('Skipping optional step');
|
|
158
|
-
return SKIP_OPTIONAL_CONFIRM;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Re-check if they say yes
|
|
162
|
-
const nowExists = await checkCommandExists(step.checkCommand);
|
|
163
|
-
if (nowExists) {
|
|
164
|
-
logger.success(`✓ ${step.checkCommand} is now available`);
|
|
165
|
-
return '';
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
logger.warning(`${step.checkCommand} still not found. Please ensure it's in your PATH.`);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// No command check, just confirm
|
|
173
|
-
const prompt = step.confirmPrompt || 'Continue?';
|
|
174
|
-
const confirmed = await promptConfirm(prompt, true);
|
|
175
|
-
if (!confirmed && step.required === false) {
|
|
176
|
-
// Optional step - skip it instead of cancelling
|
|
177
|
-
logger.dim('Skipping optional step');
|
|
178
|
-
return SKIP_OPTIONAL_CONFIRM;
|
|
179
|
-
}
|
|
180
|
-
return confirmed ? '' : null;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Execute secret step - collect masked input
|
|
185
|
-
*/
|
|
186
|
-
async function executeSecretStep(step: SecretStep, options: OnboardingOptions): Promise<string | null> {
|
|
187
|
-
const validator = step.validationPattern
|
|
188
|
-
? createValidator(step.validationPattern, step.validationMessage)
|
|
189
|
-
: undefined;
|
|
190
|
-
|
|
191
|
-
// Check if we have an existing secret for this key
|
|
192
|
-
const hasExistingSecret = options.previousSecretKeys?.includes(step.configKey);
|
|
193
|
-
|
|
194
|
-
if (hasExistingSecret && options.isRefresh) {
|
|
195
|
-
logger.dim(' (existing secret found)');
|
|
196
|
-
const keepExisting = await promptConfirm('Keep existing secret? (Enter to keep, n to change)', true);
|
|
197
|
-
if (keepExisting) {
|
|
198
|
-
// Return special marker that means "keep existing"
|
|
199
|
-
return KEEP_EXISTING_SECRET;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
while (true) {
|
|
204
|
-
const value = await promptPassword(`Enter ${step.title}:`);
|
|
205
|
-
|
|
206
|
-
if (value === null) {
|
|
207
|
-
return null; // Cancelled
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (!value && step.required !== false) {
|
|
211
|
-
logger.warning('This field is required');
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (validator && value) {
|
|
216
|
-
const validationResult = validator(value);
|
|
217
|
-
if (validationResult !== true) {
|
|
218
|
-
logger.warning(typeof validationResult === 'string' ? validationResult : 'Invalid input');
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return value;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Execute input step - collect plain text input
|
|
229
|
-
*/
|
|
230
|
-
async function executeInputStep(step: InputStep, options: OnboardingOptions): Promise<string | null> {
|
|
231
|
-
const validator = step.validationPattern
|
|
232
|
-
? createValidator(step.validationPattern, step.validationMessage)
|
|
233
|
-
: undefined;
|
|
234
|
-
|
|
235
|
-
// Use previous value as default if available (for refresh), otherwise use step's default
|
|
236
|
-
const previousValue = options.previousValues?.[step.configKey];
|
|
237
|
-
const defaultValue = previousValue ?? step.defaultValue;
|
|
238
|
-
|
|
239
|
-
if (previousValue && options.isRefresh) {
|
|
240
|
-
logger.dim(` (current value: ${previousValue})`);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const value = await promptInput(`Enter ${step.title}:`, {
|
|
244
|
-
default: defaultValue,
|
|
245
|
-
validate: (input) => {
|
|
246
|
-
if (!input && step.required !== false) {
|
|
247
|
-
return 'This field is required';
|
|
248
|
-
}
|
|
249
|
-
if (validator && input) {
|
|
250
|
-
return validator(input);
|
|
251
|
-
}
|
|
252
|
-
return true;
|
|
253
|
-
},
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
return value;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Create a validator function from regex pattern
|
|
261
|
-
* Returns undefined if the pattern is invalid
|
|
262
|
-
*/
|
|
263
|
-
function createValidator(
|
|
264
|
-
pattern: string,
|
|
265
|
-
message?: string
|
|
266
|
-
): ((value: string) => boolean | string) | undefined {
|
|
267
|
-
try {
|
|
268
|
-
const regex = new RegExp(pattern);
|
|
269
|
-
return (value: string) => {
|
|
270
|
-
if (regex.test(value)) {
|
|
271
|
-
return true;
|
|
272
|
-
}
|
|
273
|
-
return message || `Value must match pattern: ${pattern}`;
|
|
274
|
-
};
|
|
275
|
-
} catch (error) {
|
|
276
|
-
logger.warning(`Invalid validation pattern '${pattern}', skipping validation`);
|
|
277
|
-
return undefined;
|
|
278
|
-
}
|
|
279
|
-
}
|