@vibe80/vibe80 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +52 -0
  3. package/bin/vibe80.js +176 -0
  4. package/client/dist/assets/DiffPanel-C_IGzKI5.js +1 -0
  5. package/client/dist/assets/ExplorerPanel-BtlyAT00.js +11 -0
  6. package/client/dist/assets/LogsPanel-BW79JWzR.js +1 -0
  7. package/client/dist/assets/SettingsPanel-b9B7ygP_.js +1 -0
  8. package/client/dist/assets/TerminalPanel-C3fc1HbK.js +1 -0
  9. package/client/dist/assets/browser-e3WgtMs-.js +8 -0
  10. package/client/dist/assets/index-CgqGyssr.css +32 -0
  11. package/client/dist/assets/index-DnwKjoj7.js +706 -0
  12. package/client/dist/assets/vibe80_dark-D7OVPKcU.svg +51 -0
  13. package/client/dist/assets/vibe80_light-BJK37ybI.svg +50 -0
  14. package/client/dist/favicon.ico +0 -0
  15. package/client/dist/favicon.png +0 -0
  16. package/client/dist/favicon.svg +35 -0
  17. package/client/dist/index.html +14 -0
  18. package/client/index.html +16 -0
  19. package/client/package.json +34 -0
  20. package/client/public/favicon.ico +0 -0
  21. package/client/public/favicon.png +0 -0
  22. package/client/public/favicon.svg +35 -0
  23. package/client/public/pwa-192x192.png +0 -0
  24. package/client/public/pwa-512x512.png +0 -0
  25. package/client/src/App.jsx +3131 -0
  26. package/client/src/assets/logo_small.png +0 -0
  27. package/client/src/assets/vibe80_dark.svg +51 -0
  28. package/client/src/assets/vibe80_light.svg +50 -0
  29. package/client/src/components/Chat/ChatComposer.jsx +228 -0
  30. package/client/src/components/Chat/ChatMessages.jsx +811 -0
  31. package/client/src/components/Chat/ChatToolbar.jsx +109 -0
  32. package/client/src/components/Chat/useChatComposer.js +462 -0
  33. package/client/src/components/Diff/DiffPanel.jsx +129 -0
  34. package/client/src/components/Explorer/ExplorerPanel.jsx +449 -0
  35. package/client/src/components/Logs/LogsPanel.jsx +80 -0
  36. package/client/src/components/SessionGate/SessionGate.jsx +874 -0
  37. package/client/src/components/Settings/SettingsPanel.jsx +212 -0
  38. package/client/src/components/Terminal/TerminalPanel.jsx +39 -0
  39. package/client/src/components/Topbar/Topbar.jsx +101 -0
  40. package/client/src/components/WorktreeTabs.css +419 -0
  41. package/client/src/components/WorktreeTabs.jsx +604 -0
  42. package/client/src/hooks/useAttachments.jsx +125 -0
  43. package/client/src/hooks/useBacklog.js +254 -0
  44. package/client/src/hooks/useChatClear.js +90 -0
  45. package/client/src/hooks/useChatCollapse.js +42 -0
  46. package/client/src/hooks/useChatCommands.js +294 -0
  47. package/client/src/hooks/useChatExport.js +144 -0
  48. package/client/src/hooks/useChatMessagesState.js +69 -0
  49. package/client/src/hooks/useChatSend.js +158 -0
  50. package/client/src/hooks/useChatSocket.js +1239 -0
  51. package/client/src/hooks/useDiffNavigation.js +19 -0
  52. package/client/src/hooks/useExplorerActions.js +1184 -0
  53. package/client/src/hooks/useGitIdentity.js +114 -0
  54. package/client/src/hooks/useLayoutMode.js +31 -0
  55. package/client/src/hooks/useLocalPreferences.js +131 -0
  56. package/client/src/hooks/useMessageSync.js +30 -0
  57. package/client/src/hooks/useNotifications.js +132 -0
  58. package/client/src/hooks/usePaneNavigation.js +67 -0
  59. package/client/src/hooks/usePanelState.js +13 -0
  60. package/client/src/hooks/useProviderSelection.js +70 -0
  61. package/client/src/hooks/useRepoBranchesModels.js +218 -0
  62. package/client/src/hooks/useRepoStatus.js +350 -0
  63. package/client/src/hooks/useRpcLogActions.js +19 -0
  64. package/client/src/hooks/useRpcLogView.js +58 -0
  65. package/client/src/hooks/useSessionHandoff.js +97 -0
  66. package/client/src/hooks/useSessionLifecycle.js +287 -0
  67. package/client/src/hooks/useSessionReset.js +63 -0
  68. package/client/src/hooks/useSessionResync.js +77 -0
  69. package/client/src/hooks/useTerminalSession.js +328 -0
  70. package/client/src/hooks/useToolbarExport.js +27 -0
  71. package/client/src/hooks/useTurnInterrupt.js +43 -0
  72. package/client/src/hooks/useVibe80Forms.js +128 -0
  73. package/client/src/hooks/useWorkspaceAuth.js +932 -0
  74. package/client/src/hooks/useWorktreeCloseConfirm.js +46 -0
  75. package/client/src/hooks/useWorktrees.js +396 -0
  76. package/client/src/i18n.jsx +87 -0
  77. package/client/src/index.css +5147 -0
  78. package/client/src/locales/en.json +37 -0
  79. package/client/src/locales/fr.json +321 -0
  80. package/client/src/main.jsx +16 -0
  81. package/client/vite.config.js +62 -0
  82. package/docs/api/asyncapi.json +1511 -0
  83. package/docs/api/openapi.json +3242 -0
  84. package/git_hooks/prepare-commit-msg +35 -0
  85. package/package.json +36 -0
  86. package/server/package.json +29 -0
  87. package/server/scripts/rotate-workspace-secret.js +101 -0
  88. package/server/src/claudeClient.js +454 -0
  89. package/server/src/clientEvents.js +594 -0
  90. package/server/src/clientFactory.js +164 -0
  91. package/server/src/codexClient.js +468 -0
  92. package/server/src/config.js +27 -0
  93. package/server/src/helpers.js +138 -0
  94. package/server/src/index.js +1641 -0
  95. package/server/src/middleware/auth.js +93 -0
  96. package/server/src/middleware/debug.js +89 -0
  97. package/server/src/middleware/errorTypes.js +60 -0
  98. package/server/src/providerLogger.js +60 -0
  99. package/server/src/routes/files.js +114 -0
  100. package/server/src/routes/git.js +183 -0
  101. package/server/src/routes/health.js +13 -0
  102. package/server/src/routes/sessions.js +407 -0
  103. package/server/src/routes/workspaces.js +296 -0
  104. package/server/src/routes/worktrees.js +993 -0
  105. package/server/src/runAs.js +458 -0
  106. package/server/src/runtimeStore.js +32 -0
  107. package/server/src/services/auth.js +157 -0
  108. package/server/src/services/claudeThreadDirectory.js +33 -0
  109. package/server/src/services/session.js +918 -0
  110. package/server/src/services/workspace.js +858 -0
  111. package/server/src/storage/index.js +17 -0
  112. package/server/src/storage/redis.js +412 -0
  113. package/server/src/storage/sqlite.js +649 -0
  114. package/server/src/worktreeManager.js +717 -0
  115. package/server/tests/README.md +13 -0
  116. package/server/tests/factories/workspaceFactory.js +13 -0
  117. package/server/tests/fixtures/workspaceCredentials.json +4 -0
  118. package/server/tests/integration/routes/workspaces-routes.test.js +626 -0
  119. package/server/tests/setup/env.js +9 -0
  120. package/server/tests/unit/helpers.test.js +95 -0
  121. package/server/tests/unit/services/auth.test.js +181 -0
  122. package/server/tests/unit/services/workspace.test.js +115 -0
  123. package/server/vitest.config.js +23 -0
