mirror of
https://github.com/JohnRiceML/clawport-ui.git
synced 2026-08-14 00:47:50 +00:00
Fix crypto.randomUUID runtime error, add logo as default sidebar icon
Replace all crypto.randomUUID() calls with generateId() helper that falls back to a Math.random-based UUID in non-secure contexts (HTTP, older browsers). Fixes #1. Also sets the ClawPort logo as the default sidebar icon in place of the lobster emoji. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
6e6d99507a
commit
95a7bdf26f
@@ -109,23 +109,16 @@ export function MobileSidebar({
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<span
|
||||
<img
|
||||
src="/clawport-logo.png"
|
||||
alt=""
|
||||
style={{
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
borderRadius: '6px',
|
||||
background: settings.accentColor
|
||||
? `linear-gradient(135deg, ${settings.accentColor}, ${settings.accentColor}dd)`
|
||||
: 'transparent',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontSize: '13px',
|
||||
width: '48px',
|
||||
height: '48px',
|
||||
objectFit: 'contain',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
{settings.portalEmoji ?? '\ud83e\udd9e'}
|
||||
</span>
|
||||
/>
|
||||
)}
|
||||
<span
|
||||
style={{
|
||||
@@ -198,24 +191,16 @@ export function MobileSidebar({
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
<img
|
||||
src="/clawport-logo.png"
|
||||
alt=""
|
||||
style={{
|
||||
width: '36px',
|
||||
height: '36px',
|
||||
borderRadius: '10px',
|
||||
background: settings.accentColor
|
||||
? `linear-gradient(135deg, ${settings.accentColor}, ${settings.accentColor}dd)`
|
||||
: 'transparent',
|
||||
boxShadow: 'var(--shadow-card)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontSize: '18px',
|
||||
width: '72px',
|
||||
height: '72px',
|
||||
objectFit: 'contain',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
{settings.portalEmoji ?? '\ud83e\udd9e'}
|
||||
</div>
|
||||
/>
|
||||
)}
|
||||
<div>
|
||||
<div
|
||||
|
||||
+7
-17
@@ -51,26 +51,16 @@ export function Sidebar() {
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
<img
|
||||
src="/clawport-logo.png"
|
||||
alt=""
|
||||
style={{
|
||||
width: '36px',
|
||||
height: '36px',
|
||||
borderRadius: '10px',
|
||||
background: settings.iconBgHidden
|
||||
? 'transparent'
|
||||
: settings.accentColor
|
||||
? `linear-gradient(135deg, ${settings.accentColor}, ${settings.accentColor}dd)`
|
||||
: 'transparent',
|
||||
boxShadow: settings.iconBgHidden ? 'none' : 'var(--shadow-card)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontSize: settings.iconBgHidden ? '28px' : '18px',
|
||||
width: '72px',
|
||||
height: '72px',
|
||||
objectFit: 'contain',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
{settings.portalEmoji ?? '\ud83e\udd9e'}
|
||||
</div>
|
||||
/>
|
||||
)}
|
||||
<div>
|
||||
<div
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { Agent } from '@/lib/types'
|
||||
import type { Conversation, ConversationStore, Message, MediaAttachment } from '@/lib/conversations'
|
||||
import { parseMedia, addMessage, updateLastMessage } from '@/lib/conversations'
|
||||
import { buildApiContent } from '@/lib/multimodal'
|
||||
import { generateId } from '@/lib/id'
|
||||
import { useSettings } from '@/app/settings-provider'
|
||||
import { FileAttachment } from './FileAttachment'
|
||||
import { MediaPreview } from './MediaPreview'
|
||||
@@ -329,14 +330,14 @@ export function ConversationView({ agent, conversation, onUpdate, onBack }: Conv
|
||||
}
|
||||
|
||||
const userMsg: Message = {
|
||||
id: crypto.randomUUID(),
|
||||
id: generateId(),
|
||||
role: 'user',
|
||||
content,
|
||||
timestamp: Date.now(),
|
||||
media: hasMedia ? mediaToSend : undefined,
|
||||
}
|
||||
|
||||
const assistantMsgId = crypto.randomUUID()
|
||||
const assistantMsgId = generateId()
|
||||
const assistantMsg: Message = {
|
||||
id: assistantMsgId,
|
||||
role: 'assistant',
|
||||
@@ -572,7 +573,7 @@ export function ConversationView({ agent, conversation, onUpdate, onBack }: Conv
|
||||
[agent.id]: {
|
||||
agentId: agent.id,
|
||||
messages: [{
|
||||
id: crypto.randomUUID(),
|
||||
id: generateId(),
|
||||
role: 'assistant' as const,
|
||||
content: `I'm ${agent.name}. ${agent.description} What do you need?`,
|
||||
timestamp: Date.now(),
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { Agent } from '@/lib/types'
|
||||
import type { KanbanTicket, TicketStatus, TicketPriority } from '@/lib/kanban/types'
|
||||
import { PRIORITY_COLORS, ROLE_LABELS, COLUMNS } from '@/lib/kanban/types'
|
||||
import { AgentAvatar } from '@/components/AgentAvatar'
|
||||
import { generateId } from '@/lib/id'
|
||||
|
||||
/* ── Chat message type (local to kanban) ─────────────── */
|
||||
|
||||
@@ -249,13 +250,13 @@ export function TicketDetailPanel({
|
||||
if (!text || isStreaming || !agent) return
|
||||
|
||||
const userMsg: ChatMessage = {
|
||||
id: crypto.randomUUID(),
|
||||
id: generateId(),
|
||||
role: 'user',
|
||||
content: text,
|
||||
timestamp: Date.now(),
|
||||
}
|
||||
|
||||
const assistantMsgId = crypto.randomUUID()
|
||||
const assistantMsgId = generateId()
|
||||
const assistantMsg: ChatMessage = {
|
||||
id: assistantMsgId,
|
||||
role: 'assistant',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { Agent } from './types'
|
||||
import { generateId } from './id'
|
||||
|
||||
export type MediaType = 'image' | 'audio' | 'file'
|
||||
|
||||
@@ -56,7 +57,7 @@ export function getOrCreateConversation(store: ConversationStore, agent: Agent):
|
||||
return {
|
||||
agentId: agent.id,
|
||||
messages: [{
|
||||
id: crypto.randomUUID(),
|
||||
id: generateId(),
|
||||
role: 'assistant',
|
||||
content: `I'm ${agent.name}. ${agent.description} What do you need?`,
|
||||
timestamp: Date.now(),
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Generate a unique ID, with a fallback for non-secure contexts
|
||||
* where crypto.randomUUID() is not available (e.g. HTTP, older browsers).
|
||||
*/
|
||||
export function generateId(): string {
|
||||
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
||||
return crypto.randomUUID()
|
||||
}
|
||||
// Fallback: generate a UUID v4-like string
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||
const r = (Math.random() * 16) | 0
|
||||
const v = c === 'x' ? r : (r & 0x3) | 0x8
|
||||
return v.toString(16)
|
||||
})
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { KanbanTicket, TeamRole } from './types'
|
||||
import { generateId } from '../id'
|
||||
|
||||
/* ── Role-specific work prompts ──────────────────────── */
|
||||
|
||||
@@ -159,8 +160,8 @@ export function persistWorkChat(
|
||||
): void {
|
||||
const now = Date.now()
|
||||
const messages = [
|
||||
{ id: crypto.randomUUID(), role: 'user' as const, content: prompt, timestamp: now },
|
||||
{ id: crypto.randomUUID(), role: 'assistant' as const, content: response, timestamp: now + 1 },
|
||||
{ id: generateId(), role: 'user' as const, content: prompt, timestamp: now },
|
||||
{ id: generateId(), role: 'assistant' as const, content: response, timestamp: now + 1 },
|
||||
]
|
||||
|
||||
fetch(`/api/kanban/chat-history/${ticketId}`, {
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { KanbanTicket, TicketStatus, TicketPriority, WorkState } from './types'
|
||||
import { generateId } from '../id'
|
||||
|
||||
export type KanbanStore = Record<string, KanbanTicket>
|
||||
|
||||
@@ -82,7 +83,7 @@ export function createTicket(
|
||||
workResult?: KanbanTicket['workResult']
|
||||
},
|
||||
): KanbanStore {
|
||||
const id = crypto.randomUUID()
|
||||
const id = generateId()
|
||||
const now = Date.now()
|
||||
return {
|
||||
...store,
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "clawport-ui",
|
||||
"version": "0.5.5",
|
||||
"version": "0.6.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "clawport-ui",
|
||||
"version": "0.5.5",
|
||||
"version": "0.6.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@dagrejs/dagre": "^2.0.4",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clawport-ui",
|
||||
"version": "0.6.0",
|
||||
"version": "0.6.1",
|
||||
"description": "Open-source dashboard for managing, monitoring, and chatting with your OpenClaw AI agents.",
|
||||
"homepage": "https://clawport.dev",
|
||||
"repository": {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Reference in New Issue
Block a user