botschat 0.1.4 → 0.1.6
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/README.md +2 -2
- package/package.json +4 -1
- package/packages/api/package.json +2 -1
- package/packages/api/src/do/connection-do.ts +128 -33
- package/packages/api/src/index.ts +103 -6
- package/packages/api/src/routes/auth.ts +123 -29
- package/packages/api/src/routes/pairing.ts +14 -1
- package/packages/api/src/routes/setup.ts +70 -24
- package/packages/api/src/routes/upload.ts +12 -8
- package/packages/api/src/utils/auth.ts +212 -43
- package/packages/api/src/utils/id.ts +30 -14
- package/packages/api/src/utils/rate-limit.ts +73 -0
- package/packages/plugin/dist/src/channel.js +9 -3
- package/packages/plugin/dist/src/channel.js.map +1 -1
- package/packages/plugin/package.json +2 -2
- package/packages/web/dist/assets/{index-DuGeoFJT.css → index-BST9bfvT.css} +1 -1
- package/packages/web/dist/assets/index-Da18EnTa.js +851 -0
- package/packages/web/dist/botschat-icon.svg +4 -0
- package/packages/web/dist/index.html +23 -3
- package/packages/web/dist/manifest.json +24 -0
- package/packages/web/dist/sw.js +40 -0
- package/packages/web/index.html +21 -1
- package/packages/web/src/App.tsx +241 -96
- package/packages/web/src/api.ts +63 -3
- package/packages/web/src/components/ChatWindow.tsx +11 -11
- package/packages/web/src/components/ConnectionSettings.tsx +475 -0
- package/packages/web/src/components/CronDetail.tsx +475 -235
- package/packages/web/src/components/CronSidebar.tsx +1 -1
- package/packages/web/src/components/DebugLogPanel.tsx +116 -3
- package/packages/web/src/components/IconRail.tsx +56 -16
- package/packages/web/src/components/JobList.tsx +2 -6
- package/packages/web/src/components/LoginPage.tsx +126 -103
- package/packages/web/src/components/MobileLayout.tsx +480 -0
- package/packages/web/src/components/OnboardingPage.tsx +7 -16
- package/packages/web/src/components/ResizeHandle.tsx +34 -0
- package/packages/web/src/components/Sidebar.tsx +1 -1
- package/packages/web/src/components/TaskBar.tsx +2 -2
- package/packages/web/src/components/ThreadPanel.tsx +2 -5
- package/packages/web/src/hooks/useIsMobile.ts +27 -0
- package/packages/web/src/index.css +59 -0
- package/packages/web/src/main.tsx +9 -0
- package/packages/web/src/store.ts +12 -5
- package/packages/web/src/ws.ts +2 -0
- package/scripts/dev.sh +13 -13
- package/wrangler.toml +3 -1
- package/packages/web/dist/assets/index-DyzTR_Y4.js +0 -847
|
@@ -75,6 +75,12 @@
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/* ========== Base styles ========== */
|
|
78
|
+
html, body {
|
|
79
|
+
/* App manages its own scroll containers; root elements should not scroll */
|
|
80
|
+
overflow: hidden;
|
|
81
|
+
height: 100%;
|
|
82
|
+
}
|
|
83
|
+
|
|
78
84
|
body {
|
|
79
85
|
margin: 0;
|
|
80
86
|
font-family: var(--font-sans);
|
|
@@ -158,6 +164,22 @@ code:not(pre code) {
|
|
|
158
164
|
.no-scrollbar::-webkit-scrollbar { display: none; }
|
|
159
165
|
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
|
|
160
166
|
|
|
167
|
+
/* ========== Resize handles ========== */
|
|
168
|
+
/* Active state (dragging) — react-resizable-panels v4 uses data-separator + data-state */
|
|
169
|
+
[data-state="dragging"] .resize-handle-line,
|
|
170
|
+
.resize-handle:hover .resize-handle-line {
|
|
171
|
+
background: var(--text-link) !important;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
[data-state="dragging"] .resize-handle-line {
|
|
175
|
+
width: 3px !important;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* Vertical handles */
|
|
179
|
+
[data-state="dragging"].resize-handle .resize-handle-line[class*="h-"] {
|
|
180
|
+
height: 3px !important;
|
|
181
|
+
}
|
|
182
|
+
|
|
161
183
|
/* Focus visible */
|
|
162
184
|
*:focus-visible {
|
|
163
185
|
outline: 2px solid var(--bg-active);
|
|
@@ -168,3 +190,40 @@ code:not(pre code) {
|
|
|
168
190
|
body, .theme-transition {
|
|
169
191
|
transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
|
170
192
|
}
|
|
193
|
+
|
|
194
|
+
/* ========== Mobile-specific ========== */
|
|
195
|
+
@media (max-width: 767px) {
|
|
196
|
+
/* Prevent iOS rubber-band bounce on main container */
|
|
197
|
+
html, body {
|
|
198
|
+
overscroll-behavior: none;
|
|
199
|
+
-webkit-overflow-scrolling: touch;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Full-height on mobile (accounts for address bar) */
|
|
203
|
+
html {
|
|
204
|
+
height: -webkit-fill-available;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
body {
|
|
208
|
+
min-height: -webkit-fill-available;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* Mobile screen transition */
|
|
213
|
+
.mobile-screen-enter {
|
|
214
|
+
animation: slideInRight 0.2s ease-out;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.mobile-screen-exit {
|
|
218
|
+
animation: slideOutRight 0.2s ease-in;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@keyframes slideInRight {
|
|
222
|
+
from { transform: translateX(30%); opacity: 0; }
|
|
223
|
+
to { transform: translateX(0); opacity: 1; }
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
@keyframes slideOutRight {
|
|
227
|
+
from { transform: translateX(0); opacity: 1; }
|
|
228
|
+
to { transform: translateX(30%); opacity: 0; }
|
|
229
|
+
}
|
|
@@ -8,3 +8,12 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
|
8
8
|
<App />
|
|
9
9
|
</React.StrictMode>,
|
|
10
10
|
);
|
|
11
|
+
|
|
12
|
+
// Register service worker for PWA support (standalone mode on mobile)
|
|
13
|
+
if ("serviceWorker" in navigator) {
|
|
14
|
+
window.addEventListener("load", () => {
|
|
15
|
+
navigator.serviceWorker.register("/sw.js").catch(() => {
|
|
16
|
+
// SW registration failed — non-critical, app still works
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -155,15 +155,22 @@ export function appReducer(state: AppState, action: AppAction): AppState {
|
|
|
155
155
|
return { ...state, selectedChannelId: action.channelId, sessions: [], selectedSessionId: null, tasks: [], selectedTaskId: null, jobs: [], selectedJobId: null, messages: [] };
|
|
156
156
|
case "SET_SESSIONS":
|
|
157
157
|
return { ...state, sessions: action.sessions };
|
|
158
|
-
case "SELECT_SESSION":
|
|
158
|
+
case "SELECT_SESSION": {
|
|
159
|
+
const nextSessionKey = action.sessionKey ?? state.selectedSessionKey;
|
|
160
|
+
const sessionChanged = nextSessionKey !== state.selectedSessionKey;
|
|
159
161
|
return {
|
|
160
162
|
...state,
|
|
161
163
|
selectedSessionId: action.sessionId,
|
|
162
|
-
selectedSessionKey:
|
|
163
|
-
messages
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
selectedSessionKey: nextSessionKey,
|
|
165
|
+
// Only clear messages when the session actually changes;
|
|
166
|
+
// otherwise keep whatever was already loaded to avoid the
|
|
167
|
+
// race where SELECT_SESSION arrives *after* SET_MESSAGES
|
|
168
|
+
// (e.g. session-list API returns after message-list API).
|
|
169
|
+
messages: sessionChanged ? [] : state.messages,
|
|
170
|
+
activeThreadId: sessionChanged ? null : state.activeThreadId,
|
|
171
|
+
threadMessages: sessionChanged ? [] : state.threadMessages,
|
|
166
172
|
};
|
|
173
|
+
}
|
|
167
174
|
case "ADD_SESSION":
|
|
168
175
|
return { ...state, sessions: [...state.sessions, action.session] };
|
|
169
176
|
case "REMOVE_SESSION":
|
package/packages/web/src/ws.ts
CHANGED
|
@@ -31,6 +31,8 @@ export class BotsChatWSClient {
|
|
|
31
31
|
connect(): void {
|
|
32
32
|
this.intentionalClose = false;
|
|
33
33
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
34
|
+
// Token is NOT included in the URL to avoid leaking it in logs/history.
|
|
35
|
+
// Authentication is handled via the "auth" message after connection.
|
|
34
36
|
const url = `${protocol}//${window.location.host}/api/ws/${this.opts.userId}/${this.opts.sessionId}`;
|
|
35
37
|
|
|
36
38
|
dlog.info("WS", `Connecting to ${url}`);
|
package/scripts/dev.sh
CHANGED
|
@@ -54,11 +54,11 @@ do_build_web() {
|
|
|
54
54
|
do_start() {
|
|
55
55
|
kill_port 8787
|
|
56
56
|
info "Starting wrangler dev on 0.0.0.0:8787…"
|
|
57
|
-
exec npx wrangler dev --config wrangler.toml --ip 0.0.0.0
|
|
57
|
+
exec npx wrangler dev --config wrangler.toml --ip 0.0.0.0 --var ENVIRONMENT:development
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
do_sync_plugin() {
|
|
61
|
-
local REMOTE="
|
|
61
|
+
local REMOTE="mini.local"
|
|
62
62
|
local REMOTE_DIR="~/Projects/botsChat/packages/plugin"
|
|
63
63
|
|
|
64
64
|
info "Syncing plugin to $REMOTE…"
|
|
@@ -66,20 +66,20 @@ do_sync_plugin() {
|
|
|
66
66
|
packages/plugin/ "$REMOTE:$REMOTE_DIR/"
|
|
67
67
|
ok "Plugin files synced"
|
|
68
68
|
|
|
69
|
-
info "Building plugin
|
|
70
|
-
ssh "$REMOTE" "
|
|
71
|
-
export PATH="/opt/homebrew/bin:$PATH"
|
|
69
|
+
info "Building plugin, deploying to extensions, restarting gateway on mini.local…"
|
|
70
|
+
ssh "$REMOTE" 'export PATH="/opt/homebrew/bin:$PATH"
|
|
72
71
|
cd ~/Projects/botsChat/packages/plugin
|
|
73
72
|
npm run build
|
|
74
|
-
|
|
73
|
+
EXT_DIR=~/.openclaw/extensions/botschat
|
|
74
|
+
rsync -av --delete dist/ "$EXT_DIR/dist/"
|
|
75
|
+
rsync -av bin/ "$EXT_DIR/bin/" 2>/dev/null || true
|
|
76
|
+
cp -f package.json openclaw.plugin.json "$EXT_DIR/" 2>/dev/null || true
|
|
77
|
+
echo "--- Deployed to $EXT_DIR ---"
|
|
75
78
|
pkill -9 -f openclaw-gateway 2>/dev/null || true
|
|
76
79
|
sleep 3
|
|
77
|
-
nohup openclaw gateway run --bind loopback --port 18789 --force
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
REMOTE_SCRIPT
|
|
81
|
-
)"
|
|
82
|
-
ok "Plugin synced and gateway restarted"
|
|
80
|
+
nohup openclaw gateway run --bind loopback --port 18789 --force > /tmp/openclaw-gateway.log 2>&1 &
|
|
81
|
+
echo "Gateway restarted (PID=$!)"'
|
|
82
|
+
ok "Plugin synced, deployed to extensions, gateway restarted"
|
|
83
83
|
|
|
84
84
|
sleep 4
|
|
85
85
|
info "Checking connection…"
|
|
@@ -88,7 +88,7 @@ REMOTE_SCRIPT
|
|
|
88
88
|
|
|
89
89
|
do_logs() {
|
|
90
90
|
info "Tailing gateway logs on mini.local…"
|
|
91
|
-
ssh
|
|
91
|
+
ssh mini.local 'tail -f /tmp/openclaw-gateway.log'
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
# ── Main ─────────────────────────────────────────────────────────────
|
package/wrangler.toml
CHANGED
|
@@ -33,9 +33,11 @@ new_sqlite_classes = ["ConnectionDO"]
|
|
|
33
33
|
|
|
34
34
|
# --- Environment Variables ---
|
|
35
35
|
[vars]
|
|
36
|
-
ENVIRONMENT = "
|
|
36
|
+
ENVIRONMENT = "production"
|
|
37
37
|
# Firebase project ID for Google/GitHub Sign-In token verification.
|
|
38
38
|
FIREBASE_PROJECT_ID = "botschat-130ff"
|
|
39
|
+
# IMPORTANT: For production, set JWT_SECRET via `wrangler secret put JWT_SECRET`.
|
|
40
|
+
# The app will refuse to start in non-development mode without it.
|
|
39
41
|
|
|
40
42
|
# --- Dev settings ---
|
|
41
43
|
[dev]
|