@@ -0,0 +1,212 @@
1
+ import React from "react";
2
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3
+ import { faArrowLeft } from "@fortawesome/free-solid-svg-icons";
4
+
5
+ export default function SettingsPanel({
6
+ t,
7
+ activePane,
8
+ handleSettingsBack,
9
+ language,
10
+ setLanguage,
11
+ showChatCommands,
12
+ setShowChatCommands,
13
+ showToolResults,
14
+ setShowToolResults,
15
+ notificationsEnabled,
16
+ setNotificationsEnabled,
17
+ themeMode,
18
+ setThemeMode,
19
+ gitIdentityName,
20
+ setGitIdentityName,
21
+ gitIdentityEmail,
22
+ setGitIdentityEmail,
23
+ gitIdentityGlobal,
24
+ gitIdentityRepo,
25
+ gitIdentityLoading,
26
+ gitIdentitySaving,
27
+ gitIdentityError,
28
+ gitIdentityMessage,
29
+ handleSaveGitIdentity,
30
+ attachmentSession,
31
+ }) {
32
+ return (
33
+ <div className={`settings-panel ${activePane === "settings" ? "" : "is-hidden"}`}>
34
+ <div className="settings-header">
35
+ <button
36
+ type="button"
37
+ className="settings-back icon-button"
38
+ onClick={handleSettingsBack}
39
+ aria-label={t("Back to previous view")}
40
+ title={t("Back")}
41
+ >
42
+ <span aria-hidden="true">
43
+ <FontAwesomeIcon icon={faArrowLeft} />
44
+ </span>
45
+ </button>
46
+ <div className="settings-heading">
47
+ <div className="settings-title">{t("User settings")}</div>
48
+ <div className="settings-subtitle">
49
+ {t("These settings are stored in your browser.")}
50
+ </div>
51
+ </div>
52
+ </div>
53
+ <div className="settings-group">
54
+ <label className="settings-item">
55
+ <span className="settings-text">
56
+ <span className="settings-name">{t("Language")}</span>
57
+ <span className="settings-hint">{t("Select a language")}</span>
58
+ </span>
59
+ <select
60
+ className="settings-select"
61
+ value={language}
62
+ onChange={(event) => setLanguage(event.target.value)}
63
+ >
64
+ <option value="fr">{t("French")}</option>
65
+ <option value="en">{t("English")}</option>
66
+ </select>
67
+ </label>
68
+ <label className="settings-item">
69
+ <span className="settings-text">
70
+ <span className="settings-name">{t("Show commands in chat")}</span>
71
+ <span className="settings-hint">
72
+ {t("Show executed command blocks in the conversation.")}
73
+ </span>
74
+ </span>
75
+ <input
76
+ type="checkbox"
77
+ className="settings-toggle"
78
+ checked={showChatCommands}
79
+ onChange={(event) => setShowChatCommands(event.target.checked)}
80
+ />
81
+ </label>
82
+ <label className="settings-item">
83
+ <span className="settings-text">
84
+ <span className="settings-name">{t("Show tool results in chat")}</span>
85
+ <span className="settings-hint">
86
+ {t("Show tool_result blocks in the conversation.")}
87
+ </span>
88
+ </span>
89
+ <input
90
+ type="checkbox"
91
+ className="settings-toggle"
92
+ checked={showToolResults}
93
+ onChange={(event) => setShowToolResults(event.target.checked)}
94
+ />
95
+ </label>
96
+ <label className="settings-item">
97
+ <span className="settings-text">
98
+ <span className="settings-name">{t("Notifications")}</span>
99
+ <span className="settings-hint">
100
+ {t("Show a notification and sound when a new message arrives.")}
101
+ </span>
102
+ </span>
103
+ <input
104
+ type="checkbox"
105
+ className="settings-toggle"
106
+ checked={notificationsEnabled}
107
+ onChange={(event) => setNotificationsEnabled(event.target.checked)}
108
+ />
109
+ </label>
110
+ <label className="settings-item">
111
+ <span className="settings-text">
112
+ <span className="settings-name">{t("Dark mode")}</span>
113
+ <span className="settings-hint">
114
+ {t("Enable the dark theme for the interface.")}
115
+ </span>
116
+ </span>
117
+ <input
118
+ type="checkbox"
119
+ className="settings-toggle"
120
+ checked={themeMode === "dark"}
121
+ onChange={(event) =>
122
+ setThemeMode(event.target.checked ? "dark" : "light")
123
+ }
124
+ />
125
+ </label>
126
+ </div>
127
+ <div className="settings-group">
128
+ <div className="settings-item settings-item--stacked">
129
+ <div className="settings-text">
130
+ <span className="settings-name">
131
+ {t("Git identity for this repository")}
132
+ </span>
133
+ <span className="settings-hint">
134
+ {t("Provide user.name and user.email for repository commits.")}
135
+ </span>
136
+ <span className="settings-hint">
137
+ {t("Global values: {{name}} / {{email}}.", {
138
+ name: gitIdentityGlobal.name || t("Not set"),
139
+ email: gitIdentityGlobal.email || t("Not set"),
140
+ })}
141
+ </span>
142
+ <span className="settings-hint">
143
+ {gitIdentityRepo.name || gitIdentityRepo.email
144
+ ? t("Repository values: {{name}} / {{email}}.", {
145
+ name: gitIdentityRepo.name || t("Not set"),
146
+ email: gitIdentityRepo.email || t("Not set"),
147
+ })
148
+ : t("No repository-specific values.")}
149
+ </span>
150
+ </div>
151
+ <div className="settings-fields">
152
+ <label className="settings-field">
153
+ <span className="settings-field-label">{t("user.name")}</span>
154
+ <input
155
+ type="text"
156
+ className="settings-input"
157
+ value={gitIdentityName}
158
+ onChange={(event) => setGitIdentityName(event.target.value)}
159
+ placeholder={gitIdentityGlobal.name || t("Full name")}
160
+ disabled={
161
+ gitIdentityLoading ||
162
+ gitIdentitySaving ||
163
+ !attachmentSession?.sessionId
164
+ }
165
+ />
166
+ </label>
167
+ <label className="settings-field">
168
+ <span className="settings-field-label">{t("user.email")}</span>
169
+ <input
170
+ type="email"
171
+ className="settings-input"
172
+ value={gitIdentityEmail}
173
+ onChange={(event) => setGitIdentityEmail(event.target.value)}
174
+ placeholder={
175
+ gitIdentityGlobal.email || t("your.email@example.com")
176
+ }
177
+ disabled={
178
+ gitIdentityLoading ||
179
+ gitIdentitySaving ||
180
+ !attachmentSession?.sessionId
181
+ }
182
+ />
183
+ </label>
184
+ </div>
185
+ <div className="settings-actions">
186
+ <button
187
+ type="button"
188
+ className="settings-button"
189
+ onClick={handleSaveGitIdentity}
190
+ disabled={
191
+ gitIdentityLoading ||
192
+ gitIdentitySaving ||
193
+ !attachmentSession?.sessionId
194
+ }
195
+ >
196
+ {gitIdentitySaving ? t("Saving...") : t("Save")}
197
+ </button>
198
+ {gitIdentityLoading ? (
199
+ <span className="settings-status">{t("Loading...")}</span>
200
+ ) : null}
201
+ {gitIdentityError ? (
202
+ <span className="settings-status is-error">{gitIdentityError}</span>
203
+ ) : null}
204
+ {gitIdentityMessage ? (
205
+ <span className="settings-status">{gitIdentityMessage}</span>
206
+ ) : null}
207
+ </div>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ );
212
+ }
@@ -0,0 +1,39 @@
1
+ import React from "react";
2
+
3
+ export default function TerminalPanel({
4
+ t,
5
+ terminalEnabled,
6
+ activePane,
7
+ repoName,
8
+ activeWorktree,
9
+ isInWorktree,
10
+ terminalContainerRef,
11
+ attachmentSession,
12
+ }) {
13
+ if (!terminalEnabled) {
14
+ return null;
15
+ }
16
+
17
+ return (
18
+ <div
19
+ className={`terminal-panel ${activePane === "terminal" ? "" : "is-hidden"}`}
20
+ >
21
+ <div className="terminal-header">
22
+ <div className="terminal-title">{t("Terminal")}</div>
23
+ {(repoName || activeWorktree?.branchName || activeWorktree?.name) && (
24
+ <div className="terminal-meta">
25
+ {isInWorktree
26
+ ? activeWorktree?.branchName || activeWorktree?.name
27
+ : repoName}
28
+ </div>
29
+ )}
30
+ </div>
31
+ <div className="terminal-body" ref={terminalContainerRef} />
32
+ {!attachmentSession?.sessionId && (
33
+ <div className="terminal-empty">
34
+ {t("Start a session to open the terminal.")}
35
+ </div>
36
+ )}
37
+ </div>
38
+ );
39
+ }
@@ -0,0 +1,101 @@
1
+ import React from "react";
2
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3
+ import { faGear, faQrcode, faRightFromBracket } from "@fortawesome/free-solid-svg-icons";
4
+ import WorktreeTabs from "../WorktreeTabs.jsx";
5
+
6
+ export default function Topbar({
7
+ t,
8
+ brandLogo,
9
+ allTabs,
10
+ activeWorktreeId,
11
+ handleSelectWorktree,
12
+ createWorktree,
13
+ openCloseConfirm,
14
+ renameWorktreeHandler,
15
+ llmProvider,
16
+ availableProviders,
17
+ branches,
18
+ defaultBranch,
19
+ currentBranch,
20
+ branchLoading,
21
+ branchError,
22
+ defaultInternetAccess,
23
+ defaultDenyGitCredentialsAccess,
24
+ deploymentMode,
25
+ loadBranches,
26
+ providerModelState,
27
+ loadProviderModels,
28
+ connected,
29
+ isMobileLayout,
30
+ requestHandoffQr,
31
+ attachmentSession,
32
+ handoffLoading,
33
+ handleOpenSettings,
34
+ handleLeaveSession,
35
+ }) {
36
+ return (
37
+ <header className="header">
38
+ <div className="topbar-left">
39
+ <div className="topbar-spacer" />
40
+ <div className="topbar-brand">
41
+ <img className="brand-logo" src={brandLogo} alt="vibe80" />
42
+ </div>
43
+ <div className="topbar-tabs">
44
+ <WorktreeTabs
45
+ worktrees={allTabs}
46
+ activeWorktreeId={activeWorktreeId}
47
+ onSelect={handleSelectWorktree}
48
+ onCreate={createWorktree}
49
+ onClose={openCloseConfirm}
50
+ onRename={renameWorktreeHandler}
51
+ provider={llmProvider}
52
+ providers={
53
+ availableProviders.length ? availableProviders : [llmProvider]
54
+ }
55
+ branches={branches}
56
+ defaultBranch={defaultBranch || currentBranch}
57
+ branchLoading={branchLoading}
58
+ branchError={branchError}
59
+ defaultInternetAccess={defaultInternetAccess}
60
+ defaultDenyGitCredentialsAccess={defaultDenyGitCredentialsAccess}
61
+ deploymentMode={deploymentMode}
62
+ onRefreshBranches={loadBranches}
63
+ providerModelState={providerModelState}
64
+ onRequestProviderModels={loadProviderModels}
65
+ disabled={!connected}
66
+ isMobile={isMobileLayout}
67
+ />
68
+ </div>
69
+ </div>
70
+
71
+ <div className="topbar-right">
72
+ <button
73
+ type="button"
74
+ className="icon-button"
75
+ aria-label={t("Resume on mobile")}
76
+ title={t("Resume on mobile")}
77
+ onClick={requestHandoffQr}
78
+ disabled={!attachmentSession?.sessionId || handoffLoading}
79
+ >
80
+ <FontAwesomeIcon icon={faQrcode} />
81
+ </button>
82
+ <button
83
+ type="button"
84
+ className="icon-button"
85
+ aria-label={t("Open settings")}
86
+ onClick={handleOpenSettings}
87
+ >
88
+ <FontAwesomeIcon icon={faGear} />
89
+ </button>
90
+ <button
91
+ type="button"
92
+ className="icon-button"
93
+ aria-label={t("Leave session")}
94
+ onClick={handleLeaveSession}
95
+ >
96
+ <FontAwesomeIcon icon={faRightFromBracket} />
97
+ </button>
98
+ </div>
99
+ </header>
100
+ );
101
+ }