Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions sgr-agent-frontend/src/shared/lib/constants/agents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const MODEL_TYPES = [
{ name: 'sgr_agent', value: 'sgr_agent', id: 1 },
{ name: 'sgr_auto_tool_calling_agent', value: 'sgr_auto_tool_calling_agent', id: 2 },
]
4 changes: 4 additions & 0 deletions sgr-agent-frontend/src/shared/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Shared lib exports
export * from './constants/agents'
export * from './utils/id'
export * from './utils/formatMessage'
111 changes: 111 additions & 0 deletions sgr-agent-frontend/src/shared/lib/utils/formatMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import type { ChatMessageExtended } from '@/shared/types/store'

/**
* Formats message to markdown format for copying
*/
export function formatMessageToMarkdown(message: ChatMessageExtended): string {
const lines: string[] = []

// Message header
if (message.role === 'user') {
lines.push('## 👤 User\n')
} else if (message.role === 'assistant') {
lines.push('## 🤖 Assistant\n')
} else {
lines.push('## System\n')
}

// Main content
if (message.content && message.content.length > 0) {
message.content.forEach((content) => {
// content can be string or ReasoningStep object
if (typeof content === 'string') {
lines.push(content)
} else if (content && typeof content === 'object') {
// If it's an object (ReasoningStep), convert to string
lines.push(JSON.stringify(content, null, 2))
}
})
}

// Agent Reasoning (if exists)
if (message.agentReasoning) {
lines.push('\n### 🧠 Reasoning\n')

if (message.agentReasoning.reasoning) {
lines.push('**Reasoning:**')
lines.push(String(message.agentReasoning.reasoning))
lines.push('')
}

if (message.agentReasoning.steps && Array.isArray(message.agentReasoning.steps)) {
lines.push('**Steps:**\n')
message.agentReasoning.steps.forEach((step: any, index: number) => {
lines.push(`${index + 1}. **${step.action || step.title || 'Action'}**`)
if (step.reasoning) {
lines.push(` - Reasoning: ${step.reasoning}`)
}
if (step.result || step.content) {
lines.push(` - Result: ${step.result || step.content}`)
}
lines.push('')
})
}
}

// Tool History (if exists)
if (message.toolHistory && message.toolHistory.length > 0) {
lines.push('\n### 🔧 Tool History\n')
message.toolHistory.forEach((tool, index) => {
lines.push(`#### Tool ${index + 1}: ${tool.tool_name || 'Unknown'}`)
if (tool.tool_call_id) {
lines.push(`- Call ID: \`${tool.tool_call_id}\``)
}
lines.push('- Content:')
lines.push('```')
lines.push(tool.content || '')
lines.push('```')
lines.push('')
})
}

// Timestamp
if (message.timestamp) {
const date = new Date(message.timestamp)
lines.push(`\n---`)
lines.push(`*${date.toLocaleString()}*`)
}

return lines.join('\n')
}

/**
* Copies text to clipboard
*/
export async function copyToClipboard(text: string): Promise<boolean> {
try {
// Modern API
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(text)
return true
}

// Fallback for old browsers
const textArea = document.createElement('textarea')
textArea.value = text
textArea.style.position = 'fixed'
textArea.style.left = '-999999px'
textArea.style.top = '-999999px'
document.body.appendChild(textArea)
textArea.focus()
textArea.select()

const successful = document.execCommand('copy')
document.body.removeChild(textArea)

return successful
} catch (error) {
console.error('Failed to copy to clipboard:', error)
return false
}
}
26 changes: 26 additions & 0 deletions sgr-agent-frontend/src/shared/lib/utils/id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Generates a unique ID using timestamp and random string
* @param prefix - Optional prefix for the ID
* @returns Unique ID string
*/
export function generateUniqueId(prefix: string = ''): string {
const timestamp = Date.now()
const randomString = Math.random().toString(36).substr(2, 9)
return prefix ? `${prefix}_${timestamp}_${randomString}` : `${timestamp}_${randomString}`
}

/**
* Generates a unique chat session ID
* @returns Unique chat session ID
*/
export function generateChatSessionId(): string {
return generateUniqueId('chat')
}

/**
* Generates a unique message ID
* @returns Unique message ID
*/
export function generateMessageId(): string {
return generateUniqueId('msg')
}