Conversation
… crash on missing fields
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR adds WhatsApp session integration to the LogLife dashboard, allowing users to link their WhatsApp accounts and view session statistics including token usage, chat metadata, and activity status. Major Changes:
Critical Issues:
Other Issues:
Confidence Score: 1/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant Account as Account Page
participant Clerk
participant Dashboard
participant API as /api/sessions
participant FS as File System
User->>Account: Enter WhatsApp Session ID
Account->>Account: Validate UUID format
Account->>Clerk: Update user.unsafeMetadata
Clerk-->>Account: Success
Account-->>User: "Session linked successfully"
User->>Dashboard: Navigate to Dashboard
Dashboard->>Clerk: Get user.unsafeMetadata
Clerk-->>Dashboard: whatsappSessionId
Dashboard->>API: GET /api/sessions?sessionId={id}
Note over API: ⚠️ No auth check!
API->>FS: Read /home/ali/.openclaw/.../sessions.json
FS-->>API: Session data
API-->>Dashboard: Session stats (tokens, model, status)
Dashboard-->>User: Display session data & visualizations
Last reviewed commit: 009c4af |
website/app/api/sessions/route.ts
Outdated
|
|
||
| try { | ||
| // const filePath = join(process.cwd(), "..", "sessions.json"); | ||
| const filePath = join("/home/ali/.openclaw/agents/main/sessions", "sessions.json"); |
There was a problem hiding this comment.
Hardcoded absolute path /home/ali/.openclaw/agents/main/sessions exposes system username and creates deployment issues.
| const filePath = join("/home/ali/.openclaw/agents/main/sessions", "sessions.json"); | |
| const filePath = join(process.cwd(), "sessions.json"); |
| export async function GET(req: NextRequest) { | ||
| const sessionId = req.nextUrl.searchParams.get("sessionId"); | ||
| const key = req.nextUrl.searchParams.get("key"); | ||
|
|
||
| if (!sessionId && !key) { | ||
| return NextResponse.json({ error: "Provide ?sessionId= or ?key=" }, { status: 400 }); | ||
| } | ||
|
|
||
| try { | ||
| // const filePath = join(process.cwd(), "..", "sessions.json"); | ||
| const filePath = join("/home/ali/.openclaw/agents/main/sessions", "sessions.json"); | ||
| const raw = await readFile(filePath, "utf-8"); | ||
| const sessions: Record<string, Record<string, unknown>> = JSON.parse(raw); | ||
|
|
||
| let session: Record<string, unknown> | undefined; | ||
| let matchedKey = key || ""; | ||
|
|
||
| if (key) { | ||
| session = sessions[key]; | ||
| } else if (sessionId) { | ||
| for (const [k, v] of Object.entries(sessions)) { | ||
| if (v.sessionId === sessionId) { | ||
| session = v; | ||
| matchedKey = k; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (!session) { | ||
| return NextResponse.json({ error: "Session not found" }, { status: 404 }); | ||
| } | ||
|
|
||
| const origin = session.origin as Record<string, string> | undefined; | ||
| const delivery = session.deliveryContext as Record<string, string> | undefined; | ||
|
|
||
| return NextResponse.json({ | ||
| sessionKey: matchedKey, | ||
| sessionId: session.sessionId ?? "", | ||
| updatedAt: session.updatedAt ?? 0, | ||
| abortedLastRun: session.abortedLastRun ?? false, | ||
| chatType: session.chatType ?? origin?.chatType ?? "unknown", | ||
| lastChannel: session.lastChannel ?? delivery?.channel ?? "unknown", | ||
| origin: { | ||
| label: origin?.label ?? "Unknown", | ||
| from: origin?.from ?? "", | ||
| to: origin?.to ?? "", | ||
| }, | ||
| deliveryContext: { | ||
| channel: delivery?.channel ?? "unknown", | ||
| to: delivery?.to ?? "", | ||
| }, | ||
| compactionCount: session.compactionCount ?? 0, | ||
| inputTokens: session.inputTokens ?? 0, | ||
| outputTokens: session.outputTokens ?? 0, | ||
| totalTokens: session.totalTokens ?? 0, | ||
| model: session.model ?? "unknown", | ||
| }); | ||
| } catch { | ||
| return NextResponse.json({ error: "Failed to read sessions" }, { status: 500 }); | ||
| } | ||
| } |
There was a problem hiding this comment.
No authentication check - anyone can access session data by guessing session IDs or keys. This endpoint exposes sensitive user session information including phone numbers (from, to), token usage, and session metadata without verifying the requester is authorized.
Add authentication middleware:
import { auth } from "@clerk/nextjs";
export async function GET(req: NextRequest) {
const { userId } = auth();
if (!userId) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
// Then verify the requested session belongs to this user
// by checking user.unsafeMetadata.whatsappSessionId matches
website/app/dashboard/page.tsx
Outdated
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| useEffect(() => { fetchSession(); }, [whatsappSessionId]); |
There was a problem hiding this comment.
Missing fetchSession in the dependency array will cause the linter warning. Since you're disabling the exhaustive-deps rule, this useEffect will only run when whatsappSessionId changes, but won't pick up changes to fetchSession if it were to be redefined.
| // eslint-disable-next-line react-hooks/exhaustive-deps | |
| useEffect(() => { fetchSession(); }, [whatsappSessionId]); | |
| useEffect(() => { fetchSession(); }, [whatsappSessionId, fetchSession]); |
website/app/dashboard/page.tsx
Outdated
| fetch(`/api/sessions?sessionId=${encodeURIComponent(whatsappSessionId)}`) | ||
| .then((res) => res.json()) | ||
| .then((data) => { if (!data.error) setSession(data); else setSession(null); }) | ||
| .catch(() => { setSession(null); }) | ||
| .finally(() => { setSessionLoading(false); setRefreshing(false); }); |
There was a problem hiding this comment.
Fetch error responses are silently ignored, making debugging difficult for users when the API fails.
Consider logging errors or showing a user-friendly error state:
.catch((err) => {
console.error('Failed to fetch session:', err);
setSession(null);
})Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| const handleWhatsAppDisconnect = async () => { | ||
| try { | ||
| await user!.update({ | ||
| unsafeMetadata: { ...user!.unsafeMetadata, whatsappSessionId: undefined }, | ||
| }); | ||
| } catch { | ||
| // silently fail | ||
| } | ||
| }; |
There was a problem hiding this comment.
Setting whatsappSessionId to undefined doesn't remove the key from unsafeMetadata, it sets it to undefined. To actually remove it, you should omit the key entirely or set it to null, and provide user feedback.
const handleWhatsAppDisconnect = async () => {
try {
const { whatsappSessionId, ...rest } = user!.unsafeMetadata as Record<string, unknown>;
await user!.update({ unsafeMetadata: rest });
setWhatsAppMessage({ type: "success", text: "WhatsApp disconnected successfully!" });
} catch {
setWhatsAppMessage({ type: "error", text: "Failed to disconnect. Please try again." });
}
};There was a problem hiding this comment.
Yes, I'm here! How can I help you with this code?
Additional Comments (1)
Then keep the trim only in the submit handler (line 130). |
Rewrite README and plugin/README with end-to-end setup instructions (OpenClaw install, plugin linking, API key, website .env). Fix OpenClaw GitHub URL. Make apiKey optional in plugin schema so install succeeds before configuration. Rename plugin package to match manifest ID. Co-authored-by: Cursor <cursoragent@cursor.com>
Included a new "self-hosting" page in the documentation and updated the index layout to feature both "Quickstart" and "Self-hosting" cards for improved user navigation.
Introduced a new documentation page titled "OpenClaw tricks" that provides useful tips for managing OpenClaw instances, including instructions for password-protecting the web UI with Nginx. Updated the index to include the new section for improved navigation.
- Changed the deployment step name to "Deploy plugin and restart gateway" for clarity. - Added health checks to the deployment process to verify plugin functionality after restart. - Updated the development documentation to reflect the new local setup instructions and API endpoint details. - Removed outdated AI tools documentation and unnecessary sections to streamline content. - Revised the API reference to include new endpoints for session management and verification.
… numbers for OpenClaw bot functionality
…dashboard or hero section
- Introduced a new "Networking" guide detailing reverse proxy setup with Caddy for HTTPS and access control. - Updated development documentation to clarify CI/CD requirements and environment variables. - Added a new automated setup script to streamline the installation and configuration process for the LogLife plugin. - Included additional security measures in the documentation, emphasizing HTTPS and layered authentication for the Control UI.
- Introduced a new declaration file to provide type definitions for the OpenClaw plugin SDK. - This allows TypeScript compilation in CI environments without requiring the OpenClaw runtime. - Updated package.json to remove unnecessary dependencies.
- Simplified the update process for user metadata by removing the whatsappPhone property directly. - Improved error handling by replacing silent failure with an alert message for better user feedback.
No description provided.